/* _______ .__ .__ .__ .__ \ \ ____ __ __ _______ |__|| | | | |__| ____ ____ / | \ _/ __ \ | | \\_ __ \| || | | | | | / _ \ / \ / | \\ ___/ | | / | | \/| || |__| |__| |( <_> )| | \ \____|__ / \___ >|____/ |__| |__||____/|____/|__| \____/ |___| / =========\/======\/=================================================\/== v0.01 04/JUL/2007 © Copyright 2007-2007 Scott D. Yelich SOME RIGHTS RESERVED .,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.-*~'`^`'~*-,._.,-*~'`^`'~*-,. LICENSE: Creative Commons Attribution 3.0 License. SEE: http://creativecommons.org/licenses/by/3.0/ Tue Aug 21 20:44:09 EDT 2007, v0.01 sdy Thu Aug 23 23:29:36 EDT 2007, v0.04 sdy This is the third version of simple class to facilitate working with sqlite3 from C++. The first verion used the convenience function sqlite3_get_table which kept the entire result set in memory. The second version used the legacy "exec" and a "two-step" double callback with the fisrt being a static member function receiving a passed in void* pointer that was static cast to Xql3 and then called a virtual callback. Wow, fugly. Buried in the docs, it states that use of "prepare" plus "step" is the new and preferred method of accessing the sqlite3 system, so although the legacy exec did just this, there were a few other legacy dependencies and if those were changed, it would probably break some code. Therefore, this class will implement an "exec" that is similar to the legacy exec. This exec will call a virtual callback that if not overridden, simply returns (ie: returned results are ignored). This version of the class handles multi-part SQL statements. */ // C++ #include // PACKAGE #include "Xql3.h" Xql3::Xql3() { } Xql3::~Xql3() { int rc = 0; try { if (stmt) { rc = sqlite3_finalize(stmt); } Xql3::close(); } catch (Xql3Exception & e) { std::cerr << "Xql3Exception in Xql3::~Xql3() ..." << std::endl; } } int Xql3::open ( std::string const & name ) { _db_name = name.c_str(); int rc = 0; if (rc = sqlite3_open(_db_name, &_db)) { throw Xql3Exception(1, "open"); } /* if (rc = sqlite3_busy_timeout(_db, 25)) { // 25ms? throw Xql3Exception(2, "set busy timeout"); } */ if (rc = sqlite3_busy_handler(_db, Xql3::busy, this)) { throw Xql3Exception(3, "set busy handler"); } return rc; } int Xql3::close ( ) { int rc = 0; if (_db) { if (stmt) { rc = sqlite3_finalize(stmt); } if (rc = sqlite3_close(_db) ) { throw Xql3Exception(4, "close"); } _db = 0; } return rc; } int Xql3::callback(std::vector & headers, std::vector & data ) { std::cout << "Xql3::callback()\n"; return 0; } int Xql3::busy(void*,int cnt) { std::cerr << "Xql3::busy() --> "< headers; std::vector data; if ( sql_text.size() == 0 ) { return rc; } int i; int ncols; stmt = 0; const char * zSql; const char * zLeftover = sql_text.c_str(); while (1) { // loop for all sql statements ... stmt = 0; zSql = zLeftover; if (!zSql[0]) { break; } if ( SQLITE_OK != ( rc = sqlite3_prepare(_db, zSql, -1, &stmt, &zLeftover))) { throw Xql3Exception(5, "prepare"); } if (!stmt) { // parsed blank or comment? continue; } ncols = sqlite3_column_count(stmt); while (1) { // loop for all results of an individual statement ... rc = sqlite3_step(stmt); if (SQLITE_ROW == rc) { if (0 == headers.size()) { for(i=0; i " << dberrmsg() << std::endl; rc = sqlite3_finalize(stmt); stmt = 0; zSql = zLeftover; while (isspace((unsigned char)zSql[0])) zSql++; break; } } } if (stmt) sqlite3_finalize(stmt); return rc; }