tclsqlite.c
来自「sqlite最新源码」· C语言 代码 · 共 2,068 行 · 第 1/5 页
C
2,068 行
rc = SQLITE_DENY; }else if( strcmp(zReply,"SQLITE_IGNORE")==0 ){ rc = SQLITE_IGNORE; }else{ rc = 999; } return rc;}#endif /* SQLITE_OMIT_AUTHORIZATION *//*** zText is a pointer to text obtained via an sqlite3_result_text()** or similar interface. This routine returns a Tcl string object, ** reference count set to 0, containing the text. If a translation** between iso8859 and UTF-8 is required, it is preformed.*/static Tcl_Obj *dbTextToObj(char const *zText){ Tcl_Obj *pVal;#ifdef UTF_TRANSLATION_NEEDED Tcl_DString dCol; Tcl_DStringInit(&dCol); Tcl_ExternalToUtfDString(NULL, zText, -1, &dCol); pVal = Tcl_NewStringObj(Tcl_DStringValue(&dCol), -1); Tcl_DStringFree(&dCol);#else pVal = Tcl_NewStringObj(zText, -1);#endif return pVal;}/*** This routine reads a line of text from FILE in, stores** the text in memory obtained from malloc() and returns a pointer** to the text. NULL is returned at end of file, or if malloc()** fails.**** The interface is like "readline" but no command-line editing** is done.**** copied from shell.c from '.import' command*/static char *local_getline(char *zPrompt, FILE *in){ char *zLine; int nLine; int n; int eol; nLine = 100; zLine = malloc( nLine ); if( zLine==0 ) return 0; n = 0; eol = 0; while( !eol ){ if( n+100>nLine ){ nLine = nLine*2 + 100; zLine = realloc(zLine, nLine); if( zLine==0 ) return 0; } if( fgets(&zLine[n], nLine - n, in)==0 ){ if( n==0 ){ free(zLine); return 0; } zLine[n] = 0; eol = 1; break; } while( zLine[n] ){ n++; } if( n>0 && zLine[n-1]=='\n' ){ n--; zLine[n] = 0; eol = 1; } } zLine = realloc( zLine, n+1 ); return zLine;}/*** Figure out the column names for the data returned by the statement** passed as the second argument.**** If parameter papColName is not NULL, then *papColName is set to point** at an array allocated using Tcl_Alloc(). It is the callers responsibility** to free this array using Tcl_Free(), and to decrement the reference** count of each Tcl_Obj* member of the array.**** The return value of this function is the number of columns of data** returned by pStmt (and hence the size of the *papColName array).**** If pArray is not NULL, then it contains the name of a Tcl array** variable. The "*" member of this array is set to a list containing** the names of the columns returned by the statement, in order from** left to right. e.g. if the names of the returned columns are a, b and** c, it does the equivalent of the tcl command:**** set ${pArray}(*) {a b c}*/static intcomputeColumnNames( Tcl_Interp *interp, sqlite3_stmt *pStmt, /* SQL statement */ Tcl_Obj ***papColName, /* OUT: Array of column names */ Tcl_Obj *pArray /* Name of array variable (may be null) */){ int nCol; /* Compute column names */ nCol = sqlite3_column_count(pStmt); if( papColName ){ int i; Tcl_Obj **apColName = (Tcl_Obj**)Tcl_Alloc( sizeof(Tcl_Obj*)*nCol ); for(i=0; i<nCol; i++){ apColName[i] = dbTextToObj(sqlite3_column_name(pStmt,i)); Tcl_IncrRefCount(apColName[i]); } /* If results are being stored in an array variable, then create ** the array(*) entry for that array */ if( pArray ){ Tcl_Obj *pColList = Tcl_NewObj(); Tcl_Obj *pStar = Tcl_NewStringObj("*", -1); Tcl_IncrRefCount(pColList); for(i=0; i<nCol; i++){ Tcl_ListObjAppendElement(interp, pColList, apColName[i]); } Tcl_IncrRefCount(pStar); Tcl_ObjSetVar2(interp, pArray, pStar, pColList,0); Tcl_DecrRefCount(pColList); Tcl_DecrRefCount(pStar); } *papColName = apColName; } return nCol;}/*** The "sqlite" command below creates a new Tcl command for each** connection it opens to an SQLite database. This routine is invoked** whenever one of those connection-specific commands is executed** in Tcl. For example, if you run Tcl code like this:**** sqlite3 db1 "my_database"** db1 close**** The first command opens a connection to the "my_database" database** and calls that connection "db1". The second command causes this** subroutine to be invoked.*/static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ SqliteDb *pDb = (SqliteDb*)cd; int choice; int rc = TCL_OK; static const char *DB_strs[] = { "authorizer", "backup", "busy", "cache", "changes", "close", "collate", "collation_needed", "commit_hook", "complete", "copy", "enable_load_extension", "errorcode", "eval", "exists", "function", "incrblob", "interrupt", "last_insert_rowid", "nullvalue", "onecolumn", "profile", "progress", "rekey", "restore", "rollback_hook", "status", "timeout", "total_changes", "trace", "transaction", "update_hook", "version", 0 }; enum DB_enum { DB_AUTHORIZER, DB_BACKUP, DB_BUSY, DB_CACHE, DB_CHANGES, DB_CLOSE, DB_COLLATE, DB_COLLATION_NEEDED, DB_COMMIT_HOOK, DB_COMPLETE, DB_COPY, DB_ENABLE_LOAD_EXTENSION, DB_ERRORCODE, DB_EVAL, DB_EXISTS, DB_FUNCTION, DB_INCRBLOB, DB_INTERRUPT, DB_LAST_INSERT_ROWID, DB_NULLVALUE, DB_ONECOLUMN, DB_PROFILE, DB_PROGRESS, DB_REKEY, DB_RESTORE, DB_ROLLBACK_HOOK, DB_STATUS, DB_TIMEOUT, DB_TOTAL_CHANGES, DB_TRACE, DB_TRANSACTION, DB_UPDATE_HOOK, DB_VERSION, }; /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */ if( objc<2 ){ Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ..."); return TCL_ERROR; } if( Tcl_GetIndexFromObj(interp, objv[1], DB_strs, "option", 0, &choice) ){ return TCL_ERROR; } switch( (enum DB_enum)choice ){ /* $db authorizer ?CALLBACK? ** ** Invoke the given callback to authorize each SQL operation as it is ** compiled. 5 arguments are appended to the callback before it is ** invoked: ** ** (1) The authorization type (ex: SQLITE_CREATE_TABLE, SQLITE_INSERT, ...) ** (2) First descriptive name (depends on authorization type) ** (3) Second descriptive name ** (4) Name of the database (ex: "main", "temp") ** (5) Name of trigger that is doing the access ** ** The callback should return on of the following strings: SQLITE_OK, ** SQLITE_IGNORE, or SQLITE_DENY. Any other return value is an error. ** ** If this method is invoked with no arguments, the current authorization ** callback string is returned. */ case DB_AUTHORIZER: {#ifdef SQLITE_OMIT_AUTHORIZATION Tcl_AppendResult(interp, "authorization not available in this build", 0); return TCL_ERROR;#else if( objc>3 ){ Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?"); return TCL_ERROR; }else if( objc==2 ){ if( pDb->zAuth ){ Tcl_AppendResult(interp, pDb->zAuth, 0); } }else{ char *zAuth; int len; if( pDb->zAuth ){ Tcl_Free(pDb->zAuth); } zAuth = Tcl_GetStringFromObj(objv[2], &len); if( zAuth && len>0 ){ pDb->zAuth = Tcl_Alloc( len + 1 ); memcpy(pDb->zAuth, zAuth, len+1); }else{ pDb->zAuth = 0; } if( pDb->zAuth ){ pDb->interp = interp; sqlite3_set_authorizer(pDb->db, auth_callback, pDb); }else{ sqlite3_set_authorizer(pDb->db, 0, 0); } }#endif break; } /* $db backup ?DATABASE? FILENAME ** ** Open or create a database file named FILENAME. Transfer the ** content of local database DATABASE (default: "main") into the ** FILENAME database. */ case DB_BACKUP: { const char *zDestFile; const char *zSrcDb; sqlite3 *pDest; sqlite3_backup *pBackup; if( objc==3 ){ zSrcDb = "main"; zDestFile = Tcl_GetString(objv[2]); }else if( objc==4 ){ zSrcDb = Tcl_GetString(objv[2]); zDestFile = Tcl_GetString(objv[3]); }else{ Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE? FILENAME"); return TCL_ERROR; } rc = sqlite3_open(zDestFile, &pDest); if( rc!=SQLITE_OK ){ Tcl_AppendResult(interp, "cannot open target database: ", sqlite3_errmsg(pDest), (char*)0); sqlite3_close(pDest); return TCL_ERROR; } pBackup = sqlite3_backup_init(pDest, "main", pDb->db, zSrcDb); if( pBackup==0 ){ Tcl_AppendResult(interp, "backup failed: ", sqlite3_errmsg(pDest), (char*)0); sqlite3_close(pDest); return TCL_ERROR; } while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){} sqlite3_backup_finish(pBackup); if( rc==SQLITE_DONE ){ rc = TCL_OK; }else{ Tcl_AppendResult(interp, "backup failed: ", sqlite3_errmsg(pDest), (char*)0); rc = TCL_ERROR; } sqlite3_close(pDest); break; } /* $db busy ?CALLBACK? ** ** Invoke the given callback if an SQL statement attempts to open ** a locked database file. */ case DB_BUSY: { if( objc>3 ){ Tcl_WrongNumArgs(interp, 2, objv, "CALLBACK"); return TCL_ERROR; }else if( objc==2 ){ if( pDb->zBusy ){ Tcl_AppendResult(interp, pDb->zBusy, 0); } }else{ char *zBusy; int len; if( pDb->zBusy ){ Tcl_Free(pDb->zBusy); } zBusy = Tcl_GetStringFromObj(objv[2], &len); if( zBusy && len>0 ){ pDb->zBusy = Tcl_Alloc( len + 1 ); memcpy(pDb->zBusy, zBusy, len+1); }else{ pDb->zBusy = 0; } if( pDb->zBusy ){ pDb->interp = interp; sqlite3_busy_handler(pDb->db, DbBusyHandler, pDb); }else{ sqlite3_busy_handler(pDb->db, 0, 0); } } break; } /* $db cache flush ** $db cache size n ** ** Flush the prepared statement cache, or set the maximum number of ** cached statements. */ case DB_CACHE: { char *subCmd; int n; if( objc<=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "cache option ?arg?"); return TCL_ERROR; } subCmd = Tcl_GetStringFromObj( objv[2], 0 ); if( *subCmd=='f' && strcmp(subCmd,"flush")==0 ){ if( objc!=3 ){ Tcl_WrongNumArgs(interp, 2, objv, "flush"); return TCL_ERROR; }else{ flushStmtCache( pDb ); } }else if( *subCmd=='s' && strcmp(subCmd,"size")==0 ){ if( objc!=4 ){ Tcl_WrongNumArgs(interp, 2, objv, "size n"); return TCL_ERROR; }else{ if( TCL_ERROR==Tcl_GetIntFromObj(interp, objv[3], &n) ){ Tcl_AppendResult( interp, "cannot convert \"", Tcl_GetStringFromObj(objv[3],0), "\" to integer", 0); return TCL_ERROR; }else{ if( n<0 ){ flushStmtCache( pDb ); n = 0; }else if( n>MAX_PREPARED_STMTS ){ n = MAX_PREPARED_STMTS; } pDb->maxStmt = n; } } }else{ Tcl_AppendResult( interp, "bad option \"", Tcl_GetStringFromObj(objv[2],0), "\": must be flush or size", 0); return TCL_ERROR; } break; } /* $db changes ** ** Return the number of rows that were modified, inserted, or deleted by ** the most recent INSERT, UPDATE or DELETE statement, not including ** any changes made by trigger programs. */ case DB_CHANGES: { Tcl_Obj *pResult; if( objc!=2 ){ Tcl_WrongNumArgs(interp, 2, objv, ""); return TCL_ERROR; } pResult = Tcl_GetObjResult(interp); Tcl_SetIntObj(pResult, sqlite3_changes(pDb->db)); break; } /* $db close ** ** Shutdown the database */ case DB_CLOSE: { Tcl_DeleteCommand(interp, Tcl_GetStringFromObj(objv[0], 0)); break; } /* ** $db collate NAME SCRIPT ** ** Create a new SQL collation function called NAME. Whenever ** that function is called, invoke SCRIPT to evaluate the function.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?