mirror of
https://github.com/cuberite/SQLiteCpp.git
synced 2025-08-04 09:46:02 -04:00
Add Statement::getColumnName(aIndex)
- enable getting names befor gettings rows of result
This commit is contained in:
parent
078365febc
commit
8797f16d12
@ -140,28 +140,22 @@ int main ()
|
|||||||
query.reset();
|
query.reset();
|
||||||
std::cout << "SQLite statement '" << query.getQuery().c_str() << "' reseted (" << query.getColumnCount() << " columns in the result)\n";
|
std::cout << "SQLite statement '" << query.getQuery().c_str() << "' reseted (" << query.getColumnCount() << " columns in the result)\n";
|
||||||
|
|
||||||
// Execute the first step of the query, to get the fist row of results, and name of columns
|
// Show how to get the aliased names of the result columns.
|
||||||
if (query.executeStep())
|
const std::string name0 = query.getColumnName(0);
|
||||||
{
|
const std::string name1 = query.getColumnName(1);
|
||||||
// Show how to get the aliased names of the result columns.
|
const std::string name2 = query.getColumnName(2);
|
||||||
const std::string name0 = query.getColumn(0).getName();
|
std::cout << "aliased result [\"" << name0.c_str() << "\", \"" << name1.c_str() << "\", \"" << name2.c_str() << "\"]\n";
|
||||||
const std::string name1 = query.getColumn(1).getName();
|
|
||||||
const std::string name2 = query.getColumn(2).getName();
|
|
||||||
std::cout << "aliased result [\"" << name0.c_str() << "\", \"" << name1.c_str() << "\", \"" << name2.c_str() << "\"]\n";
|
|
||||||
|
|
||||||
#ifdef SQLITE_ENABLE_COLUMN_METADATA
|
#ifdef SQLITE_ENABLE_COLUMN_METADATA
|
||||||
// Show how to get origin names of the table columns from which theses result columns come from.
|
// Show how to get origin names of the table columns from which theses result columns come from.
|
||||||
// Requires the SQLITE_ENABLE_COLUMN_METADATA preprocessor macro to be
|
// Requires the SQLITE_ENABLE_COLUMN_METADATA preprocessor macro to be
|
||||||
// also defined at compile times of the SQLite library itself.
|
// also defined at compile times of the SQLite library itself.
|
||||||
const std::string oname0 = query.getColumn(0).getOriginName();
|
const std::string oname0 = query.getColumnOriginName(0);
|
||||||
const std::string oname1 = query.getColumn(1).getOriginName();
|
const std::string oname1 = query.getColumnOriginName(1);
|
||||||
const std::string oname2 = query.getColumn(2).getOriginName();
|
const std::string oname2 = query.getColumnOriginName(2);
|
||||||
std::cout << "origin table 'test' [\"" << oname0.c_str() << "\", \"" << oname1.c_str() << "\", \"" << oname2.c_str() << "\"]\n";
|
std::cout << "origin table 'test' [\"" << oname0.c_str() << "\", \"" << oname1.c_str() << "\", \"" << oname2.c_str() << "\"]\n";
|
||||||
#endif
|
#endif
|
||||||
// Demonstrates that inserting column value in a std:ostream is natural
|
// Loop to execute the query step by step, to get one a row of results at a time
|
||||||
std::cout << "row (" << query.getColumn(0) << ", \"" << query.getColumn(1) << "\", " << query.getColumn(2) << ")\n";
|
|
||||||
}
|
|
||||||
// Loop to execute the rest of the query step by step, to get one a row of results at a time
|
|
||||||
while (query.executeStep())
|
while (query.executeStep())
|
||||||
{
|
{
|
||||||
// Demonstrates that inserting column value in a std:ostream is natural
|
// Demonstrates that inserting column value in a std:ostream is natural
|
||||||
|
@ -297,7 +297,7 @@ public:
|
|||||||
Column getColumn(const int aIndex);
|
Column getColumn(const int aIndex);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Return a copy of the column data specified by its column name
|
* @brief Return a copy of the column data specified by its column name (less efficient than using an index)
|
||||||
*
|
*
|
||||||
* Can be used to access the data of the current row of result when applicable,
|
* Can be used to access the data of the current row of result when applicable,
|
||||||
* while the executeStep() method returns true.
|
* while the executeStep() method returns true.
|
||||||
@ -308,9 +308,11 @@ public:
|
|||||||
* - after the last executeStep() returned false
|
* - after the last executeStep() returned false
|
||||||
* - after a reset() call
|
* - after a reset() call
|
||||||
*
|
*
|
||||||
* Throw an exception if the specified index is out of the [0, getColumnCount()) range.
|
* Throw an exception if the specified name is not an on of the aliased name of the columns in the result.
|
||||||
*
|
*
|
||||||
* @param[in] apName Name of the column, starting at index 0
|
* @param[in] apName Aliased name of the column, that is, the named specified in the query (not the original name)
|
||||||
|
*
|
||||||
|
* @note Uses a map of column names to indexes, build on first call.
|
||||||
*
|
*
|
||||||
* @note This method is not const, reflecting the fact that the returned Column object will
|
* @note This method is not const, reflecting the fact that the returned Column object will
|
||||||
* share the ownership of the underlying sqlite3_stmt.
|
* share the ownership of the underlying sqlite3_stmt.
|
||||||
@ -329,9 +331,33 @@ public:
|
|||||||
* @param[in] aIndex Index of the column, starting at 0
|
* @param[in] aIndex Index of the column, starting at 0
|
||||||
*
|
*
|
||||||
* @return true if the column value is NULL
|
* @return true if the column value is NULL
|
||||||
|
*
|
||||||
|
* Throw an exception if the specified index is out of the [0, getColumnCount()) range.
|
||||||
*/
|
*/
|
||||||
bool isColumnNull(const int aIndex) const;
|
bool isColumnNull(const int aIndex) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Return a pointer to the named assigned to the specified result column (potentially aliased)
|
||||||
|
*
|
||||||
|
* @see getColumnOriginName() to get original column name (not aliased)
|
||||||
|
*
|
||||||
|
* Throw an exception if the specified index is out of the [0, getColumnCount()) range.
|
||||||
|
*/
|
||||||
|
const char* getColumnName(const int aIndex) const;
|
||||||
|
|
||||||
|
#ifdef SQLITE_ENABLE_COLUMN_METADATA
|
||||||
|
/**
|
||||||
|
* @brief Return a pointer to the table column name that is the origin of the specified result column
|
||||||
|
*
|
||||||
|
* Require definition of the SQLITE_ENABLE_COLUMN_METADATA preprocessor macro :
|
||||||
|
* - when building the SQLite library itself (which is the case for the Debian libsqlite3 binary for instance),
|
||||||
|
* - and also when compiling this wrapper.
|
||||||
|
*
|
||||||
|
* Throw an exception if the specified index is out of the [0, getColumnCount()) range.
|
||||||
|
*/
|
||||||
|
const char* getColumnOriginName(const int aIndex) const;
|
||||||
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/// @brief Return the UTF-8 SQL Query.
|
/// @brief Return the UTF-8 SQL Query.
|
||||||
@ -423,7 +449,35 @@ private:
|
|||||||
*
|
*
|
||||||
* @param[in] SQLite return code to test against the SQLITE_OK expected value
|
* @param[in] SQLite return code to test against the SQLITE_OK expected value
|
||||||
*/
|
*/
|
||||||
void check(const int aRet);
|
inline void Statement::check(const int aRet) const
|
||||||
|
{
|
||||||
|
if (SQLITE_OK != aRet)
|
||||||
|
{
|
||||||
|
throw SQLite::Exception(sqlite3_errmsg(mStmtPtr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if there is a row of result returnes by executeStep(), else throw a SQLite::Exception.
|
||||||
|
*/
|
||||||
|
inline void Statement::checkRow() const
|
||||||
|
{
|
||||||
|
if (false == mbOk)
|
||||||
|
{
|
||||||
|
throw SQLite::Exception("No row to get a column from. executeStep() was not called or did not returned true.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if there is a Column index is in the range of columns in the result.
|
||||||
|
*/
|
||||||
|
inline void Statement::checkIndex(const int aIndex) const
|
||||||
|
{
|
||||||
|
if ((aIndex < 0) || (aIndex >= mColumnCount))
|
||||||
|
{
|
||||||
|
throw SQLite::Exception("Column index out of range.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::map<std::string, int> TColumnNames;
|
typedef std::map<std::string, int> TColumnNames;
|
||||||
|
@ -54,7 +54,7 @@ void Statement::reset()
|
|||||||
{
|
{
|
||||||
mbOk = false;
|
mbOk = false;
|
||||||
mbDone = false;
|
mbDone = false;
|
||||||
int ret = sqlite3_reset(mStmtPtr);
|
const int ret = sqlite3_reset(mStmtPtr);
|
||||||
check(ret);
|
check(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,56 +65,56 @@ void Statement::clearBindings(void)
|
|||||||
{
|
{
|
||||||
mbOk = false;
|
mbOk = false;
|
||||||
mbDone = false;
|
mbDone = false;
|
||||||
int ret = sqlite3_clear_bindings(mStmtPtr);
|
const int ret = sqlite3_clear_bindings(mStmtPtr);
|
||||||
check(ret);
|
check(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind an int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
// 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)
|
||||||
{
|
{
|
||||||
int ret = sqlite3_bind_int(mStmtPtr, aIndex, aValue);
|
const int ret = sqlite3_bind_int(mStmtPtr, aIndex, aValue);
|
||||||
check(ret);
|
check(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind a 64bits int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
// 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)
|
||||||
{
|
{
|
||||||
int ret = sqlite3_bind_int64(mStmtPtr, aIndex, aValue);
|
const int ret = sqlite3_bind_int64(mStmtPtr, aIndex, aValue);
|
||||||
check(ret);
|
check(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind a double (64bits float) value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
// 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)
|
||||||
{
|
{
|
||||||
int ret = sqlite3_bind_double(mStmtPtr, aIndex, aValue);
|
const int ret = sqlite3_bind_double(mStmtPtr, aIndex, aValue);
|
||||||
check(ret);
|
check(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind a string value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
// 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& aValue)
|
void Statement::bind(const int aIndex, const std::string& aValue)
|
||||||
{
|
{
|
||||||
int ret = sqlite3_bind_text(mStmtPtr, aIndex, aValue.c_str(), static_cast<int>(aValue.size()), SQLITE_TRANSIENT);
|
const int ret = sqlite3_bind_text(mStmtPtr, aIndex, aValue.c_str(), static_cast<int>(aValue.size()), SQLITE_TRANSIENT);
|
||||||
check(ret);
|
check(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind a text value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
// 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)
|
void Statement::bind(const int aIndex, const char* apValue)
|
||||||
{
|
{
|
||||||
int ret = sqlite3_bind_text(mStmtPtr, aIndex, apValue, -1, SQLITE_TRANSIENT);
|
const int ret = sqlite3_bind_text(mStmtPtr, aIndex, apValue, -1, SQLITE_TRANSIENT);
|
||||||
check(ret);
|
check(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind a binary blob value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
// Bind a binary blob value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
||||||
void Statement::bind(const int aIndex, const void* apValue, const int aSize)
|
void Statement::bind(const int aIndex, const void* apValue, const int aSize)
|
||||||
{
|
{
|
||||||
int ret = sqlite3_bind_blob(mStmtPtr, aIndex, apValue, aSize, SQLITE_TRANSIENT);
|
const int ret = sqlite3_bind_blob(mStmtPtr, aIndex, apValue, aSize, SQLITE_TRANSIENT);
|
||||||
check(ret);
|
check(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind a NULL value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
// Bind a NULL value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
||||||
void Statement::bind(const int aIndex)
|
void Statement::bind(const int aIndex)
|
||||||
{
|
{
|
||||||
int ret = sqlite3_bind_null(mStmtPtr, aIndex);
|
const int ret = sqlite3_bind_null(mStmtPtr, aIndex);
|
||||||
check(ret);
|
check(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,56 +122,56 @@ void Statement::bind(const int aIndex)
|
|||||||
// Bind an int value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
// 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)
|
||||||
{
|
{
|
||||||
int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
|
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
|
||||||
int ret = sqlite3_bind_int(mStmtPtr, index, aValue);
|
const int ret = sqlite3_bind_int(mStmtPtr, index, aValue);
|
||||||
check(ret);
|
check(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind a 64bits int value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
// 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)
|
||||||
{
|
{
|
||||||
int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
|
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
|
||||||
int ret = sqlite3_bind_int64(mStmtPtr, index, aValue);
|
const int ret = sqlite3_bind_int64(mStmtPtr, index, aValue);
|
||||||
check(ret);
|
check(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind a double (64bits float) value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
// 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)
|
||||||
{
|
{
|
||||||
int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
|
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
|
||||||
int ret = sqlite3_bind_double(mStmtPtr, index, aValue);
|
const int ret = sqlite3_bind_double(mStmtPtr, index, aValue);
|
||||||
check(ret);
|
check(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind a string value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
// Bind a string value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
||||||
void Statement::bind(const char* apName, const std::string& aValue)
|
void Statement::bind(const char* apName, const std::string& aValue)
|
||||||
{
|
{
|
||||||
int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
|
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
|
||||||
int ret = sqlite3_bind_text(mStmtPtr, index, aValue.c_str(), static_cast<int>(aValue.size()), SQLITE_TRANSIENT);
|
const int ret = sqlite3_bind_text(mStmtPtr, index, aValue.c_str(), static_cast<int>(aValue.size()), SQLITE_TRANSIENT);
|
||||||
check(ret);
|
check(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind a text value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
// 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)
|
void Statement::bind(const char* apName, const char* apValue)
|
||||||
{
|
{
|
||||||
int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
|
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
|
||||||
int ret = sqlite3_bind_text(mStmtPtr, index, apValue, -1, SQLITE_TRANSIENT);
|
const int ret = sqlite3_bind_text(mStmtPtr, index, apValue, -1, SQLITE_TRANSIENT);
|
||||||
check(ret);
|
check(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind a binary blob value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
// Bind a binary blob value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
||||||
void Statement::bind(const char* apName, const void* apValue, const int aSize)
|
void Statement::bind(const char* apName, const void* apValue, const int aSize)
|
||||||
{
|
{
|
||||||
int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
|
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
|
||||||
int ret = sqlite3_bind_blob(mStmtPtr, index, apValue, aSize, SQLITE_TRANSIENT);
|
const int ret = sqlite3_bind_blob(mStmtPtr, index, apValue, aSize, SQLITE_TRANSIENT);
|
||||||
check(ret);
|
check(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind a NULL value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
// Bind a NULL value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
|
||||||
void Statement::bind(const char* apName)
|
void Statement::bind(const char* apName)
|
||||||
{
|
{
|
||||||
int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
|
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
|
||||||
int ret = sqlite3_bind_null(mStmtPtr, index);
|
const int ret = sqlite3_bind_null(mStmtPtr, index);
|
||||||
check(ret);
|
check(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,7 +181,7 @@ bool Statement::executeStep()
|
|||||||
{
|
{
|
||||||
if (false == mbDone)
|
if (false == mbDone)
|
||||||
{
|
{
|
||||||
int ret = sqlite3_step(mStmtPtr);
|
const int ret = sqlite3_step(mStmtPtr);
|
||||||
if (SQLITE_ROW == ret) // one row is ready : call getColumn(N) to access it
|
if (SQLITE_ROW == ret) // one row is ready : call getColumn(N) to access it
|
||||||
{
|
{
|
||||||
mbOk = true;
|
mbOk = true;
|
||||||
@ -200,7 +200,7 @@ bool Statement::executeStep()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw SQLite::Exception("Statement needs to be reset");
|
throw SQLite::Exception("Statement needs to be reseted.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return mbOk; // true only if one row is accessible by getColumn(N)
|
return mbOk; // true only if one row is accessible by getColumn(N)
|
||||||
@ -211,7 +211,7 @@ int Statement::exec()
|
|||||||
{
|
{
|
||||||
if (false == mbDone)
|
if (false == mbDone)
|
||||||
{
|
{
|
||||||
int ret = sqlite3_step(mStmtPtr);
|
const int ret = sqlite3_step(mStmtPtr);
|
||||||
if (SQLITE_DONE == ret) // the statement has finished executing successfully
|
if (SQLITE_DONE == ret) // the statement has finished executing successfully
|
||||||
{
|
{
|
||||||
mbOk = false;
|
mbOk = false;
|
||||||
@ -221,7 +221,7 @@ int Statement::exec()
|
|||||||
{
|
{
|
||||||
mbOk = false;
|
mbOk = false;
|
||||||
mbDone = false;
|
mbDone = false;
|
||||||
throw SQLite::Exception("exec() does not expect results");
|
throw SQLite::Exception("exec() does not expect results. Use executeStep.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -232,7 +232,7 @@ int Statement::exec()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw SQLite::Exception("Statement need to be reseted");
|
throw SQLite::Exception("Statement need to be reseted.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the number of rows modified by those SQL statements (INSERT, UPDATE or DELETE)
|
// Return the number of rows modified by those SQL statements (INSERT, UPDATE or DELETE)
|
||||||
@ -243,14 +243,8 @@ int Statement::exec()
|
|||||||
// (use the Column copy-constructor)
|
// (use the Column copy-constructor)
|
||||||
Column Statement::getColumn(const int aIndex)
|
Column Statement::getColumn(const int aIndex)
|
||||||
{
|
{
|
||||||
if (false == mbOk)
|
checkRow();
|
||||||
{
|
checkIndex(aIndex);
|
||||||
throw SQLite::Exception("No row to get a column from");
|
|
||||||
}
|
|
||||||
else if ((aIndex < 0) || (aIndex >= mColumnCount))
|
|
||||||
{
|
|
||||||
throw SQLite::Exception("Column index out of range");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Share the Statement Object handle with the new Column created
|
// Share the Statement Object handle with the new Column created
|
||||||
return Column(mStmtPtr, aIndex);
|
return Column(mStmtPtr, aIndex);
|
||||||
@ -260,62 +254,50 @@ Column Statement::getColumn(const int aIndex)
|
|||||||
// (use the Column copy-constructor)
|
// (use the Column copy-constructor)
|
||||||
Column Statement::getColumn(const char* apName)
|
Column Statement::getColumn(const char* apName)
|
||||||
{
|
{
|
||||||
int Index = -1;
|
checkRow();
|
||||||
|
|
||||||
if (false == mbOk)
|
if (mColumnNames.empty())
|
||||||
{
|
{
|
||||||
throw SQLite::Exception("No row to get a column from");
|
for (int i = 0; i < mColumnCount; ++i)
|
||||||
|
{
|
||||||
|
const char* pName = sqlite3_column_name(mStmtPtr, i);
|
||||||
|
mColumnNames[pName] = i;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
if (mColumnNames.empty())
|
|
||||||
{
|
|
||||||
for (int i = 0; i < mColumnCount; ++i)
|
|
||||||
{
|
|
||||||
const char* pName = sqlite3_column_name(mStmtPtr, i);
|
|
||||||
mColumnNames[pName] = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const TColumnNames::const_iterator iIndex = mColumnNames.find(apName);
|
const TColumnNames::const_iterator iIndex = mColumnNames.find(apName);
|
||||||
if (iIndex != mColumnNames.end())
|
if (iIndex == mColumnNames.end())
|
||||||
{
|
{
|
||||||
Index = (*iIndex).second;
|
throw SQLite::Exception("Unknown column name.");
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw SQLite::Exception("Column index out of range");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Share the Statement Object handle with the new Column created
|
// Share the Statement Object handle with the new Column created
|
||||||
return Column(mStmtPtr, Index);
|
return Column(mStmtPtr, (*iIndex).second);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test if the column is NULL
|
// Test if the column is NULL
|
||||||
bool Statement::isColumnNull(const int aIndex) const
|
bool Statement::isColumnNull(const int aIndex) const
|
||||||
{
|
{
|
||||||
if (false == mbOk)
|
checkRow();
|
||||||
{
|
checkIndex(aIndex);
|
||||||
throw SQLite::Exception("No row to get a column from");
|
|
||||||
}
|
|
||||||
else if ((aIndex < 0) || (aIndex >= mColumnCount))
|
|
||||||
{
|
|
||||||
throw SQLite::Exception("Column index out of range");
|
|
||||||
}
|
|
||||||
|
|
||||||
return (SQLITE_NULL == sqlite3_column_type(mStmtPtr, aIndex));
|
return (SQLITE_NULL == sqlite3_column_type(mStmtPtr, aIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if aRet equal SQLITE_OK, else throw a SQLite::Exception with the SQLite error message
|
// Return the named assigned to the specified result column (potentially aliased)
|
||||||
void Statement::check(const int aRet)
|
const char* Statement::getColumnName(const int aIndex) const
|
||||||
{
|
{
|
||||||
if (SQLITE_OK != aRet)
|
checkIndex(aIndex);
|
||||||
{
|
return sqlite3_column_name(mStmtPtr, aIndex);
|
||||||
throw SQLite::Exception(sqlite3_errmsg(mStmtPtr));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef SQLITE_ENABLE_COLUMN_METADATA
|
||||||
|
// Return the named assigned to the specified result column (potentially aliased)
|
||||||
|
const char* Statement::getColumnOriginName(const int aIndex) const
|
||||||
|
{
|
||||||
|
checkIndex(aIndex);
|
||||||
|
return sqlite3_column_origin_name(mStmtPtr, aIndex);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Internal class : shared pointer to the sqlite3_stmt SQLite Statement Object
|
// Internal class : shared pointer to the sqlite3_stmt SQLite Statement Object
|
||||||
@ -332,7 +314,7 @@ Statement::Ptr::Ptr(sqlite3* apSQLite, std::string& aQuery) :
|
|||||||
mpStmt(NULL),
|
mpStmt(NULL),
|
||||||
mpRefCount(NULL)
|
mpRefCount(NULL)
|
||||||
{
|
{
|
||||||
int ret = sqlite3_prepare_v2(apSQLite, aQuery.c_str(), static_cast<int>(aQuery.size()), &mpStmt, NULL);
|
const int ret = sqlite3_prepare_v2(apSQLite, aQuery.c_str(), static_cast<int>(aQuery.size()), &mpStmt, NULL);
|
||||||
if (SQLITE_OK != ret)
|
if (SQLITE_OK != ret)
|
||||||
{
|
{
|
||||||
throw SQLite::Exception(sqlite3_errmsg(mpSQLite));
|
throw SQLite::Exception(sqlite3_errmsg(mpSQLite));
|
||||||
|
@ -18,115 +18,131 @@
|
|||||||
|
|
||||||
|
|
||||||
TEST(Statement, invalid) {
|
TEST(Statement, invalid) {
|
||||||
remove("test.db3");
|
// Create a new database
|
||||||
{
|
SQLite::Database db(":memory:", SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
|
||||||
// Create a new database
|
EXPECT_EQ(SQLITE_OK, db.getErrorCode());
|
||||||
SQLite::Database db("test.db3", SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
|
EXPECT_EQ(SQLITE_OK, db.getExtendedErrorCode());
|
||||||
EXPECT_EQ(SQLITE_OK, db.getErrorCode());
|
|
||||||
EXPECT_EQ(SQLITE_OK, db.getExtendedErrorCode());
|
|
||||||
|
|
||||||
// Compile a SQL query, but without any table in the database
|
// Compile a SQL query, but without any table in the database
|
||||||
EXPECT_THROW(SQLite::Statement query(db, "SELECT * FROM test"), SQLite::Exception);
|
EXPECT_THROW(SQLite::Statement query(db, "SELECT * FROM test"), SQLite::Exception);
|
||||||
EXPECT_EQ(SQLITE_ERROR, db.getErrorCode());
|
EXPECT_EQ(SQLITE_ERROR, db.getErrorCode());
|
||||||
EXPECT_EQ(SQLITE_ERROR, db.getExtendedErrorCode());
|
EXPECT_EQ(SQLITE_ERROR, db.getExtendedErrorCode());
|
||||||
|
|
||||||
EXPECT_EQ(0, db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)"));
|
EXPECT_EQ(0, db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)"));
|
||||||
EXPECT_EQ(SQLITE_OK, db.getErrorCode());
|
EXPECT_EQ(SQLITE_OK, db.getErrorCode());
|
||||||
EXPECT_EQ(SQLITE_OK, db.getExtendedErrorCode());
|
EXPECT_EQ(SQLITE_OK, db.getExtendedErrorCode());
|
||||||
|
|
||||||
// Compile a SQL query with no parameter
|
// Compile a SQL query with no parameter
|
||||||
SQLite::Statement query(db, "SELECT * FROM test");
|
SQLite::Statement query(db, "SELECT * FROM test");
|
||||||
EXPECT_STREQ("SELECT * FROM test", query.getQuery().c_str());
|
EXPECT_STREQ("SELECT * FROM test", query.getQuery().c_str());
|
||||||
EXPECT_EQ(2, query.getColumnCount ());
|
EXPECT_EQ(2, query.getColumnCount ());
|
||||||
EXPECT_FALSE(query.isOk());
|
EXPECT_FALSE(query.isOk());
|
||||||
EXPECT_FALSE(query.isDone());
|
EXPECT_FALSE(query.isDone());
|
||||||
EXPECT_THROW(query.isColumnNull(-1), SQLite::Exception);
|
EXPECT_THROW(query.isColumnNull(-1), SQLite::Exception);
|
||||||
EXPECT_THROW(query.isColumnNull(0), SQLite::Exception);
|
EXPECT_THROW(query.isColumnNull(0), SQLite::Exception);
|
||||||
EXPECT_THROW(query.isColumnNull(1), SQLite::Exception);
|
EXPECT_THROW(query.isColumnNull(1), SQLite::Exception);
|
||||||
EXPECT_THROW(query.isColumnNull(2), SQLite::Exception);
|
EXPECT_THROW(query.isColumnNull(2), SQLite::Exception);
|
||||||
EXPECT_THROW(query.getColumn(-1), SQLite::Exception);
|
EXPECT_THROW(query.getColumn(-1), SQLite::Exception);
|
||||||
EXPECT_THROW(query.getColumn(0), SQLite::Exception);
|
EXPECT_THROW(query.getColumn(0), SQLite::Exception);
|
||||||
EXPECT_THROW(query.getColumn(1), SQLite::Exception);
|
EXPECT_THROW(query.getColumn(1), SQLite::Exception);
|
||||||
EXPECT_THROW(query.getColumn(2), SQLite::Exception);
|
EXPECT_THROW(query.getColumn(2), SQLite::Exception);
|
||||||
|
|
||||||
query.reset();
|
query.reset();
|
||||||
EXPECT_FALSE(query.isOk());
|
EXPECT_FALSE(query.isOk());
|
||||||
EXPECT_FALSE(query.isDone());
|
EXPECT_FALSE(query.isDone());
|
||||||
|
|
||||||
query.executeStep();
|
query.executeStep();
|
||||||
EXPECT_FALSE(query.isOk());
|
EXPECT_FALSE(query.isOk());
|
||||||
EXPECT_TRUE( query.isDone());
|
EXPECT_TRUE( query.isDone());
|
||||||
query.reset();
|
query.reset();
|
||||||
EXPECT_FALSE(query.isOk());
|
EXPECT_FALSE(query.isOk());
|
||||||
EXPECT_FALSE(query.isDone());
|
EXPECT_FALSE(query.isDone());
|
||||||
|
|
||||||
query.reset();
|
query.reset();
|
||||||
EXPECT_THROW(query.bind(-1, 123), SQLite::Exception);
|
EXPECT_THROW(query.bind(-1, 123), SQLite::Exception);
|
||||||
EXPECT_THROW(query.bind(0, 123), SQLite::Exception);
|
EXPECT_THROW(query.bind(0, 123), SQLite::Exception);
|
||||||
EXPECT_THROW(query.bind(1, 123), SQLite::Exception);
|
EXPECT_THROW(query.bind(1, 123), SQLite::Exception);
|
||||||
EXPECT_THROW(query.bind(2, 123), SQLite::Exception);
|
EXPECT_THROW(query.bind(2, 123), SQLite::Exception);
|
||||||
EXPECT_THROW(query.bind(0, "abc"), SQLite::Exception);
|
EXPECT_THROW(query.bind(0, "abc"), SQLite::Exception);
|
||||||
EXPECT_THROW(query.bind(0), SQLite::Exception);
|
EXPECT_THROW(query.bind(0), SQLite::Exception);
|
||||||
EXPECT_EQ(SQLITE_RANGE, db.getErrorCode());
|
EXPECT_EQ(SQLITE_RANGE, db.getErrorCode());
|
||||||
EXPECT_EQ(SQLITE_RANGE, db.getExtendedErrorCode());
|
EXPECT_EQ(SQLITE_RANGE, db.getExtendedErrorCode());
|
||||||
|
|
||||||
query.exec(); // exec() instead of executeStep() as there is no result
|
query.exec(); // exec() instead of executeStep() as there is no result
|
||||||
EXPECT_THROW(query.isColumnNull(0), SQLite::Exception);
|
EXPECT_THROW(query.isColumnNull(0), SQLite::Exception);
|
||||||
EXPECT_THROW(query.getColumn(0), SQLite::Exception);
|
EXPECT_THROW(query.getColumn(0), SQLite::Exception);
|
||||||
|
|
||||||
// Add a first row
|
// Add a first row
|
||||||
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"first\")"));
|
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"first\")"));
|
||||||
EXPECT_EQ(1, db.getLastInsertRowid());
|
EXPECT_EQ(1, db.getLastInsertRowid());
|
||||||
EXPECT_EQ(1, db.getTotalChanges());
|
EXPECT_EQ(1, db.getTotalChanges());
|
||||||
|
|
||||||
query.reset();
|
query.reset();
|
||||||
EXPECT_FALSE(query.isOk());
|
EXPECT_FALSE(query.isOk());
|
||||||
EXPECT_FALSE(query.isDone());
|
EXPECT_FALSE(query.isDone());
|
||||||
|
|
||||||
EXPECT_THROW(query.exec(), SQLite::Exception); // exec() shall throw as it does not expect a result
|
EXPECT_THROW(query.exec(), SQLite::Exception); // exec() shall throw as it does not expect a result
|
||||||
|
|
||||||
} // Close DB test.db3
|
|
||||||
remove("test.db3");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: test every kind of binding
|
||||||
|
|
||||||
TEST(Statement, getColumnByName) {
|
TEST(Statement, getColumnByName) {
|
||||||
remove("test.db3");
|
// Create a new database
|
||||||
{
|
SQLite::Database db(":memory:", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
|
||||||
// Create a new database
|
EXPECT_EQ(SQLITE_OK, db.getErrorCode());
|
||||||
SQLite::Database db("test.db3", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
|
EXPECT_EQ(SQLITE_OK, db.getExtendedErrorCode());
|
||||||
EXPECT_EQ(SQLITE_OK, db.getErrorCode());
|
|
||||||
EXPECT_EQ(SQLITE_OK, db.getExtendedErrorCode());
|
|
||||||
|
|
||||||
// Create a new table
|
// Create a new table
|
||||||
EXPECT_EQ(0, db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, msg TEXT, int INTEGER, double REAL)"));
|
EXPECT_EQ(0, db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, msg TEXT, int INTEGER, double REAL)"));
|
||||||
EXPECT_EQ(SQLITE_OK, db.getErrorCode());
|
EXPECT_EQ(SQLITE_OK, db.getErrorCode());
|
||||||
EXPECT_EQ(SQLITE_OK, db.getExtendedErrorCode());
|
EXPECT_EQ(SQLITE_OK, db.getExtendedErrorCode());
|
||||||
|
|
||||||
// Create a first row
|
// Create a first row
|
||||||
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"first\", 123, 0.123)"));
|
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"first\", 123, 0.123)"));
|
||||||
EXPECT_EQ(1, db.getLastInsertRowid());
|
EXPECT_EQ(1, db.getLastInsertRowid());
|
||||||
EXPECT_EQ(1, db.getTotalChanges());
|
EXPECT_EQ(1, db.getTotalChanges());
|
||||||
|
|
||||||
// Compile a SQL query
|
// Compile a SQL query
|
||||||
SQLite::Statement query(db, "SELECT * FROM test");
|
SQLite::Statement query(db, "SELECT * FROM test");
|
||||||
EXPECT_STREQ("SELECT * FROM test", query.getQuery().c_str());
|
EXPECT_STREQ("SELECT * FROM test", query.getQuery().c_str());
|
||||||
EXPECT_EQ(4, query.getColumnCount());
|
EXPECT_EQ(4, query.getColumnCount());
|
||||||
query.executeStep();
|
query.executeStep();
|
||||||
EXPECT_TRUE (query.isOk());
|
EXPECT_TRUE (query.isOk());
|
||||||
EXPECT_FALSE(query.isDone());
|
EXPECT_FALSE(query.isDone());
|
||||||
|
|
||||||
// Look for unexisting columns
|
// Look for unexisting columns
|
||||||
EXPECT_THROW(query.getColumn("unknown"), SQLite::Exception);
|
EXPECT_THROW(query.getColumn("unknown"), SQLite::Exception);
|
||||||
EXPECT_THROW(query.getColumn(""), SQLite::Exception);
|
EXPECT_THROW(query.getColumn(""), SQLite::Exception);
|
||||||
|
|
||||||
const std::string msg = query.getColumn("msg");
|
const std::string msg = query.getColumn("msg");
|
||||||
const int integer = query.getColumn("int");
|
const int integer = query.getColumn("int");
|
||||||
const double real = query.getColumn("double");
|
const double real = query.getColumn("double");
|
||||||
EXPECT_EQ("first", msg);
|
EXPECT_EQ("first", msg);
|
||||||
EXPECT_EQ(123, integer);
|
EXPECT_EQ(123, integer);
|
||||||
EXPECT_EQ(0.123, real);
|
EXPECT_EQ(0.123, real);
|
||||||
|
}
|
||||||
} // Close DB test.db3
|
|
||||||
remove("test.db3");
|
TEST(Statement, getName) {
|
||||||
|
// Create a new database
|
||||||
|
SQLite::Database db(":memory:", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
|
||||||
|
EXPECT_EQ(0, db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, msg TEXT)"));
|
||||||
|
|
||||||
|
// Compile a SQL query, using the "id" column name as-is, but aliasing the "msg" column with new name "value"
|
||||||
|
SQLite::Statement query(db, "SELECT id, msg as value FROM test");
|
||||||
|
query.executeStep();
|
||||||
|
|
||||||
|
const std::string name0 = query.getColumnName(0);
|
||||||
|
const std::string name1 = query.getColumnName(1);
|
||||||
|
EXPECT_EQ("id", name0);
|
||||||
|
EXPECT_EQ("value", name1);
|
||||||
|
|
||||||
|
#ifdef SQLITE_ENABLE_COLUMN_METADATA
|
||||||
|
// Show how to get origin names of the table columns from which theses result columns come from.
|
||||||
|
// Requires the SQLITE_ENABLE_COLUMN_METADATA preprocessor macro to be
|
||||||
|
// also defined at compile times of the SQLite library itself.
|
||||||
|
const std::string oname0 = query.getColumnOriginName(0);
|
||||||
|
const std::string oname1 = query.getColumnOriginName(1);
|
||||||
|
EXPECT_EQ("id", oname0);
|
||||||
|
EXPECT_EQ("msg", oname1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user