175897234Sdrh /* 275897234Sdrh ** Copyright (c) 1999, 2000 D. Richard Hipp 375897234Sdrh ** 475897234Sdrh ** This program is free software; you can redistribute it and/or 575897234Sdrh ** modify it under the terms of the GNU General Public 675897234Sdrh ** License as published by the Free Software Foundation; either 775897234Sdrh ** version 2 of the License, or (at your option) any later version. 875897234Sdrh ** 975897234Sdrh ** This program is distributed in the hope that it will be useful, 1075897234Sdrh ** but WITHOUT ANY WARRANTY; without even the implied warranty of 1175897234Sdrh ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1275897234Sdrh ** General Public License for more details. 1375897234Sdrh ** 1475897234Sdrh ** You should have received a copy of the GNU General Public 1575897234Sdrh ** License along with this library; if not, write to the 1675897234Sdrh ** Free Software Foundation, Inc., 59 Temple Place - Suite 330, 1775897234Sdrh ** Boston, MA 02111-1307, USA. 1875897234Sdrh ** 1975897234Sdrh ** Author contact information: 2075897234Sdrh ** [email protected] 2175897234Sdrh ** http://www.hwaci.com/drh/ 2275897234Sdrh ** 2375897234Sdrh ************************************************************************* 2475897234Sdrh ** A TCL Interface to SQLite 2575897234Sdrh ** 26*348784efSdrh ** $Id: tclsqlite.c,v 1.2 2000/05/29 20:41:51 drh Exp $ 2775897234Sdrh */ 2875897234Sdrh #include "sqlite.h" 2975897234Sdrh #include <tcl.h> 3075897234Sdrh #include <stdlib.h> 3175897234Sdrh #include <string.h> 3275897234Sdrh 3375897234Sdrh /* 3475897234Sdrh ** An instance of this structure passes information thru the sqlite 3575897234Sdrh ** logic from the original TCL command into the callback routine. 3675897234Sdrh */ 3775897234Sdrh typedef struct CallbackData CallbackData; 3875897234Sdrh struct CallbackData { 3975897234Sdrh Tcl_Interp *interp; /* The TCL interpreter */ 4075897234Sdrh char *zArray; /* The array into which data is written */ 4175897234Sdrh char *zCode; /* The code to execute for each row */ 4275897234Sdrh int once; /* Set only for the first invocation of callback */ 4375897234Sdrh }; 4475897234Sdrh 4575897234Sdrh /* 4675897234Sdrh ** Called for each row of the result. 4775897234Sdrh */ 4875897234Sdrh static int DbEvalCallback( 4975897234Sdrh void *clientData, /* An instance of CallbackData */ 5075897234Sdrh int nCol, /* Number of columns in the result */ 5175897234Sdrh char ** azCol, /* Data for each column */ 5275897234Sdrh char ** azN /* Name for each column */ 5375897234Sdrh ){ 5475897234Sdrh CallbackData *cbData = (CallbackData*)clientData; 5575897234Sdrh int i, rc; 5675897234Sdrh if( cbData->zArray[0] ){ 5775897234Sdrh if( cbData->once ){ 5875897234Sdrh for(i=0; i<nCol; i++){ 5975897234Sdrh Tcl_SetVar2(cbData->interp, cbData->zArray, "*", azN[i], 6075897234Sdrh TCL_LIST_ELEMENT|TCL_APPEND_VALUE); 6175897234Sdrh } 6275897234Sdrh } 6375897234Sdrh for(i=0; i<nCol; i++){ 6475897234Sdrh Tcl_SetVar2(cbData->interp, cbData->zArray, azN[i], azCol[i], 0); 6575897234Sdrh } 6675897234Sdrh }else{ 6775897234Sdrh for(i=0; i<nCol; i++){ 6875897234Sdrh Tcl_SetVar(cbData->interp, azN[i], azCol[i], 0); 6975897234Sdrh } 7075897234Sdrh } 7175897234Sdrh cbData->once = 0; 7275897234Sdrh rc = Tcl_Eval(cbData->interp, cbData->zCode); 7375897234Sdrh return rc; 7475897234Sdrh } 7575897234Sdrh 7675897234Sdrh /* 7775897234Sdrh ** Called when the command is deleted. 7875897234Sdrh */ 7975897234Sdrh static void DbDeleteCmd(void *db){ 8075897234Sdrh sqlite_close((sqlite*)db); 8175897234Sdrh } 8275897234Sdrh 8375897234Sdrh /* 8475897234Sdrh ** The "sqlite" command below creates a new Tcl command for each 8575897234Sdrh ** connection it opens to an SQLite database. This routine is invoked 8675897234Sdrh ** whenever one of those connection-specific commands is executed 8775897234Sdrh ** in Tcl. For example, if you run Tcl code like this: 8875897234Sdrh ** 8975897234Sdrh ** sqlite db1 "my_database" 9075897234Sdrh ** db1 close 9175897234Sdrh ** 9275897234Sdrh ** The first command opens a connection to the "my_database" database 9375897234Sdrh ** and calls that connection "db1". The second command causes this 9475897234Sdrh ** subroutine to be invoked. 9575897234Sdrh */ 9675897234Sdrh static int DbCmd(void *cd, Tcl_Interp *interp, int argc, char **argv){ 9775897234Sdrh char *z; 9875897234Sdrh int n, c; 9975897234Sdrh sqlite *db = cd; 10075897234Sdrh if( argc<2 ){ 10175897234Sdrh Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0], 10275897234Sdrh " SUBCOMMAND ...\"", 0); 10375897234Sdrh return TCL_ERROR; 10475897234Sdrh } 10575897234Sdrh z = argv[1]; 10675897234Sdrh n = strlen(z); 10775897234Sdrh c = z[0]; 10875897234Sdrh 10975897234Sdrh /* $db close 11075897234Sdrh ** 11175897234Sdrh ** Shutdown the database 11275897234Sdrh */ 11375897234Sdrh if( c=='c' && n>=2 && strncmp(z,"close",n)==0 ){ 11475897234Sdrh Tcl_DeleteCommand(interp, argv[0]); 11575897234Sdrh }else 11675897234Sdrh 11775897234Sdrh /* $db complete SQL 11875897234Sdrh ** 11975897234Sdrh ** Return TRUE if SQL is a complete SQL statement. Return FALSE if 12075897234Sdrh ** additional lines of input are needed. This is similar to the 12175897234Sdrh ** built-in "info complete" command of Tcl. 12275897234Sdrh */ 12375897234Sdrh if( c=='c' && n>=2 && strncmp(z,"complete",n)==0 ){ 12475897234Sdrh char *zRes; 12575897234Sdrh if( argc!=3 ){ 12675897234Sdrh Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0], 12775897234Sdrh " complete SQL\"", 0); 12875897234Sdrh return TCL_ERROR; 12975897234Sdrh } 13075897234Sdrh zRes = sqlite_complete(argv[2]) ? "1" : "0"; 13175897234Sdrh Tcl_SetResult(interp, zRes, TCL_VOLATILE); 13275897234Sdrh }else 13375897234Sdrh 13475897234Sdrh /* 13575897234Sdrh ** $db eval $sql ?array { ...code... }? 13675897234Sdrh ** 13775897234Sdrh ** The SQL statement in $sql is evaluated. For each row, the values are 13875897234Sdrh ** placed in elements of the array named "array" and ...code.. is executed. 13975897234Sdrh ** If "array" and "code" are omitted, then no callback is every invoked. 14075897234Sdrh ** If "array" is an empty string, then the values are placed in variables 14175897234Sdrh ** that have the same name as the fields extracted by the query. 14275897234Sdrh */ 14375897234Sdrh if( c=='e' && strncmp(z,"eval",n)==0 ){ 14475897234Sdrh CallbackData cbData; 14575897234Sdrh char *zErrMsg; 14675897234Sdrh int rc; 14775897234Sdrh 14875897234Sdrh if( argc!=5 && argc!=3 ){ 14975897234Sdrh Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0], 15075897234Sdrh " eval SQL ?ARRAY-NAME CODE?", 0); 15175897234Sdrh return TCL_ERROR; 15275897234Sdrh } 15375897234Sdrh if( argc==5 ){ 15475897234Sdrh cbData.interp = interp; 15575897234Sdrh cbData.zArray = argv[3]; 15675897234Sdrh cbData.zCode = argv[4]; 15775897234Sdrh zErrMsg = 0; 15875897234Sdrh rc = sqlite_exec(db, argv[2], DbEvalCallback, &cbData, &zErrMsg); 15975897234Sdrh }else{ 16075897234Sdrh rc = sqlite_exec(db, argv[2], 0, 0, &zErrMsg); 16175897234Sdrh } 16275897234Sdrh if( zErrMsg ){ 16375897234Sdrh Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE); 16475897234Sdrh free(zErrMsg); 16575897234Sdrh } 16675897234Sdrh return rc; 16775897234Sdrh } 16875897234Sdrh 16975897234Sdrh /* The default 17075897234Sdrh */ 17175897234Sdrh else{ 17275897234Sdrh Tcl_AppendResult(interp,"unknown subcommand \"", z, 17375897234Sdrh "\" - should be one of: close complete eval", 0); 17475897234Sdrh return TCL_ERROR; 17575897234Sdrh } 17675897234Sdrh return TCL_OK; 17775897234Sdrh } 17875897234Sdrh 17975897234Sdrh /* 18075897234Sdrh ** sqlite DBNAME FILENAME ?MODE? 18175897234Sdrh ** 18275897234Sdrh ** This is the main Tcl command. When the "sqlite" Tcl command is 18375897234Sdrh ** invoked, this routine runs to process that command. 18475897234Sdrh ** 18575897234Sdrh ** The first argument, DBNAME, is an arbitrary name for a new 18675897234Sdrh ** database connection. This command creates a new command named 18775897234Sdrh ** DBNAME that is used to control that connection. The database 18875897234Sdrh ** connection is deleted when the DBNAME command is deleted. 18975897234Sdrh ** 19075897234Sdrh ** The second argument is the name of the directory that contains 19175897234Sdrh ** the sqlite database that is to be accessed. 19275897234Sdrh */ 19375897234Sdrh static int DbMain(void *cd, Tcl_Interp *interp, int argc, char **argv){ 19475897234Sdrh int mode; 19575897234Sdrh sqlite *p; 19675897234Sdrh char *zErrMsg; 19775897234Sdrh if( argc!=3 && argc!=4 ){ 19875897234Sdrh Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0], 19975897234Sdrh " HANDLE FILENAME ?MODE?\"", 0); 20075897234Sdrh return TCL_ERROR; 20175897234Sdrh } 20275897234Sdrh if( argc==3 ){ 20375897234Sdrh mode = 0; 20475897234Sdrh }else if( Tcl_GetInt(interp, argv[3], &mode)!=TCL_OK ){ 20575897234Sdrh return TCL_ERROR; 20675897234Sdrh } 20775897234Sdrh zErrMsg = 0; 20875897234Sdrh p = sqlite_open(argv[2], mode, &zErrMsg); 20975897234Sdrh if( p==0 ){ 21075897234Sdrh Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE); 21175897234Sdrh free(zErrMsg); 21275897234Sdrh return TCL_ERROR; 21375897234Sdrh } 21475897234Sdrh Tcl_CreateCommand(interp, argv[1], DbCmd, p, DbDeleteCmd); 21575897234Sdrh return TCL_OK; 21675897234Sdrh } 21775897234Sdrh 21875897234Sdrh /* 21975897234Sdrh ** Initialize this module. 22075897234Sdrh ** 22175897234Sdrh ** This Tcl module contains only a single new Tcl command named "sqlite". 22275897234Sdrh ** (Hence there is no namespace. There is no point in using a namespace 22375897234Sdrh ** if the extension only supplies one new name!) The "sqlite" command is 22475897234Sdrh ** used to open a new SQLite database. See the DbMain() routine above 22575897234Sdrh ** for additional information. 22675897234Sdrh */ 22775897234Sdrh int Sqlite_Init(Tcl_Interp *interp){ 22875897234Sdrh Tcl_CreateCommand(interp, "sqlite", DbMain, 0, 0); 22975897234Sdrh return TCL_OK; 23075897234Sdrh } 23175897234Sdrh int Sqlite_SafeInit(Tcl_Interp *interp){ 23275897234Sdrh return TCL_OK; 23375897234Sdrh } 23475897234Sdrh 23575897234Sdrh /* 23675897234Sdrh ** If compiled using mktclapp, this routine runs to initialize 23775897234Sdrh ** everything. 23875897234Sdrh */ 23975897234Sdrh int Et_AppInit(Tcl_Interp *interp){ 24075897234Sdrh return Sqlite_Init(interp); 24175897234Sdrh } 242*348784efSdrh 243*348784efSdrh /* 244*348784efSdrh ** If the macro TCLSH is defined and is one, then put in code for the 245*348784efSdrh ** "main" routine that will initialize Tcl. 246*348784efSdrh */ 247*348784efSdrh #if defined(TCLSH) && TCLSH==1 248*348784efSdrh static char zMainloop[] = 249*348784efSdrh "set line {}\n" 250*348784efSdrh "while {![eof stdin]} {\n" 251*348784efSdrh "if {$line!=\"\"} {\n" 252*348784efSdrh "puts -nonewline \"> \"\n" 253*348784efSdrh "} else {\n" 254*348784efSdrh "puts -nonewline \"% \"\n" 255*348784efSdrh "}\n" 256*348784efSdrh "flush stdout\n" 257*348784efSdrh "append line [gets stdin]\n" 258*348784efSdrh "if {[info complete $line]} {\n" 259*348784efSdrh "if {[catch {uplevel #0 $line} result]} {\n" 260*348784efSdrh "puts stderr \"Error: $result\"\n" 261*348784efSdrh "} elseif {$result!=\"\"} {\n" 262*348784efSdrh "puts $result\n" 263*348784efSdrh "}\n" 264*348784efSdrh "set line {}\n" 265*348784efSdrh "} else {\n" 266*348784efSdrh "append line \\n\n" 267*348784efSdrh "}\n" 268*348784efSdrh "}\n" 269*348784efSdrh ; 270*348784efSdrh 271*348784efSdrh #define TCLSH_MAIN main /* Needed to fake out mktclapp */ 272*348784efSdrh int TCLSH_MAIN(int argc, char **argv){ 273*348784efSdrh Tcl_Interp *interp; 274*348784efSdrh interp = Tcl_CreateInterp(); 275*348784efSdrh Sqlite_Init(interp); 276*348784efSdrh if( argc>=2 ){ 277*348784efSdrh int i; 278*348784efSdrh Tcl_SetVar(interp,"argv0",argv[1],TCL_GLOBAL_ONLY); 279*348784efSdrh Tcl_SetVar(interp,"argv", "", TCL_GLOBAL_ONLY); 280*348784efSdrh for(i=2; i<argc; i++){ 281*348784efSdrh Tcl_SetVar(interp, "argv", argv[i], 282*348784efSdrh TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT | TCL_APPEND_VALUE); 283*348784efSdrh } 284*348784efSdrh if( Tcl_EvalFile(interp, argv[1])!=TCL_OK ){ 285*348784efSdrh fprintf(stderr,"%s: %s\n", *argv, 286*348784efSdrh Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY) 287*348784efSdrh ); 288*348784efSdrh return 1; 289*348784efSdrh } 290*348784efSdrh }else{ 291*348784efSdrh Tcl_GlobalEval(interp, zMainloop); 292*348784efSdrh } 293*348784efSdrh return 0; 294*348784efSdrh } 295*348784efSdrh #endif /* TCLSH */ 296