]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Simplify the bytecode generation for SQL function calls such that the
authordrh <drh@noemail.net>
Wed, 30 Oct 2019 16:29:02 +0000 (16:29 +0000)
committerdrh <drh@noemail.net>
Wed, 30 Oct 2019 16:29:02 +0000 (16:29 +0000)
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

manifest
manifest.uuid
src/analyze.c
src/attach.c
src/expr.c
src/vdbe.c
src/vdbe.h
src/vdbeaux.c

index 22e2cedd30d26ac054ff48295dcb77e584990ebe..5f1f7568dd11d64fbe195eb81f8d26790787423f 100644 (file)
--- a/manifest
+++ b/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
index 4bef0df2afe330a44d3310429ee1eb85a9ff7e29..924a8fc5ec84eca31cdd668f73a1162f08f9bff2 100644 (file)
@@ -1 +1 @@
-13fe6978b7de208d2e27460d824f7fc778cf6ea0aabfe566b32bb410b8816f63
\ No newline at end of file
+84e02d773d60cffe619104991d21d7f0c68616c0f6bb99686bf54f5306c756d0
\ No newline at end of file
index 6df6e7a6ecc0f8396440db1b53b300e29b5dd391..2a071ef126b3844f85ee8a51b90f82df87f1987d 100644 (file)
@@ -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++){
index 1dcb407edd0c49593dd285ca0c3d9883bda5c596..ca9af483c246dc8108cb7b63de26337ab9ee747c 100644 (file)
@@ -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).
index 7dd557736418c66455ac3ad595e28efa42fe7415..36ab7c795a6a181109ac297aba8863fd0e933c94 100644 (file)
@@ -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);
index 7c8d2a4ef7726f9b2a33fd849e2617ec186d1063..dbfa18a5e25cea2cee2b4ded2e080a25d1cd2c69 100644 (file)
@@ -7442,13 +7442,15 @@ case OP_MaxPgcnt: {            /* out2 */
 }
 #endif
 
-/* Opcode: Function0 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 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.
+** 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
@@ -7457,14 +7459,16 @@ case OP_MaxPgcnt: {            /* out2 */
 ** sqlite3_set_auxdata() API may be safely retained until the next
 ** invocation of this opcode.
 **
-** See also: Function, AggStep, AggFinal
+** See also: AggStep, AggFinal, PureFunc
 */
-/* Opcode: Function P1 P2 P3 P4 P5
+/* 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 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 +7478,16 @@ 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.
+** 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: Function0, AggStep, AggFinal
+** 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
index b5c2f02de81bc5c42f01bb6069fa0f6712463dc7..3214d5bce36819fb2f50e2bf64fe717ed53e916f 100644 (file)
@@ -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);
index c83292fa43363db834a5262a4f687652a8c5b416..de6575cd51dcf0aa9391885955dd340513ecd380 100644 (file)
 #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;