xref: /sqlite-3.40.0/src/tclsqlite.c (revision efc251da)
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*efc251daSdrh ** $Id: tclsqlite.c,v 1.20 2001/07/01 22:12:02 drh Exp $
2775897234Sdrh */
286d31316cSdrh #ifndef NO_TCL     /* Omit this whole file if TCL is unavailable */
296d31316cSdrh 
3075897234Sdrh #include "sqlite.h"
3117a68934Sdrh #include "tcl.h"
3275897234Sdrh #include <stdlib.h>
3375897234Sdrh #include <string.h>
3475897234Sdrh 
3575897234Sdrh /*
36bec3f402Sdrh ** There is one instance of this structure for each SQLite database
37bec3f402Sdrh ** that has been opened by the SQLite TCL interface.
38bec3f402Sdrh */
39bec3f402Sdrh typedef struct SqliteDb SqliteDb;
40bec3f402Sdrh struct SqliteDb {
41bec3f402Sdrh   sqlite *db;           /* The "real" database structure */
42bec3f402Sdrh   Tcl_Interp *interp;   /* The interpreter used for this database */
436d31316cSdrh   char *zBusy;          /* The busy callback routine */
44bec3f402Sdrh };
45bec3f402Sdrh 
46bec3f402Sdrh /*
4775897234Sdrh ** An instance of this structure passes information thru the sqlite
4875897234Sdrh ** logic from the original TCL command into the callback routine.
4975897234Sdrh */
5075897234Sdrh typedef struct CallbackData CallbackData;
5175897234Sdrh struct CallbackData {
5275897234Sdrh   Tcl_Interp *interp;       /* The TCL interpreter */
5375897234Sdrh   char *zArray;             /* The array into which data is written */
546d31316cSdrh   Tcl_Obj *pCode;           /* The code to execute for each row */
5575897234Sdrh   int once;                 /* Set only for the first invocation of callback */
56960e8c63Sdrh   int tcl_rc;               /* Return code from TCL script */
5775897234Sdrh };
5875897234Sdrh 
5975897234Sdrh /*
60297ecf14Sdrh ** If TCL uses UTF-8 and SQLite is configured to use iso8859, then we
61297ecf14Sdrh ** have to do a translation when going between the two.  Set the
62297ecf14Sdrh ** UTF_TRANSLATION_NEEDED macro to indicate that we need to do
63297ecf14Sdrh ** this translation.
64297ecf14Sdrh */
65297ecf14Sdrh #if defined(TCL_UTF_MAX) && !defined(SQLITE_UTF8)
66297ecf14Sdrh # define UTF_TRANSLATION_NEEDED 1
67297ecf14Sdrh #endif
68297ecf14Sdrh 
69297ecf14Sdrh /*
7075897234Sdrh ** Called for each row of the result.
7175897234Sdrh */
7275897234Sdrh static int DbEvalCallback(
7375897234Sdrh   void *clientData,      /* An instance of CallbackData */
7475897234Sdrh   int nCol,              /* Number of columns in the result */
7575897234Sdrh   char ** azCol,         /* Data for each column */
7675897234Sdrh   char ** azN            /* Name for each column */
7775897234Sdrh ){
7875897234Sdrh   CallbackData *cbData = (CallbackData*)clientData;
7975897234Sdrh   int i, rc;
80297ecf14Sdrh #ifdef UTF_TRANSLATION_NEEDED
81297ecf14Sdrh   Tcl_DString dCol;
82297ecf14Sdrh #endif
8375897234Sdrh   if( cbData->zArray[0] ){
8475897234Sdrh     if( cbData->once ){
859b0d0a8bSdrh       Tcl_SetVar2(cbData->interp, cbData->zArray, "*", "", 0);
8675897234Sdrh       for(i=0; i<nCol; i++){
8775897234Sdrh         Tcl_SetVar2(cbData->interp, cbData->zArray, "*", azN[i],
8875897234Sdrh            TCL_LIST_ELEMENT|TCL_APPEND_VALUE);
8975897234Sdrh       }
9075897234Sdrh     }
9175897234Sdrh     for(i=0; i<nCol; i++){
92c61053b7Sdrh       char *z = azCol[i];
93c61053b7Sdrh       if( z==0 ) z = "";
94297ecf14Sdrh #ifdef UTF_TRANSLATION_NEEDED
95297ecf14Sdrh       Tcl_DStringInit(&dCol);
96297ecf14Sdrh       Tcl_ExternalToUtfDString(NULL, z, -1, &dCol);
97297ecf14Sdrh       Tcl_SetVar2(cbData->interp, cbData->zArray, azN[i],
98297ecf14Sdrh             Tcl_DStringValue(&dCol), 0);
99297ecf14Sdrh       Tcl_DStringFree(&dCol);
100297ecf14Sdrh #else
101c61053b7Sdrh       Tcl_SetVar2(cbData->interp, cbData->zArray, azN[i], z, 0);
102297ecf14Sdrh #endif
10375897234Sdrh     }
10475897234Sdrh   }else{
10575897234Sdrh     for(i=0; i<nCol; i++){
106c61053b7Sdrh       char *z = azCol[i];
107c61053b7Sdrh       if( z==0 ) z = "";
108297ecf14Sdrh #ifdef UTF_TRANSLATION_NEEDED
109297ecf14Sdrh       Tcl_DStringInit(&dCol);
110297ecf14Sdrh       Tcl_ExternalToUtfDString(NULL, z, -1, &dCol);
111297ecf14Sdrh       Tcl_SetVar(cbData->interp, azN[i], Tcl_DStringValue(&dCol), 0);
112297ecf14Sdrh       Tcl_DStringFree(&dCol);
113297ecf14Sdrh #else
114c61053b7Sdrh       Tcl_SetVar(cbData->interp, azN[i], z, 0);
115297ecf14Sdrh #endif
11675897234Sdrh     }
11775897234Sdrh   }
11875897234Sdrh   cbData->once = 0;
1196d31316cSdrh   rc = Tcl_EvalObj(cbData->interp, cbData->pCode);
120960e8c63Sdrh   if( rc==TCL_CONTINUE ) rc = TCL_OK;
121960e8c63Sdrh   cbData->tcl_rc = rc;
122960e8c63Sdrh   return rc!=TCL_OK;
12375897234Sdrh }
12475897234Sdrh 
12575897234Sdrh /*
1266d31316cSdrh ** This is an alternative callback for database queries.  Instead
1276d31316cSdrh ** of invoking a TCL script to handle the result, this callback just
1286d31316cSdrh ** appends each column of the result to a list.  After the query
1296d31316cSdrh ** is complete, the list is returned.
1306d31316cSdrh */
1316d31316cSdrh static int DbEvalCallback2(
1326d31316cSdrh   void *clientData,      /* An instance of CallbackData */
1336d31316cSdrh   int nCol,              /* Number of columns in the result */
1346d31316cSdrh   char ** azCol,         /* Data for each column */
1356d31316cSdrh   char ** azN            /* Name for each column */
1366d31316cSdrh ){
1376d31316cSdrh   Tcl_Obj *pList = (Tcl_Obj*)clientData;
1386d31316cSdrh   int i;
1396d31316cSdrh   for(i=0; i<nCol; i++){
1406d31316cSdrh     Tcl_Obj *pElem;
1416d31316cSdrh     if( azCol[i] && *azCol[i] ){
142297ecf14Sdrh #ifdef UTF_TRANSLATION_NEEDED
143297ecf14Sdrh       Tcl_DString dCol;
144297ecf14Sdrh       Tcl_DStringInit(&dCol);
145297ecf14Sdrh       Tcl_ExternalToUtfDString(NULL, azCol[i], -1, &dCol);
146297ecf14Sdrh       pElem = Tcl_NewStringObj(Tcl_DStringValue(&dCol), -1);
147297ecf14Sdrh       Tcl_DStringFree(&dCol);
148297ecf14Sdrh #else
1496d31316cSdrh       pElem = Tcl_NewStringObj(azCol[i], -1);
150297ecf14Sdrh #endif
1516d31316cSdrh     }else{
1526d31316cSdrh       pElem = Tcl_NewObj();
1536d31316cSdrh     }
1546d31316cSdrh     Tcl_ListObjAppendElement(0, pList, pElem);
1556d31316cSdrh   }
1566d31316cSdrh   return 0;
1576d31316cSdrh }
1586d31316cSdrh 
1596d31316cSdrh /*
16075897234Sdrh ** Called when the command is deleted.
16175897234Sdrh */
16275897234Sdrh static void DbDeleteCmd(void *db){
163bec3f402Sdrh   SqliteDb *pDb = (SqliteDb*)db;
164bec3f402Sdrh   sqlite_close(pDb->db);
165bec3f402Sdrh   if( pDb->zBusy ){
166bec3f402Sdrh     Tcl_Free(pDb->zBusy);
167bec3f402Sdrh   }
168bec3f402Sdrh   Tcl_Free((char*)pDb);
169bec3f402Sdrh }
170bec3f402Sdrh 
171bec3f402Sdrh /*
172bec3f402Sdrh ** This routine is called when a database file is locked while trying
173bec3f402Sdrh ** to execute SQL.
174bec3f402Sdrh */
175bec3f402Sdrh static int DbBusyHandler(void *cd, const char *zTable, int nTries){
176bec3f402Sdrh   SqliteDb *pDb = (SqliteDb*)cd;
177bec3f402Sdrh   int rc;
178bec3f402Sdrh   char zVal[30];
179bec3f402Sdrh   char *zCmd;
180bec3f402Sdrh   Tcl_DString cmd;
181bec3f402Sdrh 
182bec3f402Sdrh   Tcl_DStringInit(&cmd);
183bec3f402Sdrh   Tcl_DStringAppend(&cmd, pDb->zBusy, -1);
184bec3f402Sdrh   Tcl_DStringAppendElement(&cmd, zTable);
185bec3f402Sdrh   sprintf(zVal, " %d", nTries);
186bec3f402Sdrh   Tcl_DStringAppend(&cmd, zVal, -1);
187bec3f402Sdrh   zCmd = Tcl_DStringValue(&cmd);
188bec3f402Sdrh   rc = Tcl_Eval(pDb->interp, zCmd);
189bec3f402Sdrh   Tcl_DStringFree(&cmd);
190bec3f402Sdrh   if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){
191bec3f402Sdrh     return 0;
192bec3f402Sdrh   }
193bec3f402Sdrh   return 1;
19475897234Sdrh }
19575897234Sdrh 
19675897234Sdrh /*
19775897234Sdrh ** The "sqlite" command below creates a new Tcl command for each
19875897234Sdrh ** connection it opens to an SQLite database.  This routine is invoked
19975897234Sdrh ** whenever one of those connection-specific commands is executed
20075897234Sdrh ** in Tcl.  For example, if you run Tcl code like this:
20175897234Sdrh **
20275897234Sdrh **       sqlite db1  "my_database"
20375897234Sdrh **       db1 close
20475897234Sdrh **
20575897234Sdrh ** The first command opens a connection to the "my_database" database
20675897234Sdrh ** and calls that connection "db1".  The second command causes this
20775897234Sdrh ** subroutine to be invoked.
20875897234Sdrh */
2096d31316cSdrh static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
210bec3f402Sdrh   SqliteDb *pDb = (SqliteDb*)cd;
2116d31316cSdrh   int choice;
2126d31316cSdrh   static char *DB_optStrs[] = {
213960e8c63Sdrh      "busy",   "close",  "complete",  "eval",  "timeout", 0
2146d31316cSdrh   };
2156d31316cSdrh   enum DB_opts {
2166d31316cSdrh      DB_BUSY,  DB_CLOSE, DB_COMPLETE, DB_EVAL, DB_TIMEOUT
2176d31316cSdrh   };
2186d31316cSdrh 
2196d31316cSdrh   if( objc<2 ){
2206d31316cSdrh     Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");
22175897234Sdrh     return TCL_ERROR;
22275897234Sdrh   }
2236d31316cSdrh   if( Tcl_GetIndexFromObj(interp, objv[1], DB_optStrs, "option", 0, &choice) ){
2246d31316cSdrh     return TCL_ERROR;
2256d31316cSdrh   }
2266d31316cSdrh 
2276d31316cSdrh   switch( (enum DB_opts)choice ){
22875897234Sdrh 
229bec3f402Sdrh   /*    $db busy ?CALLBACK?
230bec3f402Sdrh   **
231bec3f402Sdrh   ** Invoke the given callback if an SQL statement attempts to open
232bec3f402Sdrh   ** a locked database file.
233bec3f402Sdrh   */
2346d31316cSdrh   case DB_BUSY: {
2356d31316cSdrh     if( objc>3 ){
2366d31316cSdrh       Tcl_WrongNumArgs(interp, 2, objv, "CALLBACK");
237bec3f402Sdrh       return TCL_ERROR;
2386d31316cSdrh     }else if( objc==2 ){
239bec3f402Sdrh       if( pDb->zBusy ){
240bec3f402Sdrh         Tcl_AppendResult(interp, pDb->zBusy, 0);
241bec3f402Sdrh       }
242bec3f402Sdrh     }else{
2436d31316cSdrh       char *zBusy;
2446d31316cSdrh       int len;
245bec3f402Sdrh       if( pDb->zBusy ){
246bec3f402Sdrh         Tcl_Free(pDb->zBusy);
2476d31316cSdrh       }
2486d31316cSdrh       zBusy = Tcl_GetStringFromObj(objv[2], &len);
2496d31316cSdrh       if( zBusy && len>0 ){
2506d31316cSdrh         pDb->zBusy = Tcl_Alloc( len + 1 );
2516d31316cSdrh         strcpy(pDb->zBusy, zBusy);
2526d31316cSdrh       }else{
253bec3f402Sdrh         pDb->zBusy = 0;
254bec3f402Sdrh       }
255bec3f402Sdrh       if( pDb->zBusy ){
256bec3f402Sdrh         pDb->interp = interp;
257bec3f402Sdrh         sqlite_busy_handler(pDb->db, DbBusyHandler, pDb);
2586d31316cSdrh       }else{
2596d31316cSdrh         sqlite_busy_handler(pDb->db, 0, 0);
260bec3f402Sdrh       }
261bec3f402Sdrh     }
2626d31316cSdrh     break;
2636d31316cSdrh   }
264bec3f402Sdrh 
26575897234Sdrh   /*    $db close
26675897234Sdrh   **
26775897234Sdrh   ** Shutdown the database
26875897234Sdrh   */
2696d31316cSdrh   case DB_CLOSE: {
2706d31316cSdrh     Tcl_DeleteCommand(interp, Tcl_GetStringFromObj(objv[0], 0));
2716d31316cSdrh     break;
2726d31316cSdrh   }
27375897234Sdrh 
27475897234Sdrh   /*    $db complete SQL
27575897234Sdrh   **
27675897234Sdrh   ** Return TRUE if SQL is a complete SQL statement.  Return FALSE if
27775897234Sdrh   ** additional lines of input are needed.  This is similar to the
27875897234Sdrh   ** built-in "info complete" command of Tcl.
27975897234Sdrh   */
2806d31316cSdrh   case DB_COMPLETE: {
2816d31316cSdrh     Tcl_Obj *pResult;
2826d31316cSdrh     int isComplete;
2836d31316cSdrh     if( objc!=3 ){
2846d31316cSdrh       Tcl_WrongNumArgs(interp, 2, objv, "SQL");
28575897234Sdrh       return TCL_ERROR;
28675897234Sdrh     }
2876d31316cSdrh     isComplete = sqlite_complete( Tcl_GetStringFromObj(objv[2], 0) );
2886d31316cSdrh     pResult = Tcl_GetObjResult(interp);
2896d31316cSdrh     Tcl_SetBooleanObj(pResult, isComplete);
2906d31316cSdrh     break;
2916d31316cSdrh   }
29275897234Sdrh 
29375897234Sdrh   /*
29475897234Sdrh   **    $db eval $sql ?array {  ...code... }?
29575897234Sdrh   **
29675897234Sdrh   ** The SQL statement in $sql is evaluated.  For each row, the values are
297bec3f402Sdrh   ** placed in elements of the array named "array" and ...code... is executed.
29875897234Sdrh   ** If "array" and "code" are omitted, then no callback is every invoked.
29975897234Sdrh   ** If "array" is an empty string, then the values are placed in variables
30075897234Sdrh   ** that have the same name as the fields extracted by the query.
30175897234Sdrh   */
3026d31316cSdrh   case DB_EVAL: {
30375897234Sdrh     CallbackData cbData;
30475897234Sdrh     char *zErrMsg;
3056d31316cSdrh     char *zSql;
30675897234Sdrh     int rc;
307297ecf14Sdrh #ifdef UTF_TRANSLATION_NEEDED
308297ecf14Sdrh     Tcl_DString dSql;
309297ecf14Sdrh #endif
31075897234Sdrh 
3116d31316cSdrh     if( objc!=5 && objc!=3 ){
3126d31316cSdrh       Tcl_WrongNumArgs(interp, 2, objv, "SQL ?ARRAY-NAME CODE?");
31375897234Sdrh       return TCL_ERROR;
31475897234Sdrh     }
315bec3f402Sdrh     pDb->interp = interp;
3166d31316cSdrh     zSql = Tcl_GetStringFromObj(objv[2], 0);
317297ecf14Sdrh #ifdef UTF_TRANSLATION_NEEDED
318297ecf14Sdrh     Tcl_DStringInit(&dSql);
319297ecf14Sdrh     Tcl_UtfToExternalDString(NULL, zSql, -1, &dSql);
320297ecf14Sdrh     zSql = Tcl_DStringValue(&dSql);
321297ecf14Sdrh #endif
3226d31316cSdrh     Tcl_IncrRefCount(objv[2]);
3236d31316cSdrh     if( objc==5 ){
32475897234Sdrh       cbData.interp = interp;
325dcc581ccSdrh       cbData.once = 1;
3266d31316cSdrh       cbData.zArray = Tcl_GetStringFromObj(objv[3], 0);
3276d31316cSdrh       cbData.pCode = objv[4];
328960e8c63Sdrh       cbData.tcl_rc = TCL_OK;
32975897234Sdrh       zErrMsg = 0;
3306d31316cSdrh       Tcl_IncrRefCount(objv[3]);
3316d31316cSdrh       Tcl_IncrRefCount(objv[4]);
3326d31316cSdrh       rc = sqlite_exec(pDb->db, zSql, DbEvalCallback, &cbData, &zErrMsg);
3336d31316cSdrh       Tcl_DecrRefCount(objv[4]);
3346d31316cSdrh       Tcl_DecrRefCount(objv[3]);
335960e8c63Sdrh       if( cbData.tcl_rc==TCL_BREAK ){ cbData.tcl_rc = TCL_OK; }
33675897234Sdrh     }else{
3376d31316cSdrh       Tcl_Obj *pList = Tcl_NewObj();
338960e8c63Sdrh       cbData.tcl_rc = TCL_OK;
3396d31316cSdrh       rc = sqlite_exec(pDb->db, zSql, DbEvalCallback2, pList, &zErrMsg);
3406d31316cSdrh       Tcl_SetObjResult(interp, pList);
34175897234Sdrh     }
34275897234Sdrh     if( zErrMsg ){
34375897234Sdrh       Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE);
34475897234Sdrh       free(zErrMsg);
345960e8c63Sdrh       rc = TCL_ERROR;
346960e8c63Sdrh     }else{
347960e8c63Sdrh       rc = cbData.tcl_rc;
34875897234Sdrh     }
3496d31316cSdrh     Tcl_DecrRefCount(objv[2]);
350297ecf14Sdrh #ifdef UTF_TRANSLATION_NEEDED
351297ecf14Sdrh     Tcl_DStringFree(&dSql);
352297ecf14Sdrh #endif
35375897234Sdrh     return rc;
3546d31316cSdrh   }
355bec3f402Sdrh 
356bec3f402Sdrh   /*
357bec3f402Sdrh   **     $db timeout MILLESECONDS
358bec3f402Sdrh   **
359bec3f402Sdrh   ** Delay for the number of milliseconds specified when a file is locked.
360bec3f402Sdrh   */
3616d31316cSdrh   case DB_TIMEOUT: {
362bec3f402Sdrh     int ms;
3636d31316cSdrh     if( objc!=3 ){
3646d31316cSdrh       Tcl_WrongNumArgs(interp, 2, objv, "MILLISECONDS");
365bec3f402Sdrh       return TCL_ERROR;
36675897234Sdrh     }
3676d31316cSdrh     if( Tcl_GetIntFromObj(interp, objv[2], &ms) ) return TCL_ERROR;
368bec3f402Sdrh     sqlite_busy_timeout(pDb->db, ms);
3696d31316cSdrh     break;
37075897234Sdrh   }
3716d31316cSdrh   } /* End of the SWITCH statement */
37275897234Sdrh   return TCL_OK;
37375897234Sdrh }
37475897234Sdrh 
37575897234Sdrh /*
37675897234Sdrh **   sqlite DBNAME FILENAME ?MODE?
37775897234Sdrh **
37875897234Sdrh ** This is the main Tcl command.  When the "sqlite" Tcl command is
37975897234Sdrh ** invoked, this routine runs to process that command.
38075897234Sdrh **
38175897234Sdrh ** The first argument, DBNAME, is an arbitrary name for a new
38275897234Sdrh ** database connection.  This command creates a new command named
38375897234Sdrh ** DBNAME that is used to control that connection.  The database
38475897234Sdrh ** connection is deleted when the DBNAME command is deleted.
38575897234Sdrh **
38675897234Sdrh ** The second argument is the name of the directory that contains
38775897234Sdrh ** the sqlite database that is to be accessed.
388fbc3eab8Sdrh **
389fbc3eab8Sdrh ** For testing purposes, we also support the following:
390fbc3eab8Sdrh **
391fbc3eab8Sdrh **  sqlite -encoding
392fbc3eab8Sdrh **
393fbc3eab8Sdrh **       Return the encoding used by LIKE and GLOB operators.  Choices
394fbc3eab8Sdrh **       are UTF-8 and iso8859.
395fbc3eab8Sdrh **
396fbc3eab8Sdrh **  sqlite -tcl-uses-utf
397fbc3eab8Sdrh **
398fbc3eab8Sdrh **       Return "1" if compiled with a Tcl uses UTF-8.  Return "0" if
399fbc3eab8Sdrh **       not.  Used by tests to make sure the library was compiled
400fbc3eab8Sdrh **       correctly.
40175897234Sdrh */
40275897234Sdrh static int DbMain(void *cd, Tcl_Interp *interp, int argc, char **argv){
40375897234Sdrh   int mode;
404bec3f402Sdrh   SqliteDb *p;
40575897234Sdrh   char *zErrMsg;
406fbc3eab8Sdrh   if( argc==2 ){
407fbc3eab8Sdrh     if( strcmp(argv[1],"-encoding")==0 ){
408fbc3eab8Sdrh       Tcl_AppendResult(interp,sqlite_encoding,0);
409fbc3eab8Sdrh       return TCL_OK;
410fbc3eab8Sdrh     }
411fbc3eab8Sdrh     if( strcmp(argv[1],"-tcl-uses-utf")==0 ){
412fbc3eab8Sdrh #ifdef TCL_UTF_MAX
413fbc3eab8Sdrh       Tcl_AppendResult(interp,"1",0);
414fbc3eab8Sdrh #else
415fbc3eab8Sdrh       Tcl_AppendResult(interp,"0",0);
416fbc3eab8Sdrh #endif
417fbc3eab8Sdrh       return TCL_OK;
418fbc3eab8Sdrh     }
419fbc3eab8Sdrh   }
42075897234Sdrh   if( argc!=3 && argc!=4 ){
42175897234Sdrh     Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
42275897234Sdrh        " HANDLE FILENAME ?MODE?\"", 0);
42375897234Sdrh     return TCL_ERROR;
42475897234Sdrh   }
42575897234Sdrh   if( argc==3 ){
42658b9576bSdrh     mode = 0666;
42775897234Sdrh   }else if( Tcl_GetInt(interp, argv[3], &mode)!=TCL_OK ){
42875897234Sdrh     return TCL_ERROR;
42975897234Sdrh   }
43075897234Sdrh   zErrMsg = 0;
4314cdc9e84Sdrh   p = (SqliteDb*)Tcl_Alloc( sizeof(*p) );
43275897234Sdrh   if( p==0 ){
433bec3f402Sdrh     Tcl_SetResult(interp, "malloc failed", TCL_STATIC);
434bec3f402Sdrh     return TCL_ERROR;
435bec3f402Sdrh   }
436bec3f402Sdrh   memset(p, 0, sizeof(*p));
437bec3f402Sdrh   p->db = sqlite_open(argv[2], mode, &zErrMsg);
438bec3f402Sdrh   if( p->db==0 ){
43975897234Sdrh     Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE);
440bec3f402Sdrh     Tcl_Free((char*)p);
44175897234Sdrh     free(zErrMsg);
44275897234Sdrh     return TCL_ERROR;
44375897234Sdrh   }
4446d31316cSdrh   Tcl_CreateObjCommand(interp, argv[1], DbObjCmd, (char*)p, DbDeleteCmd);
44575897234Sdrh   return TCL_OK;
44675897234Sdrh }
44775897234Sdrh 
44875897234Sdrh /*
44975897234Sdrh ** Initialize this module.
45075897234Sdrh **
45175897234Sdrh ** This Tcl module contains only a single new Tcl command named "sqlite".
45275897234Sdrh ** (Hence there is no namespace.  There is no point in using a namespace
45375897234Sdrh ** if the extension only supplies one new name!)  The "sqlite" command is
45475897234Sdrh ** used to open a new SQLite database.  See the DbMain() routine above
45575897234Sdrh ** for additional information.
45675897234Sdrh */
45775897234Sdrh int Sqlite_Init(Tcl_Interp *interp){
45875897234Sdrh   Tcl_CreateCommand(interp, "sqlite", DbMain, 0, 0);
459167a4b1cSdrh   Tcl_PkgProvide(interp, "sqlite", "1.0");
46075897234Sdrh   return TCL_OK;
46175897234Sdrh }
46275897234Sdrh int Sqlite_SafeInit(Tcl_Interp *interp){
46375897234Sdrh   return TCL_OK;
46475897234Sdrh }
46575897234Sdrh 
4663cebbde3Sdrh #if 0
46775897234Sdrh /*
46875897234Sdrh ** If compiled using mktclapp, this routine runs to initialize
46975897234Sdrh ** everything.
47075897234Sdrh */
47175897234Sdrh int Et_AppInit(Tcl_Interp *interp){
47275897234Sdrh   return Sqlite_Init(interp);
47375897234Sdrh }
4743cebbde3Sdrh #endif
475348784efSdrh 
476348784efSdrh /*
477348784efSdrh ** If the macro TCLSH is defined and is one, then put in code for the
478348784efSdrh ** "main" routine that will initialize Tcl.
479348784efSdrh */
480348784efSdrh #if defined(TCLSH) && TCLSH==1
481348784efSdrh static char zMainloop[] =
482348784efSdrh   "set line {}\n"
483348784efSdrh   "while {![eof stdin]} {\n"
484348784efSdrh     "if {$line!=\"\"} {\n"
485348784efSdrh       "puts -nonewline \"> \"\n"
486348784efSdrh     "} else {\n"
487348784efSdrh       "puts -nonewline \"% \"\n"
488348784efSdrh     "}\n"
489348784efSdrh     "flush stdout\n"
490348784efSdrh     "append line [gets stdin]\n"
491348784efSdrh     "if {[info complete $line]} {\n"
492348784efSdrh       "if {[catch {uplevel #0 $line} result]} {\n"
493348784efSdrh         "puts stderr \"Error: $result\"\n"
494348784efSdrh       "} elseif {$result!=\"\"} {\n"
495348784efSdrh         "puts $result\n"
496348784efSdrh       "}\n"
497348784efSdrh       "set line {}\n"
498348784efSdrh     "} else {\n"
499348784efSdrh       "append line \\n\n"
500348784efSdrh     "}\n"
501348784efSdrh   "}\n"
502348784efSdrh ;
503348784efSdrh 
504348784efSdrh #define TCLSH_MAIN main   /* Needed to fake out mktclapp */
505348784efSdrh int TCLSH_MAIN(int argc, char **argv){
506348784efSdrh   Tcl_Interp *interp;
507297ecf14Sdrh   Tcl_FindExecutable(argv[0]);
508348784efSdrh   interp = Tcl_CreateInterp();
509348784efSdrh   Sqlite_Init(interp);
510d9b0257aSdrh #ifdef SQLITE_TEST
511d1bf3512Sdrh   {
512d1bf3512Sdrh     extern int Sqlitetest1_Init(Tcl_Interp*);
513d9b0257aSdrh     extern int Sqlitetest2_Init(Tcl_Interp*);
5148c42ca93Sdrh     extern int Sqlitetest3_Init(Tcl_Interp*);
515*efc251daSdrh     extern int Md5_Init(Tcl_Interp*);
516d1bf3512Sdrh     Sqlitetest1_Init(interp);
517d9b0257aSdrh     Sqlitetest2_Init(interp);
5188c42ca93Sdrh     Sqlitetest3_Init(interp);
519*efc251daSdrh     Md5_Init(interp);
520d1bf3512Sdrh   }
521d1bf3512Sdrh #endif
522348784efSdrh   if( argc>=2 ){
523348784efSdrh     int i;
524348784efSdrh     Tcl_SetVar(interp,"argv0",argv[1],TCL_GLOBAL_ONLY);
525348784efSdrh     Tcl_SetVar(interp,"argv", "", TCL_GLOBAL_ONLY);
526348784efSdrh     for(i=2; i<argc; i++){
527348784efSdrh       Tcl_SetVar(interp, "argv", argv[i],
528348784efSdrh           TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT | TCL_APPEND_VALUE);
529348784efSdrh     }
530348784efSdrh     if( Tcl_EvalFile(interp, argv[1])!=TCL_OK ){
531c61053b7Sdrh       char *zInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
532c61053b7Sdrh       if( zInfo==0 ) zInfo = interp->result;
533c61053b7Sdrh       fprintf(stderr,"%s: %s\n", *argv, zInfo);
534348784efSdrh       return 1;
535348784efSdrh     }
536348784efSdrh   }else{
537348784efSdrh     Tcl_GlobalEval(interp, zMainloop);
538348784efSdrh   }
539348784efSdrh   return 0;
540348784efSdrh }
541348784efSdrh #endif /* TCLSH */
5426d31316cSdrh 
5436d31316cSdrh #endif /* !defined(NO_TCL) */
544