提交 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 ...@@ -17,7 +17,11 @@ Change Log
<h1>Change Log</h1> <h1>Change Log</h1>
<h2>Next Version (unreleased)</h2> <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>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 </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) did not work properly. example: select x from (select x from (select 1 as x)
......
...@@ -363,6 +363,9 @@ public class Comparison extends Condition { ...@@ -363,6 +363,9 @@ public class Comparison extends Condition {
@Override @Override
public void createIndexConditions(Session session, TableFilter filter) { public void createIndexConditions(Session session, TableFilter filter) {
if (!filter.getTable().isQueryComparable()) {
return;
}
ExpressionColumn l = null; ExpressionColumn l = null;
if (left instanceof ExpressionColumn) { if (left instanceof ExpressionColumn) {
l = (ExpressionColumn) left; l = (ExpressionColumn) left;
......
...@@ -325,6 +325,23 @@ public abstract class Table extends SchemaObjectBase { ...@@ -325,6 +325,23 @@ public abstract class Table extends SchemaObjectBase {
throw DbException.throwInternalError(); 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. * Add all objects that this table depends on to the hash set.
* *
......
...@@ -255,6 +255,23 @@ public class TableView extends Table { ...@@ -255,6 +255,23 @@ public class TableView extends Table {
return item; 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 @Override
public String getDropSQL() { public String getDropSQL() {
return "DROP VIEW IF EXISTS " + getSQL() + " CASCADE"; return "DROP VIEW IF EXISTS " + getSQL() + " CASCADE";
......
...@@ -32,6 +32,9 @@ public class TestView extends TestBase { ...@@ -32,6 +32,9 @@ public class TestView extends TestBase {
@Override @Override
public void test() throws SQLException { public void test() throws SQLException {
deleteDb("view");
testInnerSelectWithRownum();
testInnerSelectWithRange(); testInnerSelectWithRange();
testEmptyColumn(); testEmptyColumn();
testChangeSchemaSearchPath(); testChangeSchemaSearchPath();
...@@ -48,6 +51,23 @@ public class TestView extends TestBase { ...@@ -48,6 +51,23 @@ public class TestView extends TestBase {
deleteDb("view"); 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 { private void testInnerSelectWithRange() throws SQLException {
Connection conn = getConnection("view"); Connection conn = getConnection("view");
Statement stat = conn.createStatement(); Statement stat = conn.createStatement();
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论