提交 8efb6c8d authored 作者: Thomas Mueller's avatar Thomas Mueller

When concurrently preparing many statements with a subquery, in some cases the query didn't run.

上级 9e86397a
......@@ -427,20 +427,9 @@ public abstract class Query extends Prepared {
}
public final long getMaxDataModificationId() {
ExpressionVisitor visitor = ExpressionVisitor.get(ExpressionVisitor.SET_MAX_DATA_MODIFICATION_ID);
ExpressionVisitor visitor = ExpressionVisitor.getMaxModificationIdVisitor();
isEverything(visitor);
return visitor.getMaxDataModificationId();
}
/**
* Visit all expressions and subqueries in this query using the visitor pattern.
*
* @param expressionVisitorType the visitor type
* @return true if no component returned false
*/
public final boolean isEverything(int expressionVisitorType) {
ExpressionVisitor visitor = ExpressionVisitor.get(expressionVisitorType);
return isEverything(visitor);
}
}
......@@ -789,8 +789,8 @@ public class Select extends Query {
}
if (isGroupQuery && groupIndex == null && havingIndex < 0 && filters.size() == 1) {
if (condition == null) {
ExpressionVisitor optimizable = ExpressionVisitor.get(ExpressionVisitor.OPTIMIZABLE_MIN_MAX_COUNT_ALL);
optimizable.setTable((filters.get(0)).getTable());
Table t = filters.get(0).getTable();
ExpressionVisitor optimizable = ExpressionVisitor.getOptimizableVisitor(t);
isQuickAggregateQuery = isEverything(optimizable);
}
}
......@@ -1193,22 +1193,21 @@ public class Select extends Query {
}
default:
}
visitor.incrementQueryLevel(1);
ExpressionVisitor v2 = visitor.incrementQueryLevel(1);
boolean result = true;
for (int i = 0, size = expressions.size(); i < size; i++) {
Expression e = expressions.get(i);
if (!e.isEverything(visitor)) {
if (!e.isEverything(v2)) {
result = false;
break;
}
}
if (result && condition != null && !condition.isEverything(visitor)) {
if (result && condition != null && !condition.isEverything(v2)) {
result = false;
}
if (result && having != null && !having.isEverything(visitor)) {
if (result && having != null && !having.isEverything(v2)) {
result = false;
}
visitor.incrementQueryLevel(-1);
return result;
}
......
......@@ -356,14 +356,12 @@ public class Comparison extends Condition {
return;
}
if (l == null) {
ExpressionVisitor visitor = ExpressionVisitor.get(ExpressionVisitor.NOT_FROM_RESOLVER);
visitor.setResolver(filter);
ExpressionVisitor visitor = ExpressionVisitor.getNotFromResolverVisitor(filter);
if (!left.isEverything(visitor)) {
return;
}
} else if (r == null) {
ExpressionVisitor visitor = ExpressionVisitor.get(ExpressionVisitor.NOT_FROM_RESOLVER);
visitor.setResolver(filter);
ExpressionVisitor visitor = ExpressionVisitor.getNotFromResolverVisitor(filter);
if (!right.isEverything(visitor)) {
return;
}
......
......@@ -110,8 +110,7 @@ public class ConditionIn extends Condition {
return;
}
if (session.getDatabase().getSettings().optimizeInList) {
ExpressionVisitor visitor = ExpressionVisitor.get(ExpressionVisitor.NOT_FROM_RESOLVER);
visitor.setResolver(filter);
ExpressionVisitor visitor = ExpressionVisitor.getNotFromResolverVisitor(filter);
for (Expression e : valueList) {
if (!e.isEverything(visitor)) {
return;
......
......@@ -130,8 +130,7 @@ public class ConditionInSelect extends Condition {
if (filter != l.getTableFilter()) {
return;
}
ExpressionVisitor visitor = ExpressionVisitor.get(ExpressionVisitor.NOT_FROM_RESOLVER);
visitor.setResolver(filter);
ExpressionVisitor visitor = ExpressionVisitor.getNotFromResolverVisitor(filter);
if (!query.isEverything(visitor)) {
return;
}
......
......@@ -128,18 +128,6 @@ public abstract class Expression {
*/
public abstract int getCost();
/**
* Check if this expression and all sub-expressions can fulfill a criteria.
* This is a convenience function.
*
* @param expressionVisitorType the visitor type
* @return if the criteria can be fulfilled
*/
public final boolean isEverything(int expressionVisitorType) {
ExpressionVisitor visitor = ExpressionVisitor.get(expressionVisitorType);
return isEverything(visitor);
}
/**
* If it is possible, return the negated expression. This is used
* to optimize NOT expressions: NOT ID>10 can be converted to
......
......@@ -165,6 +165,7 @@ public class ExpressionColumn extends Expression {
}
Value value = columnResolver.getValue(column);
if (value == null) {
columnResolver.getValue(column);
throw DbException.get(ErrorCode.MUST_GROUP_BY_COLUMN_1, getSQL());
}
return value;
......
......@@ -7,10 +7,7 @@
package org.h2.expression;
import java.util.HashSet;
import org.h2.constant.SysProperties;
import org.h2.engine.DbObject;
import org.h2.message.DbException;
import org.h2.table.ColumnResolver;
import org.h2.table.Table;
......@@ -98,15 +95,29 @@ public class ExpressionVisitor {
*/
public static final ExpressionVisitor QUERY_COMPARABLE_VISITOR = new ExpressionVisitor(QUERY_COMPARABLE);
private int queryLevel;
private Table table;
private int type;
private long maxDataModificationId;
private ColumnResolver resolver;
private HashSet<DbObject> dependencies;
private final int type;
private final int queryLevel;
private final HashSet<DbObject> dependencies;
private final Table table;
private final long[] maxDataModificationId;
private final ColumnResolver resolver;
private ExpressionVisitor(int type, int queryLevel, HashSet<DbObject> dependencies, Table table, ColumnResolver resolver, long[] maxDataModificationId) {
this.type = type;
this.queryLevel = queryLevel;
this.dependencies = dependencies;
this.table = table;
this.resolver = resolver;
this.maxDataModificationId = maxDataModificationId;
}
private ExpressionVisitor(int type) {
this.type = type;
this.queryLevel = 0;
this.dependencies = null;
this.table = null;
this.resolver = null;
this.maxDataModificationId = null;
}
/**
......@@ -115,18 +126,22 @@ public class ExpressionVisitor {
* @param type the visitor type
* @return the new visitor
*/
public static ExpressionVisitor get(int type) {
if (SysProperties.CHECK) {
switch (type) {
case INDEPENDENT:
case DETERMINISTIC:
case EVALUATABLE:
case READONLY:
case QUERY_COMPARABLE:
throw DbException.throwInternalError("Singleton not used");
}
}
return new ExpressionVisitor(type);
public static ExpressionVisitor getDependenciesVisitor(HashSet<DbObject> dependencies) {
return new ExpressionVisitor(GET_DEPENDENCIES, 0, dependencies, null, null, null);
}
public static ExpressionVisitor getOptimizableVisitor(Table table) {
return new ExpressionVisitor(OPTIMIZABLE_MIN_MAX_COUNT_ALL, 0, null, table, null, null);
}
public static ExpressionVisitor getNotFromResolverVisitor(ColumnResolver resolver) {
return new ExpressionVisitor(NOT_FROM_RESOLVER, 0, null, null, resolver, null);
}
public static ExpressionVisitor getMaxModificationIdVisitor() {
return new ExpressionVisitor(SET_MAX_DATA_MODIFICATION_ID, 0, null, null, null, new long[1]);
}
/**
......@@ -149,23 +164,14 @@ public class ExpressionVisitor {
return dependencies;
}
/**
* Set all dependencies.
* This is used for GET_DEPENDENCIES visitors.
*
* @param dependencies the dependency set
*/
public void setDependencies(HashSet<DbObject> dependencies) {
this.dependencies = dependencies;
}
/**
* Increment or decrement the query level.
*
* @param offset 1 to increment, -1 to decrement
* @return a clone of this expression visitor, with the changed query level
*/
public void incrementQueryLevel(int offset) {
queryLevel += offset;
public ExpressionVisitor incrementQueryLevel(int offset) {
return new ExpressionVisitor(type, queryLevel + offset, dependencies, table, resolver, maxDataModificationId);
}
/**
......@@ -178,16 +184,6 @@ public class ExpressionVisitor {
return resolver;
}
/**
* Set the column resolver.
* This is used for NOT_FROM_RESOLVER visitors.
*
* @param resolver the column resolver
*/
public void setResolver(ColumnResolver resolver) {
this.resolver = resolver;
}
/**
* Update the field maxDataModificationId if this value is higher
* than the current value.
......@@ -196,7 +192,10 @@ public class ExpressionVisitor {
* @param value the data modification id
*/
public void addDataModificationId(long value) {
maxDataModificationId = Math.max(maxDataModificationId, value);
long m = maxDataModificationId[0];
if (value > m) {
maxDataModificationId[0] = value;
}
}
/**
......@@ -206,27 +205,13 @@ public class ExpressionVisitor {
* @return the maximum modification id
*/
public long getMaxDataModificationId() {
return maxDataModificationId;
return maxDataModificationId[0];
}
int getQueryLevel() {
return queryLevel;
}
void setQueryLevel(int queryLevel) {
this.queryLevel = queryLevel;
}
/**
* Set the table.
* This is used for OPTIMIZABLE_MIN_MAX_COUNT_ALL visitors.
*
* @param table the table
*/
public void setTable(Table table) {
this.table = table;
}
/**
* Get the table.
* This is used for OPTIMIZABLE_MIN_MAX_COUNT_ALL visitors.
......
......@@ -297,8 +297,7 @@ public abstract class Table extends SchemaObjectBase {
dependencies.add(s);
}
}
ExpressionVisitor visitor = ExpressionVisitor.get(ExpressionVisitor.GET_DEPENDENCIES);
visitor.setDependencies(dependencies);
ExpressionVisitor visitor = ExpressionVisitor.getDependenciesVisitor(dependencies);
for (Column col : columns) {
col.isEverything(visitor);
}
......
......@@ -62,7 +62,11 @@ public class TestMultiConn extends TestBase implements DatabaseEventListener {
} catch (SQLException e) {
// ignore
}
t.get();
try {
t.get();
} catch (Exception e) {
// ignore
}
}
private void testThreeThreads() throws Exception {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论