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

Views using functions were not re-evaluated when necessary.

上级 13ff8d02
......@@ -220,6 +220,7 @@ public abstract class Query extends Prepared {
}
Value[] params = getParameterValues();
long now = session.getDatabase().getModificationDataId();
if (isEverything(ExpressionVisitor.DETERMINISTIC)) {
if (lastResult != null && !lastResult.isClosed() && limit == lastLimit) {
if (sameResultAsLast(session, params, lastParameters, lastEvaluated)) {
lastResult = lastResult.createShallowCopy(session);
......@@ -229,6 +230,7 @@ public abstract class Query extends Prepared {
}
}
}
}
lastParameters = params;
closeLastResult();
lastResult = queryWithoutCache(limit);
......
......@@ -1047,6 +1047,14 @@ public class Select extends Query {
public boolean isEverything(ExpressionVisitor visitor) {
switch(visitor.getType()) {
case ExpressionVisitor.DETERMINISTIC: {
for (TableFilter f : filters) {
if (!f.getTable().isDeterministic()) {
return false;
}
}
break;
}
case ExpressionVisitor.SET_MAX_DATA_MODIFICATION_ID: {
for (TableFilter f : filters) {
long m = f.getTable().getMaxDataModificationId();
......
......@@ -192,4 +192,8 @@ public class FunctionTable extends Table {
return rowCount;
}
public boolean isDeterministic() {
return function.isDeterministic();
}
}
......@@ -1746,4 +1746,8 @@ public class MetaTable extends Table {
return ROW_COUNT_APPROXIMATION;
}
public boolean isDeterministic() {
return true;
}
}
......@@ -168,4 +168,8 @@ public class RangeTable extends Table {
return 100;
}
public boolean isDeterministic() {
return true;
}
}
......@@ -231,6 +231,13 @@ public abstract class Table extends SchemaObjectBase {
*/
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.
*
......
......@@ -712,4 +712,8 @@ public class TableData extends Table implements RecordReader {
this.compareMode = compareMode;
}
public boolean isDeterministic() {
return true;
}
}
......@@ -14,7 +14,6 @@ import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.HashMap;
import org.h2.command.Prepared;
import org.h2.constant.ErrorCode;
import org.h2.engine.Session;
......@@ -535,4 +534,8 @@ public class TableLink extends Table {
prepared.put(sql, prep);
}
public boolean isDeterministic() {
return false;
}
}
......@@ -14,6 +14,7 @@ import org.h2.engine.Constants;
import org.h2.engine.Session;
import org.h2.engine.User;
import org.h2.expression.Expression;
import org.h2.expression.ExpressionVisitor;
import org.h2.expression.Parameter;
import org.h2.index.Index;
import org.h2.index.IndexType;
......@@ -359,4 +360,8 @@ public class TableView extends Table {
return topQuery == null ? 0 : topQuery.getParameters().size();
}
public boolean isDeterministic() {
return viewQuery.isEverything(ExpressionVisitor.DETERMINISTIC);
}
}
......@@ -11,7 +11,6 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.h2.test.TestBase;
/**
......@@ -19,6 +18,8 @@ import org.h2.test.TestBase;
*/
public class TestView extends TestBase {
private static int x;
/**
* Run just this test.
*
......@@ -29,12 +30,61 @@ public class TestView extends TestBase {
}
public void test() throws SQLException {
testCache();
testCacheFunction(true);
testCacheFunction(false);
testInSelect();
testUnionReconnect();
testManyViews();
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 {
deleteDb("view");
Connection conn = getConnection("view");
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论