diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/expr.c | 21 | ||||
-rw-r--r-- | src/vdbe.c | 24 |
2 files changed, 32 insertions, 13 deletions
diff --git a/src/expr.c b/src/expr.c index f592fc75a..1ac37e0b7 100644 --- a/src/expr.c +++ b/src/expr.c @@ -1602,6 +1602,7 @@ void sqlite3CodeSubselect( sqlite3VdbeAddOp2(v, OP_Null, 0, r2); for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){ Expr *pE2 = pItem->pExpr; + int iValToIns; /* If the expression is not constant then we will need to ** disable the test that was generated above that makes sure @@ -1614,14 +1615,19 @@ void sqlite3CodeSubselect( } /* Evaluate the expression and insert it into the temp table */ - r3 = sqlite3ExprCodeTarget(pParse, pE2, r1); - if( isRowid ){ - sqlite3VdbeAddOp2(v, OP_MustBeInt, r3, sqlite3VdbeCurrentAddr(v)+2); - sqlite3VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r3); + if( isRowid && sqlite3ExprIsInteger(pE2, &iValToIns) ){ + sqlite3VdbeAddOp3(v, OP_InsertInt, pExpr->iTable, r2, iValToIns); }else{ - sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1); - sqlite3ExprCacheAffinityChange(pParse, r3, 1); - sqlite3VdbeAddOp2(v, OP_IdxInsert, pExpr->iTable, r2); + r3 = sqlite3ExprCodeTarget(pParse, pE2, r1); + if( isRowid ){ + sqlite3VdbeAddOp2(v, OP_MustBeInt, r3, + sqlite3VdbeCurrentAddr(v)+2); + sqlite3VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r3); + }else{ + sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1); + sqlite3ExprCacheAffinityChange(pParse, r3, 1); + sqlite3VdbeAddOp2(v, OP_IdxInsert, pExpr->iTable, r2); + } } } sqlite3ReleaseTempReg(pParse, r1); @@ -2875,6 +2881,7 @@ static int isAppropriateForFactoring(Expr *p){ static int evalConstExpr(Walker *pWalker, Expr *pExpr){ Parse *pParse = pWalker->pParse; switch( pExpr->op ){ + case TK_IN: case TK_REGISTER: { return WRC_Prune; } diff --git a/src/vdbe.c b/src/vdbe.c index 6847b9027..3e316fc68 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -3758,7 +3758,13 @@ case OP_NewRowid: { /* out2-prerelease */ ** This instruction only works on tables. The equivalent instruction ** for indices is OP_IdxInsert. */ -case OP_Insert: { +/* Opcode: InsertInt P1 P2 P3 P4 P5 +** +** This works exactly like OP_Insert except that the key is the +** integer value P3, not the value of the integer stored in register P3. +*/ +case OP_Insert: +case OP_InsertInt: { Mem *pData; /* MEM cell holding data for the record to be inserted */ Mem *pKey; /* MEM cell holding key for the record */ i64 iKey; /* The integer ROWID or key for the record to be inserted */ @@ -3770,20 +3776,26 @@ case OP_Insert: { int op; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */ pData = &p->aMem[pOp->p2]; - pKey = &p->aMem[pOp->p3]; assert( pOp->p1>=0 && pOp->p1<p->nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( pC->pCursor!=0 ); assert( pC->pseudoTableReg==0 ); - assert( pKey->flags & MEM_Int ); assert( pC->isTable ); REGISTER_TRACE(pOp->p2, pData); - REGISTER_TRACE(pOp->p3, pKey); - iKey = pKey->u.i; + if( pOp->opcode==OP_Insert ){ + pKey = &p->aMem[pOp->p3]; + assert( pKey->flags & MEM_Int ); + REGISTER_TRACE(pOp->p3, pKey); + iKey = pKey->u.i; + }else{ + assert( pOp->opcode==OP_InsertInt ); + iKey = pOp->p3; + } + if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++; - if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = pKey->u.i; + if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = iKey; if( pData->flags & MEM_Null ){ pData->z = 0; pData->n = 0; |