From: drh Date: Wed, 11 Nov 2009 00:24:31 +0000 (+0000) Subject: Generate VDBE code for the built-in COALESCE() and IFNULL() functions. This X-Git-Tag: fts3-refactor~25 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ae6bb9570b6d6ef7893a9571d0fa10b43d936f61;p=thirdparty%2Fsqlite.git 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/manifest b/manifest index b9918728e8..e21055da57 100644 --- a/manifest +++ b/manifest @@ -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----- diff --git a/manifest.uuid b/manifest.uuid index 7e84001f86..7a2f9deebc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0c8db5d88ee41dab58d6464283b51f82f7457838 \ No newline at end of file +30055b257c3c65f8123cad5ac6c62c4c6ca2c900 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 0cc3093612..249ab9037c 100644 --- a/src/expr.c +++ b/src/expr.c @@ -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; ia[i].pExpr, target); + sqlite3ExprCachePop(pParse, 1); + } + sqlite3VdbeResolveLabel(v, endCoalesce); + break; + } + + if( pFarg ){ r1 = sqlite3GetTempRange(pParse, nFarg); sqlite3ExprCachePush(pParse); /* Ticket 2ea2425d34be */ diff --git a/src/func.c b/src/func.c index 2766fa3b1b..980d04edb6 100644 --- a/src/func.c +++ b/src/func.c @@ -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 ), diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 24debbabe9..16c1d6b386 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -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