]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Materialize subqueries using a subroutine and invoke that subroutine
authordrh <drh@noemail.net>
Thu, 15 Sep 2011 23:58:14 +0000 (23:58 +0000)
committerdrh <drh@noemail.net>
Thu, 15 Sep 2011 23:58:14 +0000 (23:58 +0000)
prior to each use of the subqueries manifestation.  Fix for
ticket [002caede898aee4]

FossilOrigin-Name: 4b8357ee3c4ccdbd34e0cd077efd84cca677f496

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

index ef2b75267cc07597f65811db09f6a06bb44fa84c..f94f12be4dba5aa8cc1df8760e0c3ad98b0ec361 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Adding\stest\scase\sfor\sticket\s[002caede898]
-D 2011-09-15T19:39:42.113
+C Materialize\ssubqueries\susing\sa\ssubroutine\sand\sinvoke\sthat\ssubroutine\nprior\sto\seach\suse\sof\sthe\ssubqueries\smanifestation.\s\sFix\sfor\nticket\s[002caede898aee4]
+D 2011-09-15T23:58:14.314
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in d314143fa6be24828021d3f583ad37d9afdce505
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -133,7 +133,7 @@ F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
 F src/ctime.c e3132ec65240b2e2f3d50831021eac387f27584d
 F src/date.c a3c6842bad7ae632281811de112a8ba63ff08ab3
 F src/delete.c ff68e5ef23aee08c0ff528f699a19397ed8bbed8
-F src/expr.c cbcd8c2f1588a9862291a081699854c5e1cb28ab
+F src/expr.c 109de1d4a58d25c062a79d7e84bdbb77b348844e
 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
 F src/fkey.c 9f00ea98f6b360d477b5a78b5b59a1fbde82431c
 F src/func.c 59bb046d7e3df1ab512ac339ccb0a6f996a17cb7
@@ -179,11 +179,11 @@ F src/printf.c 585a36b6a963df832cfb69505afa3a34ed5ef8a1
 F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
 F src/resolve.c 36368f44569208fa074e61f4dd0b6c4fb60ca2b4
 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
-F src/select.c bf7b7ea6befb483619da5f597b0864668b828c3c
+F src/select.c d85d83c334a3842b47d14e0574acb5f531d5579a
 F src/shell.c bbe7818ff5bc8614105ceb81ad67b8bdc0b671dd
 F src/sqlite.h.in 0a6c9c23337fd1352c5c75a613ff9533aa7d91cb
 F src/sqlite3ext.h 1a1a4f784aa9c3b00edd287940197de52487cd93
-F src/sqliteInt.h c7e37ee49b1a922ddcd18fa98dd750efa4d2db14
+F src/sqliteInt.h feb4f2b212fe36bbd951e44d2490c6aacf02f689
 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
 F src/status.c 7ac64842c86cec2fc1a1d0e5c16d3beb8ad332bf
 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
@@ -961,10 +961,7 @@ F tool/symbols.sh caaf6ccc7300fd43353318b44524853e222557d5
 F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
 F tool/warnings.sh b7fdb2cc525f5ef4fa43c80e771636dd3690f9d2
-P 3fc566ac5dfce314ee414a3fb79daeeed6d0f179
-R 3df652f1b6c038f8caa8cb1ea6bf4532
-T *branch * tkt-002caede898
-T *sym-tkt-002caede898 *
-T -sym-trunk *
+P 62dfc51a495be017605cf315d72e2db91bfa28f7
+R 6d5602e8586fba23bb68456f6fac9e14
 U drh
