1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-08 14:02:16 +03:00

Add the new OP_Once opcode. Use it to clean up and simplify various

one-time initialization sections in the code, including the fix for
ticket [002caede898ae].

FossilOrigin-Name: 7f00552b739fad79517b042a6ed61abe743a917b
This commit is contained in:
drh
2011-09-16 01:34:43 +00:00
parent 5b6a9ed495
commit 48f2d3b10a
9 changed files with 51 additions and 41 deletions

View File

@@ -1,5 +1,5 @@
C Materialize\ssubqueries\susing\sa\ssubroutine\sand\sinvoke\sthat\ssubroutine\nprior\sto\seach\suse\sof\sthe\ssubqueries\smanifestation.\s\sFix\sfor\nticket\s[002caede898aee4] C Add\sthe\snew\sOP_Once\sopcode.\s\sUse\sit\sto\sclean\sup\sand\ssimplify\svarious\none-time\sinitialization\ssections\sin\sthe\scode,\sincluding\sthe\sfix\sfor\nticket\s[002caede898ae].
D 2011-09-15T23:58:14.314 D 2011-09-16T01:34:43.377
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in d314143fa6be24828021d3f583ad37d9afdce505 F Makefile.in d314143fa6be24828021d3f583ad37d9afdce505
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -133,7 +133,7 @@ F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
F src/ctime.c e3132ec65240b2e2f3d50831021eac387f27584d F src/ctime.c e3132ec65240b2e2f3d50831021eac387f27584d
F src/date.c a3c6842bad7ae632281811de112a8ba63ff08ab3 F src/date.c a3c6842bad7ae632281811de112a8ba63ff08ab3
F src/delete.c ff68e5ef23aee08c0ff528f699a19397ed8bbed8 F src/delete.c ff68e5ef23aee08c0ff528f699a19397ed8bbed8
F src/expr.c 109de1d4a58d25c062a79d7e84bdbb77b348844e F src/expr.c fd54c517869919c9b0b11dcadd43c66540ffa682
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c 9f00ea98f6b360d477b5a78b5b59a1fbde82431c F src/fkey.c 9f00ea98f6b360d477b5a78b5b59a1fbde82431c
F src/func.c 59bb046d7e3df1ab512ac339ccb0a6f996a17cb7 F src/func.c 59bb046d7e3df1ab512ac339ccb0a6f996a17cb7
@@ -179,7 +179,7 @@ F src/printf.c 585a36b6a963df832cfb69505afa3a34ed5ef8a1
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
F src/resolve.c 36368f44569208fa074e61f4dd0b6c4fb60ca2b4 F src/resolve.c 36368f44569208fa074e61f4dd0b6c4fb60ca2b4
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
F src/select.c d85d83c334a3842b47d14e0574acb5f531d5579a F src/select.c c7ea7cd4462cc44a40012ebbdcd31a83ac1e7274
F src/shell.c bbe7818ff5bc8614105ceb81ad67b8bdc0b671dd F src/shell.c bbe7818ff5bc8614105ceb81ad67b8bdc0b671dd
F src/sqlite.h.in 0a6c9c23337fd1352c5c75a613ff9533aa7d91cb F src/sqlite.h.in 0a6c9c23337fd1352c5c75a613ff9533aa7d91cb
F src/sqlite3ext.h 1a1a4f784aa9c3b00edd287940197de52487cd93 F src/sqlite3ext.h 1a1a4f784aa9c3b00edd287940197de52487cd93
@@ -238,12 +238,12 @@ F src/update.c 74a6cfb34e9732c1e2a86278b229913b4b51eeec
F src/utf.c c53eb7404b3eb5c1cbb5655c6a7a0e0ce6bd50f0 F src/utf.c c53eb7404b3eb5c1cbb5655c6a7a0e0ce6bd50f0
F src/util.c 06302ffd2b80408d4f6c7af71f7090e0cf8d8ff7 F src/util.c 06302ffd2b80408d4f6c7af71f7090e0cf8d8ff7
F src/vacuum.c 05513dca036a1e7848fe18d5ed1265ac0b32365e F src/vacuum.c 05513dca036a1e7848fe18d5ed1265ac0b32365e
F src/vdbe.c 7008edbf8f608d82c035dcb1c56367ad85e68aaa F src/vdbe.c 60340bfb23f456ea0791cb28262a887363773371
F src/vdbe.h a10b360bf69474babc8aba8fcc64b824c5e97d38 F src/vdbe.h f0725ee997db869ecae5bb70a71612aabeca7755
F src/vdbeInt.h 693d6ac6810298fc6b4c503cfbe3f99a240f40af F src/vdbeInt.h 693d6ac6810298fc6b4c503cfbe3f99a240f40af
F src/vdbeapi.c 11dc47987abacb76ad016dcf5abc0dc422482a98 F src/vdbeapi.c 11dc47987abacb76ad016dcf5abc0dc422482a98
F src/vdbeaux.c ca8aa399e1be85fe82498b107128297a5d84e6a2 F src/vdbeaux.c 49be7a5ce6a1b7df9ef5791133c3e4e6ab2a1ffe
F src/vdbeblob.c f024f0bf420f36b070143c32b15cc7287341ffd3 F src/vdbeblob.c 32f2a4899d67f69634ea4dd93e3f651936d732cb
F src/vdbemem.c 5e6effb96dd53d233361cbfaa3f0a43b9af689e9 F src/vdbemem.c 5e6effb96dd53d233361cbfaa3f0a43b9af689e9
F src/vdbesort.c 468d43c057063e54da4f1988b38b4f46d60e7790 F src/vdbesort.c 468d43c057063e54da4f1988b38b4f46d60e7790
F src/vdbetrace.c 5d0dc3d5fd54878cc8d6d28eb41deb8d5885b114 F src/vdbetrace.c 5d0dc3d5fd54878cc8d6d28eb41deb8d5885b114
@@ -251,7 +251,7 @@ F src/vtab.c 901791a47318c0562cd0c676a2c6ff1bc530e582
F src/wal.c 3154756177d6219e233d84291d5b05f4e06ff5e9 F src/wal.c 3154756177d6219e233d84291d5b05f4e06ff5e9
F src/wal.h 66b40bd91bc29a5be1c88ddd1f5ade8f3f48728a F src/wal.h 66b40bd91bc29a5be1c88ddd1f5ade8f3f48728a
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
F src/where.c 7d09f4c1512affb60cc1190a4b33d121d4ce039a F src/where.c e7be35164f139003c9786921b8147ff5309254b0
F test/8_3_names.test 631ea964a3edb091cf73c3b540f6bcfdb36ce823 F test/8_3_names.test 631ea964a3edb091cf73c3b540f6bcfdb36ce823
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87 F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
@@ -961,7 +961,7 @@ F tool/symbols.sh caaf6ccc7300fd43353318b44524853e222557d5
F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
F tool/warnings.sh b7fdb2cc525f5ef4fa43c80e771636dd3690f9d2 F tool/warnings.sh b7fdb2cc525f5ef4fa43c80e771636dd3690f9d2
P 62dfc51a495be017605cf315d72e2db91bfa28f7 P 4b8357ee3c4ccdbd34e0cd077efd84cca677f496
R 6d5602e8586fba23bb68456f6fac9e14 R dfebcfb6ba63e648417a1c83afb0ef8f
U drh U drh
Z 035be646ae967eef8d7d2956eeb67c86 Z cfef9124ccdf6e060b8c4225e574e5d5

