Simplify the bytecode generation for SQL function calls such that the
OP_Function or OP_PureFunc opcodes are coded directly, rather than using the intermediate OP_Function0 or OP_PureFunc0 - opcodes that are now removed. FossilOrigin-Name: 84e02d773d60cffe619104991d21d7f0c68616c0f6bb99686bf54f5306c756d0
This commit is contained in:
parent
9ee94147f0
commit
920cf596e6
22
manifest
22
manifest
@ -1,5 +1,5 @@
|
||||
C New\stokens\sALWAYS,\sGENERATED,\sand\sSTORED\sused\sby\sgenerated\scolumns\sshould\nall\sbe\sfallback\stokens.
|
||||
D 2019-10-30T13:00:23.625
|
||||
C Simplify\sthe\sbytecode\sgeneration\sfor\sSQL\sfunction\scalls\ssuch\sthat\sthe\nOP_Function\sor\sOP_PureFunc\sopcodes\sare\scoded\sdirectly,\srather\sthan\susing\nthe\sintermediate\sOP_Function0\sor\sOP_PureFunc0\s-\sopcodes\sthat\sare\snow\sremoved.
|
||||
D 2019-10-30T16:29:02.506
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
@ -461,8 +461,8 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
|
||||
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||
F src/alter.c 0fdf14a1d1c61315a6d727252c579bc8cbfe62de195df6979dd784374e22032b
|
||||
F src/analyze.c fd70b9c7a683230a7f7936af64dd25308e93d7c9819a3168493a7c7703481f80
|
||||
F src/attach.c 3ca19504849c2d9be10fc5899d6811f9d6e848665d1a41ffb53df0cd6e7c13ed
|
||||
F src/analyze.c b3ceec3fc052df8a96ca8a8c858d455dc5029ba681b4be98bb5c5a9162cfa58c
|
||||
F src/attach.c b30c44333d55a68c0a12920b5b9d40b254cbd3d4509bda77417209eeed8b3d80
|
||||
F src/auth.c a3d5bfdba83d25abed1013a8c7a5f204e2e29b0c25242a56bc02bb0c07bf1e06
|
||||
F src/backup.c f70077d40c08b7787bfe934e4d1da8030cb0cc57d46b345fba2294b7d1be23ab
|
||||
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
|
||||
@ -478,7 +478,7 @@ F src/date.c e1d8ac7102f3f283e63e13867acb0efa33861cf34f0faf4cdbaf9fa7a1eb7041
|
||||
F src/dbpage.c 135eb3b5e74f9ef74bde5cec2571192c90c86984fa534c88bf4a055076fa19b7
|
||||
F src/dbstat.c c12833de69cb655751487d2c5a59607e36be1c58ba1f4bd536609909ad47b319
|
||||
F src/delete.c d08c9e01a2664afd12edcfa3a9c6578517e8ff8735f35509582693adbe0edeaf
|
||||
F src/expr.c c158710c5de9452fb3f82f038ed96026f1ce1a2a1fcd9bbdb2172f33bfe9fd72
|
||||
F src/expr.c 23d5f9e491921a57fe6d59b75c461d45777470d8b1653180ebb3e83ea658f889
|
||||
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
||||
F src/fkey.c ac56f02ffe7a3dff311654f86e3c2fd1ff2eb38862b0c07fd908d8cc0fb4a9a2
|
||||
F src/func.c ed33e38cd642058182a31a3f518f2e34f4bbe53aa483335705c153c4d3e50b12
|
||||
@ -598,11 +598,11 @@ F src/upsert.c b445315c8958d8f17ec3297d06842e61dacaad0633ccaec1e4e160de7e562212
|
||||
F src/utf.c 2f0fac345c7660d5c5bd3df9e9d8d33d4c27f366bcfb09e07443064d751a0507
|
||||
F src/util.c 10d910e04a4f3842042485e0df01a484f57f912c10b60b3a09ccddd5019bd138
|
||||
F src/vacuum.c 82dcec9e7b1afa980288718ad11bc499651c722d7b9f32933c4d694d91cb6ebf
|
||||
F src/vdbe.c 9e4ba6bb8e5b827b9ae771ba62a92f3099adaacd36838d54042eb2499cd7f6f5
|
||||
F src/vdbe.h 2a49df699f305afa94f338f14bf6e1bfbca8112ce9c4d522abffd9493fc22a25
|
||||
F src/vdbe.c b67d6af853e03c3dd6d1116351567f62d8a2c10d3bd6db5f7f366e75d11c6653
|
||||
F src/vdbe.h fdbc0a11e5768a702b46ce63286f60e22e71351a29bd98b3666405e1fccc7802
|
||||
F src/vdbeInt.h bd589b8b7273286858950717e0e1ec5c88b18af45079a3366dc1371865cea704
|
||||
F src/vdbeapi.c 1252d80c548711e47a6d84dae88ed4e95d3fbb4e7bd0eaa1347299af7efddf02
|
||||
F src/vdbeaux.c e3ed5475d4611f28f3cad06c0454a354148f3bb0ce21c75659ce737dc13f7968
|
||||
F src/vdbeaux.c aeba258bb045c583bd85ae1e0b218c3542897baf522da1f1ab7da4259a7394ce
|
||||
F src/vdbeblob.c 253ed82894924c362a7fa3079551d3554cd1cdace39aa833da77d3bc67e7c1b1
|
||||
F src/vdbemem.c d8e10d1773806105e62094c4ede0a4684f46caaf07667a45e6d461e94306b530
|
||||
F src/vdbesort.c a3be032cc3fee0e3af31773af4a7a6f931b7230a34f53282ccf1d9a2a72343be
|
||||
@ -1848,7 +1848,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 4d424f3047b48fc441475137f30a719d2f079390c86fe2617710ddfb05c5e240
|
||||
R d27d4fff3c6fbce4f9267adc4b31de94
|
||||
P 13fe6978b7de208d2e27460d824f7fc778cf6ea0aabfe566b32bb410b8816f63
|
||||
R 2b5ad42e3fc6b49f0350688afce0bf63
|
||||
U drh
|
||||
Z c4c731d7baeb139e7fe1ba09d543039c
|
||||
Z 8fbcb7ba95c29435c7309e57f3022596
|
||||
|
@ -1 +1 @@
|
||||
13fe6978b7de208d2e27460d824f7fc778cf6ea0aabfe566b32bb410b8816f63
|
||||
84e02d773d60cffe619104991d21d7f0c68616c0f6bb99686bf54f5306c756d0
|
@ -916,18 +916,17 @@ static const FuncDef statGetFuncdef = {
|
||||
{0}
|
||||
};
|
||||
|
||||
static void callStatGet(Vdbe *v, int regStat4, int iParam, int regOut){
|
||||
assert( regOut!=regStat4 && regOut!=regStat4+1 );
|
||||
static void callStatGet(Parse *pParse, int regStat4, int iParam, int regOut){
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, iParam, regStat4+1);
|
||||
sqlite3VdbeAddOp2(pParse->pVdbe, OP_Integer, iParam, regStat4+1);
|
||||
#elif SQLITE_DEBUG
|
||||
assert( iParam==STAT_GET_STAT1 );
|
||||
#else
|
||||
UNUSED_PARAMETER( iParam );
|
||||
#endif
|
||||
sqlite3VdbeAddOp4(v, OP_Function0, 0, regStat4, regOut,
|
||||
(char*)&statGetFuncdef, P4_FUNCDEF);
|
||||
sqlite3VdbeChangeP5(v, 1 + IsStat4);
|
||||
assert( regOut!=regStat4 && regOut!=regStat4+1 );
|
||||
sqlite3VdbeAddFunctionCall(pParse, 0, regStat4, regOut, 1+IsStat4,
|
||||
&statGetFuncdef, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1095,9 +1094,8 @@ static void analyzeOneTable(
|
||||
#endif
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, nCol, regStat4+1);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, pIdx->nKeyCol, regStat4+2);
|
||||
sqlite3VdbeAddOp4(v, OP_Function0, 0, regStat4+1, regStat4,
|
||||
(char*)&statInitFuncdef, P4_FUNCDEF);
|
||||
sqlite3VdbeChangeP5(v, 2+IsStat4);
|
||||
sqlite3VdbeAddFunctionCall(pParse, 0, regStat4+1, regStat4, 2+IsStat4,
|
||||
&statInitFuncdef, 0);
|
||||
|
||||
/* Implementation of the following:
|
||||
**
|
||||
@ -1192,13 +1190,12 @@ static void analyzeOneTable(
|
||||
}
|
||||
#endif
|
||||
assert( regChng==(regStat4+1) );
|
||||
sqlite3VdbeAddOp4(v, OP_Function0, 1, regStat4, regTemp,
|
||||
(char*)&statPushFuncdef, P4_FUNCDEF);
|
||||
sqlite3VdbeChangeP5(v, 2+IsStat4);
|
||||
sqlite3VdbeAddFunctionCall(pParse, 1, regStat4, regTemp, 2+IsStat4,
|
||||
&statPushFuncdef, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); VdbeCoverage(v);
|
||||
|
||||
/* Add the entry to the stat1 table. */
|
||||
callStatGet(v, regStat4, STAT_GET_STAT1, regStat1);
|
||||
callStatGet(pParse, regStat4, STAT_GET_STAT1, regStat1);
|
||||
assert( "BBB"[0]==SQLITE_AFF_TEXT );
|
||||
sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "BBB", 0);
|
||||
sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
|
||||
@ -1224,12 +1221,12 @@ static void analyzeOneTable(
|
||||
pParse->nMem = MAX(pParse->nMem, regCol+nCol);
|
||||
|
||||
addrNext = sqlite3VdbeCurrentAddr(v);
|
||||
callStatGet(v, regStat4, STAT_GET_ROWID, regSampleRowid);
|
||||
callStatGet(pParse, regStat4, STAT_GET_ROWID, regSampleRowid);
|
||||
addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, regSampleRowid);
|
||||
VdbeCoverage(v);
|
||||
callStatGet(v, regStat4, STAT_GET_NEQ, regEq);
|
||||
callStatGet(v, regStat4, STAT_GET_NLT, regLt);
|
||||
callStatGet(v, regStat4, STAT_GET_NDLT, regDLt);
|
||||
callStatGet(pParse, regStat4, STAT_GET_NEQ, regEq);
|
||||
callStatGet(pParse, regStat4, STAT_GET_NLT, regLt);
|
||||
callStatGet(pParse, regStat4, STAT_GET_NDLT, regDLt);
|
||||
sqlite3VdbeAddOp4Int(v, seekOp, iTabCur, addrNext, regSampleRowid, 0);
|
||||
VdbeCoverage(v);
|
||||
for(i=0; i<nCol; i++){
|
||||
|
@ -401,11 +401,8 @@ static void codeAttach(
|
||||
|
||||
assert( v || db->mallocFailed );
|
||||
if( v ){
|
||||
sqlite3VdbeAddOp4(v, OP_Function0, 0, regArgs+3-pFunc->nArg, regArgs+3,
|
||||
(char *)pFunc, P4_FUNCDEF);
|
||||
assert( pFunc->nArg==-1 || (pFunc->nArg&0xff)==pFunc->nArg );
|
||||
sqlite3VdbeChangeP5(v, (u8)(pFunc->nArg));
|
||||
|
||||
sqlite3VdbeAddFunctionCall(pParse, 0, regArgs+3-pFunc->nArg, regArgs+3,
|
||||
pFunc->nArg, pFunc, 0);
|
||||
/* Code an OP_Expire. For an ATTACH statement, set P1 to true (expire this
|
||||
** statement only). For DETACH, set it to false (expire all existing
|
||||
** statements).
|
||||
|
@ -4032,9 +4032,8 @@ expr_code_doover:
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
sqlite3VdbeAddOp4(v, pParse->iSelfTab ? OP_PureFunc0 : OP_Function0,
|
||||
constMask, r1, target, (char*)pDef, P4_FUNCDEF);
|
||||
sqlite3VdbeChangeP5(v, (u8)nFarg);
|
||||
sqlite3VdbeAddFunctionCall(pParse, constMask, r1, target, nFarg,
|
||||
pDef, pParse->iSelfTab);
|
||||
}
|
||||
if( nFarg && constMask==0 ){
|
||||
sqlite3ReleaseTempRange(pParse, r1, nFarg);
|
||||
|
88
src/vdbe.c
88
src/vdbe.c
@ -7442,29 +7442,14 @@ 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
|
||||
/* Opcode: Function P1 P2 P3 P4 *
|
||||
** 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
|
||||
** contains a pointer to the function to be run) with arguments taken
|
||||
** from register P2 and successors. The number of arguments is in
|
||||
** the sqlite3_context object that P4 points to.
|
||||
** 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
|
||||
@ -7474,40 +7459,35 @@ case OP_MaxPgcnt: { /* out2 */
|
||||
** 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
|
||||
** See also: AggStep, AggFinal, PureFunc
|
||||
*/
|
||||
/* Opcode: PureFunc P1 P2 P3 P4 *
|
||||
** 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 arguments taken
|
||||
** from register P2 and successors. The number of arguments is in
|
||||
** the sqlite3_context object that P4 points to.
|
||||
** 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.
|
||||
**
|
||||
** This opcode works exactly like OP_Function. The only difference is in
|
||||
** its name. This opcode is used in places where the function must be
|
||||
** purely non-deterministic. Some built-in date/time functions can be
|
||||
** either determinitic of non-deterministic, depending on their arguments.
|
||||
** When those function are used in a non-deterministic way, they will check
|
||||
** to see if they were called using OP_PureFunc instead of OP_Function, and
|
||||
** if they were, they throw an error.
|
||||
**
|
||||
** See also: AggStep, AggFinal, Function
|
||||
*/
|
||||
case OP_PureFunc0: /* group */
|
||||
case OP_Function0: { /* group */
|
||||
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->isError = 0;
|
||||
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: /* group */
|
||||
case OP_Function: { /* group */
|
||||
int i;
|
||||
@ -7522,9 +7502,11 @@ case OP_Function: { /* group */
|
||||
** reinitializes the relavant parts of the sqlite3_context object */
|
||||
pOut = &aMem[pOp->p3];
|
||||
if( pCtx->pOut != pOut ){
|
||||
pCtx->pVdbe = p;
|
||||
pCtx->pOut = pOut;
|
||||
for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i];
|
||||
}
|
||||
assert( pCtx->pVdbe==p );
|
||||
|
||||
memAboutToChange(p, pOut);
|
||||
#ifdef SQLITE_DEBUG
|
||||
|
@ -190,6 +190,7 @@ int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int);
|
||||
int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int);
|
||||
int sqlite3VdbeAddOp4Dup8(Vdbe*,int,int,int,int,const u8*,int);
|
||||
int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int);
|
||||
int sqlite3VdbeAddFunctionCall(Parse*,int,int,int,int,const FuncDef*,int);
|
||||
void sqlite3VdbeEndCoroutine(Vdbe*,int);
|
||||
#if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS)
|
||||
void sqlite3VdbeVerifyNoMallocRequired(Vdbe *p, int N);
|
||||
|
@ -15,6 +15,10 @@
|
||||
#include "sqliteInt.h"
|
||||
#include "vdbeInt.h"
|
||||
|
||||
/* Forward references */
|
||||
static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef);
|
||||
static void vdbeFreeOpArray(sqlite3 *, Op *, int);
|
||||
|
||||
/*
|
||||
** Create a new virtual database engine.
|
||||
*/
|
||||
@ -328,6 +332,48 @@ int sqlite3VdbeAddOp4(
|
||||
return addr;
|
||||
}
|
||||
|
||||
/*
|
||||
** Add an OP_Function or OP_PureFunc opcode.
|
||||
**
|
||||
** The eCallCtx argument is information (typically taken from Expr.op2)
|
||||
** that describes the calling context of the function. 0 means a general
|
||||
** function call. NC_IsCheck means called by a check constraint,
|
||||
** NC_IdxExpr means called as part of an index expression. NC_PartIdx
|
||||
** means in the WHERE clause of a partial index. NC_GenCol means called
|
||||
** while computing a generated column value. 0 is the usual case.
|
||||
*/
|
||||
int sqlite3VdbeAddFunctionCall(
|
||||
Parse *pParse, /* Parsing context */
|
||||
int p1, /* Constant argument mask */
|
||||
int p2, /* First argument register */
|
||||
int p3, /* Register into which results are written */
|
||||
int nArg, /* Number of argument */
|
||||
const FuncDef *pFunc, /* The function to be invoked */
|
||||
int eCallCtx /* Calling context */
|
||||
){
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
int nByte;
|
||||
int addr;
|
||||
sqlite3_context *pCtx;
|
||||
assert( v );
|
||||
nByte = sizeof(*pCtx) + (nArg-1)*sizeof(sqlite3_value*);
|
||||
pCtx = sqlite3DbMallocRawNN(pParse->db, nByte);
|
||||
if( pCtx==0 ){
|
||||
assert( pParse->db->mallocFailed );
|
||||
freeEphemeralFunction(pParse->db, (FuncDef*)pFunc);
|
||||
return 0;
|
||||
}
|
||||
pCtx->pOut = 0;
|
||||
pCtx->pFunc = (FuncDef*)pFunc;
|
||||
pCtx->pVdbe = v;
|
||||
pCtx->isError = 0;
|
||||
pCtx->argc = nArg;
|
||||
addr = sqlite3VdbeAddOp4(v, eCallCtx ? OP_PureFunc : OP_Function,
|
||||
p1, p2, p3, (char*)pCtx, P4_FUNCCTX);
|
||||
pCtx->iOp = addr;
|
||||
return addr;
|
||||
}
|
||||
|
||||
/*
|
||||
** Add an opcode that includes the p4 value with a P4_INT64 or
|
||||
** P4_REAL type.
|
||||
@ -1020,8 +1066,6 @@ static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef){
|
||||
}
|
||||
}
|
||||
|
||||
static void vdbeFreeOpArray(sqlite3 *, Op *, int);
|
||||
|
||||
/*
|
||||
** Delete a P4 value if necessary.
|
||||
*/
|
||||
@ -1031,7 +1075,7 @@ static SQLITE_NOINLINE void freeP4Mem(sqlite3 *db, Mem *p){
|
||||
}
|
||||
static SQLITE_NOINLINE void freeP4FuncCtx(sqlite3 *db, sqlite3_context *p){
|
||||
freeEphemeralFunction(db, p->pFunc);
|
||||
sqlite3DbFreeNN(db, p);
|
||||
sqlite3DbFreeNN(db, p);
|
||||
}
|
||||
static void freeP4(sqlite3 *db, int p4type, void *p4){
|
||||
assert( db );
|
||||
@ -1537,13 +1581,11 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
|
||||
sqlite3_str_appendf(&x, "%s(%d)", pDef->zName, pDef->nArg);
|
||||
break;
|
||||
}
|
||||
#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
|
||||
case P4_FUNCCTX: {
|
||||
FuncDef *pDef = pOp->p4.pCtx->pFunc;
|
||||
sqlite3_str_appendf(&x, "%s(%d)", pDef->zName, pDef->nArg);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case P4_INT64: {
|
||||
sqlite3_str_appendf(&x, "%lld", *pOp->p4.pI64);
|
||||
break;
|
||||
@ -4961,9 +5003,17 @@ int sqlite3NotPureFunc(sqlite3_context *pCtx){
|
||||
if( pCtx->pVdbe==0 ) return 1;
|
||||
#endif
|
||||
if( pCtx->pVdbe->aOp[pCtx->iOp].opcode==OP_PureFunc ){
|
||||
#if 0
|
||||
char *zMsg = sqlite3_mprintf(
|
||||
"non-deterministic use of %s() in an index, CHECK constraint, "
|
||||
"or generated column", pCtx->pFunc->zName);
|
||||
sqlite3_result_error(pCtx, zMsg, -1);
|
||||
sqlite3_free(zMsg);
|
||||
#else
|
||||
sqlite3_result_error(pCtx,
|
||||
"non-deterministic function in index expression or CHECK constraint",
|
||||
-1);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user