/ Check-in [a7be554f]
Login

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

Overview
Comment:Merge the compound SELECT operator fix from trunk.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | btree-opt2
Files: files | file ages | folders
SHA1: a7be554f4b8534fc237fa4c6defc38fcd4049707
User & Date: drh 2015-06-23 13:02:10
Context
2015-06-23
14:49
Improvements to the way balance_nonroot() constructs the b.apCell array of pointers to cells. check-in: ee44bb25 user: drh tags: btree-opt2
13:02
Merge the compound SELECT operator fix from trunk. check-in: a7be554f user: drh tags: btree-opt2
12:19
Test that the left and right sides of a compound SELECT operator have the same number of expressions in the expanded expression list before beginning to generate code. check-in: 4df852ce user: dan tags: trunk
02:37
Avoid computing cell sizes in balance_nonroot() until they are really needed. This gives an overall 1.7% performance gain for about 1000 extra bytes of code space. check-in: 43844537 user: drh tags: btree-opt2
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/resolve.c.

  1326   1326           if( ExprHasProperty(pItem->pExpr, EP_Agg) ){
  1327   1327             sqlite3ErrorMsg(pParse, "aggregate functions are not allowed in "
  1328   1328                 "the GROUP BY clause");
  1329   1329             return WRC_Abort;
  1330   1330           }
  1331   1331         }
  1332   1332       }
         1333  +
         1334  +    /* If this is part of a compound SELECT, check that it has the right
         1335  +    ** number of expressions in the select list. */
         1336  +    if( p->pNext && p->pEList->nExpr!=p->pNext->pEList->nExpr ){
         1337  +      sqlite3SelectWrongNumTermsError(pParse, p->pNext);
         1338  +      return WRC_Abort;
         1339  +    }
  1333   1340   
  1334   1341       /* Advance to the next term of the compound
  1335   1342       */
  1336   1343       p = p->pPrior;
  1337   1344       nCompound++;
  1338   1345     }
  1339   1346   

Changes to src/select.c.

  2089   2089     SelectDest *pDest     /* What to do with query results */
  2090   2090   );
  2091   2091   
  2092   2092   /*
  2093   2093   ** Error message for when two or more terms of a compound select have different
  2094   2094   ** size result sets.
  2095   2095   */
  2096         -static void selectWrongNumTermsError(Parse *pParse, Select *p){
         2096  +void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p){
  2097   2097     if( p->selFlags & SF_Values ){
  2098   2098       sqlite3ErrorMsg(pParse, "all VALUES must have the same number of terms");
  2099   2099     }else{
  2100   2100       sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s"
  2101   2101         " do not have the same number of result columns", selectOpName(p->op));
  2102   2102     }
  2103   2103   }
................................................................................
  2115   2115   */
  2116   2116   static int multiSelectValues(
  2117   2117     Parse *pParse,        /* Parsing context */
  2118   2118     Select *p,            /* The right-most of SELECTs to be coded */
  2119   2119     SelectDest *pDest     /* What to do with query results */
  2120   2120   ){
  2121   2121     Select *pPrior;
  2122         -  int nExpr = p->pEList->nExpr;
  2123   2122     int nRow = 1;
  2124   2123     int rc = 0;
  2125   2124     assert( p->selFlags & SF_MultiValue );
  2126   2125     do{
  2127   2126       assert( p->selFlags & SF_Values );
  2128   2127       assert( p->op==TK_ALL || (p->op==TK_SELECT && p->pPrior==0) );
  2129   2128       assert( p->pLimit==0 );
  2130   2129       assert( p->pOffset==0 );
  2131         -    if( p->pEList->nExpr!=nExpr ){
  2132         -      selectWrongNumTermsError(pParse, p);
  2133         -      return 1;
  2134         -    }
         2130  +    assert( p->pNext==0 || p->pEList->nExpr==p->pNext->pEList->nExpr );
  2135   2131       if( p->pPrior==0 ) break;
  2136   2132       assert( p->pPrior->pNext==p );
  2137   2133       p = p->pPrior;
  2138   2134       nRow++;
  2139   2135     }while(1);
  2140   2136     while( p ){
  2141   2137       pPrior = p->pPrior;
................................................................................
  2236   2232       goto multi_select_end;
  2237   2233     }
  2238   2234   
  2239   2235     /* Make sure all SELECTs in the statement have the same number of elements
  2240   2236     ** in their result sets.
  2241   2237     */
  2242   2238     assert( p->pEList && pPrior->pEList );
  2243         -  if( p->pEList->nExpr!=pPrior->pEList->nExpr ){
  2244         -    selectWrongNumTermsError(pParse, p);
  2245         -    rc = 1;
  2246         -    goto multi_select_end;
  2247         -  }
         2239  +  assert( p->pEList->nExpr==pPrior->pEList->nExpr );
  2248   2240   
  2249   2241   #ifndef SQLITE_OMIT_CTE
  2250   2242     if( p->selFlags & SF_Recursive ){
  2251   2243       generateWithRecursiveQuery(pParse, p, &dest);
  2252   2244     }else
  2253   2245   #endif
  2254   2246   

Changes to src/sqliteInt.h.

  3566   3566   void sqlite3AlterFunctions(void);
  3567   3567   void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
  3568   3568   int sqlite3GetToken(const unsigned char *, int *);
  3569   3569   void sqlite3NestedParse(Parse*, const char*, ...);
  3570   3570   void sqlite3ExpirePreparedStatements(sqlite3*);
  3571   3571   int sqlite3CodeSubselect(Parse *, Expr *, int, int);
  3572   3572   void sqlite3SelectPrep(Parse*, Select*, NameContext*);
         3573  +void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p);
  3573   3574   int sqlite3MatchSpanName(const char*, const char*, const char*, const char*);
  3574   3575   int sqlite3ResolveExprNames(NameContext*, Expr*);
  3575   3576   void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*);
  3576   3577   void sqlite3ResolveSelfReference(Parse*,Table*,int,Expr*,ExprList*);
  3577   3578   int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
  3578   3579   void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
  3579   3580   void sqlite3AlterFinishAddColumn(Parse *, Token *);