View File

@@ -1 +1 @@
4b8357ee3c4ccdbd34e0cd077efd84cca677f496 7f00552b739fad79517b042a6ed61abe743a917b

View File

@@ -1462,8 +1462,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
int iMem = ++pParse->nMem; int iMem = ++pParse->nMem;
int iAddr; int iAddr;
iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem); iAddr = sqlite3VdbeAddOp1(v, OP_Once, iMem);
sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem);
sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
eType = IN_INDEX_ROWID; eType = IN_INDEX_ROWID;
@@ -1494,8 +1493,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
char *pKey; char *pKey;
pKey = (char *)sqlite3IndexKeyinfo(pParse, pIdx); pKey = (char *)sqlite3IndexKeyinfo(pParse, pIdx);
iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem); iAddr = sqlite3VdbeAddOp1(v, OP_Once, iMem);
sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem);
sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb, sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb,
pKey,P4_KEYINFO_HANDOFF); pKey,P4_KEYINFO_HANDOFF);
@@ -1580,6 +1578,7 @@ int sqlite3CodeSubselect(
int rReg = 0; /* Register storing resulting */ int rReg = 0; /* Register storing resulting */
Vdbe *v = sqlite3GetVdbe(pParse); Vdbe *v = sqlite3GetVdbe(pParse);
if( NEVER(v==0) ) return 0; if( NEVER(v==0) ) return 0;
assert( sqlite3VdbeCurrentAddr(v)>0 );
sqlite3ExprCachePush(pParse); sqlite3ExprCachePush(pParse);
/* This code must be run in its entirety every time it is encountered /* This code must be run in its entirety every time it is encountered
@@ -1594,8 +1593,7 @@ int sqlite3CodeSubselect(
*/ */
if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->pTriggerTab ){ if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->pTriggerTab ){
int mem = ++pParse->nMem; int mem = ++pParse->nMem;
sqlite3VdbeAddOp1(v, OP_If, mem); testAddr = sqlite3VdbeAddOp1(v, OP_Once, mem);
testAddr = sqlite3VdbeAddOp2(v, OP_Integer, 1, mem);
assert( testAddr>0 || pParse->db->mallocFailed ); assert( testAddr>0 || pParse->db->mallocFailed );
} }
@@ -1695,7 +1693,7 @@ int sqlite3CodeSubselect(
** expression we need to rerun this code each time. ** expression we need to rerun this code each time.
*/ */
if( testAddr && !sqlite3ExprIsConstant(pE2) ){ if( testAddr && !sqlite3ExprIsConstant(pE2) ){
sqlite3VdbeChangeToNoop(v, testAddr-1, 2); sqlite3VdbeChangeToNoop(v, testAddr);
testAddr = 0; testAddr = 0;
} }
@@ -1766,7 +1764,7 @@ int sqlite3CodeSubselect(
} }
if( testAddr ){ if( testAddr ){
sqlite3VdbeJumpHere(v, testAddr-1); sqlite3VdbeJumpHere(v, testAddr);
} }
sqlite3ExprCachePop(pParse, 1); sqlite3ExprCachePop(pParse, 1);