-Z 9197dd7d4afe8679532f19b1e34148bf
+Z 035be646ae967eef8d7d2956eeb67c86
index 993429f0851400b76ad45062d0ba2bc9aee58bf4..adf0713f445085d6154ee310ec8fb1168541e0d9 100644 (file)
@@ -1 +1 @@
-62dfc51a495be017605cf315d72e2db91bfa28f7
\ No newline at end of file
+4b8357ee3c4ccdbd34e0cd077efd84cca677f496
\ No newline at end of file
index ab218078dbacd6e72bf28bb0bbbc479133092d0f..7bfcf5733a0ba0c00ee99929d215a451dd7e1114 100644 (file)
@@ -901,7 +901,8 @@ SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){
     pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
     pNewItem->jointype = pOldItem->jointype;
     pNewItem->iCursor = pOldItem->iCursor;
-    pNewItem->isPopulated = pOldItem->isPopulated;
+    pNewItem->addrFillSub = pOldItem->addrFillSub;
+    pNewItem->regReturn = pOldItem->regReturn;
     pNewItem->isCorrelated = pOldItem->isCorrelated;
     pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex);
     pNewItem->notIndexed = pOldItem->notIndexed;
index a8ea08a781a06f537b30d16cd0780024e920499e..2ddc751b58366ec903d7b69f70f00530218b720d 100644 (file)
@@ -3801,7 +3801,11 @@ int sqlite3Select(
     Select *pSub = pItem->pSelect;
     int isAggSub;
 
-    if( pSub==0 || pItem->isPopulated ) continue;
+    if( pSub==0 ) continue;
+    if( pItem->addrFillSub ){
+      sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub);
+      continue;
+    }
 
     /* Increment Parse.nHeight by the height of the largest expression
     ** tree refered to by this, the parent select. The child select
@@ -3812,21 +3816,41 @@ int sqlite3Select(
     */
     pParse->nHeight += sqlite3SelectExprHeight(p);
 
-    /* Check to see if the subquery can be absorbed into the parent. */
     isAggSub = (pSub->selFlags & SF_Aggregate)!=0;
     if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){
+      /* This subquery can be absorbed into its parent. */
       if( isAggSub ){
         isAgg = 1;
         p->selFlags |= SF_Aggregate;
       }
       i = -1;
     }else{
+      /* Generate a subroutine that will fill an ephemeral table with
+      ** the content of this subquery.  pItem->addrFillSub will point
+      ** to the address of the generated subroutine.  pItem->regReturn
+      ** is a register allocated to hold the subroutine return address
+      */
+      int topAddr = sqlite3VdbeAddOp0(v, OP_Goto);
+      int regOnce = 0;
+      assert( pItem->addrFillSub==0 );
+      pItem->addrFillSub = topAddr+1;
+      pItem->regReturn = ++pParse->nMem;
+      if( pItem->isCorrelated==0 && pParse->pTriggerTab==0 ){
+        /* If the subquery is no correlated and if we are not inside of
+        ** a trigger, then we only need to compute the value of the subquery
+        ** once. */
+        regOnce = ++pParse->nMem;
+        sqlite3VdbeAddOp1(v, OP_If, regOnce);
+        sqlite3VdbeAddOp2(v, OP_Integer, 1, regOnce);
+      }
       sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
-      assert( pItem->isPopulated==0 );
       explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
       sqlite3Select(pParse, pSub, &dest);
-      pItem->isPopulated = 1;
       pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow;
+      if( regOnce ) sqlite3VdbeJumpHere(v, topAddr+1);
+      sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
+      sqlite3VdbeJumpHere(v, topAddr);
+      sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, topAddr+1);
     }
     if( /*pParse->nErr ||*/ db->mallocFailed ){
       goto select_end;
index f27fea2b3a6cf4af7d3b87d8f741b3f8a445215c..65b0aa1fc6326e15e342602bd1a299f9648be86b 100644 (file)
@@ -1852,7 +1852,8 @@ struct SrcList {
     char *zAlias;     /* The "B" part of a "A AS B" phrase.  zName is the "A" */
     Table *pTab;      /* An SQL table corresponding to zName */
     Select *pSelect;  /* A SELECT statement used in place of a table name */
-    u8 isPopulated;   /* Temporary table associated with SELECT is populated */
+    int addrFillSub;  /* Address of subroutine to manifest a subquery */
+    int regReturn;    /* Register holding return address of addrFillSub */
     u8 jointype;      /* Type of join between this able and the previous */
     u8 notIndexed;    /* True if there is a NOT INDEXED clause */
     u8 isCorrelated;  /* True if sub-query is correlated */