KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > iapi > types > DataTypeDescriptor


1 /*
2
3    Derby - Class org.apache.derby.iapi.types.DataTypeDescriptor
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.iapi.types;
23
24 import org.apache.derby.iapi.services.io.Formatable;
25 import org.apache.derby.iapi.error.StandardException;
26 import org.apache.derby.iapi.services.loader.ClassFactory;
27
28 import org.apache.derby.catalog.TypeDescriptor;
29 import org.apache.derby.catalog.types.TypeDescriptorImpl;
30
31 import org.apache.derby.iapi.services.sanity.SanityManager;
32
33 import org.apache.derby.iapi.services.io.StoredFormatIds;
34 import org.apache.derby.iapi.services.io.FormatIdUtil;
35 import org.apache.derby.iapi.services.io.Formatable;
36
37 import org.apache.derby.iapi.error.StandardException;
38
39 import org.apache.derby.iapi.types.RowLocation;
40
41 import org.apache.derby.iapi.services.loader.ClassFactory;
42 import org.apache.derby.iapi.services.loader.ClassInspector;
43
44
45 import org.apache.derby.iapi.reference.SQLState;
46
47 import java.io.ObjectOutput JavaDoc;
48 import java.io.ObjectInput JavaDoc;
49 import java.io.IOException JavaDoc;
50
51 import java.sql.Types JavaDoc;
52
53 /**
54  * This is an implementation of DataTypeDescriptor from the generic language
55  * datatype module interface.
56  *
57  * @author Jeff Lichtman
58  * @version 1.0
59  */

