Add the sqlite3_set_auxdata() and sqlite3_get_auxdata() APIs. (CVS 1532)
FossilOrigin-Name: c2899b437366d879258ab4f6ae47868441010eca
This commit is contained in:
parent
2a02e33950
commit
682f68b020
24
manifest
24
manifest
@ -1,5 +1,5 @@
|
||||
C Ensure\sblob\svalues\ssurvive\sthe\s".dump"\scommand\sof\sthe\sshell.\s(CVS\s1531)
|
||||
D 2004-06-05T08:04:36
|
||||
C Add\sthe\ssqlite3_set_auxdata()\sand\ssqlite3_get_auxdata()\sAPIs.\s(CVS\s1532)
|
||||
D 2004-06-05T10:22:17
|
||||
F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
|
||||
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
|
||||
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
||||
@ -31,7 +31,7 @@ F src/build.c e12e602f06e37a0fbcb49af17cba68ad85e101b6
|
||||
F src/date.c 8e6fa3173386fb29fdef012ee08a853c1e9908b2
|
||||
F src/delete.c b30f08250c9ed53a25a13c7c04599c1e8753992d
|
||||
F src/encode.c a876af473d1d636faa3dca51c7571f2e007eea37
|
||||
F src/expr.c 5145de7d25a4b960a4afdb754a9e88b60cce0405
|
||||
F src/expr.c c55461f27a29c593d5b670a77583e44a0d80af0e
|
||||
F src/func.c 3b87e2e8b9aaa3a6d36b2c9616e7f404be38a667
|
||||
F src/hash.c 440c2f8cb373ee1b4e13a0988489c7cd95d55b6f
|
||||
F src/hash.h 762d95f1e567664d1eafc1687de755626be962fb
|
||||
@ -55,7 +55,7 @@ F src/printf.c ef750e8e2398ca7e8b58be991075f08c6a7f0e53
|
||||
F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
|
||||
F src/select.c 02d711160100ef3a730060f7cfb5bc85fde06d72
|
||||
F src/shell.c 79af86d39b2149c7f16219fcbe636e7c2da9df8e
|
||||
F src/sqlite.h.in 8236db65bc6d8f5f47dc5a5e86c4a9bce42f2adf
|
||||
F src/sqlite.h.in dae6a7b4f0ff7310b2ae3f0952feaa9caae94f12
|
||||
F src/sqliteInt.h 99f2b4ff4ed28123890a0c71359fec3d2c5901c9
|
||||
F src/table.c af14284fa36c8d41f6829e3f2819dce07d3e2de2
|
||||
F src/tclsqlite.c 3db6b868bd844bfb71720c8e573f4c9b0d536bd5
|
||||
@ -70,11 +70,11 @@ F src/update.c 259f06e7b22c684b2d3dda54a18185892d6e9573
|
||||
F src/utf.c c8be20ecdcb10659e23c43e35d835460e964d248
|
||||
F src/util.c d3d2f62ec94160db3cb2b092267405ba99122152
|
||||
F src/vacuum.c b921eb778842592e1fb48a9d4cef7e861103878f
|
||||
F src/vdbe.c e1e62347215a8dbe0ec72c155e4a042e81c6aa71
|
||||
F src/vdbe.h e73f890e0f2a6c42b183d7d6937947930fe4fdeb
|
||||
F src/vdbeInt.h 9f5df0a21474be02fe870cbb0a414d09b66eb31a
|
||||
F src/vdbeapi.c 77d2e681a992ef189032cd9c1b7bf922f01ebe3e
|
||||
F src/vdbeaux.c 55c6d501175edb35cd84430302bbbde8dad4b752
|
||||
F src/vdbe.c 7f270f9a882bd51f7156cb87e24c5805b192be45
|
||||
F src/vdbe.h 46f74444a213129bc4b5ce40124dd8ed613b0cde
|
||||
F src/vdbeInt.h ab592f23ed5a1913f9a506bd7b76c5e39377942a
|
||||
F src/vdbeapi.c b3d8e559eb4a6cd6b49db5b2650426a54324adc5
|
||||
F src/vdbeaux.c 185f5ad1269d92684565be3a9bdb330bbda4f597
|
||||
F src/vdbemem.c 5d029d83bc60eaf9c45837fcbc0b03348ec95d7a
|
||||
F src/where.c 444a7c3a8b1eb7bba072e489af628555d21d92a4
|
||||
F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242
|
||||
@ -215,7 +215,7 @@ F www/support.tcl 1801397edd271cc39a2aadd54e701184b5181248
|
||||
F www/tclsqlite.tcl 19191cf2a1010eaeff74c51d83fd5f5a4d899075
|
||||
F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
|
||||
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
|
||||
P cb1ffabf86996ab20dfffcb5f133fa9a9b56bbe2
|
||||
R ea7bd988d55c4ea96c95b0dedf76ecab
|
||||
P e82eb722b0e0b223ddaf7d85669792c33594f9da
|
||||
R 89202e63414e4abff52f3cb8f1936bee
|
||||
U danielk1977
|
||||
Z 4e22795b8cf7e800bcb3f1d60cd6c40a
|
||||
Z d38834ee375024a85c02b119ebf3aa3d
|
||||
|
@ -1 +1 @@
|
||||
e82eb722b0e0b223ddaf7d85669792c33594f9da
|
||||
c2899b437366d879258ab4f6ae47868441010eca
|
@ -12,7 +12,7 @@
|
||||
** This file contains routines used for analyzing expressions and
|
||||
** for generating VDBE code that evaluates expressions in SQLite.
|
||||
**
|
||||
** $Id: expr.c,v 1.133 2004/05/30 01:38:43 drh Exp $
|
||||
** $Id: expr.c,v 1.134 2004/06/05 10:22:17 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
@ -1231,11 +1231,16 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
|
||||
FuncDef *pDef;
|
||||
int nId;
|
||||
const char *zId;
|
||||
int p2 = 0;
|
||||
int i;
|
||||
getFunctionName(pExpr, &zId, &nId);
|
||||
pDef = sqlite3FindFunction(pParse->db, zId, nId, nExpr, 0);
|
||||
assert( pDef!=0 );
|
||||
nExpr = sqlite3ExprCodeExprList(pParse, pList);
|
||||
sqlite3VdbeOp3(v, OP_Function, nExpr, 0, (char*)pDef, P3_FUNCDEF);
|
||||
for(i=0; i<nExpr && i<32; i++){
|
||||
p2 &= (1<<i);
|
||||
}
|
||||
sqlite3VdbeOp3(v, OP_Function, nExpr, p2, (char*)pDef, P3_FUNCDEF);
|
||||
break;
|
||||
}
|
||||
case TK_SELECT: {
|
||||
|
@ -12,7 +12,7 @@
|
||||
** This header file defines the interface that the SQLite library
|
||||
** presents to client programs.
|
||||
**
|
||||
** @(#) $Id: sqlite.h.in,v 1.91 2004/06/02 01:22:02 drh Exp $
|
||||
** @(#) $Id: sqlite.h.in,v 1.92 2004/06/05 10:22:18 danielk1977 Exp $
|
||||
*/
|
||||
#ifndef _SQLITE_H_
|
||||
#define _SQLITE_H_
|
||||
@ -914,6 +914,35 @@ void *sqlite3_aggregate_context(sqlite3_context*, int nBytes);
|
||||
*/
|
||||
void *sqlite3_user_data(sqlite3_context*);
|
||||
|
||||
/*
|
||||
** The following two functions may be used by scalar user functions to
|
||||
** associate meta-data with argument values. If the same value is passed to
|
||||
** multiple invocations of the user-function during query execution, under
|
||||
** some circumstances the associated meta-data may be preserved. This may
|
||||
** be used, for example, to add a regular-expression matching scalar
|
||||
** function. The compiled version of the regular expression is stored as
|
||||
** meta-data associated with the SQL value passed as the regular expression
|
||||
** pattern.
|
||||
**
|
||||
** Calling sqlite3_get_auxdata() returns a pointer to the meta data
|
||||
** associated with the Nth argument value to the current user function
|
||||
** call, where N is the second parameter. If no meta-data has been set for
|
||||
** that value, then a NULL pointer is returned.
|
||||
**
|
||||
** The sqlite3_set_auxdata() is used to associate meta data with a user
|
||||
** function argument. The third parameter is a pointer to the meta data
|
||||
** to be associated with the Nth user function argument value. The fourth
|
||||
** parameter specifies a 'delete function' that will be called on the meta
|
||||
** data pointer to release it when it is no longer required. If the delete
|
||||
** function pointer is NULL, it is not invoked.
|
||||
**
|
||||
** In practice, meta-data is preserved between function calls for
|
||||
** expressions that are constant at compile time. This includes literal
|
||||
** values and SQL variables.
|
||||
*/
|
||||
void *sqlite3_get_auxdata(sqlite3_context*, int);
|
||||
void sqlite3_set_auxdata(sqlite3_context*, int, void*, void (*)(void*));
|
||||
|
||||
/*
|
||||
** User-defined functions invoke the following routines in order to
|
||||
** set their return value.
|
||||
|
41
src/vdbe.c
41
src/vdbe.c
@ -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.357 2004/06/04 06:22:02 danielk1977 Exp $
|
||||
** $Id: vdbe.c,v 1.358 2004/06/05 10:22:18 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
@ -1218,11 +1218,18 @@ divide_by_zero:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: Function P1 * P3
|
||||
/* Opcode: Function P1 P2 P3
|
||||
**
|
||||
** Invoke a user function (P3 is a pointer to a Function structure that
|
||||
** defines the function) with P1 string arguments taken from the stack.
|
||||
** Pop all arguments from the stack and push back the result.
|
||||
** defines the function) with P1 arguments taken from the stack. Pop all
|
||||
** arguments from the stack and push back the result.
|
||||
**
|
||||
** P2 is a 32-bit bitmask indicating whether or not each argument to the
|
||||
** function was determined to be constant at compile time. If the first
|
||||
** argument was constant then bit 0 of P2 is set. This is used to determine
|
||||
** whether meta data associated with a user function argument using the
|
||||
** sqlite3_set_auxdata() API may be safely retained until the next
|
||||
** invocation of this opcode.
|
||||
**
|
||||
** See also: AggFunc
|
||||
*/
|
||||
@ -1243,7 +1250,15 @@ case OP_Function: {
|
||||
storeTypeInfo(pArg, db->enc);
|
||||
}
|
||||
|
||||
ctx.pFunc = (FuncDef*)pOp->p3;
|
||||
assert( pOp->p3type==P3_FUNCDEF || pOp->p3type==P3_VDBEFUNC );
|
||||
if( pOp->p3type==P3_FUNCDEF ){
|
||||
ctx.pFunc = (FuncDef*)pOp->p3;
|
||||
ctx.pVdbeFunc = 0;
|
||||
}else{
|
||||
ctx.pVdbeFunc = (VdbeFunc*)pOp->p3;
|
||||
ctx.pFunc = ctx.pVdbeFunc->pFunc;
|
||||
}
|
||||
|
||||
ctx.s.flags = MEM_Null;
|
||||
ctx.s.z = 0;
|
||||
ctx.isError = 0;
|
||||
@ -1253,6 +1268,22 @@ case OP_Function: {
|
||||
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
|
||||
popStack(&pTos, n);
|
||||
|
||||
/* If any auxilary data functions have been called by this user function,
|
||||
** immediately call the destructor for any non-static values.
|
||||
*/
|
||||
if( ctx.pVdbeFunc ){
|
||||
int mask = pOp->p2;
|
||||
for(i=0; i<n; i++){
|
||||
struct AuxData *pAux = &ctx.pVdbeFunc->apAux[i];
|
||||
if( (i>31 || !(mask&(1<<i))) && pAux->pAux ){
|
||||
pAux->xDelete(pAux->pAux);
|
||||
pAux->pAux = 0;
|
||||
}
|
||||
}
|
||||
pOp->p3 = (char *)ctx.pVdbeFunc;
|
||||
pOp->p3type = P3_VDBEFUNC;
|
||||
}
|
||||
|
||||
/* Copy the result of the function to the top of the stack */
|
||||
pTos++;
|
||||
*pTos = ctx.s;
|
||||
|
@ -15,7 +15,7 @@
|
||||
** or VDBE. The VDBE implements an abstract machine that runs a
|
||||
** simple program to access and modify the underlying database.
|
||||
**
|
||||
** $Id: vdbe.h,v 1.84 2004/05/26 16:54:48 drh Exp $
|
||||
** $Id: vdbe.h,v 1.85 2004/06/05 10:22:18 danielk1977 Exp $
|
||||
*/
|
||||
#ifndef _SQLITE_VDBE_H_
|
||||
#define _SQLITE_VDBE_H_
|
||||
@ -71,6 +71,7 @@ typedef struct VdbeOpList VdbeOpList;
|
||||
#define P3_COLLSEQ (-4) /* P3 is a pointer to a CollSeq structure */
|
||||
#define P3_FUNCDEF (-5) /* P3 is a pointer to a FuncDef structure */
|
||||
#define P3_KEYINFO (-6) /* P3 is a pointer to a KeyInfo structure */
|
||||
#define P3_VDBEFUNC (-7) /* P3 is a pointer to a VdbeFunc structure */
|
||||
|
||||
/* When adding a P3 argument using P3_KEYINFO, a copy of the KeyInfo structure
|
||||
** is made. That copy is freed when the Vdbe is finalized. But if the
|
||||
|
@ -177,6 +177,16 @@ typedef struct Mem Mem;
|
||||
*/
|
||||
#define MEM_AggCtx 0x0400 /* Mem.z points to an agg function context */
|
||||
|
||||
struct VdbeFunc {
|
||||
FuncDef *pFunc;
|
||||
int nAux;
|
||||
struct AuxData {
|
||||
void *pAux;
|
||||
void (*xDelete)(void *);
|
||||
} apAux[0];
|
||||
};
|
||||
typedef struct VdbeFunc VdbeFunc;
|
||||
|
||||
/*
|
||||
** The "context" argument for a installable function. A pointer to an
|
||||
** instance of this structure is the first argument to the routines used
|
||||
@ -192,6 +202,7 @@ typedef struct Mem Mem;
|
||||
*/
|
||||
struct sqlite3_context {
|
||||
FuncDef *pFunc; /* Pointer to function information. MUST BE FIRST */
|
||||
VdbeFunc *pVdbeFunc; /* Auxilary data, if created. */
|
||||
Mem s; /* The return value is stored here */
|
||||
void *pAgg; /* Aggregate context */
|
||||
u8 isError; /* Set to true for an error */
|
||||
|
@ -217,6 +217,47 @@ void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){
|
||||
return p->pAgg;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the auxilary data pointer, if any, for the iArg'th argument to
|
||||
** the user-function defined by pCtx.
|
||||
*/
|
||||
void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){
|
||||
VdbeFunc *pVdbeFunc = pCtx->pVdbeFunc;
|
||||
if( !pVdbeFunc || iArg>=pVdbeFunc->nAux || iArg<0 ){
|
||||
return 0;
|
||||
}
|
||||
return pCtx->pVdbeFunc->apAux[iArg].pAux;
|
||||
}
|
||||
|
||||
/*
|
||||
** Set the auxilary data pointer and delete function, for the iArg'th
|
||||
** argument to the user-function defined by pCtx. Any previous value is
|
||||
** deleted by calling the delete function specified when it was set.
|
||||
*/
|
||||
void sqlite3_set_auxdata(
|
||||
sqlite3_context *pCtx,
|
||||
int iArg,
|
||||
void *pAux,
|
||||
void (*xDelete)(void*)
|
||||
){
|
||||
struct AuxData *pAuxData;
|
||||
if( iArg<0 ) return;
|
||||
|
||||
if( !pCtx->pVdbeFunc || pCtx->pVdbeFunc->nAux<=iArg ){
|
||||
int nMalloc = sizeof(VdbeFunc)+sizeof(struct AuxData)*(iArg+1);
|
||||
pCtx->pVdbeFunc = sqliteRealloc(pCtx->pVdbeFunc, nMalloc);
|
||||
if( !pCtx->pVdbeFunc ) return;
|
||||
pCtx->pVdbeFunc->nAux = iArg+1;
|
||||
}
|
||||
|
||||
pAuxData = &pCtx->pVdbeFunc->apAux[iArg];
|
||||
if( pAuxData->pAux && pAuxData->xDelete ){
|
||||
pAuxData->xDelete(pAuxData->pAux);
|
||||
}
|
||||
pAuxData->pAux = pAux;
|
||||
pAuxData->xDelete = xDelete;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the number of times the Step function of a aggregate has been
|
||||
** called.
|
||||
|
@ -1234,6 +1234,16 @@ void sqlite3VdbeDelete(Vdbe *p){
|
||||
if( pOp->p3type==P3_DYNAMIC || pOp->p3type==P3_KEYINFO ){
|
||||
sqliteFree(pOp->p3);
|
||||
}
|
||||
if( pOp->p3type==P3_VDBEFUNC ){
|
||||
VdbeFunc *pVdbeFunc = (VdbeFunc *)pOp->p3;
|
||||
for(i=0; i<pVdbeFunc->nAux; i++){
|
||||
struct AuxData *pAuxData = &pVdbeFunc->apAux[i].pAux;
|
||||
if( pAuxData->pAux && pAuxData->xDelete ){
|
||||
pAuxData->xDelete(pAuxData->pAux);
|
||||
}
|
||||
}
|
||||
sqliteFree(pVdbeFunc);
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
sqliteFree(pOp->zComment);
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user