diff --git a/manifest b/manifest index 9b8f2425ee..547d93a03e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Various\schanges\sto\senable\scompilation\sof\sSQLite\slibrary\sand\scommand\nline\sshell\swith\sthe\sWindows\sCE\scross\scompiler\sfrom\scegcc.sourceforge.net\s(CVS\s4541) -D 2007-11-12T21:09:11 +C Modify\sthe\sTcl\sinterface\sto\suse\ssqlite3_prepare_v2().\s(CVS\s4542) +D 2007-11-13T10:30:25 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7 F Makefile.in 30c7e3ba426ddb253b8ef037d1873425da6009a8 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -125,8 +125,8 @@ F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b F src/pager.c c5ffa55c299663b579fbcb430752c1e79d302c5b F src/pager.h d783e7f184afdc33adff37ba58d4e029bd8793b3 F src/parse.y 9640f5b930b1d0bfd05d7428da6f762305567cbb -F src/pragma.c 363e548dafb52327face8d99757ab56a7b1c1b26 -F src/prepare.c 663284f62a73a48b89f5f4e769e155fefba60384 +F src/pragma.c cb1486e76dbcad757968afc4083d3472032e62b5 +F src/prepare.c ab2374102d8367ad336d160a06cef9a8c96d8964 F src/printf.c 96c8d55315a13fc53cb3754cb15046f3ff891ea2 F src/random.c 4a22746501bf36b0a088c66e38dde5daba6a35da F src/select.c aef87a179e287c4ab864cb927c1e95f5ee66bf45 @@ -137,7 +137,7 @@ F src/sqlite3ext.h a93f59cdee3638dc0c9c086f80df743a4e68c3cb F src/sqliteInt.h 4e6fdeb5630ead97bcec60b941e7a72203c64b9e F src/sqliteLimit.h 15ffe2116746c27ace2b428a26a4fcd6dba6fa65 F src/table.c 1aeb9eab57b4235db86fe15a35dec76fb445a9c4 -F src/tclsqlite.c 8658bb91d32397e289b69445609ffd42d0a922ea +F src/tclsqlite.c c5953aedd61f0c0cb9f75dcd371e2ae10f899813 F src/test1.c 0e6fe5449ef9e7289bcaf904e9e3a2ea20650b32 F src/test2.c 77b34303883b9d722c65a6879bb0163a400e3789 F src/test3.c 73c1fd55d1ece61f295a6b9204fd97a139de86ae @@ -169,8 +169,8 @@ F src/vacuum.c a5e51c77370c1a6445e86d42abfc43867cdd482d F src/vdbe.c 791d056da2c264c2cfed6e2150852926845875e5 F src/vdbe.h 856360de71d4bdda71fbb534087668667924e41a F src/vdbeInt.h 630145b9bfaa19190ab491f52658a7db550f2247 -F src/vdbeapi.c 1795d8412b6464a59dc4c940803cf53f3d21259c -F src/vdbeaux.c 7bb91382da8f4e904650ed4a393f7ae83bee8669 +F src/vdbeapi.c eecea7fa87e20664acf270f17c6f397421e9344b +F src/vdbeaux.c 4b6fb200f3f35fb5983f39ee8527025a372aaa88 F src/vdbeblob.c 82f51cdf9b0c0af729732fde48c824e498c0a1ca F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6 F src/vdbemem.c 123994fcd344993d2fb050a83b91b341bbbd08b4 @@ -180,7 +180,7 @@ F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/all.test b59d1bd8b0c1d4a08b845e8af48fd43926f01f11 F test/alter.test a87b7933d41c713c53341abe4eb014d0e273119e -F test/alter2.test 489140038c13f4f9c76a0a8243eb1249f44d4ce1 +F test/alter2.test 4e0c502214daa710a0a9d7ec9689a0326b1a4e2a F test/alter3.test 8ce6b9c5605b3cfe7b901f454ecaf174c4f93e31 F test/altermalloc.test 29d4a8400277efb4ba8ffe90804c6dc2fdfbf063 F test/analyze.test 2f55535aa335785db1a2f97d3f3831c16c09f8b0 @@ -191,7 +191,7 @@ F test/attach.test 72529edb04115675894a7399609983ea46b73ba6 F test/attach2.test 099e46a9a753035ff1b8ec0954e18ea50a934df3 F test/attach3.test 7b92dc8e40c1ebca9732ca6f2d3fefbd46f196df F test/attachmalloc.test 56c5e55563dba6d64641ef2f70ce06900df16912 -F test/auth.test 6d98da67f40475ff9eba99b4a74954c123ba1792 +F test/auth.test 74b49b669cb6ca022124838ff957e1e11b1a8002 F test/auth2.test 65ac294b8d52cbdd463f61e77ad0165268373126 F test/autoinc.test 0e67964f4855081e3a325e484adfebaab41f23a1 F test/autovacuum.test 4339e66003b9cf813dd667a83aed2dee27c4c36d @@ -587,7 +587,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5 -P 68a43c99f1b02b8a93bfdcd5c8426b2b4199d68f -R 15eebd2e25d598175fdc22da0e8e2af5 -U chw -Z 30b89c8b53d433ead58916dedc043066 +P 8ad0ab8cb374bd34e47af9e71b2aad9dd9af0d1b +R 7f804fc953f25759b567beb020ffc09d +U danielk1977 +Z de3fed23e51ed80655b9fa7a173fd027 diff --git a/manifest.uuid b/manifest.uuid index a8b086d2dc..d55f803d4b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8ad0ab8cb374bd34e47af9e71b2aad9dd9af0d1b \ No newline at end of file +7bb00c7df672cb8988121f30e3bbdea9ad951603 \ No newline at end of file diff --git a/src/pragma.c b/src/pragma.c index b4d9774c1a..8f503218a0 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** -** $Id: pragma.c,v 1.149 2007/08/31 18:34:59 drh Exp $ +** $Id: pragma.c,v 1.150 2007/11/13 10:30:25 danielk1977 Exp $ */ #include "sqliteInt.h" #include @@ -204,8 +204,15 @@ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){ }else{ db->flags &= ~p->mask; } + + /* Many of the flag-pragmas modify the code generated by the SQL + ** compiler (eg. count_changes). So add an opcode to expire all + ** compiled SQL statements after modifying a pragma value. + */ + sqlite3VdbeAddOp(v, OP_Expire, 0, 0); } } + return 1; } } diff --git a/src/prepare.c b/src/prepare.c index 350e0a3087..ea6a4f42f6 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -13,7 +13,7 @@ ** interface, and routines that contribute to loading the database schema ** from disk. ** -** $Id: prepare.c,v 1.62 2007/10/12 20:42:30 drh Exp $ +** $Id: prepare.c,v 1.63 2007/11/13 10:30:26 danielk1977 Exp $ */ #include "sqliteInt.h" #include @@ -637,6 +637,9 @@ int sqlite3Reprepare(Vdbe *p){ assert( sqlite3_mutex_held(db->mutex) ); rc = sqlite3LockAndPrepare(db, zSql, -1, 0, &pNew, 0); if( rc ){ + if( rc==SQLITE_NOMEM ){ + db->mallocFailed = 1; + } assert( pNew==0 ); return 0; }else{ diff --git a/src/tclsqlite.c b/src/tclsqlite.c index df7f440bd5..6a9434131e 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -12,7 +12,7 @@ ** A TCL Interface to SQLite. Append this file to sqlite3.c and ** compile the whole thing to build a TCL-enabled version of SQLite. ** -** $Id: tclsqlite.c,v 1.205 2007/11/12 17:56:43 drh Exp $ +** $Id: tclsqlite.c,v 1.206 2007/11/13 10:30:26 danielk1977 Exp $ */ #include "tcl.h" #include @@ -886,6 +886,67 @@ static char *local_getline(char *zPrompt, FILE *in){ 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 int +computeColumnNames( + 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; istmtList; len = strlen(zSql); - if( pPreStmt && sqlite3_expired(pPreStmt->pStmt) ){ - flushStmtCache(pDb); - pPreStmt = 0; - } - for(; pPreStmt; pPreStmt=pPreStmt->pNext){ + for(pPreStmt = pDb->stmtList; pPreStmt; pPreStmt=pPreStmt->pNext){ int n = pPreStmt->nSql; if( len>=n && memcmp(pPreStmt->zSql, zSql, n)==0 @@ -1551,7 +1607,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ /* If no prepared statement was found. Compile the SQL text */ if( pStmt==0 ){ - if( SQLITE_OK!=sqlite3_prepare(pDb->db, zSql, -1, &pStmt, &zLeft) ){ + if( SQLITE_OK!=sqlite3_prepare_v2(pDb->db, zSql, -1, &pStmt, &zLeft) ){ Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db))); rc = TCL_ERROR; break; @@ -1625,36 +1681,20 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ } } - /* Compute column names */ - nCol = sqlite3_column_count(pStmt); - if( pScript ){ - apColName = (Tcl_Obj**)Tcl_Alloc( sizeof(Tcl_Obj*)*nCol ); - if( apColName==0 ) break; - for(i=0; idb), TCL_VOLATILE); - }else{ - /* Must flush any cached statements */ - flushStmtCache( pDb ); } break; } diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 89ac82518c..f4f831448f 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -386,14 +386,34 @@ int sqlite3_step(sqlite3_stmt *pStmt){ int cnt = 0; int rc; Vdbe *v = (Vdbe*)pStmt; - sqlite3_mutex_enter(v->db->mutex); + sqlite3 *db = v->db; + sqlite3_mutex_enter(db->mutex); while( (rc = sqlite3Step(v))==SQLITE_SCHEMA && cnt++ < 5 && sqlite3Reprepare(v) ){ sqlite3_reset(pStmt); v->expired = 0; } - sqlite3_mutex_leave(v->db->mutex); + if( rc==SQLITE_SCHEMA && v->zSql && db->pErr ){ + /* This case occurs after failing to recompile an sql statement. + ** The error message from the SQL compiler has already been loaded + ** into the database handle. This block copies the error message + ** from the database handle into the statement and sets the statement + ** program counter to 0 to ensure that when the statement is + ** finalized or reset the parser error message is available via + ** sqlite3_errmsg() and sqlite3_errcode(). + */ + const char *zErr = (const char *)sqlite3_value_text(db->pErr); + sqlite3_free(v->zErrMsg); + if( !db->mallocFailed ){ + v->zErrMsg = sqlite3DbStrDup(db, zErr); + } else { + v->zErrMsg = 0; + v->rc = SQLITE_NOMEM; + } + } + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); return rc; } #endif diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 22215b2070..14f6637755 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1586,6 +1586,8 @@ int sqlite3VdbeReset(Vdbe *p){ ** called), set the database error in this case as well. */ sqlite3Error(db, p->rc, 0); + sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, sqlite3_free); + p->zErrMsg = 0; } /* Reclaim all memory used by the VDBE diff --git a/test/alter2.test b/test/alter2.test index e0c667e44f..3f7142d9d1 100644 --- a/test/alter2.test +++ b/test/alter2.test @@ -13,7 +13,7 @@ # file format change that may be used in the future to implement # "ALTER TABLE ... ADD COLUMN". # -# $Id: alter2.test,v 1.10 2007/10/09 08:29:32 danielk1977 Exp $ +# $Id: alter2.test,v 1.11 2007/11/13 10:30:26 danielk1977 Exp $ # set testdir [file dirname $argv0] @@ -239,9 +239,20 @@ do_test alter2-4.1 { set_file_format 5 } {} do_test alter2-4.2 { - catchsql { - SELECT * FROM sqlite_master; - } + # We have to run two queries here because the Tcl interface uses + # sqlite3_prepare_v2(). In this case, the first query encounters an + # SQLITE_SCHEMA error. Then, when trying to recompile the statement, the + # "unsupported file format" error is encountered. So the error code + # returned is SQLITE_SCHEMA, not SQLITE_ERROR as required by the following + # test case. + # + # When the query is attempted a second time, the same error message is + # returned but the error code is SQLITE_ERROR, because the unsupported + # file format was detected during a call to sqlite3_prepare(), not + # sqlite3_step(). + # + catchsql { SELECT * FROM sqlite_master; } + catchsql { SELECT * FROM sqlite_master; } } {1 {unsupported file format}} do_test alter2-4.3 { sqlite3_errcode $::DB diff --git a/test/auth.test b/test/auth.test index 2614d9a7bf..5e43fbe1bb 100644 --- a/test/auth.test +++ b/test/auth.test @@ -12,7 +12,7 @@ # focus of this script is testing the sqlite3_set_authorizer() API # and related functionality. # -# $Id: auth.test,v 1.38 2007/10/09 08:29:32 danielk1977 Exp $ +# $Id: auth.test,v 1.39 2007/11/13 10:30:26 danielk1977 Exp $ # set testdir [file dirname $argv0] @@ -2121,6 +2121,16 @@ do_test auth-2.8 { catchsql {SELECT ROWID,b,c FROM t2} } {0 {{} 2 33 {} 8 9}} do_test auth-2.9.1 { + # We have to flush the cache here in case the Tcl interface tries to + # reuse a statement compiled with sqlite3_prepare_v2(). In this case, + # the first error encountered is an SQLITE_SCHEMA error. Then, when + # trying to recompile the statement, the authorization error is encountered. + # If we do not flush the cache, the correct error message is returned, but + # the error code is SQLITE_SCHEMA, not SQLITE_ERROR as required by the test + # case after this one. + # + db cache flush + proc auth {code arg1 arg2 arg3 arg4} { if {$code=="SQLITE_READ" && $arg1=="t2" && $arg2=="ROWID"} { return bogus