KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > impl > sql > compile > JavaValueNode


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.compile.JavaValueNode
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to you under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

21
22 package org.apache.derby.impl.sql.compile;
23
24 import org.apache.derby.iapi.sql.compile.CompilerContext;
25
26 import org.apache.derby.iapi.services.sanity.SanityManager;
27
28 import org.apache.derby.iapi.services.context.ContextManager;
29
30 import org.apache.derby.iapi.types.DataTypeDescriptor;
31
32 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
33
34 import org.apache.derby.iapi.types.TypeId;
35
36 import org.apache.derby.iapi.sql.dictionary.DataDictionary;
37 import org.apache.derby.iapi.error.StandardException;
38 import org.apache.derby.iapi.services.i18n.MessageService;
39 import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
40 import org.apache.derby.impl.sql.compile.ActivationClassBuilder;
41
42 import org.apache.derby.iapi.types.JSQLType;
43
44 import org.apache.derby.iapi.services.compiler.LocalField;
45 import org.apache.derby.iapi.services.compiler.MethodBuilder;
46
47
48 import org.apache.derby.iapi.services.loader.ClassInspector;
49
50 import org.apache.derby.iapi.store.access.Qualifier;
51
52 import org.apache.derby.iapi.util.JBitSet;
53
54 import org.apache.derby.iapi.reference.SQLState;
55
56 import java.lang.reflect.Modifier JavaDoc;
57
58 import java.util.Vector JavaDoc;
59
60 /**
61  * This abstract node class represents a data value in the Java domain.
62  */

