blob: 1499cf6e272adb6d6d4149de448161bc9ff67556 [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**
drh58b95762000-06-02 01:17:37 +000026** $Id: tclsqlite.c,v 1.4 2000/06/02 01:17:38 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;
drhdcc581c2000-05-30 13:44:19 +0000155 cbData.once = 1;
drh75897232000-05-29 14:26:00 +0000156 cbData.zArray = argv[3];
157 cbData.zCode = argv[4];
158 zErrMsg = 0;
159 rc = sqlite_exec(db, argv[2], DbEvalCallback, &cbData, &zErrMsg);
160 }else{
161 rc = sqlite_exec(db, argv[2], 0, 0, &zErrMsg);
162 }
163 if( zErrMsg ){
164 Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE);
165 free(zErrMsg);
166 }
167 return rc;
168 }
169
170 /* The default
171 */
172 else{
173 Tcl_AppendResult(interp,"unknown subcommand \"", z,
174 "\" - should be one of: close complete eval", 0);
175 return TCL_ERROR;
176 }
177 return TCL_OK;
178}
179
180/*
181** sqlite DBNAME FILENAME ?MODE?
182**
183** This is the main Tcl command. When the "sqlite" Tcl command is
184** invoked, this routine runs to process that command.
185**
186** The first argument, DBNAME, is an arbitrary name for a new
187** database connection. This command creates a new command named
188** DBNAME that is used to control that connection. The database
189** connection is deleted when the DBNAME command is deleted.
190**
191** The second argument is the name of the directory that contains
192** the sqlite database that is to be accessed.
193*/
194static int DbMain(void *cd, Tcl_Interp *interp, int argc, char **argv){
195 int mode;
196 sqlite *p;
197 char *zErrMsg;
198 if( argc!=3 && argc!=4 ){
199 Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
200 " HANDLE FILENAME ?MODE?\"", 0);
201 return TCL_ERROR;
202 }
203 if( argc==3 ){
drh58b95762000-06-02 01:17:37 +0000204 mode = 0666;
drh75897232000-05-29 14:26:00 +0000205 }else if( Tcl_GetInt(interp, argv[3], &mode)!=TCL_OK ){
206 return TCL_ERROR;
207 }
208 zErrMsg = 0;
209 p = sqlite_open(argv[2], mode, &zErrMsg);
210 if( p==0 ){
211 Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE);
212 free(zErrMsg);
213 return TCL_ERROR;
214 }
215 Tcl_CreateCommand(interp, argv[1], DbCmd, p, DbDeleteCmd);
216 return TCL_OK;
217}
218
219/*
220** Initialize this module.
221**
222** This Tcl module contains only a single new Tcl command named "sqlite".
223** (Hence there is no namespace. There is no point in using a namespace
224** if the extension only supplies one new name!) The "sqlite" command is
225** used to open a new SQLite database. See the DbMain() routine above
226** for additional information.
227*/
228int Sqlite_Init(Tcl_Interp *interp){
229 Tcl_CreateCommand(interp, "sqlite", DbMain, 0, 0);
230 return TCL_OK;
231}
232int Sqlite_SafeInit(Tcl_Interp *interp){
233 return TCL_OK;
234}
235
236/*
237** If compiled using mktclapp, this routine runs to initialize
238** everything.
239*/
240int Et_AppInit(Tcl_Interp *interp){
241 return Sqlite_Init(interp);
242}
drh348784e2000-05-29 20:41:49 +0000243
244/*
245** If the macro TCLSH is defined and is one, then put in code for the
246** "main" routine that will initialize Tcl.
247*/
248#if defined(TCLSH) && TCLSH==1
249static char zMainloop[] =
250 "set line {}\n"
251 "while {![eof stdin]} {\n"
252 "if {$line!=\"\"} {\n"
253 "puts -nonewline \"> \"\n"
254 "} else {\n"
255 "puts -nonewline \"% \"\n"
256 "}\n"
257 "flush stdout\n"
258 "append line [gets stdin]\n"
259 "if {[info complete $line]} {\n"
260 "if {[catch {uplevel #0 $line} result]} {\n"
261 "puts stderr \"Error: $result\"\n"
262 "} elseif {$result!=\"\"} {\n"
263 "puts $result\n"
264 "}\n"
265 "set line {}\n"
266 "} else {\n"
267 "append line \\n\n"
268 "}\n"
269 "}\n"
270;
271
272#define TCLSH_MAIN main /* Needed to fake out mktclapp */
273int TCLSH_MAIN(int argc, char **argv){
274 Tcl_Interp *interp;
275 interp = Tcl_CreateInterp();
276 Sqlite_Init(interp);
277 if( argc>=2 ){
278 int i;
279 Tcl_SetVar(interp,"argv0",argv[1],TCL_GLOBAL_ONLY);
280 Tcl_SetVar(interp,"argv", "", TCL_GLOBAL_ONLY);
281 for(i=2; i<argc; i++){
282 Tcl_SetVar(interp, "argv", argv[i],
283 TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT | TCL_APPEND_VALUE);
284 }
285 if( Tcl_EvalFile(interp, argv[1])!=TCL_OK ){
286 fprintf(stderr,"%s: %s\n", *argv,
287 Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY)
288 );
289 return 1;
290 }
291 }else{
292 Tcl_GlobalEval(interp, zMainloop);
293 }
294 return 0;
295}
296#endif /* TCLSH */