Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merge the ListPush and ListPop VDBE opcodes into ContextPush and ContextPop. (CVS 1972) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
eb9b501ad8b0fa0fd63a67ece05fe142 |
User & Date: | drh 2004-09-19 00:50:21.000 |
Context
2004-09-19
| ||
02:15 | Add comments to unused P3 fields of selected instructions when NDEBUG is not defined. This makes VDBE program dumps more readable during debugging. (CVS 1973) (check-in: 4871c77f8f user: drh tags: trunk) | |
00:50 | Merge the ListPush and ListPop VDBE opcodes into ContextPush and ContextPop. (CVS 1972) (check-in: eb9b501ad8 user: drh tags: trunk) | |
2004-09-18
| ||
18:51 | Fix typo on homepage. (CVS 1971) (check-in: 5d3b3a96bc user: drh tags: trunk) | |
Changes
Changes to src/expr.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** ** $Id: expr.c,v 1.162 2004/09/19 00:50:21 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> char const *sqlite3AffinityString(char affinity){ switch( affinity ){ case SQLITE_AFF_INTEGER: return "i"; |
︙ | ︙ | |||
1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 | pExpr->iColumn == OE_Abort || pExpr->iColumn == OE_Fail ){ sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->iColumn, pExpr->token.z, pExpr->token.n); sqlite3VdbeDequoteP3(v, -1); } else { assert( pExpr->iColumn == OE_Ignore ); sqlite3VdbeOp3(v, OP_Goto, 0, pParse->trigStack->ignoreJump, "(IGNORE jump)", 0); } } break; } } | > | 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 | pExpr->iColumn == OE_Abort || pExpr->iColumn == OE_Fail ){ sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->iColumn, pExpr->token.z, pExpr->token.n); sqlite3VdbeDequoteP3(v, -1); } else { assert( pExpr->iColumn == OE_Ignore ); sqlite3VdbeAddOp(v, OP_ContextPop, 0, 0); sqlite3VdbeOp3(v, OP_Goto, 0, pParse->trigStack->ignoreJump, "(IGNORE jump)", 0); } } break; } } |
︙ | ︙ |
Changes to src/trigger.c.
︙ | ︙ | |||
641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 | 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 * pTriggerStep = pStepList; int orconf; while( pTriggerStep ){ orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin; pParse->trigStack->orconf = orconf; switch( pTriggerStep->op ){ case TK_SELECT: { Select * ss = sqlite3SelectDup(pTriggerStep->pSelect); assert(ss); assert(ss->pSrc); sqlite3Select(pParse, ss, SRT_Discard, 0, 0, 0, 0, 0); sqlite3SelectDelete(ss); break; } case TK_UPDATE: { SrcList *pSrc; pSrc = targetSrcList(pParse, pTriggerStep); | > > > > | < < | | | | < < | > | 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 667 668 669 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 | 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 * pTriggerStep = pStepList; int orconf; Vdbe *v = pParse->pVdbe; assert( pTriggerStep!=0 ); assert( v!=0 ); sqlite3VdbeAddOp(v, OP_ContextPush, 0, 0); while( pTriggerStep ){ orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin; pParse->trigStack->orconf = orconf; switch( pTriggerStep->op ){ case TK_SELECT: { Select * ss = sqlite3SelectDup(pTriggerStep->pSelect); assert(ss); assert(ss->pSrc); sqlite3Select(pParse, ss, SRT_Discard, 0, 0, 0, 0, 0); sqlite3SelectDelete(ss); break; } case TK_UPDATE: { SrcList *pSrc; pSrc = targetSrcList(pParse, pTriggerStep); sqlite3VdbeAddOp(v, OP_ResetCount, 0, 0); sqlite3Update(pParse, pSrc, sqlite3ExprListDup(pTriggerStep->pExprList), sqlite3ExprDup(pTriggerStep->pWhere), orconf); sqlite3VdbeAddOp(v, OP_ResetCount, 1, 0); break; } case TK_INSERT: { SrcList *pSrc; pSrc = targetSrcList(pParse, pTriggerStep); sqlite3VdbeAddOp(v, OP_ResetCount, 0, 0); sqlite3Insert(pParse, pSrc, sqlite3ExprListDup(pTriggerStep->pExprList), sqlite3SelectDup(pTriggerStep->pSelect), sqlite3IdListDup(pTriggerStep->pIdList), orconf); sqlite3VdbeAddOp(v, OP_ResetCount, 1, 0); break; } case TK_DELETE: { SrcList *pSrc; sqlite3VdbeAddOp(v, OP_ResetCount, 0, 0); pSrc = targetSrcList(pParse, pTriggerStep); sqlite3DeleteFrom(pParse, pSrc, sqlite3ExprDup(pTriggerStep->pWhere)); sqlite3VdbeAddOp(v, OP_ResetCount, 1, 0); break; } default: assert(0); } pTriggerStep = pTriggerStep->pNext; } sqlite3VdbeAddOp(v, OP_ContextPop, 0, 0); return 0; } /* ** This is called to code FOR EACH ROW triggers. ** |
︙ | ︙ | |||
786 787 788 789 790 791 792 | sqliteFree(pTriggerStack); sqlite3ExprDelete(whenExpr); return 1; } sqlite3ExprIfFalse(pParse, whenExpr, endTrigger, 1); sqlite3ExprDelete(whenExpr); | < < | 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 | sqliteFree(pTriggerStack); sqlite3ExprDelete(whenExpr); return 1; } sqlite3ExprIfFalse(pParse, whenExpr, endTrigger, 1); sqlite3ExprDelete(whenExpr); codeTriggerProgram(pParse, pTrigger->step_list, orconf); /* Pop the entry off the trigger stack */ pParse->trigStack = pParse->trigStack->pNext; sqlite3AuthContextPop(&sContext); sqliteFree(pTriggerStack); sqlite3VdbeResolveLabel(pParse->pVdbe, endTrigger); } pTrigger = pTrigger->pNext; } return 0; } |
Changes to src/vdbe.c.
︙ | ︙ | |||
39 40 41 42 43 44 45 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** | | | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** ** $Id: vdbe.c,v 1.415 2004/09/19 00:50:21 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> #include "vdbeInt.h" /* |
︙ | ︙ | |||
3068 3069 3070 3071 3072 3073 3074 | ** This opcode resets the VMs internal change counter to 0. If P1 is true, ** then the value of the change counter is copied to the database handle ** change counter (returned by subsequent calls to sqlite3_changes()) ** before it is reset. This is used by trigger programs. */ case OP_ResetCount: { if( pOp->p1 ){ | | | 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 | ** This opcode resets the VMs internal change counter to 0. If P1 is true, ** then the value of the change counter is copied to the database handle ** change counter (returned by subsequent calls to sqlite3_changes()) ** before it is reset. This is used by trigger programs. */ case OP_ResetCount: { if( pOp->p1 ){ sqlite3VdbeSetChanges(db, p->nChange); } p->nChange = 0; break; } /* Opcode: KeyAsData P1 P2 * ** |
︙ | ︙ | |||
3890 3891 3892 3893 3894 3895 3896 | if( p->pList ){ sqlite3VdbeKeylistFree(p->pList); p->pList = 0; } break; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | > | | > | | | > | > > | | | | < | | < | 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 | if( p->pList ){ sqlite3VdbeKeylistFree(p->pList); p->pList = 0; } break; } /* Opcode: ContextPush * * * ** ** Save the current Vdbe context such that it can be restored by a ContextPop ** opcode. The context stores the last insert row id, the last statement change ** count, and the current statement change count. */ case OP_ContextPush: { int i = p->contextStackTop++; Context *pContext; assert( i>=0 ); /* FIX ME: This should be allocated as part of the vdbe at compile-time */ if( i>=p->contextStackDepth ){ p->contextStackDepth = i+1; p->contextStack = sqliteRealloc(p->contextStack, sizeof(Context)*(i+1)); if( p->contextStack==0 ) goto no_mem; } pContext = &p->contextStack[i]; pContext->lastRowid = db->lastRowid; pContext->nChange = p->nChange; pContext->pList = p->pList; p->pList = 0; break; } /* Opcode: ContextPop * * * ** ** Restore the Vdbe context to the state it was in when contextPush was last ** executed. The context stores the last insert row id, the last statement ** change count, and the current statement change count. */ case OP_ContextPop: { Context *pContext = &p->contextStack[--p->contextStackTop]; assert( p->contextStackTop>=0 ); db->lastRowid = pContext->lastRowid; p->nChange = pContext->nChange; sqlite3VdbeKeylistFree(p->pList); p->pList = pContext->pList; break; } /* Opcode: SortPut * * * ** ** The TOS is the key and the NOS is the data. Pop both from the stack ** and put them on the sorter. The key and data should have been |
︙ | ︙ |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
274 275 276 277 278 279 280 281 | Keylist *pNext; /* Next block of keys */ i64 aKey[1]; /* One or more keys. Extra space allocated as needed */ }; /* ** A Context stores the last insert rowid, the last statement change count, ** and the current statement change count (i.e. changes since last statement). ** Elements of Context structure type make up the ContextStack, which is | > | > > > | 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 | Keylist *pNext; /* Next block of keys */ i64 aKey[1]; /* One or more keys. Extra space allocated as needed */ }; /* ** A Context stores the last insert rowid, the last statement change count, ** and the current statement change count (i.e. changes since last statement). ** The current keylist is also stored in the context. ** Elements of Context structure type make up the ContextStack, which is ** updated by the ContextPush and ContextPop opcodes (used by triggers). ** The context is pushed before executing a trigger a popped when the ** trigger finishes. */ typedef struct Context Context; struct Context { int lastRowid; /* Last insert rowid (sqlite3.lastRowid) */ int nChange; /* Statement changes (Vdbe.nChanges) */ Keylist *pList; /* Records that will participate in a DELETE or UPDATE */ }; /* ** An instance of the virtual machine. This structure contains the complete ** state of the virtual machine. ** ** The "sqlite3_stmt" structure pointer that is returned by sqlite3_compile() |
︙ | ︙ | |||
317 318 319 320 321 322 323 | int okVar; /* True if azVar[] has been initialized */ int magic; /* Magic number for sanity checking */ int nMem; /* Number of memory locations currently allocated */ Mem *aMem; /* The memory locations */ Agg agg; /* Aggregate information */ int nCallback; /* Number of callbacks invoked so far */ Keylist *pList; /* A list of ROWIDs */ | | < | 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 | int okVar; /* True if azVar[] has been initialized */ int magic; /* Magic number for sanity checking */ int nMem; /* Number of memory locations currently allocated */ Mem *aMem; /* The memory locations */ Agg agg; /* Aggregate information */ int nCallback; /* Number of callbacks invoked so far */ Keylist *pList; /* A list of ROWIDs */ int contextStackTop; /* Index of top element in the context stack */ int contextStackDepth; /* The size of the "context" stack */ Context *contextStack; /* Stack used by opcodes ContextPush & ContextPop*/ int pc; /* The program counter */ int rc; /* Value to return */ unsigned uniqueCnt; /* Used by OP_MakeRecord when P2!=0 */ int errorAction; /* Recovery action to do in case of an error */ int inTempTrans; /* True if temp database is transactioned */ |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
842 843 844 845 846 847 848 849 850 | for(i=0; i<p->nMem; i++){ sqlite3VdbeMemRelease(&p->aMem[i]); } if( p->pList ){ sqlite3VdbeKeylistFree(p->pList); p->pList = 0; } sqlite3VdbeSorterReset(p); sqlite3VdbeAggReset(0, &p->agg, 0); | > > > < < < < < | < | < | | | 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 | for(i=0; i<p->nMem; i++){ sqlite3VdbeMemRelease(&p->aMem[i]); } if( p->pList ){ sqlite3VdbeKeylistFree(p->pList); p->pList = 0; } for(i=0; i<p->contextStackTop; i++){ sqlite3VdbeKeylistFree(p->contextStack[i].pList); } sqlite3VdbeSorterReset(p); sqlite3VdbeAggReset(0, &p->agg, 0); sqliteFree(p->contextStack); p->contextStack = 0; p->contextStackDepth = 0; p->contextStackTop = 0; sqliteFree(p->zErrMsg); p->zErrMsg = 0; } /* ** Set the number of result columns that will be returned by this SQL ** statement. This is now set at compile time, rather than during |
︙ | ︙ |