blob: 2d4d154ebcec5aaccb602647e9dd9cae7a61b146 [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**
drh348784e2000-05-29 20:41:49 +000026** $Id: tclsqlite.c,v 1.2 2000/05/29 20:41:51 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/*
34** An instance of this structure passes information thru the sqlite
35** logic from the original TCL command into the callback routine.
36*/
37typedef struct CallbackData CallbackData;
38struct CallbackData {
39 Tcl_Interp *interp; /* The TCL interpreter */
40 char *zArray; /* The array into which data is written */
41 char *zCode; /* The code to execute for each row */
42 int once; /* Set only for the first invocation of callback */
43};
44
45/*
46** Called for each row of the result.
47*/
48static int DbEvalCallback(
49 void *clientData, /* An instance of CallbackData */
50 int nCol, /* Number of columns in the result */
51 char ** azCol, /* Data for each column */
52 char ** azN /* Name for each column */
53){
54 CallbackData *cbData = (CallbackData*)clientData;
55 int i, rc;
56 if( cbData->zArray[0] ){
57 if( cbData->once ){
58 for(i=0; i<nCol; i++){
59 Tcl_SetVar2(cbData->interp, cbData->zArray, "*", azN[i],
60 TCL_LIST_ELEMENT|TCL_APPEND_VALUE);
61 }
62 }
63 for(i=0; i<nCol; i++){
64 Tcl_SetVar2(cbData->interp, cbData->zArray, azN[i], azCol[i], 0);
65 }
66 }else{
67 for(i=0; i<nCol; i++){
68 Tcl_SetVar(cbData->interp, azN[i], azCol[i], 0);
69 }
70 }
71 cbData->once = 0;
72 rc = Tcl_Eval(cbData->interp, cbData->zCode);
73 return rc;
74}
75
76/*
77** Called when the command is deleted.
78*/
79static void DbDeleteCmd(void *db){
80 sqlite_close((sqlite*)db);
81}
82
83/*
84** The "sqlite" command below creates a new Tcl command for each
85** connection it opens to an SQLite database. This routine is invoked
86** whenever one of those connection-specific commands is executed
87** in Tcl. For example, if you run Tcl code like this:
88**
89** sqlite db1 "my_database"
90** db1 close
91**
92** The first command opens a connection to the "my_database" database
93** and calls that connection "db1". The second command causes this
94** subroutine to be invoked.
95*/
96static int DbCmd(void *cd, Tcl_Interp *interp, int argc, char **argv){
97 char *z;
98 int n, c;
99 sqlite *db = cd;
100 if( argc<2 ){
101 Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
102 " SUBCOMMAND ...\"", 0);
103 return TCL_ERROR;
104 }
105 z = argv[1];
106 n = strlen(z);
107 c = z[0];
108
109 /* $db close
110 **
111 ** Shutdown the database
112 */
113 if( c=='c' && n>=2 && strncmp(z,"close",n)==0 ){
114 Tcl_DeleteCommand(interp, argv[0]);
115 }else
116
117 /* $db complete SQL
118 **
119 ** Return TRUE if SQL is a complete SQL statement. Return FALSE if
120 ** additional lines of input are needed. This is similar to the
121 ** built-in "info complete" command of Tcl.
122 */
123 if( c=='c' && n>=2 && strncmp(z,"complete",n)==0 ){
124 char *zRes;
125 if( argc!=3 ){
126 Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
127 " complete SQL\"", 0);
128 return TCL_ERROR;
129 }
130 zRes = sqlite_complete(argv[2]) ? "1" : "0";
131 Tcl_SetResult(interp, zRes, TCL_VOLATILE);
132 }else
133
134 /*
135 ** $db eval $sql ?array { ...code... }?
136 **
137 ** The SQL statement in $sql is evaluated. For each row, the values are
138 ** placed in elements of the array named "array" and ...code.. is executed.
139 ** If "array" and "code" are omitted, then no callback is every invoked.
140 ** If "array" is an empty string, then the values are placed in variables
141 ** that have the same name as the fields extracted by the query.
142 */
143 if( c=='e' && strncmp(z,"eval",n)==0 ){
144 CallbackData cbData;
145 char *zErrMsg;
146 int rc;
147
148 if( argc!=5 && argc!=3 ){
149 Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
150 " eval SQL ?ARRAY-NAME CODE?", 0);
151 return TCL_ERROR;
152 }
153 if( argc==5 ){
154 cbData.interp = interp;
155 cbData.zArray = argv[3];
156 cbData.zCode = argv[4];
157 zErrMsg = 0;
158 rc = sqlite_exec(db, argv[2], DbEvalCallback, &cbData, &zErrMsg);
159 }else{
160 rc = sqlite_exec(db, argv[2], 0, 0, &zErrMsg);
161 }
162 if( zErrMsg ){
163 Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE);
164 free(zErrMsg);
165 }
166 return rc;
167 }
168
169 /* The default
170 */
171 else{
172 Tcl_AppendResult(interp,"unknown subcommand \"", z,
173 "\" - should be one of: close complete eval", 0);
174 return TCL_ERROR;
175 }
176 return TCL_OK;
177}
178
179/*
180** sqlite DBNAME FILENAME ?MODE?
181**
182** This is the main Tcl command. When the "sqlite" Tcl command is
183** invoked, this routine runs to process that command.
184**
185** The first argument, DBNAME, is an arbitrary name for a new
186** database connection. This command creates a new command named
187** DBNAME that is used to control that connection. The database
188** connection is deleted when the DBNAME command is deleted.
189**
190** The second argument is the name of the directory that contains
191** the sqlite database that is to be accessed.
192*/
193static int DbMain(void *cd, Tcl_Interp *interp, int argc, char **argv){
194 int mode;
195 sqlite *p;
196 char *zErrMsg;
197 if( argc!=3 && argc!=4 ){
198 Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
199 " HANDLE FILENAME ?MODE?\"", 0);
200 return TCL_ERROR;
201 }
202 if( argc==3 ){
203 mode = 0;
204 }else if( Tcl_GetInt(interp, argv[3], &mode)!=TCL_OK ){
205 return TCL_ERROR;
206 }
207 zErrMsg = 0;
208 p = sqlite_open(argv[2], mode, &zErrMsg);
209 if( p==0 ){
210 Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE);
211 free(zErrMsg);
212 return TCL_ERROR;
213 }
214 Tcl_CreateCommand(interp, argv[1], DbCmd, p, DbDeleteCmd);
215 return TCL_OK;
216}
217
218/*
219** Initialize this module.
220**
221** This Tcl module contains only a single new Tcl command named "sqlite".
222** (Hence there is no namespace. There is no point in using a namespace
223** if the extension only supplies one new name!) The "sqlite" command is
224** used to open a new SQLite database. See the DbMain() routine above
225** for additional information.
226*/
227int Sqlite_Init(Tcl_Interp *interp){
228 Tcl_CreateCommand(interp, "sqlite", DbMain, 0, 0);
229 return TCL_OK;
230}
231int Sqlite_SafeInit(Tcl_Interp *interp){
232 return TCL_OK;
233}
234
235/*
236** If compiled using mktclapp, this routine runs to initialize
237** everything.
238*/
239int Et_AppInit(Tcl_Interp *interp){
240 return Sqlite_Init(interp);
241}
drh348784e2000-05-29 20:41:49 +0000242
243/*
244** If the macro TCLSH is defined and is one, then put in code for the
245** "main" routine that will initialize Tcl.
246*/
247#if defined(TCLSH) && TCLSH==1
248static char zMainloop[] =
249 "set line {}\n"
250 "while {![eof stdin]} {\n"
251 "if {$line!=\"\"} {\n"
252 "puts -nonewline \"> \"\n"
253 "} else {\n"
254 "puts -nonewline \"% \"\n"
255 "}\n"
256 "flush stdout\n"
257 "append line [gets stdin]\n"
258 "if {[info complete $line]} {\n"
259 "if {[catch {uplevel #0 $line} result]} {\n"
260 "puts stderr \"Error: $result\"\n"
261 "} elseif {$result!=\"\"} {\n"
262 "puts $result\n"
263 "}\n"
264 "set line {}\n"
265 "} else {\n"
266 "append line \\n\n"
267 "}\n"
268 "}\n"
269;
270
271#define TCLSH_MAIN main /* Needed to fake out mktclapp */
272int TCLSH_MAIN(int argc, char **argv){
273 Tcl_Interp *interp;
274 interp = Tcl_CreateInterp();
275 Sqlite_Init(interp);
276 if( argc>=2 ){
277 int i;
278 Tcl_SetVar(interp,"argv0",argv[1],TCL_GLOBAL_ONLY);
279 Tcl_SetVar(interp,"argv", "", TCL_GLOBAL_ONLY);
280 for(i=2; i<argc; i++){
281 Tcl_SetVar(interp, "argv", argv[i],
282 TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT | TCL_APPEND_VALUE);
283 }
284 if( Tcl_EvalFile(interp, argv[1])!=TCL_OK ){
285 fprintf(stderr,"%s: %s\n", *argv,
286 Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY)
287 );
288 return 1;
289 }
290 }else{
291 Tcl_GlobalEval(interp, zMainloop);
292 }
293 return 0;
294}
295#endif /* TCLSH */