Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Improvements to the SQLITE_MISUSE detection logic. Also added test cases for this logic, including the new test file "misuse.test". (CVS 559) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
f42907ce457e012592f8c043dc6c915e |
User & Date: | drh 2002-05-10 13:14:07.000 |
Context
2002-05-10
| ||
14:37 | Update the misuse.test script so that it will work under Windows. Changes to the speed testing script to support version 2.4.12. (CVS 560) (check-in: 232b7ef2c8 user: drh tags: trunk) | |
13:14 | Improvements to the SQLITE_MISUSE detection logic. Also added test cases for this logic, including the new test file "misuse.test". (CVS 559) (check-in: f42907ce45 user: drh tags: trunk) | |
05:44 | Attempt to detect when two or more threads try to use the same database at the same time and return an SQLITE_MISUSE error. Also return this error if an attempt is made to use a closed database. (CVS 558) (check-in: a05fabd2df user: drh tags: trunk) | |
Changes
Changes to VERSION.
|
| | | 1 | 2.4.12 |
Changes to src/main.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** ** $Id: main.c,v 1.71 2002/05/10 13:14:07 drh Exp $ */ #include "sqliteInt.h" #include "os.h" /* ** This is the callback routine for the code that initializes the ** database. See sqliteInit() below for additional information. |
︙ | ︙ | |||
431 432 433 434 435 436 437 | } /* ** Close an existing SQLite database */ void sqlite_close(sqlite *db){ HashElem *i; | | | 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 | } /* ** Close an existing SQLite database */ void sqlite_close(sqlite *db){ HashElem *i; if( sqliteSafetyCheck(db) || sqliteSafetyOn(db) ){ return; } db->magic = SQLITE_MAGIC_CLOSED; sqliteBtreeClose(db->pBe); clearHashTable(db, 0); if( db->pBeTemp ){ sqliteBtreeClose(db->pBeTemp); } for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){ |
︙ | ︙ | |||
526 527 528 529 530 531 532 | sqlite_callback xCallback, /* Invoke this callback routine */ void *pArg, /* First argument to xCallback() */ char **pzErrMsg /* Write error messages here */ ){ Parse sParse; if( pzErrMsg ) *pzErrMsg = 0; | | | 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 | sqlite_callback xCallback, /* Invoke this callback routine */ void *pArg, /* First argument to xCallback() */ char **pzErrMsg /* Write error messages here */ ){ Parse sParse; if( pzErrMsg ) *pzErrMsg = 0; if( sqliteSafetyOn(db) ) goto exec_misuse; if( (db->flags & SQLITE_Initialized)==0 ){ int rc = sqliteInit(db, pzErrMsg); if( rc!=SQLITE_OK ){ sqliteStrRealloc(pzErrMsg); sqliteSafetyOff(db); return rc; } |
︙ | ︙ | |||
556 557 558 559 560 561 562 | clearHashTable(db, 0); } sqliteStrRealloc(pzErrMsg); if( sParse.rc==SQLITE_SCHEMA ){ clearHashTable(db, 1); } db->recursionDepth--; | | | > > > > > | > > > < | < | < < < < < < | > > | | < < | | < < < | < | | > | < > | | | | | | | | > > > > > > | 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 | clearHashTable(db, 0); } sqliteStrRealloc(pzErrMsg); if( sParse.rc==SQLITE_SCHEMA ){ clearHashTable(db, 1); } db->recursionDepth--; if( sqliteSafetyOff(db) ) goto exec_misuse; return sParse.rc; exec_misuse: if( pzErrMsg ){ *pzErrMsg = 0; sqliteSetString(pzErrMsg, sqlite_error_string(SQLITE_MISUSE), 0); sqliteStrRealloc(pzErrMsg); } return SQLITE_MISUSE; } /* ** Return a static string that describes the kind of error specified in the ** argument. */ const char *sqlite_error_string(int rc){ const char *z; switch( rc ){ case SQLITE_OK: z = "not an error"; break; case SQLITE_ERROR: z = "SQL logic error or missing database"; break; case SQLITE_INTERNAL: z = "internal SQLite implementation flaw"; break; case SQLITE_PERM: z = "access permission denied"; break; case SQLITE_ABORT: z = "callback requested query abort"; break; case SQLITE_BUSY: z = "database is locked"; break; case SQLITE_LOCKED: z = "database table is locked"; break; case SQLITE_NOMEM: z = "out of memory"; break; case SQLITE_READONLY: z = "attempt to write a readonly database"; break; case SQLITE_INTERRUPT: z = "interrupted"; break; case SQLITE_IOERR: z = "disk I/O error"; break; case SQLITE_CORRUPT: z = "database disk image is malformed"; break; case SQLITE_NOTFOUND: z = "table or record not found"; break; case SQLITE_FULL: z = "database is full"; break; case SQLITE_CANTOPEN: z = "unable to open database file"; break; case SQLITE_PROTOCOL: z = "database locking protocol failure"; break; case SQLITE_EMPTY: z = "table contains no data"; break; case SQLITE_SCHEMA: z = "database schema has changed"; break; case SQLITE_TOOBIG: z = "too much data for one table row"; break; case SQLITE_CONSTRAINT: z = "constraint failed"; break; case SQLITE_MISMATCH: z = "datatype mismatch"; break; case SQLITE_MISUSE: z = "library routine called out of sequence";break; default: z = "unknown error"; break; } return z; } /* ** This routine implements a busy callback that sleeps and tries ** again until a timeout value is reached. The timeout value is ** an integer number of milliseconds passed in as the first ** argument. |
︙ | ︙ | |||
714 715 716 717 718 719 720 | sqlite *db, /* Add the function to this database connection */ const char *zName, /* Name of the function to add */ int nArg, /* Number of arguments */ void (*xFunc)(sqlite_func*,int,const char**), /* The implementation */ void *pUserData /* User data */ ){ FuncDef *p; | | | | 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 | sqlite *db, /* Add the function to this database connection */ const char *zName, /* Name of the function to add */ int nArg, /* Number of arguments */ void (*xFunc)(sqlite_func*,int,const char**), /* The implementation */ void *pUserData /* User data */ ){ FuncDef *p; if( db==0 || zName==0 || sqliteSafetyCheck(db) ) return 1; p = sqliteFindFunction(db, zName, strlen(zName), nArg, 1); if( p==0 ) return 1; p->xFunc = xFunc; p->xStep = 0; p->xFinalize = 0; p->pUserData = pUserData; return 0; } int sqlite_create_aggregate( sqlite *db, /* Add the function to this database connection */ const char *zName, /* Name of the function to add */ int nArg, /* Number of arguments */ void (*xStep)(sqlite_func*,int,const char**), /* The step function */ void (*xFinalize)(sqlite_func*), /* The finalizer */ void *pUserData /* User data */ ){ FuncDef *p; if( db==0 || zName==0 || sqliteSafetyCheck(db) ) return 1; p = sqliteFindFunction(db, zName, strlen(zName), nArg, 1); if( p==0 ) return 1; p->xFunc = 0; p->xStep = xStep; p->xFinalize = xFinalize; p->pUserData = pUserData; return 0; } |
Changes to src/sqliteInt.h.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.107 2002/05/10 13:14:07 drh Exp $ */ #include "sqlite.h" #include "hash.h" #include "vdbe.h" #include "parse.h" #include "btree.h" #include <stdio.h> |
︙ | ︙ | |||
657 658 659 660 661 662 663 | ExprList *sqliteExprListDup(ExprList*); IdList *sqliteIdListDup(IdList*); Select *sqliteSelectDup(Select*); FuncDef *sqliteFindFunction(sqlite*,const char*,int,int,int); void sqliteRegisterBuildinFunctions(sqlite*); int sqliteSafetyOn(sqlite*); int sqliteSafetyOff(sqlite*); | > | 657 658 659 660 661 662 663 664 | ExprList *sqliteExprListDup(ExprList*); IdList *sqliteIdListDup(IdList*); Select *sqliteSelectDup(Select*); FuncDef *sqliteFindFunction(sqlite*,const char*,int,int,int); void sqliteRegisterBuildinFunctions(sqlite*); int sqliteSafetyOn(sqlite*); int sqliteSafetyOff(sqlite*); int sqliteSafetyCheck(sqlite*); |
Changes to src/tclsqlite.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** A TCL Interface to SQLite ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** A TCL Interface to SQLite ** ** $Id: tclsqlite.c,v 1.32 2002/05/10 13:14:07 drh Exp $ */ #ifndef NO_TCL /* Omit this whole file if TCL is unavailable */ #include "sqlite.h" #include "tcl.h" #include <stdlib.h> #include <string.h> |
︙ | ︙ | |||
548 549 550 551 552 553 554 555 556 | if( p->db==0 ){ Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE); Tcl_Free((char*)p); free(zErrMsg); return TCL_ERROR; } Tcl_CreateObjCommand(interp, argv[1], DbObjCmd, (char*)p, DbDeleteCmd); #ifdef SQLITE_TEST { | > > > > > > | | > > | 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 | if( p->db==0 ){ Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE); Tcl_Free((char*)p); free(zErrMsg); return TCL_ERROR; } Tcl_CreateObjCommand(interp, argv[1], DbObjCmd, (char*)p, DbDeleteCmd); /* If compiled with SQLITE_TEST turned on, then register the "md5sum" ** SQL function and return an integer which is the memory address of ** the underlying sqlite* pointer. */ #ifdef SQLITE_TEST { char zBuf[40]; extern void Md5_Register(sqlite*); Md5_Register(p->db); sprintf(zBuf, "%d", (int)p->db); Tcl_AppendResult(interp, zBuf, 0); } #endif return TCL_OK; } /* ** Provide a dummy Tcl_InitStubs if we are using this as a static |
︙ | ︙ |
Changes to src/test1.c.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** Code for testing the printf() interface to SQLite. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** Code for testing the printf() interface to SQLite. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** ** $Id: test1.c,v 1.8 2002/05/10 13:14:07 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" #include <stdlib.h> #include <string.h> /* |
︙ | ︙ | |||
192 193 194 195 196 197 198 199 200 201 202 203 204 205 | " FILENAME\"", 0); return TCL_ERROR; } db = (sqlite*)atoi(argv[1]); sqlite_close(db); return TCL_OK; } /* ** Usage: sqlite_mprintf_int FORMAT INTEGER INTEGER INTEGER ** ** Call mprintf with three integer arguments */ static int sqlite_mprintf_int( | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 | " FILENAME\"", 0); return TCL_ERROR; } db = (sqlite*)atoi(argv[1]); sqlite_close(db); return TCL_OK; } /* ** Implementation of the x_coalesce() function. ** Return the first argument non-NULL argument. */ static void ifnullFunc(sqlite_func *context, int argc, const char **argv){ int i; for(i=0; i<argc; i++){ if( argv[i] ){ sqlite_set_result_string(context, argv[i], -1); break; } } } /* ** Implementation of the x_sqlite_exec() function. This function takes ** a single argument and attempts to execute that argument as SQL code. ** This is illegal and shut set the SQLITE_MISUSE flag on the database. ** ** This routine simulates the effect of having two threads attempt to ** use the same database at the same time. */ static void sqliteExecFunc(sqlite_func *context, int argc, const char **argv){ sqlite_exec((sqlite*)sqlite_user_data(context), argv[0], 0, 0, 0); } /* ** Usage: sqlite_test_create_function DB ** ** Call the sqlite_create_function API on the given database in order ** to create a function named "x_coalesce". This function does the same thing ** as the "coalesce" function. This function also registers an SQL function ** named "x_sqlite_exec" that invokes sqlite_exec(). Invoking sqlite_exec() ** in this way is illegal recursion and should raise an SQLITE_MISUSE error. ** The effect is similar to trying to use the same database connection from ** two threads at the same time. ** ** The original motivation for this routine was to be able to call the ** sqlite_create_function function while a query is in progress in order ** to test the SQLITE_MISUSE detection logic. */ static int sqlite_test_create_function( void *NotUsed, Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ char **argv /* Text of each argument */ ){ sqlite *db; extern void Md5_Register(sqlite*); if( argc!=2 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " FILENAME\"", 0); return TCL_ERROR; } db = (sqlite*)atoi(argv[1]); sqlite_create_function(db, "x_coalesce", -1, ifnullFunc, 0); sqlite_create_function(db, "x_sqlite_exec", 1, sqliteExecFunc, db); return TCL_OK; } /* ** Routines to implement the x_count() aggregate function. */ typedef struct CountCtx CountCtx; struct CountCtx { int n; }; static void countStep(sqlite_func *context, int argc, const char **argv){ CountCtx *p; p = sqlite_aggregate_context(context, sizeof(*p)); if( (argc==0 || argv[0]) && p ){ p->n++; } } static void countFinalize(sqlite_func *context){ CountCtx *p; p = sqlite_aggregate_context(context, sizeof(*p)); sqlite_set_result_int(context, p ? p->n : 0); } /* ** Usage: sqlite_test_create_aggregate DB ** ** Call the sqlite_create_function API on the given database in order ** to create a function named "x_count". This function does the same thing ** as the "md5sum" function. ** ** The original motivation for this routine was to be able to call the ** sqlite_create_aggregate function while a query is in progress in order ** to test the SQLITE_MISUSE detection logic. */ static int sqlite_test_create_aggregate( void *NotUsed, Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ char **argv /* Text of each argument */ ){ sqlite *db; if( argc!=2 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " FILENAME\"", 0); return TCL_ERROR; } db = (sqlite*)atoi(argv[1]); sqlite_create_aggregate(db, "x_count", 0, countStep, countFinalize, 0); sqlite_create_aggregate(db, "x_count", 1, countStep, countFinalize, 0); return TCL_OK; } /* ** Usage: sqlite_mprintf_int FORMAT INTEGER INTEGER INTEGER ** ** Call mprintf with three integer arguments */ static int sqlite_mprintf_int( |
︙ | ︙ | |||
351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 | Tcl_CreateCommand(interp, "sqlite_mprintf_double", sqlite_mprintf_double,0,0); Tcl_CreateCommand(interp, "sqlite_open", sqlite_test_open, 0, 0); Tcl_CreateCommand(interp, "sqlite_last_insert_rowid", test_last_rowid, 0, 0); Tcl_CreateCommand(interp, "sqlite_exec_printf", test_exec_printf, 0, 0); Tcl_CreateCommand(interp, "sqlite_get_table_printf", test_get_table_printf, 0, 0); Tcl_CreateCommand(interp, "sqlite_close", sqlite_test_close, 0, 0); Tcl_LinkVar(interp, "sqlite_search_count", (char*)&sqlite_search_count, TCL_LINK_INT); #ifdef MEMORY_DEBUG Tcl_CreateCommand(interp, "sqlite_malloc_fail", sqlite_malloc_fail, 0, 0); Tcl_CreateCommand(interp, "sqlite_malloc_stat", sqlite_malloc_stat, 0, 0); #endif Tcl_CreateCommand(interp, "sqlite_abort", sqlite_abort, 0, 0); return TCL_OK; } | > > > > | 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 | Tcl_CreateCommand(interp, "sqlite_mprintf_double", sqlite_mprintf_double,0,0); Tcl_CreateCommand(interp, "sqlite_open", sqlite_test_open, 0, 0); Tcl_CreateCommand(interp, "sqlite_last_insert_rowid", test_last_rowid, 0, 0); Tcl_CreateCommand(interp, "sqlite_exec_printf", test_exec_printf, 0, 0); Tcl_CreateCommand(interp, "sqlite_get_table_printf", test_get_table_printf, 0, 0); Tcl_CreateCommand(interp, "sqlite_close", sqlite_test_close, 0, 0); Tcl_CreateCommand(interp, "sqlite_create_function", sqlite_test_create_function, 0, 0); Tcl_CreateCommand(interp, "sqlite_create_aggregate", sqlite_test_create_aggregate, 0, 0); Tcl_LinkVar(interp, "sqlite_search_count", (char*)&sqlite_search_count, TCL_LINK_INT); #ifdef MEMORY_DEBUG Tcl_CreateCommand(interp, "sqlite_malloc_fail", sqlite_malloc_fail, 0, 0); Tcl_CreateCommand(interp, "sqlite_malloc_stat", sqlite_malloc_stat, 0, 0); #endif Tcl_CreateCommand(interp, "sqlite_abort", sqlite_abort, 0, 0); return TCL_OK; } |
Changes to src/util.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** ** $Id: util.c,v 1.43 2002/05/10 13:14:07 drh Exp $ */ #include "sqliteInt.h" #include <stdarg.h> #include <ctype.h> /* ** If malloc() ever fails, this global variable gets set to 1. |
︙ | ︙ | |||
1065 1066 1067 1068 1069 1070 1071 | } } } return *zString==0; } /* | > | > > > > > > > > > > > > > > > > > > > | > > > > | < < | | > > | | | > > | < < < > | | | < | > | | < > | | | | < < | | 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 | } } } return *zString==0; } /* ** Change the sqlite.magic from SQLITE_MAGIC_OPEN to SQLITE_MAGIC_BUSY. ** Return an error (non-zero) if the magic was not SQLITE_MAGIC_OPEN ** when this routine is called. ** ** This routine is a attempt to detect if two threads use the ** same sqlite* pointer at the same time. There is a race ** condition so it is possible that the error is not detected. ** But usually the problem will be seen. The result will be an ** error which can be used to debugging the application that is ** using SQLite incorrectly. */ int sqliteSafetyOn(sqlite *db){ if( db->magic==SQLITE_MAGIC_OPEN ){ db->magic = SQLITE_MAGIC_BUSY; return 0; }else{ db->magic = SQLITE_MAGIC_ERROR; db->flags |= SQLITE_Interrupt; return 1; } } /* ** Change the magic from SQLITE_MAGIC_BUSY to SQLITE_MAGIC_OPEN. ** Return an error (non-zero) if the magic was not SQLITE_MAGIC_BUSY ** when this routine is called. */ int sqliteSafetyOff(sqlite *db){ if( db->magic==SQLITE_MAGIC_BUSY ){ db->magic = SQLITE_MAGIC_OPEN; return 0; }else{ db->magic = SQLITE_MAGIC_ERROR; db->flags |= SQLITE_Interrupt; return 1; } } /* ** Check to make sure we are not currently executing an sqlite_exec(). ** If we are currently in an sqlite_exec(), return true and set ** sqlite.magic to SQLITE_MAGIC_ERROR. This will cause a complete ** shutdown of the database. ** ** This routine is used to try to detect when API routines are called ** at the wrong time or in the wrong sequence. */ int sqliteSafetyCheck(sqlite *db){ if( db->recursionDepth ){ db->magic = SQLITE_MAGIC_ERROR; return 1; } return 0; } |
Changes to src/vdbe.c.
︙ | ︙ | |||
26 27 28 29 30 31 32 | ** type to the other occurs as necessary. ** ** Most of the code in this file is taken up by the sqliteVdbeExec() ** function which does the work of interpreting a VDBE program. ** But other routines are also provided to help in building up ** a program instruction by instruction. ** | | | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | ** type to the other occurs as necessary. ** ** Most of the code in this file is taken up by the sqliteVdbeExec() ** function which does the work of interpreting a VDBE program. ** But other routines are also provided to help in building up ** a program instruction by instruction. ** ** $Id: vdbe.c,v 1.141 2002/05/10 13:14:07 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** The following global variable is incremented every time a cursor ** moves, either by the OP_MoveTo or the OP_Next opcode. The test |
︙ | ︙ | |||
1108 1109 1110 1111 1112 1113 1114 | azValue[2] = zP1; azValue[3] = zP2; azValue[5] = 0; rc = SQLITE_OK; for(i=0; rc==SQLITE_OK && i<p->nOp; i++){ if( db->flags & SQLITE_Interrupt ){ db->flags &= ~SQLITE_Interrupt; | | > > | > > | 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 | azValue[2] = zP1; azValue[3] = zP2; azValue[5] = 0; rc = SQLITE_OK; for(i=0; rc==SQLITE_OK && i<p->nOp; i++){ if( db->flags & SQLITE_Interrupt ){ db->flags &= ~SQLITE_Interrupt; if( db->magic!=SQLITE_MAGIC_BUSY ){ rc = SQLITE_MISUSE; }else{ rc = SQLITE_INTERRUPT; } sqliteSetString(pzErrMsg, sqlite_error_string(rc), 0); break; } sprintf(zAddr,"%d",i); sprintf(zP1,"%d", p->aOp[i].p1); sprintf(zP2,"%d", p->aOp[i].p2); if( p->aOp[i].p3type==P3_POINTER ){ sprintf(zP3, "ptr(%#x)", (int)p->aOp[i].p3); |
︙ | ︙ | |||
1295 1296 1297 1298 1299 1300 1301 | VERIFY(&& pc>=0); pc++){ pOp = &p->aOp[pc]; /* Interrupt processing if requested. */ if( db->flags & SQLITE_Interrupt ){ db->flags &= ~SQLITE_Interrupt; | > > > | > | | 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 | VERIFY(&& pc>=0); pc++){ pOp = &p->aOp[pc]; /* Interrupt processing if requested. */ if( db->flags & SQLITE_Interrupt ){ db->flags &= ~SQLITE_Interrupt; if( db->magic!=SQLITE_MAGIC_BUSY ){ rc = SQLITE_MISUSE; }else{ rc = SQLITE_INTERRUPT; } sqliteSetString(pzErrMsg, sqlite_error_string(rc), 0); break; } /* Only allow tracing if NDEBUG is not defined. */ #ifndef NDEBUG if( p->trace ){ |
︙ | ︙ |
Changes to test/all.test.
1 2 3 4 5 6 7 8 9 10 11 12 | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file runs all tests. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file runs all tests. # # $Id: all.test,v 1.14 2002/05/10 13:14:08 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl rename finish_test really_finish_test proc finish_test {} {memleak_check} if {[file exists ./sqlite_test_count]} { |
︙ | ︙ | |||
29 30 31 32 33 34 35 36 37 38 39 40 41 42 | # set LeakList {} set EXCLUDE { all.test quick.test malloc.test btree2.test } for {set Counter 0} {$Counter<$COUNT && $nErr==0} {incr Counter} { if {$Counter%2} { set ::SETUP_SQL {PRAGMA default_synchronous=off;} } else { | > | 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | # set LeakList {} set EXCLUDE { all.test quick.test malloc.test misuse.test btree2.test } for {set Counter 0} {$Counter<$COUNT && $nErr==0} {incr Counter} { if {$Counter%2} { set ::SETUP_SQL {PRAGMA default_synchronous=off;} } else { |
︙ | ︙ | |||
67 68 69 70 71 72 73 | lappend ::failList memory-leak-test break } } puts " Ok" } | | | > | 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | lappend ::failList memory-leak-test break } } puts " Ok" } # Run the malloc tests and the misuse test after memory leak detection. # Both tests leak memory. # catch {source $testdir/misuse.test} catch {source $testdir/malloc.test} really_finish_test |
Changes to test/lock.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this script is database locks. # | | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this script is database locks. # # $Id: lock.test,v 1.14 2002/05/10 13:14:08 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Create an alternative connection to the database # do_test lock-1.0 { sqlite db2 ./test.db set dummy {} } {} do_test lock-1.1 { execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name} } {} do_test lock-1.2 { execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name} db2 } {} |
︙ | ︙ |
Changes to test/main.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is exercising the code in main.c. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is exercising the code in main.c. # # $Id: main.test,v 1.10 2002/05/10 13:14:08 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Tests of the sqlite_complete() function. # do_test main-1.1 { |
︙ | ︙ | |||
76 77 78 79 80 81 82 | do_test main-2.0 { catch {db close} file delete -force test.db set fd [open test.db w] puts $fd hi! close $fd set v [catch {sqlite db test.db} msg] | | | 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | do_test main-2.0 { catch {db close} file delete -force test.db set fd [open test.db w] puts $fd hi! close $fd set v [catch {sqlite db test.db} msg] if {$v} {lappend v $msg} {lappend v {}} } {0 {}} # Here are some tests for tokenize.c. # do_test main-3.1 { catch {db close} foreach f [glob -nocomplain testdb/*] {file delete -force $f} |
︙ | ︙ |
Added test/misuse.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | # 2002 May 10 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. # # This file implements tests for the SQLITE_MISUSE detection logic. # This test file leaks memory and file descriptors. # # $Id: misuse.test,v 1.1 2002/05/10 13:14:08 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Make sure the test logic works # do_test misuse-1.1 { db close set ::DB [sqlite db test.db] execsql { CREATE TABLE t1(a,b); INSERT INTO t1 VALUES(1,2); } sqlite_exec_printf $::DB {SELECT * FROM t1} {} } {0 {a b 1 2}} do_test misuse-1.2 { sqlite_exec_printf $::DB {SELECT x_coalesce(NULL,a) AS 'xyz' FROM t1} {} } {1 {no such function: x_coalesce}} do_test misuse-1.3 { sqlite_create_function $::DB sqlite_exec_printf $::DB {SELECT x_coalesce(NULL,a) AS 'xyz' FROM t1} {} } {0 {xyz 1}} # Use the x_sqlite_exec() SQL function to simulate the effect of two # threads trying to use the same database at the same time. # do_test misuse-1.4 { sqlite_exec_printf $::DB { SELECT x_sqlite_exec('SELECT * FROM t1'); } {} } {21 {library routine called out of sequence}} do_test misuse-1.5 { sqlite_exec_printf $::DB {SELECT * FROM t1} {} } {21 {library routine called out of sequence}} do_test misuse-1.6 { catchsql { SELECT * FROM t1 } } {1 {library routine called out of sequence}} # Attempt to register a new SQL function while an sqlite_exec() is active. # do_test misuse-2.1 { db close set ::DB [sqlite db test.db] execsql { SELECT * FROM t1 } } {1 2} do_test misuse-2.2 { sqlite_exec_printf $::DB {SELECT * FROM t1} {} } {0 {a b 1 2}} do_test misuse-2.3 { set v [catch { db eval {SELECT * FROM t1} {} { sqlite_create_function $::DB } } msg] lappend v $msg } {1 {library routine called out of sequence}} do_test misuse-2.4 { sqlite_exec_printf $::DB {SELECT * FROM t1} {} } {21 {library routine called out of sequence}} do_test misuse-2.5 { catchsql { SELECT * FROM t1 } } {1 {library routine called out of sequence}} # Attempt to register a new SQL aggregate while an sqlite_exec() is active. # do_test misuse-3.1 { db close set ::DB [sqlite db test.db] execsql { SELECT * FROM t1 } } {1 2} do_test misuse-3.2 { sqlite_exec_printf $::DB {SELECT * FROM t1} {} } {0 {a b 1 2}} do_test misuse-3.3 { set v [catch { db eval {SELECT * FROM t1} {} { sqlite_create_aggregate $::DB } } msg] lappend v $msg } {1 {library routine called out of sequence}} do_test misuse-3.4 { sqlite_exec_printf $::DB {SELECT * FROM t1} {} } {21 {library routine called out of sequence}} do_test misuse-3.5 { catchsql { SELECT * FROM t1 } } {1 {library routine called out of sequence}} # Attempt to close the database from an sqlite_exec callback. # do_test misuse-4.1 { db close set ::DB [sqlite db test.db] execsql { SELECT * FROM t1 } } {1 2} do_test misuse-4.2 { sqlite_exec_printf $::DB {SELECT * FROM t1} {} } {0 {a b 1 2}} do_test misuse-4.3 { set v [catch { db eval {SELECT * FROM t1} {} { sqlite_close $::DB } } msg] lappend v $msg } {1 {library routine called out of sequence}} do_test misuse-4.4 { sqlite_exec_printf $::DB {SELECT * FROM t1} {} } {21 {library routine called out of sequence}} do_test misuse-4.5 { catchsql { SELECT * FROM t1 } } {1 {library routine called out of sequence}} # Attempt to use a database after it has been closed. # do_test misuse-5.1 { db close set ::DB [sqlite db test.db] execsql { SELECT * FROM t1 } } {1 2} do_test misuse-5.2 { sqlite_exec_printf $::DB {SELECT * FROM t1} {} } {0 {a b 1 2}} do_test misuse-5.3 { db close sqlite_exec_printf $::DB {SELECT * FROM t1} {} } {21 {library routine called out of sequence}} finish_test |
Changes to test/temptable.test.
︙ | ︙ | |||
8 9 10 11 12 13 14 | # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. # # This file implements tests for temporary tables and indices. # | | > | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. # # This file implements tests for temporary tables and indices. # # $Id: temptable.test,v 1.5 2002/05/10 13:14:08 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Create an alternative connection to the database # do_test temptable-1.0 { sqlite db2 ./test.db set dummy {} } {} # Create a permanent table. # do_test temptable-1.1 { execsql {CREATE TABLE t1(a,b,c);} execsql {INSERT INTO t1 VALUES(1,2,3);} |
︙ | ︙ |
Changes to www/c_interface.tcl.
1 2 3 | # # Run this Tcl script to generate the sqlite.html file. # | | | 1 2 3 4 5 6 7 8 9 10 11 | # # Run this Tcl script to generate the sqlite.html file. # set rcsid {$Id: c_interface.tcl,v 1.28 2002/05/10 13:14:08 drh Exp $} puts {<html> <head> <title>The C language interface to the SQLite library</title> </head> <body bgcolor=white> <h1 align=center> |
︙ | ︙ | |||
296 297 298 299 300 301 302 | an INTEGER PRIMARY KEY column is only allowed to store integer data. </p></dd> <dt>SQLITE_MISUSE</dt> <dd><p>This error might occur if one or more of the SQLite API routines is used incorrectly. Examples of incorrect usage include calling <b>sqlite_exec()</b> after the database has been closed using <b>sqlite_close()</b> or calling <b>sqlite_exec()</b> with the same | | < < | 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 | an INTEGER PRIMARY KEY column is only allowed to store integer data. </p></dd> <dt>SQLITE_MISUSE</dt> <dd><p>This error might occur if one or more of the SQLite API routines is used incorrectly. Examples of incorrect usage include calling <b>sqlite_exec()</b> after the database has been closed using <b>sqlite_close()</b> or calling <b>sqlite_exec()</b> with the same database pointer simultaneously from two separate threads. </p></dd> </dl> </blockquote> <h2>The Extended API</h2> <p>Only the three core routines shown above are required to use |
︙ | ︙ |
Changes to www/changes.tcl.
︙ | ︙ | |||
20 21 22 23 24 25 26 27 28 29 30 31 32 33 | } proc chng {date desc} { puts "<DT><B>$date</B></DT>" puts "<DD><P><UL>$desc</UL></P></DD>" } chng {2002 May 08 (2.4.11)} { <li>Bug fix: Column names in the result set were not being generated correctly for some (rather complex) VIEWs. This could cause a segfault under certain circumstances.</li> } | > > > > > | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | } proc chng {date desc} { puts "<DT><B>$date</B></DT>" puts "<DD><P><UL>$desc</UL></P></DD>" } chng {2002 May 09 (2.4.12)} { <li>Added logic to detect when the library API routines are called out of sequence.</li> } chng {2002 May 08 (2.4.11)} { <li>Bug fix: Column names in the result set were not being generated correctly for some (rather complex) VIEWs. This could cause a segfault under certain circumstances.</li> } |
︙ | ︙ |