提交 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
</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.
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.
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').
......
......@@ -77,12 +77,16 @@ public class IndexCursor implements Cursor {
}
Column column = condition.getColumn();
if (condition.getCompareType() == Comparison.IN_LIST) {
this.inColumn = column;
inList = condition.getCurrentValueList(session);
inListIndex = 0;
if (start == null && end == null) {
this.inColumn = column;
inList = condition.getCurrentValueList(session);
inListIndex = 0;
}
} else if (condition.getCompareType() == Comparison.IN_QUERY) {
this.inColumn = column;
inResult = condition.getCurrentResult(session);
if (start == null && end == null) {
this.inColumn = column;
inResult = condition.getCurrentResult(session);
}
} else {
Value v = column.convert(condition.getCurrentValue(session));
boolean isStart = condition.isStart();
......@@ -102,17 +106,19 @@ public class IndexCursor implements Cursor {
if (isEnd) {
end = getSearchRow(end, id, v, false);
}
if (isStart && isEnd) {
if (v == ValueNull.INSTANCE) {
// join on a column=NULL is always false
alwaysFalse = true;
}
if (isStart || isEnd) {
// an X=? condition will produce less rows than
// an X IN(..) condition
inColumn = null;
inList = null;
inResult = null;
}
if (isStart && isEnd) {
if (v == ValueNull.INSTANCE) {
// join on a column=NULL is always false
alwaysFalse = true;
}
}
}
}
if (inColumn != null) {
......
......@@ -38,6 +38,7 @@ public class TestOptimizations extends TestBase {
}
public void test() throws Exception {
testInAndBetween();
testNestedIn();
testNestedInSelectAndLike();
testNestedInSelect();
......@@ -60,6 +61,22 @@ public class TestOptimizations extends TestBase {
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 {
deleteDb("optimizations");
Connection conn = getConnection("optimizations");
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论