KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > h2 > expression > Operation


1 /*
2  * Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
3  * Initial Developer: H2 Group
4  */

5 package org.h2.expression;
6
7 import java.sql.SQLException JavaDoc;
8
9 import org.h2.engine.Mode;
10 import org.h2.engine.Session;
11 import org.h2.message.Message;
12 import org.h2.table.ColumnResolver;
13 import org.h2.table.TableFilter;
14 import org.h2.value.Value;
15 import org.h2.value.ValueNull;
16 import org.h2.value.ValueString;
17
18 public class Operation extends Expression {
19     public static final int CONCAT = 0, PLUS = 1, MINUS = 2, MULTIPLY = 3,
20             DIVIDE = 4, NEGATE = 5;
21     private int opType;
22     private Expression left, right;
23     private int dataType;
24
25     public Operation(int opType, Expression left, Expression right) {
26         this.opType = opType;
27         this.left = left;
28         this.right = right;
29     }
30
31     public String JavaDoc getSQL() {
32         String JavaDoc sql;
33         switch(opType) {
34         case NEGATE:
35             // don't remove the space, otherwise it might end up some thing line --1 which is a remark
36
// TODO need to () everything correctly, but avoiding double (())
37
sql = "- " + left.getSQL();
38             break;
39         case CONCAT:
40             sql = left.getSQL() + " || " + right.getSQL();
41             break;
42         case PLUS:
43             sql = left.getSQL() + " + " + right.getSQL();
44             break;
45         case MINUS:
46             sql = left.getSQL() + " - " + right.getSQL();
47             break;
48         case MULTIPLY:
49             sql = left.getSQL() + " * " + right.getSQL();
50             break;
51         case DIVIDE:
52             sql = left.getSQL() + " / " + right.getSQL();
53             break;
54         default:
55             throw Message.getInternalError("opType="+opType);
56         }
57         return "("+sql+")";
58     }
59
60     public Value getValue(Session session) throws SQLException JavaDoc {
61         Value l = left.getValue(session).convertTo(dataType);
62         Value r = right == null ? null : right.getValue(session).convertTo(dataType);
63
64         switch (opType) {
65         case NEGATE:
66             return l == ValueNull.INSTANCE ? l : l.negate();
67         case CONCAT: {
68             if (l == ValueNull.INSTANCE) {
69                 if(Mode.getCurrentMode().nullConcatIsNull) {
70                     return ValueNull.INSTANCE;
71                 } else {
72                     return r;
73                 }
74             } else if (r == ValueNull.INSTANCE) {
75                 if(Mode.getCurrentMode().nullConcatIsNull) {
76                     return ValueNull.INSTANCE;
77                 } else {
78                     return l;
79                 }
80             }
81             String JavaDoc s1 = l.getString(), s2 = r.getString();
82             StringBuffer JavaDoc buff = new StringBuffer JavaDoc(s1.length() + s2.length());
83             buff.append(s1);
84             buff.append(s2);
85             return ValueString.get(buff.toString());
86         }
87         case PLUS:
88             if(l == ValueNull.INSTANCE || r == ValueNull.INSTANCE) {
89                 return ValueNull.INSTANCE;
90             }
91             return l.add(r);
92         case MINUS:
93             if(l == ValueNull.INSTANCE || r == ValueNull.INSTANCE) {
94                 return ValueNull.INSTANCE;
95             }
96             return l.subtract(r);
97         case MULTIPLY:
98             if(l == ValueNull.INSTANCE || r == ValueNull.INSTANCE) {
99                 return ValueNull.INSTANCE;
100             }
101             return l.multiply(r);
102         case DIVIDE:
103             if(l == ValueNull.INSTANCE || r == ValueNull.INSTANCE) {
104                 return ValueNull.INSTANCE;
105             }
106             return l.divide(r);
107         default:
108             throw Message.getInternalError("type=" + opType);
109         }
110     }
111
112     public void mapColumns(ColumnResolver resolver, int level) throws SQLException JavaDoc {
113         left.mapColumns(resolver, level);
114         if(right != null) {
115             right.mapColumns(resolver, level);
116         }
117     }
118
119     public Expression optimize(Session session) throws SQLException JavaDoc {
120         left = left.optimize(session);
121         switch (opType) {
122         case NEGATE:
123             dataType = left.getType();
124             break;
125         case CONCAT:
126             right = right.optimize(session);
127             dataType = Value.STRING;
128             if(left.isConstant() && right.isConstant()) {
129                 return ValueExpression.get(getValue(session));
130             }
131             break;
132         case PLUS:
133         case MINUS:
134         case MULTIPLY:
135         case DIVIDE:
136             right = right.optimize(session);
137             int l = left.getType();
138             int r = right.getType();
139             if(l==Value.NULL && r==Value.NULL) {
140                 // example: (? + ?) - the most safe data type is probably decimal
141
dataType = Value.DECIMAL;
142             } else if(l == Value.DATE || l == Value.TIMESTAMP) {
143                 if(r == Value.INT && (opType == PLUS || opType == MINUS)) {
144                     // Oracle date add
145
Function f = Function.getFunction(session.getDatabase(), "DATEADD");
146                     f.setParameter(0, ValueExpression.get(ValueString.get("DAY")));
147                     if(opType == MINUS) {
148                         right = new Operation(NEGATE, right, null);
149                         right = right.optimize(session);
150                     }
151                     f.setParameter(1, right);
152                     f.setParameter(2, left);
153                     f.doneWithParameters();
154                     return f.optimize(session);
155                 } else if(opType == MINUS && (l == Value.DATE || l == Value.TIMESTAMP)) {
156                     // Oracle date subtract
157
Function f = Function.getFunction(session.getDatabase(), "DATEDIFF");
158                     f.setParameter(0, ValueExpression.get(ValueString.get("DAY")));
159                     f.setParameter(1, right);
160                     f.setParameter(2, left);
161                     f.doneWithParameters();
162                     return f.optimize(session);
163                 }
164             } else {
165                 dataType = Value.getHigherOrder(l, r);
166             }
167             break;
168         default:
169             throw Message.getInternalError("type=" + opType);
170         }
171         if(left.isConstant() && (right==null || right.isConstant())) {
172             return ValueExpression.get(getValue(session));
173         }
174         return this;
175     }
176
177     public void setEvaluatable(TableFilter tableFilter, boolean b) {
178         left.setEvaluatable(tableFilter, b);
179         if(right != null) {
180             right.setEvaluatable(tableFilter, b);
181         }
182     }
183
184     public int getType() {
185         return dataType;
186     }
187
188     public long getPrecision() {
189         if(right != null) {
190             return Math.max(left.getPrecision(), right.getPrecision());
191         }
192         return left.getPrecision();
193     }
194
195     public int getScale() {
196         if(right != null) {
197             return Math.max(left.getScale(), right.getScale());
198         }
199         return left.getScale();
200     }
201
202     public void updateAggregate(Session session) throws SQLException JavaDoc {
203         left.updateAggregate(session);
204         if(right != null) {
205             right.updateAggregate(session);
206         }
207     }
208
209     public boolean isEverything(ExpressionVisitor visitor) {
210         return left.isEverything(visitor) && (right == null || right.isEverything(visitor));
211     }
212     
213     public int getCost() {
214         return left.getCost() + 1 + (right == null ? 0 : right.getCost());
215     }
216
217 }
218
Popular Tags