📄 tclsqlite.c
字号:
sqlite3_progress_handler(pDb->db, 0, 0, 0); }#endif }else{ Tcl_WrongNumArgs(interp, 2, objv, "N CALLBACK"); return TCL_ERROR; } break; } /* $db profile ?CALLBACK? ** ** Make arrangements to invoke the CALLBACK routine after each SQL statement ** that has run. The text of the SQL and the amount of elapse time are ** appended to CALLBACK before the script is run. */ case DB_PROFILE: { if( objc>3 ){ Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?"); return TCL_ERROR; }else if( objc==2 ){ if( pDb->zProfile ){ Tcl_AppendResult(interp, pDb->zProfile, 0); } }else{ char *zProfile; int len; if( pDb->zProfile ){ Tcl_Free(pDb->zProfile); } zProfile = Tcl_GetStringFromObj(objv[2], &len); if( zProfile && len>0 ){ pDb->zProfile = Tcl_Alloc( len + 1 ); strcpy(pDb->zProfile, zProfile); }else{ pDb->zProfile = 0; }#ifndef SQLITE_OMIT_TRACE if( pDb->zProfile ){ pDb->interp = interp; sqlite3_profile(pDb->db, DbProfileHandler, pDb); }else{ sqlite3_profile(pDb->db, 0, 0); }#endif } break; } /* ** $db rekey KEY ** ** Change the encryption key on the currently open database. */ case DB_REKEY: { int nKey; void *pKey; if( objc!=3 ){ Tcl_WrongNumArgs(interp, 2, objv, "KEY"); return TCL_ERROR; } pKey = Tcl_GetByteArrayFromObj(objv[2], &nKey);#ifdef SQLITE_HAS_CODEC rc = sqlite3_rekey(pDb->db, pKey, nKey); if( rc ){ Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0); rc = TCL_ERROR; }#endif break; } /* ** $db timeout MILLESECONDS ** ** Delay for the number of milliseconds specified when a file is locked. */ case DB_TIMEOUT: { int ms; if( objc!=3 ){ Tcl_WrongNumArgs(interp, 2, objv, "MILLISECONDS"); return TCL_ERROR; } if( Tcl_GetIntFromObj(interp, objv[2], &ms) ) return TCL_ERROR; sqlite3_busy_timeout(pDb->db, ms); break; } /* ** $db total_changes ** ** Return the number of rows that were modified, inserted, or deleted ** since the database handle was created. */ case DB_TOTAL_CHANGES: { Tcl_Obj *pResult; if( objc!=2 ){ Tcl_WrongNumArgs(interp, 2, objv, ""); return TCL_ERROR; } pResult = Tcl_GetObjResult(interp); Tcl_SetIntObj(pResult, sqlite3_total_changes(pDb->db)); break; } /* $db trace ?CALLBACK? ** ** Make arrangements to invoke the CALLBACK routine for each SQL statement ** that is executed. The text of the SQL is appended to CALLBACK before ** it is executed. */ case DB_TRACE: { if( objc>3 ){ Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?"); return TCL_ERROR; }else if( objc==2 ){ if( pDb->zTrace ){ Tcl_AppendResult(interp, pDb->zTrace, 0); } }else{ char *zTrace; int len; if( pDb->zTrace ){ Tcl_Free(pDb->zTrace); } zTrace = Tcl_GetStringFromObj(objv[2], &len); if( zTrace && len>0 ){ pDb->zTrace = Tcl_Alloc( len + 1 ); strcpy(pDb->zTrace, zTrace); }else{ pDb->zTrace = 0; }#ifndef SQLITE_OMIT_TRACE if( pDb->zTrace ){ pDb->interp = interp; sqlite3_trace(pDb->db, DbTraceHandler, pDb); }else{ sqlite3_trace(pDb->db, 0, 0); }#endif } break; } /* $db transaction [-deferred|-immediate|-exclusive] SCRIPT ** ** Start a new transaction (if we are not already in the midst of a ** transaction) and execute the TCL script SCRIPT. After SCRIPT ** completes, either commit the transaction or roll it back if SCRIPT ** throws an exception. Or if no new transation was started, do nothing. ** pass the exception on up the stack. ** ** This command was inspired by Dave Thomas's talk on Ruby at the ** 2005 O'Reilly Open Source Convention (OSCON). */ case DB_TRANSACTION: { int inTrans; Tcl_Obj *pScript; const char *zBegin = "BEGIN"; if( objc!=3 && objc!=4 ){ Tcl_WrongNumArgs(interp, 2, objv, "[TYPE] SCRIPT"); return TCL_ERROR; } if( objc==3 ){ pScript = objv[2]; } else { static const char *TTYPE_strs[] = { "deferred", "exclusive", "immediate", 0 }; enum TTYPE_enum { TTYPE_DEFERRED, TTYPE_EXCLUSIVE, TTYPE_IMMEDIATE }; int ttype; if( Tcl_GetIndexFromObj(interp, objv[2], TTYPE_strs, "transaction type", 0, &ttype) ){ return TCL_ERROR; } switch( (enum TTYPE_enum)ttype ){ case TTYPE_DEFERRED: /* no-op */; break; case TTYPE_EXCLUSIVE: zBegin = "BEGIN EXCLUSIVE"; break; case TTYPE_IMMEDIATE: zBegin = "BEGIN IMMEDIATE"; break; } pScript = objv[3]; } inTrans = !sqlite3_get_autocommit(pDb->db); if( !inTrans ){ (void)sqlite3_exec(pDb->db, zBegin, 0, 0, 0); } rc = Tcl_EvalObjEx(interp, pScript, 0); if( !inTrans ){ const char *zEnd; if( rc==TCL_ERROR ){ zEnd = "ROLLBACK"; } else { zEnd = "COMMIT"; } (void)sqlite3_exec(pDb->db, zEnd, 0, 0, 0); } break; } /* ** $db update_hook ?script? ** $db rollback_hook ?script? */ case DB_UPDATE_HOOK: case DB_ROLLBACK_HOOK: { /* set ppHook to point at pUpdateHook or pRollbackHook, depending on ** whether [$db update_hook] or [$db rollback_hook] was invoked. */ Tcl_Obj **ppHook; if( choice==DB_UPDATE_HOOK ){ ppHook = &pDb->pUpdateHook; }else{ ppHook = &pDb->pRollbackHook; } if( objc!=2 && objc!=3 ){ Tcl_WrongNumArgs(interp, 2, objv, "?SCRIPT?"); return TCL_ERROR; } if( *ppHook ){ Tcl_SetObjResult(interp, *ppHook); if( objc==3 ){ Tcl_DecrRefCount(*ppHook); *ppHook = 0; } } if( objc==3 ){ assert( !(*ppHook) ); if( Tcl_GetCharLength(objv[2])>0 ){ *ppHook = objv[2]; Tcl_IncrRefCount(*ppHook); } } sqlite3_update_hook(pDb->db, (pDb->pUpdateHook?DbUpdateHandler:0), pDb); sqlite3_rollback_hook(pDb->db,(pDb->pRollbackHook?DbRollbackHandler:0),pDb); break; } /* $db version ** ** Return the version string for this database. */ case DB_VERSION: { Tcl_SetResult(interp, (char *)sqlite3_libversion(), TCL_STATIC); break; } } /* End of the SWITCH statement */ return rc;}/*** sqlite3 DBNAME FILENAME ?MODE? ?-key KEY?**** This is the main Tcl command. When the "sqlite" Tcl command is** invoked, this routine runs to process that command.**** The first argument, DBNAME, is an arbitrary name for a new** database connection. This command creates a new command named** DBNAME that is used to control that connection. The database** connection is deleted when the DBNAME command is deleted.**** The second argument is the name of the directory that contains** the sqlite database that is to be accessed.**** For testing purposes, we also support the following:**** sqlite3 -encoding**** Return the encoding used by LIKE and GLOB operators. Choices** are UTF-8 and iso8859.**** sqlite3 -version**** Return the version number of the SQLite library.**** sqlite3 -tcl-uses-utf**** Return "1" if compiled with a Tcl uses UTF-8. Return "0" if** not. Used by tests to make sure the library was compiled ** correctly.*/static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ SqliteDb *p; void *pKey = 0; int nKey = 0; const char *zArg; char *zErrMsg; const char *zFile; if( objc==2 ){ zArg = Tcl_GetStringFromObj(objv[1], 0); if( strcmp(zArg,"-version")==0 ){ Tcl_AppendResult(interp,sqlite3_version,0); return TCL_OK; } if( strcmp(zArg,"-has-codec")==0 ){#ifdef SQLITE_HAS_CODEC Tcl_AppendResult(interp,"1",0);#else Tcl_AppendResult(interp,"0",0);#endif return TCL_OK; } if( strcmp(zArg,"-tcl-uses-utf")==0 ){#ifdef TCL_UTF_MAX Tcl_AppendResult(interp,"1",0);#else Tcl_AppendResult(interp,"0",0);#endif return TCL_OK; } } if( objc==5 || objc==6 ){ zArg = Tcl_GetStringFromObj(objv[objc-2], 0); if( strcmp(zArg,"-key")==0 ){ pKey = Tcl_GetByteArrayFromObj(objv[objc-1], &nKey); objc -= 2; } } if( objc!=3 && objc!=4 ){ Tcl_WrongNumArgs(interp, 1, objv, #ifdef SQLITE_HAS_CODEC "HANDLE FILENAME ?-key CODEC-KEY?"#else "HANDLE FILENAME ?MODE?"#endif ); return TCL_ERROR; } zErrMsg = 0; p = (SqliteDb*)Tcl_Alloc( sizeof(*p) ); if( p==0 ){ Tcl_SetResult(interp, "malloc failed", TCL_STATIC); return TCL_ERROR; } memset(p, 0, sizeof(*p)); zFile = Tcl_GetStringFromObj(objv[2], 0); sqlite3_open(zFile, &p->db); if( SQLITE_OK!=sqlite3_errcode(p->db) ){ zErrMsg = strdup(sqlite3_errmsg(p->db)); sqlite3_close(p->db); p->db = 0; }#ifdef SQLITE_HAS_CODEC sqlite3_key(p->db, pKey, nKey);#endif if( p->db==0 ){ Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE); Tcl_Free((char*)p); free(zErrMsg); return TCL_ERROR; } p->maxStmt = NUM_PREPARED_STMTS; zArg = Tcl_GetStringFromObj(objv[1], 0); Tcl_CreateObjCommand(interp, zArg, DbObjCmd, (char*)p, DbDeleteCmd); /* If compiled with SQLITE_TEST turned on, then register the "md5sum" ** SQL function. */#ifdef SQLITE_TEST { extern void Md5_Register(sqlite3*);#ifdef SQLITE_MEMDEBUG int mallocfail = sqlite3_iMallocFail; sqlite3_iMallocFail = 0;#endif Md5_Register(p->db);#ifdef SQLITE_MEMDEBUG sqlite3_iMallocFail = mallocfail;#endif }#endif p->interp = interp; return TCL_OK;}/*** Provide a dummy Tcl_InitStubs if we are using this as a static** library.*/#ifndef USE_TCL_STUBS# undef Tcl_InitStubs# define Tcl_InitStubs(a,b,c)#endif/*** Make sure we have a PACKAGE_VERSION macro defined. This will be** defined automatically by the TEA makefile. But other makefiles** do not define it.*/#ifndef PACKAGE_VERSION# define PACKAGE_VERSION SQLITE_VERSION#endif/*** Initialize this module.**** This Tcl module contains only a single new Tcl command named "sqlite".** (Hence there is no namespace. There is no point in using a namespace** if the extension only supplies one new name!) The "sqlite" command is** used to open a new SQLite database. See the DbMain() routine above** for additional information.*/EXTERN int Sqlite3_Init(Tcl_Interp *interp){ Tcl_InitStubs(interp, "8.4", 0); Tcl_CreateObjCommand(interp, "sqlite3", (Tcl_ObjCmdProc*)DbMain, 0, 0); Tcl_PkgProvide(interp, "sqlite3", PACKAGE_VERSION); Tcl_CreateObjCommand(interp, "sqlite", (Tcl_ObjCmdProc*)DbMain, 0, 0); Tcl_PkgProvide(interp, "sqlite", PACKAGE_VERSION); return TCL_OK;}EXTERN int Tclsqlite3_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }EXTERN int Sqlite3_SafeInit(Tcl_Interp *interp){ return TCL_OK; }EXTERN int Tclsqlite3_SafeInit(Tcl_Interp *interp){ return TCL_OK; }#ifndef SQLITE_3_SUFFIX_ONLYEXTERN int Sqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(in
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -