-
Notifications
You must be signed in to change notification settings - Fork 553
Description
I frequently use std::string_view to avoid copying sub-strings. I wanted to pass a string_view to Statement::bindNoCopy but saw the type error. My first instinct was to replace it with statement.bindNoCopy(1, sv.data(), sv.size()) but after checking the implementation, I noticed that it calls sqlite3_bind_blob when I would have expected it to call sqlite3_bind_text.
Proposal
I'm sure one of the following approaches would work.
Support binding std::string_view
Example implementation. I would also like to use Statment::bindNoCopy with string_view.
#if __cplusplus >= 201703L // C++17
// Bind a string value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const int aIndex, const std::string_view& aValue)
{
const int ret = sqlite3_bind_text(getPreparedStatement(), aIndex, aValue.data(),
static_cast<int>(aValue.size()), SQLITE_TRANSIENT);
check(ret);
}
#endifResearch
According to the sqlite3 C interface documentation it seems that sqlite3_bind_text doesn't require that the given const char* parameter be null-terminated since we also pass a size argument that's not -1. So we should be free to use std::string_view here without problems.
In those routines that have a fourth argument, its value is the number of bytes in the parameter. To be clear: the value is the number of bytes in the value, not the number of characters. If the fourth parameter to sqlite3_bind_text() or sqlite3_bind_text16() is negative, then the length of the string is the number of bytes up to the first zero terminator. If the fourth parameter to sqlite3_bind_blob() is negative, then the behavior is undefined. If a non-negative fourth parameter is provided to sqlite3_bind_text() or sqlite3_bind_text16() or sqlite3_bind_text64() then that parameter must be the byte offset where the NUL terminator would occur assuming the string were NUL terminated. If any NUL characters occur at byte offsets less than the value of the fourth parameter then the resulting string value will contain embedded NULs. The result of expressions involving strings with embedded NULs is undefined.
Due to implicit casting, this function could actually replace the following two overloads when string_view is available.
void bind(const int aIndex, const std::string& aValue);void bind(const int aIndex, const char* apValue);
Support reading column values as std::string_view
This function would have the benefit of reducing unnecessary copies associated with std::string while still allowing the user to read strings with embedded null characters.
#if __cplusplus >= 201703L // C++17
/**
* @brief Return a std::string_view for a TEXT or BLOB column.
*
* Note this correctly handles strings that contain null bytes.
*
* @warning returned string_view is only valid until there is a type
* conversion or the statement is stepped or reset.
*/
std::string_view getStringView() const;
#endifShould I send a PR?
I started implementing these changes to SQLiteCpp but I won't be back on my desktop until tomorrow. Do you think a PR for this (plus unit tests, examples, etc.) might get merged?