4 # define COUT std::cerr << "SQ3:"<<__FILE__ << ":" << std::dec<<__LINE__ << ": " 41 sqlite3_finalize( st );
58 return ((SQLITE_DONE==rc) || (SQLITE_OK==rc) || (SQLITE_ROW==rc));
64 return this->
prepare( sql.c_str(), static_cast<int>(sql.size()) );
70 const char *tail=NULL;
71 if( 0 > len ) len = static_cast<int>(strlen(sql));
72 sqlite3_stmt * st = 0;
75 #if (SQLITE_VERSION_NUMBER >= 3003009) 80 (this->m_db.
handle(), sql, len, &st, &tail);
84 this->m_argc = sqlite3_column_count(st);
85 this->m_stmt.take( st );
97 void const * tail = NULL;
98 if( 0 > byteCount ) byteCount = ????;
99 sqlite3_stmt * st = 0;
101 #if SQLITE_VERSION_NUMBER >= 3003009 106 (this->m_db.
handle(), sql, byteCount, &st, &tail);
107 if( SQLITE_OK == rc )
109 this->m_argc = sqlite3_column_count(st);
110 this->m_stmt.take(st);
119 #endif // SQ3_USE_WCHAR 124 int rc = SQLITE_ERROR;
125 if( this->m_stmt.get() )
129 this->m_stmt.take(0);
136 : m_db(db), m_stmt(0), m_argc(0)
141 : m_db(db), m_stmt(0), m_argc(0)
146 : m_db(db), m_stmt(0), m_argc(0)
148 this->
prepare( sql, byteCount );
153 : m_db(db), m_stmt(0), m_argc(0)
158 : m_db(db), m_stmt(0), m_argc(0)
160 this->
prepare( sql, byteCount );
162 #endif // SQ3_USE_WCHAR 167 return 0 != this->m_stmt.get();
175 return sqlite3_bind_null( this->m_stmt.get(), index);
179 return sqlite3_bind_int( this->m_stmt.get(), index, data );
183 return sqlite3_bind_int64( this->m_stmt.get(), index, data );
187 return sqlite3_bind_double( this->m_stmt.get(), index, data );
191 if( 0 > len ) len = static_cast<int>(strlen(data));
192 return sqlite3_bind_text( this->m_stmt.get(), index, data, len, SQLITE_TRANSIENT );
196 return sqlite3_bind_blob( this->m_stmt.get(), index, data, len, SQLITE_TRANSIENT );
201 return this->
bind( index, data.c_str(), static_cast<int>(data.size() ) );
207 return sqlite3_bind_null( this->m_stmt.get(),
208 sqlite3_bind_parameter_index( this->m_stmt.get(), index ) );
212 return sqlite3_bind_int( this->m_stmt.get(),
213 sqlite3_bind_parameter_index( this->m_stmt.get(), index ), data );
217 return sqlite3_bind_int64( this->m_stmt.get(),
218 sqlite3_bind_parameter_index( this->m_stmt.get(), index ), data );
222 return sqlite3_bind_double( this->m_stmt.get(),
223 sqlite3_bind_parameter_index( this->m_stmt.get(), index ), data );
227 if( 0 > len ) len = static_cast<int>(strlen(data) );
228 return sqlite3_bind_text( this->m_stmt.get(),
229 sqlite3_bind_parameter_index( this->m_stmt.get(), index ) , data, len, SQLITE_TRANSIENT );
233 return sqlite3_bind_blob( this->m_stmt.get(),
234 sqlite3_bind_parameter_index( this->m_stmt.get(), index ) , data, len, SQLITE_TRANSIENT );
239 return this->
bind( index, data.c_str(), static_cast<int>(data.size() ) );
255 #define STATEMENT_EXECUTE_1ARG_IMPL \ 256 cursor rd( this->get_cursor() ); \ 257 int rc = rd.step(); \ 258 if( SQLITE_ROW == rc ) \ 260 rc = rd.get(0,tgt); \ 266 STATEMENT_EXECUTE_1ARG_IMPL;
270 STATEMENT_EXECUTE_1ARG_IMPL;
274 STATEMENT_EXECUTE_1ARG_IMPL;
278 STATEMENT_EXECUTE_1ARG_IMPL;
280 #undef STATEMENT_EXECUTE_1ARG_IMPL 286 if( SQLITE_ROW == rc )
288 rc = rd.
get(0,tgt,len);
296 if( SQLITE_ROW == rc )
298 rc = rd.
get(0,tgt,len);
306 return this->m_stmt.get()
307 ? sqlite3_reset( this->m_stmt.get() )
313 return this->m_stmt.get()
321 if( -1 == count )
return 0;
322 if( (index < 0) || (index >= count) )
return 0;
323 return sqlite3_column_name(this->m_stmt.get(), index);
328 char const * c = this->
colname( index );
330 return c ? SQLITE_OK : SQLITE_ERROR;
344 this->m_stmt.take(&st);
349 if( &cp ==
this )
return *
this;
354 void cursor::copy(
cursor const & rhs )
356 if( &rhs ==
this )
return;
358 this->m_stmt = rhs.m_stmt;
361 this->m_cn =
new NameToIndexMap(*rhs.m_cn);
372 return this->m_stmt.get()
373 ? sqlite3_step(this->m_stmt->m_stmt.get())
381 return this->m_stmt.get()
382 ? this->m_stmt->reset()
387 this->m_stmt.take(0);
397 return this->m_stmt.get()
398 ? this->m_stmt->colcount()
402 #define CURSOR_CHECK_INDEX \ 403 if( ! this->m_stmt.get() ) return SQLITE_ERROR; \ 404 if( (index)>(this->m_stmt->m_argc-1)) return SQLITE_ERROR; 409 tgt = sqlite3_column_type( this->m_stmt->m_stmt.get(), index) == SQLITE_NULL;
416 tgt = sqlite3_column_int( this->m_stmt->m_stmt.get(), index );
422 tgt = sqlite3_column_int64( this->m_stmt->m_stmt.get(), index );
428 tgt = sqlite3_column_double( this->m_stmt->m_stmt.get(), index );
434 char const * x = (
const char*)sqlite3_column_text(this->m_stmt->m_stmt.get(), index);
435 int sz = sqlite3_column_bytes(this->m_stmt->m_stmt.get(), index);
438 tgt = std::string( x, x+sz );
449 sz = sqlite3_column_bytes(this->m_stmt->m_stmt.get(), index);
452 *tgt = sqlite3_column_text( this->m_stmt->m_stmt.get(), index);
463 sz = sqlite3_column_bytes(this->m_stmt->m_stmt.get(), index);
466 *tgt = sqlite3_column_blob(this->m_stmt->m_stmt.get(), index);
476 #define CURSOR_GET_STRING_IMPL2(vaR,targetNamE) \ 477 if( ! this->m_stmt.get() ) return SQLITE_ERROR; \ 478 if( 0 == this->index_colnames() ) return SQLITE_ERROR; \ 479 NameToIndexMap::const_iterator n2iit = this->m_cn->find( vaR ); \ 480 return ( this->m_cn->end() == n2iit ) ? SQLITE_ERROR : this->get( (*n2iit).second, targetNamE ); 486 #define CURSOR_GET_STRING_IMPL3(vaR,targetNamE,sizeNamE) \ 487 if( ! this->m_stmt.get() ) return SQLITE_ERROR; \ 488 if( 0 == this->index_colnames() ) return SQLITE_ERROR; \ 489 NameToIndexMap::const_iterator n2iit = this->m_cn->find( vaR ); \ 490 return ( this->m_cn->end() == n2iit ) ? SQLITE_ERROR : this->get( (*n2iit).second, targetNamE, sizeNamE ); 495 CURSOR_GET_STRING_IMPL2(key,tgt);
499 CURSOR_GET_STRING_IMPL2(key,tgt);
503 CURSOR_GET_STRING_IMPL2(key,tgt);
507 CURSOR_GET_STRING_IMPL2(key,tgt);
511 CURSOR_GET_STRING_IMPL3(key,tgt,sz);
513 int cursor::get( std::string
const & key,
void const ** tgt,
int & sz )
515 CURSOR_GET_STRING_IMPL3(key,tgt,sz);
522 int rc = this->
colname( index, &cn );
523 if( SQLITE_OK == rc )
532 return this->m_stmt->colname( index, cn );
536 #undef CURSOR_CHECK_INDEX 537 #undef CURSOR_GET_STRING_IMPL2 538 #undef CURSOR_GET_STRING_IMPL3 542 return this->m_dbh.get();
550 : m_dbh(0), m_name(dbname)
552 this->
open( dbname );
565 return 0 != this->m_dbh.get();
574 return this->m_dbh.take();
579 if( this->m_dbh.get() == dbh )
return;
582 this->m_dbh.take( dbh );
587 char const * m = this->m_dbh.get() ? sqlite3_errmsg( this->m_dbh.get() ) : 0;
593 if( ! dbn )
return SQLITE_ERROR;
595 if( this->m_dbh.get() )
598 if( 0 != rc )
return rc;
602 #if (SQLITE_VERSION_NUMBER >= 3005001) 605 rc = sqlite3_open(dbn, &sq);
609 rc = sqlite3_open_v2( dbn, &sq, flags, NULL );
612 {
int bogus; bogus = flags; }
613 rc = sqlite3_open(dbn, &sq);
614 #endif // sqlite3 >= 3.5.1 615 if( SQLITE_OK == rc )
617 this->m_dbh.take( sq );
620 if( SQLITE_OK != rc )
629 return this->
open( dbn.c_str(), flags );
642 int rc = sqlite3_open16(dbn, &this->m_db);
644 sqlite3_open(dbn, &sq);
645 if( SQLITE_OK == rc )
647 this->m_dbh.take( sq );
650 if( SQLITE_OK != rc )
659 return this->
open( dbn.c_str() );
661 #endif // SQ3_USE_WCHAR 665 if(0 == this->m_dbh.get())
return SQLITE_ERROR;
668 return sqlite3_close( this->m_dbh.take() );
679 return this->m_dbh.get()
680 ? sqlite3_last_insert_rowid(this->m_dbh.get())
686 return this->m_dbh.get()
687 ? sqlite3_changes(this->m_dbh.get())
693 return this->m_dbh.get()
694 ? sqlite3_busy_timeout(this->m_dbh.get(), ms)
769 int database::execute( std::string
const & sql, sqlite3_callback callback,
void * data, std::string & errmsg )
771 return this->
execute( sql.c_str(), callback, data, errmsg );
774 int database::execute(
char const * sql, sqlite3_callback callback,
void * data, std::string & errmsg )
781 ret = sqlite3_exec( this->m_dbh.get(), sql, callback, data, &cerrmsg );
788 sqlite3_free( cerrmsg );
795 sqlite3_free( cerrmsg );
803 return this->
execute( sql, callback, data, ignored );
808 std::string s( sql ? sql :
"" );
810 return this->
execute( s, callback, data, ignored );
816 std::ostringstream os;
817 os <<
"pragma " << code;
818 std::string sql( os.str() );
819 return this->
execute( sql.c_str() );
824 return this->
execute(
"vacuum" );
833 char const * parts[] = {
"view",
"trigger",
"table", 0 };
835 typedef std::vector<std::string> CmdList;
838 for(
int i = 0; i < 3; ++i )
840 statement master(*
this,
"select name from sqlite_master where type=? and name not like 'sqlite_%'");
841 rc = master.
bind( 1, parts[i] );
844 while( SQLITE_ROW == cur.step() )
847 rc = cur.get(0,
name);
849 list.push_back( std::string(
"drop ") + parts[i] +
"'" +
name +
"'" );
852 CmdList::const_iterator it = list.begin();
853 CmdList::const_iterator et = list.end();
854 for( ; et != it; ++it )
856 std::string cmd = *it;
870 transaction::transaction(
database & db,
bool start )
871 : m_db(db), m_intrans(false)
873 if( start ) this->
begin();
883 if( this->m_intrans )
887 int rc = this->m_db.
execute(
"begin");
888 this->m_intrans = (SQLITE_DONE == rc) || (SQLITE_OK == rc);
894 if( ! this->m_intrans )
898 int rc = this->m_db.
execute(
"commit");
899 if( SQLITE_BUSY != rc )
903 this->m_intrans =
false;
909 if( ! this->m_intrans )
913 this->m_intrans =
false;
914 return this->m_db.
execute(
"rollback");
917 int cursor::index_colnames()
921 this->m_cn =
new NameToIndexMap;
924 if( ! this->m_cn->empty() )
932 for(
int i = 0; i < cc; ++i, ++pos )
935 if( SQLITE_OK != this->
colname( i, &cname ) )
940 (*this->m_cn)[std::string(cname ? cname :
"")] = i;
int finalize()
Finizalizes the underlying prepared statement, freeing its resources.
Encapsulates a connection to an sqlite database.
~statement()
Calls this->finalize()
char const * colname(int index)
On success, it returns the null-terminated column name of the given column.
int execute(const std::string &sql)
Functionally identical to execute(char const *).
~cursor()
A curious side-effect which one needs to be aware of but very rarely is an issue:
char unsigned sqlite3_text_char_t
The published result codes from the sqlite3 API.
virtual int on_open()
This function is called when open() succeeds.
int bind(int index)
Binds NULL to the given placeholder index (1-based, not 0-based!).
void close()
"Disconnects" this object from the underlying result set, making this object useless for anything but...
int isnull(int index, bool &tgt)
If column index (0-based) is in bounds then this function check if the value of the given column inde...
cursor & operator=(cursor const &)
See the copy ctor.
void operator()(sqlite3 *&t)
Calls sqlite3_close(t) and assigns t to 0.
int vacuum()
Convenience wrapper around execute("vacuum").
int step()
Uses sqlite3_step() to step through this object's data set by one step.
int get(int index, int &tgt)
If column index (0-based) is in bounds then this function assigns tgt to the value of the given colum...
cursor get_cursor()
Returns a cursor object ready to step over the result set from this object.
sqlite3 * handle() const
The low-level handle to the sqlite db.
virtual int open(char const *, long flags=0)
Creates/opens the given db file.
int pragma(char const *code)
This is a convenience wrapper for execute( "pragma ..." ).
virtual ~database()
Closes this db.
void operator()(::sq3::statement *&t)
Calls t->reset() and assigns t to 0.
database()
Creates an unopened database.
cursor()
Creates an empty cursor, whose only valid use is to assign it from another cursor.
bool is_prepared() const
Use after construction to ensure that a statement was compiled.
int changes()
Returns the number of database rows that were changed (or inserted or deleted) by the most recently c...
std::string errormsg() const
Returns the last error message from sqlite, or an empty string if this object is not opened.
int execute()
Assumes this object's SQL statement is a single statement.
virtual int clear()
Looks through sqlite_master for a list of views, triggers, and tables, and drops them all (in that or...
int reset()
This is functionally the same as calling reset on the underlying prepared statement object to which t...
int commit()
Commits the active transaction.
The sq3 namespace encapsulates an OO sqlite3 API very similar to the sqlite3x API,...
int colcount()
Returns the column count of this prepared statement, or -1 on error.
bool rc_is_okay(int rc)
rc_is_okay() is an easy way to check if rc is one of SQLITE_OK, SQLITE_ROW, or SQLITE_DONE.
void operator()(sqlite3_stmt *&t)
Calls sqlite3_finalize(t) and assigns t to 0.
int begin()
Starts the transaction.
int setbusytimeout(int ms)
See sqlite3_busy_timeout().
int64_t insertid()
Returns the rowid of the most recently inserted row on this db.
int reset()
Calls sqlite3_reset() on the underlying statement handle and returns the result.
void operator()(sqlite3_stmt *&t)
Calls sqlite3_reset(t) and assigns t to 0.
int colname(int index, std::string &str)
Sets str to the column name as the given index (0-based).
int colcount()
Returns the column count of the underlying prepared statement.
sqlite3 * take_handle()
Transfers ownership of this->handle() to the caller.
statement(database &db)
Initializes a prepared statement without a query.
sqlite_int64 int64_t
The type used for signed 64-bit integer operations.
~transaction()
Calls this->rollback()
bool is_open() const
Returns true if this db is opened.
int close(bool force=false)
"Closes" this db.
This type is for stepping through a db query result.
int rollback()
Initiates a rollback and returns the result of executing a rollback command.
std::string name() const
Returns the name of the db file.
int prepare(std::string const &sql)
(Re-)prepares an SQL statement.