1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-30 19:03:16 +03:00

Fix a bug in the handling of Mems inside of vdbe.c. (CVS 1745)

FossilOrigin-Name: ad65c6e24e15966d5fd15d60f81487ff97788da4
This commit is contained in:
drh
2004-06-27 01:56:33 +00:00
parent 5260f7e925
commit 6a6124e27a
7 changed files with 116 additions and 96 deletions

View File

@ -1,5 +1,5 @@
C Coverage\stesting\sof\spragma.c.\s(CVS\s1744)
D 2004-06-26T19:35:30
C Fix\sa\sbug\sin\sthe\shandling\sof\sMems\sinside\sof\svdbe.c.\s(CVS\s1745)
D 2004-06-27T01:56:33
F Makefile.in cb7a9889c38723f72b2506c4236ff30a05ff172b
F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@ -73,12 +73,12 @@ F src/update.c b66b1896c9da54678ba3eff2bf0b4d291a95986a
F src/utf.c a8fb39c94ae4ef6606d5216b6f05d9b86f6901b2
F src/util.c 43d0289d49f43c66847ebbeddfb85a2a0d1ddd2d
F src/vacuum.c 353c7f69dbeb6738434d81798465cc0698844640
F src/vdbe.c 423b55e65501ef2b60d8dedabe8d76d06ea62d99
F src/vdbe.c b750a731c90567b77ed6e0cd455ac868953d3a72
F src/vdbe.h 2d87155e31e84bb00cdc48cc1ce6987a3a484250
F src/vdbeInt.h 22ab717b69074fe7a28f64e35a39bd436ad9d150
F src/vdbeapi.c d3659f3f2982e79c06ab8e338604a39e0ea0d2d3
F src/vdbeInt.h d83fd7389838453d8392915c21f432014afc99cf
F src/vdbeapi.c e92bda928f2fe93a9a77a62bd95642563bbcdea1
F src/vdbeaux.c e7201e3f129439bc64d2ff79b54001adc2c95539
F src/vdbemem.c d37e4033f7350e542f715c061bffe23feb51bc9e
F src/vdbemem.c e8ae1f56ad16d5b01119e8dc1d25e913e06c3128
F src/where.c 6507074d8ce3f78e7a4cd33f667f11e62020553e
F test/all.test d591e074013248176402a16a0fb6fc82d241bad5
F test/attach.test 3acdffccbf5f78b07746771b9490758718e28856
@ -96,7 +96,7 @@ F test/btree5.test 8e5ff32c02e685d36516c6499add9375fe1377f2
F test/btree6.test a5ede6bfbbb2ec8b27e62813612c0f28e8f3e027
F test/btree7.test 429b96cfef5b51a7d512cfb4b5b3e453384af293
F test/capi2.test fe61f341e953f73c29bacfcbdaf688cd7b0e0d38
F test/capi3.test 6528034f21c4e8e404032124cb58b14ce934598c
F test/capi3.test ac53507f69b14fe026634afa09e6512f678f161d
F test/collate1.test 2ee4fa3a47a652ccf56c5ddf65dcc44d9bad82ef
F test/collate2.test c1a3b41f761b28853c5696037f92de928f93233b
F test/collate3.test e60b428e07ec945492ba90ff1c895902ee3a8a50
@ -229,7 +229,7 @@ F www/tclsqlite.tcl 19191cf2a1010eaeff74c51d83fd5f5a4d899075
F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
F www/version3.tcl 563ba3ac02f64da27ab17f3edbe8e56bfd0293fb
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
P b69b4fe8adff83a26e3566613bea8b477a26e8a4
R 72fd52c0e274fc83fa1945dfd7a6deb8
P 0f9c0f0aa9188c46c65cb92203687f37884f685a
R 890a4b373e4b15aa9e98bea1cb54b3e0
U drh
Z 03157110b37f81d3fef2f16d6fba5e75
Z bd1af074bc92b88e71778888aba3c921

View File

@ -1 +1 @@
0f9c0f0aa9188c46c65cb92203687f37884f685a
ad65c6e24e15966d5fd15d60f81487ff97788da4

View File

