#if defined(DBA_ENABLE_SQLITE) ////////////////////////////////////////////////////////////////////// // Copyright (c) 2010, Oliver 'kfs1' Smith // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // - Neither the name of KingFisher Software nor the names of its contributors // may be used to endorse or promote products derived from this software // without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ////////////////////////////////////////////////////////////////////// // #include "dbaConn.h" // Main include file #include namespace DBA { ////////////////////////////////////////////////////////////////////// // Constructor for SQLiteConnection type SQLiteConnection::SQLiteConnection() : Connection() , m_conn(NULL) , m_result(NULL) { } ////////////////////////////////////////////////////////////////////// // Destructor: Ensure resource cleanup. SQLiteConnection::~SQLiteConnection() { if ( m_result != NULL ) ReleaseResult() ; if ( m_conn != NULL ) Disconnect() ; } ////////////////////////////////////////////////////////////////////// // Connect to an SQLite database. void SQLiteConnection::Connect(const Credentials& credentials, unsigned int flags, bool autoReconnect /* = false */) { sqlite3* conn = NULL ; // If the user didn't supply a driver, open wants a NULL. const char* vfs = (credentials.driver == NULL || credentials.driver[0] == 0 ? NULL : credentials.driver) ; int result = sqlite3_open_v2(credentials.database, &conn, flags, vfs) ; if ( result != SQLITE_OK ) { std::stringstream error ; error << "Unable to open database '" << credentials.database << "': " ; ThrowError(error.rdbuf()->str().c_str()) ; } m_conn = conn ; } ////////////////////////////////////////////////////////////////////// // Disconnect from SQLite database void SQLiteConnection::Disconnect() { if ( m_currentResult != NULL ) m_currentResult->Release() ; _releaseResultSet() ; if ( m_conn ) { sqlite3_close(m_conn) ; m_conn = NULL ; } } ////////////////////////////////////////////////////////////////////// // Clean up the result set. void SQLiteConnection::_releaseResultSet() { if ( m_result ) { sqlite3_finalize(m_result) ; m_result = NULL ; } } ////////////////////////////////////////////////////////////////////// // Execute an SQL statement void SQLiteConnection::_execute(size_t stlen, const char* statement) { m_error = sqlite3_prepare_v2(m_conn, statement, stlen, &m_result, NULL) ; if ( m_error != SQLITE_OK ) { ThrowError("Statement Error: ") ; } } ////////////////////////////////////////////////////////////////////// // Process results that were retrieved with execute. void SQLiteConnection::_processResultSet() { m_error = sqlite3_step(m_result) ; m_affectedRows = (size_t)sqlite3_changes(m_conn) ; m_lastInsertID = (size_t)sqlite3_last_insert_rowid(m_conn) ; // Didn't return a row. if ( m_error != SQLITE_ROW ) { return ; } // Set the number of rows to be 1, and the current row to 0 // this makes it look like there is at least one row available. m_rows = 1 ; m_currentRow = 0 ; m_cols = sqlite3_column_count(m_result) ; } ////////////////////////////////////////////////////////////////////// // Attempt to retrieve the next row. bool SQLiteConnection::FetchRow() { m_currentColumn = 0 ; if ( m_currentRow > 0 ) { if ( m_currentRow >= m_rows ) return false ; // SQLite fetches the first row in _processResults, // so we only need to fetch rows after the first. m_error = sqlite3_step(m_result) ; } // Did we reach the last row? if ( m_error == SQLITE_DONE ) { sqlite3_reset(m_result) ; m_rows = m_currentRow ; return false ; } // SQLite returns SQLITE_ROW for "not the last row". if ( m_error != SQLITE_ROW ) { ThrowError("Error retrieving row: ") ; } ++m_currentRow ; ++m_rows ; return true ; } } ; // namespace DBA #endif // DBA_ENABLE_SQLITE