/ Check-in [d04d7033]
Login

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

Overview
Comment:Defer deleting Table objects associated with flattened subqueries until all code has been generated, in case some expression node still references the Table object. Ticket #3346. (CVS 5650)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:d04d70336727a0db959c672e6c22cdaa0505dce5
User & Date: drh 2008-09-01 15:52:11
Context
2008-09-01
17:23
Remove an unused function declaration from a header file. Ticket #3349. (CVS 5651) check-in: 7a577428 user: drh tags: trunk
15:52
Defer deleting Table objects associated with flattened subqueries until all code has been generated, in case some expression node still references the Table object. Ticket #3346. (CVS 5650) check-in: d04d7033 user: drh tags: trunk
12:47
Have the rtree module set the estimatedCost output variable. Ticket #3312. (CVS 5649) check-in: 483932c4 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.471 2008/08/26 12:56:14 drh Exp $
           15  +** $Id: select.c,v 1.472 2008/09/01 15:52:11 drh 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.
................................................................................
  2423   2423   }
  2424   2424   static void substSelect(
  2425   2425     sqlite3 *db,         /* Report malloc errors here */
  2426   2426     Select *p,           /* SELECT statement in which to make substitutions */
  2427   2427     int iTable,          /* Table to be replaced */
  2428   2428     ExprList *pEList     /* Substitute values */
  2429   2429   ){
         2430  +  SrcList *pSrc;
         2431  +  struct SrcList_item *pItem;
         2432  +  int i;
  2430   2433     if( !p ) return;
  2431   2434     substExprList(db, p->pEList, iTable, pEList);
  2432   2435     substExprList(db, p->pGroupBy, iTable, pEList);
  2433   2436     substExprList(db, p->pOrderBy, iTable, pEList);
  2434   2437     substExpr(db, p->pHaving, iTable, pEList);
  2435   2438     substExpr(db, p->pWhere, iTable, pEList);
  2436   2439     substSelect(db, p->pPrior, iTable, pEList);
         2440  +  pSrc = p->pSrc;
         2441  +  if( pSrc ){
         2442  +    for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
         2443  +      substSelect(db, pItem->pSelect, iTable, pEList);
         2444  +    }
         2445  +  }
  2437   2446   }
  2438   2447   #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
  2439   2448   
  2440   2449   #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
  2441   2450   /*
  2442   2451   ** This routine attempts to flatten subqueries in order to speed
  2443   2452   ** execution.  It returns 1 if it makes changes and 0 if no flattening
................................................................................
  2714   2723       ** the cursor number for the original outer query FROM element in
  2715   2724       ** iParent.  The iParent cursor will never be used.  Subsequent code
  2716   2725       ** will scan expressions looking for iParent references and replace
  2717   2726       ** those references with expressions that resolve to the subquery FROM
  2718   2727       ** elements we are now copying in.
  2719   2728       */
  2720   2729       if( pSrc ){
         2730  +      Table *pTabToDel;
  2721   2731         pSubitem = &pSrc->a[iFrom];
  2722   2732         nSubSrc = pSubSrc->nSrc;
  2723   2733         jointype = pSubitem->jointype;
  2724         -      sqlite3DeleteTable(pSubitem->pTab);
  2725   2734         sqlite3DbFree(db, pSubitem->zDatabase);
  2726   2735         sqlite3DbFree(db, pSubitem->zName);
  2727   2736         sqlite3DbFree(db, pSubitem->zAlias);
  2728         -      pSubitem->pTab = 0;
  2729   2737         pSubitem->zDatabase = 0;
  2730   2738         pSubitem->zName = 0;
  2731   2739         pSubitem->zAlias = 0;
         2740  +
         2741  +      /* If the FROM element is a subquery, defer deleting the Table
         2742  +      ** object associated with that subquery until code generation is
         2743  +      ** complete, since there may still exist Expr.pTab entires that
         2744  +      ** refer to the subquery even after flattening.  Ticket #3346.
         2745  +      */
         2746  +      if( (pTabToDel = pSubitem->pTab)!=0 ){
         2747  +        if( pTabToDel->nRef==1 ){
         2748  +          pTabToDel->pNextZombie = pParse->pZombieTab;
         2749  +          pParse->pZombieTab = pTabToDel;
         2750  +        }else{
         2751  +          pTabToDel->nRef--;
         2752  +        }
         2753  +      }
         2754  +      pSubitem->pTab = 0;
  2732   2755       }
  2733   2756       if( nSubSrc!=1 || !pSrc ){
  2734   2757         int extra = nSubSrc - 1;
  2735   2758         for(i=(pSrc?1:0); i<nSubSrc; i++){
  2736   2759           pSrc = sqlite3SrcListAppend(db, pSrc, 0, 0);
  2737   2760           if( pSrc==0 ){
  2738   2761             pParent->pSrc = 0;

Changes to src/sqliteInt.h.

     7      7   **    May you do good and not evil.
     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   ** Internal interface definitions for SQLite.
    13     13   **
    14         -** @(#) $Id: sqliteInt.h,v 1.764 2008/08/29 18:42:30 rse Exp $
           14  +** @(#) $Id: sqliteInt.h,v 1.765 2008/09/01 15:52:11 drh Exp $
    15     15   */
    16     16   #ifndef _SQLITEINT_H_
    17     17   #define _SQLITEINT_H_
    18     18   
    19     19   /*
    20     20   ** Include the configuration header output by 'configure' if we're using the
    21     21   ** autoconf-based build
................................................................................
   979    979   #ifndef SQLITE_OMIT_VIRTUALTABLE
   980    980     Module *pMod;        /* Pointer to the implementation of the module */
   981    981     sqlite3_vtab *pVtab; /* Pointer to the module instance */
   982    982     int nModuleArg;      /* Number of arguments to the module */
   983    983     char **azModuleArg;  /* Text of all module args. [0] is module name */
   984    984   #endif
   985    985     Schema *pSchema;     /* Schema that contains this table */
          986  +  Table *pNextZombie;  /* Next on the Parse.pZombieTab list */
   986    987   };
   987    988   
   988    989   /*
   989    990   ** Allowed values for Tabe.tabFlags.
   990    991   */
   991    992   #define TF_Readonly        0x01    /* Read-only system table */
   992    993   #define TF_Ephemeral       0x02    /* An emphermal table */
................................................................................
  1697   1698   #ifndef SQLITE_OMIT_VIRTUALTABLE
  1698   1699     Token sArg;                /* Complete text of a module argument */
  1699   1700     u8 declareVtab;            /* True if inside sqlite3_declare_vtab() */
  1700   1701     int nVtabLock;             /* Number of virtual tables to lock */
  1701   1702     Table **apVtabLock;        /* Pointer to virtual tables needing locking */
  1702   1703   #endif
  1703   1704     int nHeight;            /* Expression tree height of current sub-select */
         1705  +  Table *pZombieTab;      /* List of Table objects to delete after code gen */
  1704   1706   };
  1705   1707   
  1706   1708   #ifdef SQLITE_OMIT_VIRTUALTABLE
  1707   1709     #define IN_DECLARE_VTAB 0
  1708   1710   #else
  1709   1711     #define IN_DECLARE_VTAB (pParse->declareVtab)
  1710   1712   #endif

Changes to src/tokenize.c.

    11     11   *************************************************************************
    12     12   ** An tokenizer for SQL
    13     13   **
    14     14   ** This file contains C code that splits an SQL input string up into
    15     15   ** individual tokens and sends those tokens one-by-one over to the
    16     16   ** parser for analysis.
    17     17   **
    18         -** $Id: tokenize.c,v 1.151 2008/08/29 02:14:03 drh Exp $
           18  +** $Id: tokenize.c,v 1.152 2008/09/01 15:52:11 drh Exp $
    19     19   */
    20     20   #include "sqliteInt.h"
    21     21   #include <ctype.h>
    22     22   #include <stdlib.h>
    23     23   
    24     24   /*
    25     25   ** The charMap() macro maps alphabetic characters into their
................................................................................
   500    500       */
   501    501       sqlite3DeleteTable(pParse->pNewTable);
   502    502     }
   503    503   
   504    504     sqlite3DeleteTrigger(db, pParse->pNewTrigger);
   505    505     sqlite3DbFree(db, pParse->apVarExpr);
   506    506     sqlite3DbFree(db, pParse->aAlias);
          507  +  while( pParse->pZombieTab ){
          508  +    Table *p = pParse->pZombieTab;
          509  +    pParse->pZombieTab = p->pNextZombie;
          510  +    sqlite3DeleteTable(p);
          511  +  }
   507    512     if( nErr>0 && (pParse->rc==SQLITE_OK || pParse->rc==SQLITE_DONE) ){
   508    513       pParse->rc = SQLITE_ERROR;
   509    514     }
   510    515     return nErr;
   511    516   }

Changes to test/capi2.test.

     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.  The
    12     12   # focus of this script testing the callback-free C/C++ API.
    13     13   #
    14         -# $Id: capi2.test,v 1.35 2008/01/16 17:46:38 drh Exp $
           14  +# $Id: capi2.test,v 1.36 2008/09/01 15:52:11 drh Exp $
    15     15   #
    16     16   
    17     17   set testdir [file dirname $argv0]
    18     18   source $testdir/tester.tcl
    19     19   
    20     20   # Return the text values from the current row pointed at by STMT as a list.
    21     21   proc get_row_values {STMT} {
................................................................................
   718    718     do_test capi2-12.3 {
   719    719       check_origins {SELECT col2 AS hello, col1 AS world FROM view1}
   720    720     } [list {main tab1 col2} {main tab1 col1}]
   721    721     do_test capi2-12.4 {
   722    722       check_origins {SELECT b, a FROM (SELECT col1 AS a, col2 AS b FROM view1)}
   723    723     } [list {main tab1 col2} {main tab1 col1}]
   724    724     do_test capi2-12.5 {
          725  +breakpoint
   725    726       check_origins {SELECT (SELECT col2 FROM view1), (SELECT col1 FROM view1)}
   726    727     } [list {main tab1 col2} {main tab1 col1}]
   727    728     do_test capi2-12.6 {
   728    729       check_origins {SELECT (SELECT col2), (SELECT col1) FROM view1}
   729    730     } [list {main tab1 col2} {main tab1 col1}]
   730    731     do_test capi2-12.7 {
   731    732       check_origins {SELECT * FROM view1}

Added test/tkt3346.test.

            1  +# 2008 September 1
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +#
           12  +# This file implements regression tests for SQLite library.  The
           13  +# focus of this file is testing the fix for ticket #3346
           14  +#
           15  +# $Id: tkt3346.test,v 1.1 2008/09/01 15:52:11 drh Exp $
           16  +
           17  +set testdir [file dirname $argv0]
           18  +source $testdir/tester.tcl
           19  +
           20  +do_test tkt3346-1.1 {
           21  +  db eval {
           22  +   CREATE TABLE t1(a,b);
           23  +   INSERT INTO t1 VALUES(2,'bob');
           24  +   INSERT INTO t1 VALUES(1,'alice');
           25  +   INSERT INTO t1 VALUES(3,'claire');
           26  +   SELECT *, ( SELECT y FROM (SELECT x.b='alice' AS y) )
           27  +     FROM ( SELECT * FROM t1 ) AS x;
           28  +  }
           29  +} {2 bob 0 1 alice 1 3 claire 0}
           30  +
           31  +finish_test

Changes to test/where.test.

     1         -# 4 2001 September 15
            1  +# 2001 September 15
     2      2   #
     3      3   # The author disclaims copyright to this source code.  In place of
     4      4   # a legal notice, here is a blessing:
     5      5   #
     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.  The
    12     12   # focus of this file is testing the use of indices in WHERE clases.
    13     13   #
    14         -# $Id: where.test,v 1.46 2008/07/15 00:27:35 drh Exp $
           14  +# $Id: where.test,v 1.47 2008/09/01 15:52:11 drh Exp $
    15     15   
    16     16   set testdir [file dirname $argv0]
    17     17   source $testdir/tester.tcl
    18     18   
    19     19   # Build some test data
    20     20   #
    21     21   do_test where-1.0 {