From 411995dc0d1611c8aa2a00c48d0c9cf756a34d98 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 25 Jun 2002 19:31:18 +0000 Subject: [PATCH] Add the sqlite_open_aux_file() API. (CVS 646) FossilOrigin-Name: 332164d6455658ca633a1dc49811d9fb0fd4b01c --- manifest | 20 +++++++++---------- manifest.uuid | 2 +- src/main.c | 46 +++++++++++++++++++++++++++++++++++++++++-- src/shell.c | 12 +++++++++++- src/sqlite.h.in | 10 +++++++++- src/tclsqlite.c | 48 ++++++++++++++++++++++++++++++++++++--------- test/tclsqlite.test | 4 ++-- 7 files changed, 116 insertions(+), 26 deletions(-) diff --git a/manifest b/manifest index 1a3b815cea..6814b31623 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Version\s2.5.3\s(CVS\s645) -D 2002-06-25T15:19:03 +C Add\sthe\ssqlite_open_aux_file()\sAPI.\s(CVS\s646) +D 2002-06-25T19:31:18 F Makefile.in 6291a33b87d2a395aafd7646ee1ed562c6f2c28c F Makefile.template 4e11752e0b5c7a043ca50af4296ec562857ba495 F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0 @@ -28,7 +28,7 @@ F src/func.c 5eae8227a8b0d276a64d51a3880a6e86f238fedf F src/hash.c 6a6236b89c8c060c65dabd300a1c8ce7c10edb72 F src/hash.h cd0433998bc1a3759d244e1637fe5a3c13b53bf8 F src/insert.c 4bb40ed9dbaba4516fc2abbcff3f08d5687b073c -F src/main.c 43d5f4e38108129a13cf42c59087e6e20b3596ad +F src/main.c 6ac32ca71ab4728212c5b44aed25e26dc6cfe73c F src/md5.c 0ae1f3e2cac92d06fc6246d1b4b8f61a2fe66d3b F src/os.c 9cc40c5384baba4a85e160e67807645ca98ba3cc F src/os.h 4a361fccfbc4e7609b3e1557f604f94c1e96ad10 @@ -38,12 +38,12 @@ F src/parse.y c75ea2580de675bcb80ff8b7c10c0a15e02a21ab F src/printf.c 236ed7a79386feed4456fa728fff8be793f1547c F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe F src/select.c f7d74f20f5ecc335fbccba367eda727b9d6fb299 -F src/shell.c 7b9d98ef3976ff5e44c18620dd17d32af83fbdd6 +F src/shell.c 0b06e4421ddf34f30263a2674abe768a2b5fd538 F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e -F src/sqlite.h.in 7c8882e352cb70818cfaf9bdb5b1b3bee81ef144 +F src/sqlite.h.in 75c5bbb066d0faf34424b7d1babf8b44d5b31af2 F src/sqliteInt.h 3d1d86cb9ea4f06e49af855267478e3661abcd1b F src/table.c eed2098c9b577aa17f8abe89313a9c4413f57d63 -F src/tclsqlite.c 9300c9606a38bc0c75d6c0bc8a6197ab979353d1 +F src/tclsqlite.c 7bbdf1873d843cc8706826987268322798aaf6cd F src/test1.c 5cc4f0bbf38237e04e1b2077e285b41bfb4c4cbf F src/test2.c 669cc22781c6461a273416ec1a7414d25c081730 F src/test3.c 4e52fff8b01f08bd202f7633feda5639b7ba2b5e @@ -97,7 +97,7 @@ F test/sort.test 3b996ce7ca385f9cd559944ac0f4027a23aa546b F test/subselect.test f3bc1dcbddddcea08d818fcff75228ad3464fc83 F test/table.test 42511f98a3e9bbee62913e3ae1774777faa23d35 F test/tableapi.test 3c80421a889e1d106df16e5800fa787f0d2914a6 -F test/tclsqlite.test 79deeffd7cd637ca0f06c5dbbf2f44d272079533 +F test/tclsqlite.test 6f4b9760681c7dbca52a18d0ab46a1679cdc79b9 F test/temptable.test 9ed7ec0288f887e132de66d90c428ad109105f67 F test/tester.tcl 6f603d90881bd835ea27c568a7fecaa57dce91cc F test/trans.test 4eeb19975bb9607dce4fd4c0ef6723c2185c7d84 @@ -137,7 +137,7 @@ F www/speed.tcl da8afcc1d3ccc5696cfb388a68982bc3d9f7f00f F www/sqlite.tcl ac64065d0c5e2de0f71238d55b2c14bb5c5c194c F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218 -P 37cc40442bab50506978f428001b77f23d3a4e4c -R 0b524c6f8ffa1c6addaf260fe881aaa9 +P d5cb675432cbaeac2c1a8a08181613b9d1eb5ca1 +R 23f9cfbf0d6380c4cbde26b796391b19 U drh -Z 2f6c7812cc74c55fc0ded8ee085ed6f3 +Z f72865dbf4a454e4ffbff1c2543dcab0 diff --git a/manifest.uuid b/manifest.uuid index 6700fa5e35..f6c432620f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d5cb675432cbaeac2c1a8a08181613b9d1eb5ca1 \ No newline at end of file +332164d6455658ca633a1dc49811d9fb0fd4b01c \ No newline at end of file diff --git a/src/main.c b/src/main.c index e6877b38fa..ee79bfdb9b 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.84 2002/06/25 01:09:11 drh Exp $ +** $Id: main.c,v 1.85 2002/06/25 19:31:18 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -710,7 +710,9 @@ int sqlite_create_aggregate( } /* -** Change the datatype for all functions with a given name. +** Change the datatype for all functions with a given name. See the +** header comment for the prototype of this function in sqlite.h for +** additional information. */ int sqlite_function_type(sqlite *db, const char *zName, int dataType){ FuncDef *p = (FuncDef*)sqliteHashFind(&db->aFunc, zName, strlen(zName)); @@ -720,3 +722,43 @@ int sqlite_function_type(sqlite *db, const char *zName, int dataType){ } return SQLITE_OK; } + +/* +** Attempt to open the file named in the argument as the auxiliary database +** file. The auxiliary database file is used to store TEMP tables. But +** by using this API, it is possible to trick SQLite into opening two +** separate databases and acting on them as if they were one. +** +** This routine closes the existing auxiliary database file, which will +** cause any previously created TEMP tables to be created. +** +** The zName parameter can be a NULL pointer or an empty string to cause +** a temporary file to be opened and automatically deleted when closed. +*/ +int sqlite_open_aux_file(sqlite *db, const char *zName, char **pzErrMsg){ + int rc; + if( zName && zName[0]==0 ) zName = 0; + if( sqliteSafetyOn(db) ) goto openaux_misuse; + sqliteResetInternalSchema(db); + if( db->pBeTemp!=0 ){ + sqliteBtreeClose(db->pBeTemp); + } + rc = sqliteBtreeOpen(zName, 0, MAX_PAGES, &db->pBeTemp); + if( rc ){ + if( zName==0 ) zName = "a temporary file"; + sqliteSetString(pzErrMsg, "unable to open ", zName, + ": ", sqlite_error_string(rc), 0); + sqliteStrRealloc(pzErrMsg); + sqliteSafetyOff(db); + return rc; + } + rc = sqliteInit(db, pzErrMsg); + if( sqliteSafetyOff(db) ) goto openaux_misuse; + sqliteStrRealloc(pzErrMsg); + return rc; + +openaux_misuse: + sqliteSetString(pzErrMsg, sqlite_error_string(SQLITE_MISUSE), 0); + sqliteStrRealloc(pzErrMsg); + return SQLITE_MISUSE; +} diff --git a/src/shell.c b/src/shell.c index d8ee2108e0..a3c94bf67f 100644 --- a/src/shell.c +++ b/src/shell.c @@ -12,7 +12,7 @@ ** This file contains code to implement the "sqlite" command line ** utility for accessing SQLite databases. ** -** $Id: shell.c,v 1.58 2002/06/25 01:09:12 drh Exp $ +** $Id: shell.c,v 1.59 2002/06/25 19:31:18 drh Exp $ */ #include #include @@ -486,6 +486,7 @@ static char zHelp[] = " \"insert\", \"list\", or \"html\"\n" ".mode insert TABLE Generate SQL insert statements for TABLE\n" ".nullvalue STRING Print STRING instead of nothing for NULL data\n" + ".openaux FILENAME Use FILENAME to hold TEMP tables\n" ".output FILENAME Send output to FILENAME\n" ".output stdout Send output to the screen\n" ".prompt MAIN CONTINUE Replace the standard prompts\n" @@ -702,6 +703,15 @@ static int do_meta_command(char *zLine, sqlite *db, struct callback_data *p){ sprintf(p->nullvalue, "%.*s", (int)ArraySize(p->nullvalue)-1, azArg[1]); }else + if( c=='o' && strncmp(azArg[0], "openaux", n)==0 ){ + char *zErrMsg = 0; + sqlite_open_aux_file(db, nArg>=2 ? azArg[1] : 0, &zErrMsg); + if( zErrMsg ){ + fprintf(stderr,"Error: %s\n", zErrMsg); + free(zErrMsg); + } + }else + if( c=='o' && strncmp(azArg[0], "output", n)==0 && nArg==2 ){ if( p->out!=stdout ){ fclose(p->out); diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 5d7d52c1f4..f14e06ff44 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.32 2002/06/20 11:36:50 drh Exp $ +** @(#) $Id: sqlite.h.in,v 1.33 2002/06/25 19:31:18 drh Exp $ */ #ifndef _SQLITE_H_ #define _SQLITE_H_ @@ -496,6 +496,14 @@ void *sqlite_aggregate_context(sqlite_func*, int nBytes); */ int sqlite_aggregate_count(sqlite_func*); +/* +** Attempt to open the file named in the argument as the auxiliary database +** file. The auxiliary database file is used to store TEMP tables. But +** by using this API, it is possible to trick SQLite into opening two +** separate databases and acting on them as if they were one. +*/ +int sqlite_open_aux_file(sqlite *db, const char *zName, char **pzErrMsg); + #ifdef __cplusplus } /* End of the 'extern "C"' block */ #endif diff --git a/src/tclsqlite.c b/src/tclsqlite.c index 7df3f77419..c613e8a602 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -11,7 +11,7 @@ ************************************************************************* ** A TCL Interface to SQLite ** -** $Id: tclsqlite.c,v 1.32 2002/05/10 13:14:07 drh Exp $ +** $Id: tclsqlite.c,v 1.33 2002/06/25 19:31:18 drh Exp $ */ #ifndef NO_TCL /* Omit this whole file if TCL is unavailable */ @@ -267,24 +267,26 @@ static int DbBusyHandler(void *cd, const char *zTable, int nTries){ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ SqliteDb *pDb = (SqliteDb*)cd; int choice; - static char *DB_optStrs[] = { - "busy", "changes", "close", "complete", - "eval", "last_insert_rowid", "timeout", 0 + static char *DB_strs[] = { + "busy", "changes", "close", + "complete", "eval", "last_insert_rowid", + "open_aux_file", "timeout", 0 }; - enum DB_opts { - DB_BUSY, DB_CHANGES, DB_CLOSE, DB_COMPLETE, - DB_EVAL, DB_LAST_INSERT_ROWID, DB_TIMEOUT + enum DB_enum { + DB_BUSY, DB_CHANGES, DB_CLOSE, + DB_COMPLETE, DB_EVAL, DB_LAST_INSERT_ROWID, + DB_OPEN_AUX_FILE, DB_TIMEOUT, }; if( objc<2 ){ Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ..."); return TCL_ERROR; } - if( Tcl_GetIndexFromObj(interp, objv[1], DB_optStrs, "option", 0, &choice) ){ + if( Tcl_GetIndexFromObj(interp, objv[1], DB_strs, "option", 0, &choice) ){ return TCL_ERROR; } - switch( (enum DB_opts)choice ){ + switch( (enum DB_enum)choice ){ /* $db busy ?CALLBACK? ** @@ -463,6 +465,34 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ break; } + /* + ** $db open_aux_file FILENAME + ** + ** Begin using FILENAME as the database file used to store temporary + ** tables. + */ + case DB_OPEN_AUX_FILE: { + const char *zFilename; + char *zErrMsg = 0; + int rc; + if( objc!=3 ){ + Tcl_WrongNumArgs(interp, 2, objv, "FILENAME"); + return TCL_ERROR; + } + zFilename = Tcl_GetStringFromObj(objv[2], 0); + rc = sqlite_open_aux_file(pDb->db, zFilename, &zErrMsg); + if( rc!=0 ){ + if( zErrMsg ){ + Tcl_AppendResult(interp, zErrMsg, 0); + free(zErrMsg); + }else{ + Tcl_AppendResult(interp, sqlite_error_string(rc), 0); + } + return TCL_ERROR; + } + break; + } + /* ** $db timeout MILLESECONDS ** diff --git a/test/tclsqlite.test b/test/tclsqlite.test index b8e99b2f32..e4844ae8f7 100644 --- a/test/tclsqlite.test +++ b/test/tclsqlite.test @@ -15,7 +15,7 @@ # interface is pretty well tested. This file contains some addition # tests for fringe issues that the main test suite does not cover. # -# $Id: tclsqlite.test,v 1.6 2002/04/12 10:09:00 drh Exp $ +# $Id: tclsqlite.test,v 1.7 2002/06/25 19:31:18 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -29,7 +29,7 @@ do_test tcl-1.1 { do_test tcl-1.2 { set v [catch {db bogus} msg] lappend v $msg -} {1 {bad option "bogus": must be busy, changes, close, complete, eval, last_insert_rowid, or timeout}} +} {1 {bad option "bogus": must be busy, changes, close, complete, eval, last_insert_rowid, open_aux_file, or timeout}} do_test tcl-1.3 { execsql {CREATE TABLE t1(a int, b int)} execsql {INSERT INTO t1 VALUES(10,20)}