Changes to test/in.test.

   446    446   ifcapable compound {
   447    447   do_test in-12.10 {
   448    448     catchsql {
   449    449       SELECT * FROM t2 WHERE a IN (
   450    450         SELECT a FROM t3 UNION ALL SELECT a, b FROM t2
   451    451       );
   452    452     }
   453         -} {1 {only a single result allowed for a SELECT that is part of an expression}}
          453  +} {1 {SELECTs to the left and right of UNION ALL do not have the same number of result columns}}
   454    454   do_test in-12.11 {
   455    455     catchsql {
   456    456       SELECT * FROM t2 WHERE a IN (
   457    457         SELECT a FROM t3 UNION SELECT a, b FROM t2
   458    458       );
   459    459     }
   460         -} {1 {only a single result allowed for a SELECT that is part of an expression}}
          460  +} {1 {SELECTs to the left and right of UNION do not have the same number of result columns}}
   461    461   do_test in-12.12 {
   462    462     catchsql {
   463    463       SELECT * FROM t2 WHERE a IN (
   464    464         SELECT a FROM t3 EXCEPT SELECT a, b FROM t2
   465    465       );
   466    466     }
   467         -} {1 {only a single result allowed for a SELECT that is part of an expression}}
          467  +} {1 {SELECTs to the left and right of EXCEPT do not have the same number of result columns}}
   468    468   do_test in-12.13 {
   469    469     catchsql {
   470    470       SELECT * FROM t2 WHERE a IN (
   471    471         SELECT a FROM t3 INTERSECT SELECT a, b FROM t2
   472    472       );
          473  +  }
          474  +} {1 {SELECTs to the left and right of INTERSECT do not have the same number of result columns}}
          475  +do_test in-12.14 {
          476  +  catchsql {
          477  +    SELECT * FROM t2 WHERE a IN (
          478  +      SELECT a, b FROM t3 UNION ALL SELECT a, b FROM t2
          479  +    );
   473    480     }
   474    481   } {1 {only a single result allowed for a SELECT that is part of an expression}}
          482  +do_test in-12.15 {
          483  +  catchsql {
          484  +    SELECT * FROM t2 WHERE a IN (
          485  +      SELECT a, b FROM t3 UNION ALL SELECT a FROM t2
          486  +    );
          487  +  }
          488  +} {1 {SELECTs to the left and right of UNION ALL do not have the same number of result columns}}
   475    489   }; #ifcapable compound
   476    490   
   477    491   
   478    492   #------------------------------------------------------------------------
   479    493   # The following tests check that NULL is handled correctly when it 
   480    494   # appears as part of a set of values on the right-hand side of an
   481    495   # IN or NOT IN operator.

Changes to test/select7.test.

    11     11   # views.
    12     12   #
    13     13   # $Id: select7.test,v 1.11 2007/09/12 17:01:45 danielk1977 Exp $
    14     14   
    15     15   
    16     16   set testdir [file dirname $argv0]
    17     17   source $testdir/tester.tcl
           18  +set testprefix select7
    18     19   
    19     20   ifcapable compound {
    20     21   
    21     22   # A 3-way INTERSECT.  Ticket #875
    22     23   ifcapable tempdb {
    23     24     do_test select7-1.1 {
    24     25       execsql {
................................................................................
   196    197   do_test select7-7.7 {
   197    198     execsql {
   198    199       CREATE TABLE t5(a TEXT, b INT);
   199    200       INSERT INTO t5 VALUES(123, 456);
   200    201       SELECT typeof(a), a FROM t5 GROUP BY a HAVING a<b;
   201    202     }
   202    203   } {text 123}
          204  +
          205  +do_execsql_test 8.0 { 
          206  +  CREATE TABLE t01(x, y);
          207  +  CREATE TABLE t02(x, y);
          208  +}
          209  +
          210  +do_catchsql_test 8.1 {
          211  +  SELECT * FROM (
          212  +    SELECT * FROM t01 UNION SELECT x FROM t02
          213  +  ) WHERE y=1
          214  +} {1 {SELECTs to the left and right of UNION do not have the same number of result columns}}
          215  +
          216  +do_catchsql_test 8.2 {
          217  +  CREATE VIEW v0 as SELECT x, y FROM t01 UNION SELECT x FROM t02;
          218  +  EXPLAIN QUERY PLAN SELECT * FROM v0 WHERE x='0' OR y;
          219  +} {1 {SELECTs to the left and right of UNION do not have the same number of result columns}}
          220  +
   203    221   
   204    222   finish_test
          223  +
          224  +