mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-08 14:02:16 +03:00
Allow indexes to be created on date/time functions as long as the 'now'
date and the 'localtime' and 'utc' modifiers are not used. FossilOrigin-Name: 0a5e1c04d9d07bb7fd6546a9ddac1bf42b19ea19c2b79570aea6cd4226887a27
This commit is contained in:
226
src/vdbe.c
226
src/vdbe.c
@@ -1590,117 +1590,6 @@ case OP_CollSeq: {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: Function0 P1 P2 P3 P4 P5
|
||||
** Synopsis: r[P3]=func(r[P2@P5])
|
||||
**
|
||||
** Invoke a user function (P4 is a pointer to a FuncDef object that
|
||||
** defines the function) with P5 arguments taken from register P2 and
|
||||
** successors. The result of the function is stored in register P3.
|
||||
** Register P3 must not be one of the function inputs.
|
||||
**
|
||||
** P1 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 P1 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: Function, AggStep, AggFinal
|
||||
*/
|
||||
/* Opcode: Function P1 P2 P3 P4 P5
|
||||
** Synopsis: r[P3]=func(r[P2@P5])
|
||||
**
|
||||
** Invoke a user function (P4 is a pointer to an sqlite3_context object that
|
||||
** contains a pointer to the function to be run) with P5 arguments taken
|
||||
** from register P2 and successors. The result of the function is stored
|
||||
** in register P3. Register P3 must not be one of the function inputs.
|
||||
**
|
||||
** P1 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 P1 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.
|
||||
**
|
||||
** SQL functions are initially coded as OP_Function0 with P4 pointing
|
||||
** to a FuncDef object. But on first evaluation, the P4 operand is
|
||||
** automatically converted into an sqlite3_context object and the operation
|
||||
** changed to this OP_Function opcode. In this way, the initialization of
|
||||
** the sqlite3_context object occurs only once, rather than once for each
|
||||
** evaluation of the function.
|
||||
**
|
||||
** See also: Function0, AggStep, AggFinal
|
||||
*/
|
||||
case OP_Function0: {
|
||||
int n;
|
||||
sqlite3_context *pCtx;
|
||||
|
||||
assert( pOp->p4type==P4_FUNCDEF );
|
||||
n = pOp->p5;
|
||||
assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
|
||||
assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem+1 - p->nCursor)+1) );
|
||||
assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n );
|
||||
pCtx = sqlite3DbMallocRawNN(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*));
|
||||
if( pCtx==0 ) goto no_mem;
|
||||
pCtx->pOut = 0;
|
||||
pCtx->pFunc = pOp->p4.pFunc;
|
||||
pCtx->iOp = (int)(pOp - aOp);
|
||||
pCtx->pVdbe = p;
|
||||
pCtx->argc = n;
|
||||
pOp->p4type = P4_FUNCCTX;
|
||||
pOp->p4.pCtx = pCtx;
|
||||
pOp->opcode = OP_Function;
|
||||
/* Fall through into OP_Function */
|
||||
}
|
||||
case OP_Function: {
|
||||
int i;
|
||||
sqlite3_context *pCtx;
|
||||
|
||||
assert( pOp->p4type==P4_FUNCCTX );
|
||||
pCtx = pOp->p4.pCtx;
|
||||
|
||||
/* If this function is inside of a trigger, the register array in aMem[]
|
||||
** might change from one evaluation to the next. The next block of code
|
||||
** checks to see if the register array has changed, and if so it
|
||||
** reinitializes the relavant parts of the sqlite3_context object */
|
||||
pOut = &aMem[pOp->p3];
|
||||
if( pCtx->pOut != pOut ){
|
||||
pCtx->pOut = pOut;
|
||||
for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i];
|
||||
}
|
||||
|
||||
memAboutToChange(p, pOut);
|
||||
#ifdef SQLITE_DEBUG
|
||||
for(i=0; i<pCtx->argc; i++){
|
||||
assert( memIsValid(pCtx->argv[i]) );
|
||||
REGISTER_TRACE(pOp->p2+i, pCtx->argv[i]);
|
||||
}
|
||||
#endif
|
||||
MemSetTypeFlag(pOut, MEM_Null);
|
||||
pCtx->fErrorOrAux = 0;
|
||||
(*pCtx->pFunc->xSFunc)(pCtx, pCtx->argc, pCtx->argv);/* IMP: R-24505-23230 */
|
||||
|
||||
/* If the function returned an error, throw an exception */
|
||||
if( pCtx->fErrorOrAux ){
|
||||
if( pCtx->isError ){
|
||||
sqlite3VdbeError(p, "%s", sqlite3_value_text(pOut));
|
||||
rc = pCtx->isError;
|
||||
}
|
||||
sqlite3VdbeDeleteAuxData(db, &p->pAuxData, pCtx->iOp, pOp->p1);
|
||||
if( rc ) goto abort_due_to_error;
|
||||
}
|
||||
|
||||
/* Copy the result of the function into register P3 */
|
||||
if( pOut->flags & (MEM_Str|MEM_Blob) ){
|
||||
sqlite3VdbeChangeEncoding(pOut, encoding);
|
||||
if( sqlite3VdbeMemTooBig(pOut) ) goto too_big;
|
||||
}
|
||||
|
||||
REGISTER_TRACE(pOp->p3, pOut);
|
||||
UPDATE_MAX_BLOBSIZE(pOut);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: BitAnd P1 P2 P3 * *
|
||||
** Synopsis: r[P3]=r[P1]&r[P2]
|
||||
**
|
||||
@@ -7000,6 +6889,121 @@ case OP_MaxPgcnt: { /* out2 */
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Opcode: Function0 P1 P2 P3 P4 P5
|
||||
** Synopsis: r[P3]=func(r[P2@P5])
|
||||
**
|
||||
** Invoke a user function (P4 is a pointer to a FuncDef object that
|
||||
** defines the function) with P5 arguments taken from register P2 and
|
||||
** successors. The result of the function is stored in register P3.
|
||||
** Register P3 must not be one of the function inputs.
|
||||
**
|
||||
** P1 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 P1 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: Function, AggStep, AggFinal
|
||||
*/
|
||||
/* Opcode: Function P1 P2 P3 P4 P5
|
||||
** Synopsis: r[P3]=func(r[P2@P5])
|
||||
**
|
||||
** Invoke a user function (P4 is a pointer to an sqlite3_context object that
|
||||
** contains a pointer to the function to be run) with P5 arguments taken
|
||||
** from register P2 and successors. The result of the function is stored
|
||||
** in register P3. Register P3 must not be one of the function inputs.
|
||||
**
|
||||
** P1 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 P1 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.
|
||||
**
|
||||
** SQL functions are initially coded as OP_Function0 with P4 pointing
|
||||
** to a FuncDef object. But on first evaluation, the P4 operand is
|
||||
** automatically converted into an sqlite3_context object and the operation
|
||||
** changed to this OP_Function opcode. In this way, the initialization of
|
||||
** the sqlite3_context object occurs only once, rather than once for each
|
||||
** evaluation of the function.
|
||||
**
|
||||
** See also: Function0, AggStep, AggFinal
|
||||
*/
|
||||
case OP_PureFunc0:
|
||||
case OP_Function0: {
|
||||
int n;
|
||||
sqlite3_context *pCtx;
|
||||
|
||||
assert( pOp->p4type==P4_FUNCDEF );
|
||||
n = pOp->p5;
|
||||
assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
|
||||
assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem+1 - p->nCursor)+1) );
|
||||
assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n );
|
||||
pCtx = sqlite3DbMallocRawNN(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*));
|
||||
if( pCtx==0 ) goto no_mem;
|
||||
pCtx->pOut = 0;
|
||||
pCtx->pFunc = pOp->p4.pFunc;
|
||||
pCtx->iOp = (int)(pOp - aOp);
|
||||
pCtx->pVdbe = p;
|
||||
pCtx->argc = n;
|
||||
pOp->p4type = P4_FUNCCTX;
|
||||
pOp->p4.pCtx = pCtx;
|
||||
assert( OP_PureFunc == OP_PureFunc0+2 );
|
||||
assert( OP_Function == OP_Function0+2 );
|
||||
pOp->opcode += 2;
|
||||
/* Fall through into OP_Function */
|
||||
}
|
||||
case OP_PureFunc:
|
||||
case OP_Function: {
|
||||
int i;
|
||||
sqlite3_context *pCtx;
|
||||
|
||||
assert( pOp->p4type==P4_FUNCCTX );
|
||||
pCtx = pOp->p4.pCtx;
|
||||
|
||||
/* If this function is inside of a trigger, the register array in aMem[]
|
||||
** might change from one evaluation to the next. The next block of code
|
||||
** checks to see if the register array has changed, and if so it
|
||||
** reinitializes the relavant parts of the sqlite3_context object */
|
||||
pOut = &aMem[pOp->p3];
|
||||
if( pCtx->pOut != pOut ){
|
||||
pCtx->pOut = pOut;
|
||||
for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i];
|
||||
}
|
||||
|
||||
memAboutToChange(p, pOut);
|
||||
#ifdef SQLITE_DEBUG
|
||||
for(i=0; i<pCtx->argc; i++){
|
||||
assert( memIsValid(pCtx->argv[i]) );
|
||||
REGISTER_TRACE(pOp->p2+i, pCtx->argv[i]);
|
||||
}
|
||||
#endif
|
||||
MemSetTypeFlag(pOut, MEM_Null);
|
||||
pCtx->fErrorOrAux = 0;
|
||||
(*pCtx->pFunc->xSFunc)(pCtx, pCtx->argc, pCtx->argv);/* IMP: R-24505-23230 */
|
||||
|
||||
/* If the function returned an error, throw an exception */
|
||||
if( pCtx->fErrorOrAux ){
|
||||
if( pCtx->isError ){
|
||||
sqlite3VdbeError(p, "%s", sqlite3_value_text(pOut));
|
||||
rc = pCtx->isError;
|
||||
}
|
||||
sqlite3VdbeDeleteAuxData(db, &p->pAuxData, pCtx->iOp, pOp->p1);
|
||||
if( rc ) goto abort_due_to_error;
|
||||
}
|
||||
|
||||
/* Copy the result of the function into register P3 */
|
||||
if( pOut->flags & (MEM_Str|MEM_Blob) ){
|
||||
sqlite3VdbeChangeEncoding(pOut, encoding);
|
||||
if( sqlite3VdbeMemTooBig(pOut) ) goto too_big;
|
||||
}
|
||||
|
||||
REGISTER_TRACE(pOp->p3, pOut);
|
||||
UPDATE_MAX_BLOBSIZE(pOut);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* Opcode: Init P1 P2 * P4 *
|
||||
** Synopsis: Start at P2
|
||||
|
Reference in New Issue
Block a user