KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.compile.TableElementList
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.sanity.SanityManager;
25
26 import org.apache.derby.iapi.error.StandardException;
27
28 import org.apache.derby.iapi.sql.compile.CompilerContext;
29 import org.apache.derby.iapi.sql.compile.C_NodeTypes;
30
31 import org.apache.derby.iapi.types.DataTypeDescriptor;
32
33 import org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor;
34 import org.apache.derby.iapi.sql.dictionary.DataDictionary;
35 import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
36 import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
37
38 import org.apache.derby.iapi.sql.depend.DependencyManager;
39 import org.apache.derby.iapi.sql.depend.ProviderInfo;
40 import org.apache.derby.iapi.sql.depend.ProviderList;
41
42 import org.apache.derby.iapi.reference.SQLState;
43
44 import org.apache.derby.impl.sql.execute.ColumnInfo;
45 import org.apache.derby.impl.sql.execute.ConstraintInfo;
46 import org.apache.derby.impl.sql.execute.ConstraintConstantAction;
47 import org.apache.derby.impl.sql.execute.IndexConstantAction;
48
49 import org.apache.derby.iapi.sql.dictionary.ConstraintDescriptorList;
50 import org.apache.derby.iapi.sql.dictionary.ColumnDescriptor;
51
52 import org.apache.derby.catalog.UUID;
53
54 import java.util.Hashtable JavaDoc;
55 import java.util.Vector JavaDoc;
56
57 /**
58  * A TableElementList represents the list of columns and other table elements
59  * such as constraints in a CREATE TABLE or ALTER TABLE statement.
60  *
61  * @author Jeff Lichtman
62  */

