mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-30 19:03:16 +03:00
Ensure that all auxiliary data registered by calls to sqlite3_set_auxdata() is destroyed when the VM is halted. Partial fix for [406d3b2ef9].
FossilOrigin-Name: 71effa59c98d167e6e4b269e59ad5f468e664ac1
This commit is contained in:
24
manifest
24
manifest
@ -1,5 +1,5 @@
|
|||||||
C Fix\sa\s8-byte\salignment\sproblem\sin\sthe\squery\splanner\sthat\smight\scause\nproblems\son\ssparc\swhen\scompiled\swith\s-m32.
|
C Ensure\sthat\sall\sauxiliary\sdata\sregistered\sby\scalls\sto\ssqlite3_set_auxdata()\sis\sdestroyed\swhen\sthe\sVM\sis\shalted.\sPartial\sfix\sfor\s[406d3b2ef9].
|
||||||
D 2013-07-18T14:50:56.888
|
D 2013-07-18T17:12:08.417
|
||||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||||
F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e
|
F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e
|
||||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||||
@ -277,11 +277,11 @@ F src/update.c 8e76c3d03e4b7b21cb250bd2df0c05e12993e577
|
|||||||
F src/utf.c 8d819e2e5104a430fc2005f018db14347c95a38f
|
F src/utf.c 8d819e2e5104a430fc2005f018db14347c95a38f
|
||||||
F src/util.c f566b5138099a2df8533b190d0dcc74b7dfbe0c9
|
F src/util.c f566b5138099a2df8533b190d0dcc74b7dfbe0c9
|
||||||
F src/vacuum.c d9c5759f4c5a438bb43c2086f72c5d2edabc36c8
|
F src/vacuum.c d9c5759f4c5a438bb43c2086f72c5d2edabc36c8
|
||||||
F src/vdbe.c 420ebf1d551a76406cbbe0adc52d22d45aac039a
|
F src/vdbe.c 7fab3ee5adbcf841fad9db65308ac5dc36c4e0be
|
||||||
F src/vdbe.h b52887278cb173e66188da84dfab216bea61119d
|
F src/vdbe.h f380af2a7fab32ba8a8b05bf042497636afec66d
|
||||||
F src/vdbeInt.h 5e666c971c555c7977714b0e34cb8d4b20282557
|
F src/vdbeInt.h e9b7c6b165a31a4715c5aa97223d20d265515231
|
||||||
F src/vdbeapi.c c88222946d657984bdaf394604cb58ed1d641460
|
F src/vdbeapi.c 4d13580bd058b39623e8fcfc233b7df4b8191e8b
|
||||||
F src/vdbeaux.c 1633408f6dea06129441c5e2f22b2a5ce30fe97e
|
F src/vdbeaux.c c01594ecf5a78ef41a721f3465152bb91883a942
|
||||||
F src/vdbeblob.c 5dc79627775bd9a9b494dd956e26297946417d69
|
F src/vdbeblob.c 5dc79627775bd9a9b494dd956e26297946417d69
|
||||||
F src/vdbemem.c 833005f1cbbf447289f1973dba2a0c2228c7b8ab
|
F src/vdbemem.c 833005f1cbbf447289f1973dba2a0c2228c7b8ab
|
||||||
F src/vdbesort.c 3937e06b2a0e354500e17dc206ef4c35770a5017
|
F src/vdbesort.c 3937e06b2a0e354500e17dc206ef4c35770a5017
|
||||||
@ -556,7 +556,7 @@ F test/fts4merge4.test c19c85ca1faa7b6d536832b49c12e1867235f584
|
|||||||
F test/fts4noti.test aed33ba44808852dcb24bf70fa132e7bf530f057
|
F test/fts4noti.test aed33ba44808852dcb24bf70fa132e7bf530f057
|
||||||
F test/fts4unicode.test c8ac44217bf6c17812b03eaafa6c06995ad304c2
|
F test/fts4unicode.test c8ac44217bf6c17812b03eaafa6c06995ad304c2
|
||||||
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
|
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
|
||||||
F test/func.test b0fc34fdc36897769651975a2b0a606312753643
|
F test/func.test 9161beda516d6006d31e6ea6119579286512f751
|
||||||
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
|
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
|
||||||
F test/func3.test 001021e5b88bd02a3b365a5c5fd8f6f49d39744a
|
F test/func3.test 001021e5b88bd02a3b365a5c5fd8f6f49d39744a
|
||||||
F test/fuzz-oss1.test 4912e528ec9cf2f42134456933659d371c9e0d74
|
F test/fuzz-oss1.test 4912e528ec9cf2f42134456933659d371c9e0d74
|
||||||
@ -1103,7 +1103,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
|||||||
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
||||||
F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae
|
F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae
|
||||||
F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
|
F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
|
||||||
P 7acc8cd32d593a473c9e9adaf323220a7a46480a
|
P 5dcffa671f592ae9355628afa439ae9a2d26f0cd
|
||||||
R 17b8abd2c5b717cffa3f1d157b1c3142
|
R 5f8d56aac1f51039dd4e137aed108558
|
||||||
U drh
|
U dan
|
||||||
Z 8aedb025f873aeef3a714ef3251c3e91
|
Z e317751ba4c386bb8e1c47226cf1f704
|
||||||
|
@ -1 +1 @@
|
|||||||
5dcffa671f592ae9355628afa439ae9a2d26f0cd
|
71effa59c98d167e6e4b269e59ad5f468e664ac1
|
19
src/vdbe.c
19
src/vdbe.c
@ -1420,19 +1420,14 @@ case OP_Function: {
|
|||||||
REGISTER_TRACE(pOp->p2+i, pArg);
|
REGISTER_TRACE(pOp->p2+i, pArg);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert( pOp->p4type==P4_FUNCDEF || pOp->p4type==P4_VDBEFUNC );
|
assert( pOp->p4type==P4_FUNCDEF );
|
||||||
if( pOp->p4type==P4_FUNCDEF ){
|
ctx.pFunc = pOp->p4.pFunc;
|
||||||
ctx.pFunc = pOp->p4.pFunc;
|
|
||||||
ctx.pVdbeFunc = 0;
|
|
||||||
}else{
|
|
||||||
ctx.pVdbeFunc = (VdbeFunc*)pOp->p4.pVdbeFunc;
|
|
||||||
ctx.pFunc = ctx.pVdbeFunc->pFunc;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.s.flags = MEM_Null;
|
ctx.s.flags = MEM_Null;
|
||||||
ctx.s.db = db;
|
ctx.s.db = db;
|
||||||
ctx.s.xDel = 0;
|
ctx.s.xDel = 0;
|
||||||
ctx.s.zMalloc = 0;
|
ctx.s.zMalloc = 0;
|
||||||
|
ctx.iOp = pc;
|
||||||
|
ctx.pVdbe = p;
|
||||||
|
|
||||||
/* The output cell may already have a buffer allocated. Move
|
/* The output cell may already have a buffer allocated. Move
|
||||||
** the pointer to ctx.s so in case the user-function can use
|
** the pointer to ctx.s so in case the user-function can use
|
||||||
@ -1455,11 +1450,7 @@ case OP_Function: {
|
|||||||
/* If any auxiliary data functions have been called by this user function,
|
/* If any auxiliary data functions have been called by this user function,
|
||||||
** immediately call the destructor for any non-static values.
|
** immediately call the destructor for any non-static values.
|
||||||
*/
|
*/
|
||||||
if( ctx.pVdbeFunc ){
|
sqlite3VdbeDeleteAuxData(ppc, pc, pOp->p1);
|
||||||
sqlite3VdbeDeleteAuxData(ctx.pVdbeFunc, pOp->p1);
|
|
||||||
pOp->p4.pVdbeFunc = ctx.pVdbeFunc;
|
|
||||||
pOp->p4type = P4_VDBEFUNC;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( db->mallocFailed ){
|
if( db->mallocFailed ){
|
||||||
/* Even though a malloc() has failed, the implementation of the
|
/* Even though a malloc() has failed, the implementation of the
|
||||||
|
@ -30,7 +30,6 @@ typedef struct Vdbe Vdbe;
|
|||||||
** The names of the following types declared in vdbeInt.h are required
|
** The names of the following types declared in vdbeInt.h are required
|
||||||
** for the VdbeOp definition.
|
** for the VdbeOp definition.
|
||||||
*/
|
*/
|
||||||
typedef struct VdbeFunc VdbeFunc;
|
|
||||||
typedef struct Mem Mem;
|
typedef struct Mem Mem;
|
||||||
typedef struct SubProgram SubProgram;
|
typedef struct SubProgram SubProgram;
|
||||||
|
|
||||||
@ -54,7 +53,6 @@ struct VdbeOp {
|
|||||||
i64 *pI64; /* Used when p4type is P4_INT64 */
|
i64 *pI64; /* Used when p4type is P4_INT64 */
|
||||||
double *pReal; /* Used when p4type is P4_REAL */
|
double *pReal; /* Used when p4type is P4_REAL */
|
||||||
FuncDef *pFunc; /* Used when p4type is P4_FUNCDEF */
|
FuncDef *pFunc; /* Used when p4type is P4_FUNCDEF */
|
||||||
VdbeFunc *pVdbeFunc; /* Used when p4type is P4_VDBEFUNC */
|
|
||||||
CollSeq *pColl; /* Used when p4type is P4_COLLSEQ */
|
CollSeq *pColl; /* Used when p4type is P4_COLLSEQ */
|
||||||
Mem *pMem; /* Used when p4type is P4_MEM */
|
Mem *pMem; /* Used when p4type is P4_MEM */
|
||||||
VTable *pVtab; /* Used when p4type is P4_VTAB */
|
VTable *pVtab; /* Used when p4type is P4_VTAB */
|
||||||
@ -108,7 +106,6 @@ typedef struct VdbeOpList VdbeOpList;
|
|||||||
#define P4_COLLSEQ (-4) /* P4 is a pointer to a CollSeq structure */
|
#define P4_COLLSEQ (-4) /* P4 is a pointer to a CollSeq structure */
|
||||||
#define P4_FUNCDEF (-5) /* P4 is a pointer to a FuncDef structure */
|
#define P4_FUNCDEF (-5) /* P4 is a pointer to a FuncDef structure */
|
||||||
#define P4_KEYINFO (-6) /* P4 is a pointer to a KeyInfo structure */
|
#define P4_KEYINFO (-6) /* P4 is a pointer to a KeyInfo structure */
|
||||||
#define P4_VDBEFUNC (-7) /* P4 is a pointer to a VdbeFunc structure */
|
|
||||||
#define P4_MEM (-8) /* P4 is a pointer to a Mem* structure */
|
#define P4_MEM (-8) /* P4 is a pointer to a Mem* structure */
|
||||||
#define P4_TRANSIENT 0 /* P4 is a pointer to a transient string */
|
#define P4_TRANSIENT 0 /* P4 is a pointer to a transient string */
|
||||||
#define P4_VTAB (-10) /* P4 is a pointer to an sqlite3_vtab structure */
|
#define P4_VTAB (-10) /* P4 is a pointer to an sqlite3_vtab structure */
|
||||||
|
@ -44,6 +44,9 @@ typedef struct VdbeSorter VdbeSorter;
|
|||||||
/* Opaque type used by the explainer */
|
/* Opaque type used by the explainer */
|
||||||
typedef struct Explain Explain;
|
typedef struct Explain Explain;
|
||||||
|
|
||||||
|
/* Elements of the linked list at Vdbe.pAuxData */
|
||||||
|
typedef struct AuxData AuxData;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** A cursor is a pointer into a single BTree within a database file.
|
** A cursor is a pointer into a single BTree within a database file.
|
||||||
** The cursor can seek to a BTree entry with a particular key, or
|
** The cursor can seek to a BTree entry with a particular key, or
|
||||||
@ -230,23 +233,19 @@ struct Mem {
|
|||||||
#define memIsValid(M) ((M)->flags & MEM_Invalid)==0
|
#define memIsValid(M) ((M)->flags & MEM_Invalid)==0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
/* A VdbeFunc is just a FuncDef (defined in sqliteInt.h) that contains
|
** Each auxilliary data pointer stored by a user defined function
|
||||||
** additional information about auxiliary information bound to arguments
|
** implementation calling sqlite3_set_auxdata() is stored in an instance
|
||||||
** of the function. This is used to implement the sqlite3_get_auxdata()
|
** of this structure. All such structures associated with a single VM
|
||||||
** and sqlite3_set_auxdata() APIs. The "auxdata" is some auxiliary data
|
** are stored in a linked list headed at Vdbe.pAuxData. All are destroyed
|
||||||
** that can be associated with a constant argument to a function. This
|
** when the VM is halted (if not before).
|
||||||
** allows functions such as "regexp" to compile their constant regular
|
|
||||||
** expression argument once and reused the compiled code for multiple
|
|
||||||
** invocations.
|
|
||||||
*/
|
*/
|
||||||
struct VdbeFunc {
|
struct AuxData {
|
||||||
FuncDef *pFunc; /* The definition of the function */
|
int iOp; /* Instruction number of OP_Function opcode */
|
||||||
int nAux; /* Number of entries allocated for apAux[] */
|
int iArg; /* Index of function argument. */
|
||||||
struct AuxData {
|
void *pAux; /* Aux data pointer */
|
||||||
void *pAux; /* Aux data for the i-th argument */
|
void (*xDelete)(void *); /* Destructor for the aux data */
|
||||||
void (*xDelete)(void *); /* Destructor for the aux data */
|
AuxData *pNext; /* Next element in list */
|
||||||
} apAux[1]; /* One slot for each function argument */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -264,12 +263,13 @@ struct VdbeFunc {
|
|||||||
*/
|
*/
|
||||||
struct sqlite3_context {
|
struct sqlite3_context {
|
||||||
FuncDef *pFunc; /* Pointer to function information. MUST BE FIRST */
|
FuncDef *pFunc; /* Pointer to function information. MUST BE FIRST */
|
||||||
VdbeFunc *pVdbeFunc; /* Auxilary data, if created. */
|
|
||||||
Mem s; /* The return value is stored here */
|
Mem s; /* The return value is stored here */
|
||||||
Mem *pMem; /* Memory cell used to store aggregate context */
|
Mem *pMem; /* Memory cell used to store aggregate context */
|
||||||
CollSeq *pColl; /* Collating sequence */
|
CollSeq *pColl; /* Collating sequence */
|
||||||
int isError; /* Error code returned by the function. */
|
int isError; /* Error code returned by the function. */
|
||||||
int skipFlag; /* Skip skip accumulator loading if true */
|
int skipFlag; /* Skip skip accumulator loading if true */
|
||||||
|
int iOp; /* Instruction number of OP_Function */
|
||||||
|
Vdbe *pVdbe; /* The VM that owns this context */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -368,6 +368,7 @@ struct Vdbe {
|
|||||||
SubProgram *pProgram; /* Linked list of all sub-programs used by VM */
|
SubProgram *pProgram; /* Linked list of all sub-programs used by VM */
|
||||||
int nOnceFlag; /* Size of array aOnceFlag[] */
|
int nOnceFlag; /* Size of array aOnceFlag[] */
|
||||||
u8 *aOnceFlag; /* Flags for OP_Once */
|
u8 *aOnceFlag; /* Flags for OP_Once */
|
||||||
|
AuxData *pAuxData; /* Linked list of auxdata allocations */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -391,7 +392,7 @@ u32 sqlite3VdbeSerialTypeLen(u32);
|
|||||||
u32 sqlite3VdbeSerialType(Mem*, int);
|
u32 sqlite3VdbeSerialType(Mem*, int);
|
||||||
u32 sqlite3VdbeSerialPut(unsigned char*, int, Mem*, int);
|
u32 sqlite3VdbeSerialPut(unsigned char*, int, Mem*, int);
|
||||||
u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
|
u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
|
||||||
void sqlite3VdbeDeleteAuxData(VdbeFunc*, int);
|
void sqlite3VdbeDeleteAuxData(Vdbe*, int, int);
|
||||||
|
|
||||||
int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
|
int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
|
||||||
int sqlite3VdbeIdxKeyCompare(VdbeCursor*,UnpackedRecord*,int*);
|
int sqlite3VdbeIdxKeyCompare(VdbeCursor*,UnpackedRecord*,int*);
|
||||||
|
@ -584,14 +584,14 @@ void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){
|
|||||||
** the user-function defined by pCtx.
|
** the user-function defined by pCtx.
|
||||||
*/
|
*/
|
||||||
void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){
|
void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){
|
||||||
VdbeFunc *pVdbeFunc;
|
AuxData *pAuxData;
|
||||||
|
|
||||||
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
|
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
|
||||||
pVdbeFunc = pCtx->pVdbeFunc;
|
for(pAuxData=pCtx->pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNext){
|
||||||
if( !pVdbeFunc || iArg>=pVdbeFunc->nAux || iArg<0 ){
|
if( pAuxData->iOp==pCtx->iOp && pAuxData->iArg==iArg ) break;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
return pVdbeFunc->apAux[iArg].pAux;
|
|
||||||
|
return (pAuxData ? pAuxData->pAux : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -605,29 +605,26 @@ void sqlite3_set_auxdata(
|
|||||||
void *pAux,
|
void *pAux,
|
||||||
void (*xDelete)(void*)
|
void (*xDelete)(void*)
|
||||||
){
|
){
|
||||||
struct AuxData *pAuxData;
|
AuxData *pAuxData;
|
||||||
VdbeFunc *pVdbeFunc;
|
Vdbe *pVdbe = pCtx->pVdbe;
|
||||||
if( iArg<0 ) goto failed;
|
|
||||||
|
|
||||||
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
|
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
|
||||||
pVdbeFunc = pCtx->pVdbeFunc;
|
if( iArg<0 ) goto failed;
|
||||||
if( !pVdbeFunc || pVdbeFunc->nAux<=iArg ){
|
|
||||||
int nAux = (pVdbeFunc ? pVdbeFunc->nAux : 0);
|
|
||||||
int nMalloc = sizeof(VdbeFunc) + sizeof(struct AuxData)*iArg;
|
|
||||||
pVdbeFunc = sqlite3DbRealloc(pCtx->s.db, pVdbeFunc, nMalloc);
|
|
||||||
if( !pVdbeFunc ){
|
|
||||||
goto failed;
|
|
||||||
}
|
|
||||||
pCtx->pVdbeFunc = pVdbeFunc;
|
|
||||||
memset(&pVdbeFunc->apAux[nAux], 0, sizeof(struct AuxData)*(iArg+1-nAux));
|
|
||||||
pVdbeFunc->nAux = iArg+1;
|
|
||||||
pVdbeFunc->pFunc = pCtx->pFunc;
|
|
||||||
}
|
|
||||||
|
|
||||||
pAuxData = &pVdbeFunc->apAux[iArg];
|
for(pAuxData=pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNext){
|
||||||
if( pAuxData->pAux && pAuxData->xDelete ){
|
if( pAuxData->iOp==pCtx->iOp && pAuxData->iArg==iArg ) break;
|
||||||
|
}
|
||||||
|
if( pAuxData==0 ){
|
||||||
|
pAuxData = sqlite3DbMallocZero(pVdbe->db, sizeof(AuxData));
|
||||||
|
if( !pAuxData ) goto failed;
|
||||||
|
pAuxData->iOp = pCtx->iOp;
|
||||||
|
pAuxData->iArg = iArg;
|
||||||
|
pAuxData->pNext = pVdbe->pAuxData;
|
||||||
|
pVdbe->pAuxData = pAuxData;
|
||||||
|
}else if( pAuxData->xDelete ){
|
||||||
pAuxData->xDelete(pAuxData->pAux);
|
pAuxData->xDelete(pAuxData->pAux);
|
||||||
}
|
}
|
||||||
|
|
||||||
pAuxData->pAux = pAux;
|
pAuxData->pAux = pAux;
|
||||||
pAuxData->xDelete = xDelete;
|
pAuxData->xDelete = xDelete;
|
||||||
return;
|
return;
|
||||||
|
@ -612,13 +612,6 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){
|
|||||||
if( db->pnBytesFreed==0 ) sqlite3_free(p4);
|
if( db->pnBytesFreed==0 ) sqlite3_free(p4);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case P4_VDBEFUNC: {
|
|
||||||
VdbeFunc *pVdbeFunc = (VdbeFunc *)p4;
|
|
||||||
freeEphemeralFunction(db, pVdbeFunc->pFunc);
|
|
||||||
if( db->pnBytesFreed==0 ) sqlite3VdbeDeleteAuxData(pVdbeFunc, 0);
|
|
||||||
sqlite3DbFree(db, pVdbeFunc);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case P4_FUNCDEF: {
|
case P4_FUNCDEF: {
|
||||||
freeEphemeralFunction(db, (FuncDef*)p4);
|
freeEphemeralFunction(db, (FuncDef*)p4);
|
||||||
break;
|
break;
|
||||||
@ -1648,6 +1641,10 @@ static void closeAllCursors(Vdbe *p){
|
|||||||
p->pDelFrame = pDel->pParent;
|
p->pDelFrame = pDel->pParent;
|
||||||
sqlite3VdbeFrameDelete(pDel);
|
sqlite3VdbeFrameDelete(pDel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Delete any auxdata allocations made by the VM */
|
||||||
|
sqlite3VdbeDeleteAuxData(p, -1, 0);
|
||||||
|
assert( p->pAuxData==0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2446,20 +2443,35 @@ int sqlite3VdbeFinalize(Vdbe *p){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Call the destructor for each auxdata entry in pVdbeFunc for which
|
** If parameter iOp is less than zero, then invoke the destructor for
|
||||||
** the corresponding bit in mask is clear. Auxdata entries beyond 31
|
** all auxiliary data pointers currently cached by the VM passed as
|
||||||
** are always destroyed. To destroy all auxdata entries, call this
|
** the first argument.
|
||||||
** routine with mask==0.
|
**
|
||||||
|
** Or, if iOp is greater than or equal to zero, then the destructor is
|
||||||
|
** only invoked for those auxiliary data pointers created by the user
|
||||||
|
** function invoked by the OP_Function opcode at instruction iOp of
|
||||||
|
** VM pVdbe, and only then if:
|
||||||
|
**
|
||||||
|
** * the associated function parameter is the 32nd or later (counting
|
||||||
|
** from left to right), or
|
||||||
|
**
|
||||||
|
** * the corresponding bit in argument mask is clear (where the first
|
||||||
|
** function parameter corrsponds to bit 0 etc.).
|
||||||
*/
|
*/
|
||||||
void sqlite3VdbeDeleteAuxData(VdbeFunc *pVdbeFunc, int mask){
|
void sqlite3VdbeDeleteAuxData(Vdbe *pVdbe, int iOp, int mask){
|
||||||
int i;
|
AuxData **pp = &pVdbe->pAuxData;
|
||||||
for(i=0; i<pVdbeFunc->nAux; i++){
|
while( *pp ){
|
||||||
struct AuxData *pAux = &pVdbeFunc->apAux[i];
|
AuxData *pAux = *pp;
|
||||||
if( (i>31 || !(mask&(((u32)1)<<i))) && pAux->pAux ){
|
if( (iOp<0)
|
||||||
|
|| (pAux->iOp==iOp && (pAux->iArg>31 || !(mask & ((u32)1<<pAux->iArg))))
|
||||||
|
){
|
||||||
if( pAux->xDelete ){
|
if( pAux->xDelete ){
|
||||||
pAux->xDelete(pAux->pAux);
|
pAux->xDelete(pAux->pAux);
|
||||||
}
|
}
|
||||||
pAux->pAux = 0;
|
*pp = pAux->pNext;
|
||||||
|
sqlite3DbFree(pVdbe->db, pAux);
|
||||||
|
}else{
|
||||||
|
pp= &pAux->pNext;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -682,6 +682,32 @@ do_test func-13.7 {
|
|||||||
lappend res [sqlite3_finalize $STMT]
|
lappend res [sqlite3_finalize $STMT]
|
||||||
} {{0 0} {1 0} SQLITE_OK}
|
} {{0 0} {1 0} SQLITE_OK}
|
||||||
|
|
||||||
|
# Test that auxiliary data is discarded when a statement is reset.
|
||||||
|
do_execsql_test 13.8.1 {
|
||||||
|
SELECT test_auxdata('constant') FROM t4;
|
||||||
|
} {0 1}
|
||||||
|
do_execsql_test 13.8.2 {
|
||||||
|
SELECT test_auxdata('constant') FROM t4;
|
||||||
|
} {0 1}
|
||||||
|
db cache flush
|
||||||
|
do_execsql_test 13.8.3 {
|
||||||
|
SELECT test_auxdata('constant') FROM t4;
|
||||||
|
} {0 1}
|
||||||
|
set V "one"
|
||||||
|
do_execsql_test 13.8.4 {
|
||||||
|
SELECT test_auxdata($V), $V FROM t4;
|
||||||
|
} {0 one 1 one}
|
||||||
|
set V "two"
|
||||||
|
do_execsql_test 13.8.5 {
|
||||||
|
SELECT test_auxdata($V), $V FROM t4;
|
||||||
|
} {0 two 1 two}
|
||||||
|
db cache flush
|
||||||
|
set V "three"
|
||||||
|
do_execsql_test 2.3 {
|
||||||
|
SELECT test_auxdata($V), $V FROM t4;
|
||||||
|
} {0 three 1 three}
|
||||||
|
|
||||||
|
|
||||||
# Make sure that a function with a very long name is rejected
|
# Make sure that a function with a very long name is rejected
|
||||||
do_test func-14.1 {
|
do_test func-14.1 {
|
||||||
catch {
|
catch {
|
||||||
|
Reference in New Issue
Block a user