63
64 abstract class JavaValueNode extends QueryTreeNode
65 {
66     private boolean mustCastToPrimitive;
67
68     protected boolean forCallStatement;
69     private boolean valueReturnedToSQLDomain;
70     private boolean returnValueDiscarded;
71
72     protected JSQLType jsqlType;
73
74     /* Name of field holding receiver value, if any */
75     private LocalField receiverField;
76
77     public boolean isPrimitiveType() throws StandardException
78     {
79         JSQLType myType = getJSQLType();
80         
81         if ( myType == null ) { return false; }
82         else { return ( myType.getCategory() == JSQLType.JAVA_PRIMITIVE ); }
83     }
84
85     public String JavaDoc getJavaTypeName() throws StandardException
86     {
87         JSQLType myType = getJSQLType();
88
89         if ( myType == null ) { return ""; }
90
91         switch( myType.getCategory() )
92         {
93             case JSQLType.JAVA_CLASS: return myType.getJavaClassName();
94
95             case JSQLType.JAVA_PRIMITIVE: return JSQLType.primitiveNames[ myType.getPrimitiveKind() ];
96
97             default:
98
99                 if (SanityManager.DEBUG)
100                 { SanityManager.THROWASSERT( "Inappropriate JSQLType: " + myType ); }
101         }
102
103         return "";
104     }
105
106     public void setJavaTypeName(String JavaDoc javaTypeName)
107     {
108         jsqlType = new JSQLType( javaTypeName );
109     }
110
111     public String JavaDoc getPrimitiveTypeName()
112         throws StandardException
113     {
114         JSQLType myType = getJSQLType();
115
116         if ( myType == null ) { return ""; }
117
118         switch( myType.getCategory() )
119         {
120             case JSQLType.JAVA_PRIMITIVE: return JSQLType.primitiveNames[ myType.getPrimitiveKind() ];
121
122             default:
123
124                 if (SanityManager.DEBUG)
125                 { SanityManager.THROWASSERT( "Inappropriate JSQLType: " + myType ); }
126         }
127
128         return "";
129     }
130
131     /**
132       * Toggles whether the code generator should add a cast to extract a primitive
133       * value from an object.
134       *
135       * @param booleanValue true if we want the code generator to add a cast
136       * false otherwise
137       */

138     public void castToPrimitive(boolean booleanValue)
139     {
140         mustCastToPrimitive = booleanValue;
141     }
142
143     /**
144       * Reports whether the code generator should add a cast to extract a primitive
145       * value from an object.
146       *
147       * @return true if we want the code generator to add a cast
148       * false otherwise
149       */

150     public boolean mustCastToPrimitive() { return mustCastToPrimitive; }
151
152     /**
153       * Get the JSQLType that corresponds to this node. Could be a SQLTYPE,
154       * a Java primitive, or a Java class.
155       *
156       * @return the corresponding JSQLType
157       *
158       */

159     public JSQLType getJSQLType() throws StandardException
160     { return jsqlType; }
161
162
163     /**
164       * Map a JSQLType to a compilation type id.
165       *
166       * @param jsqlType the universal type to map
167       *
168       * @return the corresponding compilation type id
169       *
170       */

171     public TypeId mapToTypeID( JSQLType jsqlType )
172     {
173         DataTypeDescriptor dts = jsqlType.getSQLType();
174
175         if ( dts == null ) { return null; }
176
177         return dts.getTypeId();
178     }
179
180     /**
181      * Set the clause that this node appears in.
182      *
183      * @param clause The clause that this node appears in.
184      */

185     public void setClause(int clause)
186     {
187         clause = clause;
188     }
189
190     /**
191      * Mark this node as being for a CALL Statement.
192      * (void methods are only okay for CALL Statements)
193      */

194     public void markForCallStatement()
195     {
196         forCallStatement = true;
197     }
198
199     /**
200      * @see ValueNode#remapColumnReferencesToExpressions
201      *
202      * @exception StandardException Thrown on error
203      */

204     abstract public JavaValueNode remapColumnReferencesToExpressions()
205         throws StandardException;
206
207     /**
208      * @see ValueNode#categorize
209      *
210      * @exception StandardException Thrown on error
211      */

212     abstract public boolean categorize(JBitSet referencedTabs, boolean simplePredsOnly)
213         throws StandardException;
214
215     /**
216      * @see ValueNode#bindExpression
217      *
218      * @return the new node, usually this
219      *
220      * @exception StandardException Thrown on error
221      */

222     abstract JavaValueNode bindExpression(FromList fromList, SubqueryList subqueryList,
223                             Vector JavaDoc aggregateVector)
224                             throws StandardException;
225     /**
226      * @see ValueNode#preprocess
227      *
228      * @exception StandardException Thrown on error
229      */

230     abstract public void preprocess(int numTables,
231                                     FromList outerFromList,
232                                     SubqueryList outerSubqueryList,
233                                     PredicateList outerPredicateList)
234                             throws StandardException;
235
236     /** @see ValueNode#getConstantValueAsObject
237      *
238      * @exception StandardException Thrown on error
239      */

240     Object JavaDoc getConstantValueAsObject()
241         throws StandardException
242     {
243         return null;
244     }
245
246     /**
247      * Do the code generation for this node. Call the more general
248      * routine that generates expressions.
249      *
250      * @param acb The ActivationClassBuilder for the class being built
251      * @param mb the method the expression will go into
252      *
253      * @exception StandardException Thrown on error
254      */

255
256     protected final void generate(ActivationClassBuilder acb,
257                                         MethodBuilder mb)
258                                     throws StandardException
259     {
260         generateExpression( acb, mb );
261     }
262
263     /**
264      * Generate the expression that evaluates to the receiver. This is
265      * for the case where a java expression is being returned to the SQL
266      * domain, and we need to check whether the receiver is null (if so,
267      * the SQL value should be set to null, and this Java expression
268      * not evaluated). Instance method calls and field references have
269      * receivers, while class method calls and calls to constructors do
270      * not. If this Java expression does not have a receiver, this method
271      * returns null.
272      *
273      * The implementation of this method should only generate the receiver
274      * once and cache it in a field. This is because there will be two
275      * references to the receiver, and we want to evaluate it only once.
276      *
277      *
278      * @param acb The ExpressionClassBuilder for the class being built
279      * @param mb the method the expression will go into
280      *
281      * @return True if has compiled receiver.
282      *
283      * @exception StandardException Thrown on error
284      */

285     protected boolean generateReceiver(ExpressionClassBuilder acb,
286                                                     MethodBuilder mb)
287                                     throws StandardException
288     {
289         return false;
290     }
291
292     /**
293      * Return the variant type for the underlying expression.
294      * The variant type can be:
295      * VARIANT - variant within a scan
296      * (method calls and non-static field access)
297      * SCAN_INVARIANT - invariant within a scan
298      * (column references from outer tables)
299      * QUERY_INVARIANT - invariant within the life of a query
300      * (constant expressions)
301      *
302      * @return The variant type for the underlying expression.
303      */

304     protected int getOrderableVariantType() throws StandardException
305     {
306         // The default is VARIANT
307
return Qualifier.VARIANT;
308         //return Qualifier.SCAN_INVARIANT;
309
}
310
311     /**
312      * General logic shared by Core compilation and by the Replication Filter
313      * compiler. Every child of ValueNode must implement one of these methods.
314      *
315      * @param acb The ExpressionClassBuilder for the class being built
316      * @param mb the method the expression will go into
317      *
318      * @exception StandardException Thrown on error
319      */

320
321     protected abstract void generateExpression(
322                                             ExpressionClassBuilder acb,
323                                             MethodBuilder mb)
324                                     throws StandardException;
325
326     /**
327      * Generate the expression that evaluates to the receiver. This is
328      * for the case where a java expression is being returned to the SQL
329      * domain, and we need to check whether the receiver is null (if so,
330      * the SQL value should be set to null, and this Java expression
331      * not evaluated). Instance method calls and field references have
332      * receivers, while class method calls and calls to constructors do
333      * not. If this Java expression does not have a receiver, this method
334      * returns null.
335      *
336      * This also covers the case where a java expression is being returned
337      * to the Java domain. In this case, we need to check whether the
338      * receiver is null only if the value returned by the Java expression
339      * is an object (not a primitive type). We don't want to generate the
340      * expression here if we are returning a primitive type to the Java
341      * domain, because there's no point in checking whether the receiver
342      * is null in this case (we can't make the expression return a null
343      * value).
344      *
345      * Only generate the receiver once and cache it in a field. This is
346      * because there will be two references to the receiver, and we want
347      * to evaluate it only once.
348      *
349      *
350      * @param acb The ActivationClassBuilder for the class being built
351      * @param mb the method the expression will go into
352      * @param receiver The query tree form of the receiver expression
353      *
354      * @return The compiled receiver, if any.
355      *
356      * @exception StandardException Thrown on error
357      */

358     protected final boolean generateReceiver(ExpressionClassBuilder acb,
359                                             MethodBuilder mb,
360                                             JavaValueNode receiver)
361                                     throws StandardException
362     {
363         ClassInspector classInspector = getClassFactory().getClassInspector();
364
365         /*
366         ** Don't generate the expression now if it returns a primitive
367         ** type to the Java domain.
368         */

369         if ( (! valueReturnedToSQLDomain()) &&
370                 classInspector.primitiveType(getJavaTypeName()))
371         {
372             return false;
373         }
374
375         /*
376         ** Generate the following:
377         **
378         ** <receiver class> <field name>;
379         ** <field name> = <receiver>;
380         **
381         ** for non-static calls.
382         */

383
384         String JavaDoc receiverClassName = receiver.getJavaTypeName();
385         receiverField =
386                 acb.newFieldDeclaration(Modifier.PRIVATE, receiverClassName);
387
388         receiver.generateExpression(acb, mb);
389         mb.putField(receiverField);
390         return true;
391     }
392
393     /**
394      * Get an expression that has the value of the receiver. If a field
395      * holding the receiver value was already generated, use that. If not,
396      * generate the receiver value.
397      *
398      * @param acb The ExpressionClassBuilder for the class we're generating
399      * @param mb the method the expression will go into
400      * @param receiver The query tree form of the receiver expression
401      *
402      *
403      * @exception StandardException Thrown on error
404      */

405     protected final void getReceiverExpression(ExpressionClassBuilder acb,
406                                     MethodBuilder mb,
407                                     JavaValueNode receiver)
408                                         throws StandardException
409     {
410         if (receiverField != null)
411         {
412             mb.getField(receiverField);
413         }
414         else
415         {
416             receiver.generateExpression(acb, mb);
417         }
418     }
419
420     /** Inform this node that it returns its value to the SQL domain */
421     protected void returnValueToSQLDomain()
422     {
423         valueReturnedToSQLDomain = true;
424     }
425
426     /** Tell whether this node returns its value to the SQL domain */
427     protected boolean valueReturnedToSQLDomain()
428     {
429         return valueReturnedToSQLDomain;
430     }
431
432     /** Tell this node that nothing is done with the returned value */
433     protected void markReturnValueDiscarded()
434     {
435         returnValueDiscarded = true;
436     }
437
438     /** Tell whether the return value from this node is discarded */
439     protected boolean returnValueDiscarded()
440     {
441         return returnValueDiscarded;
442     }
443
444     /**
445         Check the reliability type of this java value.
446
447         @exception StandardException Thrown on error
448
449         @see org.apache.derby.iapi.sql.compile.CompilerContext
450     */

451     public void checkReliability(ValueNode sqlNode) throws StandardException {
452         sqlNode.checkReliability(
453                 CompilerContext.FUNCTION_CALL_ILLEGAL,
454                 SQLState.LANG_JAVA_METHOD_CALL_OR_FIELD_REF
455                 );
456     }
457 }
458
Popular Tags