-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
-C Factor\sout\sthe\sIN\soperator\scode\sgeneration\sinto\sa\ssubroutine.\s\sUse\sthis\nsubroutine\sto\simplement\sboth\slogic\sand\sbranching\sversions\sof\sthe\sIN\soperator.
-D 2009-11-12T17:52:24
+C Enhance\sthe\sOP_Found\sand\sOP_NotFound\sopcodes\sso\sthat\sthey\scan\saccept\san\narray\sof\sregisters\sas\san\sunpacked\srecord\sin\saddition\sto\sa\srecord\sbuilt\nusing\sOP_MakeRecord.\s\sUse\sthis\sto\savoid\sOP_MakeRecord\scalls\sduring\sIN\nexpression\sprocessing.
+D 2009-11-12T19:59:44
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in 53f3dfa49f28ab5b80cb083fb7c9051e596bcfa1
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
F src/complete.c 77016e5a2766cf8b84381397152d2c99ea4b218f
F src/date.c a79c0a8f219370b972e320741f995a3bef9df33f
F src/delete.c ec04635d152debdab70d4b30c5516b59282075ea
-F src/expr.c 98925d79ea6a0a13a2ce46369482ae2fdb2fa616
+F src/expr.c 33c08bb50674d6b5e4c8100d18c6270e6d07fb14
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
-F src/fkey.c 41219cba186bcf0a053e42327dfa23aaba4f834a
+F src/fkey.c e2116672a6bd610dc888e27df292ebc7999c9bb0
F src/func.c bf54e1202cbfb28bf4b1fd9b58899009ae76716f
F src/global.c 271952d199a8cc59d4ce840b3bbbfd2f30c8ba32
F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af
F src/pcache.c 3b079306376e0e04c0d3df40c0a4b750a1839310
F src/pcache.h c683390d50f856d4cd8e24342ae62027d1bb6050
F src/pcache1.c db4a996e456eec2380732a1036e23e3f551f6573
-F src/pragma.c 97031c9f38e4ad09b92e19e698e3c26a54370591
+F src/pragma.c 0057a8838eec9ac78ed759687fe30e45622fd58b
F src/prepare.c ad90970bba3aead154266d8bb6faf9fbb5233b94
F src/printf.c 03fabdd6112a0e23f78f8ac9a1396947ade0273b
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
F src/resolve.c aa3cb21e1ecd905c071fce8fb64d1a166cefc239
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
-F src/select.c 696f245c519c83b5d3b8892db22cfa6c55ef3bd0
+F src/select.c 55051bfa85dc23079a333230a368e0bce4a78cf8
F src/shell.c f4948cb6d30665d755a6b5e0ec313d1094aab828
F src/sqlite.h.in 4464e9772122f0447305d425e04d122b6f1bffec
F src/sqlite3ext.h 69dfb8116af51b84a029cddb3b35062354270c89
F src/utf.c dad16adcc0c35ef2437dca125a4b07419d361052
F src/util.c ad4f03079ba0fe83590d1cc9197e8e4844e38592
F src/vacuum.c 03309a08d549f9389cc3a3589afd4fadbdaf0679
-F src/vdbe.c 7c0238174a2400eb4c578978ae164c025aef0872
-F src/vdbe.h 7b06b21f76e349bc2b7e18599550d79bf943c940
+F src/vdbe.c d035dd3b693cb37874dfdfc77812e8496c435380
+F src/vdbe.h 65cd747e36ad444cb1a17e529030942c45a61fe3
F src/vdbeInt.h 59c65e7b810836b9e946acee45c7b3c02b967d1b
F src/vdbeapi.c 17680ab7a75ec938c5ba039a6c87489d01faf2cb
-F src/vdbeaux.c e85c8c7dc63b8e8941afe445a708bd188e5f9ba9
+F src/vdbeaux.c ee52010d2517eae2ef1c6766a372d79bfaea6e2e
F src/vdbeblob.c 84f924700a7a889152aeebef77ca5f4e3875ffb4
F src/vdbemem.c 1e16e3a16e55f4c3452834f0e041726021aa66e0
F src/vtab.c 456fc226614569f0e46f216e33265bea268bd917
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
-F src/where.c c4ef49803cced21b9387381b5b71aaf98c4b8103
+F src/where.c d5c9692fc228bdc4826f50971b3801068cd4513b
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
F test/all.test 14165b3e32715b700b5f0cbf8f6e3833dda0be45
F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
F test/analyze.test ad5329098fe4de4a96852231d53e3e9e6283ad4b
F test/analyze2.test a2ad7b0a4e13801ee3968fe70f22aff52326569c
-F test/analyze3.test 851bcc0738b87e1c1990d8dbad6ab53cdfcc19d6
+F test/analyze3.test ae06e0f8b3eaae0dd644ac9ac9d617058b5ac131
F test/async.test 8c75d31b8330f8b70cf2571b014d4476a063efdb
F test/async2.test bf5e2ca2c96763b4cba3d016249ad7259a5603b6
F test/async3.test 93edaa9122f498e56ea98c36c72abc407f4fb11e
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P 5735f60b23460e7677b9c982a26bc13b0f4ed02b
-R cd9746f4aa3a1481551f5a560f35dd38
+P fcff5b7e2d059ffb8d21df57d0c9648bd876e813
+R 289cc41bc3e406dfdc738b417fc25b8c
U drh
-Z 81c5b2ffa7a845f506af8b1b8ae99199
+Z 968caa638a1107429c124a260631802c
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
-iD8DBQFK/EtboxKgR168RlERAkKeAJ4iV9MT2c84lYVox/EKQ+FokU0xYgCfa68+
-e8jT2Mgzw0vJyZcF2wVoLY8=
-=fBGP
+iD8DBQFK/GkzoxKgR168RlERAl33AJ9QBMxhsMt2M9vYW0zsZxtSjE5sMACfUjh4
+j4sLHQ3TmHMP7T2ltUWwkRc=
+=u7bi
-----END PGP SIGNATURE-----
-fcff5b7e2d059ffb8d21df57d0c9648bd876e813
\ No newline at end of file
+b9eab885cd2ca1a1633329e7036c125e8dba62c5
\ No newline at end of file
affinity = sqlite3ExprAffinity(pLeft);
/* Whether this is an 'x IN(SELECT...)' or an 'x IN(<exprlist>)'
- ** expression it is handled the same way. A virtual table is
+ ** expression it is handled the same way. An ephemeral table is
** filled with single-field index keys representing the results
** from the SELECT or the <exprlist>.
**
}else{
/* In this case, the RHS is an index b-tree.
*/
- int r2; /* Register holding LHS value as a Record */
-
- /* Create a record that can be used for membership testing.
- */
- r2 = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp4(v, OP_MakeRecord, r1, 1, r2, &affinity, 1);
+ sqlite3VdbeAddOp4(v, OP_Affinity, r1, 1, 0, &affinity, 1);
/* If the set membership test fails, then the result of the
** "x IN (...)" expression must be either 0 or NULL. If the set
** Also run this branch if NULL is equivalent to FALSE
** for this particular IN operator.
*/
- sqlite3VdbeAddOp3(v, OP_NotFound, pExpr->iTable, destIfFalse, r2);
+ sqlite3VdbeAddOp4Int(v, OP_NotFound, pExpr->iTable, destIfFalse, r1, 1);
}else{
/* In this branch, the RHS of the IN might contain a NULL and
** the presence of a NULL on the RHS makes a difference in the
** outcome.
*/
- static const char nullRecord[] = { 0x02, 0x00 };
int j1, j2, j3;
/* First check to see if the LHS is contained in the RHS. If so,
** then the presence of NULLs in the RHS does not matter, so jump
** over all of the code that follows.
*/
- j1 = sqlite3VdbeAddOp3(v, OP_Found, pExpr->iTable, 0, r2);
+ j1 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, r1, 1);
/* Here we begin generating code that runs if the LHS is not
** contained within the RHS. Generate additional code that
** jump to destIfFalse.
*/
j2 = sqlite3VdbeAddOp1(v, OP_NotNull, rRhsHasNull);
- sqlite3VdbeAddOp4(v, OP_Blob, 2, r2, 0, nullRecord, P4_STATIC);
- j3 = sqlite3VdbeAddOp3(v, OP_Found, pExpr->iTable, 0, r2);
+ j3 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, rRhsHasNull, 1);
sqlite3VdbeAddOp2(v, OP_Integer, -1, rRhsHasNull);
sqlite3VdbeJumpHere(v, j3);
sqlite3VdbeAddOp2(v, OP_AddImm, rRhsHasNull, 1);
*/
sqlite3VdbeJumpHere(v, j1);
}
- sqlite3ReleaseTempReg(pParse, r2);
}
sqlite3ReleaseTempReg(pParse, r1);
sqlite3ExprCachePop(pParse, 1);
sqlite3VdbeAddOp3(v, OP_MakeRecord, regTemp, nCol, regRec);
sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v, pIdx), 0);
- sqlite3VdbeAddOp3(v, OP_Found, iCur, iOk, regRec);
+ sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0);
sqlite3ReleaseTempReg(pParse, regRec);
sqlite3ReleaseTempRange(pParse, regTemp, nCol);
{ OP_Halt, 0, 0, 0},
};
sqlite3GenerateIndexKey(pParse, pIdx, 1, 3, 1);
- jmp2 = sqlite3VdbeAddOp3(v, OP_Found, j+2, 0, 3);
+ jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, j+2, 0, 3, 0);
addr = sqlite3VdbeAddOpList(v, ArraySize(idxErr), idxErr);
sqlite3VdbeChangeP4(v, addr+1, "rowid ", P4_STATIC);
sqlite3VdbeChangeP4(v, addr+3, " missing from index ", P4_STATIC);
v = pParse->pVdbe;
r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1);
- sqlite3VdbeAddOp3(v, OP_Found, iTab, addrRepeat, r1);
+ sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, r1, 0);
sqlite3VdbeAddOp2(v, OP_IdxInsert, iTab, r1);
sqlite3ReleaseTempReg(pParse, r1);
}
sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak);
r1 = sqlite3GetTempReg(pParse);
iStart = sqlite3VdbeAddOp2(v, OP_RowKey, tab1, r1);
- sqlite3VdbeAddOp3(v, OP_NotFound, tab2, iCont, r1);
+ sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0);
sqlite3ReleaseTempReg(pParse, r1);
selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr,
0, -1, &dest, iCont, iBreak);
}
-/* Opcode: Found P1 P2 P3 * *
+/* Opcode: Found P1 P2 P3 P4 *
**
-** Register P3 holds a blob constructed by MakeRecord. P1 is an index.
-** If P3 is a prefix of any entry in P1 then a jump is made to P2 and
+** If P4==0 then register P3 holds a blob constructed by MakeRecord. If
+** P4>0 then register P3 is the first of P4 registers that form an unpacked
+** record.
+**
+** Cursor P1 is on an index btree. If the record identified by P3 and P4
+** is a prefix of any entry in P1 then a jump is made to P2 and
** P1 is left pointing at the matching entry.
*/
-/* Opcode: NotFound P1 P2 P3 * *
+/* Opcode: NotFound P1 P2 P3 P4 *
**
-** Register P3 holds a blob constructed by MakeRecord. P1 is
-** an index. If P3 is not the prefix of any entry in P1 then a jump
-** is made to P2. If P1 does contain an entry whose prefix matches
-** P3 then control falls through to the next instruction and P1 is
-** left pointing at the matching entry.
+** If P4==0 then register P3 holds a blob constructed by MakeRecord. If
+** P4>0 then register P3 is the first of P4 registers that form an unpacked
+** record.
+**
+** Cursor P1 is on an index btree. If the record identified by P3 and P4
+** is not the prefix of any entry in P1 then a jump is made to P2. If P1
+** does contain an entry whose prefix matches the P3/P4 record then control
+** falls through to the next instruction and P1 is left pointing at the
+** matching entry.
**
** See also: Found, NotExists, IsUnique
*/
VdbeCursor *pC;
int res;
UnpackedRecord *pIdxKey;
+ UnpackedRecord r;
char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7];
#ifdef SQLITE_TEST
alreadyExists = 0;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ assert( pOp->p4type==P4_INT32 );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
if( ALWAYS(pC->pCursor!=0) ){
assert( pC->isTable==0 );
- assert( pIn3->flags & MEM_Blob );
- ExpandBlob(pIn3);
- pIdxKey = sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z,
- aTempRec, sizeof(aTempRec));
- if( pIdxKey==0 ){
- goto no_mem;
+ if( pOp->p4.i>0 ){
+ r.pKeyInfo = pC->pKeyInfo;
+ r.nField = pOp->p4.i;
+ r.aMem = pIn3;
+ r.flags = UNPACKED_PREFIX_MATCH;
+ pIdxKey = &r;
+ }else{
+ assert( pIn3->flags & MEM_Blob );
+ ExpandBlob(pIn3);
+ pIdxKey = sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z,
+ aTempRec, sizeof(aTempRec));
+ if( pIdxKey==0 ){
+ goto no_mem;
+ }
+ pIdxKey->flags |= UNPACKED_PREFIX_MATCH;
}
- pIdxKey->flags |= UNPACKED_PREFIX_MATCH;
rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, pIdxKey, 0, 0, &res);
- sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
+ if( pOp->p4.i==0 ){
+ sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
+ }
if( rc!=SQLITE_OK ){
break;
}
/* Opcode: IsUnique P1 P2 P3 P4 *
**
-** Cursor P1 is open on an index. So it has no data and its key consists
-** of a record generated by OP_MakeRecord where the last field is the
-** rowid of the entry that the index refers to.
+** Cursor P1 is open on an index b-tree - that is to say, a btree which
+** no data and where the key are records generated by OP_MakeRecord with
+** the list field being the integer ROWID of the entry that the index
+** entry refers to.
**
** The P3 register contains an integer record number. Call this record
** number R. Register P4 is the first in a set of N contiguous registers
int sqlite3VdbeAddOp2(Vdbe*,int,int,int);
int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int);
int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int);
+int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int);
int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp);
void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1);
void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2);
return addr;
}
+/*
+** Add an opcode that includes the p4 value as an integer.
+*/
+int sqlite3VdbeAddOp4Int(
+ Vdbe *p, /* Add the opcode to this VM */
+ int op, /* The new opcode */
+ int p1, /* The P1 operand */
+ int p2, /* The P2 operand */
+ int p3, /* The P3 operand */
+ int p4 /* The P4 operand as an integer */
+){
+ int addr = sqlite3VdbeAddOp3(p, op, p1, p2, p3);
+ sqlite3VdbeChangeP4(p, addr, SQLITE_INT_TO_PTR(p4), P4_INT32);
+ return addr;
+}
+
/*
** Create a new symbolic label for an instruction that has yet to be
** coded. The symbolic label is really just a negative number. The
testcase( op==OP_SeekGe );
testcase( op==OP_SeekLe );
testcase( op==OP_SeekLt );
- sqlite3VdbeAddOp4(v, op, iIdxCur, addrNxt, regBase,
- SQLITE_INT_TO_PTR(nConstraint), P4_INT32);
+ sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
/* Load the value for the inequality constraint at the end of the
** range (if any).
testcase( op==OP_IdxGE );
testcase( op==OP_IdxLT );
if( op!=OP_Noop ){
- sqlite3VdbeAddOp4(v, op, iIdxCur, addrNxt, regBase,
- SQLITE_INT_TO_PTR(nConstraint), P4_INT32);
+ sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
sqlite3VdbeChangeP5(v, endEq!=bRev ?1:0);
}
int r;
r = sqlite3ExprCodeGetColumn(pParse, pTabItem->pTab, -1, iCur,
regRowid, 0);
- sqlite3VdbeAddOp4(v, OP_RowSetTest, regRowset,
- sqlite3VdbeCurrentAddr(v)+2,
- r, SQLITE_INT_TO_PTR(iSet), P4_INT32);
+ sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset,
+ sqlite3VdbeCurrentAddr(v)+2, r, iSet);
}
sqlite3VdbeAddOp2(v, OP_Gosub, regReturn, iLoopBody);
Bitmask b = pTabItem->colUsed;
int n = 0;
for(; b; b=b>>1, n++){}
- sqlite3VdbeChangeP4(v, sqlite3VdbeCurrentAddr(v)-1, SQLITE_INT_TO_PTR(n), P4_INT32);
+ sqlite3VdbeChangeP4(v, sqlite3VdbeCurrentAddr(v)-1,
+ SQLITE_INT_TO_PTR(n), P4_INT32);
assert( n<=pTab->nCol );
}
}else{
} {SQLITE_OK}
finish_test
-