SQLite

Check-in [9600a99804]
Login

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

Overview
Comment:Do not flatten subqueries that are part of a compound SELECT and which have both an ORDER BY and a LIMIT clause. Ticket #2339. (CVS 3932)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 9600a998043c6dd1d5ecb03d1ee9a9273910243d
User & Date: drh 2007-05-06 20:04:25.000
Context
2007-05-06
21:20
Fix missing word in the copyright.html web page. (CVS 3933) (check-in: 2d1348dda2 user: drh tags: trunk)
20:04
Do not flatten subqueries that are part of a compound SELECT and which have both an ORDER BY and a LIMIT clause. Ticket #2339. (CVS 3932) (check-in: 9600a99804 user: drh tags: trunk)
16:04
Add the start of the ICU extension. (CVS 3931) (check-in: f473e85267 user: danielk1977 tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/select.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.340 2007/05/04 13:15:56 drh Exp $
*/
#include "sqliteInt.h"


/*
** Delete all the content of a Select structure but do not deallocate
** the select structure itself.







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.341 2007/05/06 20:04:25 drh Exp $
*/
#include "sqliteInt.h"


/*
** Delete all the content of a Select structure but do not deallocate
** the select structure itself.
2123
2124
2125
2126
2127
2128
2129




2130
2131
2132
2133
2134
2135
2136
**
**  (12)  The subquery is not the right term of a LEFT OUTER JOIN or the
**        subquery has no WHERE clause.  (added by ticket #350)
**
**  (13)  The subquery and outer query do not both use LIMIT
**
**  (14)  The subquery does not use OFFSET




**
** In this routine, the "p" parameter is a pointer to the outer query.
** The subquery is p->pSrc->a[iFrom].  isAgg is true if the outer query
** uses aggregates and subqueryIsAgg is true if the subquery uses aggregates.
**
** If flattening is not attempted, this routine is a no-op and returns 0.
** If flattening is attempted this routine returns 1.







>
>
>
>







2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
**
**  (12)  The subquery is not the right term of a LEFT OUTER JOIN or the
**        subquery has no WHERE clause.  (added by ticket #350)
**
**  (13)  The subquery and outer query do not both use LIMIT
**
**  (14)  The subquery does not use OFFSET
**
**  (15)  The outer query is not part of a compound select or the
**        subquery does not have both an ORDER BY and a LIMIT clause.
**        (See ticket #2339)
**
** In this routine, the "p" parameter is a pointer to the outer query.
** The subquery is p->pSrc->a[iFrom].  isAgg is true if the outer query
** uses aggregates and subqueryIsAgg is true if the subquery uses aggregates.
**
** If flattening is not attempted, this routine is a no-op and returns 0.
** If flattening is attempted this routine returns 1.
2168
2169
2170
2171
2172
2173
2174



2175
2176
2177
2178
2179
2180
2181
  /* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants,
  ** not arbitrary expresssions, we allowed some combining of LIMIT and OFFSET
  ** because they could be computed at compile-time.  But when LIMIT and OFFSET
  ** became arbitrary expressions, we were forced to add restrictions (13)
  ** and (14). */
  if( pSub->pLimit && p->pLimit ) return 0;              /* Restriction (13) */
  if( pSub->pOffset ) return 0;                          /* Restriction (14) */



  if( pSubSrc->nSrc==0 ) return 0;                       /* Restriction (7)  */
  if( (pSub->isDistinct || pSub->pLimit) 
         && (pSrc->nSrc>1 || isAgg) ){          /* Restrictions (4)(5)(8)(9) */
     return 0;       
  }
  if( p->isDistinct && subqueryIsAgg ) return 0;         /* Restriction (6)  */
  if( (p->disallowOrderBy || p->pOrderBy) && pSub->pOrderBy ){







>
>
>







2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
  /* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants,
  ** not arbitrary expresssions, we allowed some combining of LIMIT and OFFSET
  ** because they could be computed at compile-time.  But when LIMIT and OFFSET
  ** became arbitrary expressions, we were forced to add restrictions (13)
  ** and (14). */
  if( pSub->pLimit && p->pLimit ) return 0;              /* Restriction (13) */
  if( pSub->pOffset ) return 0;                          /* Restriction (14) */
  if( p->pRightmost && pSub->pLimit && pSub->pOrderBy ){
    return 0;                                            /* Restriction (15) */
  }
  if( pSubSrc->nSrc==0 ) return 0;                       /* Restriction (7)  */
  if( (pSub->isDistinct || pSub->pLimit) 
         && (pSrc->nSrc>1 || isAgg) ){          /* Restrictions (4)(5)(8)(9) */
     return 0;       
  }
  if( p->isDistinct && subqueryIsAgg ) return 0;         /* Restriction (6)  */
  if( (p->disallowOrderBy || p->pOrderBy) && pSub->pOrderBy ){
Added test/tkt2339.test.






























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# 2007 May 6
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# $Id: tkt2339.test,v 1.1 2007/05/06 20:04:25 drh Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_test tkt2339.1 {
  execsql {
    create table t1(num int);
    insert into t1 values (1);
    insert into t1 values (2);
    insert into t1 values (3);
    insert into t1 values (4);
    
    create table t2(num int);
    insert into t2 values (11);
    insert into t2 values (12);
    insert into t2 values (13);
    insert into t2 values (14);
    
    SELECT * FROM (SELECT * FROM t1 ORDER BY num DESC LIMIT 2)
    UNION
    SELECT * FROM (SELECT * FROM t2 ORDER BY num DESC LIMIT 2)
  }
} {3 4 13 14}
do_test tkt2339.2 {
  execsql {
    SELECT * FROM (SELECT * FROM t1 ORDER BY num DESC LIMIT 2)
    UNION ALL
    SELECT * FROM (SELECT * FROM t2 ORDER BY num DESC LIMIT 2)
  }
} {4 3 14 13}
do_test tkt2339.3 {
  execsql {
    SELECT * FROM (SELECT * FROM t1 ORDER BY num DESC)
    UNION ALL
    SELECT * FROM (SELECT * FROM t2 ORDER BY num DESC LIMIT 2)
  }
} {4 3 2 1 14 13}
do_test tkt2339.4 {
  execsql {
    SELECT * FROM (SELECT * FROM t1 ORDER BY num DESC LIMIT 2)
    UNION ALL
    SELECT * FROM (SELECT * FROM t2 ORDER BY num DESC)
  }
} {4 3 14 13 12 11}
do_test tkt2339.5 {
  execsql {
    SELECT * FROM (SELECT * FROM t1 ORDER BY num DESC LIMIT 2)
    UNION
    SELECT * FROM (SELECT * FROM t2 ORDER BY num DESC)
  }
} {3 4 11 12 13 14}
do_test tkt2339.6 {
  execsql {
    SELECT * FROM (SELECT * FROM t1 ORDER BY num DESC LIMIT 2)
    EXCEPT
    SELECT * FROM (SELECT * FROM t2 ORDER BY num DESC)
  }
} {3 4}
do_test tkt2339.7 {
  execsql {
    SELECT * FROM (SELECT * FROM t1 LIMIT 2)
    UNION
    SELECT * FROM (SELECT * FROM t2 ORDER BY num DESC LIMIT 2)
  }
} {1 2 13 14}
do_test tkt2339.8 {
  execsql {
    SELECT * FROM (SELECT * FROM t1 LIMIT 2)
    UNION
    SELECT * FROM (SELECT * FROM t2 LIMIT 2)
  }
} {1 2 11 12}
do_test tkt2339.9 {
  execsql {
    SELECT * FROM (SELECT * FROM t1 ORDER BY num DESC LIMIT 2)
    UNION
    SELECT * FROM (SELECT * FROM t2 LIMIT 2)
  }
} {3 4 11 12}


finish_test