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:
15
manifest
15
manifest
@@ -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
|
||||
|
||||
@@ -1 +1 @@
|
||||
5a954533edbde58aa7158572ece7ceeb1c6e610b71f3ae45d0b8371d74f9fea5
|
||||
83da4d4104ee1870a2a95bb5fa15ee6584c655d8b314b6b8ab97592dad4ee811
|
||||
12
src/where.c
12
src/where.c
@@ -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
109
test/bestindex6.test
Normal 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
|
||||
Reference in New Issue
Block a user