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

Rework the VDBE data structures to combine string representations into the

same structure with integer and floating point.  This opens the door to
significant optimizations. (CVS 1202)

FossilOrigin-Name: c0faa1c67a967f028cd018e58988fb08bc814d3d
This commit is contained in:
drh
2004-01-30 14:49:16 +00:00
parent 0c37e6309b
commit 00706be366
6 changed files with 428 additions and 445 deletions

View File

@@ -1,5 +1,5 @@
C Make\ssure\smin()\sand\smax()\soptimizations\swork\sfor\ssubqueries.\sTicket\s#587.\s(CVS\s1201) C Rework\sthe\sVDBE\sdata\sstructures\sto\scombine\sstring\srepresentations\sinto\sthe\nsame\sstructure\swith\sinteger\sand\sfloating\spoint.\s\sThis\sopens\sthe\sdoor\sto\nsignificant\soptimizations.\s(CVS\s1202)
D 2004-01-30T02:01:04 D 2004-01-30T14:49:17
F Makefile.in 0515ff9218ad8d5a8f6220f0494b8ef94c67013b F Makefile.in 0515ff9218ad8d5a8f6220f0494b8ef94c67013b
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -32,7 +32,7 @@ F src/date.c c6b7e3fa5364d50fe19641882194f3c75364a5af
F src/delete.c 0778fe05df0a1d62ac27fd1a3dba237c186ff4d1 F src/delete.c 0778fe05df0a1d62ac27fd1a3dba237c186ff4d1
F src/encode.c 9e70ea1e4e746f23f18180949e94f1bb1c2220d3 F src/encode.c 9e70ea1e4e746f23f18180949e94f1bb1c2220d3
F src/expr.c 3928893e8a7576484cd2ed5548468ba978d8005a F src/expr.c 3928893e8a7576484cd2ed5548468ba978d8005a
F src/func.c fd710743e4026dfebfd48c12d20b1a5c27318fa5 F src/func.c 5a0face8c3a948c62677243987a18ba2f9ef9c9b
F src/hash.c 9b56ef3b291e25168f630d5643a4264ec011c70e F src/hash.c 9b56ef3b291e25168f630d5643a4264ec011c70e
F src/hash.h 3247573ab95b9dd90bcca0307a75d9a16da1ccc7 F src/hash.h 3247573ab95b9dd90bcca0307a75d9a16da1ccc7
F src/insert.c 01f66866f35c986eab4a57373ca689a3255ef2df F src/insert.c 01f66866f35c986eab4a57373ca689a3255ef2df
@@ -61,10 +61,10 @@ F src/trigger.c ce83e017b407d046e909d05373d7f8ee70f9f7f9
F src/update.c 24260b4fda00c9726d27699a0561d53c0dccc397 F src/update.c 24260b4fda00c9726d27699a0561d53c0dccc397
F src/util.c 64995b5949a5d377629ffd2598747bc771cade1e F src/util.c 64995b5949a5d377629ffd2598747bc771cade1e
F src/vacuum.c 77485a64a6e4e358170f150fff681c1624a092b0 F src/vacuum.c 77485a64a6e4e358170f150fff681c1624a092b0
F src/vdbe.c 802364c5b1b989ec4592aaffcbf575fa3eb0478b F src/vdbe.c fcd5b6f27b3041ef022cf04ecaf63bbdccf88950
F src/vdbe.h 3957844e46fea71fd030e78f6a3bd2f7e320fb43 F src/vdbe.h 3957844e46fea71fd030e78f6a3bd2f7e320fb43
F src/vdbeInt.h eab39bc209b267271bc4afbcf4991d6c229bae9a F src/vdbeInt.h 6f12f5b9344cbb0e5cc2277458d84f7b951122bf
F src/vdbeaux.c dae9f8de7140daebbd621bfccb0982e17c352a9f F src/vdbeaux.c 358d955a23d29e268a3b45c428e49292b89dfcf5
F src/where.c 1302d728bd338c237e6a8282e4e3eadbbdf11e45 F src/where.c 1302d728bd338c237e6a8282e4e3eadbbdf11e45
F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242 F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242
F test/attach.test c26848402e7ac829e043e1fa5e0eb87032e5d81d F test/attach.test c26848402e7ac829e043e1fa5e0eb87032e5d81d
@@ -182,7 +182,7 @@ F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604
F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1 F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
P eafa714d1f0abe7e4822a6d137c2a7c6179ffab3 P af73fbca839f8cbe39c21f1f9e439fe9b79005c8
R d39fa065e30e1e0532ab6dc3e864bd94 R 498fe1480c9c56c03607a7a6c9f9b96c
U drh U drh
Z c358c54959e4dcb73fab284646bd586a Z 222ac74ccb7f92ccb269c2c94a8bca52

