| Index: third_party/sqlite/src/src/tclsqlite.c
|
| diff --git a/third_party/sqlite/src/src/tclsqlite.c b/third_party/sqlite/src/src/tclsqlite.c
|
| index 575651d7e561d11c8e54280377b72ff6bddd75ec..756d0daa5a914287f55b0faeb431caf6d0a40b03 100644
|
| --- a/third_party/sqlite/src/src/tclsqlite.c
|
| +++ b/third_party/sqlite/src/src/tclsqlite.c
|
| @@ -41,6 +41,18 @@
|
| #endif
|
| #include <ctype.h>
|
|
|
| +/* Used to get the current process ID */
|
| +#if !defined(_WIN32)
|
| +# include <unistd.h>
|
| +# define GETPID getpid
|
| +#elif !defined(_WIN32_WCE)
|
| +# ifndef SQLITE_AMALGAMATION
|
| +# define WIN32_LEAN_AND_MEAN
|
| +# include <windows.h>
|
| +# endif
|
| +# define GETPID (int)GetCurrentProcessId
|
| +#endif
|
| +
|
| /*
|
| * Windows needs to know which symbols to export. Unix does not.
|
| * BUILD_sqlite should be undefined for Unix.
|
| @@ -53,15 +65,8 @@
|
| #define NUM_PREPARED_STMTS 10
|
| #define MAX_PREPARED_STMTS 100
|
|
|
| -/*
|
| -** If TCL uses UTF-8 and SQLite is configured to use iso8859, then we
|
| -** have to do a translation when going between the two. Set the
|
| -** UTF_TRANSLATION_NEEDED macro to indicate that we need to do
|
| -** this translation.
|
| -*/
|
| -#if defined(TCL_UTF_MAX) && !defined(SQLITE_UTF8)
|
| -# define UTF_TRANSLATION_NEEDED 1
|
| -#endif
|
| +/* Forward declaration */
|
| +typedef struct SqliteDb SqliteDb;
|
|
|
| /*
|
| ** New SQL functions can be created as TCL scripts. Each such function
|
| @@ -71,6 +76,7 @@ typedef struct SqlFunc SqlFunc;
|
| struct SqlFunc {
|
| Tcl_Interp *interp; /* The TCL interpret to execute the function */
|
| Tcl_Obj *pScript; /* The Tcl_Obj representation of the script */
|
| + SqliteDb *pDb; /* Database connection that owns this function */
|
| int useEvalObjv; /* True if it is safe to use Tcl_EvalObjv */
|
| char *zName; /* Name of this function */
|
| SqlFunc *pNext; /* Next function on the list of them all */
|
| @@ -107,8 +113,12 @@ typedef struct IncrblobChannel IncrblobChannel;
|
| /*
|
| ** There is one instance of this structure for each SQLite database
|
| ** that has been opened by the SQLite TCL interface.
|
| +**
|
| +** If this module is built with SQLITE_TEST defined (to create the SQLite
|
| +** testfixture executable), then it may be configured to use either
|
| +** sqlite3_prepare_v2() or sqlite3_prepare() to prepare SQL statements.
|
| +** If SqliteDb.bLegacyPrepare is true, sqlite3_prepare() is used.
|
| */
|
| -typedef struct SqliteDb SqliteDb;
|
| struct SqliteDb {
|
| sqlite3 *db; /* The "real" database structure. MUST BE FIRST */
|
| Tcl_Interp *interp; /* The interpreter used for this database */
|
| @@ -135,6 +145,9 @@ struct SqliteDb {
|
| IncrblobChannel *pIncrblob;/* Linked list of open incrblob channels */
|
| int nStep, nSort, nIndex; /* Statistics for most recent operation */
|
| int nTransaction; /* Number of nested [transaction] methods */
|
| +#ifdef SQLITE_TEST
|
| + int bLegacyPrepare; /* True to use sqlite3_prepare() */
|
| +#endif
|
| };
|
|
|
| struct IncrblobChannel {
|
| @@ -411,18 +424,18 @@ static int safeToUseEvalObjv(Tcl_Interp *interp, Tcl_Obj *pCmd){
|
| */
|
| static SqlFunc *findSqlFunc(SqliteDb *pDb, const char *zName){
|
| SqlFunc *p, *pNew;
|
| - int i;
|
| - pNew = (SqlFunc*)Tcl_Alloc( sizeof(*pNew) + strlen30(zName) + 1 );
|
| + int nName = strlen30(zName);
|
| + pNew = (SqlFunc*)Tcl_Alloc( sizeof(*pNew) + nName + 1 );
|
| pNew->zName = (char*)&pNew[1];
|
| - for(i=0; zName[i]; i++){ pNew->zName[i] = tolower(zName[i]); }
|
| - pNew->zName[i] = 0;
|
| + memcpy(pNew->zName, zName, nName+1);
|
| for(p=pDb->pFunc; p; p=p->pNext){
|
| - if( strcmp(p->zName, pNew->zName)==0 ){
|
| + if( sqlite3_stricmp(p->zName, pNew->zName)==0 ){
|
| Tcl_Free((char*)pNew);
|
| return p;
|
| }
|
| }
|
| pNew->interp = pDb->interp;
|
| + pNew->pDb = pDb;
|
| pNew->pScript = 0;
|
| pNew->pNext = pDb->pFunc;
|
| pDb->pFunc = pNew;
|
| @@ -430,19 +443,32 @@ static SqlFunc *findSqlFunc(SqliteDb *pDb, const char *zName){
|
| }
|
|
|
| /*
|
| +** Free a single SqlPreparedStmt object.
|
| +*/
|
| +static void dbFreeStmt(SqlPreparedStmt *pStmt){
|
| +#ifdef SQLITE_TEST
|
| + if( sqlite3_sql(pStmt->pStmt)==0 ){
|
| + Tcl_Free((char *)pStmt->zSql);
|
| + }
|
| +#endif
|
| + sqlite3_finalize(pStmt->pStmt);
|
| + Tcl_Free((char *)pStmt);
|
| +}
|
| +
|
| +/*
|
| ** Finalize and free a list of prepared statements
|
| */
|
| -static void flushStmtCache( SqliteDb *pDb ){
|
| +static void flushStmtCache(SqliteDb *pDb){
|
| SqlPreparedStmt *pPreStmt;
|
| + SqlPreparedStmt *pNext;
|
|
|
| - while( pDb->stmtList ){
|
| - sqlite3_finalize( pDb->stmtList->pStmt );
|
| - pPreStmt = pDb->stmtList;
|
| - pDb->stmtList = pDb->stmtList->pNext;
|
| - Tcl_Free( (char*)pPreStmt );
|
| + for(pPreStmt = pDb->stmtList; pPreStmt; pPreStmt=pNext){
|
| + pNext = pPreStmt->pNext;
|
| + dbFreeStmt(pPreStmt);
|
| }
|
| pDb->nStmt = 0;
|
| pDb->stmtLast = 0;
|
| + pDb->stmtList = 0;
|
| }
|
|
|
| /*
|
| @@ -457,6 +483,7 @@ static void DbDeleteCmd(void *db){
|
| while( pDb->pFunc ){
|
| SqlFunc *pFunc = pDb->pFunc;
|
| pDb->pFunc = pFunc->pNext;
|
| + assert( pFunc->pDb==pDb );
|
| Tcl_DecrRefCount(pFunc->pScript);
|
| Tcl_Free((char*)pFunc);
|
| }
|
| @@ -733,7 +760,7 @@ static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){
|
| /* If there are arguments to the function, make a shallow copy of the
|
| ** script object, lappend the arguments, then evaluate the copy.
|
| **
|
| - ** By "shallow" copy, we mean a only the outer list Tcl_Obj is duplicated.
|
| + ** By "shallow" copy, we mean only the outer list Tcl_Obj is duplicated.
|
| ** The new Tcl_Obj contains pointers to the original list elements.
|
| ** That way, when Tcl_EvalObjv() is run and shimmers the first element
|
| ** of the list to tclCmdNameType, that alternate representation will
|
| @@ -761,7 +788,7 @@ static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){
|
| case SQLITE_INTEGER: {
|
| sqlite_int64 v = sqlite3_value_int64(pIn);
|
| if( v>=-2147483647 && v<=2147483647 ){
|
| - pVal = Tcl_NewIntObj(v);
|
| + pVal = Tcl_NewIntObj((int)v);
|
| }else{
|
| pVal = Tcl_NewWideIntObj(v);
|
| }
|
| @@ -773,7 +800,7 @@ static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){
|
| break;
|
| }
|
| case SQLITE_NULL: {
|
| - pVal = Tcl_NewStringObj("", 0);
|
| + pVal = Tcl_NewStringObj(p->pDb->zNull, -1);
|
| break;
|
| }
|
| default: {
|
| @@ -845,8 +872,11 @@ static int auth_callback(
|
| const char *zArg2,
|
| const char *zArg3,
|
| const char *zArg4
|
| +#ifdef SQLITE_USER_AUTHENTICATION
|
| + ,const char *zArg5
|
| +#endif
|
| ){
|
| - char *zCode;
|
| + const char *zCode;
|
| Tcl_DString str;
|
| int rc;
|
| const char *zReply;
|
| @@ -887,6 +917,7 @@ static int auth_callback(
|
| case SQLITE_DROP_VTABLE : zCode="SQLITE_DROP_VTABLE"; break;
|
| case SQLITE_FUNCTION : zCode="SQLITE_FUNCTION"; break;
|
| case SQLITE_SAVEPOINT : zCode="SQLITE_SAVEPOINT"; break;
|
| + case SQLITE_RECURSIVE : zCode="SQLITE_RECURSIVE"; break;
|
| default : zCode="????"; break;
|
| }
|
| Tcl_DStringInit(&str);
|
| @@ -896,9 +927,12 @@ static int auth_callback(
|
| Tcl_DStringAppendElement(&str, zArg2 ? zArg2 : "");
|
| Tcl_DStringAppendElement(&str, zArg3 ? zArg3 : "");
|
| Tcl_DStringAppendElement(&str, zArg4 ? zArg4 : "");
|
| +#ifdef SQLITE_USER_AUTHENTICATION
|
| + Tcl_DStringAppendElement(&str, zArg5 ? zArg5 : "");
|
| +#endif
|
| rc = Tcl_GlobalEval(pDb->interp, Tcl_DStringValue(&str));
|
| Tcl_DStringFree(&str);
|
| - zReply = Tcl_GetStringResult(pDb->interp);
|
| + zReply = rc==TCL_OK ? Tcl_GetStringResult(pDb->interp) : "SQLITE_DENY";
|
| if( strcmp(zReply,"SQLITE_OK")==0 ){
|
| rc = SQLITE_OK;
|
| }else if( strcmp(zReply,"SQLITE_DENY")==0 ){
|
| @@ -913,26 +947,6 @@ static int auth_callback(
|
| #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()
|
| @@ -947,14 +961,12 @@ 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 ){
|
| + while( 1 ){
|
| if( n+100>nLine ){
|
| nLine = nLine*2 + 100;
|
| zLine = realloc(zLine, nLine);
|
| @@ -966,14 +978,13 @@ static char *local_getline(char *zPrompt, FILE *in){
|
| 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;
|
| + break;
|
| }
|
| }
|
| zLine = realloc( zLine, n+1 );
|
| @@ -994,7 +1005,7 @@ static int DbTransPostCmd(
|
| Tcl_Interp *interp, /* Tcl interpreter */
|
| int result /* Result of evaluating SCRIPT */
|
| ){
|
| - static const char *azEnd[] = {
|
| + static const char *const azEnd[] = {
|
| "RELEASE _tcl_transaction", /* rc==TCL_ERROR, nTransaction!=0 */
|
| "COMMIT", /* rc!=TCL_ERROR, nTransaction==0 */
|
| "ROLLBACK TO _tcl_transaction ; RELEASE _tcl_transaction",
|
| @@ -1012,7 +1023,7 @@ static int DbTransPostCmd(
|
| /* This is a tricky scenario to handle. The most likely cause of an
|
| ** error is that the exec() above was an attempt to commit the
|
| ** top-level transaction that returned SQLITE_BUSY. Or, less likely,
|
| - ** that an IO-error has occured. In either case, throw a Tcl exception
|
| + ** that an IO-error has occurred. In either case, throw a Tcl exception
|
| ** and try to rollback the transaction.
|
| **
|
| ** But it could also be that the user executed one or more BEGIN,
|
| @@ -1020,7 +1031,7 @@ static int DbTransPostCmd(
|
| ** this method's logic. Not clear how this would be best handled.
|
| */
|
| if( rc!=TCL_ERROR ){
|
| - Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), 0);
|
| + Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), (char*)0);
|
| rc = TCL_ERROR;
|
| }
|
| sqlite3_exec(pDb->db, "ROLLBACK", 0, 0, 0);
|
| @@ -1031,6 +1042,27 @@ static int DbTransPostCmd(
|
| }
|
|
|
| /*
|
| +** Unless SQLITE_TEST is defined, this function is a simple wrapper around
|
| +** sqlite3_prepare_v2(). If SQLITE_TEST is defined, then it uses either
|
| +** sqlite3_prepare_v2() or legacy interface sqlite3_prepare(), depending
|
| +** on whether or not the [db_use_legacy_prepare] command has been used to
|
| +** configure the connection.
|
| +*/
|
| +static int dbPrepare(
|
| + SqliteDb *pDb, /* Database object */
|
| + const char *zSql, /* SQL to compile */
|
| + sqlite3_stmt **ppStmt, /* OUT: Prepared statement */
|
| + const char **pzOut /* OUT: Pointer to next SQL statement */
|
| +){
|
| +#ifdef SQLITE_TEST
|
| + if( pDb->bLegacyPrepare ){
|
| + return sqlite3_prepare(pDb->db, zSql, -1, ppStmt, pzOut);
|
| + }
|
| +#endif
|
| + return sqlite3_prepare_v2(pDb->db, zSql, -1, ppStmt, pzOut);
|
| +}
|
| +
|
| +/*
|
| ** Search the cache for a prepared-statement object that implements the
|
| ** first SQL statement in the buffer pointed to by parameter zIn. If
|
| ** no such prepared-statement can be found, allocate and prepare a new
|
| @@ -1057,13 +1089,14 @@ static int dbPrepareAndBind(
|
| int nSql; /* Length of zSql in bytes */
|
| int nVar; /* Number of variables in statement */
|
| int iParm = 0; /* Next free entry in apParm */
|
| + char c;
|
| int i;
|
| Tcl_Interp *interp = pDb->interp;
|
|
|
| *ppPreStmt = 0;
|
|
|
| /* Trim spaces from the start of zSql and calculate the remaining length. */
|
| - while( isspace(zSql[0]) ){ zSql++; }
|
| + while( (c = zSql[0])==' ' || c=='\t' || c=='\r' || c=='\n' ){ zSql++; }
|
| nSql = strlen30(zSql);
|
|
|
| for(pPreStmt = pDb->stmtList; pPreStmt; pPreStmt=pPreStmt->pNext){
|
| @@ -1100,14 +1133,14 @@ static int dbPrepareAndBind(
|
| if( pPreStmt==0 ){
|
| int nByte;
|
|
|
| - if( SQLITE_OK!=sqlite3_prepare_v2(pDb->db, zSql, -1, &pStmt, pzOut) ){
|
| - Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db)));
|
| + if( SQLITE_OK!=dbPrepare(pDb, zSql, &pStmt, pzOut) ){
|
| + Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3_errmsg(pDb->db), -1));
|
| return TCL_ERROR;
|
| }
|
| if( pStmt==0 ){
|
| if( SQLITE_OK!=sqlite3_errcode(pDb->db) ){
|
| /* A compile-time error in the statement. */
|
| - Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db)));
|
| + Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3_errmsg(pDb->db), -1));
|
| return TCL_ERROR;
|
| }else{
|
| /* The statement was a no-op. Continue to the next statement
|
| @@ -1124,9 +1157,17 @@ static int dbPrepareAndBind(
|
| memset(pPreStmt, 0, nByte);
|
|
|
| pPreStmt->pStmt = pStmt;
|
| - pPreStmt->nSql = (*pzOut - zSql);
|
| + pPreStmt->nSql = (int)(*pzOut - zSql);
|
| pPreStmt->zSql = sqlite3_sql(pStmt);
|
| pPreStmt->apParm = (Tcl_Obj **)&pPreStmt[1];
|
| +#ifdef SQLITE_TEST
|
| + if( pPreStmt->zSql==0 ){
|
| + char *zCopy = Tcl_Alloc(pPreStmt->nSql + 1);
|
| + memcpy(zCopy, zSql, pPreStmt->nSql);
|
| + zCopy[pPreStmt->nSql] = '\0';
|
| + pPreStmt->zSql = zCopy;
|
| + }
|
| +#endif
|
| }
|
| assert( pPreStmt );
|
| assert( strlen30(pPreStmt->zSql)==pPreStmt->nSql );
|
| @@ -1180,7 +1221,6 @@ static int dbPrepareAndBind(
|
| return TCL_OK;
|
| }
|
|
|
| -
|
| /*
|
| ** Release a statement reference obtained by calling dbPrepareAndBind().
|
| ** There should be exactly one call to this function for each call to
|
| @@ -1205,8 +1245,7 @@ static void dbReleaseStmt(
|
|
|
| if( pDb->maxStmt<=0 || discard ){
|
| /* If the cache is turned off, deallocated the statement */
|
| - sqlite3_finalize(pPreStmt->pStmt);
|
| - Tcl_Free((char *)pPreStmt);
|
| + dbFreeStmt(pPreStmt);
|
| }else{
|
| /* Add the prepared statement to the beginning of the cache list. */
|
| pPreStmt->pNext = pDb->stmtList;
|
| @@ -1226,11 +1265,11 @@ static void dbReleaseStmt(
|
| /* If we have too many statement in cache, remove the surplus from
|
| ** the end of the cache list. */
|
| while( pDb->nStmt>pDb->maxStmt ){
|
| - sqlite3_finalize(pDb->stmtLast->pStmt);
|
| - pDb->stmtLast = pDb->stmtLast->pPrev;
|
| - Tcl_Free((char*)pDb->stmtLast->pNext);
|
| + SqlPreparedStmt *pLast = pDb->stmtLast;
|
| + pDb->stmtLast = pLast->pPrev;
|
| pDb->stmtLast->pNext = 0;
|
| pDb->nStmt--;
|
| + dbFreeStmt(pLast);
|
| }
|
| }
|
| }
|
| @@ -1320,7 +1359,7 @@ static void dbEvalRowInfo(
|
| if( nCol>0 && (papColName || p->pArray) ){
|
| apColName = (Tcl_Obj**)Tcl_Alloc( sizeof(Tcl_Obj*)*nCol );
|
| for(i=0; i<nCol; i++){
|
| - apColName[i] = dbTextToObj(sqlite3_column_name(pStmt,i));
|
| + apColName[i] = Tcl_NewStringObj(sqlite3_column_name(pStmt,i), -1);
|
| Tcl_IncrRefCount(apColName[i]);
|
| }
|
| p->apColName = apColName;
|
| @@ -1363,9 +1402,12 @@ static void dbEvalRowInfo(
|
| ** no further rows available. This is similar to SQLITE_DONE.
|
| */
|
| static int dbEvalStep(DbEvalContext *p){
|
| + const char *zPrevSql = 0; /* Previous value of p->zSql */
|
| +
|
| while( p->zSql[0] || p->pPreStmt ){
|
| int rc;
|
| if( p->pPreStmt==0 ){
|
| + zPrevSql = (p->zSql==zPrevSql ? 0 : p->zSql);
|
| rc = dbPrepareAndBind(p->pDb, p->zSql, &p->zSql, &p->pPreStmt);
|
| if( rc!=TCL_OK ) return rc;
|
| }else{
|
| @@ -1392,8 +1434,20 @@ static int dbEvalStep(DbEvalContext *p){
|
| if( rcs!=SQLITE_OK ){
|
| /* If a run-time error occurs, report the error and stop reading
|
| ** the SQL. */
|
| - Tcl_SetObjResult(pDb->interp, dbTextToObj(sqlite3_errmsg(pDb->db)));
|
| dbReleaseStmt(pDb, pPreStmt, 1);
|
| +#if SQLITE_TEST
|
| + if( p->pDb->bLegacyPrepare && rcs==SQLITE_SCHEMA && zPrevSql ){
|
| + /* If the runtime error was an SQLITE_SCHEMA, and the database
|
| + ** handle is configured to use the legacy sqlite3_prepare()
|
| + ** interface, retry prepare()/step() on the same SQL statement.
|
| + ** This only happens once. If there is a second SQLITE_SCHEMA
|
| + ** error, the error will be returned to the caller. */
|
| + p->zSql = zPrevSql;
|
| + continue;
|
| + }
|
| +#endif
|
| + Tcl_SetObjResult(pDb->interp,
|
| + Tcl_NewStringObj(sqlite3_errmsg(pDb->db), -1));
|
| return TCL_ERROR;
|
| }else{
|
| dbReleaseStmt(pDb, pPreStmt, 0);
|
| @@ -1441,7 +1495,7 @@ static Tcl_Obj *dbEvalColumnValue(DbEvalContext *p, int iCol){
|
| case SQLITE_INTEGER: {
|
| sqlite_int64 v = sqlite3_column_int64(pStmt, iCol);
|
| if( v>=-2147483647 && v<=2147483647 ){
|
| - return Tcl_NewIntObj(v);
|
| + return Tcl_NewIntObj((int)v);
|
| }else{
|
| return Tcl_NewWideIntObj(v);
|
| }
|
| @@ -1450,11 +1504,11 @@ static Tcl_Obj *dbEvalColumnValue(DbEvalContext *p, int iCol){
|
| return Tcl_NewDoubleObj(sqlite3_column_double(pStmt, iCol));
|
| }
|
| case SQLITE_NULL: {
|
| - return dbTextToObj(p->pDb->zNull);
|
| + return Tcl_NewStringObj(p->pDb->zNull, -1);
|
| }
|
| }
|
|
|
| - return dbTextToObj((char *)sqlite3_column_text(pStmt, iCol));
|
| + return Tcl_NewStringObj((char*)sqlite3_column_text(pStmt, iCol), -1);
|
| }
|
|
|
| /*
|
| @@ -1483,9 +1537,9 @@ static int DbUseNre(void){
|
| */
|
| # define SQLITE_TCL_NRE 0
|
| # define DbUseNre() 0
|
| -# define Tcl_NRAddCallback(a,b,c,d,e,f) 0
|
| +# define Tcl_NRAddCallback(a,b,c,d,e,f) (void)0
|
| # define Tcl_NREvalObj(a,b,c) 0
|
| -# define Tcl_NRCreateCommand(a,b,c,d,e,f) 0
|
| +# define Tcl_NRCreateCommand(a,b,c,d,e,f) (void)0
|
| #endif
|
|
|
| /*
|
| @@ -1627,7 +1681,8 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| */
|
| case DB_AUTHORIZER: {
|
| #ifdef SQLITE_OMIT_AUTHORIZATION
|
| - Tcl_AppendResult(interp, "authorization not available in this build", 0);
|
| + Tcl_AppendResult(interp, "authorization not available in this build",
|
| + (char*)0);
|
| return TCL_ERROR;
|
| #else
|
| if( objc>3 ){
|
| @@ -1635,7 +1690,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| return TCL_ERROR;
|
| }else if( objc==2 ){
|
| if( pDb->zAuth ){
|
| - Tcl_AppendResult(interp, pDb->zAuth, 0);
|
| + Tcl_AppendResult(interp, pDb->zAuth, (char*)0);
|
| }
|
| }else{
|
| char *zAuth;
|
| @@ -1651,8 +1706,11 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| pDb->zAuth = 0;
|
| }
|
| if( pDb->zAuth ){
|
| + typedef int (*sqlite3_auth_cb)(
|
| + void*,int,const char*,const char*,
|
| + const char*,const char*);
|
| pDb->interp = interp;
|
| - sqlite3_set_authorizer(pDb->db, auth_callback, pDb);
|
| + sqlite3_set_authorizer(pDb->db,(sqlite3_auth_cb)auth_callback,pDb);
|
| }else{
|
| sqlite3_set_authorizer(pDb->db, 0, 0);
|
| }
|
| @@ -1721,7 +1779,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| return TCL_ERROR;
|
| }else if( objc==2 ){
|
| if( pDb->zBusy ){
|
| - Tcl_AppendResult(interp, pDb->zBusy, 0);
|
| + Tcl_AppendResult(interp, pDb->zBusy, (char*)0);
|
| }
|
| }else{
|
| char *zBusy;
|
| @@ -1775,7 +1833,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| }else{
|
| if( TCL_ERROR==Tcl_GetIntFromObj(interp, objv[3], &n) ){
|
| Tcl_AppendResult( interp, "cannot convert \"",
|
| - Tcl_GetStringFromObj(objv[3],0), "\" to integer", 0);
|
| + Tcl_GetStringFromObj(objv[3],0), "\" to integer", (char*)0);
|
| return TCL_ERROR;
|
| }else{
|
| if( n<0 ){
|
| @@ -1789,7 +1847,8 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| }
|
| }else{
|
| Tcl_AppendResult( interp, "bad option \"",
|
| - Tcl_GetStringFromObj(objv[2],0), "\": must be flush or size", 0);
|
| + Tcl_GetStringFromObj(objv[2],0), "\": must be flush or size",
|
| + (char*)0);
|
| return TCL_ERROR;
|
| }
|
| break;
|
| @@ -1886,10 +1945,10 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| return TCL_ERROR;
|
| }else if( objc==2 ){
|
| if( pDb->zCommit ){
|
| - Tcl_AppendResult(interp, pDb->zCommit, 0);
|
| + Tcl_AppendResult(interp, pDb->zCommit, (char*)0);
|
| }
|
| }else{
|
| - char *zCommit;
|
| + const char *zCommit;
|
| int len;
|
| if( pDb->zCommit ){
|
| Tcl_Free(pDb->zCommit);
|
| @@ -1962,14 +2021,14 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| char *zSql; /* An SQL statement */
|
| char *zLine; /* A single line of input from the file */
|
| char **azCol; /* zLine[] broken up into columns */
|
| - char *zCommit; /* How to commit changes */
|
| + const char *zCommit; /* How to commit changes */
|
| FILE *in; /* The input file */
|
| int lineno = 0; /* Line number of input file */
|
| char zLineNum[80]; /* Line number print buffer */
|
| Tcl_Obj *pResult; /* interp result */
|
|
|
| - char *zSep;
|
| - char *zNull;
|
| + const char *zSep;
|
| + const char *zNull;
|
| if( objc<5 || objc>7 ){
|
| Tcl_WrongNumArgs(interp, 2, objv,
|
| "CONFLICT-ALGORITHM TABLE FILENAME ?SEPARATOR? ?NULLINDICATOR?");
|
| @@ -1991,7 +2050,8 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| nSep = strlen30(zSep);
|
| nNull = strlen30(zNull);
|
| if( nSep==0 ){
|
| - Tcl_AppendResult(interp,"Error: non-null separator required for copy",0);
|
| + Tcl_AppendResult(interp,"Error: non-null separator required for copy",
|
| + (char*)0);
|
| return TCL_ERROR;
|
| }
|
| if(strcmp(zConflict, "rollback") != 0 &&
|
| @@ -2001,19 +2061,19 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| strcmp(zConflict, "replace" ) != 0 ) {
|
| Tcl_AppendResult(interp, "Error: \"", zConflict,
|
| "\", conflict-algorithm must be one of: rollback, "
|
| - "abort, fail, ignore, or replace", 0);
|
| + "abort, fail, ignore, or replace", (char*)0);
|
| return TCL_ERROR;
|
| }
|
| zSql = sqlite3_mprintf("SELECT * FROM '%q'", zTable);
|
| if( zSql==0 ){
|
| - Tcl_AppendResult(interp, "Error: no such table: ", zTable, 0);
|
| + Tcl_AppendResult(interp, "Error: no such table: ", zTable, (char*)0);
|
| return TCL_ERROR;
|
| }
|
| nByte = strlen30(zSql);
|
| rc = sqlite3_prepare(pDb->db, zSql, -1, &pStmt, 0);
|
| sqlite3_free(zSql);
|
| if( rc ){
|
| - Tcl_AppendResult(interp, "Error: ", sqlite3_errmsg(pDb->db), 0);
|
| + Tcl_AppendResult(interp, "Error: ", sqlite3_errmsg(pDb->db), (char*)0);
|
| nCol = 0;
|
| }else{
|
| nCol = sqlite3_column_count(pStmt);
|
| @@ -2024,7 +2084,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| }
|
| zSql = malloc( nByte + 50 + nCol*2 );
|
| if( zSql==0 ) {
|
| - Tcl_AppendResult(interp, "Error: can't malloc()", 0);
|
| + Tcl_AppendResult(interp, "Error: can't malloc()", (char*)0);
|
| return TCL_ERROR;
|
| }
|
| sqlite3_snprintf(nByte+50, zSql, "INSERT OR %q INTO '%q' VALUES(?",
|
| @@ -2039,7 +2099,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| rc = sqlite3_prepare(pDb->db, zSql, -1, &pStmt, 0);
|
| free(zSql);
|
| if( rc ){
|
| - Tcl_AppendResult(interp, "Error: ", sqlite3_errmsg(pDb->db), 0);
|
| + Tcl_AppendResult(interp, "Error: ", sqlite3_errmsg(pDb->db), (char*)0);
|
| sqlite3_finalize(pStmt);
|
| return TCL_ERROR;
|
| }
|
| @@ -2051,7 +2111,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| }
|
| azCol = malloc( sizeof(azCol[0])*(nCol+1) );
|
| if( azCol==0 ) {
|
| - Tcl_AppendResult(interp, "Error: can't malloc()", 0);
|
| + Tcl_AppendResult(interp, "Error: can't malloc()", (char*)0);
|
| fclose(in);
|
| return TCL_ERROR;
|
| }
|
| @@ -2059,7 +2119,6 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| zCommit = "COMMIT";
|
| while( (zLine = local_getline(0, in))!=0 ){
|
| char *z;
|
| - i = 0;
|
| lineno++;
|
| azCol[0] = zLine;
|
| for(i=0, z=zLine; *z; z++){
|
| @@ -2080,7 +2139,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| sqlite3_snprintf(nErr, zErr,
|
| "Error: %s line %d: expected %d columns of data but found %d",
|
| zFile, lineno, nCol, i+1);
|
| - Tcl_AppendResult(interp, zErr, 0);
|
| + Tcl_AppendResult(interp, zErr, (char*)0);
|
| free(zErr);
|
| }
|
| zCommit = "ROLLBACK";
|
| @@ -2100,7 +2159,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| rc = sqlite3_reset(pStmt);
|
| free(zLine);
|
| if( rc!=SQLITE_OK ){
|
| - Tcl_AppendResult(interp,"Error: ", sqlite3_errmsg(pDb->db), 0);
|
| + Tcl_AppendResult(interp,"Error: ", sqlite3_errmsg(pDb->db), (char*)0);
|
| zCommit = "ROLLBACK";
|
| break;
|
| }
|
| @@ -2118,7 +2177,8 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| }else{
|
| /* failure, append lineno where failed */
|
| sqlite3_snprintf(sizeof(zLineNum), zLineNum,"%d",lineno);
|
| - Tcl_AppendResult(interp,", failed while processing line: ",zLineNum,0);
|
| + Tcl_AppendResult(interp,", failed while processing line: ",zLineNum,
|
| + (char*)0);
|
| rc = TCL_ERROR;
|
| }
|
| break;
|
| @@ -2144,7 +2204,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| break;
|
| #else
|
| Tcl_AppendResult(interp, "extension loading is turned off at compile-time",
|
| - 0);
|
| + (char*)0);
|
| return TCL_ERROR;
|
| #endif
|
| }
|
| @@ -2180,6 +2240,8 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| if( choice==DB_ONECOLUMN ){
|
| if( rc==TCL_OK ){
|
| Tcl_SetObjResult(interp, dbEvalColumnValue(&sEval, 0));
|
| + }else if( rc==TCL_BREAK ){
|
| + Tcl_ResetResult(interp);
|
| }
|
| }else if( rc==TCL_BREAK || rc==TCL_OK ){
|
| Tcl_SetObjResult(interp, Tcl_NewBooleanObj(rc==TCL_OK));
|
| @@ -2300,14 +2362,14 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| */
|
| case DB_INCRBLOB: {
|
| #ifdef SQLITE_OMIT_INCRBLOB
|
| - Tcl_AppendResult(interp, "incrblob not available in this build", 0);
|
| + Tcl_AppendResult(interp, "incrblob not available in this build", (char*)0);
|
| return TCL_ERROR;
|
| #else
|
| int isReadonly = 0;
|
| const char *zDb = "main";
|
| const char *zTable;
|
| const char *zColumn;
|
| - sqlite_int64 iRow;
|
| + Tcl_WideInt iRow;
|
|
|
| /* Check for the -readonly option */
|
| if( objc>3 && strcmp(Tcl_GetString(objv[2]), "-readonly")==0 ){
|
| @@ -2328,7 +2390,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
|
|
| if( rc==TCL_OK ){
|
| rc = createIncrblobChannel(
|
| - interp, pDb, zDb, zTable, zColumn, iRow, isReadonly
|
| + interp, pDb, zDb, zTable, zColumn, (sqlite3_int64)iRow, isReadonly
|
| );
|
| }
|
| #endif
|
| @@ -2367,13 +2429,13 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| }
|
| if( zNull && len>0 ){
|
| pDb->zNull = Tcl_Alloc( len + 1 );
|
| - strncpy(pDb->zNull, zNull, len);
|
| + memcpy(pDb->zNull, zNull, len);
|
| pDb->zNull[len] = '\0';
|
| }else{
|
| pDb->zNull = 0;
|
| }
|
| }
|
| - Tcl_SetObjResult(interp, dbTextToObj(pDb->zNull));
|
| + Tcl_SetObjResult(interp, Tcl_NewStringObj(pDb->zNull, -1));
|
| break;
|
| }
|
|
|
| @@ -2407,7 +2469,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| case DB_PROGRESS: {
|
| if( objc==2 ){
|
| if( pDb->zProgress ){
|
| - Tcl_AppendResult(interp, pDb->zProgress, 0);
|
| + Tcl_AppendResult(interp, pDb->zProgress, (char*)0);
|
| }
|
| }else if( objc==4 ){
|
| char *zProgress;
|
| @@ -2453,7 +2515,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| return TCL_ERROR;
|
| }else if( objc==2 ){
|
| if( pDb->zProfile ){
|
| - Tcl_AppendResult(interp, pDb->zProfile, 0);
|
| + Tcl_AppendResult(interp, pDb->zProfile, (char*)0);
|
| }
|
| }else{
|
| char *zProfile;
|
| @@ -2486,17 +2548,19 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| ** Change the encryption key on the currently open database.
|
| */
|
| case DB_REKEY: {
|
| +#ifdef SQLITE_HAS_CODEC
|
| int nKey;
|
| void *pKey;
|
| +#endif
|
| if( objc!=3 ){
|
| Tcl_WrongNumArgs(interp, 2, objv, "KEY");
|
| return TCL_ERROR;
|
| }
|
| - pKey = Tcl_GetByteArrayFromObj(objv[2], &nKey);
|
| #ifdef SQLITE_HAS_CODEC
|
| + pKey = Tcl_GetByteArrayFromObj(objv[2], &nKey);
|
| rc = sqlite3_rekey(pDb->db, pKey, nKey);
|
| if( rc ){
|
| - Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0);
|
| + Tcl_AppendResult(interp, sqlite3_errstr(rc), (char*)0);
|
| rc = TCL_ERROR;
|
| }
|
| #endif
|
| @@ -2637,7 +2701,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| return TCL_ERROR;
|
| }else if( objc==2 ){
|
| if( pDb->zTrace ){
|
| - Tcl_AppendResult(interp, pDb->zTrace, 0);
|
| + Tcl_AppendResult(interp, pDb->zTrace, (char*)0);
|
| }
|
| }else{
|
| char *zTrace;
|
| @@ -2708,7 +2772,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| rc = sqlite3_exec(pDb->db, zBegin, 0, 0, 0);
|
| pDb->disableAuth--;
|
| if( rc!=SQLITE_OK ){
|
| - Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), 0);
|
| + Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), (char*)0);
|
| return TCL_ERROR;
|
| }
|
| pDb->nTransaction++;
|
| @@ -2720,7 +2784,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| ** or savepoint. */
|
| if( DbUseNre() ){
|
| Tcl_NRAddCallback(interp, DbTransPostCmd, cd, 0, 0, 0);
|
| - Tcl_NREvalObj(interp, pScript, 0);
|
| + (void)Tcl_NREvalObj(interp, pScript, 0);
|
| }else{
|
| rc = DbTransPostCmd(&cd, interp, Tcl_EvalObjEx(interp, pScript, 0));
|
| }
|
| @@ -2732,7 +2796,8 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| */
|
| case DB_UNLOCK_NOTIFY: {
|
| #ifndef SQLITE_ENABLE_UNLOCK_NOTIFY
|
| - Tcl_AppendResult(interp, "unlock_notify not available in this build", 0);
|
| + Tcl_AppendResult(interp, "unlock_notify not available in this build",
|
| + (char*)0);
|
| rc = TCL_ERROR;
|
| #else
|
| if( objc!=2 && objc!=3 ){
|
| @@ -2755,7 +2820,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| }
|
|
|
| if( sqlite3_unlock_notify(pDb->db, xNotify, pNotifyArg) ){
|
| - Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), 0);
|
| + Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), (char*)0);
|
| rc = TCL_ERROR;
|
| }
|
| }
|
| @@ -2856,8 +2921,6 @@ static int DbObjCmdAdaptor(
|
| */
|
| 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;
|
| int i;
|
| @@ -2865,6 +2928,11 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| const char *zVfs = 0;
|
| int flags;
|
| Tcl_DString translatedFilename;
|
| +#ifdef SQLITE_HAS_CODEC
|
| + void *pKey = 0;
|
| + int nKey = 0;
|
| +#endif
|
| + int rc;
|
|
|
| /* In normal use, each TCL interpreter runs in a single thread. So
|
| ** by default, we can turn of mutexing on SQLite database connections.
|
| @@ -2881,14 +2949,14 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| if( objc==2 ){
|
| zArg = Tcl_GetStringFromObj(objv[1], 0);
|
| if( strcmp(zArg,"-version")==0 ){
|
| - Tcl_AppendResult(interp,sqlite3_version,0);
|
| + Tcl_AppendResult(interp,sqlite3_libversion(), (char*)0);
|
| return TCL_OK;
|
| }
|
| if( strcmp(zArg,"-has-codec")==0 ){
|
| #ifdef SQLITE_HAS_CODEC
|
| - Tcl_AppendResult(interp,"1",0);
|
| + Tcl_AppendResult(interp,"1",(char*)0);
|
| #else
|
| - Tcl_AppendResult(interp,"0",0);
|
| + Tcl_AppendResult(interp,"0",(char*)0);
|
| #endif
|
| return TCL_OK;
|
| }
|
| @@ -2896,7 +2964,9 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| for(i=3; i+1<objc; i+=2){
|
| zArg = Tcl_GetString(objv[i]);
|
| if( strcmp(zArg,"-key")==0 ){
|
| +#ifdef SQLITE_HAS_CODEC
|
| pKey = Tcl_GetByteArrayFromObj(objv[i+1], &nKey);
|
| +#endif
|
| }else if( strcmp(zArg, "-vfs")==0 ){
|
| zVfs = Tcl_GetString(objv[i+1]);
|
| }else if( strcmp(zArg, "-readonly")==0 ){
|
| @@ -2926,7 +2996,7 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| }else{
|
| flags &= ~SQLITE_OPEN_NOMUTEX;
|
| }
|
| - }else if( strcmp(zArg, "-fullmutex")==0 ){
|
| + }else if( strcmp(zArg, "-fullmutex")==0 ){
|
| int b;
|
| if( Tcl_GetBooleanFromObj(interp, objv[i+1], &b) ) return TCL_ERROR;
|
| if( b ){
|
| @@ -2935,6 +3005,14 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| }else{
|
| flags &= ~SQLITE_OPEN_FULLMUTEX;
|
| }
|
| + }else if( strcmp(zArg, "-uri")==0 ){
|
| + int b;
|
| + if( Tcl_GetBooleanFromObj(interp, objv[i+1], &b) ) return TCL_ERROR;
|
| + if( b ){
|
| + flags |= SQLITE_OPEN_URI;
|
| + }else{
|
| + flags &= ~SQLITE_OPEN_URI;
|
| + }
|
| }else{
|
| Tcl_AppendResult(interp, "unknown option: ", zArg, (char*)0);
|
| return TCL_ERROR;
|
| @@ -2943,7 +3021,7 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| if( objc<3 || (objc&1)!=1 ){
|
| Tcl_WrongNumArgs(interp, 1, objv,
|
| "HANDLE FILENAME ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN?"
|
| - " ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN?"
|
| + " ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?"
|
| #ifdef SQLITE_HAS_CODEC
|
| " ?-key CODECKEY?"
|
| #endif
|
| @@ -2953,18 +3031,22 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| zErrMsg = 0;
|
| p = (SqliteDb*)Tcl_Alloc( sizeof(*p) );
|
| if( p==0 ){
|
| - Tcl_SetResult(interp, "malloc failed", TCL_STATIC);
|
| + Tcl_SetResult(interp, (char *)"malloc failed", TCL_STATIC);
|
| return TCL_ERROR;
|
| }
|
| memset(p, 0, sizeof(*p));
|
| zFile = Tcl_GetStringFromObj(objv[2], 0);
|
| zFile = Tcl_TranslateFileName(interp, zFile, &translatedFilename);
|
| - sqlite3_open_v2(zFile, &p->db, flags, zVfs);
|
| + rc = sqlite3_open_v2(zFile, &p->db, flags, zVfs);
|
| Tcl_DStringFree(&translatedFilename);
|
| - if( SQLITE_OK!=sqlite3_errcode(p->db) ){
|
| - zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(p->db));
|
| - sqlite3_close(p->db);
|
| - p->db = 0;
|
| + if( p->db ){
|
| + if( SQLITE_OK!=sqlite3_errcode(p->db) ){
|
| + zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(p->db));
|
| + sqlite3_close(p->db);
|
| + p->db = 0;
|
| + }
|
| + }else{
|
| + zErrMsg = sqlite3_mprintf("%s", sqlite3_errstr(rc));
|
| }
|
| #ifdef SQLITE_HAS_CODEC
|
| if( p->db ){
|
| @@ -2995,7 +3077,7 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| */
|
| #ifndef USE_TCL_STUBS
|
| # undef Tcl_InitStubs
|
| -# define Tcl_InitStubs(a,b,c)
|
| +# define Tcl_InitStubs(a,b,c) TCL_VERSION
|
| #endif
|
|
|
| /*
|
| @@ -3019,38 +3101,33 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
| ** The EXTERN macros are required by TCL in order to work on windows.
|
| */
|
| 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);
|
| -
|
| + int rc = Tcl_InitStubs(interp, "8.4", 0)==0 ? TCL_ERROR : TCL_OK;
|
| + if( rc==TCL_OK ){
|
| + Tcl_CreateObjCommand(interp, "sqlite3", (Tcl_ObjCmdProc*)DbMain, 0, 0);
|
| #ifndef SQLITE_3_SUFFIX_ONLY
|
| - /* The "sqlite" alias is undocumented. It is here only to support
|
| - ** legacy scripts. All new scripts should use only the "sqlite3"
|
| - ** command.
|
| - */
|
| - Tcl_CreateObjCommand(interp, "sqlite", (Tcl_ObjCmdProc*)DbMain, 0, 0);
|
| + /* The "sqlite" alias is undocumented. It is here only to support
|
| + ** legacy scripts. All new scripts should use only the "sqlite3"
|
| + ** command. */
|
| + Tcl_CreateObjCommand(interp, "sqlite", (Tcl_ObjCmdProc*)DbMain, 0, 0);
|
| #endif
|
| -
|
| - return TCL_OK;
|
| + rc = Tcl_PkgProvide(interp, "sqlite3", PACKAGE_VERSION);
|
| + }
|
| + return rc;
|
| }
|
| 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; }
|
| EXTERN int Sqlite3_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }
|
| EXTERN int Tclsqlite3_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }
|
| -EXTERN int Sqlite3_SafeUnload(Tcl_Interp *interp, int flags){ return TCL_OK; }
|
| -EXTERN int Tclsqlite3_SafeUnload(Tcl_Interp *interp, int flags){ return TCL_OK;}
|
|
|
| +/* Because it accesses the file-system and uses persistent state, SQLite
|
| +** is not considered appropriate for safe interpreters. Hence, we deliberately
|
| +** omit the _SafeInit() interfaces.
|
| +*/
|
|
|
| #ifndef SQLITE_3_SUFFIX_ONLY
|
| int Sqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
|
| int Tclsqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
|
| -int Sqlite_SafeInit(Tcl_Interp *interp){ return TCL_OK; }
|
| -int Tclsqlite_SafeInit(Tcl_Interp *interp){ return TCL_OK; }
|
| int Sqlite_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }
|
| int Tclsqlite_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }
|
| -int Sqlite_SafeUnload(Tcl_Interp *interp, int flags){ return TCL_OK; }
|
| -int Tclsqlite_SafeUnload(Tcl_Interp *interp, int flags){ return TCL_OK;}
|
| #endif
|
|
|
| #ifdef TCLSH
|
| @@ -3309,13 +3386,11 @@ static void MD5Final(unsigned char digest[16], MD5Context *ctx){
|
| byteReverse(ctx->in, 14);
|
|
|
| /* Append length in bits and transform */
|
| - ((uint32 *)ctx->in)[ 14 ] = ctx->bits[0];
|
| - ((uint32 *)ctx->in)[ 15 ] = ctx->bits[1];
|
| + memcpy(ctx->in + 14*4, ctx->bits, 8);
|
|
|
| MD5Transform(ctx->buf, (uint32 *)ctx->in);
|
| byteReverse((unsigned char *)ctx->buf, 4);
|
| memcpy(digest, ctx->buf, 16);
|
| - memset(ctx, 0, sizeof(ctx)); /* In case it is sensitive */
|
| }
|
|
|
| /*
|
| @@ -3363,7 +3438,7 @@ static int md5_cmd(void*cd, Tcl_Interp *interp, int argc, const char **argv){
|
|
|
| if( argc!=2 ){
|
| Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
|
| - " TEXT\"", 0);
|
| + " TEXT\"", (char*)0);
|
| return TCL_ERROR;
|
| }
|
| MD5Init(&ctx);
|
| @@ -3388,19 +3463,19 @@ static int md5file_cmd(void*cd, Tcl_Interp*interp, int argc, const char **argv){
|
|
|
| if( argc!=2 ){
|
| Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
|
| - " FILENAME\"", 0);
|
| + " FILENAME\"", (char*)0);
|
| return TCL_ERROR;
|
| }
|
| in = fopen(argv[1],"rb");
|
| if( in==0 ){
|
| Tcl_AppendResult(interp,"unable to open file \"", argv[1],
|
| - "\" for reading", 0);
|
| + "\" for reading", (char*)0);
|
| return TCL_ERROR;
|
| }
|
| MD5Init(&ctx);
|
| for(;;){
|
| int n;
|
| - n = fread(zBuf, 1, sizeof(zBuf), in);
|
| + n = (int)fread(zBuf, 1, sizeof(zBuf), in);
|
| if( n<=0 ) break;
|
| MD5Update(&ctx, (unsigned char*)zBuf, (unsigned)n);
|
| }
|
| @@ -3446,7 +3521,7 @@ static void md5step(sqlite3_context *context, int argc, sqlite3_value **argv){
|
| for(i=0; i<argc; i++){
|
| const char *zData = (char*)sqlite3_value_text(argv[i]);
|
| if( zData ){
|
| - MD5Update(p, (unsigned char*)zData, strlen(zData));
|
| + MD5Update(p, (unsigned char*)zData, (int)strlen(zData));
|
| }
|
| }
|
| }
|
| @@ -3475,33 +3550,34 @@ int Md5_Register(sqlite3 *db){
|
| ** the TCL interpreter reads and evaluates that file.
|
| */
|
| #if TCLSH==1
|
| -static 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"
|
| +static const char *tclsh_main_loop(void){
|
| + static const 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"
|
| - "set line {}\n"
|
| - "} else {\n"
|
| - "append line \\n\n"
|
| "}\n"
|
| - "}\n"
|
| -;
|
| + ;
|
| + return zMainloop;
|
| +}
|
| #endif
|
| #if TCLSH==2
|
| -static char zMainloop[] =
|
| -#include "spaceanal_tcl.h"
|
| -;
|
| +static const char *tclsh_main_loop(void);
|
| #endif
|
|
|
| #ifdef SQLITE_TEST
|
| @@ -3527,6 +3603,44 @@ static int init_all_cmd(
|
| init_all(slave);
|
| return TCL_OK;
|
| }
|
| +
|
| +/*
|
| +** Tclcmd: db_use_legacy_prepare DB BOOLEAN
|
| +**
|
| +** The first argument to this command must be a database command created by
|
| +** [sqlite3]. If the second argument is true, then the handle is configured
|
| +** to use the sqlite3_prepare_v2() function to prepare statements. If it
|
| +** is false, sqlite3_prepare().
|
| +*/
|
| +static int db_use_legacy_prepare_cmd(
|
| + ClientData cd,
|
| + Tcl_Interp *interp,
|
| + int objc,
|
| + Tcl_Obj *CONST objv[]
|
| +){
|
| + Tcl_CmdInfo cmdInfo;
|
| + SqliteDb *pDb;
|
| + int bPrepare;
|
| +
|
| + if( objc!=3 ){
|
| + Tcl_WrongNumArgs(interp, 1, objv, "DB BOOLEAN");
|
| + return TCL_ERROR;
|
| + }
|
| +
|
| + if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){
|
| + Tcl_AppendResult(interp, "no such db: ", Tcl_GetString(objv[1]), (char*)0);
|
| + return TCL_ERROR;
|
| + }
|
| + pDb = (SqliteDb*)cmdInfo.objClientData;
|
| + if( Tcl_GetBooleanFromObj(interp, objv[2], &bPrepare) ){
|
| + return TCL_ERROR;
|
| + }
|
| +
|
| + pDb->bLegacyPrepare = bPrepare;
|
| +
|
| + Tcl_ResetResult(interp);
|
| + return TCL_OK;
|
| +}
|
| #endif
|
|
|
| /*
|
| @@ -3547,6 +3661,17 @@ static void init_all(Tcl_Interp *interp){
|
| Md5_Init(interp);
|
| #endif
|
|
|
| + /* Install the [register_dbstat_vtab] command to access the implementation
|
| + ** of virtual table dbstat (source file test_stat.c). This command is
|
| + ** required for testfixture and sqlite3_analyzer, but not by the production
|
| + ** Tcl extension. */
|
| +#if defined(SQLITE_TEST) || TCLSH==2
|
| + {
|
| + extern int SqlitetestStat_Init(Tcl_Interp*);
|
| + SqlitetestStat_Init(interp);
|
| + }
|
| +#endif
|
| +
|
| #ifdef SQLITE_TEST
|
| {
|
| extern int Sqliteconfig_Init(Tcl_Interp*);
|
| @@ -3570,20 +3695,22 @@ static void init_all(Tcl_Interp *interp){
|
| extern int Sqlitetestschema_Init(Tcl_Interp*);
|
| extern int Sqlitetestsse_Init(Tcl_Interp*);
|
| extern int Sqlitetesttclvar_Init(Tcl_Interp*);
|
| + extern int Sqlitetestfs_Init(Tcl_Interp*);
|
| extern int SqlitetestThread_Init(Tcl_Interp*);
|
| extern int SqlitetestOnefile_Init();
|
| extern int SqlitetestOsinst_Init(Tcl_Interp*);
|
| extern int Sqlitetestbackup_Init(Tcl_Interp*);
|
| extern int Sqlitetestintarray_Init(Tcl_Interp*);
|
| extern int Sqlitetestvfs_Init(Tcl_Interp *);
|
| - extern int SqlitetestStat_Init(Tcl_Interp*);
|
| extern int Sqlitetestrtree_Init(Tcl_Interp*);
|
| extern int Sqlitequota_Init(Tcl_Interp*);
|
| extern int Sqlitemultiplex_Init(Tcl_Interp*);
|
| extern int SqliteSuperlock_Init(Tcl_Interp*);
|
| extern int SqlitetestSyscall_Init(Tcl_Interp*);
|
| - extern int Sqlitetestfuzzer_Init(Tcl_Interp*);
|
| - extern int Sqlitetestwholenumber_Init(Tcl_Interp*);
|
| +
|
| +#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)
|
| + extern int Sqlitetestfts3_Init(Tcl_Interp *interp);
|
| +#endif
|
|
|
| #ifdef SQLITE_ENABLE_ZIPVFS
|
| extern int Zipvfs_Init(Tcl_Interp*);
|
| @@ -3610,22 +3737,29 @@ static void init_all(Tcl_Interp *interp){
|
| Sqlitetest_mutex_Init(interp);
|
| Sqlitetestschema_Init(interp);
|
| Sqlitetesttclvar_Init(interp);
|
| + Sqlitetestfs_Init(interp);
|
| SqlitetestThread_Init(interp);
|
| SqlitetestOnefile_Init(interp);
|
| SqlitetestOsinst_Init(interp);
|
| Sqlitetestbackup_Init(interp);
|
| Sqlitetestintarray_Init(interp);
|
| Sqlitetestvfs_Init(interp);
|
| - SqlitetestStat_Init(interp);
|
| Sqlitetestrtree_Init(interp);
|
| Sqlitequota_Init(interp);
|
| Sqlitemultiplex_Init(interp);
|
| SqliteSuperlock_Init(interp);
|
| SqlitetestSyscall_Init(interp);
|
| - Sqlitetestfuzzer_Init(interp);
|
| - Sqlitetestwholenumber_Init(interp);
|
|
|
| - Tcl_CreateObjCommand(interp,"load_testfixture_extensions",init_all_cmd,0,0);
|
| +#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)
|
| + Sqlitetestfts3_Init(interp);
|
| +#endif
|
| +
|
| + Tcl_CreateObjCommand(
|
| + interp, "load_testfixture_extensions", init_all_cmd, 0, 0
|
| + );
|
| + Tcl_CreateObjCommand(
|
| + interp, "db_use_legacy_prepare", db_use_legacy_prepare_cmd, 0, 0
|
| + );
|
|
|
| #ifdef SQLITE_SSE
|
| Sqlitetestsse_Init(interp);
|
| @@ -3637,18 +3771,29 @@ static void init_all(Tcl_Interp *interp){
|
| #define TCLSH_MAIN main /* Needed to fake out mktclapp */
|
| int TCLSH_MAIN(int argc, char **argv){
|
| Tcl_Interp *interp;
|
| -
|
| +
|
| +#if !defined(_WIN32_WCE)
|
| + if( getenv("BREAK") ){
|
| + fprintf(stderr,
|
| + "attach debugger to process %d and press any key to continue.\n",
|
| + GETPID());
|
| + fgetc(stdin);
|
| + }
|
| +#endif
|
| +
|
| /* Call sqlite3_shutdown() once before doing anything else. This is to
|
| ** test that sqlite3_shutdown() can be safely called by a process before
|
| ** sqlite3_initialize() is. */
|
| sqlite3_shutdown();
|
|
|
| + Tcl_FindExecutable(argv[0]);
|
| + Tcl_SetSystemEncoding(NULL, "utf-8");
|
| + interp = Tcl_CreateInterp();
|
| +
|
| #if TCLSH==2
|
| sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);
|
| #endif
|
| - Tcl_FindExecutable(argv[0]);
|
|
|
| - interp = Tcl_CreateInterp();
|
| init_all(interp);
|
| if( argc>=2 ){
|
| int i;
|
| @@ -3669,7 +3814,7 @@ int TCLSH_MAIN(int argc, char **argv){
|
| }
|
| }
|
| if( TCLSH==2 || argc<=1 ){
|
| - Tcl_GlobalEval(interp, zMainloop);
|
| + Tcl_GlobalEval(interp, tclsh_main_loop());
|
| }
|
| return 0;
|
| }
|
|
|