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

Fix the OP_SeekRowid opcode so that it works correctly with a Real argument

without damaging the value in the register that is the argument.
Ticket [b2d4edaffdc156cc].  Test cases in TH3.

FossilOrigin-Name: 3cde82c86b963fa75192907d548febd3882c7d8fc7daf1903fadd5ca46623be1
This commit is contained in:
drh
2019-10-07 01:05:57 +00:00
parent 705e73344e
commit b29ef5ef03
3 changed files with 21 additions and 18 deletions

View File

@@ -4539,23 +4539,27 @@ case OP_SeekRowid: { /* jump, in3 */
pIn3 = &aMem[pOp->p3];
testcase( pIn3->flags & MEM_Int );
testcase( pIn3->flags & MEM_IntReal );
testcase( pIn3->flags & MEM_Real );
testcase( (pIn3->flags & (MEM_Str|MEM_Int))==MEM_Str );
if( (pIn3->flags & (MEM_Int|MEM_IntReal))==0 ){
/* Make sure pIn3->u.i contains a valid integer representation of
** the key value, but do not change the datatype of the register, as
** other parts of the perpared statement might be depending on the
** current datatype. */
u16 origFlags = pIn3->flags;
int isNotInt;
applyAffinity(pIn3, SQLITE_AFF_NUMERIC, encoding);
isNotInt = (pIn3->flags & MEM_Int)==0;
pIn3->flags = origFlags;
if( isNotInt ) goto jump_to_p2;
/* If pIn3->u.i does not contain an integer, compute iKey as the
** integer value of pIn3. Jump to P2 if pIn3 cannot be converted
** into an integer without loss of information. Take care to avoid
** changing the datatype of pIn3, however, as it is used by other
** parts of the prepared statement. */
Mem x = pIn3[0];
applyAffinity(&x, SQLITE_AFF_NUMERIC, encoding);
if( (x.flags & MEM_Int)==0 ) goto jump_to_p2;
iKey = x.u.i;
goto notExistsWithKey;
}
/* Fall through into OP_NotExists */
case OP_NotExists: /* jump, in3 */
pIn3 = &aMem[pOp->p3];
assert( (pIn3->flags & MEM_Int)!=0 || pOp->opcode==OP_SeekRowid );
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
iKey = pIn3->u.i;
notExistsWithKey:
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
#ifdef SQLITE_DEBUG
@@ -4566,7 +4570,6 @@ case OP_NotExists: /* jump, in3 */
pCrsr = pC->uc.pCursor;
assert( pCrsr!=0 );
res = 0;
iKey = pIn3->u.i;
rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0, &res);
assert( rc==SQLITE_OK || res==0 );
pC->movetoTarget = iKey; /* Used by OP_Delete */