File D:\maven-qcr-plugin-testsunitaires\qcr4java\h2-1.3.170-sources\target\site\qc\lecode\expression\JavaAggregate.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.sql.Connection;
10 import java.sql.SQLException;
11 import java.util.HashMap;
12 import org.h2.api.AggregateFunction;
13 import org.h2.command.Parser;
14 import org.h2.command.dml.Select;
15 import org.h2.constant.ErrorCode;
16 import org.h2.engine.Session;
17 import org.h2.engine.UserAggregate;
18 import org.h2.message.DbException;
19 import org.h2.table.ColumnResolver;
20 import org.h2.table.TableFilter;
21 import org.h2.util.StatementBuilder;
22 import org.h2.value.DataType;
23 import org.h2.value.Value;
24 import org.h2.value.ValueNull;
25
26 /**
27 * This class wraps a user-defined aggregate.
28 */
29 public class JavaAggregate extends Expression {
30
31 private final UserAggregate userAggregate;
32 private final Select select;
33 private final Expression[] args;
34 private int[] argTypes;
35 private int dataType;
36 private Connection userConnection;
37 private int lastGroupRowId;
38
39 public JavaAggregate(UserAggregate userAggregate, Expression[] args, Select select) {
40 this.userAggregate = userAggregate;
41 this.args = args;
42 this.select = select;
43 }
44
45 public int getCost() {
46 int cost = 5;
47 for (Expression e : args) {
48 cost += e.getCost();
49 }
50 return cost;
51 }
52
53 public long getPrecision() {
54 return Integer.MAX_VALUE;
55 }
56
57 public int getDisplaySize() {
58 return Integer.MAX_VALUE;
59 }
60
61 public int getScale() {
62 return DataType.getDataType(dataType).defaultScale;
63 }
64
65 public String getSQL() {
66 StatementBuilder buff = new StatementBuilder();
67 buff.append(Parser.quoteIdentifier(userAggregate.getName())).append('(');
68 for (Expression e : args) {
69 buff.appendExceptFirst(", ");
70 buff.append(e.getSQL());
71 }
72 return buff.append(')').toString();
73 }
74
75 public int getType() {
76 return dataType;
77 }
78
79 public boolean isEverything(ExpressionVisitor visitor) {
80 switch(visitor.getType()) {
81 case ExpressionVisitor.DETERMINISTIC:
82 // TODO optimization: some functions are deterministic, but we don't
83 // know (no setting for that)
84 case ExpressionVisitor.OPTIMIZABLE_MIN_MAX_COUNT_ALL:
85 // user defined aggregate functions can not be optimized
86 return false;
87 case ExpressionVisitor.GET_DEPENDENCIES:
88 visitor.addDependency(userAggregate);
89 break;
90 default:
91 }
92 for (Expression e : args) {
93 if (e != null && !e.isEverything(visitor)) {
94 return false;
95 }
96 }
97 return true;
98 }
99
100 public void mapColumns(ColumnResolver resolver, int level) {
101 for (Expression arg : args) {
102 arg.mapColumns(resolver, level);
103 }
104 }
105
106 public Expression optimize(Session session) {
107 userConnection = session.createConnection(false);
108 int len = args.length;
109 argTypes = new int[len];
110 int[] argSqlTypes = new int[len];
111 for (int i = 0; i < len; i++) {
112 Expression expr = args[i];
113 args[i] = expr.optimize(session);
114 int type = expr.getType();
115 argTypes[i] = type;
116 argSqlTypes[i] = DataType.convertTypeToSQLType(type);
117 }
118 try {
119 AggregateFunction aggregate = getInstance();
120 dataType = DataType.convertSQLTypeToValueType(aggregate.getType(argSqlTypes));
121 } catch (SQLException e) {
122 throw DbException.convert(e);
123 }
124 return this;
125 }
126
127 public void setEvaluatable(TableFilter tableFilter, boolean b) {
128 for (Expression e : args) {
129 e.setEvaluatable(tableFilter, b);
130 }
131 }
132
133 private AggregateFunction getInstance() throws SQLException {
134 AggregateFunction agg = userAggregate.getInstance();
135 agg.init(userConnection);
136 return agg;
137 }
138
139 public Value getValue(Session session) {
140 HashMap<Expression, Object> group = select.getCurrentGroup();
141 if (group == null) {
142 throw DbException.get(ErrorCode.INVALID_USE_OF_AGGREGATE_FUNCTION_1, getSQL());
143 }
144 try {
145 AggregateFunction agg = (AggregateFunction) group.get(this);
146 if (agg == null) {
147 agg = getInstance();
148 }
149 Object obj = agg.getResult();
150 if (obj == null) {
151 return ValueNull.INSTANCE;
152 }
153 return DataType.convertToValue(session, obj, dataType);
154 } catch (SQLException e) {
155 throw DbException.convert(e);
156 }
157 }
158
159 public void updateAggregate(Session session) {
160 HashMap<Expression, Object> group = select.getCurrentGroup();
161 if (group == null) {
162 // this is a different level (the enclosing query)
163 return;
164 }
165
166 int groupRowId = select.getCurrentGroupRowId();
167 if (lastGroupRowId == groupRowId) {
168 // already visited
169 return;
170 }
171 lastGroupRowId = groupRowId;
172
173 AggregateFunction agg = (AggregateFunction) group.get(this);
174 try {
175 if (agg == null) {
176 agg = getInstance();
177 group.put(this, agg);
178 }
179 Object[] argValues = new Object[args.length];
180 Object arg = null;
181 for (int i = 0, len = args.length; i < len; i++) {
182 Value v = args[i].getValue(session);
183 v = v.convertTo(argTypes[i]);
184 arg = v.getObject();
185 argValues[i] = arg;
186 }
187 if (args.length == 1) {
188 agg.add(arg);
189 } else {
190 agg.add(argValues);
191 }
192 } catch (SQLException e) {
193 throw DbException.convert(e);
194 }
195 }
196
197 }
198