63
64 public class TableElementList extends QueryTreeNodeVector
65 {
66     private int numColumns;
67     private TableDescriptor td;
68
69     /**
70      * Add a TableElementNode to this TableElementList
71      *
72      * @param tableElement The TableElementNode to add to this list
73      */

74
75     public void addTableElement(TableElementNode tableElement)
76     {
77         addElement(tableElement);
78         if ((tableElement instanceof ColumnDefinitionNode) ||
79             tableElement.getElementType() == TableElementNode.AT_DROP_COLUMN)
80         {
81             numColumns++;
82         }
83     }
84
85     /**
86      * Convert this object to a String. See comments in QueryTreeNode.java
87      * for how this should be done for tree printing.
88      *
89      * @return This object as a String
90      */

91
92     public String JavaDoc toString()
93     {
94         if (SanityManager.DEBUG)
95         {
96             StringBuffer JavaDoc buffer = new StringBuffer JavaDoc("");
97
98             for (int index = 0; index < size(); index++)
99             {
100                 buffer.append(elementAt(index).toString()).append("\n");
101             }
102
103             return buffer.toString();
104         }
105         else
106         {
107             return "";
108         }
109     }
110
111     /**
112      * Validate this TableElementList. This includes checking for
113      * duplicate columns names, and checking that user types really exist.
114      *
115      * @param ddlStmt DDLStatementNode which contains this list
116      * @param dd DataDictionary to use
117      * @param td TableDescriptor for table, if existing table.
118      *
119      * @exception StandardException Thrown on error
120      */

121     void validate(DDLStatementNode ddlStmt,
122                          DataDictionary dd,
123                          TableDescriptor td)
124                     throws StandardException
125     {
126         this.td = td;
127         int numAutoCols = 0;
128
129         int size = size();
130         Hashtable JavaDoc columnHT = new Hashtable JavaDoc(size + 2, (float) .999);
131         Hashtable JavaDoc constraintHT = new Hashtable JavaDoc(size + 2, (float) .999);
132         //all the primary key/unique key constraints for this table
133
Vector JavaDoc constraintsVector = new Vector JavaDoc();
134
135         //special case for alter table (td is not null in case of alter table)
136
if (td != null)
137         {
138             //In case of alter table, get the already existing primary key and unique
139
//key constraints for this table. And then we will compare them with new
140
//primary key/unique key constraint column lists.
141
ConstraintDescriptorList cdl = dd.getConstraintDescriptors(td);
142             ConstraintDescriptor cd;
143
144             if (cdl != null) //table does have some pre-existing constraints defined on it
145
{
146                 for (int i=0; i<cdl.size();i++)
147                 {
148                     cd = cdl.elementAt(i);
149                     //if the constraint type is not primary key or unique key, ignore it.
150
if (cd.getConstraintType() == DataDictionary.PRIMARYKEY_CONSTRAINT ||
151                     cd.getConstraintType() == DataDictionary.UNIQUE_CONSTRAINT)
152                         constraintsVector.addElement(cd);
153                 }
154             }
155         }
156
157         int tableType = TableDescriptor.BASE_TABLE_TYPE;
158         if (ddlStmt instanceof CreateTableNode)
159             tableType = ((CreateTableNode)ddlStmt).tableType;
160
161         for (int index = 0; index < size; index++)
162         {
163             TableElementNode tableElement = (TableElementNode) elementAt(index);
164
165             if (tableElement instanceof ColumnDefinitionNode)
166             {
167                 ColumnDefinitionNode cdn = (ColumnDefinitionNode) elementAt(index);
168                 if (tableType == TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE &&
169                     (cdn.getDataTypeServices().getTypeId().isLongConcatableTypeId() ||
170                     cdn.getDataTypeServices().getTypeId().isUserDefinedTypeId()))
171                 {
172                     throw StandardException.newException(SQLState.LANG_LONG_DATA_TYPE_NOT_ALLOWED, cdn.getColumnName());
173                 }
174                 checkForDuplicateColumns(ddlStmt, columnHT, cdn.getColumnName());
175                 cdn.checkUserType(td);
176                 cdn.bindAndValidateDefault(dd, td);
177
178                 cdn.validateAutoincrement(dd, td, tableType);
179
180                 if (tableElement instanceof ModifyColumnNode)
181                 {
182                     ModifyColumnNode mcdn = (ModifyColumnNode)cdn;
183                     mcdn.checkExistingConstraints(td);
184                 } else if (cdn.isAutoincrementColumn())
185                     numAutoCols ++;
186             }
187             else if (tableElement.getElementType() == TableElementNode.AT_DROP_COLUMN)
188             {
189                 String JavaDoc colName = tableElement.getName();
190                 if (td.getColumnDescriptor(colName) == null)
191                 {
192                     throw StandardException.newException(
193                                                 SQLState.LANG_COLUMN_NOT_FOUND_IN_TABLE,
194                                                 colName,
195                                                 td.getQualifiedName());
196                 }
197                 break;
198             }
199
200             /* The rest of this method deals with validating constraints */
201             if (! (tableElement.hasConstraint()))
202             {
203                 continue;
204             }
205
206             ConstraintDefinitionNode cdn = (ConstraintDefinitionNode) tableElement;
207
208             cdn.bind(ddlStmt, dd);
209
210             //if constraint is primary key or unique key, add it to the vector
211
if (cdn.getConstraintType() == DataDictionary.PRIMARYKEY_CONSTRAINT ||
212             cdn.getConstraintType() == DataDictionary.UNIQUE_CONSTRAINT)
213             {
214                 /* In case of create table, the vector can have only ConstraintDefinitionNode
215                 * elements. In case of alter table, it can have both ConstraintDefinitionNode
216                 * (for new constraints) and ConstraintDescriptor(for pre-existing constraints).
217                 */

218
219                 Object JavaDoc destConstraint;
220                 String JavaDoc destName = null;
221                 String JavaDoc[] destColumnNames = null;
222
223                 for (int i=0; i<constraintsVector.size();i++)
224                 {
225
226                     destConstraint = constraintsVector.elementAt(i);
227                     if (destConstraint instanceof ConstraintDefinitionNode)
228                     {
229                         ConstraintDefinitionNode destCDN = (ConstraintDefinitionNode)destConstraint;
230                         destName = destCDN.getConstraintMoniker();
231                         destColumnNames = destCDN.getColumnList().getColumnNames();
232                     }
233                     else if (destConstraint instanceof ConstraintDescriptor)
234                     {
235                         //will come here only for pre-existing constraints in case of alter table
236
ConstraintDescriptor destCD = (ConstraintDescriptor)destConstraint;
237                         destName = destCD.getConstraintName();
238                         destColumnNames = destCD.getColumnDescriptors().getColumnNames();
239                     }
240                     //check if there are multiple constraints with same set of columns
241
if (columnsMatch(cdn.getColumnList().getColumnNames(), destColumnNames))
242                         throw StandardException.newException(SQLState.LANG_MULTIPLE_CONSTRAINTS_WITH_SAME_COLUMNS,
243                         cdn.getConstraintMoniker(), destName);
244                 }
245                 constraintsVector.addElement(cdn);
246             }
247
248             /* Make sure that there are no duplicate constraint names in the list */
249             if (cdn instanceof ConstraintDefinitionNode)
250                 checkForDuplicateConstraintNames(ddlStmt, constraintHT, cdn.getConstraintMoniker());
251
252             /* Make sure that the constraint we are trying to drop exists */
253             if (cdn.getConstraintType() == DataDictionary.DROP_CONSTRAINT)
254             {
255                 /*
256                 ** If no schema descriptor, then must be an invalid
257                 ** schema name.
258                 */

259
260                 String JavaDoc dropConstraintName = cdn.getConstraintMoniker();
261
262                 if (dropConstraintName != null) {
263
264                     String JavaDoc dropSchemaName = cdn.getDropSchemaName();
265
266                     SchemaDescriptor sd = dropSchemaName == null ? td.getSchemaDescriptor() :
267                                             getSchemaDescriptor(dropSchemaName);
268
269                     ConstraintDescriptor cd =
270                                 dd.getConstraintDescriptorByName(
271                                         td, sd, dropConstraintName,
272                                         false);
273                     if (cd == null)
274                     {
275                         throw StandardException.newException(SQLState.LANG_DROP_NON_EXISTENT_CONSTRAINT,
276                                 (sd.getSchemaName() + "."+ dropConstraintName),
277                                 td.getQualifiedName());
278                     }
279                     /* Statement is dependendent on the ConstraintDescriptor */
280                     getCompilerContext().createDependency(cd);
281                 }
282             }
283
284             if (cdn.hasPrimaryKeyConstraint())
285             {
286                 // for PRIMARY KEY, check that columns are unique
287
verifyUniqueColumnList(ddlStmt, cdn);
288
289                 if (td == null)
290                 {
291                     // in CREATE TABLE so set PRIMARY KEY columns to NOT NULL
292
setColumnListToNotNull(cdn);
293                 }
294                 else
295                 {
296                     // in ALTER TABLE so raise error if any columns are nullable
297
checkForNullColumns(cdn, td);
298                 }
299             }
300             else if (cdn.hasUniqueKeyConstraint())
301             {
302                 // for UNIQUE, check that columns are unique and NOT NULL
303
verifyUniqueColumnList(ddlStmt, cdn);
304                 checkForNullColumns(cdn, td);
305             }
306             else if (cdn.hasForeignKeyConstraint())
307             {
308                 // for FOREIGN KEY, check that columns are unique
309
verifyUniqueColumnList(ddlStmt, cdn);
310             }
311         }
312
313         /* Can have only one autoincrement column in DB2 mode */
314         if (numAutoCols > 1)
315             throw StandardException.newException(SQLState.LANG_MULTIPLE_AUTOINCREMENT_COLUMNS);
316
317     }
318
319     /**
320      * Count the number of constraints of the specified type.
321      *
322      * @param constraintType The constraint type to search for.
323      *
324      * @return int The number of constraints of the specified type.
325      */

326     public int countConstraints(int constraintType)
327     {
328         int numConstraints = 0;
329         int size = size();
330
331         for (int index = 0; index < size; index++)
332         {
333             ConstraintDefinitionNode cdn;
334             TableElementNode element = (TableElementNode) elementAt(index);
335
336             if (! (element instanceof ConstraintDefinitionNode))
337             {
338                 continue;
339             }
340
341             cdn = (ConstraintDefinitionNode) element;
342
343             if (constraintType == cdn.getConstraintType())
344             {
345                 numConstraints++;
346             }
347         }
348
349         return numConstraints;
350     }
351
352     /**
353      * Count the number of columns.
354      *
355      * @return int The number of columns.
356      */

357     public int countNumberOfColumns()
358     {
359         return numColumns;
360     }
361
362     /**
363      * Fill in the ColumnInfo[] for this table element list.
364      *
365      * @param colInfos The ColumnInfo[] to be filled in.
366      *
367      * @return int The number of constraints in the create table.
368      */

369     public int genColumnInfos(ColumnInfo[] colInfos)
370     {
371         int numConstraints = 0;
372         int size = size();
373
374         for (int index = 0; index < size; index++)
375         {
376             if (((TableElementNode) elementAt(index)).getElementType() == TableElementNode.AT_DROP_COLUMN)
377             {
378                 colInfos[index] = new ColumnInfo(
379                                 ((TableElementNode) elementAt(index)).getName(),
380                                 null, null, null, null, null,
381                                 ColumnInfo.DROP, 0, 0, 0);
382                 break;
383             }
384
385             if (! (elementAt(index) instanceof ColumnDefinitionNode))
386             {
387                 if (SanityManager.DEBUG)
388                 {
389                     SanityManager.ASSERT( elementAt(index) instanceof ConstraintDefinitionNode,
390                         "elementAt(index) expected to be instanceof " +
391                         "ConstraintDefinitionNode");
392                 }
393
394                 /* Remember how many constraints that we've seen */
395                 numConstraints++;
396                 continue;
397             }
398
399             ColumnDefinitionNode coldef = (ColumnDefinitionNode) elementAt(index);
400
401             colInfos[index - numConstraints] =
402                 new ColumnInfo(coldef.getColumnName(),
403                                coldef.getDataTypeServices(),
404                                coldef.getDefaultValue(),
405                                coldef.getDefaultInfo(),
406                                (UUID) null,
407                                coldef.getOldDefaultUUID(),
408                                coldef.getAction(),
409                                (coldef.isAutoincrementColumn() ?
410                                 coldef.getAutoincrementStart() : 0),
411                                (coldef.isAutoincrementColumn() ?
412                                 coldef.getAutoincrementIncrement() : 0),
413                                (coldef.isAutoincrementColumn() ?
414                                 coldef.getAutoinc_create_or_modify_Start_Increment() : -1));
415
416             /* Remember how many constraints that we've seen */
417             if (coldef.hasConstraint())
418             {
419                 numConstraints++;
420             }
421         }
422
423         return numConstraints;
424     }
425     /**
426      * Append goobered up ResultColumns to the table's RCL.
427      * This is useful for binding check constraints for CREATE and ALTER TABLE.
428      *
429      * @param table The table in question.
430      *
431      * @exception StandardException Thrown on error
432      */

433     public void appendNewColumnsToRCL(FromBaseTable table)
434         throws StandardException
435     {
436         int size = size();
437         ResultColumnList rcl = table.getResultColumns();
438         TableName exposedName = table.getTableName();
439
440         for (int index = 0; index < size; index++)
441         {
442             if (elementAt(index) instanceof ColumnDefinitionNode)
443             {
444                 ColumnDefinitionNode cdn = (ColumnDefinitionNode) elementAt(index);
445                 ResultColumn resultColumn;
446                 ValueNode valueNode;
447
448                 /* Build a ResultColumn/BaseColumnNode pair for the column */
449                 valueNode = (ValueNode) getNodeFactory().getNode(
450                                             C_NodeTypes.BASE_COLUMN_NODE,
451                                             cdn.getColumnName(),
452                                             exposedName,
453                                             cdn.getDataTypeServices(),
454                                             getContextManager());
455
456                 resultColumn = (ResultColumn) getNodeFactory().getNode(
457                                                 C_NodeTypes.RESULT_COLUMN,
458                                                 cdn.getDataTypeServices(),
459                                                 valueNode,
460                                                 getContextManager());
461                 resultColumn.setName(cdn.getColumnName());
462                 rcl.addElement(resultColumn);
463             }
464         }
465     }
466
467     /**
468      * Bind and validate all of the check constraints in this list against
469      * the specified FromList.
470      *
471      * @param fromList The FromList in question.
472      *
473      * @exception StandardException Thrown on error
474      */

475     void bindAndValidateCheckConstraints(FromList fromList)
476         throws StandardException
477     {
478         CompilerContext cc;
479         FromBaseTable table = (FromBaseTable) fromList.elementAt(0);
480         int size = size();
481
482         cc = getCompilerContext();
483
484         Vector JavaDoc aggregateVector = new Vector JavaDoc();
485
486         for (int index = 0; index < size; index++)
487         {
488             ConstraintDefinitionNode cdn;
489             TableElementNode element = (TableElementNode) elementAt(index);
490             ValueNode checkTree;
491
492             if (! (element instanceof ConstraintDefinitionNode))
493             {
494                 continue;
495             }
496
497             cdn = (ConstraintDefinitionNode) element;
498
499             if (cdn.getConstraintType() != DataDictionary.CHECK_CONSTRAINT)
500             {
501                 continue;
502             }
503
504             checkTree = cdn.getCheckCondition();
505
506             // bind the check condition
507
// verify that it evaluates to a boolean
508
final int previousReliability = cc.getReliability();
509             try
510             {
511                 /* Each check constraint can have its own set of dependencies.
512                  * These dependencies need to be shared with the prepared
513                  * statement as well. We create a new auxiliary provider list
514                  * for the check constraint, "push" it on the compiler context
515                  * by swapping it with the current auxiliary provider list
516                  * and the "pop" it when we're done by restoring the old
517                  * auxiliary provider list.
518                  */

519                 ProviderList apl = new ProviderList();
520
521                 ProviderList prevAPL = cc.getCurrentAuxiliaryProviderList();
522                 cc.setCurrentAuxiliaryProviderList(apl);
523
524                 // Tell the compiler context to only allow deterministic nodes
525
cc.setReliability( CompilerContext.CHECK_CONSTRAINT );
526                 checkTree = checkTree.bindExpression(fromList, (SubqueryList) null,
527                                          aggregateVector);
528
529                 // no aggregates, please
530
if (aggregateVector.size() != 0)
531                 {
532                     throw StandardException.newException(SQLState.LANG_INVALID_CHECK_CONSTRAINT, cdn.getConstraintText());
533                 }
534                 
535                 checkTree = checkTree.checkIsBoolean();
536                 cdn.setCheckCondition(checkTree);
537
538                 /* Save the APL off in the constraint node */
539                 if (apl.size() > 0)
540                 {
541                     cdn.setAuxiliaryProviderList(apl);
542                 }
543
544                 // Restore the previous AuxiliaryProviderList
545
cc.setCurrentAuxiliaryProviderList(prevAPL);
546             }
547             finally
548             {
549                 cc.setReliability(previousReliability);
550             }
551     
552             /* We have a valid check constraint, now build an array of
553              * 1-based columnIds that the constraint references.
554              */

555             ResultColumnList rcl = table.getResultColumns();
556             int numReferenced = rcl.countReferencedColumns();
557             int[] checkColumnReferences = new int[numReferenced];
558
559             rcl.recordColumnReferences(checkColumnReferences, 1);
560             cdn.setCheckColumnReferences(checkColumnReferences);
561
562             /* Now we build a list with only the referenced columns and
563              * copy it to the cdn. Thus we can build the array of
564              * column names for the referenced columns during generate().
565              */

566             ResultColumnList refRCL =
567                         (ResultColumnList) getNodeFactory().getNode(
568                                                 C_NodeTypes.RESULT_COLUMN_LIST,
569                                                 getContextManager());
570             rcl.copyReferencedColumnsToNewList(refRCL);
571
572             /* A column check constraint can only refer to that column. If this is a
573              * column constraint, we should have an RCL with that column
574              */

575             if (cdn.getColumnList() != null)
576             {
577                 String JavaDoc colName = ((ResultColumn)(cdn.getColumnList().elementAt(0))).getName();
578                 if (numReferenced > 1 ||
579                     !colName.equals(((ResultColumn)(refRCL.elementAt(0))).getName()))
580                     throw StandardException.newException(SQLState.LANG_DB2_INVALID_CHECK_CONSTRAINT, colName);
581                 
582             }
583             cdn.setColumnList(refRCL);
584
585             /* Clear the column references in the RCL so each check constraint
586              * starts with a clean list.
587              */

588             rcl.clearColumnReferences();
589         }
590     }
591
592     /**
593      * Fill in the ConstraintConstantAction[] for this create/alter table.
594      *
595      * @param conActions The ConstraintConstantAction[] to be filled in.
596      * @param tableName The name of the Table being created.
597      * @param tableSd The schema for that table.
598      * @param dd The DataDictionary
599      *
600      * @exception StandardException Thrown on failure
601      */

602     void genConstraintActions(
603                 ConstraintConstantAction[] conActions,
604                 String JavaDoc tableName,
605                 SchemaDescriptor tableSd,
606                 DataDictionary dd)
607         throws StandardException
608     {
609         int size = size();
610         int conActionIndex = 0;
611         for (int index = 0; index < size; index++)
612         {
613             String JavaDoc[] columnNames = null;
614             TableElementNode ten = (TableElementNode) elementAt(index);
615             IndexConstantAction indexAction = null;
616
617             if (! ten.hasConstraint())
618             {
619                 continue;
620             }
621
622             if (ten instanceof ColumnDefinitionNode)
623             {
624                 continue;
625             }
626
627             ConstraintDefinitionNode constraintDN = (ConstraintDefinitionNode) ten;
628
629             if (constraintDN.getColumnList() != null)
630             {
631                 columnNames = new String JavaDoc[constraintDN.getColumnList().size()];
632                 constraintDN.getColumnList().exportNames(columnNames);
633             }
634
635             int constraintType = constraintDN.getConstraintType();
636             String JavaDoc constraintText = constraintDN.getConstraintText();
637
638             /*
639             ** If the constraint is not named (e.g.
640             ** create table x (x int primary key)), then
641             ** the constraintSd is the same as the table.
642             */

643             String JavaDoc constraintName = constraintDN.getConstraintMoniker();
644
645             /* At execution time, we will generate a unique name for the backing
646              * index (for CREATE CONSTRAINT) and we will look up the conglomerate
647              * name (for DROP CONSTRAINT).
648              */

649             if (constraintDN.requiresBackingIndex())
650             {
651                 indexAction = genIndexAction(constraintDN.requiresUniqueIndex(),
652                                              null, constraintDN,
653                                              columnNames, true, tableSd, tableName,
654                                              constraintType, dd);
655             }
656
657             if (constraintType == DataDictionary.DROP_CONSTRAINT)
658             {
659                 conActions[conActionIndex] =
660                     getGenericConstantActionFactory().
661                         getDropConstraintConstantAction(
662                                                  constraintName,
663                                                  constraintDN.getDropSchemaName(), /// FiX
664
tableName,
665                                                  td.getUUID(),
666                                                  tableSd.getSchemaName(),
667                                                  indexAction,
668                                                  constraintDN.getDropBehavior(),
669                                                  constraintDN.getVerifyType());
670             }
671             else
672             {
673                 ProviderList apl = constraintDN.getAuxiliaryProviderList();
674                 ConstraintInfo refInfo = null;
675                 ProviderInfo[] providerInfos = null;
676
677                 if (constraintDN instanceof FKConstraintDefinitionNode)
678                 {
679                     refInfo = ((FKConstraintDefinitionNode)constraintDN).getReferencedConstraintInfo();
680                 }
681
682                 /* Create the ProviderInfos, if the constraint is dependent on any Providers */
683                 if (apl != null && apl.size() > 0)
684                 {
685                     /* Get all the dependencies for the current statement and transfer
686                      * them to this view.
687                      */

688                     DependencyManager dm = dd.getDependencyManager();
689                     providerInfos = dm.getPersistentProviderInfos(apl);
690                 }
691                 else
692                 {
693                     providerInfos = new ProviderInfo[0];
694                     // System.out.println("TABLE ELEMENT LIST EMPTY");
695
}
696
697                 conActions[conActionIndex++] =
698                     getGenericConstantActionFactory().
699                         getCreateConstraintConstantAction(
700                                                  constraintName,
701                                                  constraintType,
702                                                  tableName,
703                                                  ((td != null) ? td.getUUID() : (UUID) null),
704                                                  tableSd.getSchemaName(),
705                                                  columnNames,
706                                                  indexAction,
707                                                  constraintText,
708                                                  true, // enabled
709
refInfo,
710                                                  providerInfos);
711             }
712         }
713     }
714
715       //check if one array is same as another
716
private boolean columnsMatch(String JavaDoc[] columnNames1, String JavaDoc[] columnNames2)
717     {
718         int srcCount, srcSize, destCount,destSize;
719         boolean match = true;
720
721         if (columnNames1.length != columnNames2.length)
722             return false;
723
724         srcSize = columnNames1.length;
725         destSize = columnNames2.length;
726
727         for (srcCount = 0; srcCount < srcSize; srcCount++)
728         {
729             match = false;
730             for (destCount = 0; destCount < destSize; destCount++) {
731                 if (columnNames1[srcCount].equals(columnNames2[destCount])) {
732                     match = true;
733                     break;
734                 }
735             }
736             if (match == false)
737                 return false;
738         }
739
740         return true;
741     }
742
743     private IndexConstantAction genIndexAction(
744                                         boolean isUnique,
745                                         String JavaDoc indexName,
746                                         ConstraintDefinitionNode cdn,
747                                         String JavaDoc[] columnNames,
748                                         boolean isConstraint,
749                                         SchemaDescriptor sd,
750                                         String JavaDoc tableName,
751                                         int constraintType,
752                                         DataDictionary dd)
753         throws StandardException
754     {
755         if ( indexName == null ) { indexName = cdn.getBackingIndexName(dd); }
756
757         if (constraintType == DataDictionary.DROP_CONSTRAINT)
758         {
759             return getGenericConstantActionFactory().getDropIndexConstantAction(
760                                       null,
761                                       indexName,
762                                       tableName,
763                                       sd.getSchemaName(),
764                                       td.getUUID(),
765                                       td.getHeapConglomerateId());
766         }
767         else
768         {
769             boolean[] isAscending = new boolean[columnNames.length];
770             for (int i = 0; i < isAscending.length; i++)
771                 isAscending[i] = true;
772             return getGenericConstantActionFactory().getCreateIndexConstantAction(
773                                     isUnique,
774                                     "BTREE", // indexType
775
sd.getSchemaName(),
776                                     indexName,
777                                     tableName,
778                                     ((td != null) ? td.getUUID() : (UUID) null),
779                                     0, // conglomId
780
columnNames,
781                                     isAscending,
782                                     isConstraint,
783                                     cdn.getBackingIndexUUID(),
784                                     cdn.getProperties());
785         }
786     }
787
788     /**
789      * Check to make sure that there are no duplicate column names
790      * in the list. (The comparison here is case sensitive.
791      * The work of converting column names that are not quoted
792      * identifiers to upper case is handled by the parser.)
793      * RESOLVE: This check will also be performed by alter table.
794      *
795      * @param ddlStmt DDLStatementNode which contains this list
796      * @param ht Hashtable for enforcing uniqueness.
797      * @param colName Column name to check for.
798      *
799      * @exception StandardException Thrown on error
800      */

801     private void checkForDuplicateColumns(DDLStatementNode ddlStmt,
802                                     Hashtable JavaDoc ht,
803                                     String JavaDoc colName)
804             throws StandardException
805     {
806         Object JavaDoc object = ht.put(colName, colName);
807         if (object != null)
808         {
809             /* RESOLVE - different error messages for create and alter table */
810             if (ddlStmt instanceof CreateTableNode)
811             {
812                 throw StandardException.newException(SQLState.LANG_DUPLICATE_COLUMN_NAME_CREATE, colName);
813             }
814         }
815     }
816
817     /**
818      * Check to make sure that there are no duplicate constraint names
819      * in the list. (The comparison here is case sensitive.
820      * The work of converting column names that are not quoted
821      * identifiers to upper case is handled by the parser.)
822      * RESOLVE: This check will also be performed by alter table.
823      *
824      * @param ddlStmt DDLStatementNode which contains this list
825      *
826      * @exception StandardException Thrown on error
827      */

828     private void checkForDuplicateConstraintNames(DDLStatementNode ddlStmt,
829                                     Hashtable JavaDoc ht,
830                                     String JavaDoc constraintName)
831             throws StandardException
832     {
833         if (constraintName == null)
834             return;
835
836         Object JavaDoc object = ht.put(constraintName, constraintName);
837         if (object != null) {
838
839             /* RESOLVE - different error messages for create and alter table */
840             if (ddlStmt instanceof CreateTableNode)
841             {
842                 /* RESOLVE - new error message */
843                 throw StandardException.newException(SQLState.LANG_DUPLICATE_CONSTRAINT_NAME_CREATE,
844                         constraintName);
845             }
846         }
847     }
848
849     /**
850      * Verify that a primary/unique table constraint has a valid column list.
851      * (All columns in table and no duplicates.)
852      *
853      * @param ddlStmt The outer DDLStatementNode
854      * @param cdn The ConstraintDefinitionNode
855      *
856      * @exception StandardException Thrown if the column list is invalid
857      */

858     private void verifyUniqueColumnList(DDLStatementNode ddlStmt,
859                                 ConstraintDefinitionNode cdn)
860         throws StandardException
861     {
862         String JavaDoc invalidColName;
863
864         /* Verify that every column in the list appears in the table's list of columns */
865         if (ddlStmt instanceof CreateTableNode)
866         {
867             invalidColName = cdn.getColumnList().verifyCreateConstraintColumnList(this);
868             if (invalidColName != null)
869             {
870                 throw StandardException.newException(SQLState.LANG_INVALID_CREATE_CONSTRAINT_COLUMN_LIST,
871                                 ddlStmt.getRelativeName(),
872                                 invalidColName);
873             }
874         }
875         else
876         {
877             /* RESOLVE - alter table will need to get table descriptor */
878         }
879
880         /* Check the uniqueness of the column names within the list */
881         invalidColName = cdn.getColumnList().verifyUniqueNames(false);
882         if (invalidColName != null)
883         {
884             throw StandardException.newException(SQLState.LANG_DUPLICATE_CONSTRAINT_COLUMN_NAME, invalidColName);
885         }
886     }
887
888     /**
889      * Set all columns in that appear in a PRIMARY KEY constraint in a CREATE TABLE statement to NOT NULL.
890      *
891      * @param cdn The ConstraintDefinitionNode for a PRIMARY KEY constraint
892      */

893     private void setColumnListToNotNull(ConstraintDefinitionNode cdn)
894     {
895         ResultColumnList rcl = cdn.getColumnList();
896         int rclSize = rcl.size();
897         for (int index = 0; index < rclSize; index++)
898         {
899             String JavaDoc colName = ((ResultColumn) rcl.elementAt(index)).getName();
900             DataTypeDescriptor dtd = getColumnDataTypeDescriptor(colName);
901             dtd.setNullability(false);
902         }
903     }
904
905
906     private void checkForNullColumns(ConstraintDefinitionNode cdn, TableDescriptor td) throws StandardException
907     {
908         ResultColumnList rcl = cdn.getColumnList();
909         int rclSize = rcl.size();
910         for (int index = 0; index < rclSize; index++)
911         {
912             String JavaDoc colName = ((ResultColumn) rcl.elementAt(index)).getName();
913             DataTypeDescriptor dtd;
914             if (td == null)
915             {
916                 dtd = getColumnDataTypeDescriptor(colName);
917             }
918             else
919             {
920                 dtd = getColumnDataTypeDescriptor(colName, td);
921             }
922             // todo dtd may be null if the column does not exist, we should check that first
923
if (dtd != null && dtd.isNullable())
924             {
925                 throw StandardException.newException(SQLState.LANG_DB2_ADD_UNIQUE_OR_PRIMARY_KEY_ON_NULL_COLS, colName);
926             }
927         }
928     }
929
930     private DataTypeDescriptor getColumnDataTypeDescriptor(String JavaDoc colName)
931     {
932         int size = size();
933
934         for (int index = 0; index < size; index++)
935         {
936             TableElementNode tableElement = (TableElementNode) elementAt(index);
937
938             if (tableElement instanceof ColumnDefinitionNode)
939             {
940                 ColumnDefinitionNode cdn = (ColumnDefinitionNode) tableElement;
941                 if (colName.equals(cdn.getColumnName()))
942                 {
943                     return cdn.getDataTypeServices();
944                 }
945             }
946         }
947         return null;
948     }
949
950     private DataTypeDescriptor getColumnDataTypeDescriptor(String JavaDoc colName, TableDescriptor td)
951     {
952         // check existing columns
953
ColumnDescriptor cd = td.getColumnDescriptor(colName);
954         if (cd != null)
955         {
956             return cd.getType();
957         }
958         // check for new columns
959
return getColumnDataTypeDescriptor(colName);
960     }
961
962     /**
963      * Determine whether or not the parameter matches a column name in this list.
964      *
965      * @param colName The column name to search for.
966      *
967      * @return boolean Whether or not a match is found.
968      */

969     public boolean containsColumnName(String JavaDoc colName)
970     {
971         int size = size();
972         for (int index = 0; index < size; index++)
973         {
974             TableElementNode tableElement = (TableElementNode) elementAt(index);
975
976             if (tableElement instanceof ColumnDefinitionNode)
977             {
978                 if (colName.equals(((ColumnDefinitionNode) tableElement).getName()))
979                 {
980                     return true;
981                 }
982             }
983         }
984
985         return false;
986     }
987 }
988
989
Popular Tags