33 #define STRMATCH(strA,strB) ( (strA) && (strB) && ( 0 == _strcmpi( (strA), (strB) ) ) ) 34 #define FINALIZE_STR( message ) mexErrMsgTxt( message ) 36 #define FINALIZE( identifier ) FINALIZE_STR( ::getLocaleMsg( identifier ) ) 49 extern "C" void mexFunction(
int nlhs, mxArray*plhs[],
int nrhs,
const mxArray*prhs[] );
109 return newId >= 0 && newId < COUNT_DB;
133 for(
int i = 0; i < COUNT_DB; i++ )
135 PRINTF(
"DB Handle %d: %s\n", i+1, m_db[i].isOpen() ?
"OPEN" :
"CLOSED" );
140 dbid = (dbid_req > 0) ? dbid_req : dbid;
141 PRINTF(
"DB Handle %d: %s\n", dbid, m_db[dbid-1].isOpen() ?
"OPEN" :
"CLOSED" );
152 for(
int i = 0; i < COUNT_DB; i++ )
154 if( !m_db[i].isOpen() )
170 for(
int i = 0; i < COUNT_DB; i++ )
172 if( m_db[i].isOpen() )
211 static bool is_initialized =
false;
213 if( !is_initialized )
215 mxArray *plhs[3] = {0};
217 if( 0 == mexCallMATLAB( 3, plhs, 0, NULL,
"computer" ) )
219 g_compression_type = BLOSC_DEFAULT_ID;
227 PRINTF(
"Platform: %s, %s\n\n",
229 TBH_endian[0] ==
'L' ?
"little endian" :
"big endian" );
231 is_initialized =
true;
238 if( 0 == mexCallMATLAB( 1, plhs, 0, NULL,
"namelengthmax" ) )
243 #if CONFIG_USE_HEAP_CHECK 244 PRINTF(
"Heap checking is on, this may slow down execution time dramatically!\n" );
262 mxArray* item = NULL;
269 item = mxCreateDoubleScalar( DBL_NAN );
273 item = mxCreateDoubleMatrix( 0, 0, mxREAL );
278 item = mxCreateNumericMatrix( 1, 1, mxINT64_CLASS, mxREAL );
282 *(sqlite3_int64*)mxGetData( item ) = value.m_integer;
287 item = mxCreateDoubleScalar( value.m_float );
291 item = mxCreateString( value.m_text );
297 size_t blob_size = blob.
ByData();
305 item = mxCreateNumericMatrix( (mwSize)blob_size, 1, mxUINT8_CLASS, mxREAL );
309 memcpy(
ValueMex(item).Data(), blob.
Data(), blob_size );
316 double process_time = 0.0;
327 item = mxCreateDoubleMatrix( 0, 0, mxREAL );
360 switch( iTypeComplexity )
368 err_id = MSG_INVALIDARG;
392 size_t blob_size = 0;
393 double process_time = 0.0;
397 err_id =
blob_pack( item.
Item(), bStreamable, &blob, &blob_size, &process_time, &ratio );
399 if( MSG_NOERROR == err_id )
401 value =
ValueSQL( (
char*)blob, blob_size );
410 case ValueMex::LOGICAL_CLASS:
411 case ValueMex::INT8_CLASS:
412 case ValueMex::UINT8_CLASS:
413 case ValueMex::INT16_CLASS:
414 case ValueMex::INT32_CLASS:
415 case ValueMex::UINT16_CLASS:
416 case ValueMex::UINT32_CLASS:
421 case ValueMex::INT64_CLASS:
426 case ValueMex::DOUBLE_CLASS:
427 case ValueMex::SINGLE_CLASS:
432 case ValueMex::CHAR_CLASS:
439 err_id = MSG_ERRMEMORY;
450 err_id = MSG_INVALIDARG;
461 err_id = MSG_INVALIDARG;
501 Mksqlite(
int nlhs, mxArray** plhs,
int nrhs,
const mxArray** prhs )
502 : m_nlhs( nlhs ), m_plhs( plhs ),
503 m_narg( nrhs ), m_parg( prhs ),
504 m_command(NULL), m_query(NULL), m_dbid_req(-1), m_dbid(1), m_interface( NULL )
512 m_err.
set( MSG_INVALIDARG );
560 const char *errId = NULL;
561 const char *errMsg = m_err.
get( &errId );
563 assert( errPending() );
565 mexErrMsgIdAndTxt( errId ? errId :
"MKSQLITE:ANY", errMsg );
579 if( !assureSQLinterface() || !m_interface->
isOpen() )
581 m_err.
set( MSG_DBNOTOPEN );
596 if( m_dbid_req != -1 )
611 if( !m_interface && m_dbid > 0 )
616 return m_interface != NULL;
631 if( errPending() )
return false;
635 m_err.
set( MSG_MISSINGARG );
638 else if( !mxIsNumeric( m_parg[0] ) )
640 m_err.
set( MSG_NUMARGEXPCT );
647 refValue = ( refValue != 0 );
667 if( errPending() )
return false;
671 m_err.
set( MSG_MISSINGARG );
674 else if( !mxIsEmpty( m_parg[0]) && mxGetClassID( m_parg[0] ) != mxFUNCTION_CLASS )
676 m_err.
set( MSG_FCNHARGEXPCT );
680 refValue = m_parg[0];
699 if( errPending() )
return false;
703 m_err.
set( MSG_MISSINGARG );
706 else if( mxGetClassID( m_parg[0] ) != mxCHAR_CLASS )
708 m_err.
set( MSG_LITERALARGEXPCT );
712 refValue = m_parg[0];
731 if( errPending() )
return false;
738 if( argGetNextInteger( m_dbid_req,
false ) )
742 m_err.
set( MSG_INVALIDDBHANDLE );
761 m_dbid = ( m_dbid_req < 0 ) ? 1 : m_dbid_req;
776 if( errPending() )
return false;
784 if( !m_narg || !mxIsChar( m_parg[0] ) )
787 m_err.
set( MSG_INVALIDARG );
817 if( errPending() || !
STRMATCH( m_command, strMatchFlagName ) )
825 int iOldValue = refFlag;
829 m_err.
set( MSG_UNEXPECTEDARG );
833 if( m_narg > 0 && !argGetNextInteger( refFlag,
true ) )
840 m_plhs[0] = mxCreateDoubleScalar( (
double)iOldValue );
859 if( errPending() )
return false;
861 if(
STRMATCH( m_command, strCmdMatchVerMex ) )
868 m_err.
set( MSG_UNEXPECTEDARG );
884 else if(
STRMATCH( m_command, strCmdMatchVerSql ) )
891 m_err.
set( MSG_UNEXPECTEDARG );
898 PRINTF(
"SQLite Version %s\n", SQLITE_VERSION_STRING );
902 m_plhs[0] = mxCreateString( SQLITE_VERSION_STRING );
924 if( errPending() || !
STRMATCH( m_command, strCmdMatchName ) )
950 int new_mode = old_mode;
954 m_err.
set( MSG_UNEXPECTEDARG );
958 if( m_narg > 0 && !argGetNextInteger( new_mode ) )
965 if( new_mode != old_mode )
967 if( new_mode < 0 || new_mode > 2 )
969 m_err.
set( MSG_INVALIDARG );
979 m_plhs[0] = mxCreateDoubleScalar( (
double)old_mode );
995 if( errPending() || !
STRMATCH( m_command, strCmdMatchName ) )
1001 if( !ensureDbIsOpen() )
1012 m_err.
set( MSG_UNEXPECTEDARG );
1017 if( !argGetNextInteger( flagOnOff,
true ) )
1025 const char* errid = NULL;
1026 m_err.
set( m_interface->
getErr(&errid), errid );
1030 PRINTF(
"%s\n", ::
getLocaleMsg( flagOnOff ? MSG_EXTENSION_EN : MSG_EXTENSION_DIS ) );
1046 if( errPending() || !
STRMATCH( m_command, strCmdMatchName ) )
1052 if( !ensureDbIsOpen() )
1063 m_err.
set( MSG_UNEXPECTEDARG );
1070 const mxArray* arg = NULL;
1072 if( !argGetNextLiteral( arg ) )
1087 const mxArray* fcnHandle;
1088 if( !argGetNextFcnHandle( fcnHandle ) )
1099 const char* errid = NULL;
1100 m_err.
set( m_interface->
getErr(&errid), errid );
1118 if( errPending() || !
STRMATCH( m_command, strCmdMatchName ) )
1124 if( !ensureDbIsOpen() )
1135 m_err.
set( MSG_UNEXPECTEDARG );
1142 const mxArray* arg = NULL;
1144 if( !argGetNextLiteral( arg ) )
1159 const mxArray* fcnHandleStep;
1160 if( !argGetNextFcnHandle( fcnHandleStep ) )
1166 const mxArray* fcnHandleFinal;
1167 if( !argGetNextFcnHandle( fcnHandleFinal ) )
1178 const char* errid = NULL;
1179 m_err.
set( m_interface->
getErr(&errid), errid );
1199 if( errPending() || !
STRMATCH( m_command, strCmdMatchName ) )
1210 mxArray* cell = mxCreateCellMatrix( 2, 1 );
1211 mxArray* compressor = mxCreateString( g_compression_type ? g_compression_type :
"" );
1212 mxArray* level = mxCreateDoubleScalar( (
double)g_compression_level );
1214 mxSetCell( cell, 0, compressor );
1215 mxSetCell( cell, 1, level );
1222 int new_compression_level = 0;
1223 char* new_compressor = NULL;
1227 m_err.
set( MSG_MISSINGARG );
1230 else if( m_narg > 2 )
1232 m_err.
set( MSG_UNEXPECTEDARG );
1236 if( !mxIsChar( m_parg[0] ) || !mxIsNumeric( m_parg[1] ) )
1238 m_err.
set( MSG_INVALIDARG );
1246 if( new_compression_level < 0 || new_compression_level > 9 )
1248 m_err.
set( MSG_INVALIDARG );
1252 if(
STRMATCH( new_compressor, BLOSC_LZ4_ID ) )
1254 g_compression_type = BLOSC_LZ4_ID;
1256 else if(
STRMATCH( new_compressor, BLOSC_LZ4HC_ID ) )
1258 g_compression_type = BLOSC_LZ4HC_ID;
1260 else if(
STRMATCH( new_compressor, BLOSC_DEFAULT_ID ) )
1262 g_compression_type = BLOSC_DEFAULT_ID;
1264 else if(
STRMATCH( new_compressor, QLIN16_ID ) )
1266 g_compression_type = QLIN16_ID;
1267 new_compression_level = ( new_compression_level > 0 );
1269 else if(
STRMATCH( new_compressor, QLOG16_ID ) )
1271 g_compression_type = QLOG16_ID;
1272 new_compression_level = ( new_compression_level > 0 );
1276 m_err.
set( MSG_INVALIDARG );
1283 g_compression_level = new_compression_level;
1301 if( errPending() || !
STRMATCH( m_command, strCmdMatchName ) )
1313 m_err.
set( MSG_UNEXPECTEDARG );
1323 if( m_dbid_req == 0 )
1325 mxArray* result = mxCreateCellMatrix(
SQLstack.COUNT_DB, 1 );
1326 for(
int i = 0; result && i <
SQLstack.COUNT_DB; i++ )
1328 mxArray* item = mxGetCell( result, i );
1329 mxSetCell( result, i, mxCreateString(
SQLstack.
m_db[i].
isOpen() ?
"OPEN" :
"CLOSED" ) );
1330 mxDestroyArray( item );
1359 if( errPending() || !
STRMATCH( m_command, strCmdMatchName ) )
1372 m_err.
set( MSG_MISSINGARG );
1375 else if( m_narg > 1 )
1377 m_err.
set( MSG_UNEXPECTEDARG );
1381 if( !mxIsNumeric( m_parg[0] ) )
1383 m_err.
set( MSG_NUMARGEXPCT );
1390 m_err.
set( MSG_INVALIDARG );
1409 char *db_filename = NULL;
1410 char *db_name = NULL;
1412 if( errPending() || !
STRMATCH( m_command, strCmdMatchName ) )
1420 if( !ensureDbIsOpen() )
1431 m_err.
set( MSG_UNEXPECTEDARG );
1438 if( !mxIsChar( m_parg[0] ) )
1440 m_err.
set( MSG_LITERALARGEXPCT );
1449 if( NULL == db_filename )
1451 m_plhs[0] = mxCreateString(
"" );
1455 m_plhs[0] = mxCreateString( db_filename );
1477 if( errPending() || !
STRMATCH( m_command, strCmdMatchName ) )
1490 m_err.
set( MSG_UNEXPECTEDARG );
1498 if( m_narg && !argGetNextInteger( flagOnOff,
true ) )
1519 m_plhs[0] = mxCreateDoubleScalar( (
double)
g_streaming );
1522 g_streaming = flagOnOff;
1540 int new_result_type;
1543 if( errPending() || !
STRMATCH( m_command, strCmdMatchName ) )
1556 m_err.
set( MSG_UNEXPECTEDARG );
1577 if( m_narg && !argGetNextInteger( new_result_type,
false ) )
1584 if( new_result_type != old_result_type )
1588 m_err.
set( MSG_INVALIDARG );
1596 m_plhs[0] = mxCreateDoubleScalar( (
double)old_result_type );
1615 if( errPending() || !
STRMATCH( m_command, strCmdMatchName ) )
1621 if( !ensureDbIsOpen() )
1632 m_err.
set( MSG_UNEXPECTEDARG );
1638 const char* errid = NULL;
1643 m_err.
set( m_interface->
getErr(&errid), errid );
1647 if( m_narg && !argGetNextInteger( iTimeout,
false ) )
1659 const char* errid = NULL;
1664 m_err.
set( m_interface->
getErr(&errid), errid );
1669 m_plhs[0] = mxCreateDoubleScalar( (
double)iTimeout );
1700 || cmdTryHandleFlag(
"compression_check", g_compression_check )
1702 || cmdTryHandleStatus(
"status" )
1703 || cmdTryHandleLanguage(
"lang" )
1704 || cmdTryHandleFilename(
"filename" )
1705 || cmdTryHandleVersion(
"version mex",
"version sql" )
1706 || cmdTryHandleStreaming(
"streaming" )
1707 || cmdTryHandleTypedBlob(
"typedBLOBs" )
1708 || cmdTryHandleResultType(
"result_type" )
1709 || cmdTryHandleCompression(
"compression" )
1710 || cmdTryHandleSetBusyTimeout(
"setbusytimeout" )
1711 || cmdTryHandleEnableExtension(
"enable extension" )
1712 || cmdTryHandleCreateFunction(
"create function" )
1713 || cmdTryHandleCreateAggregation(
"create aggregation" ) )
1717 else if (
STRMATCH( m_command,
"show tables" ) )
1719 m_query =
"SELECT name as tablename FROM sqlite_master " 1720 "WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%' " 1722 "SELECT name as tablename FROM sqlite_temp_master " 1723 "WHERE type IN ('table','view') " 1747 if(
STRMATCH( m_command,
"open" ) )
return OPEN;
1748 if(
STRMATCH( m_command,
"close" ) )
return CLOSE;
1749 if( cmdTryHandleNonSqlStatement() )
return DONE;
1750 if( errPending() )
return FAILED;
1767 if( errPending() )
return false;
1773 if( !m_narg || !mxIsChar( m_parg[0] ) )
1775 m_err.
set( MSG_NOOPENARG );
1786 const char* errid = NULL;
1787 m_err.
set( m_interface->
getErr(&errid), errid );
1793 if( m_narg > 0 && !errPending() )
1802 openFlags |= SQLITE_OPEN_READONLY;
1804 else if(
STRMATCH( iomode,
"rw" ) )
1806 openFlags |= SQLITE_OPEN_READWRITE;
1808 else if(
STRMATCH( iomode,
"rwc" ) )
1810 openFlags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
1814 m_err.
set( MSG_ERRUNKOPENMODE );
1821 openFlags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
1828 if( m_narg > 0 && !errPending() )
1835 if(
STRMATCH( threadmode,
"single" ) )
1839 else if(
STRMATCH( threadmode,
"multi" ) )
1841 openFlags |= SQLITE_OPEN_NOMUTEX;
1843 else if(
STRMATCH( threadmode,
"serial" ) )
1845 openFlags |= SQLITE_OPEN_FULLMUTEX;
1849 m_err.
set( MSG_ERRUNKTHREADMODE );
1865 const char* errid = NULL;
1873 m_err.
set( m_interface->
getErr(&errid), errid );
1881 m_plhs[0] = mxCreateDoubleScalar( (
double)m_dbid );
1885 return !errPending();
1899 if( errPending() )
return false;
1906 m_err.
set( MSG_INVALIDARG );
1927 return errPending();
1941 int err_id = MSG_NOERROR;
1944 if( MSG_NOERROR != err_id )
1946 m_err.
set( err_id );
1965 mxArray* colNames = mxCreateCellMatrix( (
int)cols.size(), (int)cols.size() ? 2 : 0 );
1968 for(
int i = 0; !errPending() && i < (int)cols.size(); i++ )
1971 mxArray* colNameSql = mxCreateString( cols[i].m_col_name.c_str() );
1972 mxArray* colNameMat = mxCreateString( cols[i].m_name.c_str() );
1974 if( !colNames || !colNameSql || !colNameMat )
1980 m_err.
set( MSG_ERRMEMORY );
1985 int j = (int)cols.size() + i;
1986 mxDestroyArray( mxGetCell( colNames, i ) );
1987 mxDestroyArray( mxGetCell( colNames, j ) );
1988 mxSetCell( colNames, i, colNameSql );
1989 mxSetCell( colNames, j, colNameMat );
2012 mxArray* result = mxCreateStructMatrix( (
int)cols[0].size(), 1, 0, NULL );
2015 for(
int i = 0; !errPending() && i < (int)cols.size(); i++ )
2020 if( !result || -1 == ( j = mxAddField( result, cols[i].m_name.c_str() ) ) )
2022 m_err.
set( MSG_ERRMEMORY );
2026 for(
int row = 0; !errPending() && row < (int)cols[i].size(); row++ )
2035 m_err.
set( MSG_ERRMEMORY );
2041 mxDestroyArray( mxGetFieldByNumber( result, row, j ) );
2043 mxSetFieldByNumber( result, row, j, item );
2045 cols[i].Destroy(row);
2072 mxArray* result = mxCreateStructMatrix( 1, 1, 0, NULL );
2075 for(
int i = 0; !errPending() && i < (int)cols.size(); i++ )
2077 mxArray* column = NULL;
2082 column = cols[i].m_isAnyType ?
2083 mxCreateCellMatrix( (
int)cols[0].size(), 1 ) :
2084 mxCreateDoubleMatrix( (
int)cols[0].size(), 1, mxREAL );
2087 if( !result || !column || -1 == ( j = mxAddField( result, cols[i].m_name.c_str() ) ) )
2089 m_err.
set( MSG_ERRMEMORY );
2093 if( !cols[i].m_isAnyType )
2096 for(
int row = 0; !errPending() && row < (int)cols[i].size(); row++ )
2098 assert( cols[i][row].m_typeID == SQLITE_FLOAT );
2099 mxGetPr(column)[row] = cols[i][row].m_float;
2105 for(
int row = 0; !errPending() && row < (int)cols[i].size(); row++ )
2111 m_err.
set( MSG_ERRMEMORY );
2117 mxDestroyArray( mxGetCell( column, row ) );
2119 mxSetCell( column, row, item );
2121 cols[i].Destroy(row);
2130 mxSetFieldByNumber( result, 0, j, column );
2151 bool allFloat =
true;
2154 for(
int i = 0; i < (int)cols.size(); i++ )
2156 if( cols[i].m_isAnyType )
2166 mxArray* result = allFloat ?
2167 mxCreateDoubleMatrix( (
int)cols[0].size(), (
int)cols.size(), mxREAL ) :
2168 mxCreateCellMatrix( (
int)cols[0].size(), (int)cols.size() );
2171 for(
int i = 0; !errPending() && i < (int)cols.size(); i++ )
2175 m_err.
set( MSG_ERRMEMORY );
2180 for(
int row = 0; !errPending() && row < (int)cols[i].size(); row++ )
2184 assert( cols[i][row].m_typeID == SQLITE_FLOAT );
2185 double dVal = cols[i][row].m_float;
2187 mxGetPr(result)[i * (int)cols[0].size() + row] = dVal;
2195 m_err.
set( MSG_ERRMEMORY );
2200 mxDestroyArray( mxGetCell( result, i * (
int)cols[i].size() + row ) );
2202 mxSetCell( result, i * (
int)cols[i].size() + row, item );
2204 cols[i].Destroy(row);
2224 if( errPending() )
return false;
2228 if( !ensureDbIsOpen() )
2240 char* new_command = NULL;
2243 if( cmd_length < strlen( m_command ) )
2245 cmd_length = (int)strlen( m_command );
2248 new_command = (
char*)
MEM_ALLOC( cmd_length + 2, 1 );
2252 m_err.
set( MSG_ERRMEMORY );
2258 ::utils_latin2utf( (
const unsigned char*)m_command, (
unsigned char*)new_command );
2259 sprintf( new_command + strlen( new_command ),
";" );
2263 sprintf( new_command,
"%s;", m_command );
2266 m_command = new_command;
2268 m_query = m_command;
2273 if( !m_interface->
setQuery( m_query ) )
2275 const char* errid = NULL;
2276 m_err.
set( m_interface->
getErr(&errid), errid );
2283 const mxArray** nextBindParam = m_parg;
2284 int countBindParam = m_narg;
2286 bool haveParamCell =
false;
2287 bool haveParamStruct =
false;
2288 long* last_insert_row = NULL;
2289 bool initialize =
true;
2308 haveParamCell =
true;
2316 m_err.
set( MSG_SINGLECELLNOTALLOWED );
2319 haveParamCell =
false;
2326 nextBindParam = (
const mxArray**)
ValueMex(*nextBindParam).
Data();
2333 haveParamStruct =
true;
2345 m_err.
set( MSG_SINGLESTRUCTNOTALLOWED );
2348 else haveParamStruct =
false;
2351 if( haveParamStruct )
2366 count = argsNeeded ? ( countBindParam / argsNeeded ) : 1;
2367 int remain = argsNeeded ? ( countBindParam % argsNeeded ) : 0;
2370 if( remain || !count )
2372 if( haveParamStruct )
2374 m_err.
set( MSG_MISSINGARG_STRUCT );
2376 else if( haveParamCell )
2378 m_err.
set( MSG_MISSINGARG_CELL );
2382 m_err.
set( MSG_MISSINGARG );
2389 bool flagIgnoreLessParameters =
true;
2393 if( countBindParam > argsNeeded )
2395 m_err.
set( MSG_UNEXPECTEDARG );
2400 if( !flagIgnoreLessParameters && countBindParam != argsNeeded )
2402 if( haveParamStruct )
2404 m_err.
set( MSG_MISSINGARG_STRUCT );
2406 else if( haveParamCell )
2408 m_err.
set( MSG_MISSINGARG_CELL );
2412 m_err.
set( MSG_MISSINGARG );
2418 last_insert_row =
new long[count];
2420 if( !last_insert_row )
2422 m_err.
set( MSG_ERRMEMORY );
2427 for(
int i = 0; i < count; i++ )
2430 m_interface->
reset();
2436 for(
int iParam = 0; !errPending() && iParam < argsNeeded && countBindParam; iParam++, countBindParam-- )
2438 const mxArray* bindParam = NULL;
2440 if( !haveParamStruct )
2442 bindParam = *nextBindParam++;
2447 bindParam = name ?
ValueMex( *nextBindParam ).
GetField( i, ++name ) : NULL;
2451 m_err.
set_printf( MSG_MISSINGARG_STRUCT, NULL, name ? name :
"(unnamed)");
2458 const char* errid = NULL;
2459 m_err.
set( m_interface->
getErr(&errid), errid );
2467 if( !errPending() && !m_interface->
fetch( cols, initialize ) )
2469 const char* errid = NULL;
2470 m_err.
set( m_interface->
getErr(&errid), errid );
2495 for(
int i = 0; i < m_nlhs; i++ )
2497 mxArray* result = mxCreateDoubleMatrix( 0, 0, mxREAL );
2500 m_err.
set( MSG_CANTCREATEOUTPUT );
2511 mxArray* result = NULL;
2517 result = createResultAsArrayOfStructs( cols );
2521 result = createResultAsStructOfArrays( cols );
2525 result = createResultAsMatrix( cols );
2535 m_err.
set( MSG_CANTCREATEOUTPUT );
2549 int row_count = cols.size() > 0 ? (int)cols[0].size() : 0;
2550 m_plhs[1] = mxCreateDoubleScalar( (
double)row_count );
2551 assert( NULL != m_plhs[1] );
2558 m_plhs[2] = createResultColNameMatrix( cols );
2564 result = mxCreateDoubleMatrix(count, 1, mxREAL);
2567 m_err.
set( MSG_CANTCREATEOUTPUT );
2571 for (
int i = 0; i < count; i++)
2573 mxGetPr(result)[i] = (double)last_insert_row[i];
2582 delete[] last_insert_row;
2584 return !errPending();
2597 if( command < DONE )
2602 if( command == OPEN )
2606 m_err.
set( MSG_NOFREESLOT );
2610 else if( command == CLOSE )
2616 m_err.
set( MSG_ERRNULLDBID );
2634 if( !argTryReadValidDbid() || !argReadCommand() )
2639 command_e command = cmdAnalyseCommand();
2641 if( switchDBSlot( command ) )
2646 case Mksqlite::OPEN:
2647 (void)cmdHandleOpen();
2650 case Mksqlite::CLOSE:
2651 (void)cmdHandleClose();
2654 case Mksqlite::QUERY:
2655 (void)cmdHandleSQLStatement();
2658 case Mksqlite::DONE:
2661 case Mksqlite::FAILED:
2693 void mexFunction(
int nlhs, mxArray* plhs[],
int nrhs,
const mxArray*prhs[] )
2702 switch( PRIMARYLANGID( GetUserDefaultLangID() ) )
2721 Mksqlite mksqlite( nlhs, plhs, nrhs, prhs );
2732 #if CONFIG_USE_HEAP_CHECK #define STRMATCH(strA, strB)
Returns 0 if strA and strB are equal (ignoring case)
mxArray * createResultAsMatrix(ValueSQLCols &cols)
Transform SQL fetch to MATLAB (cell) array.
bool setEnableLoadExtension(int flagOnOff)
Enable or disable load extensions.
Encapsulating a MATLAB mxArray.
void throwOnException()
(Re-)Throws an exception, if any occurred
SQLiface * m_interface
interface (holding current SQLite statement) to current database
Class holding an exception array, the function map and the handle for one database.
const mxArray * GetField(int n, const char *name) const
Get field from a struct array.
int getParameterCount()
Returns the count of parameters the current statement expects.
void printStatuses(int dbid_req, int dbid)
Outputs current status for each database slot.
void errClear()
Clear recent error.
mxArray * createResultAsStructOfArrays(ValueSQLCols &cols)
Transform SQL fetch to MATLAB struct of arrays.
int g_param_wrapping
Wrap parameters.
bool isOpen()
Returns true, if database is opened.
bool setLocale(int iLang)
Sets the current locale.
const char * getErr(const char **errid=NULL)
Get recent error message.
void cmdExecute()
Execute the command string passed to mksqlite.
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.
char * m_command
SQL command. Allocated and freed by this class.
mxClassID ClassID() const
Returns item class ID or mxUNKNOWN_CLASS if item is NULL.
command_e
Return values of cmdAnalyseCommand()
type_complexity_e Complexity(bool bCanSerialize=false) const
Get complexity information. Which storage level is necessary (scalar, vector, matrix, text, blob)
void mex_module_deinit()
Module deinitialization.
single non-complex value, char or simple string (SQLite simple types)
bool closeDb(SQLerror &err)
Close database.
bool errPending()
Returns true, if any error is pending.
bool cmdTryHandleStatus(const char *strCmdMatchName)
Handle status command.
#define CONFIG_BUSYTIMEOUT
default SQL busy timeout in milliseconds (1000)
bool argGetNextFcnHandle(const mxArray *&refValue)
Get next value as function handle from argument list.
char * GetString(bool flagUTF=false, const char *format=NULL) const
Convert a string to char, due flagUTF converted to utf8.
const char * getParameterName(int n)
Returns the name for nth parameter.
int m_narg
count of right hand side arguments
int GetInt(int errval=0) const
Get integer value from item.
int m_typeID
Type of SQL value as integer ID.
bool warnOnDefDbid()
Omits a warning if database is given but superfluous.
bool cmdHandleClose()
Handle close command.
bool fetch(ValueSQLCols &cols, bool initialize=false)
Proceed a table fetch.
const char * getLocaleMsg(int iMsgNr)
Returns the translation for a defined message.
mxArray * createResultAsArrayOfStructs(ValueSQLCols &cols)
Transform SQL fetch to MATLAB array of structs.
char * utils_strlwr(char *)
Change string to lowercase (inplace)
bool switchDBSlot(command_e command)
Selects the desired slot from SQLStack for the operation.
mxArray * Detach()
Detach hosted MATLAB array.
ValueMex createItemFromValueSQL(const ValueSQL &value)
Transfer fetched SQL value into a MATLAB array.
bool setQuery(const char *query)
Dispatch a SQL query.
int closeAllDbs()
Closes all open databases and returns the number of closed DBs, if any open.
bool cmdTryHandleCompression(const char *strCmdMatchName)
Handle compression setting command.
bool argGetNextInteger(int &refValue, bool asBoolInt=false)
Get next integer from argument list.
int m_dbid
selected database slot (1..COUNT_DB)
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.
SQLiface * createInterface()
Returns a new interface to the current database.
int blob_unpack(const void *pBlob, size_t blob_size, bool bStreamable, mxArray **ppItem, double *pProcess_time, double *pdRatio)
uncompress a typed blob and return as MATLAB array
bool cmdTryHandleFilename(const char *strCmdMatchName)
Get the filename of current database.
void clearBindings()
Clears all parameter bindings from current statement.
size_t ByData() const
Returns data size in bytes.
int getNextFreeId()
Returns the first next free id slot (base 0). Database must be closed.
void finalize()
Clear parameter bindings and finalize current statement.
bool cmdTryHandleNonSqlStatement()
Interpret current argument as command or switch.
#define FINALIZE(identifier)
Terminates the function immediately with an error message.
sqlite3_int64 GetInt64(int errval=0) const
Get 64 bit integer value from item.
Class encapsulating a SQL field value.
void typed_blobs_mode_set(int mode)
Set mode of typed blob usage.
bool cmdTryHandleStreaming(const char *strCmdMatchName)
Handle streaming setting command.
char TBH_endian[]
endian (little or big)
int g_result_type
Data organisation of returning query results.
bool isPending()
Returns true, if the current error message is still not handled.
bool cmdTryHandleEnableExtension(const char *strCmdMatchName)
Handle command to (en-/dis-)able loading extensions.
structs, cells, complex data (SQLite typed ByteStream BLOB)
void clear()
Reset error message.
SQLerror m_err
recent error
void utils_destroy_array(mxArray *&pmxarr)
Freeing memory allocated by mxCreateNumericMatrix() or mxCreateNumericArray().
ValueSQL createValueSQLFromItem(const ValueMex &item, bool bStreamable, int &iTypeComplexity, int &err_id)
Transfer MATLAB array into a SQL value.
mxArray ** m_plhs
pointer to current left hand side argument
void mex_module_init()
Module initialization.
char TBH_platform[]
platform name
int m_dbid
recent selected database id, base 0
size_t NumElements() const
Returns number of elements.
int m_nlhs
count of left hand side arguments
bool isValidId(int newId)
Checks if database newId is in valid range.
bool cmdTryHandleVersion(const char *strCmdMatchVerMex, const char *strCmdMatchVerSql)
Handle version commands.
#define CONFIG_MAX_NUM_OF_DBS
maximum number of databases, simultaneous open
int g_streaming
Flag: Allow streaming.
mxArray * createResultColNameMatrix(const ValueSQLCols &cols)
Create a MATLAB cell array of column names.
int g_namelengthmax
MATALAB specific globals.
bool can_serialize()
Returns true, if streaming is switched on (user setting) and serialization is accessible.
Template class extending base class uniquely.
bool cmdTryHandleFlag(const char *strMatchFlagName, int &refFlag)
Handle flag from command.
void Release()
Release object.
int g_convertUTF8
Flag: String representation (utf8 or ansi)
int blob_pack(const mxArray *pcItem, bool bStreamable, void **ppBlob, size_t *pBlob_size, double *pdProcess_time, double *pdRatio, const char *compressor=g_compression_type, int level=g_compression_level)
create a compressed typed blob from a Matlab item (deep copy)
vector< ValueSQLCol > ValueSQLCols
type for column container
const char * m_query
m_command, or a translation from m_command
bool cmdTryHandleCreateFunction(const char *strCmdMatchName)
Handle command to create or delete a SQL user function.
bool cmdHandleSQLStatement()
Handle common SQL statement.
int typed_blobs_mode_on()
Get mode of typed blob usage.
void switchTo(int newId)
Makes newId as current database id.
void set(const char *strMsg, const char *strId=NULL)
Set error message to a constant string (without translation)
ValueMex & getException()
Returns the exception array for this database.
void utils_free_ptr(T *&pmxarr)
Freeing memory allocated by mxAlloc() or mxRealloc()
void * Data() const
Returns pointer to raw data.
bool cmdTryHandleLanguage(const char *strCmdMatchName)
Handle language command.
bool argTryReadValidDbid()
Get database ID from argument list.
int getLocale()
Get current locale id.
bool IsStruct() const
Returns true if item is a struct array.
bool openDb(const char *filename, int openFlags, SQLerror &err)
Opens (or create) database.
SQLstackitem & current()
Returns the handle of the current database.
bool cmdTryHandleTypedBlob(const char *strCmdMatchName)
Handle typed BLOB settings command.
bool cmdTryHandleSetBusyTimeout(const char *strCmdMatchName)
Handle set busy timeout command.
ValueMex createItemFromValueSQL(const ValueSQL &value, int &err_id)
Transfer fetched SQL value into MATLAB array.
bool cmdHandleOpen()
Handle open command.
char * GetEncString() const
Returns allocated memory with items test, due to global flag converted to UTF.
int g_NULLasNaN
Flag: return NULL as NaN.
char * utils_strnewdup(const char *s, int flagConvertUTF8)
duplicate a string and recode from UTF8 to char due to flag flagConvertUTF8
int utils_latin2utf(const unsigned char *s, unsigned char *buffer)
Convert char string to UTF-8 string.
Helperclass for memory leak and access violation detection.
bool have_serialize()
Returns true, if current MATLAB version supports serialization.
ValueMex & Adopt(bool doAdopt=true)
Take ownership (custody) of a MEX array.
#define CONFIG_MKSQLITE_VERSION_STRING
mksqlite version string
void Walk(const char *text=NULL)
Reporting walk through the linked memory list.
bool argReadCommand()
Get command from argument list.
bool setBusyTimeout(int iTimeoutValue)
Sets the busy timemout in milliseconds.
bool assureSQLinterface()
Creates a SQL interface if not already happen.
bool argGetNextLiteral(const mxArray *&refValue)
Get next value as literal argument from argument list.
bool cmdTryHandleCreateAggregation(const char *strCmdMatchName)
Handle command to create or delete a SQL user aggregate function.
void returnWithError()
Terminate function.
const mxArray * Item() const
Returns hosted MATLAB array.
const mxArray ** m_parg
pointer to current right hand side argument
bool bindParameter(int index, const ValueMex &item, bool bStreamable)
Binds one parameter from current statement to a MATLAB array.
bool ensureDbIsOpen()
Ensuring current database is open.
const char * get(const char **errId=NULL)
Get the current error message.
void reset()
Reset current SQL statement.
Mksqlite(int nlhs, mxArray **plhs, int nrhs, const mxArray **prhs)
Standard ctor.
command_e cmdAnalyseCommand()
Analyse command string and process if its neither open, close nor a sql command.
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
MEX Entry function declared the as pure C.
multidimensional non-complex numeric or char arrays (SQLite typed BLOB)
long getLastRowID()
kv69: Returns the number of last row id; usefull for inserts in tables with autoincrement primary key...
non-complex numeric vectors (SQLite BLOB)
Limit for bound checking only.
bool cmdTryHandleResultType(const char *strCmdMatchName)
Handle result type command.
bool getBusyTimeout(int &iTimeoutValue)
Returns the busy timeout in milliseconds.
#define HC_COMP_ASSERT(exp)
Verifies design-time assumptions (exp) at compile-time.
SQLstack()
Standard Ctor (first database slot is default)
char * utils_getString(const mxArray *str)
Copy string characters into allocated memory.
#define PRINTF
Global text output function.
int m_dbid_req
requested database id (user input) -1="arg missing", 0="next free slot" or 1..COUNT_DB ...
void typed_blobs_init()
Initialization.
SQLstackitem m_db[COUNT_DB]
SQLite database slots.
#define MEM_ALLOC(count, bytes)
standard memory allocator
int g_check4uniquefields
Flag: Check for unique fieldnames.
bool IsCell() const
Returns true if item is a cell array.