KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > triactive > jdo > store > QueryStatement


1 /*
2  * Copyright 2002 (C) TJDO.
3  * All rights reserved.
4  *
5  * This software is distributed under the terms of the TJDO License version 1.0.
6  * See the terms of the TJDO License in the documentation provided with this software.
7  *
8  * $Id: QueryStatement.java,v 1.6 2003/08/11 16:01:52 pierreg0 Exp $
9  */

10
11 package com.triactive.jdo.store;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.HashMap JavaDoc;
15 import java.util.Iterator JavaDoc;
16 import javax.jdo.JDOFatalInternalException;
17
18
19 public class QueryStatement
20 {
21     protected final StoreManager storeMgr;
22     protected final DatabaseAdapter dba;
23     protected final SQLIdentifier defaultRangeVar;
24     protected final TableExpression initialTableExpr;
25
26     protected HashMap JavaDoc tableExprsByRangeVar = new HashMap JavaDoc();
27     protected boolean distinctResults = false;
28     protected ArrayList JavaDoc selected = new ArrayList JavaDoc();
29     protected ArrayList JavaDoc joins = new ArrayList JavaDoc();
30     protected BooleanExpression whereExpr = null;
31     protected StatementText orderByList = null;
32     protected StatementText stmtText = null;
33
34     public QueryStatement(Table initialTable)
35     {
36         this.storeMgr = initialTable.getStoreManager();
37         this.dba = storeMgr.getDatabaseAdapter();
38
39         defaultRangeVar = new TableIdentifier(dba, "this");
40
41         initialTableExpr = newTableExpression(initialTable, defaultRangeVar);
42         tableExprsByRangeVar.put(defaultRangeVar, initialTableExpr);
43     }
44
45     public QueryStatement(Table initialTable, SQLIdentifier initialRangeVar)
46     {
47         this.storeMgr = initialTable.getStoreManager();
48         this.dba = storeMgr.getDatabaseAdapter();
49
50         defaultRangeVar = new TableIdentifier(dba, "this");
51
52         initialTableExpr = newTableExpression(initialTable, initialRangeVar);
53         tableExprsByRangeVar.put(initialRangeVar, initialTableExpr);
54     }
55
56     protected void assertNotFrozen()
57     {
58         if (stmtText != null)
59             throw new JDOFatalInternalException("A query statement cannot be modified after being output");
60     }
61
62     public StoreManager getStoreManager()
63     {
64         return storeMgr;
65     }
66
67     public TableExpression getTableExpression(SQLIdentifier rangeVar)
68     {
69         return (TableExpression)tableExprsByRangeVar.get(rangeVar);
70     }
71
72     public TableExpression getDefaultTableExpression()
73     {
74         return getTableExpression(defaultRangeVar);
75     }
76
77     public TableExpression newTableExpression(Table mainTable, SQLIdentifier rangeVar)
78     {
79         assertNotFrozen();
80
81         TableExpression te = (TableExpression)tableExprsByRangeVar.get(rangeVar);
82
83         if (te == null)
84         {
85             te = dba.newTableExpression(this, mainTable, rangeVar);
86
87             tableExprsByRangeVar.put(rangeVar, te);
88         }
89         else
90         {
91             if (!te.getMainTable().equals(mainTable))
92                 throw new JDOFatalInternalException("Range variable " + rangeVar + " already in use in query: " + this);
93         }
94
95         return te;
96     }
97
98     public boolean getDistinctResults()
99     {
100         return distinctResults;
101     }
102
103     public void setDistinctResults(boolean distinctResults)
104     {
105         assertNotFrozen();
106
107         this.distinctResults = distinctResults;
108     }
109
110     public int select(Column col)
111     {
112         return select(defaultRangeVar, col);
113     }
114
115     public int select(SQLIdentifier rangeVar, Column col)
116     {
117         assertNotFrozen();
118
119         String JavaDoc columnID = getColumn(rangeVar, col).toString();
120
121         if (!selected.contains(columnID))
122             selected.add(columnID);
123
124         return selected.indexOf(columnID) + 1;
125     }
126
127     public int columnsSelected()
128     {
129         return selected.size();
130     }
131
132     public QueryColumn getColumn(Column col)
133     {
134         return getColumn(defaultRangeVar, col);
135     }
136
137     public QueryColumn getColumn(SQLIdentifier rangeVar, Column col)
138     {
139         TableExpression te = (TableExpression)tableExprsByRangeVar.get(rangeVar);
140
141         if (te == null)
142             throw new JDOFatalInternalException("No such range variable: " + rangeVar);
143
144         return getColumn(te, col);
145     }
146
147     public QueryColumn getColumn(TableExpression te, Column col)
148     {
149         return new QueryColumn(te, col);
150     }
151
152     public void innerJoin(QueryColumn from, QueryColumn to)
153     {
154         assertNotFrozen();
155
156         joins.add(new Join("INNER JOIN", from, to));
157     }
158
159     public void leftOuterJoin(QueryColumn from, QueryColumn to)
160     {
161         assertNotFrozen();
162
163         joins.add(new Join("LEFT OUTER JOIN", from, to));
164     }
165
166     public void rightOuterJoin(QueryColumn from, QueryColumn to)
167     {
168         assertNotFrozen();
169
170         joins.add(new Join("RIGHT OUTER JOIN", from, to));
171     }
172
173     public void andCondition(BooleanExpression condition)
174     {
175         assertNotFrozen();
176
177         if (whereExpr == null)
178             whereExpr = condition;
179         else
180             whereExpr = whereExpr.and(condition);
181     }
182
183     public void setOrdering(SQLExpression[] exprs, boolean[] descending)
184     {
185         assertNotFrozen();
186
187         boolean needsSelect = dba.includeOrderByColumnsInSelect();
188
189         orderByList = new StatementText();
190
191         for (int i = 0; i < exprs.length; ++i)
192         {
193             if (i > 0)
194                 orderByList.append(',');
195
196             orderByList.append(exprs[i]);
197
198             if (descending[i])
199                 orderByList.append(" DESC");
200
201             if (needsSelect)
202             {
203                 Iterator JavaDoc j = exprs[i].toStatementText().getReferencedColumns().iterator();
204
205                 while (j.hasNext())
206                 {
207                     String JavaDoc columnRef = j.next().toString();
208
209                     if (!selected.contains(columnRef))
210                         selected.add(columnRef);
211                 }
212             }
213         }
214     }
215
216     public StatementText toStatementText()
217     {
218         if (stmtText == null)
219         {
220             stmtText = new StatementText("SELECT ");
221
222             if (distinctResults)
223                 stmtText.append("DISTINCT ");
224
225             Iterator JavaDoc i = selected.iterator();
226
227             while (i.hasNext())
228             {
229                 stmtText.append(i.next());
230
231                 if (i.hasNext())
232                     stmtText.append(',');
233             }
234
235             stmtText.append(" FROM ").append(initialTableExpr);
236
237             i = joins.iterator();
238
239             while (i.hasNext())
240                 stmtText.append(' ').append(i.next());
241
242             if (whereExpr != null)
243                 stmtText.append(" WHERE ").append(whereExpr);
244
245             if (orderByList != null)
246                 stmtText.append(" ORDER BY ").append(orderByList);
247         }
248
249         return stmtText;
250     }
251
252     public String JavaDoc toString()
253     {
254         return toStatementText().toString();
255     }
256
257     protected static class Join
258     {
259         private final String JavaDoc type;
260         private final TableExpression te;
261         private final String JavaDoc condition;
262
263         public Join(String JavaDoc type, QueryColumn from, QueryColumn to)
264         {
265             this.type = type;
266
267             /*
268              * Believe it or not, the order of converting things to string here
269              * is important; that's why 'condition' is constructed in advance.
270              * QueryColumn.toString() has a side effect: if its TableExpression
271              * employs a subquery it causes the column to get SELECTed in that
272              * subquery.
273              *
274              * to.te.toString() actually freezes to.te, which means you can no
275              * longer call to.toString(), so they have to be called in the other
276              * order.
277              *
278              * I'm not particularly happy with it either but I haven't yet
279              * figured out a better way to model things.
280              */

281             te = to.te;
282             condition = from + " = " + to;
283         }
284
285         public String JavaDoc toString()
286         {
287             return type + " " + te + " ON " + condition;
288         }
289     }
290
291     public class QueryColumn
292     {
293         public final TableExpression te;
294         public final Column column;
295
296         private QueryColumn(TableExpression te, Column column)
297         {
298             this.te = te;
299             this.column = column;
300         }
301
302         public QueryStatement getQueryStatement()
303         {
304             return QueryStatement.this;
305         }
306
307         public int hashCode()
308         {
309             return te.hashCode() ^ column.hashCode();
310         }
311
312         public boolean equals(Object JavaDoc o)
313         {
314             if (o == this)
315                 return true;
316
317             if (!(o instanceof QueryColumn))
318                 return false;
319
320             QueryColumn qsc = (QueryColumn)o;
321
322             return te.equals(qsc.te) && column.equals(qsc.column);
323         }
324
325         public String JavaDoc toString()
326         {
327             return te.referenceColumn(column);
328         }
329     }
330 }
331
Popular Tags