View File

@@ -3831,7 +3831,7 @@ int sqlite3Select(
** is a register allocated to hold the subroutine return address ** is a register allocated to hold the subroutine return address
*/ */
int topAddr = sqlite3VdbeAddOp0(v, OP_Goto); int topAddr = sqlite3VdbeAddOp0(v, OP_Goto);
int regOnce = 0; int onceAddr = 0;
assert( pItem->addrFillSub==0 ); assert( pItem->addrFillSub==0 );
pItem->addrFillSub = topAddr+1; pItem->addrFillSub = topAddr+1;
pItem->regReturn = ++pParse->nMem; pItem->regReturn = ++pParse->nMem;
@@ -3839,15 +3839,14 @@ int sqlite3Select(
/* If the subquery is no correlated and if we are not inside of /* If the subquery is no correlated and if we are not inside of
** a trigger, then we only need to compute the value of the subquery ** a trigger, then we only need to compute the value of the subquery
** once. */ ** once. */
regOnce = ++pParse->nMem; int regOnce = ++pParse->nMem;
sqlite3VdbeAddOp1(v, OP_If, regOnce); onceAddr = sqlite3VdbeAddOp1(v, OP_Once, regOnce);
sqlite3VdbeAddOp2(v, OP_Integer, 1, regOnce);
} }
sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor); sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId); explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
sqlite3Select(pParse, pSub, &dest); sqlite3Select(pParse, pSub, &dest);
pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow; pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow;
if( regOnce ) sqlite3VdbeJumpHere(v, topAddr+1); if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn); sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
sqlite3VdbeJumpHere(v, topAddr); sqlite3VdbeJumpHere(v, topAddr);
sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, topAddr+1); sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, topAddr+1);
@@ -3991,7 +3990,7 @@ int sqlite3Select(
** into an OP_Noop. ** into an OP_Noop.
*/ */
if( addrSortIndex>=0 && pOrderBy==0 ){ if( addrSortIndex>=0 && pOrderBy==0 ){
sqlite3VdbeChangeToNoop(v, addrSortIndex, 1); sqlite3VdbeChangeToNoop(v, addrSortIndex);
p->addrOpenEphm[2] = -1; p->addrOpenEphm[2] = -1;
} }
@@ -4274,7 +4273,7 @@ int sqlite3Select(
sqlite3VdbeAddOp2(v, OP_SorterNext, sAggInfo.sortingIdx, addrTopOfLoop); sqlite3VdbeAddOp2(v, OP_SorterNext, sAggInfo.sortingIdx, addrTopOfLoop);
}else{ }else{
sqlite3WhereEnd(pWInfo); sqlite3WhereEnd(pWInfo);
sqlite3VdbeChangeToNoop(v, addrSortingIdx, 1); sqlite3VdbeChangeToNoop(v, addrSortingIdx);
} }
/* Output the final row of result /* Output the final row of result

View File

@@ -2021,6 +2021,16 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
break; break;
} }
/* Opcode: Once P1 P2 * * *
**
** Jump to P2 if the value in register P1 is a not null or zero. If
** the value is NULL or zero, fall through and change the P1 register
** to an integer 1.
**
** When P1 is not used otherwise in a program, this opcode falls through
** once and jumps on all subsequent invocations. It is the equivalent
** of "OP_If P1 P2", followed by "OP_Integer 1 P1".
*/
/* Opcode: If P1 P2 P3 * * /* Opcode: If P1 P2 P3 * *
** **
** Jump to P2 if the value in register P1 is true. The value ** Jump to P2 if the value in register P1 is true. The value
@@ -2033,6 +2043,7 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
** is considered true if it has a numeric value of zero. If the value ** is considered true if it has a numeric value of zero. If the value
** in P1 is NULL then take the jump if P3 is true. ** in P1 is NULL then take the jump if P3 is true.
*/ */
case OP_Once: /* jump, in1 */
case OP_If: /* jump, in1 */ case OP_If: /* jump, in1 */
case OP_IfNot: { /* jump, in1 */ case OP_IfNot: { /* jump, in1 */
int c; int c;
@@ -2049,6 +2060,12 @@ case OP_IfNot: { /* jump, in1 */
} }
if( c ){ if( c ){
pc = pOp->p2-1; pc = pOp->p2-1;
}else if( pOp->opcode==OP_Once ){
assert( (pIn1->flags & (MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))==0 );
memAboutToChange(p, pIn1);
pIn1->flags = MEM_Int;
pIn1->u.i = 1;
REGISTER_TRACE(pOp->p1, pIn1);
} }
break; break;
} }

