Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Generalize the interrupt mechanism so that individual statements can be interrupted and so that codes other than just SQLITE_INTERRUPT can be returned as a consequence of an interrupt. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | generalize-interrupt |
Files: | files | file ages | folders |
SHA1: |
922bcbb42361b5a2ecb2eada7416c550 |
User & Date: | drh 2012-02-13 13:44:48.091 |
Context
2012-02-13
| ||
13:44 | Generalize the interrupt mechanism so that individual statements can be interrupted and so that codes other than just SQLITE_INTERRUPT can be returned as a consequence of an interrupt. (Closed-Leaf check-in: 922bcbb423 user: drh tags: generalize-interrupt) | |
10:00 | Changes to various test scripts so that veryquick.test runs with OMIT_COMPOUND_SELECT defined. (check-in: 76bb649ee2 user: dan tags: trunk) | |
Changes
Changes to src/main.c.
︙ | ︙ | |||
1046 1047 1048 1049 1050 1051 1052 | return SQLITE_OK; } /* ** Cause any pending operation to stop at its earliest opportunity. */ void sqlite3_interrupt(sqlite3 *db){ | > | | 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 | return SQLITE_OK; } /* ** Cause any pending operation to stop at its earliest opportunity. */ void sqlite3_interrupt(sqlite3 *db){ db->errcodeInterrupt = SQLITE_INTERRUPT; db->nInterrupt++; } /* ** This function is exactly the same as sqlite3_create_function(), except ** that it is designed to be called by internal code. The difference is ** that if a malloc() fails in sqlite3_create_function(), an error code |
︙ | ︙ |
Changes to src/prepare.c.
︙ | ︙ | |||
539 540 541 542 543 544 545 546 547 548 549 550 551 552 | /* Allocate the parsing context */ pParse = sqlite3StackAllocZero(db, sizeof(*pParse)); if( pParse==0 ){ rc = SQLITE_NOMEM; goto end_prepare; } pParse->pReprepare = pReprepare; assert( ppStmt && *ppStmt==0 ); assert( !db->mallocFailed ); assert( sqlite3_mutex_held(db->mutex) ); /* Check to verify that it is possible to get a read lock on all ** database schemas. The inability to get a read lock indicates that ** some other database connection is holding a write-lock, which in | > | 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 | /* Allocate the parsing context */ pParse = sqlite3StackAllocZero(db, sizeof(*pParse)); if( pParse==0 ){ rc = SQLITE_NOMEM; goto end_prepare; } pParse->pReprepare = pReprepare; pParse->nInterrupt = db->nInterrupt; assert( ppStmt && *ppStmt==0 ); assert( !db->mallocFailed ); assert( sqlite3_mutex_held(db->mutex) ); /* Check to verify that it is possible to get a read lock on all ** database schemas. The inability to get a read lock indicates that ** some other database connection is holding a write-lock, which in |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
850 851 852 853 854 855 856 | #endif void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*); void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*); void *pCollNeededArg; sqlite3_value *pErr; /* Most recent error message */ char *zErrMsg; /* Most recent error message (UTF-8 encoded) */ char *zErrMsg16; /* Most recent error message (UTF-16 encoded) */ | < | | < | 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 | #endif void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*); void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*); void *pCollNeededArg; sqlite3_value *pErr; /* Most recent error message */ char *zErrMsg; /* Most recent error message (UTF-8 encoded) */ char *zErrMsg16; /* Most recent error message (UTF-16 encoded) */ u32 nInterrupt; /* Increment on each sqlite3_interrupt() */ int errcodeInterrupt; /* Reason for the most recent interrupt */ Lookaside lookaside; /* Lookaside malloc configuration */ #ifndef SQLITE_OMIT_AUTHORIZATION int (*xAuth)(void*,int,const char*,const char*,const char*,const char*); /* Access authorization function */ void *pAuthArg; /* 1st argument to the access auth function */ #endif #ifndef SQLITE_OMIT_PROGRESS_CALLBACK |
︙ | ︙ | |||
2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 | ** list. */ struct Parse { sqlite3 *db; /* The main database structure */ char *zErrMsg; /* An error message */ Vdbe *pVdbe; /* An engine for executing database bytecode */ int rc; /* Return code from execution */ u8 colNamesSet; /* TRUE after OP_ColumnName has been issued to pVdbe */ u8 checkSchema; /* Causes schema cookie check after an error */ u8 nested; /* Number of nested calls to the parser/code generator */ u8 nTempReg; /* Number of temporary registers in aTempReg[] */ u8 nTempInUse; /* Number of aTempReg[] currently checked out */ u8 nColCache; /* Number of entries in aColCache[] */ u8 iColCache; /* Next entry in aColCache[] to replace */ | > | 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 | ** list. */ struct Parse { sqlite3 *db; /* The main database structure */ char *zErrMsg; /* An error message */ Vdbe *pVdbe; /* An engine for executing database bytecode */ int rc; /* Return code from execution */ u32 nInterrupt; /* Interrupts seen prior to this parse */ u8 colNamesSet; /* TRUE after OP_ColumnName has been issued to pVdbe */ u8 checkSchema; /* Causes schema cookie check after an error */ u8 nested; /* Number of nested calls to the parser/code generator */ u8 nTempReg; /* Number of temporary registers in aTempReg[] */ u8 nTempInUse; /* Number of aTempReg[] currently checked out */ u8 nColCache; /* Number of entries in aColCache[] */ u8 iColCache; /* Next entry in aColCache[] to replace */ |
︙ | ︙ |
Changes to src/tokenize.c.
︙ | ︙ | |||
392 393 394 395 396 397 398 | int lastTokenParsed = -1; /* type of the previous token */ u8 enableLookaside; /* Saved value of db->lookaside.bEnabled */ sqlite3 *db = pParse->db; /* The database connection */ int mxSqlLen; /* Max length of an SQL string */ mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; | < < < | 392 393 394 395 396 397 398 399 400 401 402 403 404 405 | int lastTokenParsed = -1; /* type of the previous token */ u8 enableLookaside; /* Saved value of db->lookaside.bEnabled */ sqlite3 *db = pParse->db; /* The database connection */ int mxSqlLen; /* Max length of an SQL string */ mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; pParse->rc = SQLITE_OK; pParse->zTail = zSql; i = 0; assert( pzErrMsg!=0 ); pEngine = sqlite3ParserAlloc((void*(*)(size_t))sqlite3Malloc); if( pEngine==0 ){ db->mallocFailed = 1; |
︙ | ︙ | |||
422 423 424 425 426 427 428 | i += pParse->sLastToken.n; if( i>mxSqlLen ){ pParse->rc = SQLITE_TOOBIG; break; } switch( tokenType ){ case TK_SPACE: { | | | 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 | i += pParse->sLastToken.n; if( i>mxSqlLen ){ pParse->rc = SQLITE_TOOBIG; break; } switch( tokenType ){ case TK_SPACE: { if( db->nInterrupt!=pParse->nInterrupt ){ sqlite3ErrorMsg(pParse, "interrupt"); pParse->rc = SQLITE_INTERRUPT; goto abort_parse; } break; } case TK_ILLEGAL: { |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
472 473 474 475 476 477 478 | ** ** This macro added to every instruction that does a jump in order to ** implement a loop. This test used to be on every single instruction, ** but that meant we more testing than we needed. By only testing the ** flag on jump instructions, we get a (small) speed improvement. */ #define CHECK_FOR_INTERRUPT \ | | | 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 | ** ** This macro added to every instruction that does a jump in order to ** implement a loop. This test used to be on every single instruction, ** but that meant we more testing than we needed. By only testing the ** flag on jump instructions, we get a (small) speed improvement. */ #define CHECK_FOR_INTERRUPT \ if( db->nInterrupt!=p->nInterrupt ) goto abort_due_to_interrupt; #ifndef NDEBUG /* ** This function is only called from within an assert() expression. It ** checks that the sqlite3.nTransaction variable is correctly set to ** the number of non-transaction savepoints currently in the |
︙ | ︙ | |||
6173 6174 6175 6176 6177 6178 6179 | } goto vdbe_error_halt; /* Jump to here if the sqlite3_interrupt() API sets the interrupt ** flag. */ abort_due_to_interrupt: | | | | 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182 6183 6184 6185 | } goto vdbe_error_halt; /* Jump to here if the sqlite3_interrupt() API sets the interrupt ** flag. */ abort_due_to_interrupt: assert( db->nInterrupt!=p->nInterrupt ); rc = db->errcodeInterrupt; p->rc = rc; sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3ErrStr(rc)); goto vdbe_error_halt; } |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
309 310 311 312 313 314 315 316 317 318 319 320 321 322 | Mem *aVar; /* Values for the OP_Variable opcode. */ char **azVar; /* Name of variables */ ynVar nVar; /* Number of entries in aVar[] */ ynVar nzVar; /* Number of entries in azVar[] */ u32 cacheCtr; /* VdbeCursor row cache generation counter */ int pc; /* The program counter */ int rc; /* Value to return */ u8 errorAction; /* Recovery action to do in case of an error */ u8 explain; /* True if EXPLAIN present on SQL command */ u8 changeCntOn; /* True to update the change-counter */ u8 expired; /* True if the VM needs to be recompiled */ u8 runOnlyOnce; /* Automatically expire on reset */ u8 minWriteFileFormat; /* Minimum file format for writable database files */ u8 inVtabMethod; /* See comments above */ | > | 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 | Mem *aVar; /* Values for the OP_Variable opcode. */ char **azVar; /* Name of variables */ ynVar nVar; /* Number of entries in aVar[] */ ynVar nzVar; /* Number of entries in azVar[] */ u32 cacheCtr; /* VdbeCursor row cache generation counter */ int pc; /* The program counter */ int rc; /* Value to return */ u32 nInterrupt; /* Interrupts prior to start of this statement */ u8 errorAction; /* Recovery action to do in case of an error */ u8 explain; /* True if EXPLAIN present on SQL command */ u8 changeCntOn; /* True to update the change-counter */ u8 expired; /* True if the VM needs to be recompiled */ u8 runOnlyOnce; /* Automatically expire on reset */ u8 minWriteFileFormat; /* Minimum file format for writable database files */ u8 inVtabMethod; /* See comments above */ |
︙ | ︙ |
Changes to src/vdbeapi.c.
︙ | ︙ | |||
380 381 382 383 384 385 386 | if( p->pc<=0 && p->expired ){ p->rc = SQLITE_SCHEMA; rc = SQLITE_ERROR; goto end_of_step; } if( p->pc<0 ){ | < < < < < < < < > | 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 | if( p->pc<=0 && p->expired ){ p->rc = SQLITE_SCHEMA; rc = SQLITE_ERROR; goto end_of_step; } if( p->pc<0 ){ assert( db->writeVdbeCnt>0 || db->autoCommit==0 || db->nDeferredCons==0 ); #ifndef SQLITE_OMIT_TRACE if( db->xProfile && !db->init.busy ){ sqlite3OsCurrentTimeInt64(db->pVfs, &p->startTime); } #endif db->activeVdbeCnt++; if( p->readOnly==0 ) db->writeVdbeCnt++; p->pc = 0; p->nInterrupt = db->nInterrupt; } #ifndef SQLITE_OMIT_EXPLAIN if( p->explain ){ rc = sqlite3VdbeList(p); }else #endif /* SQLITE_OMIT_EXPLAIN */ { |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
1189 1190 1191 1192 1193 1194 1195 | do{ i = p->pc++; }while( i<nRow && p->explain==2 && p->aOp[i].opcode!=OP_Explain ); if( i>=nRow ){ p->rc = SQLITE_OK; rc = SQLITE_DONE; | | | | 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 | do{ i = p->pc++; }while( i<nRow && p->explain==2 && p->aOp[i].opcode!=OP_Explain ); if( i>=nRow ){ p->rc = SQLITE_OK; rc = SQLITE_DONE; }else if( db->nInterrupt!=p->nInterrupt ){ p->rc = db->errcodeInterrupt; rc = SQLITE_ERROR; sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3ErrStr(p->rc)); }else{ char *z; Op *pOp; if( i<p->nOp ){ /* The output line number is small enough that we are still in the |
︙ | ︙ |