Generate VDBE code for the built-in COALESCE() and IFNULL() functions. This
allows unused arguments to never be evaluated, which is a performance win when
the unused argument is a subquery.
FossilOrigin-Name: 30055b257c3c65f8123cad5ac6c62c4c6ca2c900
diff --git a/src/expr.c b/src/expr.c
index 0cc3093..249ab90 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -2394,6 +2394,27 @@
sqlite3ErrorMsg(pParse, "unknown function: %.*s()", nId, zId);
break;
}
+
+ /* Attempt a direct implementation of the built-in COALESCE() and
+ ** IFNULL() functions. This avoids unnecessary evalation of
+ ** arguments past the first non-NULL argument.
+ */
+ if( pDef->flags & SQLITE_FUNC_COALESCE ){
+ int endCoalesce = sqlite3VdbeMakeLabel(v);
+ assert( nFarg>=2 );
+ sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target);
+ for(i=1; i<nFarg; i++){
+ sqlite3VdbeAddOp2(v, OP_NotNull, target, endCoalesce);
+ sqlite3ExprCacheRemove(pParse, target);
+ sqlite3ExprCachePush(pParse);
+ sqlite3ExprCode(pParse, pFarg->a[i].pExpr, target);
+ sqlite3ExprCachePop(pParse, 1);
+ }
+ sqlite3VdbeResolveLabel(v, endCoalesce);
+ break;
+ }
+
+
if( pFarg ){
r1 = sqlite3GetTempRange(pParse, nFarg);
sqlite3ExprCachePush(pParse); /* Ticket 2ea2425d34be */