Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Changes to support recursive triggers. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
9b9c19211593d5ff7b39254a29c28456 |
User & Date: | dan 2009-08-28 18:53:45.000 |
Context
2009-08-30
| ||
11:42 | Fixes for new triggers scheme. (check-in: 9eb91efda5 user: dan tags: trunk) | |
2009-08-28
| ||
18:53 | Changes to support recursive triggers. (check-in: 9b9c192115 user: dan tags: trunk) | |
2009-08-24
| ||
01:35 | Run the column cache in a new context when generating code for trigger programs. Fix for ticket [efc02f9779]. (check-in: dee1b8eb40 user: drh tags: trunk) | |
Changes
Changes to src/alter.c.
︙ | ︙ | |||
192 193 194 195 196 197 198 | ** expression being built up in zWhere. */ if( pTab->pSchema!=pTempSchema ){ sqlite3 *db = pParse->db; for(pTrig=sqlite3TriggerList(pParse, pTab); pTrig; pTrig=pTrig->pNext){ if( pTrig->pSchema==pTempSchema ){ if( !zWhere ){ | | | | 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | ** expression being built up in zWhere. */ if( pTab->pSchema!=pTempSchema ){ sqlite3 *db = pParse->db; for(pTrig=sqlite3TriggerList(pParse, pTab); pTrig; pTrig=pTrig->pNext){ if( pTrig->pSchema==pTempSchema ){ if( !zWhere ){ zWhere = sqlite3MPrintf(db, "name=%Q", pTrig->zName); }else{ tmp = zWhere; zWhere = sqlite3MPrintf(db, "%s OR name=%Q", zWhere, pTrig->zName); sqlite3DbFree(db, tmp); } } } } return zWhere; } |
︙ | ︙ | |||
231 232 233 234 235 236 237 | assert( iDb>=0 ); #ifndef SQLITE_OMIT_TRIGGER /* Drop any table triggers from the internal schema. */ for(pTrig=sqlite3TriggerList(pParse, pTab); pTrig; pTrig=pTrig->pNext){ int iTrigDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema); assert( iTrigDb==iDb || iTrigDb==1 ); | | | 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 | assert( iDb>=0 ); #ifndef SQLITE_OMIT_TRIGGER /* Drop any table triggers from the internal schema. */ for(pTrig=sqlite3TriggerList(pParse, pTab); pTrig; pTrig=pTrig->pNext){ int iTrigDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema); assert( iTrigDb==iDb || iTrigDb==1 ); sqlite3VdbeAddOp4(v, OP_DropTrigger, iTrigDb, 0, 0, pTrig->zName, 0); } #endif /* Drop the table and index from the internal schema */ sqlite3VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0); /* Reload the table, index and permanent trigger schemas. */ |
︙ | ︙ |
Changes to src/build.c.
︙ | ︙ | |||
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | const char *zName /* Name of the table to be locked */ ){ int i; int nBytes; TableLock *p; assert( iDb>=0 ); for(i=0; i<pParse->nTableLock; i++){ p = &pParse->aTableLock[i]; if( p->iDb==iDb && p->iTab==iTab ){ p->isWriteLock = (p->isWriteLock || isWriteLock); return; } } nBytes = sizeof(TableLock) * (pParse->nTableLock+1); | > > > > | | 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 | const char *zName /* Name of the table to be locked */ ){ int i; int nBytes; TableLock *p; assert( iDb>=0 ); if( pParse->pRoot ){ pParse = pParse->pRoot; } for(i=0; i<pParse->nTableLock; i++){ p = &pParse->aTableLock[i]; if( p->iDb==iDb && p->iTab==iTab ){ p->isWriteLock = (p->isWriteLock || isWriteLock); return; } } nBytes = sizeof(TableLock) * (pParse->nTableLock+1); pParse->aTableLock = sqlite3DbReallocOrFree(pParse->db, pParse->aTableLock, nBytes); if( pParse->aTableLock ){ p = &pParse->aTableLock[pParse->nTableLock++]; p->iDb = iDb; p->iTab = iTab; p->isWriteLock = isWriteLock; p->zName = zName; |
︙ | ︙ | |||
190 191 192 193 194 195 196 | if( v && ALWAYS(pParse->nErr==0) && !db->mallocFailed ){ #ifdef SQLITE_DEBUG FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0; sqlite3VdbeTrace(v, trace); #endif assert( pParse->iCacheLevel==0 ); /* Disables and re-enables match */ sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem, | | | 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 | if( v && ALWAYS(pParse->nErr==0) && !db->mallocFailed ){ #ifdef SQLITE_DEBUG FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0; sqlite3VdbeTrace(v, trace); #endif assert( pParse->iCacheLevel==0 ); /* Disables and re-enables match */ sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem, pParse->nTab, pParse->nArg, pParse->explain); pParse->rc = SQLITE_DONE; pParse->colNamesSet = 0; }else if( pParse->rc==SQLITE_OK ){ pParse->rc = SQLITE_ERROR; } pParse->nTab = 0; pParse->nMem = 0; |
︙ | ︙ | |||
3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 | ** schema on any databases. This can be used to position the OP_Goto ** early in the code, before we know if any database tables will be used. */ void sqlite3CodeVerifySchema(Parse *pParse, int iDb){ sqlite3 *db; Vdbe *v; int mask; v = sqlite3GetVdbe(pParse); if( v==0 ) return; /* This only happens if there was a prior error */ db = pParse->db; | > | > > > | | | | > > > > | | | 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 | ** schema on any databases. This can be used to position the OP_Goto ** early in the code, before we know if any database tables will be used. */ void sqlite3CodeVerifySchema(Parse *pParse, int iDb){ sqlite3 *db; Vdbe *v; int mask; Parse *pRoot = pParse->pRoot; /* Root parse structure */ v = sqlite3GetVdbe(pParse); if( v==0 ) return; /* This only happens if there was a prior error */ db = pParse->db; if( pParse->cookieGoto==0 && pRoot==0 ){ pParse->cookieGoto = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0)+1; } if( iDb>=0 ){ if( pRoot==0 ){ pRoot = pParse; } assert( iDb<db->nDb ); assert( db->aDb[iDb].pBt!=0 || iDb==1 ); assert( iDb<SQLITE_MAX_ATTACHED+2 ); mask = 1<<iDb; if( (pRoot->cookieMask & mask)==0 ){ pRoot->cookieMask |= mask; pRoot->cookieValue[iDb] = db->aDb[iDb].pSchema->schema_cookie; if( !OMIT_TEMPDB && iDb==1 ){ sqlite3OpenTempDatabase(pRoot); } } } } /* ** Generate VDBE code that prepares for doing an operation that ** might change the database. ** ** This routine starts a new transaction if we are not already within ** a transaction. If we are already within a transaction, then a checkpoint ** is set if the setStatement parameter is true. A checkpoint should ** be set for operations that might fail (due to a constraint) part of ** the way through and which will need to undo some writes without having to ** rollback the whole transaction. For operations where all constraints ** can be checked before any changes are made to the database, it is never ** necessary to undo a write and the checkpoint should not be set. */ void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){ Parse *pRoot = pParse->pRoot; sqlite3CodeVerifySchema(pParse, iDb); if( pRoot==0 ){ pRoot = pParse; } pRoot->writeMask |= 1<<iDb; if( setStatement && pParse->nested==0 && pParse->pRoot==0 ){ /* Every place where this routine is called with setStatement!=0 has ** already successfully created a VDBE. */ assert( pParse->pVdbe ); sqlite3VdbeAddOp1(pParse->pVdbe, OP_Statement, iDb); } } |
︙ | ︙ |
Changes to src/delete.c.
︙ | ︙ | |||
224 225 226 227 228 229 230 | int end, addr = 0; /* A couple addresses of generated code */ int i; /* Loop counter */ WhereInfo *pWInfo; /* Information about the WHERE clause */ Index *pIdx; /* For looping over indices of the table */ int iCur; /* VDBE Cursor number for pTab */ sqlite3 *db; /* Main database structure */ AuthContext sContext; /* Authorization context */ | < < < < < < | 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 | int end, addr = 0; /* A couple addresses of generated code */ int i; /* Loop counter */ WhereInfo *pWInfo; /* Information about the WHERE clause */ Index *pIdx; /* For looping over indices of the table */ int iCur; /* VDBE Cursor number for pTab */ sqlite3 *db; /* Main database structure */ AuthContext sContext; /* Authorization context */ NameContext sNC; /* Name context to resolve expressions in */ int iDb; /* Database number */ int memCnt = -1; /* Memory cell used for change counting */ int rcauth; /* Value returned by authorization callback */ #ifndef SQLITE_OMIT_TRIGGER int isView; /* True if attempting to delete from a view */ Trigger *pTrigger; /* List of table triggers, if required */ #endif memset(&sContext, 0, sizeof(sContext)); db = pParse->db; if( pParse->nErr || db->mallocFailed ){ goto delete_from_cleanup; } assert( pTabList->nSrc==1 ); |
︙ | ︙ | |||
289 290 291 292 293 294 295 | rcauth = sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb); assert( rcauth==SQLITE_OK || rcauth==SQLITE_DENY || rcauth==SQLITE_IGNORE ); if( rcauth==SQLITE_DENY ){ goto delete_from_cleanup; } assert(!isView || pTrigger); | < < < < < < | 283 284 285 286 287 288 289 290 291 292 293 294 295 296 | rcauth = sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb); assert( rcauth==SQLITE_OK || rcauth==SQLITE_DENY || rcauth==SQLITE_IGNORE ); if( rcauth==SQLITE_DENY ){ goto delete_from_cleanup; } assert(!isView || pTrigger); /* Assign cursor number to the table and all its indices. */ assert( pTabList->nSrc==1 ); iCur = pTabList->a[0].iCursor = pParse->nTab++; for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ pParse->nTab++; } |
︙ | ︙ | |||
318 319 320 321 322 323 324 | v = sqlite3GetVdbe(pParse); if( v==0 ){ goto delete_from_cleanup; } if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); sqlite3BeginWriteOperation(pParse, (pTrigger?1:0), iDb); | < < < < < < < < < < < < < < < < < < | 306 307 308 309 310 311 312 313 314 315 316 317 318 319 | v = sqlite3GetVdbe(pParse); if( v==0 ){ goto delete_from_cleanup; } if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); sqlite3BeginWriteOperation(pParse, (pTrigger?1:0), iDb); /* If we are trying to delete from a view, realize that view into ** a ephemeral table. */ #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) if( isView ){ sqlite3MaterializeView(pParse, pTab, pWhere, iCur); } |
︙ | ︙ | |||
381 382 383 384 385 386 387 388 | } }else #endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */ /* The usual case: There is a WHERE clause so we have to scan through ** the table and pick which records to delete. */ { int iRowid = ++pParse->nMem; /* Used for storing rowid values. */ | > | < < < < < < | < > > > > < < < < < < < < < > > > > > | > > > | | | | | < | | | > | < | < | < | | < | | | | | 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 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 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 | } }else #endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */ /* The usual case: There is a WHERE clause so we have to scan through ** the table and pick which records to delete. */ { int iRowSet = ++pParse->nMem; /* Register for rowset of rows to delete */ int iRowid = ++pParse->nMem; /* Used for storing rowid values. */ int regOld = pParse->nMem + 1; /* Start of array for old.* (if triggers) */ int regRowid; /* Actual register containing rowids */ /* Collect rowids of every row to be deleted. */ sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet); pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0,WHERE_DUPLICATES_OK); if( pWInfo==0 ) goto delete_from_cleanup; regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid, 0); sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid); if( db->flags & SQLITE_CountRows ){ sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1); } sqlite3WhereEnd(pWInfo); /* Delete every item whose key was written to the list during the ** database scan. We have to delete items after the scan is complete ** because deleting an item can change the scan order. */ end = sqlite3VdbeMakeLabel(v); /* Unless this is a view, open cursors for the table we are ** deleting from and all its indices. If this is a view, then the ** only effect this statement has is to fire the INSTEAD OF ** triggers. */ if( !isView ){ sqlite3OpenTableAndIndices(pParse, pTab, iCur, OP_OpenWrite); } addr = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, end, iRowid); /* If there are triggers, populate an array of registers with the ** data required by the old.* references in the trigger bodies. */ if( pTrigger ){ u32 mask = 0; /* Mask of OLD.* columns in use */ u32 dummy = 0; /* Unused. Initialized to prevent valgrind error. */ pParse->nMem += pTab->nCol; /* Open the pseudo-table used to store OLD if there are triggers. */ sqlite3TriggerUses( pParse, pTrigger, TK_DELETE, 0, pTab, OE_Default, &mask, &dummy); /* If the record is no longer present in the table, jump to the ** next iteration of the loop through the contents of the fifo. */ sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, iRowid); /* Populate the OLD.* pseudo-table */ assert( regOld==iRowid+1 ); for(i=0; i<pTab->nCol; i++){ if( mask==0xffffffff || mask&(1<<i) ){ sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regOld+i); } } sqlite3CodeRowTrigger(pParse, pTrigger, TK_DELETE, 0, TRIGGER_BEFORE, pTab, -1, regOld, OE_Default, addr ); } if( !isView ){ /* Delete the row */ #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(pTab) ){ const char *pVTab = (const char *)sqlite3GetVTable(db, pTab); sqlite3VtabMakeWritable(pParse, pTab); sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iRowid, pVTab, P4_VTAB); }else #endif { sqlite3GenerateRowDelete(pParse, pTab, iCur, iRowid, pParse->nested==0); } } /* Code the AFTER triggers. This is a no-op if there are no triggers. */ sqlite3CodeRowTrigger(pParse, pTrigger, TK_DELETE, 0, TRIGGER_AFTER, pTab, -1, regOld, OE_Default, addr ); /* End of the delete loop */ sqlite3VdbeAddOp2(v, OP_Goto, 0, addr); sqlite3VdbeResolveLabel(v, end); /* Close the cursors open on the table and its indexes. */ if( !isView && !IsVirtual(pTab) ){ for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ sqlite3VdbeAddOp2(v, OP_Close, iCur + i, pIdx->tnum); } sqlite3VdbeAddOp1(v, OP_Close, iCur); } } /* Update the sqlite_sequence table by storing the content of the ** maximum rowid counter values recorded while inserting into ** autoincrement tables. */ if( pParse->nested==0 && pParse->pTriggerTab==0 ){ sqlite3AutoincrementEnd(pParse); } /* ** Return the number of rows that were deleted. If this routine is ** generating code because of a call to sqlite3NestedParse(), do not ** invoke the callback function. */ if( (db->flags&SQLITE_CountRows) && !pParse->nested && !pParse->pTriggerTab ){ sqlite3VdbeAddOp2(v, OP_ResultRow, memCnt, 1); sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", SQLITE_STATIC); } delete_from_cleanup: sqlite3AuthContextPop(&sContext); |
︙ | ︙ |
Changes to src/expr.c.
︙ | ︙ | |||
1517 1518 1519 1520 1521 1522 1523 | ** * The right-hand side is a correlated subquery ** * The right-hand side is an expression list containing variables ** * We are inside a trigger ** ** If all of the above are false, then we can run this code just once ** save the results, and reuse the same result on subsequent invocations. */ | | | 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 | ** * The right-hand side is a correlated subquery ** * The right-hand side is an expression list containing variables ** * We are inside a trigger ** ** If all of the above are false, then we can run this code just once ** save the results, and reuse the same result on subsequent invocations. */ if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->pTriggerTab ){ int mem = ++pParse->nMem; sqlite3VdbeAddOp1(v, OP_If, mem); testAddr = sqlite3VdbeAddOp2(v, OP_Integer, 1, mem); assert( testAddr>0 || pParse->db->mallocFailed ); } switch( pExpr->op ){ |
︙ | ︙ | |||
2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 | sqlite3ReleaseTempReg(pParse, r4); break; } case TK_UPLUS: { inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); break; } /* ** Form A: ** CASE x WHEN e1 THEN r1 WHEN e2 THEN r2 ... WHEN eN THEN rN ELSE y END ** ** Form B: ** CASE WHEN e1 THEN r1 WHEN e2 THEN r2 ... WHEN eN THEN rN ELSE y END | > > > > > > > > > > > | 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 | sqlite3ReleaseTempReg(pParse, r4); break; } case TK_UPLUS: { inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); break; } case TK_TRIGGER: { sqlite3VdbeAddOp3(v, OP_TriggerVal, pExpr->iColumn, target,pExpr->iTable); assert( pExpr->pTab ); VdbeComment((v, "%s.%s", (pExpr->iTable ? "new" : "old"), (pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName) )); break; } /* ** Form A: ** CASE x WHEN e1 THEN r1 WHEN e2 THEN r2 ... WHEN eN THEN rN ELSE y END ** ** Form B: ** CASE WHEN e1 THEN r1 WHEN e2 THEN r2 ... WHEN eN THEN rN ELSE y END |
︙ | ︙ | |||
2636 2637 2638 2639 2640 2641 2642 | assert( db->mallocFailed || pParse->nErr>0 || pParse->iCacheLevel==iCacheLevel ); sqlite3VdbeResolveLabel(v, endLabel); break; } #ifndef SQLITE_OMIT_TRIGGER case TK_RAISE: { | > | | | | | > | < < < | | < < < | 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 | assert( db->mallocFailed || pParse->nErr>0 || pParse->iCacheLevel==iCacheLevel ); sqlite3VdbeResolveLabel(v, endLabel); break; } #ifndef SQLITE_OMIT_TRIGGER case TK_RAISE: { int vrc; if( !pParse->pTriggerTab ){ sqlite3ErrorMsg(pParse, "RAISE() may only be used within a trigger-program"); return 0; } assert( pExpr->affinity==OE_Rollback || pExpr->affinity==OE_Abort || pExpr->affinity==OE_Fail || pExpr->affinity==OE_Ignore ); assert( !ExprHasProperty(pExpr, EP_IntValue) ); vrc = (pExpr->affinity==OE_Ignore ? SQLITE_OK : SQLITE_CONSTRAINT); sqlite3VdbeAddOp4(v, OP_Halt, vrc, pExpr->affinity, 0, pExpr->u.zToken,0); break; } #endif } sqlite3ReleaseTempReg(pParse, regFree1); sqlite3ReleaseTempReg(pParse, regFree2); return inReg; |
︙ | ︙ |
Changes to src/insert.c.
︙ | ︙ | |||
532 533 534 535 536 537 538 | /* Allocate a VDBE */ v = sqlite3GetVdbe(pParse); if( v==0 ) goto insert_cleanup; if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); sqlite3BeginWriteOperation(pParse, pSelect || pTrigger, iDb); | < < < < < | 532 533 534 535 536 537 538 539 540 541 542 543 544 545 | /* Allocate a VDBE */ v = sqlite3GetVdbe(pParse); if( v==0 ) goto insert_cleanup; if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); sqlite3BeginWriteOperation(pParse, pSelect || pTrigger, iDb); #ifndef SQLITE_OMIT_XFER_OPT /* If the statement is of the form ** ** INSERT INTO <table1> SELECT * FROM <table2>; ** ** Then special optimizations can be applied that make the transfer ** very fast and which reduce fragmentation of indices. |
︙ | ︙ | |||
740 741 742 743 744 745 746 | /* If there is no IDLIST term but the table has an integer primary ** key, the set the keyColumn variable to the primary key column index ** in the original table definition. */ if( pColumn==0 && nColumn>0 ){ keyColumn = pTab->iPKey; } | < < < < < < | 735 736 737 738 739 740 741 742 743 744 745 746 747 748 | /* If there is no IDLIST term but the table has an integer primary ** key, the set the keyColumn variable to the primary key column index ** in the original table definition. */ if( pColumn==0 && nColumn>0 ){ keyColumn = pTab->iPKey; } /* Initialize the count of rows to be inserted */ if( db->flags & SQLITE_CountRows ){ regRowCount = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount); } |
︙ | ︙ | |||
814 815 816 817 818 819 820 | /* Run the BEFORE and INSTEAD OF triggers, if there are any */ endOfLoop = sqlite3VdbeMakeLabel(v); if( tmask & TRIGGER_BEFORE ){ int regTrigRowid; int regCols; | < | 803 804 805 806 807 808 809 810 811 812 813 814 815 816 | /* Run the BEFORE and INSTEAD OF triggers, if there are any */ endOfLoop = sqlite3VdbeMakeLabel(v); if( tmask & TRIGGER_BEFORE ){ int regTrigRowid; int regCols; /* build the NEW.* reference row. Note that if there is an INTEGER ** PRIMARY KEY into which a NULL is being inserted, that NULL will be ** translated into a unique ID for the row. But on a BEFORE trigger, ** we do not know what the unique ID will be (because the insert has ** not happened yet) so we substitute a rowid of -1 */ |
︙ | ︙ | |||
842 843 844 845 846 847 848 | sqlite3VdbeJumpHere(v, j1); sqlite3VdbeAddOp1(v, OP_MustBeInt, regTrigRowid); } /* Cannot have triggers on a virtual table. If it were possible, ** this block would have to account for hidden column. */ | | | 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 | sqlite3VdbeJumpHere(v, j1); sqlite3VdbeAddOp1(v, OP_MustBeInt, regTrigRowid); } /* Cannot have triggers on a virtual table. If it were possible, ** this block would have to account for hidden column. */ assert( !IsVirtual(pTab) ); /* Create the new column data */ regCols = sqlite3GetTempRange(pParse, pTab->nCol); for(i=0; i<pTab->nCol; i++){ if( pColumn==0 ){ j = i; |
︙ | ︙ | |||
864 865 866 867 868 869 870 | }else if( useTempTable ){ sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, regCols+i); }else{ assert( pSelect==0 ); /* Otherwise useTempTable is true */ sqlite3ExprCodeAndCache(pParse, pList->a[j].pExpr, regCols+i); } } | < < > < < < < | | < | > > | 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 | }else if( useTempTable ){ sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, regCols+i); }else{ assert( pSelect==0 ); /* Otherwise useTempTable is true */ sqlite3ExprCodeAndCache(pParse, pList->a[j].pExpr, regCols+i); } } /* If this is an INSERT on a view with an INSTEAD OF INSERT trigger, ** do not attempt any conversions before assembling the record. ** If this is a real table, attempt conversions as required by the ** table column affinities. */ if( !isView ){ sqlite3VdbeAddOp2(v, OP_Affinity, regCols, pTab->nCol); sqlite3TableAffinityStr(v, pTab); } /* Fire BEFORE or INSTEAD OF triggers */ sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_BEFORE, pTab, regCols, -1, onError, endOfLoop); sqlite3ReleaseTempReg(pParse, regTrigRowid); sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol); } /* Push the record number for the new entry onto the stack. The ** record number is a randomly generate integer created by NewRowid ** except when the table has an INTEGER PRIMARY KEY column, in which ** case the record number is the same as that column. */ |
︙ | ︙ | |||
1005 1006 1007 1008 1009 1010 1011 | */ if( (db->flags & SQLITE_CountRows)!=0 ){ sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1); } if( pTrigger ){ /* Code AFTER triggers */ | | | < < | 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 | */ if( (db->flags & SQLITE_CountRows)!=0 ){ sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1); } if( pTrigger ){ /* Code AFTER triggers */ sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_AFTER, pTab, regData, -1, onError, endOfLoop); } /* The bottom of the main insertion loop, if the data source ** is a SELECT statement. */ sqlite3VdbeResolveLabel(v, endOfLoop); if( useTempTable ){ |
︙ | ︙ | |||
1037 1038 1039 1040 1041 1042 1043 | } insert_end: /* Update the sqlite_sequence table by storing the content of the ** maximum rowid counter values recorded while inserting into ** autoincrement tables. */ | | | | 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 | } insert_end: /* Update the sqlite_sequence table by storing the content of the ** maximum rowid counter values recorded while inserting into ** autoincrement tables. */ if( pParse->nested==0 && pParse->pTriggerTab==0 ){ sqlite3AutoincrementEnd(pParse); } /* ** Return the number of rows inserted. If this routine is ** generating code because of a call to sqlite3NestedParse(), do not ** invoke the callback function. */ if( (db->flags&SQLITE_CountRows) && !pParse->nested && !pParse->pTriggerTab ){ sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1); sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", SQLITE_STATIC); } insert_cleanup: sqlite3SrcListDelete(db, pTabList); |
︙ | ︙ | |||
1419 1420 1421 1422 1423 1424 1425 | } } regData = regRowid + 1; regRec = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec); sqlite3TableAffinityStr(v, pTab); sqlite3ExprCacheAffinityChange(pParse, regData, pTab->nCol); | < < < < < | 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 | } } regData = regRowid + 1; regRec = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec); sqlite3TableAffinityStr(v, pTab); sqlite3ExprCacheAffinityChange(pParse, regData, pTab->nCol); if( pParse->nested ){ pik_flags = 0; }else{ pik_flags = OPFLAG_NCHANGE; pik_flags |= (isUpdate?OPFLAG_ISUPDATE:OPFLAG_LASTROWID); } if( appendBias ){ |
︙ | ︙ |
Changes to src/prepare.c.
︙ | ︙ | |||
671 672 673 674 675 676 677 678 679 680 681 682 683 684 | if( zErrMsg ){ sqlite3Error(db, rc, "%s", zErrMsg); sqlite3DbFree(db, zErrMsg); }else{ sqlite3Error(db, rc, 0); } end_prepare: sqlite3StackFree(db, pParse); rc = sqlite3ApiExit(db, rc); assert( (rc&db->errMask)==rc ); return rc; | > > > > > > > | 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 | if( zErrMsg ){ sqlite3Error(db, rc, "%s", zErrMsg); sqlite3DbFree(db, zErrMsg); }else{ sqlite3Error(db, rc, 0); } while( pParse->pCodedTrigger ){ CodedTrigger *pT = pParse->pCodedTrigger; pParse->pCodedTrigger = pT->pNext; sqlite3VdbeProgramDelete(db, pT->pProgram, 0); sqlite3DbFree(db, pT); } end_prepare: sqlite3StackFree(db, pParse); rc = sqlite3ApiExit(db, rc); assert( (rc&db->errMask)==rc ); return rc; |
︙ | ︙ |
Changes to src/resolve.c.
︙ | ︙ | |||
133 134 135 136 137 138 139 140 141 142 143 144 145 146 | int cnt = 0; /* Number of matching column names */ int cntTab = 0; /* Number of matching table names */ sqlite3 *db = pParse->db; /* The database connection */ struct SrcList_item *pItem; /* Use for looping over pSrcList items */ struct SrcList_item *pMatch = 0; /* The matching pSrcList item */ NameContext *pTopNC = pNC; /* First namecontext in the list */ Schema *pSchema = 0; /* Schema of the expression */ assert( pNC ); /* the name context cannot be NULL. */ assert( zCol ); /* The Z in X.Y.Z cannot be NULL */ assert( ~ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) ); /* Initialize the node to no-match */ pExpr->iTable = -1; | > | 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | int cnt = 0; /* Number of matching column names */ int cntTab = 0; /* Number of matching table names */ sqlite3 *db = pParse->db; /* The database connection */ struct SrcList_item *pItem; /* Use for looping over pSrcList items */ struct SrcList_item *pMatch = 0; /* The matching pSrcList item */ NameContext *pTopNC = pNC; /* First namecontext in the list */ Schema *pSchema = 0; /* Schema of the expression */ int isTrigger = 0; /* True if a new.* or old.* reference. */ assert( pNC ); /* the name context cannot be NULL. */ assert( zCol ); /* The Z in X.Y.Z cannot be NULL */ assert( ~ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) ); /* Initialize the node to no-match */ pExpr->iTable = -1; |
︙ | ︙ | |||
218 219 220 221 222 223 224 | } } #ifndef SQLITE_OMIT_TRIGGER /* If we have not already resolved the name, then maybe ** it is a new.* or old.* trigger argument reference */ | | < | | < | | | | < | | < < > | > < | 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 | } } #ifndef SQLITE_OMIT_TRIGGER /* If we have not already resolved the name, then maybe ** it is a new.* or old.* trigger argument reference */ if( zDb==0 && zTab!=0 && cnt==0 && pParse->pTriggerTab!=0 ){ Table *pTab = 0; u32 *piColMask = 0; if( pParse->triggerOp!=TK_DELETE && sqlite3StrICmp("new",zTab) == 0 ){ pExpr->iTable = 1; pTab = pParse->pTriggerTab; piColMask = &(pParse->newmask); }else if( pParse->triggerOp!=TK_INSERT && sqlite3StrICmp("old",zTab)==0 ){ pExpr->iTable = 0; pTab = pParse->pTriggerTab; piColMask = &(pParse->oldmask); } if( pTab ){ int iCol; pSchema = pTab->pSchema; cntTab++; isTrigger = 1; for(iCol=0; iCol<pTab->nCol; iCol++){ Column *pCol = &pTab->aCol[iCol]; if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ cnt++; pExpr->iColumn = iCol==pTab->iPKey ? -1 : (i16)iCol; testcase( iCol==31 ); testcase( iCol==32 ); if( iCol>=32 ){ *piColMask = 0xffffffff; }else{ *piColMask |= ((u32)1)<<iCol; } |
︙ | ︙ | |||
378 379 380 381 382 383 384 385 386 387 388 389 390 391 | ** the point where the name matched. */ for(;;){ assert( pTopNC!=0 ); pTopNC->nRef++; if( pTopNC==pNC ) break; pTopNC = pTopNC->pNext; } return WRC_Prune; } else { return WRC_Abort; } } /* | > > > > | 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 | ** the point where the name matched. */ for(;;){ assert( pTopNC!=0 ); pTopNC->nRef++; if( pTopNC==pNC ) break; pTopNC = pTopNC->pNext; } if( isTrigger ){ pExpr->pTab = pParse->pTriggerTab; pExpr->op = TK_TRIGGER; } return WRC_Prune; } else { return WRC_Abort; } } /* |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
2729 2730 2731 2732 2733 2734 2735 2736 | ** complete, since there may still exist Expr.pTab entries that ** refer to the subquery even after flattening. Ticket #3346. ** ** pSubitem->pTab is always non-NULL by test restrictions and tests above. */ if( ALWAYS(pSubitem->pTab!=0) ){ Table *pTabToDel = pSubitem->pTab; if( pTabToDel->nRef==1 ){ | > | | | 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 | ** complete, since there may still exist Expr.pTab entries that ** refer to the subquery even after flattening. Ticket #3346. ** ** pSubitem->pTab is always non-NULL by test restrictions and tests above. */ if( ALWAYS(pSubitem->pTab!=0) ){ Table *pTabToDel = pSubitem->pTab; Parse *pRoot = (pParse->pRoot ? pParse->pRoot : pParse); if( pTabToDel->nRef==1 ){ pTabToDel->pNextZombie = pRoot->pZombieTab; pRoot->pZombieTab = pTabToDel; }else{ pTabToDel->nRef--; } pSubitem->pTab = 0; } /* The following loop runs once for each term in a compound-subquery |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 | /* ** Size of the column cache */ #ifndef SQLITE_N_COLCACHE # define SQLITE_N_COLCACHE 10 #endif /* ** An SQL parser context. A copy of this structure is passed through ** the parser and down into all the parser action routine in order to ** carry around information that is global to the entire parse. ** ** The structure is divided into two parts. When the parser and code ** generate call themselves recursively, the first part of the structure | > > > > > > > > > > | 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 | /* ** Size of the column cache */ #ifndef SQLITE_N_COLCACHE # define SQLITE_N_COLCACHE 10 #endif typedef struct CodedTrigger CodedTrigger; struct CodedTrigger { SubProgram *pProgram; Trigger *pTrigger; u32 oldmask; /* Mask of old.* columns accessed */ u32 newmask; /* Mask of new.* columns accessed */ int orconf; /* Default ON CONFLICT policy */ CodedTrigger *pNext; }; /* ** An SQL parser context. A copy of this structure is passed through ** the parser and down into all the parser action routine in order to ** carry around information that is global to the entire parse. ** ** The structure is divided into two parts. When the parser and code ** generate call themselves recursively, the first part of the structure |
︙ | ︙ | |||
2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 | int nTableLock; /* Number of locks in aTableLock */ TableLock *aTableLock; /* Required table locks for shared-cache mode */ #endif int regRowid; /* Register holding rowid of CREATE TABLE entry */ int regRoot; /* Register holding root page number for new objects */ AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */ /* Above is constant between recursions. Below is reset before and after ** each recursion */ int nVar; /* Number of '?' variables seen in the SQL so far */ int nVarExpr; /* Number of used slots in apVarExpr[] */ int nVarExprAlloc; /* Number of allocated slots in apVarExpr[] */ Expr **apVarExpr; /* Pointers to :aaa and $aaaa wildcard expressions */ int nAlias; /* Number of aliased result set columns */ int nAliasAlloc; /* Number of allocated slots for aAlias[] */ int *aAlias; /* Register used to hold aliased result */ u8 explain; /* True if the EXPLAIN flag is found on the query */ Token sNameToken; /* Token with unqualified schema object name */ Token sLastToken; /* The last token parsed */ const char *zTail; /* All SQL text past the last semicolon parsed */ Table *pNewTable; /* A table being constructed by CREATE TABLE */ Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */ TriggerStack *trigStack; /* Trigger actions being coded */ const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */ #ifndef SQLITE_OMIT_VIRTUALTABLE Token sArg; /* Complete text of a module argument */ u8 declareVtab; /* True if inside sqlite3_declare_vtab() */ int nVtabLock; /* Number of virtual tables to lock */ Table **apVtabLock; /* Pointer to virtual tables needing locking */ #endif int nHeight; /* Expression tree height of current sub-select */ Table *pZombieTab; /* List of Table objects to delete after code gen */ }; #ifdef SQLITE_OMIT_VIRTUALTABLE #define IN_DECLARE_VTAB 0 #else #define IN_DECLARE_VTAB (pParse->declareVtab) #endif | > > > > > > > > > > > > | 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 | int nTableLock; /* Number of locks in aTableLock */ TableLock *aTableLock; /* Required table locks for shared-cache mode */ #endif int regRowid; /* Register holding rowid of CREATE TABLE entry */ int regRoot; /* Register holding root page number for new objects */ AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */ /* Information used while coding trigger programs. */ Parse *pRoot; /* Root Parse structure */ Table *pTriggerTab; /* Table triggers are being coded for */ u32 oldmask; u32 newmask; int triggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */ int nArg; int orconf; /* Default ON CONFLICT policy for trigger steps */ /* Above is constant between recursions. Below is reset before and after ** each recursion */ int nVar; /* Number of '?' variables seen in the SQL so far */ int nVarExpr; /* Number of used slots in apVarExpr[] */ int nVarExprAlloc; /* Number of allocated slots in apVarExpr[] */ Expr **apVarExpr; /* Pointers to :aaa and $aaaa wildcard expressions */ int nAlias; /* Number of aliased result set columns */ int nAliasAlloc; /* Number of allocated slots for aAlias[] */ int *aAlias; /* Register used to hold aliased result */ u8 explain; /* True if the EXPLAIN flag is found on the query */ Token sNameToken; /* Token with unqualified schema object name */ Token sLastToken; /* The last token parsed */ const char *zTail; /* All SQL text past the last semicolon parsed */ Table *pNewTable; /* A table being constructed by CREATE TABLE */ Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */ #if 0 TriggerStack *trigStack; /* Trigger actions being coded */ #endif const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */ #ifndef SQLITE_OMIT_VIRTUALTABLE Token sArg; /* Complete text of a module argument */ u8 declareVtab; /* True if inside sqlite3_declare_vtab() */ int nVtabLock; /* Number of virtual tables to lock */ Table **apVtabLock; /* Pointer to virtual tables needing locking */ #endif int nHeight; /* Expression tree height of current sub-select */ Table *pZombieTab; /* List of Table objects to delete after code gen */ CodedTrigger *pCodedTrigger; /* Linked list of coded triggers */ }; #ifdef SQLITE_OMIT_VIRTUALTABLE #define IN_DECLARE_VTAB 0 #else #define IN_DECLARE_VTAB (pParse->declareVtab) #endif |
︙ | ︙ | |||
2140 2141 2142 2143 2144 2145 2146 | * linked list is stored as the "pTrigger" member of the associated * struct Table. * * The "step_list" member points to the first element of a linked list * containing the SQL statements specified as the trigger program. */ struct Trigger { | | | 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 | * linked list is stored as the "pTrigger" member of the associated * struct Table. * * The "step_list" member points to the first element of a linked list * containing the SQL statements specified as the trigger program. */ struct Trigger { char *zName; /* The name of the trigger */ char *table; /* The table or view to which the trigger applies */ u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT */ u8 tr_tm; /* One of TRIGGER_BEFORE, TRIGGER_AFTER */ Expr *pWhen; /* The WHEN clause of the expression (may be NULL) */ IdList *pColumns; /* If this is an UPDATE OF <column-list> trigger, the <column-list> is stored here */ Schema *pSchema; /* Schema containing the trigger */ |
︙ | ︙ | |||
2683 2684 2685 2686 2687 2688 2689 | void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*, Expr*,int, int); void sqlite3FinishTrigger(Parse*, TriggerStep*, Token*); void sqlite3DropTrigger(Parse*, SrcList*, int); void sqlite3DropTriggerPtr(Parse*, Trigger*); Trigger *sqlite3TriggersExist(Parse *, Table*, int, ExprList*, int *pMask); Trigger *sqlite3TriggerList(Parse *, Table *); | | | > | | 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 | void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*, Expr*,int, int); void sqlite3FinishTrigger(Parse*, TriggerStep*, Token*); void sqlite3DropTrigger(Parse*, SrcList*, int); void sqlite3DropTriggerPtr(Parse*, Trigger*); Trigger *sqlite3TriggersExist(Parse *, Table*, int, ExprList*, int *pMask); Trigger *sqlite3TriggerList(Parse *, Table *); void sqlite3CodeRowTrigger(Parse*, Trigger *, int, ExprList*, int, Table *, int, int, int, int); void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*); void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*); TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*); TriggerStep *sqlite3TriggerInsertStep(sqlite3*,Token*, IdList*, ExprList*,Select*,u8); TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList*, Expr*, u8); TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*); void sqlite3DeleteTrigger(sqlite3*, Trigger*); void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*); void sqlite3TriggerUses(Parse*,Trigger*,int,ExprList*,Table*,int,u32*,u32*); #else # define sqlite3TriggersExist(B,C,D,E,F) 0 # define sqlite3DeleteTrigger(A,B) # define sqlite3DropTriggerPtr(A,B) # define sqlite3UnlinkAndDeleteTrigger(A,B,C) # define sqlite3CodeRowTrigger(A,B,C,D,E,F,G,H,I,J) # define sqlite3TriggerList(X, Y) 0 #endif int sqlite3JoinType(Parse*, Token*, Token*, Token*); void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int); void sqlite3DeferForeignKey(Parse*, int); #ifndef SQLITE_OMIT_AUTHORIZATION |
︙ | ︙ |
Changes to src/trigger.c.
︙ | ︙ | |||
215 216 217 218 219 220 221 | if (tr_tm == TK_INSTEAD){ tr_tm = TK_BEFORE; } /* Build the Trigger object */ pTrigger = (Trigger*)sqlite3DbMallocZero(db, sizeof(Trigger)); if( pTrigger==0 ) goto trigger_cleanup; | | | 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 | if (tr_tm == TK_INSTEAD){ tr_tm = TK_BEFORE; } /* Build the Trigger object */ pTrigger = (Trigger*)sqlite3DbMallocZero(db, sizeof(Trigger)); if( pTrigger==0 ) goto trigger_cleanup; pTrigger->zName = zName; zName = 0; pTrigger->table = sqlite3DbStrDup(db, pTableName->a[0].zName); pTrigger->pSchema = db->aDb[iDb].pSchema; pTrigger->pTabSchema = pTab->pSchema; pTrigger->op = (u8)op; pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER; pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE); |
︙ | ︙ | |||
258 259 260 261 262 263 264 | DbFixer sFix; int iDb; /* Database containing the trigger */ Token nameToken; /* Trigger name for error reporting */ pTrig = pParse->pNewTrigger; pParse->pNewTrigger = 0; if( NEVER(pParse->nErr) || !pTrig ) goto triggerfinish_cleanup; | | | | 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 | DbFixer sFix; int iDb; /* Database containing the trigger */ Token nameToken; /* Trigger name for error reporting */ pTrig = pParse->pNewTrigger; pParse->pNewTrigger = 0; if( NEVER(pParse->nErr) || !pTrig ) goto triggerfinish_cleanup; zName = pTrig->zName; iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema); pTrig->step_list = pStepList; while( pStepList ){ pStepList->pTrig = pTrig; pStepList = pStepList->pNext; } nameToken.z = pTrig->zName; nameToken.n = sqlite3Strlen30(nameToken.z); if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken) && sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){ goto triggerfinish_cleanup; } /* if we are not initializing, and this trigger is not on a TEMP table, |
︙ | ︙ | |||
447 448 449 450 451 452 453 | /* ** Recursively delete a Trigger structure */ void sqlite3DeleteTrigger(sqlite3 *db, Trigger *pTrigger){ if( pTrigger==0 ) return; sqlite3DeleteTriggerStep(db, pTrigger->step_list); | | | 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 | /* ** Recursively delete a Trigger structure */ void sqlite3DeleteTrigger(sqlite3 *db, Trigger *pTrigger){ if( pTrigger==0 ) return; sqlite3DeleteTriggerStep(db, pTrigger->step_list); sqlite3DbFree(db, pTrigger->zName); sqlite3DbFree(db, pTrigger->table); sqlite3ExprDelete(db, pTrigger->pWhen); sqlite3IdListDelete(db, pTrigger->pColumns); sqlite3DbFree(db, pTrigger); } /* |
︙ | ︙ | |||
554 555 556 557 558 559 560 | { OP_Delete, 0, 0, 0}, { OP_Next, 0, ADDR(1), 0}, /* 8 */ }; sqlite3BeginWriteOperation(pParse, 0, iDb); sqlite3OpenMasterTable(pParse, iDb); base = sqlite3VdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger); | | | | 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 | { OP_Delete, 0, 0, 0}, { OP_Next, 0, ADDR(1), 0}, /* 8 */ }; sqlite3BeginWriteOperation(pParse, 0, iDb); sqlite3OpenMasterTable(pParse, iDb); base = sqlite3VdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger); sqlite3VdbeChangeP4(v, base+1, pTrigger->zName, 0); sqlite3VdbeChangeP4(v, base+4, "trigger", P4_STATIC); sqlite3ChangeCookie(pParse, iDb); sqlite3VdbeAddOp2(v, OP_Close, 0, 0); sqlite3VdbeAddOp4(v, OP_DropTrigger, iDb, 0, 0, pTrigger->zName, 0); if( pParse->nMem<3 ){ pParse->nMem = 3; } } } /* |
︙ | ︙ | |||
670 671 672 673 674 675 676 | ** trigger. */ static int codeTriggerProgram( Parse *pParse, /* The parser context */ TriggerStep *pStepList, /* List of statements inside the trigger body */ int orconfin /* Conflict algorithm. (OE_Abort, etc) */ ){ | | < > | | < | | > > > > > > > > > > > > | | | < < < | > | | < > > < < < | > | | | < > > < < < | > | < > | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > | > > > > > > > > > > > > > > > > > > | > > | > > > > > > > > > > > > > > > > > > | | | > > > > | > > > > > > > > > | > > > > > > > | > > > | | > > > > > > > > > | > > > > > > | > > > > > > > > > | | 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 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 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 | ** trigger. */ static int codeTriggerProgram( Parse *pParse, /* The parser context */ TriggerStep *pStepList, /* List of statements inside the trigger body */ int orconfin /* Conflict algorithm. (OE_Abort, etc) */ ){ TriggerStep * pStep = pStepList; Vdbe *v = pParse->pVdbe; sqlite3 *db = pParse->db; assert( pParse->pRoot ); assert( pStep!=0 ); assert( v!=0 ); /* sqlite3VdbeAddOp2(v, OP_ContextPush, 0, 0); */ while( pStep ){ /* Figure out the ON CONFLICT policy that will be used for this step ** of the trigger program. If the statement that caused this trigger ** to fire had an explicit ON CONFLICT, then use it. Otherwise, use ** the ON CONFLICT policy that was specified as part of the trigger ** step statement. Example: ** ** CREATE TRIGGER AFTER INSERT ON t1 BEGIN; ** INSERT OR REPLACE INTO t2 VALUES(new.a, new.b); ** END; ** ** INSERT INTO t1 ... ; -- insert into t2 uses REPLACE policy ** INSERT OR IGNORE INTO t1 ... ; -- insert into t2 uses IGNORE policy */ pParse->orconf = (orconfin==OE_Default)?pStep->orconf:orconfin; switch( pStep->op ){ case TK_UPDATE: { sqlite3Update(pParse, targetSrcList(pParse, pStep), sqlite3ExprListDup(db, pStep->pExprList, 0), sqlite3ExprDup(db, pStep->pWhere, 0), pParse->orconf ); break; } case TK_INSERT: { sqlite3Insert(pParse, targetSrcList(pParse, pStep), sqlite3ExprListDup(db, pStep->pExprList, 0), sqlite3SelectDup(db, pStep->pSelect, 0), sqlite3IdListDup(db, pStep->pIdList), pParse->orconf ); break; } case TK_DELETE: { sqlite3DeleteFrom(pParse, targetSrcList(pParse, pStep), sqlite3ExprDup(db, pStep->pWhere, 0) ); break; } default: assert( pStep->op==TK_SELECT ); { SelectDest sDest; Select *pSelect = sqlite3SelectDup(db, pStep->pSelect, 0); sqlite3SelectDestInit(&sDest, SRT_Discard, 0); sqlite3Select(pParse, pSelect, &sDest); sqlite3SelectDelete(db, pSelect); break; } } pStep = pStep->pNext; } /* sqlite3VdbeAddOp2(v, OP_ContextPop, 0, 0); */ return 0; } #ifdef SQLITE_DEBUG /* ** This function is used to add VdbeComment() annotations to a VDBE ** program. It is not used in production code, only for debugging. */ static const char *onErrorText(int onError){ switch( onError ){ case OE_Abort: return "abort"; case OE_Rollback: return "rollback"; case OE_Fail: return "fail"; case OE_Replace: return "replace"; case OE_Ignore: return "ignore"; case OE_Default: return "default"; } return "n/a"; } #endif /* ** Parse context structure pFrom has just been used to create a sub-vdbe ** (trigger program). If an error has occurred, transfer error information ** from pFrom to pTo. */ static void transferParseError(Parse *pTo, Parse *pFrom){ assert( pFrom->zErrMsg==0 || pFrom->nErr ); assert( pTo->zErrMsg==0 || pTo->nErr ); if( pTo->nErr==0 ){ pTo->zErrMsg = pFrom->zErrMsg; pTo->nErr = pFrom->nErr; }else{ sqlite3DbFree(pFrom->db, pFrom->zErrMsg); } } static CodedTrigger *codeRowTrigger( Parse *pRoot, /* Root parse context */ Parse *pParse, /* Current parse context */ Trigger *pTrigger, /* Trigger to code */ int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */ Table *pTab, /* The table to code triggers from */ int orconf ){ sqlite3 *db = pParse->db; CodedTrigger *pC; Expr *pWhen = 0; /* Duplicate of trigger WHEN expression */ Vdbe *v; /* Temporary VM */ AuthContext sContext; /* Auth context for sub-vdbe */ NameContext sNC; /* Name context for sub-vdbe */ SubProgram *pProgram = 0; /* Sub-vdbe for trigger program */ Parse *pSubParse; /* Parse context for sub-vdbe */ int iEndTrigger = 0; /* Label to jump to if WHEN is false */ pC = sqlite3DbMallocZero(db, sizeof(CodedTrigger)); if( !pC ) return 0; pC->pNext = pRoot->pCodedTrigger; pRoot->pCodedTrigger = pC; pC->pProgram = pProgram = sqlite3DbMallocZero(db, sizeof(SubProgram)); if( !pProgram ) return 0; pProgram->nRef = 1; pSubParse = sqlite3StackAllocZero(db, sizeof(Parse)); if( !pSubParse ) return 0; pC->pProgram = pProgram; pC->pTrigger = pTrigger; pC->orconf = orconf; memset(&sNC, 0, sizeof(sNC)); sNC.pParse = pSubParse; pSubParse->db = db; pSubParse->pTriggerTab = pTab; pSubParse->pRoot = pRoot; /* Push an entry on to the auth context stack */ sqlite3AuthContextPush(pParse, &sContext, pTrigger->name); v = sqlite3GetVdbe(pSubParse); if( v ){ VdbeComment((v, "Trigger: %s (%s %s%s%s ON %s) (%s)", pTrigger->zName, (pTrigger->tr_tm==TRIGGER_BEFORE ? "BEFORE" : "AFTER"), (op==TK_UPDATE ? "UPDATE" : ""), (op==TK_INSERT ? "INSERT" : ""), (op==TK_DELETE ? "DELETE" : ""), pTab->zName, onErrorText(orconf) )); if( pTrigger->pWhen ){ /* Code the WHEN clause. If it evaluates to false (or NULL) the ** sub-vdbe is immediately halted. */ pWhen = sqlite3ExprDup(db, pTrigger->pWhen, 0); if( SQLITE_OK==sqlite3ResolveExprNames(&sNC, pWhen) ){ iEndTrigger = sqlite3VdbeMakeLabel(v); sqlite3ExprIfFalse(pSubParse, pWhen, iEndTrigger, SQLITE_JUMPIFNULL); } sqlite3ExprDelete(db, pWhen); } /* Code the trigger program into the sub-vdbe. */ codeTriggerProgram(pSubParse, pTrigger->step_list, OE_Default); if( iEndTrigger ){ sqlite3VdbeResolveLabel(v, iEndTrigger); } sqlite3VdbeAddOp0(v, OP_Halt); transferParseError(pParse, pSubParse); pProgram->aOp = sqlite3VdbeTakeOpArray(v, &pProgram->nOp, &pParse->nArg); pProgram->nMem = pSubParse->nMem; pProgram->nCsr = pSubParse->nTab; pProgram->token = (void *)pTrigger; pC->oldmask = pSubParse->oldmask; pC->newmask = pSubParse->newmask; sqlite3VdbeDelete(v); while( pSubParse->pAinc ){ AutoincInfo *p = pSubParse->pAinc; pSubParse->pAinc = p->pNext; sqlite3DbFree(db, p); } } sqlite3StackFree(db, pSubParse); /* Pop the entry off the authorization stack */ sqlite3AuthContextPop(&sContext); return pC; } static CodedTrigger *getRowTrigger( Parse *pParse, Trigger *pTrigger, /* Trigger to code */ int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */ Table *pTab, /* The table to code triggers from */ int orconf ){ CodedTrigger *pC; Parse *pRoot = pParse; /* It may be that this trigger has already been coded (or is in the ** process of being coded). If this is the case, then an entry with ** a matching CodedTrigger.pTrigger field will be present somewhere ** in the Parse.pCodedTrigger list. Search for such an entry. */ if( pParse->pRoot ){ pRoot = pParse->pRoot; } for(pC=pRoot->pCodedTrigger; pC && (pC->pTrigger!=pTrigger || pC->orconf!=orconf); pC=pC->pNext ); if( !pC ){ pC = codeRowTrigger(pRoot, pParse, pTrigger, op, pTab, orconf); } return pC; } /* ** This is called to code FOR EACH ROW triggers. ** ** When the code that this function generates is executed, the following ** must be true: |
︙ | ︙ | |||
761 762 763 764 765 766 767 | ** are set to values that describe the columns used by the trigger program ** in the OLD.* and NEW.* tables respectively. If column N of the ** pseudo-table is read at least once, the corresponding bit of the output ** mask is set. If a column with an index greater than 32 is read, the ** output mask is set to the special value 0xffffffff. ** */ | | | < < < < < < < < < < | > < | | | > | | | < | > | < > | | | > < | < < < < < | < < < < < < < < < | | | | | | | | | | > | < | < < < | | < | < | | > > > | < < < | < | | < < < | | 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 | ** are set to values that describe the columns used by the trigger program ** in the OLD.* and NEW.* tables respectively. If column N of the ** pseudo-table is read at least once, the corresponding bit of the output ** mask is set. If a column with an index greater than 32 is read, the ** output mask is set to the special value 0xffffffff. ** */ void sqlite3CodeRowTrigger( Parse *pParse, /* Parse context */ Trigger *pTrigger, /* List of triggers on table pTab */ int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */ ExprList *pChanges, /* Changes list for any UPDATE OF triggers */ int tr_tm, /* One of TRIGGER_BEFORE, TRIGGER_AFTER */ Table *pTab, /* The table to code triggers from */ int newIdx, /* The indice of the "new" row to access */ int oldIdx, /* The indice of the "old" row to access */ int orconf, /* ON CONFLICT policy */ int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */ ){ Trigger *p; assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE); assert(tr_tm == TRIGGER_BEFORE || tr_tm == TRIGGER_AFTER ); for(p=pTrigger; p; p=p->pNext){ /* Sanity checking: The schema for the trigger and for the table are ** always defined. The trigger must be in the same schema as the table ** or else it must be a TEMP trigger. */ assert( p->pSchema!=0 ); assert( p->pTabSchema!=0 ); assert( p->pSchema==p->pTabSchema || p->pSchema==pParse->db->aDb[1].pSchema ); /* Determine whether we should code this trigger */ if( p->op==op && p->tr_tm==tr_tm && checkColumnOverlap(p->pColumns,pChanges) ){ Vdbe *v = sqlite3GetVdbe(pParse); /* Main VM */ CodedTrigger *pC; pC = getRowTrigger(pParse, p, op, pTab, orconf); assert( pC || pParse->nErr || pParse->db->mallocFailed ); /* Code the OP_Program opcode in the parent VDBE. P4 of the OP_Program ** is a pointer to the sub-vdbe containing the trigger program. */ if( pC ){ sqlite3VdbeAddOp3(v, OP_Program, oldIdx, newIdx, ++pParse->nMem); pC->pProgram->nRef++; sqlite3VdbeChangeP4(v, -1, (const char *)pC->pProgram, P4_SUBPROGRAM); VdbeComment((v, "Call trigger: %s (%s)", p->zName,onErrorText(orconf))); } } } } void sqlite3TriggerUses( Parse *pParse, /* Parse context */ Trigger *pTrigger, /* List of triggers on table pTab */ int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */ ExprList *pChanges, /* Changes list for any UPDATE OF triggers */ Table *pTab, /* The table to code triggers from */ int orconf, /* Default ON CONFLICT policy for trigger steps */ u32 *piOldColMask, /* OUT: Mask of columns used from the OLD.* table */ u32 *piNewColMask /* OUT: Mask of columns used from the NEW.* table */ ){ Trigger *p; assert(op==TK_UPDATE || op==TK_INSERT || op==TK_DELETE); for(p=pTrigger; p; p=p->pNext){ if( p->op==op && checkColumnOverlap(p->pColumns,pChanges) ){ CodedTrigger *pC; pC = getRowTrigger(pParse, p, op, pTab, orconf); if( pC ){ *piOldColMask |= pC->oldmask; *piNewColMask |= pC->newmask; } } } } #endif /* !defined(SQLITE_OMIT_TRIGGER) */ |
Changes to src/update.c.
︙ | ︙ | |||
116 117 118 119 120 121 122 | int j1; /* Addresses of jump instructions */ int okOnePass; /* True for one-pass algorithm without the FIFO */ #ifndef SQLITE_OMIT_TRIGGER int isView; /* Trying to update a view */ Trigger *pTrigger; /* List of triggers on pTab, if required */ #endif | < < < < < < < | > | 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | int j1; /* Addresses of jump instructions */ int okOnePass; /* True for one-pass algorithm without the FIFO */ #ifndef SQLITE_OMIT_TRIGGER int isView; /* Trying to update a view */ Trigger *pTrigger; /* List of triggers on pTab, if required */ #endif u32 old_col_mask = 0; /* Mask of OLD.* columns in use */ u32 new_col_mask = 0; /* Mask of NEW.* columns in use */ /* Register Allocations */ int regRowCount = 0; /* A count of rows changed */ int regOldRowid; /* The old rowid */ int regNewRowid; /* The new rowid */ int regNew; int regOld; int regRowSet = 0; /* Rowset of rows to be updated */ memset(&sContext, 0, sizeof(sContext)); db = pParse->db; if( pParse->nErr || db->mallocFailed ){ goto update_cleanup; } |
︙ | ︙ | |||
171 172 173 174 175 176 177 | if( sqlite3IsReadOnly(pParse, pTab, (pTrigger?1:0)) ){ goto update_cleanup; } aXRef = sqlite3DbMallocRaw(db, sizeof(int) * pTab->nCol ); if( aXRef==0 ) goto update_cleanup; for(i=0; i<pTab->nCol; i++) aXRef[i] = -1; | < < < < < < < < | 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | if( sqlite3IsReadOnly(pParse, pTab, (pTrigger?1:0)) ){ goto update_cleanup; } aXRef = sqlite3DbMallocRaw(db, sizeof(int) * pTab->nCol ); if( aXRef==0 ) goto update_cleanup; for(i=0; i<pTab->nCol; i++) aXRef[i] = -1; /* Allocate a cursors for the main database table and for all indices. ** The index cursors might not be used, but if they are used they ** need to occur right after the database cursor. So go ahead and ** allocate enough space, just in case. */ pTabList->a[0].iCursor = iCur = pParse->nTab++; for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ |
︙ | ︙ | |||
264 265 266 267 268 269 270 | break; } } } aRegIdx[j] = reg; } | < < < < < < < < < < < < < < < < | < | < < < < | < < < > > | < < < < > > | < < < | | < < | < < > | | < < | < < | > > > > | 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 | break; } } } aRegIdx[j] = reg; } /* Begin generating code. */ v = sqlite3GetVdbe(pParse); if( v==0 ) goto update_cleanup; if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); sqlite3BeginWriteOperation(pParse, 1, iDb); #ifndef SQLITE_OMIT_VIRTUALTABLE /* Virtual tables must be handled separately */ if( IsVirtual(pTab) ){ updateVirtualTable(pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef, pWhere); pWhere = 0; pTabList = 0; goto update_cleanup; } #endif /* Allocate required registers. */ regOldRowid = regNewRowid = ++pParse->nMem; if( pTrigger ){ regOld = pParse->nMem + 1; pParse->nMem += pTab->nCol; } if( chngRowid || pTrigger ){ regNewRowid = ++pParse->nMem; } regNew = pParse->nMem + 1; pParse->nMem += pTab->nCol; /* Start the view context. */ if( isView ){ sqlite3AuthContextPush(pParse, &sContext, pTab->zName); } /* If there are any triggers, set old_col_mask and new_col_mask. */ sqlite3TriggerUses(pParse, pTrigger, TK_UPDATE, pChanges, pTab, onError, &old_col_mask, &new_col_mask ); /* If we are trying to update a view, realize that view into ** a ephemeral table. */ #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) if( isView ){ sqlite3MaterializeView(pParse, pTab, pWhere, iCur); |
︙ | ︙ | |||
370 371 372 373 374 375 376 | /* End the database scan loop. */ sqlite3WhereEnd(pWInfo); /* Initialize the count of updated rows */ | | | 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 | /* End the database scan loop. */ sqlite3WhereEnd(pWInfo); /* Initialize the count of updated rows */ if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab ){ regRowCount = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount); } if( !isView ){ /* ** Open every index that needs updating. Note that if any |
︙ | ︙ | |||
403 404 405 406 407 408 409 | KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx); sqlite3VdbeAddOp4(v, OP_OpenWrite, iCur+i+1, pIdx->tnum, iDb, (char*)pKey, P4_KEYINFO_HANDOFF); assert( pParse->nTab>iCur+i+1 ); } } } | < < < < < < < < < < | < > > | > | < < < < > > | < < < < | | < < < < < | | | < < < < < | < < < < < < < | > > > > > > > > > | | | | > > > > | | | < | | | | | < | < | | | < < < < < < < < | < < < < < < < | | < > > > < < < < < | < | < < < < | < < | < | < | < | | < | | < | < | < < < | < < < > < < < < | | | 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 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 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 | KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx); sqlite3VdbeAddOp4(v, OP_OpenWrite, iCur+i+1, pIdx->tnum, iDb, (char*)pKey, P4_KEYINFO_HANDOFF); assert( pParse->nTab>iCur+i+1 ); } } } /* Top of the update loop */ if( okOnePass ){ int a1 = sqlite3VdbeAddOp1(v, OP_NotNull, regOldRowid); addr = sqlite3VdbeAddOp0(v, OP_Goto); sqlite3VdbeJumpHere(v, a1); }else{ addr = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet, 0, regOldRowid); } /* Make cursor iCur point to the record that is being updated. If ** this record does not exist for some reason (deleted by a trigger, ** for example, then jump to the next iteration of the RowSet loop. */ sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, regOldRowid); /* If there are triggers on this table, populate an array of registers ** with the required old.* column data. */ if( pTrigger ){ for(i=0; i<pTab->nCol; i++){ if( aXRef[i]<0 || old_col_mask==0xffffffff || (old_col_mask & (1<<i)) ){ sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regOld+i); sqlite3ColumnDefault(v, pTab, i, regOld+i); }else{ sqlite3VdbeAddOp2(v, OP_Null, 0, regOld+i); } } } /* If the record number will change, set register regNewRowid to ** contain the new value. If the record number is not being modified, ** then regNewRowid is the same register as regOldRowid, which is ** already populated. */ assert( chngRowid || pTrigger || regOldRowid==regNewRowid ); if( chngRowid ){ sqlite3ExprCode(pParse, pRowidExpr, regNewRowid); sqlite3VdbeAddOp1(v, OP_MustBeInt, regNewRowid); }else if( pTrigger ){ sqlite3VdbeAddOp2(v, OP_Copy, regOldRowid, regNewRowid); } /* Populate the array of registers beginning at regNew with the new ** row data. This array is used to check constaints, create the new ** table and index records, and as the values for any new.* references ** made by triggers. */ for(i=0; i<pTab->nCol; i++){ if( i==pTab->iPKey ){ sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i); }else{ j = aXRef[i]; if( j<0 ){ sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regNew+i); sqlite3ColumnDefault(v, pTab, i, regNew+i); }else{ sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i); } } } /* Fire any BEFORE UPDATE triggers. This happens before constraints are ** verified. One could argue that this is wrong. */ sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, TRIGGER_BEFORE, pTab, regNew, regOld, onError, addr); if( !isView ){ /* Do constraint checks. */ sqlite3GenerateConstraintChecks(pParse, pTab, iCur, regNewRowid, aRegIdx, chngRowid, 1, onError, addr, 0); /* Delete the index entries associated with the current record. */ j1 = sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regOldRowid); sqlite3GenerateRowIndexDelete(pParse, pTab, iCur, aRegIdx); /* If changing the record number, delete the old record. */ if( chngRowid ){ sqlite3VdbeAddOp2(v, OP_Delete, iCur, 0); } sqlite3VdbeJumpHere(v, j1); /* Create the new index entries and the new record. */ sqlite3CompleteInsertion(pParse, pTab, iCur, regNewRowid, aRegIdx,1,-1,0,0); } /* Increment the row counter */ if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab){ sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1); } sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, TRIGGER_AFTER, pTab, regNew, regOld, onError, addr); /* Repeat the above with the next record to be updated, until ** all record selected by the WHERE clause have been updated. */ sqlite3VdbeAddOp2(v, OP_Goto, 0, addr); sqlite3VdbeJumpHere(v, addr); /* Close all tables */ for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ if( openAll || aRegIdx[i]>0 ){ sqlite3VdbeAddOp2(v, OP_Close, iCur+i+1, 0); } } sqlite3VdbeAddOp2(v, OP_Close, iCur, 0); /* Update the sqlite_sequence table by storing the content of the ** maximum rowid counter values recorded while inserting into ** autoincrement tables. */ if( pParse->nested==0 && pParse->pTriggerTab==0 ){ sqlite3AutoincrementEnd(pParse); } /* ** Return the number of rows that were changed. If this routine is ** generating code because of a call to sqlite3NestedParse(), do not ** invoke the callback function. */ if( (db->flags&SQLITE_CountRows) && !pParse->pTriggerTab && !pParse->nested ){ sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1); sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows updated", SQLITE_STATIC); } update_cleanup: sqlite3AuthContextPop(&sContext); |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
842 843 844 845 846 847 848 849 | ** If P4 is not null then it is an error message string. ** ** There is an implied "Halt 0 0 0" instruction inserted at the very end of ** every program. So a jump past the last instruction of the program ** is the same as executing Halt. */ case OP_Halt: { p->rc = pOp->p1; | > > > > > > > > > < > | 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 | ** If P4 is not null then it is an error message string. ** ** There is an implied "Halt 0 0 0" instruction inserted at the very end of ** every program. So a jump past the last instruction of the program ** is the same as executing Halt. */ case OP_Halt: { if( pOp->p1==SQLITE_OK && p->pFrame ){ VdbeFrame *pFrame = p->pFrame; p->pFrame = pFrame->pParent; p->nFrame--; pc = sqlite3VdbeFrameRestore(pFrame); if( pOp->p2==OE_Ignore ){ } break; } p->rc = pOp->p1; p->errorAction = (u8)pOp->p2; p->pc = pc; if( pOp->p4.z ){ sqlite3SetString(&p->zErrMsg, db, "%s", pOp->p4.z); } rc = sqlite3VdbeHalt(p); assert( rc==SQLITE_BUSY || rc==SQLITE_OK ); if( rc==SQLITE_BUSY ){ p->rc = rc = SQLITE_BUSY; |
︙ | ︙ | |||
4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 | Context *pContext; pContext = &p->contextStack[--p->contextStackTop]; assert( p->contextStackTop>=0 ); db->lastRowid = pContext->lastRowid; p->nChange = pContext->nChange; break; } #endif /* #ifndef SQLITE_OMIT_TRIGGER */ #ifndef SQLITE_OMIT_AUTOINCREMENT /* Opcode: MemMax P1 P2 * * * ** ** Set the value of register P1 to the maximum of its current value ** and the value in register P2. | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 | Context *pContext; pContext = &p->contextStack[--p->contextStackTop]; assert( p->contextStackTop>=0 ); db->lastRowid = pContext->lastRowid; p->nChange = pContext->nChange; break; } /* Opcode: Program P1 P2 P3 P4 * ** ** Execute a trigger program. P1 contains the address of the memory cell ** that contains the left-most column of the old.* table (unless the trigger ** program is firing as a result of an INSERT statement). P2 is the address ** of the corresponding column in the new.* table (unless the trigger ** program is being fired due to a DELETE). ** ** Register P3 contains the address of a memory cell in this (the parent) ** VM that is used to allocate the memory required by the sub-vdbe at ** runtime. ** ** P4 is a pointer to the VM containing the trigger program. */ case OP_Program: { VdbeFrame *pFrame; SubProgram *pProgram = pOp->p4.pProgram; Mem *pRt = &p->aMem[pOp->p3]; /* Register to allocate runtime space */ assert( pProgram->nOp>0 ); /* If noRecTrigger is true, then recursive invocation of triggers is ** disabled for backwards compatibility. ** ** It is recursive invocation of triggers, at the SQL level, that is ** disabled. In some cases a single trigger may generate more than one ** SubProgram (if the trigger may be executed with more than one different ** ON CONFLICT algorithm). SubProgram structures associated with a ** single trigger all have the same value for the SubProgram.token ** variable. */ if( 1 || p->noRecTrigger ){ void *t = pProgram->token; for(pFrame=p->pFrame; pFrame && pFrame->token!=t; pFrame=pFrame->pParent); if( pFrame ) break; } /* TODO: This constant should be configurable. */ if( p->nFrame>1000 ){ rc = SQLITE_ERROR; sqlite3SetString(&p->zErrMsg, db, "too many levels of trigger recursion"); break; } /* Register pRt is used to store the memory required to save the state ** of the current program, and the memory required at runtime to execute ** the trigger program. If this trigger has been fired before, then pRt ** is already allocated. Otherwise, it must be initialized. */ if( (pRt->flags&MEM_Frame)==0 ){ Mem *pMem; Mem *pEnd; /* SubProgram.nMem is set to the number of memory cells used by the ** program stored in SubProgram.aOp. As well as these, one memory ** cell is required for each cursor used by the program. Set local ** variable nMem (and later, VdbeFrame.nChildMem) to this value. */ int nMem = pProgram->nMem + pProgram->nCsr; int nByte = ROUND8(sizeof(VdbeFrame)) + nMem * sizeof(Mem) + pProgram->nCsr * sizeof(VdbeCursor *); pFrame = sqlite3DbMallocZero(db, nByte); if( !pFrame ){ goto no_mem; } sqlite3VdbeMemRelease(pRt); pRt->flags = MEM_Frame; pRt->u.pFrame = pFrame; pFrame->v = p; pFrame->nChildMem = nMem; pFrame->nChildCsr = pProgram->nCsr; pFrame->pc = pc; pFrame->aMem = p->aMem; pFrame->nMem = p->nMem; pFrame->apCsr = p->apCsr; pFrame->nCursor = p->nCursor; pFrame->aOp = p->aOp; pFrame->nOp = p->nOp; pFrame->token = pProgram->token; pEnd = &VdbeFrameMem(pFrame)[pFrame->nChildMem]; for(pMem=VdbeFrameMem(pFrame); pMem!=pEnd; pMem++){ pMem->flags = MEM_Null; pMem->db = db; } }else{ pFrame = pRt->u.pFrame; assert( pProgram->nMem+pProgram->nCsr==pFrame->nChildMem ); assert( pProgram->nCsr==pFrame->nChildCsr ); assert( pc==pFrame->pc ); } p->nFrame++; pFrame->pParent = p->pFrame; p->pFrame = pFrame; p->aMem = &VdbeFrameMem(pFrame)[-1]; p->nMem = pFrame->nChildMem; p->nCursor = pFrame->nChildCsr; p->apCsr = (VdbeCursor **)&p->aMem[p->nMem+1]; p->aOp = pProgram->aOp; p->nOp = pProgram->nOp; pc = -1; break; } /* Opcode: TriggerVal P1 P2 P3 * * ** ** Copy a value currently stored in a memory cell of the parent VM to ** a cell in this VMs address space. This is used by trigger programs ** to access the new.* and old.* values. ** ** If parameter P3 is non-zero, then the value read is from the new.* ** table. If P3 is zero, then the value is read from the old.* table. ** Parameter P1 is the index of the required new.* or old.* column (or ** -1 for rowid). ** ** Parameter P2 is the index of the memory cell in this VM to copy the ** value to. */ case OP_TriggerVal: { /* out2-prerelease */ VdbeFrame *pF = p->pFrame; Mem *pIn; int iFrom = pOp->p1; /* Memory cell in parent frame */ iFrom += (pOp->p3 ? pF->aOp[pF->pc].p2 : pF->aOp[pF->pc].p1); pIn = &pF->aMem[iFrom]; sqlite3VdbeMemShallowCopy(pOut, pIn, MEM_Ephem); break; } #endif /* #ifndef SQLITE_OMIT_TRIGGER */ #ifndef SQLITE_OMIT_AUTOINCREMENT /* Opcode: MemMax P1 P2 * * * ** ** Set the value of register P1 to the maximum of its current value ** and the value in register P2. |
︙ | ︙ |
Changes to src/vdbe.h.
︙ | ︙ | |||
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | /* ** The names of the following types declared in vdbeInt.h are required ** for the VdbeOp definition. */ typedef struct VdbeFunc VdbeFunc; typedef struct Mem Mem; /* ** A single instruction of the virtual machine has an opcode ** and as many as three operands. The instruction is recorded ** as an instance of the following structure: */ struct VdbeOp { u8 opcode; /* What operation to perform */ signed char p4type; /* One of the P4_xxx constants for p4 */ u8 opflags; /* Not currently used */ u8 p5; /* Fifth parameter is an unsigned character */ int p1; /* First operand */ int p2; /* Second parameter (often the jump destination) */ int p3; /* The third parameter */ | > | > > > > > > > > > > > > > > | > | 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 | /* ** The names of the following types declared in vdbeInt.h are required ** for the VdbeOp definition. */ typedef struct VdbeFunc VdbeFunc; typedef struct Mem Mem; typedef struct SubProgram SubProgram; /* ** A single instruction of the virtual machine has an opcode ** and as many as three operands. The instruction is recorded ** as an instance of the following structure: */ struct VdbeOp { u8 opcode; /* What operation to perform */ signed char p4type; /* One of the P4_xxx constants for p4 */ u8 opflags; /* Not currently used */ u8 p5; /* Fifth parameter is an unsigned character */ int p1; /* First operand */ int p2; /* Second parameter (often the jump destination) */ int p3; /* The third parameter */ union { /* fourth parameter */ int i; /* Integer value if p4type==P4_INT32 */ void *p; /* Generic pointer */ char *z; /* Pointer to data for string (char array) types */ i64 *pI64; /* Used when p4type is P4_INT64 */ double *pReal; /* Used when p4type is P4_REAL */ FuncDef *pFunc; /* Used when p4type is P4_FUNCDEF */ VdbeFunc *pVdbeFunc; /* Used when p4type is P4_VDBEFUNC */ CollSeq *pColl; /* Used when p4type is P4_COLLSEQ */ Mem *pMem; /* Used when p4type is P4_MEM */ VTable *pVtab; /* Used when p4type is P4_VTAB */ KeyInfo *pKeyInfo; /* Used when p4type is P4_KEYINFO */ int *ai; /* Used when p4type is P4_INTARRAY */ SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */ } p4; #ifdef SQLITE_DEBUG char *zComment; /* Comment to improve readability */ #endif #ifdef VDBE_PROFILE int cnt; /* Number of times this instruction was executed */ u64 cycles; /* Total time spent executing this instruction */ #endif }; typedef struct VdbeOp VdbeOp; /* ** A sub-routine used to implement a trigger program. */ struct SubProgram { VdbeOp *aOp; /* Array of opcodes for sub-program */ int nOp; /* Elements in aOp[] */ int nMem; /* Number of memory cells required */ int nCsr; /* Number of cursors required */ int nRef; /* Number of pointers to this structure */ void *token; /* id that may be used to recursive triggers */ }; /* ** A smaller version of VdbeOp used for the VdbeAddOpList() function because ** it takes up less space. */ struct VdbeOpList { u8 opcode; /* What operation to perform */ signed char p1; /* First operand */ signed char p2; /* Second parameter (often the jump destination) */ signed char p3; /* Third parameter */ }; typedef struct VdbeOpList VdbeOpList; /* ** Allowed values of VdbeOp.p4type */ #define P4_NOTUSED 0 /* The P4 parameter is not used */ #define P4_DYNAMIC (-1) /* Pointer to a string obtained from sqliteMalloc() */ #define P4_STATIC (-2) /* Pointer to a static string */ #define P4_COLLSEQ (-4) /* P4 is a pointer to a CollSeq structure */ #define P4_FUNCDEF (-5) /* P4 is a pointer to a FuncDef structure */ #define P4_KEYINFO (-6) /* P4 is a pointer to a KeyInfo structure */ #define P4_VDBEFUNC (-7) /* P4 is a pointer to a VdbeFunc structure */ #define P4_MEM (-8) /* P4 is a pointer to a Mem* structure */ #define P4_TRANSIENT (-9) /* P4 is a pointer to a transient string */ #define P4_VTAB (-10) /* P4 is a pointer to an sqlite3_vtab structure */ #define P4_MPRINTF (-11) /* P4 is a string obtained from sqlite3_mprintf() */ #define P4_REAL (-12) /* P4 is a 64-bit floating point value */ #define P4_INT64 (-13) /* P4 is a 64-bit signed integer */ #define P4_INT32 (-14) /* P4 is a 32-bit signed integer */ #define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */ #define P4_SUBPROGRAM (-18) /* P4 is a pointer to a SubProgram structure */ /* When adding a P4 argument using P4_KEYINFO, a copy of the KeyInfo structure ** is made. That copy is freed when the Vdbe is finalized. But if the ** argument is P4_KEYINFO_HANDOFF, the passed in pointer is used. It still ** gets freed when the Vdbe is finalized so it still should be obtained ** from a single sqliteMalloc(). But no copy is made and the calling ** function should *not* try to free the KeyInfo. |
︙ | ︙ | |||
164 165 166 167 168 169 170 | void sqlite3VdbeJumpHere(Vdbe*, int addr); void sqlite3VdbeChangeToNoop(Vdbe*, int addr, int N); void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N); void sqlite3VdbeUsesBtree(Vdbe*, int); VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); int sqlite3VdbeMakeLabel(Vdbe*); void sqlite3VdbeDelete(Vdbe*); | | > > | 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | void sqlite3VdbeJumpHere(Vdbe*, int addr); void sqlite3VdbeChangeToNoop(Vdbe*, int addr, int N); void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N); void sqlite3VdbeUsesBtree(Vdbe*, int); VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); int sqlite3VdbeMakeLabel(Vdbe*); void sqlite3VdbeDelete(Vdbe*); void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int,int); int sqlite3VdbeFinalize(Vdbe*); void sqlite3VdbeResolveLabel(Vdbe*, int); int sqlite3VdbeCurrentAddr(Vdbe*); #ifdef SQLITE_DEBUG void sqlite3VdbeTrace(Vdbe*,FILE*); #endif void sqlite3VdbeResetStepResult(Vdbe*); int sqlite3VdbeReset(Vdbe*); void sqlite3VdbeSetNumCols(Vdbe*,int); int sqlite3VdbeSetColName(Vdbe*, int, int, const char *, void(*)(void*)); void sqlite3VdbeCountChanges(Vdbe*); sqlite3 *sqlite3VdbeDb(Vdbe*); void sqlite3VdbeSetSql(Vdbe*, const char *z, int n, int); void sqlite3VdbeSwap(Vdbe*,Vdbe*); VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*); void sqlite3VdbeProgramDelete(sqlite3 *, SubProgram *, int); #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT int sqlite3VdbeReleaseMemory(int); #endif UnpackedRecord *sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,char*,int); void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord*); int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*); |
︙ | ︙ |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
85 86 87 88 89 90 91 92 93 94 95 96 97 98 | int payloadSize; /* Total number of bytes in the record */ u32 *aType; /* Type values for all entries in the record */ u32 *aOffset; /* Cached offsets to the start of each columns data */ u8 *aRow; /* Data for the current row, if all on one page */ }; typedef struct VdbeCursor VdbeCursor; /* ** A value for VdbeCursor.cacheValid that means the cache is always invalid. */ #define CACHE_STALE 0 /* ** Internally, the vdbe manipulates nearly all SQL values as Mem | > > > > > > > > > > > > > > > > > > | 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 | int payloadSize; /* Total number of bytes in the record */ u32 *aType; /* Type values for all entries in the record */ u32 *aOffset; /* Cached offsets to the start of each columns data */ u8 *aRow; /* Data for the current row, if all on one page */ }; typedef struct VdbeCursor VdbeCursor; typedef struct VdbeFrame VdbeFrame; struct VdbeFrame { Vdbe *v; /* VM this frame belongs to */ int pc; /* Program Counter */ Op *aOp; /* Program instructions */ int nOp; /* Size of aOp array */ Mem *aMem; /* Array of memory cells */ int nMem; /* Number of entries in aMem */ VdbeCursor **apCsr; /* Element of Vdbe cursors */ u16 nCursor; /* Number of entries in apCsr */ VdbeFrame *pParent; /* Parent of this frame */ void *token; /* Copy of SubProgram.token */ int nChildMem; /* Number of memory cells for child frame */ int nChildCsr; /* Number of cursors for child frame */ }; #define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))]) /* ** A value for VdbeCursor.cacheValid that means the cache is always invalid. */ #define CACHE_STALE 0 /* ** Internally, the vdbe manipulates nearly all SQL values as Mem |
︙ | ︙ | |||
107 108 109 110 111 112 113 114 115 116 117 118 119 120 | */ struct Mem { union { i64 i; /* Integer value. */ int nZero; /* Used when bit MEM_Zero is set in flags */ FuncDef *pDef; /* Used only when flags==MEM_Agg */ RowSet *pRowSet; /* Used only when flags==MEM_RowSet */ } u; double r; /* Real value */ sqlite3 *db; /* The associated database connection */ char *z; /* String or BLOB value */ int n; /* Number of characters in string value, excluding '\0' */ u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */ u8 type; /* One of SQLITE_NULL, SQLITE_TEXT, SQLITE_INTEGER, etc */ | > | 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | */ struct Mem { union { i64 i; /* Integer value. */ int nZero; /* Used when bit MEM_Zero is set in flags */ FuncDef *pDef; /* Used only when flags==MEM_Agg */ RowSet *pRowSet; /* Used only when flags==MEM_RowSet */ VdbeFrame *pFrame; /* Used when flags==MEM_Frame */ } u; double r; /* Real value */ sqlite3 *db; /* The associated database connection */ char *z; /* String or BLOB value */ int n; /* Number of characters in string value, excluding '\0' */ u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */ u8 type; /* One of SQLITE_NULL, SQLITE_TEXT, SQLITE_INTEGER, etc */ |
︙ | ︙ | |||
140 141 142 143 144 145 146 147 148 149 150 151 152 153 | */ #define MEM_Null 0x0001 /* Value is NULL */ #define MEM_Str 0x0002 /* Value is a string */ #define MEM_Int 0x0004 /* Value is an integer */ #define MEM_Real 0x0008 /* Value is a real number */ #define MEM_Blob 0x0010 /* Value is a BLOB */ #define MEM_RowSet 0x0020 /* Value is a RowSet object */ #define MEM_TypeMask 0x00ff /* Mask of type bits */ /* Whenever Mem contains a valid string or blob representation, one of ** the following flags must be set to determine the memory management ** policy for Mem.z. The MEM_Term flag tells us whether or not the ** string is \000 or \u0000 terminated */ | > | 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 | */ #define MEM_Null 0x0001 /* Value is NULL */ #define MEM_Str 0x0002 /* Value is a string */ #define MEM_Int 0x0004 /* Value is an integer */ #define MEM_Real 0x0008 /* Value is a real number */ #define MEM_Blob 0x0010 /* Value is a BLOB */ #define MEM_RowSet 0x0020 /* Value is a RowSet object */ #define MEM_Frame 0x0040 /* Value is a VdbeFrame object */ #define MEM_TypeMask 0x00ff /* Mask of type bits */ /* Whenever Mem contains a valid string or blob representation, one of ** the following flags must be set to determine the memory management ** policy for Mem.z. The MEM_Term flag tells us whether or not the ** string is \000 or \u0000 terminated */ |
︙ | ︙ | |||
298 299 300 301 302 303 304 305 306 307 308 309 310 311 | int aCounter[2]; /* Counters used by sqlite3_stmt_status() */ char *zSql; /* Text of the SQL statement that generated this */ void *pFree; /* Free this when deleting the vdbe */ int iStatement; /* Statement number (or 0 if has not opened stmt) */ #ifdef SQLITE_DEBUG FILE *trace; /* Write an execution trace here, if not NULL */ #endif }; /* ** The following are allowed values for Vdbe.magic */ #define VDBE_MAGIC_INIT 0x26bceaa5 /* Building a VDBE program */ #define VDBE_MAGIC_RUN 0xbdf20da3 /* VDBE is ready to execute */ | > > > | 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 | int aCounter[2]; /* Counters used by sqlite3_stmt_status() */ char *zSql; /* Text of the SQL statement that generated this */ void *pFree; /* Free this when deleting the vdbe */ int iStatement; /* Statement number (or 0 if has not opened stmt) */ #ifdef SQLITE_DEBUG FILE *trace; /* Write an execution trace here, if not NULL */ #endif VdbeFrame *pFrame; /* Parent frame */ int nFrame; /* Number of frames in pFrame list */ u8 noRecTrigger; /* True to disable recursive triggers */ }; /* ** The following are allowed values for Vdbe.magic */ #define VDBE_MAGIC_INIT 0x26bceaa5 /* Building a VDBE program */ #define VDBE_MAGIC_RUN 0xbdf20da3 /* VDBE is ready to execute */ |
︙ | ︙ | |||
358 359 360 361 362 363 364 365 366 367 368 369 370 371 | void sqlite3VdbeMemRelease(Mem *p); void sqlite3VdbeMemReleaseExternal(Mem *p); int sqlite3VdbeMemFinalize(Mem*, FuncDef*); const char *sqlite3OpcodeName(int); int sqlite3VdbeOpcodeHasProperty(int, int); int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve); int sqlite3VdbeCloseStatement(Vdbe *, int); #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT int sqlite3VdbeReleaseBuffers(Vdbe *p); #endif #ifndef SQLITE_OMIT_SHARED_CACHE void sqlite3VdbeMutexArrayEnter(Vdbe *p); #else | > > | 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 | void sqlite3VdbeMemRelease(Mem *p); void sqlite3VdbeMemReleaseExternal(Mem *p); int sqlite3VdbeMemFinalize(Mem*, FuncDef*); const char *sqlite3OpcodeName(int); int sqlite3VdbeOpcodeHasProperty(int, int); int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve); int sqlite3VdbeCloseStatement(Vdbe *, int); void sqlite3VdbeFrameDelete(VdbeFrame*); int sqlite3VdbeFrameRestore(VdbeFrame *); #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT int sqlite3VdbeReleaseBuffers(Vdbe *p); #endif #ifndef SQLITE_OMIT_SHARED_CACHE void sqlite3VdbeMutexArrayEnter(Vdbe *p); #else |
︙ | ︙ |
Changes to src/vdbeapi.c.
︙ | ︙ | |||
72 73 74 75 76 77 78 | int rc; if( pStmt==0 ){ rc = SQLITE_OK; }else{ Vdbe *v = (Vdbe*)pStmt; sqlite3_mutex_enter(v->db->mutex); rc = sqlite3VdbeReset(v); | | | 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | int rc; if( pStmt==0 ){ rc = SQLITE_OK; }else{ Vdbe *v = (Vdbe*)pStmt; sqlite3_mutex_enter(v->db->mutex); rc = sqlite3VdbeReset(v); sqlite3VdbeMakeReady(v, -1, 0, 0, 0, 0); assert( (rc & (v->db->errMask))==rc ); rc = sqlite3ApiExit(v->db, rc); sqlite3_mutex_leave(v->db->mutex); } return rc; } |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
262 263 264 265 266 267 268 | ** ** If no such instruction is found, then every Statement instruction ** is changed to a Noop. In this way, we avoid creating the statement ** journal file unnecessarily. */ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){ int i; | | | 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 | ** ** If no such instruction is found, then every Statement instruction ** is changed to a Noop. In this way, we avoid creating the statement ** journal file unnecessarily. */ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){ int i; int nMaxArgs = *pMaxFuncArgs; Op *pOp; int *aLabel = p->aLabel; int doesStatementRollback = 0; int hasStatementBegin = 0; p->readOnly = 1; p->usesStmtJournal = 0; for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){ |
︙ | ︙ | |||
334 335 336 337 338 339 340 341 342 343 344 345 346 347 | /* ** Return the address of the next instruction to be inserted. */ int sqlite3VdbeCurrentAddr(Vdbe *p){ assert( p->magic==VDBE_MAGIC_INIT ); return p->nOp; } /* ** Add a whole list of operations to the operation stack. Return the ** address of the first operation added. */ int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){ int addr; | > > > > > > > > | 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 | /* ** Return the address of the next instruction to be inserted. */ int sqlite3VdbeCurrentAddr(Vdbe *p){ assert( p->magic==VDBE_MAGIC_INIT ); return p->nOp; } VdbeOp *sqlite3VdbeTakeOpArray(Vdbe *p, int *pnOp, int *pnMaxArg){ VdbeOp *aOp = p->aOp; resolveP2Values(p, pnMaxArg); *pnOp = p->nOp; p->aOp = 0; return aOp; } /* ** Add a whole list of operations to the operation stack. Return the ** address of the first operation added. */ int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){ int addr; |
︙ | ︙ | |||
478 479 480 481 482 483 484 | sqlite3ValueFree((sqlite3_value*)p4); break; } case P4_VTAB : { sqlite3VtabUnlock((VTable *)p4); break; } | > > > | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 | sqlite3ValueFree((sqlite3_value*)p4); break; } case P4_VTAB : { sqlite3VtabUnlock((VTable *)p4); break; } case P4_SUBPROGRAM : { sqlite3VdbeProgramDelete(db, (SubProgram *)p4, 1); break; } } } } static void vdbeFreeOpArray(sqlite3 *db, Op *aOp, int nOp){ if( aOp ){ Op *pOp; for(pOp=aOp; pOp<&aOp[nOp]; pOp++){ freeP4(db, pOp->p4type, pOp->p4.p); #ifdef SQLITE_DEBUG sqlite3DbFree(db, pOp->zComment); #endif } } sqlite3DbFree(db, aOp); } void sqlite3VdbeProgramDelete(sqlite3 *db, SubProgram *p, int freeop){ assert( p->nRef>0 ); if( freeop || p->nRef==1 ){ Op *aOp = p->aOp; p->aOp = 0; vdbeFreeOpArray(db, aOp, p->nOp); p->nOp = 0; } p->nRef--; if( p->nRef==0 ){ sqlite3DbFree(db, p); } } /* ** Change N opcodes starting at addr to No-ops. */ void sqlite3VdbeChangeToNoop(Vdbe *p, int addr, int N){ if( p->aOp ){ |
︙ | ︙ | |||
600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 | ** Change the comment on the the most recently coded instruction. Or ** insert a No-op and add the comment to that new instruction. This ** makes the code easier to read during debugging. None of this happens ** in a production build. */ void sqlite3VdbeComment(Vdbe *p, const char *zFormat, ...){ va_list ap; assert( p->nOp>0 || p->aOp==0 ); assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed ); if( p->nOp ){ char **pz = &p->aOp[p->nOp-1].zComment; va_start(ap, zFormat); sqlite3DbFree(p->db, *pz); *pz = sqlite3VMPrintf(p->db, zFormat, ap); va_end(ap); } } void sqlite3VdbeNoopComment(Vdbe *p, const char *zFormat, ...){ va_list ap; sqlite3VdbeAddOp0(p, OP_Noop); assert( p->nOp>0 || p->aOp==0 ); assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed ); if( p->nOp ){ char **pz = &p->aOp[p->nOp-1].zComment; va_start(ap, zFormat); sqlite3DbFree(p->db, *pz); | > > | 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 | ** Change the comment on the the most recently coded instruction. Or ** insert a No-op and add the comment to that new instruction. This ** makes the code easier to read during debugging. None of this happens ** in a production build. */ void sqlite3VdbeComment(Vdbe *p, const char *zFormat, ...){ va_list ap; if( !p ) return; assert( p->nOp>0 || p->aOp==0 ); assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed ); if( p->nOp ){ char **pz = &p->aOp[p->nOp-1].zComment; va_start(ap, zFormat); sqlite3DbFree(p->db, *pz); *pz = sqlite3VMPrintf(p->db, zFormat, ap); va_end(ap); } } void sqlite3VdbeNoopComment(Vdbe *p, const char *zFormat, ...){ va_list ap; if( !p ) return; sqlite3VdbeAddOp0(p, OP_Noop); assert( p->nOp>0 || p->aOp==0 ); assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed ); if( p->nOp ){ char **pz = &p->aOp[p->nOp-1].zComment; va_start(ap, zFormat); sqlite3DbFree(p->db, *pz); |
︙ | ︙ | |||
744 745 746 747 748 749 750 751 752 753 754 755 756 757 | sqlite3_snprintf(nTemp, zTemp, "vtab:%p:%p", pVtab, pVtab->pModule); break; } #endif case P4_INTARRAY: { sqlite3_snprintf(nTemp, zTemp, "intarray"); break; } default: { zP4 = pOp->p4.z; if( zP4==0 ){ zP4 = zTemp; zTemp[0] = 0; } | > > > > | 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 | sqlite3_snprintf(nTemp, zTemp, "vtab:%p:%p", pVtab, pVtab->pModule); break; } #endif case P4_INTARRAY: { sqlite3_snprintf(nTemp, zTemp, "intarray"); break; } case P4_SUBPROGRAM: { sqlite3_snprintf(nTemp, zTemp, "program"); break; } default: { zP4 = pOp->p4.z; if( zP4==0 ){ zP4 = zTemp; zTemp[0] = 0; } |
︙ | ︙ | |||
819 820 821 822 823 824 825 | ** callgrind, this causes a certain test case to hit the CPU 4.7 ** percent less (x86 linux, gcc version 4.1.2, -O6) than if ** sqlite3MemRelease() were called from here. With -O2, this jumps ** to 6.6 percent. The test case is inserting 1000 rows into a table ** with no indexes using a single prepared INSERT statement, bind() ** and reset(). Inserts are grouped into a transaction. */ | | > > > > > > > > > > > > | 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 | ** callgrind, this causes a certain test case to hit the CPU 4.7 ** percent less (x86 linux, gcc version 4.1.2, -O6) than if ** sqlite3MemRelease() were called from here. With -O2, this jumps ** to 6.6 percent. The test case is inserting 1000 rows into a table ** with no indexes using a single prepared INSERT statement, bind() ** and reset(). Inserts are grouped into a transaction. */ if( p->flags&(MEM_Agg|MEM_Dyn|MEM_Frame|MEM_RowSet) ){ sqlite3VdbeMemRelease(p); }else if( p->zMalloc ){ sqlite3DbFree(db, p->zMalloc); p->zMalloc = 0; } p->flags = MEM_Null; } db->mallocFailed = malloc_failed; } } void sqlite3VdbeFrameDelete(VdbeFrame *p){ int i; Mem *aMem = VdbeFrameMem(p); VdbeCursor **apCsr = (VdbeCursor **)&aMem[p->nChildMem]; for(i=0; i<p->nChildCsr; i++){ sqlite3VdbeFreeCursor(p->v, apCsr[i]); } releaseMemArray(aMem, p->nChildMem); sqlite3DbFree(p->v->db, p); } #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT int sqlite3VdbeReleaseBuffers(Vdbe *p){ int ii; int nFree = 0; assert( sqlite3_mutex_held(p->db->mutex) ); for(ii=1; ii<=p->nMem; ii++){ |
︙ | ︙ | |||
868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 | ** p->explain==2, only OP_Explain instructions are listed and these ** are shown in a different format. p->explain==2 is used to implement ** EXPLAIN QUERY PLAN. */ int sqlite3VdbeList( Vdbe *p /* The VDBE */ ){ sqlite3 *db = p->db; int i; int rc = SQLITE_OK; Mem *pMem = p->pResultSet = &p->aMem[1]; assert( p->explain ); assert( p->magic==VDBE_MAGIC_RUN ); assert( db->magic==SQLITE_MAGIC_BUSY ); assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY || p->rc==SQLITE_NOMEM ); /* Even though this opcode does not use dynamic strings for ** the result, result columns may become dynamic if the user calls ** sqlite3_column_text16(), causing a translation to UTF-16 encoding. */ | > > > > | > > > > > > > > > > > > > > | | > > | > > > > > > > > > > > > > > > > > > > > > > | 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 | ** p->explain==2, only OP_Explain instructions are listed and these ** are shown in a different format. p->explain==2 is used to implement ** EXPLAIN QUERY PLAN. */ int sqlite3VdbeList( Vdbe *p /* The VDBE */ ){ int nRow; /* Total number of rows to return */ int nSub = 0; /* Number of sub-vdbes seen so far */ SubProgram **apSub = 0; /* Array of sub-vdbes */ Mem *pSub = 0; sqlite3 *db = p->db; int i; int rc = SQLITE_OK; Mem *pMem = p->pResultSet = &p->aMem[1]; assert( p->explain ); assert( p->magic==VDBE_MAGIC_RUN ); assert( db->magic==SQLITE_MAGIC_BUSY ); assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY || p->rc==SQLITE_NOMEM ); /* Even though this opcode does not use dynamic strings for ** the result, result columns may become dynamic if the user calls ** sqlite3_column_text16(), causing a translation to UTF-16 encoding. */ releaseMemArray(pMem, 8); if( p->rc==SQLITE_NOMEM ){ /* This happens if a malloc() inside a call to sqlite3_column_text() or ** sqlite3_column_text16() failed. */ db->mallocFailed = 1; return SQLITE_ERROR; } /* Figure out total number of rows that will be returned by this ** EXPLAIN program. */ nRow = p->nOp; if( p->explain==1 ){ pSub = &p->aMem[9]; if( pSub->flags&MEM_Blob ){ nSub = pSub->n/sizeof(Vdbe*); apSub = (SubProgram **)pSub->z; } for(i=0; i<nSub; i++){ nRow += apSub[i]->nOp; } } 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->u1.isInterrupted ){ p->rc = SQLITE_INTERRUPT; rc = SQLITE_ERROR; sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3ErrStr(p->rc)); }else{ char *z; Op *pOp; if( i<p->nOp ){ pOp = &p->aOp[i]; }else{ int j; i -= p->nOp; for(j=0; i>=apSub[j]->nOp; j++){ i -= apSub[j]->nOp; } pOp = &apSub[j]->aOp[i]; } if( p->explain==1 ){ pMem->flags = MEM_Int; pMem->type = SQLITE_INTEGER; pMem->u.i = i; /* Program counter */ pMem++; pMem->flags = MEM_Static|MEM_Str|MEM_Term; pMem->z = (char*)sqlite3OpcodeName(pOp->opcode); /* Opcode */ assert( pMem->z!=0 ); pMem->n = sqlite3Strlen30(pMem->z); pMem->type = SQLITE_TEXT; pMem->enc = SQLITE_UTF8; pMem++; if( pOp->p4type==P4_SUBPROGRAM ){ int nByte = (nSub+1)*sizeof(SubProgram*); int j; for(j=0; j<nSub; j++){ if( apSub[j]==pOp->p4.pProgram ) break; } if( j==nSub && SQLITE_OK==sqlite3VdbeMemGrow(pSub, nByte, 1) ){ apSub = (SubProgram **)pSub->z; apSub[nSub++] = pOp->p4.pProgram; pSub->flags |= MEM_Blob; pSub->n = nSub*sizeof(SubProgram*); } } } pMem->flags = MEM_Int; pMem->u.i = pOp->p1; /* P1 */ pMem->type = SQLITE_INTEGER; pMem++; |
︙ | ︙ | |||
1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 | ** is passed -1 and nMem, nCursor and isExplain are all passed zero. */ void sqlite3VdbeMakeReady( Vdbe *p, /* The VDBE */ int nVar, /* Number of '?' see in the SQL statement */ int nMem, /* Number of memory cells to allocate */ int nCursor, /* Number of cursors to allocate */ int isExplain /* True if the EXPLAIN keywords is present */ ){ int n; sqlite3 *db = p->db; assert( p!=0 ); assert( p->magic==VDBE_MAGIC_INIT ); | > | 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 | ** is passed -1 and nMem, nCursor and isExplain are all passed zero. */ void sqlite3VdbeMakeReady( Vdbe *p, /* The VDBE */ int nVar, /* Number of '?' see in the SQL statement */ int nMem, /* Number of memory cells to allocate */ int nCursor, /* Number of cursors to allocate */ int nArg, /* Maximum number of args in SubPrograms */ int isExplain /* True if the EXPLAIN keywords is present */ ){ int n; sqlite3 *db = p->db; assert( p!=0 ); assert( p->magic==VDBE_MAGIC_INIT ); |
︙ | ︙ | |||
1126 1127 1128 1129 1130 1131 1132 | ** first time this function is called for a given VDBE, not when it is ** being called from sqlite3_reset() to reset the virtual machine. */ if( nVar>=0 && ALWAYS(db->mallocFailed==0) ){ u8 *zCsr = (u8 *)&p->aOp[p->nOp]; u8 *zEnd = (u8 *)&p->aOp[p->nOpAlloc]; int nByte; | < | 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 | ** first time this function is called for a given VDBE, not when it is ** being called from sqlite3_reset() to reset the virtual machine. */ if( nVar>=0 && ALWAYS(db->mallocFailed==0) ){ u8 *zCsr = (u8 *)&p->aOp[p->nOp]; u8 *zEnd = (u8 *)&p->aOp[p->nOpAlloc]; int nByte; resolveP2Values(p, &nArg); if( isExplain && nMem<10 ){ nMem = 10; } memset(zCsr, 0, zEnd-zCsr); zCsr += (zCsr - (u8*)0)&7; assert( EIGHT_BYTE_ALIGNMENT(zCsr) ); |
︙ | ︙ | |||
1224 1225 1226 1227 1228 1229 1230 1231 1232 | p->inVtabMethod = 0; } #endif if( !pCx->ephemPseudoTable ){ sqlite3DbFree(p->db, pCx->pData); } } /* | > > > > > > > > > > > | > > > > > | > > > > > > > > > > < < < < < < | > > > > > | > | < | 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 | p->inVtabMethod = 0; } #endif if( !pCx->ephemPseudoTable ){ sqlite3DbFree(p->db, pCx->pData); } } int sqlite3VdbeFrameRestore(VdbeFrame *pFrame){ Vdbe *v = pFrame->v; v->aOp = pFrame->aOp; v->nOp = pFrame->nOp; v->aMem = pFrame->aMem; v->nMem = pFrame->nMem; v->apCsr = pFrame->apCsr; v->nCursor = pFrame->nCursor; return pFrame->pc; } /* ** Close all cursors. ** ** Also release any dynamic memory held by the VM in the Vdbe.aMem memory ** cell array. This is necessary as the memory cell array may contain ** pointers to VdbeFrame objects, which may in turn contain pointers to ** open cursors. */ static void closeAllCursors(Vdbe *p){ int i; /* if( p->apCsr==0 ) return; */ if( p->pFrame ){ VdbeFrame *pFrame = p->pFrame; for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent); sqlite3VdbeFrameRestore(pFrame); } p->pFrame = 0; p->nFrame = 0; for(i=0; i<p->nCursor; i++){ VdbeCursor *pC = p->apCsr[i]; if( pC ){ sqlite3VdbeFreeCursor(p, pC); p->apCsr[i] = 0; } } releaseMemArray(&p->aMem[1], p->nMem); } /* ** Clean up the VM after execution. ** ** This routine will automatically close any cursors, lists, and/or ** sorters that were left open. It also deletes the values of ** variables in the aVar[] array. */ static void Cleanup(Vdbe *p){ sqlite3 *db = p->db; #ifdef SQLITE_DEBUG /* Execute assert() statements to ensure that the Vdbe.apCsr[] and ** Vdbe.aMem[] arrays have already been cleaned up. */ int i; for(i=0; i<p->nCursor; i++){ assert( p->apCsr[i]==0 ); } for(i=1; i<=p->nMem; i++){ assert( p->aMem[i].flags==MEM_Null ); } #endif if( p->contextStack ){ sqlite3DbFree(db, p->contextStack); } p->contextStack = 0; p->contextStackDepth = 0; p->contextStackTop = 0; sqlite3DbFree(db, p->zErrMsg); |
︙ | ︙ | |||
1989 1990 1991 1992 1993 1994 1995 | } } /* ** Delete an entire VDBE. */ void sqlite3VdbeDelete(Vdbe *p){ | < < < < < < < < < < < > > < | 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 | } } /* ** Delete an entire VDBE. */ void sqlite3VdbeDelete(Vdbe *p){ sqlite3 *db; if( NEVER(p==0) ) return; db = p->db; if( p->pPrev ){ p->pPrev->pNext = p->pNext; }else{ assert( db->pVdbe==p ); db->pVdbe = p->pNext; } if( p->pNext ){ p->pNext->pPrev = p->pPrev; } releaseMemArray(p->aVar, p->nVar); releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); vdbeFreeOpArray(db, p->aOp, p->nOp); sqlite3DbFree(db, p->aLabel); sqlite3DbFree(db, p->aColName); sqlite3DbFree(db, p->zSql); p->magic = VDBE_MAGIC_DEAD; sqlite3DbFree(db, p->pFree); sqlite3DbFree(db, p); } /* ** Make sure the cursor p is ready to read or write the row to which it ** was last positioned. Return an error code if an OOM fault or I/O error |
︙ | ︙ |
Changes to src/vdbeblob.c.
︙ | ︙ | |||
200 201 202 203 204 205 206 | ** always return an SQL NULL. This is useful because it means ** we can invoke OP_Column to fill in the vdbe cursors type ** and offset cache without causing any IO. */ sqlite3VdbeChangeP4(v, 3+flags, SQLITE_INT_TO_PTR(pTab->nCol+1),P4_INT32); sqlite3VdbeChangeP2(v, 7, pTab->nCol); if( !db->mallocFailed ){ | | | 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 | ** always return an SQL NULL. This is useful because it means ** we can invoke OP_Column to fill in the vdbe cursors type ** and offset cache without causing any IO. */ sqlite3VdbeChangeP4(v, 3+flags, SQLITE_INT_TO_PTR(pTab->nCol+1),P4_INT32); sqlite3VdbeChangeP2(v, 7, pTab->nCol); if( !db->mallocFailed ){ sqlite3VdbeMakeReady(v, 1, 1, 1, 0, 0); } } sqlite3BtreeLeaveAll(db); rc = sqlite3SafetyOff(db); if( NEVER(rc!=SQLITE_OK) || db->mallocFailed ){ goto blob_open_out; |
︙ | ︙ |
Changes to src/vdbemem.c.
︙ | ︙ | |||
266 267 268 269 270 271 272 | /* ** If the memory cell contains a string value that must be freed by ** invoking an external callback, free it now. Calling this function ** does not free any Mem.zMalloc buffer. */ void sqlite3VdbeMemReleaseExternal(Mem *p){ assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) ); | | > > > | 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 | /* ** If the memory cell contains a string value that must be freed by ** invoking an external callback, free it now. Calling this function ** does not free any Mem.zMalloc buffer. */ void sqlite3VdbeMemReleaseExternal(Mem *p){ assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) ); if( p->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame) ){ if( p->flags&MEM_Agg ){ sqlite3VdbeMemFinalize(p, p->u.pDef); assert( (p->flags & MEM_Agg)==0 ); sqlite3VdbeMemRelease(p); }else if( p->flags&MEM_Dyn && p->xDel ){ assert( (p->flags&MEM_RowSet)==0 ); p->xDel((void *)p->z); p->xDel = 0; }else if( p->flags&MEM_RowSet ){ sqlite3RowSetClear(p->u.pRowSet); }else if( p->flags&MEM_Frame ){ sqlite3VdbeFrameDelete(p->u.pFrame); p->flags &= ~MEM_Frame; } } } /* ** Release any memory held by the Mem. This may leave the Mem in an ** inconsistent state, for example with (Mem.z==0) and |
︙ | ︙ | |||
478 479 480 481 482 483 484 485 486 487 488 489 490 491 | return SQLITE_OK; } /* ** Delete any previous value and set the value stored in *pMem to NULL. */ void sqlite3VdbeMemSetNull(Mem *pMem){ if( pMem->flags & MEM_RowSet ){ sqlite3RowSetClear(pMem->u.pRowSet); } MemSetTypeFlag(pMem, MEM_Null); pMem->type = SQLITE_NULL; } | > > > | 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 | return SQLITE_OK; } /* ** Delete any previous value and set the value stored in *pMem to NULL. */ void sqlite3VdbeMemSetNull(Mem *pMem){ if( pMem->flags & MEM_Frame ){ sqlite3VdbeFrameDelete(pMem->u.pFrame); } if( pMem->flags & MEM_RowSet ){ sqlite3RowSetClear(pMem->u.pRowSet); } MemSetTypeFlag(pMem, MEM_Null); pMem->type = SQLITE_NULL; } |
︙ | ︙ |
Changes to src/vtab.c.
︙ | ︙ | |||
939 940 941 942 943 944 945 946 947 | ** array so that an OP_VBegin will get generated for it. Add pTab to the ** array if it is missing. If pTab is already in the array, this routine ** is a no-op. */ void sqlite3VtabMakeWritable(Parse *pParse, Table *pTab){ int i, n; Table **apVtabLock; assert( IsVirtual(pTab) ); | > | | | | | | | | 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 | ** array so that an OP_VBegin will get generated for it. Add pTab to the ** array if it is missing. If pTab is already in the array, this routine ** is a no-op. */ void sqlite3VtabMakeWritable(Parse *pParse, Table *pTab){ int i, n; Table **apVtabLock; Parse *pRoot = (pParse->pRoot ? pParse->pRoot : pParse); assert( IsVirtual(pTab) ); for(i=0; i<pRoot->nVtabLock; i++){ if( pTab==pRoot->apVtabLock[i] ) return; } n = (pRoot->nVtabLock+1)*sizeof(pRoot->apVtabLock[0]); apVtabLock = sqlite3_realloc(pRoot->apVtabLock, n); if( apVtabLock ){ pRoot->apVtabLock = apVtabLock; pRoot->apVtabLock[pRoot->nVtabLock++] = pTab; }else{ pRoot->db->mallocFailed = 1; } } #endif /* SQLITE_OMIT_VIRTUALTABLE */ |
Changes to test/attach3.test.
︙ | ︙ | |||
313 314 315 316 317 318 319 320 321 322 323 324 325 326 | do_test attach3-12.9 { execsql { ATTACH DATABASE '' AS NULL } db_list } {main temp {}} do_test attach3-12.10 { execsql { DETACH ? } db_list } {main temp} do_test attach3-12.11 { catchsql { | > | 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 | do_test attach3-12.9 { execsql { ATTACH DATABASE '' AS NULL } db_list } {main temp {}} do_test attach3-12.10 { breakpoint execsql { DETACH ? } db_list } {main temp} do_test attach3-12.11 { catchsql { |
︙ | ︙ |
Changes to test/autoinc.test.
︙ | ︙ | |||
20 21 22 23 24 25 26 27 28 29 30 31 32 33 | # If the library is not compiled with autoincrement support then # skip all tests in this file. # ifcapable {!autoinc} { finish_test return } # The database is initially empty. # do_test autoinc-1.1 { execsql { SELECT name FROM sqlite_master WHERE type='table'; } | > > | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | # If the library is not compiled with autoincrement support then # skip all tests in this file. # ifcapable {!autoinc} { finish_test return } sqlite3_db_config_lookaside db 0 0 0 # The database is initially empty. # do_test autoinc-1.1 { execsql { SELECT name FROM sqlite_master WHERE type='table'; } |
︙ | ︙ |
Changes to test/trigger1.test.
︙ | ︙ | |||
59 60 61 62 63 64 65 | catchsql { CREATE TRIGGER trig UPDATE ON t1 FOR EACH STATEMENT BEGIN SELECT * FROM sqlite_master; END; } } {1 {near "STATEMENT": syntax error}} execsql { | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 162 163 | catchsql { CREATE TRIGGER trig UPDATE ON t1 FOR EACH STATEMENT BEGIN SELECT * FROM sqlite_master; END; } } {1 {near "STATEMENT": syntax error}} execsql { CREATE TRIGGER tr1 INSERT ON t1 BEGIN INSERT INTO t1 values(1); END; } do_test trigger1-1.2.0 { catchsql { CREATE TRIGGER IF NOT EXISTS tr1 DELETE ON t1 BEGIN SELECT * FROM sqlite_master; END } } {0 {}} do_test trigger1-1.2.1 { catchsql { CREATE TRIGGER tr1 DELETE ON t1 BEGIN SELECT * FROM sqlite_master; END } } {1 {trigger tr1 already exists}} do_test trigger1-1.2.2 { catchsql { CREATE TRIGGER "tr1" DELETE ON t1 BEGIN SELECT * FROM sqlite_master; END } } {1 {trigger "tr1" already exists}} do_test trigger1-1.2.3 { catchsql { CREATE TRIGGER [tr1] DELETE ON t1 BEGIN SELECT * FROM sqlite_master; END } } {1 {trigger [tr1] already exists}} do_test trigger1-1.3 { catchsql { BEGIN; CREATE TRIGGER tr2 INSERT ON t1 BEGIN SELECT * from sqlite_master; END; ROLLBACK; CREATE TRIGGER tr2 INSERT ON t1 BEGIN SELECT * from sqlite_master; END; } } {0 {}} do_test trigger1-1.4 { catchsql { DROP TRIGGER IF EXISTS tr1; CREATE TRIGGER tr1 DELETE ON t1 BEGIN SELECT * FROM sqlite_master; END } } {0 {}} do_test trigger1-1.5 { execsql { BEGIN; DROP TRIGGER tr2; ROLLBACK; DROP TRIGGER tr2; } } {} do_test trigger1-1.6.1 { catchsql { DROP TRIGGER IF EXISTS biggles; } } {0 {}} do_test trigger1-1.6.2 { catchsql { DROP TRIGGER biggles; } } {1 {no such trigger: biggles}} do_test trigger1-1.7 { catchsql { DROP TABLE t1; DROP TRIGGER tr1; } } {1 {no such trigger: tr1}} ifcapable tempdb { execsql { CREATE TEMP TABLE temp_table(a); } do_test trigger1-1.8 { execsql { CREATE TRIGGER temp_trig UPDATE ON temp_table BEGIN SELECT * from sqlite_master; END; SELECT count(*) FROM sqlite_master WHERE name = 'temp_trig'; } } {0} } do_test trigger1-1.9 { catchsql { CREATE TRIGGER tr1 AFTER UPDATE ON sqlite_master BEGIN |
︙ | ︙ | |||
399 400 401 402 403 404 405 | } do_test trigger1-6.1 { execsql {SELECT type, name FROM sqlite_master} } [concat $view_v1 {table t2}] do_test trigger1-6.2 { execsql { CREATE TRIGGER t2 BEFORE DELETE ON t2 BEGIN | | | | 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 | } do_test trigger1-6.1 { execsql {SELECT type, name FROM sqlite_master} } [concat $view_v1 {table t2}] do_test trigger1-6.2 { execsql { CREATE TRIGGER t2 BEFORE DELETE ON t2 BEGIN SELECT RAISE(ABORT,'deletes are not permitted'); END; SELECT type, name FROM sqlite_master; } } [concat $view_v1 {table t2 trigger t2}] do_test trigger1-6.3 { catchsql {DELETE FROM t2} } {1 {deletes are not permitted}} do_test trigger1-6.4 { execsql {SELECT * FROM t2} } {3 4 7 8} do_test trigger1-6.5 { db close sqlite3 db test.db execsql {SELECT type, name FROM sqlite_master} |
︙ | ︙ |
Changes to test/trigger8.test.
︙ | ︙ | |||
28 29 30 31 32 33 34 35 36 37 38 39 40 41 | # heap, use 1000. # set nStatement 10000 if {$tcl_platform(platform) == "symbian"} { set nStatement 1000 } do_test trigger8-1.1 { execsql { CREATE TABLE t1(x); CREATE TABLE t2(y); } set sql "CREATE TRIGGER r${nStatement} AFTER INSERT ON t1 BEGIN\n" for {set i 0} {$i<$nStatement} {incr i} { | > | 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | # heap, use 1000. # set nStatement 10000 if {$tcl_platform(platform) == "symbian"} { set nStatement 1000 } set nStatement 5 do_test trigger8-1.1 { execsql { CREATE TABLE t1(x); CREATE TABLE t2(y); } set sql "CREATE TRIGGER r${nStatement} AFTER INSERT ON t1 BEGIN\n" for {set i 0} {$i<$nStatement} {incr i} { |
︙ | ︙ |