Always disallow the use of non-deterministic functions in CHECK constraints,
even date/time functions that use the 'now' or similar keywords.  Provide
improved error messages when this requirement is not met.
Ticket [830277d9db6c3ba1]

FossilOrigin-Name: 2978b65ebe25eeabe543b67cb266308cceb20082a4ae71565d6d083d7c08bc9f
diff --git a/src/expr.c b/src/expr.c
index 36ab7c7..b0c61f0 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -4033,7 +4033,7 @@
 #endif
       {
         sqlite3VdbeAddFunctionCall(pParse, constMask, r1, target, nFarg,
-                                   pDef, pParse->iSelfTab);
+                                   pDef, pExpr->op2);
       }
       if( nFarg && constMask==0 ){
         sqlite3ReleaseTempRange(pParse, r1, nFarg);
@@ -5028,7 +5028,7 @@
      && (combinedFlags & EP_Reduced)==0
     ){
       if( pA->iColumn!=pB->iColumn ) return 2;
-      if( pA->op2!=pB->op2 ) return 2;
+      if( pA->op2!=pB->op2 && (pA->op!=TK_FUNCTION || iTab<0) ) return 2;
       if( pA->op!=TK_IN && pA->iTable!=pB->iTable && pA->iTable!=iTab ){
         return 2;
       }
diff --git a/src/resolve.c b/src/resolve.c
index a9c20b1..9be62c0 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -815,15 +815,18 @@
         if( pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG) ){
           /* For the purposes of the EP_ConstFunc flag, date and time
           ** functions and other functions that change slowly are considered
-          ** constant because they are constant for the duration of one query */
+          ** constant because they are constant for the duration of one query.
+          ** This allows them to be factored out of inner loops. */
           ExprSetProperty(pExpr,EP_ConstFunc);
         }
         if( (pDef->funcFlags & SQLITE_FUNC_CONSTANT)==0 ){
           /* Date/time functions that use 'now', and other functions like
           ** sqlite_version() that might change over time cannot be used
           ** in an index. */
-          notValid(pParse, pNC, "non-deterministic functions",
-                   NC_IdxExpr|NC_PartIdx|NC_GenCol);
+          notValid(pParse, pNC, "non-deterministic functions", NC_SelfRef);
+        }else{
+          assert( (NC_SelfRef & 0xff)==NC_SelfRef ); /* Must fit in 8 bits */
+          pExpr->op2 = pNC->ncFlags & NC_SelfRef;
         }
         if( (pDef->funcFlags & SQLITE_FUNC_INTERNAL)!=0
          && pParse->nested==0
@@ -1789,11 +1792,13 @@
 ** Resolve names in expressions that can only reference a single table
 ** or which cannot reference any tables at all.  Examples:
 **
-**    (1)   CHECK constraints
-**    (2)   WHERE clauses on partial indices
-**    (3)   Expressions in indexes on expressions
-**    (4)   Expression arguments to VACUUM INTO.
-**    (5)   GENERATED ALWAYS as expressions
+**                                                    "type" flag
+**                                                    ------------
+**    (1)   CHECK constraints                         NC_IsCheck
+**    (2)   WHERE clauses on partial indices          NC_PartIdx
+**    (3)   Expressions in indexes on expressions     NC_IdxExpr
+**    (4)   Expression arguments to VACUUM INTO.      0
+**    (5)   GENERATED ALWAYS as expressions           NC_GenCol
 **
 ** In all cases except (4), the Expr.iTable value for Expr.op==TK_COLUMN
 ** nodes of the expression is set to -1 and the Expr.iColumn value is
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index d8668a2..cf7abfe 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -2487,6 +2487,10 @@
 struct Expr {
   u8 op;                 /* Operation performed by this node */
   char affExpr;          /* affinity, or RAISE type */
+  u8 op2;                /* TK_REGISTER/TK_TRUTH: original value of Expr.op
+                         ** TK_COLUMN: the value of p5 for OP_Column
+                         ** TK_AGG_FUNCTION: nesting depth
+                         ** TK_FUNCTION: NC_SelfRef flag if needs OP_PureFunc */
   u32 flags;             /* Various flags.  EP_* See below */
   union {
     char *zToken;          /* Token value. Zero terminated and dequoted */
@@ -2525,9 +2529,6 @@
                          ** TK_SELECT_COLUMN: column of the result vector */
   i16 iAgg;              /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
   i16 iRightJoinTable;   /* If EP_FromJoin, the right table of the join */
-  u8 op2;                /* TK_REGISTER/TK_TRUTH: original value of Expr.op
-                         ** TK_COLUMN: the value of p5 for OP_Column
-                         ** TK_AGG_FUNCTION: nesting depth */
   AggInfo *pAggInfo;     /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
   union {
     Table *pTab;           /* TK_COLUMN: Table containing column. Can be NULL
@@ -2840,9 +2841,10 @@
 #define NC_AllowAgg  0x00001  /* Aggregate functions are allowed here */
 #define NC_PartIdx   0x00002  /* True if resolving a partial index WHERE */
 #define NC_IsCheck   0x00004  /* True if resolving a CHECK constraint */
-#define NC_InAggFunc 0x00008  /* True if analyzing arguments to an agg func */
+#define NC_GenCol    0x00008  /* True for a GENERATED ALWAYS AS clause */
 #define NC_HasAgg    0x00010  /* One or more aggregate functions seen */
 #define NC_IdxExpr   0x00020  /* True if resolving columns of CREATE INDEX */
+#define NC_SelfRef   0x0002e  /* Combo: PartIdx, isCheck, GenCol, and IdxExpr */
 #define NC_VarSelect 0x00040  /* A correlated subquery has been seen */
 #define NC_UEList    0x00080  /* True if uNC.pEList is used */
 #define NC_UAggInfo  0x00100  /* True if uNC.pAggInfo is used */
@@ -2852,7 +2854,7 @@
 #define NC_AllowWin  0x04000  /* Window functions are allowed here */
 #define NC_HasWin    0x08000  /* One or more window functions seen */
 #define NC_IsDDL     0x10000  /* Resolving names in a CREATE statement */
-#define NC_GenCol    0x20000  /* True for a GENERATED ALWAYS AS clause */
+#define NC_InAggFunc 0x20000  /* True if analyzing arguments to an agg func */
 
 /*
 ** An instance of the following object describes a single ON CONFLICT
diff --git a/src/vdbeaux.c b/src/vdbeaux.c
index de6575c..9596e16 100644
--- a/src/vdbeaux.c
+++ b/src/vdbeaux.c
@@ -365,11 +365,12 @@
   }
   pCtx->pOut = 0;
   pCtx->pFunc = (FuncDef*)pFunc;
-  pCtx->pVdbe = v;
+  pCtx->pVdbe = 0;
   pCtx->isError = 0;
   pCtx->argc = nArg;
   addr = sqlite3VdbeAddOp4(v, eCallCtx ? OP_PureFunc : OP_Function,
                            p1, p2, p3, (char*)pCtx, P4_FUNCCTX);
+  sqlite3VdbeChangeP5(v, eCallCtx & NC_SelfRef);
   pCtx->iOp = addr;
   return addr;
 }
@@ -4999,21 +5000,25 @@
 ** features such as 'now'.
 */
 int sqlite3NotPureFunc(sqlite3_context *pCtx){
+  const VdbeOp *pOp;
 #ifdef SQLITE_ENABLE_STAT4
   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);
+  pOp = pCtx->pVdbe->aOp + pCtx->iOp;
+  if( pOp->opcode==OP_PureFunc ){
+    const char *zContext;
+    char *zMsg;
+    if( pOp->p5 & NC_IsCheck ){
+      zContext = "a CHECK constraint";
+    }else if( pOp->p5 & NC_GenCol ){
+      zContext = "a generated column";
+    }else{
+      zContext = "an index";
+    }
+    zMsg = sqlite3_mprintf("non-deterministic use of %s() in %s",
+                           pCtx->pFunc->zName, zContext);
     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;