|
|
@@ -672,7 +672,7 @@ extern "C" {
|
|
|
*/
|
|
|
#define SQLITE_VERSION "3.8.0"
|
|
|
#define SQLITE_VERSION_NUMBER 3008000
|
|
|
-#define SQLITE_SOURCE_ID "2013-07-12 21:09:24 92adaee5bd31c152dbc1592f4aeb5d8da957a1ea"
|
|
|
+#define SQLITE_SOURCE_ID "2013-07-20 00:34:31 ad0551e039ccaa9e7a28682b756b56ac2b8fef0d"
|
|
|
|
|
|
/*
|
|
|
** CAPI3REF: Run-Time Library Version Numbers
|
|
|
@@ -4776,41 +4776,49 @@ SQLITE_API void *sqlite3_db_user_data(sqlite3_context *context);
|
|
|
/*
|
|
|
** CAPI3REF: Function Auxiliary Data
|
|
|
**
|
|
|
-** The following two functions may be used by scalar SQL functions to
|
|
|
+** These functions may be used by (non-aggregate) SQL functions to
|
|
|
** associate metadata with argument values. If the same value is passed to
|
|
|
** multiple invocations of the same SQL function during query execution, under
|
|
|
-** some circumstances the associated metadata 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
|
|
|
-** metadata associated with the SQL value passed as the regular expression
|
|
|
-** pattern. The compiled regular expression can be reused on multiple
|
|
|
-** invocations of the same function so that the original pattern string
|
|
|
-** does not need to be recompiled on each invocation.
|
|
|
+** some circumstances the associated metadata may be preserved. An example
|
|
|
+** of where this might be useful is in a regular-expression matching
|
|
|
+** function. The compiled version of the regular expression can be stored as
|
|
|
+** metadata associated with the pattern string.
|
|
|
+** Then as long as the pattern string remains the same,
|
|
|
+** the compiled regular expression can be reused on multiple
|
|
|
+** invocations of the same function.
|
|
|
**
|
|
|
** ^The sqlite3_get_auxdata() interface returns a pointer to the metadata
|
|
|
** associated by the sqlite3_set_auxdata() function with the Nth argument
|
|
|
-** value to the application-defined function. ^If no metadata has been ever
|
|
|
-** been set for the Nth argument of the function, or if the corresponding
|
|
|
-** function parameter has changed since the meta-data was set,
|
|
|
-** then sqlite3_get_auxdata() returns a NULL pointer.
|
|
|
-**
|
|
|
-** ^The sqlite3_set_auxdata() interface saves the metadata
|
|
|
-** pointed to by its 3rd parameter as the metadata for the N-th
|
|
|
-** argument of the application-defined function. Subsequent
|
|
|
-** calls to sqlite3_get_auxdata() might return this data, if it has
|
|
|
-** not been destroyed.
|
|
|
-** ^If it is not NULL, SQLite will invoke the destructor
|
|
|
-** function given by the 4th parameter to sqlite3_set_auxdata() on
|
|
|
-** the metadata when the corresponding function parameter changes
|
|
|
-** or when the SQL statement completes, whichever comes first.
|
|
|
-**
|
|
|
-** SQLite is free to call the destructor and drop metadata on any
|
|
|
-** parameter of any function at any time. ^The only guarantee is that
|
|
|
-** the destructor will be called before the metadata is dropped.
|
|
|
+** value to the application-defined function. ^If there is no metadata
|
|
|
+** associated with the function argument, this sqlite3_get_auxdata() interface
|
|
|
+** returns a NULL pointer.
|
|
|
+**
|
|
|
+** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as metadata for the N-th
|
|
|
+** argument of the application-defined function. ^Subsequent
|
|
|
+** calls to sqlite3_get_auxdata(C,N) return P from the most recent
|
|
|
+** sqlite3_set_auxdata(C,N,P,X) call if the metadata is still valid or
|
|
|
+** NULL if the metadata has been discarded.
|
|
|
+** ^After each call to sqlite3_set_auxdata(C,N,P,X) where X is not NULL,
|
|
|
+** SQLite will invoke the destructor function X with parameter P exactly
|
|
|
+** once, when the metadata is discarded.
|
|
|
+** SQLite is free to discard the metadata at any time, including: <ul>
|
|
|
+** <li> when the corresponding function parameter changes, or
|
|
|
+** <li> when [sqlite3_reset()] or [sqlite3_finalize()] is called for the
|
|
|
+** SQL statement, or
|
|
|
+** <li> when sqlite3_set_auxdata() is invoked again on the same parameter, or
|
|
|
+** <li> during the original sqlite3_set_auxdata() call when a memory
|
|
|
+** allocation error occurs. </ul>)^
|
|
|
+**
|
|
|
+** Note the last bullet in particular. The destructor X in
|
|
|
+** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before the
|
|
|
+** sqlite3_set_auxdata() interface even returns. Hence sqlite3_set_auxdata()
|
|
|
+** should be called near the end of the function implementation and the
|
|
|
+** function implementation should not make any use of P after
|
|
|
+** sqlite3_set_auxdata() has been called.
|
|
|
**
|
|
|
** ^(In practice, metadata is preserved between function calls for
|
|
|
-** expressions that are constant at compile time. This includes literal
|
|
|
-** values and [parameters].)^
|
|
|
+** function parameters that are compile-time constants, including literal
|
|
|
+** values and [parameters] and expressions composed from the same.)^
|
|
|
**
|
|
|
** These routines must be called from the same thread in which
|
|
|
** the SQL function is running.
|
|
|
@@ -5727,10 +5735,23 @@ SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff);
|
|
|
** on the list of automatic extensions is a harmless no-op. ^No entry point
|
|
|
** will be called more than once for each database connection that is opened.
|
|
|
**
|
|
|
-** See also: [sqlite3_reset_auto_extension()].
|
|
|
+** See also: [sqlite3_reset_auto_extension()]
|
|
|
+** and [sqlite3_cancel_auto_extension()]
|
|
|
*/
|
|
|
SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void));
|
|
|
|
|
|
+/*
|
|
|
+** CAPI3REF: Cancel Automatic Extension Loading
|
|
|
+**
|
|
|
+** ^The [sqlite3_cancel_auto_extension(X)] interface unregisters the
|
|
|
+** initialization routine X that was registered using a prior call to
|
|
|
+** [sqlite3_auto_extension(X)]. ^The [sqlite3_cancel_auto_extension(X)]
|
|
|
+** routine returns 1 if initialization routine X was successfully
|
|
|
+** unregistered and it returns 0 if X was not on the list of initialization
|
|
|
+** routines.
|
|
|
+*/
|
|
|
+SQLITE_API int sqlite3_cancel_auto_extension(void (*xEntryPoint)(void));
|
|
|
+
|
|
|
/*
|
|
|
** CAPI3REF: Reset Automatic Extension Loading
|
|
|
**
|
|
|
@@ -8856,7 +8877,6 @@ typedef struct Vdbe Vdbe;
|
|
|
** The names of the following types declared in vdbeInt.h are required
|
|
|
** for the VdbeOp definition.
|
|
|
*/
|
|
|
-typedef struct VdbeFunc VdbeFunc;
|
|
|
typedef struct Mem Mem;
|
|
|
typedef struct SubProgram SubProgram;
|
|
|
|
|
|
@@ -8880,7 +8900,6 @@ struct VdbeOp {
|
|
|
i64 *pI64; /* Used when p4type is P4_INT64 */
|
|
|
sqlite_double *pReal; /* Used when p4type is P4_REAL */
|
|
|
FuncDef *pFunc; /* Used when p4type is P4_FUNCDEF */
|
|
|
- VdbeFunc *pVdbeFunc; /* Used when p4type is P4_VDBEFUNC */
|
|
|
CollSeq *pColl; /* Used when p4type is P4_COLLSEQ */
|
|
|
Mem *pMem; /* Used when p4type is P4_MEM */
|
|
|
VTable *pVtab; /* Used when p4type is P4_VTAB */
|
|
|
@@ -8934,7 +8953,6 @@ typedef struct VdbeOpList VdbeOpList;
|
|
|
#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_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_TRANSIENT 0 /* P4 is a pointer to a transient string */
|
|
|
#define P4_VTAB (-10) /* P4 is a pointer to an sqlite3_vtab structure */
|
|
|
@@ -13290,6 +13308,9 @@ typedef struct VdbeSorter VdbeSorter;
|
|
|
/* Opaque type used by the explainer */
|
|
|
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.
|
|
|
** The cursor can seek to a BTree entry with a particular key, or
|
|
|
@@ -13476,23 +13497,19 @@ struct Mem {
|
|
|
#define memIsValid(M) ((M)->flags & MEM_Invalid)==0
|
|
|
#endif
|
|
|
|
|
|
-
|
|
|
-/* A VdbeFunc is just a FuncDef (defined in sqliteInt.h) that contains
|
|
|
-** additional information about auxiliary information bound to arguments
|
|
|
-** of the function. This is used to implement the sqlite3_get_auxdata()
|
|
|
-** and sqlite3_set_auxdata() APIs. The "auxdata" is some auxiliary data
|
|
|
-** that can be associated with a constant argument to a function. This
|
|
|
-** allows functions such as "regexp" to compile their constant regular
|
|
|
-** expression argument once and reused the compiled code for multiple
|
|
|
-** invocations.
|
|
|
+/*
|
|
|
+** Each auxilliary data pointer stored by a user defined function
|
|
|
+** implementation calling sqlite3_set_auxdata() is stored in an instance
|
|
|
+** of this structure. All such structures associated with a single VM
|
|
|
+** are stored in a linked list headed at Vdbe.pAuxData. All are destroyed
|
|
|
+** when the VM is halted (if not before).
|
|
|
*/
|
|
|
-struct VdbeFunc {
|
|
|
- FuncDef *pFunc; /* The definition of the function */
|
|
|
- int nAux; /* Number of entries allocated for apAux[] */
|
|
|
- struct AuxData {
|
|
|
- void *pAux; /* Aux data for the i-th argument */
|
|
|
- void (*xDelete)(void *); /* Destructor for the aux data */
|
|
|
- } apAux[1]; /* One slot for each function argument */
|
|
|
+struct AuxData {
|
|
|
+ int iOp; /* Instruction number of OP_Function opcode */
|
|
|
+ int iArg; /* Index of function argument. */
|
|
|
+ void *pAux; /* Aux data pointer */
|
|
|
+ void (*xDelete)(void *); /* Destructor for the aux data */
|
|
|
+ AuxData *pNext; /* Next element in list */
|
|
|
};
|
|
|
|
|
|
/*
|
|
|
@@ -13510,12 +13527,13 @@ struct VdbeFunc {
|
|
|
*/
|
|
|
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 */
|
|
|
Mem *pMem; /* Memory cell used to store aggregate context */
|
|
|
CollSeq *pColl; /* Collating sequence */
|
|
|
int isError; /* Error code returned by the function. */
|
|
|
int skipFlag; /* Skip skip accumulator loading if true */
|
|
|
+ int iOp; /* Instruction number of OP_Function */
|
|
|
+ Vdbe *pVdbe; /* The VM that owns this context */
|
|
|
};
|
|
|
|
|
|
/*
|
|
|
@@ -13614,6 +13632,7 @@ struct Vdbe {
|
|
|
SubProgram *pProgram; /* Linked list of all sub-programs used by VM */
|
|
|
int nOnceFlag; /* Size of array aOnceFlag[] */
|
|
|
u8 *aOnceFlag; /* Flags for OP_Once */
|
|
|
+ AuxData *pAuxData; /* Linked list of auxdata allocations */
|
|
|
};
|
|
|
|
|
|
/*
|
|
|
@@ -13637,7 +13656,7 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32);
|
|
|
SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem*, int);
|
|
|
SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(unsigned char*, int, Mem*, int);
|
|
|
SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
|
|
|
-SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(VdbeFunc*, int);
|
|
|
+SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(Vdbe*, int, int);
|
|
|
|
|
|
int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
|
|
|
SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(VdbeCursor*,UnpackedRecord*,int*);
|
|
|
@@ -60723,13 +60742,6 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){
|
|
|
if( db->pnBytesFreed==0 ) sqlite3_free(p4);
|
|
|
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: {
|
|
|
freeEphemeralFunction(db, (FuncDef*)p4);
|
|
|
break;
|
|
|
@@ -61759,6 +61771,10 @@ static void closeAllCursors(Vdbe *p){
|
|
|
p->pDelFrame = pDel->pParent;
|
|
|
sqlite3VdbeFrameDelete(pDel);
|
|
|
}
|
|
|
+
|
|
|
+ /* Delete any auxdata allocations made by the VM */
|
|
|
+ sqlite3VdbeDeleteAuxData(p, -1, 0);
|
|
|
+ assert( p->pAuxData==0 );
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
@@ -62557,20 +62573,35 @@ SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe *p){
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
-** Call the destructor for each auxdata entry in pVdbeFunc for which
|
|
|
-** the corresponding bit in mask is clear. Auxdata entries beyond 31
|
|
|
-** are always destroyed. To destroy all auxdata entries, call this
|
|
|
-** routine with mask==0.
|
|
|
+** If parameter iOp is less than zero, then invoke the destructor for
|
|
|
+** all auxiliary data pointers currently cached by the VM passed as
|
|
|
+** the first argument.
|
|
|
+**
|
|
|
+** 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.).
|
|
|
*/
|
|
|
-SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(VdbeFunc *pVdbeFunc, int mask){
|
|
|
- int i;
|
|
|
- for(i=0; i<pVdbeFunc->nAux; i++){
|
|
|
- struct AuxData *pAux = &pVdbeFunc->apAux[i];
|
|
|
- if( (i>31 || !(mask&(((u32)1)<<i))) && pAux->pAux ){
|
|
|
+SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(Vdbe *pVdbe, int iOp, int mask){
|
|
|
+ AuxData **pp = &pVdbe->pAuxData;
|
|
|
+ while( *pp ){
|
|
|
+ AuxData *pAux = *pp;
|
|
|
+ if( (iOp<0)
|
|
|
+ || (pAux->iOp==iOp && (pAux->iArg>31 || !(mask & ((u32)1<<pAux->iArg))))
|
|
|
+ ){
|
|
|
if( pAux->xDelete ){
|
|
|
pAux->xDelete(pAux->pAux);
|
|
|
}
|
|
|
- pAux->pAux = 0;
|
|
|
+ *pp = pAux->pNext;
|
|
|
+ sqlite3DbFree(pVdbe->db, pAux);
|
|
|
+ }else{
|
|
|
+ pp= &pAux->pNext;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -63969,14 +64000,14 @@ SQLITE_API void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){
|
|
|
** the user-function defined by pCtx.
|
|
|
*/
|
|
|
SQLITE_API void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){
|
|
|
- VdbeFunc *pVdbeFunc;
|
|
|
+ AuxData *pAuxData;
|
|
|
|
|
|
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
|
|
|
- pVdbeFunc = pCtx->pVdbeFunc;
|
|
|
- if( !pVdbeFunc || iArg>=pVdbeFunc->nAux || iArg<0 ){
|
|
|
- return 0;
|
|
|
+ for(pAuxData=pCtx->pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNext){
|
|
|
+ if( pAuxData->iOp==pCtx->iOp && pAuxData->iArg==iArg ) break;
|
|
|
}
|
|
|
- return pVdbeFunc->apAux[iArg].pAux;
|
|
|
+
|
|
|
+ return (pAuxData ? pAuxData->pAux : 0);
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
@@ -63990,29 +64021,26 @@ SQLITE_API void sqlite3_set_auxdata(
|
|
|
void *pAux,
|
|
|
void (*xDelete)(void*)
|
|
|
){
|
|
|
- struct AuxData *pAuxData;
|
|
|
- VdbeFunc *pVdbeFunc;
|
|
|
- if( iArg<0 ) goto failed;
|
|
|
+ AuxData *pAuxData;
|
|
|
+ Vdbe *pVdbe = pCtx->pVdbe;
|
|
|
|
|
|
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
|
|
|
- pVdbeFunc = pCtx->pVdbeFunc;
|
|
|
- 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;
|
|
|
- }
|
|
|
+ if( iArg<0 ) goto failed;
|
|
|
|
|
|
- pAuxData = &pVdbeFunc->apAux[iArg];
|
|
|
- if( pAuxData->pAux && pAuxData->xDelete ){
|
|
|
+ for(pAuxData=pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNext){
|
|
|
+ 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->pAux = pAux;
|
|
|
pAuxData->xDelete = xDelete;
|
|
|
return;
|
|
|
@@ -66934,19 +66962,14 @@ case OP_Function: {
|
|
|
REGISTER_TRACE(pOp->p2+u.ai.i, u.ai.pArg);
|
|
|
}
|
|
|
|
|
|
- assert( pOp->p4type==P4_FUNCDEF || pOp->p4type==P4_VDBEFUNC );
|
|
|
- if( pOp->p4type==P4_FUNCDEF ){
|
|
|
- u.ai.ctx.pFunc = pOp->p4.pFunc;
|
|
|
- u.ai.ctx.pVdbeFunc = 0;
|
|
|
- }else{
|
|
|
- u.ai.ctx.pVdbeFunc = (VdbeFunc*)pOp->p4.pVdbeFunc;
|
|
|
- u.ai.ctx.pFunc = u.ai.ctx.pVdbeFunc->pFunc;
|
|
|
- }
|
|
|
-
|
|
|
+ assert( pOp->p4type==P4_FUNCDEF );
|
|
|
+ u.ai.ctx.pFunc = pOp->p4.pFunc;
|
|
|
u.ai.ctx.s.flags = MEM_Null;
|
|
|
u.ai.ctx.s.db = db;
|
|
|
u.ai.ctx.s.xDel = 0;
|
|
|
u.ai.ctx.s.zMalloc = 0;
|
|
|
+ u.ai.ctx.iOp = pc;
|
|
|
+ u.ai.ctx.pVdbe = p;
|
|
|
|
|
|
/* The output cell may already have a buffer allocated. Move
|
|
|
** the pointer to u.ai.ctx.s so in case the user-function can use
|
|
|
@@ -66969,11 +66992,7 @@ case OP_Function: {
|
|
|
/* If any auxiliary data functions have been called by this user function,
|
|
|
** immediately call the destructor for any non-static values.
|
|
|
*/
|
|
|
- if( u.ai.ctx.pVdbeFunc ){
|
|
|
- sqlite3VdbeDeleteAuxData(u.ai.ctx.pVdbeFunc, pOp->p1);
|
|
|
- pOp->p4.pVdbeFunc = u.ai.ctx.pVdbeFunc;
|
|
|
- pOp->p4type = P4_VDBEFUNC;
|
|
|
- }
|
|
|
+ sqlite3VdbeDeleteAuxData(p, pc, pOp->p1);
|
|
|
|
|
|
if( db->mallocFailed ){
|
|
|
/* Even though a malloc() has failed, the implementation of the
|
|
|
@@ -93579,6 +93598,35 @@ SQLITE_API int sqlite3_auto_extension(void (*xInit)(void)){
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+** Cancel a prior call to sqlite3_auto_extension. Remove xInit from the
|
|
|
+** set of routines that is invoked for each new database connection, if it
|
|
|
+** is currently on the list. If xInit is not on the list, then this
|
|
|
+** routine is a no-op.
|
|
|
+**
|
|
|
+** Return 1 if xInit was found on the list and removed. Return 0 if xInit
|
|
|
+** was not on the list.
|
|
|
+*/
|
|
|
+SQLITE_API int sqlite3_cancel_auto_extension(void (*xInit)(void)){
|
|
|
+#if SQLITE_THREADSAFE
|
|
|
+ sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
|
|
|
+#endif
|
|
|
+ int i;
|
|
|
+ int n = 0;
|
|
|
+ wsdAutoextInit;
|
|
|
+ sqlite3_mutex_enter(mutex);
|
|
|
+ for(i=wsdAutoext.nExt-1; i>=0; i--){
|
|
|
+ if( wsdAutoext.aExt[i]==xInit ){
|
|
|
+ wsdAutoext.nExt--;
|
|
|
+ wsdAutoext.aExt[i] = wsdAutoext.aExt[wsdAutoext.nExt];
|
|
|
+ n++;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ sqlite3_mutex_leave(mutex);
|
|
|
+ return n;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
** Reset the automatic extension loading mechanism.
|
|
|
*/
|
|
|
@@ -96286,6 +96334,12 @@ static int sqlite3Prepare16(
|
|
|
if( !sqlite3SafetyCheckOk(db) ){
|
|
|
return SQLITE_MISUSE_BKPT;
|
|
|
}
|
|
|
+ if( nBytes>=0 ){
|
|
|
+ int sz;
|
|
|
+ const char *z = (const char*)zSql;
|
|
|
+ for(sz=0; sz<nBytes && (z[sz]!=0 || z[sz+1]!=0); sz += 2){}
|
|
|
+ nBytes = sz;
|
|
|
+ }
|
|
|
sqlite3_mutex_enter(db->mutex);
|
|
|
zSql8 = sqlite3Utf16to8(db, zSql, nBytes, SQLITE_UTF16NATIVE);
|
|
|
if( zSql8 ){
|
|
|
@@ -104377,8 +104431,8 @@ SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, char **pzErrmsg){
|
|
|
if( pVtab && (x = pVtab->pModule->xSync)!=0 ){
|
|
|
rc = x(pVtab);
|
|
|
sqlite3DbFree(db, *pzErrmsg);
|
|
|
- *pzErrmsg = sqlite3DbStrDup(db, pVtab->zErrMsg);
|
|
|
- sqlite3_free(pVtab->zErrMsg);
|
|
|
+ *pzErrmsg = pVtab->zErrMsg;
|
|
|
+ pVtab->zErrMsg = 0;
|
|
|
}
|
|
|
}
|
|
|
db->aVTrans = aVTrans;
|
|
|
@@ -104698,6 +104752,8 @@ typedef struct WherePath WherePath;
|
|
|
typedef struct WhereTerm WhereTerm;
|
|
|
typedef struct WhereLoopBuilder WhereLoopBuilder;
|
|
|
typedef struct WhereScan WhereScan;
|
|
|
+typedef struct WhereOrCost WhereOrCost;
|
|
|
+typedef struct WhereOrSet WhereOrSet;
|
|
|
|
|
|
/*
|
|
|
** Cost X is tracked as 10*log2(X) stored in a 16-bit integer. The
|
|
|
@@ -104805,6 +104861,27 @@ struct WhereLoop {
|
|
|
WhereTerm *aLTermSpace[4]; /* Initial aLTerm[] space */
|
|
|
};
|
|
|
|
|
|
+/* This object holds the prerequisites and the cost of running a
|
|
|
+** subquery on one operand of an OR operator in the WHERE clause.
|
|
|
+** See WhereOrSet for additional information
|
|
|
+*/
|
|
|
+struct WhereOrCost {
|
|
|
+ Bitmask prereq; /* Prerequisites */
|
|
|
+ WhereCost rRun; /* Cost of running this subquery */
|
|
|
+ WhereCost nOut; /* Number of outputs for this subquery */
|
|
|
+};
|
|
|
+
|
|
|
+/* The WhereOrSet object holds a set of possible WhereOrCosts that
|
|
|
+** correspond to the subquery(s) of OR-clause processing. At most
|
|
|
+** favorable N_OR_COST elements are retained.
|
|
|
+*/
|
|
|
+#define N_OR_COST 3
|
|
|
+struct WhereOrSet {
|
|
|
+ u16 n; /* Number of valid a[] entries */
|
|
|
+ WhereOrCost a[N_OR_COST]; /* Set of best costs */
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
/* Forward declaration of methods */
|
|
|
static int whereLoopResize(sqlite3*, WhereLoop*, int);
|
|
|
|
|
|
@@ -105019,7 +105096,7 @@ struct WhereLoopBuilder {
|
|
|
WhereClause *pWC; /* WHERE clause terms */
|
|
|
ExprList *pOrderBy; /* ORDER BY clause */
|
|
|
WhereLoop *pNew; /* Template WhereLoop */
|
|
|
- WhereLoop *pBest; /* If non-NULL, store single best loop here */
|
|
|
+ WhereOrSet *pOrSet; /* Record best loops here, if not NULL */
|
|
|
};
|
|
|
|
|
|
/*
|
|
|
@@ -105162,6 +105239,54 @@ SQLITE_PRIVATE int sqlite3WhereOkOnePass(WhereInfo *pWInfo){
|
|
|
return pWInfo->okOnePass;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+** Move the content of pSrc into pDest
|
|
|
+*/
|
|
|
+static void whereOrMove(WhereOrSet *pDest, WhereOrSet *pSrc){
|
|
|
+ pDest->n = pSrc->n;
|
|
|
+ memcpy(pDest->a, pSrc->a, pDest->n*sizeof(pDest->a[0]));
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+** Try to insert a new prerequisite/cost entry into the WhereOrSet pSet.
|
|
|
+**
|
|
|
+** The new entry might overwrite an existing entry, or it might be
|
|
|
+** appended, or it might be discarded. Do whatever is the right thing
|
|
|
+** so that pSet keeps the N_OR_COST best entries seen so far.
|
|
|
+*/
|
|
|
+static int whereOrInsert(
|
|
|
+ WhereOrSet *pSet, /* The WhereOrSet to be updated */
|
|
|
+ Bitmask prereq, /* Prerequisites of the new entry */
|
|
|
+ WhereCost rRun, /* Run-cost of the new entry */
|
|
|
+ WhereCost nOut /* Number of outputs for the new entry */
|
|
|
+){
|
|
|
+ u16 i;
|
|
|
+ WhereOrCost *p;
|
|
|
+ for(i=pSet->n, p=pSet->a; i>0; i--, p++){
|
|
|
+ if( rRun<=p->rRun && (prereq & p->prereq)==prereq ){
|
|
|
+ goto whereOrInsert_done;
|
|
|
+ }
|
|
|
+ if( p->rRun<=rRun && (p->prereq & prereq)==p->prereq ){
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if( pSet->n<N_OR_COST ){
|
|
|
+ p = &pSet->a[pSet->n++];
|
|
|
+ p->nOut = nOut;
|
|
|
+ }else{
|
|
|
+ p = pSet->a;
|
|
|
+ for(i=1; i<pSet->n; i++){
|
|
|
+ if( p->rRun>pSet->a[i].rRun ) p = pSet->a + i;
|
|
|
+ }
|
|
|
+ if( p->rRun<=rRun ) return 0;
|
|
|
+ }
|
|
|
+whereOrInsert_done:
|
|
|
+ p->prereq = prereq;
|
|
|
+ p->rRun = rRun;
|
|
|
+ if( p->nOut>nOut ) p->nOut = nOut;
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
** Initialize a preallocated WhereClause structure.
|
|
|
*/
|
|
|
@@ -108395,8 +108520,9 @@ static Bitmask codeOneLoopStart(
|
|
|
int iTerm;
|
|
|
for(iTerm=0; iTerm<pWC->nTerm; iTerm++){
|
|
|
Expr *pExpr = pWC->a[iTerm].pExpr;
|
|
|
+ if( &pWC->a[iTerm] == pTerm ) continue;
|
|
|
if( ExprHasProperty(pExpr, EP_FromJoin) ) continue;
|
|
|
- if( pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_ORINFO) ) continue;
|
|
|
+ if( pWC->a[iTerm].wtFlags & (TERM_ORINFO) ) continue;
|
|
|
if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue;
|
|
|
pExpr = sqlite3ExprDup(pParse->db, pExpr, 0);
|
|
|
pAndExpr = sqlite3ExprAnd(pParse->db, pAndExpr, pExpr);
|
|
|
@@ -108724,12 +108850,12 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
|
|
|
** fewer dependencies than the template. Otherwise a new WhereLoop is
|
|
|
** added based on the template.
|
|
|
**
|
|
|
-** If pBuilder->pBest is not NULL then we only care about the very
|
|
|
-** best template and that template should be stored in pBuilder->pBest.
|
|
|
-** If pBuilder->pBest is NULL then a list of the best templates are stored
|
|
|
-** in pBuilder->pWInfo->pLoops.
|
|
|
+** If pBuilder->pOrSet is not NULL then we only care about only the
|
|
|
+** prerequisites and rRun and nOut costs of the N best loops. That
|
|
|
+** information is gathered in the pBuilder->pOrSet object. This special
|
|
|
+** processing mode is used only for OR clause processing.
|
|
|
**
|
|
|
-** When accumulating multiple loops (when pBuilder->pBest is NULL) we
|
|
|
+** When accumulating multiple loops (when pBuilder->pOrSet is NULL) we
|
|
|
** still might overwrite similar loops with the new template if the
|
|
|
** template is better. Loops may be overwritten if the following
|
|
|
** conditions are met:
|
|
|
@@ -108746,30 +108872,22 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
|
|
|
WhereInfo *pWInfo = pBuilder->pWInfo;
|
|
|
sqlite3 *db = pWInfo->pParse->db;
|
|
|
|
|
|
- /* If pBuilder->pBest is defined, then only keep track of the single
|
|
|
- ** best WhereLoop. pBuilder->pBest->maskSelf==0 indicates that no
|
|
|
- ** prior WhereLoops have been evaluated and that the current pTemplate
|
|
|
- ** is therefore the first and hence the best and should be retained.
|
|
|
- */
|
|
|
- if( (p = pBuilder->pBest)!=0 ){
|
|
|
- if( p->maskSelf!=0 ){
|
|
|
- WhereCost rCost = whereCostAdd(p->rRun,p->rSetup);
|
|
|
- WhereCost rTemplate = whereCostAdd(pTemplate->rRun,pTemplate->rSetup);
|
|
|
- if( rCost < rTemplate ){
|
|
|
- testcase( rCost==rTemplate-1 );
|
|
|
- goto whereLoopInsert_noop;
|
|
|
- }
|
|
|
- if( rCost==rTemplate && (p->prereq & pTemplate->prereq)==p->prereq ){
|
|
|
- goto whereLoopInsert_noop;
|
|
|
- }
|
|
|
- }
|
|
|
+ /* If pBuilder->pOrSet is defined, then only keep track of the costs
|
|
|
+ ** and prereqs.
|
|
|
+ */
|
|
|
+ if( pBuilder->pOrSet!=0 ){
|
|
|
+#if WHERETRACE_ENABLED
|
|
|
+ u16 n = pBuilder->pOrSet->n;
|
|
|
+ int x =
|
|
|
+#endif
|
|
|
+ whereOrInsert(pBuilder->pOrSet, pTemplate->prereq, pTemplate->rRun,
|
|
|
+ pTemplate->nOut);
|
|
|
#if WHERETRACE_ENABLED
|
|
|
if( sqlite3WhereTrace & 0x8 ){
|
|
|
- sqlite3DebugPrintf(p->maskSelf==0 ? "ins-init: " : "ins-best: ");
|
|
|
+ sqlite3DebugPrintf(x?" or-%d: ":" or-X: ", n);
|
|
|
whereLoopPrint(pTemplate, pWInfo->pTabList);
|
|
|
}
|
|
|
#endif
|
|
|
- whereLoopXfer(db, p, pTemplate);
|
|
|
return SQLITE_OK;
|
|
|
}
|
|
|
|
|
|
@@ -108863,7 +108981,7 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
|
|
|
whereLoopInsert_noop:
|
|
|
#if WHERETRACE_ENABLED
|
|
|
if( sqlite3WhereTrace & 0x8 ){
|
|
|
- sqlite3DebugPrintf(pBuilder->pBest ? "ins-skip: " : "ins-noop: ");
|
|
|
+ sqlite3DebugPrintf("ins-noop: ");
|
|
|
whereLoopPrint(pTemplate, pWInfo->pTabList);
|
|
|
}
|
|
|
#endif
|
|
|
@@ -109145,7 +109263,7 @@ static int whereLoopAddBtree(
|
|
|
rLogSize = estLog(rSize);
|
|
|
|
|
|
/* Automatic indexes */
|
|
|
- if( !pBuilder->pBest
|
|
|
+ if( !pBuilder->pOrSet
|
|
|
&& (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0
|
|
|
&& pSrc->pIndex==0
|
|
|
&& !pSrc->viaCoroutine
|
|
|
@@ -109431,7 +109549,7 @@ static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){
|
|
|
int iCur;
|
|
|
WhereClause tempWC;
|
|
|
WhereLoopBuilder sSubBuild;
|
|
|
- WhereLoop sBest;
|
|
|
+ WhereOrSet sSum, sCur, sPrev;
|
|
|
struct SrcList_item *pItem;
|
|
|
|
|
|
pWC = pBuilder->pWC;
|
|
|
@@ -109446,16 +109564,14 @@ static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){
|
|
|
WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc;
|
|
|
WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm];
|
|
|
WhereTerm *pOrTerm;
|
|
|
- WhereCost rTotal = 0;
|
|
|
- WhereCost nRow = 0;
|
|
|
- Bitmask prereq = mExtra;
|
|
|
+ int once = 1;
|
|
|
+ int i, j;
|
|
|
|
|
|
- whereLoopInit(&sBest);
|
|
|
pItem = pWInfo->pTabList->a + pNew->iTab;
|
|
|
iCur = pItem->iCursor;
|
|
|
sSubBuild = *pBuilder;
|
|
|
sSubBuild.pOrderBy = 0;
|
|
|
- sSubBuild.pBest = &sBest;
|
|
|
+ sSubBuild.pOrSet = &sCur;
|
|
|
|
|
|
for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){
|
|
|
if( (pOrTerm->eOperator & WO_AND)!=0 ){
|
|
|
@@ -109470,39 +109586,48 @@ static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){
|
|
|
}else{
|
|
|
continue;
|
|
|
}
|
|
|
- sBest.maskSelf = 0;
|
|
|
- sBest.rSetup = 0;
|
|
|
- sBest.rRun = 0;
|
|
|
+ sCur.n = 0;
|
|
|
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
|
|
if( IsVirtual(pItem->pTab) ){
|
|
|
rc = whereLoopAddVirtual(&sSubBuild);
|
|
|
+ for(i=0; i<sCur.n; i++) sCur.a[i].prereq |= mExtra;
|
|
|
}else
|
|
|
#endif
|
|
|
{
|
|
|
rc = whereLoopAddBtree(&sSubBuild, mExtra);
|
|
|
}
|
|
|
- /* sBest.maskSelf is always zero if an error occurs */
|
|
|
- assert( rc==SQLITE_OK || sBest.maskSelf==0 );
|
|
|
- if( sBest.maskSelf==0 ) break;
|
|
|
- assert( sBest.rSetup==0 );
|
|
|
- rTotal = whereCostAdd(rTotal, sBest.rRun);
|
|
|
- nRow = whereCostAdd(nRow, sBest.nOut);
|
|
|
- prereq |= sBest.prereq;
|
|
|
+ assert( rc==SQLITE_OK || sCur.n==0 );
|
|
|
+ if( sCur.n==0 ){
|
|
|
+ sSum.n = 0;
|
|
|
+ break;
|
|
|
+ }else if( once ){
|
|
|
+ whereOrMove(&sSum, &sCur);
|
|
|
+ once = 0;
|
|
|
+ }else{
|
|
|
+ whereOrMove(&sPrev, &sSum);
|
|
|
+ sSum.n = 0;
|
|
|
+ for(i=0; i<sPrev.n; i++){
|
|
|
+ for(j=0; j<sCur.n; j++){
|
|
|
+ whereOrInsert(&sSum, sPrev.a[i].prereq | sCur.a[j].prereq,
|
|
|
+ whereCostAdd(sPrev.a[i].rRun, sCur.a[j].rRun),
|
|
|
+ whereCostAdd(sPrev.a[i].nOut, sCur.a[j].nOut));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
- assert( pNew->nLSlot>=1 );
|
|
|
- if( sBest.maskSelf ){
|
|
|
- pNew->nLTerm = 1;
|
|
|
- pNew->aLTerm[0] = pTerm;
|
|
|
- pNew->wsFlags = WHERE_MULTI_OR;
|
|
|
- pNew->rSetup = 0;
|
|
|
+ pNew->nLTerm = 1;
|
|
|
+ pNew->aLTerm[0] = pTerm;
|
|
|
+ pNew->wsFlags = WHERE_MULTI_OR;
|
|
|
+ pNew->rSetup = 0;
|
|
|
+ pNew->iSortIdx = 0;
|
|
|
+ memset(&pNew->u, 0, sizeof(pNew->u));
|
|
|
+ for(i=0; rc==SQLITE_OK && i<sSum.n; i++){
|
|
|
/* TUNING: Multiple by 3.5 for the secondary table lookup */
|
|
|
- pNew->rRun = rTotal + 18; assert( 18==whereCost(7)-whereCost(2) );
|
|
|
- pNew->nOut = nRow;
|
|
|
- pNew->prereq = prereq;
|
|
|
- memset(&pNew->u, 0, sizeof(pNew->u));
|
|
|
+ pNew->rRun = sSum.a[i].rRun + 18;
|
|
|
+ pNew->nOut = sSum.a[i].nOut;
|
|
|
+ pNew->prereq = sSum.a[i].prereq;
|
|
|
rc = whereLoopInsert(pBuilder, pNew);
|
|
|
}
|
|
|
- whereLoopClear(pWInfo->pParse->db, &sBest);
|
|
|
}
|
|
|
}
|
|
|
return rc;
|
|
|
@@ -110309,7 +110434,8 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
|
|
|
pMaskSet = &pWInfo->sMaskSet;
|
|
|
sWLB.pWInfo = pWInfo;
|
|
|
sWLB.pWC = &pWInfo->sWC;
|
|
|
- sWLB.pNew = (WhereLoop*)&pWInfo->a[nTabList];
|
|
|
+ sWLB.pNew = (WhereLoop*)(((char*)pWInfo)+nByteWInfo);
|
|
|
+ assert( EIGHT_BYTE_ALIGNMENT(sWLB.pNew) );
|
|
|
whereLoopInit(sWLB.pNew);
|
|
|
#ifdef SQLITE_DEBUG
|
|
|
sWLB.pNew->cId = '*';
|