KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > oracle > toplink > essentials > internal > expressions > SubSelectExpression


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the "License"). You may not use this file except
5  * in compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * glassfish/bootstrap/legal/CDDLv1.0.txt or
9  * https://glassfish.dev.java.net/public/CDDLv1.0.html.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * HEADER in each file and include the License file at
15  * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable,
16  * add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your
18  * own identifying information: Portions Copyright [yyyy]
19  * [name of copyright owner]
20  */

21 // Copyright (c) 1998, 2006, Oracle. All rights reserved.
22
package oracle.toplink.essentials.internal.expressions;
23
24 import java.io.*;
25 import java.util.*;
26 import oracle.toplink.essentials.queryframework.*;
27 import oracle.toplink.essentials.expressions.*;
28 import oracle.toplink.essentials.internal.queryframework.*;
29
30 /**
31  * This is used to support subselects.
32  * The subselect represents a mostly independent (has own expression builder) query using a report query.
33  * Subselects can be used for, in (single column), exists (empty or non-empty), comparisons (single value).
34  */

35 public class SubSelectExpression extends Expression {
36     protected Expression baseExpression;
37     protected ReportQuery subQuery;
38
39     public SubSelectExpression() {
40         super();
41     }
42
43     public SubSelectExpression(ReportQuery query, Expression baseExpression) {
44         this();
45         this.subQuery = query;
46         this.baseExpression = baseExpression;
47     }
48
49     /**
50      * INTERNAL:
51      * Used in debug printing of this node.
52      */

53     public String JavaDoc descriptionOfNodeType() {
54         return "SubSelect";
55     }
56
57     public Expression getBaseExpression() {
58         return baseExpression;
59     }
60
61     /**
62      * Return the builder from the defining expression.
63      */

64     public ExpressionBuilder getBuilder() {
65         return getBaseExpression().getBuilder();
66     }
67
68     public ReportQuery getSubQuery() {
69         return subQuery;
70     }
71
72     /**
73      * INTERNAL:
74      * For iterating using an inner class
75      */

76     public void iterateOn(ExpressionIterator iterator) {
77         super.iterateOn(iterator);
78         if (baseExpression != null) {
79             baseExpression.iterateOn(iterator);
80         }
81
82         // For Flashback: It is now possible to create iterators that will span
83
// the entire expression, even the where clause embedded in a subQuery.
84
if (iterator.shouldIterateOverSubSelects()) {
85             if (getSubQuery().getSelectionCriteria() != null) {
86                 getSubQuery().getSelectionCriteria().iterateOn(iterator);
87             } else {
88                 getSubQuery().getExpressionBuilder().iterateOn(iterator);
89             }
90         }
91     }
92
93     /**
94      * INTERNAL:
95      * The subquery must be normalized with the knowledge of the outer statement for outer references and correct aliasing.
96      * For CR#4223 it will now be normalized after the outer statement is, rather than
97      * somewhere in the middle of the outer statement's normalize.
98      */

99     public Expression normalize(ExpressionNormalizer normalizer) {
100         //has no effect but validateNode is here for consistency
101
validateNode();
102         // Defer normalization of this expression until later.
103
normalizer.addSubSelectExpression(this);
104         normalizer.getStatement().setRequiresAliases(true);
105         return this;
106     }
107
108     /**
109      * INTERNAL:
110      * Normalize this expression now that the parent statment has been normalized.
111      * For CR#4223
112      */

113     public Expression normalizeSubSelect(ExpressionNormalizer normalizer, Dictionary clonedExpressions) {
114         // Anonymous subqueries: The following is to support sub-queries created
115
// on the fly by OSQL Expressions isEmpty(), isNotEmpty(), size().
116
if (!getSubQuery().isCallQuery() && (getSubQuery().getReferenceClass() == null)) {
117             ReportQuery subQuery = getSubQuery();
118             Expression criteria = subQuery.getSelectionCriteria();
119
120             // The criteria should be of form builder.equal(exp), where exp belongs
121
// to the parent statement and has already been normalized, hence it
122
// knows its reference class.
123
if (criteria instanceof LogicalExpression) {
124                 criteria = ((LogicalExpression)criteria).getFirstChild();
125             }
126             if (criteria instanceof RelationExpression) {
127                 Expression rightChild = ((RelationExpression)criteria).getSecondChild();
128                 if (rightChild instanceof QueryKeyExpression) {
129                     subQuery.setReferenceClass(((QueryKeyExpression)rightChild).getDescriptor().getJavaClass());
130                 }
131             }
132         }
133
134         //has no effect but validateNode is here for consistency
135
validateNode();
136         getSubQuery().prepareSubSelect(normalizer.getSession(), null, clonedExpressions);
137         if (!getSubQuery().isCallQuery()) {
138             SQLSelectStatement statement = (SQLSelectStatement)((StatementQueryMechanism)getSubQuery().getQueryMechanism()).getSQLStatement();
139
140             // setRequiresAliases was already set for parent statement.
141
statement.setRequiresAliases(true);
142             statement.setParentStatement(normalizer.getStatement());
143             statement.normalize(normalizer.getSession(), getSubQuery().getDescriptor(), clonedExpressions);
144         }
145         return this;
146     }
147
148     /**
149      * The query must be cloned, and the sub-expression must be cloned using the same outer expression identity.
150      */

151     protected void postCopyIn(Dictionary alreadyDone) {
152         super.postCopyIn(alreadyDone);
153         setBaseExpression(getBaseExpression().copiedVersionFrom(alreadyDone));
154         ReportQuery clonedQuery = (ReportQuery)getSubQuery().clone();
155         if ((!clonedQuery.isCallQuery()) && (clonedQuery.getSelectionCriteria() != null)) {
156             clonedQuery.setSelectionCriteria(getSubQuery().getSelectionCriteria().copiedVersionFrom(alreadyDone));
157
158             // If we are building/cloning a selection criteria for a batch query, a little extra work
159
// needs to be done (see bug 2812185).
160
if (alreadyDone.get(alreadyDone) != null) {
161                 clonedQuery.copyReportItems(alreadyDone);
162             }
163         }
164         setSubQuery(clonedQuery);
165     }
166
167     /**
168      * Print the sub query to the printer.
169      */

170     protected void printCustomSQL(ExpressionSQLPrinter printer) {
171
172         /*
173          * modified for bug#2658466. This fix ensures that Custom SQL sub-queries are translated
174          * and have variables substituted with values correctly.
175          */

176         SQLCall call = (SQLCall)getSubQuery().getCall();
177         call.translateCustomQuery();
178         printer.getCall().getParameters().addAll(call.getParameters());
179         printer.getCall().getParameterTypes().addAll(call.getParameterTypes());
180         printer.printString(call.getCallString());
181     }
182
183     /**
184      * Print the sub query to the printer.
185      */

186     public void printSQL(ExpressionSQLPrinter printer) {
187         ReportQuery query = getSubQuery();
188         printer.printString("(");
189         if (query.isCallQuery()) {
190             printCustomSQL(printer);
191         } else {
192             SQLSelectStatement statement = (SQLSelectStatement)((ExpressionQueryMechanism)query.getQueryMechanism()).getSQLStatement();
193             boolean isFirstElementPrinted = printer.isFirstElementPrinted();
194             printer.setIsFirstElementPrinted(false);
195             boolean requiresDistinct = printer.requiresDistinct();
196             statement.printSQL(printer);
197             printer.setIsFirstElementPrinted(isFirstElementPrinted);
198             printer.setRequiresDistinct(requiresDistinct);
199         }
200         printer.printString(")");
201     }
202
203     /**
204      * Should not rebuild as has its on expression builder.
205      */

206     public Expression rebuildOn(Expression newBase) {
207         return this;
208     }
209
210     protected void setBaseExpression(Expression baseExpression) {
211         this.baseExpression = baseExpression;
212     }
213
214     public void setSubQuery(ReportQuery subQuery) {
215         this.subQuery = subQuery;
216     }
217
218     /**
219      * INTERNAL:
220      * Used to print a debug form of the expression tree.
221      */

222     public void writeDescriptionOn(BufferedWriter writer) throws IOException {
223         writer.write(String.valueOf(getSubQuery()));
224     }
225
226     /**
227      * INTERNAL:
228      * Used in SQL printing.
229      */

230     public void writeSubexpressionsTo(BufferedWriter writer, int indent) throws IOException {
231         if (getSubQuery().getSelectionCriteria() != null) {
232             getSubQuery().getSelectionCriteria().toString(writer, indent);
233         }
234     }
235 }
236
Popular Tags