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: |
9600a998043c6dd1d5ecb03d1ee9a927 |
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
Changes to src/select.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** 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. ** | | | 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 |