View File

@@ -1 +1 @@
af73fbca839f8cbe39c21f1f9e439fe9b79005c8 c0faa1c67a967f028cd018e58988fb08bc814d3d

View File

@@ -16,7 +16,7 @@
** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** sqliteRegisterBuildinFunctions() found at the bottom of the file.
** All other code has file scope. ** All other code has file scope.
** **
** $Id: func.c,v 1.37 2004/01/19 04:53:25 jplyon Exp $ ** $Id: func.c,v 1.38 2004/01/30 14:49:17 drh Exp $
*/ */
#include <ctype.h> #include <ctype.h>
#include <math.h> #include <math.h>
@@ -495,14 +495,16 @@ static void minStep(sqlite_func *context, int argc, const char **argv){
if( p==0 || argc<1 || argv[0]==0 ) return; if( p==0 || argc<1 || argv[0]==0 ) return;
if( p->z==0 || sqliteCompare(argv[0],p->z)<0 ){ if( p->z==0 || sqliteCompare(argv[0],p->z)<0 ){
int len; int len;
if( p->z && p->z!=p->zBuf ){ if( !p->zBuf[0] ){
sqliteFree(p->z); sqliteFree(p->z);
} }
len = strlen(argv[0]); len = strlen(argv[0]);
if( len < sizeof(p->zBuf) ){ if( len < sizeof(p->zBuf)-1 ){
p->z = p->zBuf; p->z = &p->zBuf[1];
p->zBuf[0] = 1;
}else{ }else{
p->z = sqliteMalloc( len+1 ); p->z = sqliteMalloc( len+1 );
p->zBuf[0] = 0;
if( p->z==0 ) return; if( p->z==0 ) return;
} }
strcpy(p->z, argv[0]); strcpy(p->z, argv[0]);
@@ -514,14 +516,16 @@ static void maxStep(sqlite_func *context, int argc, const char **argv){
if( p==0 || argc<1 || argv[0]==0 ) return; if( p==0 || argc<1 || argv[0]==0 ) return;
if( p->z==0 || sqliteCompare(argv[0],p->z)>0 ){ if( p->z==0 || sqliteCompare(argv[0],p->z)>0 ){
int len; int len;
if( p->z && p->z!=p->zBuf ){ if( !p->zBuf[0] ){
sqliteFree(p->z); sqliteFree(p->z);
} }
len = strlen(argv[0]); len = strlen(argv[0]);
if( len < sizeof(p->zBuf) ){ if( len < sizeof(p->zBuf)-1 ){
p->z = p->zBuf; p->z = &p->zBuf[1];
p->zBuf[0] = 1;
}else{ }else{
p->z = sqliteMalloc( len+1 ); p->z = sqliteMalloc( len+1 );
p->zBuf[0] = 0;
if( p->z==0 ) return; if( p->z==0 ) return;
} }
strcpy(p->z, argv[0]); strcpy(p->z, argv[0]);
@@ -533,7 +537,7 @@ static void minMaxFinalize(sqlite_func *context){
if( p && p->z ){ if( p && p->z ){
sqlite_set_result_string(context, p->z, strlen(p->z)); sqlite_set_result_string(context, p->z, strlen(p->z));
} }
if( p && p->z && p->z!=p->zBuf ){ if( p && !p->zBuf[0] ){
sqliteFree(p->z); sqliteFree(p->z);
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -106,47 +106,35 @@ struct Sorter {
#define NBFS 32 #define NBFS 32
/* /*
** A single level of the stack is an instance of the following ** A single level of the stack or a single memory cell
** structure. Except, string values are stored on a separate ** is an instance of the following structure.
** list of of pointers to character. The reason for storing
** strings separately is so that they can be easily passed
** to the callback function.
*/
struct Stack {
int i; /* Integer value */
int n; /* Number of characters in string value, including '\0' */
int flags; /* Some combination of STK_Null, STK_Str, STK_Dyn, etc. */
double r; /* Real value */
char z[NBFS]; /* Space for short strings */
};
typedef struct Stack Stack;
/*
** Memory cells use the same structure as the stack except that space
** for an arbitrary string is added.
*/ */
struct Mem { struct Mem {
Stack s; /* All values of the memory cell besides string */ int i; /* Integer value */
char *z; /* String value for this memory cell */ int n; /* Number of characters in string value, including '\0' */
int flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
double r; /* Real value */
char *z; /* String value */
char zShort[NBFS]; /* Space for short strings */
}; };
typedef struct Mem Mem; typedef struct Mem Mem;
/* /*
** Allowed values for Stack.flags ** Allowed values for Mem.flags
*/ */
#define STK_Null 0x0001 /* Value is NULL */ #define MEM_Null 0x0001 /* Value is NULL */
#define STK_Str 0x0002 /* Value is a string */ #define MEM_Str 0x0002 /* Value is a string */
#define STK_Int 0x0004 /* Value is an integer */ #define MEM_Int 0x0004 /* Value is an integer */
#define STK_Real 0x0008 /* Value is a real number */ #define MEM_Real 0x0008 /* Value is a real number */
#define STK_Dyn 0x0010 /* Need to call sqliteFree() on zStack[] */ #define MEM_Dyn 0x0010 /* Need to call sqliteFree() on Mem.z */
#define STK_Static 0x0020 /* zStack[] points to a static string */ #define MEM_Static 0x0020 /* Mem.z points to a static string */
#define STK_Ephem 0x0040 /* zStack[] points to an ephemeral string */ #define MEM_Ephem 0x0040 /* Mem.z points to an ephemeral string */
/* The following STK_ value appears only in AggElem.aMem.s.flag fields. /* The following MEM_ value appears only in AggElem.aMem.s.flag fields.
** It indicates that the corresponding AggElem.aMem.z points to a ** It indicates that the corresponding AggElem.aMem.z points to a
** aggregate function context that needs to be finalized. ** aggregate function context that needs to be finalized.
*/ */
#define STK_AggCtx 0x0040 /* zStack[] points to an agg function context */ #define MEM_AggCtx 0x0040 /* Mem.z points to an agg function context */
/* /*
** The "context" argument for a installable function. A pointer to an ** The "context" argument for a installable function. A pointer to an
@@ -159,12 +147,11 @@ typedef struct Mem Mem;
** structure are known. ** structure are known.
** **
** This structure is defined inside of vdbe.c because it uses substructures ** This structure is defined inside of vdbe.c because it uses substructures
** (Stack) which are only defined there. ** (Mem) which are only defined there.
*/ */
struct sqlite_func { struct sqlite_func {
FuncDef *pFunc; /* Pointer to function information. MUST BE FIRST */ FuncDef *pFunc; /* Pointer to function information. MUST BE FIRST */
Stack s; /* Small strings, ints, and double values go here */ Mem s; /* The return value is stored here */
char *z; /* Space for holding dynamic string results */
void *pAgg; /* Aggregate context */ void *pAgg; /* Aggregate context */
u8 isError; /* Set to true for an error */ u8 isError; /* Set to true for an error */
u8 isStep; /* Current in the step function */ u8 isStep; /* Current in the step function */
@@ -237,8 +224,8 @@ struct Vdbe {
int nLabelAlloc; /* Number of slots allocated in aLabel[] */ int nLabelAlloc; /* Number of slots allocated in aLabel[] */
int *aLabel; /* Space to hold the labels */ int *aLabel; /* Space to hold the labels */
int tos; /* Index of top of stack */ int tos; /* Index of top of stack */
Stack *aStack; /* The operand stack, except string values */ Mem *aStack; /* The operand stack, except string values */
char **zStack; /* Text or binary values of the stack */ char **zArgv; /* Text values used by the callback */
char **azColName; /* Becomes the 4th parameter to callbacks */ char **azColName; /* Becomes the 4th parameter to callbacks */
int nCursor; /* Number of slots in aCsr[] */ int nCursor; /* Number of slots in aCsr[] */
Cursor *aCsr; /* One element of this array for each open cursor */ Cursor *aCsr; /* One element of this array for each open cursor */
@@ -294,7 +281,7 @@ struct Vdbe {
*/ */
#define POPSTACK \ #define POPSTACK \
assert(p->tos>=0); \ assert(p->tos>=0); \
if( aStack[p->tos].flags & STK_Dyn ) sqliteFree(zStack[p->tos]); \ if( aStack[p->tos].flags & MEM_Dyn ) sqliteFree(aStack[p->tos].z); \
p->tos--; p->tos--;
/* /*

View File

@@ -375,48 +375,48 @@ VdbeOp *sqliteVdbeGetOp(Vdbe *p, int addr){
*/ */
char *sqlite_set_result_string(sqlite_func *p, const char *zResult, int n){ char *sqlite_set_result_string(sqlite_func *p, const char *zResult, int n){
assert( !p->isStep ); assert( !p->isStep );
if( p->s.flags & STK_Dyn ){ if( p->s.flags & MEM_Dyn ){
sqliteFree(p->z); sqliteFree(p->s.z);
} }
if( zResult==0 ){ if( zResult==0 ){
p->s.flags = STK_Null; p->s.flags = MEM_Null;
n = 0; n = 0;
p->z = 0; p->s.z = 0;
p->s.n = 0; p->s.n = 0;
}else{ }else{
if( n<0 ) n = strlen(zResult); if( n<0 ) n = strlen(zResult);
if( n<NBFS-1 ){ if( n<NBFS-1 ){
memcpy(p->s.z, zResult, n); memcpy(p->s.zShort, zResult, n);
p->s.z[n] = 0; p->s.zShort[n] = 0;
p->s.flags = STK_Str; p->s.flags = MEM_Str;
p->z = p->s.z; p->s.z = p->s.zShort;
}else{ }else{
p->z = sqliteMallocRaw( n+1 ); p->s.z = sqliteMallocRaw( n+1 );
if( p->z ){ if( p->s.z ){
memcpy(p->z, zResult, n); memcpy(p->s.z, zResult, n);
p->z[n] = 0; p->s.z[n] = 0;
} }
p->s.flags = STK_Str | STK_Dyn; p->s.flags = MEM_Str | MEM_Dyn;
} }
p->s.n = n+1; p->s.n = n+1;
} }
return p->z; return p->s.z;
} }
void sqlite_set_result_int(sqlite_func *p, int iResult){ void sqlite_set_result_int(sqlite_func *p, int iResult){
assert( !p->isStep ); assert( !p->isStep );
if( p->s.flags & STK_Dyn ){ if( p->s.flags & MEM_Dyn ){
sqliteFree(p->z); sqliteFree(p->s.z);
} }
p->s.i = iResult; p->s.i = iResult;
p->s.flags = STK_Int; p->s.flags = MEM_Int;
} }
void sqlite_set_result_double(sqlite_func *p, double rResult){ void sqlite_set_result_double(sqlite_func *p, double rResult){
assert( !p->isStep ); assert( !p->isStep );
if( p->s.flags & STK_Dyn ){ if( p->s.flags & MEM_Dyn ){
sqliteFree(p->z); sqliteFree(p->s.z);
} }
p->s.r = rResult; p->s.r = rResult;
p->s.flags = STK_Real; p->s.flags = MEM_Real;
} }
void sqlite_set_result_error(sqlite_func *p, const char *zMsg, int n){ void sqlite_set_result_error(sqlite_func *p, const char *zMsg, int n){
assert( !p->isStep ); assert( !p->isStep );
@@ -446,7 +446,8 @@ void *sqlite_aggregate_context(sqlite_func *p, int nByte){
assert( p && p->pFunc && p->pFunc->xStep ); assert( p && p->pFunc && p->pFunc->xStep );
if( p->pAgg==0 ){ if( p->pAgg==0 ){
if( nByte<=NBFS ){ if( nByte<=NBFS ){
p->pAgg = (void*)p->z; p->pAgg = (void*)p->s.z;
memset(p->pAgg, 0, nByte);
}else{ }else{
p->pAgg = sqliteMalloc( nByte ); p->pAgg = sqliteMalloc( nByte );
} }
@@ -508,8 +509,8 @@ int sqliteVdbeList(
assert( p->popStack==0 ); assert( p->popStack==0 );
assert( p->explain ); assert( p->explain );
p->azColName = azColumnNames; p->azColName = azColumnNames;
p->azResColumn = p->zStack; p->azResColumn = p->zArgv;
for(i=0; i<5; i++) p->zStack[i] = p->aStack[i].z; for(i=0; i<5; i++) p->zArgv[i] = p->aStack[i].zShort;
p->rc = SQLITE_OK; p->rc = SQLITE_OK;
for(i=p->pc; p->rc==SQLITE_OK && i<p->nOp; i++){ for(i=p->pc; p->rc==SQLITE_OK && i<p->nOp; i++){
if( db->flags & SQLITE_Interrupt ){ if( db->flags & SQLITE_Interrupt ){
@@ -522,19 +523,19 @@ int sqliteVdbeList(
sqliteSetString(&p->zErrMsg, sqlite_error_string(p->rc), (char*)0); sqliteSetString(&p->zErrMsg, sqlite_error_string(p->rc), (char*)0);
break; break;
} }
sprintf(p->zStack[0],"%d",i); sprintf(p->zArgv[0],"%d",i);
sprintf(p->zStack[2],"%d", p->aOp[i].p1); sprintf(p->zArgv[2],"%d", p->aOp[i].p1);
sprintf(p->zStack[3],"%d", p->aOp[i].p2); sprintf(p->zArgv[3],"%d", p->aOp[i].p2);
if( p->aOp[i].p3type==P3_POINTER ){ if( p->aOp[i].p3type==P3_POINTER ){
sprintf(p->aStack[4].z, "ptr(%#x)", (int)p->aOp[i].p3); sprintf(p->aStack[4].zShort, "ptr(%#x)", (int)p->aOp[i].p3);
p->zStack[4] = p->aStack[4].z; p->zArgv[4] = p->aStack[4].zShort;
}else{ }else{
p->zStack[4] = p->aOp[i].p3; p->zArgv[4] = p->aOp[i].p3;
} }
p->zStack[1] = sqliteOpcodeNames[p->aOp[i].opcode]; p->zArgv[1] = sqliteOpcodeNames[p->aOp[i].opcode];
if( p->xCallback==0 ){ if( p->xCallback==0 ){
p->pc = i+1; p->pc = i+1;
p->azResColumn = p->zStack; p->azResColumn = p->zArgv;
p->nResColumn = 5; p->nResColumn = 5;
return SQLITE_ROW; return SQLITE_ROW;
} }
@@ -542,7 +543,7 @@ int sqliteVdbeList(
p->rc = SQLITE_MISUSE; p->rc = SQLITE_MISUSE;
break; break;
} }
if( p->xCallback(p->pCbArg, 5, p->zStack, p->azColName) ){ if( p->xCallback(p->pCbArg, 5, p->zArgv, p->azColName) ){
p->rc = SQLITE_ABORT; p->rc = SQLITE_ABORT;
} }
if( sqliteSafetyOn(db) ){ if( sqliteSafetyOn(db) ){
@@ -596,11 +597,11 @@ void sqliteVdbeMakeReady(
assert( nVar>=0 ); assert( nVar>=0 );
n = isExplain ? 10 : p->nOp; n = isExplain ? 10 : p->nOp;
p->aStack = sqliteMalloc( p->aStack = sqliteMalloc(
n*(sizeof(p->aStack[0]) + 2*sizeof(char*)) /* aStack and zStack */ n*(sizeof(p->aStack[0]) + 2*sizeof(char*)) /* aStack and zArgv */
+ p->nVar*(sizeof(char*)+sizeof(int)+1) /* azVar, anVar, abVar */ + p->nVar*(sizeof(char*)+sizeof(int)+1) /* azVar, anVar, abVar */
); );
p->zStack = (char**)&p->aStack[n]; p->zArgv = (char**)&p->aStack[n];
p->azColName = (char**)&p->zStack[n]; p->azColName = (char**)&p->zArgv[n];
p->azVar = (char**)&p->azColName[n]; p->azVar = (char**)&p->azColName[n];
p->anVar = (int*)&p->azVar[p->nVar]; p->anVar = (int*)&p->azVar[p->nVar];
p->abVar = (u8*)&p->anVar[p->nVar]; p->abVar = (u8*)&p->anVar[p->nVar];
@@ -656,15 +657,12 @@ void sqliteVdbeSorterReset(Vdbe *p){
*/ */
void sqliteVdbePopStack(Vdbe *p, int N){ void sqliteVdbePopStack(Vdbe *p, int N){
assert( N>=0 ); assert( N>=0 );
if( p->zStack==0 ) return;
assert( p->aStack || sqlite_malloc_failed );
if( p->aStack==0 ) return; if( p->aStack==0 ) return;
while( N-- > 0 ){ while( N-- > 0 ){
if( p->aStack[p->tos].flags & STK_Dyn ){ if( p->aStack[p->tos].flags & MEM_Dyn ){
sqliteFree(p->zStack[p->tos]); sqliteFree(p->aStack[p->tos].z);
} }
p->aStack[p->tos].flags = 0; p->aStack[p->tos].flags = 0;
p->zStack[p->tos] = 0;
p->tos--; p->tos--;
} }
} }
@@ -686,20 +684,19 @@ void sqliteVdbeAggReset(Agg *pAgg){
assert( pAgg->apFunc!=0 ); assert( pAgg->apFunc!=0 );
for(i=0; i<pAgg->nMem; i++){ for(i=0; i<pAgg->nMem; i++){
Mem *pMem = &pElem->aMem[i]; Mem *pMem = &pElem->aMem[i];
if( pAgg->apFunc[i] && (pMem->s.flags & STK_AggCtx)!=0 ){ if( pAgg->apFunc[i] && (pMem->flags & MEM_AggCtx)!=0 ){
sqlite_func ctx; sqlite_func ctx;
ctx.pFunc = pAgg->apFunc[i]; ctx.pFunc = pAgg->apFunc[i];
ctx.s.flags = STK_Null; ctx.s.flags = MEM_Null;
ctx.z = 0;
ctx.pAgg = pMem->z; ctx.pAgg = pMem->z;
ctx.cnt = pMem->s.i; ctx.cnt = pMem->i;
ctx.isStep = 0; ctx.isStep = 0;
ctx.isError = 0; ctx.isError = 0;
(*pAgg->apFunc[i]->xFinalize)(&ctx); (*pAgg->apFunc[i]->xFinalize)(&ctx);
if( pMem->z!=0 && pMem->z!=pMem->s.z ){ if( pMem->z!=0 && pMem->z!=pMem->zShort ){
sqliteFree(pMem->z); sqliteFree(pMem->z);
} }
}else if( pMem->s.flags & STK_Dyn ){ }else if( pMem->flags & MEM_Dyn ){
sqliteFree(pMem->z); sqliteFree(pMem->z);
} }
} }
@@ -765,7 +762,7 @@ static void Cleanup(Vdbe *p){
closeAllCursors(p); closeAllCursors(p);
if( p->aMem ){ if( p->aMem ){
for(i=0; i<p->nMem; i++){ for(i=0; i<p->nMem; i++){
if( p->aMem[i].s.flags & STK_Dyn ){ if( p->aMem[i].flags & MEM_Dyn ){
sqliteFree(p->aMem[i].z); sqliteFree(p->aMem[i].z);
} }
} }