OLD | NEW |
| (Empty) |
1 /* | |
2 ** 2001 September 15 | |
3 ** | |
4 ** The author disclaims copyright to this source code. In place of | |
5 ** a legal notice, here is a blessing: | |
6 ** | |
7 ** May you do good and not evil. | |
8 ** May you find forgiveness for yourself and forgive others. | |
9 ** May you share freely, never taking more than you give. | |
10 ** | |
11 ************************************************************************* | |
12 ** A TCL Interface to SQLite. Append this file to sqlite3.c and | |
13 ** compile the whole thing to build a TCL-enabled version of SQLite. | |
14 ** | |
15 ** Compile-time options: | |
16 ** | |
17 ** -DTCLSH=1 Add a "main()" routine that works as a tclsh. | |
18 ** | |
19 ** -DSQLITE_TCLMD5 When used in conjuction with -DTCLSH=1, add | |
20 ** four new commands to the TCL interpreter for | |
21 ** generating MD5 checksums: md5, md5file, | |
22 ** md5-10x8, and md5file-10x8. | |
23 ** | |
24 ** -DSQLITE_TEST When used in conjuction with -DTCLSH=1, add | |
25 ** hundreds of new commands used for testing | |
26 ** SQLite. This option implies -DSQLITE_TCLMD5. | |
27 */ | |
28 | |
29 /* | |
30 ** If requested, include the SQLite compiler options file for MSVC. | |
31 */ | |
32 #if defined(INCLUDE_MSVC_H) | |
33 #include "msvc.h" | |
34 #endif | |
35 | |
36 #include "tcl.h" | |
37 #include <errno.h> | |
38 | |
39 /* | |
40 ** Some additional include files are needed if this file is not | |
41 ** appended to the amalgamation. | |
42 */ | |
43 #ifndef SQLITE_AMALGAMATION | |
44 # include "sqlite3.h" | |
45 # include <stdlib.h> | |
46 # include <string.h> | |
47 # include <assert.h> | |
48 typedef unsigned char u8; | |
49 #endif | |
50 #include <ctype.h> | |
51 | |
52 /* Used to get the current process ID */ | |
53 #if !defined(_WIN32) | |
54 # include <unistd.h> | |
55 # define GETPID getpid | |
56 #elif !defined(_WIN32_WCE) | |
57 # ifndef SQLITE_AMALGAMATION | |
58 # define WIN32_LEAN_AND_MEAN | |
59 # include <windows.h> | |
60 # endif | |
61 # define GETPID (int)GetCurrentProcessId | |
62 #endif | |
63 | |
64 /* | |
65 * Windows needs to know which symbols to export. Unix does not. | |
66 * BUILD_sqlite should be undefined for Unix. | |
67 */ | |
68 #ifdef BUILD_sqlite | |
69 #undef TCL_STORAGE_CLASS | |
70 #define TCL_STORAGE_CLASS DLLEXPORT | |
71 #endif /* BUILD_sqlite */ | |
72 | |
73 #define NUM_PREPARED_STMTS 10 | |
74 #define MAX_PREPARED_STMTS 100 | |
75 | |
76 /* Forward declaration */ | |
77 typedef struct SqliteDb SqliteDb; | |
78 | |
79 /* | |
80 ** New SQL functions can be created as TCL scripts. Each such function | |
81 ** is described by an instance of the following structure. | |
82 */ | |
83 typedef struct SqlFunc SqlFunc; | |
84 struct SqlFunc { | |
85 Tcl_Interp *interp; /* The TCL interpret to execute the function */ | |
86 Tcl_Obj *pScript; /* The Tcl_Obj representation of the script */ | |
87 SqliteDb *pDb; /* Database connection that owns this function */ | |
88 int useEvalObjv; /* True if it is safe to use Tcl_EvalObjv */ | |
89 char *zName; /* Name of this function */ | |
90 SqlFunc *pNext; /* Next function on the list of them all */ | |
91 }; | |
92 | |
93 /* | |
94 ** New collation sequences function can be created as TCL scripts. Each such | |
95 ** function is described by an instance of the following structure. | |
96 */ | |
97 typedef struct SqlCollate SqlCollate; | |
98 struct SqlCollate { | |
99 Tcl_Interp *interp; /* The TCL interpret to execute the function */ | |
100 char *zScript; /* The script to be run */ | |
101 SqlCollate *pNext; /* Next function on the list of them all */ | |
102 }; | |
103 | |
104 /* | |
105 ** Prepared statements are cached for faster execution. Each prepared | |
106 ** statement is described by an instance of the following structure. | |
107 */ | |
108 typedef struct SqlPreparedStmt SqlPreparedStmt; | |
109 struct SqlPreparedStmt { | |
110 SqlPreparedStmt *pNext; /* Next in linked list */ | |
111 SqlPreparedStmt *pPrev; /* Previous on the list */ | |
112 sqlite3_stmt *pStmt; /* The prepared statement */ | |
113 int nSql; /* chars in zSql[] */ | |
114 const char *zSql; /* Text of the SQL statement */ | |
115 int nParm; /* Size of apParm array */ | |
116 Tcl_Obj **apParm; /* Array of referenced object pointers */ | |
117 }; | |
118 | |
119 typedef struct IncrblobChannel IncrblobChannel; | |
120 | |
121 /* | |
122 ** There is one instance of this structure for each SQLite database | |
123 ** that has been opened by the SQLite TCL interface. | |
124 ** | |
125 ** If this module is built with SQLITE_TEST defined (to create the SQLite | |
126 ** testfixture executable), then it may be configured to use either | |
127 ** sqlite3_prepare_v2() or sqlite3_prepare() to prepare SQL statements. | |
128 ** If SqliteDb.bLegacyPrepare is true, sqlite3_prepare() is used. | |
129 */ | |
130 struct SqliteDb { | |
131 sqlite3 *db; /* The "real" database structure. MUST BE FIRST */ | |
132 Tcl_Interp *interp; /* The interpreter used for this database */ | |
133 char *zBusy; /* The busy callback routine */ | |
134 char *zCommit; /* The commit hook callback routine */ | |
135 char *zTrace; /* The trace callback routine */ | |
136 char *zProfile; /* The profile callback routine */ | |
137 char *zProgress; /* The progress callback routine */ | |
138 char *zAuth; /* The authorization callback routine */ | |
139 int disableAuth; /* Disable the authorizer if it exists */ | |
140 char *zNull; /* Text to substitute for an SQL NULL value */ | |
141 SqlFunc *pFunc; /* List of SQL functions */ | |
142 Tcl_Obj *pUpdateHook; /* Update hook script (if any) */ | |
143 Tcl_Obj *pRollbackHook; /* Rollback hook script (if any) */ | |
144 Tcl_Obj *pWalHook; /* WAL hook script (if any) */ | |
145 Tcl_Obj *pUnlockNotify; /* Unlock notify script (if any) */ | |
146 SqlCollate *pCollate; /* List of SQL collation functions */ | |
147 int rc; /* Return code of most recent sqlite3_exec() */ | |
148 Tcl_Obj *pCollateNeeded; /* Collation needed script */ | |
149 SqlPreparedStmt *stmtList; /* List of prepared statements*/ | |
150 SqlPreparedStmt *stmtLast; /* Last statement in the list */ | |
151 int maxStmt; /* The next maximum number of stmtList */ | |
152 int nStmt; /* Number of statements in stmtList */ | |
153 IncrblobChannel *pIncrblob;/* Linked list of open incrblob channels */ | |
154 int nStep, nSort, nIndex; /* Statistics for most recent operation */ | |
155 int nTransaction; /* Number of nested [transaction] methods */ | |
156 #ifdef SQLITE_TEST | |
157 int bLegacyPrepare; /* True to use sqlite3_prepare() */ | |
158 #endif | |
159 }; | |
160 | |
161 struct IncrblobChannel { | |
162 sqlite3_blob *pBlob; /* sqlite3 blob handle */ | |
163 SqliteDb *pDb; /* Associated database connection */ | |
164 int iSeek; /* Current seek offset */ | |
165 Tcl_Channel channel; /* Channel identifier */ | |
166 IncrblobChannel *pNext; /* Linked list of all open incrblob channels */ | |
167 IncrblobChannel *pPrev; /* Linked list of all open incrblob channels */ | |
168 }; | |
169 | |
170 /* | |
171 ** Compute a string length that is limited to what can be stored in | |
172 ** lower 30 bits of a 32-bit signed integer. | |
173 */ | |
174 static int strlen30(const char *z){ | |
175 const char *z2 = z; | |
176 while( *z2 ){ z2++; } | |
177 return 0x3fffffff & (int)(z2 - z); | |
178 } | |
179 | |
180 | |
181 #ifndef SQLITE_OMIT_INCRBLOB | |
182 /* | |
183 ** Close all incrblob channels opened using database connection pDb. | |
184 ** This is called when shutting down the database connection. | |
185 */ | |
186 static void closeIncrblobChannels(SqliteDb *pDb){ | |
187 IncrblobChannel *p; | |
188 IncrblobChannel *pNext; | |
189 | |
190 for(p=pDb->pIncrblob; p; p=pNext){ | |
191 pNext = p->pNext; | |
192 | |
193 /* Note: Calling unregister here call Tcl_Close on the incrblob channel, | |
194 ** which deletes the IncrblobChannel structure at *p. So do not | |
195 ** call Tcl_Free() here. | |
196 */ | |
197 Tcl_UnregisterChannel(pDb->interp, p->channel); | |
198 } | |
199 } | |
200 | |
201 /* | |
202 ** Close an incremental blob channel. | |
203 */ | |
204 static int incrblobClose(ClientData instanceData, Tcl_Interp *interp){ | |
205 IncrblobChannel *p = (IncrblobChannel *)instanceData; | |
206 int rc = sqlite3_blob_close(p->pBlob); | |
207 sqlite3 *db = p->pDb->db; | |
208 | |
209 /* Remove the channel from the SqliteDb.pIncrblob list. */ | |
210 if( p->pNext ){ | |
211 p->pNext->pPrev = p->pPrev; | |
212 } | |
213 if( p->pPrev ){ | |
214 p->pPrev->pNext = p->pNext; | |
215 } | |
216 if( p->pDb->pIncrblob==p ){ | |
217 p->pDb->pIncrblob = p->pNext; | |
218 } | |
219 | |
220 /* Free the IncrblobChannel structure */ | |
221 Tcl_Free((char *)p); | |
222 | |
223 if( rc!=SQLITE_OK ){ | |
224 Tcl_SetResult(interp, (char *)sqlite3_errmsg(db), TCL_VOLATILE); | |
225 return TCL_ERROR; | |
226 } | |
227 return TCL_OK; | |
228 } | |
229 | |
230 /* | |
231 ** Read data from an incremental blob channel. | |
232 */ | |
233 static int incrblobInput( | |
234 ClientData instanceData, | |
235 char *buf, | |
236 int bufSize, | |
237 int *errorCodePtr | |
238 ){ | |
239 IncrblobChannel *p = (IncrblobChannel *)instanceData; | |
240 int nRead = bufSize; /* Number of bytes to read */ | |
241 int nBlob; /* Total size of the blob */ | |
242 int rc; /* sqlite error code */ | |
243 | |
244 nBlob = sqlite3_blob_bytes(p->pBlob); | |
245 if( (p->iSeek+nRead)>nBlob ){ | |
246 nRead = nBlob-p->iSeek; | |
247 } | |
248 if( nRead<=0 ){ | |
249 return 0; | |
250 } | |
251 | |
252 rc = sqlite3_blob_read(p->pBlob, (void *)buf, nRead, p->iSeek); | |
253 if( rc!=SQLITE_OK ){ | |
254 *errorCodePtr = rc; | |
255 return -1; | |
256 } | |
257 | |
258 p->iSeek += nRead; | |
259 return nRead; | |
260 } | |
261 | |
262 /* | |
263 ** Write data to an incremental blob channel. | |
264 */ | |
265 static int incrblobOutput( | |
266 ClientData instanceData, | |
267 CONST char *buf, | |
268 int toWrite, | |
269 int *errorCodePtr | |
270 ){ | |
271 IncrblobChannel *p = (IncrblobChannel *)instanceData; | |
272 int nWrite = toWrite; /* Number of bytes to write */ | |
273 int nBlob; /* Total size of the blob */ | |
274 int rc; /* sqlite error code */ | |
275 | |
276 nBlob = sqlite3_blob_bytes(p->pBlob); | |
277 if( (p->iSeek+nWrite)>nBlob ){ | |
278 *errorCodePtr = EINVAL; | |
279 return -1; | |
280 } | |
281 if( nWrite<=0 ){ | |
282 return 0; | |
283 } | |
284 | |
285 rc = sqlite3_blob_write(p->pBlob, (void *)buf, nWrite, p->iSeek); | |
286 if( rc!=SQLITE_OK ){ | |
287 *errorCodePtr = EIO; | |
288 return -1; | |
289 } | |
290 | |
291 p->iSeek += nWrite; | |
292 return nWrite; | |
293 } | |
294 | |
295 /* | |
296 ** Seek an incremental blob channel. | |
297 */ | |
298 static int incrblobSeek( | |
299 ClientData instanceData, | |
300 long offset, | |
301 int seekMode, | |
302 int *errorCodePtr | |
303 ){ | |
304 IncrblobChannel *p = (IncrblobChannel *)instanceData; | |
305 | |
306 switch( seekMode ){ | |
307 case SEEK_SET: | |
308 p->iSeek = offset; | |
309 break; | |
310 case SEEK_CUR: | |
311 p->iSeek += offset; | |
312 break; | |
313 case SEEK_END: | |
314 p->iSeek = sqlite3_blob_bytes(p->pBlob) + offset; | |
315 break; | |
316 | |
317 default: assert(!"Bad seekMode"); | |
318 } | |
319 | |
320 return p->iSeek; | |
321 } | |
322 | |
323 | |
324 static void incrblobWatch(ClientData instanceData, int mode){ | |
325 /* NO-OP */ | |
326 } | |
327 static int incrblobHandle(ClientData instanceData, int dir, ClientData *hPtr){ | |
328 return TCL_ERROR; | |
329 } | |
330 | |
331 static Tcl_ChannelType IncrblobChannelType = { | |
332 "incrblob", /* typeName */ | |
333 TCL_CHANNEL_VERSION_2, /* version */ | |
334 incrblobClose, /* closeProc */ | |
335 incrblobInput, /* inputProc */ | |
336 incrblobOutput, /* outputProc */ | |
337 incrblobSeek, /* seekProc */ | |
338 0, /* setOptionProc */ | |
339 0, /* getOptionProc */ | |
340 incrblobWatch, /* watchProc (this is a no-op) */ | |
341 incrblobHandle, /* getHandleProc (always returns error) */ | |
342 0, /* close2Proc */ | |
343 0, /* blockModeProc */ | |
344 0, /* flushProc */ | |
345 0, /* handlerProc */ | |
346 0, /* wideSeekProc */ | |
347 }; | |
348 | |
349 /* | |
350 ** Create a new incrblob channel. | |
351 */ | |
352 static int createIncrblobChannel( | |
353 Tcl_Interp *interp, | |
354 SqliteDb *pDb, | |
355 const char *zDb, | |
356 const char *zTable, | |
357 const char *zColumn, | |
358 sqlite_int64 iRow, | |
359 int isReadonly | |
360 ){ | |
361 IncrblobChannel *p; | |
362 sqlite3 *db = pDb->db; | |
363 sqlite3_blob *pBlob; | |
364 int rc; | |
365 int flags = TCL_READABLE|(isReadonly ? 0 : TCL_WRITABLE); | |
366 | |
367 /* This variable is used to name the channels: "incrblob_[incr count]" */ | |
368 static int count = 0; | |
369 char zChannel[64]; | |
370 | |
371 rc = sqlite3_blob_open(db, zDb, zTable, zColumn, iRow, !isReadonly, &pBlob); | |
372 if( rc!=SQLITE_OK ){ | |
373 Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE); | |
374 return TCL_ERROR; | |
375 } | |
376 | |
377 p = (IncrblobChannel *)Tcl_Alloc(sizeof(IncrblobChannel)); | |
378 p->iSeek = 0; | |
379 p->pBlob = pBlob; | |
380 | |
381 sqlite3_snprintf(sizeof(zChannel), zChannel, "incrblob_%d", ++count); | |
382 p->channel = Tcl_CreateChannel(&IncrblobChannelType, zChannel, p, flags); | |
383 Tcl_RegisterChannel(interp, p->channel); | |
384 | |
385 /* Link the new channel into the SqliteDb.pIncrblob list. */ | |
386 p->pNext = pDb->pIncrblob; | |
387 p->pPrev = 0; | |
388 if( p->pNext ){ | |
389 p->pNext->pPrev = p; | |
390 } | |
391 pDb->pIncrblob = p; | |
392 p->pDb = pDb; | |
393 | |
394 Tcl_SetResult(interp, (char *)Tcl_GetChannelName(p->channel), TCL_VOLATILE); | |
395 return TCL_OK; | |
396 } | |
397 #else /* else clause for "#ifndef SQLITE_OMIT_INCRBLOB" */ | |
398 #define closeIncrblobChannels(pDb) | |
399 #endif | |
400 | |
401 /* | |
402 ** Look at the script prefix in pCmd. We will be executing this script | |
403 ** after first appending one or more arguments. This routine analyzes | |
404 ** the script to see if it is safe to use Tcl_EvalObjv() on the script | |
405 ** rather than the more general Tcl_EvalEx(). Tcl_EvalObjv() is much | |
406 ** faster. | |
407 ** | |
408 ** Scripts that are safe to use with Tcl_EvalObjv() consists of a | |
409 ** command name followed by zero or more arguments with no [...] or $ | |
410 ** or {...} or ; to be seen anywhere. Most callback scripts consist | |
411 ** of just a single procedure name and they meet this requirement. | |
412 */ | |
413 static int safeToUseEvalObjv(Tcl_Interp *interp, Tcl_Obj *pCmd){ | |
414 /* We could try to do something with Tcl_Parse(). But we will instead | |
415 ** just do a search for forbidden characters. If any of the forbidden | |
416 ** characters appear in pCmd, we will report the string as unsafe. | |
417 */ | |
418 const char *z; | |
419 int n; | |
420 z = Tcl_GetStringFromObj(pCmd, &n); | |
421 while( n-- > 0 ){ | |
422 int c = *(z++); | |
423 if( c=='$' || c=='[' || c==';' ) return 0; | |
424 } | |
425 return 1; | |
426 } | |
427 | |
428 /* | |
429 ** Find an SqlFunc structure with the given name. Or create a new | |
430 ** one if an existing one cannot be found. Return a pointer to the | |
431 ** structure. | |
432 */ | |
433 static SqlFunc *findSqlFunc(SqliteDb *pDb, const char *zName){ | |
434 SqlFunc *p, *pNew; | |
435 int nName = strlen30(zName); | |
436 pNew = (SqlFunc*)Tcl_Alloc( sizeof(*pNew) + nName + 1 ); | |
437 pNew->zName = (char*)&pNew[1]; | |
438 memcpy(pNew->zName, zName, nName+1); | |
439 for(p=pDb->pFunc; p; p=p->pNext){ | |
440 if( sqlite3_stricmp(p->zName, pNew->zName)==0 ){ | |
441 Tcl_Free((char*)pNew); | |
442 return p; | |
443 } | |
444 } | |
445 pNew->interp = pDb->interp; | |
446 pNew->pDb = pDb; | |
447 pNew->pScript = 0; | |
448 pNew->pNext = pDb->pFunc; | |
449 pDb->pFunc = pNew; | |
450 return pNew; | |
451 } | |
452 | |
453 /* | |
454 ** Free a single SqlPreparedStmt object. | |
455 */ | |
456 static void dbFreeStmt(SqlPreparedStmt *pStmt){ | |
457 #ifdef SQLITE_TEST | |
458 if( sqlite3_sql(pStmt->pStmt)==0 ){ | |
459 Tcl_Free((char *)pStmt->zSql); | |
460 } | |
461 #endif | |
462 sqlite3_finalize(pStmt->pStmt); | |
463 Tcl_Free((char *)pStmt); | |
464 } | |
465 | |
466 /* | |
467 ** Finalize and free a list of prepared statements | |
468 */ | |
469 static void flushStmtCache(SqliteDb *pDb){ | |
470 SqlPreparedStmt *pPreStmt; | |
471 SqlPreparedStmt *pNext; | |
472 | |
473 for(pPreStmt = pDb->stmtList; pPreStmt; pPreStmt=pNext){ | |
474 pNext = pPreStmt->pNext; | |
475 dbFreeStmt(pPreStmt); | |
476 } | |
477 pDb->nStmt = 0; | |
478 pDb->stmtLast = 0; | |
479 pDb->stmtList = 0; | |
480 } | |
481 | |
482 /* | |
483 ** TCL calls this procedure when an sqlite3 database command is | |
484 ** deleted. | |
485 */ | |
486 static void DbDeleteCmd(void *db){ | |
487 SqliteDb *pDb = (SqliteDb*)db; | |
488 flushStmtCache(pDb); | |
489 closeIncrblobChannels(pDb); | |
490 sqlite3_close(pDb->db); | |
491 while( pDb->pFunc ){ | |
492 SqlFunc *pFunc = pDb->pFunc; | |
493 pDb->pFunc = pFunc->pNext; | |
494 assert( pFunc->pDb==pDb ); | |
495 Tcl_DecrRefCount(pFunc->pScript); | |
496 Tcl_Free((char*)pFunc); | |
497 } | |
498 while( pDb->pCollate ){ | |
499 SqlCollate *pCollate = pDb->pCollate; | |
500 pDb->pCollate = pCollate->pNext; | |
501 Tcl_Free((char*)pCollate); | |
502 } | |
503 if( pDb->zBusy ){ | |
504 Tcl_Free(pDb->zBusy); | |
505 } | |
506 if( pDb->zTrace ){ | |
507 Tcl_Free(pDb->zTrace); | |
508 } | |
509 if( pDb->zProfile ){ | |
510 Tcl_Free(pDb->zProfile); | |
511 } | |
512 if( pDb->zAuth ){ | |
513 Tcl_Free(pDb->zAuth); | |
514 } | |
515 if( pDb->zNull ){ | |
516 Tcl_Free(pDb->zNull); | |
517 } | |
518 if( pDb->pUpdateHook ){ | |
519 Tcl_DecrRefCount(pDb->pUpdateHook); | |
520 } | |
521 if( pDb->pRollbackHook ){ | |
522 Tcl_DecrRefCount(pDb->pRollbackHook); | |
523 } | |
524 if( pDb->pWalHook ){ | |
525 Tcl_DecrRefCount(pDb->pWalHook); | |
526 } | |
527 if( pDb->pCollateNeeded ){ | |
528 Tcl_DecrRefCount(pDb->pCollateNeeded); | |
529 } | |
530 Tcl_Free((char*)pDb); | |
531 } | |
532 | |
533 /* | |
534 ** This routine is called when a database file is locked while trying | |
535 ** to execute SQL. | |
536 */ | |
537 static int DbBusyHandler(void *cd, int nTries){ | |
538 SqliteDb *pDb = (SqliteDb*)cd; | |
539 int rc; | |
540 char zVal[30]; | |
541 | |
542 sqlite3_snprintf(sizeof(zVal), zVal, "%d", nTries); | |
543 rc = Tcl_VarEval(pDb->interp, pDb->zBusy, " ", zVal, (char*)0); | |
544 if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){ | |
545 return 0; | |
546 } | |
547 return 1; | |
548 } | |
549 | |
550 #ifndef SQLITE_OMIT_PROGRESS_CALLBACK | |
551 /* | |
552 ** This routine is invoked as the 'progress callback' for the database. | |
553 */ | |
554 static int DbProgressHandler(void *cd){ | |
555 SqliteDb *pDb = (SqliteDb*)cd; | |
556 int rc; | |
557 | |
558 assert( pDb->zProgress ); | |
559 rc = Tcl_Eval(pDb->interp, pDb->zProgress); | |
560 if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){ | |
561 return 1; | |
562 } | |
563 return 0; | |
564 } | |
565 #endif | |
566 | |
567 #ifndef SQLITE_OMIT_TRACE | |
568 /* | |
569 ** This routine is called by the SQLite trace handler whenever a new | |
570 ** block of SQL is executed. The TCL script in pDb->zTrace is executed. | |
571 */ | |
572 static void DbTraceHandler(void *cd, const char *zSql){ | |
573 SqliteDb *pDb = (SqliteDb*)cd; | |
574 Tcl_DString str; | |
575 | |
576 Tcl_DStringInit(&str); | |
577 Tcl_DStringAppend(&str, pDb->zTrace, -1); | |
578 Tcl_DStringAppendElement(&str, zSql); | |
579 Tcl_Eval(pDb->interp, Tcl_DStringValue(&str)); | |
580 Tcl_DStringFree(&str); | |
581 Tcl_ResetResult(pDb->interp); | |
582 } | |
583 #endif | |
584 | |
585 #ifndef SQLITE_OMIT_TRACE | |
586 /* | |
587 ** This routine is called by the SQLite profile handler after a statement | |
588 ** SQL has executed. The TCL script in pDb->zProfile is evaluated. | |
589 */ | |
590 static void DbProfileHandler(void *cd, const char *zSql, sqlite_uint64 tm){ | |
591 SqliteDb *pDb = (SqliteDb*)cd; | |
592 Tcl_DString str; | |
593 char zTm[100]; | |
594 | |
595 sqlite3_snprintf(sizeof(zTm)-1, zTm, "%lld", tm); | |
596 Tcl_DStringInit(&str); | |
597 Tcl_DStringAppend(&str, pDb->zProfile, -1); | |
598 Tcl_DStringAppendElement(&str, zSql); | |
599 Tcl_DStringAppendElement(&str, zTm); | |
600 Tcl_Eval(pDb->interp, Tcl_DStringValue(&str)); | |
601 Tcl_DStringFree(&str); | |
602 Tcl_ResetResult(pDb->interp); | |
603 } | |
604 #endif | |
605 | |
606 /* | |
607 ** This routine is called when a transaction is committed. The | |
608 ** TCL script in pDb->zCommit is executed. If it returns non-zero or | |
609 ** if it throws an exception, the transaction is rolled back instead | |
610 ** of being committed. | |
611 */ | |
612 static int DbCommitHandler(void *cd){ | |
613 SqliteDb *pDb = (SqliteDb*)cd; | |
614 int rc; | |
615 | |
616 rc = Tcl_Eval(pDb->interp, pDb->zCommit); | |
617 if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){ | |
618 return 1; | |
619 } | |
620 return 0; | |
621 } | |
622 | |
623 static void DbRollbackHandler(void *clientData){ | |
624 SqliteDb *pDb = (SqliteDb*)clientData; | |
625 assert(pDb->pRollbackHook); | |
626 if( TCL_OK!=Tcl_EvalObjEx(pDb->interp, pDb->pRollbackHook, 0) ){ | |
627 Tcl_BackgroundError(pDb->interp); | |
628 } | |
629 } | |
630 | |
631 /* | |
632 ** This procedure handles wal_hook callbacks. | |
633 */ | |
634 static int DbWalHandler( | |
635 void *clientData, | |
636 sqlite3 *db, | |
637 const char *zDb, | |
638 int nEntry | |
639 ){ | |
640 int ret = SQLITE_OK; | |
641 Tcl_Obj *p; | |
642 SqliteDb *pDb = (SqliteDb*)clientData; | |
643 Tcl_Interp *interp = pDb->interp; | |
644 assert(pDb->pWalHook); | |
645 | |
646 assert( db==pDb->db ); | |
647 p = Tcl_DuplicateObj(pDb->pWalHook); | |
648 Tcl_IncrRefCount(p); | |
649 Tcl_ListObjAppendElement(interp, p, Tcl_NewStringObj(zDb, -1)); | |
650 Tcl_ListObjAppendElement(interp, p, Tcl_NewIntObj(nEntry)); | |
651 if( TCL_OK!=Tcl_EvalObjEx(interp, p, 0) | |
652 || TCL_OK!=Tcl_GetIntFromObj(interp, Tcl_GetObjResult(interp), &ret) | |
653 ){ | |
654 Tcl_BackgroundError(interp); | |
655 } | |
656 Tcl_DecrRefCount(p); | |
657 | |
658 return ret; | |
659 } | |
660 | |
661 #if defined(SQLITE_TEST) && defined(SQLITE_ENABLE_UNLOCK_NOTIFY) | |
662 static void setTestUnlockNotifyVars(Tcl_Interp *interp, int iArg, int nArg){ | |
663 char zBuf[64]; | |
664 sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", iArg); | |
665 Tcl_SetVar(interp, "sqlite_unlock_notify_arg", zBuf, TCL_GLOBAL_ONLY); | |
666 sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", nArg); | |
667 Tcl_SetVar(interp, "sqlite_unlock_notify_argcount", zBuf, TCL_GLOBAL_ONLY); | |
668 } | |
669 #else | |
670 # define setTestUnlockNotifyVars(x,y,z) | |
671 #endif | |
672 | |
673 #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY | |
674 static void DbUnlockNotify(void **apArg, int nArg){ | |
675 int i; | |
676 for(i=0; i<nArg; i++){ | |
677 const int flags = (TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT); | |
678 SqliteDb *pDb = (SqliteDb *)apArg[i]; | |
679 setTestUnlockNotifyVars(pDb->interp, i, nArg); | |
680 assert( pDb->pUnlockNotify); | |
681 Tcl_EvalObjEx(pDb->interp, pDb->pUnlockNotify, flags); | |
682 Tcl_DecrRefCount(pDb->pUnlockNotify); | |
683 pDb->pUnlockNotify = 0; | |
684 } | |
685 } | |
686 #endif | |
687 | |
688 static void DbUpdateHandler( | |
689 void *p, | |
690 int op, | |
691 const char *zDb, | |
692 const char *zTbl, | |
693 sqlite_int64 rowid | |
694 ){ | |
695 SqliteDb *pDb = (SqliteDb *)p; | |
696 Tcl_Obj *pCmd; | |
697 | |
698 assert( pDb->pUpdateHook ); | |
699 assert( op==SQLITE_INSERT || op==SQLITE_UPDATE || op==SQLITE_DELETE ); | |
700 | |
701 pCmd = Tcl_DuplicateObj(pDb->pUpdateHook); | |
702 Tcl_IncrRefCount(pCmd); | |
703 Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj( | |
704 ( (op==SQLITE_INSERT)?"INSERT":(op==SQLITE_UPDATE)?"UPDATE":"DELETE"), -1)); | |
705 Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zDb, -1)); | |
706 Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zTbl, -1)); | |
707 Tcl_ListObjAppendElement(0, pCmd, Tcl_NewWideIntObj(rowid)); | |
708 Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT); | |
709 Tcl_DecrRefCount(pCmd); | |
710 } | |
711 | |
712 static void tclCollateNeeded( | |
713 void *pCtx, | |
714 sqlite3 *db, | |
715 int enc, | |
716 const char *zName | |
717 ){ | |
718 SqliteDb *pDb = (SqliteDb *)pCtx; | |
719 Tcl_Obj *pScript = Tcl_DuplicateObj(pDb->pCollateNeeded); | |
720 Tcl_IncrRefCount(pScript); | |
721 Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj(zName, -1)); | |
722 Tcl_EvalObjEx(pDb->interp, pScript, 0); | |
723 Tcl_DecrRefCount(pScript); | |
724 } | |
725 | |
726 /* | |
727 ** This routine is called to evaluate an SQL collation function implemented | |
728 ** using TCL script. | |
729 */ | |
730 static int tclSqlCollate( | |
731 void *pCtx, | |
732 int nA, | |
733 const void *zA, | |
734 int nB, | |
735 const void *zB | |
736 ){ | |
737 SqlCollate *p = (SqlCollate *)pCtx; | |
738 Tcl_Obj *pCmd; | |
739 | |
740 pCmd = Tcl_NewStringObj(p->zScript, -1); | |
741 Tcl_IncrRefCount(pCmd); | |
742 Tcl_ListObjAppendElement(p->interp, pCmd, Tcl_NewStringObj(zA, nA)); | |
743 Tcl_ListObjAppendElement(p->interp, pCmd, Tcl_NewStringObj(zB, nB)); | |
744 Tcl_EvalObjEx(p->interp, pCmd, TCL_EVAL_DIRECT); | |
745 Tcl_DecrRefCount(pCmd); | |
746 return (atoi(Tcl_GetStringResult(p->interp))); | |
747 } | |
748 | |
749 /* | |
750 ** This routine is called to evaluate an SQL function implemented | |
751 ** using TCL script. | |
752 */ | |
753 static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){ | |
754 SqlFunc *p = sqlite3_user_data(context); | |
755 Tcl_Obj *pCmd; | |
756 int i; | |
757 int rc; | |
758 | |
759 if( argc==0 ){ | |
760 /* If there are no arguments to the function, call Tcl_EvalObjEx on the | |
761 ** script object directly. This allows the TCL compiler to generate | |
762 ** bytecode for the command on the first invocation and thus make | |
763 ** subsequent invocations much faster. */ | |
764 pCmd = p->pScript; | |
765 Tcl_IncrRefCount(pCmd); | |
766 rc = Tcl_EvalObjEx(p->interp, pCmd, 0); | |
767 Tcl_DecrRefCount(pCmd); | |
768 }else{ | |
769 /* If there are arguments to the function, make a shallow copy of the | |
770 ** script object, lappend the arguments, then evaluate the copy. | |
771 ** | |
772 ** By "shallow" copy, we mean only the outer list Tcl_Obj is duplicated. | |
773 ** The new Tcl_Obj contains pointers to the original list elements. | |
774 ** That way, when Tcl_EvalObjv() is run and shimmers the first element | |
775 ** of the list to tclCmdNameType, that alternate representation will | |
776 ** be preserved and reused on the next invocation. | |
777 */ | |
778 Tcl_Obj **aArg; | |
779 int nArg; | |
780 if( Tcl_ListObjGetElements(p->interp, p->pScript, &nArg, &aArg) ){ | |
781 sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1); | |
782 return; | |
783 } | |
784 pCmd = Tcl_NewListObj(nArg, aArg); | |
785 Tcl_IncrRefCount(pCmd); | |
786 for(i=0; i<argc; i++){ | |
787 sqlite3_value *pIn = argv[i]; | |
788 Tcl_Obj *pVal; | |
789 | |
790 /* Set pVal to contain the i'th column of this row. */ | |
791 switch( sqlite3_value_type(pIn) ){ | |
792 case SQLITE_BLOB: { | |
793 int bytes = sqlite3_value_bytes(pIn); | |
794 pVal = Tcl_NewByteArrayObj(sqlite3_value_blob(pIn), bytes); | |
795 break; | |
796 } | |
797 case SQLITE_INTEGER: { | |
798 sqlite_int64 v = sqlite3_value_int64(pIn); | |
799 if( v>=-2147483647 && v<=2147483647 ){ | |
800 pVal = Tcl_NewIntObj((int)v); | |
801 }else{ | |
802 pVal = Tcl_NewWideIntObj(v); | |
803 } | |
804 break; | |
805 } | |
806 case SQLITE_FLOAT: { | |
807 double r = sqlite3_value_double(pIn); | |
808 pVal = Tcl_NewDoubleObj(r); | |
809 break; | |
810 } | |
811 case SQLITE_NULL: { | |
812 pVal = Tcl_NewStringObj(p->pDb->zNull, -1); | |
813 break; | |
814 } | |
815 default: { | |
816 int bytes = sqlite3_value_bytes(pIn); | |
817 pVal = Tcl_NewStringObj((char *)sqlite3_value_text(pIn), bytes); | |
818 break; | |
819 } | |
820 } | |
821 rc = Tcl_ListObjAppendElement(p->interp, pCmd, pVal); | |
822 if( rc ){ | |
823 Tcl_DecrRefCount(pCmd); | |
824 sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1); | |
825 return; | |
826 } | |
827 } | |
828 if( !p->useEvalObjv ){ | |
829 /* Tcl_EvalObjEx() will automatically call Tcl_EvalObjv() if pCmd | |
830 ** is a list without a string representation. To prevent this from | |
831 ** happening, make sure pCmd has a valid string representation */ | |
832 Tcl_GetString(pCmd); | |
833 } | |
834 rc = Tcl_EvalObjEx(p->interp, pCmd, TCL_EVAL_DIRECT); | |
835 Tcl_DecrRefCount(pCmd); | |
836 } | |
837 | |
838 if( rc && rc!=TCL_RETURN ){ | |
839 sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1); | |
840 }else{ | |
841 Tcl_Obj *pVar = Tcl_GetObjResult(p->interp); | |
842 int n; | |
843 u8 *data; | |
844 const char *zType = (pVar->typePtr ? pVar->typePtr->name : ""); | |
845 char c = zType[0]; | |
846 if( c=='b' && strcmp(zType,"bytearray")==0 && pVar->bytes==0 ){ | |
847 /* Only return a BLOB type if the Tcl variable is a bytearray and | |
848 ** has no string representation. */ | |
849 data = Tcl_GetByteArrayFromObj(pVar, &n); | |
850 sqlite3_result_blob(context, data, n, SQLITE_TRANSIENT); | |
851 }else if( c=='b' && strcmp(zType,"boolean")==0 ){ | |
852 Tcl_GetIntFromObj(0, pVar, &n); | |
853 sqlite3_result_int(context, n); | |
854 }else if( c=='d' && strcmp(zType,"double")==0 ){ | |
855 double r; | |
856 Tcl_GetDoubleFromObj(0, pVar, &r); | |
857 sqlite3_result_double(context, r); | |
858 }else if( (c=='w' && strcmp(zType,"wideInt")==0) || | |
859 (c=='i' && strcmp(zType,"int")==0) ){ | |
860 Tcl_WideInt v; | |
861 Tcl_GetWideIntFromObj(0, pVar, &v); | |
862 sqlite3_result_int64(context, v); | |
863 }else{ | |
864 data = (unsigned char *)Tcl_GetStringFromObj(pVar, &n); | |
865 sqlite3_result_text(context, (char *)data, n, SQLITE_TRANSIENT); | |
866 } | |
867 } | |
868 } | |
869 | |
870 #ifndef SQLITE_OMIT_AUTHORIZATION | |
871 /* | |
872 ** This is the authentication function. It appends the authentication | |
873 ** type code and the two arguments to zCmd[] then invokes the result | |
874 ** on the interpreter. The reply is examined to determine if the | |
875 ** authentication fails or succeeds. | |
876 */ | |
877 static int auth_callback( | |
878 void *pArg, | |
879 int code, | |
880 const char *zArg1, | |
881 const char *zArg2, | |
882 const char *zArg3, | |
883 const char *zArg4 | |
884 #ifdef SQLITE_USER_AUTHENTICATION | |
885 ,const char *zArg5 | |
886 #endif | |
887 ){ | |
888 const char *zCode; | |
889 Tcl_DString str; | |
890 int rc; | |
891 const char *zReply; | |
892 SqliteDb *pDb = (SqliteDb*)pArg; | |
893 if( pDb->disableAuth ) return SQLITE_OK; | |
894 | |
895 switch( code ){ | |
896 case SQLITE_COPY : zCode="SQLITE_COPY"; break; | |
897 case SQLITE_CREATE_INDEX : zCode="SQLITE_CREATE_INDEX"; break; | |
898 case SQLITE_CREATE_TABLE : zCode="SQLITE_CREATE_TABLE"; break; | |
899 case SQLITE_CREATE_TEMP_INDEX : zCode="SQLITE_CREATE_TEMP_INDEX"; break; | |
900 case SQLITE_CREATE_TEMP_TABLE : zCode="SQLITE_CREATE_TEMP_TABLE"; break; | |
901 case SQLITE_CREATE_TEMP_TRIGGER: zCode="SQLITE_CREATE_TEMP_TRIGGER"; break; | |
902 case SQLITE_CREATE_TEMP_VIEW : zCode="SQLITE_CREATE_TEMP_VIEW"; break; | |
903 case SQLITE_CREATE_TRIGGER : zCode="SQLITE_CREATE_TRIGGER"; break; | |
904 case SQLITE_CREATE_VIEW : zCode="SQLITE_CREATE_VIEW"; break; | |
905 case SQLITE_DELETE : zCode="SQLITE_DELETE"; break; | |
906 case SQLITE_DROP_INDEX : zCode="SQLITE_DROP_INDEX"; break; | |
907 case SQLITE_DROP_TABLE : zCode="SQLITE_DROP_TABLE"; break; | |
908 case SQLITE_DROP_TEMP_INDEX : zCode="SQLITE_DROP_TEMP_INDEX"; break; | |
909 case SQLITE_DROP_TEMP_TABLE : zCode="SQLITE_DROP_TEMP_TABLE"; break; | |
910 case SQLITE_DROP_TEMP_TRIGGER : zCode="SQLITE_DROP_TEMP_TRIGGER"; break; | |
911 case SQLITE_DROP_TEMP_VIEW : zCode="SQLITE_DROP_TEMP_VIEW"; break; | |
912 case SQLITE_DROP_TRIGGER : zCode="SQLITE_DROP_TRIGGER"; break; | |
913 case SQLITE_DROP_VIEW : zCode="SQLITE_DROP_VIEW"; break; | |
914 case SQLITE_INSERT : zCode="SQLITE_INSERT"; break; | |
915 case SQLITE_PRAGMA : zCode="SQLITE_PRAGMA"; break; | |
916 case SQLITE_READ : zCode="SQLITE_READ"; break; | |
917 case SQLITE_SELECT : zCode="SQLITE_SELECT"; break; | |
918 case SQLITE_TRANSACTION : zCode="SQLITE_TRANSACTION"; break; | |
919 case SQLITE_UPDATE : zCode="SQLITE_UPDATE"; break; | |
920 case SQLITE_ATTACH : zCode="SQLITE_ATTACH"; break; | |
921 case SQLITE_DETACH : zCode="SQLITE_DETACH"; break; | |
922 case SQLITE_ALTER_TABLE : zCode="SQLITE_ALTER_TABLE"; break; | |
923 case SQLITE_REINDEX : zCode="SQLITE_REINDEX"; break; | |
924 case SQLITE_ANALYZE : zCode="SQLITE_ANALYZE"; break; | |
925 case SQLITE_CREATE_VTABLE : zCode="SQLITE_CREATE_VTABLE"; break; | |
926 case SQLITE_DROP_VTABLE : zCode="SQLITE_DROP_VTABLE"; break; | |
927 case SQLITE_FUNCTION : zCode="SQLITE_FUNCTION"; break; | |
928 case SQLITE_SAVEPOINT : zCode="SQLITE_SAVEPOINT"; break; | |
929 case SQLITE_RECURSIVE : zCode="SQLITE_RECURSIVE"; break; | |
930 default : zCode="????"; break; | |
931 } | |
932 Tcl_DStringInit(&str); | |
933 Tcl_DStringAppend(&str, pDb->zAuth, -1); | |
934 Tcl_DStringAppendElement(&str, zCode); | |
935 Tcl_DStringAppendElement(&str, zArg1 ? zArg1 : ""); | |
936 Tcl_DStringAppendElement(&str, zArg2 ? zArg2 : ""); | |
937 Tcl_DStringAppendElement(&str, zArg3 ? zArg3 : ""); | |
938 Tcl_DStringAppendElement(&str, zArg4 ? zArg4 : ""); | |
939 #ifdef SQLITE_USER_AUTHENTICATION | |
940 Tcl_DStringAppendElement(&str, zArg5 ? zArg5 : ""); | |
941 #endif | |
942 rc = Tcl_GlobalEval(pDb->interp, Tcl_DStringValue(&str)); | |
943 Tcl_DStringFree(&str); | |
944 zReply = rc==TCL_OK ? Tcl_GetStringResult(pDb->interp) : "SQLITE_DENY"; | |
945 if( strcmp(zReply,"SQLITE_OK")==0 ){ | |
946 rc = SQLITE_OK; | |
947 }else if( strcmp(zReply,"SQLITE_DENY")==0 ){ | |
948 rc = SQLITE_DENY; | |
949 }else if( strcmp(zReply,"SQLITE_IGNORE")==0 ){ | |
950 rc = SQLITE_IGNORE; | |
951 }else{ | |
952 rc = 999; | |
953 } | |
954 return rc; | |
955 } | |
956 #endif /* SQLITE_OMIT_AUTHORIZATION */ | |
957 | |
958 /* | |
959 ** This routine reads a line of text from FILE in, stores | |
960 ** the text in memory obtained from malloc() and returns a pointer | |
961 ** to the text. NULL is returned at end of file, or if malloc() | |
962 ** fails. | |
963 ** | |
964 ** The interface is like "readline" but no command-line editing | |
965 ** is done. | |
966 ** | |
967 ** copied from shell.c from '.import' command | |
968 */ | |
969 static char *local_getline(char *zPrompt, FILE *in){ | |
970 char *zLine; | |
971 int nLine; | |
972 int n; | |
973 | |
974 nLine = 100; | |
975 zLine = malloc( nLine ); | |
976 if( zLine==0 ) return 0; | |
977 n = 0; | |
978 while( 1 ){ | |
979 if( n+100>nLine ){ | |
980 nLine = nLine*2 + 100; | |
981 zLine = realloc(zLine, nLine); | |
982 if( zLine==0 ) return 0; | |
983 } | |
984 if( fgets(&zLine[n], nLine - n, in)==0 ){ | |
985 if( n==0 ){ | |
986 free(zLine); | |
987 return 0; | |
988 } | |
989 zLine[n] = 0; | |
990 break; | |
991 } | |
992 while( zLine[n] ){ n++; } | |
993 if( n>0 && zLine[n-1]=='\n' ){ | |
994 n--; | |
995 zLine[n] = 0; | |
996 break; | |
997 } | |
998 } | |
999 zLine = realloc( zLine, n+1 ); | |
1000 return zLine; | |
1001 } | |
1002 | |
1003 | |
1004 /* | |
1005 ** This function is part of the implementation of the command: | |
1006 ** | |
1007 ** $db transaction [-deferred|-immediate|-exclusive] SCRIPT | |
1008 ** | |
1009 ** It is invoked after evaluating the script SCRIPT to commit or rollback | |
1010 ** the transaction or savepoint opened by the [transaction] command. | |
1011 */ | |
1012 static int DbTransPostCmd( | |
1013 ClientData data[], /* data[0] is the Sqlite3Db* for $db */ | |
1014 Tcl_Interp *interp, /* Tcl interpreter */ | |
1015 int result /* Result of evaluating SCRIPT */ | |
1016 ){ | |
1017 static const char *const azEnd[] = { | |
1018 "RELEASE _tcl_transaction", /* rc==TCL_ERROR, nTransaction!=0 */ | |
1019 "COMMIT", /* rc!=TCL_ERROR, nTransaction==0 */ | |
1020 "ROLLBACK TO _tcl_transaction ; RELEASE _tcl_transaction", | |
1021 "ROLLBACK" /* rc==TCL_ERROR, nTransaction==0 */ | |
1022 }; | |
1023 SqliteDb *pDb = (SqliteDb*)data[0]; | |
1024 int rc = result; | |
1025 const char *zEnd; | |
1026 | |
1027 pDb->nTransaction--; | |
1028 zEnd = azEnd[(rc==TCL_ERROR)*2 + (pDb->nTransaction==0)]; | |
1029 | |
1030 pDb->disableAuth++; | |
1031 if( sqlite3_exec(pDb->db, zEnd, 0, 0, 0) ){ | |
1032 /* This is a tricky scenario to handle. The most likely cause of an | |
1033 ** error is that the exec() above was an attempt to commit the | |
1034 ** top-level transaction that returned SQLITE_BUSY. Or, less likely, | |
1035 ** that an IO-error has occurred. In either case, throw a Tcl exception | |
1036 ** and try to rollback the transaction. | |
1037 ** | |
1038 ** But it could also be that the user executed one or more BEGIN, | |
1039 ** COMMIT, SAVEPOINT, RELEASE or ROLLBACK commands that are confusing | |
1040 ** this method's logic. Not clear how this would be best handled. | |
1041 */ | |
1042 if( rc!=TCL_ERROR ){ | |
1043 Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), (char*)0); | |
1044 rc = TCL_ERROR; | |
1045 } | |
1046 sqlite3_exec(pDb->db, "ROLLBACK", 0, 0, 0); | |
1047 } | |
1048 pDb->disableAuth--; | |
1049 | |
1050 return rc; | |
1051 } | |
1052 | |
1053 /* | |
1054 ** Unless SQLITE_TEST is defined, this function is a simple wrapper around | |
1055 ** sqlite3_prepare_v2(). If SQLITE_TEST is defined, then it uses either | |
1056 ** sqlite3_prepare_v2() or legacy interface sqlite3_prepare(), depending | |
1057 ** on whether or not the [db_use_legacy_prepare] command has been used to | |
1058 ** configure the connection. | |
1059 */ | |
1060 static int dbPrepare( | |
1061 SqliteDb *pDb, /* Database object */ | |
1062 const char *zSql, /* SQL to compile */ | |
1063 sqlite3_stmt **ppStmt, /* OUT: Prepared statement */ | |
1064 const char **pzOut /* OUT: Pointer to next SQL statement */ | |
1065 ){ | |
1066 #ifdef SQLITE_TEST | |
1067 if( pDb->bLegacyPrepare ){ | |
1068 return sqlite3_prepare(pDb->db, zSql, -1, ppStmt, pzOut); | |
1069 } | |
1070 #endif | |
1071 return sqlite3_prepare_v2(pDb->db, zSql, -1, ppStmt, pzOut); | |
1072 } | |
1073 | |
1074 /* | |
1075 ** Search the cache for a prepared-statement object that implements the | |
1076 ** first SQL statement in the buffer pointed to by parameter zIn. If | |
1077 ** no such prepared-statement can be found, allocate and prepare a new | |
1078 ** one. In either case, bind the current values of the relevant Tcl | |
1079 ** variables to any $var, :var or @var variables in the statement. Before | |
1080 ** returning, set *ppPreStmt to point to the prepared-statement object. | |
1081 ** | |
1082 ** Output parameter *pzOut is set to point to the next SQL statement in | |
1083 ** buffer zIn, or to the '\0' byte at the end of zIn if there is no | |
1084 ** next statement. | |
1085 ** | |
1086 ** If successful, TCL_OK is returned. Otherwise, TCL_ERROR is returned | |
1087 ** and an error message loaded into interpreter pDb->interp. | |
1088 */ | |
1089 static int dbPrepareAndBind( | |
1090 SqliteDb *pDb, /* Database object */ | |
1091 char const *zIn, /* SQL to compile */ | |
1092 char const **pzOut, /* OUT: Pointer to next SQL statement */ | |
1093 SqlPreparedStmt **ppPreStmt /* OUT: Object used to cache statement */ | |
1094 ){ | |
1095 const char *zSql = zIn; /* Pointer to first SQL statement in zIn */ | |
1096 sqlite3_stmt *pStmt = 0; /* Prepared statement object */ | |
1097 SqlPreparedStmt *pPreStmt; /* Pointer to cached statement */ | |
1098 int nSql; /* Length of zSql in bytes */ | |
1099 int nVar = 0; /* Number of variables in statement */ | |
1100 int iParm = 0; /* Next free entry in apParm */ | |
1101 char c; | |
1102 int i; | |
1103 Tcl_Interp *interp = pDb->interp; | |
1104 | |
1105 *ppPreStmt = 0; | |
1106 | |
1107 /* Trim spaces from the start of zSql and calculate the remaining length. */ | |
1108 while( (c = zSql[0])==' ' || c=='\t' || c=='\r' || c=='\n' ){ zSql++; } | |
1109 nSql = strlen30(zSql); | |
1110 | |
1111 for(pPreStmt = pDb->stmtList; pPreStmt; pPreStmt=pPreStmt->pNext){ | |
1112 int n = pPreStmt->nSql; | |
1113 if( nSql>=n | |
1114 && memcmp(pPreStmt->zSql, zSql, n)==0 | |
1115 && (zSql[n]==0 || zSql[n-1]==';') | |
1116 ){ | |
1117 pStmt = pPreStmt->pStmt; | |
1118 *pzOut = &zSql[pPreStmt->nSql]; | |
1119 | |
1120 /* When a prepared statement is found, unlink it from the | |
1121 ** cache list. It will later be added back to the beginning | |
1122 ** of the cache list in order to implement LRU replacement. | |
1123 */ | |
1124 if( pPreStmt->pPrev ){ | |
1125 pPreStmt->pPrev->pNext = pPreStmt->pNext; | |
1126 }else{ | |
1127 pDb->stmtList = pPreStmt->pNext; | |
1128 } | |
1129 if( pPreStmt->pNext ){ | |
1130 pPreStmt->pNext->pPrev = pPreStmt->pPrev; | |
1131 }else{ | |
1132 pDb->stmtLast = pPreStmt->pPrev; | |
1133 } | |
1134 pDb->nStmt--; | |
1135 nVar = sqlite3_bind_parameter_count(pStmt); | |
1136 break; | |
1137 } | |
1138 } | |
1139 | |
1140 /* If no prepared statement was found. Compile the SQL text. Also allocate | |
1141 ** a new SqlPreparedStmt structure. */ | |
1142 if( pPreStmt==0 ){ | |
1143 int nByte; | |
1144 | |
1145 if( SQLITE_OK!=dbPrepare(pDb, zSql, &pStmt, pzOut) ){ | |
1146 Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3_errmsg(pDb->db), -1)); | |
1147 return TCL_ERROR; | |
1148 } | |
1149 if( pStmt==0 ){ | |
1150 if( SQLITE_OK!=sqlite3_errcode(pDb->db) ){ | |
1151 /* A compile-time error in the statement. */ | |
1152 Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3_errmsg(pDb->db), -1)); | |
1153 return TCL_ERROR; | |
1154 }else{ | |
1155 /* The statement was a no-op. Continue to the next statement | |
1156 ** in the SQL string. | |
1157 */ | |
1158 return TCL_OK; | |
1159 } | |
1160 } | |
1161 | |
1162 assert( pPreStmt==0 ); | |
1163 nVar = sqlite3_bind_parameter_count(pStmt); | |
1164 nByte = sizeof(SqlPreparedStmt) + nVar*sizeof(Tcl_Obj *); | |
1165 pPreStmt = (SqlPreparedStmt*)Tcl_Alloc(nByte); | |
1166 memset(pPreStmt, 0, nByte); | |
1167 | |
1168 pPreStmt->pStmt = pStmt; | |
1169 pPreStmt->nSql = (int)(*pzOut - zSql); | |
1170 pPreStmt->zSql = sqlite3_sql(pStmt); | |
1171 pPreStmt->apParm = (Tcl_Obj **)&pPreStmt[1]; | |
1172 #ifdef SQLITE_TEST | |
1173 if( pPreStmt->zSql==0 ){ | |
1174 char *zCopy = Tcl_Alloc(pPreStmt->nSql + 1); | |
1175 memcpy(zCopy, zSql, pPreStmt->nSql); | |
1176 zCopy[pPreStmt->nSql] = '\0'; | |
1177 pPreStmt->zSql = zCopy; | |
1178 } | |
1179 #endif | |
1180 } | |
1181 assert( pPreStmt ); | |
1182 assert( strlen30(pPreStmt->zSql)==pPreStmt->nSql ); | |
1183 assert( 0==memcmp(pPreStmt->zSql, zSql, pPreStmt->nSql) ); | |
1184 | |
1185 /* Bind values to parameters that begin with $ or : */ | |
1186 for(i=1; i<=nVar; i++){ | |
1187 const char *zVar = sqlite3_bind_parameter_name(pStmt, i); | |
1188 if( zVar!=0 && (zVar[0]=='$' || zVar[0]==':' || zVar[0]=='@') ){ | |
1189 Tcl_Obj *pVar = Tcl_GetVar2Ex(interp, &zVar[1], 0, 0); | |
1190 if( pVar ){ | |
1191 int n; | |
1192 u8 *data; | |
1193 const char *zType = (pVar->typePtr ? pVar->typePtr->name : ""); | |
1194 c = zType[0]; | |
1195 if( zVar[0]=='@' || | |
1196 (c=='b' && strcmp(zType,"bytearray")==0 && pVar->bytes==0) ){ | |
1197 /* Load a BLOB type if the Tcl variable is a bytearray and | |
1198 ** it has no string representation or the host | |
1199 ** parameter name begins with "@". */ | |
1200 data = Tcl_GetByteArrayFromObj(pVar, &n); | |
1201 sqlite3_bind_blob(pStmt, i, data, n, SQLITE_STATIC); | |
1202 Tcl_IncrRefCount(pVar); | |
1203 pPreStmt->apParm[iParm++] = pVar; | |
1204 }else if( c=='b' && strcmp(zType,"boolean")==0 ){ | |
1205 Tcl_GetIntFromObj(interp, pVar, &n); | |
1206 sqlite3_bind_int(pStmt, i, n); | |
1207 }else if( c=='d' && strcmp(zType,"double")==0 ){ | |
1208 double r; | |
1209 Tcl_GetDoubleFromObj(interp, pVar, &r); | |
1210 sqlite3_bind_double(pStmt, i, r); | |
1211 }else if( (c=='w' && strcmp(zType,"wideInt")==0) || | |
1212 (c=='i' && strcmp(zType,"int")==0) ){ | |
1213 Tcl_WideInt v; | |
1214 Tcl_GetWideIntFromObj(interp, pVar, &v); | |
1215 sqlite3_bind_int64(pStmt, i, v); | |
1216 }else{ | |
1217 data = (unsigned char *)Tcl_GetStringFromObj(pVar, &n); | |
1218 sqlite3_bind_text(pStmt, i, (char *)data, n, SQLITE_STATIC); | |
1219 Tcl_IncrRefCount(pVar); | |
1220 pPreStmt->apParm[iParm++] = pVar; | |
1221 } | |
1222 }else{ | |
1223 sqlite3_bind_null(pStmt, i); | |
1224 } | |
1225 } | |
1226 } | |
1227 pPreStmt->nParm = iParm; | |
1228 *ppPreStmt = pPreStmt; | |
1229 | |
1230 return TCL_OK; | |
1231 } | |
1232 | |
1233 /* | |
1234 ** Release a statement reference obtained by calling dbPrepareAndBind(). | |
1235 ** There should be exactly one call to this function for each call to | |
1236 ** dbPrepareAndBind(). | |
1237 ** | |
1238 ** If the discard parameter is non-zero, then the statement is deleted | |
1239 ** immediately. Otherwise it is added to the LRU list and may be returned | |
1240 ** by a subsequent call to dbPrepareAndBind(). | |
1241 */ | |
1242 static void dbReleaseStmt( | |
1243 SqliteDb *pDb, /* Database handle */ | |
1244 SqlPreparedStmt *pPreStmt, /* Prepared statement handle to release */ | |
1245 int discard /* True to delete (not cache) the pPreStmt */ | |
1246 ){ | |
1247 int i; | |
1248 | |
1249 /* Free the bound string and blob parameters */ | |
1250 for(i=0; i<pPreStmt->nParm; i++){ | |
1251 Tcl_DecrRefCount(pPreStmt->apParm[i]); | |
1252 } | |
1253 pPreStmt->nParm = 0; | |
1254 | |
1255 if( pDb->maxStmt<=0 || discard ){ | |
1256 /* If the cache is turned off, deallocated the statement */ | |
1257 dbFreeStmt(pPreStmt); | |
1258 }else{ | |
1259 /* Add the prepared statement to the beginning of the cache list. */ | |
1260 pPreStmt->pNext = pDb->stmtList; | |
1261 pPreStmt->pPrev = 0; | |
1262 if( pDb->stmtList ){ | |
1263 pDb->stmtList->pPrev = pPreStmt; | |
1264 } | |
1265 pDb->stmtList = pPreStmt; | |
1266 if( pDb->stmtLast==0 ){ | |
1267 assert( pDb->nStmt==0 ); | |
1268 pDb->stmtLast = pPreStmt; | |
1269 }else{ | |
1270 assert( pDb->nStmt>0 ); | |
1271 } | |
1272 pDb->nStmt++; | |
1273 | |
1274 /* If we have too many statement in cache, remove the surplus from | |
1275 ** the end of the cache list. */ | |
1276 while( pDb->nStmt>pDb->maxStmt ){ | |
1277 SqlPreparedStmt *pLast = pDb->stmtLast; | |
1278 pDb->stmtLast = pLast->pPrev; | |
1279 pDb->stmtLast->pNext = 0; | |
1280 pDb->nStmt--; | |
1281 dbFreeStmt(pLast); | |
1282 } | |
1283 } | |
1284 } | |
1285 | |
1286 /* | |
1287 ** Structure used with dbEvalXXX() functions: | |
1288 ** | |
1289 ** dbEvalInit() | |
1290 ** dbEvalStep() | |
1291 ** dbEvalFinalize() | |
1292 ** dbEvalRowInfo() | |
1293 ** dbEvalColumnValue() | |
1294 */ | |
1295 typedef struct DbEvalContext DbEvalContext; | |
1296 struct DbEvalContext { | |
1297 SqliteDb *pDb; /* Database handle */ | |
1298 Tcl_Obj *pSql; /* Object holding string zSql */ | |
1299 const char *zSql; /* Remaining SQL to execute */ | |
1300 SqlPreparedStmt *pPreStmt; /* Current statement */ | |
1301 int nCol; /* Number of columns returned by pStmt */ | |
1302 Tcl_Obj *pArray; /* Name of array variable */ | |
1303 Tcl_Obj **apColName; /* Array of column names */ | |
1304 }; | |
1305 | |
1306 /* | |
1307 ** Release any cache of column names currently held as part of | |
1308 ** the DbEvalContext structure passed as the first argument. | |
1309 */ | |
1310 static void dbReleaseColumnNames(DbEvalContext *p){ | |
1311 if( p->apColName ){ | |
1312 int i; | |
1313 for(i=0; i<p->nCol; i++){ | |
1314 Tcl_DecrRefCount(p->apColName[i]); | |
1315 } | |
1316 Tcl_Free((char *)p->apColName); | |
1317 p->apColName = 0; | |
1318 } | |
1319 p->nCol = 0; | |
1320 } | |
1321 | |
1322 /* | |
1323 ** Initialize a DbEvalContext structure. | |
1324 ** | |
1325 ** If pArray is not NULL, then it contains the name of a Tcl array | |
1326 ** variable. The "*" member of this array is set to a list containing | |
1327 ** the names of the columns returned by the statement as part of each | |
1328 ** call to dbEvalStep(), in order from left to right. e.g. if the names | |
1329 ** of the returned columns are a, b and c, it does the equivalent of the | |
1330 ** tcl command: | |
1331 ** | |
1332 ** set ${pArray}(*) {a b c} | |
1333 */ | |
1334 static void dbEvalInit( | |
1335 DbEvalContext *p, /* Pointer to structure to initialize */ | |
1336 SqliteDb *pDb, /* Database handle */ | |
1337 Tcl_Obj *pSql, /* Object containing SQL script */ | |
1338 Tcl_Obj *pArray /* Name of Tcl array to set (*) element of */ | |
1339 ){ | |
1340 memset(p, 0, sizeof(DbEvalContext)); | |
1341 p->pDb = pDb; | |
1342 p->zSql = Tcl_GetString(pSql); | |
1343 p->pSql = pSql; | |
1344 Tcl_IncrRefCount(pSql); | |
1345 if( pArray ){ | |
1346 p->pArray = pArray; | |
1347 Tcl_IncrRefCount(pArray); | |
1348 } | |
1349 } | |
1350 | |
1351 /* | |
1352 ** Obtain information about the row that the DbEvalContext passed as the | |
1353 ** first argument currently points to. | |
1354 */ | |
1355 static void dbEvalRowInfo( | |
1356 DbEvalContext *p, /* Evaluation context */ | |
1357 int *pnCol, /* OUT: Number of column names */ | |
1358 Tcl_Obj ***papColName /* OUT: Array of column names */ | |
1359 ){ | |
1360 /* Compute column names */ | |
1361 if( 0==p->apColName ){ | |
1362 sqlite3_stmt *pStmt = p->pPreStmt->pStmt; | |
1363 int i; /* Iterator variable */ | |
1364 int nCol; /* Number of columns returned by pStmt */ | |
1365 Tcl_Obj **apColName = 0; /* Array of column names */ | |
1366 | |
1367 p->nCol = nCol = sqlite3_column_count(pStmt); | |
1368 if( nCol>0 && (papColName || p->pArray) ){ | |
1369 apColName = (Tcl_Obj**)Tcl_Alloc( sizeof(Tcl_Obj*)*nCol ); | |
1370 for(i=0; i<nCol; i++){ | |
1371 apColName[i] = Tcl_NewStringObj(sqlite3_column_name(pStmt,i), -1); | |
1372 Tcl_IncrRefCount(apColName[i]); | |
1373 } | |
1374 p->apColName = apColName; | |
1375 } | |
1376 | |
1377 /* If results are being stored in an array variable, then create | |
1378 ** the array(*) entry for that array | |
1379 */ | |
1380 if( p->pArray ){ | |
1381 Tcl_Interp *interp = p->pDb->interp; | |
1382 Tcl_Obj *pColList = Tcl_NewObj(); | |
1383 Tcl_Obj *pStar = Tcl_NewStringObj("*", -1); | |
1384 | |
1385 for(i=0; i<nCol; i++){ | |
1386 Tcl_ListObjAppendElement(interp, pColList, apColName[i]); | |
1387 } | |
1388 Tcl_IncrRefCount(pStar); | |
1389 Tcl_ObjSetVar2(interp, p->pArray, pStar, pColList, 0); | |
1390 Tcl_DecrRefCount(pStar); | |
1391 } | |
1392 } | |
1393 | |
1394 if( papColName ){ | |
1395 *papColName = p->apColName; | |
1396 } | |
1397 if( pnCol ){ | |
1398 *pnCol = p->nCol; | |
1399 } | |
1400 } | |
1401 | |
1402 /* | |
1403 ** Return one of TCL_OK, TCL_BREAK or TCL_ERROR. If TCL_ERROR is | |
1404 ** returned, then an error message is stored in the interpreter before | |
1405 ** returning. | |
1406 ** | |
1407 ** A return value of TCL_OK means there is a row of data available. The | |
1408 ** data may be accessed using dbEvalRowInfo() and dbEvalColumnValue(). This | |
1409 ** is analogous to a return of SQLITE_ROW from sqlite3_step(). If TCL_BREAK | |
1410 ** is returned, then the SQL script has finished executing and there are | |
1411 ** no further rows available. This is similar to SQLITE_DONE. | |
1412 */ | |
1413 static int dbEvalStep(DbEvalContext *p){ | |
1414 const char *zPrevSql = 0; /* Previous value of p->zSql */ | |
1415 | |
1416 while( p->zSql[0] || p->pPreStmt ){ | |
1417 int rc; | |
1418 if( p->pPreStmt==0 ){ | |
1419 zPrevSql = (p->zSql==zPrevSql ? 0 : p->zSql); | |
1420 rc = dbPrepareAndBind(p->pDb, p->zSql, &p->zSql, &p->pPreStmt); | |
1421 if( rc!=TCL_OK ) return rc; | |
1422 }else{ | |
1423 int rcs; | |
1424 SqliteDb *pDb = p->pDb; | |
1425 SqlPreparedStmt *pPreStmt = p->pPreStmt; | |
1426 sqlite3_stmt *pStmt = pPreStmt->pStmt; | |
1427 | |
1428 rcs = sqlite3_step(pStmt); | |
1429 if( rcs==SQLITE_ROW ){ | |
1430 return TCL_OK; | |
1431 } | |
1432 if( p->pArray ){ | |
1433 dbEvalRowInfo(p, 0, 0); | |
1434 } | |
1435 rcs = sqlite3_reset(pStmt); | |
1436 | |
1437 pDb->nStep = sqlite3_stmt_status(pStmt,SQLITE_STMTSTATUS_FULLSCAN_STEP,1); | |
1438 pDb->nSort = sqlite3_stmt_status(pStmt,SQLITE_STMTSTATUS_SORT,1); | |
1439 pDb->nIndex = sqlite3_stmt_status(pStmt,SQLITE_STMTSTATUS_AUTOINDEX,1); | |
1440 dbReleaseColumnNames(p); | |
1441 p->pPreStmt = 0; | |
1442 | |
1443 if( rcs!=SQLITE_OK ){ | |
1444 /* If a run-time error occurs, report the error and stop reading | |
1445 ** the SQL. */ | |
1446 dbReleaseStmt(pDb, pPreStmt, 1); | |
1447 #if SQLITE_TEST | |
1448 if( p->pDb->bLegacyPrepare && rcs==SQLITE_SCHEMA && zPrevSql ){ | |
1449 /* If the runtime error was an SQLITE_SCHEMA, and the database | |
1450 ** handle is configured to use the legacy sqlite3_prepare() | |
1451 ** interface, retry prepare()/step() on the same SQL statement. | |
1452 ** This only happens once. If there is a second SQLITE_SCHEMA | |
1453 ** error, the error will be returned to the caller. */ | |
1454 p->zSql = zPrevSql; | |
1455 continue; | |
1456 } | |
1457 #endif | |
1458 Tcl_SetObjResult(pDb->interp, | |
1459 Tcl_NewStringObj(sqlite3_errmsg(pDb->db), -1)); | |
1460 return TCL_ERROR; | |
1461 }else{ | |
1462 dbReleaseStmt(pDb, pPreStmt, 0); | |
1463 } | |
1464 } | |
1465 } | |
1466 | |
1467 /* Finished */ | |
1468 return TCL_BREAK; | |
1469 } | |
1470 | |
1471 /* | |
1472 ** Free all resources currently held by the DbEvalContext structure passed | |
1473 ** as the first argument. There should be exactly one call to this function | |
1474 ** for each call to dbEvalInit(). | |
1475 */ | |
1476 static void dbEvalFinalize(DbEvalContext *p){ | |
1477 if( p->pPreStmt ){ | |
1478 sqlite3_reset(p->pPreStmt->pStmt); | |
1479 dbReleaseStmt(p->pDb, p->pPreStmt, 0); | |
1480 p->pPreStmt = 0; | |
1481 } | |
1482 if( p->pArray ){ | |
1483 Tcl_DecrRefCount(p->pArray); | |
1484 p->pArray = 0; | |
1485 } | |
1486 Tcl_DecrRefCount(p->pSql); | |
1487 dbReleaseColumnNames(p); | |
1488 } | |
1489 | |
1490 /* | |
1491 ** Return a pointer to a Tcl_Obj structure with ref-count 0 that contains | |
1492 ** the value for the iCol'th column of the row currently pointed to by | |
1493 ** the DbEvalContext structure passed as the first argument. | |
1494 */ | |
1495 static Tcl_Obj *dbEvalColumnValue(DbEvalContext *p, int iCol){ | |
1496 sqlite3_stmt *pStmt = p->pPreStmt->pStmt; | |
1497 switch( sqlite3_column_type(pStmt, iCol) ){ | |
1498 case SQLITE_BLOB: { | |
1499 int bytes = sqlite3_column_bytes(pStmt, iCol); | |
1500 const char *zBlob = sqlite3_column_blob(pStmt, iCol); | |
1501 if( !zBlob ) bytes = 0; | |
1502 return Tcl_NewByteArrayObj((u8*)zBlob, bytes); | |
1503 } | |
1504 case SQLITE_INTEGER: { | |
1505 sqlite_int64 v = sqlite3_column_int64(pStmt, iCol); | |
1506 if( v>=-2147483647 && v<=2147483647 ){ | |
1507 return Tcl_NewIntObj((int)v); | |
1508 }else{ | |
1509 return Tcl_NewWideIntObj(v); | |
1510 } | |
1511 } | |
1512 case SQLITE_FLOAT: { | |
1513 return Tcl_NewDoubleObj(sqlite3_column_double(pStmt, iCol)); | |
1514 } | |
1515 case SQLITE_NULL: { | |
1516 return Tcl_NewStringObj(p->pDb->zNull, -1); | |
1517 } | |
1518 } | |
1519 | |
1520 return Tcl_NewStringObj((char*)sqlite3_column_text(pStmt, iCol), -1); | |
1521 } | |
1522 | |
1523 /* | |
1524 ** If using Tcl version 8.6 or greater, use the NR functions to avoid | |
1525 ** recursive evalution of scripts by the [db eval] and [db trans] | |
1526 ** commands. Even if the headers used while compiling the extension | |
1527 ** are 8.6 or newer, the code still tests the Tcl version at runtime. | |
1528 ** This allows stubs-enabled builds to be used with older Tcl libraries. | |
1529 */ | |
1530 #if TCL_MAJOR_VERSION>8 || (TCL_MAJOR_VERSION==8 && TCL_MINOR_VERSION>=6) | |
1531 # define SQLITE_TCL_NRE 1 | |
1532 static int DbUseNre(void){ | |
1533 int major, minor; | |
1534 Tcl_GetVersion(&major, &minor, 0, 0); | |
1535 return( (major==8 && minor>=6) || major>8 ); | |
1536 } | |
1537 #else | |
1538 /* | |
1539 ** Compiling using headers earlier than 8.6. In this case NR cannot be | |
1540 ** used, so DbUseNre() to always return zero. Add #defines for the other | |
1541 ** Tcl_NRxxx() functions to prevent them from causing compilation errors, | |
1542 ** even though the only invocations of them are within conditional blocks | |
1543 ** of the form: | |
1544 ** | |
1545 ** if( DbUseNre() ) { ... } | |
1546 */ | |
1547 # define SQLITE_TCL_NRE 0 | |
1548 # define DbUseNre() 0 | |
1549 # define Tcl_NRAddCallback(a,b,c,d,e,f) (void)0 | |
1550 # define Tcl_NREvalObj(a,b,c) 0 | |
1551 # define Tcl_NRCreateCommand(a,b,c,d,e,f) (void)0 | |
1552 #endif | |
1553 | |
1554 /* | |
1555 ** This function is part of the implementation of the command: | |
1556 ** | |
1557 ** $db eval SQL ?ARRAYNAME? SCRIPT | |
1558 */ | |
1559 static int DbEvalNextCmd( | |
1560 ClientData data[], /* data[0] is the (DbEvalContext*) */ | |
1561 Tcl_Interp *interp, /* Tcl interpreter */ | |
1562 int result /* Result so far */ | |
1563 ){ | |
1564 int rc = result; /* Return code */ | |
1565 | |
1566 /* The first element of the data[] array is a pointer to a DbEvalContext | |
1567 ** structure allocated using Tcl_Alloc(). The second element of data[] | |
1568 ** is a pointer to a Tcl_Obj containing the script to run for each row | |
1569 ** returned by the queries encapsulated in data[0]. */ | |
1570 DbEvalContext *p = (DbEvalContext *)data[0]; | |
1571 Tcl_Obj *pScript = (Tcl_Obj *)data[1]; | |
1572 Tcl_Obj *pArray = p->pArray; | |
1573 | |
1574 while( (rc==TCL_OK || rc==TCL_CONTINUE) && TCL_OK==(rc = dbEvalStep(p)) ){ | |
1575 int i; | |
1576 int nCol; | |
1577 Tcl_Obj **apColName; | |
1578 dbEvalRowInfo(p, &nCol, &apColName); | |
1579 for(i=0; i<nCol; i++){ | |
1580 Tcl_Obj *pVal = dbEvalColumnValue(p, i); | |
1581 if( pArray==0 ){ | |
1582 Tcl_ObjSetVar2(interp, apColName[i], 0, pVal, 0); | |
1583 }else{ | |
1584 Tcl_ObjSetVar2(interp, pArray, apColName[i], pVal, 0); | |
1585 } | |
1586 } | |
1587 | |
1588 /* The required interpreter variables are now populated with the data | |
1589 ** from the current row. If using NRE, schedule callbacks to evaluate | |
1590 ** script pScript, then to invoke this function again to fetch the next | |
1591 ** row (or clean up if there is no next row or the script throws an | |
1592 ** exception). After scheduling the callbacks, return control to the | |
1593 ** caller. | |
1594 ** | |
1595 ** If not using NRE, evaluate pScript directly and continue with the | |
1596 ** next iteration of this while(...) loop. */ | |
1597 if( DbUseNre() ){ | |
1598 Tcl_NRAddCallback(interp, DbEvalNextCmd, (void*)p, (void*)pScript, 0, 0); | |
1599 return Tcl_NREvalObj(interp, pScript, 0); | |
1600 }else{ | |
1601 rc = Tcl_EvalObjEx(interp, pScript, 0); | |
1602 } | |
1603 } | |
1604 | |
1605 Tcl_DecrRefCount(pScript); | |
1606 dbEvalFinalize(p); | |
1607 Tcl_Free((char *)p); | |
1608 | |
1609 if( rc==TCL_OK || rc==TCL_BREAK ){ | |
1610 Tcl_ResetResult(interp); | |
1611 rc = TCL_OK; | |
1612 } | |
1613 return rc; | |
1614 } | |
1615 | |
1616 /* | |
1617 ** The "sqlite" command below creates a new Tcl command for each | |
1618 ** connection it opens to an SQLite database. This routine is invoked | |
1619 ** whenever one of those connection-specific commands is executed | |
1620 ** in Tcl. For example, if you run Tcl code like this: | |
1621 ** | |
1622 ** sqlite3 db1 "my_database" | |
1623 ** db1 close | |
1624 ** | |
1625 ** The first command opens a connection to the "my_database" database | |
1626 ** and calls that connection "db1". The second command causes this | |
1627 ** subroutine to be invoked. | |
1628 */ | |
1629 static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ | |
1630 SqliteDb *pDb = (SqliteDb*)cd; | |
1631 int choice; | |
1632 int rc = TCL_OK; | |
1633 static const char *DB_strs[] = { | |
1634 "authorizer", "backup", "busy", | |
1635 "cache", "changes", "close", | |
1636 "collate", "collation_needed", "commit_hook", | |
1637 "complete", "copy", "enable_load_extension", | |
1638 "errorcode", "eval", "exists", | |
1639 "function", "incrblob", "interrupt", | |
1640 "last_insert_rowid", "nullvalue", "onecolumn", | |
1641 "profile", "progress", "rekey", | |
1642 "restore", "rollback_hook", "status", | |
1643 "timeout", "total_changes", "trace", | |
1644 "transaction", "unlock_notify", "update_hook", | |
1645 "version", "wal_hook", 0 | |
1646 }; | |
1647 enum DB_enum { | |
1648 DB_AUTHORIZER, DB_BACKUP, DB_BUSY, | |
1649 DB_CACHE, DB_CHANGES, DB_CLOSE, | |
1650 DB_COLLATE, DB_COLLATION_NEEDED, DB_COMMIT_HOOK, | |
1651 DB_COMPLETE, DB_COPY, DB_ENABLE_LOAD_EXTENSION, | |
1652 DB_ERRORCODE, DB_EVAL, DB_EXISTS, | |
1653 DB_FUNCTION, DB_INCRBLOB, DB_INTERRUPT, | |
1654 DB_LAST_INSERT_ROWID, DB_NULLVALUE, DB_ONECOLUMN, | |
1655 DB_PROFILE, DB_PROGRESS, DB_REKEY, | |
1656 DB_RESTORE, DB_ROLLBACK_HOOK, DB_STATUS, | |
1657 DB_TIMEOUT, DB_TOTAL_CHANGES, DB_TRACE, | |
1658 DB_TRANSACTION, DB_UNLOCK_NOTIFY, DB_UPDATE_HOOK, | |
1659 DB_VERSION, DB_WAL_HOOK | |
1660 }; | |
1661 /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */ | |
1662 | |
1663 if( objc<2 ){ | |
1664 Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ..."); | |
1665 return TCL_ERROR; | |
1666 } | |
1667 if( Tcl_GetIndexFromObj(interp, objv[1], DB_strs, "option", 0, &choice) ){ | |
1668 return TCL_ERROR; | |
1669 } | |
1670 | |
1671 switch( (enum DB_enum)choice ){ | |
1672 | |
1673 /* $db authorizer ?CALLBACK? | |
1674 ** | |
1675 ** Invoke the given callback to authorize each SQL operation as it is | |
1676 ** compiled. 5 arguments are appended to the callback before it is | |
1677 ** invoked: | |
1678 ** | |
1679 ** (1) The authorization type (ex: SQLITE_CREATE_TABLE, SQLITE_INSERT, ...) | |
1680 ** (2) First descriptive name (depends on authorization type) | |
1681 ** (3) Second descriptive name | |
1682 ** (4) Name of the database (ex: "main", "temp") | |
1683 ** (5) Name of trigger that is doing the access | |
1684 ** | |
1685 ** The callback should return on of the following strings: SQLITE_OK, | |
1686 ** SQLITE_IGNORE, or SQLITE_DENY. Any other return value is an error. | |
1687 ** | |
1688 ** If this method is invoked with no arguments, the current authorization | |
1689 ** callback string is returned. | |
1690 */ | |
1691 case DB_AUTHORIZER: { | |
1692 #ifdef SQLITE_OMIT_AUTHORIZATION | |
1693 Tcl_AppendResult(interp, "authorization not available in this build", | |
1694 (char*)0); | |
1695 return TCL_ERROR; | |
1696 #else | |
1697 if( objc>3 ){ | |
1698 Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?"); | |
1699 return TCL_ERROR; | |
1700 }else if( objc==2 ){ | |
1701 if( pDb->zAuth ){ | |
1702 Tcl_AppendResult(interp, pDb->zAuth, (char*)0); | |
1703 } | |
1704 }else{ | |
1705 char *zAuth; | |
1706 int len; | |
1707 if( pDb->zAuth ){ | |
1708 Tcl_Free(pDb->zAuth); | |
1709 } | |
1710 zAuth = Tcl_GetStringFromObj(objv[2], &len); | |
1711 if( zAuth && len>0 ){ | |
1712 pDb->zAuth = Tcl_Alloc( len + 1 ); | |
1713 memcpy(pDb->zAuth, zAuth, len+1); | |
1714 }else{ | |
1715 pDb->zAuth = 0; | |
1716 } | |
1717 if( pDb->zAuth ){ | |
1718 typedef int (*sqlite3_auth_cb)( | |
1719 void*,int,const char*,const char*, | |
1720 const char*,const char*); | |
1721 pDb->interp = interp; | |
1722 sqlite3_set_authorizer(pDb->db,(sqlite3_auth_cb)auth_callback,pDb); | |
1723 }else{ | |
1724 sqlite3_set_authorizer(pDb->db, 0, 0); | |
1725 } | |
1726 } | |
1727 #endif | |
1728 break; | |
1729 } | |
1730 | |
1731 /* $db backup ?DATABASE? FILENAME | |
1732 ** | |
1733 ** Open or create a database file named FILENAME. Transfer the | |
1734 ** content of local database DATABASE (default: "main") into the | |
1735 ** FILENAME database. | |
1736 */ | |
1737 case DB_BACKUP: { | |
1738 const char *zDestFile; | |
1739 const char *zSrcDb; | |
1740 sqlite3 *pDest; | |
1741 sqlite3_backup *pBackup; | |
1742 | |
1743 if( objc==3 ){ | |
1744 zSrcDb = "main"; | |
1745 zDestFile = Tcl_GetString(objv[2]); | |
1746 }else if( objc==4 ){ | |
1747 zSrcDb = Tcl_GetString(objv[2]); | |
1748 zDestFile = Tcl_GetString(objv[3]); | |
1749 }else{ | |
1750 Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE? FILENAME"); | |
1751 return TCL_ERROR; | |
1752 } | |
1753 rc = sqlite3_open(zDestFile, &pDest); | |
1754 if( rc!=SQLITE_OK ){ | |
1755 Tcl_AppendResult(interp, "cannot open target database: ", | |
1756 sqlite3_errmsg(pDest), (char*)0); | |
1757 sqlite3_close(pDest); | |
1758 return TCL_ERROR; | |
1759 } | |
1760 pBackup = sqlite3_backup_init(pDest, "main", pDb->db, zSrcDb); | |
1761 if( pBackup==0 ){ | |
1762 Tcl_AppendResult(interp, "backup failed: ", | |
1763 sqlite3_errmsg(pDest), (char*)0); | |
1764 sqlite3_close(pDest); | |
1765 return TCL_ERROR; | |
1766 } | |
1767 while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){} | |
1768 sqlite3_backup_finish(pBackup); | |
1769 if( rc==SQLITE_DONE ){ | |
1770 rc = TCL_OK; | |
1771 }else{ | |
1772 Tcl_AppendResult(interp, "backup failed: ", | |
1773 sqlite3_errmsg(pDest), (char*)0); | |
1774 rc = TCL_ERROR; | |
1775 } | |
1776 sqlite3_close(pDest); | |
1777 break; | |
1778 } | |
1779 | |
1780 /* $db busy ?CALLBACK? | |
1781 ** | |
1782 ** Invoke the given callback if an SQL statement attempts to open | |
1783 ** a locked database file. | |
1784 */ | |
1785 case DB_BUSY: { | |
1786 if( objc>3 ){ | |
1787 Tcl_WrongNumArgs(interp, 2, objv, "CALLBACK"); | |
1788 return TCL_ERROR; | |
1789 }else if( objc==2 ){ | |
1790 if( pDb->zBusy ){ | |
1791 Tcl_AppendResult(interp, pDb->zBusy, (char*)0); | |
1792 } | |
1793 }else{ | |
1794 char *zBusy; | |
1795 int len; | |
1796 if( pDb->zBusy ){ | |
1797 Tcl_Free(pDb->zBusy); | |
1798 } | |
1799 zBusy = Tcl_GetStringFromObj(objv[2], &len); | |
1800 if( zBusy && len>0 ){ | |
1801 pDb->zBusy = Tcl_Alloc( len + 1 ); | |
1802 memcpy(pDb->zBusy, zBusy, len+1); | |
1803 }else{ | |
1804 pDb->zBusy = 0; | |
1805 } | |
1806 if( pDb->zBusy ){ | |
1807 pDb->interp = interp; | |
1808 sqlite3_busy_handler(pDb->db, DbBusyHandler, pDb); | |
1809 }else{ | |
1810 sqlite3_busy_handler(pDb->db, 0, 0); | |
1811 } | |
1812 } | |
1813 break; | |
1814 } | |
1815 | |
1816 /* $db cache flush | |
1817 ** $db cache size n | |
1818 ** | |
1819 ** Flush the prepared statement cache, or set the maximum number of | |
1820 ** cached statements. | |
1821 */ | |
1822 case DB_CACHE: { | |
1823 char *subCmd; | |
1824 int n; | |
1825 | |
1826 if( objc<=2 ){ | |
1827 Tcl_WrongNumArgs(interp, 1, objv, "cache option ?arg?"); | |
1828 return TCL_ERROR; | |
1829 } | |
1830 subCmd = Tcl_GetStringFromObj( objv[2], 0 ); | |
1831 if( *subCmd=='f' && strcmp(subCmd,"flush")==0 ){ | |
1832 if( objc!=3 ){ | |
1833 Tcl_WrongNumArgs(interp, 2, objv, "flush"); | |
1834 return TCL_ERROR; | |
1835 }else{ | |
1836 flushStmtCache( pDb ); | |
1837 } | |
1838 }else if( *subCmd=='s' && strcmp(subCmd,"size")==0 ){ | |
1839 if( objc!=4 ){ | |
1840 Tcl_WrongNumArgs(interp, 2, objv, "size n"); | |
1841 return TCL_ERROR; | |
1842 }else{ | |
1843 if( TCL_ERROR==Tcl_GetIntFromObj(interp, objv[3], &n) ){ | |
1844 Tcl_AppendResult( interp, "cannot convert \"", | |
1845 Tcl_GetStringFromObj(objv[3],0), "\" to integer", (char*)0); | |
1846 return TCL_ERROR; | |
1847 }else{ | |
1848 if( n<0 ){ | |
1849 flushStmtCache( pDb ); | |
1850 n = 0; | |
1851 }else if( n>MAX_PREPARED_STMTS ){ | |
1852 n = MAX_PREPARED_STMTS; | |
1853 } | |
1854 pDb->maxStmt = n; | |
1855 } | |
1856 } | |
1857 }else{ | |
1858 Tcl_AppendResult( interp, "bad option \"", | |
1859 Tcl_GetStringFromObj(objv[2],0), "\": must be flush or size", | |
1860 (char*)0); | |
1861 return TCL_ERROR; | |
1862 } | |
1863 break; | |
1864 } | |
1865 | |
1866 /* $db changes | |
1867 ** | |
1868 ** Return the number of rows that were modified, inserted, or deleted by | |
1869 ** the most recent INSERT, UPDATE or DELETE statement, not including | |
1870 ** any changes made by trigger programs. | |
1871 */ | |
1872 case DB_CHANGES: { | |
1873 Tcl_Obj *pResult; | |
1874 if( objc!=2 ){ | |
1875 Tcl_WrongNumArgs(interp, 2, objv, ""); | |
1876 return TCL_ERROR; | |
1877 } | |
1878 pResult = Tcl_GetObjResult(interp); | |
1879 Tcl_SetIntObj(pResult, sqlite3_changes(pDb->db)); | |
1880 break; | |
1881 } | |
1882 | |
1883 /* $db close | |
1884 ** | |
1885 ** Shutdown the database | |
1886 */ | |
1887 case DB_CLOSE: { | |
1888 Tcl_DeleteCommand(interp, Tcl_GetStringFromObj(objv[0], 0)); | |
1889 break; | |
1890 } | |
1891 | |
1892 /* | |
1893 ** $db collate NAME SCRIPT | |
1894 ** | |
1895 ** Create a new SQL collation function called NAME. Whenever | |
1896 ** that function is called, invoke SCRIPT to evaluate the function. | |
1897 */ | |
1898 case DB_COLLATE: { | |
1899 SqlCollate *pCollate; | |
1900 char *zName; | |
1901 char *zScript; | |
1902 int nScript; | |
1903 if( objc!=4 ){ | |
1904 Tcl_WrongNumArgs(interp, 2, objv, "NAME SCRIPT"); | |
1905 return TCL_ERROR; | |
1906 } | |
1907 zName = Tcl_GetStringFromObj(objv[2], 0); | |
1908 zScript = Tcl_GetStringFromObj(objv[3], &nScript); | |
1909 pCollate = (SqlCollate*)Tcl_Alloc( sizeof(*pCollate) + nScript + 1 ); | |
1910 if( pCollate==0 ) return TCL_ERROR; | |
1911 pCollate->interp = interp; | |
1912 pCollate->pNext = pDb->pCollate; | |
1913 pCollate->zScript = (char*)&pCollate[1]; | |
1914 pDb->pCollate = pCollate; | |
1915 memcpy(pCollate->zScript, zScript, nScript+1); | |
1916 if( sqlite3_create_collation(pDb->db, zName, SQLITE_UTF8, | |
1917 pCollate, tclSqlCollate) ){ | |
1918 Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE); | |
1919 return TCL_ERROR; | |
1920 } | |
1921 break; | |
1922 } | |
1923 | |
1924 /* | |
1925 ** $db collation_needed SCRIPT | |
1926 ** | |
1927 ** Create a new SQL collation function called NAME. Whenever | |
1928 ** that function is called, invoke SCRIPT to evaluate the function. | |
1929 */ | |
1930 case DB_COLLATION_NEEDED: { | |
1931 if( objc!=3 ){ | |
1932 Tcl_WrongNumArgs(interp, 2, objv, "SCRIPT"); | |
1933 return TCL_ERROR; | |
1934 } | |
1935 if( pDb->pCollateNeeded ){ | |
1936 Tcl_DecrRefCount(pDb->pCollateNeeded); | |
1937 } | |
1938 pDb->pCollateNeeded = Tcl_DuplicateObj(objv[2]); | |
1939 Tcl_IncrRefCount(pDb->pCollateNeeded); | |
1940 sqlite3_collation_needed(pDb->db, pDb, tclCollateNeeded); | |
1941 break; | |
1942 } | |
1943 | |
1944 /* $db commit_hook ?CALLBACK? | |
1945 ** | |
1946 ** Invoke the given callback just before committing every SQL transaction. | |
1947 ** If the callback throws an exception or returns non-zero, then the | |
1948 ** transaction is aborted. If CALLBACK is an empty string, the callback | |
1949 ** is disabled. | |
1950 */ | |
1951 case DB_COMMIT_HOOK: { | |
1952 if( objc>3 ){ | |
1953 Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?"); | |
1954 return TCL_ERROR; | |
1955 }else if( objc==2 ){ | |
1956 if( pDb->zCommit ){ | |
1957 Tcl_AppendResult(interp, pDb->zCommit, (char*)0); | |
1958 } | |
1959 }else{ | |
1960 const char *zCommit; | |
1961 int len; | |
1962 if( pDb->zCommit ){ | |
1963 Tcl_Free(pDb->zCommit); | |
1964 } | |
1965 zCommit = Tcl_GetStringFromObj(objv[2], &len); | |
1966 if( zCommit && len>0 ){ | |
1967 pDb->zCommit = Tcl_Alloc( len + 1 ); | |
1968 memcpy(pDb->zCommit, zCommit, len+1); | |
1969 }else{ | |
1970 pDb->zCommit = 0; | |
1971 } | |
1972 if( pDb->zCommit ){ | |
1973 pDb->interp = interp; | |
1974 sqlite3_commit_hook(pDb->db, DbCommitHandler, pDb); | |
1975 }else{ | |
1976 sqlite3_commit_hook(pDb->db, 0, 0); | |
1977 } | |
1978 } | |
1979 break; | |
1980 } | |
1981 | |
1982 /* $db complete SQL | |
1983 ** | |
1984 ** Return TRUE if SQL is a complete SQL statement. Return FALSE if | |
1985 ** additional lines of input are needed. This is similar to the | |
1986 ** built-in "info complete" command of Tcl. | |
1987 */ | |
1988 case DB_COMPLETE: { | |
1989 #ifndef SQLITE_OMIT_COMPLETE | |
1990 Tcl_Obj *pResult; | |
1991 int isComplete; | |
1992 if( objc!=3 ){ | |
1993 Tcl_WrongNumArgs(interp, 2, objv, "SQL"); | |
1994 return TCL_ERROR; | |
1995 } | |
1996 isComplete = sqlite3_complete( Tcl_GetStringFromObj(objv[2], 0) ); | |
1997 pResult = Tcl_GetObjResult(interp); | |
1998 Tcl_SetBooleanObj(pResult, isComplete); | |
1999 #endif | |
2000 break; | |
2001 } | |
2002 | |
2003 /* $db copy conflict-algorithm table filename ?SEPARATOR? ?NULLINDICATOR? | |
2004 ** | |
2005 ** Copy data into table from filename, optionally using SEPARATOR | |
2006 ** as column separators. If a column contains a null string, or the | |
2007 ** value of NULLINDICATOR, a NULL is inserted for the column. | |
2008 ** conflict-algorithm is one of the sqlite conflict algorithms: | |
2009 ** rollback, abort, fail, ignore, replace | |
2010 ** On success, return the number of lines processed, not necessarily same | |
2011 ** as 'db changes' due to conflict-algorithm selected. | |
2012 ** | |
2013 ** This code is basically an implementation/enhancement of | |
2014 ** the sqlite3 shell.c ".import" command. | |
2015 ** | |
2016 ** This command usage is equivalent to the sqlite2.x COPY statement, | |
2017 ** which imports file data into a table using the PostgreSQL COPY file format: | |
2018 ** $db copy $conflit_algo $table_name $filename \t \\N | |
2019 */ | |
2020 case DB_COPY: { | |
2021 char *zTable; /* Insert data into this table */ | |
2022 char *zFile; /* The file from which to extract data */ | |
2023 char *zConflict; /* The conflict algorithm to use */ | |
2024 sqlite3_stmt *pStmt; /* A statement */ | |
2025 int nCol; /* Number of columns in the table */ | |
2026 int nByte; /* Number of bytes in an SQL string */ | |
2027 int i, j; /* Loop counters */ | |
2028 int nSep; /* Number of bytes in zSep[] */ | |
2029 int nNull; /* Number of bytes in zNull[] */ | |
2030 char *zSql; /* An SQL statement */ | |
2031 char *zLine; /* A single line of input from the file */ | |
2032 char **azCol; /* zLine[] broken up into columns */ | |
2033 const char *zCommit; /* How to commit changes */ | |
2034 FILE *in; /* The input file */ | |
2035 int lineno = 0; /* Line number of input file */ | |
2036 char zLineNum[80]; /* Line number print buffer */ | |
2037 Tcl_Obj *pResult; /* interp result */ | |
2038 | |
2039 const char *zSep; | |
2040 const char *zNull; | |
2041 if( objc<5 || objc>7 ){ | |
2042 Tcl_WrongNumArgs(interp, 2, objv, | |
2043 "CONFLICT-ALGORITHM TABLE FILENAME ?SEPARATOR? ?NULLINDICATOR?"); | |
2044 return TCL_ERROR; | |
2045 } | |
2046 if( objc>=6 ){ | |
2047 zSep = Tcl_GetStringFromObj(objv[5], 0); | |
2048 }else{ | |
2049 zSep = "\t"; | |
2050 } | |
2051 if( objc>=7 ){ | |
2052 zNull = Tcl_GetStringFromObj(objv[6], 0); | |
2053 }else{ | |
2054 zNull = ""; | |
2055 } | |
2056 zConflict = Tcl_GetStringFromObj(objv[2], 0); | |
2057 zTable = Tcl_GetStringFromObj(objv[3], 0); | |
2058 zFile = Tcl_GetStringFromObj(objv[4], 0); | |
2059 nSep = strlen30(zSep); | |
2060 nNull = strlen30(zNull); | |
2061 if( nSep==0 ){ | |
2062 Tcl_AppendResult(interp,"Error: non-null separator required for copy", | |
2063 (char*)0); | |
2064 return TCL_ERROR; | |
2065 } | |
2066 if(strcmp(zConflict, "rollback") != 0 && | |
2067 strcmp(zConflict, "abort" ) != 0 && | |
2068 strcmp(zConflict, "fail" ) != 0 && | |
2069 strcmp(zConflict, "ignore" ) != 0 && | |
2070 strcmp(zConflict, "replace" ) != 0 ) { | |
2071 Tcl_AppendResult(interp, "Error: \"", zConflict, | |
2072 "\", conflict-algorithm must be one of: rollback, " | |
2073 "abort, fail, ignore, or replace", (char*)0); | |
2074 return TCL_ERROR; | |
2075 } | |
2076 zSql = sqlite3_mprintf("SELECT * FROM '%q'", zTable); | |
2077 if( zSql==0 ){ | |
2078 Tcl_AppendResult(interp, "Error: no such table: ", zTable, (char*)0); | |
2079 return TCL_ERROR; | |
2080 } | |
2081 nByte = strlen30(zSql); | |
2082 rc = sqlite3_prepare(pDb->db, zSql, -1, &pStmt, 0); | |
2083 sqlite3_free(zSql); | |
2084 if( rc ){ | |
2085 Tcl_AppendResult(interp, "Error: ", sqlite3_errmsg(pDb->db), (char*)0); | |
2086 nCol = 0; | |
2087 }else{ | |
2088 nCol = sqlite3_column_count(pStmt); | |
2089 } | |
2090 sqlite3_finalize(pStmt); | |
2091 if( nCol==0 ) { | |
2092 return TCL_ERROR; | |
2093 } | |
2094 zSql = malloc( nByte + 50 + nCol*2 ); | |
2095 if( zSql==0 ) { | |
2096 Tcl_AppendResult(interp, "Error: can't malloc()", (char*)0); | |
2097 return TCL_ERROR; | |
2098 } | |
2099 sqlite3_snprintf(nByte+50, zSql, "INSERT OR %q INTO '%q' VALUES(?", | |
2100 zConflict, zTable); | |
2101 j = strlen30(zSql); | |
2102 for(i=1; i<nCol; i++){ | |
2103 zSql[j++] = ','; | |
2104 zSql[j++] = '?'; | |
2105 } | |
2106 zSql[j++] = ')'; | |
2107 zSql[j] = 0; | |
2108 rc = sqlite3_prepare(pDb->db, zSql, -1, &pStmt, 0); | |
2109 free(zSql); | |
2110 if( rc ){ | |
2111 Tcl_AppendResult(interp, "Error: ", sqlite3_errmsg(pDb->db), (char*)0); | |
2112 sqlite3_finalize(pStmt); | |
2113 return TCL_ERROR; | |
2114 } | |
2115 in = fopen(zFile, "rb"); | |
2116 if( in==0 ){ | |
2117 Tcl_AppendResult(interp, "Error: cannot open file: ", zFile, NULL); | |
2118 sqlite3_finalize(pStmt); | |
2119 return TCL_ERROR; | |
2120 } | |
2121 azCol = malloc( sizeof(azCol[0])*(nCol+1) ); | |
2122 if( azCol==0 ) { | |
2123 Tcl_AppendResult(interp, "Error: can't malloc()", (char*)0); | |
2124 fclose(in); | |
2125 return TCL_ERROR; | |
2126 } | |
2127 (void)sqlite3_exec(pDb->db, "BEGIN", 0, 0, 0); | |
2128 zCommit = "COMMIT"; | |
2129 while( (zLine = local_getline(0, in))!=0 ){ | |
2130 char *z; | |
2131 lineno++; | |
2132 azCol[0] = zLine; | |
2133 for(i=0, z=zLine; *z; z++){ | |
2134 if( *z==zSep[0] && strncmp(z, zSep, nSep)==0 ){ | |
2135 *z = 0; | |
2136 i++; | |
2137 if( i<nCol ){ | |
2138 azCol[i] = &z[nSep]; | |
2139 z += nSep-1; | |
2140 } | |
2141 } | |
2142 } | |
2143 if( i+1!=nCol ){ | |
2144 char *zErr; | |
2145 int nErr = strlen30(zFile) + 200; | |
2146 zErr = malloc(nErr); | |
2147 if( zErr ){ | |
2148 sqlite3_snprintf(nErr, zErr, | |
2149 "Error: %s line %d: expected %d columns of data but found %d", | |
2150 zFile, lineno, nCol, i+1); | |
2151 Tcl_AppendResult(interp, zErr, (char*)0); | |
2152 free(zErr); | |
2153 } | |
2154 zCommit = "ROLLBACK"; | |
2155 break; | |
2156 } | |
2157 for(i=0; i<nCol; i++){ | |
2158 /* check for null data, if so, bind as null */ | |
2159 if( (nNull>0 && strcmp(azCol[i], zNull)==0) | |
2160 || strlen30(azCol[i])==0 | |
2161 ){ | |
2162 sqlite3_bind_null(pStmt, i+1); | |
2163 }else{ | |
2164 sqlite3_bind_text(pStmt, i+1, azCol[i], -1, SQLITE_STATIC); | |
2165 } | |
2166 } | |
2167 sqlite3_step(pStmt); | |
2168 rc = sqlite3_reset(pStmt); | |
2169 free(zLine); | |
2170 if( rc!=SQLITE_OK ){ | |
2171 Tcl_AppendResult(interp,"Error: ", sqlite3_errmsg(pDb->db), (char*)0); | |
2172 zCommit = "ROLLBACK"; | |
2173 break; | |
2174 } | |
2175 } | |
2176 free(azCol); | |
2177 fclose(in); | |
2178 sqlite3_finalize(pStmt); | |
2179 (void)sqlite3_exec(pDb->db, zCommit, 0, 0, 0); | |
2180 | |
2181 if( zCommit[0] == 'C' ){ | |
2182 /* success, set result as number of lines processed */ | |
2183 pResult = Tcl_GetObjResult(interp); | |
2184 Tcl_SetIntObj(pResult, lineno); | |
2185 rc = TCL_OK; | |
2186 }else{ | |
2187 /* failure, append lineno where failed */ | |
2188 sqlite3_snprintf(sizeof(zLineNum), zLineNum,"%d",lineno); | |
2189 Tcl_AppendResult(interp,", failed while processing line: ",zLineNum, | |
2190 (char*)0); | |
2191 rc = TCL_ERROR; | |
2192 } | |
2193 break; | |
2194 } | |
2195 | |
2196 /* | |
2197 ** $db enable_load_extension BOOLEAN | |
2198 ** | |
2199 ** Turn the extension loading feature on or off. It if off by | |
2200 ** default. | |
2201 */ | |
2202 case DB_ENABLE_LOAD_EXTENSION: { | |
2203 #ifndef SQLITE_OMIT_LOAD_EXTENSION | |
2204 int onoff; | |
2205 if( objc!=3 ){ | |
2206 Tcl_WrongNumArgs(interp, 2, objv, "BOOLEAN"); | |
2207 return TCL_ERROR; | |
2208 } | |
2209 if( Tcl_GetBooleanFromObj(interp, objv[2], &onoff) ){ | |
2210 return TCL_ERROR; | |
2211 } | |
2212 sqlite3_enable_load_extension(pDb->db, onoff); | |
2213 break; | |
2214 #else | |
2215 Tcl_AppendResult(interp, "extension loading is turned off at compile-time", | |
2216 (char*)0); | |
2217 return TCL_ERROR; | |
2218 #endif | |
2219 } | |
2220 | |
2221 /* | |
2222 ** $db errorcode | |
2223 ** | |
2224 ** Return the numeric error code that was returned by the most recent | |
2225 ** call to sqlite3_exec(). | |
2226 */ | |
2227 case DB_ERRORCODE: { | |
2228 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_errcode(pDb->db))); | |
2229 break; | |
2230 } | |
2231 | |
2232 /* | |
2233 ** $db exists $sql | |
2234 ** $db onecolumn $sql | |
2235 ** | |
2236 ** The onecolumn method is the equivalent of: | |
2237 ** lindex [$db eval $sql] 0 | |
2238 */ | |
2239 case DB_EXISTS: | |
2240 case DB_ONECOLUMN: { | |
2241 DbEvalContext sEval; | |
2242 if( objc!=3 ){ | |
2243 Tcl_WrongNumArgs(interp, 2, objv, "SQL"); | |
2244 return TCL_ERROR; | |
2245 } | |
2246 | |
2247 dbEvalInit(&sEval, pDb, objv[2], 0); | |
2248 rc = dbEvalStep(&sEval); | |
2249 if( choice==DB_ONECOLUMN ){ | |
2250 if( rc==TCL_OK ){ | |
2251 Tcl_SetObjResult(interp, dbEvalColumnValue(&sEval, 0)); | |
2252 }else if( rc==TCL_BREAK ){ | |
2253 Tcl_ResetResult(interp); | |
2254 } | |
2255 }else if( rc==TCL_BREAK || rc==TCL_OK ){ | |
2256 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(rc==TCL_OK)); | |
2257 } | |
2258 dbEvalFinalize(&sEval); | |
2259 | |
2260 if( rc==TCL_BREAK ){ | |
2261 rc = TCL_OK; | |
2262 } | |
2263 break; | |
2264 } | |
2265 | |
2266 /* | |
2267 ** $db eval $sql ?array? ?{ ...code... }? | |
2268 ** | |
2269 ** The SQL statement in $sql is evaluated. For each row, the values are | |
2270 ** placed in elements of the array named "array" and ...code... is executed. | |
2271 ** If "array" and "code" are omitted, then no callback is every invoked. | |
2272 ** If "array" is an empty string, then the values are placed in variables | |
2273 ** that have the same name as the fields extracted by the query. | |
2274 */ | |
2275 case DB_EVAL: { | |
2276 if( objc<3 || objc>5 ){ | |
2277 Tcl_WrongNumArgs(interp, 2, objv, "SQL ?ARRAY-NAME? ?SCRIPT?"); | |
2278 return TCL_ERROR; | |
2279 } | |
2280 | |
2281 if( objc==3 ){ | |
2282 DbEvalContext sEval; | |
2283 Tcl_Obj *pRet = Tcl_NewObj(); | |
2284 Tcl_IncrRefCount(pRet); | |
2285 dbEvalInit(&sEval, pDb, objv[2], 0); | |
2286 while( TCL_OK==(rc = dbEvalStep(&sEval)) ){ | |
2287 int i; | |
2288 int nCol; | |
2289 dbEvalRowInfo(&sEval, &nCol, 0); | |
2290 for(i=0; i<nCol; i++){ | |
2291 Tcl_ListObjAppendElement(interp, pRet, dbEvalColumnValue(&sEval, i)); | |
2292 } | |
2293 } | |
2294 dbEvalFinalize(&sEval); | |
2295 if( rc==TCL_BREAK ){ | |
2296 Tcl_SetObjResult(interp, pRet); | |
2297 rc = TCL_OK; | |
2298 } | |
2299 Tcl_DecrRefCount(pRet); | |
2300 }else{ | |
2301 ClientData cd2[2]; | |
2302 DbEvalContext *p; | |
2303 Tcl_Obj *pArray = 0; | |
2304 Tcl_Obj *pScript; | |
2305 | |
2306 if( objc==5 && *(char *)Tcl_GetString(objv[3]) ){ | |
2307 pArray = objv[3]; | |
2308 } | |
2309 pScript = objv[objc-1]; | |
2310 Tcl_IncrRefCount(pScript); | |
2311 | |
2312 p = (DbEvalContext *)Tcl_Alloc(sizeof(DbEvalContext)); | |
2313 dbEvalInit(p, pDb, objv[2], pArray); | |
2314 | |
2315 cd2[0] = (void *)p; | |
2316 cd2[1] = (void *)pScript; | |
2317 rc = DbEvalNextCmd(cd2, interp, TCL_OK); | |
2318 } | |
2319 break; | |
2320 } | |
2321 | |
2322 /* | |
2323 ** $db function NAME [-argcount N] [-deterministic] SCRIPT | |
2324 ** | |
2325 ** Create a new SQL function called NAME. Whenever that function is | |
2326 ** called, invoke SCRIPT to evaluate the function. | |
2327 */ | |
2328 case DB_FUNCTION: { | |
2329 int flags = SQLITE_UTF8; | |
2330 SqlFunc *pFunc; | |
2331 Tcl_Obj *pScript; | |
2332 char *zName; | |
2333 int nArg = -1; | |
2334 int i; | |
2335 if( objc<4 ){ | |
2336 Tcl_WrongNumArgs(interp, 2, objv, "NAME ?SWITCHES? SCRIPT"); | |
2337 return TCL_ERROR; | |
2338 } | |
2339 for(i=3; i<(objc-1); i++){ | |
2340 const char *z = Tcl_GetString(objv[i]); | |
2341 int n = strlen30(z); | |
2342 if( n>2 && strncmp(z, "-argcount",n)==0 ){ | |
2343 if( i==(objc-2) ){ | |
2344 Tcl_AppendResult(interp, "option requires an argument: ", z, 0); | |
2345 return TCL_ERROR; | |
2346 } | |
2347 if( Tcl_GetIntFromObj(interp, objv[i+1], &nArg) ) return TCL_ERROR; | |
2348 if( nArg<0 ){ | |
2349 Tcl_AppendResult(interp, "number of arguments must be non-negative", | |
2350 (char*)0); | |
2351 return TCL_ERROR; | |
2352 } | |
2353 i++; | |
2354 }else | |
2355 if( n>2 && strncmp(z, "-deterministic",n)==0 ){ | |
2356 flags |= SQLITE_DETERMINISTIC; | |
2357 }else{ | |
2358 Tcl_AppendResult(interp, "bad option \"", z, | |
2359 "\": must be -argcount or -deterministic", 0 | |
2360 ); | |
2361 return TCL_ERROR; | |
2362 } | |
2363 } | |
2364 | |
2365 pScript = objv[objc-1]; | |
2366 zName = Tcl_GetStringFromObj(objv[2], 0); | |
2367 pFunc = findSqlFunc(pDb, zName); | |
2368 if( pFunc==0 ) return TCL_ERROR; | |
2369 if( pFunc->pScript ){ | |
2370 Tcl_DecrRefCount(pFunc->pScript); | |
2371 } | |
2372 pFunc->pScript = pScript; | |
2373 Tcl_IncrRefCount(pScript); | |
2374 pFunc->useEvalObjv = safeToUseEvalObjv(interp, pScript); | |
2375 rc = sqlite3_create_function(pDb->db, zName, nArg, flags, | |
2376 pFunc, tclSqlFunc, 0, 0); | |
2377 if( rc!=SQLITE_OK ){ | |
2378 rc = TCL_ERROR; | |
2379 Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE); | |
2380 } | |
2381 break; | |
2382 } | |
2383 | |
2384 /* | |
2385 ** $db incrblob ?-readonly? ?DB? TABLE COLUMN ROWID | |
2386 */ | |
2387 case DB_INCRBLOB: { | |
2388 #ifdef SQLITE_OMIT_INCRBLOB | |
2389 Tcl_AppendResult(interp, "incrblob not available in this build", (char*)0); | |
2390 return TCL_ERROR; | |
2391 #else | |
2392 int isReadonly = 0; | |
2393 const char *zDb = "main"; | |
2394 const char *zTable; | |
2395 const char *zColumn; | |
2396 Tcl_WideInt iRow; | |
2397 | |
2398 /* Check for the -readonly option */ | |
2399 if( objc>3 && strcmp(Tcl_GetString(objv[2]), "-readonly")==0 ){ | |
2400 isReadonly = 1; | |
2401 } | |
2402 | |
2403 if( objc!=(5+isReadonly) && objc!=(6+isReadonly) ){ | |
2404 Tcl_WrongNumArgs(interp, 2, objv, "?-readonly? ?DB? TABLE COLUMN ROWID"); | |
2405 return TCL_ERROR; | |
2406 } | |
2407 | |
2408 if( objc==(6+isReadonly) ){ | |
2409 zDb = Tcl_GetString(objv[2]); | |
2410 } | |
2411 zTable = Tcl_GetString(objv[objc-3]); | |
2412 zColumn = Tcl_GetString(objv[objc-2]); | |
2413 rc = Tcl_GetWideIntFromObj(interp, objv[objc-1], &iRow); | |
2414 | |
2415 if( rc==TCL_OK ){ | |
2416 rc = createIncrblobChannel( | |
2417 interp, pDb, zDb, zTable, zColumn, (sqlite3_int64)iRow, isReadonly | |
2418 ); | |
2419 } | |
2420 #endif | |
2421 break; | |
2422 } | |
2423 | |
2424 /* | |
2425 ** $db interrupt | |
2426 ** | |
2427 ** Interrupt the execution of the inner-most SQL interpreter. This | |
2428 ** causes the SQL statement to return an error of SQLITE_INTERRUPT. | |
2429 */ | |
2430 case DB_INTERRUPT: { | |
2431 sqlite3_interrupt(pDb->db); | |
2432 break; | |
2433 } | |
2434 | |
2435 /* | |
2436 ** $db nullvalue ?STRING? | |
2437 ** | |
2438 ** Change text used when a NULL comes back from the database. If ?STRING? | |
2439 ** is not present, then the current string used for NULL is returned. | |
2440 ** If STRING is present, then STRING is returned. | |
2441 ** | |
2442 */ | |
2443 case DB_NULLVALUE: { | |
2444 if( objc!=2 && objc!=3 ){ | |
2445 Tcl_WrongNumArgs(interp, 2, objv, "NULLVALUE"); | |
2446 return TCL_ERROR; | |
2447 } | |
2448 if( objc==3 ){ | |
2449 int len; | |
2450 char *zNull = Tcl_GetStringFromObj(objv[2], &len); | |
2451 if( pDb->zNull ){ | |
2452 Tcl_Free(pDb->zNull); | |
2453 } | |
2454 if( zNull && len>0 ){ | |
2455 pDb->zNull = Tcl_Alloc( len + 1 ); | |
2456 memcpy(pDb->zNull, zNull, len); | |
2457 pDb->zNull[len] = '\0'; | |
2458 }else{ | |
2459 pDb->zNull = 0; | |
2460 } | |
2461 } | |
2462 Tcl_SetObjResult(interp, Tcl_NewStringObj(pDb->zNull, -1)); | |
2463 break; | |
2464 } | |
2465 | |
2466 /* | |
2467 ** $db last_insert_rowid | |
2468 ** | |
2469 ** Return an integer which is the ROWID for the most recent insert. | |
2470 */ | |
2471 case DB_LAST_INSERT_ROWID: { | |
2472 Tcl_Obj *pResult; | |
2473 Tcl_WideInt rowid; | |
2474 if( objc!=2 ){ | |
2475 Tcl_WrongNumArgs(interp, 2, objv, ""); | |
2476 return TCL_ERROR; | |
2477 } | |
2478 rowid = sqlite3_last_insert_rowid(pDb->db); | |
2479 pResult = Tcl_GetObjResult(interp); | |
2480 Tcl_SetWideIntObj(pResult, rowid); | |
2481 break; | |
2482 } | |
2483 | |
2484 /* | |
2485 ** The DB_ONECOLUMN method is implemented together with DB_EXISTS. | |
2486 */ | |
2487 | |
2488 /* $db progress ?N CALLBACK? | |
2489 ** | |
2490 ** Invoke the given callback every N virtual machine opcodes while executing | |
2491 ** queries. | |
2492 */ | |
2493 case DB_PROGRESS: { | |
2494 if( objc==2 ){ | |
2495 if( pDb->zProgress ){ | |
2496 Tcl_AppendResult(interp, pDb->zProgress, (char*)0); | |
2497 } | |
2498 }else if( objc==4 ){ | |
2499 char *zProgress; | |
2500 int len; | |
2501 int N; | |
2502 if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &N) ){ | |
2503 return TCL_ERROR; | |
2504 }; | |
2505 if( pDb->zProgress ){ | |
2506 Tcl_Free(pDb->zProgress); | |
2507 } | |
2508 zProgress = Tcl_GetStringFromObj(objv[3], &len); | |
2509 if( zProgress && len>0 ){ | |
2510 pDb->zProgress = Tcl_Alloc( len + 1 ); | |
2511 memcpy(pDb->zProgress, zProgress, len+1); | |
2512 }else{ | |
2513 pDb->zProgress = 0; | |
2514 } | |
2515 #ifndef SQLITE_OMIT_PROGRESS_CALLBACK | |
2516 if( pDb->zProgress ){ | |
2517 pDb->interp = interp; | |
2518 sqlite3_progress_handler(pDb->db, N, DbProgressHandler, pDb); | |
2519 }else{ | |
2520 sqlite3_progress_handler(pDb->db, 0, 0, 0); | |
2521 } | |
2522 #endif | |
2523 }else{ | |
2524 Tcl_WrongNumArgs(interp, 2, objv, "N CALLBACK"); | |
2525 return TCL_ERROR; | |
2526 } | |
2527 break; | |
2528 } | |
2529 | |
2530 /* $db profile ?CALLBACK? | |
2531 ** | |
2532 ** Make arrangements to invoke the CALLBACK routine after each SQL statement | |
2533 ** that has run. The text of the SQL and the amount of elapse time are | |
2534 ** appended to CALLBACK before the script is run. | |
2535 */ | |
2536 case DB_PROFILE: { | |
2537 if( objc>3 ){ | |
2538 Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?"); | |
2539 return TCL_ERROR; | |
2540 }else if( objc==2 ){ | |
2541 if( pDb->zProfile ){ | |
2542 Tcl_AppendResult(interp, pDb->zProfile, (char*)0); | |
2543 } | |
2544 }else{ | |
2545 char *zProfile; | |
2546 int len; | |
2547 if( pDb->zProfile ){ | |
2548 Tcl_Free(pDb->zProfile); | |
2549 } | |
2550 zProfile = Tcl_GetStringFromObj(objv[2], &len); | |
2551 if( zProfile && len>0 ){ | |
2552 pDb->zProfile = Tcl_Alloc( len + 1 ); | |
2553 memcpy(pDb->zProfile, zProfile, len+1); | |
2554 }else{ | |
2555 pDb->zProfile = 0; | |
2556 } | |
2557 #if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) | |
2558 if( pDb->zProfile ){ | |
2559 pDb->interp = interp; | |
2560 sqlite3_profile(pDb->db, DbProfileHandler, pDb); | |
2561 }else{ | |
2562 sqlite3_profile(pDb->db, 0, 0); | |
2563 } | |
2564 #endif | |
2565 } | |
2566 break; | |
2567 } | |
2568 | |
2569 /* | |
2570 ** $db rekey KEY | |
2571 ** | |
2572 ** Change the encryption key on the currently open database. | |
2573 */ | |
2574 case DB_REKEY: { | |
2575 #ifdef SQLITE_HAS_CODEC | |
2576 int nKey; | |
2577 void *pKey; | |
2578 #endif | |
2579 if( objc!=3 ){ | |
2580 Tcl_WrongNumArgs(interp, 2, objv, "KEY"); | |
2581 return TCL_ERROR; | |
2582 } | |
2583 #ifdef SQLITE_HAS_CODEC | |
2584 pKey = Tcl_GetByteArrayFromObj(objv[2], &nKey); | |
2585 rc = sqlite3_rekey(pDb->db, pKey, nKey); | |
2586 if( rc ){ | |
2587 Tcl_AppendResult(interp, sqlite3_errstr(rc), (char*)0); | |
2588 rc = TCL_ERROR; | |
2589 } | |
2590 #endif | |
2591 break; | |
2592 } | |
2593 | |
2594 /* $db restore ?DATABASE? FILENAME | |
2595 ** | |
2596 ** Open a database file named FILENAME. Transfer the content | |
2597 ** of FILENAME into the local database DATABASE (default: "main"). | |
2598 */ | |
2599 case DB_RESTORE: { | |
2600 const char *zSrcFile; | |
2601 const char *zDestDb; | |
2602 sqlite3 *pSrc; | |
2603 sqlite3_backup *pBackup; | |
2604 int nTimeout = 0; | |
2605 | |
2606 if( objc==3 ){ | |
2607 zDestDb = "main"; | |
2608 zSrcFile = Tcl_GetString(objv[2]); | |
2609 }else if( objc==4 ){ | |
2610 zDestDb = Tcl_GetString(objv[2]); | |
2611 zSrcFile = Tcl_GetString(objv[3]); | |
2612 }else{ | |
2613 Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE? FILENAME"); | |
2614 return TCL_ERROR; | |
2615 } | |
2616 rc = sqlite3_open_v2(zSrcFile, &pSrc, SQLITE_OPEN_READONLY, 0); | |
2617 if( rc!=SQLITE_OK ){ | |
2618 Tcl_AppendResult(interp, "cannot open source database: ", | |
2619 sqlite3_errmsg(pSrc), (char*)0); | |
2620 sqlite3_close(pSrc); | |
2621 return TCL_ERROR; | |
2622 } | |
2623 pBackup = sqlite3_backup_init(pDb->db, zDestDb, pSrc, "main"); | |
2624 if( pBackup==0 ){ | |
2625 Tcl_AppendResult(interp, "restore failed: ", | |
2626 sqlite3_errmsg(pDb->db), (char*)0); | |
2627 sqlite3_close(pSrc); | |
2628 return TCL_ERROR; | |
2629 } | |
2630 while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK | |
2631 || rc==SQLITE_BUSY ){ | |
2632 if( rc==SQLITE_BUSY ){ | |
2633 if( nTimeout++ >= 3 ) break; | |
2634 sqlite3_sleep(100); | |
2635 } | |
2636 } | |
2637 sqlite3_backup_finish(pBackup); | |
2638 if( rc==SQLITE_DONE ){ | |
2639 rc = TCL_OK; | |
2640 }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){ | |
2641 Tcl_AppendResult(interp, "restore failed: source database busy", | |
2642 (char*)0); | |
2643 rc = TCL_ERROR; | |
2644 }else{ | |
2645 Tcl_AppendResult(interp, "restore failed: ", | |
2646 sqlite3_errmsg(pDb->db), (char*)0); | |
2647 rc = TCL_ERROR; | |
2648 } | |
2649 sqlite3_close(pSrc); | |
2650 break; | |
2651 } | |
2652 | |
2653 /* | |
2654 ** $db status (step|sort|autoindex) | |
2655 ** | |
2656 ** Display SQLITE_STMTSTATUS_FULLSCAN_STEP or | |
2657 ** SQLITE_STMTSTATUS_SORT for the most recent eval. | |
2658 */ | |
2659 case DB_STATUS: { | |
2660 int v; | |
2661 const char *zOp; | |
2662 if( objc!=3 ){ | |
2663 Tcl_WrongNumArgs(interp, 2, objv, "(step|sort|autoindex)"); | |
2664 return TCL_ERROR; | |
2665 } | |
2666 zOp = Tcl_GetString(objv[2]); | |
2667 if( strcmp(zOp, "step")==0 ){ | |
2668 v = pDb->nStep; | |
2669 }else if( strcmp(zOp, "sort")==0 ){ | |
2670 v = pDb->nSort; | |
2671 }else if( strcmp(zOp, "autoindex")==0 ){ | |
2672 v = pDb->nIndex; | |
2673 }else{ | |
2674 Tcl_AppendResult(interp, | |
2675 "bad argument: should be autoindex, step, or sort", | |
2676 (char*)0); | |
2677 return TCL_ERROR; | |
2678 } | |
2679 Tcl_SetObjResult(interp, Tcl_NewIntObj(v)); | |
2680 break; | |
2681 } | |
2682 | |
2683 /* | |
2684 ** $db timeout MILLESECONDS | |
2685 ** | |
2686 ** Delay for the number of milliseconds specified when a file is locked. | |
2687 */ | |
2688 case DB_TIMEOUT: { | |
2689 int ms; | |
2690 if( objc!=3 ){ | |
2691 Tcl_WrongNumArgs(interp, 2, objv, "MILLISECONDS"); | |
2692 return TCL_ERROR; | |
2693 } | |
2694 if( Tcl_GetIntFromObj(interp, objv[2], &ms) ) return TCL_ERROR; | |
2695 sqlite3_busy_timeout(pDb->db, ms); | |
2696 break; | |
2697 } | |
2698 | |
2699 /* | |
2700 ** $db total_changes | |
2701 ** | |
2702 ** Return the number of rows that were modified, inserted, or deleted | |
2703 ** since the database handle was created. | |
2704 */ | |
2705 case DB_TOTAL_CHANGES: { | |
2706 Tcl_Obj *pResult; | |
2707 if( objc!=2 ){ | |
2708 Tcl_WrongNumArgs(interp, 2, objv, ""); | |
2709 return TCL_ERROR; | |
2710 } | |
2711 pResult = Tcl_GetObjResult(interp); | |
2712 Tcl_SetIntObj(pResult, sqlite3_total_changes(pDb->db)); | |
2713 break; | |
2714 } | |
2715 | |
2716 /* $db trace ?CALLBACK? | |
2717 ** | |
2718 ** Make arrangements to invoke the CALLBACK routine for each SQL statement | |
2719 ** that is executed. The text of the SQL is appended to CALLBACK before | |
2720 ** it is executed. | |
2721 */ | |
2722 case DB_TRACE: { | |
2723 if( objc>3 ){ | |
2724 Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?"); | |
2725 return TCL_ERROR; | |
2726 }else if( objc==2 ){ | |
2727 if( pDb->zTrace ){ | |
2728 Tcl_AppendResult(interp, pDb->zTrace, (char*)0); | |
2729 } | |
2730 }else{ | |
2731 char *zTrace; | |
2732 int len; | |
2733 if( pDb->zTrace ){ | |
2734 Tcl_Free(pDb->zTrace); | |
2735 } | |
2736 zTrace = Tcl_GetStringFromObj(objv[2], &len); | |
2737 if( zTrace && len>0 ){ | |
2738 pDb->zTrace = Tcl_Alloc( len + 1 ); | |
2739 memcpy(pDb->zTrace, zTrace, len+1); | |
2740 }else{ | |
2741 pDb->zTrace = 0; | |
2742 } | |
2743 #if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) | |
2744 if( pDb->zTrace ){ | |
2745 pDb->interp = interp; | |
2746 sqlite3_trace(pDb->db, DbTraceHandler, pDb); | |
2747 }else{ | |
2748 sqlite3_trace(pDb->db, 0, 0); | |
2749 } | |
2750 #endif | |
2751 } | |
2752 break; | |
2753 } | |
2754 | |
2755 /* $db transaction [-deferred|-immediate|-exclusive] SCRIPT | |
2756 ** | |
2757 ** Start a new transaction (if we are not already in the midst of a | |
2758 ** transaction) and execute the TCL script SCRIPT. After SCRIPT | |
2759 ** completes, either commit the transaction or roll it back if SCRIPT | |
2760 ** throws an exception. Or if no new transation was started, do nothing. | |
2761 ** pass the exception on up the stack. | |
2762 ** | |
2763 ** This command was inspired by Dave Thomas's talk on Ruby at the | |
2764 ** 2005 O'Reilly Open Source Convention (OSCON). | |
2765 */ | |
2766 case DB_TRANSACTION: { | |
2767 Tcl_Obj *pScript; | |
2768 const char *zBegin = "SAVEPOINT _tcl_transaction"; | |
2769 if( objc!=3 && objc!=4 ){ | |
2770 Tcl_WrongNumArgs(interp, 2, objv, "[TYPE] SCRIPT"); | |
2771 return TCL_ERROR; | |
2772 } | |
2773 | |
2774 if( pDb->nTransaction==0 && objc==4 ){ | |
2775 static const char *TTYPE_strs[] = { | |
2776 "deferred", "exclusive", "immediate", 0 | |
2777 }; | |
2778 enum TTYPE_enum { | |
2779 TTYPE_DEFERRED, TTYPE_EXCLUSIVE, TTYPE_IMMEDIATE | |
2780 }; | |
2781 int ttype; | |
2782 if( Tcl_GetIndexFromObj(interp, objv[2], TTYPE_strs, "transaction type", | |
2783 0, &ttype) ){ | |
2784 return TCL_ERROR; | |
2785 } | |
2786 switch( (enum TTYPE_enum)ttype ){ | |
2787 case TTYPE_DEFERRED: /* no-op */; break; | |
2788 case TTYPE_EXCLUSIVE: zBegin = "BEGIN EXCLUSIVE"; break; | |
2789 case TTYPE_IMMEDIATE: zBegin = "BEGIN IMMEDIATE"; break; | |
2790 } | |
2791 } | |
2792 pScript = objv[objc-1]; | |
2793 | |
2794 /* Run the SQLite BEGIN command to open a transaction or savepoint. */ | |
2795 pDb->disableAuth++; | |
2796 rc = sqlite3_exec(pDb->db, zBegin, 0, 0, 0); | |
2797 pDb->disableAuth--; | |
2798 if( rc!=SQLITE_OK ){ | |
2799 Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), (char*)0); | |
2800 return TCL_ERROR; | |
2801 } | |
2802 pDb->nTransaction++; | |
2803 | |
2804 /* If using NRE, schedule a callback to invoke the script pScript, then | |
2805 ** a second callback to commit (or rollback) the transaction or savepoint | |
2806 ** opened above. If not using NRE, evaluate the script directly, then | |
2807 ** call function DbTransPostCmd() to commit (or rollback) the transaction | |
2808 ** or savepoint. */ | |
2809 if( DbUseNre() ){ | |
2810 Tcl_NRAddCallback(interp, DbTransPostCmd, cd, 0, 0, 0); | |
2811 (void)Tcl_NREvalObj(interp, pScript, 0); | |
2812 }else{ | |
2813 rc = DbTransPostCmd(&cd, interp, Tcl_EvalObjEx(interp, pScript, 0)); | |
2814 } | |
2815 break; | |
2816 } | |
2817 | |
2818 /* | |
2819 ** $db unlock_notify ?script? | |
2820 */ | |
2821 case DB_UNLOCK_NOTIFY: { | |
2822 #ifndef SQLITE_ENABLE_UNLOCK_NOTIFY | |
2823 Tcl_AppendResult(interp, "unlock_notify not available in this build", | |
2824 (char*)0); | |
2825 rc = TCL_ERROR; | |
2826 #else | |
2827 if( objc!=2 && objc!=3 ){ | |
2828 Tcl_WrongNumArgs(interp, 2, objv, "?SCRIPT?"); | |
2829 rc = TCL_ERROR; | |
2830 }else{ | |
2831 void (*xNotify)(void **, int) = 0; | |
2832 void *pNotifyArg = 0; | |
2833 | |
2834 if( pDb->pUnlockNotify ){ | |
2835 Tcl_DecrRefCount(pDb->pUnlockNotify); | |
2836 pDb->pUnlockNotify = 0; | |
2837 } | |
2838 | |
2839 if( objc==3 ){ | |
2840 xNotify = DbUnlockNotify; | |
2841 pNotifyArg = (void *)pDb; | |
2842 pDb->pUnlockNotify = objv[2]; | |
2843 Tcl_IncrRefCount(pDb->pUnlockNotify); | |
2844 } | |
2845 | |
2846 if( sqlite3_unlock_notify(pDb->db, xNotify, pNotifyArg) ){ | |
2847 Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), (char*)0); | |
2848 rc = TCL_ERROR; | |
2849 } | |
2850 } | |
2851 #endif | |
2852 break; | |
2853 } | |
2854 | |
2855 /* | |
2856 ** $db wal_hook ?script? | |
2857 ** $db update_hook ?script? | |
2858 ** $db rollback_hook ?script? | |
2859 */ | |
2860 case DB_WAL_HOOK: | |
2861 case DB_UPDATE_HOOK: | |
2862 case DB_ROLLBACK_HOOK: { | |
2863 | |
2864 /* set ppHook to point at pUpdateHook or pRollbackHook, depending on | |
2865 ** whether [$db update_hook] or [$db rollback_hook] was invoked. | |
2866 */ | |
2867 Tcl_Obj **ppHook; | |
2868 if( choice==DB_UPDATE_HOOK ){ | |
2869 ppHook = &pDb->pUpdateHook; | |
2870 }else if( choice==DB_WAL_HOOK ){ | |
2871 ppHook = &pDb->pWalHook; | |
2872 }else{ | |
2873 ppHook = &pDb->pRollbackHook; | |
2874 } | |
2875 | |
2876 if( objc!=2 && objc!=3 ){ | |
2877 Tcl_WrongNumArgs(interp, 2, objv, "?SCRIPT?"); | |
2878 return TCL_ERROR; | |
2879 } | |
2880 if( *ppHook ){ | |
2881 Tcl_SetObjResult(interp, *ppHook); | |
2882 if( objc==3 ){ | |
2883 Tcl_DecrRefCount(*ppHook); | |
2884 *ppHook = 0; | |
2885 } | |
2886 } | |
2887 if( objc==3 ){ | |
2888 assert( !(*ppHook) ); | |
2889 if( Tcl_GetCharLength(objv[2])>0 ){ | |
2890 *ppHook = objv[2]; | |
2891 Tcl_IncrRefCount(*ppHook); | |
2892 } | |
2893 } | |
2894 | |
2895 sqlite3_update_hook(pDb->db, (pDb->pUpdateHook?DbUpdateHandler:0), pDb); | |
2896 sqlite3_rollback_hook(pDb->db,(pDb->pRollbackHook?DbRollbackHandler:0),pDb); | |
2897 sqlite3_wal_hook(pDb->db,(pDb->pWalHook?DbWalHandler:0),pDb); | |
2898 | |
2899 break; | |
2900 } | |
2901 | |
2902 /* $db version | |
2903 ** | |
2904 ** Return the version string for this database. | |
2905 */ | |
2906 case DB_VERSION: { | |
2907 Tcl_SetResult(interp, (char *)sqlite3_libversion(), TCL_STATIC); | |
2908 break; | |
2909 } | |
2910 | |
2911 | |
2912 } /* End of the SWITCH statement */ | |
2913 return rc; | |
2914 } | |
2915 | |
2916 #if SQLITE_TCL_NRE | |
2917 /* | |
2918 ** Adaptor that provides an objCmd interface to the NRE-enabled | |
2919 ** interface implementation. | |
2920 */ | |
2921 static int DbObjCmdAdaptor( | |
2922 void *cd, | |
2923 Tcl_Interp *interp, | |
2924 int objc, | |
2925 Tcl_Obj *const*objv | |
2926 ){ | |
2927 return Tcl_NRCallObjProc(interp, DbObjCmd, cd, objc, objv); | |
2928 } | |
2929 #endif /* SQLITE_TCL_NRE */ | |
2930 | |
2931 /* | |
2932 ** sqlite3 DBNAME FILENAME ?-vfs VFSNAME? ?-key KEY? ?-readonly BOOLEAN? | |
2933 ** ?-create BOOLEAN? ?-nomutex BOOLEAN? | |
2934 ** | |
2935 ** This is the main Tcl command. When the "sqlite" Tcl command is | |
2936 ** invoked, this routine runs to process that command. | |
2937 ** | |
2938 ** The first argument, DBNAME, is an arbitrary name for a new | |
2939 ** database connection. This command creates a new command named | |
2940 ** DBNAME that is used to control that connection. The database | |
2941 ** connection is deleted when the DBNAME command is deleted. | |
2942 ** | |
2943 ** The second argument is the name of the database file. | |
2944 ** | |
2945 */ | |
2946 static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ | |
2947 SqliteDb *p; | |
2948 const char *zArg; | |
2949 char *zErrMsg; | |
2950 int i; | |
2951 const char *zFile; | |
2952 const char *zVfs = 0; | |
2953 int flags; | |
2954 Tcl_DString translatedFilename; | |
2955 #ifdef SQLITE_HAS_CODEC | |
2956 void *pKey = 0; | |
2957 int nKey = 0; | |
2958 #endif | |
2959 int rc; | |
2960 | |
2961 /* In normal use, each TCL interpreter runs in a single thread. So | |
2962 ** by default, we can turn of mutexing on SQLite database connections. | |
2963 ** However, for testing purposes it is useful to have mutexes turned | |
2964 ** on. So, by default, mutexes default off. But if compiled with | |
2965 ** SQLITE_TCL_DEFAULT_FULLMUTEX then mutexes default on. | |
2966 */ | |
2967 #ifdef SQLITE_TCL_DEFAULT_FULLMUTEX | |
2968 flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX; | |
2969 #else | |
2970 flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX; | |
2971 #endif | |
2972 | |
2973 if( objc==2 ){ | |
2974 zArg = Tcl_GetStringFromObj(objv[1], 0); | |
2975 if( strcmp(zArg,"-version")==0 ){ | |
2976 Tcl_AppendResult(interp,sqlite3_libversion(), (char*)0); | |
2977 return TCL_OK; | |
2978 } | |
2979 if( strcmp(zArg,"-has-codec")==0 ){ | |
2980 #ifdef SQLITE_HAS_CODEC | |
2981 Tcl_AppendResult(interp,"1",(char*)0); | |
2982 #else | |
2983 Tcl_AppendResult(interp,"0",(char*)0); | |
2984 #endif | |
2985 return TCL_OK; | |
2986 } | |
2987 } | |
2988 for(i=3; i+1<objc; i+=2){ | |
2989 zArg = Tcl_GetString(objv[i]); | |
2990 if( strcmp(zArg,"-key")==0 ){ | |
2991 #ifdef SQLITE_HAS_CODEC | |
2992 pKey = Tcl_GetByteArrayFromObj(objv[i+1], &nKey); | |
2993 #endif | |
2994 }else if( strcmp(zArg, "-vfs")==0 ){ | |
2995 zVfs = Tcl_GetString(objv[i+1]); | |
2996 }else if( strcmp(zArg, "-readonly")==0 ){ | |
2997 int b; | |
2998 if( Tcl_GetBooleanFromObj(interp, objv[i+1], &b) ) return TCL_ERROR; | |
2999 if( b ){ | |
3000 flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE); | |
3001 flags |= SQLITE_OPEN_READONLY; | |
3002 }else{ | |
3003 flags &= ~SQLITE_OPEN_READONLY; | |
3004 flags |= SQLITE_OPEN_READWRITE; | |
3005 } | |
3006 }else if( strcmp(zArg, "-create")==0 ){ | |
3007 int b; | |
3008 if( Tcl_GetBooleanFromObj(interp, objv[i+1], &b) ) return TCL_ERROR; | |
3009 if( b && (flags & SQLITE_OPEN_READONLY)==0 ){ | |
3010 flags |= SQLITE_OPEN_CREATE; | |
3011 }else{ | |
3012 flags &= ~SQLITE_OPEN_CREATE; | |
3013 } | |
3014 }else if( strcmp(zArg, "-nomutex")==0 ){ | |
3015 int b; | |
3016 if( Tcl_GetBooleanFromObj(interp, objv[i+1], &b) ) return TCL_ERROR; | |
3017 if( b ){ | |
3018 flags |= SQLITE_OPEN_NOMUTEX; | |
3019 flags &= ~SQLITE_OPEN_FULLMUTEX; | |
3020 }else{ | |
3021 flags &= ~SQLITE_OPEN_NOMUTEX; | |
3022 } | |
3023 }else if( strcmp(zArg, "-fullmutex")==0 ){ | |
3024 int b; | |
3025 if( Tcl_GetBooleanFromObj(interp, objv[i+1], &b) ) return TCL_ERROR; | |
3026 if( b ){ | |
3027 flags |= SQLITE_OPEN_FULLMUTEX; | |
3028 flags &= ~SQLITE_OPEN_NOMUTEX; | |
3029 }else{ | |
3030 flags &= ~SQLITE_OPEN_FULLMUTEX; | |
3031 } | |
3032 }else if( strcmp(zArg, "-uri")==0 ){ | |
3033 int b; | |
3034 if( Tcl_GetBooleanFromObj(interp, objv[i+1], &b) ) return TCL_ERROR; | |
3035 if( b ){ | |
3036 flags |= SQLITE_OPEN_URI; | |
3037 }else{ | |
3038 flags &= ~SQLITE_OPEN_URI; | |
3039 } | |
3040 }else{ | |
3041 Tcl_AppendResult(interp, "unknown option: ", zArg, (char*)0); | |
3042 return TCL_ERROR; | |
3043 } | |
3044 } | |
3045 if( objc<3 || (objc&1)!=1 ){ | |
3046 Tcl_WrongNumArgs(interp, 1, objv, | |
3047 "HANDLE FILENAME ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN?" | |
3048 " ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?" | |
3049 #ifdef SQLITE_HAS_CODEC | |
3050 " ?-key CODECKEY?" | |
3051 #endif | |
3052 ); | |
3053 return TCL_ERROR; | |
3054 } | |
3055 zErrMsg = 0; | |
3056 p = (SqliteDb*)Tcl_Alloc( sizeof(*p) ); | |
3057 if( p==0 ){ | |
3058 Tcl_SetResult(interp, (char *)"malloc failed", TCL_STATIC); | |
3059 return TCL_ERROR; | |
3060 } | |
3061 memset(p, 0, sizeof(*p)); | |
3062 zFile = Tcl_GetStringFromObj(objv[2], 0); | |
3063 zFile = Tcl_TranslateFileName(interp, zFile, &translatedFilename); | |
3064 rc = sqlite3_open_v2(zFile, &p->db, flags, zVfs); | |
3065 Tcl_DStringFree(&translatedFilename); | |
3066 if( p->db ){ | |
3067 if( SQLITE_OK!=sqlite3_errcode(p->db) ){ | |
3068 zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(p->db)); | |
3069 sqlite3_close(p->db); | |
3070 p->db = 0; | |
3071 } | |
3072 }else{ | |
3073 zErrMsg = sqlite3_mprintf("%s", sqlite3_errstr(rc)); | |
3074 } | |
3075 #ifdef SQLITE_HAS_CODEC | |
3076 if( p->db ){ | |
3077 sqlite3_key(p->db, pKey, nKey); | |
3078 } | |
3079 #endif | |
3080 if( p->db==0 ){ | |
3081 Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE); | |
3082 Tcl_Free((char*)p); | |
3083 sqlite3_free(zErrMsg); | |
3084 return TCL_ERROR; | |
3085 } | |
3086 p->maxStmt = NUM_PREPARED_STMTS; | |
3087 p->interp = interp; | |
3088 zArg = Tcl_GetStringFromObj(objv[1], 0); | |
3089 if( DbUseNre() ){ | |
3090 Tcl_NRCreateCommand(interp, zArg, DbObjCmdAdaptor, DbObjCmd, | |
3091 (char*)p, DbDeleteCmd); | |
3092 }else{ | |
3093 Tcl_CreateObjCommand(interp, zArg, DbObjCmd, (char*)p, DbDeleteCmd); | |
3094 } | |
3095 return TCL_OK; | |
3096 } | |
3097 | |
3098 /* | |
3099 ** Provide a dummy Tcl_InitStubs if we are using this as a static | |
3100 ** library. | |
3101 */ | |
3102 #ifndef USE_TCL_STUBS | |
3103 # undef Tcl_InitStubs | |
3104 # define Tcl_InitStubs(a,b,c) TCL_VERSION | |
3105 #endif | |
3106 | |
3107 /* | |
3108 ** Make sure we have a PACKAGE_VERSION macro defined. This will be | |
3109 ** defined automatically by the TEA makefile. But other makefiles | |
3110 ** do not define it. | |
3111 */ | |
3112 #ifndef PACKAGE_VERSION | |
3113 # define PACKAGE_VERSION SQLITE_VERSION | |
3114 #endif | |
3115 | |
3116 /* | |
3117 ** Initialize this module. | |
3118 ** | |
3119 ** This Tcl module contains only a single new Tcl command named "sqlite". | |
3120 ** (Hence there is no namespace. There is no point in using a namespace | |
3121 ** if the extension only supplies one new name!) The "sqlite" command is | |
3122 ** used to open a new SQLite database. See the DbMain() routine above | |
3123 ** for additional information. | |
3124 ** | |
3125 ** The EXTERN macros are required by TCL in order to work on windows. | |
3126 */ | |
3127 EXTERN int Sqlite3_Init(Tcl_Interp *interp){ | |
3128 int rc = Tcl_InitStubs(interp, "8.4", 0) ? TCL_OK : TCL_ERROR; | |
3129 if( rc==TCL_OK ){ | |
3130 Tcl_CreateObjCommand(interp, "sqlite3", (Tcl_ObjCmdProc*)DbMain, 0, 0); | |
3131 #ifndef SQLITE_3_SUFFIX_ONLY | |
3132 /* The "sqlite" alias is undocumented. It is here only to support | |
3133 ** legacy scripts. All new scripts should use only the "sqlite3" | |
3134 ** command. */ | |
3135 Tcl_CreateObjCommand(interp, "sqlite", (Tcl_ObjCmdProc*)DbMain, 0, 0); | |
3136 #endif | |
3137 rc = Tcl_PkgProvide(interp, "sqlite3", PACKAGE_VERSION); | |
3138 } | |
3139 return rc; | |
3140 } | |
3141 EXTERN int Tclsqlite3_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); } | |
3142 EXTERN int Sqlite3_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; } | |
3143 EXTERN int Tclsqlite3_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; } | |
3144 | |
3145 /* Because it accesses the file-system and uses persistent state, SQLite | |
3146 ** is not considered appropriate for safe interpreters. Hence, we deliberately | |
3147 ** omit the _SafeInit() interfaces. | |
3148 */ | |
3149 | |
3150 #ifndef SQLITE_3_SUFFIX_ONLY | |
3151 int Sqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); } | |
3152 int Tclsqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); } | |
3153 int Sqlite_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; } | |
3154 int Tclsqlite_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; } | |
3155 #endif | |
3156 | |
3157 #ifdef TCLSH | |
3158 /***************************************************************************** | |
3159 ** All of the code that follows is used to build standalone TCL interpreters | |
3160 ** that are statically linked with SQLite. Enable these by compiling | |
3161 ** with -DTCLSH=n where n can be 1 or 2. An n of 1 generates a standard | |
3162 ** tclsh but with SQLite built in. An n of 2 generates the SQLite space | |
3163 ** analysis program. | |
3164 */ | |
3165 | |
3166 #if defined(SQLITE_TEST) || defined(SQLITE_TCLMD5) | |
3167 /* | |
3168 * This code implements the MD5 message-digest algorithm. | |
3169 * The algorithm is due to Ron Rivest. This code was | |
3170 * written by Colin Plumb in 1993, no copyright is claimed. | |
3171 * This code is in the public domain; do with it what you wish. | |
3172 * | |
3173 * Equivalent code is available from RSA Data Security, Inc. | |
3174 * This code has been tested against that, and is equivalent, | |
3175 * except that you don't need to include two pages of legalese | |
3176 * with every copy. | |
3177 * | |
3178 * To compute the message digest of a chunk of bytes, declare an | |
3179 * MD5Context structure, pass it to MD5Init, call MD5Update as | |
3180 * needed on buffers full of bytes, and then call MD5Final, which | |
3181 * will fill a supplied 16-byte array with the digest. | |
3182 */ | |
3183 | |
3184 /* | |
3185 * If compiled on a machine that doesn't have a 32-bit integer, | |
3186 * you just set "uint32" to the appropriate datatype for an | |
3187 * unsigned 32-bit integer. For example: | |
3188 * | |
3189 * cc -Duint32='unsigned long' md5.c | |
3190 * | |
3191 */ | |
3192 #ifndef uint32 | |
3193 # define uint32 unsigned int | |
3194 #endif | |
3195 | |
3196 struct MD5Context { | |
3197 int isInit; | |
3198 uint32 buf[4]; | |
3199 uint32 bits[2]; | |
3200 unsigned char in[64]; | |
3201 }; | |
3202 typedef struct MD5Context MD5Context; | |
3203 | |
3204 /* | |
3205 * Note: this code is harmless on little-endian machines. | |
3206 */ | |
3207 static void byteReverse (unsigned char *buf, unsigned longs){ | |
3208 uint32 t; | |
3209 do { | |
3210 t = (uint32)((unsigned)buf[3]<<8 | buf[2]) << 16 | | |
3211 ((unsigned)buf[1]<<8 | buf[0]); | |
3212 *(uint32 *)buf = t; | |
3213 buf += 4; | |
3214 } while (--longs); | |
3215 } | |
3216 /* The four core functions - F1 is optimized somewhat */ | |
3217 | |
3218 /* #define F1(x, y, z) (x & y | ~x & z) */ | |
3219 #define F1(x, y, z) (z ^ (x & (y ^ z))) | |
3220 #define F2(x, y, z) F1(z, x, y) | |
3221 #define F3(x, y, z) (x ^ y ^ z) | |
3222 #define F4(x, y, z) (y ^ (x | ~z)) | |
3223 | |
3224 /* This is the central step in the MD5 algorithm. */ | |
3225 #define MD5STEP(f, w, x, y, z, data, s) \ | |
3226 ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ) | |
3227 | |
3228 /* | |
3229 * The core of the MD5 algorithm, this alters an existing MD5 hash to | |
3230 * reflect the addition of 16 longwords of new data. MD5Update blocks | |
3231 * the data and converts bytes into longwords for this routine. | |
3232 */ | |
3233 static void MD5Transform(uint32 buf[4], const uint32 in[16]){ | |
3234 register uint32 a, b, c, d; | |
3235 | |
3236 a = buf[0]; | |
3237 b = buf[1]; | |
3238 c = buf[2]; | |
3239 d = buf[3]; | |
3240 | |
3241 MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7); | |
3242 MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12); | |
3243 MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17); | |
3244 MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22); | |
3245 MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7); | |
3246 MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12); | |
3247 MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17); | |
3248 MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22); | |
3249 MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7); | |
3250 MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12); | |
3251 MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17); | |
3252 MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22); | |
3253 MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7); | |
3254 MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12); | |
3255 MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17); | |
3256 MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22); | |
3257 | |
3258 MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5); | |
3259 MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9); | |
3260 MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14); | |
3261 MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20); | |
3262 MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5); | |
3263 MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9); | |
3264 MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14); | |
3265 MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20); | |
3266 MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5); | |
3267 MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9); | |
3268 MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14); | |
3269 MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20); | |
3270 MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5); | |
3271 MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9); | |
3272 MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14); | |
3273 MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20); | |
3274 | |
3275 MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4); | |
3276 MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11); | |
3277 MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16); | |
3278 MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23); | |
3279 MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4); | |
3280 MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11); | |
3281 MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16); | |
3282 MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23); | |
3283 MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4); | |
3284 MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11); | |
3285 MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16); | |
3286 MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23); | |
3287 MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4); | |
3288 MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11); | |
3289 MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16); | |
3290 MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23); | |
3291 | |
3292 MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6); | |
3293 MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10); | |
3294 MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15); | |
3295 MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21); | |
3296 MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6); | |
3297 MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10); | |
3298 MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15); | |
3299 MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21); | |
3300 MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6); | |
3301 MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10); | |
3302 MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15); | |
3303 MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21); | |
3304 MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6); | |
3305 MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10); | |
3306 MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15); | |
3307 MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21); | |
3308 | |
3309 buf[0] += a; | |
3310 buf[1] += b; | |
3311 buf[2] += c; | |
3312 buf[3] += d; | |
3313 } | |
3314 | |
3315 /* | |
3316 * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious | |
3317 * initialization constants. | |
3318 */ | |
3319 static void MD5Init(MD5Context *ctx){ | |
3320 ctx->isInit = 1; | |
3321 ctx->buf[0] = 0x67452301; | |
3322 ctx->buf[1] = 0xefcdab89; | |
3323 ctx->buf[2] = 0x98badcfe; | |
3324 ctx->buf[3] = 0x10325476; | |
3325 ctx->bits[0] = 0; | |
3326 ctx->bits[1] = 0; | |
3327 } | |
3328 | |
3329 /* | |
3330 * Update context to reflect the concatenation of another buffer full | |
3331 * of bytes. | |
3332 */ | |
3333 static | |
3334 void MD5Update(MD5Context *ctx, const unsigned char *buf, unsigned int len){ | |
3335 uint32 t; | |
3336 | |
3337 /* Update bitcount */ | |
3338 | |
3339 t = ctx->bits[0]; | |
3340 if ((ctx->bits[0] = t + ((uint32)len << 3)) < t) | |
3341 ctx->bits[1]++; /* Carry from low to high */ | |
3342 ctx->bits[1] += len >> 29; | |
3343 | |
3344 t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ | |
3345 | |
3346 /* Handle any leading odd-sized chunks */ | |
3347 | |
3348 if ( t ) { | |
3349 unsigned char *p = (unsigned char *)ctx->in + t; | |
3350 | |
3351 t = 64-t; | |
3352 if (len < t) { | |
3353 memcpy(p, buf, len); | |
3354 return; | |
3355 } | |
3356 memcpy(p, buf, t); | |
3357 byteReverse(ctx->in, 16); | |
3358 MD5Transform(ctx->buf, (uint32 *)ctx->in); | |
3359 buf += t; | |
3360 len -= t; | |
3361 } | |
3362 | |
3363 /* Process data in 64-byte chunks */ | |
3364 | |
3365 while (len >= 64) { | |
3366 memcpy(ctx->in, buf, 64); | |
3367 byteReverse(ctx->in, 16); | |
3368 MD5Transform(ctx->buf, (uint32 *)ctx->in); | |
3369 buf += 64; | |
3370 len -= 64; | |
3371 } | |
3372 | |
3373 /* Handle any remaining bytes of data. */ | |
3374 | |
3375 memcpy(ctx->in, buf, len); | |
3376 } | |
3377 | |
3378 /* | |
3379 * Final wrapup - pad to 64-byte boundary with the bit pattern | |
3380 * 1 0* (64-bit count of bits processed, MSB-first) | |
3381 */ | |
3382 static void MD5Final(unsigned char digest[16], MD5Context *ctx){ | |
3383 unsigned count; | |
3384 unsigned char *p; | |
3385 | |
3386 /* Compute number of bytes mod 64 */ | |
3387 count = (ctx->bits[0] >> 3) & 0x3F; | |
3388 | |
3389 /* Set the first char of padding to 0x80. This is safe since there is | |
3390 always at least one byte free */ | |
3391 p = ctx->in + count; | |
3392 *p++ = 0x80; | |
3393 | |
3394 /* Bytes of padding needed to make 64 bytes */ | |
3395 count = 64 - 1 - count; | |
3396 | |
3397 /* Pad out to 56 mod 64 */ | |
3398 if (count < 8) { | |
3399 /* Two lots of padding: Pad the first block to 64 bytes */ | |
3400 memset(p, 0, count); | |
3401 byteReverse(ctx->in, 16); | |
3402 MD5Transform(ctx->buf, (uint32 *)ctx->in); | |
3403 | |
3404 /* Now fill the next block with 56 bytes */ | |
3405 memset(ctx->in, 0, 56); | |
3406 } else { | |
3407 /* Pad block to 56 bytes */ | |
3408 memset(p, 0, count-8); | |
3409 } | |
3410 byteReverse(ctx->in, 14); | |
3411 | |
3412 /* Append length in bits and transform */ | |
3413 memcpy(ctx->in + 14*4, ctx->bits, 8); | |
3414 | |
3415 MD5Transform(ctx->buf, (uint32 *)ctx->in); | |
3416 byteReverse((unsigned char *)ctx->buf, 4); | |
3417 memcpy(digest, ctx->buf, 16); | |
3418 } | |
3419 | |
3420 /* | |
3421 ** Convert a 128-bit MD5 digest into a 32-digit base-16 number. | |
3422 */ | |
3423 static void MD5DigestToBase16(unsigned char *digest, char *zBuf){ | |
3424 static char const zEncode[] = "0123456789abcdef"; | |
3425 int i, j; | |
3426 | |
3427 for(j=i=0; i<16; i++){ | |
3428 int a = digest[i]; | |
3429 zBuf[j++] = zEncode[(a>>4)&0xf]; | |
3430 zBuf[j++] = zEncode[a & 0xf]; | |
3431 } | |
3432 zBuf[j] = 0; | |
3433 } | |
3434 | |
3435 | |
3436 /* | |
3437 ** Convert a 128-bit MD5 digest into sequency of eight 5-digit integers | |
3438 ** each representing 16 bits of the digest and separated from each | |
3439 ** other by a "-" character. | |
3440 */ | |
3441 static void MD5DigestToBase10x8(unsigned char digest[16], char zDigest[50]){ | |
3442 int i, j; | |
3443 unsigned int x; | |
3444 for(i=j=0; i<16; i+=2){ | |
3445 x = digest[i]*256 + digest[i+1]; | |
3446 if( i>0 ) zDigest[j++] = '-'; | |
3447 sqlite3_snprintf(50-j, &zDigest[j], "%05u", x); | |
3448 j += 5; | |
3449 } | |
3450 zDigest[j] = 0; | |
3451 } | |
3452 | |
3453 /* | |
3454 ** A TCL command for md5. The argument is the text to be hashed. The | |
3455 ** Result is the hash in base64. | |
3456 */ | |
3457 static int md5_cmd(void*cd, Tcl_Interp *interp, int argc, const char **argv){ | |
3458 MD5Context ctx; | |
3459 unsigned char digest[16]; | |
3460 char zBuf[50]; | |
3461 void (*converter)(unsigned char*, char*); | |
3462 | |
3463 if( argc!=2 ){ | |
3464 Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0], | |
3465 " TEXT\"", (char*)0); | |
3466 return TCL_ERROR; | |
3467 } | |
3468 MD5Init(&ctx); | |
3469 MD5Update(&ctx, (unsigned char*)argv[1], (unsigned)strlen(argv[1])); | |
3470 MD5Final(digest, &ctx); | |
3471 converter = (void(*)(unsigned char*,char*))cd; | |
3472 converter(digest, zBuf); | |
3473 Tcl_AppendResult(interp, zBuf, (char*)0); | |
3474 return TCL_OK; | |
3475 } | |
3476 | |
3477 /* | |
3478 ** A TCL command to take the md5 hash of a file. The argument is the | |
3479 ** name of the file. | |
3480 */ | |
3481 static int md5file_cmd(void*cd, Tcl_Interp*interp, int argc, const char **argv){ | |
3482 FILE *in; | |
3483 MD5Context ctx; | |
3484 void (*converter)(unsigned char*, char*); | |
3485 unsigned char digest[16]; | |
3486 char zBuf[10240]; | |
3487 | |
3488 if( argc!=2 ){ | |
3489 Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0], | |
3490 " FILENAME\"", (char*)0); | |
3491 return TCL_ERROR; | |
3492 } | |
3493 in = fopen(argv[1],"rb"); | |
3494 if( in==0 ){ | |
3495 Tcl_AppendResult(interp,"unable to open file \"", argv[1], | |
3496 "\" for reading", (char*)0); | |
3497 return TCL_ERROR; | |
3498 } | |
3499 MD5Init(&ctx); | |
3500 for(;;){ | |
3501 int n; | |
3502 n = (int)fread(zBuf, 1, sizeof(zBuf), in); | |
3503 if( n<=0 ) break; | |
3504 MD5Update(&ctx, (unsigned char*)zBuf, (unsigned)n); | |
3505 } | |
3506 fclose(in); | |
3507 MD5Final(digest, &ctx); | |
3508 converter = (void(*)(unsigned char*,char*))cd; | |
3509 converter(digest, zBuf); | |
3510 Tcl_AppendResult(interp, zBuf, (char*)0); | |
3511 return TCL_OK; | |
3512 } | |
3513 | |
3514 /* | |
3515 ** Register the four new TCL commands for generating MD5 checksums | |
3516 ** with the TCL interpreter. | |
3517 */ | |
3518 int Md5_Init(Tcl_Interp *interp){ | |
3519 Tcl_CreateCommand(interp, "md5", (Tcl_CmdProc*)md5_cmd, | |
3520 MD5DigestToBase16, 0); | |
3521 Tcl_CreateCommand(interp, "md5-10x8", (Tcl_CmdProc*)md5_cmd, | |
3522 MD5DigestToBase10x8, 0); | |
3523 Tcl_CreateCommand(interp, "md5file", (Tcl_CmdProc*)md5file_cmd, | |
3524 MD5DigestToBase16, 0); | |
3525 Tcl_CreateCommand(interp, "md5file-10x8", (Tcl_CmdProc*)md5file_cmd, | |
3526 MD5DigestToBase10x8, 0); | |
3527 return TCL_OK; | |
3528 } | |
3529 #endif /* defined(SQLITE_TEST) || defined(SQLITE_TCLMD5) */ | |
3530 | |
3531 #if defined(SQLITE_TEST) | |
3532 /* | |
3533 ** During testing, the special md5sum() aggregate function is available. | |
3534 ** inside SQLite. The following routines implement that function. | |
3535 */ | |
3536 static void md5step(sqlite3_context *context, int argc, sqlite3_value **argv){ | |
3537 MD5Context *p; | |
3538 int i; | |
3539 if( argc<1 ) return; | |
3540 p = sqlite3_aggregate_context(context, sizeof(*p)); | |
3541 if( p==0 ) return; | |
3542 if( !p->isInit ){ | |
3543 MD5Init(p); | |
3544 } | |
3545 for(i=0; i<argc; i++){ | |
3546 const char *zData = (char*)sqlite3_value_text(argv[i]); | |
3547 if( zData ){ | |
3548 MD5Update(p, (unsigned char*)zData, (int)strlen(zData)); | |
3549 } | |
3550 } | |
3551 } | |
3552 static void md5finalize(sqlite3_context *context){ | |
3553 MD5Context *p; | |
3554 unsigned char digest[16]; | |
3555 char zBuf[33]; | |
3556 p = sqlite3_aggregate_context(context, sizeof(*p)); | |
3557 MD5Final(digest,p); | |
3558 MD5DigestToBase16(digest, zBuf); | |
3559 sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); | |
3560 } | |
3561 int Md5_Register(sqlite3 *db){ | |
3562 int rc = sqlite3_create_function(db, "md5sum", -1, SQLITE_UTF8, 0, 0, | |
3563 md5step, md5finalize); | |
3564 sqlite3_overload_function(db, "md5sum", -1); /* To exercise this API */ | |
3565 return rc; | |
3566 } | |
3567 #endif /* defined(SQLITE_TEST) */ | |
3568 | |
3569 | |
3570 /* | |
3571 ** If the macro TCLSH is one, then put in code this for the | |
3572 ** "main" routine that will initialize Tcl and take input from | |
3573 ** standard input, or if a file is named on the command line | |
3574 ** the TCL interpreter reads and evaluates that file. | |
3575 */ | |
3576 #if TCLSH==1 | |
3577 static const char *tclsh_main_loop(void){ | |
3578 static const char zMainloop[] = | |
3579 "set line {}\n" | |
3580 "while {![eof stdin]} {\n" | |
3581 "if {$line!=\"\"} {\n" | |
3582 "puts -nonewline \"> \"\n" | |
3583 "} else {\n" | |
3584 "puts -nonewline \"% \"\n" | |
3585 "}\n" | |
3586 "flush stdout\n" | |
3587 "append line [gets stdin]\n" | |
3588 "if {[info complete $line]} {\n" | |
3589 "if {[catch {uplevel #0 $line} result]} {\n" | |
3590 "puts stderr \"Error: $result\"\n" | |
3591 "} elseif {$result!=\"\"} {\n" | |
3592 "puts $result\n" | |
3593 "}\n" | |
3594 "set line {}\n" | |
3595 "} else {\n" | |
3596 "append line \\n\n" | |
3597 "}\n" | |
3598 "}\n" | |
3599 ; | |
3600 return zMainloop; | |
3601 } | |
3602 #endif | |
3603 #if TCLSH==2 | |
3604 static const char *tclsh_main_loop(void); | |
3605 #endif | |
3606 | |
3607 #ifdef SQLITE_TEST | |
3608 static void init_all(Tcl_Interp *); | |
3609 static int init_all_cmd( | |
3610 ClientData cd, | |
3611 Tcl_Interp *interp, | |
3612 int objc, | |
3613 Tcl_Obj *CONST objv[] | |
3614 ){ | |
3615 | |
3616 Tcl_Interp *slave; | |
3617 if( objc!=2 ){ | |
3618 Tcl_WrongNumArgs(interp, 1, objv, "SLAVE"); | |
3619 return TCL_ERROR; | |
3620 } | |
3621 | |
3622 slave = Tcl_GetSlave(interp, Tcl_GetString(objv[1])); | |
3623 if( !slave ){ | |
3624 return TCL_ERROR; | |
3625 } | |
3626 | |
3627 init_all(slave); | |
3628 return TCL_OK; | |
3629 } | |
3630 | |
3631 /* | |
3632 ** Tclcmd: db_use_legacy_prepare DB BOOLEAN | |
3633 ** | |
3634 ** The first argument to this command must be a database command created by | |
3635 ** [sqlite3]. If the second argument is true, then the handle is configured | |
3636 ** to use the sqlite3_prepare_v2() function to prepare statements. If it | |
3637 ** is false, sqlite3_prepare(). | |
3638 */ | |
3639 static int db_use_legacy_prepare_cmd( | |
3640 ClientData cd, | |
3641 Tcl_Interp *interp, | |
3642 int objc, | |
3643 Tcl_Obj *CONST objv[] | |
3644 ){ | |
3645 Tcl_CmdInfo cmdInfo; | |
3646 SqliteDb *pDb; | |
3647 int bPrepare; | |
3648 | |
3649 if( objc!=3 ){ | |
3650 Tcl_WrongNumArgs(interp, 1, objv, "DB BOOLEAN"); | |
3651 return TCL_ERROR; | |
3652 } | |
3653 | |
3654 if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){ | |
3655 Tcl_AppendResult(interp, "no such db: ", Tcl_GetString(objv[1]), (char*)0); | |
3656 return TCL_ERROR; | |
3657 } | |
3658 pDb = (SqliteDb*)cmdInfo.objClientData; | |
3659 if( Tcl_GetBooleanFromObj(interp, objv[2], &bPrepare) ){ | |
3660 return TCL_ERROR; | |
3661 } | |
3662 | |
3663 pDb->bLegacyPrepare = bPrepare; | |
3664 | |
3665 Tcl_ResetResult(interp); | |
3666 return TCL_OK; | |
3667 } | |
3668 | |
3669 /* | |
3670 ** Tclcmd: db_last_stmt_ptr DB | |
3671 ** | |
3672 ** If the statement cache associated with database DB is not empty, | |
3673 ** return the text representation of the most recently used statement | |
3674 ** handle. | |
3675 */ | |
3676 static int db_last_stmt_ptr( | |
3677 ClientData cd, | |
3678 Tcl_Interp *interp, | |
3679 int objc, | |
3680 Tcl_Obj *CONST objv[] | |
3681 ){ | |
3682 extern int sqlite3TestMakePointerStr(Tcl_Interp*, char*, void*); | |
3683 Tcl_CmdInfo cmdInfo; | |
3684 SqliteDb *pDb; | |
3685 sqlite3_stmt *pStmt = 0; | |
3686 char zBuf[100]; | |
3687 | |
3688 if( objc!=2 ){ | |
3689 Tcl_WrongNumArgs(interp, 1, objv, "DB"); | |
3690 return TCL_ERROR; | |
3691 } | |
3692 | |
3693 if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){ | |
3694 Tcl_AppendResult(interp, "no such db: ", Tcl_GetString(objv[1]), (char*)0); | |
3695 return TCL_ERROR; | |
3696 } | |
3697 pDb = (SqliteDb*)cmdInfo.objClientData; | |
3698 | |
3699 if( pDb->stmtList ) pStmt = pDb->stmtList->pStmt; | |
3700 if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ){ | |
3701 return TCL_ERROR; | |
3702 } | |
3703 Tcl_SetResult(interp, zBuf, TCL_VOLATILE); | |
3704 | |
3705 return TCL_OK; | |
3706 } | |
3707 #endif /* SQLITE_TEST */ | |
3708 | |
3709 /* | |
3710 ** Configure the interpreter passed as the first argument to have access | |
3711 ** to the commands and linked variables that make up: | |
3712 ** | |
3713 ** * the [sqlite3] extension itself, | |
3714 ** | |
3715 ** * If SQLITE_TCLMD5 or SQLITE_TEST is defined, the Md5 commands, and | |
3716 ** | |
3717 ** * If SQLITE_TEST is set, the various test interfaces used by the Tcl | |
3718 ** test suite. | |
3719 */ | |
3720 static void init_all(Tcl_Interp *interp){ | |
3721 Sqlite3_Init(interp); | |
3722 | |
3723 #if defined(SQLITE_TEST) || defined(SQLITE_TCLMD5) | |
3724 Md5_Init(interp); | |
3725 #endif | |
3726 | |
3727 #ifdef SQLITE_TEST | |
3728 { | |
3729 extern int Sqliteconfig_Init(Tcl_Interp*); | |
3730 extern int Sqlitetest1_Init(Tcl_Interp*); | |
3731 extern int Sqlitetest2_Init(Tcl_Interp*); | |
3732 extern int Sqlitetest3_Init(Tcl_Interp*); | |
3733 extern int Sqlitetest4_Init(Tcl_Interp*); | |
3734 extern int Sqlitetest5_Init(Tcl_Interp*); | |
3735 extern int Sqlitetest6_Init(Tcl_Interp*); | |
3736 extern int Sqlitetest7_Init(Tcl_Interp*); | |
3737 extern int Sqlitetest8_Init(Tcl_Interp*); | |
3738 extern int Sqlitetest9_Init(Tcl_Interp*); | |
3739 extern int Sqlitetestasync_Init(Tcl_Interp*); | |
3740 extern int Sqlitetest_autoext_Init(Tcl_Interp*); | |
3741 extern int Sqlitetest_blob_Init(Tcl_Interp*); | |
3742 extern int Sqlitetest_demovfs_Init(Tcl_Interp *); | |
3743 extern int Sqlitetest_func_Init(Tcl_Interp*); | |
3744 extern int Sqlitetest_hexio_Init(Tcl_Interp*); | |
3745 extern int Sqlitetest_init_Init(Tcl_Interp*); | |
3746 extern int Sqlitetest_malloc_Init(Tcl_Interp*); | |
3747 extern int Sqlitetest_mutex_Init(Tcl_Interp*); | |
3748 extern int Sqlitetestschema_Init(Tcl_Interp*); | |
3749 extern int Sqlitetestsse_Init(Tcl_Interp*); | |
3750 extern int Sqlitetesttclvar_Init(Tcl_Interp*); | |
3751 extern int Sqlitetestfs_Init(Tcl_Interp*); | |
3752 extern int SqlitetestThread_Init(Tcl_Interp*); | |
3753 extern int SqlitetestOnefile_Init(); | |
3754 extern int SqlitetestOsinst_Init(Tcl_Interp*); | |
3755 extern int Sqlitetestbackup_Init(Tcl_Interp*); | |
3756 extern int Sqlitetestintarray_Init(Tcl_Interp*); | |
3757 extern int Sqlitetestvfs_Init(Tcl_Interp *); | |
3758 extern int Sqlitetestrtree_Init(Tcl_Interp*); | |
3759 extern int Sqlitequota_Init(Tcl_Interp*); | |
3760 extern int Sqlitemultiplex_Init(Tcl_Interp*); | |
3761 extern int SqliteSuperlock_Init(Tcl_Interp*); | |
3762 extern int SqlitetestSyscall_Init(Tcl_Interp*); | |
3763 extern int Fts5tcl_Init(Tcl_Interp *); | |
3764 extern int SqliteRbu_Init(Tcl_Interp*); | |
3765 #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) | |
3766 extern int Sqlitetestfts3_Init(Tcl_Interp *interp); | |
3767 #endif | |
3768 | |
3769 #ifdef SQLITE_ENABLE_ZIPVFS | |
3770 extern int Zipvfs_Init(Tcl_Interp*); | |
3771 Zipvfs_Init(interp); | |
3772 #endif | |
3773 | |
3774 Sqliteconfig_Init(interp); | |
3775 Sqlitetest1_Init(interp); | |
3776 Sqlitetest2_Init(interp); | |
3777 Sqlitetest3_Init(interp); | |
3778 Sqlitetest4_Init(interp); | |
3779 Sqlitetest5_Init(interp); | |
3780 Sqlitetest6_Init(interp); | |
3781 Sqlitetest7_Init(interp); | |
3782 Sqlitetest8_Init(interp); | |
3783 Sqlitetest9_Init(interp); | |
3784 Sqlitetestasync_Init(interp); | |
3785 Sqlitetest_autoext_Init(interp); | |
3786 Sqlitetest_blob_Init(interp); | |
3787 Sqlitetest_demovfs_Init(interp); | |
3788 Sqlitetest_func_Init(interp); | |
3789 Sqlitetest_hexio_Init(interp); | |
3790 Sqlitetest_init_Init(interp); | |
3791 Sqlitetest_malloc_Init(interp); | |
3792 Sqlitetest_mutex_Init(interp); | |
3793 Sqlitetestschema_Init(interp); | |
3794 Sqlitetesttclvar_Init(interp); | |
3795 Sqlitetestfs_Init(interp); | |
3796 SqlitetestThread_Init(interp); | |
3797 SqlitetestOnefile_Init(interp); | |
3798 SqlitetestOsinst_Init(interp); | |
3799 Sqlitetestbackup_Init(interp); | |
3800 Sqlitetestintarray_Init(interp); | |
3801 Sqlitetestvfs_Init(interp); | |
3802 Sqlitetestrtree_Init(interp); | |
3803 Sqlitequota_Init(interp); | |
3804 Sqlitemultiplex_Init(interp); | |
3805 SqliteSuperlock_Init(interp); | |
3806 SqlitetestSyscall_Init(interp); | |
3807 Fts5tcl_Init(interp); | |
3808 SqliteRbu_Init(interp); | |
3809 | |
3810 #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) | |
3811 Sqlitetestfts3_Init(interp); | |
3812 #endif | |
3813 | |
3814 Tcl_CreateObjCommand( | |
3815 interp, "load_testfixture_extensions", init_all_cmd, 0, 0 | |
3816 ); | |
3817 Tcl_CreateObjCommand( | |
3818 interp, "db_use_legacy_prepare", db_use_legacy_prepare_cmd, 0, 0 | |
3819 ); | |
3820 Tcl_CreateObjCommand( | |
3821 interp, "db_last_stmt_ptr", db_last_stmt_ptr, 0, 0 | |
3822 ); | |
3823 | |
3824 #ifdef SQLITE_SSE | |
3825 Sqlitetestsse_Init(interp); | |
3826 #endif | |
3827 } | |
3828 #endif | |
3829 } | |
3830 | |
3831 /* Needed for the setrlimit() system call on unix */ | |
3832 #if defined(unix) | |
3833 #include <sys/resource.h> | |
3834 #endif | |
3835 | |
3836 #define TCLSH_MAIN main /* Needed to fake out mktclapp */ | |
3837 int TCLSH_MAIN(int argc, char **argv){ | |
3838 Tcl_Interp *interp; | |
3839 | |
3840 #if !defined(_WIN32_WCE) | |
3841 if( getenv("BREAK") ){ | |
3842 fprintf(stderr, | |
3843 "attach debugger to process %d and press any key to continue.\n", | |
3844 GETPID()); | |
3845 fgetc(stdin); | |
3846 } | |
3847 #endif | |
3848 | |
3849 /* Since the primary use case for this binary is testing of SQLite, | |
3850 ** be sure to generate core files if we crash */ | |
3851 #if defined(SQLITE_TEST) && defined(unix) | |
3852 { struct rlimit x; | |
3853 getrlimit(RLIMIT_CORE, &x); | |
3854 x.rlim_cur = x.rlim_max; | |
3855 setrlimit(RLIMIT_CORE, &x); | |
3856 } | |
3857 #endif /* SQLITE_TEST && unix */ | |
3858 | |
3859 | |
3860 /* Call sqlite3_shutdown() once before doing anything else. This is to | |
3861 ** test that sqlite3_shutdown() can be safely called by a process before | |
3862 ** sqlite3_initialize() is. */ | |
3863 sqlite3_shutdown(); | |
3864 | |
3865 Tcl_FindExecutable(argv[0]); | |
3866 Tcl_SetSystemEncoding(NULL, "utf-8"); | |
3867 interp = Tcl_CreateInterp(); | |
3868 | |
3869 #if TCLSH==2 | |
3870 sqlite3_config(SQLITE_CONFIG_SINGLETHREAD); | |
3871 #endif | |
3872 | |
3873 init_all(interp); | |
3874 if( argc>=2 ){ | |
3875 int i; | |
3876 char zArgc[32]; | |
3877 sqlite3_snprintf(sizeof(zArgc), zArgc, "%d", argc-(3-TCLSH)); | |
3878 Tcl_SetVar(interp,"argc", zArgc, TCL_GLOBAL_ONLY); | |
3879 Tcl_SetVar(interp,"argv0",argv[1],TCL_GLOBAL_ONLY); | |
3880 Tcl_SetVar(interp,"argv", "", TCL_GLOBAL_ONLY); | |
3881 for(i=3-TCLSH; i<argc; i++){ | |
3882 Tcl_SetVar(interp, "argv", argv[i], | |
3883 TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT | TCL_APPEND_VALUE); | |
3884 } | |
3885 if( TCLSH==1 && Tcl_EvalFile(interp, argv[1])!=TCL_OK ){ | |
3886 const char *zInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY); | |
3887 if( zInfo==0 ) zInfo = Tcl_GetStringResult(interp); | |
3888 fprintf(stderr,"%s: %s\n", *argv, zInfo); | |
3889 return 1; | |
3890 } | |
3891 } | |
3892 if( TCLSH==2 || argc<=1 ){ | |
3893 Tcl_GlobalEval(interp, tclsh_main_loop()); | |
3894 } | |
3895 return 0; | |
3896 } | |
3897 #endif /* TCLSH */ | |
OLD | NEW |