-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
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
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
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
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
-e82eb722b0e0b223ddaf7d85669792c33594f9da
\ No newline at end of file
+c2899b437366d879258ab4f6ae47868441010eca
\ No newline at end of file
** 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>
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: {
** 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_
*/
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.
** 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"
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
*/
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;
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;
** 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_
#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
*/
#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
*/
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 */
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.
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