View File

@@ -180,7 +180,7 @@ void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2);
void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3); void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3);
void sqlite3VdbeChangeP5(Vdbe*, u8 P5); void sqlite3VdbeChangeP5(Vdbe*, u8 P5);
void sqlite3VdbeJumpHere(Vdbe*, int addr); void sqlite3VdbeJumpHere(Vdbe*, int addr);
void sqlite3VdbeChangeToNoop(Vdbe*, int addr, int N); void sqlite3VdbeChangeToNoop(Vdbe*, int addr);
void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N); void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
void sqlite3VdbeUsesBtree(Vdbe*, int); void sqlite3VdbeUsesBtree(Vdbe*, int);
VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);

View File

@@ -670,18 +670,15 @@ void sqlite3VdbeLinkSubProgram(Vdbe *pVdbe, SubProgram *p){
} }
/* /*
** Change N opcodes starting at addr to No-ops. ** Change the opcode at addr into OP_Noop
*/ */
void sqlite3VdbeChangeToNoop(Vdbe *p, int addr, int N){ void sqlite3VdbeChangeToNoop(Vdbe *p, int addr){
if( p->aOp ){ if( p->aOp ){
VdbeOp *pOp = &p->aOp[addr]; VdbeOp *pOp = &p->aOp[addr];
sqlite3 *db = p->db; sqlite3 *db = p->db;
while( N-- ){ freeP4(db, pOp->p4type, pOp->p4.p);
freeP4(db, pOp->p4type, pOp->p4.p); memset(pOp, 0, sizeof(pOp[0]));
memset(pOp, 0, sizeof(pOp[0])); pOp->opcode = OP_Noop;
pOp->opcode = OP_Noop;
pOp++;
}
} }
} }

View File

@@ -273,7 +273,7 @@ int sqlite3_blob_open(
/* Configure the OP_TableLock instruction */ /* Configure the OP_TableLock instruction */
#ifdef SQLITE_OMIT_SHARED_CACHE #ifdef SQLITE_OMIT_SHARED_CACHE
sqlite3VdbeChangeToNoop(v, 2, 1); sqlite3VdbeChangeToNoop(v, 2);
#else #else
sqlite3VdbeChangeP1(v, 2, iDb); sqlite3VdbeChangeP1(v, 2, iDb);
sqlite3VdbeChangeP2(v, 2, pTab->tnum); sqlite3VdbeChangeP2(v, 2, pTab->tnum);
@@ -283,7 +283,7 @@ int sqlite3_blob_open(
/* Remove either the OP_OpenWrite or OpenRead. Set the P2 /* Remove either the OP_OpenWrite or OpenRead. Set the P2
** parameter of the other to pTab->tnum. */ ** parameter of the other to pTab->tnum. */
sqlite3VdbeChangeToNoop(v, 4 - flags, 1); sqlite3VdbeChangeToNoop(v, 4 - flags);
sqlite3VdbeChangeP2(v, 3 + flags, pTab->tnum); sqlite3VdbeChangeP2(v, 3 + flags, pTab->tnum);
sqlite3VdbeChangeP3(v, 3 + flags, iDb); sqlite3VdbeChangeP3(v, 3 + flags, iDb);

View File

@@ -1994,8 +1994,7 @@ static void constructAutomaticIndex(
v = pParse->pVdbe; v = pParse->pVdbe;
assert( v!=0 ); assert( v!=0 );
regIsInit = ++pParse->nMem; regIsInit = ++pParse->nMem;
addrInit = sqlite3VdbeAddOp1(v, OP_If, regIsInit); addrInit = sqlite3VdbeAddOp1(v, OP_Once, regIsInit);
sqlite3VdbeAddOp2(v, OP_Integer, 1, regIsInit);
/* Count the number of columns that will be added to the index /* Count the number of columns that will be added to the index
** and used to match WHERE clause constraints */ ** and used to match WHERE clause constraints */