/ Check-in [6ee71f4d]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix a memory leak to do with the recent UNION ALL sub-select optimization. (CVS 5333)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 6ee71f4ddb4fa934f58c87dad2d30560af2e55d7
User & Date: danielk1977 2008-07-01 16:05:26
Context
2008-07-01
16:34
In Lemon, if a non-terminal has the same type as a terminal, then reuse the terminal type in the YYMINORTYPE union for the non-terminal. This gives better table compression. (CVS 5334) check-in: 5c9cc22c user: drh tags: trunk
16:05
Fix a memory leak to do with the recent UNION ALL sub-select optimization. (CVS 5333) check-in: 6ee71f4d user: danielk1977 tags: trunk
14:39
Fix a problem with LIMIT and OFFSET clauses on the parent query when optimizing a UNION ALL sub-select. (CVS 5332) check-in: a79786a9 user: danielk1977 tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/select.c.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains C code routines that are called by the parser
    13     13   ** to handle SELECT statements in SQLite.
    14     14   **
    15         -** $Id: select.c,v 1.442 2008/07/01 14:39:35 danielk1977 Exp $
           15  +** $Id: select.c,v 1.443 2008/07/01 16:05:26 danielk1977 Exp $
    16     16   */
    17     17   #include "sqliteInt.h"
    18     18   
    19     19   
    20     20   /*
    21     21   ** Delete all the content of a Select structure but do not deallocate
    22     22   ** the select structure itself.
................................................................................
  1914   1914     Select *pPrior;       /* Another SELECT immediately to our left */
  1915   1915     Vdbe *v;              /* Generate code to this VDBE */
  1916   1916     int nCol;             /* Number of columns in the result set */
  1917   1917     ExprList *pOrderBy;   /* The ORDER BY clause on p */
  1918   1918     int aSetP2[2];        /* Set P2 value of these op to number of columns */
  1919   1919     int nSetP2 = 0;       /* Number of slots in aSetP2[] used */
  1920   1920     SelectDest dest;      /* Alternative data destination */
         1921  +  Select *pDelete = 0;  /* Chain of simple selects to delete */
  1921   1922   
  1922   1923     /* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs.  Only
  1923   1924     ** the last (right-most) SELECT in the series may have an ORDER BY or LIMIT.
  1924   1925     */
  1925   1926     if( p==0 || p->pPrior==0 ){
  1926   1927       rc = 1;
  1927   1928       goto multi_select_end;
................................................................................
  1996   1997           p->iLimit = pPrior->iLimit;
  1997   1998           p->iOffset = pPrior->iOffset;
  1998   1999           if( p->iLimit ){
  1999   2000             addr = sqlite3VdbeAddOp1(v, OP_IfZero, p->iLimit);
  2000   2001             VdbeComment((v, "Jump ahead if LIMIT reached"));
  2001   2002           }
  2002   2003           rc = sqlite3Select(pParse, p, &dest, 0, 0, 0, aff);
         2004  +        pDelete = p->pPrior;
  2003   2005           p->pPrior = pPrior;
  2004   2006           if( rc ){
  2005   2007             goto multi_select_end;
  2006   2008           }
  2007   2009           if( addr ){
  2008   2010             sqlite3VdbeJumpHere(v, addr);
  2009   2011           }
................................................................................
  2072   2074         pOffset = p->pOffset;
  2073   2075         p->pOffset = 0;
  2074   2076         uniondest.eDest = op;
  2075   2077         rc = sqlite3Select(pParse, p, &uniondest, 0, 0, 0, aff);
  2076   2078         /* Query flattening in sqlite3Select() might refill p->pOrderBy.
  2077   2079         ** Be sure to delete p->pOrderBy, therefore, to avoid a memory leak. */
  2078   2080         sqlite3ExprListDelete(p->pOrderBy);
         2081  +      pDelete = p->pPrior;
  2079   2082         p->pPrior = pPrior;
  2080   2083         p->pOrderBy = pOrderBy;
  2081   2084         sqlite3ExprDelete(p->pLimit);
  2082   2085         p->pLimit = pLimit;
  2083   2086         p->pOffset = pOffset;
  2084   2087         p->iLimit = 0;
  2085   2088         p->iOffset = 0;
................................................................................
  2155   2158         p->pPrior = 0;
  2156   2159         pLimit = p->pLimit;
  2157   2160         p->pLimit = 0;
  2158   2161         pOffset = p->pOffset;
  2159   2162         p->pOffset = 0;
  2160   2163         intersectdest.iParm = tab2;
  2161   2164         rc = sqlite3Select(pParse, p, &intersectdest, 0, 0, 0, aff);
         2165  +      pDelete = p->pPrior;
  2162   2166         p->pPrior = pPrior;
  2163   2167         sqlite3ExprDelete(p->pLimit);
  2164   2168         p->pLimit = pLimit;
  2165   2169         p->pOffset = pOffset;
  2166   2170         if( rc ){
  2167   2171           goto multi_select_end;
  2168   2172         }
................................................................................
  2300   2304   
  2301   2305       sqlite3_free(pKeyInfo);
  2302   2306     }
  2303   2307   
  2304   2308   multi_select_end:
  2305   2309     pDest->iMem = dest.iMem;
  2306   2310     pDest->nMem = dest.nMem;
         2311  +  sqlite3SelectDelete(pDelete);
  2307   2312     return rc;
  2308   2313   }
  2309   2314   #endif /* SQLITE_OMIT_COMPOUND_SELECT */
  2310   2315   
  2311   2316   /*
  2312   2317   ** Code an output subroutine for a coroutine implementation of a
  2313   2318   ** SELECT statment.

Changes to test/selectB.test.

     6      6   #    May you do good and not evil.
     7      7   #    May you find forgiveness for yourself and forgive others.
     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library. 
    12     12   #
    13         -# $Id: selectB.test,v 1.2 2008/07/01 14:39:35 danielk1977 Exp $
           13  +# $Id: selectB.test,v 1.3 2008/07/01 16:05:26 danielk1977 Exp $
    14     14   
    15     15   set testdir [file dirname $argv0]
    16     16   source $testdir/tester.tcl
    17     17   
    18     18   proc test_transform {testname sql1 sql2 results} {
    19     19     set ::vdbe1 [list]
    20     20     set ::vdbe2 [list]
................................................................................
    47     47   
    48     48       INSERT INTO t2 VALUES(3,   6,  9);
    49     49       INSERT INTO t2 VALUES(12, 15, 18);
    50     50       INSERT INTO t2 VALUES(21, 24, 27);
    51     51     }
    52     52   } {}
    53     53   
    54         -test_transform selectB-1.2 {
    55         -  SELECT * FROM (SELECT a FROM t1 UNION ALL SELECT d FROM t2)
    56         -} {
    57         -  SELECT a FROM t1 UNION ALL SELECT d FROM t2
    58         -} {2 8 14 3 12 21}
           54  +for {set ii 1} {$ii <= 2} {incr ii} {
           55  +
           56  +  if {$ii == 2} {
           57  +    do_test selectB-2.1 {
           58  +      execsql {
           59  +        CREATE INDEX i1 ON t1(a);
           60  +        CREATE INDEX i2 ON t2(d);
           61  +      }
           62  +    } {}
           63  +  }
           64  +
           65  +  test_transform selectB-$ii.2 {
           66  +    SELECT * FROM (SELECT a FROM t1 UNION ALL SELECT d FROM t2)
           67  +  } {
           68  +    SELECT a FROM t1 UNION ALL SELECT d FROM t2
           69  +  } {2 8 14 3 12 21}
           70  +  
           71  +  test_transform selectB-$ii.3 {
           72  +    SELECT * FROM (SELECT a FROM t1 UNION ALL SELECT d FROM t2) ORDER BY 1
           73  +  } {
           74  +    SELECT a FROM t1 UNION ALL SELECT d FROM t2 ORDER BY 1
           75  +  } {2 3 8 12 14 21}
           76  +  
           77  +  test_transform selectB-$ii.4 {
           78  +    SELECT * FROM 
           79  +      (SELECT a FROM t1 UNION ALL SELECT d FROM t2) 
           80  +    WHERE a>10 ORDER BY 1
           81  +  } {
           82  +    SELECT a FROM t1 WHERE a>10 UNION ALL SELECT d FROM t2 WHERE d>10 ORDER BY 1
           83  +  } {12 14 21}
           84  +  
           85  +  test_transform selectB-$ii.5 {
           86  +    SELECT * FROM 
           87  +      (SELECT a FROM t1 UNION ALL SELECT d FROM t2) 
           88  +    WHERE a>10 ORDER BY a
           89  +  } {
           90  +    SELECT a FROM t1 WHERE a>10 
           91  +      UNION ALL 
           92  +    SELECT d FROM t2 WHERE d>10 
           93  +    ORDER BY a
           94  +  } {12 14 21}
           95  +  
           96  +  test_transform selectB-$ii.6 {
           97  +    SELECT * FROM 
           98  +      (SELECT a FROM t1 UNION ALL SELECT d FROM t2 WHERE d > 12) 
           99  +    WHERE a>10 ORDER BY a
          100  +  } {
          101  +    SELECT a FROM t1 WHERE a>10
          102  +      UNION ALL 
          103  +    SELECT d FROM t2 WHERE d>12 AND d>10
          104  +    ORDER BY a
          105  +  } {14 21}
          106  +  
          107  +  test_transform selectB-$ii.7 {
          108  +    SELECT * FROM (SELECT a FROM t1 UNION ALL SELECT d FROM t2) ORDER BY 1 
          109  +    LIMIT 2
          110  +  } {
          111  +    SELECT a FROM t1 UNION ALL SELECT d FROM t2 ORDER BY 1 LIMIT 2
          112  +  } {2 3}
          113  +  
          114  +  test_transform selectB-$ii.8 {
          115  +    SELECT * FROM (SELECT a FROM t1 UNION ALL SELECT d FROM t2) ORDER BY 1 
          116  +    LIMIT 2 OFFSET 3
          117  +  } {
          118  +    SELECT a FROM t1 UNION ALL SELECT d FROM t2 ORDER BY 1 LIMIT 2 OFFSET 3
          119  +  } {12 14}
          120  +  
          121  +  test_transform selectB-$ii.9 {
          122  +    SELECT * FROM (
          123  +      SELECT a FROM t1 UNION ALL SELECT d FROM t2 UNION ALL SELECT c FROM t1
          124  +    ) 
          125  +  } {
          126  +    SELECT a FROM t1 UNION ALL SELECT d FROM t2 UNION ALL SELECT c FROM t1
          127  +  } {2 8 14 3 12 21 6 12 18}
          128  +  
          129  +  test_transform selectB-$ii.10 {
          130  +    SELECT * FROM (
          131  +      SELECT a FROM t1 UNION ALL SELECT d FROM t2 UNION ALL SELECT c FROM t1
          132  +    ) ORDER BY 1
          133  +  } {
          134  +    SELECT a FROM t1 UNION ALL SELECT d FROM t2 UNION ALL SELECT c FROM t1
          135  +    ORDER BY 1
          136  +  } {2 3 6 8 12 12 14 18 21}
          137  +  
          138  +  test_transform selectB-$ii.11 {
          139  +    SELECT * FROM (
          140  +      SELECT a FROM t1 UNION ALL SELECT d FROM t2 UNION ALL SELECT c FROM t1
          141  +    ) WHERE a>=10 ORDER BY 1 LIMIT 3
          142  +  } {
          143  +    SELECT a FROM t1 WHERE a>=10 UNION ALL SELECT d FROM t2 WHERE d>=10
          144  +    UNION ALL SELECT c FROM t1 WHERE c>=10
          145  +    ORDER BY 1 LIMIT 3
          146  +  } {12 12 14}
          147  +
          148  +}
          149  +
    59    150   
    60         -test_transform selectB-1.3 {
    61         -  SELECT * FROM (SELECT a FROM t1 UNION ALL SELECT d FROM t2) ORDER BY 1
    62         -} {
    63         -  SELECT a FROM t1 UNION ALL SELECT d FROM t2 ORDER BY 1
    64         -} {2 3 8 12 14 21}
          151  +do_test selectB-2.1 {
          152  +  execsql {
          153  +    SELECT DISTINCT * FROM 
          154  +      (SELECT c FROM t1 UNION ALL SELECT e FROM t2) 
          155  +    ORDER BY 1;
          156  +  }
          157  +} {6 12 15 18 24}
    65    158   
    66         -test_transform selectB-1.4 {
    67         -  SELECT * FROM 
    68         -    (SELECT a FROM t1 UNION ALL SELECT d FROM t2) 
    69         -  WHERE a>10 ORDER BY 1
    70         -} {
    71         -  SELECT a FROM t1 WHERE a>10 UNION ALL SELECT d FROM t2 WHERE d>10 ORDER BY 1
    72         -} {12 14 21}
          159  +do_test selectB-2.2 {
          160  +  execsql {
          161  +    SELECT c, count(*) FROM 
          162  +      (SELECT c FROM t1 UNION ALL SELECT e FROM t2) 
          163  +    GROUP BY c ORDER BY 1;
          164  +  }
          165  +} {6 2 12 1 15 1 18 1 24 1}
          166  +do_test selectB-2.3 {
          167  +  execsql {
          168  +    SELECT c, count(*) FROM 
          169  +      (SELECT c FROM t1 UNION ALL SELECT e FROM t2) 
          170  +    GROUP BY c HAVING count(*)>1;
          171  +  }
          172  +} {6 2}
          173  +do_test selectB-2.4 {
          174  +  execsql {
          175  +    SELECT t4.c, t3.a FROM 
          176  +      (SELECT c FROM t1 UNION ALL SELECT e FROM t2) AS t4, t1 AS t3
          177  +    WHERE t3.a=14
          178  +    ORDER BY 1
          179  +  }
          180  +} {6 14 6 14 12 14 15 14 18 14 24 14}
    73    181   
    74         -test_transform selectB-1.5 {
    75         -  SELECT * FROM 
    76         -    (SELECT a FROM t1 UNION ALL SELECT d FROM t2) 
    77         -  WHERE a>10 ORDER BY a
    78         -} {
    79         -  SELECT a FROM t1 WHERE a>10 
    80         -    UNION ALL 
    81         -  SELECT d FROM t2 WHERE d>10 
    82         -  ORDER BY a
    83         -} {12 14 21}
          182  +do_test selectB-2.5 {
          183  +  execsql {
          184  +    SELECT d FROM t2 
          185  +    EXCEPT 
          186  +    SELECT a FROM (SELECT a FROM t1 UNION ALL SELECT d FROM t2)
          187  +  }
          188  +} {}
    84    189   
    85         -test_transform selectB-1.6 {
    86         -  SELECT * FROM 
    87         -    (SELECT a FROM t1 UNION ALL SELECT d FROM t2 WHERE d > 12) 
    88         -  WHERE a>10 ORDER BY a
    89         -} {
    90         -  SELECT a FROM t1 WHERE a>10
    91         -    UNION ALL 
    92         -  SELECT d FROM t2 WHERE d>12 AND d>10
    93         -  ORDER BY a
    94         -} {14 21}
    95         -
    96         -test_transform selectB-1.7 {
    97         -  SELECT * FROM (SELECT a FROM t1 UNION ALL SELECT d FROM t2) ORDER BY 1 LIMIT 2
    98         -} {
    99         -  SELECT a FROM t1 UNION ALL SELECT d FROM t2 ORDER BY 1 LIMIT 2
   100         -} {2 3}
   101         -
   102         -test_transform selectB-1.8 {
   103         -  SELECT * FROM (SELECT a FROM t1 UNION ALL SELECT d FROM t2) ORDER BY 1 
   104         -  LIMIT 2 OFFSET 3
   105         -} {
   106         -  SELECT a FROM t1 UNION ALL SELECT d FROM t2 ORDER BY 1 LIMIT 2 OFFSET 3
   107         -} {12 14}
   108         -
          190  +do_test selectB-2.6 {
          191  +  execsql {
          192  +    SELECT * FROM (SELECT a FROM t1 UNION ALL SELECT d FROM t2)
          193  +    EXCEPT 
          194  +    SELECT * FROM (SELECT a FROM t1 UNION ALL SELECT d FROM t2)
          195  +  }
          196  +} {}
   109    197   
   110    198   finish_test
   111    199