Implement FROM-clause subqueries as co-routines whenever they are guaranteed

to be the outer-most loop of the join.

FossilOrigin-Name: c7bae50bdccb5bcf3bc22e8ac5bb6725ef13db39
This commit is contained in:
drh 2016-03-15 17:52:12 +00:00
parent 82f525406a
commit 0ff47e9e1b
4 changed files with 61 additions and 12 deletions

View File

@ -1,5 +1,5 @@
C More\stest-case\schanges\sso\sthat\severything\sworks\swhen\sthe\sreserved_bytes\nvalue\sin\sthe\sheader\sis\snon-zero.
D 2016-03-15T12:37:08.820
C Implement\sFROM-clause\ssubqueries\sas\sco-routines\swhenever\sthey\sare\sguaranteed\nto\sbe\sthe\souter-most\sloop\sof\sthe\sjoin.
D 2016-03-15T17:52:12.224
F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc df0bf9ff7f8b3f4dd9fb4cc43f92fe58f6ec5c66
@ -350,7 +350,7 @@ F src/printf.c 63e6fb12bbe702dd664dc3703776c090383a5a26
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
F src/resolve.c b8f7174e5f8c33c44ded3a25a973d0bb89228c20
F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e
F src/select.c 137b31daa84d57d67847bf621bb54f3353e2077b
F src/select.c 6dd2097bb158efe3b8d68683dcc3b4a49e907a34
F src/shell.c 5e0ab1e708dc294330ccd8230536e1801f60822e
F src/sqlite.h.in 0235586b3fb639e85998d495c90f007657fd82af
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
@ -999,7 +999,7 @@ F test/securedel2.test 2d54c28e46eb1fd6902089958b20b1b056c6f1c5
F test/select1.test be62204d2bd9a5a8a149e9974cfddce893d8f686
F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56
F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054
F test/select4.test 453631158540e5f685b81cac5b7e8bd8c6b4c5fc
F test/select4.test d926792a5e4d88fef0ddcddeb45d27ce75f7296c
F test/select5.test e758b8ef94f69b111df4cb819008856655dcd535
F test/select6.test 39eac4a5c03650b2b473c532882273283ee8b7a0
F test/select7.test 95e370c42d47c3c52377d05e9ffc01ccff7c1f61
@ -1456,7 +1456,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 051c61ebae921b70f843c55aacf046a9922cc187
R 1b522ee9926e242e3422d1eddaaf0fbf
P 2fd095b14b03a508169bba710d2e8e2addf4b8f5
R dae03fc18d1aaaa839efcf6d42490a7e
U drh
Z 3fc58440746cd83f06c07d7c16cdd74a
Z 042547ad8e59422492ad781582901ed5

View File

@ -1 +1 @@
2fd095b14b03a508169bba710d2e8e2addf4b8f5
c7bae50bdccb5bcf3bc22e8ac5bb6725ef13db39

View File

@ -4970,10 +4970,24 @@ int sqlite3Select(
}
/* Generate code to implement the subquery
**
** The subquery is implemented as a co-routine if all of these are true:
** (1) The subquery is guaranteed to be the outer loop (so that it
** does not need to be computed more than once)
** (2) The ALL keyword after SELECT is omitted. (Applications are
** allowed to say "SELECT ALL" instead of just "SELECT" to disable
** the use of co-routines.)
** (3) Co-routines are not disabled using sqlite3_test_control()
** with SQLITE_TESTCTRL_OPTIMIZATIONS.
**
** TODO: Are there other reasons beside (1) to use a co-routine
** implementation?
*/
if( pTabList->nSrc==1
&& (p->selFlags & SF_All)==0
&& OptimizationEnabled(db, SQLITE_SubqCoroutine)
if( i==0
&& (pTabList->nSrc==1
|| (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0) /* (1) */
&& (p->selFlags & SF_All)==0 /* (2) */
&& OptimizationEnabled(db, SQLITE_SubqCoroutine) /* (3) */
){
/* Implement a co-routine that will return a single row of the result
** set on each invocation.

View File

@ -12,7 +12,6 @@
# focus of this file is testing UNION, INTERSECT and EXCEPT operators
# in SELECT statements.
#
# $Id: select4.test,v 1.30 2009/04/16 00:24:24 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@ -936,4 +935,40 @@ do_execsql_test select4-15.1 {
ORDER BY 1;
} {1 33 456 2 33 789}
# Enhancement (2016-03-15): Use a co-routine for subqueries if the
# subquery is guaranteed to be the outer-most query
#
do_execsql_test select4-16.1 {
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,
PRIMARY KEY(a,b DESC)) WITHOUT ROWID;
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100)
INSERT INTO t1(a,b,c,d)
SELECT x%10, x/10, x, printf('xyz%dabc',x) FROM c;
SELECT t3.c FROM
(SELECT a,max(b) AS m FROM t1 WHERE a>=5 GROUP BY a) AS t2
JOIN t1 AS t3
WHERE t2.a=t3.a AND t2.m=t3.b
ORDER BY t3.a;
} {95 96 97 98 99}
do_execsql_test select4-16.2 {
SELECT t3.c FROM
(SELECT a,max(b) AS m FROM t1 WHERE a>=5 GROUP BY a) AS t2
CROSS JOIN t1 AS t3
WHERE t2.a=t3.a AND t2.m=t3.b
ORDER BY t3.a;
} {95 96 97 98 99}
do_execsql_test select4-16.3 {
SELECT t3.c FROM
(SELECT a,max(b) AS m FROM t1 WHERE a>=5 GROUP BY a) AS t2
LEFT JOIN t1 AS t3
WHERE t2.a=t3.a AND t2.m=t3.b
ORDER BY t3.a;
} {95 96 97 98 99}
finish_test