KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.compile.ColumnDefinitionNode
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.services.loader.ClassInspector;
25
26 import org.apache.derby.iapi.services.sanity.SanityManager;
27 import org.apache.derby.iapi.services.io.StoredFormatIds;
28 import org.apache.derby.iapi.reference.Limits;
29 import org.apache.derby.iapi.error.StandardException;
30
31 import org.apache.derby.iapi.sql.compile.CompilerContext;
32 import org.apache.derby.iapi.sql.compile.C_NodeTypes;
33
34 import org.apache.derby.iapi.sql.dictionary.AliasDescriptor;
35 import org.apache.derby.iapi.sql.dictionary.DataDictionary;
36 import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
37
38 import org.apache.derby.iapi.types.DataTypeDescriptor;
39 import org.apache.derby.iapi.types.DataValueDescriptor;
40 import org.apache.derby.iapi.types.TypeId;
41
42 import org.apache.derby.iapi.sql.depend.DependencyManager;
43 import org.apache.derby.iapi.sql.depend.ProviderList;
44 import org.apache.derby.iapi.sql.depend.ProviderInfo;
45
46 import org.apache.derby.iapi.reference.SQLState;
47
48 import org.apache.derby.impl.sql.execute.ColumnInfo;
49
50 import org.apache.derby.catalog.AliasInfo;
51 import org.apache.derby.catalog.DefaultInfo;
52 import org.apache.derby.catalog.UUID;
53
54 import org.apache.derby.catalog.types.DefaultInfoImpl;
55
56 import java.util.Vector JavaDoc;
57 import java.sql.Types JavaDoc;
58
59 /**
60  * A ColumnDefinitionNode represents a column definition in a DDL statement.
61  * There will be a ColumnDefinitionNode for each column in a CREATE TABLE
62  * statement, and for the column in an ALTER TABLE ADD COLUMN statement.
63  *
64  * @author Jeff Lichtman
65  */

