KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.compile.CreateTableNode
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.reference.Property;
25 import org.apache.derby.iapi.reference.SQLState;
26 import org.apache.derby.iapi.reference.Limits;
27
28 import org.apache.derby.iapi.services.property.PropertyUtil;
29 import org.apache.derby.iapi.services.sanity.SanityManager;
30
31 import org.apache.derby.iapi.sql.execute.ConstantAction;
32
33 import org.apache.derby.iapi.sql.dictionary.DataDictionary;
34 import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
35 import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
36
37 import org.apache.derby.iapi.sql.compile.C_NodeTypes;
38
39 import org.apache.derby.iapi.error.StandardException;
40
41 import org.apache.derby.impl.sql.execute.ColumnInfo;
42 import org.apache.derby.impl.sql.execute.CreateConstraintConstantAction;
43 import org.apache.derby.iapi.types.DataTypeDescriptor;
44 import java.util.Properties JavaDoc;
45
46 /**
47  * A CreateTableNode is the root of a QueryTree that represents a CREATE TABLE or DECLARE GLOBAL TEMPORARY TABLE
48  * statement.
49  *
50  * @author Jeff Lichtman
51  */

52
53 public class CreateTableNode extends DDLStatementNode
54 {
55     private char lockGranularity;
56     private boolean onCommitDeleteRows; //If true, on commit delete rows else on commit preserve rows of temporary table.
57
private boolean onRollbackDeleteRows; //If true, on rollback delete rows from temp table if it was logically modified in that UOW. true is the only supported value
58
private Properties JavaDoc properties;
59     private TableElementList tableElementList;
60     protected int tableType; //persistent table or global temporary table
61

62     /**
63      * Initializer for a CreateTableNode for a base table
64      *
65      * @param newObjectName The name of the new object being created (ie base table)
66      * @param tableElementList The elements of the table: columns,
67      * constraints, etc.
68      * @param properties The optional list of properties associated with
69      * the table.
70      * @param lockGranularity The lock granularity.
71      *
72      * @exception StandardException Thrown on error
73      */

74
75     public void init(
76             Object JavaDoc newObjectName,
77             Object JavaDoc tableElementList,
78             Object JavaDoc properties,
79             Object JavaDoc lockGranularity)
80         throws StandardException
81     {
82         tableType = TableDescriptor.BASE_TABLE_TYPE;
83         this.lockGranularity = ((Character JavaDoc) lockGranularity).charValue();
84         implicitCreateSchema = true;
85
86         if (SanityManager.DEBUG)
87         {
88             if (this.lockGranularity != TableDescriptor.TABLE_LOCK_GRANULARITY &&
89                 this.lockGranularity != TableDescriptor.ROW_LOCK_GRANULARITY)
90             {
91                 SanityManager.THROWASSERT(
92                 "Unexpected value for lockGranularity = " + this.lockGranularity);
93             }
94         }
95
96         initAndCheck(newObjectName);
97         this.tableElementList = (TableElementList) tableElementList;
98         this.properties = (Properties JavaDoc) properties;
99     }
100
101     /**
102      * Initializer for a CreateTableNode for a global temporary table
103      *
104      * @param newObjectName The name of the new object being declared (ie temporary table)
105      * @param tableElementList The elements of the table: columns,
106      * constraints, etc.
107      * @param properties The optional list of properties associated with
108      * the table.
109      * @param onCommitDeleteRows If true, on commit delete rows else on commit preserve rows of temporary table.
110      * @param onRollbackDeleteRows If true, on rollback, delete rows from temp tables which were logically modified. true is the only supported value
111      *
112      * @exception StandardException Thrown on error
113      */

114
115     public void init(
116             Object JavaDoc newObjectName,
117             Object JavaDoc tableElementList,
118             Object JavaDoc properties,
119             Object JavaDoc onCommitDeleteRows,
120             Object JavaDoc onRollbackDeleteRows)
121         throws StandardException
122     {
123         tableType = TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE;
124         newObjectName = tempTableSchemaNameCheck(newObjectName);
125         this.onCommitDeleteRows = ((Boolean JavaDoc) onCommitDeleteRows).booleanValue();
126         this.onRollbackDeleteRows = ((Boolean JavaDoc) onRollbackDeleteRows).booleanValue();
127         initAndCheck(newObjectName);
128         this.tableElementList = (TableElementList) tableElementList;
129         this.properties = (Properties JavaDoc) properties;
130
131         if (SanityManager.DEBUG)
132         {
133             if (this.onRollbackDeleteRows == false)
134             {
135                 SanityManager.THROWASSERT(
136                 "Unexpected value for onRollbackDeleteRows = " + this.onRollbackDeleteRows);
137             }
138         }
139     }
140
141     /**
142      * If no schema name specified for global temporary table, SESSION is the implicit schema.
143      * Otherwise, make sure the specified schema name for global temporary table is SESSION.
144      * @param objectName The name of the new object being declared (ie temporary table)
145     */

146     private Object JavaDoc tempTableSchemaNameCheck(Object JavaDoc objectName)
147         throws StandardException {
148         TableName tempTableName = (TableName) objectName;
149         if (tempTableName != null)
150         {
151             if (tempTableName.getSchemaName() == null)
152                 tempTableName.setSchemaName(SchemaDescriptor.STD_DECLARED_GLOBAL_TEMPORARY_TABLES_SCHEMA_NAME); //If no schema specified, SESSION is the implicit schema.
153
else if (!(isSessionSchema(tempTableName.getSchemaName())))
154                 throw StandardException.newException(SQLState.LANG_DECLARED_GLOBAL_TEMP_TABLE_ONLY_IN_SESSION_SCHEMA);
155         }
156         return(tempTableName);
157     }
158
159     /**
160      * Convert this object to a String. See comments in QueryTreeNode.java
161      * for how this should be done for tree printing.
162      *
163      * @return This object as a String
164      */

165
166     public String JavaDoc toString()
167     {
168         if (SanityManager.DEBUG)
169         {
170             String JavaDoc tempString = "tableElementList: " + "\n" + tableElementList + "\n";
171             if (tableType == TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE)
172             {
173                 tempString = tempString + "onCommitDeleteRows: " + "\n" + onCommitDeleteRows + "\n";
174                 tempString = tempString + "onRollbackDeleteRows: " + "\n" + onRollbackDeleteRows + "\n";
175             } else
176                 tempString = tempString + "properties: " + "\n" + properties + "\n" + "lockGranularity: " + "\n" + lockGranularity + "\n";
177             return super.toString() + tempString;
178         }
179         else
180         {
181             return "";
182         }
183     }
184
185     public String JavaDoc statementToString()
186     {
187         if (tableType == TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE)
188             return "DECLARE GLOBAL TEMPORARY TABLE";
189         else
190             return "CREATE TABLE";
191     }
192
193     // We inherit the generate() method from DDLStatementNode.
194

195     /**
196      * Bind this CreateTableNode. This means doing any static error checking that can be
197      * done before actually creating the base table or declaring the global temporary table.
198      * For eg, verifying that the TableElementList does not contain any duplicate column names.
199      *
200      * @return The bound query tree
201      *
202      * @exception StandardException Thrown on error
203      */

204
205     public QueryTreeNode bind() throws StandardException
206     {
207         DataDictionary dataDictionary = getDataDictionary();
208         int numPrimaryKeys = 0;
209         int numCheckConstraints = 0;
210         int numReferenceConstraints = 0;
211         int numUniqueConstraints = 0;
212
213         tableElementList.validate(this, dataDictionary, (TableDescriptor) null);
214
215         /* Only 1012 columns allowed per table */
216         if (tableElementList.countNumberOfColumns() > Limits.DB2_MAX_COLUMNS_IN_TABLE)
217         {
218             throw StandardException.newException(SQLState.LANG_TOO_MANY_COLUMNS_IN_TABLE_OR_VIEW,
219                 String.valueOf(tableElementList.countNumberOfColumns()),
220                 getRelativeName(),
221                 String.valueOf(Limits.DB2_MAX_COLUMNS_IN_TABLE));
222         }
223
224         numPrimaryKeys = tableElementList.countConstraints(
225                                 DataDictionary.PRIMARYKEY_CONSTRAINT);
226
227         /* Only 1 primary key allowed per table */
228         if (numPrimaryKeys > 1)
229         {
230             throw StandardException.newException(SQLState.LANG_TOO_MANY_PRIMARY_KEY_CONSTRAINTS, getRelativeName());
231         }
232
233         /* Check the validity of all check constraints */
234         numCheckConstraints = tableElementList.countConstraints(
235                                     DataDictionary.CHECK_CONSTRAINT);
236
237         numReferenceConstraints = tableElementList.countConstraints(
238                                     DataDictionary.FOREIGNKEY_CONSTRAINT);
239
240         numUniqueConstraints = tableElementList.countConstraints(
241                                     DataDictionary.UNIQUE_CONSTRAINT);
242
243         //temp tables can't have primary key or check or foreign key or unique constraints defined on them
244
if ((tableType == TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE) &&
245             (numPrimaryKeys > 0 || numCheckConstraints > 0 || numReferenceConstraints > 0 || numUniqueConstraints > 0))
246                 throw StandardException.newException(SQLState.LANG_NOT_ALLOWED_FOR_DECLARED_GLOBAL_TEMP_TABLE);
247
248         //each of these constraints have a backing index in the back. We need to make sure that a table never has more
249
//more than 32767 indexes on it and that is why this check.
250
if ((numPrimaryKeys + numReferenceConstraints + numUniqueConstraints) > Limits.DB2_MAX_INDEXES_ON_TABLE)
251         {
252             throw StandardException.newException(SQLState.LANG_TOO_MANY_INDEXES_ON_TABLE,
253                 String.valueOf(numPrimaryKeys + numReferenceConstraints + numUniqueConstraints),
254                 getRelativeName(),
255                 String.valueOf(Limits.DB2_MAX_INDEXES_ON_TABLE));
256         }
257
258         if (numCheckConstraints > 0)
259         {
260             /* In order to check the validity of the check constraints
261              * we must goober up a FromList containing a single table,
262              * the table being created, with an RCL containing the
263              * new columns and their types. This will allow us to
264              * bind the constraint definition trees against that
265              * FromList. When doing this, we verify that there are
266              * no nodes which can return non-deterministic results.
267              */

268             FromList fromList = (FromList) getNodeFactory().getNode(
269                                     C_NodeTypes.FROM_LIST,
270                                     getNodeFactory().doJoinOrderOptimization(),
271                                     getContextManager());
272             FromBaseTable table = (FromBaseTable)
273                                     getNodeFactory().getNode(
274                                         C_NodeTypes.FROM_BASE_TABLE,
275                                         getObjectName(),
276                                         null,
277                                         null,
278                                         null,
279                                         getContextManager());
280             table.setTableNumber(0);
281             fromList.addFromTable(table);
282             table.setResultColumns((ResultColumnList) getNodeFactory().getNode(
283                                                 C_NodeTypes.RESULT_COLUMN_LIST,
284                                                 getContextManager()));
285             tableElementList.appendNewColumnsToRCL(table);
286
287             /* Now that we've finally goobered stuff up, bind and validate
288              * the check constraints.
289              */

290             tableElementList.bindAndValidateCheckConstraints(fromList);
291         }
292
293         return this;
294     }
295
296     /**
297      * Return true if the node references SESSION schema tables (temporary or permanent)
298      *
299      * @return true if references SESSION schema tables, else false
300      *
301      * @exception StandardException Thrown on error
302      */

303     public boolean referencesSessionSchema()
304         throws StandardException
305     {
306         //If table being created/declared is in SESSION schema, then return true.
307
return isSessionSchema(getSchemaDescriptor());
308     }
309
310     /**
311      * Create the Constant information that will drive the guts of Execution.
312      *
313      * @exception StandardException Thrown on failure
314      */

315     public ConstantAction makeConstantAction() throws StandardException
316     {
317         TableElementList coldefs = tableElementList;
318
319         // for each column, stuff system.column
320
ColumnInfo[] colInfos = new ColumnInfo[coldefs.countNumberOfColumns()];
321
322         int numConstraints = coldefs.genColumnInfos(colInfos);
323
324         /* If we've seen a constraint, then build a constraint list */
325         CreateConstraintConstantAction[] conActions = null;
326
327         SchemaDescriptor sd = getSchemaDescriptor();
328
329         if (numConstraints > 0)
330         {
331             conActions =
332                 new CreateConstraintConstantAction[numConstraints];
333
334             coldefs.genConstraintActions(
335                 conActions, getRelativeName(), sd, getDataDictionary());
336         }
337
338         // if the any of columns are "long" and user has not specified a
339
// page size, set the pagesize to 32k.
340
// Also in case where the approximate sum of the column sizes is
341
// greater than the bump threshold , bump the pagesize to 32k
342

343         boolean table_has_long_column = false;
344         int approxLength = 0;
345
346         for (int i = 0; i < colInfos.length; i++)
347         {
348             DataTypeDescriptor dts = colInfos[i].dataType;
349             if (dts.getTypeId().isLongConcatableTypeId())
350             {
351                 table_has_long_column = true;
352                 break;
353             }
354
355             approxLength += dts.getTypeId().getApproximateLengthInBytes(dts);
356         }
357
358         if (table_has_long_column || (approxLength > Property.TBL_PAGE_SIZE_BUMP_THRESHOLD))
359         {
360             if (((properties == null) ||
361                  (properties.get(Property.PAGE_SIZE_PARAMETER) == null)) &&
362                 (PropertyUtil.getServiceProperty(
363                      getLanguageConnectionContext().getTransactionCompile(),
364                      Property.PAGE_SIZE_PARAMETER) == null))
365             {
366                 // do not override the user's choice of page size, whether it
367
// is set for the whole database or just set on this statement.
368

369                 if (properties == null)
370                     properties = new Properties JavaDoc();
371
372                 properties.put(
373                     Property.PAGE_SIZE_PARAMETER,
374                     Property.PAGE_SIZE_DEFAULT_LONG);
375             }
376         }
377
378         return(
379             getGenericConstantActionFactory().getCreateTableConstantAction(
380                 sd.getSchemaName(),
381                 getRelativeName(),
382                 tableType,
383                 colInfos,
384                 conActions,
385                 properties,
386                 lockGranularity,
387                 onCommitDeleteRows,
388                 onRollbackDeleteRows));
389     }
390 }
391
Popular Tags