60
61 public final class DataTypeDescriptor implements TypeDescriptor, Formatable
62 {
63     /********************************************************
64     **
65     ** This class implements Formatable. That means that it
66     ** can write itself to and from a formatted stream. If
67     ** you add more fields to this class, make sure that you
68     ** also write/read them with the writeExternal()/readExternal()
69     ** methods.
70     **
71     ** If, inbetween releases, you add more fields to this class,
72     ** then you should bump the version number emitted by the getTypeFormatId()
73     ** method.
74     **
75     ********************************************************/

76
77     /*
78     ** Static creators
79     */

80     /**
81      * Get a descriptor that corresponds to a builtin JDBC type.
82      *
83      * @param jdbcType The int type of the JDBC type for which to get
84      * a corresponding SQL DataTypeDescriptor
85      *
86      * @return A new DataTypeDescriptor that corresponds to the Java type.
87      * A null return value means there is no corresponding SQL type
88      */

89     public static DataTypeDescriptor getBuiltInDataTypeDescriptor
90     (
91         int jdbcType
92     )
93     {
94         return DataTypeDescriptor.getBuiltInDataTypeDescriptor(jdbcType, true);
95     }
96     public static DataTypeDescriptor getBuiltInDataTypeDescriptor
97     (
98         int jdbcType,
99         int length
100     )
101     {
102         return DataTypeDescriptor.getBuiltInDataTypeDescriptor(jdbcType, true, length);
103     }
104
105     /**
106      * Get a descriptor that corresponds to a builtin JDBC type.
107      *
108      * @param jdbcType The int type of the JDBC type for which to get
109      * a corresponding SQL DataTypeDescriptor
110      * @param isNullable TRUE means it could contain NULL, FALSE means
111      * it definitely cannot contain NULL.
112      *
113      * @return A new DataTypeDescriptor that corresponds to the Java type.
114      * A null return value means there is no corresponding SQL type
115      */

116     public static DataTypeDescriptor getBuiltInDataTypeDescriptor
117     (
118         int jdbcType,
119         boolean isNullable
120     )
121     {
122         TypeId typeId = TypeId.getBuiltInTypeId(jdbcType);
123         if (typeId == null)
124         {
125             return null;
126         }
127
128         return new DataTypeDescriptor(typeId, isNullable);
129     }
130     /**
131      * Get a descriptor that corresponds to a builtin JDBC type.
132      *
133      * @param jdbcType The int type of the JDBC type for which to get
134      * a corresponding SQL DataTypeDescriptor
135      * @param isNullable TRUE means it could contain NULL, FALSE means
136      * it definitely cannot contain NULL.
137      *
138      * @return A new DataTypeDescriptor that corresponds to the Java type.
139      * A null return value means there is no corresponding SQL type
140      */

141     public static DataTypeDescriptor getBuiltInDataTypeDescriptor
142     (
143         int jdbcType,
144         boolean isNullable,
145         int maxLength
146     )
147     {
148         TypeId typeId = TypeId.getBuiltInTypeId(jdbcType);
149         if (typeId == null)
150         {
151             return null;
152         }
153
154         return new DataTypeDescriptor(typeId, isNullable, maxLength);
155     }
156     /**
157      * Get a DataTypeServices that corresponds to a builtin SQL type
158      *
159      * @param sqlTypeName The name of the type for which to get
160      * a corresponding SQL DataTypeDescriptor
161      *
162      * @return A new DataTypeDescriptor that corresponds to the Java type.
163      * A null return value means there is no corresponding SQL type (only for 'char')
164      */

165     public static DataTypeDescriptor getBuiltInDataTypeDescriptor
166     (
167         String JavaDoc sqlTypeName
168     )
169     {
170         return new DataTypeDescriptor(TypeId.getBuiltInTypeId(sqlTypeName), true);
171     }
172     /**
173      * Get a DataTypeServices that corresponds to a builtin SQL type
174      *
175      * @param sqlTypeName The name of the type for which to get
176      * a corresponding SQL DataTypeDescriptor
177      *
178      * @return A new DataTypeDescriptor that corresponds to the Java type.
179      * A null return value means there is no corresponding SQL type (only for 'char')
180      */

181     public static DataTypeDescriptor getBuiltInDataTypeDescriptor
182     (
183         String JavaDoc sqlTypeName,
184         int length
185     )
186     {
187         return new DataTypeDescriptor(TypeId.getBuiltInTypeId(sqlTypeName), true, length);
188     }
189     /**
190      * Get a DataTypeServices that corresponds to a Java type
191      *
192      * @param javaTypeName The name of the Java type for which to get
193      * a corresponding SQL DataTypeDescriptor
194      *
195      * @return A new DataTypeDescriptor that corresponds to the Java type.
196      * A null return value means there is no corresponding SQL type (only for 'char')
197      */

198     public static DataTypeDescriptor getSQLDataTypeDescriptor
199     (
200         String JavaDoc javaTypeName
201     )
202     {
203             return DataTypeDescriptor.getSQLDataTypeDescriptor(javaTypeName, true);
204     }
205
206     /**
207      * Get a DataTypeServices that corresponds to a Java type
208      *
209      * @param javaTypeName The name of the Java type for which to get
210      * a corresponding SQL DataTypeDescriptor
211      * @param isNullable TRUE means it could contain NULL, FALSE means
212      * it definitely cannot contain NULL.
213      *
214      * @return A new DataTypeDescriptor that corresponds to the Java type.
215      * A null return value means there is no corresponding SQL type (only for 'char')
216      */

217     public static DataTypeDescriptor getSQLDataTypeDescriptor
218     (
219         String JavaDoc javaTypeName,
220         boolean isNullable
221     )
222     {
223         TypeId typeId = TypeId.getSQLTypeForJavaType(javaTypeName);
224         if (typeId == null)
225         {
226             return null;
227         }
228
229         return new DataTypeDescriptor(typeId, isNullable);
230     }
231
232     /**
233      * Get a DataTypeDescriptor that corresponds to a Java type
234      *
235      * @param javaTypeName The name of the Java type for which to get
236      * a corresponding SQL DataTypeDescriptor
237      * @param precision The number of decimal digits
238      * @param scale The number of digits after the decimal point
239      * @param isNullable TRUE means it could contain NULL, FALSE means
240      * it definitely cannot contain NULL.
241      * @param maximumWidth The maximum width of a data value
242      * represented by this type.
243      *
244      * @return A new DataTypeDescriptor that corresponds to the Java type.
245      * A null return value means there is no corresponding SQL type.
246      */

247     public static DataTypeDescriptor getSQLDataTypeDescriptor
248     (
249         String JavaDoc javaTypeName,
250         int precision,
251         int scale,
252         boolean isNullable,
253         int maximumWidth
254     )
255     {
256         TypeId typeId = TypeId.getSQLTypeForJavaType(javaTypeName);
257         if (typeId == null)
258         {
259             return null;
260         }
261
262         return new DataTypeDescriptor(typeId,
263                                             precision,
264                                             scale,
265                                             isNullable,
266                                             maximumWidth);
267     }
268     /*
269     ** Instance fields & methods
270     */

271
272     private TypeDescriptorImpl typeDescriptor;
273     private TypeId typeId;
274
275     /**
276      * Public niladic constructor. Needed for Formatable interface to work.
277      *
278      */

279     public DataTypeDescriptor() {}
280
281     /**
282      * Constructor for use with numeric types
283      *
284      * @param typeId The typeId of the type being described
285      * @param precision The number of decimal digits.
286      * @param scale The number of digits after the decimal point.
287      * @param isNullable TRUE means it could contain NULL, FALSE means
288      * it definitely cannot contain NULL.
289      * @param maximumWidth The maximum number of bytes for this datatype
290      */

291     public DataTypeDescriptor(TypeId typeId, int precision, int scale,
292         boolean isNullable, int maximumWidth)
293     {
294         this.typeId = typeId;
295         typeDescriptor = new TypeDescriptorImpl(typeId.getBaseTypeId(),
296                                                 precision,
297                                                 scale,
298                                                 isNullable,
299                                                 maximumWidth);
300     }
301
302     /**
303      * Constructor for use with non-numeric types
304      *
305      * @param typeId The typeId of the type being described
306      * @param isNullable TRUE means it could contain NULL, FALSE means
307      * it definitely cannot contain NULL.
308      * @param maximumWidth The maximum number of bytes for this datatype
309      */

310     public DataTypeDescriptor(TypeId typeId, boolean isNullable,
311         int maximumWidth)
312     {
313         this.typeId = typeId;
314         typeDescriptor = new TypeDescriptorImpl(typeId.getBaseTypeId(),
315                                                 isNullable,
316                                                 maximumWidth);
317     }
318
319
320     public DataTypeDescriptor(TypeId typeId, boolean isNullable) {
321
322         this.typeId = typeId;
323         typeDescriptor = new TypeDescriptorImpl(typeId.getBaseTypeId(),
324                                                 typeId.getMaximumPrecision(),
325                                                 typeId.getMaximumScale(),
326                                                 isNullable,
327                                                 typeId.getMaximumMaximumWidth());
328     }
329     public DataTypeDescriptor(DataTypeDescriptor source, boolean isNullable)
330     {
331         this.typeId = source.typeId;
332         typeDescriptor = new TypeDescriptorImpl(source.typeDescriptor,
333                                                 source.getPrecision(),
334                                                 source.getScale(),
335                                                 isNullable,
336                                                 source.getMaximumWidth());
337     }
338
339     /**
340      * Constructor for internal uses only.
341      * (This is useful when the precision and scale are potentially wider than
342      * those in the source, like when determining the dominant data type.)
343      *
344      * @param source The DTSI to copy
345      * @param precision The number of decimal digits.
346      * @param scale The number of digits after the decimal point.
347      * @param isNullable TRUE means it could contain NULL, FALSE means
348      * it definitely cannot contain NULL.
349      * @param maximumWidth The maximum number of bytes for this datatype
350      */

351     public DataTypeDescriptor(DataTypeDescriptor source,
352                                 int precision,
353                                 int scale,
354                                 boolean isNullable,
355                                 int maximumWidth)
356     {
357         this.typeId = source.typeId;
358         typeDescriptor = new TypeDescriptorImpl(source.typeDescriptor,
359                                                 precision,
360                                                 scale,
361                                                 isNullable,
362                                                 maximumWidth);
363     }
364
365     /**
366      * Constructor for internal uses only
367      *
368      * @param source The DTSI to copy
369      * @param isNullable TRUE means it could contain NULL, FALSE means
370      * it definitely cannot contain NULL.
371      * @param maximumWidth The maximum number of bytes for this datatype
372      */

373     public DataTypeDescriptor(DataTypeDescriptor source, boolean isNullable,
374         int maximumWidth)
375     {
376         this.typeId = source.typeId;
377         typeDescriptor = new TypeDescriptorImpl(source.typeDescriptor,
378                                                 isNullable,
379                                                 maximumWidth);
380     }
381
382     /**
383      * Constructor for use in reconstructing a DataTypeDescriptor from a
384      * TypeDescriptorImpl and a TypeId
385      *
386      * @param source The TypeDescriptorImpl to construct this DTSI from
387      */

388     public DataTypeDescriptor(TypeDescriptorImpl source, TypeId typeId)
389     {
390         typeDescriptor = source;
391         this.typeId = typeId;;
392     }
393
394     /* DataTypeDescriptor Interface */
395     public DataValueDescriptor normalize(DataValueDescriptor source,
396                                         DataValueDescriptor cachedDest)
397             throws StandardException
398     {
399         if (SanityManager.DEBUG) {
400             if (cachedDest != null) {
401                 if (!getTypeId().isUserDefinedTypeId()) {
402                     String JavaDoc t1 = getTypeName();
403                     String JavaDoc t2 = cachedDest.getTypeName();
404                     if (!t1.equals(t2)) {
405
406                         if (!(((t1.equals("DECIMAL") || t1.equals("NUMERIC"))
407                             && (t2.equals("DECIMAL") || t2.equals("NUMERIC"))) ||
408                             (t1.startsWith("INT") && t2.startsWith("INT")))) //INT/INTEGER
409

410                             SanityManager.THROWASSERT(
411                                 "Normalization of " + t2 + " being asked to convert to " + t1);
412                     }
413                 }
414             }
415         }
416
417         if (source.isNull())
418         {
419             if (!isNullable())
420                 throw StandardException.newException(SQLState.LANG_NULL_INTO_NON_NULL,"");
421
422             if (cachedDest == null)
423                 cachedDest = getNull();
424             else
425                 cachedDest.setToNull();
426         } else {
427
428             if (cachedDest == null)
429                 cachedDest = getNull();
430
431             int jdbcId = getJDBCTypeId();
432
433             cachedDest.normalize(this, source);
434             //doing the following check after normalize so that normalize method would get called on long varchs and long varbinary
435
//Need normalize to be called on long varchar for bug 5592 where we need to enforce a lenght limit in db2 mode
436
if ((jdbcId == Types.LONGVARCHAR) || (jdbcId == Types.LONGVARBINARY)) {
437                 // special case for possible streams
438
if (source.getClass() == cachedDest.getClass())
439                     return source;
440             }
441
442         }
443         return cachedDest;
444     }
445     
446     /**
447      * Get the dominant type (DataTypeDescriptor) of the 2.
448      * For variable length types, the resulting type will have the
449      * biggest max length of the 2.
450      * If either side is nullable, then the result will also be nullable.
451      *
452      * @param otherDTS DataTypeDescriptor to compare with.
453      * @param cf A ClassFactory
454      *
455      * @return DataTypeDescriptor DTS for dominant type
456      *
457      * @exception StandardException Thrown on error
458      */

459     public DataTypeDescriptor getDominantType(DataTypeDescriptor otherDTS, ClassFactory cf)
460             throws StandardException
461     {
462         boolean nullable;
463         TypeId thisType;
464         TypeId otherType;
465         DataTypeDescriptor higherType = null;
466         DataTypeDescriptor lowerType = null;
467         int maximumWidth;
468         int precision = getPrecision();
469         int scale = getScale();
470
471         thisType = getTypeId();
472         otherType = otherDTS.getTypeId();
473
474         /* The result is nullable if either side is nullable */
475         nullable = isNullable() || otherDTS.isNullable();
476
477         /*
478         ** The result will have the maximum width of both sides
479         */

480         maximumWidth = (getMaximumWidth() > otherDTS.getMaximumWidth())
481             ? getMaximumWidth() : otherDTS.getMaximumWidth();
482
483         /* We need 2 separate methods of determining type dominance - 1 if both
484          * types are system built-in types and the other if at least 1 is
485          * a user type. (typePrecedence is meaningless for user types.)
486          */

487         if (!thisType.userType() && !otherType.userType())
488         {
489             TypeId higherTypeId;
490             TypeId lowerTypeId;
491             if (thisType.typePrecedence() > otherType.typePrecedence())
492             {
493                 higherType = this;
494                 lowerType = otherDTS;
495                 higherTypeId = thisType;
496                 lowerTypeId = otherType;
497             }
498             else
499             {
500                 higherType = otherDTS;
501                 lowerType = this;
502                 higherTypeId = otherType;
503                 lowerTypeId = thisType;
504             }
505
506             //Following is checking if higher type argument is real and other argument is decimal/bigint/integer/smallint,
507
//then result type should be double
508
if (higherTypeId.isRealTypeId() && (!lowerTypeId.isRealTypeId()) && lowerTypeId.isNumericTypeId())
509             {
510                 higherType = DataTypeDescriptor.getBuiltInDataTypeDescriptor(Types.DOUBLE);
511                 higherTypeId = TypeId.getBuiltInTypeId(Types.DOUBLE);
512             }
513             /*
514             ** If we have a DECIMAL/NUMERIC we have to do some
515             ** extra work to make sure the resultant type can
516             ** handle the maximum values for the two input
517             ** types. We cannot just take the maximum for
518             ** precision. E.g. we want something like:
519             **
520             ** DEC(10,10) and DEC(3,0) => DEC(13,10)
521             **
522             ** (var)char type needs some conversion handled later.
523             */

524             if (higherTypeId.isDecimalTypeId() && (!lowerTypeId.isStringTypeId()))
525             {
526                 precision = higherTypeId.getPrecision(this, otherDTS);
527                 if (precision > 31) precision = 31; //db2 silently does this and so do we
528
scale = higherTypeId.getScale(this, otherDTS);
529
530                 /* maximumWidth needs to count possible leading '-' and
531                  * decimal point and leading '0' if scale > 0. See also
532                  * sqlgrammar.jj(exactNumericType). Beetle 3875
533                  */

534                 maximumWidth = (scale > 0) ? precision + 3 : precision + 1;
535             }
536             else if (thisType.typePrecedence() != otherType.typePrecedence())
537             {
538                 precision = higherType.getPrecision();
539                 scale = higherType.getScale();
540
541                 /* GROSS HACKS:
542                  * If we are doing an implicit (var)char->(var)bit conversion
543                  * then the maximum width for the (var)char as a (var)bit
544                  * is really 16 * its width as a (var)char. Adjust
545                  * maximumWidth accordingly.
546                  * If we are doing an implicit (var)char->decimal conversion
547                  * then we need to increment the decimal's precision by
548                  * 2 * the maximum width for the (var)char and the scale
549                  * by the maximum width for the (var)char. The maximumWidth
550                  * becomes the new precision + 3. This is because
551                  * the (var)char could contain any decimal value from XXXXXX
552                  * to 0.XXXXX. (In other words, we don't know which side of the
553                  * decimal point the characters will be on.)
554                  */

555                 if (lowerTypeId.isStringTypeId())
556                 {
557                     if (higherTypeId.isBitTypeId() &&
558                         ! (higherTypeId.isLongConcatableTypeId()))
559                     {
560                         if (lowerTypeId.isLongConcatableTypeId())
561                         {
562                             if (maximumWidth > (Integer.MAX_VALUE / 16))
563                                 maximumWidth = Integer.MAX_VALUE;
564                             else
565                                 maximumWidth *= 16;
566                         }
567                         else
568                         {
569                             int charMaxWidth;
570
571                             int fromWidth = lowerType.getMaximumWidth();
572                             if (fromWidth > (Integer.MAX_VALUE / 16))
573                                 charMaxWidth = Integer.MAX_VALUE;
574                             else
575                                 charMaxWidth = 16 * fromWidth;
576
577                             maximumWidth = (maximumWidth >= charMaxWidth) ?
578                                                 maximumWidth : charMaxWidth;
579                         }
580                     }
581                 }
582
583                 /*
584                  * If we are doing an implicit (var)char->decimal conversion
585                  * then the resulting decimal's precision could be as high as
586                  * 2 * the maximum width (precisely 2mw-1) for the (var)char
587                  * and the scale could be as high as the maximum width
588                  * (precisely mw-1) for the (var)char.
589                  * The maximumWidth becomes the new precision + 3. This is
590                  * because the (var)char could contain any decimal value from
591                  * XXXXXX to 0.XXXXX. (In other words, we don't know which
592                  * side of the decimal point the characters will be on.)
593                  *
594                  * We don't follow this algorithm for long varchar because the
595                  * maximum length of a long varchar is maxint, and we don't
596                  * want to allocate a huge decimal value. So in this case,
597                  * the precision, scale, and maximum width all come from
598                  * the decimal type.
599                  */

600                 if (lowerTypeId.isStringTypeId() &&
601                     ! (lowerTypeId.isLongConcatableTypeId()) &&
602                     higherTypeId.isDecimalTypeId() )
603                 {
604                     int charMaxWidth = lowerType.getMaximumWidth();
605                     int charPrecision;
606
607                     /*
608                     ** Be careful not to overflow when calculating the
609                     ** precision. Remember that we will be adding
610                     ** three to the precision to get the maximum width.
611                     */

612                     if (charMaxWidth > (Integer.MAX_VALUE - 3) / 2)
613                         charPrecision = Integer.MAX_VALUE - 3;
614                     else
615                         charPrecision = charMaxWidth * 2;
616
617                     if (precision < charPrecision)
618                         precision = charPrecision;
619
620                     if (scale < charMaxWidth)
621                         scale = charMaxWidth;
622
623                     maximumWidth = precision + 3;
624                 }
625             }
626         }
627         else
628         {
629             /* At least 1 type is not a system built-in type */
630             ClassInspector cu = cf.getClassInspector();
631
632             TypeId thisCompType = (TypeId) thisType;
633             TypeId otherCompType = (TypeId) otherType;
634
635             if (cu.assignableTo(thisCompType.getCorrespondingJavaTypeName(),
636                                 otherCompType.getCorrespondingJavaTypeName()))
637             {
638                 higherType = otherDTS;
639             }
640             else
641             {
642                 if (SanityManager.DEBUG)
643                         SanityManager.ASSERT(
644                             cu.assignableTo(otherCompType.getCorrespondingJavaTypeName(),
645                                     thisCompType.getCorrespondingJavaTypeName()),
646                             otherCompType.getCorrespondingJavaTypeName() +
647                             " expected to be assignable to " +
648                             thisCompType.getCorrespondingJavaTypeName());
649
650                 higherType = this;
651             }
652             precision = higherType.getPrecision();
653             scale = higherType.getScale();
654         }
655
656         higherType = new DataTypeDescriptor(higherType,
657                                               precision, scale, nullable, maximumWidth);
658
659         return higherType;
660     }
661
662     /**
663      * Check whether or not the 2 types (DataTypeDescriptor) have the same type
664      * and length.
665      * This is useful for UNION when trying to decide whether a NormalizeResultSet
666      * is required.
667      *
668      * @param otherDTS DataTypeDescriptor to compare with.
669      *
670      * @return boolean Whether or not the 2 DTSs have the same type and length.
671      */

672     public boolean isExactTypeAndLengthMatch(DataTypeDescriptor otherDTS)
673     {
674         /* Do both sides have the same length? */
675         if (getMaximumWidth() != otherDTS.getMaximumWidth())
676         {
677             return false;
678         }
679         if (getScale() != otherDTS.getScale())
680         {
681             return false;
682         }
683
684         if (getPrecision() != otherDTS.getPrecision())
685         {
686             return false;
687         }
688
689         TypeId thisType = getTypeId();
690         TypeId otherType = otherDTS.getTypeId();
691
692         /* Do both sides have the same type? */
693         if ( ! thisType.equals(otherType))
694         {
695             return false;
696         }
697
698         return true;
699     }
700
701     /**
702     * @see TypeDescriptor#getMaximumWidth
703      */

704     public int getMaximumWidth()
705     {
706         return typeDescriptor.getMaximumWidth();
707     }
708
709     /**
710      * @see TypeDescriptor#getMaximumWidthInBytes
711      */

712     public int getMaximumWidthInBytes()
713     {
714         return typeDescriptor.getMaximumWidthInBytes();
715     }
716
717     /**
718      * Gets the TypeId for the datatype.
719      *
720      * @return The TypeId for the datatype.
721      */

722     public TypeId getTypeId()
723     {
724         return typeId;
725     }
726
727     /**
728         Get a Null for this type.
729     */

730     public DataValueDescriptor getNull() {
731         return typeId.getNull();
732     }
733
734     /**
735      * Gets the name of this datatype.
736      *
737      *
738      * @return the name of this datatype
739      */

740     public String JavaDoc getTypeName()
741     {
742         return typeId.getSQLTypeName();
743     }
744
745     /**
746      * Get the jdbc type id for this type. JDBC type can be
747      * found in java.sql.Types.
748      *
749      * @return a jdbc type, e.g. java.sql.Types.DECIMAL
750      *
751      * @see Types
752      */

753     public int getJDBCTypeId()
754     {
755         return typeId.getJDBCTypeId();
756     }
757
758     /**
759      * Returns the number of decimal digits for the datatype, if applicable.
760      *
761      * @return The number of decimal digits for the datatype. Returns
762      * zero for non-numeric datatypes.
763      */

764     public int getPrecision()
765     {
766         return typeDescriptor.getPrecision();
767     }
768
769     /**
770      * Returns the number of digits to the right of the decimal for
771      * the datatype, if applicable.
772      *
773      * @return The number of digits to the right of the decimal for
774      * the datatype. Returns zero for non-numeric datatypes.
775      */

776     public int getScale()
777     {
778         return typeDescriptor.getScale();
779     }
780
781     /**
782      * Returns TRUE if the datatype can contain NULL, FALSE if not.
783      * JDBC supports a return value meaning "nullability unknown" -
784      * I assume we will never have columns where the nullability is unknown.
785      *
786      * @return TRUE if the datatype can contain NULL, FALSE if not.
787      */

788     public boolean isNullable()
789     {
790         return typeDescriptor.isNullable();
791     }
792
793     /**
794      * Set the nullability of the datatype described by this descriptor
795      *
796      * @param nullable TRUE means set nullability to TRUE, FALSE
797      * means set it to FALSE
798      */

799     public void setNullability(boolean nullable)
800     {
801         typeDescriptor.setNullability(nullable);
802     }
803
804     /**
805       Compare if two TypeDescriptors are exactly the same
806       @param aTypeDescriptor the typeDescriptor to compare to.
807       */

808     public boolean equals(Object JavaDoc aTypeDescriptor)
809     {
810         return typeDescriptor.equals(aTypeDescriptor);
811     }
812
813     /**
814      * Converts this data type descriptor (including length/precision)
815      * to a string. E.g.
816      *
817      * VARCHAR(30)
818      *
819      * or
820      *
821      * java.util.Hashtable
822      *
823      * @return String version of datatype, suitable for running through
824      * the Parser.
825      */

826     public String JavaDoc getSQLstring()
827     {
828         return typeId.toParsableString( this );
829     }
830
831     /**
832      * Get the simplified type descriptor that is intended to be stored
833      * in the system tables.
834      */

835     public TypeDescriptorImpl getCatalogType()
836     {
837         return typeDescriptor;
838     }
839
840     /**
841      * Get the estimated memory usage for this type descriptor.
842      */

843     public double estimatedMemoryUsage() {
844         switch (typeId.getTypeFormatId())
845         {
846             case StoredFormatIds.LONGVARBIT_TYPE_ID:
847                 /* Who knows? Let's just use some big number */
848                 return 10000.0;
849
850             case StoredFormatIds.BIT_TYPE_ID:
851                 return (double) ( ( ((float) getMaximumWidth()) / 8.0) + 0.5);
852
853             case StoredFormatIds.BOOLEAN_TYPE_ID:
854                 return 4.0;
855
856             case StoredFormatIds.CHAR_TYPE_ID:
857             case StoredFormatIds.VARCHAR_TYPE_ID:
858             case StoredFormatIds.NATIONAL_CHAR_TYPE_ID:
859             case StoredFormatIds.NATIONAL_VARCHAR_TYPE_ID:
860                 return (double) (2.0 * getMaximumWidth());
861
862             case StoredFormatIds.LONGVARCHAR_TYPE_ID:
863             case StoredFormatIds.NATIONAL_LONGVARCHAR_TYPE_ID:
864                 /* Who knows? Let's just use some big number */
865                 return 10000.0;
866
867             case StoredFormatIds.DECIMAL_TYPE_ID:
868                 /*
869                 ** 0.415 converts from number decimal digits to number of 8-bit digits.
870                 ** Add 1.0 for the sign byte, and 0.5 to force it to round up.
871                 */

872                 return (double) ( (getPrecision() * 0.415) + 1.5 );
873
874             case StoredFormatIds.DOUBLE_TYPE_ID:
875                 return 8.0;
876
877             case StoredFormatIds.INT_TYPE_ID:
878                 return 4.0;
879
880             case StoredFormatIds.LONGINT_TYPE_ID:
881                 return 8.0;
882
883             case StoredFormatIds.REAL_TYPE_ID:
884                 return 4.0;
885
886             case StoredFormatIds.SMALLINT_TYPE_ID:
887                 return 2.0;
888
889             case StoredFormatIds.TINYINT_TYPE_ID:
890                 return 1.0;
891
892             case StoredFormatIds.REF_TYPE_ID:
893                 /* I think 12 is the right number */
894                 return 12.0;
895
896             case StoredFormatIds.USERDEFINED_TYPE_ID_V3:
897                 if (typeId.userType()) {
898                     /* Who knows? Let's just use some medium-sized number */
899                     return 256.0;
900                 }
901             case StoredFormatIds.DATE_TYPE_ID:
902             case StoredFormatIds.TIME_TYPE_ID:
903             case StoredFormatIds.TIMESTAMP_TYPE_ID:
904                 return 12.0;
905
906             default:
907                 return 0.0;
908         }
909     }
910
911     /**
912      * Compare JdbcTypeIds to determine if they represent equivalent
913      * SQL types. For example Types.NUMERIC and Types.DECIMAL are
914      * equivalent
915      *
916      * @param existingType JDBC type id of Cloudscape data type
917      * @param jdbcTypeId JDBC type id passed in from application.
918      *
919      * @return boolean true if types are equivalent, false if not
920      */

921
922     public static boolean isJDBCTypeEquivalent(int existingType, int jdbcTypeId)
923     {
924         // Any type matches itself.
925
if (existingType == jdbcTypeId)
926             return true;
927
928         // To a numeric type
929
if (DataTypeDescriptor.isNumericType(existingType)) {
930             if (DataTypeDescriptor.isNumericType(jdbcTypeId))
931                 return true;
932
933             if (DataTypeDescriptor.isCharacterType(jdbcTypeId))
934                 return true;
935
936             return false;
937         }
938
939         // To character type.
940
if (DataTypeDescriptor.isCharacterType(existingType)) {
941
942             if (DataTypeDescriptor.isCharacterType(jdbcTypeId))
943                 return true;
944
945             if (DataTypeDescriptor.isNumericType(jdbcTypeId))
946                 return true;
947
948
949             switch (jdbcTypeId) {
950             case Types.DATE:
951             case Types.TIME:
952             case Types.TIMESTAMP:
953                 return true;
954             default:
955                 break;
956             }
957
958             
959             return false;
960
961         }
962
963         // To binary type
964
if (DataTypeDescriptor.isBinaryType(existingType)) {
965
966             if (DataTypeDescriptor.isBinaryType(jdbcTypeId))
967                 return true;
968
969             return false;
970         }
971
972         // To DATE, TIME
973
if (existingType == Types.DATE || existingType == Types.TIME) {
974             if (DataTypeDescriptor.isCharacterType(jdbcTypeId))
975                 return true;
976
977             if (jdbcTypeId == Types.TIMESTAMP)
978                 return true;
979
980             return false;
981         }
982
983         // To TIMESTAMP
984
if (existingType == Types.TIMESTAMP) {
985             if (DataTypeDescriptor.isCharacterType(jdbcTypeId))
986                 return true;
987
988             if (jdbcTypeId == Types.DATE)
989                 return true;
990
991             return false;
992         }
993         
994         // To CLOB
995
if (existingType == Types.CLOB && DataTypeDescriptor.isCharacterType(jdbcTypeId))
996             return true;
997
998         return false;
999     }
1000
1001    public static boolean isNumericType(int jdbcType) {
1002
1003        switch (jdbcType) {
1004        case Types.BIT:
1005        case org.apache.derby.iapi.reference.JDBC30Translation.SQL_TYPES_BOOLEAN:
1006        case Types.TINYINT:
1007        case Types.SMALLINT:
1008        case Types.INTEGER:
1009        case Types.BIGINT:
1010        case Types.REAL:
1011        case Types.FLOAT:
1012        case Types.DOUBLE:
1013        case Types.DECIMAL:
1014        case Types.NUMERIC:
1015            return true;
1016        default:
1017            return false;
1018        }
1019    }
1020
1021    /**
1022     * Check whether a JDBC type is one of the character types that are
1023     * compatible with the Java type <code>String</code>.
1024     *
1025     * <p><strong>Note:</strong> <code>CLOB</code> is not compatible with
1026     * <code>String</code>. See tables B-4, B-5 and B-6 in the JDBC 3.0
1027     * Specification.
1028     *
1029     * <p> There are some non-character types that are compatible with
1030     * <code>String</code> (examples: numeric types, binary types and
1031     * time-related types), but they are not covered by this method.
1032     *
1033     * @param jdbcType a JDBC type
1034     * @return <code>true</code> iff <code>jdbcType</code> is a character type
1035     * and compatible with <code>String</code>
1036     * @see java.sql.Types
1037     */

1038    private static boolean isCharacterType(int jdbcType) {
1039
1040        switch (jdbcType) {
1041        case Types.CHAR:
1042        case Types.VARCHAR:
1043        case Types.LONGVARCHAR:
1044            return true;
1045        default:
1046            return false;
1047        }
1048    }
1049
1050    /**
1051     * Check whether a JDBC type is compatible with the Java type
1052     * <code>byte[]</code>.
1053     *
1054     * <p><strong>Note:</strong> <code>BLOB</code> is not compatible with
1055     * <code>byte[]</code>. See tables B-4, B-5 and B-6 in the JDBC 3.0
1056     * Specification.
1057     *
1058     * @param jdbcType a JDBC type
1059     * @return <code>true</code> iff <code>jdbcType</code> is compatible with
1060     * <code>byte[]</code>
1061     * @see java.sql.Types
1062     */

1063    private static boolean isBinaryType(int jdbcType) {
1064        switch (jdbcType) {
1065        case Types.BINARY:
1066        case Types.VARBINARY:
1067        case Types.LONGVARBINARY:
1068            return true;
1069        default:
1070            return false;
1071        }
1072    }
1073
1074    /**
1075     * Determine if an ASCII stream can be inserted into a column or parameter
1076     * of type <code>jdbcType</code>.
1077     *
1078     * @param jdbcType JDBC type of column or parameter
1079     * @return <code>true</code> if an ASCII stream can be inserted;
1080     * <code>false</code> otherwise
1081     */

1082    public static boolean isAsciiStreamAssignable(int jdbcType) {
1083        return jdbcType == Types.CLOB || isCharacterType(jdbcType);
1084    }
1085
1086    /**
1087     * Determine if a binary stream can be inserted into a column or parameter
1088     * of type <code>jdbcType</code>.
1089     *
1090     * @param jdbcType JDBC type of column or parameter
1091     * @return <code>true</code> if a binary stream can be inserted;
1092     * <code>false</code> otherwise
1093     */

1094    public static boolean isBinaryStreamAssignable(int jdbcType) {
1095        return jdbcType == Types.BLOB || isBinaryType(jdbcType);
1096    }
1097
1098    /**
1099     * Determine if a character stream can be inserted into a column or
1100     * parameter of type <code>jdbcType</code>.
1101     *
1102     * @param jdbcType JDBC type of column or parameter
1103     * @return <code>true</code> if a character stream can be inserted;
1104     * <code>false</code> otherwise
1105     */

1106    public static boolean isCharacterStreamAssignable(int jdbcType) {
1107        // currently, we support the same types for ASCII streams and
1108
// character streams
1109
return isAsciiStreamAssignable(jdbcType);
1110    }
1111
1112    public String JavaDoc toString()
1113    {
1114        return typeDescriptor.toString();
1115    }
1116
1117    // Formatable methods
1118

1119    /**
1120     * Read this object from a stream of stored objects.
1121     *
1122     * @param in read this.
1123     *
1124     * @exception IOException thrown on error
1125     * @exception ClassNotFoundException thrown on error
1126     */

1127    public void readExternal( ObjectInput JavaDoc in )
1128         throws IOException JavaDoc, ClassNotFoundException JavaDoc
1129    {
1130        /* NOTE: We only write out the generic type id.
1131         * typeId will be reset to be the generic type id
1132         * when we get read back in since the generic
1133         * one is all that is needed at execution time.
1134         */

1135        typeId = (TypeId) in.readObject();
1136        typeDescriptor = (TypeDescriptorImpl) in.readObject();
1137    }
1138
1139    /**
1140     * Write this object to a stream of stored objects.
1141     *
1142     * @param out write bytes here.
1143     *
1144     * @exception IOException thrown on error
1145     */

1146    public void writeExternal( ObjectOutput JavaDoc out )
1147         throws IOException JavaDoc
1148    {
1149        out.writeObject( typeId );
1150        out.writeObject( typeDescriptor );
1151    }
1152 
1153    /**
1154     * Get the formatID which corresponds to this class.
1155     *
1156     * @return the formatID of this class
1157     */

1158    public int getTypeFormatId() { return StoredFormatIds.DATA_TYPE_SERVICES_IMPL_V01_ID; }
1159}
1160
1161
Popular Tags