blob: dc9894c71e8a10dfc649d8713b16f2055439ad80 [file] [log] [blame]
drh75897232000-05-29 14:26:00 +00001/*
2** Copyright (c) 1999, 2000 D. Richard Hipp
3**
4** This program is free software; you can redistribute it and/or
5** modify it under the terms of the GNU General Public
6** License as published by the Free Software Foundation; either
7** version 2 of the License, or (at your option) any later version.
8**
9** This program is distributed in the hope that it will be useful,
10** but WITHOUT ANY WARRANTY; without even the implied warranty of
11** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12** General Public License for more details.
13**
14** You should have received a copy of the GNU General Public
15** License along with this library; if not, write to the
16** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17** Boston, MA 02111-1307, USA.
18**
19** Author contact information:
20** drh@hwaci.com
21** http://www.hwaci.com/drh/
22**
23*************************************************************************
24** A TCL Interface to SQLite
25**
drh4cdc9e82000-08-04 14:56:24 +000026** $Id: tclsqlite.c,v 1.7 2000/08/04 14:56:25 drh Exp $
drh75897232000-05-29 14:26:00 +000027*/
28#include "sqlite.h"
29#include <tcl.h>
30#include <stdlib.h>
31#include <string.h>
32
33/*
drhbec3f402000-08-04 13:49:02 +000034** There is one instance of this structure for each SQLite database
35** that has been opened by the SQLite TCL interface.
36*/
37typedef struct SqliteDb SqliteDb;
38struct SqliteDb {
39 sqlite *db; /* The "real" database structure */
40 Tcl_Interp *interp; /* The interpreter used for this database */
41 char *zBusy; /* The name of the busy callback routine */
42};
43
44/*
drh75897232000-05-29 14:26:00 +000045** An instance of this structure passes information thru the sqlite
46** logic from the original TCL command into the callback routine.
47*/
48typedef struct CallbackData CallbackData;
49struct CallbackData {
50 Tcl_Interp *interp; /* The TCL interpreter */
51 char *zArray; /* The array into which data is written */
52 char *zCode; /* The code to execute for each row */
53 int once; /* Set only for the first invocation of callback */
54};
55
56/*
57** Called for each row of the result.
58*/
59static int DbEvalCallback(
60 void *clientData, /* An instance of CallbackData */
61 int nCol, /* Number of columns in the result */
62 char ** azCol, /* Data for each column */
63 char ** azN /* Name for each column */
64){
65 CallbackData *cbData = (CallbackData*)clientData;
66 int i, rc;
67 if( cbData->zArray[0] ){
68 if( cbData->once ){
69 for(i=0; i<nCol; i++){
70 Tcl_SetVar2(cbData->interp, cbData->zArray, "*", azN[i],
71 TCL_LIST_ELEMENT|TCL_APPEND_VALUE);
72 }
73 }
74 for(i=0; i<nCol; i++){
drhc61053b2000-06-04 12:58:36 +000075 char *z = azCol[i];
76 if( z==0 ) z = "";
77 Tcl_SetVar2(cbData->interp, cbData->zArray, azN[i], z, 0);
drh75897232000-05-29 14:26:00 +000078 }
79 }else{
80 for(i=0; i<nCol; i++){
drhc61053b2000-06-04 12:58:36 +000081 char *z = azCol[i];
82 if( z==0 ) z = "";
83 Tcl_SetVar(cbData->interp, azN[i], z, 0);
drh75897232000-05-29 14:26:00 +000084 }
85 }
86 cbData->once = 0;
87 rc = Tcl_Eval(cbData->interp, cbData->zCode);
88 return rc;
89}
90
91/*
92** Called when the command is deleted.
93*/
94static void DbDeleteCmd(void *db){
drhbec3f402000-08-04 13:49:02 +000095 SqliteDb *pDb = (SqliteDb*)db;
96 sqlite_close(pDb->db);
97 if( pDb->zBusy ){
98 Tcl_Free(pDb->zBusy);
99 }
100 Tcl_Free((char*)pDb);
101}
102
103/*
104** This routine is called when a database file is locked while trying
105** to execute SQL.
106*/
107static int DbBusyHandler(void *cd, const char *zTable, int nTries){
108 SqliteDb *pDb = (SqliteDb*)cd;
109 int rc;
110 char zVal[30];
111 char *zCmd;
112 char *zResult;
113 Tcl_DString cmd;
114
115 Tcl_DStringInit(&cmd);
116 Tcl_DStringAppend(&cmd, pDb->zBusy, -1);
117 Tcl_DStringAppendElement(&cmd, zTable);
118 sprintf(zVal, " %d", nTries);
119 Tcl_DStringAppend(&cmd, zVal, -1);
120 zCmd = Tcl_DStringValue(&cmd);
121 rc = Tcl_Eval(pDb->interp, zCmd);
122 Tcl_DStringFree(&cmd);
123 if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){
124 return 0;
125 }
126 return 1;
drh75897232000-05-29 14:26:00 +0000127}
128
129/*
130** The "sqlite" command below creates a new Tcl command for each
131** connection it opens to an SQLite database. This routine is invoked
132** whenever one of those connection-specific commands is executed
133** in Tcl. For example, if you run Tcl code like this:
134**
135** sqlite db1 "my_database"
136** db1 close
137**
138** The first command opens a connection to the "my_database" database
139** and calls that connection "db1". The second command causes this
140** subroutine to be invoked.
141*/
142static int DbCmd(void *cd, Tcl_Interp *interp, int argc, char **argv){
143 char *z;
144 int n, c;
drhbec3f402000-08-04 13:49:02 +0000145 SqliteDb *pDb = (SqliteDb*)cd;
drh75897232000-05-29 14:26:00 +0000146 if( argc<2 ){
147 Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
148 " SUBCOMMAND ...\"", 0);
149 return TCL_ERROR;
150 }
151 z = argv[1];
152 n = strlen(z);
153 c = z[0];
154
drhbec3f402000-08-04 13:49:02 +0000155 /* $db busy ?CALLBACK?
156 **
157 ** Invoke the given callback if an SQL statement attempts to open
158 ** a locked database file.
159 */
160 if( c=='b' && strncmp(z,"busy",n)==0 ){
161 if( argc>3 ){
162 Tcl_AppendResult(interp,"wrong # args: should be \"",
163 argv[0], " busy ?CALLBACK?", 0);
164 return TCL_ERROR;
165 }else if( argc==2 ){
166 if( pDb->zBusy ){
167 Tcl_AppendResult(interp, pDb->zBusy, 0);
168 }
169 }else{
170 if( pDb->zBusy ){
171 Tcl_Free(pDb->zBusy);
172 pDb->zBusy = 0;
173 }
174 if( argv[2][0] ){
175 pDb->zBusy = Tcl_Alloc( strlen(argv[2]) + 1 );
176 if( pDb->zBusy ){
177 strcpy(pDb->zBusy, argv[2]);
178 }
179 }
180 if( pDb->zBusy ){
181 pDb->interp = interp;
182 sqlite_busy_handler(pDb->db, DbBusyHandler, pDb);
183 }
184 }
185 }else
186
drh75897232000-05-29 14:26:00 +0000187 /* $db close
188 **
189 ** Shutdown the database
190 */
191 if( c=='c' && n>=2 && strncmp(z,"close",n)==0 ){
192 Tcl_DeleteCommand(interp, argv[0]);
193 }else
194
195 /* $db complete SQL
196 **
197 ** Return TRUE if SQL is a complete SQL statement. Return FALSE if
198 ** additional lines of input are needed. This is similar to the
199 ** built-in "info complete" command of Tcl.
200 */
201 if( c=='c' && n>=2 && strncmp(z,"complete",n)==0 ){
202 char *zRes;
203 if( argc!=3 ){
204 Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
205 " complete SQL\"", 0);
206 return TCL_ERROR;
207 }
208 zRes = sqlite_complete(argv[2]) ? "1" : "0";
209 Tcl_SetResult(interp, zRes, TCL_VOLATILE);
210 }else
211
212 /*
213 ** $db eval $sql ?array { ...code... }?
214 **
215 ** The SQL statement in $sql is evaluated. For each row, the values are
drhbec3f402000-08-04 13:49:02 +0000216 ** placed in elements of the array named "array" and ...code... is executed.
drh75897232000-05-29 14:26:00 +0000217 ** If "array" and "code" are omitted, then no callback is every invoked.
218 ** If "array" is an empty string, then the values are placed in variables
219 ** that have the same name as the fields extracted by the query.
220 */
221 if( c=='e' && strncmp(z,"eval",n)==0 ){
222 CallbackData cbData;
223 char *zErrMsg;
224 int rc;
225
226 if( argc!=5 && argc!=3 ){
227 Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
228 " eval SQL ?ARRAY-NAME CODE?", 0);
229 return TCL_ERROR;
230 }
drhbec3f402000-08-04 13:49:02 +0000231 pDb->interp = interp;
drh75897232000-05-29 14:26:00 +0000232 if( argc==5 ){
233 cbData.interp = interp;
drhdcc581c2000-05-30 13:44:19 +0000234 cbData.once = 1;
drh75897232000-05-29 14:26:00 +0000235 cbData.zArray = argv[3];
236 cbData.zCode = argv[4];
237 zErrMsg = 0;
drhbec3f402000-08-04 13:49:02 +0000238 rc = sqlite_exec(pDb->db, argv[2], DbEvalCallback, &cbData, &zErrMsg);
drh75897232000-05-29 14:26:00 +0000239 }else{
drhbec3f402000-08-04 13:49:02 +0000240 rc = sqlite_exec(pDb->db, argv[2], 0, 0, &zErrMsg);
drh75897232000-05-29 14:26:00 +0000241 }
242 if( zErrMsg ){
243 Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE);
244 free(zErrMsg);
245 }
246 return rc;
drhbec3f402000-08-04 13:49:02 +0000247 }else
248
249 /*
250 ** $db timeout MILLESECONDS
251 **
252 ** Delay for the number of milliseconds specified when a file is locked.
253 */
254 if( c=='t' && strncmp(z,"timeout",n)==0 ){
255 int ms;
256 if( argc!=3 ){
257 Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
258 " timeout MILLISECONDS", 0);
259 return TCL_ERROR;
260 }
261 if( Tcl_GetInt(interp, argv[2], &ms) ) return TCL_ERROR;
262 sqlite_busy_timeout(pDb->db, ms);
263 }else
drh75897232000-05-29 14:26:00 +0000264
265 /* The default
266 */
drhbec3f402000-08-04 13:49:02 +0000267 {
drh75897232000-05-29 14:26:00 +0000268 Tcl_AppendResult(interp,"unknown subcommand \"", z,
269 "\" - should be one of: close complete eval", 0);
270 return TCL_ERROR;
271 }
272 return TCL_OK;
273}
274
275/*
276** sqlite DBNAME FILENAME ?MODE?
277**
278** This is the main Tcl command. When the "sqlite" Tcl command is
279** invoked, this routine runs to process that command.
280**
281** The first argument, DBNAME, is an arbitrary name for a new
282** database connection. This command creates a new command named
283** DBNAME that is used to control that connection. The database
284** connection is deleted when the DBNAME command is deleted.
285**
286** The second argument is the name of the directory that contains
287** the sqlite database that is to be accessed.
288*/
289static int DbMain(void *cd, Tcl_Interp *interp, int argc, char **argv){
290 int mode;
drhbec3f402000-08-04 13:49:02 +0000291 SqliteDb *p;
drh75897232000-05-29 14:26:00 +0000292 char *zErrMsg;
293 if( argc!=3 && argc!=4 ){
294 Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
295 " HANDLE FILENAME ?MODE?\"", 0);
296 return TCL_ERROR;
297 }
298 if( argc==3 ){
drh58b95762000-06-02 01:17:37 +0000299 mode = 0666;
drh75897232000-05-29 14:26:00 +0000300 }else if( Tcl_GetInt(interp, argv[3], &mode)!=TCL_OK ){
301 return TCL_ERROR;
302 }
303 zErrMsg = 0;
drh4cdc9e82000-08-04 14:56:24 +0000304 p = (SqliteDb*)Tcl_Alloc( sizeof(*p) );
drh75897232000-05-29 14:26:00 +0000305 if( p==0 ){
drhbec3f402000-08-04 13:49:02 +0000306 Tcl_SetResult(interp, "malloc failed", TCL_STATIC);
307 return TCL_ERROR;
308 }
309 memset(p, 0, sizeof(*p));
310 p->db = sqlite_open(argv[2], mode, &zErrMsg);
311 if( p->db==0 ){
drh75897232000-05-29 14:26:00 +0000312 Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE);
drhbec3f402000-08-04 13:49:02 +0000313 Tcl_Free((char*)p);
drh75897232000-05-29 14:26:00 +0000314 free(zErrMsg);
315 return TCL_ERROR;
316 }
drhbec3f402000-08-04 13:49:02 +0000317 Tcl_CreateCommand(interp, argv[1], DbCmd, (char*)p, DbDeleteCmd);
drh75897232000-05-29 14:26:00 +0000318 return TCL_OK;
319}
320
321/*
322** Initialize this module.
323**
324** This Tcl module contains only a single new Tcl command named "sqlite".
325** (Hence there is no namespace. There is no point in using a namespace
326** if the extension only supplies one new name!) The "sqlite" command is
327** used to open a new SQLite database. See the DbMain() routine above
328** for additional information.
329*/
330int Sqlite_Init(Tcl_Interp *interp){
331 Tcl_CreateCommand(interp, "sqlite", DbMain, 0, 0);
332 return TCL_OK;
333}
334int Sqlite_SafeInit(Tcl_Interp *interp){
335 return TCL_OK;
336}
337
338/*
339** If compiled using mktclapp, this routine runs to initialize
340** everything.
341*/
342int Et_AppInit(Tcl_Interp *interp){
343 return Sqlite_Init(interp);
344}
drh348784e2000-05-29 20:41:49 +0000345
346/*
347** If the macro TCLSH is defined and is one, then put in code for the
348** "main" routine that will initialize Tcl.
349*/
350#if defined(TCLSH) && TCLSH==1
351static char zMainloop[] =
352 "set line {}\n"
353 "while {![eof stdin]} {\n"
354 "if {$line!=\"\"} {\n"
355 "puts -nonewline \"> \"\n"
356 "} else {\n"
357 "puts -nonewline \"% \"\n"
358 "}\n"
359 "flush stdout\n"
360 "append line [gets stdin]\n"
361 "if {[info complete $line]} {\n"
362 "if {[catch {uplevel #0 $line} result]} {\n"
363 "puts stderr \"Error: $result\"\n"
364 "} elseif {$result!=\"\"} {\n"
365 "puts $result\n"
366 "}\n"
367 "set line {}\n"
368 "} else {\n"
369 "append line \\n\n"
370 "}\n"
371 "}\n"
372;
373
374#define TCLSH_MAIN main /* Needed to fake out mktclapp */
375int TCLSH_MAIN(int argc, char **argv){
376 Tcl_Interp *interp;
377 interp = Tcl_CreateInterp();
378 Sqlite_Init(interp);
379 if( argc>=2 ){
380 int i;
381 Tcl_SetVar(interp,"argv0",argv[1],TCL_GLOBAL_ONLY);
382 Tcl_SetVar(interp,"argv", "", TCL_GLOBAL_ONLY);
383 for(i=2; i<argc; i++){
384 Tcl_SetVar(interp, "argv", argv[i],
385 TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT | TCL_APPEND_VALUE);
386 }
387 if( Tcl_EvalFile(interp, argv[1])!=TCL_OK ){
drhc61053b2000-06-04 12:58:36 +0000388 char *zInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
389 if( zInfo==0 ) zInfo = interp->result;
390 fprintf(stderr,"%s: %s\n", *argv, zInfo);
drh348784e2000-05-29 20:41:49 +0000391 return 1;
392 }
393 }else{
394 Tcl_GlobalEval(interp, zMainloop);
395 }
396 return 0;
397}
398#endif /* TCLSH */