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.Parser;
011: import org.h2.engine.FunctionAlias;
012: import org.h2.engine.Session;
013: import org.h2.table.ColumnResolver;
014: import org.h2.table.TableFilter;
015: import org.h2.value.Value;
016: import org.h2.value.ValueNull;
017: import org.h2.value.ValueResultSet;
018:
019: /**
020: * This class wraps a user defined function.
021: */
022: public class JavaFunction extends Expression implements FunctionCall {
023:
024: private FunctionAlias functionAlias;
025: private Expression[] args;
026:
027: public JavaFunction(FunctionAlias functionAlias, Expression[] args) {
028: this .functionAlias = functionAlias;
029: this .args = args;
030: }
031:
032: public Value getValue(Session session) throws SQLException {
033: return functionAlias.getValue(session, args);
034: }
035:
036: public int getType() {
037: return functionAlias.getDataType();
038: }
039:
040: public void mapColumns(ColumnResolver resolver, int level)
041: throws SQLException {
042: for (int i = 0; i < args.length; i++) {
043: args[i].mapColumns(resolver, level);
044: }
045: }
046:
047: public Expression optimize(Session session) throws SQLException {
048: for (int i = 0; i < args.length; i++) {
049: Expression e = args[i].optimize(session);
050: args[i] = e;
051: }
052: return this ;
053: }
054:
055: public void setEvaluatable(TableFilter tableFilter, boolean b) {
056: for (int i = 0; i < args.length; i++) {
057: Expression e = args[i];
058: if (e != null) {
059: e.setEvaluatable(tableFilter, b);
060: }
061: }
062: }
063:
064: public int getScale() {
065: return 0;
066: }
067:
068: public long getPrecision() {
069: return Integer.MAX_VALUE;
070: }
071:
072: public int getDisplaySize() {
073: return Integer.MAX_VALUE;
074: }
075:
076: public String getSQL() {
077: StringBuffer buff = new StringBuffer();
078: buff.append(Parser.quoteIdentifier(functionAlias.getName()));
079: buff.append('(');
080: for (int i = 0; i < args.length; i++) {
081: if (i > 0) {
082: buff.append(", ");
083: }
084: Expression e = args[i];
085: buff.append(e.getSQL());
086: }
087: buff.append(')');
088: return buff.toString();
089: }
090:
091: public void updateAggregate(Session session) throws SQLException {
092: for (int i = 0; i < args.length; i++) {
093: Expression e = args[i];
094: if (e != null) {
095: e.updateAggregate(session);
096: }
097: }
098: }
099:
100: public FunctionAlias getFunctionAlias() {
101: return functionAlias;
102: }
103:
104: public String getName() {
105: return functionAlias.getName();
106: }
107:
108: public int getParameterCount() throws SQLException {
109: return functionAlias.getParameterCount();
110: }
111:
112: public ValueResultSet getValueForColumnList(Session session,
113: Expression[] args) throws SQLException {
114: Value v = functionAlias.getValue(session, args, true);
115: return v == ValueNull.INSTANCE ? null : (ValueResultSet) v;
116: }
117:
118: public Expression[] getArgs() {
119: return args;
120: }
121:
122: public boolean isEverything(ExpressionVisitor visitor) {
123: switch (visitor.type) {
124: case ExpressionVisitor.DETERMINISTIC:
125: // TODO optimization: some functions are deterministic, but we don't
126: // know (no setting for that)
127: return false;
128: case ExpressionVisitor.GET_DEPENDENCIES:
129: visitor.addDependency(functionAlias);
130: break;
131: }
132: for (int i = 0; i < args.length; i++) {
133: Expression e = args[i];
134: if (e != null && !e.isEverything(visitor)) {
135: return false;
136: }
137: }
138: return true;
139: }
140:
141: public int getCost() {
142: int cost = functionAlias.hasConnectionParam() ? 25 : 5;
143: for (int i = 0; i < args.length; i++) {
144: cost += args[i].getCost();
145: }
146: return cost;
147: }
148:
149: }
|