KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.compile.UserTypeConstantNode
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.error.StandardException;
25
26 import org.apache.derby.iapi.types.TypeId;
27 import org.apache.derby.iapi.types.UserDataValue;
28
29 import org.apache.derby.iapi.sql.compile.TypeCompiler;
30
31 import org.apache.derby.iapi.services.compiler.MethodBuilder;
32 import org.apache.derby.iapi.services.compiler.LocalField;
33 import org.apache.derby.iapi.services.io.StoredFormatIds;
34
35 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
36
37 import org.apache.derby.iapi.types.DataValueFactory;
38
39 import org.apache.derby.iapi.types.TypeId;
40
41 import org.apache.derby.iapi.types.TypeId;
42
43 import org.apache.derby.iapi.types.DataValueDescriptor;
44
45 import org.apache.derby.iapi.services.sanity.SanityManager;
46 import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
47
48 import org.apache.derby.iapi.reference.ClassName;
49
50 import org.apache.derby.catalog.TypeDescriptor;
51
52 import org.apache.derby.iapi.util.ReuseFactory;
53 import org.apache.derby.iapi.services.classfile.VMOpcode;
54 import org.apache.derby.iapi.types.*;
55
56 import java.lang.reflect.Modifier JavaDoc;
57 import java.sql.Date JavaDoc;
58 import java.sql.Time JavaDoc;
59 import java.sql.Timestamp JavaDoc;
60 import java.sql.Types JavaDoc;
61
62 /**
63     User type constants. These are created by built-in types
64     that use user types as their implementation. This could also
65     potentially be used by an optimizer that wanted to store plans
66     for frequently-used parameter values.
67
68     This is also used to represent nulls in user types, which occurs
69     when NULL is inserted into or supplied as the update value for
70     a usertype column.
71
72     @author ames
73  */

