From 0ff47e9e1b74e270648cac1ea72f9bcf4e35031d Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 15 Mar 2016 17:52:12 +0000 Subject: [PATCH] Implement FROM-clause subqueries as co-routines whenever they are guaranteed to be the outer-most loop of the join. FossilOrigin-Name: c7bae50bdccb5bcf3bc22e8ac5bb6725ef13db39 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/select.c | 20 +++++++++++++++++--- test/select4.test | 37 ++++++++++++++++++++++++++++++++++++- 4 files changed, 61 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 5b830ffdfa..61ece923e2 100644 --- a/manifest +++ b/manifest @@ -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 diff --git a/manifest.uuid b/manifest.uuid index e76d63af73..b2a61f89c1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2fd095b14b03a508169bba710d2e8e2addf4b8f5 \ No newline at end of file +c7bae50bdccb5bcf3bc22e8ac5bb6725ef13db39 \ No newline at end of file diff --git a/src/select.c b/src/select.c index c9bc389b2f..a62581efc1 100644 --- a/src/select.c +++ b/src/select.c @@ -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. diff --git a/test/select4.test b/test/select4.test index be8d0e0ab1..1f29f29073 100644 --- a/test/select4.test +++ b/test/select4.test @@ -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