//  // //  #### # # # -= SQLiteX =-  // // # # ## ## Query.cpp  // //  ## # ###  // //  ## # ### SQL transaction  // //  # # ## ##  // // #### ##### # # R1 (C)2005 Markus Ewald -> License.txt  // //  // #include "SQLiteX/Query.h" #include "SQLiteX/Errors.h" using namespace SQLiteX; // ############################################################################################# // // # SQLiteX::Query::Query() # // // ############################################################################################# // /** Initializes an SQLite transaction @param sStatement Statements for the query; optional */ Query::Query(const std::string &sStatements) : m_SQLStatements(sStatements + ";\n") {} // ############################################################################################# // // # SQLiteX::Query::~Query() # // // ############################################################################################# // /** Cleans up any memory reserved for variable bindings */ Query::~Query() {} // ############################################################################################# // // # SQLiteX::Query::add() # // // ############################################################################################# // /** Appends one or more SQL statements to the query @param sStatements Statements to be appended to the query */ void Query::add(const std::string &sStatements) { m_SQLStatements += sStatements; } // ############################################################################################# // // # SQLiteX::Query::execute() # // // ############################################################################################# // /** Executes the query @param SQLiteDB Database on which to operate; provided by an inverse call from the database */ void Query::execute(const SharedSQLite3 &SQLiteDB) { m_Results.clear(); // Execute all SQL statements contained in this transaction const char *pNext = m_SQLStatements.c_str(); while(*pNext) { sqlite3_stmt *pStatement; checkError(SQLiteDB, ::sqlite3_prepare( SQLiteDB, pNext, static_cast(m_SQLStatements.length()), &pStatement, &pNext )); // Empty lines construct NULL statements which can be skipped if(pStatement) { /// Bind all host parameters bindVariables(SQLiteDB, pStatement); // Ensure that the statement is finalized in all cases struct StatementFinalizer { StatementFinalizer(sqlite3_stmt *pStatement) : m_pStatement(pStatement) {} ~StatementFinalizer() { ::sqlite3_finalize(m_pStatement); } sqlite3_stmt *m_pStatement; } finalize_Statement(pStatement); // Execute the statement until it is completed int ErrorCode; do { ErrorCode = ::sqlite3_step(pStatement); if(ErrorCode == SQLITE_ROW) { VariantDeque Values; for( size_t ColumnIndex = 0; ColumnIndex < static_cast(::sqlite3_column_count(pStatement)); ++ColumnIndex ) { switch(::sqlite3_column_type(pStatement, static_cast(ColumnIndex))) { case SQLITE_NULL: { Values.push_back(Variant()); break; } case SQLITE_INTEGER: { Values.push_back( ::sqlite3_column_int(pStatement, static_cast(ColumnIndex)) ); break; } case SQLITE_FLOAT: { Values.push_back( ::sqlite3_column_double(pStatement, static_cast(ColumnIndex)) ); break; } case SQLITE_TEXT: { Values.push_back(std::string( reinterpret_cast(::sqlite3_column_text( pStatement, static_cast(ColumnIndex) )), ::sqlite3_column_bytes(pStatement, static_cast(ColumnIndex)) )); break; } case SQLITE_BLOB: { std::vector Data( ::sqlite3_column_bytes(pStatement, static_cast(ColumnIndex)) ); std::memcpy( &Data[0], ::sqlite3_column_blob(pStatement, static_cast(ColumnIndex)), Data.size() ); Values.push_back(Data); break; } } } m_Results.push_back(Values); } } while(ErrorCode == SQLITE_ROW); checkError(SQLiteDB, ErrorCode); } } } // ############################################################################################# // // # SQLiteX::Query::bindVariables() # // // ############################################################################################# // void Query::bindVariables(sqlite3 *pSQLiteDB, sqlite3_stmt *pStatement) { for(size_t Index = 1; Index < m_BoundVariables.size(); ++Index) { switch(m_BoundVariables[Index].getType()) { case Variant::T_NULL: { checkError(pSQLiteDB, ::sqlite3_bind_null( pStatement, static_cast(Index) )); break; } case Variant::T_INT: { checkError(pSQLiteDB, ::sqlite3_bind_int( pStatement, static_cast(Index), static_cast(m_BoundVariables[Index]) )); break; } case Variant::T_FLOAT: { checkError(pSQLiteDB, ::sqlite3_bind_double( pStatement, static_cast(Index), static_cast(m_BoundVariables[Index]) )); break; } case Variant::T_TEXT: { std::string sValue = static_cast(m_BoundVariables[Index]); checkError(pSQLiteDB, ::sqlite3_bind_text( pStatement, static_cast(Index), sValue.c_str(), static_cast(sValue.length()), SQLITE_TRANSIENT )); break; } case Variant::T_BLOB: { std::vector Data = static_cast >(m_BoundVariables[Index]); checkError(pSQLiteDB, ::sqlite3_bind_blob( pStatement, static_cast(Index), &Data[0], static_cast(Data.size()), SQLITE_TRANSIENT )); break; } } } }