@ -43,7 +43,7 @@
** in this file for details. If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.389 2004/06/26 08:38:25 danielk1977 Exp $
** $Id: vdbe.c,v 1.390 2004/06/27 01:56:33 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -115,17 +115,15 @@ int sqlite3_interrupt_count = 0;
** Any prior string or real representation is invalidated.
** NULLs are converted into 0.
*/
#define Integerify(P, enc) \
if((P)->flags!=MEM_Int){ sqlite3VdbeMemIntegerify(P); }
#define Integerify(P) sqlite3VdbeMemIntegerify(P)
/*
** Get a valid Real representation for the given stack element.
** Convert P so that it has type MEM_Real.
**
** Any prior string or integer representation is retained.
** Any prior string or integer representation is invalidated.
** NULLs are converted into 0.0.
*/
#define Realify(P,enc) \
if(((P)->flags&MEM_Real)==0){ sqlite3VdbeMemRealify(P); }
#define Realify(P) sqlite3VdbeMemRealify(P)
/*
** Argument pMem points at a memory cell that will be passed to a
@ -304,9 +302,9 @@ static void applyAffinity(Mem *pRec, char affinity, u8 enc){
sqlite3VdbeMemNulTerminate(pRec);
if( pRec->flags&MEM_Str && sqlite3IsNumber(pRec->z, &realnum, enc) ){
if( realnum ){
Realify(pRec, enc);
Realify(pRec);
}else{
Integerify(pRec, enc);
Integerify(pRec);
}
}
}
@ -686,7 +684,8 @@ case OP_Integer: {
pTos->z = pOp->p3;
pTos->n = strlen(pTos->z);
pTos->enc = SQLITE_UTF8;
Integerify(pTos, 0);
pTos->i = sqlite3VdbeIntValue(pTos);
pTos->flags |= MEM_Int;
}
break;
}
@ -701,7 +700,8 @@ case OP_Real: {
pTos->z = pOp->p3;
pTos->n = strlen(pTos->z);
pTos->enc = SQLITE_UTF8;
Realify(pTos, 0);
pTos->r = sqlite3VdbeRealValue(pTos);
pTos->flags |= MEM_Real;
break;
}
@ -1162,10 +1162,8 @@ case OP_Remainder: {
pTos->flags = MEM_Int;
}else{
double a, b;
Realify(pTos, db->enc);
Realify(pNos, db->enc);
a = pTos->r;
b = pNos->r;
a = sqlite3VdbeRealValue(pTos);
b = sqlite3VdbeRealValue(pNos);
switch( pOp->opcode ){
case OP_Add: b += a; break;
case OP_Subtract: b -= a; break;
@ -1339,10 +1337,8 @@ case OP_ShiftRight: {
pTos->flags = MEM_Null;
break;
}
Integerify(pTos, db->enc);
Integerify(pNos, db->enc);
a = pTos->i;
b = pNos->i;
a = sqlite3VdbeIntValue(pTos);
b = sqlite3VdbeIntValue(pNos);
switch( pOp->opcode ){
case OP_BitAnd: a &= b; break;
case OP_BitOr: a |= b; break;
@ -1350,13 +1346,6 @@ case OP_ShiftRight: {
case OP_ShiftRight: a >>= b; break;
default: /* CANT HAPPEN */ break;
}
/* FIX ME: Because constant P3 values sometimes need to be translated,
** the following assert() can fail. When P3 is always in the native text
** encoding, this assert() will be valid again. Until then, the Release()
** is neeed instead.
assert( (pTos->flags & MEM_Dyn)==0 );
assert( (pNos->flags & MEM_Dyn)==0 );
*/
Release(pTos);
pTos--;
Release(pTos);
@ -1374,7 +1363,7 @@ case OP_ShiftRight: {
*/
case OP_AddImm: {
assert( pTos>=p->aStack );
Integerify(pTos, db->enc);
Integerify(pTos);
pTos->i += pOp->p1;
break;
}
@ -1402,7 +1391,7 @@ case OP_ForceInt: {
if( pTos->flags & MEM_Int ){
v = pTos->i + (pOp->p1!=0);
}else{
Realify(pTos, db->enc);
Realify(pTos);
v = (int)pTos->r;
if( pTos->r>(double)v ) v++;
if( pOp->p1 && pTos->r==(double)v ) v++;
@ -1446,7 +1435,7 @@ case OP_MustBeInt: {
if( !sqlite3IsNumber(pTos->z, 0, db->enc) ){
goto mismatch;
}
Realify(pTos, db->enc);
Realify(pTos);
v = (int)pTos->r;
r = (double)v;
if( r!=pTos->r ){
@ -1609,13 +1598,13 @@ case OP_Or: {
if( pTos->flags & MEM_Null ){
v1 = 2;
}else{
Integerify(pTos, db->enc);
Integerify(pTos);
v1 = pTos->i==0;
}
if( pNos->flags & MEM_Null ){
v2 = 2;
}else{
Integerify(pNos, db->enc);
Integerify(pNos);
v2 = pNos->i==0;
}
if( pOp->opcode==OP_And ){
@ -1666,8 +1655,7 @@ case OP_AbsValue: {
}else if( pTos->flags & MEM_Null ){
/* Do nothing */
}else{
Realify(pTos, db->enc);
Release(pTos);
Realify(pTos);
if( pOp->opcode==OP_Negative || pTos->r<0.0 ){
pTos->r = -pTos->r;
}
@ -1685,8 +1673,8 @@ case OP_AbsValue: {
case OP_Not: {
assert( pTos>=p->aStack );
if( pTos->flags & MEM_Null ) break; /* Do nothing to NULLs */
Integerify(pTos, db->enc);
Release(pTos);
Integerify(pTos);
assert( (pTos->flags & MEM_Dyn)==0 );
pTos->i = !pTos->i;
pTos->flags = MEM_Int;
break;
@ -1701,8 +1689,8 @@ case OP_Not: {
case OP_BitNot: {
assert( pTos>=p->aStack );
if( pTos->flags & MEM_Null ) break; /* Do nothing to NULLs */
Integerify(pTos, db->enc);
Release(pTos);
Integerify(pTos);
assert( (pTos->flags & MEM_Dyn)==0 );
pTos->i = ~pTos->i;
pTos->flags = MEM_Int;
break;
@ -1744,16 +1732,9 @@ case OP_IfNot: {
if( pTos->flags & MEM_Null ){
c = pOp->p1;
}else{
Integerify(pTos, db->enc);
c = pTos->i;
c = sqlite3VdbeIntValue(pTos);
if( pOp->opcode==OP_IfNot ) c = !c;
}
/* FIX ME: Because constant P3 values sometimes need to be translated,
** the following assert() can fail. When P3 is always in the native text
** encoding, this assert() will be valid again. Until then, the Release()
** is neeed instead.
assert( (pTos->flags & MEM_Dyn)==0 );
*/
Release(pTos);
pTos--;
if( c ) pc = pOp->p2-1;
@ -2144,7 +2125,7 @@ case OP_MakeRecord: {
if( addRowid ){
pRowid = &pTos[0-nField];
assert( pRowid>=p->aStack );
Integerify(pRowid, db->enc);
Integerify(pRowid);
serial_type = sqlite3VdbeSerialType(pRowid);
nData += sqlite3VdbeSerialTypeLen(serial_type);
nHdr += sqlite3VarintLen(serial_type);
@ -2360,10 +2341,10 @@ case OP_SetCookie: {
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( db->aDb[pOp->p1].pBt!=0 );
assert( pTos>=p->aStack );
Integerify(pTos, db->enc);
Integerify(pTos);
/* See note about index shifting on OP_ReadCookie */
rc = sqlite3BtreeUpdateMeta(db->aDb[pOp->p1].pBt, 1+pOp->p2, (int)pTos->i);
Release(pTos);
assert( (pTos->flags & MEM_Dyn)==0 );
pTos--;
break;
}
@ -2447,8 +2428,9 @@ case OP_OpenWrite: {
Cursor *pCur;
assert( pTos>=p->aStack );
Integerify(pTos, db->enc);
Integerify(pTos);
iDb = pTos->i;
assert( (pTos->flags & MEM_Dyn)==0 );
pTos--;
assert( iDb>=0 && iDb<db->nDb );
pX = db->aDb[iDb].pBt;
@ -2456,8 +2438,9 @@ case OP_OpenWrite: {
wrFlag = pOp->opcode==OP_OpenWrite;
if( p2<=0 ){
assert( pTos>=p->aStack );
Integerify(pTos, db->enc);
Integerify(pTos);
p2 = pTos->i;
assert( (pTos->flags & MEM_Dyn)==0 );
pTos--;
if( p2<2 ){
sqlite3SetString(&p->zErrMsg, "root page number less than 2", (char*)0);
@ -2657,12 +2640,12 @@ case OP_MoveGt: {
if( pC->intKey ){
i64 iKey;
assert( !pOp->p3 );
Integerify(pTos, db->enc);
Integerify(pTos);
iKey = intToKey(pTos->i);
if( pOp->p2==0 && pOp->opcode==OP_MoveGe ){
pC->movetoTarget = iKey;
pC->deferredMoveto = 1;
Release(pTos);
assert( (pTos->flags & MEM_Dyn)==0 );
pTos--;
break;
}
@ -2801,8 +2784,9 @@ case OP_IsUnique: {
/* Pop the value R off the top of the stack
*/
assert( pNos>=p->aStack );
Integerify(pTos, db->enc);
Integerify(pTos);
R = pTos->i;
assert( (pTos->flags & MEM_Dyn)==0 );
pTos--;
assert( i>=0 && i<=p->nCursor );
pCx = p->apCsr[i];
@ -3851,9 +3835,9 @@ case OP_ListWrite: {
pKeylist->pNext = p->pList;
p->pList = pKeylist;
}
Integerify(pTos, db->enc);
Integerify(pTos);
pKeylist->aKey[pKeylist->nUsed++] = pTos->i;
Release(pTos);
assert( (pTos->flags & MEM_Dyn)==0 );
pTos--;
break;
}

View File

@ -391,7 +391,9 @@ void sqlite3VdbeMemSetNull(Mem*);
int sqlite3VdbeMemMakeWriteable(Mem*);
int sqlite3VdbeMemDynamicify(Mem*);
int sqlite3VdbeMemStringify(Mem*, int);
i64 sqlite3VdbeIntValue(Mem*);
int sqlite3VdbeMemIntegerify(Mem*);
double sqlite3VdbeRealValue(Mem*);
int sqlite3VdbeMemRealify(Mem*);
int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*);
void sqlite3VdbeMemRelease(Mem *p);

View File

@ -43,19 +43,13 @@ int sqlite3_value_bytes16(sqlite3_value *pVal){
return 0;
}
double sqlite3_value_double(sqlite3_value *pVal){
Mem *pMem = (Mem *)pVal;
sqlite3VdbeMemRealify(pMem);
return pMem->r;
return sqlite3VdbeRealValue((Mem*)pVal);
}
int sqlite3_value_int(sqlite3_value *pVal){
Mem *pMem = (Mem *)pVal;
sqlite3VdbeMemIntegerify(pMem);
return (int)pVal->i;
return sqlite3VdbeIntValue((Mem*)pVal);
}
sqlite_int64 sqlite3_value_int64(sqlite3_value *pVal){
Mem *pMem = (Mem *)pVal;
sqlite3VdbeMemIntegerify(pMem);
return pVal->i;
return sqlite3VdbeIntValue((Mem*)pVal);
}
const unsigned char *sqlite3_value_text(sqlite3_value *pVal){
return (const char *)sqlite3ValueText(pVal, SQLITE_UTF8);

View File

@ -207,50 +207,76 @@ void sqlite3VdbeMemRelease(Mem *p){
}
/*
** Convert the Mem to have representation MEM_Int only. All
** prior representations are invalidated. NULL is converted into 0.
** Return some kind of integer value which is the best we can do
** at representing the value that *pMem describes as an integer.
** If pMem is an integer, then the value is exact. If pMem is
** a floating-point then the value returned is the integer part.
** If pMem is a string or blob, then we make an attempt to convert
** it into a integer and return that. If pMem is NULL, return 0.
**
** If pMem is a string, its encoding might be changed.
*/
int sqlite3VdbeMemIntegerify(Mem *pMem){
i64 sqlite3VdbeIntValue(Mem *pMem){
int flags = pMem->flags;
if( flags & MEM_Int ){
/* Do nothing */
return pMem->i;
}else if( flags & MEM_Real ){
pMem->i = (i64)pMem->r;
return (i64)pMem->r;
}else if( flags & (MEM_Str|MEM_Blob) ){
i64 value;
if( sqlite3VdbeChangeEncoding(pMem, SQLITE_UTF8)
|| sqlite3VdbeMemNulTerminate(pMem) ){
return SQLITE_NOMEM;
}
assert( pMem->z );
sqlite3atoi64(pMem->z, &pMem->i);
sqlite3atoi64(pMem->z, &value);
return value;
}else{
pMem->i = 0;
return 0;
}
pMem->flags |= MEM_Int;
}
/*
** Convert pMem to type integer. Invalidate any prior representations.
*/
int sqlite3VdbeMemIntegerify(Mem *pMem){
pMem->i = sqlite3VdbeIntValue(pMem);
sqlite3VdbeMemRelease(pMem);
pMem->flags = MEM_Int;
return SQLITE_OK;
}
/*
** Add MEM_Real to the set of representations for pMem. Prior
** prior representations other than MEM_Null retained. NULL is
** converted into 0.0.
** Return the best representation of pMem that we can get into a
** double. If pMem is already a double or an integer, return its
** value. If it is a string or blob, try to convert it to a double.
** If it is a NULL, return 0.0.
*/
int sqlite3VdbeMemRealify(Mem *pMem){
double sqlite3VdbeRealValue(Mem *pMem){
if( pMem->flags & MEM_Real ){
/* Do nothing */
}else if( (pMem->flags & MEM_Int) && pMem->type!=SQLITE_TEXT ){
pMem->r = pMem->i;
return pMem->r;
}else if( pMem->flags & MEM_Int ){
return (double)pMem->i;
}else if( pMem->flags & (MEM_Str|MEM_Blob) ){
if( sqlite3VdbeChangeEncoding(pMem, SQLITE_UTF8)
|| sqlite3VdbeMemNulTerminate(pMem) ){
return SQLITE_NOMEM;
}
assert( pMem->z );
pMem->r = sqlite3AtoF(pMem->z, 0);
return sqlite3AtoF(pMem->z, 0);
}else{
pMem->r = 0.0;
return 0.0;
}
pMem->flags |= MEM_Real;
}
/*
** Convert pMem so that it is of type MEM_Real. Invalidate any
** prior representations.
*/
int sqlite3VdbeMemRealify(Mem *pMem){
pMem->r = sqlite3VdbeRealValue(pMem);
sqlite3VdbeMemRelease(pMem);
pMem->flags = MEM_Real;
return SQLITE_OK;
}
@ -599,6 +625,9 @@ void sqlite3VdbeMemSanity(Mem *pMem, u8 db_enc){
/* MEM_Null excludes all other types */
assert( (pMem->flags&(MEM_Str|MEM_Int|MEM_Real|MEM_Blob))==0
|| (pMem->flags&MEM_Null)==0 );
if( (pMem->flags & (MEM_Int|MEM_Real))==(MEM_Int|MEM_Real) ){
assert( pMem->r==pMem->i );
}
}
#endif
@ -623,6 +652,9 @@ const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){
return (const void *)(pVal->z);
}
/*
** Create a new sqlite3_value object.
*/
sqlite3_value* sqlite3ValueNew(){
Mem *p = sqliteMalloc(sizeof(*p));
if( p ){
@ -632,6 +664,9 @@ sqlite3_value* sqlite3ValueNew(){
return p;
}
/*
** Change the string value of an sqlite3_value object
*/
void sqlite3ValueSetStr(
sqlite3_value *v,
int n,
@ -642,12 +677,19 @@ void sqlite3ValueSetStr(
if( v ) sqlite3VdbeMemSetStr((Mem *)v, z, n, enc, xDel);
}
/*
** Free an sqlite3_value object
*/
void sqlite3ValueFree(sqlite3_value *v){
if( !v ) return;
sqlite3ValueSetStr(v, 0, 0, SQLITE_UTF8, SQLITE_STATIC);
sqliteFree(v);
}
/*
** Return the number of bytes in the sqlite3_value object assuming
** that it uses the encoding "enc"
*/
int sqlite3ValueBytes(sqlite3_value *pVal, u8 enc){
Mem *p = (Mem*)pVal;
if( (p->flags & MEM_Blob)!=0 || sqlite3ValueText(pVal, enc) ){

View File

@ -11,7 +11,7 @@
# This file implements regression tests for SQLite library. The
# focus of this script testing the callback-free C/C++ API.
#
# $Id: capi3.test,v 1.12 2004/06/19 03:33:57 danielk1977 Exp $
# $Id: capi3.test,v 1.13 2004/06/27 01:56:33 drh Exp $
#
set testdir [file dirname $argv0]
@ -397,5 +397,3 @@ do_test capi3-6.4 {
} {SQLITE_OK}
finish_test