From a07aa6bb23abd9763d1ca4c3236e6271d07ef7b3 Mon Sep 17 00:00:00 2001 From: Petr Chornyj Date: Mon, 30 Mar 2009 08:23:58 +0000 Subject: [PATCH] 2009-03-30 11:30 UTC+0200 Petr Chornyj (myorg63 at mail.ru) * contrib/hbsqlit3/hbsqlit3.ch * contrib/hbsqlit3/hbsqlit3.c * Added support for sqlite_exec() callback. Now the 3rd parameter is an optional callback that is invoked once for each row of any query results. * Now we can pass name of logfile as third parameter of sqlite3_trace(), sqlite3_profile(). + Added sqlite3_set_authorizer() - Compile-Time Authorization Callbacks. + Added sqlite3_busy_handler() - A Callback To Handle SQLITE_BUSY Errors. + Added sqlite3_progress_handler() - Query Progress Callbacks. + Added sqlite3_commit_hook(), sqlite3_rollback_hook() - Commit And Rollback Notification Callbacks + Added sqlite3_backup_*() API for backups purposes. + Added sqlite3_initialize(), sqlite3_shutdown(), sqlite3_interrupt(), sqlite3_status(), sqlite3_db_status(), sqlite3_stmt_status(), sqlite3_sql(), sqlite3_extended_errcode(), sqlite3_threadsafe(), sqlite3_memory_used(), sqlite3_memory_highwater(). ! Fixed sqlite3_table_column_metadata(). - Temporary disabled sqlite3_db_handle(). * Minor changes, cleanup and formating. + contrib/hbsqlit3/tests/authorizer.prg + contrib/hbsqlit3/tests/backup.prg + contrib/hbsqlit3/tests/hooks.prg + Added for demonstration of new possibilities. + contrib/hbsqlit3/tests/metadata.prg * Minor changes --- harbour/ChangeLog | 30 + harbour/contrib/hbsqlit3/hbsqlit3.c | 1822 +++++++++++++---- harbour/contrib/hbsqlit3/hbsqlit3.ch | 120 +- harbour/contrib/hbsqlit3/tests/authorizer.prg | 255 +++ harbour/contrib/hbsqlit3/tests/backup.prg | 236 +++ harbour/contrib/hbsqlit3/tests/hooks.prg | 251 +++ harbour/contrib/hbsqlit3/tests/metadata.prg | 4 +- 7 files changed, 2319 insertions(+), 399 deletions(-) create mode 100644 harbour/contrib/hbsqlit3/tests/authorizer.prg create mode 100644 harbour/contrib/hbsqlit3/tests/backup.prg create mode 100644 harbour/contrib/hbsqlit3/tests/hooks.prg diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 06aa7d4262..8db2db9bd3 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,36 @@ 2009-12-31 13:59 UTC+0100 Foo Bar (foo.bar foobar.org) */ +2009-03-30 11:30 UTC+0200 Petr Chornyj (myorg63 at mail.ru) + * contrib/hbsqlit3/hbsqlit3.ch + * contrib/hbsqlit3/hbsqlit3.c + * Added support for sqlite_exec() callback. + Now the 3rd parameter is an optional callback that is invoked + once for each row of any query results. + * Now we can pass name of logfile as third parameter of + sqlite3_trace(), sqlite3_profile(). + + Added sqlite3_set_authorizer() - + Compile-Time Authorization Callbacks. + + Added sqlite3_busy_handler() - + A Callback To Handle SQLITE_BUSY Errors. + + Added sqlite3_progress_handler() - Query Progress Callbacks. + + Added sqlite3_commit_hook(), sqlite3_rollback_hook() - + Commit And Rollback Notification Callbacks + + Added sqlite3_backup_*() API for backups purposes. + + Added sqlite3_initialize(), sqlite3_shutdown(), sqlite3_interrupt(), + sqlite3_status(), sqlite3_db_status(), sqlite3_stmt_status(), + sqlite3_sql(), sqlite3_extended_errcode(), sqlite3_threadsafe(), + sqlite3_memory_used(), sqlite3_memory_highwater(). + ! Fixed sqlite3_table_column_metadata(). + - Temporary disabled sqlite3_db_handle(). + * Minor changes, cleanup and formating. + + contrib/hbsqlit3/tests/authorizer.prg + + contrib/hbsqlit3/tests/backup.prg + + contrib/hbsqlit3/tests/hooks.prg + + Added for demonstration of new possibilities. + + contrib/hbsqlit3/tests/metadata.prg + * Minor changes + 2009-03-30 10:01 UTC+0200 Viktor Szakats (harbour.01 syenar hu) * config/win/owatcom.cf * config/linux/owatcom.cf diff --git a/harbour/contrib/hbsqlit3/hbsqlit3.c b/harbour/contrib/hbsqlit3/hbsqlit3.c index 710fa01cac..84a638beff 100644 --- a/harbour/contrib/hbsqlit3/hbsqlit3.c +++ b/harbour/contrib/hbsqlit3/hbsqlit3.c @@ -6,7 +6,7 @@ * Harbour Project source code: * SQLite3 library low level (client api) interface code * - * Copyright 2007 P.Chornyj + * Copyright 2007-2009 P.Chornyj * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -51,14 +51,6 @@ * */ -/* - TODO?: Formatted String Printing Functions - - char *sqlite3_mprintf(const char*,...); - char *sqlite3_vmprintf(const char*, va_list); - char *sqlite3_hb_snprintf(int,char*,const char*, ...); -*/ - #include "sqlite3.h" #include "hbvm.h" @@ -66,56 +58,330 @@ #include "hbapiitm.h" #include "hbapierr.h" #include "hbapifs.h" +#include "hbstack.h" -#ifdef NODLL -extern char * sqlite3_temp_directory; -#endif -typedef sqlite3 * psqlite3; -typedef sqlite3_stmt * psqlite3_stmt; +#define HB_SQLITE3_DB 6000001 -/* - destructor, it's executed automatically +#define HB_ERR_MEMSTRU_NOT_MEM_BLOCK 4001 +#define HB_ERR_MEMSTRU_WRONG_MEMSTRU_BLOCK 4002 +#define HB_ERR_MEMSTRU_DESTROYED 4003 + +#ifdef SQLITE3_LIB +extern char *sqlite3_temp_directory; +#endif /* SQLITE3_LIB */ +PHB_ITEM hb_sqlite3_itemPut( PHB_ITEM pItem, void *pMemAddr, int iType ); +void *hb_sqlite3_itemGet( PHB_ITEM pItem, int iType, BOOL fError ); +void hb_sqlite3_ret( void *pMemAddr, int iType ); +void *hb_sqlite3_param( int iParam, int iType, BOOL fError ); +BOOL hb_sqlite3_store( void *pMemAddr, int iType, int iParam ); + +static int callback( void *, int, char **, char ** ); +static int authorizer( void *, int, const char *, const char *, const char *, const char * ); +static int busy_handler( void *, int ); +static int progress_handler( void * ); +static int hook_commit( void * ); +static void hook_rollback( void * ); + +static int callback( void *, int, char **, char ** ); +static int hook_commit( void * ); +static void hook_rollback( void * ); +static int authorizer( void *, int, const char *, const char *, const char *, const char * ); + +typedef struct +{ + sqlite3 *db; + PHB_DYNS cbAuthorizer; + PHB_DYNS cbBusyHandler; + PHB_DYNS cbProgressHandler; + PHB_DYNS cbHookCommit; + PHB_DYNS cbHookRollback; +} HB_SQLITE3, *PHB_SQLITE3; + +typedef struct +{ + int type; + HB_SQLITE3 *hbsqlite3; +} HB_SQLITE3_HOLDER, *PHB_SQLITE3_HOLDER; + +typedef sqlite3_stmt *psqlite3_stmt; + +/** + destructor, it's executed automatically */ -static HB_GARBAGE_FUNC( hb_sqlite3_Destructor ) +static HB_GARBAGE_FUNC( hb_sqlite3_destructor ) { - psqlite3 * dbPtr = ( psqlite3 * ) Cargo; + PHB_SQLITE3_HOLDER pStructHolder = ( PHB_SQLITE3_HOLDER ) Cargo; - if( *dbPtr ) + if( pStructHolder->hbsqlite3 ) { - sqlite3 * pDb = ( sqlite3 * ) dbPtr; + if( pStructHolder->hbsqlite3->db ) + { + sqlite3_close( pStructHolder->hbsqlite3->db ); + pStructHolder->hbsqlite3->db = NULL; + } - sqlite3_close( pDb ); + if( pStructHolder->hbsqlite3->cbAuthorizer ) + { + pStructHolder->hbsqlite3->cbAuthorizer = NULL; + } - *dbPtr = NULL; + if( pStructHolder->hbsqlite3->cbBusyHandler ) + { + pStructHolder->hbsqlite3->cbBusyHandler = NULL; + } + + if( pStructHolder->hbsqlite3->cbProgressHandler ) + { + pStructHolder->hbsqlite3->cbProgressHandler = NULL; + } + + if( pStructHolder->hbsqlite3->cbHookCommit ) + { + pStructHolder->hbsqlite3->cbHookCommit = NULL; + } + + if( pStructHolder->hbsqlite3->cbHookRollback ) + { + pStructHolder->hbsqlite3->cbHookRollback = NULL; + } + + hb_xfree( pStructHolder->hbsqlite3 ); + pStructHolder->hbsqlite3 = NULL; } } -/* - hb_par* & hb_ret* for sqlite3* +PHB_ITEM hb_sqlite3_itemPut( PHB_ITEM pItem, void *pMemAddr, int iType ) +{ + PHB_SQLITE3_HOLDER pStructHolder; + + if( pItem ) + { + if( HB_IS_COMPLEX(pItem) ) + { + hb_itemClear( pItem ); + } + } + else + { + pItem = hb_itemNew( pItem ); + } + + pStructHolder = ( PHB_SQLITE3_HOLDER ) hb_gcAlloc( sizeof(HB_SQLITE3_HOLDER), hb_sqlite3_destructor ); + pStructHolder->hbsqlite3 = ( HB_SQLITE3 * ) pMemAddr; + pStructHolder->type = iType; + + return hb_itemPutPtrGC( pItem, pStructHolder ); +} + +void *hb_sqlite3_itemGet( PHB_ITEM pItem, int iType, BOOL fError ) +{ + PHB_SQLITE3_HOLDER pStructHolder = ( PHB_SQLITE3_HOLDER ) hb_itemGetPtrGC( pItem, hb_sqlite3_destructor ); + int iError = 0; + + HB_SYMBOL_UNUSED( iError ); + + if( !pStructHolder ) + { + iError = HB_ERR_MEMSTRU_NOT_MEM_BLOCK; + } + else if( pStructHolder->type != iType ) + { + iError = HB_ERR_MEMSTRU_WRONG_MEMSTRU_BLOCK; + } + else if( !pStructHolder->hbsqlite3 ) + { + iError = HB_ERR_MEMSTRU_DESTROYED; + } + else + { + return pStructHolder->hbsqlite3; + } + + if( fError ) + { + hb_errRT_BASE_SubstR( EG_ARG, iError, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); + } + + return NULL; +} + +void hb_sqlite3_ret( void *pMemAddr, int iType ) +{ + hb_sqlite3_itemPut( hb_stackReturnItem(), pMemAddr, iType ); +} + +void *hb_sqlite3_param( int iParam, int iType, BOOL fError ) +{ + return hb_sqlite3_itemGet( hb_param(iParam, HB_IT_POINTER), iType, fError ); +} + +BOOL hb_sqlite3_store( void *pMemAddr, int iType, int iParam ) +{ + PHB_ITEM pItem = hb_param( iParam, HB_IT_BYREF ); + if( !pItem ) + { + return FALSE; + } + + hb_sqlite3_itemPut( pItem, pMemAddr, iType ); + return TRUE; +} + +/** + Callbacs helpers: + Compile-Time Authorization Callback + A Callback To Handle SQLITE_BUSY Errors + Query Progress Callbacks + Commit And Rollback Notification Callback */ -static psqlite3 hb_parsqlite3( int iParam ) +static int callback( void *Cargo, int argc, char **argv, char **azColName ) { - psqlite3 * dbPtr = ( psqlite3 * ) hb_parptrGC( hb_sqlite3_Destructor, iParam ); + PHB_DYNS pSym = ( PHB_DYNS ) Cargo; - return dbPtr ? *dbPtr : NULL; + if( pSym ) + { + PHB_ITEM pArrayValue = hb_itemArrayNew( argc ); + PHB_ITEM pArrayColName = hb_itemArrayNew( argc ); + int iRes, i; + + for( i = 0; i < argc; i++ ) + { + hb_arraySetC( pArrayValue, i + 1, argv[i] ? argv[i] : "NULL" ); + hb_arraySetC( pArrayColName, i + 1, azColName[i] ); + } + + hb_vmPushDynSym( pSym ); + hb_vmPushNil(); + hb_vmPushInteger( argc ); + hb_vmPush( pArrayValue ); + hb_vmPush( pArrayColName ); + hb_vmDo( 3 ); + + iRes = hb_parni( -1 ); + + hb_itemRelease( pArrayValue ); + hb_itemRelease( pArrayColName ); + + return iRes; + } + + return 0; } -static void hb_retsqlite3( sqlite3 * pDb ) +static int authorizer( void *Cargo, int iAction, const char *sName1, const char *sName2, const char *sName3, const char *sName4 ) { - psqlite3 * dbPtr = ( psqlite3 * ) hb_gcAlloc( sizeof( psqlite3 ), hb_sqlite3_Destructor ); + PHB_DYNS pSym = ( PHB_DYNS ) Cargo; - *dbPtr = pDb; + if( pSym ) + { + int iRes; + PHB_ITEM pItem1 = hb_itemPutCConst( NULL, sName1 ); + PHB_ITEM pItem2 = hb_itemPutCConst( NULL, sName2 ); + PHB_ITEM pItem3 = hb_itemPutCConst( NULL, sName3 ); + PHB_ITEM pItem4 = hb_itemPutCConst( NULL, sName4 ); - hb_retptrGC( ( void * ) dbPtr ); + hb_vmPushDynSym( pSym ); + hb_vmPushNil(); + hb_vmPushInteger( iAction ); + hb_vmPush( pItem1 ); + hb_vmPush( pItem2 ); + hb_vmPush( pItem3 ); + hb_vmPush( pItem4 ); + + hb_vmDo( 5 ); + iRes = hb_parni( -1 ); + + hb_itemRelease( pItem1 ); + hb_itemRelease( pItem2 ); + hb_itemRelease( pItem3 ); + hb_itemRelease( pItem4 ); + + return iRes; + } + + return 0; } -/* +static int busy_handler( void *Cargo, int iNumberOfTimes ) +{ + PHB_DYNS pSym = ( PHB_DYNS ) Cargo; + + if( pSym ) + { + int iRes; + + hb_vmPushDynSym( pSym ); + hb_vmPushNil(); + hb_vmPushInteger( iNumberOfTimes ); + hb_vmDo( 1 ); + + iRes = hb_parni( -1 ); + + return iRes; + } + + return 0; +} + +static int progress_handler( void *Cargo ) +{ + PHB_DYNS pSym = ( PHB_DYNS ) Cargo; + + if( pSym ) + { + int iRes; + + hb_vmPushDynSym( pSym ); + hb_vmPushNil(); + hb_vmDo( 0 ); + + iRes = hb_parni( -1 ); + + return iRes; + } + + return 0; +} + +static int hook_commit( void *Cargo ) +{ + PHB_DYNS pSym = ( PHB_DYNS ) Cargo; + + if( pSym ) + { + int iRes; + + hb_vmPushDynSym( pSym ); + hb_vmPushNil(); + hb_vmDo( 0 ); + + iRes = hb_parni( -1 ); + + return iRes; + } + + return 0; +} + +static void hook_rollback( void *Cargo ) +{ + PHB_DYNS pSym = ( PHB_DYNS ) Cargo; + + if( pSym ) + { + hb_vmPushDynSym( pSym ); + hb_vmPushNil(); + hb_vmDo( 0 ); + } +} + +/** sqlite3_libversion() -> cVersion sqlite3_libversion_number() -> nVersionNumber - Returns values equivalent to the header constants + Returns values equivalent to the header constants SQLITE_VERSION and SQLITE_VERSION_NUMBER. */ @@ -129,7 +395,26 @@ HB_FUNC( SQLITE3_LIBVERSION_NUMBER ) hb_retni( sqlite3_libversion_number() ); } -/* +/** + sqlite3_initialize() -> nResult + sqlite3_shutdown() -> nResult + + The sqlite3_initialize() routine initializes the SQLite library. + The sqlite3_shutdown() routine deallocates any resources that were + allocated by sqlite3_initialize() +*/ + +HB_FUNC( SQLITE3_INITIALIZE ) +{ + hb_retni( sqlite3_initialize() ); +} + +HB_FUNC( SQLITE3_SHUTDOWN ) +{ + hb_retni( sqlite3_shutdown() ); +} + +/** Enable Or Disable Extended Result Codes sqlite3_extended_result_codes( db, lOnOff) -> nResultCode @@ -137,44 +422,72 @@ HB_FUNC( SQLITE3_LIBVERSION_NUMBER ) HB_FUNC( SQLITE3_EXTENDED_RESULT_CODES ) { - psqlite3 db = hb_parsqlite3( 1 ); + HB_SQLITE3 *pHbSqlite3 = ( HB_SQLITE3 * ) hb_sqlite3_param( 1, HB_SQLITE3_DB, TRUE ); - if( db ) - hb_retni( sqlite3_extended_result_codes( db, hb_parl( 2 ) ) ); + if( pHbSqlite3 && pHbSqlite3->db ) + { + hb_retni( sqlite3_extended_result_codes(pHbSqlite3->db, hb_parl(2)) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } -/* +/** Error Codes And Messages sqlite3_errcode( db ) -> returns the numeric result code or extended result - code - sqlite3_errmsg( db ) -> return English-language text + code + sqlite3_errmsg( db ) -> return English-language text that describes the error */ HB_FUNC( SQLITE3_ERRCODE ) { - psqlite3 db = hb_parsqlite3( 1 ); + HB_SQLITE3 *pHbSqlite3 = ( HB_SQLITE3 * ) hb_sqlite3_param( 1, HB_SQLITE3_DB, TRUE ); - if( db ) - hb_retni( sqlite3_errcode( db ) ); + if( pHbSqlite3 && pHbSqlite3->db ) + { + hb_retni( sqlite3_errcode(pHbSqlite3->db) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } +#if SQLITE_VERSION_NUMBER >= 3006005 +HB_FUNC( SQLITE3_EXTENDED_ERRCODE ) +{ + HB_SQLITE3 *pHbSqlite3 = ( HB_SQLITE3 * ) hb_sqlite3_param( 1, HB_SQLITE3_DB, TRUE ); + + if( pHbSqlite3 && pHbSqlite3->db ) + { + hb_retni( sqlite3_extended_errcode(pHbSqlite3->db) ); + } + else + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } +} +#endif /* SQLITE_VERSION_NUMBER >= 3006005 */ + HB_FUNC( SQLITE3_ERRMSG ) { - psqlite3 db = hb_parsqlite3( 1 ); + HB_SQLITE3 *pHbSqlite3 = ( HB_SQLITE3 * ) hb_sqlite3_param( 1, HB_SQLITE3_DB, TRUE ); - if( db ) - hb_retc( sqlite3_errmsg( db ) ); + if( pHbSqlite3 && pHbSqlite3->db ) + { + hb_retc( sqlite3_errmsg(pHbSqlite3->db) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } -/* +/** Suspend Execution For A Short Time sqlite3_sleep( ms ) @@ -182,10 +495,10 @@ HB_FUNC( SQLITE3_ERRMSG ) HB_FUNC( SQLITE3_SLEEP ) { - hb_retni( sqlite3_sleep( hb_parni( 1 ) ) ); + hb_retni( sqlite3_sleep(hb_parni(1)) ); } -/* +/** Last Insert Rowid sqlite3_last_insert_rowid( db ) -> nROWID @@ -193,77 +506,95 @@ HB_FUNC( SQLITE3_SLEEP ) HB_FUNC( SQLITE3_LAST_INSERT_ROWID ) { - psqlite3 db = hb_parsqlite3( 1 ); + HB_SQLITE3 *pHbSqlite3 = ( HB_SQLITE3 * ) hb_sqlite3_param( 1, HB_SQLITE3_DB, TRUE ); - if( db ) - hb_retnint( sqlite3_last_insert_rowid( db ) ); + if( pHbSqlite3 && pHbSqlite3->db ) + { + hb_retnint( sqlite3_last_insert_rowid(pHbSqlite3->db) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } -/* +/** Name Of The Folder Holding Temporary Files - sqlite3_temp_directory( cDirName ) -> lResult (TRUE/FALSE) + sqlite3_temp_directory( cDirName ) -> lResult (TRUE/FALSE) */ HB_FUNC( SQLITE3_TEMP_DIRECTORY ) { BOOL bResult = FALSE; - #ifdef NODLL + #ifdef SQLITE3_LIB { - BOOL fFree; - char * pszDirName = hb_fsNameConv( ( BYTE * ) hb_parc( 1 ), &fFree ); + BOOL fFree; + BYTE *pszDirName = hb_fsNameConv( ( BYTE * ) hb_parcx(1), &fFree ); - if( hb_fsIsDirectory( pszDirName ) ) + if( hb_fsIsDirectory(pszDirName) ) + { bResult = TRUE; + } else { - if( hb_parl( 2 ) ) /* create temp directory if not exist */ + if( hb_parl(2) ) /* create temp directory if not exist */ { - if( hb_fsMkDir( pszDirName ) ) + if( hb_fsMkDir(pszDirName) ) + { bResult = TRUE; + } else { - HB_TRACE(HB_TR_DEBUG, ("sqlite_temp_directory(): Can't create directory %s", pszDirName)); + HB_TRACE( HB_TR_DEBUG, ("sqlite_temp_directory(): Can't create directory %s", pszDirName) ); } } else { - HB_TRACE(HB_TR_DEBUG, ("sqlite_temp_directory(): Directory doesn't exist %s", pszDirName)); + HB_TRACE( HB_TR_DEBUG, ("sqlite_temp_directory(): Directory doesn't exist %s", pszDirName) ); } } if( bResult ) - sqlite3_temp_directory = hb_strdup( pszDirName ); + { + sqlite3_temp_directory = hb_strdup( ( const char * ) pszDirName ); + } if( fFree ) - hb_xfree( pszDirName ); + { + hb_xfree( ( void * ) pszDirName ); + } } - #endif - + #endif /* SQLITE3_LIB */ hb_retl( bResult ); } -/* +/** Opening( creating ) A New Database Connection sqlite3_open( cDatabace, lCreateIfNotExist ) -> return pointer to Db or NIL if error occurs - sqlite3_open_v2( cDatabace, nOpenMode ) -> return pDb or NIL + sqlite3_open_v2( cDatabace, nOpenMode ) -> return pHbSqlite3 or NIL */ HB_FUNC( SQLITE3_OPEN ) { - psqlite3 db; - BOOL fFree; - char * pszdbName = ( char * ) hb_fsNameConv( ( BYTE * ) hb_parc( 1 ), &fFree ); + sqlite3 *db; + BOOL fFree; + char *pszdbName = ( char * ) hb_fsNameConv( ( BYTE * ) hb_parcx(1), &fFree ); - if( hb_fsFile( ( BYTE * ) pszdbName ) || hb_parl( 2 ) ) + if( hb_fsFileExists(( const char * ) pszdbName) || hb_parl(2) ) { - if( sqlite3_open( pszdbName, &db ) == SQLITE_OK ) - hb_retsqlite3( db ); + if( sqlite3_open(pszdbName, &db) == SQLITE_OK ) + { + HB_SQLITE3 *hbsqlite3; + + hbsqlite3 = ( HB_SQLITE3 * ) hb_xgrab( sizeof(HB_SQLITE3) ); + hb_xmemset( hbsqlite3, 0, sizeof(HB_SQLITE3) ); + hbsqlite3->db = db; + hb_sqlite3_ret( hbsqlite3, HB_SQLITE3_DB ); + } else { sqlite3_close( db ); @@ -273,23 +604,32 @@ HB_FUNC( SQLITE3_OPEN ) } else { - HB_TRACE(HB_TR_DEBUG, ("sqlite3_open(): Database doesn't exist %s", pszdbName)); + HB_TRACE( HB_TR_DEBUG, ("sqlite3_open(): Database doesn't exist %s", pszdbName) ); hb_retptr( NULL ); } if( fFree ) + { hb_xfree( pszdbName ); + } } HB_FUNC( SQLITE3_OPEN_V2 ) { - psqlite3 db; - BOOL fFree; - char * pszdbName = ( char * ) hb_fsNameConv( ( BYTE * ) hb_parc( 1 ), &fFree ); + sqlite3 *db; + BOOL fFree; + char *pszdbName = ( char * ) hb_fsNameConv( ( BYTE * ) hb_parcx(1), &fFree ); - if( sqlite3_open_v2( pszdbName, &db, hb_parni( 2 ), NULL ) == SQLITE_OK ) - hb_retsqlite3( db ); + if( sqlite3_open_v2(pszdbName, &db, hb_parni(2), NULL) == SQLITE_OK ) + { + HB_SQLITE3 *hbsqlite3; + + hbsqlite3 = ( HB_SQLITE3 * ) hb_xgrab( sizeof(HB_SQLITE3) ); + hb_xmemset( hbsqlite3, 0, sizeof(HB_SQLITE3) ); + hbsqlite3->db = db; + hb_sqlite3_ret( hbsqlite3, HB_SQLITE3_DB ); + } else { sqlite3_close( db ); @@ -298,40 +638,70 @@ HB_FUNC( SQLITE3_OPEN_V2 ) } if( fFree ) + { hb_xfree( pszdbName ); + } } -/* +/** One-Step Query Execution Interface - - sqlite3_exec( db, cSQLTEXT ) -> nResultCode + + sqlite3_exec( db, cSQLTEXT, [pCallbackFunc]|[cCallbackFunc] ) -> nResultCode */ HB_FUNC( SQLITE3_EXEC ) { - psqlite3 db = hb_parsqlite3( 1 ); + HB_SQLITE3 *pHbSqlite3 = ( HB_SQLITE3 * ) hb_sqlite3_param( 1, HB_SQLITE3_DB, TRUE ); - if( db ) + if( pHbSqlite3 && pHbSqlite3->db ) { - char * pszErrMsg = NULL; - int rc = sqlite3_exec( db, hb_parc( 2 ), NULL, 0, &pszErrMsg ); + char *pszErrMsg = NULL; + PHB_DYNS pDynSym; + int rc; + + if( HB_ISCHAR(3) || HB_ISSYMBOL(3) ) + { + if( HB_ISCHAR(3) ) + { + pDynSym = hb_dynsymFindName( hb_parc(3) ); + } + else + { + pDynSym = hb_dynsymNew( hb_itemGetSymbol(hb_param(3, HB_IT_SYMBOL)) ); + } + + if( pDynSym && hb_dynsymIsFunction(pDynSym) ) + { + rc = sqlite3_exec( pHbSqlite3->db, hb_parc(2), callback, ( void * ) pDynSym, &pszErrMsg ); + } + else + { + rc = sqlite3_exec( pHbSqlite3->db, hb_parc(2), NULL, 0, &pszErrMsg ); + } + } + else + { + rc = sqlite3_exec( pHbSqlite3->db, hb_parc(2), NULL, 0, &pszErrMsg ); + } if( rc != SQLITE_OK ) { - HB_TRACE(HB_TR_DEBUG, ("sqlite3_exec(): Returned error: %s", pszErrMsg)); + HB_TRACE( HB_TR_DEBUG, ("sqlite3_exec(): Returned error: %s", pszErrMsg) ); sqlite3_free( pszErrMsg ); } hb_retni( rc ); } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } -/* +/** Compiling An SQL Statement - sqlite3_prepare( db, cSQLTEXT ) + sqlite3_prepare( db, cSQLTEXT ) -> return pointer to compiled statement or NIL if error occurs TODO: pszTail? @@ -339,21 +709,23 @@ HB_FUNC( SQLITE3_EXEC ) HB_FUNC( SQLITE3_PREPARE ) { - psqlite3 pDb = hb_parsqlite3( 1 ); + HB_SQLITE3 *pHbSqlite3 = ( HB_SQLITE3 * ) hb_sqlite3_param( 1, HB_SQLITE3_DB, TRUE ); - if( pDb ) + if( pHbSqlite3 && pHbSqlite3->db ) { PHB_ITEM SQL = hb_param( 2, HB_IT_STRING ); if( SQL ) { - char * pSQL = hb_itemGetCPtr( SQL ); - ULONG ulLen = hb_itemGetCLen( SQL ); - psqlite3_stmt pStmt; - const char * pszTail; + char *pSQL = hb_itemGetCPtr( SQL ); + ULONG ulLen = hb_itemGetCLen( SQL ); + psqlite3_stmt pStmt; + const char *pszTail; - if( sqlite3_prepare_v2( pDb, pSQL, ulLen, &pStmt, &pszTail ) == SQLITE_OK ) + if( sqlite3_prepare_v2(pHbSqlite3->db, pSQL, ulLen, &pStmt, &pszTail) == SQLITE_OK ) + { hb_retptr( pStmt ); + } else { sqlite3_finalize( pStmt ); @@ -362,65 +734,138 @@ HB_FUNC( SQLITE3_PREPARE ) } } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 2 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(2) ); + } } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } -/* - Find The Database Handle Associated With A Prepared Statement +/** + Determine If An SQL Statement Is Complete - sqlite3_db_handle( pStmt ) -> pDb + sqlite3_complete( sqlText ) -> lResult */ -HB_FUNC( SQLITE3_DB_HANDLE ) +HB_FUNC( SQLITE3_COMPLETE ) { - psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); - - if( pStmt ) - hb_retsqlite3( sqlite3_db_handle( pStmt ) ); - else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + hb_retl( sqlite3_complete(hb_parc(1)) ); } -/* - Evaluate An Prepared SQL Statement +/** + This interface can be used to retrieve a saved copy of the original SQL text + used to create a prepared statement + if that statement was compiled using either sqlite3_prepare() + sqlite3_sql( pStmt ) -> cSQLTEXT +*/ + +HB_FUNC( SQLITE3_SQL ) +{ + psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); + + if( pStmt ) + { + hb_retc( sqlite3_sql(pStmt) ); + } + else + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } +} + +/** + Prepared Statement Status. + + sqlite3_stmt_status( pStmt, nOp, lResetFlag) -> nStatus +*/ + +#if SQLITE_VERSION_NUMBER >= 3006004 +HB_FUNC( SQLITE3_STMT_STATUS ) +{ + psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); + + if( pStmt ) + { + hb_retni( sqlite3_stmt_status(pStmt, hb_parni(2), ( int ) hb_parl(3)) ); + } + else + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } +} +#endif /* SQLITE_VERSION_NUMBER >= 3006004 */ + +/** + Find The Database Handle Associated With A Prepared Statement + + sqlite3_db_handle( pStmt ) -> pHbSqlite3 +*/ + +/* +HB_FUNC( SQLITE3_DB_HANDLE ) +{ + psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); + + if( pStmt ) + { + ; + } + else + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } +} +*/ + +/** + Evaluate An Prepared SQL Statement + sqlite3_step( pStmt ) -> nResultCode */ HB_FUNC( SQLITE3_STEP ) { - psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); + psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); if( pStmt ) - hb_retni( sqlite3_step( pStmt ) ); + { + hb_retni( sqlite3_step(pStmt) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } -/* +/** Reset All Bindings On A Prepared Statement sqlite3_clear_bindings( pStmt ) -> nResultCode - Contrary to the intuition of many, - sqlite3_reset() does not reset the bindings on a prepared statement. + Contrary to the intuition of many, + sqlite3_reset() does not reset the bindings on a prepared statement. Use this routine to reset all host parameters to NULL. */ HB_FUNC( SQLITE3_CLEAR_BINDINGS ) { - psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); + psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); if( pStmt ) - hb_retni( sqlite3_clear_bindings( pStmt ) ); + { + hb_retni( sqlite3_clear_bindings(pStmt) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } -/* +/** Reset A Prepared Statement Object sqlite3_reset( pStmt ) -> nResultCode @@ -428,15 +873,19 @@ HB_FUNC( SQLITE3_CLEAR_BINDINGS ) HB_FUNC( SQLITE3_RESET ) { - psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); + psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); if( pStmt ) - hb_retni( sqlite3_reset( pStmt ) ); + { + hb_retni( sqlite3_reset(pStmt) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } -/* +/** Finalize A Prepared Statement Object sqlite3_finalize( pStmt ) -> nResultCode @@ -444,12 +893,16 @@ HB_FUNC( SQLITE3_RESET ) HB_FUNC( SQLITE3_FINALIZE ) { - psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); + psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); if( pStmt ) - hb_retni( sqlite3_finalize( pStmt ) ); + { + hb_retni( sqlite3_finalize(pStmt) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } /* @@ -463,89 +916,117 @@ int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n) */ -/* +/** Binding Values To Prepared Statements - These routines return SQLITE_OK on success or an error code if anything - goes wrong. - SQLITE_RANGE is returned if the parameter index is out of range. - SQLITE_NOMEM is returned if malloc fails. + These routines return SQLITE_OK on success or an error code if anything + goes wrong. + SQLITE_RANGE is returned if the parameter index is out of range. + SQLITE_NOMEM is returned if malloc fails. SQLITE_MISUSE is returned if these routines are called on a virtual machine that is the wrong state or which has already been finalized. */ HB_FUNC( SQLITE3_BIND_BLOB ) { - psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); + psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); if( pStmt ) - hb_retni( sqlite3_bind_blob( pStmt, hb_parni( 2 ), ( const char * ) hb_parcx( 3 ), hb_parcsiz( 3 ) - 1, SQLITE_TRANSIENT ) ); + { + hb_retni( sqlite3_bind_blob(pStmt, hb_parni(2), ( const char * ) hb_parcx(3), hb_parcsiz(3) - 1, SQLITE_TRANSIENT) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } HB_FUNC( SQLITE3_BIND_DOUBLE ) { - psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); + psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); if( pStmt ) - hb_retni( sqlite3_bind_double( pStmt, hb_parni( 2 ), hb_parnd( 3 ) ) ); + { + hb_retni( sqlite3_bind_double(pStmt, hb_parni(2), hb_parnd(3)) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } HB_FUNC( SQLITE3_BIND_INT ) { - psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); + psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); if( pStmt ) - hb_retni( sqlite3_bind_int( pStmt, hb_parni( 2 ), hb_parni( 3 ) ) ); + { + hb_retni( sqlite3_bind_int(pStmt, hb_parni(2), hb_parni(3)) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } HB_FUNC( SQLITE3_BIND_INT64 ) { - psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); - sqlite3_int64 int64 = hb_parnint( 3 ); + psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); + sqlite3_int64 int64 = hb_parnint( 3 ); if( pStmt ) - hb_retni( sqlite3_bind_int64( pStmt, hb_parni( 2 ), int64 ) ); + { + hb_retni( sqlite3_bind_int64(pStmt, hb_parni(2), int64) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } HB_FUNC( SQLITE3_BIND_NULL ) { - psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); + psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); if( pStmt ) - hb_retni( sqlite3_bind_null( pStmt, hb_parni( 2 ) ) ); + { + hb_retni( sqlite3_bind_null(pStmt, hb_parni(2)) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } HB_FUNC( SQLITE3_BIND_TEXT ) { - psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); + psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); if( pStmt ) - hb_retni( sqlite3_bind_text( pStmt, hb_parni( 2 ), ( const char * ) hb_parc( 3 ), hb_parclen( 3 ), SQLITE_TRANSIENT ) ); + { + hb_retni( sqlite3_bind_text(pStmt, hb_parni(2), ( const char * ) hb_parc(3), hb_parclen(3), SQLITE_TRANSIENT) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } HB_FUNC( SQLITE3_BIND_ZEROBLOB ) { - psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); + psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); if( pStmt ) - hb_retni( sqlite3_bind_zeroblob( pStmt, hb_parni( 2 ), hb_parni( 3 ) ) ); + { + hb_retni( sqlite3_bind_zeroblob(pStmt, hb_parni(2), hb_parni(3)) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } -/* +/** Number Of Host Parameters sqlite3_bind_parameter_count( pStmt ) -> nResult @@ -553,15 +1034,19 @@ HB_FUNC( SQLITE3_BIND_ZEROBLOB ) HB_FUNC( SQLITE3_BIND_PARAMETER_COUNT ) { - psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); + psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); if( pStmt ) - hb_retni( sqlite3_bind_parameter_count( pStmt ) ); + { + hb_retni( sqlite3_bind_parameter_count(pStmt) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } -/* +/** Index Of A Parameter With A Given Name sqlite3_bind_parameter_index( pStmt, cParameterName ) -> nResult @@ -569,15 +1054,19 @@ HB_FUNC( SQLITE3_BIND_PARAMETER_COUNT ) HB_FUNC( SQLITE3_BIND_PARAMETER_INDEX ) { - psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); + psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); if( pStmt ) - hb_retni( sqlite3_bind_parameter_index( pStmt, hb_parc( 2 ) ) ); + { + hb_retni( sqlite3_bind_parameter_index(pStmt, hb_parc(2)) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } -/* +/** Name Of A Host Parameter sqlite3_bind_parameter_name( pStmt, nParameterIndex ) -> cParameterName @@ -585,15 +1074,19 @@ HB_FUNC( SQLITE3_BIND_PARAMETER_INDEX ) HB_FUNC( SQLITE3_BIND_PARAMETER_NAME ) { - psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); + psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); if( pStmt ) - hb_retc( sqlite3_bind_parameter_name( pStmt, hb_parni( 2 ) ) ); + { + hb_retc( sqlite3_bind_parameter_name(pStmt, hb_parni(2)) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } -/* +/** Count The Number Of Rows Modified sqlite3_changes( db ) -> nRowCount @@ -601,15 +1094,19 @@ HB_FUNC( SQLITE3_BIND_PARAMETER_NAME ) HB_FUNC( SQLITE3_CHANGES ) { - psqlite3 db = hb_parsqlite3( 1 ); + HB_SQLITE3 *pHbSqlite3 = ( HB_SQLITE3 * ) hb_sqlite3_param( 1, HB_SQLITE3_DB, TRUE ); - if( db ) - hb_retni( sqlite3_changes(db) ); + if( pHbSqlite3 && pHbSqlite3->db ) + { + hb_retni( sqlite3_changes(pHbSqlite3->db) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } -/* +/** Total Number Of Rows Modified sqlite3_total_changes( db ) -> nRowCount @@ -617,15 +1114,19 @@ HB_FUNC( SQLITE3_CHANGES ) HB_FUNC( SQLITE3_TOTAL_CHANGES ) { - psqlite3 db = hb_parsqlite3( 1 ); + HB_SQLITE3 *pHbSqlite3 = ( HB_SQLITE3 * ) hb_sqlite3_param( 1, HB_SQLITE3_DB, TRUE ); - if( db ) - hb_retni( sqlite3_total_changes(db) ); + if( pHbSqlite3 && pHbSqlite3->db ) + { + hb_retni( sqlite3_total_changes(pHbSqlite3->db) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } -/* +/** Number Of Columns In A Result Set sqlite3_column_count( pStmt ) -> nColumnCount @@ -633,17 +1134,20 @@ HB_FUNC( SQLITE3_TOTAL_CHANGES ) HB_FUNC( SQLITE3_COLUMN_COUNT ) { - psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); + psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); if( pStmt ) - hb_retni( sqlite3_column_count( pStmt ) ); + { + hb_retni( sqlite3_column_count(pStmt) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } -/* +/** sqlite3_column_type( pStmt, nIndex ) -> nColumnType - nColumnType is Datatype code for the initial data type of the result column SQLITE_INTEGER 1 @@ -652,32 +1156,40 @@ HB_FUNC( SQLITE3_COLUMN_COUNT ) SQLITE3_TEXT 3 SQLITE_BLOB 4 SQLITE_NULL 5 - + Declared Datatype Of A Query Result (see doc) sqlite3_column_decltype( pStmt, nIndex ) -> nColumnDeclType */ HB_FUNC( SQLITE3_COLUMN_TYPE ) { - psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); + psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); if( pStmt ) - hb_retni( sqlite3_column_type( pStmt, hb_parni( 2 ) - 1 ) ); + { + hb_retni( sqlite3_column_type(pStmt, hb_parni(2) - 1) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } HB_FUNC( SQLITE3_COLUMN_DECLTYPE ) { - psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); + psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); if( pStmt ) - hb_retc( sqlite3_column_decltype( pStmt, hb_parni( 2 ) - 1 ) ); + { + hb_retc( sqlite3_column_decltype(pStmt, hb_parni(2) - 1) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } -/* +/** Column Names In A Result Set sqlite3_column_name( pStmt, columnIndex) -> columnName @@ -685,16 +1197,20 @@ HB_FUNC( SQLITE3_COLUMN_DECLTYPE ) HB_FUNC( SQLITE3_COLUMN_NAME ) { - psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); + psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); if( pStmt ) - hb_retc( sqlite3_column_name( pStmt, hb_parni( 2 ) - 1 ) ); + { + hb_retc( sqlite3_column_name(pStmt, hb_parni(2) - 1) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } -/* - sqlite3_column_bytes( pStmt, columnIndex ) +/** + sqlite3_column_bytes( pStmt, columnIndex ) -> returns the number of bytes in that BLOB or string Results Values From A Query @@ -708,74 +1224,92 @@ HB_FUNC( SQLITE3_COLUMN_NAME ) HB_FUNC( SQLITE3_COLUMN_BYTES ) { - psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); + psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); if( pStmt ) - hb_retni( sqlite3_column_bytes( pStmt, hb_parni( 2 ) - 1 ) ); + { + hb_retni( sqlite3_column_bytes(pStmt, hb_parni(2) - 1) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } HB_FUNC( SQLITE3_COLUMN_BLOB ) { - psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); + psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); if( pStmt ) { - int index = hb_parni( 2 ) - 1; + int index = hb_parni( 2 ) - 1; - hb_retclen( ( const char * ) sqlite3_column_blob( pStmt, index ), - sqlite3_column_bytes( pStmt, index ) ); + hb_retclen( ( const char * ) sqlite3_column_blob(pStmt, index), sqlite3_column_bytes(pStmt, index) ); } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } HB_FUNC( SQLITE3_COLUMN_DOUBLE ) { - psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); + psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); if( pStmt ) - hb_retnd( sqlite3_column_double( pStmt, hb_parni( 2 ) - 1 ) ); + { + hb_retnd( sqlite3_column_double(pStmt, hb_parni(2) - 1) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } HB_FUNC( SQLITE3_COLUMN_INT ) { - psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); + psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); if( pStmt ) - hb_retni( sqlite3_column_int( pStmt, hb_parni( 2 ) - 1 ) ); + { + hb_retni( sqlite3_column_int(pStmt, hb_parni(2) - 1) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } HB_FUNC( SQLITE3_COLUMN_INT64 ) { - psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); + psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); if( pStmt ) - hb_retnint( sqlite3_column_int64( pStmt, hb_parni( 2 ) - 1 ) ); + { + hb_retnint( sqlite3_column_int64(pStmt, hb_parni(2) - 1) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } HB_FUNC( SQLITE3_COLUMN_TEXT ) { - psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); + psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); if( pStmt ) { - int index = hb_parni( 2 ) - 1; - hb_retclen( ( char * ) sqlite3_column_text( pStmt, index ), - sqlite3_column_bytes( pStmt, index ) ); + int index = hb_parni( 2 ) - 1; + hb_retclen( ( char * ) sqlite3_column_text(pStmt, index), sqlite3_column_bytes(pStmt, index) ); } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } -/* +/** Enable Or Disable Extension Loading sqlite3_enable_load_extension( db, lOnOff ) -> prev.state @@ -783,12 +1317,16 @@ HB_FUNC( SQLITE3_COLUMN_TEXT ) HB_FUNC( SQLITE3_ENABLE_LOAD_EXTENSION ) { - psqlite3 db = hb_parsqlite3( 1 ); + HB_SQLITE3 *pHbSqlite3 = ( HB_SQLITE3 * ) hb_sqlite3_param( 1, HB_SQLITE3_DB, TRUE ); - if( db ) - hb_retni( sqlite3_enable_load_extension( db, hb_parl( 2 ) ) ); + if( pHbSqlite3 && pHbSqlite3->db ) + { + hb_retni( sqlite3_enable_load_extension(pHbSqlite3->db, hb_parl(2)) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } /* @@ -802,7 +1340,7 @@ HB_FUNC( SQLITE3_RESET_AUTO_EXTENSION ) sqlite3_reset_auto_extension(); } -/* +/** Set A Busy Timeout sqlite3_busy_timeout( db, ms ) @@ -810,26 +1348,19 @@ HB_FUNC( SQLITE3_RESET_AUTO_EXTENSION ) HB_FUNC( SQLITE3_BUSY_TIMEOUT ) { - psqlite3 db = hb_parsqlite3( 1 ); + HB_SQLITE3 *pHbSqlite3 = ( HB_SQLITE3 * ) hb_sqlite3_param( 1, HB_SQLITE3_DB, TRUE ); - if( db ) - hb_retni( sqlite3_busy_timeout( db, hb_parni( 2 ) ) ); + if( pHbSqlite3 && pHbSqlite3->db ) + { + hb_retni( sqlite3_busy_timeout(pHbSqlite3->db, hb_parni(2)) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } -/* - Determine If An SQL Statement Is Complete - - sqlite3_complete( sqlText ) -> lResult -*/ - -HB_FUNC( SQLITE3_COMPLETE ) -{ - hb_retl( sqlite3_complete( hb_parc( 1 ) ) ); -} - -/* +/** Convenience Routines For Running Queries sqlite3_get_table( db, sqlText ) -> aResult @@ -837,25 +1368,27 @@ HB_FUNC( SQLITE3_COMPLETE ) HB_FUNC( SQLITE3_GET_TABLE ) { - psqlite3 db = hb_parsqlite3( 1 ); + HB_SQLITE3 *pHbSqlite3 = ( HB_SQLITE3 * ) hb_sqlite3_param( 1, HB_SQLITE3_DB, TRUE ); - if( db ) + if( pHbSqlite3 && pHbSqlite3->db ) { PHB_ITEM pResultList = hb_itemArrayNew( 0 ); int iRow, iCol; - char * pszErrMsg = NULL; - char ** pResult; + char *pszErrMsg = NULL; + char **pResult; - if( sqlite3_get_table( db, hb_parc( 2 ), &pResult, &iRow, &iCol, &pszErrMsg ) == SQLITE_OK ) + if( sqlite3_get_table(pHbSqlite3->db, hb_parc(2), &pResult, &iRow, &iCol, &pszErrMsg) == SQLITE_OK ) { - int i, j, k = 0; + int i, j, k = 0; for( i = 0; i < iRow + 1; i++ ) { PHB_ITEM pArray = hb_itemArrayNew( iCol ); for( j = 1; j <= iCol; j++, k++ ) - hb_arraySetC( pArray, j, pResult[ k ] ); + { + hb_arraySetC( pArray, j, pResult[k] ); + } hb_arrayAddForward( pResultList, pArray ); hb_itemRelease( pArray ); @@ -863,7 +1396,7 @@ HB_FUNC( SQLITE3_GET_TABLE ) } else { - HB_TRACE(HB_TR_DEBUG, ("sqlite3_get_table(): Returned error: %s", pszErrMsg)); + HB_TRACE( HB_TR_DEBUG, ("sqlite3_get_table(): Returned error: %s", pszErrMsg) ); sqlite3_free( pszErrMsg ); } @@ -872,65 +1405,74 @@ HB_FUNC( SQLITE3_GET_TABLE ) hb_itemReturnRelease( pResultList ); } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } -#ifdef SQLITE_ENABLE_COLUMN_METADATA - -/* +/** Extract Metadata About A Column Of A Table based on - int sqlite3_table_column_metadata( - sqlite3 *db, - IN: Connection handle - const char *zDbName, - IN: Database name or NULL - const char *zTableName, - IN: Table name - const char *zColumnName, - IN: Column name - char const **pzDataType, - OUT: Declared data type - char const **pzCollSeq, - OUT: Collation sequence name - int *pNotNull, - OUT: True if NOT NULL constraint exists - int *pPrimaryKey, - OUT: True if column part of PK - int *pAutoinc - OUT: True if column is auto-increment + int sqlite3_table_column_metadata( + sqlite3 *db, - IN: Connection handle + const char *zDbName, - IN: Database name or NULL + const char *zTableName, - IN: Table name + const char *zColumnName, - IN: Column name + char const **pzDataType, - OUT: Declared data type + char const **pzCollSeq, - OUT: Collation sequence name + int *pNotNull, - OUT: True if NOT NULL constraint exists + int *pPrimaryKey, - OUT: True if column part of PK + int *pAutoinc - OUT: True if column is auto-increment ); */ +#ifdef SQLITE_ENABLE_COLUMN_METADATA HB_FUNC( SQLITE3_TABLE_COLUMN_METADATA ) { - psqlite3 pDb = hb_parsqlite3( 1 ); + HB_SQLITE3 *pHbSqlite3 = ( HB_SQLITE3 * ) hb_sqlite3_param( 1, HB_SQLITE3_DB, TRUE ); - if( pDb ) + if( pHbSqlite3 && pHbSqlite3->db ) { - char const ** pzDataType = NULL; - char const ** pzCollSeq = NULL; - int iNotNull = 0; - int iPrimaryKey = 0; - int iAutoinc = 0; + char const *pzDataType = NULL; + char const *pzCollSeq = NULL; + int iNotNull = 0; + int iPrimaryKey = 0; + int iAutoinc = 0; - if( sqlite3_table_column_metadata( pDb, - ( const char * ) hb_parc( 2 ) /* zDbName */, - ( const char * ) hb_parc( 3 ) /* zTableName */, - ( const char * ) hb_parc( 4 ) /* zColumnName */, - &pzDataType /* pzDataDtype */, - &pzCollSeq /* pzCollSeq */, - &iNotNull, - &iPrimaryKey, - &iAutoinc ) == SQLITE_OK ) + if + ( + sqlite3_table_column_metadata + ( + pHbSqlite3->db, + ( const char * ) hb_parc(2) /* zDbName */, + ( const char * ) hb_parc(3) /* zTableName */, + ( const char * ) hb_parc(4) /* zColumnName */, + &pzDataType /* pzDataDtype */, + &pzCollSeq /* pzCollSeq */, + &iNotNull, + &iPrimaryKey, + &iAutoinc + ) == SQLITE_OK + ) { PHB_ITEM pArray = hb_itemArrayNew( 5 ); hb_arraySetC( pArray, 1, ( char * ) pzDataType ); hb_arraySetC( pArray, 2, ( char * ) pzCollSeq ); - hb_arraySetL( pArray, 3, ( BOOL ) iNotNull ); - hb_arraySetL( pArray, 4, ( BOOL ) iPrimaryKey ); - hb_arraySetL( pArray, 5, ( BOOL ) iAutoinc ); + hb_arraySetL( pArray, 3, (BOOL) iNotNull ); + hb_arraySetL( pArray, 4, (BOOL) iPrimaryKey ); + hb_arraySetL( pArray, 5, (BOOL) iAutoinc ); hb_itemReturnRelease( pArray ); } } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } -/* +/** Source Of Data In A Query Result sqlite3_column_database_name( pStmt, ColumnIndex) -> cDatabaseName @@ -940,153 +1482,195 @@ HB_FUNC( SQLITE3_TABLE_COLUMN_METADATA ) HB_FUNC( SQLITE3_COLUMN_DATABASE_NAME ) { - psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); + psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); if( pStmt ) - hb_retc( sqlite3_column_database_name( pStmt, hb_parni( 2 ) - 1 ) ); + { + hb_retc( sqlite3_column_database_name(pStmt, hb_parni(2) - 1) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } HB_FUNC( SQLITE3_COLUMN_TABLE_NAME ) { - psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); + psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); if( pStmt ) - hb_retc( sqlite3_column_table_name( pStmt, hb_parni( 2 ) - 1 ) ); + { + hb_retc( sqlite3_column_table_name(pStmt, hb_parni(2) - 1) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } HB_FUNC( SQLITE3_COLUMN_ORIGIN_NAME ) { - psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); + psqlite3_stmt pStmt = ( psqlite3_stmt ) hb_parptr( 1 ); if( pStmt ) - hb_retc( sqlite3_column_origin_name( pStmt, hb_parni( 2 ) - 1 ) ); + { + hb_retc( sqlite3_column_origin_name(pStmt, hb_parni(2) - 1) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } - -#endif +#endif /* SQLITE_ENABLE_COLUMN_METADATA */ /* - BLOB I/O + BLOB I/O */ -/* +/** Open A BLOB For Incremental I/O - Open a handle to the blob located in row iRow, column zColumn, table zTable + Open a handle to the blob located in row iRow, column zColumn, table zTable in database zDb. i.e. the same blob that would be selected by: - + SELECT zColumn FROM zDb.zTable WHERE rowid = iRow; */ HB_FUNC( SQLITE3_BLOB_OPEN ) { - psqlite3 pDb = hb_parsqlite3( 1 ); + HB_SQLITE3 *pHbSqlite3 = ( HB_SQLITE3 * ) hb_sqlite3_param( 1, HB_SQLITE3_DB, TRUE ); - if( pDb ) + if( pHbSqlite3 && pHbSqlite3->db ) { - sqlite3_blob * ppBlob = NULL; + sqlite3_blob *ppBlob = NULL; - if( sqlite3_blob_open( pDb, - ( const char * ) hb_parc( 2 ) /* zDb */, - ( const char * ) hb_parc( 3 ) /* zTable */, - ( const char * ) hb_parc( 4 ) /* zColumn */, - ( sqlite3_int64 ) hb_parnint( 5 ) /* iRow */, - hb_parni( 6 ) /* flags */, - &ppBlob ) == SQLITE_OK ) + if + ( + sqlite3_blob_open + ( + pHbSqlite3->db, + ( const char * ) hb_parc(2) /* zDb */, + ( const char * ) hb_parc(3) /* zTable */, + ( const char * ) hb_parc(4) /* zColumn */, + (sqlite3_int64) hb_parnint(5) /* iRow */, + hb_parni(6) /* flags */, + &ppBlob + ) == SQLITE_OK + ) + { hb_retptr( ppBlob ); + } else + { hb_retptr( NULL ); + } } else + { hb_retptr( NULL ); + } } -/* +/** Close A BLOB Handle */ HB_FUNC( SQLITE3_BLOB_CLOSE ) { - sqlite3_blob * pBlob = ( sqlite3_blob * ) hb_parptr( 1 ); + sqlite3_blob *pBlob = ( sqlite3_blob * ) hb_parptr( 1 ); if( pBlob ) - hb_retni( sqlite3_blob_close( pBlob ) ); + { + hb_retni( sqlite3_blob_close(pBlob) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } -/* +/** Return The Size Of An Open BLOB */ HB_FUNC( SQLITE3_BLOB_BYTES ) { - sqlite3_blob * pBlob = ( sqlite3_blob * ) hb_parptr( 1 ); + sqlite3_blob *pBlob = ( sqlite3_blob * ) hb_parptr( 1 ); if( pBlob ) - hb_retni( sqlite3_blob_bytes( pBlob ) ); + { + hb_retni( sqlite3_blob_bytes(pBlob) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } -/* +/** Read Data From A BLOB Incrementally */ HB_FUNC( SQLITE3_BLOB_READ ) { - sqlite3_blob * pBlob = ( sqlite3_blob * ) hb_parptr( 1 ); + sqlite3_blob *pBlob = ( sqlite3_blob * ) hb_parptr( 1 ); if( pBlob ) { - int iLen = hb_parni( 2 ); - BYTE * buffer; + int iLen = hb_parni( 2 ); + BYTE *buffer; if( iLen == 0 ) + { iLen = sqlite3_blob_bytes( pBlob ); + } buffer = ( BYTE * ) hb_xgrab( iLen + 1 ); + /*hb_xmemset( buffer, 0, iLen );*/ - if( SQLITE_OK == sqlite3_blob_read( pBlob, buffer, iLen, hb_parni( 3 ) ) ) + if( SQLITE_OK == sqlite3_blob_read(pBlob, buffer, iLen, hb_parni(3)) ) { - buffer[ iLen ] = '\0'; + buffer[iLen] = '\0'; hb_retclen_buffer( ( char * ) buffer, iLen ); } else + { hb_xfree( buffer ); + } } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } -/* +/** Write Data Into A BLOB Incrementally */ HB_FUNC( SQLITE3_BLOB_WRITE ) { - sqlite3_blob * pBlob = ( sqlite3_blob * ) hb_parptr( 1 ); + sqlite3_blob *pBlob = ( sqlite3_blob * ) hb_parptr( 1 ); if( pBlob ) { - int iLen = hb_parni( 3 ); + int iLen = hb_parni( 3 ); if( iLen == 0 ) + { iLen = hb_parcsiz( 2 ) - 1; + } - hb_retni( sqlite3_blob_write( pBlob, hb_parcx( 2 ), iLen, hb_parni( 4 ) ) ); + hb_retni( sqlite3_blob_write(pBlob, hb_parcx(2), iLen, hb_parni(4)) ); } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } -/* +/** Test To See If The Database Is In Auto-Commit Mode sqlite3_get_autocommit( db ) -> lResult (TRUE/FALSE) @@ -1094,15 +1678,19 @@ HB_FUNC( SQLITE3_BLOB_WRITE ) HB_FUNC( SQLITE3_GET_AUTOCOMMIT ) { - psqlite3 db = hb_parsqlite3( 1 ); + HB_SQLITE3 *pHbSqlite3 = ( HB_SQLITE3 * ) hb_sqlite3_param( 1, HB_SQLITE3_DB, TRUE ); - if( db ) - hb_retl( sqlite3_get_autocommit( db ) ); + if( pHbSqlite3 && pHbSqlite3->db ) + { + hb_retl( sqlite3_get_autocommit(pHbSqlite3->db) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } -/* +/** Enable Or Disable Shared Pager Cache sqlite3_enable_shared_cache( lOnOff ) -> nResultCode @@ -1110,35 +1698,35 @@ HB_FUNC( SQLITE3_GET_AUTOCOMMIT ) HB_FUNC( SQLITE3_ENABLE_SHARED_CACHE ) { - hb_retni( sqlite3_enable_shared_cache( hb_parl( 1 ) ) ); + hb_retni( sqlite3_enable_shared_cache(hb_parl(1)) ); } -/* +/** Tracing And Profiling Functions sqlite3_trace( db, lOnOff ) - sqlite3_profile( db, lOnOff ) + sqlite3_profile( db, lOnOff ) */ -static void SQL3ProfileLog( void * sFile, const char * sProfileMsg, sqlite3_uint64 int64 ) +static void SQL3ProfileLog( void *sFile, const char *sProfileMsg, sqlite3_uint64 int64 ) { if( sProfileMsg ) { - FILE * hFile = fopen( sFile ? ( const char * ) sFile : "hbsq3_pr.log", "a" ); + FILE *hFile = fopen( sFile ? ( const char * ) sFile : "hbsq3_pr.log", "a" ); if( hFile ) { - fprintf( hFile, "%s - %" PFLL "d\n", sProfileMsg, int64 ); + fprintf( hFile, "%s - %"PFLL "d\n", sProfileMsg, int64 ); fclose( hFile ); } } } -static void SQL3TraceLog( void * sFile, const char * sTraceMsg ) +static void SQL3TraceLog( void *sFile, const char *sTraceMsg ) { if( sTraceMsg ) { - FILE * hFile = fopen( sFile ? ( const char * ) sFile : "hbsq3_tr.log", "a" ); + FILE *hFile = fopen( sFile ? ( const char * ) sFile : "hbsq3_tr.log", "a" ); if( hFile ) { @@ -1150,60 +1738,568 @@ static void SQL3TraceLog( void * sFile, const char * sTraceMsg ) HB_FUNC( SQLITE3_PROFILE ) { - psqlite3 db = hb_parsqlite3( 1 ); + HB_SQLITE3 *pHbSqlite3 = ( HB_SQLITE3 * ) hb_sqlite3_param( 1, HB_SQLITE3_DB, TRUE ); - if( db ) - sqlite3_profile( db, hb_parl( 2 ) ? SQL3ProfileLog : NULL, NULL ); + if( pHbSqlite3 && pHbSqlite3->db ) + { + sqlite3_profile( pHbSqlite3->db, hb_parl(2) ? SQL3ProfileLog : NULL, ( void * ) (HB_ISCHAR(3) ? hb_parcx(3) : NULL) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } HB_FUNC( SQLITE3_TRACE ) { - psqlite3 db = hb_parsqlite3( 1 ); + HB_SQLITE3 *pHbSqlite3 = ( HB_SQLITE3 * ) hb_sqlite3_param( 1, HB_SQLITE3_DB, TRUE ); - if( db ) - sqlite3_trace( db, hb_parl( 2 ) ? SQL3TraceLog : NULL, NULL ); + if( pHbSqlite3 && pHbSqlite3->db ) + { + sqlite3_trace( pHbSqlite3->db, hb_parl(2) ? SQL3TraceLog : NULL, ( void * ) (HB_ISCHAR(3) ? hb_parcx(3) : NULL) ); + } else - hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) ); + { + hb_errRT_BASE_SubstR( EG_ARG, 0, NULL, HB_ERR_FUNCNAME, 1, hb_paramError(1) ); + } } -/* - BLOB Import/export +/** + BLOB Import/export */ HB_FUNC( SQLITE3_FILE_TO_BUFF ) { - int handle = hb_fsOpen( ( BYTE * ) hb_parc( 1 ), FO_READ ); + int handle = hb_fsOpen( ( BYTE * ) hb_parc(1), FO_READ ); if( handle != FS_ERROR ) { - BYTE * buffer; - ULONG iSize; + BYTE *buffer; + ULONG iSize; iSize = ( int ) hb_fsSeek( handle, 0, FS_END ); iSize -= ( int ) hb_fsSeek( handle, 0, FS_SET ); buffer = ( BYTE * ) hb_xgrab( iSize + 1 ); iSize = hb_fsReadLarge( handle, buffer, iSize ); - buffer[ iSize ] = '\0'; + buffer[iSize] = '\0'; hb_fsClose( handle ); hb_retclen_buffer( ( char * ) buffer, iSize ); } else + { hb_retc_null(); + } } HB_FUNC( SQLITE3_BUFF_TO_FILE ) { - int handle = hb_fsCreate( ( BYTE * ) hb_parc( 1 ), FC_NORMAL ); + int handle = hb_fsCreate( ( BYTE * ) hb_parc(1), FC_NORMAL ); ULONG iSize = hb_parcsiz( 2 ) - 1; if( handle != FS_ERROR && iSize > 0 ) { - hb_retni( hb_fsWriteLarge( handle, ( BYTE * ) hb_parcx( 2 ), iSize ) == iSize ? 0 : -1 ); + hb_retni( hb_fsWriteLarge(handle, ( BYTE * ) hb_parcx(2), iSize) == iSize ? 0 : -1 ); hb_fsClose( handle ); } else + { hb_retni( 1 ); + } +} + +/** + Causes any pending database operation to abort and return at its + earliest opportunity. + + sqlite3_interrupt( db) -> Nil +*/ + +HB_FUNC( SQLITE3_INTERRUPT ) +{ + HB_SQLITE3 *pHbSqlite3 = ( HB_SQLITE3 * ) hb_sqlite3_param( 1, HB_SQLITE3_DB, TRUE ); + + if( pHbSqlite3 && pHbSqlite3->db ) + { + sqlite3_interrupt( pHbSqlite3->db ); + } +} + +/** + A Callback To Handle SQLITE_BUSY Errors + + sqlite3_busy_handler( db, nNumOfOpCodes, [Nil]|[cFunc]|[sFunc] ) +*/ + +HB_FUNC( SQLITE3_BUSY_HANDLER ) +{ + HB_SQLITE3 *pHbSqlite3 = ( HB_SQLITE3 * ) hb_sqlite3_param( 1, HB_SQLITE3_DB, TRUE ); + + if( pHbSqlite3 && pHbSqlite3->db ) + { + if( (hb_pcount() > 2) && (HB_ISCHAR(2) || HB_ISSYMBOL(2)) ) + { + PHB_DYNS pDynSym; + + if( HB_ISCHAR(2) ) + { + pDynSym = hb_dynsymFindName( hb_parc(2) ); + } + else + { + pDynSym = hb_dynsymNew( hb_itemGetSymbol(hb_param(2, HB_IT_SYMBOL)) ); + } + + if( pDynSym && hb_dynsymIsFunction(pDynSym) ) + { + if( pHbSqlite3->cbBusyHandler ) + { + pHbSqlite3->cbBusyHandler = NULL; + } + + pHbSqlite3->cbBusyHandler = pDynSym; + + sqlite3_busy_handler( pHbSqlite3->db, busy_handler, ( void * ) pHbSqlite3->cbBusyHandler ); + } + + /* + else + { + if (pHbSqlite3->cbBusyHandler) + { + pHbSqlite3->cbBusyHandler = NULL; + } + + sqlite3_busy_handler( pHbSqlite3->db, NULL, NULL ); + } +*/ + + } + else + { + if( pHbSqlite3->cbBusyHandler ) + { + pHbSqlite3->cbBusyHandler = NULL; + } + + sqlite3_busy_handler( pHbSqlite3->db, NULL, NULL ); + } + } +} + +/** + Query Progress Callbacks + + sqlite3_progress_handler( db, nNumOfOpCodes, [Nil]|[cFunc]|[sFunc] ) +*/ + +HB_FUNC( SQLITE3_PROGRESS_HANDLER ) +{ + HB_SQLITE3 *pHbSqlite3 = ( HB_SQLITE3 * ) hb_sqlite3_param( 1, HB_SQLITE3_DB, TRUE ); + + if( pHbSqlite3 && pHbSqlite3->db ) + { + if( (hb_pcount() > 2) && HB_ISNUM(2) && (HB_ISCHAR(3) || HB_ISSYMBOL(3)) ) + { + PHB_DYNS pDynSym; + + if( HB_ISCHAR(3) ) + { + pDynSym = hb_dynsymFindName( hb_parc(3) ); + } + else + { + pDynSym = hb_dynsymNew( hb_itemGetSymbol(hb_param(3, HB_IT_SYMBOL)) ); + } + + if( pDynSym && hb_dynsymIsFunction(pDynSym) ) + { + if( pHbSqlite3->cbProgressHandler ) + { + pHbSqlite3->cbProgressHandler = NULL; + } + + pHbSqlite3->cbProgressHandler = pDynSym; + + sqlite3_progress_handler( pHbSqlite3->db, hb_parni(2), progress_handler, ( void * ) pHbSqlite3->cbProgressHandler ); + } + + /* + else + { + if (pHbSqlite3->cbProgressHandler) + { + pHbSqlite3->cbProgressHandler = NULL; + } + + sqlite3_progress_handler( pHbSqlite3->db, 0, NULL, NULL ); + } +*/ + + } + else + { + if( pHbSqlite3->cbProgressHandler ) + { + pHbSqlite3->cbProgressHandler = NULL; + } + + sqlite3_progress_handler( pHbSqlite3->db, 0, NULL, NULL ); + } + } +} + +/** + Commit And Rollback Notification Callbacks + + sqlite3_commit_hook( db, [Nil]|[cFunc]|[sFunc] ) + sqlite3_rollback_hook( db, [Nil]|[cFunc]|[sFunc] ) +*/ + +HB_FUNC( SQLITE3_COMMIT_HOOK ) +{ + HB_SQLITE3 *pHbSqlite3 = ( HB_SQLITE3 * ) hb_sqlite3_param( 1, HB_SQLITE3_DB, TRUE ); + + if( pHbSqlite3 && pHbSqlite3->db ) + { + if( (hb_pcount() > 1) && (HB_ISCHAR(2) || HB_ISSYMBOL(2)) ) + { + PHB_DYNS pDynSym; + + if( HB_ISCHAR(2) ) + { + pDynSym = hb_dynsymFindName( hb_parc(2) ); + } + else + { + pDynSym = hb_dynsymNew( hb_itemGetSymbol(hb_param(2, HB_IT_SYMBOL)) ); + } + + if( pDynSym && hb_dynsymIsFunction(pDynSym) ) + { + if( pHbSqlite3->cbHookCommit ) + { + pHbSqlite3->cbHookCommit = NULL; + } + + pHbSqlite3->cbHookCommit = pDynSym; + + sqlite3_commit_hook( pHbSqlite3->db, hook_commit, ( void * ) pHbSqlite3->cbHookCommit ); + } + + /* + else + { + if (pHbSqlite3->cbHookCommit) + { + pHbSqlite3->cbHookCommit = NULL; + } + + sqlite3_commit_hook( pHbSqlite3->db, NULL, NULL ); + } +*/ + + } + else + { + if( pHbSqlite3->cbHookCommit ) + { + pHbSqlite3->cbHookCommit = NULL; + } + + sqlite3_commit_hook( pHbSqlite3->db, NULL, NULL ); + } + } +} + +HB_FUNC( SQLITE3_ROLLBACK_HOOK ) +{ + HB_SQLITE3 *pHbSqlite3 = ( HB_SQLITE3 * ) hb_sqlite3_param( 1, HB_SQLITE3_DB, TRUE ); + + if( pHbSqlite3 && pHbSqlite3->db ) + { + if( (hb_pcount() > 1) && (HB_ISCHAR(2) || HB_ISSYMBOL(2)) ) + { + PHB_DYNS pDynSym; + + if( HB_ISCHAR(2) ) + { + pDynSym = hb_dynsymFindName( hb_parc(2) ); + } + else + { + pDynSym = hb_dynsymNew( hb_itemGetSymbol(hb_param(2, HB_IT_SYMBOL)) ); + } + + if( pDynSym && hb_dynsymIsFunction(pDynSym) ) + { + if( pHbSqlite3->cbHookRollback ) + { + pHbSqlite3->cbHookRollback = NULL; + } + + pHbSqlite3->cbHookRollback = pDynSym; + + sqlite3_rollback_hook( pHbSqlite3->db, hook_rollback, ( void * ) pHbSqlite3->cbHookRollback ); + } + + /* + else + { + if (pHbSqlite3->cbHookRollback) + { + pHbSqlite3->cbHookRollback = NULL; + } + + sqlite3_rollback_hook( pHbSqlite3->db, NULL, NULL ); + } +*/ + + } + else + { + if( pHbSqlite3->cbHookRollback ) + { + pHbSqlite3->cbHookRollback = NULL; + } + + sqlite3_rollback_hook( pHbSqlite3->db, NULL, NULL ); + } + } +} + +/** + Compile-Time Authorization Callbacks + + sqlite3_set_authorizer( pDb, [Nil]|[cFunc]|[sFunc] ) +*/ + +HB_FUNC( SQLITE3_SET_AUTHORIZER ) +{ + HB_SQLITE3 *pHbSqlite3 = ( HB_SQLITE3 * ) hb_sqlite3_param( 1, HB_SQLITE3_DB, TRUE ); + + if( pHbSqlite3 && pHbSqlite3->db ) + { + if( (hb_pcount() > 1) && (HB_ISCHAR(2) || HB_ISSYMBOL(2)) ) + { + PHB_DYNS pDynSym; + + if( HB_ISCHAR(2) ) + { + pDynSym = hb_dynsymFindName( hb_parc(2) ); + } + else + { + pDynSym = hb_dynsymNew( hb_itemGetSymbol(hb_param(2, HB_IT_SYMBOL)) ); + } + + if( pDynSym && hb_dynsymIsFunction(pDynSym) ) + { + if( pHbSqlite3->cbAuthorizer ) + { + pHbSqlite3->cbAuthorizer = NULL; + } + + pHbSqlite3->cbAuthorizer = pDynSym; + + hb_retni( sqlite3_set_authorizer(pHbSqlite3->db, authorizer, ( void * ) pHbSqlite3->cbAuthorizer) ); + } + + /* + else + { + if (pHbSqlite3->cbAuthorizer) + { + pHbSqlite3->cbAuthorizer = NULL; + } + + hb_retni( sqlite3_set_authorizer(pHbSqlite3->db, NULL, NULL) ); + } +*/ + + } + else + { + if( pHbSqlite3->cbAuthorizer ) + { + pHbSqlite3->cbAuthorizer = NULL; + } + + hb_retni( sqlite3_set_authorizer(pHbSqlite3->db, NULL, NULL) ); + } + } +} + +/** + This API is used to overwrite the contents of one database with that + of another. It is useful either for creating backups of databases or + for copying in-memory databases to or from persistent files. + + ! Experimental ! + + sqlite3_backup_init( DbDest, cDestName, DbSource, cSourceName ) -> + return pointer to Backup or NIL if error occurs + + sqlite3_backup_step( pBackup, nPage ) -> nResult + sqlite3_backup_finish( pBackup ) -> nResult + sqlite3_backup_remaining( pBackup ) -> nResult + sqlite3_backup_pagecount( pBackup ) -> nResult +*/ + +#if SQLITE_VERSION_NUMBER >= 3006011 +HB_FUNC( SQLITE3_BACKUP_INIT ) +{ + HB_SQLITE3 *pHbSqlite3Dest = ( HB_SQLITE3 * ) hb_sqlite3_param( 1, HB_SQLITE3_DB, TRUE ); + HB_SQLITE3 *pHbSqlite3Source = ( HB_SQLITE3 * ) hb_sqlite3_param( 3, HB_SQLITE3_DB, TRUE ); + sqlite3_backup *pBackup; + + if( pHbSqlite3Dest && pHbSqlite3Dest->db && pHbSqlite3Source && pHbSqlite3Source->db && ISCHAR(2) && ISCHAR(4) ) + { + pBackup = sqlite3_backup_init( pHbSqlite3Dest->db, hb_parcx(2), pHbSqlite3Source->db, hb_parcx(4) ); + + if( pBackup ) + { + hb_retptr( pBackup ); + } + else + { + hb_retptr( NULL ); + } + } + else + { + hb_retptr( NULL ); + } +} + +HB_FUNC( SQLITE3_BACKUP_STEP ) +{ + sqlite3_backup *pBackup = ( sqlite3_backup * ) hb_parptr( 1 ); + + if( pBackup ) + { + hb_retni( sqlite3_backup_step(pBackup, hb_parni(2)) ); + } + else + { + hb_retni( -1 ); + } +} + +HB_FUNC( SQLITE3_BACKUP_FINISH ) +{ + sqlite3_backup *pBackup = ( sqlite3_backup * ) hb_parptr( 1 ); + + if( pBackup ) + { + hb_retni( sqlite3_backup_finish(pBackup) ); + } + else + { + hb_retni( -1 ); + } +} + +HB_FUNC( SQLITE3_BACKUP_REMAINING ) +{ + sqlite3_backup *pBackup = ( sqlite3_backup * ) hb_parptr( 1 ); + + if( pBackup ) + { + hb_retni( sqlite3_backup_remaining(pBackup) ); + } + else + { + hb_retni( -1 ); + } +} + +HB_FUNC( SQLITE3_BACKUP_PAGECOUNT ) +{ + sqlite3_backup *pBackup = ( sqlite3_backup * ) hb_parptr( 1 ); + + if( pBackup ) + { + hb_retni( sqlite3_backup_pagecount(pBackup) ); + } + else + { + hb_retni( -1 ); + } +} +#endif /* SQLITE_VERSION_NUMBER >= 3006011 */ + +/** + Memory Allocator Statistics + + sqlite3_memory_used() -> nResult + sqlite3_memory_highwater( lResetFlag ) -> nResult +*/ + +HB_FUNC( SQLITE3_MEMORY_USED ) +{ + hb_retnint( sqlite3_memory_used() ); +} + +HB_FUNC( SQLITE3_MEMORY_HIGHWATER ) +{ + hb_retnint( sqlite3_memory_highwater(( int ) hb_parl(1)) ); +} + +/** + Test To See If The Library Is Threadsafe + + sqlite3_threadsafe() -> nResult +*/ + +HB_FUNC( SQLITE3_THREADSAFE ) +{ + hb_retni( sqlite3_threadsafe() ); +} + +/** + SQLite Runtime Status + + sqlite3_status( nOp, @nCurrent, @nHighwater, lResetFlag); +*/ + +HB_FUNC( SQLITE3_STATUS ) +{ + int iCurrent, iHighwater; + + if( hb_pcount() > 3 && (HB_ISNUM(2) && HB_ISBYREF(2)) && (HB_ISNUM(3) && HB_ISBYREF(3)) ) + { + hb_retni( sqlite3_status(hb_parni(1), &iCurrent, &iHighwater, ( int ) hb_parl(4)) ); + + hb_storni( iCurrent, 2 ); + hb_storni( iHighwater, 3 ); + } + else + { + hb_retni( -1 ); + } +} + +/** + Database Connection Status + + sqlite3_status( pDb, nOp, @nCurrent, @nHighwater, lResetFlag); +*/ + +HB_FUNC( SQLITE3_DB_STATUS ) +{ + int iCurrent, iHighwater; + HB_SQLITE3 *pHbSqlite3 = ( HB_SQLITE3 * ) hb_sqlite3_param( 1, HB_SQLITE3_DB, TRUE ); + + if( pHbSqlite3 && pHbSqlite3->db && (hb_pcount() > 4) && (HB_ISNUM(3) && HB_ISBYREF(3)) && (HB_ISNUM(4) && HB_ISBYREF(4)) ) + { + hb_retni( sqlite3_db_status(pHbSqlite3->db, hb_parni(2), &iCurrent, &iHighwater, ( int ) hb_parl(5)) ); + + hb_storni( iCurrent, 3 ); + hb_storni( iHighwater, 4 ); + } + else + { + hb_retni( -1 ); + } } diff --git a/harbour/contrib/hbsqlit3/hbsqlit3.ch b/harbour/contrib/hbsqlit3/hbsqlit3.ch index 4a68596ba7..f11c61fad1 100644 --- a/harbour/contrib/hbsqlit3/hbsqlit3.ch +++ b/harbour/contrib/hbsqlit3/hbsqlit3.ch @@ -47,7 +47,7 @@ * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. * - * See COPYING for licensing terms. + * See doc/license.txt for licensing terms. * */ @@ -61,45 +61,44 @@ #define SQLITE_INTEGER 1 #define SQLITE_FLOAT 2 #ifdef SQLITE_TEXT -#undef SQLITE_TEXT + #undef SQLITE_TEXT #else -#define SQLITE_TEXT 3 + #define SQLITE_TEXT 3 #endif #define SQLITE3_TEXT 3 #define SQLITE_BLOB 4 #define SQLITE_NULL 5 -#define SQLITE_OK 0 /* Successful result */ - +#define SQLITE_OK 0 /* Successful result */ /* Beginning-of-Error-Codes */ -#define SQLITE_ERROR 1 /* SQL error or missing database */ -#define SQLITE_INTERNAL 2 /* NOT USED. Internal logic error in SQLite */ -#define SQLITE_PERM 3 /* Access permission denied */ -#define SQLITE_ABORT 4 /* Callback routine requested an abort */ -#define SQLITE_BUSY 5 /* The database file is locked */ -#define SQLITE_LOCKED 6 /* A table in the database is locked */ -#define SQLITE_NOMEM 7 /* A malloc() failed */ -#define SQLITE_READONLY 8 /* Attempt to write a readonly database */ -#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/ -#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */ -#define SQLITE_CORRUPT 11 /* The database disk image is malformed */ -#define SQLITE_NOTFOUND 12 /* NOT USED. Table or record not found */ -#define SQLITE_FULL 13 /* Insertion failed because database is full */ -#define SQLITE_CANTOPEN 14 /* Unable to open the database file */ -#define SQLITE_PROTOCOL 15 /* NOT USED. Database lock protocol error */ -#define SQLITE_EMPTY 16 /* Database is empty */ -#define SQLITE_SCHEMA 17 /* The database schema changed */ -#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */ -#define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */ -#define SQLITE_MISMATCH 20 /* Data type mismatch */ -#define SQLITE_MISUSE 21 /* Library used incorrectly */ -#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ -#define SQLITE_AUTH 23 /* Authorization denied */ -#define SQLITE_FORMAT 24 /* Auxiliary database format error */ -#define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */ -#define SQLITE_NOTADB 26 /* File opened that is not a database file */ -#define SQLITE_ROW 100 /* sqlite3_step() has another row ready */ -#define SQLITE_DONE 101 /* sqlite3_step() has finished executing */ +#define SQLITE_ERROR 1 /* SQL error or missing database */ +#define SQLITE_INTERNAL 2 /* NOT USED. Internal logic error in SQLite */ +#define SQLITE_PERM 3 /* Access permission denied */ +#define SQLITE_ABORT 4 /* Callback routine requested an abort */ +#define SQLITE_BUSY 5 /* The database file is locked */ +#define SQLITE_LOCKED 6 /* A table in the database is locked */ +#define SQLITE_NOMEM 7 /* A malloc() failed */ +#define SQLITE_READONLY 8 /* Attempt to write a readonly database */ +#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/ +#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */ +#define SQLITE_CORRUPT 11 /* The database disk image is malformed */ +#define SQLITE_NOTFOUND 12 /* NOT USED. Table or record not found */ +#define SQLITE_FULL 13 /* Insertion failed because database is full */ +#define SQLITE_CANTOPEN 14 /* Unable to open the database file */ +#define SQLITE_PROTOCOL 15 /* NOT USED. Database lock protocol error */ +#define SQLITE_EMPTY 16 /* Database is empty */ +#define SQLITE_SCHEMA 17 /* The database schema changed */ +#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */ +#define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */ +#define SQLITE_MISMATCH 20 /* Data type mismatch */ +#define SQLITE_MISUSE 21 /* Library used incorrectly */ +#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ +#define SQLITE_AUTH 23 /* Authorization denied */ +#define SQLITE_FORMAT 24 /* Auxiliary database format error */ +#define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */ +#define SQLITE_NOTADB 26 /* File opened that is not a database file */ +#define SQLITE_ROW 100 /* sqlite3_step() has another row ready */ +#define SQLITE_DONE 101 /* sqlite3_step() has finished executing */ /* End-of-Error-Codes */ /* Combination of the following bit values are used @@ -117,4 +116,59 @@ #define SQLITE_OPEN_SUBJOURNAL 8192 #define SQLITE_OPEN_MASTER_JOURNAL 16384 +/* Status Parameters for prepared statements */ +#define SQLITE_STMTSTATUS_FULLSCAN_STEP 1 +#define SQLITE_STMTSTATUS_SORT 2 + +/* Authorizer Action Codes */ +#define SQLITE_CREATE_INDEX 1 /* Index Name Table Name */ +#define SQLITE_CREATE_TABLE 2 /* Table Name NULL */ +#define SQLITE_CREATE_TEMP_INDEX 3 /* Index Name Table Name */ +#define SQLITE_CREATE_TEMP_TABLE 4 /* Table Name NULL */ +#define SQLITE_CREATE_TEMP_TRIGGER 5 /* Trigger Name Table Name */ +#define SQLITE_CREATE_TEMP_VIEW 6 /* View Name NULL */ +#define SQLITE_CREATE_TRIGGER 7 /* Trigger Name Table Name */ +#define SQLITE_CREATE_VIEW 8 /* View Name NULL */ +#define SQLITE_DELETE 9 /* Table Name NULL */ +#define SQLITE_DROP_INDEX 10 /* Index Name Table Name */ +#define SQLITE_DROP_TABLE 11 /* Table Name NULL */ +#define SQLITE_DROP_TEMP_INDEX 12 /* Index Name Table Name */ +#define SQLITE_DROP_TEMP_TABLE 13 /* Table Name NULL */ +#define SQLITE_DROP_TEMP_TRIGGER 14 /* Trigger Name Table Name */ +#define SQLITE_DROP_TEMP_VIEW 15 /* View Name NULL */ +#define SQLITE_DROP_TRIGGER 16 /* Trigger Name Table Name */ +#define SQLITE_DROP_VIEW 17 /* View Name NULL */ +#define SQLITE_INSERT 18 /* Table Name NULL */ +#define SQLITE_PRAGMA 19 /* Pragma Name 1st arg or NULL */ +#define SQLITE_READ 20 /* Table Name Column Name */ +#define SQLITE_SELECT 21 /* NULL NULL */ +#define SQLITE_TRANSACTION 22 /* Operation NULL */ +#define SQLITE_UPDATE 23 /* Table Name Column Name */ +#define SQLITE_ATTACH 24 /* Filename NULL */ +#define SQLITE_DETACH 25 /* Database Name NULL */ +#define SQLITE_ALTER_TABLE 26 /* Database Name Table Name */ +#define SQLITE_REINDEX 27 /* Index Name NULL */ +#define SQLITE_ANALYZE 28 /* Table Name NULL */ +#define SQLITE_CREATE_VTABLE 29 /* Table Name Module Name */ +#define SQLITE_DROP_VTABLE 30 /* Table Name Module Name */ +#define SQLITE_FUNCTION 31 /* NULL Function Name */ +#define SQLITE_SAVEPOINT 32 /* Operation Savepoint Name */ + +/* Authorizer Return Codes */ +#define SQLITE_DENY 1 /* Abort the SQL statement with an error */ +#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */ + +/* Status Parameters */ +#define SQLITE_STATUS_MEMORY_USED 0 +#define SQLITE_STATUS_PAGECACHE_USED 1 +#define SQLITE_STATUS_PAGECACHE_OVERFLOW 2 +#define SQLITE_STATUS_SCRATCH_USED 3 +#define SQLITE_STATUS_SCRATCH_OVERFLOW 4 +#define SQLITE_STATUS_MALLOC_SIZE 5 +#define SQLITE_STATUS_PARSER_STACK 6 +#define SQLITE_STATUS_PAGECACHE_SIZE 7 +#define SQLITE_STATUS_SCRATCH_SIZE 8 + +/* Status Parameters for database connections */ +#define SQLITE_DBSTATUS_LOOKASIDE_USED 0 #endif diff --git a/harbour/contrib/hbsqlit3/tests/authorizer.prg b/harbour/contrib/hbsqlit3/tests/authorizer.prg new file mode 100644 index 0000000000..b69355f029 --- /dev/null +++ b/harbour/contrib/hbsqlit3/tests/authorizer.prg @@ -0,0 +1,255 @@ +/* + * $Id$ + */ + +/* + * SQLite3 Demo. Using sqlite3_set_authorizer() + * + * Copyright 2009 P.Chornyj + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/). + * + * As a special exception, the Harbour Project gives permission for + * additional uses of the text contained in its release of Harbour. + * + * The exception is that, if you link the Harbour libraries with other + * files to produce an executable, this does not by itself cause the + * resulting executable to be covered by the GNU General Public License. + * Your use of that executable is in no way restricted on account of + * linking the Harbour library code into it. + * + * This exception does not however invalidate any other reasons why + * the executable file might be covered by the GNU General Public License. + * + * This exception applies only to the code released by the Harbour + * Project under the name Harbour. If you copy code from other + * Harbour Project or Free Software Foundation releases into a copy of + * Harbour, as the General Public License permits, the exception does + * not apply to the code that you add in this way. To avoid misleading + * anyone as to the status of such modified files, you must delete + * this exception notice from them. + * + * If you write modifications of your own for Harbour, it is your choice + * whether to permit this exception to apply to your modifications. + * If you do not wish that, delete this exception notice. + * + * See COPYING for licensing terms. + * + */ + +/* + * Using sqlite3_set_authorizer() + * + * This routine registers a authorizer callback with a particular + * database connection, supplied in the first argument. + * The authorizer callback is invoked as SQL statements are being compiled + * by sqlite3_prepare(). + * + * When the callback returns SQLITE_OK, that means the operation requested + * is ok. + * When the callback returns SQLITE_DENY, the sqlite3_prepare() or + * equivalent call that triggered the authorizer will fail with an error + * message explaining that access is denied. + * If the authorizer code is SQLITE_READ and the callback returns + * SQLITE_IGNORE then the prepared statement statement is constructed to + * substitute a NULL value in place of the table column that would have + * been read if SQLITE_OK had been returned. + * The SQLITE_IGNORE return can be used to deny an untrusted user access + * to individual columns of a table. + * + * The first parameter to the authorizer callback is an integer + * action code that specifies the particular action to be authorized. + * The second through fourth parameters to the callback are strings + * that contain additional details about the action to be authorized. + */ + +#include "common.ch" +#include "hbsqlit3.ch" + +FUNCTION main() + LOCAL cFile := ":memory:", cSQLTEXT + LOCAL pDb, cb + // + IF Empty( pDb := PrepareDB(cFile) ) + RETURN 1 + ENDIF + // Authorizer1 + sqlite3_set_authorizer( pDb, @Authorizer() /*"Authorizer"*/ ) + + QOut( cSQLTEXT := "SELECT * FROM main.person WHERE age BETWEEN 20 AND 40" ) + cb := @CallBack() // "CallBack" + Qout( cErrorMsg(sqlite3_exec(pDb, cSQLTEXT, cb)) ) + + sqlite3_sleep( 3000 ) + // Authorizer2 + Qout( cErrorMsg(sqlite3_set_authorizer(pDb, @Authorizer2() /*"Authorizer2"*/)) ) + + QOut( cSQLTEXT := "SELECT * FROM main.person WHERE age BETWEEN 20 AND 40" ) + Qout( cErrorMsg(sqlite3_exec(pDb, cSQLTEXT, cb)) ) + + sqlite3_sleep( 3000 ) + // Authorizer3 + Qout( cErrorMsg(sqlite3_set_authorizer(pDb, @Authorizer3() /*"Authorizer3"*/)) ) + + QOut( cSQLTEXT := "SELECT * FROM main.person WHERE age BETWEEN 20 AND 40" ) + Qout( cErrorMsg(sqlite3_exec(pDb, cSQLTEXT, cb), FALSE) ) + + sqlite3_sleep( 3000 ) + // + pDb := Nil // close database + // +RETURN 0 + +/** +*/ +FUNCTION Authorizer( nAction, cName1, cName2, cDatabaseName, cTriggerOrViewName ) +LOCAL oldColor := SetColor( "R/N" ) + // + Qout( "=>", StrZero(nAction, 2), cName1, cName2, cDatabaseName, cTriggerOrViewName ) + + SetColor( oldColor ) + // +RETURN SQLITE_OK + +/** +*/ +FUNCTION Authorizer2( nAction, cName1, cName2, cDatabaseName, cTriggerOrViewName ) +LOCAL oldColor := SetColor( "R/N" ) + // + Qout( "=>", StrZero(nAction, 2), cName1, cName2, cDatabaseName, cTriggerOrViewName ) + + SetColor( oldColor ) + // +RETURN iif( cName2 == "pasw", SQLITE_IGNORE, SQLITE_OK ) + +/** +*/ +FUNCTION Authorizer3( nAction, cName1, cName2, cDatabaseName, cTriggerOrViewName ) + // +RETURN iif( nAction == SQLITE_SELECT, SQLITE_DENY, SQLITE_OK ) + +/** +*/ +FUNCTION CallBack( nColCount, aValue, aColName ) +LOCAL nI +LOCAL oldColor := SetColor( "G/N" ) + // + FOR nI := 1 TO nColCount + Qout( Padr(aColName[nI], 5) , " == ", aValue[nI] ) + NEXT + + SetColor( oldColor ) + // +RETURN 0 + +/** +*/ +STATIC FUNCTION cErrorMsg( nError, lShortMsg ) + LOCAL aErrorCodes := { ; + { SQLITE_ERROR , "SQLITE_ERROR" , "SQL error or missing database" }, ; + { SQLITE_INTERNAL , "SQLITE_INTERNAL" , "NOT USED. Internal logic error in SQLite" }, ; + { SQLITE_PERM , "SQLITE_PERM" , "Access permission denied" }, ; + { SQLITE_ABORT , "SQLITE_ABORT" , "Callback routine requested an abort" }, ; + { SQLITE_BUSY , "SQLITE_BUSY" , "The database file is locked" }, ; + { SQLITE_LOCKED , "SQLITE_LOCKED" , "A table in the database is locked" }, ; + { SQLITE_NOMEM , "SQLITE_NOMEM" , "A malloc() failed" }, ; + { SQLITE_READONLY , "SQLITE_READONLY" , "Attempt to write a readonly database" }, ; + { SQLITE_INTERRUPT , "SQLITE_INTERRUPT" , "Operation terminated by sqlite3_interrupt()" }, ; + { SQLITE_IOERR , "SQLITE_IOERR" , "Some kind of disk I/O error occurred" }, ; + { SQLITE_CORRUPT , "SQLITE_CORRUPT" , "The database disk image is malformed" }, ; + { SQLITE_NOTFOUND , "SQLITE_NOTFOUND" , "NOT USED. Table or record not found" }, ; + { SQLITE_FULL , "SQLITE_FULL" , "Insertion failed because database is full" }, ; + { SQLITE_CANTOPEN , "SQLITE_CANTOPEN" , "Unable to open the database file" }, ; + { SQLITE_PROTOCOL , "SQLITE_PROTOCOL" , "NOT USED. Database lock protocol error" }, ; + { SQLITE_EMPTY , "SQLITE_EMPTY" , "Database is empty" }, ; + { SQLITE_SCHEMA , "SQLITE_SCHEMA" , "The database schema changed" }, ; + { SQLITE_TOOBIG , "SQLITE_TOOBIG" , "String or BLOB exceeds size limit" }, ; + { SQLITE_CONSTRAINT , "SQLITE_CONSTRAINT" , "Abort due to constraint violation" }, ; + { SQLITE_MISMATCH , "SQLITE_MISMATCH" , "Data type mismatch" }, ; + { SQLITE_MISUSE , "SQLITE_MISUSE" , "Library used incorrectly" }, ; + { SQLITE_NOLFS , "SQLITE_NOLFS" , "Uses OS features not supported on host" }, ; + { SQLITE_AUTH , "SQLITE_AUTH" , "Authorization denied" }, ; + { SQLITE_FORMAT , "SQLITE_FORMAT" , "Auxiliary database format error" }, ; + { SQLITE_RANGE , "SQLITE_RANGE" , "2nd parameter to sqlite3_bind out of range" }, ; + { SQLITE_NOTADB , "SQLITE_NOTADB" , "File opened that is not a database file" }, ; + { SQLITE_ROW , "SQLITE_ROW" , "sqlite3_step() has another row ready" }, ; + { SQLITE_DONE , "SQLITE_DONE" , "sqlite3_step() has finished executing" } ; + }, nIndex, cErrorMsg := "UNKNOWN" + // + DEFAULT lShortMsg TO TRUE + + IF hb_IsNumeric( nError ) + IF nError == 0 + cErrorMsg := "SQLITE_OK" + ELSE + nIndex := AScan( aErrorCodes, {|x| x[1] == nError } ) + cErrorMsg := iif( nIndex > 0, aErrorCodes[ nIndex ][ iif(lShortMsg,2,3) ], cErrorMsg ) + ENDIF + ENDIF + // +RETURN cErrorMsg + +/** +*/ +STATIC FUNCTION PrepareDB( cFile ) + LOCAL cSQLTEXT, cMsg + LOCAL pDb, pStmt + LOCAL hPerson := { ; + "Bob" => 52, ; + "Fred" => 32, ; + "Sasha" => 17, ; + "Andy" => 20, ; + "Ivet" => 28 ; + }, enum + // + pDb := sqlite3_open( cFile, TRUE ) + IF Empty( pDb ) + QOut( "Can't open/create database : ", cFile ) + + RETURN NIL + ENDIF + + cSQLTEXT := "CREATE TABLE person( name TEXT, age INTEGER, pasw TEXT(32) )" + cMsg := cErrorMsg( sqlite3_exec(pDb, cSQLTEXT) ) + + IF cMsg <> "SQLITE_OK" + QOut( "Can't create table : person" ) + pDb := NIL // close database + + RETURN NIL + ENDIF + // + cSQLTEXT := "INSERT INTO person( name, age, pasw ) VALUES( :name, :age, :pasw )" + pStmt := sqlite3_prepare( pDb, cSQLTEXT ) + IF Empty( pStmt ) + QOut( "Can't prepare statement : ", cSQLTEXT ) + pDb := NIL + + RETURN NIL + ENDIF + + FOR EACH enum IN hPerson + sqlite3_reset( pStmt ) + sqlite3_bind_text( pStmt, 1, enum:__enumKey ) + sqlite3_bind_int( pStmt, 2, enum:__enumValue ) + sqlite3_bind_text( pStmt, 3, hb_md5(enum:__enumKey) ) + sqlite3_step( pStmt ) + NEXT + + sqlite3_clear_bindings( pStmt ) + sqlite3_finalize( pStmt ) + // +RETURN pDb \ No newline at end of file diff --git a/harbour/contrib/hbsqlit3/tests/backup.prg b/harbour/contrib/hbsqlit3/tests/backup.prg new file mode 100644 index 0000000000..4816a3967c --- /dev/null +++ b/harbour/contrib/hbsqlit3/tests/backup.prg @@ -0,0 +1,236 @@ +/* + * $Id$ + */ + +/* + * SQLite3 Demo. Using sqlite3_backup_*() + * + * Copyright 2009 P.Chornyj + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/). + * + * As a special exception, the Harbour Project gives permission for + * additional uses of the text contained in its release of Harbour. + * + * The exception is that, if you link the Harbour libraries with other + * files to produce an executable, this does not by itself cause the + * resulting executable to be covered by the GNU General Public License. + * Your use of that executable is in no way restricted on account of + * linking the Harbour library code into it. + * + * This exception does not however invalidate any other reasons why + * the executable file might be covered by the GNU General Public License. + * + * This exception applies only to the code released by the Harbour + * Project under the name Harbour. If you copy code from other + * Harbour Project or Free Software Foundation releases into a copy of + * Harbour, as the General Public License permits, the exception does + * not apply to the code that you add in this way. To avoid misleading + * anyone as to the status of such modified files, you must delete + * this exception notice from them. + * + * If you write modifications of your own for Harbour, it is your choice + * whether to permit this exception to apply to your modifications. + * If you do not wish that, delete this exception notice. + * + * See COPYING for licensing terms. + * + */ + +/* + * Using sqlite3_backup_*() + * + * This API is used to overwrite the contents of one database with that + * of another. It is useful either for creating backups of databases or + * for copying in-memory databases to or from persistent files. + * + * sqlite3_backup_init() is called once to initialize the backup, + * sqlite3_backup_step() is called one or more times to transfer the data + * between the two databases, and finally + * sqlite3_backup_finish() is called to release all resources associated + * with the backup operation. + */ + +#include "common.ch" +#include "hbsqlit3.ch" + +FUNCTION main() + LOCAL cFileSource := ":memory:", cFileDest := "backup.db", cSQLTEXT + LOCAL pDbSource, pDbDest, pBackup, cb, nDbFlags + // + IF sqlite3_libversion_number() < 3006011 + RETURN 1 + ENDIF + + IF Empty( pDbSource := PrepareDB(cFileSource) ) + RETURN 1 + ENDIF + + nDbFlags := SQLITE_OPEN_CREATE + SQLITE_OPEN_READWRITE + ; + SQLITE_OPEN_EXCLUSIVE + pDbDest := sqlite3_open_v2( cFileDest, nDbFlags ) + + IF Empty( pDbDest ) + QOut( "Can't open database : ", cFileDest ) + + RETURN 1 + ENDIF + + sqlite3_trace( pDbDest, TRUE, "backup.log" ) + + // + pBackup := sqlite3_backup_init( pDbDest, "main", pDbSource, "main" ) + IF Empty( pBackup ) + QOut( "Can't initialize backup" ) + + RETURN 1 + ELSE + QOut( "Start backup.." ) + ENDIF + + IF sqlite3_backup_step(pBackup, -1) == SQLITE_DONE + QOut( "Backup successful." ) + ENDIF + + sqlite3_backup_finish( pBackup ) /* !!! */ + + pDbSource := Nil /* close :memory: database */ + + /* Little test for sqlite3_exec with callback */ + QOut( "" ) + QOut( cSQLTEXT := "SELECT * FROM main.person WHERE age BETWEEN 20 AND 40" ) + cb := @CallBack() // "CallBack" + Qout( cErrorMsg(sqlite3_exec(pDbDest, cSQLTEXT, cb)) ) + + pDbDest := Nil // close database + + sqlite3_sleep( 3000 ) + // +RETURN 0 + +/** +*/ +FUNCTION CallBack( nColCount, aValue, aColName ) +LOCAL nI +LOCAL oldColor := SetColor( "G/N" ) + // + FOR nI := 1 TO nColCount + Qout( Padr(aColName[nI], 5) , " == ", aValue[nI] ) + NEXT + + SetColor( oldColor ) + // +RETURN 0 + +/** +*/ +STATIC FUNCTION cErrorMsg( nError, lShortMsg ) + LOCAL aErrorCodes := { ; + { SQLITE_ERROR , "SQLITE_ERROR" , "SQL error or missing database" }, ; + { SQLITE_INTERNAL , "SQLITE_INTERNAL" , "NOT USED. Internal logic error in SQLite" }, ; + { SQLITE_PERM , "SQLITE_PERM" , "Access permission denied" }, ; + { SQLITE_ABORT , "SQLITE_ABORT" , "Callback routine requested an abort" }, ; + { SQLITE_BUSY , "SQLITE_BUSY" , "The database file is locked" }, ; + { SQLITE_LOCKED , "SQLITE_LOCKED" , "A table in the database is locked" }, ; + { SQLITE_NOMEM , "SQLITE_NOMEM" , "A malloc() failed" }, ; + { SQLITE_READONLY , "SQLITE_READONLY" , "Attempt to write a readonly database" }, ; + { SQLITE_INTERRUPT , "SQLITE_INTERRUPT" , "Operation terminated by sqlite3_interrupt()" }, ; + { SQLITE_IOERR , "SQLITE_IOERR" , "Some kind of disk I/O error occurred" }, ; + { SQLITE_CORRUPT , "SQLITE_CORRUPT" , "The database disk image is malformed" }, ; + { SQLITE_NOTFOUND , "SQLITE_NOTFOUND" , "NOT USED. Table or record not found" }, ; + { SQLITE_FULL , "SQLITE_FULL" , "Insertion failed because database is full" }, ; + { SQLITE_CANTOPEN , "SQLITE_CANTOPEN" , "Unable to open the database file" }, ; + { SQLITE_PROTOCOL , "SQLITE_PROTOCOL" , "NOT USED. Database lock protocol error" }, ; + { SQLITE_EMPTY , "SQLITE_EMPTY" , "Database is empty" }, ; + { SQLITE_SCHEMA , "SQLITE_SCHEMA" , "The database schema changed" }, ; + { SQLITE_TOOBIG , "SQLITE_TOOBIG" , "String or BLOB exceeds size limit" }, ; + { SQLITE_CONSTRAINT , "SQLITE_CONSTRAINT" , "Abort due to constraint violation" }, ; + { SQLITE_MISMATCH , "SQLITE_MISMATCH" , "Data type mismatch" }, ; + { SQLITE_MISUSE , "SQLITE_MISUSE" , "Library used incorrectly" }, ; + { SQLITE_NOLFS , "SQLITE_NOLFS" , "Uses OS features not supported on host" }, ; + { SQLITE_AUTH , "SQLITE_AUTH" , "Authorization denied" }, ; + { SQLITE_FORMAT , "SQLITE_FORMAT" , "Auxiliary database format error" }, ; + { SQLITE_RANGE , "SQLITE_RANGE" , "2nd parameter to sqlite3_bind out of range" }, ; + { SQLITE_NOTADB , "SQLITE_NOTADB" , "File opened that is not a database file" }, ; + { SQLITE_ROW , "SQLITE_ROW" , "sqlite3_step() has another row ready" }, ; + { SQLITE_DONE , "SQLITE_DONE" , "sqlite3_step() has finished executing" } ; + }, nIndex, cErrorMsg := "UNKNOWN" + // + DEFAULT lShortMsg TO TRUE + + IF hb_IsNumeric( nError ) + IF nError == 0 + cErrorMsg := "SQLITE_OK" + ELSE + nIndex := AScan( aErrorCodes, {|x| x[1] == nError } ) + cErrorMsg := iif( nIndex > 0, aErrorCodes[ nIndex ][ iif(lShortMsg,2,3) ], cErrorMsg ) + ENDIF + ENDIF + // +RETURN cErrorMsg + +/** +*/ +STATIC FUNCTION PrepareDB( cFile ) + LOCAL cSQLTEXT, cMsg + LOCAL pDb, pStmt + LOCAL hPerson := { ; + "Bob" => 52, ; + "Fred" => 32, ; + "Sasha" => 17, ; + "Andy" => 20, ; + "Ivet" => 28 ; + }, enum + // + pDb := sqlite3_open( cFile, TRUE ) + IF Empty( pDb ) + QOut( "Can't open/create database : ", cFile ) + + RETURN NIL + ENDIF + + sqlite3_trace( pDb, TRUE, "backup.log" ) + + cSQLTEXT := "CREATE TABLE person( name TEXT, age INTEGER )" + cMsg := cErrorMsg( sqlite3_exec(pDb, cSQLTEXT) ) + + IF cMsg <> "SQLITE_OK" + QOut( "Can't create table : person" ) + pDb := NIL // close database + + RETURN NIL + ENDIF + // + cSQLTEXT := "INSERT INTO person( name, age ) VALUES( :name, :age )" + pStmt := sqlite3_prepare( pDb, cSQLTEXT ) + IF Empty( pStmt ) + QOut( "Can't prepare statement : ", cSQLTEXT ) + pDb := NIL + + RETURN NIL + ENDIF + + FOR EACH enum IN hPerson + sqlite3_reset( pStmt ) + sqlite3_bind_text( pStmt, 1, enum:__enumKey ) + sqlite3_bind_int( pStmt, 2, enum:__enumValue ) + sqlite3_step( pStmt ) + NEXT + + sqlite3_clear_bindings( pStmt ) + sqlite3_finalize( pStmt ) + // +RETURN pDb \ No newline at end of file diff --git a/harbour/contrib/hbsqlit3/tests/hooks.prg b/harbour/contrib/hbsqlit3/tests/hooks.prg new file mode 100644 index 0000000000..010139c68b --- /dev/null +++ b/harbour/contrib/hbsqlit3/tests/hooks.prg @@ -0,0 +1,251 @@ +/* + * $Id$ + */ + +/* + * SQLite3 Demo. Using sqlite3_commit_hook(), sqlite3_rollback_hook() + * + * Copyright 2009 P.Chornyj + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/). + * + * As a special exception, the Harbour Project gives permission for + * additional uses of the text contained in its release of Harbour. + * + * The exception is that, if you link the Harbour libraries with other + * files to produce an executable, this does not by itself cause the + * resulting executable to be covered by the GNU General Public License. + * Your use of that executable is in no way restricted on account of + * linking the Harbour library code into it. + * + * This exception does not however invalidate any other reasons why + * the executable file might be covered by the GNU General Public License. + * + * This exception applies only to the code released by the Harbour + * Project under the name Harbour. If you copy code from other + * Harbour Project or Free Software Foundation releases into a copy of + * Harbour, as the General Public License permits, the exception does + * not apply to the code that you add in this way. To avoid misleading + * anyone as to the status of such modified files, you must delete + * this exception notice from them. + * + * If you write modifications of your own for Harbour, it is your choice + * whether to permit this exception to apply to your modifications. + * If you do not wish that, delete this exception notice. + * + * See COPYING for licensing terms. + * + */ + +#include "common.ch" +#include "hbsqlit3.ch" + +FUNCTION main() + LOCAL cSQLTEXT, cFile := ":memory:" + LOCAL pDb, cb := @CallBack() + // + IF Empty( pDb := PrepareDB(cFile) ) + RETURN 1 + ENDIF + // + sqlite3_commit_hook( pDb, "HookCommitY" ) + + QOut( cSQLTEXT := "SELECT * FROM person WHERE name == 'Andy'" ) + Qout( "return value: ", cErrorMsg(sqlite3_exec(pDb, cSQLTEXT, cb)) ) + + QOut( cSQLTEXT := "BEGIN EXCLUSIVE TRANSACTION" ) + Qout( "return value: ",cErrorMsg(sqlite3_exec(pDb, cSQLTEXT)) ) + + QOut( cSQLTEXT := "DELETE FROM person WHERE name == 'Andy'" ) + Qout( "return value: ", cErrorMsg(sqlite3_exec(pDb, cSQLTEXT)) ) + + QOut( cSQLTEXT := "END TRANSACTION" ) + Qout( "return value: ", cErrorMsg(sqlite3_exec(pDb, cSQLTEXT)) ) + + QOut( cSQLTEXT := "SELECT * FROM person WHERE name == 'Andy'" ) + Qout( "return value: ", cErrorMsg(sqlite3_exec(pDb, cSQLTEXT, cb)) ) + + QOut( Replicate("-", Len(cSQLTEXT)) ) + + sqlite3_sleep( 10000 ) + // + sqlite3_commit_hook( pDb, @HookCommitN() ) + sqlite3_rollback_hook( pDb, @HookRollback() ) + + QOut( cSQLTEXT := "SELECT * FROM person WHERE name == 'Ivet'" ) + Qout( "return value: ", cErrorMsg(sqlite3_exec(pDb, cSQLTEXT, cb)) ) + + QOut( cSQLTEXT := "BEGIN EXCLUSIVE TRANSACTION" ) + Qout( "return value: ", cErrorMsg(sqlite3_exec(pDb, cSQLTEXT)) ) + + QOut( cSQLTEXT := "DELETE FROM person WHERE name == 'Ivet'" ) + Qout( "return value: ", cErrorMsg(sqlite3_exec(pDb, cSQLTEXT)) ) + + QOut( cSQLTEXT := "END TRANSACTION" ) + Qout( "return value: ", cErrorMsg(sqlite3_exec(pDb, cSQLTEXT)) ) + + QOut( cSQLTEXT := "SELECT * FROM person WHERE name == 'Ivet'" ) + Qout( "return value: ", cErrorMsg(sqlite3_exec(pDb, cSQLTEXT, cb)) ) + // + pDb := NIL + + sqlite3_sleep( 10000 ) + // +RETURN 0 + +/** +*/ +FUNCTION CallBack( nColCount, aValue, aColName ) +LOCAL nI +LOCAL oldColor := SetColor( "G/N" ) + // + FOR nI := 1 TO nColCount + Qout( Padr(aColName[nI], 5) , " == ", aValue[nI] ) + NEXT + + SetColor( oldColor ) + // +RETURN 0 + +/** +*/ +FUNCTION HookCommitY() +LOCAL oldColor := SetColor( "R+/N" ) + // + Qout( "!! COMMIT" ) + + SetColor( oldColor ) + // +RETURN 0 + +FUNCTION HookCommitN() +LOCAL oldColor := SetColor( "B+/N" ) + // + Qout( "?? COMMIT or ROLLBACK" ) + + SetColor( oldColor ) + // +RETURN 1 // not 0 + +FUNCTION HookRollback() +LOCAL oldColor := SetColor( "R+/N" ) + // + Qout( "!! ROLLBACK" ) + + SetColor( oldColor ) + // +RETURN 1 + +/** +*/ +STATIC FUNCTION cErrorMsg( nError, lShortMsg ) + LOCAL aErrorCodes := { ; + { SQLITE_ERROR , "SQLITE_ERROR" , "SQL error or missing database" }, ; + { SQLITE_INTERNAL , "SQLITE_INTERNAL" , "NOT USED. Internal logic error in SQLite" }, ; + { SQLITE_PERM , "SQLITE_PERM" , "Access permission denied" }, ; + { SQLITE_ABORT , "SQLITE_ABORT" , "Callback routine requested an abort" }, ; + { SQLITE_BUSY , "SQLITE_BUSY" , "The database file is locked" }, ; + { SQLITE_LOCKED , "SQLITE_LOCKED" , "A table in the database is locked" }, ; + { SQLITE_NOMEM , "SQLITE_NOMEM" , "A malloc() failed" }, ; + { SQLITE_READONLY , "SQLITE_READONLY" , "Attempt to write a readonly database" }, ; + { SQLITE_INTERRUPT , "SQLITE_INTERRUPT" , "Operation terminated by sqlite3_interrupt()" }, ; + { SQLITE_IOERR , "SQLITE_IOERR" , "Some kind of disk I/O error occurred" }, ; + { SQLITE_CORRUPT , "SQLITE_CORRUPT" , "The database disk image is malformed" }, ; + { SQLITE_NOTFOUND , "SQLITE_NOTFOUND" , "NOT USED. Table or record not found" }, ; + { SQLITE_FULL , "SQLITE_FULL" , "Insertion failed because database is full" }, ; + { SQLITE_CANTOPEN , "SQLITE_CANTOPEN" , "Unable to open the database file" }, ; + { SQLITE_PROTOCOL , "SQLITE_PROTOCOL" , "NOT USED. Database lock protocol error" }, ; + { SQLITE_EMPTY , "SQLITE_EMPTY" , "Database is empty" }, ; + { SQLITE_SCHEMA , "SQLITE_SCHEMA" , "The database schema changed" }, ; + { SQLITE_TOOBIG , "SQLITE_TOOBIG" , "String or BLOB exceeds size limit" }, ; + { SQLITE_CONSTRAINT , "SQLITE_CONSTRAINT" , "Abort due to constraint violation" }, ; + { SQLITE_MISMATCH , "SQLITE_MISMATCH" , "Data type mismatch" }, ; + { SQLITE_MISUSE , "SQLITE_MISUSE" , "Library used incorrectly" }, ; + { SQLITE_NOLFS , "SQLITE_NOLFS" , "Uses OS features not supported on host" }, ; + { SQLITE_AUTH , "SQLITE_AUTH" , "Authorization denied" }, ; + { SQLITE_FORMAT , "SQLITE_FORMAT" , "Auxiliary database format error" }, ; + { SQLITE_RANGE , "SQLITE_RANGE" , "2nd parameter to sqlite3_bind out of range" }, ; + { SQLITE_NOTADB , "SQLITE_NOTADB" , "File opened that is not a database file" }, ; + { SQLITE_ROW , "SQLITE_ROW" , "sqlite3_step() has another row ready" }, ; + { SQLITE_DONE , "SQLITE_DONE" , "sqlite3_step() has finished executing" } ; + }, nIndex, cErrorMsg := "UNKNOWN" + // + DEFAULT lShortMsg TO TRUE + + IF hb_IsNumeric( nError ) + IF nError == 0 + cErrorMsg := "SQLITE_OK" + ELSE + nIndex := AScan( aErrorCodes, {|x| x[1] == nError } ) + cErrorMsg := iif( nIndex > 0, aErrorCodes[ nIndex ][ iif(lShortMsg,2,3) ], cErrorMsg ) + ENDIF + ENDIF + // +RETURN cErrorMsg + +/** +*/ +STATIC FUNCTION PrepareDB( cFile ) + LOCAL cSQLTEXT, cMsg + LOCAL pDb, pStmt + LOCAL hPerson := { ; + "Bob" => 52, ; + "Fred" => 32, ; + "Sasha" => 17, ; + "Andy" => 20, ; + "Ivet" => 28 ; + }, enum + // + pDb := sqlite3_open( cFile, TRUE ) + IF Empty( pDb ) + QOut( "Can't open/create database : ", cFile ) + + RETURN NIL + ENDIF + + Qout( cSQLTEXT := "CREATE TABLE person( name TEXT, age INTEGER )" ) + cMsg := cErrorMsg( sqlite3_exec(pDb, cSQLTEXT) ) + + IF cMsg <> "SQLITE_OK" + QOut( "Can't create table : person" ) + pDb := NIL // close database + + RETURN NIL + ENDIF + // + cSQLTEXT := "INSERT INTO person( name, age ) VALUES( :name, :age )" + pStmt := sqlite3_prepare( pDb, cSQLTEXT ) + IF Empty( pStmt ) + QOut( "Can't prepare statement : ", cSQLTEXT ) + pDb := NIL + + RETURN NIL + ENDIF + + QOut( sqlite3_sql(pStmt) ) + QOut( Replicate("-", Len(cSQLTEXT)) ) + + FOR EACH enum IN hPerson + sqlite3_reset( pStmt ) + sqlite3_bind_text( pStmt, 1, enum:__enumKey ) + sqlite3_bind_int( pStmt, 2, enum:__enumValue ) + sqlite3_step( pStmt ) + NEXT + + sqlite3_clear_bindings( pStmt ) + sqlite3_finalize( pStmt ) + // +RETURN pDb \ No newline at end of file diff --git a/harbour/contrib/hbsqlit3/tests/metadata.prg b/harbour/contrib/hbsqlit3/tests/metadata.prg index 3f49adf560..1d838151be 100644 --- a/harbour/contrib/hbsqlit3/tests/metadata.prg +++ b/harbour/contrib/hbsqlit3/tests/metadata.prg @@ -52,9 +52,7 @@ #include "hbsqlit3.ch" -#ifdef NODLL - #define SQLITE_ENABLE_COLUMN_METADATA -#endif +//#define SQLITE_ENABLE_COLUMN_METADATA PROCEDURE main() LOCAL lCreateIfNotExist := .f.