1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-18 10:21:03 +03:00

Fix a problem with processing a "vtab.col IS NULL" expression within

the WHERE clause of a query when "vtab" is a virtual table on the rhs of a
LEFT JOIN.

FossilOrigin-Name: 83da4d4104ee1870a2a95bb5fa15ee6584c655d8b314b6b8ab97592dad4ee811
This commit is contained in:
dan
2018-09-10 12:17:16 +00:00
parent f7ded14792
commit eb3fe0b9d4
4 changed files with 130 additions and 8 deletions

View File

@@ -1,5 +1,5 @@
C Fix\san\sunreachable\sbranch\sin\sthe\snew\ssqlite3WhereOrderByLimitOptLabel()\nfunction\sof\sthe\squery\splanner.
D 2018-09-08T20:29:04.477
C Fix\sa\sproblem\swith\sprocessing\sa\s"vtab.col\sIS\sNULL"\sexpression\swithin\nthe\sWHERE\sclause\sof\sa\squery\swhen\s"vtab"\sis\sa\svirtual\stable\son\sthe\srhs\sof\sa\nLEFT\sJOIN.
D 2018-09-10T12:17:16.759
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F Makefile.in 6b650013511fd9d8b094203ac268af9220d292cc7d4e1bc9fbca15aacd8c7995
@@ -586,7 +586,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c df50883d93689d009be5ad9bdc4e53a4ee45fcc291087ec9272569d00b360791
F src/wal.h 606292549f5a7be50b6227bd685fa76e3a4affad71bb8ac5ce4cb5c79f6a176a
F src/walker.c ba7225773931760cf60bf22f34d0cce2588df7ce5ce0f215a52eb88234b55ac4
F src/where.c ff7f4024cba3d7619dd92239d006364d8c836037afb5c4f8ebf861c9a360b8f3
F src/where.c 071572677469d54899ef0d9fc3ad380a849b860375df5af5ebdc4f49f1dc20cc
F src/whereInt.h b90ef9b9707ef750eab2a7a080c48fb4900315033274689def32d0cf5a81ebe4
F src/wherecode.c 2b6cd1b27736cc803060289e04ecf9849976106f4077aa67d1a2c0e3ec420159
F src/whereexpr.c d87df2c00ecc0c2ef4409562608d19cec259a6a03ca72b86fc999db9c07ce119
@@ -665,6 +665,7 @@ F test/bestindex2.test 9a0ccd320b6525eec3a706aae6cdab7e1b7b5abca75027e39f39f755e
F test/bestindex3.test 001788a114ad96d81d5154fe77c7f1e26e84b3a2b5635ca29e4f96f6decc534e
F test/bestindex4.test 4cb5ff7dbaebadb87d366f51969271778423b455
F test/bestindex5.test 412b42f8036b28d8b2f3534d89389ad946a4b1a65a12263f51936f7424296f1b
F test/bestindex6.test d856a9bb63d927493575823eed44053bc36251e241aa364e54d0f2a2d302e1d4
F test/between.test 34d375fb5ce1ae283ffe82b6b233e9f38e84fc6c
F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59
F test/bigfile2.test 1b489a3a39ae90c7f027b79110d6b4e1dbc71bfc
@@ -1764,7 +1765,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 206720129ed2fa8875a286266d05b99fb2caf8671e4b74b26a6286a2073fcd8b
R c6d02a1d720ce0f314484950383248d6
U drh
Z 283f6327b802e617589c73f6c602d59b
P 5a954533edbde58aa7158572ece7ceeb1c6e610b71f3ae45d0b8371d74f9fea5
R 756e7ce3d56663b883e7e3032dfd4880
U dan
Z f6d9c644621f4f427fb7da91247b3ddb

View File

@@ -1 +1 @@
5a954533edbde58aa7158572ece7ceeb1c6e610b71f3ae45d0b8371d74f9fea5
83da4d4104ee1870a2a95bb5fa15ee6584c655d8b314b6b8ab97592dad4ee811

View File

@@ -966,6 +966,18 @@ static sqlite3_index_info *allocateIndexInfo(
testcase( pTerm->eOperator & WO_ALL );
if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue;
if( pTerm->wtFlags & TERM_VNULL ) continue;
if( (pSrc->fg.jointype & JT_LEFT)!=0
&& !ExprHasProperty(pTerm->pExpr, EP_FromJoin)
&& (pTerm->eOperator & (WO_IS|WO_ISNULL))
){
/* An "IS" term in the WHERE clause where the virtual table is the rhs
** of a LEFT JOIN. Do not pass this term to the virtual table
** implementation, as this can lead to incorrect results from SQL such
** as:
**
** "LEFT JOIN vtab WHERE vtab.col IS NULL" */
continue;
}
assert( pTerm->u.leftColumn>=(-1) );
pIdxCons[j].iColumn = pTerm->u.leftColumn;
pIdxCons[j].iTermOffset = i;

109
test/bestindex6.test Normal file
View File

@@ -0,0 +1,109 @@
# 2018-09-09
#
# 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.
#
#***********************************************************************
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix bestindex6
ifcapable !vtab {
finish_test
return
}
register_tcl_module db
proc vtab_command {src method args} {
switch -- $method {
xConnect {
return [db one {SELECT sql FROM sqlite_master where name = $src}]
}
xBestIndex {
set clist [lindex $args 0]
set wlist 1
set iCons 0
set ret [list]
foreach cons $clist {
catch { array unset C }
array set C $cons
if {$C(usable)} {
set col [db one {
SELECT name FROM pragma_table_info($src) WHERE cid=$C(column)
}]
switch $C(op) {
isnull {
lappend wlist "$col IS NULL"
lappend ret omit $iCons
}
eq {
lappend wlist "$col = %$iCons%"
lappend ret omit $iCons
}
}
}
incr iCons
}
#puts "xBestIndex: $ret"
lappend ret idxStr [join $wlist " AND "]
return $ret
}
xFilter {
foreach {idxnum idxstr aa} $args {}
set map [list]
for {set iCons 0} {$iCons < [llength $aa]} {incr iCons} {
lappend map %$iCons% [lindex $aa $iCons]
}
set ret [list sql \
"SELECT rowid, * FROM $src WHERE [string map $map $idxstr]"
]
# puts "xFilter: $ret"
return $ret
}
}
return {}
}
do_execsql_test 1.0 {
CREATE TABLE t1(id int, value text);
CREATE TABLE t2(ctx int, id int, value text);
INSERT INTO t1 VALUES(1,'try');
INSERT INTO t2 VALUES(1,1,'good');
INSERT INTO t2 VALUES(2,2,'evil');
CREATE VIRTUAL TABLE vt1 USING tcl(vtab_command t1);
CREATE VIRTUAL TABLE vt2 USING tcl(vtab_command t2);
}
do_execsql_test 1.1 {
select * from t2 left join t1 on t1.id=t2.ctx where t1.value is null;
} {2 2 evil {} {}}
do_execsql_test 1.2 {
select * from vt2 left join vt1 on vt1.id=vt2.ctx where vt1.value is null;
} {2 2 evil {} {}}
unset -nocomplain xxx
do_execsql_test 1.3 {
select * from vt2 left join vt1 on vt1.id=vt2.ctx where vt1.value is $xxx;
} {2 2 evil {} {}}
do_execsql_test 1.4 {
select * from t2 left join vt1 on vt1.id=t2.ctx where vt1.value = 3
} {}
finish_test