org.glowroot.shaded.h2.expression.ExpressionVisitor Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2004-2013 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.glowroot.shaded.h2.expression;
import java.util.HashSet;
import org.glowroot.shaded.h2.engine.DbObject;
import org.glowroot.shaded.h2.table.Column;
import org.glowroot.shaded.h2.table.ColumnResolver;
import org.glowroot.shaded.h2.table.Table;
/**
* The visitor pattern is used to iterate through all expressions of a query
* to optimize a statement.
*/
public class ExpressionVisitor {
/**
* Is the value independent on unset parameters or on columns of a higher
* level query, or sequence values (that means can it be evaluated right
* now)?
*/
public static final int INDEPENDENT = 0;
/**
* The visitor singleton for the type INDEPENDENT.
*/
public static final ExpressionVisitor INDEPENDENT_VISITOR =
new ExpressionVisitor(INDEPENDENT);
/**
* Are all aggregates MIN(column), MAX(column), or COUNT(*) for the given
* table (getTable)?
*/
public static final int OPTIMIZABLE_MIN_MAX_COUNT_ALL = 1;
/**
* Does the expression return the same results for the same parameters?
*/
public static final int DETERMINISTIC = 2;
/**
* The visitor singleton for the type DETERMINISTIC.
*/
public static final ExpressionVisitor DETERMINISTIC_VISITOR =
new ExpressionVisitor(DETERMINISTIC);
/**
* Can the expression be evaluated, that means are all columns set to
* 'evaluatable'?
*/
public static final int EVALUATABLE = 3;
/**
* The visitor singleton for the type EVALUATABLE.
*/
public static final ExpressionVisitor EVALUATABLE_VISITOR =
new ExpressionVisitor(EVALUATABLE);
/**
* Request to set the latest modification id (addDataModificationId).
*/
public static final int SET_MAX_DATA_MODIFICATION_ID = 4;
/**
* Does the expression have no side effects (change the data)?
*/
public static final int READONLY = 5;
/**
* The visitor singleton for the type EVALUATABLE.
*/
public static final ExpressionVisitor READONLY_VISITOR =
new ExpressionVisitor(READONLY);
/**
* Does an expression have no relation to the given table filter
* (getResolver)?
*/
public static final int NOT_FROM_RESOLVER = 6;
/**
* Request to get the set of dependencies (addDependency).
*/
public static final int GET_DEPENDENCIES = 7;
/**
* Can the expression be added to a condition of an outer query. Example:
* ROWNUM() can't be added as a condition to the inner query of select id
* from (select t.*, rownum as r from test t) where r between 2 and 3; Also
* a sequence expression must not be used.
*/
public static final int QUERY_COMPARABLE = 8;
/**
* Get all referenced columns.
*/
public static final int GET_COLUMNS = 9;
/**
* The visitor singleton for the type QUERY_COMPARABLE.
*/
public static final ExpressionVisitor QUERY_COMPARABLE_VISITOR =
new ExpressionVisitor(QUERY_COMPARABLE);
private final int type;
private final int queryLevel;
private final HashSet dependencies;
private final HashSet columns;
private final Table table;
private final long[] maxDataModificationId;
private final ColumnResolver resolver;
private ExpressionVisitor(int type,
int queryLevel,
HashSet dependencies,
HashSet columns,
Table table, ColumnResolver resolver,
long[] maxDataModificationId) {
this.type = type;
this.queryLevel = queryLevel;
this.dependencies = dependencies;
this.columns = columns;
this.table = table;
this.resolver = resolver;
this.maxDataModificationId = maxDataModificationId;
}
private ExpressionVisitor(int type) {
this.type = type;
this.queryLevel = 0;
this.dependencies = null;
this.columns = null;
this.table = null;
this.resolver = null;
this.maxDataModificationId = null;
}
/**
* Create a new visitor object to collect dependencies.
*
* @param dependencies the dependencies set
* @return the new visitor
*/
public static ExpressionVisitor getDependenciesVisitor(
HashSet dependencies) {
return new ExpressionVisitor(GET_DEPENDENCIES, 0, dependencies, null,
null, null, null);
}
/**
* Create a new visitor to check if all aggregates are for the given table.
*
* @param table the table
* @return the new visitor
*/
public static ExpressionVisitor getOptimizableVisitor(Table table) {
return new ExpressionVisitor(OPTIMIZABLE_MIN_MAX_COUNT_ALL, 0, null,
null, table, null, null);
}
/**
* Create a new visitor to check if no expression depends on the given
* resolver.
*
* @param resolver the resolver
* @return the new visitor
*/
static ExpressionVisitor getNotFromResolverVisitor(ColumnResolver resolver) {
return new ExpressionVisitor(NOT_FROM_RESOLVER, 0, null, null, null,
resolver, null);
}
/**
* Create a new visitor to get all referenced columns.
*
* @param columns the columns map
* @return the new visitor
*/
public static ExpressionVisitor getColumnsVisitor(HashSet columns) {
return new ExpressionVisitor(GET_COLUMNS, 0, null, columns, null, null, null);
}
public static ExpressionVisitor getMaxModificationIdVisitor() {
return new ExpressionVisitor(SET_MAX_DATA_MODIFICATION_ID, 0, null,
null, null, null, new long[1]);
}
/**
* Add a new dependency to the set of dependencies.
* This is used for GET_DEPENDENCIES visitors.
*
* @param obj the additional dependency.
*/
public void addDependency(DbObject obj) {
dependencies.add(obj);
}
/**
* Add a new column to the set of columns.
* This is used for GET_COLUMNS visitors.
*
* @param column the additional column.
*/
void addColumn(Column column) {
columns.add(column);
}
/**
* Get the dependency set.
* This is used for GET_DEPENDENCIES visitors.
*
* @return the set
*/
public HashSet getDependencies() {
return 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 ExpressionVisitor incrementQueryLevel(int offset) {
return new ExpressionVisitor(type, queryLevel + offset, dependencies,
columns, table, resolver, maxDataModificationId);
}
/**
* Get the column resolver.
* This is used for NOT_FROM_RESOLVER visitors.
*
* @return the column resolver
*/
public ColumnResolver getResolver() {
return resolver;
}
/**
* Update the field maxDataModificationId if this value is higher
* than the current value.
* This is used for SET_MAX_DATA_MODIFICATION_ID visitors.
*
* @param value the data modification id
*/
public void addDataModificationId(long value) {
long m = maxDataModificationId[0];
if (value > m) {
maxDataModificationId[0] = value;
}
}
/**
* Get the last data modification.
* This is used for SET_MAX_DATA_MODIFICATION_ID visitors.
*
* @return the maximum modification id
*/
public long getMaxDataModificationId() {
return maxDataModificationId[0];
}
int getQueryLevel() {
return queryLevel;
}
/**
* Get the table.
* This is used for OPTIMIZABLE_MIN_MAX_COUNT_ALL visitors.
*
* @return the table
*/
public Table getTable() {
return table;
}
/**
* Get the visitor type.
*
* @return the type
*/
public int getType() {
return type;
}
}