libsq3  2007.10.18
sq3.cpp
1 #if 0
2 # ifndef COUT
3 # include <iostream>
4 # define COUT std::cerr << "SQ3:"<<__FILE__ << ":" << std::dec<<__LINE__ << ": "
5 # endif
6 #endif
7 
8 #include "sq3.hpp"
9 #include <vector>
10 #include <sstream>
11 #include <cstring>
12 
13 #if SQ3_USE_WCHAR
14 #include <cwchar>
15 #endif
16 
17 namespace sq3 {
18 
20  {
21  if( st )
22  {
23  st->reset();
24  st = 0;
25  }
26  }
27 
28  void sqlite3_stmt_reset_finalizer::operator()( sqlite3_stmt * & st )
29  {
30  if( st )
31  {
32  sqlite3_reset( st );
33  st = 0;
34  }
35  }
36 
37  void sqlite3_stmt_finalizer::operator()( sqlite3_stmt * & st )
38  {
39  if( st )
40  {
41  sqlite3_finalize( st );
42  st = 0;
43  }
44  }
45 
46  void sqlite3_finalizer::operator()( sqlite3 * & s )
47  {
48  if( s )
49  {
50  sqlite3_close( s );
51  s = 0;
52  }
53  }
54 
55 
56  bool rc_is_okay( int rc )
57  {
58  return ((SQLITE_DONE==rc) || (SQLITE_OK==rc) || (SQLITE_ROW==rc));
59  }
60 
61 
62  int statement::prepare( std::string const & sql )
63  {
64  return this->prepare( sql.c_str(), static_cast<int>(sql.size()) );
65  }
66 
67  int statement::prepare( char const * sql, int len )
68  {
69  // FIXME: make this function clean up any existing sqlite3_stmt.
70  const char *tail=NULL;
71  if( 0 > len ) len = static_cast<int>(strlen(sql));
72  sqlite3_stmt * st = 0;
73 
74  int rc =
75 #if (SQLITE_VERSION_NUMBER >= 3003009)
76  sqlite3_prepare_v2
77 #else
78  sqlite3_prepare
79 #endif
80  (this->m_db.handle(), sql, len, &st, &tail);
81 
82  if( SQLITE_OK == rc )
83  {
84  this->m_argc = sqlite3_column_count(st);
85  this->m_stmt.take( st );
86  }
87  else
88  {
89  this->finalize();
90  }
91  return rc;
92  }
93 
94 #if SQ3_USE_WCHAR
95  int statement::prepare( sqlite3_wstring_t const sql, int byteCount )
96  {
97  void const * tail = NULL;
98  if( 0 > byteCount ) byteCount = ????;
99  sqlite3_stmt * st = 0;
100  int rc =
101 #if SQLITE_VERSION_NUMBER >= 3003009
102  sqlite3_prepare16_v2
103 #else
104  sqlite3_prepare16
105 #endif
106  (this->m_db.handle(), sql, byteCount, &st, &tail);
107  if( SQLITE_OK == rc )
108  {
109  this->m_argc = sqlite3_column_count(st);
110  this->m_stmt.take(st);
111  }
112  else
113  {
114  this->finalize();
115  }
116  return rc;
117 
118  }
119 #endif // SQ3_USE_WCHAR
120 
121 
123  {
124  int rc = SQLITE_ERROR;
125  if( this->m_stmt.get() )
126  {
127  rc = SQLITE_OK; // we'll fudge a bit here.
128  //sqlite3_finalize(this->m_stmt.get());
129  this->m_stmt.take(0); // give up ownership.
130  }
131  return rc;
132  }
133 
134 
136  : m_db(db), m_stmt(0), m_argc(0)
137  {
138  }
139 
140  statement::statement( database & db, std::string const & sql )
141  : m_db(db), m_stmt(0), m_argc(0)
142  {
143  this->prepare( sql );
144  }
145  statement::statement( database & db, char const * sql, int byteCount )
146  : m_db(db), m_stmt(0), m_argc(0)
147  {
148  this->prepare( sql, byteCount );
149  }
150 
151 #if SQ3_USE_WCHAR
152  statement::statement( database & db, std::wstring const & sql )
153  : m_db(db), m_stmt(0), m_argc(0)
154  {
155  this->prepare( sql );
156  }
157  statement::statement( database & db, wchar_t const * sql, int byteCount )
158  : m_db(db), m_stmt(0), m_argc(0)
159  {
160  this->prepare( sql, byteCount );
161  }
162 #endif // SQ3_USE_WCHAR
163 
164 
166  {
167  return 0 != this->m_stmt.get();
168  }
170  {
171  this->finalize();
172  }
173  int statement::bind( int index )
174  {
175  return sqlite3_bind_null( this->m_stmt.get(), index);
176  }
177  int statement::bind( int index, int data )
178  {
179  return sqlite3_bind_int( this->m_stmt.get(), index, data );
180  }
181  int statement::bind( int index, int64_t data )
182  {
183  return sqlite3_bind_int64( this->m_stmt.get(), index, data );
184  }
185  int statement::bind( int index, double data )
186  {
187  return sqlite3_bind_double( this->m_stmt.get(), index, data );
188  }
189  int statement::bind( int index, char const * data, int len )
190  {
191  if( 0 > len ) len = static_cast<int>(strlen(data));
192  return sqlite3_bind_text( this->m_stmt.get(), index, data, len, SQLITE_TRANSIENT );
193  }
194  int statement::bind( int index, void const * data, int len )
195  {
196  return sqlite3_bind_blob( this->m_stmt.get(), index, data, len, SQLITE_TRANSIENT );
197  }
198  //int statement::bind( int index, wchar_t const * data, int len );
199  int statement::bind( int index, std::string const & data )
200  {
201  return this->bind( index, data.c_str(), static_cast<int>(data.size() ) );
202  }
203  //int statement::bind( int index, std::wstring const & data );
204 
205  int statement::bind( char const * index )
206  {
207  return sqlite3_bind_null( this->m_stmt.get(),
208  sqlite3_bind_parameter_index( this->m_stmt.get(), index ) );
209  }
210  int statement::bind( char const * index, int data )
211  {
212  return sqlite3_bind_int( this->m_stmt.get(),
213  sqlite3_bind_parameter_index( this->m_stmt.get(), index ), data );
214  }
215  int statement::bind( char const * index, int64_t data )
216  {
217  return sqlite3_bind_int64( this->m_stmt.get(),
218  sqlite3_bind_parameter_index( this->m_stmt.get(), index ), data );
219  }
220  int statement::bind( char const * index, double data )
221  {
222  return sqlite3_bind_double( this->m_stmt.get(),
223  sqlite3_bind_parameter_index( this->m_stmt.get(), index ), data );
224  }
225  int statement::bind( char const * index, char const * data, int len )
226  {
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 );
230  }
231  int statement::bind( char const * index, void const * data, int len )
232  {
233  return sqlite3_bind_blob( this->m_stmt.get(),
234  sqlite3_bind_parameter_index( this->m_stmt.get(), index ) , data, len, SQLITE_TRANSIENT );
235  }
236 
237  int statement::bind( char const * index, std::string const & data )
238  {
239  return this->bind( index, data.c_str(), static_cast<int>(data.size() ) );
240  }
241 
242 
243 
244 
245 
247  {
248  return cursor(*this);
249  }
251  {
252  return this->get_cursor().step();
253  }
254 
255 #define STATEMENT_EXECUTE_1ARG_IMPL \
256  cursor rd( this->get_cursor() ); \
257  int rc = rd.step(); \
258  if( SQLITE_ROW == rc ) \
259  { \
260  rc = rd.get(0,tgt); \
261  } \
262  return rc;
263 
264  int statement::execute( int & tgt )
265  {
266  STATEMENT_EXECUTE_1ARG_IMPL;
267  }
269  {
270  STATEMENT_EXECUTE_1ARG_IMPL;
271  }
272  int statement::execute( double & tgt )
273  {
274  STATEMENT_EXECUTE_1ARG_IMPL;
275  }
276  int statement::execute( std::string & tgt )
277  {
278  STATEMENT_EXECUTE_1ARG_IMPL;
279  }
280 #undef STATEMENT_EXECUTE_1ARG_IMPL
281 
282  int statement::execute( sqlite3_text_char_t const ** tgt, int & len )
283  {
284  cursor rd( this->get_cursor() );
285  int rc = rd.step();
286  if( SQLITE_ROW == rc )
287  {
288  rc = rd.get(0,tgt,len);
289  }
290  return rc;
291  }
292  int statement::execute( void const ** tgt, int & len )
293  {
294  cursor rd( this->get_cursor() );
295  int rc = rd.step();
296  if( SQLITE_ROW == rc )
297  {
298  rc = rd.get(0,tgt,len);
299  }
300  return rc;
301  }
302 
303 
305  {
306  return this->m_stmt.get()
307  ? sqlite3_reset( this->m_stmt.get() )
308  : SQLITE_ERROR;
309  }
310 
312  {
313  return this->m_stmt.get()
314  ? this->m_argc
315  : -1;
316  }
317 
318  char const * statement::colname( int index )
319  {
320  int count = this->colcount();
321  if( -1 == count ) return 0;
322  if( (index < 0) || (index >= count) ) return 0;
323  return sqlite3_column_name(this->m_stmt.get(), index);
324  }
325 
326  int statement::colname( int index, char const ** cn )
327  {
328  char const * c = this->colname( index );
329  if( c ) *cn = c;
330  return c ? SQLITE_OK : SQLITE_ERROR;
331  }
332 
333 
334  cursor::cursor() : m_stmt(0),m_cn(0)
335  {
336  }
337  cursor::cursor( cursor const & cp ) : m_stmt(cp.m_stmt),m_cn(0)
338  {
339  this->copy(cp);
340  }
341 
342  cursor::cursor( statement & st ) : m_stmt(&st),m_cn(0)
343  {
344  this->m_stmt.take(&st);
345  }
346 
348  {
349  if( &cp == this ) return *this;
350  this->copy(cp);
351  return *this;
352  }
353 
354  void cursor::copy( cursor const & rhs )
355  {
356  if( &rhs == this ) return;
357  this->close();
358  this->m_stmt = rhs.m_stmt;
359  if( rhs.m_cn )
360  {
361  this->m_cn = new NameToIndexMap(*rhs.m_cn);
362  }
363  }
364 
366  {
367  this->close();
368  }
369 
371  {
372  return this->m_stmt.get()
373  ? sqlite3_step(this->m_stmt->m_stmt.get())
374  : SQLITE_ERROR;
375  }
376 
378  {
379  delete this->m_cn;
380  this->m_cn = 0;
381  return this->m_stmt.get()
382  ? this->m_stmt->reset()
383  : SQLITE_ERROR;
384  }
386  {
387  this->m_stmt.take(0);
388  if( this->m_cn )
389  {
390  delete this->m_cn;
391  this->m_cn = 0;
392  }
393  }
394 
396  {
397  return this->m_stmt.get()
398  ? this->m_stmt->colcount()
399  : -1;
400  }
401 
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;
405 
406  int cursor::isnull( int index, bool & tgt )
407  {
408  CURSOR_CHECK_INDEX;
409  tgt = sqlite3_column_type( this->m_stmt->m_stmt.get(), index) == SQLITE_NULL;
410  return SQLITE_OK;
411  }
412 
413  int cursor::get( int index, int & tgt )
414  {
415  CURSOR_CHECK_INDEX;
416  tgt = sqlite3_column_int( this->m_stmt->m_stmt.get(), index );
417  return SQLITE_OK;
418  }
419  int cursor::get( int index, int64_t & tgt )
420  {
421  CURSOR_CHECK_INDEX;
422  tgt = sqlite3_column_int64( this->m_stmt->m_stmt.get(), index );
423  return SQLITE_OK;
424  }
425  int cursor::get( int index, double & tgt )
426  {
427  CURSOR_CHECK_INDEX;
428  tgt = sqlite3_column_double( this->m_stmt->m_stmt.get(), index );
429  return SQLITE_OK;
430  }
431  int cursor::get( int index, std::string & tgt )
432  {
433  CURSOR_CHECK_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);
436  if( 0 < sz )
437  {
438  tgt = std::string( x, x+sz );
439  }
440  else
441  {
442  tgt = std::string();
443  }
444  return SQLITE_OK;
445  }
446  int cursor::get( int index, sqlite3_text_char_t const ** tgt, int & sz )
447  {
448  CURSOR_CHECK_INDEX;
449  sz = sqlite3_column_bytes(this->m_stmt->m_stmt.get(), index);
450  if( 0 < sz )
451  {
452  *tgt = sqlite3_column_text( this->m_stmt->m_stmt.get(), index);
453  }
454  else
455  {
456  tgt = 0;
457  }
458  return SQLITE_OK;
459  }
460  int cursor::get( int index, void const ** tgt, int & sz )
461  {
462  CURSOR_CHECK_INDEX;
463  sz = sqlite3_column_bytes(this->m_stmt->m_stmt.get(), index);
464  if( 0 < sz )
465  {
466  *tgt = sqlite3_column_blob(this->m_stmt->m_stmt.get(), index);
467  }
468  return SQLITE_OK;
469  }
470 
471 
472  /**
473  CURSOR_GET_STRING_IMPL2 is the implementation for the get(string,xxx) family of funcs
474  which take 2 arguments.
475  */
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 );
481 
482  /**
483  CURSOR_GET_STRING_IMPL3 is the implementation for the get(string,xxx) family of funcs
484  which take 3 arguments. It is *almost* identicle to CURSOR_GET_STRING_IMPL2.
485  */
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 );
491 
492 
493  int cursor::get( std::string const & key, int & tgt )
494  {
495  CURSOR_GET_STRING_IMPL2(key,tgt);
496  }
497  int cursor::get( std::string const & key, int64_t & tgt )
498  {
499  CURSOR_GET_STRING_IMPL2(key,tgt);
500  }
501  int cursor::get( std::string const & key, double & tgt )
502  {
503  CURSOR_GET_STRING_IMPL2(key,tgt);
504  }
505  int cursor::get( std::string const & key, std::string & tgt )
506  {
507  CURSOR_GET_STRING_IMPL2(key,tgt);
508  }
509  int cursor::get( std::string const & key, sqlite3_text_char_t const ** tgt, int & sz )
510  {
511  CURSOR_GET_STRING_IMPL3(key,tgt,sz);
512  }
513  int cursor::get( std::string const & key, void const ** tgt, int & sz )
514  {
515  CURSOR_GET_STRING_IMPL3(key,tgt,sz);
516  }
517 
518 
519  int cursor::colname( int index, std::string & tgt )
520  {
521  char const * cn = 0;
522  int rc = this->colname( index, &cn );
523  if( SQLITE_OK == rc )
524  {
525  tgt = cn ? cn : "";
526  }
527  return rc;
528  }
529 
530  int cursor::colname( int index, char const ** cn )
531  {
532  return this->m_stmt->colname( index, cn );
533  }
534 
535 
536 #undef CURSOR_CHECK_INDEX
537 #undef CURSOR_GET_STRING_IMPL2
538 #undef CURSOR_GET_STRING_IMPL3
539 
540  sqlite3 * database::handle() const
541  {
542  return this->m_dbh.get();
543  }
544  database::database() : m_dbh(0), m_name()
545  {
546  }
547 
548 
549  database::database( std::string const & dbname )
550  : m_dbh(0), m_name(dbname)
551  {
552  this->open( dbname );
553  }
554 
556  {
557  this->close();
558  }
559 
560 
561 
562 
563  bool database::is_open() const
564  {
565  return 0 != this->m_dbh.get();
566  }
567  std::string database::name() const
568  {
569  return this->m_name;
570  }
571 
573  {
574  return this->m_dbh.take();
575  }
576 
577  void database::take_handle( sqlite3 * dbh, std::string const & name )
578  {
579  if( this->m_dbh.get() == dbh ) return;
580  this->close();
581  this->m_name = name;
582  this->m_dbh.take( dbh );
583  }
584 
585  std::string database::errormsg() const
586  {
587  char const * m = this->m_dbh.get() ? sqlite3_errmsg( this->m_dbh.get() ) : 0;
588  return m ? m : "";
589  }
590 
591  int database::open( char const * dbn, long flags )
592  {
593  if( ! dbn ) return SQLITE_ERROR;
594  int rc = 0;
595  if( this->m_dbh.get() )
596  {
597  rc = this->close();
598  if( 0 != rc ) return rc;
599  }
600  this->m_name = dbn;
601  sqlite3 * sq = 0;
602 #if (SQLITE_VERSION_NUMBER >= 3005001)
603  if( ! flags )
604  {
605  rc = sqlite3_open(dbn, &sq);
606  }
607  else
608  {
609  rc = sqlite3_open_v2( dbn, &sq, flags, NULL );
610  }
611 #else
612  { int bogus; bogus = flags; } // avoid "unused variable: flags" warning from gcc
613  rc = sqlite3_open(dbn, &sq);
614 #endif // sqlite3 >= 3.5.1
615  if( SQLITE_OK == rc )
616  {
617  this->m_dbh.take( sq );
618  rc = this->on_open();
619  }
620  if( SQLITE_OK != rc )
621  {
622  this->close(); // ingore any close() failure in this case
623  }
624  return rc;
625  }
626 
627  int database::open( std::string const & dbn, long flags )
628  {
629  return this->open( dbn.c_str(), flags );
630  }
631 
633  {
634  return SQLITE_OK;
635  }
636 
637 #if SQ3_USE_WCHAR
638  int database::open( sqlite3_wstring_t dbn )
639  {
640  //std::wcerr << L"database::open(wchar_t " << dbn << L")\n";
641  this->close();
642  int rc = sqlite3_open16(dbn, &this->m_db);
643  sqlite3 * sq = 0;
644  sqlite3_open(dbn, &sq);
645  if( SQLITE_OK == rc )
646  {
647  this->m_dbh.take( sq );
648  rc = this->on_open();
649  }
650  if( SQLITE_OK != rc )
651  {
652  this->close();
653  }
654  return rc;
655  }
656 
657  int database::open( std::wstring const & dbn )
658  {
659  return this->open( dbn.c_str() );
660  }
661 #endif // SQ3_USE_WCHAR
662 
663  int database::close( bool force )
664  {
665  if(0 == this->m_dbh.get()) return SQLITE_ERROR;
666  if( force )
667  { // do immediately close:
668  return sqlite3_close( this->m_dbh.take() /* transfer ownership to sqlite3 */ );
669  }
670  else
671  { // --reference_count and queue up the close:
672  this->m_dbh.take(0); // drop existing handle.
673  return SQLITE_OK;
674  }
675  }
676 
678  {
679  return this->m_dbh.get()
680  ? sqlite3_last_insert_rowid(this->m_dbh.get())
681  : -1;
682  }
683 
685  {
686  return this->m_dbh.get()
687  ? sqlite3_changes(this->m_dbh.get())
688  : -1;
689  }
690 
692  {
693  return this->m_dbh.get()
694  ? sqlite3_busy_timeout(this->m_dbh.get(), ms)
695  : SQLITE_ERROR;
696  }
697 
698  int database::execute(const std::string &sql)
699  {
700  return statement( *this, sql ).execute();
701  }
702 
703  int database::execute(char const * sql )
704  {
705  return statement( *this, sql, -1 ).execute();
706  }
707 
708  int database::execute(char const * sql, int & tgt)
709  {
710  return statement( *this, sql ).execute( tgt );
711  }
712 
713  int database::execute(std::string const & sql, int & tgt)
714  {
715  return statement( *this, sql ).execute( tgt );
716  }
717 
718  int database::execute(char const * sql, int64_t & tgt)
719  {
720  return statement( *this, sql, -1 ).execute( tgt );
721  }
722 
723  int database::execute(std::string const & sql, int64_t & tgt)
724  {
725  return statement( *this, sql ).execute( tgt );
726  }
727 
728  int database::execute(char const * sql, double & tgt)
729  {
730  return statement( *this, sql, -1 ).execute( tgt );
731  }
732 
733  int database::execute(std::string const & sql, double & tgt)
734  {
735  return statement( *this, sql ).execute( tgt );
736  }
737 
738  int database::execute(char const * sql, std::string & tgt)
739  {
740  return statement( *this, sql ).execute( tgt );
741  }
742 
743  int database::execute(std::string const & sql, std::string & tgt)
744  {
745  return statement( *this, sql ).execute( tgt );
746  }
747 
748  int database::execute(char const * sql, sqlite3_text_char_t const ** tgt, int & len )
749  {
750  return statement( *this, sql ).execute( tgt, len );
751  }
752 
753  int database::execute(std::string const & sql, sqlite3_text_char_t const ** tgt, int & len )
754  {
755  return statement( *this, sql ).execute( tgt, len );
756  }
757 
758 // int database::execute(char const * sql, std::wstring & tgt);
759 // int database::execute(std::string const & sql, std::wstring & tgt);
760  int database::execute(char const * sql, void const ** tgt, int & len )
761  {
762  return statement( *this, sql ).execute( tgt, len );
763  }
764  int database::execute(std::string const & sql, void const ** tgt, int & len )
765  {
766  return statement( *this, sql ).execute( tgt, len );
767  }
768 
769  int database::execute( std::string const & sql, sqlite3_callback callback, void * data, std::string & errmsg )
770  {
771  return this->execute( sql.c_str(), callback, data, errmsg );
772  }
773 
774  int database::execute( char const * sql, sqlite3_callback callback, void * data, std::string & errmsg )
775  {
776  char * cerrmsg = 0;
777  int ret = 0;
778  try
779  {
780  // allow callback to safely throw.
781  ret = sqlite3_exec( this->m_dbh.get(), sql, callback, data, &cerrmsg );
782  }
783  catch( ... )
784  {
785  if( cerrmsg )
786  {
787  errmsg = cerrmsg;
788  sqlite3_free( cerrmsg );
789  }
790  throw;
791  }
792  if( cerrmsg )
793  {
794  errmsg = cerrmsg;
795  sqlite3_free( cerrmsg );
796  }
797  return ret;
798  }
799 
800  int database::execute( std::string const & sql, sqlite3_callback callback, void * data )
801  {
802  std::string ignored;
803  return this->execute( sql, callback, data, ignored );
804  }
805 
806  int database::execute( char const * sql, sqlite3_callback callback, void * data )
807  {
808  std::string s( sql ? sql : "" );
809  std::string ignored;
810  return this->execute( s, callback, data, ignored );
811  }
812 
813 
814  int database::pragma( char const * code )
815  {
816  std::ostringstream os;
817  os << "pragma " << code;
818  std::string sql( os.str() );
819  return this->execute( sql.c_str() );
820  }
821 
823  {
824  return this->execute( "vacuum" );
825  }
826 
828  {
829  if( ! this->is_open() )
830  {
831  return SQLITE_ERROR;
832  }
833  char const * parts[] = { "view", "trigger", "table", 0 };
834  std::string name;
835  typedef std::vector<std::string> CmdList;
836  CmdList list;
837  int rc = SQLITE_OK;
838  for( int i = 0; i < 3; ++i )
839  {
840  statement master(*this,"select name from sqlite_master where type=? and name not like 'sqlite_%'");
841  rc = master.bind( 1, parts[i] );
842  if( ! rc_is_okay(rc) ) return rc;
843  cursor cur(master.get_cursor());
844  while( SQLITE_ROW == cur.step() )
845  {
846  name = "";
847  rc = cur.get(0, name);
848  if( ! rc_is_okay(rc) ) return rc;
849  list.push_back( std::string("drop ") + parts[i] + "'" + name + "'" );
850  }
851  }
852  CmdList::const_iterator it = list.begin();
853  CmdList::const_iterator et = list.end();
854  for( ; et != it; ++it )
855  {
856  std::string cmd = *it;
857  rc = this->execute( cmd );
858  }
859  return rc;
860  }
861 
862 
863 
864 
865 
866 
867 
868 
869 
870  transaction::transaction( database & db, bool start )
871  : m_db(db), m_intrans(false)
872  {
873  if( start ) this->begin();
874  }
875 
877  {
878  this->rollback();
879  }
880 
882  {
883  if( this->m_intrans )
884  {
885  return SQLITE_ERROR;
886  }
887  int rc = this->m_db.execute("begin");
888  this->m_intrans = (SQLITE_DONE == rc) || (SQLITE_OK == rc);
889  return rc;
890  }
891 
893  {
894  if( ! this->m_intrans )
895  {
896  return SQLITE_ERROR;
897  }
898  int rc = this->m_db.execute("commit");
899  if( SQLITE_BUSY != rc )
900  {
901  // According to the sqlite3 docs, if a COMMIT fails with BUSY
902  // then the transaction is still open.
903  this->m_intrans = false;
904  }
905  return rc;
906  }
908  {
909  if( ! this->m_intrans )
910  {
911  return SQLITE_ERROR;
912  }
913  this->m_intrans = false;
914  return this->m_db.execute("rollback");
915  }
916 
917  int cursor::index_colnames()
918  {
919  if( ! this->m_cn )
920  {
921  this->m_cn = new NameToIndexMap;
922  }
923  else
924  if( ! this->m_cn->empty() )
925  {
926  // We're using a cached result
927  return -1;
928  }
929  char const * cname;
930  int cc = this->colcount();
931  int pos = 0;
932  for( int i = 0; i < cc; ++i, ++pos )
933  {
934  cname = 0;
935  if( SQLITE_OK != this->colname( i, &cname ) )
936  //if( ! (cname = this->m_stmt->colname( i ) ) )
937  {
938  break;
939  }
940  (*this->m_cn)[std::string(cname ? cname : "")] = i;
941  }
942  return pos;
943  }
944 
945 
946 } // namespace