📄 tclsqlite.c
字号:
} /* ** $db last_insert_rowid ** ** Return an integer which is the ROWID for the most recent insert. */ case DB_LAST_INSERT_ROWID: { Tcl_Obj *pResult; int rowid; if( objc!=2 ){ Tcl_WrongNumArgs(interp, 2, objv, ""); return TCL_ERROR; } rowid = sqlite_last_insert_rowid(pDb->db); pResult = Tcl_GetObjResult(interp); Tcl_SetIntObj(pResult, rowid); break; } /* ** $db onecolumn SQL ** ** Return a single column from a single row of the given SQL query. */ case DB_ONECOLUMN: { char *zSql; char *zErrMsg = 0; if( objc!=3 ){ Tcl_WrongNumArgs(interp, 2, objv, "SQL"); return TCL_ERROR; } zSql = Tcl_GetStringFromObj(objv[2], 0); rc = sqlite_exec(pDb->db, zSql, DbEvalCallback3, interp, &zErrMsg); if( rc==SQLITE_ABORT ){ rc = SQLITE_OK; }else if( zErrMsg ){ Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE); free(zErrMsg); rc = TCL_ERROR; }else if( rc!=SQLITE_OK ){ Tcl_AppendResult(interp, sqlite_error_string(rc), 0); rc = TCL_ERROR; } 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 = sqlite_rekey(pDb->db, pKey, nKey); if( rc ){ Tcl_AppendResult(interp, sqlite_error_string(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; sqlite_busy_timeout(pDb->db, ms); 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?"); }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; } if( pDb->zTrace ){ pDb->interp = interp; sqlite_trace(pDb->db, DbTraceHandler, pDb); }else{ sqlite_trace(pDb->db, 0, 0); } } break; } } /* End of the SWITCH statement */ return rc;}/*** sqlite 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:**** sqlite -encoding**** Return the encoding used by LIKE and GLOB operators. Choices** are UTF-8 and iso8859.**** sqlite -version**** Return the version number of the SQLite library.**** sqlite -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){ int mode; SqliteDb *p; void *pKey = 0; int nKey = 0; const char *zArg; char *zErrMsg; const char *zFile; char zBuf[80]; if( objc==2 ){ zArg = Tcl_GetStringFromObj(objv[1], 0); if( strcmp(zArg,"-encoding")==0 ){ Tcl_AppendResult(interp,sqlite_encoding,0); return TCL_OK; } if( strcmp(zArg,"-version")==0 ){ Tcl_AppendResult(interp,sqlite_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; } if( objc==3 ){ mode = 0666; }else if( Tcl_GetIntFromObj(interp, objv[3], &mode)!=TCL_OK ){ 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);#ifdef SQLITE_HAS_CODEC p->db = sqlite_open_encrypted(zFile, pKey, nKey, 0, &zErrMsg);#else p->db = sqlite_open(zFile, mode, &zErrMsg);#endif if( p->db==0 ){ Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE); Tcl_Free((char*)p); free(zErrMsg); return TCL_ERROR; } zArg = Tcl_GetStringFromObj(objv[1], 0); Tcl_CreateObjCommand(interp, zArg, DbObjCmd, (char*)p, DbDeleteCmd); /* The return value is the value of the sqlite* pointer */ sprintf(zBuf, "%p", p->db); if( strncmp(zBuf,"0x",2) ){ sprintf(zBuf, "0x%p", p->db); } Tcl_AppendResult(interp, zBuf, 0); /* If compiled with SQLITE_TEST turned on, then register the "md5sum" ** SQL function. */#ifdef SQLITE_TEST { extern void Md5_Register(sqlite*); Md5_Register(p->db); }#endif 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/*** 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.*/int Sqlite_Init(Tcl_Interp *interp){ Tcl_InitStubs(interp, "8.0", 0); Tcl_CreateObjCommand(interp, "sqlite", (Tcl_ObjCmdProc*)DbMain, 0, 0); Tcl_PkgProvide(interp, "sqlite", "2.0"); return TCL_OK;}int Tclsqlite_Init(Tcl_Interp *interp){ Tcl_InitStubs(interp, "8.0", 0); Tcl_CreateObjCommand(interp, "sqlite", (Tcl_ObjCmdProc*)DbMain, 0, 0); Tcl_PkgProvide(interp, "sqlite", "2.0"); return TCL_OK;}int Sqlite_SafeInit(Tcl_Interp *interp){ return TCL_OK;}int Tclsqlite_SafeInit(Tcl_Interp *interp){ return TCL_OK;}#if 0/*** If compiled using mktclapp, this routine runs to initialize** everything.*/int Et_AppInit(Tcl_Interp *interp){ return Sqlite_Init(interp);}#endif/***************************************************************************** The remaining code is only included if the TCLSH macro is defined to** be an integer greater than 0*/#if defined(TCLSH) && TCLSH>0/*** If the macro TCLSH is defined and is one, then put in code for the** "main" routine that implement a interactive shell into which the user** can type TCL commands.*/#if TCLSH==1static char zMainloop[] = "set line {}\n" "while {![eof stdin]} {\n" "if {$line!=\"\"} {\n" "puts -nonewline \"> \"\n" "} else {\n" "puts -nonewline \"% \"\n" "}\n" "flush stdout\n" "append line [gets stdin]\n" "if {[info complete $line]} {\n" "if {[catch {uplevel #0 $line} result]} {\n" "puts stderr \"Error: $result\"\n" "} elseif {$result!=\"\"} {\n" "puts $result\n" "}\n" "set line {}\n" "} else {\n" "append line \\n\n" "}\n" "}\n";#endif /* TCLSH==1 */int Libsqlite_Init( Tcl_Interp *interp) {#ifdef TCL_THREADS if (Thread_Init(interp) == TCL_ERROR) { return TCL_ERROR; }#endif Sqlite_Init(interp);#ifdef SQLITE_TEST { extern int Sqlitetest1_Init(Tcl_Interp*); extern int Sqlitetest2_Init(Tcl_Interp*); extern int Sqlitetest3_Init(Tcl_Interp*); extern int Md5_Init(Tcl_Interp*); Sqlitetest1_Init(interp); Sqlitetest2_Init(interp); Sqlitetest3_Init(interp); Md5_Init(interp); Tcl_StaticPackage(interp, "sqlite", Libsqlite_Init, Libsqlite_Init); }#endif return TCL_OK;}#define TCLSH_MAIN main /* Needed to fake out mktclapp */#if TCLSH==1int TCLSH_MAIN(int argc, char **argv){#ifndef TCL_THREADS Tcl_Interp *interp; Tcl_FindExecutable(argv[0]); interp = Tcl_CreateInterp(); Libsqlite_Init(interp); if( argc>=2 ){ int i; Tcl_SetVar(interp,"argv0",argv[1],TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"argv", "", TCL_GLOBAL_ONLY); for(i=2; i<argc; i++){ Tcl_SetVar(interp, "argv", argv[i], TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT | TCL_APPEND_VALUE); } if( Tcl_EvalFile(interp, argv[1])!=TCL_OK ){ const char *zInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY); if( zInfo==0 ) zInfo = interp->result; fprintf(stderr,"%s: %s\n", *argv, zInfo); return TCL_ERROR; } }else{ Tcl_GlobalEval(interp, zMainloop); } return 0;#else Tcl_Main(argc, argv, Libsqlite_Init);#endif /* TCL_THREADS */ return 0;}#endif /* TCLSH==1 *//*** If the macro TCLSH is set to 2, then implement a space analysis tool.*/#if TCLSH==2static char zAnalysis[] = #include "spaceanal_tcl.h";int main(int argc, char **argv){ Tcl_Interp *interp; int i; Tcl_FindExecutable(argv[0]); interp = Tcl_CreateInterp(); Libsqlite_Init(interp); Tcl_SetVar(interp,"argv0",argv[0],TCL_GLOBAL_ONLY); Tcl_SetVar(interp,"argv", "", TCL_GLOBAL_ONLY); for(i=1; i<argc; i++){ Tcl_SetVar(interp, "argv", argv[i], TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT | TCL_APPEND_VALUE); } if( Tcl_GlobalEval(interp, zAnalysis)!=TCL_OK ){ const char *zInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY); if( zInfo==0 ) zInfo = interp->result; fprintf(stderr,"%s: %s\n", *argv, zInfo); return TCL_ERROR; } return 0;}#endif /* TCLSH==2 */#endif /* TCLSH */#endif /* NO_TCL */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -