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*dcc581ccSdrh ** $Id: tclsqlite.c,v 1.3 2000/05/30 13:44:20 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; 155*dcc581ccSdrh cbData.once = 1; 15675897234Sdrh cbData.zArray = argv[3]; 15775897234Sdrh cbData.zCode = argv[4]; 15875897234Sdrh zErrMsg = 0; 15975897234Sdrh rc = sqlite_exec(db, argv[2], DbEvalCallback, &cbData, &zErrMsg); 16075897234Sdrh }else{ 16175897234Sdrh rc = sqlite_exec(db, argv[2], 0, 0, &zErrMsg); 16275897234Sdrh } 16375897234Sdrh if( zErrMsg ){ 16475897234Sdrh Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE); 16575897234Sdrh free(zErrMsg); 16675897234Sdrh } 16775897234Sdrh return rc; 16875897234Sdrh } 16975897234Sdrh 17075897234Sdrh /* The default 17175897234Sdrh */ 17275897234Sdrh else{ 17375897234Sdrh Tcl_AppendResult(interp,"unknown subcommand \"", z, 17475897234Sdrh "\" - should be one of: close complete eval", 0); 17575897234Sdrh return TCL_ERROR; 17675897234Sdrh } 17775897234Sdrh return TCL_OK; 17875897234Sdrh } 17975897234Sdrh 18075897234Sdrh /* 18175897234Sdrh ** sqlite DBNAME FILENAME ?MODE? 18275897234Sdrh ** 18375897234Sdrh ** This is the main Tcl command. When the "sqlite" Tcl command is 18475897234Sdrh ** invoked, this routine runs to process that command. 18575897234Sdrh ** 18675897234Sdrh ** The first argument, DBNAME, is an arbitrary name for a new 18775897234Sdrh ** database connection. This command creates a new command named 18875897234Sdrh ** DBNAME that is used to control that connection. The database 18975897234Sdrh ** connection is deleted when the DBNAME command is deleted. 19075897234Sdrh ** 19175897234Sdrh ** The second argument is the name of the directory that contains 19275897234Sdrh ** the sqlite database that is to be accessed. 19375897234Sdrh */ 19475897234Sdrh static int DbMain(void *cd, Tcl_Interp *interp, int argc, char **argv){ 19575897234Sdrh int mode; 19675897234Sdrh sqlite *p; 19775897234Sdrh char *zErrMsg; 19875897234Sdrh if( argc!=3 && argc!=4 ){ 19975897234Sdrh Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0], 20075897234Sdrh " HANDLE FILENAME ?MODE?\"", 0); 20175897234Sdrh return TCL_ERROR; 20275897234Sdrh } 20375897234Sdrh if( argc==3 ){ 20475897234Sdrh mode = 0; 20575897234Sdrh }else if( Tcl_GetInt(interp, argv[3], &mode)!=TCL_OK ){ 20675897234Sdrh return TCL_ERROR; 20775897234Sdrh } 20875897234Sdrh zErrMsg = 0; 20975897234Sdrh p = sqlite_open(argv[2], mode, &zErrMsg); 21075897234Sdrh if( p==0 ){ 21175897234Sdrh Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE); 21275897234Sdrh free(zErrMsg); 21375897234Sdrh return TCL_ERROR; 21475897234Sdrh } 21575897234Sdrh Tcl_CreateCommand(interp, argv[1], DbCmd, p, DbDeleteCmd); 21675897234Sdrh return TCL_OK; 21775897234Sdrh } 21875897234Sdrh 21975897234Sdrh /* 22075897234Sdrh ** Initialize this module. 22175897234Sdrh ** 22275897234Sdrh ** This Tcl module contains only a single new Tcl command named "sqlite". 22375897234Sdrh ** (Hence there is no namespace. There is no point in using a namespace 22475897234Sdrh ** if the extension only supplies one new name!) The "sqlite" command is 22575897234Sdrh ** used to open a new SQLite database. See the DbMain() routine above 22675897234Sdrh ** for additional information. 22775897234Sdrh */ 22875897234Sdrh int Sqlite_Init(Tcl_Interp *interp){ 22975897234Sdrh Tcl_CreateCommand(interp, "sqlite", DbMain, 0, 0); 23075897234Sdrh return TCL_OK; 23175897234Sdrh } 23275897234Sdrh int Sqlite_SafeInit(Tcl_Interp *interp){ 23375897234Sdrh return TCL_OK; 23475897234Sdrh } 23575897234Sdrh 23675897234Sdrh /* 23775897234Sdrh ** If compiled using mktclapp, this routine runs to initialize 23875897234Sdrh ** everything. 23975897234Sdrh */ 24075897234Sdrh int Et_AppInit(Tcl_Interp *interp){ 24175897234Sdrh return Sqlite_Init(interp); 24275897234Sdrh } 243348784efSdrh 244348784efSdrh /* 245348784efSdrh ** If the macro TCLSH is defined and is one, then put in code for the 246348784efSdrh ** "main" routine that will initialize Tcl. 247348784efSdrh */ 248348784efSdrh #if defined(TCLSH) && TCLSH==1 249348784efSdrh static char zMainloop[] = 250348784efSdrh "set line {}\n" 251348784efSdrh "while {![eof stdin]} {\n" 252348784efSdrh "if {$line!=\"\"} {\n" 253348784efSdrh "puts -nonewline \"> \"\n" 254348784efSdrh "} else {\n" 255348784efSdrh "puts -nonewline \"% \"\n" 256348784efSdrh "}\n" 257348784efSdrh "flush stdout\n" 258348784efSdrh "append line [gets stdin]\n" 259348784efSdrh "if {[info complete $line]} {\n" 260348784efSdrh "if {[catch {uplevel #0 $line} result]} {\n" 261348784efSdrh "puts stderr \"Error: $result\"\n" 262348784efSdrh "} elseif {$result!=\"\"} {\n" 263348784efSdrh "puts $result\n" 264348784efSdrh "}\n" 265348784efSdrh "set line {}\n" 266348784efSdrh "} else {\n" 267348784efSdrh "append line \\n\n" 268348784efSdrh "}\n" 269348784efSdrh "}\n" 270348784efSdrh ; 271348784efSdrh 272348784efSdrh #define TCLSH_MAIN main /* Needed to fake out mktclapp */ 273348784efSdrh int TCLSH_MAIN(int argc, char **argv){ 274348784efSdrh Tcl_Interp *interp; 275348784efSdrh interp = Tcl_CreateInterp(); 276348784efSdrh Sqlite_Init(interp); 277348784efSdrh if( argc>=2 ){ 278348784efSdrh int i; 279348784efSdrh Tcl_SetVar(interp,"argv0",argv[1],TCL_GLOBAL_ONLY); 280348784efSdrh Tcl_SetVar(interp,"argv", "", TCL_GLOBAL_ONLY); 281348784efSdrh for(i=2; i<argc; i++){ 282348784efSdrh Tcl_SetVar(interp, "argv", argv[i], 283348784efSdrh TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT | TCL_APPEND_VALUE); 284348784efSdrh } 285348784efSdrh if( Tcl_EvalFile(interp, argv[1])!=TCL_OK ){ 286348784efSdrh fprintf(stderr,"%s: %s\n", *argv, 287348784efSdrh Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY) 288348784efSdrh ); 289348784efSdrh return 1; 290348784efSdrh } 291348784efSdrh }else{ 292348784efSdrh Tcl_GlobalEval(interp, zMainloop); 293348784efSdrh } 294348784efSdrh return 0; 295348784efSdrh } 296348784efSdrh #endif /* TCLSH */ 297