74 public class UserTypeConstantNode extends ConstantNode {
75     /*
76     ** This value field hides the value in the super-type. It is here
77     ** Because user-type constants work differently from built-in constants.
78     ** User-type constant values are stored as Objects, while built-in
79     ** constants are stored as StorableDataValues.
80     **
81     ** RESOLVE: This is a bit of a mess, and should be fixed. All constants
82     ** should be represented the same way.
83     */

84     Object JavaDoc value;
85
86     /**
87      * Initializer for a typed null node
88      * or a date, time, or timestamp value. Parameters may be:
89      *
90      * <ul>
91      * <li>arg1 The TypeId for the type of the node</li>
92      * <li>arg2 The factory to get the TypeId and DataTypeServices factories from.</li>
93      * </ul>
94      *
95      * <p>
96      * - OR -
97      * </p>
98      *
99      * <ul>
100      * <li>arg1 the date, time, or timestamp value</li>
101      * </ul>
102      *
103      * @exception StandardException thrown on failure
104      */

105     public void init(Object JavaDoc arg1)
106             throws StandardException {
107         DataValueDescriptor dvd = null;
108         
109         if (arg1 instanceof TypeId)
110         {
111             super.init(
112                     arg1,
113                     Boolean.TRUE,
114                     ReuseFactory.getInteger(
115                                         TypeDescriptor.MAXIMUM_WIDTH_UNKNOWN));
116         }
117         else
118         {
119             Integer JavaDoc maxWidth = null;
120             TypeId typeId = null;
121
122             if( arg1 instanceof DataValueDescriptor)
123                 dvd = (DataValueDescriptor) arg1;
124             if (arg1 instanceof Date JavaDoc
125                 || (dvd != null && dvd.getTypeFormatId() == StoredFormatIds.SQL_DATE_ID))
126             {
127                 maxWidth = ReuseFactory.getInteger(TypeId.DATE_MAXWIDTH);
128                 typeId = TypeId.getBuiltInTypeId(Types.DATE);
129             }
130             else if (arg1 instanceof Time JavaDoc
131                      || (dvd != null && dvd.getTypeFormatId() == StoredFormatIds.SQL_TIME_ID))
132             {
133                 maxWidth = ReuseFactory.getInteger(TypeId.TIME_MAXWIDTH);
134                 typeId = TypeId.getBuiltInTypeId(Types.TIME);
135             }
136             else if (arg1 instanceof Timestamp JavaDoc
137                      || (dvd != null && dvd.getTypeFormatId() == StoredFormatIds.SQL_TIMESTAMP_ID))
138             {
139                 maxWidth = ReuseFactory.getInteger(TypeId.TIMESTAMP_MAXWIDTH);
140                 typeId = TypeId.getBuiltInTypeId(Types.TIMESTAMP);
141             }
142             else
143             {
144                 if (SanityManager.DEBUG)
145                 {
146                     SanityManager.THROWASSERT(
147                             "Unexpected class " + arg1.getClass().getName());
148                 }
149             }
150
151             super.init(
152                 typeId,
153                 (arg1 == null) ? Boolean.TRUE : Boolean.FALSE,
154                 maxWidth);
155
156             if( dvd != null)
157                 setValue( dvd);
158             else if (arg1 instanceof Date JavaDoc)
159             {
160                 setValue(getDataValueFactory().getDataValue((Date JavaDoc) arg1));
161             }
162             else if (arg1 instanceof Time JavaDoc)
163             {
164                 setValue(getDataValueFactory().getDataValue((Time JavaDoc) arg1));
165             }
166             else if (arg1 instanceof Timestamp JavaDoc)
167             {
168                 setValue(getDataValueFactory().getDataValue((Timestamp JavaDoc) arg1));
169             }
170
171             value = arg1;
172         }
173     }
174
175     /**
176      * Return the object value of this user defined type.
177      *
178      * @return the value of this constant. can't use getValue() for this.
179      * getValue() returns the DataValueDescriptor for the built-in
180      * types that are implemented as user types (date, time, timestamp)
181      */

182     public Object JavaDoc getObjectValue() { return value; }
183
184     /**
185      * Return whether or not this node represents a typed null constant.
186      *
187      */

188     public boolean isNull()
189     {
190         return (value == null);
191     }
192
193     /**
194      * Return the value of this user defined type as a Storable
195      *
196      * @return the value of this constant as a UserType
197      * @exception StandardException thrown on failure
198      */

199     public DataValueDescriptor getStorableValue()
200             throws StandardException
201     {
202         if( value instanceof DataValueDescriptor)
203             return ((DataValueDescriptor) value).getClone();
204         
205         DataValueFactory dvf = getDataValueFactory();
206         TypeId typeID = getTypeId();
207         String JavaDoc typeName = typeID.getSQLTypeName();
208
209         if ( typeName.equals( TypeId.DATE_NAME ) )
210         {
211             return new SQLDate((Date JavaDoc) value);
212         }
213         else if ( typeName.equals( TypeId.TIME_NAME ) )
214         {
215             return new SQLTime( (Time JavaDoc) value);
216         }
217         else if ( typeName.equals( TypeId.TIMESTAMP_NAME ) )
218         {
219             return new SQLTimestamp( (Timestamp JavaDoc) value);
220         }
221         else
222         {
223             return dvf.getDataValue( value, (UserDataValue) null );
224         }
225     }
226
227     /**
228      * Sets the object value of this user defined type
229      *
230      * @param newValue the value of this constant. can't use setValue() for this.
231      */

232     public void setObjectValue( Object JavaDoc newValue ) { value = newValue; }
233
234     /**
235      * Return the length
236      *
237      * @return The length of the value this node represents
238      *
239      * @exception StandardException Thrown on error
240      */

241     //public int getLength() throws StandardException {
242
// return TypeDescriptor.MAXIMUM_WIDTH_UNKNOWN;
243
//}
244

245     /**
246      * Return an Object representing the bind time value of this
247      * expression tree. If the expression tree does not evaluate to
248      * a constant at bind time then we return null.
249      * This is useful for bind time resolution of VTIs.
250      * RESOLVE: What do we do for primitives?
251      *
252      * @return An Object representing the bind time value of this expression tree.
253      * (null if not a bind time constant.)
254      *
255      */

256     public Object JavaDoc getConstantValueAsObject()
257     {
258         return value;
259     }
260
261     /**
262      * For a UserTypeConstantNode, we have to store away the object somewhere
263      * and have a way to get it back at runtime.
264      * These objects are serializable. This gives us at least two options:
265      * 1) serialize it out into a byte array field, and serialize
266      * it back in when needed, from the field.
267      * 2) have an array of objects in the prepared statement and a #,
268      * to find the object directly. Because it is serializable, it
269      * will store with the rest of the executable just fine.
270      * Choice 2 gives better performance -- the ser/deser cost is paid
271      * on database access for the statement, not for each execution of it.
272      * However, it requires some infrastructure support from prepared
273      * statements. For now, we take choice 3, and make some assumptions
274      * about available methods on the user type. This choice has the
275      * shortcoming that it will not work for arbitrary user types.
276      * REVISIT and implement choice 2 when a general solution is needed.
277      * <p>
278      * A null is generated as a Null value cast to the type of
279      * the constant node.
280      *
281      * @param acb The ExpressionClassBuilder for the class being built
282      * @param mb The method the expression will go into
283      *
284      *
285      * @exception StandardException Thrown on error
286      */

287     public void generateExpression(ExpressionClassBuilder acb,
288                                             MethodBuilder mb)
289                                     throws StandardException {
290
291         TypeCompiler tc = getTypeCompiler();
292         String JavaDoc fieldType = tc.interfaceName();
293
294         /*
295         ** NOTE: DO NOT CALL THE CONSTRUCTOR TO GENERATE ANYTHING. IT HAS
296         ** A DIFFERENT value FIELD.
297         */

298         
299         /* Are we generating a SQL null value? */
300         if (value == null)
301         {
302             acb.generateNull(mb, tc);
303         }
304         // The code generated here is invoked when the generated class is constructed. However the prepared statement
305
// is not set into the activation class when it is constructed, but later. So we cannot use the getSavedObject
306
// method to retrieve the value.
307
// else if( value instanceof DataValueDescriptor)
308
// {
309
// acb.pushThisAsActivation( mb);
310
// mb.callMethod( VMOpcode.INVOKEINTERFACE,
311
// null,
312
// "getPreparedStatement",
313
// ClassName.ExecPreparedStatement,
314
// 0);
315
// mb.push( acb.addItem( value));
316
// mb.callMethod( VMOpcode.INVOKEINTERFACE,
317
// null,
318
// "getSavedObject",
319
// "java.lang.Object",
320
// 1);
321
// mb.cast( fieldType);
322
// }
323
else
324         {
325             /*
326                 The generated java is the expression:
327                     <java type name>.valueOf("<value.toString>")
328
329                 super.generateValue will wrap this expression in
330                 the appropriate column constructor.
331
332                 If the type doesn't have a valueOf method, then we will
333                 give an error. We have to assume that valueOf will
334                 reconstruct the object from a String literal. If this is
335                 a false assumption, some other object may be constructed,
336                 or a runtime error may result due to valueOf failing.
337             */

338             String JavaDoc typeName = getTypeId().getCorrespondingJavaTypeName();
339
340             mb.push(value.toString());
341             mb.callMethod(VMOpcode.INVOKESTATIC, typeName, "valueOf", typeName, 1);
342
343             LocalField field = acb.newFieldDeclaration(Modifier.PRIVATE, fieldType);
344
345             acb.generateDataValue(mb, tc, field);
346         }
347     }
348
349
350     /**
351      * Should never be called for UserTypeConstantNode because
352      * we have our own generateExpression().
353      *
354      * @param acb The ExpressionClassBuilder for the class being built
355      * @param mb The method the expression will go into
356      *
357      * @exception StandardException Thrown on error
358      */

359     void generateConstant(ExpressionClassBuilder acb, MethodBuilder mb)
360     throws StandardException
361     {
362         if (SanityManager.DEBUG)
363         {
364             SanityManager.THROWASSERT("geneateConstant() not expected to be called for UserTypeConstantNode because we have implemented our own generateExpression().");
365         }
366     }
367 }
368
Popular Tags