001: /*
002: * Copyright 2004-2008 H2 Group. Licensed under the H2 License, Version 1.0
003: * (http://h2database.com/html/license.html).
004: * Initial Developer: H2 Group
005: */
006: package org.h2.expression;
007:
008: import java.sql.SQLException;
009:
010: import org.h2.command.dml.Select;
011: import org.h2.engine.Session;
012: import org.h2.table.Column;
013: import org.h2.table.ColumnResolver;
014: import org.h2.table.TableFilter;
015: import org.h2.util.StringUtils;
016: import org.h2.value.Value;
017:
018: /**
019: * An expression is a operation, a value, or a function in a query.
020: */
021: public abstract class Expression {
022:
023: private boolean addedToFilter;
024:
025: /**
026: * Return the resulting value for the current row.
027: *
028: * @param session the session
029: * @return the result
030: */
031: public abstract Value getValue(Session session) throws SQLException;
032:
033: /**
034: * Return the data type. The data type may not be known before the
035: * optimization phase.
036: *
037: * @return the type
038: */
039: public abstract int getType();
040:
041: /**
042: * Map the columns of the resolver to expression columns.
043: *
044: * @param resolver the column resolver
045: * @param level the subquery nesting level
046: */
047: public abstract void mapColumns(ColumnResolver resolver, int level)
048: throws SQLException;
049:
050: /**
051: * Try to optimize the expression.
052: *
053: * @param session the session
054: * @return the optimized expression
055: */
056: public abstract Expression optimize(Session session)
057: throws SQLException;
058:
059: /**
060: * Tell the expression columns whether the table filter can return values now.
061: * This is used when optimizing the query.
062: *
063: * @param tableFilter the table filter
064: * @param value true if the table filter can return value
065: */
066: public abstract void setEvaluatable(TableFilter tableFilter,
067: boolean value);
068:
069: /**
070: * Get the scale of this expression.
071: *
072: * @return the scale
073: */
074: public abstract int getScale();
075:
076: /**
077: * Get the precision of this expression.
078: *
079: * @return the precision
080: */
081: public abstract long getPrecision();
082:
083: /**
084: * Get the display size of this expression.
085: *
086: * @return the display size
087: */
088: public abstract int getDisplaySize();
089:
090: /**
091: * Get the SQL statement of this expression.
092: * This may not always be the original SQL statement,
093: * specially after optimization.
094: *
095: * @return the SQL statement
096: */
097: public abstract String getSQL();
098:
099: /**
100: * Update an aggregate value.
101: * This method is called at statement execution time once for each row.
102: *
103: * @param session the session
104: */
105: public abstract void updateAggregate(Session session)
106: throws SQLException;
107:
108: /**
109: * Check if this expression and all sub-expressions can fulfill a criteria.
110: * If any part returns false, the result is false.
111: *
112: * @param visitor the visitor
113: * @return if the criteria can be fulfilled
114: */
115: public abstract boolean isEverything(ExpressionVisitor visitor);
116:
117: /**
118: * Estimate the cost to process the expression.
119: * Used when optimizing the query, to calculate the query plan
120: * with the lowest estimated cost.
121: *
122: * @return the estimated cost
123: */
124: public abstract int getCost();
125:
126: /**
127: * Check if this expression and all sub-expressions can fulfill a criteria.
128: * This is a convenience function.
129: *
130: * @param expressionVisitorType the visitor type
131: * @return if the criteria can be fulfilled
132: */
133: public final boolean isEverything(int expressionVisitorType) {
134: ExpressionVisitor visitor = ExpressionVisitor
135: .get(expressionVisitorType);
136: return isEverything(visitor);
137: }
138:
139: /**
140: * If it is possible, return the negated expression. This is used
141: * to optimize NOT expressions: NOT ID>10 can be converted to
142: * ID<=10. Returns null if negating is not possible.
143: *
144: * @param session the session
145: * @return the negated expression, or null
146: */
147: public Expression getNotIfPossible(Session session) {
148: // by default it is not possible
149: return null;
150: }
151:
152: /**
153: * Check if this expression will always return the same value.
154: *
155: * @return if the expression is constant
156: */
157: public boolean isConstant() {
158: return false;
159: }
160:
161: /**
162: * Is the value of a parameter set.
163: *
164: * @return if it is set
165: */
166: public boolean isValueSet() {
167: return false;
168: }
169:
170: /**
171: * Check if this is an auto-increment column.
172: *
173: * @return true if it is an auto-increment column
174: */
175: public boolean isAutoIncrement() {
176: return false;
177: }
178:
179: /**
180: * Get the value in form of a boolean expression.
181: * Returns true, false, or null.
182: * In this database, everything can be a condition.
183: *
184: * @param session the session
185: * @return the result
186: */
187: public Boolean getBooleanValue(Session session) throws SQLException {
188: return getValue(session).getBoolean();
189: }
190:
191: /**
192: * Create index conditions if possible and attach them to the table filter.
193: *
194: * @param session the session
195: * @param filter the table filter
196: */
197: public void createIndexConditions(Session session,
198: TableFilter filter) throws SQLException {
199: // default is do nothing
200: }
201:
202: /**
203: * Get the column name or alias name of this expression.
204: *
205: * @return the column name
206: */
207: public String getColumnName() {
208: return getAlias();
209: }
210:
211: /**
212: * Get the schema name, or null
213: *
214: * @return the schema name
215: */
216: public String getSchemaName() {
217: return null;
218: }
219:
220: /**
221: * Get the table name, or null
222: *
223: * @return the table name
224: */
225: public String getTableName() {
226: return null;
227: }
228:
229: /**
230: * Check whether this expression is a column and can store null values.
231: *
232: * @return whether null values are allowed
233: */
234: public int getNullable() {
235: return Column.NULLABLE_UNKNOWN;
236: }
237:
238: /**
239: * Get the table alias name or null
240: * if this expression does not represent a column.
241: *
242: * @return the table alias name
243: */
244: public String getTableAlias() {
245: return null;
246: }
247:
248: /**
249: * Get the alias name of a column or SQL expression
250: * if it is not an aliased expression.
251: *
252: * @return the alias name
253: */
254: public String getAlias() {
255: return StringUtils.unEnclose(getSQL());
256: }
257:
258: /**
259: * Only returns true if the expression is a wildcard.
260: *
261: * @return if this expression is a wildcard
262: */
263: public boolean isWildcard() {
264: return false;
265: }
266:
267: /**
268: * Returns the main expression, skipping aliases.
269: *
270: * @return the expression
271: */
272: public Expression getNonAliasExpression() {
273: return this ;
274: }
275:
276: /**
277: * Add conditions to a table filter if they can be evaluated.
278: *
279: * @param filter the table filter
280: * @param outerJoin if the expression is part of an outer join
281: */
282: public void addFilterConditions(TableFilter filter,
283: boolean outerJoin) {
284: if (!addedToFilter && !outerJoin
285: && isEverything(ExpressionVisitor.EVALUATABLE)) {
286: filter.addFilterCondition(this , false);
287: addedToFilter = true;
288: }
289: }
290:
291: /**
292: * Convert this expression to a String.
293: *
294: * @return the string representation
295: */
296: public String toString() {
297: return getSQL();
298: }
299:
300: /**
301: * Optimize IN(...) expressions if possible.
302: *
303: * @param session the session
304: * @param select the query
305: * @return the optimized expression
306: */
307: public Expression optimizeInJoin(Session session, Select select)
308: throws SQLException {
309: return this;
310: }
311:
312: }
|