-C Minor\senhancement\sto\smutex\stracing\son\sWin32.
-D 2017-02-15T18:30:57.375
+C Query\splanner\soptimization\sto\sdetect\sempty\stables\sin\sa\sjoin\searly\sand\sbail\sout\nwithout\sdoing\sexcess\swork.
+D 2017-02-15T22:36:15.061
F Makefile.in edb6bcdd37748d2b1c3422ff727c748df7ffe918
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc 067a6766f800cc8d72845ab61f8de4ffe8f3fc99
F src/walker.c 91a6df7435827e41cff6bb7df50ea00934ee78b0
F src/where.c 6397fab50fdbf9bde76c574ce07b3b776eb28b34
F src/whereInt.h 2bcc3d176e6091cb8f50a30b65c006e88a73614d
-F src/wherecode.c 99a8ced164c75edf41b3a865a75381c9adb38b28
+F src/wherecode.c 677e95413c472c0b413023b6b69a47f40fce1b04
F src/whereexpr.c 130cdd1a43af71b19755270fb1224874cf55158c
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
F test/e_walauto.test 248af31e73c98df23476a22bdb815524c9dc3ba8
F test/e_walckpt.test 28c371a6bb5e5fe7f31679c1df1763a19d19e8a0
F test/e_walhook.test 4c0613a0c76e7a9d5c4c211e1b4cbcc1143914df
+F test/emptytable.test a38110becbdfa6325cd65cb588dca658cd885f62
F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
F test/enc2.test 83437a79ba1545a55fb549309175c683fb334473
F test/enc3.test 6807f7a7740a00361ca8d0ccd66bc60c8dc5f2b6
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 810d29320b853b3a01aa50d8f2a0bceacf79e0aa
-R 91fee55f54fe2e54254ba44f0240778d
-U mistachkin
-Z 72fbc76e1b27f40edc76050b0de83496
+P 830b9235673be55f0c932fb157de03725e648c25
+R 32e948726be0c8ec843ec4b81e44685b
+U drh
+Z 345aeb62ab5f52d0700dc3107ec5c535
-830b9235673be55f0c932fb157de03725e648c25
\ No newline at end of file
+58797e9bafa95709e0f706a15f42f93b409e2db5
\ No newline at end of file
Vdbe *v; /* The prepared stmt under constructions */
struct SrcList_item *pTabItem; /* FROM clause term being coded */
int addrBrk; /* Jump here to break out of the loop */
+ int addrHalt; /* addrBrk for the outermost loop */
int addrCont; /* Jump here to continue with next cycle */
int iRowidReg = 0; /* Rowid is stored in this register, if not zero */
int iReleaseReg = 0; /* Temp register to free before returning */
VdbeComment((v, "init LEFT JOIN no-match flag"));
}
+ /* Compute a safe address to jump to if we discover that the table for
+ ** this loop is empty and can never contribute content. */
+ for(j=iLevel; j>0 && pWInfo->a[j].iLeftJoin==0; j--){}
+ addrHalt = pWInfo->a[j].addrBrk;
+
/* Special case of a FROM clause subquery implemented as a co-routine */
if( pTabItem->fg.viaCoroutine ){
int regYield = pTabItem->regReturn;
sqlite3ExprCacheAffinityChange(pParse, r1, 1);
sqlite3ReleaseTempReg(pParse, rTemp);
}else{
- sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrBrk);
+ sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrHalt);
VdbeCoverageIf(v, bRev==0);
VdbeCoverageIf(v, bRev!=0);
}
codeCursorHint(pTabItem, pWInfo, pLevel, 0);
pLevel->op = aStep[bRev];
pLevel->p1 = iCur;
- pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk);
+ pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrHalt);
VdbeCoverageIf(v, bRev==0);
VdbeCoverageIf(v, bRev!=0);
pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
--- /dev/null
+# 2017-02-15
+#
+# 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.
+#
+#***********************************************************************
+#
+# Test cases to show that a join involving an empty table is very fast.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Build some test data
+#
+do_execsql_test emptytable-100 {
+ CREATE TABLE t1(a);
+ WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100)
+ INSERT INTO t1(a) SELECT x FROM c;
+ CREATE TABLE empty(x);
+ SELECT count(*) FROM t1;
+} {100}
+
+# Interrupt queries after 1M cycles to prevent burning excess CPU
+proc stopDb {args} {
+ db interrupt
+}
+db progress 1000000 {stopDb}
+
+# Prior to the query planner optimization on 2017-02-15, this query would
+# take a ridiculous amount of time. If that optimization stops working,
+# the result here will be in interrupt for running too long.
+#
+do_catchsql_test emptytable-110 {
+ SELECT count(*) FROM t1, t1, t1, t1, t1, t1, empty;
+} {0 0}
+
+do_catchsql_test emptytable-120 {
+ SELECT count(*) FROM t1, t1 LEFT JOIN empty;
+} {0 10000}
+do_catchsql_test emptytable-121 {
+ SELECT count(*) FROM t1, t1 LEFT JOIN t1, empty;
+} {0 0}
+
+
+finish_test