66
67 public class ColumnDefinitionNode extends TableElementNode
68 {
69     boolean isAutoincrement;
70     DataTypeDescriptor dataTypeServices;
71     DataValueDescriptor defaultValue;
72     DefaultInfoImpl defaultInfo;
73     DefaultNode defaultNode;
74     long autoincrementIncrement;
75     long autoincrementStart;
76     //This variable tells if the autoincrement column is participating
77
//in create or alter table. And if it is participating in alter
78
//table, then it further knows if it is represting a change in
79
//increment value or a change in start value.
80
//This information is later used to make sure that the autoincrement
81
//column's increment value is not 0 at the time of create, or is not
82
//getting set to 0 at the time of increment value modification.
83
long autoinc_create_or_modify_Start_Increment;
84     boolean autoincrementVerify;
85
86     //autoinc_create_or_modify_Start_Increment will be set to one of the
87
//following 3 values.
88
//CREATE_AUTOINCREMENT - this autoincrement column definition is for create table
89
public static final int CREATE_AUTOINCREMENT = 0;
90     //MODIFY_AUTOINCREMENT_RESTART_VALUE - this column definition is for
91
//alter table command to change the start value of the column
92
public static final int MODIFY_AUTOINCREMENT_RESTART_VALUE = 1;
93     //MODIFY_AUTOINCREMENT_INC_VALUE - this column definition is for
94
//alter table command to change the increment value of the column
95
public static final int MODIFY_AUTOINCREMENT_INC_VALUE = 2;
96     
97     /**
98      * Initializer for a ColumnDefinitionNode
99      *
100      * @param name The name of the column
101      * @param defaultNode The default value of the column
102      * @param dataTypeServices A DataTypeServices telling the type
103      * of the column
104      * @param autoIncrementInfo Info for autoincrement columns
105      *
106      */

107
108     public void init(
109                     Object JavaDoc name,
110                     Object JavaDoc defaultNode,
111                     Object JavaDoc dataTypeServices,
112                     Object JavaDoc autoIncrementInfo)
113         throws StandardException
114     {
115         super.init(name);
116         this.dataTypeServices = (DataTypeDescriptor) dataTypeServices;
117         if (defaultNode instanceof UntypedNullConstantNode)
118         {
119             /* No DTS yet for MODIFY DEFAULT */
120             if (dataTypeServices != null)
121             {
122                 defaultValue =
123                     ((UntypedNullConstantNode) defaultNode).
124                                     convertDefaultNode(this.dataTypeServices);
125             }
126         }
127         else
128         {
129             if (SanityManager.DEBUG)
130             {
131                 if (defaultNode != null &&
132                     ! (defaultNode instanceof DefaultNode))
133                 {
134                     SanityManager.THROWASSERT(
135                         "defaultNode expected to be instanceof DefaultNode, not " +
136                         defaultNode.getClass().getName());
137                 }
138             }
139             this.defaultNode = (DefaultNode) defaultNode;
140             if (autoIncrementInfo != null)
141             {
142                 long[] aii = (long[]) autoIncrementInfo;
143                 autoincrementStart = aii[QueryTreeNode.AUTOINCREMENT_START_INDEX];
144                 autoincrementIncrement = aii[QueryTreeNode.AUTOINCREMENT_INC_INDEX];
145                 //Parser has passed the info about autoincrement column's status in the
146
//following array element. It will tell if the autoinc column is part of
147
//a create table or if is a part of alter table. And if it is part of
148
//alter table, is it for changing the increment value or for changing
149
//the start value?
150
autoinc_create_or_modify_Start_Increment = aii[QueryTreeNode.AUTOINCREMENT_CREATE_MODIFY];
151                 
152                 /*
153                  * If using DB2 syntax to set increment value, will need to check if column
154                  * is already created for autoincrement.
155                  */

156                 autoincrementVerify = (aii[QueryTreeNode.AUTOINCREMENT_IS_AUTOINCREMENT_INDEX] > 0) ? false : true;
157                 isAutoincrement = true;
158                 // an autoincrement column cannot be null-- setting
159
// non-nullability for this column is needed because
160
// you could create a column with ai default, add data, drop
161
// the default, and try to add it back again you'll get an
162
// error because the column is marked nullable.
163
if (dataTypeServices != null)
164                     (this.dataTypeServices).setNullability(false);
165             }
166         }
167     }
168
169     /**
170      * Convert this object to a String. See comments in QueryTreeNode.java
171      * for how this should be done for tree printing.
172      *
173      * @return This object as a String
174      */

175
176     public String JavaDoc toString()
177     {
178         if (SanityManager.DEBUG)
179         {
180             return "dataTypeServices: " + dataTypeServices.toString() + "\n" +
181                 "defaultValue: " + defaultValue + "\n" +
182                 super.toString();
183         }
184         else
185         {
186             return "";
187         }
188     }
189
190     /**
191      * Returns the unqualified name of the column being defined.
192      *
193      * @return the name of the column
194      */

195     public String JavaDoc getColumnName()
196     {
197         return this.name;
198     }
199
200     /**
201      * Returns the data type services of the column being defined.
202      *
203      * @return the data type services of the column
204      */

205     public DataTypeDescriptor getDataTypeServices()
206     {
207         return this.dataTypeServices;
208     }
209
210     /**
211      * Return the DataValueDescriptor containing the default value for this
212      * column
213      *
214      * @return The default value of the column
215      */

216
217     public DataValueDescriptor getDefaultValue()
218     {
219         return this.defaultValue;
220     }
221
222     /**
223      * Return the DefaultInfo containing the default information for this
224      * column
225      *
226      * @return The default info for the column
227      */

228
229     public DefaultInfo getDefaultInfo()
230     {
231         return defaultInfo;
232     }
233
234     /**
235      * Return the DefaultNode, if any, associated with this node.
236      *
237      * @return The DefaultNode, if any, associated with this node.
238      */

239     public DefaultNode getDefaultNode()
240     {
241         return defaultNode;
242     }
243
244     /**
245      * Is this an autoincrement column?
246      *
247      * @return Whether or not this is an autoincrement column.
248      */

249     public boolean isAutoincrementColumn()
250     {
251         if (SanityManager.DEBUG)
252         {
253             //increment value for autoincrement column can't be 0 if the autoinc column
254
//is part of create table or it is part of alter table to change the
255
//increment value.
256
if (isAutoincrement && autoincrementIncrement == 0 &&
257                     (autoinc_create_or_modify_Start_Increment == ColumnDefinitionNode.CREATE_AUTOINCREMENT ||
258                             autoinc_create_or_modify_Start_Increment == ColumnDefinitionNode.MODIFY_AUTOINCREMENT_INC_VALUE))
259             {
260                 SanityManager.THROWASSERT(
261                     "autoincrementIncrement expected to be non-zero");
262             }
263             if ((! isAutoincrement) &&
264                 (autoincrementStart != 0 || autoincrementIncrement != 0))
265             {
266                 SanityManager.THROWASSERT(
267                     "both autoincrementStart and autoincrementIncrement expected to be 0");
268             }
269         }
270         return isAutoincrement;
271     }
272
273     /**
274      * Get the autoincrement start value
275      *
276      * @return Autoincrement start value.
277      */

278     long getAutoincrementStart()
279     {
280         if (SanityManager.DEBUG)
281         {
282             SanityManager.ASSERT(isAutoincrement,
283                 "isAutoincrement expected to be true");
284         }
285         return autoincrementStart;
286     }
287
288     /**
289      * Get the autoincrement increment value
290      *
291      * @return Autoincrement increment value.
292      */

293     long getAutoincrementIncrement()
294     {
295         if (SanityManager.DEBUG)
296         {
297             SanityManager.ASSERT(isAutoincrement,
298                 "isAutoincrement expected to be true");
299         }
300         return autoincrementIncrement;
301     }
302
303     /**
304      * Get the status of this autoincrement column
305      *
306      * @return ColumnDefinitionNode.CREATE_AUTOINCREMENT -
307      * if this definition is for autoincrement column creatoin
308      * ColumnDefinitionNode.MODIFY_AUTOINCREMENT_RESTART_VALUE -
309      * if this definition is for alter sutoincrement column to change the start value
310      * ColumnDefinitionNode.MODIFY_AUTOINCREMENT_INC_VALUE
311      * if this definition is for alter autoincrement column to change the increment value
312      */

313     long getAutoinc_create_or_modify_Start_Increment()
314     {
315         if (SanityManager.DEBUG)
316         {
317             SanityManager.ASSERT(isAutoincrement,
318                 "isAutoincrement expected to be true");
319         }
320         return autoinc_create_or_modify_Start_Increment;
321     }
322     
323     /**
324      * Check the validity of a user type. Checks whether this column
325      * definition describes a user type that either doesn't exist or is
326      * inaccessible, or that doesn't implement Serializable.
327      *
328      * @exception StandardException Thrown on error
329      */

330
331     public void checkUserType(TableDescriptor td)
332         throws StandardException
333     {
334         String JavaDoc columnTypeName;
335
336         /* Built-in types need no checking */
337         if (!dataTypeServices.getTypeId().userType())
338             return;
339
340         ClassInspector classInspector = getClassFactory().getClassInspector();
341
342         columnTypeName =
343             dataTypeServices.getTypeId().getCorrespondingJavaTypeName();
344
345
346
347
348         /* User type - We first check for the columnTypeName as a java class.
349          * If that fails, then we treat it as a class alias.
350          */

351
352         boolean foundMatch = false;
353         Throwable JavaDoc reason = null;
354         try {
355             foundMatch = classInspector.accessible(columnTypeName);
356         } catch (ClassNotFoundException JavaDoc cnfe) {
357             reason = cnfe;
358         }
359
360         if (!foundMatch)
361         {
362             throw StandardException.newException(SQLState.LANG_TYPE_DOESNT_EXIST, reason, columnTypeName,
363                                                                 name);
364         }
365
366         if (! classInspector.assignableTo(columnTypeName,
367                                             "java.io.Serializable") &&
368             // Before Java2, SQLData is not defined, assignableTo call returns false
369
! classInspector.assignableTo(columnTypeName,"java.sql.SQLData"))
370         {
371             getCompilerContext().addWarning(
372                 StandardException.newWarning(SQLState.LANG_TYPE_NOT_SERIALIZABLE, columnTypeName,
373                                                                  name));
374         }
375     }
376
377     /**
378      * Get the UUID of the old column default.
379      *
380      * @return The UUID of the old column default.
381      */

382     UUID getOldDefaultUUID()
383     {
384         return null;
385     }
386
387     /**
388      * Get the action associated with this node.
389      *
390      * @return The action associated with this node.
391      */

392     int getAction()
393     {
394         return ColumnInfo.CREATE;
395     }
396
397     /**
398      * Check the validity of the default, if any, for this node.
399      *
400      * @param dd The DataDictionary.
401      * @param td The TableDescriptor.
402      *
403      * @exception StandardException Thrown on error
404      */

405     void bindAndValidateDefault(DataDictionary dd, TableDescriptor td)
406         throws StandardException
407     {
408         /* DB2 requires non-nullable columns to have a default in ALTER TABLE */
409         if (td != null && !dataTypeServices.isNullable() && defaultNode == null)
410         {
411             if (!isAutoincrement)
412                 throw StandardException.newException(SQLState.LANG_DB2_NOT_NULL_COLUMN_INVALID_DEFAULT, getColumnName());
413         }
414             
415         // No work to do if no user specified default
416
if (defaultNode == null)
417         {
418             return;
419         }
420
421         // No work to do if user specified NULL
422
if (defaultValue != null)
423         {
424             return;
425         }
426
427         // Now validate the default
428
validateDefault(dd, td);
429     }
430
431
432     /**
433      * Check the validity of the autoincrement values for this node.
434      * The following errors are thrown by this routine.
435      * 1. 42z21 Invalid Increment; i.e 0.
436      * 2. 42z22 Invalid Type; autoincrement created on a non-exact-numeric type
437      * 3. 42995 The requested function does not apply to global temporary tables
438      *
439      * @param dd DataDictionary.
440      * @param td table descriptor.
441      * @param tableType base table or declared global temporary table.
442      *
443      * @exception StandardException if autoincrement default is incorrect; i.e
444      * if increment is 0 or if initial or increment values are out
445      * of range for the datatype.
446      */

447     public void validateAutoincrement(DataDictionary dd, TableDescriptor td, int tableType)
448          throws StandardException
449     {
450         if (isAutoincrement == false)
451             return;
452
453         if (tableType == TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE)
454             throw StandardException.newException(SQLState.LANG_NOT_ALLOWED_FOR_DECLARED_GLOBAL_TEMP_TABLE);
455
456         //increment value for autoincrement column can't be 0 if the autoinc column
457
//is part of create table or it is part of alter table to change the
458
//increment value.
459
if (autoincrementIncrement == 0 &&
460                 (autoinc_create_or_modify_Start_Increment == ColumnDefinitionNode.CREATE_AUTOINCREMENT ||
461                         autoinc_create_or_modify_Start_Increment == ColumnDefinitionNode.MODIFY_AUTOINCREMENT_INC_VALUE))
462             throw StandardException.newException(SQLState.LANG_AI_INVALID_INCREMENT, getColumnName());
463         int jdbctype = dataTypeServices.getTypeId().getJDBCTypeId();
464         switch (jdbctype)
465         {
466         case Types.TINYINT:
467             autoincrementCheckRange((long)Byte.MIN_VALUE,
468                                     (long)Byte.MAX_VALUE,
469                                     TypeId.TINYINT_NAME);
470             break;
471         case Types.SMALLINT:
472             autoincrementCheckRange((long)Short.MIN_VALUE,
473                                     (long)Short.MAX_VALUE,
474                                     TypeId.SMALLINT_NAME);
475             break;
476         case Types.INTEGER:
477             autoincrementCheckRange((long)Integer.MIN_VALUE,
478                                     (long)Integer.MAX_VALUE,
479                                     TypeId.INTEGER_NAME);
480             break;
481         case Types.BIGINT:
482             autoincrementCheckRange(Long.MIN_VALUE, Long.MAX_VALUE,
483                                     TypeId.LONGINT_NAME);
484             break;
485         default:
486             throw StandardException.newException(SQLState.LANG_AI_INVALID_TYPE,
487                                                  getColumnName());
488         }
489     }
490
491     /**
492      * checks to see if autoincrementIncrement and autoincrementInitial
493      * are within the bounds of the type whose min and max values are
494      * passed into this routine.
495      */

496     private void autoincrementCheckRange(long minValue, long maxValue,
497                                     String JavaDoc typeName)
498                 throws StandardException
499     {
500         if ((minValue > autoincrementIncrement) ||
501             (maxValue < autoincrementIncrement))
502         {
503             throw StandardException.newException(
504                                  SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE, typeName);
505         }
506         if ((minValue > autoincrementStart) ||
507             (maxValue < autoincrementStart))
508         {
509             throw StandardException.newException(
510                                  SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE, typeName);
511         }
512     }
513     /**
514      * Check the validity of the default for this node.
515      *
516      * @param td The TableDescriptor.
517      *
518      * @exception StandardException Thrown on error
519      */

520     void validateDefault(DataDictionary dd, TableDescriptor td)
521         throws StandardException
522     {
523         if (defaultNode == null)
524             return;
525
526         //Examin whether default value is autoincrement.
527
if (isAutoincrement){
528             defaultInfo = createDefaultInfoOfAutoInc();
529             return;
530         }
531         
532         
533         //Judged as default value is constant value.
534

535         CompilerContext cc = getCompilerContext();
536
537         ValueNode defaultTree = defaultNode.getDefaultTree();
538
539         /* bind the default.
540          * Verify that it does not contain any ColumnReferences or subqueries
541          * and that it is type compatable with the column.
542          */

543         final int previousReliability = cc.getReliability();
544         try
545         {
546             /*
547                 Defaults cannot have dependencies as they
548                 should just be constants. Code used to exist
549                 to handle dependencies in defaults, now this
550                 is under sanity to ensure no dependencies exist.
551              */

552             ProviderList apl = null;
553             ProviderList prevAPL = null;
554
555             if (SanityManager.DEBUG) {
556                 apl = new ProviderList();
557                 prevAPL = cc.getCurrentAuxiliaryProviderList();
558                 cc.setCurrentAuxiliaryProviderList(apl);
559             }
560             
561             // Tell the compiler context to only allow deterministic nodes
562
cc.setReliability( CompilerContext.DEFAULT_RESTRICTION );
563             defaultTree = defaultTree.bindExpression(
564                             (FromList) getNodeFactory().getNode(
565                                 C_NodeTypes.FROM_LIST,
566                                 getNodeFactory().doJoinOrderOptimization(),
567                                 getContextManager()),
568                             (SubqueryList) null,
569                             (Vector JavaDoc) null);
570
571             TypeId columnTypeId = (TypeId) dataTypeServices.getTypeId();
572             TypeId defaultTypeId = defaultTree.getTypeId();
573
574             // Check for 'invalid default' errors (42894)
575
// before checking for 'not storable' errors (42821).
576
if (!defaultTypeIsValid(columnTypeId, dataTypeServices,
577                     defaultTypeId, defaultTree, defaultNode.getDefaultText()))
578             {
579                     throw StandardException.newException(
580                         SQLState.LANG_DB2_INVALID_DEFAULT_VALUE,
581                         this.name);
582             }
583
584             // Now check 'not storable' errors.
585
if (! getTypeCompiler(columnTypeId).
586                                 storable(defaultTypeId, getClassFactory()))
587             {
588                 throw StandardException.newException(SQLState.LANG_NOT_STORABLE,
589                     columnTypeId.getSQLTypeName(),
590                     defaultTypeId.getSQLTypeName() );
591             }
592
593             // Save off the default text
594
// RESOLVEDEFAULT - Convert to constant if possible
595
defaultInfo = new DefaultInfoImpl(false,
596                               defaultNode.getDefaultText(),
597                               defaultValue);
598
599             if (SanityManager.DEBUG)
600             {
601                 /* Save the APL off in the constraint node */
602                 if (apl.size() > 0)
603                 {
604
605                     SanityManager.THROWASSERT("DEFAULT clause has unexpected dependencies");
606                 }
607                 // Restore the previous AuxiliaryProviderList
608
cc.setCurrentAuxiliaryProviderList(prevAPL);
609             }
610
611         }
612         finally
613         {
614             cc.setReliability(previousReliability);
615         }
616     }
617
618
619     private static DefaultInfoImpl createDefaultInfoOfAutoInc(){
620         return new DefaultInfoImpl(true,
621                        null,
622                        null);
623     }
624     
625
626     /**
627      * Check the validity of the default for this node
628      *
629      * @param columnType TypeId of the target column.
630      * @param columnDesc Description of the type of the
631      * target column.
632      * @param defaultType TypeId of the default node.
633      * @param defaultNode Parsed ValueNode for the default value.
634      * @param defaultText Unparsed default value (as entered
635      * by user).
636      * @return True if the defaultNode abides by the restrictions
637      * imposed by DB2 on default constants; false otherwise.
638      *
639      */

640
641     public boolean defaultTypeIsValid(TypeId columnType,
642         DataTypeDescriptor columnDesc, TypeId defaultType,
643         ValueNode defaultNode, String JavaDoc defaultText)
644     throws StandardException
645     {
646
647         if (defaultText.length() > Limits.DB2_CHAR_MAXWIDTH)
648         // DB2 spec says this isn't allowed.
649
return false;
650
651         /* We can use info about the way the parser works
652          * to guide this process a little (see the getNumericNode()
653          * method in sqlgrammar.jj):
654          *
655          * 1) Tinyint and Smallints are both parsed as "INT" types,
656          * while integers larger than a basic "INT" are parsed into
657          * "LONGINT" or, if needed, "DECIMAL".
658          * 2) Floats, doubles, and decimals with fractional parts
659          * are all parsed as "DECIMAL".
660          * 3) All strings are parsed as "CHAR" constants (no varchar
661          * or any others; see stringLiteral() method in
662          * sqlgrammar.jj).
663          */

664
665         int colType = columnType.getTypeFormatId();
666         int defType = (defaultType == null ? -1 : defaultType.getTypeFormatId());
667
668         if (!defaultNode.isConstantExpression()) {
669         // then we have a built-in function, such as "user"
670
// or "current schema". If the function is a datetime
671
// value function, then we don't need any special
672
// action; however, if it's a "user" or "current schema"
673
// function, then the column must be a char type with
674
// minimum lengths matching those of DB2 (note that
675
// such limits are ONLY enforced on defaults, not at
676
// normal insertion time).
677

678             boolean charCol = ((colType == StoredFormatIds.CHAR_TYPE_ID) ||
679                 (colType == StoredFormatIds.VARCHAR_TYPE_ID) ||
680                 (colType == StoredFormatIds.LONGVARCHAR_TYPE_ID));
681
682             if (defaultNode instanceof SpecialFunctionNode) {
683
684                 switch (defaultNode.getNodeType())
685                 {
686                 case C_NodeTypes.USER_NODE:
687                 case C_NodeTypes.CURRENT_USER_NODE:
688                 case C_NodeTypes.SESSION_USER_NODE:
689                 case C_NodeTypes.SYSTEM_USER_NODE:
690                 // DB2 enforces min length of 8.
691
// Note also: any size under 30 gives a warning in DB2.
692
return (charCol && (columnDesc.getMaximumWidth() >=
693                         Limits.DB2_MIN_COL_LENGTH_FOR_CURRENT_USER));
694
695                 case C_NodeTypes.CURRENT_SCHEMA_NODE:
696                 // DB2 enforces min length of 128.
697
return (charCol && (columnDesc.getMaximumWidth() >=
698                         Limits.DB2_MIN_COL_LENGTH_FOR_CURRENT_SCHEMA));
699                 default:
700                     // else, function not allowed.
701
return false;
702                 }
703             }
704
705         }
706
707         switch (colType) {
708
709             case StoredFormatIds.INT_TYPE_ID:
710             // DB2 doesn't allow floating point values to be used
711
// as defaults for integer columns (they ARE allowed
712
// as part of normal insertions, but not as defaults).
713
// If the default is an integer that's too big, then
714
// it won't have type INT_TYPE_ID (it'll be either
715
// LONGINT or DECIMAL)--so we only allow the default
716
// value if it's integer.
717
return (defType == StoredFormatIds.INT_TYPE_ID);
718
719             case StoredFormatIds.LONGINT_TYPE_ID:
720             // This is a BIGINT column: we allow smallints, ints,
721
// and big int constants. Smallint and int literals
722
// are both covered by INT_TYPE; big int literals are
723
// covered by LONG_INT type.
724
return ((defType == StoredFormatIds.INT_TYPE_ID)
725                     || (defType == StoredFormatIds.LONGINT_TYPE_ID));
726     
727             case StoredFormatIds.DECIMAL_TYPE_ID:
728                 if (defType == StoredFormatIds.DECIMAL_TYPE_ID) {
729                 // only valid if scale and precision are within
730
// those of the column. Note that scale here should
731
// exclude any trailing 0's after the decimal
732
DataTypeDescriptor defDesc = defaultNode.getTypeServices();
733                     int len = defaultText.length();
734                     int precision = defDesc.getPrecision();
735                     int scale = defDesc.getScale();
736                     for (int i = 1; i <= scale; scale--, precision--) {
737                         if (defaultText.charAt(len - i) != '0')
738                             break;
739                     }
740                     return ((scale <= columnDesc.getScale()) &&
741                         ((precision - scale) <=
742                         (columnDesc.getPrecision() - columnDesc.getScale())));
743                 }
744                 else if ((defType == StoredFormatIds.LONGINT_TYPE_ID) ||
745                     (defType == StoredFormatIds.INT_TYPE_ID)) {
746                 // only valid if number of digits is within limits of
747
// the decimal column. We'll check this at insertion time;
748
// see Beetle 5585 regarding the need to move that check to
749
// here instead of waiting until insert time. Until that's
750
// done, just allow this and wait for insertion...
751
return true;
752                 }
753                 else
754                 // no other types allowed.
755
return false;
756
757             case StoredFormatIds.CHAR_TYPE_ID:
758             case StoredFormatIds.VARCHAR_TYPE_ID:
759             case StoredFormatIds.LONGVARCHAR_TYPE_ID:
760             // only valid if the default type is a character string.
761
// That's not to say that all character defaults are
762
// valid, but we only check for character string here;
763
// further checking will be done at insertion time. See
764
// beetle 5585 regarding the need to move that check
765
// to here instead of waiting until insert time.
766
return (defType == StoredFormatIds.CHAR_TYPE_ID);
767
768             case StoredFormatIds.BIT_TYPE_ID:
769             case StoredFormatIds.VARBIT_TYPE_ID:
770             case StoredFormatIds.LONGVARBIT_TYPE_ID:
771             // only valid if the default type is a BIT string.
772
return (defType == StoredFormatIds.BIT_TYPE_ID);
773
774             case StoredFormatIds.USERDEFINED_TYPE_ID_V3:
775             // default is only valid if it's the same type as the column.
776
return (defType == colType);
777
778             case StoredFormatIds.BLOB_TYPE_ID:
779             case StoredFormatIds.CLOB_TYPE_ID:
780             case StoredFormatIds.SMALLINT_TYPE_ID:
781             case StoredFormatIds.REAL_TYPE_ID:
782             case StoredFormatIds.DOUBLE_TYPE_ID:
783             case StoredFormatIds.DATE_TYPE_ID:
784             case StoredFormatIds.TIME_TYPE_ID:
785             case StoredFormatIds.TIMESTAMP_TYPE_ID:
786             // For these types, validity checks will be performed
787
// by Cloudscape at insertion time--see beetle 5585 regarding
788
// the need to do such checks here instead of later. For now,
789
// just assume we're okay.
790
return true;
791
792             default:
793             // All other default type checks either
794
// (TINYINT, NATIONAL_CHAR, etc), or 2) require a DB2 cast-
795
// function (ex. blob(...), which Cloudscape doesn't
796
// support yet--see Beetle 5281), and so they are not
797
// valid for Cloudscape running in DB2 compatibility mode.
798
return false;
799
800         }
801
802     }
803
804 }
805
Popular Tags