diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/expr.c | 18 | ||||
-rw-r--r-- | src/fkey.c | 2 | ||||
-rw-r--r-- | src/pragma.c | 2 | ||||
-rw-r--r-- | src/select.c | 4 | ||||
-rw-r--r-- | src/vdbe.c | 61 | ||||
-rw-r--r-- | src/vdbe.h | 1 | ||||
-rw-r--r-- | src/vdbeaux.c | 16 | ||||
-rw-r--r-- | src/where.c | 14 |
8 files changed, 73 insertions, 45 deletions
diff --git a/src/expr.c b/src/expr.c index 8ff43381b..a50348f2d 100644 --- a/src/expr.c +++ b/src/expr.c @@ -1546,7 +1546,7 @@ int sqlite3CodeSubselect( 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>. ** @@ -1754,12 +1754,7 @@ static void sqlite3ExprCodeIN( }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 @@ -1775,21 +1770,20 @@ static void sqlite3ExprCodeIN( ** 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 @@ -1798,8 +1792,7 @@ static void sqlite3ExprCodeIN( ** 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); @@ -1816,7 +1809,6 @@ static void sqlite3ExprCodeIN( */ sqlite3VdbeJumpHere(v, j1); } - sqlite3ReleaseTempReg(pParse, r2); } sqlite3ReleaseTempReg(pParse, r1); sqlite3ExprCachePop(pParse, 1); diff --git a/src/fkey.c b/src/fkey.c index df0a5b466..e6f4bfc05 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -399,7 +399,7 @@ static void fkLookupParent( 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); diff --git a/src/pragma.c b/src/pragma.c index fb6d37219..69dea4edb 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -1142,7 +1142,7 @@ void sqlite3Pragma( { 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); diff --git a/src/select.c b/src/select.c index be504603a..80a04f40e 100644 --- a/src/select.c +++ b/src/select.c @@ -440,7 +440,7 @@ static void codeDistinct( 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); } @@ -1670,7 +1670,7 @@ static int multiSelect( 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); diff --git a/src/vdbe.c b/src/vdbe.c index 758e07973..a13a7e62a 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -3354,19 +3354,27 @@ case OP_Seek: { /* in2 */ } -/* 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 */ @@ -3376,6 +3384,7 @@ case OP_Found: { /* jump, in3 */ VdbeCursor *pC; int res; UnpackedRecord *pIdxKey; + UnpackedRecord r; char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7]; #ifdef SQLITE_TEST @@ -3384,21 +3393,32 @@ case OP_Found: { /* jump, in3 */ 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; } @@ -3416,9 +3436,10 @@ case OP_Found: { /* jump, in3 */ /* 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 diff --git a/src/vdbe.h b/src/vdbe.h index 7caf90442..fbe62d772 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -170,6 +170,7 @@ int sqlite3VdbeAddOp1(Vdbe*,int,int); 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); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index a3905da17..16499ce12 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -196,6 +196,22 @@ int sqlite3VdbeAddOp4( } /* +** 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 ** label can be used as the P2 value of an operation. Later, when diff --git a/src/where.c b/src/where.c index 135ff8002..90df4c495 100644 --- a/src/where.c +++ b/src/where.c @@ -3119,8 +3119,7 @@ static Bitmask codeOneLoopStart( 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). @@ -3153,8 +3152,7 @@ static Bitmask codeOneLoopStart( 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); } @@ -3283,9 +3281,8 @@ static Bitmask codeOneLoopStart( 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); @@ -3816,7 +3813,8 @@ WhereInfo *sqlite3WhereBegin( 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{ |