aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/expr.c70
-rw-r--r--src/sqliteInt.h2
-rw-r--r--src/where.c58
3 files changed, 71 insertions, 59 deletions
diff --git a/src/expr.c b/src/expr.c
index 1b18828dd..83b1ff56c 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -1164,6 +1164,7 @@ Expr *sqlite3ExprFunction(
){
Expr *pNew;
sqlite3 *db = pParse->db;
+ int ii;
assert( pToken );
pNew = sqlite3ExprAlloc(db, TK_FUNCTION, pToken, 1);
if( pNew==0 ){
@@ -1178,6 +1179,11 @@ Expr *sqlite3ExprFunction(
){
sqlite3ErrorMsg(pParse, "too many arguments on function %T", pToken);
}
+ if( pList && pParse->nErr==0 ){
+ for(ii=0; ii<pList->nExpr; ii++){
+ ExprSetProperty(pList->a[ii].pExpr, EP_FuncArg);
+ }
+ }
pNew->x.pList = pList;
ExprSetProperty(pNew, EP_HasFunc);
assert( ExprUseXList(pNew) );
@@ -4555,6 +4561,59 @@ static int exprCodeInlineFunction(
}
/*
+** Expression Node callback for sqlite3ExprCanReturnSubtype().
+**
+** Only a function call is able to return a subtype. So if the node
+** is not a function call, return WRC_Prune immediately.
+**
+** A function call is able to return a subtype if it has the
+** SQLITE_RESULT_SUBTYPE property.
+**
+** Assume that every function is able to pass-through a subtype from
+** one of its argument (using sqlite3_result_value()). Most functions
+** are not this way, but we don't have a mechanism to distinguish those
+** that are from those that are not, so assume they all work this way.
+** That means that if one of its arguments is another function and that
+** other function is able to return a subtype, then this function is
+** able to return a subtype.
+*/
+static int exprNodeCanReturnSubtype(Walker *pWalker, Expr *pExpr){
+ int n;
+ FuncDef *pDef;
+ sqlite3 *db;
+ if( pExpr->op!=TK_FUNCTION ){
+ return WRC_Prune;
+ }
+ assert( ExprUseXList(pExpr) );
+ db = pWalker->pParse->db;
+ n = pExpr->x.pList ? pExpr->x.pList->nExpr : 0;
+ pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0);
+ if( pDef==0 || (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){
+ pWalker->eCode = 1;
+ return WRC_Prune;
+ }
+ return WRC_Continue;
+}
+
+/*
+** Return TRUE if expression pExpr is able to return a subtype.
+**
+** A TRUE return does not guarantee that a subtype will be returned.
+** It only indicates that a subtype return is possible. False positives
+** are acceptable as they only disable an optimization. False negatives,
+** on the other hand, can lead to incorrect answers.
+*/
+static int sqlite3ExprCanReturnSubtype(Parse *pParse, Expr *pExpr){
+ Walker w;
+ memset(&w, 0, sizeof(w));
+ w.pParse = pParse;
+ w.xExprCallback = exprNodeCanReturnSubtype;
+ sqlite3WalkExpr(&w, pExpr);
+ return w.eCode;
+}
+
+
+/*
** Check to see if pExpr is one of the indexed expressions on pParse->pIdxEpr.
** If it is, then resolve the expression by reading from the index and
** return the register into which the value has been read. If pExpr is
@@ -4586,6 +4645,17 @@ static SQLITE_NOINLINE int sqlite3IndexedExprLookup(
continue;
}
+
+ /* Functions that might set a subtype should not be replaced by the
+ ** value taken from an expression index if they are themselves an
+ ** argument to another scalar function or aggregate.
+ ** https://sqlite.org/forum/forumpost/68d284c86b082c3e */
+ if( ExprHasProperty(pExpr, EP_FuncArg)
+ && sqlite3ExprCanReturnSubtype(pParse, pExpr)
+ ){
+ continue;
+ }
+
v = pParse->pVdbe;
assert( v!=0 );
if( p->bMaybeNullRow ){
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 0e0035ce6..828878670 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -3104,7 +3104,7 @@ struct Expr {
#define EP_IsTrue 0x10000000 /* Always has boolean value of TRUE */
#define EP_IsFalse 0x20000000 /* Always has boolean value of FALSE */
#define EP_FromDDL 0x40000000 /* Originates from sqlite_schema */
- /* 0x80000000 // Available */
+#define EP_FuncArg 0x80000000 /* Is a function() argument */
/* The EP_Propagate mask is a set of properties that automatically propagate
** upwards into parent nodes.
diff --git a/src/where.c b/src/where.c
index 9aaa082cd..c2fc33824 100644
--- a/src/where.c
+++ b/src/where.c
@@ -6303,58 +6303,6 @@ static SQLITE_NOINLINE void whereCheckIfBloomFilterIsUseful(
}
/*
-** Expression Node callback for sqlite3ExprCanReturnSubtype().
-**
-** Only a function call is able to return a subtype. So if the node
-** is not a function call, return WRC_Prune immediately.
-**
-** A function call is able to return a subtype if it has the
-** SQLITE_RESULT_SUBTYPE property.
-**
-** Assume that every function is able to pass-through a subtype from
-** one of its argument (using sqlite3_result_value()). Most functions
-** are not this way, but we don't have a mechanism to distinguish those
-** that are from those that are not, so assume they all work this way.
-** That means that if one of its arguments is another function and that
-** other function is able to return a subtype, then this function is
-** able to return a subtype.
-*/
-static int exprNodeCanReturnSubtype(Walker *pWalker, Expr *pExpr){
- int n;
- FuncDef *pDef;
- sqlite3 *db;
- if( pExpr->op!=TK_FUNCTION ){
- return WRC_Prune;
- }
- assert( ExprUseXList(pExpr) );
- db = pWalker->pParse->db;
- n = pExpr->x.pList ? pExpr->x.pList->nExpr : 0;
- pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0);
- if( pDef==0 || (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){
- pWalker->eCode = 1;
- return WRC_Prune;
- }
- return WRC_Continue;
-}
-
-/*
-** Return TRUE if expression pExpr is able to return a subtype.
-**
-** A TRUE return does not guarantee that a subtype will be returned.
-** It only indicates that a subtype return is possible. False positives
-** are acceptable as they only disable an optimization. False negatives,
-** on the other hand, can lead to incorrect answers.
-*/
-static int sqlite3ExprCanReturnSubtype(Parse *pParse, Expr *pExpr){
- Walker w;
- memset(&w, 0, sizeof(w));
- w.pParse = pParse;
- w.xExprCallback = exprNodeCanReturnSubtype;
- sqlite3WalkExpr(&w, pExpr);
- return w.eCode;
-}
-
-/*
** The index pIdx is used by a query and contains one or more expressions.
** In other words pIdx is an index on an expression. iIdxCur is the cursor
** number for the index and iDataCur is the cursor number for the corresponding
@@ -6387,12 +6335,6 @@ static SQLITE_NOINLINE void whereAddIndexedExpr(
continue;
}
if( sqlite3ExprIsConstant(0,pExpr) ) continue;
- if( pExpr->op==TK_FUNCTION && sqlite3ExprCanReturnSubtype(pParse,pExpr) ){
- /* Functions that might set a subtype should not be replaced by the
- ** value taken from an expression index since the index omits the
- ** subtype. https://sqlite.org/forum/forumpost/68d284c86b082c3e */
- continue;
- }
p = sqlite3DbMallocRaw(pParse->db, sizeof(IndexedExpr));
if( p==0 ) break;
p->pIENext = pParse->pIdxEpr;