File D:\maven-qcr-plugin-testsunitaires\qcr4java\h2-1.3.170-sources\target\site\qc\lecode\expression\ExpressionVisitor.java.html

1 /*
2 * Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
3 * Version 1.0, and under the Eclipse Public License, Version 1.0
4 * (http://h2database.com/html/license.html).
5 * Initial Developer: H2 Group
6 */
7 package org.h2.expression;
8
9 import java.util.HashSet;
10 import org.h2.engine.DbObject;
11 import org.h2.table.Column;
12 import org.h2.table.ColumnResolver;
13 import org.h2.table.Table;
14
15 /**
16 * The visitor pattern is used to iterate through all expressions of a query
17 * to optimize a statement.
18 */
19 public class ExpressionVisitor {
20
21 /**
22 * Is the value independent on unset parameters or on columns of a higher
23 * level query, or sequence values (that means can it be evaluated right
24 * now)?
25 */
26 public static final int INDEPENDENT = 0;
27
28 /**
29 * The visitor singleton for the type INDEPENDENT.
30 */
31 public static final ExpressionVisitor INDEPENDENT_VISITOR = new ExpressionVisitor(INDEPENDENT);
32
33 /**
34 * Are all aggregates MIN(column), MAX(column), or COUNT(*) for the given
35 * table (getTable)?
36 */
37 public static final int OPTIMIZABLE_MIN_MAX_COUNT_ALL = 1;
38
39 /**
40 * Does the expression return the same results for the same parameters?
41 */
42 public static final int DETERMINISTIC = 2;
43
44 /**
45 * The visitor singleton for the type DETERMINISTIC.
46 */
47 public static final ExpressionVisitor DETERMINISTIC_VISITOR = new ExpressionVisitor(DETERMINISTIC);
48
49 /**
50 * Can the expression be evaluated, that means are all columns set to
51 * 'evaluatable'?
52 */
53 public static final int EVALUATABLE = 3;
54
55 /**
56 * The visitor singleton for the type EVALUATABLE.
57 */
58 public static final ExpressionVisitor EVALUATABLE_VISITOR = new ExpressionVisitor(EVALUATABLE);
59
60 /**
61 * Request to set the latest modification id (addDataModificationId).
62 */
63 public static final int SET_MAX_DATA_MODIFICATION_ID = 4;
64
65 /**
66 * Does the expression have no side effects (change the data)?
67 */
68 public static final int READONLY = 5;
69
70 /**
71 * The visitor singleton for the type EVALUATABLE.
72 */
73 public static final ExpressionVisitor READONLY_VISITOR = new ExpressionVisitor(READONLY);
74
75 /**
76 * Does an expression have no relation to the given table filter
77 * (getResolver)?
78 */
79 public static final int NOT_FROM_RESOLVER = 6;
80
81 /**
82 * Request to get the set of dependencies (addDependency).
83 */
84 public static final int GET_DEPENDENCIES = 7;
85
86 /**
87 * Can the expression be added to a condition of an outer query.
88 * Example: ROWNUM() can't be added as a condition to the inner query of
89 * select id from (select t.*, rownum as r from test t) where r between 2 and 3;
90 * Also a sequence expression must not be used.
91 */
92 public static final int QUERY_COMPARABLE = 8;
93
94 /**
95 * Get all referenced columns.
96 */
97 public static final int GET_COLUMNS = 9;
98
99 /**
100 * The visitor singleton for the type QUERY_COMPARABLE.
101 */
102 public static final ExpressionVisitor QUERY_COMPARABLE_VISITOR = new ExpressionVisitor(QUERY_COMPARABLE);
103
104 private final int type;
105 private final int queryLevel;
106 private final HashSet<DbObject> dependencies;
107 private final HashSet<Column> columns;
108 private final Table table;
109 private final long[] maxDataModificationId;
110 private final ColumnResolver resolver;
111
112 private ExpressionVisitor(int type,
113 int queryLevel,
114 HashSet<DbObject> dependencies,
115 HashSet<Column> columns,
116 Table table, ColumnResolver resolver,
117 long[] maxDataModificationId) {
118 this.type = type;
119 this.queryLevel = queryLevel;
120 this.dependencies = dependencies;
121 this.columns = columns;
122 this.table = table;
123 this.resolver = resolver;
124 this.maxDataModificationId = maxDataModificationId;
125 }
126
127 private ExpressionVisitor(int type) {
128 this.type = type;
129 this.queryLevel = 0;
130 this.dependencies = null;
131 this.columns = null;
132 this.table = null;
133 this.resolver = null;
134 this.maxDataModificationId = null;
135 }
136
137 /**
138 * Create a new visitor object to collect dependencies.
139 *
140 * @param dependencies the dependencies set
141 * @return the new visitor
142 */
143 public static ExpressionVisitor getDependenciesVisitor(HashSet<DbObject> dependencies) {
144 return new ExpressionVisitor(GET_DEPENDENCIES, 0, dependencies, null, null, null, null);
145 }
146
147 /**
148 * Create a new visitor to check if all aggregates are for the given table.
149 *
150 * @param table the table
151 * @return the new visitor
152 */
153 public static ExpressionVisitor getOptimizableVisitor(Table table) {
154 return new ExpressionVisitor(OPTIMIZABLE_MIN_MAX_COUNT_ALL, 0, null, null, table, null, null);
155 }
156
157 /**
158 * Create a new visitor to check if no expression depends on the given
159 * resolver.
160 *
161 * @param resolver the resolver
162 * @return the new visitor
163 */
164 static ExpressionVisitor getNotFromResolverVisitor(ColumnResolver resolver) {
165 return new ExpressionVisitor(NOT_FROM_RESOLVER, 0, null, null, null, resolver, null);
166 }
167
168 /**
169 * Create a new visitor to get all referenced columns.
170 *
171 * @param columns the columns map
172 * @return the new visitor
173 */
174 public static ExpressionVisitor getColumnsVisitor(HashSet<Column> columns) {
175 return new ExpressionVisitor(GET_COLUMNS, 0, null, columns, null, null, null);
176 }
177
178 public static ExpressionVisitor getMaxModificationIdVisitor() {
179 return new ExpressionVisitor(SET_MAX_DATA_MODIFICATION_ID, 0, null, null, null, null, new long[1]);
180 }
181
182 /**
183 * Add a new dependency to the set of dependencies.
184 * This is used for GET_DEPENDENCIES visitors.
185 *
186 * @param obj the additional dependency.
187 */
188 public void addDependency(DbObject obj) {
189 dependencies.add(obj);
190 }
191
192 /**
193 * Add a new column to the set of columns.
194 * This is used for GET_COLUMNS visitors.
195 *
196 * @param column the additional column.
197 */
198 void addColumn(Column column) {
199 columns.add(column);
200 }
201
202 /**
203 * Get the dependency set.
204 * This is used for GET_DEPENDENCIES visitors.
205 *
206 * @return the set
207 */
208 public HashSet<DbObject> getDependencies() {
209 return dependencies;
210 }
211
212 /**
213 * Increment or decrement the query level.
214 *
215 * @param offset 1 to increment, -1 to decrement
216 * @return a clone of this expression visitor, with the changed query level
217 */
218 public ExpressionVisitor incrementQueryLevel(int offset) {
219 return new ExpressionVisitor(type, queryLevel + offset, dependencies, columns, table, resolver, maxDataModificationId);
220 }
221
222 /**
223 * Get the column resolver.
224 * This is used for NOT_FROM_RESOLVER visitors.
225 *
226 * @return the column resolver
227 */
228 public ColumnResolver getResolver() {
229 return resolver;
230 }
231
232 /**
233 * Update the field maxDataModificationId if this value is higher
234 * than the current value.
235 * This is used for SET_MAX_DATA_MODIFICATION_ID visitors.
236 *
237 * @param value the data modification id
238 */
239 public void addDataModificationId(long value) {
240 long m = maxDataModificationId[0];
241 if (value > m) {
242 maxDataModificationId[0] = value;
243 }
244 }
245
246 /**
247 * Get the last data modification.
248 * This is used for SET_MAX_DATA_MODIFICATION_ID visitors.
249 *
250 * @return the maximum modification id
251 */
252 public long getMaxDataModificationId() {
253 return maxDataModificationId[0];
254 }
255
256 int getQueryLevel() {
257 return queryLevel;
258 }
259
260 /**
261 * Get the table.
262 * This is used for OPTIMIZABLE_MIN_MAX_COUNT_ALL visitors.
263 *
264 * @return the table
265 */
266 public Table getTable() {
267 return table;
268 }
269
270 /**
271 * Get the visitor type.
272 *
273 * @return the type
274 */
275 public int getType() {
276 return type;
277 }
278
279 }
280