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
This commit is contained in:
drh 2009-11-11 00:24:31 +00:00
parent 63b3878921
commit ae6bb9570b
5 changed files with 48 additions and 14 deletions

View File

@ -1,8 +1,8 @@
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
C Additional\sintarray\stest\scases\sand\stweaks\sto\scomments.
D 2009-11-10T17:55:48
C Generate\sVDBE\scode\sfor\sthe\sbuilt-in\sCOALESCE()\sand\sIFNULL()\sfunctions.\s\sThis\nallows\sunused\sarguments\sto\snever\sbe\sevaluated,\swhich\sis\sa\sperformance\swin\swhen\nthe\sunused\sargument\sis\sa\ssubquery.
D 2009-11-11T00:24:32
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in 53f3dfa49f28ab5b80cb083fb7c9051e596bcfa1
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@ -117,10 +117,10 @@ F src/callback.c 908f3e0172c3d4058f4ca0acd42c637c52e9669f
F src/complete.c 77016e5a2766cf8b84381397152d2c99ea4b218f
F src/date.c a79c0a8f219370b972e320741f995a3bef9df33f
F src/delete.c ec04635d152debdab70d4b30c5516b59282075ea
F src/expr.c 11c163003b79f38a5b5100228052aca57b454807
F src/expr.c be605c60ff84699f3087209f2f86a140a6a5e96c
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c 41219cba186bcf0a053e42327dfa23aaba4f834a
F src/func.c e536218d193b8d326aab91120bc4c6f28aa2b606
F src/func.c 5949e2633bb8ff57cc70c1904db171ba23f13537
F src/global.c 271952d199a8cc59d4ce840b3bbbfd2f30c8ba32
F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af
F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970
@ -167,7 +167,7 @@ F src/select.c ecd7fb2fcb8d207dd381338377b5bacce0b38a2d
F src/shell.c 360ed53f8672a16b0767bf59e947a9ba7bfe7e21
F src/sqlite.h.in 4464e9772122f0447305d425e04d122b6f1bffec
F src/sqlite3ext.h 69dfb8116af51b84a029cddb3b35062354270c89
F src/sqliteInt.h 55d26b83d16107804693982028c8b3a075f5a836
F src/sqliteInt.h ee54fe752ba5672b7ca52bdd0e300c3902103d93
F src/sqliteLimit.h 3afab2291762b5d09ae20c18feb8e9fa935a60a6
F src/status.c e651be6b30d397d86384c6867bc016e4913bcac7
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
@ -769,14 +769,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
P 0e7d29253f093d4125ede3cfc478e4bf09aef987
R 52665a87e5d6f5919cd61ce7e30fc2a5
P 0c8db5d88ee41dab58d6464283b51f82f7457838
R 77b5dc144a79987f5b38b3638c59cf4e
U drh
Z e6118dcdbf5f85120b9d2f449d14ebe3
Z 3ce600a45d7855e5b1ce1fd4101b7aec
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
iD8DBQFK+aknoxKgR168RlERAh2vAKCNrNhYRrSdILHfT2qkBmO24bu4dQCdFRxQ
rpBL1GTilzggZG+f9ilj4Ms=
=uaJx
iD8DBQFK+gRDoxKgR168RlERAgIHAJ0c3Kp4EnYcJoKIuhzMw7RRNw4w4wCcDLfM
lEOWeC7zbgysoema8RzHOEA=
=mkIE
-----END PGP SIGNATURE-----

View File

@ -1 +1 @@
0c8db5d88ee41dab58d6464283b51f82f7457838
30055b257c3c65f8123cad5ac6c62c4c6ca2c900

View File

@ -2394,6 +2394,27 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
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 */

View File

@ -335,6 +335,14 @@ static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
}
}
#if 0 /* This function is never used. */
/*
** The COALESCE() and IFNULL() functions used to be implemented as shown
** here. But now they are implemented as VDBE code so that unused arguments
** do not have to be computed. This legacy implementation is retained as
** comment.
*/
/*
** Implementation of the IFNULL(), NVL(), and COALESCE() functions.
** All three do the same thing. They return the first non-NULL
@ -353,6 +361,8 @@ static void ifnullFunc(
}
}
}
#endif /* NOT USED */
#define ifnullFunc versionFunc /* Substitute function - never called */
/*
** Implementation of random(). Return a random integer.
@ -1437,10 +1447,12 @@ void sqlite3RegisterGlobalFunctions(void){
FUNCTION(upper, 1, 0, 0, upperFunc ),
FUNCTION(lower, 1, 0, 0, lowerFunc ),
FUNCTION(coalesce, 1, 0, 0, 0 ),
FUNCTION(coalesce, -1, 0, 0, ifnullFunc ),
FUNCTION(coalesce, 0, 0, 0, 0 ),
/* FUNCTION(coalesce, -1, 0, 0, ifnullFunc ), */
{-1,SQLITE_UTF8,SQLITE_FUNC_COALESCE,0,0,ifnullFunc,0,0,"coalesce",0},
FUNCTION(hex, 1, 0, 0, hexFunc ),
FUNCTION(ifnull, 2, 0, 1, ifnullFunc ),
/* FUNCTION(ifnull, 2, 0, 0, ifnullFunc ), */
{2,SQLITE_UTF8,SQLITE_FUNC_COALESCE,0,0,ifnullFunc,0,0,"ifnull",0},
FUNCTION(random, 0, 0, 0, randomFunc ),
FUNCTION(randomblob, 1, 0, 0, randomBlob ),
FUNCTION(nullif, 2, 0, 1, nullifFunc ),

View File

@ -959,6 +959,7 @@ struct FuncDef {
#define SQLITE_FUNC_NEEDCOLL 0x08 /* sqlite3GetFuncCollSeq() might be called */
#define SQLITE_FUNC_PRIVATE 0x10 /* Allowed for internal use only */
#define SQLITE_FUNC_COUNT 0x20 /* Built-in count(*) aggregate */
#define SQLITE_FUNC_COALESCE 0x40 /* Built-in coalesce() or ifnull() function */
/*
** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are