]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Generate VDBE code for the built-in COALESCE() and IFNULL() functions. This
authordrh <drh@noemail.net>
Wed, 11 Nov 2009 00:24:31 +0000 (00:24 +0000)
committerdrh <drh@noemail.net>
Wed, 11 Nov 2009 00:24:31 +0000 (00:24 +0000)
allows unused arguments to never be evaluated, which is a performance win when
the unused argument is a subquery.

FossilOrigin-Name: 30055b257c3c65f8123cad5ac6c62c4c6ca2c900

manifest
manifest.uuid
src/expr.c
src/func.c
src/sqliteInt.h

index b9918728e84666959045c97e834212e7be279abc..e21055da579441a4265fa9466c70e2300e0cb635 100644 (file)
--- 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-----
index 7e84001f8699bac8f8b9e1f37bda6610a85687b5..7a2f9deebcab1c2e4c9c4ecde8a2c6bcb67b821d 100644 (file)
@@ -1 +1 @@
-0c8db5d88ee41dab58d6464283b51f82f7457838
\ No newline at end of file
+30055b257c3c65f8123cad5ac6c62c4c6ca2c900
\ No newline at end of file
index 0cc30936124f24bd44cb63c98942575ed6ae710c..249ab9037cd6306b28526c0d7ab8ed138d4ee998 100644 (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 */
index 2766fa3b1b8638d23d15783187684d8abc9df712..980d04edb6fd0c0d942a4b26f4eb66e39c85717f 100644 (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       ),
index 24debbabe94592541a224b7a167dead2d27faad2..16c1d6b386cea78d6c3dd95b1078481ab04705ce 100644 (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