mirror of
https://github.com/cuberite/SQLiteCpp.git
synced 2025-08-04 09:46:02 -04:00
Add bindNoCopy methods to allow binding std::string with SQLITE_STATIC.
Should be safe, as long as you can guarantee the std::string exists while executing the query. Added an accessor to Column that returns a std::string, that can handle BLOB or TEXT values that contain null-bytes. Also more binding & Column cast support for uint32_t - fixes ambiguous overload errors when using unsigned-integer types. Note that I didn't use uint64_t, because unsigned 64-bit integers doesn't fit into SQLite (except for using int64_t and dealing with overflow with custom functions). Added a C++11 move constructor to Statement, to allow storing it inside STL containers (eg. vector).
This commit is contained in:
parent
4e7c12f629
commit
a84c04aada
@ -99,6 +99,13 @@ public:
|
||||
* thus you must copy it before using it beyond its scope (to a std::string for instance).
|
||||
*/
|
||||
const void* getBlob() const noexcept; // nothrow
|
||||
/**
|
||||
* @brief Return a std::string for a TEXT or BLOB column.
|
||||
*
|
||||
* Note this correctly handles strings that contain null bytes.
|
||||
*
|
||||
*/
|
||||
std::string getString() const noexcept; // nothrow
|
||||
|
||||
/**
|
||||
* @brief Return the type of the value of the column
|
||||
@ -158,6 +165,11 @@ public:
|
||||
{
|
||||
return getInt();
|
||||
}
|
||||
/// @brief Inline cast operator to 32bits unsigned integer
|
||||
inline operator uint32_t() const
|
||||
{
|
||||
return static_cast<uint32_t>(getInt64());
|
||||
}
|
||||
/// @brief Inline cast operator to 64bits integer
|
||||
inline operator sqlite3_int64() const
|
||||
{
|
||||
@ -193,12 +205,19 @@ public:
|
||||
// but is not working under Microsoft Visual Studio 2010, 2012 and 2013
|
||||
// (error C2440: 'initializing' : cannot convert from 'SQLite::Column' to 'std::basic_string<_Elem,_Traits,_Ax>'
|
||||
// [...] constructor overload resolution was ambiguous)
|
||||
/// Inline cast operator to std::string
|
||||
inline operator const std::string() const
|
||||
/**
|
||||
* @brief Inline cast operator to std::string
|
||||
*
|
||||
* Handles BLOB or TEXT, which may contain null bytes within
|
||||
*
|
||||
* @see getString
|
||||
*/
|
||||
inline operator std::string() const
|
||||
{
|
||||
return getText();
|
||||
return getString();
|
||||
}
|
||||
#endif
|
||||
|
||||
// NOTE : the following is required by GCC and Clang to cast a Column result in a long/int64_t
|
||||
/// @brief Inline cast operator to long as 64bits integer
|
||||
inline operator long() const
|
||||
|
@ -67,6 +67,17 @@ public:
|
||||
*/
|
||||
Statement(Database& aDatabase, const std::string& aQuery);
|
||||
|
||||
// Require C++11
|
||||
#if ( __cplusplus>= 201103L) || ( defined(_MSC_VER) && (_MSC_VER >= 1900) )
|
||||
#define Statement_CAN_MOVE 1
|
||||
/**
|
||||
* @breif Move Constructor
|
||||
*
|
||||
* (Allows inserting into STL containers that may need to move memory when growing.)
|
||||
*/
|
||||
Statement(Statement &&other);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Finalize and unregister the SQL query from the SQLite Database Connection.
|
||||
*/
|
||||
@ -105,21 +116,33 @@ public:
|
||||
/**
|
||||
* @brief Bind an int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
|
||||
*/
|
||||
void bind(const int aIndex, const int& aValue);
|
||||
void bind(const int aIndex, const int aValue);
|
||||
/**
|
||||
* @brief Bind a 64bits int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
|
||||
*/
|
||||
void bind(const int aIndex, const sqlite3_int64& aValue);
|
||||
void bind(const int aIndex, const sqlite3_int64 aValue);
|
||||
/**
|
||||
* @brief Bind a 32bits unsigned int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
|
||||
*/
|
||||
void bind(const int aIndex, const uint32_t aValue);
|
||||
/**
|
||||
* @brief Bind a double (64bits float) value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
|
||||
*/
|
||||
void bind(const int aIndex, const double& aValue);
|
||||
void bind(const int aIndex, const double aValue);
|
||||
/**
|
||||
* @brief Bind a string value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
|
||||
*
|
||||
* @note This uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use
|
||||
*/
|
||||
void bind(const int aIndex, const std::string& aValue);
|
||||
|
||||
/**
|
||||
* @brief Bind a string value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
|
||||
*
|
||||
* @note This uses the SQLITE_STATIC flag, NOT making a copy of the data. It must exist while executing the statement.
|
||||
*/
|
||||
void bindNoCopy(const int aIndex, const std::string& aValue);
|
||||
|
||||
/**
|
||||
* @brief Bind a text value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
|
||||
*
|
||||
@ -132,6 +155,14 @@ public:
|
||||
* @note This uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use
|
||||
*/
|
||||
void bind(const int aIndex, const void* apValue, const int aSize);
|
||||
|
||||
/**
|
||||
* @brief Bind a binary blob value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
|
||||
*
|
||||
* @note This uses the SQLITE_STATIC flag, NOT making a copy of the data. It must exist while executing the statement.
|
||||
*/
|
||||
void bindNoCopy(const int aIndex, const void* apValue, const int aSize);
|
||||
|
||||
/**
|
||||
* @brief Bind a NULL value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
|
||||
*/
|
||||
@ -140,21 +171,31 @@ public:
|
||||
/**
|
||||
* @brief Bind an int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
|
||||
*/
|
||||
void bind(const char* apName, const int& aValue);
|
||||
void bind(const char* apName, const int aValue);
|
||||
/**
|
||||
* @brief Bind a 64bits int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
|
||||
*/
|
||||
void bind(const char* apName, const sqlite3_int64& aValue);
|
||||
void bind(const char* apName, const sqlite3_int64 aValue);
|
||||
/**
|
||||
* @brief Bind a 32bits unsigned int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
|
||||
*/
|
||||
void bind(const char* apName, const uint32_t aValue);
|
||||
/**
|
||||
* @brief Bind a double (64bits float) value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
|
||||
*/
|
||||
void bind(const char* apName, const double& aValue);
|
||||
void bind(const char* apName, const double aValue);
|
||||
/**
|
||||
* @brief Bind a string value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
|
||||
*
|
||||
* @note This uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use
|
||||
*/
|
||||
void bind(const char* apName, const std::string& aValue);
|
||||
/**
|
||||
* @brief Bind a string value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
|
||||
*
|
||||
* @note This uses the SQLITE_STATIC flag, NOT making a copy of the data.
|
||||
*/
|
||||
void bindNoCopy(const char* apName, const std::string& aValue);
|
||||
/**
|
||||
* @brief Bind a text value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
|
||||
*
|
||||
@ -167,6 +208,12 @@ public:
|
||||
* @note This uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use
|
||||
*/
|
||||
void bind(const char* apName, const void* apValue, const int aSize);
|
||||
/**
|
||||
* @brief Bind a binary blob value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
|
||||
*
|
||||
* @note This uses the SQLITE_STATIC flag, making a copy of the data.
|
||||
*/
|
||||
void bindNoCopy(const char* apName, const void* apValue, const int aSize);
|
||||
/**
|
||||
* @brief Bind a NULL value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
|
||||
*/
|
||||
@ -176,21 +223,28 @@ public:
|
||||
/**
|
||||
* @brief Bind an int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
|
||||
*/
|
||||
inline void bind(const std::string& aName, const int& aValue)
|
||||
inline void bind(const std::string& aName, const int aValue)
|
||||
{
|
||||
bind(aName.c_str(), aValue);
|
||||
}
|
||||
/**
|
||||
* @brief Bind a 64bits int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
|
||||
*/
|
||||
inline void bind(const std::string& aName, const sqlite3_int64& aValue)
|
||||
inline void bind(const std::string& aName, const sqlite3_int64 aValue)
|
||||
{
|
||||
bind(aName.c_str(), aValue);
|
||||
}
|
||||
/**
|
||||
* @brief Bind a 32bits unsigned int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
|
||||
*/
|
||||
inline void bind(const std::string& aName, const uint32_t aValue)
|
||||
{
|
||||
bind(aName.c_str(), aValue);
|
||||
}
|
||||
/**
|
||||
* @brief Bind a double (64bits float) value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
|
||||
*/
|
||||
inline void bind(const std::string& aName, const double& aValue)
|
||||
inline void bind(const std::string& aName, const double aValue)
|
||||
{
|
||||
bind(aName.c_str(), aValue);
|
||||
}
|
||||
@ -203,6 +257,15 @@ public:
|
||||
{
|
||||
bind(aName.c_str(), aValue);
|
||||
}
|
||||
/**
|
||||
* @brief Bind a string value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
|
||||
*
|
||||
* @note This uses the SQLITE_STATIC flag, NOT making a copy of the data.
|
||||
*/
|
||||
inline void bindNoCopy(const std::string& aName, const std::string& aValue)
|
||||
{
|
||||
bindNoCopy(aName.c_str(), aValue);
|
||||
}
|
||||
/**
|
||||
* @brief Bind a text value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
|
||||
*
|
||||
@ -221,6 +284,15 @@ public:
|
||||
{
|
||||
bind(aName.c_str(), apValue, aSize);
|
||||
}
|
||||
/**
|
||||
* @brief Bind a binary blob value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
|
||||
*
|
||||
* @note This uses the SQLITE_STATIC flag, NOT making a copy of the data.
|
||||
*/
|
||||
inline void bindNoCopy(const std::string& aName, const void* apValue, const int aSize)
|
||||
{
|
||||
bindNoCopy(aName.c_str(), apValue, aSize);
|
||||
}
|
||||
/**
|
||||
* @brief Bind a NULL value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
|
||||
*/
|
||||
|
@ -69,12 +69,25 @@ const char* Column::getText(const char* apDefaultValue /* = "" */) const noexcep
|
||||
return (pText?pText:apDefaultValue);
|
||||
}
|
||||
|
||||
// Return a pointer to the text value (NULL terminated string) of the column specified by its index starting at 0
|
||||
// Return a pointer to the blob value (*not* NULL terminated) of the column specified by its index starting at 0
|
||||
const void* Column::getBlob() const noexcept // nothrow
|
||||
{
|
||||
return sqlite3_column_blob(mStmtPtr, mIndex);
|
||||
}
|
||||
|
||||
// Return a std::string to a TEXT or BLOB column
|
||||
std::string Column::getString() const noexcept // nothrow
|
||||
{
|
||||
// Note: using sqlite3_column_blob and not sqlite3_column_text
|
||||
// - no need for sqlite3_column_text to add a \0 on the end, as we're getting the bytes length directly
|
||||
const char *data = static_cast<const char *>(sqlite3_column_blob(mStmtPtr, mIndex));
|
||||
|
||||
// Note: C++ order of argument evaluation is unspecified, so not calling _blob and _bytes both directly in std::string constructor
|
||||
// SQLite docs: "The safest policy is to invoke… sqlite3_column_blob() followed by sqlite3_column_bytes()"
|
||||
// Note: std::string is ok to pass nullptr as first arg, if length is 0
|
||||
return std::string(data, sqlite3_column_bytes(mStmtPtr, mIndex));
|
||||
}
|
||||
|
||||
// Return the type of the value of the column
|
||||
int Column::getType() const noexcept // nothrow
|
||||
{
|
||||
|
@ -43,6 +43,23 @@ Statement::Statement(Database &aDatabase, const std::string& aQuery) :
|
||||
mColumnCount = sqlite3_column_count(mStmtPtr);
|
||||
}
|
||||
|
||||
#ifdef Statement_CAN_MOVE
|
||||
// Move Constructor
|
||||
Statement::Statement(Statement &&other):
|
||||
mQuery(std::move(other.mQuery)),
|
||||
mStmtPtr(other.mStmtPtr),
|
||||
mColumnCount(other.mColumnCount),
|
||||
mColumnNames(std::move(other.mColumnNames)),
|
||||
mbOk(other.mbOk),
|
||||
mbDone(other.mbDone)
|
||||
{
|
||||
//other.mStmtPtr = nullptr; // doesn't support reassigning
|
||||
other.mColumnCount = 0;
|
||||
other.mbOk = false;
|
||||
other.mbDone = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Finalize and unregister the SQL query from the SQLite Database Connection.
|
||||
Statement::~Statement() noexcept // nothrow
|
||||
{
|
||||
@ -66,21 +83,28 @@ void Statement::clearBindings()
|
||||
}
|
||||
|
||||
// Bind an int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
||||
void Statement::bind(const int aIndex, const int& aValue)
|
||||
void Statement::bind(const int aIndex, const int aValue)
|
||||
{
|
||||
const int ret = sqlite3_bind_int(mStmtPtr, aIndex, aValue);
|
||||
check(ret);
|
||||
}
|
||||
|
||||
// Bind a 64bits int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
||||
void Statement::bind(const int aIndex, const sqlite3_int64& aValue)
|
||||
void Statement::bind(const int aIndex, const sqlite3_int64 aValue)
|
||||
{
|
||||
const int ret = sqlite3_bind_int64(mStmtPtr, aIndex, aValue);
|
||||
check(ret);
|
||||
}
|
||||
|
||||
// Bind a 32bits unsigned int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
||||
void Statement::bind(const int aIndex, const uint32_t aValue)
|
||||
{
|
||||
const int ret = sqlite3_bind_int64(mStmtPtr, aIndex, aValue);
|
||||
check(ret);
|
||||
}
|
||||
|
||||
// Bind a double (64bits float) value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
||||
void Statement::bind(const int aIndex, const double& aValue)
|
||||
void Statement::bind(const int aIndex, const double aValue)
|
||||
{
|
||||
const int ret = sqlite3_bind_double(mStmtPtr, aIndex, aValue);
|
||||
check(ret);
|
||||
@ -94,6 +118,14 @@ void Statement::bind(const int aIndex, const std::string& aValue)
|
||||
check(ret);
|
||||
}
|
||||
|
||||
// Bind a string value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
||||
void Statement::bindNoCopy(const int aIndex, const std::string& aValue)
|
||||
{
|
||||
const int ret = sqlite3_bind_text(mStmtPtr, aIndex, aValue.c_str(),
|
||||
static_cast<int>(aValue.size()), SQLITE_STATIC);
|
||||
check(ret);
|
||||
}
|
||||
|
||||
// Bind a text value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
||||
void Statement::bind(const int aIndex, const char* apValue)
|
||||
{
|
||||
@ -108,6 +140,13 @@ void Statement::bind(const int aIndex, const void* apValue, const int aSize)
|
||||
check(ret);
|
||||
}
|
||||
|
||||
// Bind a binary blob value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
||||
void Statement::bindNoCopy(const int aIndex, const void* apValue, const int aSize)
|
||||
{
|
||||
const int ret = sqlite3_bind_blob(mStmtPtr, aIndex, apValue, aSize, SQLITE_STATIC);
|
||||
check(ret);
|
||||
}
|
||||
|
||||
// Bind a NULL value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
||||
void Statement::bind(const int aIndex)
|
||||
{
|
||||
@ -117,7 +156,7 @@ void Statement::bind(const int aIndex)
|
||||
|
||||
|
||||
// Bind an int value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
||||
void Statement::bind(const char* apName, const int& aValue)
|
||||
void Statement::bind(const char* apName, const int aValue)
|
||||
{
|
||||
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
|
||||
const int ret = sqlite3_bind_int(mStmtPtr, index, aValue);
|
||||
@ -125,7 +164,15 @@ void Statement::bind(const char* apName, const int& aValue)
|
||||
}
|
||||
|
||||
// Bind a 64bits int value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
||||
void Statement::bind(const char* apName, const sqlite3_int64& aValue)
|
||||
void Statement::bind(const char* apName, const sqlite3_int64 aValue)
|
||||
{
|
||||
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
|
||||
const int ret = sqlite3_bind_int64(mStmtPtr, index, aValue);
|
||||
check(ret);
|
||||
}
|
||||
|
||||
// Bind a 32bits unsigned int value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
||||
void Statement::bind(const char* apName, const uint32_t aValue)
|
||||
{
|
||||
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
|
||||
const int ret = sqlite3_bind_int64(mStmtPtr, index, aValue);
|
||||
@ -133,7 +180,7 @@ void Statement::bind(const char* apName, const sqlite3_int64& aValue)
|
||||
}
|
||||
|
||||
// Bind a double (64bits float) value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
||||
void Statement::bind(const char* apName, const double& aValue)
|
||||
void Statement::bind(const char* apName, const double aValue)
|
||||
{
|
||||
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
|
||||
const int ret = sqlite3_bind_double(mStmtPtr, index, aValue);
|
||||
@ -149,6 +196,15 @@ void Statement::bind(const char* apName, const std::string& aValue)
|
||||
check(ret);
|
||||
}
|
||||
|
||||
// Bind a string value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
||||
void Statement::bindNoCopy(const char* apName, const std::string& aValue)
|
||||
{
|
||||
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
|
||||
const int ret = sqlite3_bind_text(mStmtPtr, index, aValue.c_str(),
|
||||
static_cast<int>(aValue.size()), SQLITE_STATIC);
|
||||
check(ret);
|
||||
}
|
||||
|
||||
// Bind a text value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
||||
void Statement::bind(const char* apName, const char* apValue)
|
||||
{
|
||||
@ -165,6 +221,14 @@ void Statement::bind(const char* apName, const void* apValue, const int aSize)
|
||||
check(ret);
|
||||
}
|
||||
|
||||
// Bind a binary blob value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
||||
void Statement::bindNoCopy(const char* apName, const void* apValue, const int aSize)
|
||||
{
|
||||
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
|
||||
const int ret = sqlite3_bind_blob(mStmtPtr, index, apValue, aSize, SQLITE_STATIC);
|
||||
check(ret);
|
||||
}
|
||||
|
||||
// Bind a NULL value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
||||
void Statement::bind(const char* apName)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user