mksqlite  2.5
A MATLAB interface to SQLite
sql_interface.hpp
Go to the documentation of this file.
1 
18 #pragma once
19 
20 //#include "config.h"
21 //#include "global.hpp"
22 //#include "sqlite/sqlite3.h"
24 //#include "utils.hpp"
25 //#include "value.hpp"
26 //#include "locale.hpp"
27 #include <map>
28 
29 // Handling Ctrl+C functions, see also http://undocumentedmatlab.com/blog/mex-ctrl-c-interrupt
30 extern "C" bool utIsInterruptPending();
31 extern "C" bool utSetInterruptEnabled( bool );
32 extern "C" bool utSetInterruptHandled( bool );
33 
35 typedef vector<ValueSQLCol> ValueSQLCols;
36 
37 extern ValueMex createItemFromValueSQL( const ValueSQL& value, int& err_id ); /* mksqlite.cpp */
38 extern ValueSQL createValueSQLFromItem( const ValueMex& item, bool bStreamable, int& iTypeComplexity, int& err_id ); /* mksqlite.cpp */
39 
40 class SQLstack;
41 class SQLiface;
42 class MexFunctors;
43 
44 
46 class SQLerror : public Err
47 {
48 public:
50  void setSqlError( sqlite3* dbid, int rc )
51  {
52  if( SQLITE_OK == rc )
53  {
54  clear();
55  }
56  else
57  {
58  if( rc < 0 )
59  {
60  rc = sqlite3_extended_errcode( dbid );
61  }
62  set_printf( sqlite3_errmsg( dbid ), trans_err_to_ident( rc ) );
63  }
64  }
65 
69  const char* trans_err_to_ident( int errorcode )
70  {
71  static char dummy[32];
72 
73  //int errorcode = sqlite3_extended_errcode( m_db );
74 
75  switch( errorcode )
76  {
77  case SQLITE_OK: return( "SQLITE:OK" );
78  case SQLITE_ERROR: return( "SQLITE:ERROR" );
79  case SQLITE_INTERNAL: return( "SQLITE:INTERNAL" );
80  case SQLITE_PERM: return( "SQLITE:PERM" );
81  case SQLITE_ABORT: return( "SQLITE:ABORT" );
82  case SQLITE_BUSY: return( "SQLITE:BUSY" );
83  case SQLITE_LOCKED: return( "SQLITE:LOCKED" );
84  case SQLITE_NOMEM: return( "SQLITE:NOMEM" );
85  case SQLITE_READONLY: return( "SQLITE:READONLY" );
86  case SQLITE_INTERRUPT: return( "SQLITE:INTERRUPT" );
87  case SQLITE_IOERR: return( "SQLITE:IOERR" );
88  case SQLITE_CORRUPT: return( "SQLITE:CORRUPT" );
89  case SQLITE_NOTFOUND: return( "SQLITE:NOTFOUND" );
90  case SQLITE_FULL: return( "SQLITE:FULL" );
91  case SQLITE_CANTOPEN: return( "SQLITE:CANTOPEN" );
92  case SQLITE_PROTOCOL: return( "SQLITE:PROTOCOL" );
93  case SQLITE_EMPTY: return( "SQLITE:EMPTY" );
94  case SQLITE_SCHEMA: return( "SQLITE:SCHEMA" );
95  case SQLITE_TOOBIG: return( "SQLITE:TOOBIG" );
96  case SQLITE_CONSTRAINT: return( "SQLITE:CONSTRAINT" );
97  case SQLITE_MISMATCH: return( "SQLITE:MISMATCH" );
98  case SQLITE_MISUSE: return( "SQLITE:MISUSE" );
99  case SQLITE_NOLFS: return( "SQLITE:NOLFS" );
100  case SQLITE_AUTH: return( "SQLITE:AUTH" );
101  case SQLITE_FORMAT: return( "SQLITE:FORMAT" );
102  case SQLITE_RANGE: return( "SQLITE:RANGE" );
103  case SQLITE_NOTADB: return( "SQLITE:NOTADB" );
104  case SQLITE_NOTICE: return( "SQLITE:NOTICE" );
105  case SQLITE_WARNING: return( "SQLITE:WARNING" );
106  case SQLITE_ROW: return( "SQLITE:ROW" );
107  case SQLITE_DONE: return( "SQLITE:DONE" );
108  /* extended codes */
109  case SQLITE_IOERR_READ: return( "SQLITE:IOERR_READ" );
110  case SQLITE_IOERR_SHORT_READ: return( "SQLITE:IOERR_SHORT_READ" );
111  case SQLITE_IOERR_WRITE: return( "SQLITE:IOERR_WRITE" );
112  case SQLITE_IOERR_FSYNC: return( "SQLITE:IOERR_FSYNC" );
113  case SQLITE_IOERR_DIR_FSYNC: return( "SQLITE:IOERR_DIR_FSYNC" );
114  case SQLITE_IOERR_TRUNCATE: return( "SQLITE:IOERR_TRUNCATE" );
115  case SQLITE_IOERR_FSTAT: return( "SQLITE:IOERR_FSTAT" );
116  case SQLITE_IOERR_UNLOCK: return( "SQLITE:IOERR_UNLOCK" );
117  case SQLITE_IOERR_RDLOCK: return( "SQLITE:IOERR_RDLOCK" );
118  case SQLITE_IOERR_DELETE: return( "SQLITE:IOERR_DELETE" );
119  case SQLITE_IOERR_BLOCKED: return( "SQLITE:IOERR_BLOCKED" );
120  case SQLITE_IOERR_NOMEM: return( "SQLITE:IOERR_NOMEM" );
121  case SQLITE_IOERR_ACCESS: return( "SQLITE:IOERR_ACCESS" );
122  case SQLITE_IOERR_CHECKRESERVEDLOCK: return( "SQLITE:IOERR_CHECKRESERVEDLOCK" );
123  case SQLITE_IOERR_LOCK: return( "SQLITE:IOERR_LOCK" );
124  case SQLITE_IOERR_CLOSE: return( "SQLITE:IOERR_CLOSE" );
125  case SQLITE_IOERR_DIR_CLOSE: return( "SQLITE:IOERR_DIR_CLOSE" );
126  case SQLITE_IOERR_SHMOPEN: return( "SQLITE:IOERR_SHMOPEN" );
127  case SQLITE_IOERR_SHMSIZE: return( "SQLITE:IOERR_SHMSIZE" );
128  case SQLITE_IOERR_SHMLOCK: return( "SQLITE:IOERR_SHMLOCK" );
129  case SQLITE_IOERR_SHMMAP: return( "SQLITE:IOERR_SHMMAP" );
130  case SQLITE_IOERR_SEEK: return( "SQLITE:IOERR_SEEK" );
131  case SQLITE_IOERR_DELETE_NOENT: return( "SQLITE:IOERR_DELETE_NOENT" );
132  case SQLITE_IOERR_MMAP: return( "SQLITE:IOERR_MMAP" );
133  case SQLITE_IOERR_GETTEMPPATH: return( "SQLITE:IOERR_GETTEMPPATH" );
134  case SQLITE_IOERR_CONVPATH: return( "SQLITE:IOERR_CONVPATH" );
135  case SQLITE_LOCKED_SHAREDCACHE: return( "SQLITE:LOCKED_SHAREDCACHE" );
136  case SQLITE_BUSY_RECOVERY: return( "SQLITE:BUSY_RECOVERY" );
137  case SQLITE_BUSY_SNAPSHOT: return( "SQLITE:BUSY_SNAPSHOT" );
138  case SQLITE_CANTOPEN_NOTEMPDIR: return( "SQLITE:CANTOPEN_NOTEMPDIR" );
139  case SQLITE_CANTOPEN_ISDIR: return( "SQLITE:CANTOPEN_ISDIR" );
140  case SQLITE_CANTOPEN_FULLPATH: return( "SQLITE:CANTOPEN_FULLPATH" );
141  case SQLITE_CANTOPEN_CONVPATH: return( "SQLITE:CANTOPEN_CONVPATH" );
142  case SQLITE_CORRUPT_VTAB: return( "SQLITE:CORRUPT_VTAB" );
143  case SQLITE_READONLY_RECOVERY: return( "SQLITE:READONLY_RECOVERY" );
144  case SQLITE_READONLY_CANTLOCK: return( "SQLITE:READONLY_CANTLOCK" );
145  case SQLITE_READONLY_ROLLBACK: return( "SQLITE:READONLY_ROLLBACK" );
146  case SQLITE_READONLY_DBMOVED: return( "SQLITE:READONLY_DBMOVED" );
147  case SQLITE_ABORT_ROLLBACK: return( "SQLITE:ABORT_ROLLBACK" );
148  case SQLITE_CONSTRAINT_CHECK: return( "SQLITE:CONSTRAINT_CHECK" );
149  case SQLITE_CONSTRAINT_COMMITHOOK: return( "SQLITE:CONSTRAINT_COMMITHOOK" );
150  case SQLITE_CONSTRAINT_FOREIGNKEY: return( "SQLITE:CONSTRAINT_FOREIGNKEY" );
151  case SQLITE_CONSTRAINT_FUNCTION: return( "SQLITE:CONSTRAINT_FUNCTION" );
152  case SQLITE_CONSTRAINT_NOTNULL: return( "SQLITE:CONSTRAINT_NOTNULL" );
153  case SQLITE_CONSTRAINT_PRIMARYKEY: return( "SQLITE:CONSTRAINT_PRIMARYKEY" );
154  case SQLITE_CONSTRAINT_TRIGGER: return( "SQLITE:CONSTRAINT_TRIGGER" );
155  case SQLITE_CONSTRAINT_UNIQUE: return( "SQLITE:CONSTRAINT_UNIQUE" );
156  case SQLITE_CONSTRAINT_VTAB: return( "SQLITE:CONSTRAINT_VTAB" );
157  case SQLITE_CONSTRAINT_ROWID: return( "SQLITE:CONSTRAINT_ROWID" );
158  case SQLITE_NOTICE_RECOVER_WAL: return( "SQLITE:NOTICE_RECOVER_WAL" );
159  case SQLITE_NOTICE_RECOVER_ROLLBACK: return( "SQLITE:NOTICE_RECOVER_ROLLBACK" );
160  case SQLITE_WARNING_AUTOINDEX: return( "SQLITE:WARNING_AUTOINDEX" );
161  case SQLITE_AUTH_USER: return( "SQLITE:AUTH_USER" );
162 
163  default:
164  _snprintf( dummy, sizeof( dummy ), "SQLITE:ERRNO%d", errorcode );
165  return dummy;
166  }
167  }
168 };
169 
170 
173 {
174  ValueMex m_functors[3];
177 
180 
182  MexFunctors( const MexFunctors& other )
183  {
184  ValueMex exception = other.m_pexception->Duplicate();
185  *this = MexFunctors( exception, other.getFunc(FCN), other.getFunc(STEP), other.getFunc(FINAL) );
186  m_group_data = other.m_group_data;
187  }
188 
189 
190 public:
191 
192  bool m_busy;
193  enum {FCN, STEP, FINAL};
194 
195 
197  MexFunctors( ValueMex& exception, const ValueMex& func, const ValueMex& step, const ValueMex& final )
198  {
199  m_busy = false;
200 
201  m_functors[FCN] = ValueMex(func).Duplicate();
202  m_functors[STEP] = ValueMex(step).Duplicate();
203  m_functors[FINAL] = ValueMex(final).Duplicate();
204 
205  for( int i = 0; i < 3; i++ )
206  {
207  // Prevent function handles to be deleted when mex function returns
208  // (MATLAB automatically deletes arrays, allocated in mex functions)
209  m_functors[i].MakePersistent();
210  }
211 
212  initGroupData();
213  m_pexception = &exception;
214  }
215 
216 
219  {
220  *this = MexFunctors( *other.m_pexception, other.getFunc(FCN), other.getFunc(STEP), other.getFunc(FINAL) );
221  m_group_data = other.m_group_data;
222  }
223 
224 
227  {
228  for( int i = 0; i < 3; i++ )
229  {
230  m_functors[i] = other.m_functors[i];
231  }
232  m_group_data = other.m_group_data;
233  m_pexception = other.m_pexception;
234  }
235 
236 
239  {
240  if( this != &other )
241  {
242  *this = MexFunctors( other );
243  }
244  return *this;
245  }
246 
247 
250  {
251  if( this != &other )
252  {
253  *this = MexFunctors( other );
254  }
255  return *this;
256  }
257 
258 
261  {
262  for( int i = 0; i < 3; i++ )
263  {
264  m_functors[i].Destroy();
265  }
266 
267  m_group_data.Destroy();
268 
269 #ifndef NDEBUG
270  PRINTF( "%s\n", "Functors destroyed" );
271 #endif
272  }
273 
274 
276  void swapException( ValueMex& exception )
277  {
278  std::swap( *m_pexception, exception );
279  }
280 
281 
284  {
285  m_group_data.Destroy();
286  m_group_data = ValueMex::CreateCellMatrix( 0, 0 );
287  m_group_data.MakePersistent();
288  }
289 
290 
293  {
294  return m_group_data;
295  }
296 
297 
299  const ValueMex& getFunc(int nr) const
300  {
301  return m_functors[nr];
302  }
303 
304 
306  ValueMex dupFunc(int nr) const
307  {
308  return ValueMex( getFunc(nr) ).Duplicate();
309  }
310 
311 
313  bool checkFunc(int nr) const
314  {
315  return ValueMex( getFunc(nr) ).IsFunctionHandle();
316  }
317 
318 
320  bool IsEmpty() const
321  {
322  return m_functors[FCN].IsEmpty() && m_functors[STEP].IsEmpty() && m_functors[FINAL].IsEmpty();
323  }
324 
325 
327  bool IsValid() const
328  {
329  for( int i = 0; i < 3; i++ )
330  {
331  if( m_functors[i].IsEmpty() )
332  {
333  continue;
334  }
335 
336  if( !m_functors[i].IsFunctionHandle() || m_functors[i].NumElements() != 1 )
337  {
338  return false;
339  }
340  }
341 
342  if( IsEmpty() )
343  {
344  return false;
345  }
346 
347  return true;
348  }
349 };
350 
351 
354 {
355  typedef map<string, MexFunctors*> MexFunctorsMap;
356 
357  sqlite3* m_db;
358  MexFunctorsMap m_fcnmap;
360 
361 public:
362 
364  SQLstackitem() : m_db( NULL )
365  {}
366 
367 
370  {
371  SQLerror err;
372  closeDb( err );
373  }
374 
375 
377  sqlite3* dbid()
378  {
379  return m_db;
380  }
381 
384  {
385  return m_exception;
386  }
387 
388 
391  {
392  m_exception.Throw();
393  }
394 
395 
397  MexFunctorsMap& fcnmap()
398  {
399  return m_fcnmap;
400  }
401 
402 
404  static
405  int progressHandler( void* data )
406  {
407  // Ctrl+C pressed?
408  if( utIsInterruptPending() )
409  {
410  utSetInterruptHandled( true );
411  PRINTF( "%s\n", ::getLocaleMsg( MSG_ABORTED ) );
412  return 1;
413  }
414  return 0;
415  }
416 
417 
419  void setProgressHandler( bool enable = true )
420  {
421  const int N_INSTRUCTIONS = 1000;
422  sqlite3_progress_handler( m_db, enable ? N_INSTRUCTIONS : 0, &SQLstackitem::progressHandler, NULL );
423  }
424 
425 
434  bool openDb( const char* filename, int openFlags, SQLerror& err )
435  {
436  if( !closeDb( err ) )
437  {
438  return false;
439  }
440 
441  /*
442  * Open the database
443  * m_db is assigned by sqlite3_open_v2(), even if an error
444  * occures
445  */
446  unsigned char* filename_utf8 = NULL;
447  int filename_utf8_bytes = utils_latin2utf( (const unsigned char*)filename, NULL );
448 
449  if( filename_utf8_bytes )
450  {
451  filename_utf8 = (unsigned char*)MEM_ALLOC( filename_utf8_bytes, sizeof(char) );
452  utils_latin2utf( (const unsigned char*)filename, filename_utf8 );
453 
454  if( !filename_utf8 )
455  {
456  err.set( MSG_ERRMEMORY );
457  }
458  }
459 
460  if( filename_utf8 && !err.isPending() )
461  {
462  int rc = sqlite3_open_v2( (char*)filename_utf8, &m_db, openFlags, NULL );
463 
464  if( SQLITE_OK != rc )
465  {
466  err.setSqlError( m_db, -1 );
467  }
468 
469  sqlite3_extended_result_codes( m_db, true );
470  attachBuiltinFunctions();
471  utSetInterruptEnabled( true );
472  setProgressHandler( true );
473  }
474 
475  MEM_FREE( filename_utf8 );
476 
477  return !err.isPending();
478  }
479 
480 
482  bool closeDb( SQLerror& err )
483  {
484  // Deallocate functors
485  for( MexFunctorsMap::iterator it = m_fcnmap.begin(); it != m_fcnmap.end(); it++ )
486  {
487  delete it->second;
488  }
489  m_fcnmap.clear();
490 
491  // m_db may be NULL, since sqlite3_close with a NULL argument is a harmless no-op
492  int rc = sqlite3_close( m_db );
493  if( SQLITE_OK == rc )
494  {
495  m_db = NULL;
496  }
497  else
498  {
499  PRINTF( "%s\n", ::getLocaleMsg( MSG_ERRCANTCLOSE ) );
500  err.setSqlError( m_db, -1 ); /* not SQL_ERR_CLOSE */
501  }
502 
503  return !isOpen();
504  }
505 
506 
508  bool isOpen()
509  {
510  return NULL != m_db;
511  }
512 
513 
526  {
527  if( !isOpen() )
528  {
529  assert( false );
530  }
531  else
532  {
533  // attach new SQL commands to opened database
534  sqlite3_create_function( m_db, "pow", 2, SQLITE_UTF8, NULL, pow_func, NULL, NULL ); // power function (math)
535  sqlite3_create_function( m_db, "lg", 1, SQLITE_UTF8, NULL, lg_func, NULL, NULL ); // power function (math)
536  sqlite3_create_function( m_db, "ln", 1, SQLITE_UTF8, NULL, ln_func, NULL, NULL ); // power function (math)
537  sqlite3_create_function( m_db, "exp", 1, SQLITE_UTF8, NULL, exp_func, NULL, NULL ); // power function (math)
538  sqlite3_create_function( m_db, "regex", 2, SQLITE_UTF8, NULL, regex_func, NULL, NULL ); // regular expressions (MATCH mode)
539  sqlite3_create_function( m_db, "regex", 3, SQLITE_UTF8, NULL, regex_func, NULL, NULL ); // regular expressions (REPLACE mode)
540  sqlite3_create_function( m_db, "bdcratio", 1, SQLITE_UTF8, NULL, BDC_ratio_func, NULL, NULL ); // compression ratio (blob data compression)
541  sqlite3_create_function( m_db, "bdcpacktime", 1, SQLITE_UTF8, NULL, BDC_pack_time_func, NULL, NULL ); // compression time (blob data compression)
542  sqlite3_create_function( m_db, "bdcunpacktime", 1, SQLITE_UTF8, NULL, BDC_unpack_time_func, NULL, NULL ); // decompression time (blob data compression)
543  sqlite3_create_function( m_db, "md5", 1, SQLITE_UTF8, NULL, MD5_func, NULL, NULL ); // Message-Digest (RSA)
544  }
545  }
546 };
547 
548 
549 
550 
551 
552 
558 class SQLiface
559 {
561  sqlite3* m_db;
562  const char* m_command;
563  sqlite3_stmt* m_stmt;
565 
566 public:
567  friend class SQLerror;
568 
570  SQLiface( SQLstackitem& stackitem ) :
571  m_pstackitem( &stackitem ),
572  m_db( stackitem.dbid() ),
573  m_command( NULL ),
574  m_stmt( NULL )
575  {
576  // Multiple calls of sqlite3_initialize() are harmless no-ops
577  sqlite3_initialize();
578  }
579 
580 
583  {
584  closeStmt();
585  }
586 
587 
589  bool isOpen()
590  {
591  return NULL != m_db;
592  }
593 
594 
596  void clearErr()
597  {
598  m_lasterr.clear();
599  }
600 
601 
603  const char* getErr( const char** errid = NULL )
604  {
605  return m_lasterr.get( errid );
606  }
607 
608 
610  void setErr( int err_id )
611  {
612  m_lasterr.set( err_id );
613  }
614 
615 
617  void setSqlError( int rc )
618  {
619  m_lasterr.setSqlError( m_db, rc );
620  }
621 
622 
624  bool errPending()
625  {
626  return m_lasterr.isPending();
627  }
628 
629 
631  const char* getDbFilename( const char* database )
632  {
633  if( !isOpen() )
634  {
635  assert( false );
636  return false;
637  }
638 
639  return sqlite3_db_filename( m_db, database ? database : "MAIN" );
640  }
641 
642 
644  bool setBusyTimeout( int iTimeoutValue )
645  {
646  if( !isOpen() )
647  {
648  assert( false );
649  return false;
650  }
651 
652  int rc = sqlite3_busy_timeout( m_db, iTimeoutValue );
653  if( SQLITE_OK != rc )
654  {
655  setSqlError( rc );
656  return false;
657  }
658  return true;
659  }
660 
661 
663  bool getBusyTimeout( int& iTimeoutValue )
664  {
665  if( !isOpen() )
666  {
667  assert( false );
668  return false;
669  }
670 
671  int rc = sqlite3_busy_timeout( m_db, iTimeoutValue );
672  if( SQLITE_OK != rc )
673  {
674  setSqlError( rc );
675  return false;
676  }
677  return true;
678  }
679 
680 
682  bool setEnableLoadExtension( int flagOnOff )
683  {
684  if( !isOpen() )
685  {
686  assert( false );
687  return false;
688  }
689 
690  int rc = sqlite3_enable_load_extension( m_db, flagOnOff != 0 );
691  if( SQLITE_OK != rc )
692  {
693  setSqlError( rc );
694  return false;
695  }
696  return true;
697  }
698 
699 
701  void closeStmt()
702  {
703  if( m_stmt )
704  {
705  // sqlite3_reset() does not reset the bindings on a prepared statement!
706  sqlite3_clear_bindings( m_stmt );
707  sqlite3_reset( m_stmt );
708  sqlite3_finalize( m_stmt );
709  m_stmt = NULL;
710  m_command = NULL;
711  }
712  }
713 
714 
716  static
717  void mexFcnWrapper_FCN( sqlite3_context *ctx, int argc, sqlite3_value **argv )
718  {
719  mexFcnWrapper( ctx, argc, argv, MexFunctors::FCN );
720  }
721 
723  static
724  void mexFcnWrapper_STEP( sqlite3_context *ctx, int argc, sqlite3_value **argv )
725  {
726  mexFcnWrapper( ctx, argc, argv, MexFunctors::STEP );
727  }
728 
730  static
731  void mexFcnWrapper_FINAL( sqlite3_context *ctx )
732  {
733  mexFcnWrapper( ctx, 0, NULL, MexFunctors::FINAL );
734  }
735 
737  static
738  void mexFcnWrapper( sqlite3_context *ctx, int argc, sqlite3_value **argv, int func_nr )
739  {
740  MexFunctors* fcn = (MexFunctors*)sqlite3_user_data( ctx );
741  int nArgs = argc + 1 + (func_nr > MexFunctors::FCN); // Number of arguments for "feval"
742  ValueMex arg( ValueMex::CreateCellMatrix( 1, nArgs ) );
743  bool failed = false;
744 
745  assert( fcn && arg.Item() );
746 
747  if( !fcn->checkFunc(func_nr) )
748  {
749  arg.Destroy();
750  sqlite3_result_error( ctx, ::getLocaleMsg( MSG_INVALIDFUNCTION ), -1 );
751  failed = true;
752  }
753 
754  if( fcn->m_busy )
755  {
756  arg.Destroy();
757  sqlite3_result_error( ctx, ::getLocaleMsg( MSG_RECURSIVECALL ), -1 );
758  failed = true;
759  }
760 
761  // Transform SQL value arguments into a MATLAB cell array
762  for( int j = 0; j < nArgs && !failed; j++ )
763  {
764  int err_id = MSG_NOERROR;
765  int i = j;
766  ValueSQL value;
767  ValueMex item;
768 
769  if( j == 0 )
770  {
771  arg.SetCell( j, fcn->dupFunc(func_nr).Detach() );
772  continue;
773  }
774  i--;
775 
776  if( func_nr > MexFunctors::FCN )
777  {
778  if( j == 1 )
779  {
780  assert( fcn->getData().Item() );
781  arg.SetCell( j, fcn->getData().Duplicate().Detach() );
782  continue;
783  }
784  i--;
785  }
786 
787  switch( sqlite3_value_type( argv[i] ) )
788  {
789  case SQLITE_NULL:
790  break;
791 
792  case SQLITE_INTEGER:
793  value = ValueSQL( sqlite3_value_int64( argv[i] ) );
794  break;
795 
796  case SQLITE_FLOAT:
797  value = ValueSQL( sqlite3_value_double( argv[i] ) );
798  break;
799 
800  case SQLITE_TEXT:
801  {
802  char* str = (char*)utils_strnewdup( (const char*)sqlite3_value_text( argv[i] ), g_convertUTF8 );
803 
804  if( str )
805  {
806  value = ValueSQL( str );
807  break;
808  }
809  }
810 
811  case SQLITE_BLOB:
812  {
813  size_t bytes = sqlite3_value_bytes( argv[i] );
814 
815  item = ValueMex( (int)bytes, bytes ? 1 : 0, ValueMex::UINT8_CLASS );
816 
817  if( item.Data() )
818  {
819  if( bytes )
820  {
821  memcpy( item.Data(), sqlite3_value_blob( argv[i] ), bytes );
822  }
823 
824  value = ValueSQL( item.Detach() );
825  }
826  else
827  {
828  sqlite3_result_error( ctx, getLocaleMsg( MSG_ERRMEMORY ), -1 );
829  failed = true;
830  }
831 
832  break;
833  }
834 
835  default:
836  sqlite3_result_error( ctx, getLocaleMsg( MSG_UNKNWNDBTYPE ), -1 );
837  failed = true;
838  }
839 
840  if( failed )
841  {
842  value.Destroy();
843  }
844  else
845  {
846  // Cumulate arguments into a cell array
847  arg.SetCell( j, createItemFromValueSQL( value, err_id ).Detach() );
848 
849  if( MSG_NOERROR != err_id )
850  {
851  sqlite3_result_error( ctx, ::getLocaleMsg( err_id ), -1 );
852  failed = true;
853  }
854  }
855  }
856 
857  if( !failed )
858  {
859  ValueMex exception, item;
860  fcn->m_busy = true;
861  arg.Call( &item, &exception );
862  fcn->m_busy = false;
863 
864  if( !exception.IsEmpty() )
865  {
866  // Exception handling
867  fcn->swapException( exception );
868  sqlite3_result_error( ctx, "MATLAB Exception!", -1 );
869  failed = true;
870  }
871  else
872  {
873  if( func_nr == MexFunctors::STEP )
874  {
875  if( !item.IsEmpty() )
876  {
877  item.MakePersistent();
878  std::swap( fcn->getData(), item );
879  item.Destroy();
880  }
881  sqlite3_result_null( ctx );
882  }
883  else
884  {
885  if( !item.IsEmpty() )
886  {
887  int iTypeComplexity;
888  int err_id = MSG_NOERROR;
889 
890  ValueSQL value = createValueSQLFromItem( item, can_serialize(), iTypeComplexity, err_id );
891 
892  if( MSG_NOERROR != err_id )
893  {
894  Err err;
895  err.set( err_id );
896  sqlite3_result_error( ctx, err.get(), -1 );
897  }
898  else
899  {
900  switch( value.m_typeID )
901  {
902  case SQLITE_NULL:
903  sqlite3_result_null( ctx );
904  break;
905 
906  case SQLITE_FLOAT:
907  // scalar floating point value
908  sqlite3_result_double( ctx, item.GetScalar() );
909  break;
910 
911  case SQLITE_INTEGER:
912  if( (int)item.ClassID() == (int)ValueMex::INT64_CLASS )
913  {
914  // scalar integer value
915  sqlite3_result_int64( ctx, item.GetInt64() );
916  }
917  else
918  {
919  // scalar integer value
920  sqlite3_result_int( ctx, item.GetInt() );
921  }
922  break;
923 
924  case SQLITE_TEXT:
925  // string argument
926  // SQLite makes a local copy of the text (thru SQLITE_TRANSIENT)
927  sqlite3_result_text( ctx, value.m_text, -1, SQLITE_TRANSIENT );
928  break;
929 
930  case SQLITE_BLOB:
931  // SQLite makes a local copy of the blob (thru SQLITE_TRANSIENT)
932  sqlite3_result_blob( ctx, item.Data(),
933  (int)item.ByData(),
934  SQLITE_TRANSIENT );
935  break;
936 
937  case SQLITE_BLOBX:
938  // sqlite takes custody of the blob, even if sqlite3_bind_blob() fails
939  // the sqlite allocator provided blob memory
940  sqlite3_result_blob( ctx, value.Detach(),
941  (int)value.m_blobsize,
942  sqlite3_free );
943  break;
944 
945  default:
946  {
947  // all other (unsuppored types)
948  Err err;
949  err.set( MSG_INVALIDARG );
950  sqlite3_result_error( ctx, err.get(), - 1 );
951  break;
952  }
953  }
954  }
955  }
956  else
957  {
958  sqlite3_result_null( ctx );
959  }
960  }
961  }
962 
963  item.Destroy();
964  exception.Destroy();
965  }
966 
967  arg.Destroy();
968 
969  if( func_nr == MexFunctors::FINAL )
970  {
971  fcn->initGroupData();
972  }
973  }
974 
975 
979  bool attachMexFunction( const char* name, const ValueMex& func, const ValueMex& step, const ValueMex& final, ValueMex& exception )
980  {
981  if( !isOpen() )
982  {
983  assert( false );
984  }
985  else
986  {
987  MexFunctors* fcn = new MexFunctors( exception, func, step, final );
988  int rc = SQLITE_OK;
989  int action = -1;
990  bool failed = false;
991 
992  if( fcn->IsEmpty() )
993  {
994  // Remove function
995  rc = sqlite3_create_function( m_db, name, -1, SQLITE_UTF8, NULL, NULL, NULL, NULL );
996  action = 0;
997  }
998  else
999  {
1000  if( !fcn->IsValid() )
1001  {
1002  setErr( MSG_FCNHARGEXPCT );
1003  failed = true;
1004  }
1005  else
1006  {
1007  // Add function
1008  void (*xFunc)(sqlite3_context*,int,sqlite3_value**) = mexFcnWrapper_FCN;
1009  void (*xStep)(sqlite3_context*,int,sqlite3_value**) = mexFcnWrapper_STEP;
1010  void (*xFinal)(sqlite3_context*) = mexFcnWrapper_FINAL;
1011 
1012  if( fcn->getFunc(MexFunctors::FCN).IsEmpty() ) xFunc = NULL;
1013  if( fcn->getFunc(MexFunctors::STEP).IsEmpty() ) xStep = NULL;
1014  if( fcn->getFunc(MexFunctors::FINAL).IsEmpty() ) xFinal = NULL;
1015 
1016  rc = sqlite3_create_function( m_db, name, -1, SQLITE_UTF8, (void*)fcn, xFunc, xStep, xFinal );
1017  action = 1;
1018  }
1019  }
1020 
1021  if( SQLITE_OK != rc )
1022  {
1023  setSqlError( rc );
1024  failed = true;
1025  }
1026 
1027  if( !failed )
1028  {
1029  if( action >= 0 )
1030  {
1031  if( m_pstackitem->fcnmap().count(name) )
1032  {
1033 #ifndef NDEBUG
1034  PRINTF( "Deleting functors for %s\n", name );
1035 #endif
1036  delete m_pstackitem->fcnmap()[name];
1037  m_pstackitem->fcnmap().erase(name);
1038  }
1039  }
1040 
1041  if( action > 0 )
1042  {
1043  m_pstackitem->fcnmap()[name] = fcn;
1044  fcn = NULL;
1045  }
1046  }
1047 
1048  delete fcn;
1049 
1050  return !errPending();
1051  }
1052 
1053  return true;
1054  }
1055 
1056 
1062  bool setQuery( const char* query )
1063  {
1064  if( !isOpen() )
1065  {
1066  assert( false );
1067  return false;
1068  }
1069 
1070  /*
1071  * complete the query
1072  */
1073  // sqlite3_complete() returns 1 if the string is complete and valid...
1074  if( !sqlite3_complete( query ) )
1075  {
1076  setErr( MSG_INVQUERY );
1077  return false;
1078  }
1079 
1080  // Close previous statement, if any
1081  closeStmt();
1082 
1083  /*
1084  * and prepare it
1085  * if anything is wrong with the query, than complain about it.
1086  */
1087  int rc = sqlite3_prepare_v2( m_db, query, -1, &m_stmt, 0 );
1088  if( SQLITE_OK != rc )
1089  {
1090  setSqlError( rc );
1091  return false;
1092  }
1093 
1094  m_command = query;
1095  return true;
1096  }
1097 
1098 
1101  {
1102  return m_stmt ? sqlite3_bind_parameter_count( m_stmt ) : 0;
1103  }
1104 
1106  const char* getParameterName( int n )
1107  {
1108  return m_stmt ? sqlite3_bind_parameter_name( m_stmt, n ) : NULL;
1109  }
1110 
1113  {
1114  return m_stmt ? (long)sqlite3_last_insert_rowid(m_db) : 0;
1115  }
1116 
1117 
1120  {
1121  if( m_stmt )
1122  {
1123  sqlite3_clear_bindings( m_stmt );
1124  }
1125  }
1126 
1127 
1135  bool bindParameter( int index, const ValueMex& item, bool bStreamable )
1136  {
1137  int err_id = MSG_NOERROR;
1138  int iTypeComplexity;
1139  int rc;
1140 
1141  assert( isOpen() );
1142 
1143  ValueSQL value = createValueSQLFromItem( item, bStreamable, iTypeComplexity, err_id );
1144 
1145  if( MSG_NOERROR != err_id )
1146  {
1147  setErr( err_id );
1148  return false;
1149  }
1150 
1151  switch( value.m_typeID )
1152  {
1153  case SQLITE_NULL:
1154  rc = sqlite3_bind_null( m_stmt, index );
1155  if( SQLITE_OK != rc )
1156  {
1157  setSqlError( rc );
1158  }
1159  break;
1160 
1161  case SQLITE_FLOAT:
1162  // scalar floating point value
1163  rc = sqlite3_bind_double( m_stmt, index, item.GetScalar() );
1164  if( SQLITE_OK != rc )
1165  {
1166  setSqlError( rc );
1167  }
1168  break;
1169 
1170  case SQLITE_INTEGER:
1171  if( (int)item.ClassID() == (int)ValueMex::INT64_CLASS )
1172  {
1173  // scalar integer value
1174  rc = sqlite3_bind_int64( m_stmt, index, item.GetInt64() );
1175  if( SQLITE_OK != rc )
1176  {
1177  setSqlError( rc );
1178  }
1179  }
1180  else
1181  {
1182  // scalar integer value
1183  rc = sqlite3_bind_int( m_stmt, index, item.GetInt() );
1184  if( SQLITE_OK != rc )
1185  {
1186  setSqlError( rc );
1187  }
1188  }
1189  break;
1190 
1191  case SQLITE_TEXT:
1192  // string argument
1193  // SQLite makes a local copy of the text (thru SQLITE_TRANSIENT)
1194  rc = sqlite3_bind_text( m_stmt, index, value.m_text, -1, SQLITE_TRANSIENT );
1195  if( SQLITE_OK != rc )
1196  {
1197  setSqlError( rc );
1198  }
1199  break;
1200 
1201  case SQLITE_BLOB:
1202  // SQLite makes a local copy of the blob (thru SQLITE_TRANSIENT)
1203  rc = sqlite3_bind_blob( m_stmt, index, item.Data(),
1204  (int)item.ByData(),
1205  SQLITE_TRANSIENT );
1206  if( SQLITE_OK != rc )
1207  {
1208  setSqlError( rc );
1209  }
1210  break;
1211 
1212  case SQLITE_BLOBX:
1213  // sqlite takes custody of the blob, even if sqlite3_bind_blob() fails
1214  // the sqlite allocator provided blob memory
1215  rc = sqlite3_bind_blob( m_stmt, index, value.Detach(),
1216  (int)value.m_blobsize,
1217  sqlite3_free );
1218  if( SQLITE_OK != rc )
1219  {
1220  setSqlError( rc );
1221  }
1222  break;
1223 
1224  default:
1225  // all other (unsuppored types)
1226  setErr( MSG_INVALIDARG );
1227  break;
1228  }
1229 
1230  return !errPending();
1231  }
1232 
1233 
1235  int step()
1236  {
1237  return m_stmt ? sqlite3_step( m_stmt ) : SQLITE_ERROR;
1238  }
1239 
1240 
1242  int colCount()
1243  {
1244  return m_stmt ? sqlite3_column_count( m_stmt ) : 0;
1245  }
1246 
1247 
1254  int colType( int index )
1255  {
1256  return m_stmt ? sqlite3_column_type( m_stmt, index ) : -1;
1257  }
1258 
1259 
1261  sqlite3_int64 colInt64( int index )
1262  {
1263  return m_stmt ? sqlite3_column_int64( m_stmt, index ) : 0;
1264  }
1265 
1266 
1268  double colFloat( int index )
1269  {
1270  return m_stmt ? sqlite3_column_double( m_stmt, index ) : 0.0;
1271  }
1272 
1273 
1275  const unsigned char* colText( int index )
1276  {
1277  return m_stmt ? sqlite3_column_text( m_stmt, index ) : (const unsigned char*)"";
1278  }
1279 
1280 
1282  const void* colBlob( int index )
1283  {
1284  unsigned char* test = (unsigned char*)sqlite3_column_blob( m_stmt, index );
1285  return m_stmt ? sqlite3_column_blob( m_stmt, index ) : NULL;
1286  }
1287 
1288 
1290  size_t colBytes( int index )
1291  {
1292  return m_stmt ? sqlite3_column_bytes( m_stmt, index ) : 0;
1293  }
1294 
1295 
1297  const char* colName( int index )
1298  {
1299  return m_stmt ? sqlite3_column_name( m_stmt, index ) : "";
1300  }
1301 
1302 
1305  {
1307  char operator()( char a )
1308  {
1309  if( a >= 'a' && a <= 'z' ) return a;
1310  if( a >= 'A' && a <= 'Z' ) return a;
1311  if( a >= '0' && a <= '9' ) return a;
1312 
1313  return '_';
1314  }
1315  };
1316 
1317 
1331  {
1332  names.clear();
1333 
1334  // iterate columns
1335  for( int i = 0; i < colCount(); i++ )
1336  {
1337  pair<string,string> item( colName(i), colName(i) );
1338 
1339  // truncate column name if necessary
1340  item.second = item.second.substr( 0, g_namelengthmax );
1341 
1342  // only alphanumeric characters allowed, transform alias
1343  std::transform( item.second.begin(), item.second.end(), item.second.begin(), to_alphanum() );
1344 
1345  // fieldname must start with a valid letter
1346  if( !item.second.size() || !isalpha(item.second[0]) )
1347  {
1348  item.second = string("X") + item.second;
1349  }
1350 
1351  // Optionally ensure fieldnames are unambiguous
1352  if( g_check4uniquefields )
1353  {
1354  int loop = 0;
1355  int number = 1;
1356  string new_name(item.second);
1357 
1358  // break if more than 100 equal column names \literal
1359  while( loop < i && number < 100 )
1360  {
1361  // if name exists already, then append consecutive numbers to differ
1362  if( new_name == names[loop].second )
1363  {
1364  char* str_number = new char[g_namelengthmax+1];
1365  char* buffer = new char[g_namelengthmax+1];
1366  int str_number_len;
1367 
1368  // measure suffix length
1369  str_number_len = _snprintf( str_number, g_namelengthmax+1, "_%d", number );
1370  // truncate name if necessary and append suffix
1371  _snprintf( buffer, g_namelengthmax+1, "%.*s%s", g_namelengthmax - str_number_len, item.second.c_str(), str_number );
1372  new_name = buffer;
1373 
1374  delete[] str_number;
1375  delete[] buffer;
1376 
1377  loop = 0; // name is new, check again precedent
1378  number++;
1379 
1380  } else loop++;
1381  }
1382 
1383  // number may not exceed limit
1384  if( loop < i )
1385  {
1386  names.clear();
1387  setErr( MSG_ERRVARNAME );
1388  break;
1389  }
1390 
1391  item.second = new_name;
1392  }
1393 
1394  names.push_back( item );
1395  }
1396 
1397  return (int)names.size();
1398  }
1399 
1400 
1402  void reset()
1403  {
1404  if( m_stmt )
1405  {
1406  sqlite3_reset( m_stmt );
1407  }
1408  }
1409 
1410 
1412  void finalize()
1413  {
1414  if( m_stmt )
1415  {
1416  sqlite3_clear_bindings( m_stmt );
1417  sqlite3_finalize( m_stmt );
1418  m_stmt = NULL;
1419  }
1420  }
1421 
1422 
1432  bool fetch( ValueSQLCols& cols, bool initialize = false ) // kv69: enable for skipping initialization to accumulate query results
1433  {
1434  assert( isOpen() );
1435 
1436  if( initialize )
1437  {
1439 
1440  getColNames( names );
1441  cols.clear();
1442 
1443  // build column vectors
1444  for( int i = 0; i < (int)names.size(); i++ )
1445  {
1446  cols.push_back( ValueSQLCol(names[i]) );
1447  }
1448 
1449  names.clear();
1450  }
1451 
1452  // step through
1453  for( ; !errPending() ; )
1454  {
1455  /*
1456  * Advance to the next row
1457  */
1458  int step_res = step();
1459 
1460  if (step_res == SQLITE_DONE) // kv69 sqlite has finished executing
1461  {
1462  break;
1463  }
1464 
1465 
1466  if (step_res != SQLITE_ROW) // kv69 no other row ? this must be an error
1467  {
1468  setSqlError( step_res );
1469  break;
1470  }
1471 
1472  /*
1473  * get new memory for the result
1474  */
1475  for( int jCol = 0; jCol < (int)cols.size() && !errPending(); jCol++ )
1476  {
1477  // Init value as SQLITE_NULL;
1478  ValueSQL value;
1479 
1480  switch( colType( jCol ) )
1481  {
1482  case SQLITE_NULL:
1483  break;
1484 
1485  case SQLITE_INTEGER:
1486  value = ValueSQL( colInt64( jCol ) );
1487  break;
1488 
1489  case SQLITE_FLOAT:
1490  value = ValueSQL( colFloat( jCol ) );
1491  break;
1492 
1493  case SQLITE_TEXT:
1494  value = ValueSQL( (char*)utils_strnewdup( (const char*)colText( jCol ), g_convertUTF8 ) );
1495  break;
1496 
1497  case SQLITE_BLOB:
1498  {
1499  size_t bytes = colBytes( jCol );
1500 
1501  ValueMex item = ValueMex( (int)bytes, bytes ? 1 : 0, ValueMex::UINT8_CLASS );
1502 
1503  if( item.Item() )
1504  {
1505  if( bytes )
1506  {
1507  memcpy( item.Data(), colBlob( jCol ), bytes );
1508  }
1509  }
1510  else
1511  {
1512  setErr( MSG_ERRMEMORY );
1513  continue;
1514  }
1515 
1516  value = ValueSQL( item.Detach() );
1517  break;
1518  }
1519 
1520  default:
1521  setErr( MSG_UNKNWNDBTYPE );
1522  continue;
1523  }
1524 
1525  cols[jCol].append( value );
1526  }
1527  }
1528 
1529  if( errPending() )
1530  {
1531  cols.clear();
1532  return false;
1533  }
1534 
1535  return true;
1536  }
1537 
1538 };
bool setEnableLoadExtension(int flagOnOff)
Enable or disable load extensions.
Encapsulating a MATLAB mxArray.
Definition: value.hpp:178
void throwOnException()
(Re-)Throws an exception, if any occurred
size_t m_blobsize
Size of BLOB in bytes (only type SQLITE_BLOBX)
Definition: value.hpp:866
Class holding an exception array, the function map and the handle for one database.
int getParameterCount()
Returns the count of parameters the current statement expects.
bool isOpen()
Returns true, if database is opened.
void clearErr()
Clear recent error message.
MexFunctorsMap m_fcnmap
MEX function map with MATLAB functions for application-defined SQL functions.
const char * getErr(const char **errid=NULL)
Get recent error message.
static void mexFcnWrapper(sqlite3_context *ctx, int argc, sqlite3_value **argv, int func_nr)
Common wrapper for all user defined SQL functions.
void setErr(int err_id)
Sets an error by its ID (see MSG_IDS)
void ln_func(sqlite3_context *ctx, int argc, sqlite3_value **argv)
Natural logarithm function implementation.
bool isOpen()
Returns true, if database is open.
void set_printf(int iMessageNr, const char *strId,...)
Set error message by identifier (translations available) with printf arguments.
Definition: locale.hpp:218
MexFunctors(MexFunctors &&other)
Move Ctor.
mxClassID ClassID() const
Returns item class ID or mxUNKNOWN_CLASS if item is NULL.
Definition: value.hpp:520
ValueMex m_group_data
Data container for "step" and "final" functions.
MexFunctors()
inhibit standard Ctor
void swapException(ValueMex &exception)
Exchange exception stack information.
ValueMex createItemFromValueSQL(const ValueSQL &value, int &err_id)
Transfer fetched SQL value into MATLAB array.
Definition: mksqlite.cpp:260
bool closeDb(SQLerror &err)
Close database.
bool checkFunc(int nr) const
Check if function handle is valid (not empty and of functon handle class)
void closeStmt()
Closing current statement.
ValueMex * m_pexception
Exception stack information.
static ValueMex CreateCellMatrix(int m, int n)
Create a cell array.
Definition: value.hpp:298
ValueMex Duplicate() const
Returns a duplictae of the hosted MATLAB array.
Definition: value.hpp:371
bool IsEmpty() const
Check if one of the functors is empty.
void BDC_pack_time_func(sqlite3_context *ctx, int argc, sqlite3_value **argv)
BDCPackTime function implementation.
int colType(int index)
Returns the (prefered) type of one column for current statement.
const char * getParameterName(int n)
Returns the name for nth parameter.
int GetInt(int errval=0) const
Get integer value from item.
Definition: value.hpp:677
int m_typeID
Type of SQL value as integer ID.
Definition: value.hpp:865
SQLstackitem * m_pstackitem
pointer to current database
bool fetch(ValueSQLCols &cols, bool initialize=false)
Proceed a table fetch.
const char * getLocaleMsg(int iMsgNr)
Returns the translation for a defined message.
Definition: locale.hpp:480
void MakePersistent()
Make the MATLAB array persistent.
Definition: value.hpp:782
void Destroy()
Freeing memory space if having ownership.
Definition: value.hpp:1002
const unsigned char * colText(int index)
Returns a text value for least fetch and column number.
~MexFunctors()
Dtor.
mxArray * Detach()
Detach hosted MATLAB array.
Definition: value.hpp:381
static int progressHandler(void *data)
Progress handler (watchdog)
bool setQuery(const char *query)
Dispatch a SQL query.
MexFunctors & operator=(const MexFunctors &other)
Copy assignment.
void initGroupData()
Initialize data for "step" and "final" function.
void attachBuiltinFunctions()
Attach builtin functions to database object.
bool attachMexFunction(const char *name, const ValueMex &func, const ValueMex &step, const ValueMex &final, ValueMex &exception)
Attach application-defined function to database object.
const char * getDbFilename(const char *database)
Get the filename of current database.
double colFloat(int index)
Returns a floating point value for least fetch and column number.
const ValueMex & getFunc(int nr) const
Return one of the functors (function, init or final)
sqlite3 * m_db
SQLite db handle.
void clearBindings()
Clears all parameter bindings from current statement.
ValueMex dupFunc(int nr) const
Duplicate one of the functors (function, init or final)
size_t ByData() const
Returns data size in bytes.
Definition: value.hpp:511
void finalize()
Clear parameter bindings and finalize current statement.
void regex_func(sqlite3_context *ctx, int argc, sqlite3_value **argv)
Regular expression function implementation.
sqlite3_int64 GetInt64(int errval=0) const
Get 64 bit integer value from item.
Definition: value.hpp:708
const char * m_command
SQL query (no ownership, read-only!)
Class encapsulating a SQL field value.
Definition: value.hpp:862
SQLite interface.
MexFunctors(ValueMex &exception, const ValueMex &func, const ValueMex &step, const ValueMex &final)
Ctor.
MexFunctors(const MexFunctors &other)
Copy Ctor.
bool isPending()
Returns true, if the current error message is still not handled.
Definition: locale.hpp:285
#define MEM_FREE(ptr)
standard memory free function
Definition: global.hpp:158
ValueMex m_exception
MATALAB exception array, may be thrown when mksqlite function leaves.
const void * colBlob(int index)
Returns a BLOB for least fetch and column number.
void clear()
Reset error message.
Definition: locale.hpp:134
sqlite3_stmt * m_stmt
SQL statement (sqlite bridge)
MexFunctors(MexFunctors &other)
Copy Ctor.
void MD5_func(sqlite3_context *ctx, int argc, sqlite3_value **argv)
MD5 hashing implementation.
char operator()(char a)
Functor.
Class holding an error.
int g_namelengthmax
MATALAB specific globals.
Definition: global.hpp:260
bool can_serialize()
Returns true, if streaming is switched on (user setting) and serialization is accessible.
Definition: serialize.hpp:108
Helperclass for error message transport.
Definition: locale.hpp:116
bool errPending()
Returns true, if an unhandled error is pending.
bool m_busy
true, if function is in progress to prevent recursive calls
~SQLiface()
Dtor.
MexFunctorsMap & fcnmap()
Returns the function map for this database.
bool IsEmpty() const
Returns true if item is NULL or empty ([])
Definition: value.hpp:412
SQLstackitem()
Ctor.
int g_convertUTF8
Flag: String representation (utf8 or ansi)
Definition: global.hpp:253
vector< ValueSQLCol > ValueSQLCols
type for column container
sqlite3_int64 colInt64(int index)
Returns an integer value for least fetch and column number.
size_t colBytes(int index)
Returns the size of one value of least fetch and column number in bytes.
Converts one char to a printable (non-white-space) character.
static void mexFcnWrapper_STEP(sqlite3_context *ctx, int argc, sqlite3_value **argv)
Wrapper for SQL step function (aggregation)
void set(const char *strMsg, const char *strId=NULL)
Set error message to a constant string (without translation)
Definition: locale.hpp:150
ValueMex & getException()
Returns the exception array for this database.
void * Data() const
Returns pointer to raw data.
Definition: value.hpp:572
bool IsFunctionHandle() const
Returns true if m_pcItem is of type mxFUNCTION_CLASS.
Definition: value.hpp:475
bool openDb(const char *filename, int openFlags, SQLerror &err)
Opens (or create) database.
SQLite interface stack.
Definition: mksqlite.cpp:70
static void mexFcnWrapper_FCN(sqlite3_context *ctx, int argc, sqlite3_value **argv)
Wrapper for SQL function.
~SQLstackitem()
Dtor.
#define SQLITE_BLOBX
Identifier to flag another allocator as used for SQLITE_BLOB.
Definition: value.hpp:46
map< string, MexFunctors * > MexFunctorsMap
Dictionary: function name => function handles.
char * utils_strnewdup(const char *s, int flagConvertUTF8)
duplicate a string and recode from UTF8 to char due to flag flagConvertUTF8
Definition: utils.hpp:211
int utils_latin2utf(const unsigned char *s, unsigned char *buffer)
Convert char string to UTF-8 string.
Definition: utils.hpp:171
int colCount()
Returns the column count for current statement.
double GetScalar() const
Definition: value.hpp:726
Functors for SQL application-defined (aggregation) functions.
void setSqlError(sqlite3 *dbid, int rc)
Set error by its result code.
void pow_func(sqlite3_context *ctx, int argc, sqlite3_value **argv)
Power function implementation.
bool setBusyTimeout(int iTimeoutValue)
Sets the busy timemout in milliseconds.
Class encapsulating a complete SQL table column with type and name.
Definition: value.hpp:1039
void BDC_unpack_time_func(sqlite3_context *ctx, int argc, sqlite3_value **argv)
BDCUnpackTime function implementation.
void Throw()
Throws an exception if any occured.
Definition: value.hpp:795
const char * trans_err_to_ident(int errorcode)
Get least SQLite error code and return identifier as string.
const mxArray * Item() const
Returns hosted MATLAB array.
Definition: value.hpp:351
void lg_func(sqlite3_context *ctx, int argc, sqlite3_value **argv)
Logarithm function to base 10 implementation.
void exp_func(sqlite3_context *ctx, int argc, sqlite3_value **argv)
Exponential function implementation.
bool bindParameter(int index, const ValueMex &item, bool bStreamable)
Binds one parameter from current statement to a MATLAB array.
void setProgressHandler(bool enable=true)
Installing progress handler to enable aborting by Ctrl+C.
const char * get(const char **errId=NULL)
Get the current error message.
Definition: locale.hpp:266
void setSqlError(int rc)
Sets an error by its SQL return code.
void BDC_ratio_func(sqlite3_context *ctx, int argc, sqlite3_value **argv)
BDCRatio function implementation.
void reset()
Reset current SQL statement.
int getColNames(ValueSQLCol::StringPairList &names)
Returns the column names of least fetch.
void SetCell(int i, const mxArray *cell)
Sets a cell of a MATLAB cell array.
Definition: value.hpp:770
long getLastRowID()
kv69: Returns the number of last row id; usefull for inserts in tables with autoincrement primary key...
static void mexFcnWrapper_FINAL(sqlite3_context *ctx)
Wrapper for SQL final function (aggregation)
ValueSQL createValueSQLFromItem(const ValueMex &item, bool bStreamable, int &iTypeComplexity, int &err_id)
Transfer MATLAB array into a SQL value.
Definition: mksqlite.cpp:354
SQL builtin functions, automatically attached to each database.
SQLiface(SQLstackitem &stackitem)
Standard ctor.
bool getBusyTimeout(int &iTimeoutValue)
Returns the busy timeout in milliseconds.
ValueMex & getData()
Return data array from "step" and "final" function.
MexFunctors & operator=(MexFunctors &&other)
Move assignment.
int step()
Evaluates current SQL statement.
#define PRINTF
Global text output function.
Definition: global.hpp:230
void * Detach()
Release custody and return pointer type.
Definition: value.hpp:990
void Destroy()
Dtor.
Definition: value.hpp:335
sqlite3 * m_db
SQLite db object.
sqlite3 * dbid()
Return.
vector< StringPair > StringPairList
list of string pairs
Definition: value.hpp:1052
const char * colName(int index)
Returns the column name least fetch and column number.
SQLerror m_lasterr
recent error message
#define MEM_ALLOC(count, bytes)
standard memory allocator
Definition: global.hpp:156
int g_check4uniquefields
Flag: Check for unique fieldnames.
Definition: global.hpp:266
bool IsValid() const
Check if all functors are valid.