1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-08 03:22:21 +03:00

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----- -----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1 Hash: SHA1
C Additional\sintarray\stest\scases\sand\stweaks\sto\scomments. 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-10T17:55:48 D 2009-11-11T00:24:32
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in 53f3dfa49f28ab5b80cb083fb7c9051e596bcfa1 F Makefile.in 53f3dfa49f28ab5b80cb083fb7c9051e596bcfa1
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -117,10 +117,10 @@ F src/callback.c 908f3e0172c3d4058f4ca0acd42c637c52e9669f
F src/complete.c 77016e5a2766cf8b84381397152d2c99ea4b218f F src/complete.c 77016e5a2766cf8b84381397152d2c99ea4b218f
F src/date.c a79c0a8f219370b972e320741f995a3bef9df33f F src/date.c a79c0a8f219370b972e320741f995a3bef9df33f
F src/delete.c ec04635d152debdab70d4b30c5516b59282075ea F src/delete.c ec04635d152debdab70d4b30c5516b59282075ea
F src/expr.c 11c163003b79f38a5b5100228052aca57b454807 F src/expr.c be605c60ff84699f3087209f2f86a140a6a5e96c
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c 41219cba186bcf0a053e42327dfa23aaba4f834a F src/fkey.c 41219cba186bcf0a053e42327dfa23aaba4f834a
F src/func.c e536218d193b8d326aab91120bc4c6f28aa2b606 F src/func.c 5949e2633bb8ff57cc70c1904db171ba23f13537
F src/global.c 271952d199a8cc59d4ce840b3bbbfd2f30c8ba32 F src/global.c 271952d199a8cc59d4ce840b3bbbfd2f30c8ba32
F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af
F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970 F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970
@@ -167,7 +167,7 @@ F src/select.c ecd7fb2fcb8d207dd381338377b5bacce0b38a2d
F src/shell.c 360ed53f8672a16b0767bf59e947a9ba7bfe7e21 F src/shell.c 360ed53f8672a16b0767bf59e947a9ba7bfe7e21
F src/sqlite.h.in 4464e9772122f0447305d425e04d122b6f1bffec F src/sqlite.h.in 4464e9772122f0447305d425e04d122b6f1bffec
F src/sqlite3ext.h 69dfb8116af51b84a029cddb3b35062354270c89 F src/sqlite3ext.h 69dfb8116af51b84a029cddb3b35062354270c89
F src/sqliteInt.h 55d26b83d16107804693982028c8b3a075f5a836 F src/sqliteInt.h ee54fe752ba5672b7ca52bdd0e300c3902103d93
F src/sqliteLimit.h 3afab2291762b5d09ae20c18feb8e9fa935a60a6 F src/sqliteLimit.h 3afab2291762b5d09ae20c18feb8e9fa935a60a6
F src/status.c e651be6b30d397d86384c6867bc016e4913bcac7 F src/status.c e651be6b30d397d86384c6867bc016e4913bcac7
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
@@ -769,14 +769,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
P 0e7d29253f093d4125ede3cfc478e4bf09aef987 P 0c8db5d88ee41dab58d6464283b51f82f7457838
R 52665a87e5d6f5919cd61ce7e30fc2a5 R 77b5dc144a79987f5b38b3638c59cf4e
U drh U drh
Z e6118dcdbf5f85120b9d2f449d14ebe3 Z 3ce600a45d7855e5b1ce1fd4101b7aec
-----BEGIN PGP SIGNATURE----- -----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux) Version: GnuPG v1.4.6 (GNU/Linux)
iD8DBQFK+aknoxKgR168RlERAh2vAKCNrNhYRrSdILHfT2qkBmO24bu4dQCdFRxQ iD8DBQFK+gRDoxKgR168RlERAgIHAJ0c3Kp4EnYcJoKIuhzMw7RRNw4w4wCcDLfM
rpBL1GTilzggZG+f9ilj4Ms= lEOWeC7zbgysoema8RzHOEA=
=uaJx =mkIE
-----END PGP SIGNATURE----- -----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); sqlite3ErrorMsg(pParse, "unknown function: %.*s()", nId, zId);
break; 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 ){ if( pFarg ){
r1 = sqlite3GetTempRange(pParse, nFarg); r1 = sqlite3GetTempRange(pParse, nFarg);
sqlite3ExprCachePush(pParse); /* Ticket 2ea2425d34be */ 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. ** Implementation of the IFNULL(), NVL(), and COALESCE() functions.
** All three do the same thing. They return the first non-NULL ** 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. ** Implementation of random(). Return a random integer.
@@ -1437,10 +1447,12 @@ void sqlite3RegisterGlobalFunctions(void){
FUNCTION(upper, 1, 0, 0, upperFunc ), FUNCTION(upper, 1, 0, 0, upperFunc ),
FUNCTION(lower, 1, 0, 0, lowerFunc ), FUNCTION(lower, 1, 0, 0, lowerFunc ),
FUNCTION(coalesce, 1, 0, 0, 0 ), FUNCTION(coalesce, 1, 0, 0, 0 ),
FUNCTION(coalesce, -1, 0, 0, ifnullFunc ),
FUNCTION(coalesce, 0, 0, 0, 0 ), 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(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(random, 0, 0, 0, randomFunc ),
FUNCTION(randomblob, 1, 0, 0, randomBlob ), FUNCTION(randomblob, 1, 0, 0, randomBlob ),
FUNCTION(nullif, 2, 0, 1, nullifFunc ), 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_NEEDCOLL 0x08 /* sqlite3GetFuncCollSeq() might be called */
#define SQLITE_FUNC_PRIVATE 0x10 /* Allowed for internal use only */ #define SQLITE_FUNC_PRIVATE 0x10 /* Allowed for internal use only */
#define SQLITE_FUNC_COUNT 0x20 /* Built-in count(*) aggregate */ #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 ** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are