提交 99bb7a1b authored 作者: Thomas Mueller's avatar Thomas Mueller

Statements with IN(SELECT..) conditions could produce the wrong result.

上级 82e4de37
...@@ -25,6 +25,8 @@ Change Log ...@@ -25,6 +25,8 @@ Change Log
</li><li>Optimization index conditions of the form 'column=NULL' (which is always false; unlike 'column IS NULL'). </li><li>Optimization index conditions of the form 'column=NULL' (which is always false; unlike 'column IS NULL').
</li><li>Script command and tool: the primary key constraint is now listed before inserting the data. </li><li>Script command and tool: the primary key constraint is now listed before inserting the data.
This will result in a smaller database when using the page store. This will result in a smaller database when using the page store.
</li><li>Statements with IN(SELECT..) conditions could produce the wrong result.
Example: index on id, name; query: select * from test where id between 1 and 3 and name in (select 'World').
</li><li>Statements with IN(..) conditions could produce the wrong result when using views or nested select statements. </li><li>Statements with IN(..) conditions could produce the wrong result when using views or nested select statements.
Example: index on id; index on name; query: select * from (select * from test) where id=1 and name in('a', 'b'). Example: index on id; index on name; query: select * from (select * from test) where id=1 and name in('a', 'b').
select * from (select * from test) where id=1 and name in('Hello', 'World'). select * from (select * from test) where id=1 and name in('Hello', 'World').
......
...@@ -77,12 +77,16 @@ public class IndexCursor implements Cursor { ...@@ -77,12 +77,16 @@ public class IndexCursor implements Cursor {
} }
Column column = condition.getColumn(); Column column = condition.getColumn();
if (condition.getCompareType() == Comparison.IN_LIST) { if (condition.getCompareType() == Comparison.IN_LIST) {
if (start == null && end == null) {
this.inColumn = column; this.inColumn = column;
inList = condition.getCurrentValueList(session); inList = condition.getCurrentValueList(session);
inListIndex = 0; inListIndex = 0;
}
} else if (condition.getCompareType() == Comparison.IN_QUERY) { } else if (condition.getCompareType() == Comparison.IN_QUERY) {
if (start == null && end == null) {
this.inColumn = column; this.inColumn = column;
inResult = condition.getCurrentResult(session); inResult = condition.getCurrentResult(session);
}
} else { } else {
Value v = column.convert(condition.getCurrentValue(session)); Value v = column.convert(condition.getCurrentValue(session));
boolean isStart = condition.isStart(); boolean isStart = condition.isStart();
...@@ -102,17 +106,19 @@ public class IndexCursor implements Cursor { ...@@ -102,17 +106,19 @@ public class IndexCursor implements Cursor {
if (isEnd) { if (isEnd) {
end = getSearchRow(end, id, v, false); end = getSearchRow(end, id, v, false);
} }
if (isStart && isEnd) { if (isStart || isEnd) {
if (v == ValueNull.INSTANCE) {
// join on a column=NULL is always false
alwaysFalse = true;
}
// an X=? condition will produce less rows than // an X=? condition will produce less rows than
// an X IN(..) condition // an X IN(..) condition
inColumn = null; inColumn = null;
inList = null; inList = null;
inResult = null; inResult = null;
} }
if (isStart && isEnd) {
if (v == ValueNull.INSTANCE) {
// join on a column=NULL is always false
alwaysFalse = true;
}
}
} }
} }
if (inColumn != null) { if (inColumn != null) {
......
...@@ -38,6 +38,7 @@ public class TestOptimizations extends TestBase { ...@@ -38,6 +38,7 @@ public class TestOptimizations extends TestBase {
} }
public void test() throws Exception { public void test() throws Exception {
testInAndBetween();
testNestedIn(); testNestedIn();
testNestedInSelectAndLike(); testNestedInSelectAndLike();
testNestedInSelect(); testNestedInSelect();
...@@ -60,6 +61,22 @@ public class TestOptimizations extends TestBase { ...@@ -60,6 +61,22 @@ public class TestOptimizations extends TestBase {
deleteDb("optimizations"); deleteDb("optimizations");
} }
private void testInAndBetween() throws SQLException {
deleteDb("optimizations");
Connection conn = getConnection("optimizations");
Statement stat = conn.createStatement();
ResultSet rs;
stat.execute("create table test(id int, name varchar)");
stat.execute("create index idx_name on test(id, name)");
stat.execute("insert into test values(1, 'Hello'), (2, 'World')");
rs = stat.executeQuery("select * from test where id between 1 and 3 and name in ('World')");
assertTrue(rs.next());
rs = stat.executeQuery("select * from test where id between 1 and 3 and name in (select 'World')");
assertTrue(rs.next());
stat.execute("drop table test");
conn.close();
}
private void testNestedIn() throws SQLException { private void testNestedIn() throws SQLException {
deleteDb("optimizations"); deleteDb("optimizations");
Connection conn = getConnection("optimizations"); Connection conn = getConnection("optimizations");
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论