提交 9319d138 authored 作者: Thomas Mueller's avatar Thomas Mueller

Using "row_number" or "rownum" in views or derived tables had unexpected results…

Using "row_number" or "rownum" in views or derived tables had unexpected results if the outer query contained constraints for the given view.
上级 9366c741
......@@ -17,7 +17,11 @@ Change Log
<h1>Change Log</h1>
<h2>Next Version (unreleased)</h2>
<ul><li>MVStore: the Recover tool can now deal with more types of corruption in the file.
<ul><li>Using "row_number" or "rownum" in views or derived tables had unexpected results
if the outer query contained constraints for the given view. Example:
select b.nr, b.id from (select row_number() over() as nr, a.id as id
from (select id from test order by name) as a) as b where b.id = 1
</li><li>MVStore: the Recover tool can now deal with more types of corruption in the file.
</li><li>MVStore: the TransactionStore now first needs to be initialized before it can be used.
</li><li>Views and derived tables with equality and range conditions on the same columns
did not work properly. example: select x from (select x from (select 1 as x)
......
......@@ -363,6 +363,9 @@ public class Comparison extends Condition {
@Override
public void createIndexConditions(Session session, TableFilter filter) {
if (!filter.getTable().isQueryComparable()) {
return;
}
ExpressionColumn l = null;
if (left instanceof ExpressionColumn) {
l = (ExpressionColumn) left;
......
......@@ -324,6 +324,23 @@ public abstract class Table extends SchemaObjectBase {
public String getCreateSQLForCopy(Table table, String quotedName) {
throw DbException.throwInternalError();
}
/**
* Check whether the table (or view) contains no columns that prevent index
* conditions to be used. For example, a view that contains the ROWNUM()
* pseudo-column prevents this.
*
* @return true if the table contains no query-comparable column
*/
public boolean isQueryComparable() {
ExpressionVisitor visitor = ExpressionVisitor.QUERY_COMPARABLE_VISITOR;
for (Column col : columns) {
if (!col.isEverything(visitor)) {
return false;
}
}
return true;
}
/**
* Add all objects that this table depends on to the hash set.
......
......@@ -254,6 +254,23 @@ public class TableView extends Table {
}
return item;
}
@Override
public boolean isQueryComparable() {
if (!super.isQueryComparable()) {
return false;
}
for (Table t : tables) {
if (!t.isQueryComparable()) {
return false;
}
}
if (topQuery != null &&
!topQuery.isEverything(ExpressionVisitor.QUERY_COMPARABLE_VISITOR)) {
return false;
}
return true;
}
@Override
public String getDropSQL() {
......
......@@ -32,6 +32,9 @@ public class TestView extends TestBase {
@Override
public void test() throws SQLException {
deleteDb("view");
testInnerSelectWithRownum();
testInnerSelectWithRange();
testEmptyColumn();
testChangeSchemaSearchPath();
......@@ -47,6 +50,23 @@ public class TestView extends TestBase {
testViewConstraintFromColumnExpression();
deleteDb("view");
}
private void testInnerSelectWithRownum() throws SQLException {
Connection conn = getConnection("view");
Statement stat = conn.createStatement();
stat.execute("drop table test if exists");
stat.execute("create table test(id int primary key, name varchar(1))");
stat.execute("insert into test(id, name) values(1, 'b'), (3, 'a')");
ResultSet rs = stat.executeQuery(
"select nr from (select row_number() over() as nr, " +
"a.id as id from (select id from test order by name) as a) as b " +
"where b.id = 1;");
assertTrue(rs.next());
assertEquals(2, rs.getInt(1));
assertFalse(rs.next());
stat.execute("drop table test");
conn.close();
}
private void testInnerSelectWithRange() throws SQLException {
Connection conn = getConnection("view");
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论