2023-11-16 18:12 UTC+0100 Phil Krylov (phil a t krylov.eu)
* contrib/hbsqlit3/core.c
* contrib/hbsqlit3/hbsqlit3.ch
* contrib/hbsqlit3/hbsqlit3.hbx
* Implemented SQLITE3_DB_FILENAME() on SQLite 3.7.10+.
* Implemented SQLITE3_EXPANDED_SQL(), SQLITE3_TRACE_V2() on SQLite 3.14.0+.
; Thanks to Mindaugas Kavaliauskas for thorough reviewing!
* contrib/hbsqlit3/tests/backup.prg
* contrib/hbsqlit3/tests/demo.prg
* Updated examples to use SQLITE3_TRACE_V2() on SQLite 3.14.0+.
This commit is contained in:
@@ -7,6 +7,17 @@
|
||||
Entries may not always be in chronological/commit order.
|
||||
See license at the end of file. */
|
||||
|
||||
2023-11-30 18:12 UTC+0100 Phil Krylov (phil a t krylov.eu)
|
||||
* contrib/hbsqlit3/core.c
|
||||
* contrib/hbsqlit3/hbsqlit3.ch
|
||||
* contrib/hbsqlit3/hbsqlit3.hbx
|
||||
* Implemented SQLITE3_DB_FILENAME() on SQLite 3.7.10+.
|
||||
* Implemented SQLITE3_EXPANDED_SQL(), SQLITE3_TRACE_V2() on SQLite 3.14.0+.
|
||||
; Thanks to Mindaugas Kavaliauskas for thorough reviewing!
|
||||
* contrib/hbsqlit3/tests/backup.prg
|
||||
* contrib/hbsqlit3/tests/demo.prg
|
||||
* Updated examples to use SQLITE3_TRACE_V2() on SQLite 3.14.0+.
|
||||
|
||||
2023-11-22 09:06 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl)
|
||||
* contrib/hbssl/hbssl.hbm
|
||||
* contrib/hbssl/hbssl.hbx
|
||||
|
||||
@@ -82,6 +82,9 @@ static int progress_handler( void * );
|
||||
static int hook_commit( void * );
|
||||
static void hook_rollback( void * );
|
||||
static void func( sqlite3_context *, int, sqlite3_value ** );
|
||||
#if SQLITE_VERSION_NUMBER >= 3014000
|
||||
static int trace_handler( unsigned, void *, void *, void * );
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -92,8 +95,12 @@ typedef struct
|
||||
PHB_ITEM cbHookCommit;
|
||||
PHB_ITEM cbHookRollback;
|
||||
PHB_ITEM cbFunc;
|
||||
#if SQLITE_VERSION_NUMBER >= 3014000
|
||||
PHB_ITEM cbTraceHandler;
|
||||
#else
|
||||
PHB_ITEM sProfileFileName;
|
||||
PHB_ITEM sTraceFileName;
|
||||
#endif
|
||||
} HB_SQLITE3, * PHB_SQLITE3;
|
||||
|
||||
typedef struct
|
||||
@@ -156,6 +163,13 @@ static HB_GARBAGE_FUNC( hb_sqlite3_destructor )
|
||||
pStructHolder->hbsqlite3->cbFunc = NULL;
|
||||
}
|
||||
|
||||
#if SQLITE_VERSION_NUMBER >= 3014000
|
||||
if( pStructHolder->hbsqlite3->cbTraceHandler )
|
||||
{
|
||||
hb_itemRelease( pStructHolder->hbsqlite3->cbTraceHandler );
|
||||
pStructHolder->hbsqlite3->cbTraceHandler = NULL;
|
||||
}
|
||||
#else
|
||||
if( pStructHolder->hbsqlite3->sProfileFileName )
|
||||
{
|
||||
hb_itemRelease( pStructHolder->hbsqlite3->sProfileFileName );
|
||||
@@ -166,6 +180,7 @@ static HB_GARBAGE_FUNC( hb_sqlite3_destructor )
|
||||
hb_itemRelease( pStructHolder->hbsqlite3->sTraceFileName );
|
||||
pStructHolder->hbsqlite3->sTraceFileName = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
hb_xfree( pStructHolder->hbsqlite3 );
|
||||
pStructHolder->hbsqlite3 = NULL;
|
||||
@@ -196,6 +211,12 @@ static HB_GARBAGE_FUNC( hb_sqlite3_mark )
|
||||
if( pStructHolder->hbsqlite3->cbFunc )
|
||||
hb_gcMark( pStructHolder->hbsqlite3->cbFunc );
|
||||
|
||||
#if SQLITE_VERSION_NUMBER >= 3014000
|
||||
if( pStructHolder->hbsqlite3->cbTraceHandler )
|
||||
{
|
||||
hb_gcMark( pStructHolder->hbsqlite3->cbTraceHandler );
|
||||
}
|
||||
#else
|
||||
if( pStructHolder->hbsqlite3->sProfileFileName )
|
||||
{
|
||||
hb_gcMark( pStructHolder->hbsqlite3->sProfileFileName );
|
||||
@@ -204,6 +225,7 @@ static HB_GARBAGE_FUNC( hb_sqlite3_mark )
|
||||
{
|
||||
hb_gcMark( pStructHolder->hbsqlite3->sTraceFileName );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1776,14 +1798,108 @@ HB_FUNC( SQLITE3_ENABLE_SHARED_CACHE )
|
||||
hb_retni( sqlite3_enable_shared_cache( hb_parl( 1 ) ) );
|
||||
}
|
||||
|
||||
/* TODO: implement sqlite3_trace_v2(), that replaces both of these deprecated functions */
|
||||
|
||||
/**
|
||||
Tracing And Profiling Functions
|
||||
|
||||
sqlite3_trace_v2( db, nMask, [ bCallback ] ) // Starting with 3.14.0
|
||||
|
||||
sqlite3_trace( db, lOnOff, [ filename ] ) // Deprecated in 3.14.0
|
||||
sqlite3_profile( db, lOnOff, [ filename ] ) // Deprecated in 3.14.0
|
||||
*/
|
||||
|
||||
#if SQLITE_VERSION_NUMBER >= 3014000
|
||||
static int trace_handler( unsigned uType, void *cbTraceHandler, void * p, void * x )
|
||||
{
|
||||
PHB_ITEM pCallback = ( PHB_ITEM ) cbTraceHandler;
|
||||
int iRes = 0;
|
||||
|
||||
if( pCallback && hb_vmRequestReenter() )
|
||||
{
|
||||
hb_vmPushEvalSym();
|
||||
hb_vmPush( pCallback );
|
||||
hb_vmPushNumInt( uType );
|
||||
switch( uType )
|
||||
{
|
||||
case SQLITE_TRACE_STMT:
|
||||
hb_vmPushPointer( p );
|
||||
hb_vmPushString( x, strlen( x ) );
|
||||
hb_vmSend( 3 );
|
||||
break;
|
||||
case SQLITE_TRACE_PROFILE:
|
||||
hb_vmPushPointer( p );
|
||||
hb_vmPushNumInt( *( sqlite3_uint64 * ) x );
|
||||
hb_vmSend( 3 );
|
||||
break;
|
||||
case SQLITE_TRACE_ROW:
|
||||
HB_SYMBOL_UNUSED( x );
|
||||
hb_vmPushPointer( p );
|
||||
hb_vmSend( 2 );
|
||||
break;
|
||||
case SQLITE_TRACE_CLOSE:
|
||||
{
|
||||
PHB_ITEM pItem = hb_itemNew( NULL );
|
||||
HB_SQLITE3 * hbsqlite3 = ( HB_SQLITE3 * ) hb_xgrabz( sizeof( HB_SQLITE3 ) );
|
||||
HB_SYMBOL_UNUSED( x );
|
||||
|
||||
hbsqlite3->db = p;
|
||||
hb_sqlite3_itemPut( pItem, hbsqlite3, HB_SQLITE3_DB );
|
||||
hb_vmPush( pItem );
|
||||
hb_vmSend( 2 );
|
||||
|
||||
/* We don't want sqlite3_close() called recursively
|
||||
* and don't want to implement a weak reference engine yet
|
||||
* so we just clear the pointer before hb_itemRelease(). */
|
||||
hbsqlite3->db = NULL;
|
||||
hb_itemRelease( pItem );
|
||||
break;
|
||||
}
|
||||
}
|
||||
iRes = hb_parni( -1 );
|
||||
hb_vmRequestRestore();
|
||||
}
|
||||
return iRes;
|
||||
}
|
||||
#endif
|
||||
|
||||
HB_FUNC( SQLITE3_TRACE_V2 )
|
||||
{
|
||||
#if SQLITE_VERSION_NUMBER >= 3014000
|
||||
HB_SQLITE3 * pHbSqlite3 = ( HB_SQLITE3 * ) hb_sqlite3_param( 1, HB_SQLITE3_DB, HB_TRUE );
|
||||
|
||||
if( pHbSqlite3 && pHbSqlite3->db )
|
||||
{
|
||||
unsigned uMask = ( unsigned int ) hb_parnint( 2 );
|
||||
int iRes;
|
||||
|
||||
if( pHbSqlite3->cbTraceHandler )
|
||||
{
|
||||
hb_itemRelease( pHbSqlite3->cbTraceHandler );
|
||||
pHbSqlite3->cbTraceHandler = NULL;
|
||||
}
|
||||
|
||||
if( HB_ISEVALITEM( 3 ) )
|
||||
{
|
||||
pHbSqlite3->cbTraceHandler = hb_itemNew( hb_param( 3, HB_IT_EVALITEM ) );
|
||||
hb_gcUnlock( pHbSqlite3->cbTraceHandler );
|
||||
|
||||
iRes = sqlite3_trace_v2( pHbSqlite3->db, uMask,
|
||||
uMask ? trace_handler : NULL,
|
||||
uMask ? ( void * ) pHbSqlite3->cbTraceHandler : NULL );
|
||||
}
|
||||
else
|
||||
iRes = sqlite3_trace_v2( pHbSqlite3->db, 0, NULL, NULL );
|
||||
hb_retni( iRes );
|
||||
}
|
||||
else
|
||||
hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
|
||||
#else
|
||||
hb_errRT_BASE_SubstR( EG_UNSUPPORTED, 0, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if SQLITE_VERSION_NUMBER < 3014000
|
||||
static void SQL3ProfileLog( void * sFile, const char * sProfileMsg, sqlite3_uint64 uint64 )
|
||||
{
|
||||
if( sProfileMsg )
|
||||
@@ -1811,9 +1927,11 @@ static void SQL3TraceLog( void * sFile, const char * sTraceMsg )
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
HB_FUNC( SQLITE3_PROFILE )
|
||||
{
|
||||
#if SQLITE_VERSION_NUMBER < 3014000
|
||||
HB_SQLITE3 * pHbSqlite3 = ( HB_SQLITE3 * ) hb_sqlite3_param( 1, HB_SQLITE3_DB, HB_TRUE );
|
||||
|
||||
if( pHbSqlite3 && pHbSqlite3->db )
|
||||
@@ -1835,10 +1953,14 @@ HB_FUNC( SQLITE3_PROFILE )
|
||||
}
|
||||
else
|
||||
hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
|
||||
#else
|
||||
hb_errRT_BASE_SubstR( EG_UNSUPPORTED, 0, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
|
||||
#endif
|
||||
}
|
||||
|
||||
HB_FUNC( SQLITE3_TRACE )
|
||||
{
|
||||
#if SQLITE_VERSION_NUMBER < 3014000
|
||||
HB_SQLITE3 * pHbSqlite3 = ( HB_SQLITE3 * ) hb_sqlite3_param( 1, HB_SQLITE3_DB, HB_TRUE );
|
||||
|
||||
if( pHbSqlite3 && pHbSqlite3->db )
|
||||
@@ -1860,8 +1982,12 @@ HB_FUNC( SQLITE3_TRACE )
|
||||
}
|
||||
else
|
||||
hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
|
||||
#else
|
||||
hb_errRT_BASE_SubstR( EG_UNSUPPORTED, 0, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
BLOB Import/export
|
||||
*/
|
||||
@@ -2360,3 +2486,46 @@ HB_FUNC( SQLITE3_CREATE_FUNCTION )
|
||||
else
|
||||
hb_retni( SQLITE_ERROR );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Get database filename for given connection and database name
|
||||
|
||||
sqlite3_db_filename( pDb, sDbName )
|
||||
*/
|
||||
HB_FUNC( SQLITE3_DB_FILENAME )
|
||||
{
|
||||
#if SQLITE_VERSION_NUMBER >= 3007010
|
||||
HB_SQLITE3 * pHbSqlite3 = ( HB_SQLITE3 * ) hb_sqlite3_param( 1, HB_SQLITE3_DB, HB_TRUE );
|
||||
|
||||
if( pHbSqlite3 && pHbSqlite3->db && HB_ISCHAR( 2 ) )
|
||||
hb_retc( ( const char * ) sqlite3_db_filename( pHbSqlite3->db, hb_parc( 2 ) ) );
|
||||
else
|
||||
hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
|
||||
#else
|
||||
hb_errRT_BASE_SubstR( EG_UNSUPPORTED, 0, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Get expanded SQL for a prepared statement
|
||||
|
||||
sqlite3_expanded_sql( pPreparedStatement )
|
||||
*/
|
||||
HB_FUNC( SQLITE3_EXPANDED_SQL )
|
||||
{
|
||||
#if SQLITE_VERSION_NUMBER >= 3014000
|
||||
psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 );
|
||||
if( pStmt )
|
||||
{
|
||||
char *sql = sqlite3_expanded_sql( pStmt );
|
||||
hb_retstr_utf8( sql );
|
||||
sqlite3_free( sql );
|
||||
}
|
||||
else
|
||||
hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
|
||||
#else
|
||||
hb_errRT_BASE_SubstR( EG_UNSUPPORTED, 0, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -174,4 +174,10 @@
|
||||
#define SQLITE_LIMIT_VARIABLE_NUMBER 9
|
||||
#define SQLITE_LIMIT_TRIGGER_DEPTH 10
|
||||
|
||||
/* Trace Event Codes */
|
||||
#define SQLITE_TRACE_STMT 0x01
|
||||
#define SQLITE_TRACE_PROFILE 0x02
|
||||
#define SQLITE_TRACE_ROW 0x04
|
||||
#define SQLITE_TRACE_CLOSE 0x08
|
||||
|
||||
#endif
|
||||
|
||||
@@ -72,6 +72,7 @@ DYNAMIC sqlite3_compileoption_get
|
||||
DYNAMIC sqlite3_compileoption_used
|
||||
DYNAMIC sqlite3_complete
|
||||
DYNAMIC sqlite3_create_function
|
||||
DYNAMIC sqlite3_db_filename
|
||||
DYNAMIC sqlite3_db_status
|
||||
DYNAMIC sqlite3_enable_load_extension
|
||||
DYNAMIC sqlite3_enable_shared_cache
|
||||
@@ -79,6 +80,7 @@ DYNAMIC sqlite3_errcode
|
||||
DYNAMIC sqlite3_errmsg
|
||||
DYNAMIC sqlite3_errstr
|
||||
DYNAMIC sqlite3_exec
|
||||
DYNAMIC sqlite3_expanded_sql
|
||||
DYNAMIC sqlite3_extended_errcode
|
||||
DYNAMIC sqlite3_extended_result_codes
|
||||
DYNAMIC sqlite3_file_to_buff
|
||||
@@ -116,6 +118,7 @@ DYNAMIC sqlite3_temp_directory
|
||||
DYNAMIC sqlite3_threadsafe
|
||||
DYNAMIC sqlite3_total_changes
|
||||
DYNAMIC sqlite3_trace
|
||||
DYNAMIC sqlite3_trace_v2
|
||||
|
||||
#if defined( __HBEXTREQ__ ) .OR. defined( __HBEXTERN__HBSQLIT3__REQUEST )
|
||||
#uncommand DYNAMIC <fncs,...> => EXTERNAL <fncs>
|
||||
|
||||
@@ -60,8 +60,29 @@
|
||||
|
||||
#require "hbsqlit3"
|
||||
|
||||
PROCEDURE init_trace( pDbDest, cPrefix )
|
||||
sqlite3_trace( pDbDest, .T., cPrefix + ".log" )
|
||||
#include "fileio.ch"
|
||||
|
||||
|
||||
PROCEDURE init_trace( pDb, cPrefix )
|
||||
LOCAL hFile
|
||||
IF sqlite3_libversion_number() < 3014000
|
||||
sqlite3_trace( pDb, .T., cPrefix + ".log" )
|
||||
ELSE
|
||||
hFile := FOpen( cPrefix + ".log", FO_READWRITE + HB_FO_CREAT )
|
||||
FSeek( hFile, 0, FS_END )
|
||||
sqlite3_trace_v2( pDb, SQLITE_TRACE_STMT + SQLITE_TRACE_CLOSE, {| nMask, p, x |
|
||||
IF nMask == SQLITE_TRACE_STMT /* p is pPreparedStatement, x is cOriginalSql */
|
||||
IF hb_LeftEq( x, "--" )
|
||||
FWrite( hFile, x + hb_eol() )
|
||||
ELSE
|
||||
FWrite( hFile, sqlite3_expanded_sql( p ) + hb_eol() )
|
||||
ENDIF
|
||||
ELSEIF nMask == SQLITE_TRACE_CLOSE /* p is the database connection */
|
||||
FWrite( hFile, "Closing the database connection: " + sqlite3_db_filename( p, "main" ) + hb_eol() )
|
||||
ENDIF
|
||||
RETURN 0
|
||||
} )
|
||||
ENDIF
|
||||
RETURN
|
||||
|
||||
PROCEDURE Main()
|
||||
@@ -69,6 +90,8 @@ PROCEDURE Main()
|
||||
LOCAL cFileSource := ":memory:", cFileDest := "backup.db", cSQLTEXT
|
||||
LOCAL pDbSource, pDbDest, pBackup, cb, nDbFlags
|
||||
|
||||
? "Using SQLite3 version " + hb_NToS( sqlite3_libversion_number() )
|
||||
|
||||
IF sqlite3_libversion_number() < 3006011
|
||||
ErrorLevel( 1 )
|
||||
RETURN
|
||||
@@ -167,7 +190,7 @@ STATIC FUNCTION PrepareDB( cFile )
|
||||
RETURN NIL
|
||||
ENDIF
|
||||
|
||||
sqlite3_trace( pDb, .T., "backup.log" )
|
||||
init_trace( pDb, "backup" )
|
||||
|
||||
cSQLTEXT := "CREATE TABLE person( name TEXT, age INTEGER )"
|
||||
IF sqlite3_exec( pDb, cSQLTEXT ) != SQLITE_OK
|
||||
|
||||
@@ -46,6 +46,8 @@
|
||||
|
||||
#require "hbsqlit3"
|
||||
|
||||
#include "fileio.ch"
|
||||
|
||||
#define TRACE
|
||||
#define TABLE_SQL "CREATE TABLE t1( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER )"
|
||||
|
||||
@@ -86,12 +88,34 @@ PROCEDURE t2()
|
||||
LOCAL nCCount, nCType, nI, nJ
|
||||
LOCAL aCType := { "SQLITE_INTEGER", "SQLITE_FLOAT", "SQLITE_TEXT", "SQLITE_BLOB", "SQLITE_NULL" }
|
||||
LOCAL aTable
|
||||
#ifdef TRACE
|
||||
LOCAL hTraceFile, hProfileFile
|
||||
#endif
|
||||
|
||||
IF ! Empty( db )
|
||||
|
||||
#ifdef TRACE
|
||||
sqlite3_profile( db, .T. )
|
||||
sqlite3_trace( db, .T. )
|
||||
IF sqlite3_libversion_number() < 3014000
|
||||
sqlite3_profile( db, .T. )
|
||||
sqlite3_trace( db, .T. )
|
||||
ELSE
|
||||
hTraceFile := FOpen( "hbsq3_tr.log", FO_READWRITE + HB_FO_CREAT )
|
||||
FSeek( hTraceFile, 0, FS_END )
|
||||
hProfileFile := FOpen( "hbsq3_pr.log", FO_READWRITE + HB_FO_CREAT )
|
||||
FSeek( hProfileFile, 0, FS_END )
|
||||
sqlite3_trace_v2( db, SQLITE_TRACE_STMT + SQLITE_TRACE_PROFILE, {| nMask, pStmt, x |
|
||||
IF nMask == SQLITE_TRACE_STMT
|
||||
IF hb_LeftEq( x, "--" )
|
||||
FWrite( hTraceFile, x + hb_eol() )
|
||||
ELSE
|
||||
FWrite( hTraceFile, sqlite3_expanded_sql( pStmt ) + hb_eol() )
|
||||
ENDIF
|
||||
ELSEIF nMask == SQLITE_TRACE_PROFILE
|
||||
FWrite( hProfileFile, sqlite3_expanded_sql( pStmt ) + " - " + hb_NToS( x ) + hb_eol() )
|
||||
ENDIF
|
||||
RETURN 0
|
||||
} )
|
||||
ENDIF
|
||||
#endif
|
||||
sqlite3_exec( db, "PRAGMA auto_vacuum=0" )
|
||||
sqlite3_exec( db, "PRAGMA page_size=4096" )
|
||||
|
||||
Reference in New Issue
Block a user