KickJava   Java API By Example, From Geeks To Geeks.

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


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.Constants;
10 import org.h2.engine.Database;
11 import org.h2.engine.Session;
12 import org.h2.index.IndexCondition;
13 import org.h2.message.Message;
14 import org.h2.table.ColumnResolver;
15 import org.h2.table.TableFilter;
16 import org.h2.value.Value;
17 import org.h2.value.ValueBoolean;
18 import org.h2.value.ValueNull;
19
20 /**
21  * @author Thomas
22  */

23 public class Comparison extends Condition {
24     public static final int EQUAL = 0, BIGGER_EQUAL = 1, BIGGER = 2, SMALLER_EQUAL = 3,
25         SMALLER = 4, NOT_EQUAL = 5, IS_NULL = 6, IS_NOT_NULL = 7;
26     // TODO refactor: comparison: there never is a comparison 'false', the constant is used only for index conditions
27
public static final int FALSE = 8;
28     private Expression left;
29     private Expression right;
30     private int compareType;
31     private int dataType = -1;
32     private Database database;
33
34     public Comparison(Session session, int compareType, Expression left, Expression right) {
35         this.database = session.getDatabase();
36         this.left = left;
37         this.right = right;
38         this.compareType = compareType;
39     }
40
41     public String JavaDoc getSQL() {
42         String JavaDoc sql;
43         switch(compareType) {
44         case EQUAL:
45             sql = left.getSQL() + " = " + right.getSQL();
46             break;
47         case BIGGER_EQUAL:
48             sql = left.getSQL() + " >= " + right.getSQL();
49             break;
50         case BIGGER:
51             sql = left.getSQL() + " > " + right.getSQL();
52             break;
53         case SMALLER_EQUAL:
54             sql = left.getSQL() + " <= " + right.getSQL();
55             break;
56         case SMALLER:
57             sql = left.getSQL() + " < " + right.getSQL();
58             break;
59         case NOT_EQUAL:
60             sql = left.getSQL() + " <> " + right.getSQL();
61             break;
62         case IS_NULL:
63             sql = left.getSQL() +" IS NULL";
64             break;
65         case IS_NOT_NULL:
66             sql = left.getSQL() +" IS NOT NULL";
67             break;
68         default:
69             throw Message.getInternalError("compareType="+compareType);
70         }
71         return "("+sql+")";
72     }
73     
74     private Expression getCast(Expression expr, int dataType, long precision, int scale, Session session) throws SQLException JavaDoc {
75         if(expr == ValueExpression.NULL) {
76             return expr;
77         }
78         Function function = Function.getFunction(session.getDatabase(), "CAST");
79         function.setParameter(0, expr);
80         function.setDataType(dataType, precision, scale);
81         return function.optimize(session);
82     }
83
84     public Expression optimize(Session session) throws SQLException JavaDoc {
85         left = left.optimize(session);
86         if(right == null) {
87             dataType = left.getType();
88         } else {
89             right = right.optimize(session);
90             int lt = left.getType(), rt = right.getType();
91             if(lt == rt) {
92                 if(lt == Value.UNKNOWN) {
93                     throw Message.getSQLException(Message.UNKNOWN_DATA_TYPE_1, getSQL());
94                 }
95                 dataType = lt;
96             } else {
97                 dataType = Value.getHigherOrder(left.getType(), right.getType());
98                 long precision = Math.max(left.getPrecision(), right.getPrecision());
99                 int scale = Math.max(left.getScale(), right.getScale());
100                 if(dataType != lt) {
101                     left = getCast(left, dataType, precision, scale, session);
102                 }
103                 if(dataType != rt) {
104                     right = getCast(right, dataType, precision, scale, session);
105                 }
106             }
107         }
108         if(compareType == IS_NULL || compareType == IS_NOT_NULL) {
109             if(left.isConstant()) {
110                 return ValueExpression.get(getValue(session));
111             }
112         } else {
113             if(Constants.CHECK && (left==null || right==null)) {
114                 throw Message.getInternalError();
115             }
116             if(left == ValueExpression.NULL || right == ValueExpression.NULL) {
117                 // TODO NULL handling: maybe issue a warning when comparing with a NULL constants
118
return ValueExpression.NULL;
119             }
120             if(left.isConstant() && right.isConstant()) {
121                 return ValueExpression.get(getValue(session));
122             }
123         }
124         return this;
125     }
126
127     public Value getValue(Session session) throws SQLException JavaDoc {
128         Value l = left.getValue(session);
129         if(right==null) {
130             boolean result;
131             switch(compareType) {
132             case IS_NULL:
133                 result = l == ValueNull.INSTANCE;
134                 break;
135             case IS_NOT_NULL:
136                 result = !(l == ValueNull.INSTANCE);
137                 break;
138             default:
139                 throw Message.getInternalError("type="+compareType);
140             }
141             return ValueBoolean.get(result);
142         }
143         l = l.convertTo(dataType);
144         Value r = right.getValue(session).convertTo(dataType);
145         if(l == ValueNull.INSTANCE || r == ValueNull.INSTANCE) {
146             return ValueNull.INSTANCE;
147         }
148         boolean result = compareNotNull(database, l, r, compareType);
149         return ValueBoolean.get(result);
150     }
151     
152     public static boolean compareNotNull(Database database, Value l, Value r, int compareType) throws SQLException JavaDoc {
153         boolean result;
154         switch(compareType) {
155         case EQUAL:
156             result = database.areEqual(l, r);
157             break;
158         case NOT_EQUAL:
159             result = !database.areEqual(l, r);
160             break;
161         case BIGGER_EQUAL:
162             result = database.compare(l, r) >= 0;
163             break;
164         case BIGGER:
165             result = database.compare(l, r) > 0;
166             break;
167         case SMALLER_EQUAL:
168             result = database.compare(l, r) <= 0;
169             break;
170         case SMALLER:
171             result = database.compare(l, r) < 0;
172             break;
173         default:
174             throw Message.getInternalError("type="+compareType);
175         }
176         return result;
177     }
178
179     private int getReversedCompareType(int type) {
180         switch(compareType) {
181         case EQUAL:
182         case NOT_EQUAL:
183             return type;
184         case BIGGER_EQUAL:
185             return SMALLER_EQUAL;
186         case BIGGER:
187             return SMALLER;
188         case SMALLER_EQUAL:
189             return BIGGER_EQUAL;
190         case SMALLER:
191             return BIGGER;
192         default:
193             throw Message.getInternalError("type="+compareType);
194         }
195     }
196
197     public void createIndexConditions(TableFilter filter) {
198         if(right==null) {
199             // TODO index usage: IS [NOT] NULL index usage is possible
200
return;
201         }
202         ExpressionColumn l = null;
203         if(left instanceof ExpressionColumn) {
204             l = (ExpressionColumn)left;
205             if(filter != l.getTableFilter()) {
206                 l = null;
207             }
208         }
209         ExpressionColumn r = null;
210         if(right instanceof ExpressionColumn) {
211             r = (ExpressionColumn)right;
212             if(filter != r.getTableFilter()) {
213                 r = null;
214             }
215         }
216         // one side must be from the current filter
217
if(l==null && r==null) {
218             return;
219         }
220         // filter.addFilterCondition(this, join);
221
// if both sides are part of the same filter, it can't be used for index lookup
222
if(l!=null && r!=null) {
223             return;
224         }
225         boolean addIndex;
226         switch(compareType) {
227         case NOT_EQUAL:
228             addIndex = false;
229             break;
230         case EQUAL:
231         case BIGGER:
232         case BIGGER_EQUAL:
233         case SMALLER_EQUAL:
234         case SMALLER:
235             addIndex = true;
236             break;
237         default:
238             throw Message.getInternalError("type="+compareType);
239         }
240         if(addIndex) {
241             if(l!=null) {
242                 filter.addIndexCondition(new IndexCondition(compareType, l, right));
243             } else if(r!=null) {
244                 int compareRev = getReversedCompareType(compareType);
245                 filter.addIndexCondition(new IndexCondition(compareRev, r, left));
246             }
247         }
248     }
249
250     public void setEvaluatable(TableFilter tableFilter, boolean b) {
251         left.setEvaluatable(tableFilter, b);
252         if(right != null) {
253             right.setEvaluatable(tableFilter, b);
254         }
255     }
256
257     public void updateAggregate(Session session) throws SQLException JavaDoc {
258         left.updateAggregate(session);
259         if(right != null) {
260             right.updateAggregate(session);
261         }
262     }
263     
264     public void addFilterConditions(TableFilter filter, boolean outerJoin) {
265         if(compareType == IS_NULL && outerJoin) {
266             // can not optimize:
267
// select * from test t1 left join test t2 on t1.id = t2.id where t2.id is null
268
// to
269
// select * from test t1 left join test t2 on t1.id = t2.id and t2.id is null
270
return;
271         }
272         super.addFilterConditions(filter, outerJoin);
273     }
274     
275     public void mapColumns(ColumnResolver resolver, int level) throws SQLException JavaDoc {
276         left.mapColumns(resolver, level);
277         if(right!=null) {
278             right.mapColumns(resolver, level);
279         }
280     }
281
282     public boolean isEverything(ExpressionVisitor visitor) {
283         return left.isEverything(visitor) && (right == null || right.isEverything(visitor));
284     }
285     
286     public int getCost() {
287         return left.getCost() + (right == null ? 0 : right.getCost()) + 1;
288     }
289
290 }
291
Popular Tags