提交 e3578c9e authored 作者: Thomas Mueller's avatar Thomas Mueller

Views using functions were not re-evaluated when necessary.

上级 13ff8d02
...@@ -220,12 +220,14 @@ public abstract class Query extends Prepared { ...@@ -220,12 +220,14 @@ public abstract class Query extends Prepared {
} }
Value[] params = getParameterValues(); Value[] params = getParameterValues();
long now = session.getDatabase().getModificationDataId(); long now = session.getDatabase().getModificationDataId();
if (lastResult != null && !lastResult.isClosed() && limit == lastLimit) { if (isEverything(ExpressionVisitor.DETERMINISTIC)) {
if (sameResultAsLast(session, params, lastParameters, lastEvaluated)) { if (lastResult != null && !lastResult.isClosed() && limit == lastLimit) {
lastResult = lastResult.createShallowCopy(session); if (sameResultAsLast(session, params, lastParameters, lastEvaluated)) {
if (lastResult != null) { lastResult = lastResult.createShallowCopy(session);
lastResult.reset(); if (lastResult != null) {
return lastResult; lastResult.reset();
return lastResult;
}
} }
} }
} }
......
...@@ -1047,6 +1047,14 @@ public class Select extends Query { ...@@ -1047,6 +1047,14 @@ public class Select extends Query {
public boolean isEverything(ExpressionVisitor visitor) { public boolean isEverything(ExpressionVisitor visitor) {
switch(visitor.getType()) { switch(visitor.getType()) {
case ExpressionVisitor.DETERMINISTIC: {
for (TableFilter f : filters) {
if (!f.getTable().isDeterministic()) {
return false;
}
}
break;
}
case ExpressionVisitor.SET_MAX_DATA_MODIFICATION_ID: { case ExpressionVisitor.SET_MAX_DATA_MODIFICATION_ID: {
for (TableFilter f : filters) { for (TableFilter f : filters) {
long m = f.getTable().getMaxDataModificationId(); long m = f.getTable().getMaxDataModificationId();
......
...@@ -192,4 +192,8 @@ public class FunctionTable extends Table { ...@@ -192,4 +192,8 @@ public class FunctionTable extends Table {
return rowCount; return rowCount;
} }
public boolean isDeterministic() {
return function.isDeterministic();
}
} }
...@@ -1746,4 +1746,8 @@ public class MetaTable extends Table { ...@@ -1746,4 +1746,8 @@ public class MetaTable extends Table {
return ROW_COUNT_APPROXIMATION; return ROW_COUNT_APPROXIMATION;
} }
public boolean isDeterministic() {
return true;
}
} }
...@@ -168,4 +168,8 @@ public class RangeTable extends Table { ...@@ -168,4 +168,8 @@ public class RangeTable extends Table {
return 100; return 100;
} }
public boolean isDeterministic() {
return true;
}
} }
...@@ -231,6 +231,13 @@ public abstract class Table extends SchemaObjectBase { ...@@ -231,6 +231,13 @@ public abstract class Table extends SchemaObjectBase {
*/ */
public abstract long getMaxDataModificationId(); public abstract long getMaxDataModificationId();
/**
* Check if the table is deterministic.
*
* @return true if it is
*/
public abstract boolean isDeterministic();
/** /**
* Check if the row count can be retrieved quickly. * Check if the row count can be retrieved quickly.
* *
......
...@@ -712,4 +712,8 @@ public class TableData extends Table implements RecordReader { ...@@ -712,4 +712,8 @@ public class TableData extends Table implements RecordReader {
this.compareMode = compareMode; this.compareMode = compareMode;
} }
public boolean isDeterministic() {
return true;
}
} }
...@@ -14,7 +14,6 @@ import java.sql.SQLException; ...@@ -14,7 +14,6 @@ import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import java.sql.Types; import java.sql.Types;
import java.util.HashMap; import java.util.HashMap;
import org.h2.command.Prepared; import org.h2.command.Prepared;
import org.h2.constant.ErrorCode; import org.h2.constant.ErrorCode;
import org.h2.engine.Session; import org.h2.engine.Session;
...@@ -535,4 +534,8 @@ public class TableLink extends Table { ...@@ -535,4 +534,8 @@ public class TableLink extends Table {
prepared.put(sql, prep); prepared.put(sql, prep);
} }
public boolean isDeterministic() {
return false;
}
} }
...@@ -14,6 +14,7 @@ import org.h2.engine.Constants; ...@@ -14,6 +14,7 @@ import org.h2.engine.Constants;
import org.h2.engine.Session; import org.h2.engine.Session;
import org.h2.engine.User; import org.h2.engine.User;
import org.h2.expression.Expression; import org.h2.expression.Expression;
import org.h2.expression.ExpressionVisitor;
import org.h2.expression.Parameter; import org.h2.expression.Parameter;
import org.h2.index.Index; import org.h2.index.Index;
import org.h2.index.IndexType; import org.h2.index.IndexType;
...@@ -359,4 +360,8 @@ public class TableView extends Table { ...@@ -359,4 +360,8 @@ public class TableView extends Table {
return topQuery == null ? 0 : topQuery.getParameters().size(); return topQuery == null ? 0 : topQuery.getParameters().size();
} }
public boolean isDeterministic() {
return viewQuery.isEverything(ExpressionVisitor.DETERMINISTIC);
}
} }
...@@ -11,7 +11,6 @@ import java.sql.PreparedStatement; ...@@ -11,7 +11,6 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import org.h2.test.TestBase; import org.h2.test.TestBase;
/** /**
...@@ -19,6 +18,8 @@ import org.h2.test.TestBase; ...@@ -19,6 +18,8 @@ import org.h2.test.TestBase;
*/ */
public class TestView extends TestBase { public class TestView extends TestBase {
private static int x;
/** /**
* Run just this test. * Run just this test.
* *
...@@ -29,12 +30,61 @@ public class TestView extends TestBase { ...@@ -29,12 +30,61 @@ public class TestView extends TestBase {
} }
public void test() throws SQLException { public void test() throws SQLException {
testCache();
testCacheFunction(true);
testCacheFunction(false);
testInSelect(); testInSelect();
testUnionReconnect(); testUnionReconnect();
testManyViews(); testManyViews();
deleteDb("view"); deleteDb("view");
} }
private void testCacheFunction(boolean deterministic) throws SQLException {
deleteDb("view");
Connection conn = getConnection("view");
Statement stat = conn.createStatement();
stat.execute("CREATE ALIAS GET_X " +
(deterministic ? "DETERMINISTIC" : "") +
" FOR \"" + getClass().getName() + ".getX\"");
stat.execute("CREATE VIEW V AS SELECT * FROM (SELECT GET_X())");
ResultSet rs;
x = 8;
rs = stat.executeQuery("SELECT * FROM V");
rs.next();
assertEquals(8, rs.getInt(1));
x = 5;
rs = stat.executeQuery("SELECT * FROM V");
rs.next();
assertEquals(deterministic ? 8 : 5, rs.getInt(1));
conn.close();
}
/**
* This method is called via reflection from the database.
*
* @return the static value x
*/
public static int getX() {
return x;
}
private void testCache() throws SQLException {
deleteDb("view");
Connection conn = getConnection("view");
Statement stat = conn.createStatement();
stat.execute("SET @X 8");
stat.execute("CREATE VIEW V AS SELECT * FROM (SELECT @X)");
ResultSet rs;
rs = stat.executeQuery("SELECT * FROM V");
rs.next();
assertEquals(8, rs.getInt(1));
stat.execute("SET @X 5");
rs = stat.executeQuery("SELECT * FROM V");
rs.next();
assertEquals(5, rs.getInt(1));
conn.close();
}
private void testInSelect() throws SQLException { private void testInSelect() throws SQLException {
deleteDb("view"); deleteDb("view");
Connection conn = getConnection("view"); Connection conn = getConnection("view");
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论