diff --git a/manifest b/manifest index 4ce5c60c60..1a93546ea2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Sorting\sbug\sfixes.\s\sNow\sonly\s17\stests\sfail.\s(CVS\s1422) -D 2004-05-21T01:29:06 +C Add\snew\ssqlite3_open()\sand\ssqlite3_open16()\sAPIs.\s(CVS\s1423) +D 2004-05-21T01:47:27 F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd @@ -37,7 +37,7 @@ F src/func.c cfbb7096efb58e2857e3b312a8958a12774b625a F src/hash.c 440c2f8cb373ee1b4e13a0988489c7cd95d55b6f F src/hash.h 762d95f1e567664d1eafc1687de755626be962fb F src/insert.c e510d62d23b4de4d901e7ccbbe7833b7fb3b9570 -F src/main.c bb0e84eda9beb447bff109b061a82e6c9b3dc811 +F src/main.c a9ee98262a12454c72741d94da2317119d3a1071 F src/md5.c 8e39fdae6d8776b87558e91dcc94740c9b635a9c F src/os.c ddcda92f7fd71b4513c57c1ec797917f206d504e F src/os.h 6e446a17cbeb6c2ce470683a0bb8d9c63abe8607 @@ -49,11 +49,11 @@ F src/printf.c ef750e8e2398ca7e8b58be991075f08c6a7f0e53 F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3 F src/select.c d77f773165a2690e6e58c0a94dc21b28270695c2 F src/shell.c 0c4662e13bfbfd3d13b066c5859cc97ad2f95d21 -F src/sqlite.h.in 8c000826a517ac7302dc2e1c483e71cd06eaf0de -F src/sqliteInt.h 3f4848eb5b7cd7818943e9f4b924a8601f7ef06a +F src/sqlite.h.in de337e211905c6bd4ad901916f78df28f1467df4 +F src/sqliteInt.h 2e5533ba50106d266cddfb00b2eb3ab6944b8f3e F src/table.c af14284fa36c8d41f6829e3f2819dce07d3e2de2 F src/tclsqlite.c fbf0fac73624ae246551a6c671f1de0235b5faa1 -F src/test1.c 5ba6352c8d63eae9eb98e6ae5bfe24a448b3bcb7 +F src/test1.c c72aed60609038b25c0782ec69b71f33f1157d64 F src/test2.c 6195a1ca2c8d0d2d93644e86da3289b403486872 F src/test3.c 5e4a6d596f982f6f47a5f9f75ede9b4a3b739968 F src/test4.c b3fab9aea7a8940a8a7386ce1c7e2157b09bd296 @@ -71,18 +71,18 @@ F src/vdbeaux.c 51f7d0cc6c515111b11576e2d82f4637156075cd F src/where.c efe5d25fe18cd7381722457898cd863e84097a0c F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242 F test/attach.test cb9b884344e6cfa5e165965d5b1adea679a24c83 -F test/attach2.test 7c388dee63a4c1997695c3d41957f32ce784ac56 +F test/attach2.test 7a722607c1fa37837d3b2717605357d89b86c8b9 F test/auth.test 5c4d95cdaf539c0c236e20ce1f71a93e7dde9185 F test/bigfile.test ea904b853ce2d703b16c5ce90e2b54951bc1ae81 F test/bigrow.test 8ab252dba108f12ad64e337b0f2ff31a807ac578 -F test/bind.test 5d6ac8ab0dbec03ce79284abefa9230726cb9dad +F test/bind.test 4517a8e8296c12f57f5917764cc1029ff567ff4f F test/btree.test 08e4093c78d2bc1d54e27266f8d17fed14751125 F test/btree2.test aa4a6d05b1ea90b1acaf83ba89039dd302a88635 F test/btree4.test 3797b4305694c7af6828675b0f4b1424b8ca30e4 F test/btree5.test 8e5ff32c02e685d36516c6499add9375fe1377f2 F test/btree6.test a5ede6bfbbb2ec8b27e62813612c0f28e8f3e027 -F test/capi2.test ec96e0e235d87b53cbaef3d8e3e0f8ccf32c71ca -F test/capi3.test acc3919c0f37e85ac3561fc33d6abf7183e1aee1 +F test/capi2.test 007f856cc7fe5a9aaeb076d2df9aff92012a0d5e +F test/capi3.test ff3dfacdd07abad140c17eb58b235623c6957322 F test/conflict.test 0911bb2f079046914a6e9c3341b36658c4e2103e F test/copy.test f07ea8d60878da7a67416ab62f78e9706b9d3c45 F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2 @@ -137,7 +137,7 @@ F test/table.test 50e4534552d0385a0e59b3a6d7dde059ced02f83 F test/tableapi.test e0c4cce61e58343caa84dab33fa6823cb35fe1e1 F test/tclsqlite.test a684fc191b81e6cded8a81263663d5a130fbb013 F test/temptable.test a770ba6308d7f7332fce985086b8e06bed6430c2 -F test/tester.tcl 4f7d3ec86d86d9e6ce6939ad6dba4438d8375fba +F test/tester.tcl 8c234ba903a437ce8c8a58f388d120310b54b44c F test/thread1.test 53f050d5be6932d9430df7756edd379366508ff6 F test/threadtest1.c f7f896e62ed46feae1dc411114a48c15a0f82ee2 F test/threadtest2.c d94ca4114fd1504f7e0ae724bcd83d4b40931d86 @@ -150,7 +150,7 @@ F test/types.test e1e0d71c8e65f8aa5d9a36751f4c8cbce6f01f7a F test/types2.test 5d725fcb68dbd032c6d4950d568d75fa33872687 F test/unique.test 0e38d4cc7affeef2527720d1dafd1f6870f02f2b F test/update.test b29bd9061a1150426dab6959806fcc73a41b1217 -F test/vacuum.test a2a44544df719666efb51afbfeb6062fd59a672a +F test/vacuum.test 7b5f504636a13992344871f8155b8557b683232a F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102 F test/version.test 2ba212ba06380e65e476bdf2fcd390e8b05af5a0 F test/view.test 1ee12c6f8f4791a2c0655120d5562a49400cfe53 @@ -195,7 +195,7 @@ F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604 F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4 -P b032b646b72a03e828d732ac22192f992904d79f -R 855c0de9c9913c06ac48c05901c20ce2 -U drh -Z cf8b0e36973f7277ebb2343b2ce02ab9 +P 0736b7e8401f587f8b412602d029ef9bd69425f6 +R 48a2aee2f380542eefb73a0652ba3654 +U danielk1977 +Z 95516270bea0185aee7836097f272d88 diff --git a/manifest.uuid b/manifest.uuid index e83806edae..f5a141590c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0736b7e8401f587f8b412602d029ef9bd69425f6 \ No newline at end of file +307b55006c401f10ec5fa5b12cc7d5ba860f9a46 \ No newline at end of file diff --git a/src/main.c b/src/main.c index 84c4d96edc..186c012b84 100644 --- a/src/main.c +++ b/src/main.c @@ -14,7 +14,7 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: main.c,v 1.178 2004/05/20 22:16:29 drh Exp $ +** $Id: main.c,v 1.179 2004/05/21 01:47:27 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -1055,14 +1055,51 @@ int sqlite3BtreeFactory( return sqlite3BtreeOpen(zFilename, ppBtree, nCache, btree_flags); } +/* +** Return UTF-8 encoded English language explanation of the most recent +** error. +*/ const char *sqlite3_errmsg(sqlite3 *db){ + if( !db ){ + /* If db is NULL, then assume that a malloc() failed during an + ** sqlite3_open() call. + */ + return sqlite3_error_string(SQLITE_NOMEM); + } if( db->zErrMsg ){ return db->zErrMsg; } return sqlite3_error_string(db->errCode); } +/* +** Return UTF-16 encoded English language explanation of the most recent +** error. +*/ const void *sqlite3_errmsg16(sqlite3 *db){ + if( !db ){ + /* If db is NULL, then assume that a malloc() failed during an + ** sqlite3_open() call. We have a static version of the string + ** "out of memory" encoded using UTF-16 just for this purpose. + ** + ** Because all the characters in the string are in the unicode + ** range 0x00-0xFF, if we pad the big-endian string with a + ** zero byte, we can obtain the little-endian string with + ** &big_endian[1]. + */ + static char outOfMemBe[] = { + 0, 'o', 0, 'u', 0, 't', 0, ' ', + 0, 'o', 0, 'f', 0, ' ', + 0, 'm', 0, 'e', 0, 'm', 0, 'o', 0, 'r', 0, 'y', 0, 0, 0 + }; + static char *outOfMemLe = &outOfMemBe[1]; + + if( SQLITE3_BIGENDIAN ){ + return (void *)outOfMemBe; + }else{ + return (void *)outOfMemLe; + } + } if( !db->zErrMsg16 ){ char const *zErr8 = sqlite3_errmsg(db); if( SQLITE3_BIGENDIAN ){ @@ -1212,6 +1249,118 @@ int sqlite3_prepare16( return rc; } +/* +** This routine does the work of opening a database on behalf of +** sqlite3_open() and sqlite3_open16(). The database filename "zFilename" +** is UTF-8 encoded. The fourth argument, "def_enc" is one of the TEXT_* +** macros from sqliteInt.h. If we end up creating a new database file +** (not opening an existing one), the text encoding of the database +** will be set to this value. +*/ +static int openDatabase( + const char *zFilename, /* Database filename UTF-8 encoded */ + sqlite3 **ppDb, /* OUT: Returned database handle */ + const char **options, /* Null terminated list of db options, or null */ + u8 def_enc /* One of TEXT_Utf8, TEXT_Utf16le or TEXT_Utf16be */ +){ + sqlite3 *db; + int rc, i; + char *zErrMsg = 0; + + /* Allocate the sqlite data structure */ + db = sqliteMalloc( sizeof(sqlite) ); + if( db==0 ) goto opendb_out; + db->onError = OE_Default; + db->priorNewRowid = 0; + db->magic = SQLITE_MAGIC_BUSY; + db->nDb = 2; + db->aDb = db->aDbStatic; + /* db->flags |= SQLITE_ShortColNames; */ + sqlite3HashInit(&db->aFunc, SQLITE_HASH_STRING, 1); + sqlite3HashInit(&db->aCollSeq, SQLITE_HASH_STRING, 0); + for(i=0; i<db->nDb; i++){ + sqlite3HashInit(&db->aDb[i].tblHash, SQLITE_HASH_STRING, 0); + sqlite3HashInit(&db->aDb[i].idxHash, SQLITE_HASH_STRING, 0); + sqlite3HashInit(&db->aDb[i].trigHash, SQLITE_HASH_STRING, 0); + sqlite3HashInit(&db->aDb[i].aFKey, SQLITE_HASH_STRING, 1); + } + db->pDfltColl = + sqlite3ChangeCollatingFunction(db, "BINARY", 6, 0, binaryCollatingFunc); + + /* Open the backend database driver */ + if( zFilename[0]==':' && strcmp(zFilename,":memory:")==0 ){ + db->temp_store = 2; + } + rc = sqlite3BtreeFactory(db, zFilename, 0, MAX_PAGES, &db->aDb[0].pBt); + if( rc!=SQLITE_OK ){ + /* FIX ME: sqlite3BtreeFactory() should call sqlite3Error(). */ + sqlite3Error(db, rc, 0); + db->magic = SQLITE_MAGIC_CLOSED; + goto opendb_out; + } + db->aDb[0].zName = "main"; + db->aDb[1].zName = "temp"; + + /* Attempt to read the schema */ + sqlite3RegisterBuiltinFunctions(db); + rc = sqlite3Init(db, &zErrMsg); + if( sqlite3_malloc_failed ){ + sqlite3_close(db); + db = 0; + goto opendb_out; + }else if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){ + sqlite3Error(db, rc, "%s", zErrMsg, 0); + db->magic = SQLITE_MAGIC_CLOSED; + }else{ + db->magic = SQLITE_MAGIC_OPEN; + } + if( zErrMsg ) sqliteFree(zErrMsg); + +opendb_out: + *ppDb = db; + return sqlite3_errcode(db); +} + +/* +** Open a new database handle. +*/ +int sqlite3_open_new( + const char *zFilename, + sqlite3 **ppDb, + const char **options +){ + return openDatabase(zFilename, ppDb, options, TEXT_Utf8); +} + +/* +** Open a new database handle. +*/ +int sqlite3_open16( + const void *zFilename, + sqlite3 **ppDb, + const char **options +){ + char *zFilename8; /* zFilename encoded in UTF-8 instead of UTF-16 */ + int rc; + + assert( ppDb ); + + zFilename8 = sqlite3utf16to8(zFilename, -1); + if( !zFilename8 ){ + *ppDb = 0; + return SQLITE_NOMEM; + } + + if( SQLITE3_BIGENDIAN ){ + rc = openDatabase(zFilename8, ppDb, options, TEXT_Utf16be); + }else{ + rc = openDatabase(zFilename8, ppDb, options, TEXT_Utf16le); + } + + sqliteFree(zFilename8); + return rc; +} + #if 0 diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 777205ee37..123d1268ed 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -12,7 +12,7 @@ ** This header file defines the interface that the SQLite library ** presents to client programs. ** -** @(#) $Id: sqlite.h.in,v 1.66 2004/05/20 11:00:52 danielk1977 Exp $ +** @(#) $Id: sqlite.h.in,v 1.67 2004/05/21 01:47:27 danielk1977 Exp $ */ #ifndef _SQLITE_H_ #define _SQLITE_H_ @@ -596,7 +596,7 @@ int sqlite3_set_authorizer( /* ** Register a function that is called at every invocation of sqlite3_exec() -** or sqlite3_compile(). This function can be used (for example) to generate +** or sqlite3_prepare(). This function can be used (for example) to generate ** a log file of all SQL executed against a database. */ void *sqlite3_trace(sqlite*, void(*xTrace)(void*,const char*), void*); @@ -727,11 +727,11 @@ int sqlite3_finalize(sqlite_vm*, char **pzErrMsg); int sqlite3_reset(sqlite_vm*, char **pzErrMsg); /* -** If the SQL that was handed to sqlite3_compile contains variables that +** If the SQL that was handed to sqlite3_prepare contains variables that ** are represeted in the SQL text by a question mark ('?'). This routine ** is used to assign values to those variables. ** -** The first parameter is a virtual machine obtained from sqlite3_compile(). +** The first parameter is a virtual machine obtained from sqlite3_prepare(). ** The 2nd "idx" parameter determines which variable in the SQL statement ** to bind the value to. The left most '?' is 1. The 3rd parameter is ** the value to assign to that variable. The 4th parameter is the number @@ -748,7 +748,7 @@ int sqlite3_reset(sqlite_vm*, char **pzErrMsg); ** If the 4th "len" parameter is -1, then strlen() is used to find the ** length. ** -** This routine can only be called immediately after sqlite3_compile() +** This routine can only be called immediately after sqlite3_prepare() ** or sqlite3_reset() and before any calls to sqlite3_step(). ** ******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ****** @@ -868,33 +868,33 @@ typedef sqlite sqlite3; /* ** This routine is used to bind a 32-bit integer value to a variable -** in an SQL statement compiled by sqlite3_compile(). See comments for -** sqlite3_compile() for more details on SQL statement variables. +** in an SQL statement compiled by sqlite3_prepare(). See comments for +** sqlite3_prepare() for more details on SQL statement variables. ** ** The first argument is a pointer to an SQL statement previously -** obtained from a call to sqlite3_compile(). The second parameter "i" +** obtained from a call to sqlite3_prepare(). The second parameter "i" ** determines the parameter to bind the value "iValue" to. */ int sqlite3_bind_int32(sqlite3_stmt*, int i, int iValue); /* ** This routine is used to bind a 64-bit integer value to a variable -** in an SQL statement compiled by sqlite3_compile(). See comments for -** sqlite3_compile() for more details on SQL statement variables. +** in an SQL statement compiled by sqlite3_prepare(). See comments for +** sqlite3_prepare() for more details on SQL statement variables. ** ** The first argument is a pointer to an SQL statement previously -** obtained from a call to sqlite3_compile(). The second parameter "i" +** obtained from a call to sqlite3_prepare(). The second parameter "i" ** determines the parameter to bind the value "iValue" to. */ int sqlite3_bind_int64(sqlite3_stmt*, int i, long long int iValue); /* ** This routine is used to bind a real (floating point) value to a variable -** in an SQL statement compiled by sqlite3_compile(). See comments for -** sqlite3_compile() for more details on SQL statement variables. +** in an SQL statement compiled by sqlite3_prepare(). See comments for +** sqlite3_prepare() for more details on SQL statement variables. ** ** The first argument is a pointer to an SQL statement previously obtained -** from a call to sqlite3_compile(). The second parameter "i" determines +** from a call to sqlite3_prepare(). The second parameter "i" determines ** the parameter to bind the value "iValue" to. Internally, SQLite will ** manipulate the value as a 64-bit IEEE float. */ @@ -902,22 +902,22 @@ int sqlite3_bind_double(sqlite3_stmt*, int i, double iValue); /* ** This routine is used to bind a NULL value to a variable in an SQL -** statement compiled by sqlite3_compile(). See comments for -** sqlite3_compile() for more details on SQL statement variables. +** statement compiled by sqlite3_prepare(). See comments for +** sqlite3_prepare() for more details on SQL statement variables. ** ** The first argument is a pointer to an SQL statement previously obtained -** from a call to sqlite3_compile(). The second parameter "i" determines +** from a call to sqlite3_prepare(). The second parameter "i" determines ** the parameter to bind the NULL value to. */ int sqlite3_bind_null(sqlite3_stmt*, int i); /* ** This routine is used to bind a UTF-8 string value to a variable in an -** SQL statement compiled by sqlite3_compile(). See comments for -** sqlite3_compile() for more details on SQL statement variables. +** SQL statement compiled by sqlite3_prepare(). See comments for +** sqlite3_prepare() for more details on SQL statement variables. ** ** The first argument is a pointer to an SQL statement previously obtained -** from a call to sqlite3_compile(). The second parameter "i" determines +** from a call to sqlite3_prepare(). The second parameter "i" determines ** the parameter to bind the value to. Parameter three "z" is a pointer ** to the UTF-8 string. ** @@ -936,11 +936,11 @@ int sqlite3_bind_text(sqlite3_stmt*, int i, const char* z, int n, int eCopy); /* ** This routine is used to bind a UTF-16 string value to a variable in an -** SQL statement compiled by sqlite3_compile(). See comments for -** sqlite3_compile() for more details on SQL statement variables. +** SQL statement compiled by sqlite3_prepare(). See comments for +** sqlite3_prepare() for more details on SQL statement variables. ** ** The first argument is a pointer to an SQL statement previously obtained -** from a call to sqlite3_compile(). The second parameter "i" determines +** from a call to sqlite3_prepare(). The second parameter "i" determines ** the parameter to bind the value to. Parameter three "z" is a pointer to ** the UTF-16 string. If the string does not begin with a byte-order-mark, ** it is assumed to be encoded in the native byte order of the machine. @@ -960,11 +960,11 @@ int sqlite3_bind_text16(sqlite3_stmt*, int i, const void *z, int, int eCopy); /* ** This routine is used to bind a blob value to a variable in an -** SQL statement compiled by sqlite3_compile(). See comments for -** sqlite3_compile() for more details on SQL statement variables. +** SQL statement compiled by sqlite3_prepare(). See comments for +** sqlite3_prepare() for more details on SQL statement variables. ** ** The first argument is a pointer to an SQL statement previously obtained -** from a call to sqlite3_compile(). The second parameter "i" determines +** from a call to sqlite3_prepare(). The second parameter "i" determines ** the parameter to bind the value to. Parameter three "z" is a pointer to ** the blob of data. ** @@ -1025,6 +1025,27 @@ const char *sqlite3_errmsg(sqlite3*); */ const void *sqlite3_errmsg16(sqlite3*); +/* +** To execute an SQL query, it must first be compiled into a byte-code +** program using this routine. The first parameter "db" is an SQLite +** database handle. The second parameter "zSql" is the statement +** to be compiled, encoded as UTF-8 text. If the next parameter, "nBytes", +** is less than zero, then zSql is read up to the first nul terminator. +** If "nBytes" is not less than zero, then it is the length of the +** string zSql, in bytes (not characters). +** +** *pzTail is made to point to the first character past the end of the first +** SQL statement in zSql. This routine only compiles the first statement +** in zSql, so *pzTail is left pointing to what remains uncompiled. +** +** *ppStmt is left pointing to a compiled SQL statement that can be +** executed using sqlite3_step(). Or if there is an error, *ppStmt may be +** set to NULL. If the input text contained no SQL (if the input is and +** empty string or a comment) then *ppStmt is set to NULL. +** +** On success, SQLITE_OK is returned. Otherwise an error code is returned. +** +*/ int sqlite3_prepare( sqlite3 *db, /* Database handle */ const char *zSql, /* SQL statement, UTF-8 encoded */ @@ -1041,10 +1062,21 @@ int sqlite3_prepare16( const void **pzTail /* OUT: Pointer to unused portion of zSql */ ); +int sqlite3_open_new( + const char *filename, /* Database filename (UTF-8) */ + sqlite3 **ppDb, /* OUT: SQLite db handle */ + const char **args /* Null terminated array of option strings */ +); + +int sqlite3_open16( + const void *filename, /* Database filename (UTF-16) */ + sqlite3 **ppDb, /* OUT: SQLite db handle */ + const char **args /* Null terminated array of option strings */ +); + + #if 0 -int sqlite3_open(const char*, sqlite3**, const char**); -int sqlite3_open16(const void*, sqlite3**, const char**); int sqlite3_close(sqlite3*); int sqlite3_finalize(sqlite3_stmt*); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 9257953827..03dbfaaf67 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.242 2004/05/21 01:29:06 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.243 2004/05/21 01:47:27 danielk1977 Exp $ */ #include "config.h" #include "sqlite.h" @@ -282,6 +282,7 @@ struct Db { u16 flags; /* Flags associated with this database */ void *pAux; /* Auxiliary data. Usually NULL */ void (*xFreeAux)(void*); /* Routine to free pAux */ + u8 textEnc; /* Text encoding for this database. */ }; /* @@ -315,6 +316,12 @@ struct Db { #define DB_SchemaLoaded 0x0004 /* The schema has been loaded */ #define DB_UnresetViews 0x0008 /* Some views have defined column names */ +/* +** Possible values for the Db.textEnc field. +*/ +#define TEXT_Utf8 1 +#define TEXT_Utf16le 2 +#define TEXT_Utf16be 3 /* ** Each database is an instance of the following structure. diff --git a/src/test1.c b/src/test1.c index 3636d81d2d..9a86ddff9f 100644 --- a/src/test1.c +++ b/src/test1.c @@ -13,7 +13,7 @@ ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test1.c,v 1.43 2004/05/20 22:16:30 drh Exp $ +** $Id: test1.c,v 1.44 2004/05/21 01:47:27 danielk1977 Exp $ */ #include "sqliteInt.h" #include "tcl.h" @@ -132,36 +132,6 @@ static int makePointerStr(Tcl_Interp *interp, char *zPtr, void *p){ return TCL_OK; } -/* -** Usage: sqlite3_open filename -** -** Returns: The name of an open database. -*/ -static int sqlite_test_open( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - char **argv /* Text of each argument */ -){ - sqlite *db; - char *zErr = 0; - char zBuf[100]; - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " FILENAME\"", 0); - return TCL_ERROR; - } - db = sqlite3_open(argv[1], 0666, &zErr); - if( db==0 ){ - Tcl_AppendResult(interp, zErr, 0); - free(zErr); - return TCL_ERROR; - } - if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR; - Tcl_AppendResult(interp, zBuf, 0); - return TCL_OK; -} - /* ** The callback routine for sqlite3_exec_printf(). */ @@ -781,47 +751,6 @@ static int sqlite_datatypes( return TCL_OK; } -/* -** Usage: sqlite3_compile DB SQL ?TAILVAR? -** -** Attempt to compile an SQL statement. Return a pointer to the virtual -** machine used to execute that statement. Unprocessed SQL is written -** into TAILVAR. -*/ -static int test_compile( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - char **argv /* Text of each argument */ -){ - sqlite *db; - sqlite_vm *vm; - int rc; - char *zErr = 0; - const char *zTail; - char zBuf[50]; - if( argc!=3 && argc!=4 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " DB SQL TAILVAR", 0); - return TCL_ERROR; - } - if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; - rc = sqlite3_compile(db, argv[2], argc==4 ? &zTail : 0, &vm, &zErr); - if( argc==4 ) Tcl_SetVar(interp, argv[3], zTail, 0); - if( rc ){ - assert( vm==0 ); - sprintf(zBuf, "(%d) ", rc); - Tcl_AppendResult(interp, zBuf, zErr, 0); - sqlite3_freemem(zErr); - return TCL_ERROR; - } - if( vm ){ - if( makePointerStr(interp, zBuf, vm) ) return TCL_ERROR; - Tcl_AppendResult(interp, zBuf, 0); - } - return TCL_OK; -} - /* ** Usage: sqlite3_step VM ?NVAR? ?VALUEVAR? ?COLNAMEVAR? ** @@ -1330,6 +1259,7 @@ static int test_prepare( const char *zTail = 0; sqlite3_stmt *pStmt = 0; char zBuf[50]; + int rc; if( objc!=5 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", @@ -1340,19 +1270,24 @@ static int test_prepare( zSql = Tcl_GetString(objv[2]); if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; - if( SQLITE_OK!=sqlite3_prepare(db, zSql, bytes, &pStmt, &zTail) ){ - return TCL_ERROR; - } - + rc = sqlite3_prepare(db, zSql, bytes, &pStmt, &zTail); if( zTail ){ if( bytes>=0 ){ bytes = bytes - (zTail-zSql); } Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0); } + if( rc!=SQLITE_OK ){ + assert( pStmt==0 ); + sprintf(zBuf, "(%d) ", rc); + Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0); + return TCL_ERROR; + } - if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; - Tcl_AppendResult(interp, zBuf, 0); + if( pStmt ){ + if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; + Tcl_AppendResult(interp, zBuf, 0); + } return TCL_OK; } @@ -1400,13 +1335,70 @@ static int test_prepare16( pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen); Tcl_IncrRefCount(pTail); Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0); - // Tcl_DecrRefCount(pTail); + Tcl_DecrRefCount(pTail); - if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; + if( pStmt ){ + if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; + } Tcl_AppendResult(interp, zBuf, 0); return TCL_OK; } +/* +** Usage: sqlite3_open filename ?options-list? +*/ +static int test_open( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + const char *zFilename; + sqlite3 *db; + int rc; + char zBuf[100]; + + if( objc!=3 && objc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetString(objv[0]), " filename options-list", 0); + return TCL_ERROR; + } + + zFilename = Tcl_GetString(objv[1]); + rc = sqlite3_open_new(zFilename, &db, 0); + + if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR; + Tcl_AppendResult(interp, zBuf, 0); + return TCL_OK; +} + +/* +** Usage: sqlite3_open16 filename options +*/ +static int test_open16( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + const void *zFilename; + sqlite3 *db; + int rc; + char zBuf[100]; + + if( objc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetString(objv[0]), " filename options-list", 0); + return TCL_ERROR; + } + + zFilename = Tcl_GetByteArrayFromObj(objv[1], 0); + rc = sqlite3_open16(zFilename, &db, 0); + + if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR; + Tcl_AppendResult(interp, zBuf, 0); + return TCL_OK; +} /* ** This is a collating function named "REVERSE" which sorts text @@ -1467,7 +1459,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ { "sqlite3_mprintf_double", (Tcl_CmdProc*)sqlite3_mprintf_double }, { "sqlite3_mprintf_scaled", (Tcl_CmdProc*)sqlite3_mprintf_scaled }, { "sqlite3_mprintf_z_test", (Tcl_CmdProc*)test_mprintf_z }, - { "sqlite3_open", (Tcl_CmdProc*)sqlite_test_open }, +// { "sqlite3_open", (Tcl_CmdProc*)sqlite_test_open }, { "sqlite3_last_insert_rowid", (Tcl_CmdProc*)test_last_rowid }, { "sqlite3_exec_printf", (Tcl_CmdProc*)test_exec_printf }, { "sqlite3_get_table_printf", (Tcl_CmdProc*)test_get_table_printf }, @@ -1481,12 +1473,11 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ { "sqlite_malloc_fail", (Tcl_CmdProc*)sqlite_malloc_fail }, { "sqlite_malloc_stat", (Tcl_CmdProc*)sqlite_malloc_stat }, #endif - { "sqlite_compile", (Tcl_CmdProc*)test_compile }, - { "sqlite_step", (Tcl_CmdProc*)test_step }, - { "sqlite_finalize", (Tcl_CmdProc*)test_finalize }, - { "sqlite_bind", (Tcl_CmdProc*)test_bind }, - { "sqlite_reset", (Tcl_CmdProc*)test_reset }, - { "breakpoint", (Tcl_CmdProc*)test_breakpoint }, + { "sqlite_step", (Tcl_CmdProc*)test_step }, + { "sqlite_finalize", (Tcl_CmdProc*)test_finalize }, + { "sqlite_bind", (Tcl_CmdProc*)test_bind }, + { "sqlite_reset", (Tcl_CmdProc*)test_reset }, + { "breakpoint", (Tcl_CmdProc*)test_breakpoint }, }; static struct { char *zName; @@ -1504,6 +1495,8 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ { "sqlite3_errmsg16", (Tcl_ObjCmdProc*)test_errmsg16 }, { "sqlite3_prepare", (Tcl_ObjCmdProc*)test_prepare }, { "sqlite3_prepare16", (Tcl_ObjCmdProc*)test_prepare16 }, + { "sqlite3_open", (Tcl_ObjCmdProc*)test_open }, + { "sqlite3_open16", (Tcl_ObjCmdProc*)test_open16 }, { "add_reverse_collating_func", (Tcl_ObjCmdProc*)reverse_collfunc }, }; int i; diff --git a/test/attach2.test b/test/attach2.test index 38b58cc44f..58ff5e2b56 100644 --- a/test/attach2.test +++ b/test/attach2.test @@ -12,7 +12,7 @@ # focus of this script is testing the ATTACH and DETACH commands # and related functionality. # -# $Id: attach2.test,v 1.7 2004/05/13 11:34:17 danielk1977 Exp $ +# $Id: attach2.test,v 1.8 2004/05/21 01:47:27 danielk1977 Exp $ # @@ -124,13 +124,13 @@ do_test attach2-2.12 { do_test attach2-3.1 { db close set DB [sqlite db test.db] - set rc [catch {sqlite_compile $DB "ATTACH 'test2.db' AS t2" TAIL} VM] + set rc [catch {sqlite3_prepare $DB "ATTACH 'test2.db' AS t2" -1 TAIL} VM] if {$rc} {lappend rc $VM} sqlite_finalize $VM set rc } {0} do_test attach2-3.2 { - set rc [catch {sqlite_compile $DB "DETACH t2" TAIL} VM] + set rc [catch {sqlite3_prepare $DB "DETACH t2" -1 TAIL} VM] if {$rc} {lappend rc $VM} sqlite_finalize $VM set rc diff --git a/test/bind.test b/test/bind.test index 7c03560e33..fe95bd5214 100644 --- a/test/bind.test +++ b/test/bind.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The # focus of this script testing the sqlite_bind API. # -# $Id: bind.test,v 1.3 2004/05/20 11:00:53 danielk1977 Exp $ +# $Id: bind.test,v 1.4 2004/05/21 01:47:27 danielk1977 Exp $ # set testdir [file dirname $argv0] @@ -21,7 +21,7 @@ do_test bind-1.1 { db close set DB [sqlite db test.db] execsql {CREATE TABLE t1(a,b,c)} - set VM [sqlite_compile $DB {INSERT INTO t1 VALUES(?,?,?)} TAIL] + set VM [sqlite3_prepare $DB {INSERT INTO t1 VALUES(?,?,?)} -1 TAIL] set TAIL } {} do_test bind-1.2 { @@ -71,7 +71,7 @@ do_test bind-2.1 { execsql { DELETE FROM t1; } - set VM [sqlite_compile $DB {INSERT INTO t1 VALUES(?,?,?)} TAIL] + set VM [sqlite3_bind_int32 $DB {INSERT INTO t1 VALUES(?,?,?)} TAIL] set TAIL } {} diff --git a/test/capi2.test b/test/capi2.test index 92073e0ac5..1efe3299ea 100644 --- a/test/capi2.test +++ b/test/capi2.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The # focus of this script testing the callback-free C/C++ API. # -# $Id: capi2.test,v 1.10 2003/08/05 13:13:38 drh Exp $ +# $Id: capi2.test,v 1.11 2004/05/21 01:47:27 danielk1977 Exp $ # set testdir [file dirname $argv0] @@ -23,7 +23,7 @@ do_test capi2-1.1 { db close set DB [sqlite db test.db] execsql {CREATE TABLE t1(a,b,c)} - set VM [sqlite_compile $DB {SELECT name, rowid FROM sqlite_master} TAIL] + set VM [sqlite3_prepare $DB {SELECT name, rowid FROM sqlite_master} -1 TAIL] set TAIL } {} do_test capi2-1.2 { @@ -61,7 +61,7 @@ do_test capi2-1.10 { } {} # Check to make sure that the "tail" of a multi-statement SQL script -# is returned by sqlite_compile. +# is returned by sqlite3_prepare. # do_test capi2-2.1 { set SQL { @@ -69,7 +69,7 @@ do_test capi2-2.1 { SELECT name, rowid FROM sqlite_temp_master; -- A comment at the end } - set VM [sqlite_compile $DB $SQL SQL] + set VM [sqlite3_prepare $DB $SQL -1 SQL] set SQL } { SELECT name, rowid FROM sqlite_temp_master; @@ -87,7 +87,7 @@ do_test capi2-2.4 { sqlite_finalize $VM } {} do_test capi2-2.5 { - set VM [sqlite_compile $DB $SQL SQL] + set VM [sqlite3_prepare $DB $SQL -1 SQL] set SQL } { -- A comment at the end @@ -100,7 +100,7 @@ do_test capi2-2.7 { sqlite_finalize $VM } {} do_test capi2-2.8 { - set VM [sqlite_compile $DB $SQL SQL] + set VM [sqlite3_prepare $DB $SQL -1 SQL] list $SQL $VM } {{} {}} @@ -108,37 +108,37 @@ do_test capi2-2.8 { # do_test capi2-3.1 { set rc [catch { - sqlite_compile $DB {select bogus from sqlite_master} TAIL + sqlite3_prepare $DB {select bogus from sqlite_master} -1 TAIL } msg] lappend rc $msg $TAIL } {1 {(1) no such column: bogus} {}} do_test capi2-3.2 { set rc [catch { - sqlite_compile $DB {select bogus from } TAIL + sqlite3_prepare $DB {select bogus from } -1 TAIL } msg] lappend rc $msg $TAIL } {1 {(1) near " ": syntax error} {}} do_test capi2-3.3 { set rc [catch { - sqlite_compile $DB {;;;;select bogus from sqlite_master} TAIL + sqlite3_prepare $DB {;;;;select bogus from sqlite_master} -1 TAIL } msg] lappend rc $msg $TAIL } {1 {(1) no such column: bogus} {}} do_test capi2-3.4 { set rc [catch { - sqlite_compile $DB {select bogus from sqlite_master;x;} TAIL + sqlite3_prepare $DB {select bogus from sqlite_master;x;} -1 TAIL } msg] lappend rc $msg $TAIL } {1 {(1) no such column: bogus} {x;}} do_test capi2-3.5 { set rc [catch { - sqlite_compile $DB {select bogus from sqlite_master;;;x;} TAIL + sqlite3_prepare $DB {select bogus from sqlite_master;;;x;} -1 TAIL } msg] lappend rc $msg $TAIL } {1 {(1) no such column: bogus} {;;x;}} do_test capi2-3.6 { set rc [catch { - sqlite_compile $DB {select 5/0} TAIL + sqlite3_prepare $DB {select 5/0} -1 TAIL } VM] lappend rc $TAIL } {0 {}} @@ -153,7 +153,7 @@ do_test capi2-3.8 { } {} do_test capi2-3.9 { execsql {CREATE UNIQUE INDEX i1 ON t1(a)} - set VM [sqlite_compile $DB {INSERT INTO t1 VALUES(1,2,3)} TAIL] + set VM [sqlite3_prepare $DB {INSERT INTO t1 VALUES(1,2,3)} -1 TAIL] set TAIL } {} do_test capi2-3.9b {db changes} {0} @@ -172,7 +172,7 @@ do_test capi2-3.12 { list [catch {sqlite_finalize $VM} msg] [set msg] } {1 {(21) library routine called out of sequence}} do_test capi2-3.13 { - set VM [sqlite_compile $DB {INSERT INTO t1 VALUES(1,3,4)} TAIL] + set VM [sqlite3_prepare $DB {INSERT INTO t1 VALUES(1,3,4)} -1 TAIL] list [sqlite_step $VM N VALUE COLNAME] [set N] [set VALUE] [set COLNAME] } {SQLITE_ERROR 0 {} {}} do_test capi2-3.13b {db changes} {0} @@ -180,7 +180,7 @@ do_test capi2-3.14 { list [catch {sqlite_finalize $VM} msg] [set msg] } {1 {(19) column a is not unique}} do_test capi2-3.15 { - set VM [sqlite_compile $DB {CREATE TABLE t2(a NOT NULL, b)} TAIL] + set VM [sqlite3_prepare $DB {CREATE TABLE t2(a NOT NULL, b)} -1 TAIL] set TAIL } {} do_test capi2-3.16 { @@ -190,7 +190,7 @@ do_test capi2-3.17 { list [catch {sqlite_finalize $VM} msg] [set msg] } {0 {}} do_test capi2-3.18 { - set VM [sqlite_compile $DB {INSERT INTO t2 VALUES(NULL,2)} TAIL] + set VM [sqlite3_prepare $DB {INSERT INTO t2 VALUES(NULL,2)} -1 TAIL] list [sqlite_step $VM N VALUE COLNAME] [set N] [set VALUE] [set COLNAME] } {SQLITE_ERROR 0 {} {}} do_test capi2-3.19 { @@ -200,15 +200,15 @@ do_test capi2-3.19 { # Two or more virtual machines exists at the same time. # do_test capi2-4.1 { - set VM1 [sqlite_compile $DB {INSERT INTO t2 VALUES(1,2)} TAIL] + set VM1 [sqlite3_prepare $DB {INSERT INTO t2 VALUES(1,2)} -1 TAIL] set TAIL } {} do_test capi2-4.2 { - set VM2 [sqlite_compile $DB {INSERT INTO t2 VALUES(2,3)} TAIL] + set VM2 [sqlite3_prepare $DB {INSERT INTO t2 VALUES(2,3)} -1 TAIL] set TAIL } {} do_test capi2-4.3 { - set VM3 [sqlite_compile $DB {INSERT INTO t2 VALUES(3,4)} TAIL] + set VM3 [sqlite3_prepare $DB {INSERT INTO t2 VALUES(3,4)} -1 TAIL] set TAIL } {} do_test capi2-4.4 { @@ -242,9 +242,9 @@ do_test capi2-4.12 { # Interleaved SELECTs # do_test capi2-5.1 { - set VM1 [sqlite_compile $DB {SELECT * FROM t2} TAIL] - set VM2 [sqlite_compile $DB {SELECT * FROM t2} TAIL] - set VM3 [sqlite_compile $DB {SELECT * FROM t2} TAIL] + set VM1 [sqlite3_prepare $DB {SELECT * FROM t2} -1 TAIL] + set VM2 [sqlite3_prepare $DB {SELECT * FROM t2} -1 TAIL] + set VM3 [sqlite3_prepare $DB {SELECT * FROM t2} -1 TAIL] list [sqlite_step $VM1 N VALUE COLNAME] [set N] [set VALUE] [set COLNAME] } {SQLITE_ROW 2 {2 3} {a b {} {}}} do_test capi2-5.2 { @@ -297,7 +297,7 @@ do_test capi2-6.1 { INSERT INTO t3 SELECT x+8 FROM t3; COMMIT; } - set VM1 [sqlite_compile $DB {SELECT * FROM t3} TAIL] + set VM1 [sqlite3_prepare $DB {SELECT * FROM t3} -1 TAIL] sqlite db2 test.db execsql {BEGIN} db2 } {} @@ -457,15 +457,15 @@ do_test capi2-7.12 { # Ticket #261 - make sure we can finalize before the end of a query. # do_test capi2-8.1 { - set VM1 [sqlite_compile $DB {SELECT * FROM t2} TAIL] + set VM1 [sqlite3_prepare $DB {SELECT * FROM t2} -1 TAIL] sqlite_finalize $VM1 } {} -# Tickets #384 and #385 - make sure the TAIL argument to sqlite_compile +# Tickets #384 and #385 - make sure the TAIL argument to sqlite3_prepare # and all of the return pointers in sqlite_step can be null. # do_test capi2-9.1 { - set VM1 [sqlite_compile $DB {SELECT * FROM t2}] + set VM1 [sqlite3_prepare $DB {SELECT * FROM t2} -1 DUMMY] sqlite_step $VM1 sqlite_finalize $VM1 } {} diff --git a/test/capi3.test b/test/capi3.test index a4542bfaec..23eab119c4 100644 --- a/test/capi3.test +++ b/test/capi3.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The # focus of this script testing the callback-free C/C++ API. # -# $Id: capi3.test,v 1.1 2004/05/20 11:00:53 danielk1977 Exp $ +# $Id: capi3.test,v 1.2 2004/05/21 01:47:27 danielk1977 Exp $ # set testdir [file dirname $argv0] @@ -45,6 +45,8 @@ proc utf8 {str} { # # capi3-1.*: Test sqlite3_prepare # capi3-2.*: Test sqlite3_prepare16 +# capi3-3.*: Test sqlite3_open +# capi3-4.*: Test sqlite3_open16 # db close @@ -105,6 +107,54 @@ do_test capi3-2.5 { sqlite3_errmsg $DB } {no such column: namex} +# rename sqlite3_open sqlite3_open_old +# proc sqlite3_open {fname options} {sqlite3_open_new $fname $options} + +do_test capi3-3.1 { + set db2 [sqlite3_open test.db {}] + sqlite3_errcode $db2 +} {SQLITE_OK} +# FIX ME: Should test the db handle works. +do_test capi3-3.2 { + sqlite3_close $db2 +} {} +do_test capi3-3.3 { + catch { + set db2 [sqlite3_open /bogus/path/test.db {}] + } + sqlite3_errcode $db2 +} {SQLITE_CANTOPEN} +do_test capi3-3.4 { + sqlite3_errmsg $db2 +} {unable to open database file} +do_test capi3-3.4 { + sqlite3_close $db2 +} {} + +# rename sqlite3_open "" +# rename sqlite3_open_old sqlite3_open + +do_test capi3-4.1 { + set db2 [sqlite3_open16 [utf16 test.db] {}] + sqlite3_errcode $db2 +} {SQLITE_OK} +# FIX ME: Should test the db handle works. +do_test capi3-4.2 { + sqlite3_close $db2 +} {} +do_test capi3-4.3 { + catch { + set db2 [sqlite3_open16 [utf16 /bogus/path/test.db] {}] + } + sqlite3_errcode $db2 +} {SQLITE_CANTOPEN} +do_test capi3-4.4 { + utf8 [sqlite3_errmsg16 $db2] +} {unable to open database file} +do_test capi3-4.4 { + sqlite3_close $db2 +} {} + finish_test diff --git a/test/tester.tcl b/test/tester.tcl index cc09d9593b..08b11cb2c0 100644 --- a/test/tester.tcl +++ b/test/tester.tcl @@ -11,7 +11,7 @@ # This file implements some common TCL routines used for regression # testing the SQLite library # -# $Id: tester.tcl,v 1.33 2004/05/20 22:16:31 drh Exp $ +# $Id: tester.tcl,v 1.34 2004/05/21 01:47:27 danielk1977 Exp $ # Make sure tclsqlite was compiled correctly. Abort now with an # error message if not. @@ -198,7 +198,7 @@ proc stepsql {dbptr sql} { set sql [string trim $sql] set r 0 while {[string length $sql]>0} { - if {[catch {sqlite_compile $dbptr $sql sqltail} vm]} { + if {[catch {sqlite3_prepare $dbptr $sql -1 sqltail} vm]} { return [list 1 $vm] } set sql [string trim $sqltail] diff --git a/test/vacuum.test b/test/vacuum.test index 8158ece98c..df4bbe598d 100644 --- a/test/vacuum.test +++ b/test/vacuum.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The # focus of this file is testing the VACUUM statement. # -# $Id: vacuum.test,v 1.15 2004/02/14 16:31:04 drh Exp $ +# $Id: vacuum.test,v 1.16 2004/05/21 01:47:27 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -130,12 +130,12 @@ do_test vacuum-3.1 { } } {} -# Ticket #464. Make sure VACUUM works with the sqlite_compile() API. +# Ticket #464. Make sure VACUUM works with the sqlite3_prepare() API. # do_test vacuum-4.1 { db close set DB [sqlite db test.db] - set VM [sqlite_compile $DB {VACUUM} TAIL] + set VM [sqlite3_prepare $DB {VACUUM} -1 TAIL] sqlite_step $VM N VALUES COLNAMES } {SQLITE_DONE} do_test vacuum-4.2 {