001: /*
002:
003: Derby - Class org.apache.derby.impl.sql.execute.CreateTableConstantAction
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to you under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.impl.sql.execute;
023:
024: import org.apache.derby.iapi.sql.execute.ConstantAction;
025:
026: import org.apache.derby.iapi.store.access.TransactionController;
027:
028: import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
029:
030: import org.apache.derby.iapi.sql.dictionary.DataDescriptorGenerator;
031: import org.apache.derby.iapi.sql.dictionary.DataDictionary;
032: import org.apache.derby.iapi.sql.dictionary.DefaultDescriptor;
033: import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor;
034: import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptorList;
035: import org.apache.derby.iapi.sql.dictionary.ColumnDescriptor;
036: import org.apache.derby.iapi.sql.dictionary.ColumnDescriptorList;
037: import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
038: import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
039:
040: import org.apache.derby.iapi.sql.depend.Provider;
041: import org.apache.derby.iapi.sql.depend.ProviderInfo;
042:
043: import org.apache.derby.iapi.sql.execute.ExecRow;
044:
045: import org.apache.derby.iapi.sql.Activation;
046: import org.apache.derby.iapi.sql.depend.DependencyManager;
047:
048: import org.apache.derby.iapi.error.StandardException;
049:
050: import org.apache.derby.iapi.services.sanity.SanityManager;
051:
052: import org.apache.derby.catalog.UUID;
053:
054: import org.apache.derby.catalog.types.DefaultInfoImpl;
055:
056: import java.util.Properties;
057:
058: /**
059: * This class describes actions that are ALWAYS performed for a
060: * CREATE TABLE Statement at Execution time.
061: *
062: * @author Rick Hillegas Extracted code from CreateTableResultSet.
063: */
064:
065: class CreateTableConstantAction extends DDLConstantAction {
066:
067: private char lockGranularity;
068: private boolean onCommitDeleteRows; //If true, on commit delete rows else on commit preserve rows of temporary table.
069: 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
070: private String tableName;
071: private String schemaName;
072: private int tableType;
073: private ColumnInfo[] columnInfo;
074: private CreateConstraintConstantAction[] constraintActions;
075: private Properties properties;
076:
077: /**
078: * Make the ConstantAction for a CREATE TABLE statement.
079: *
080: * @param schemaName name for the schema that table lives in.
081: * @param tableName Name of table.
082: * @param tableType Type of table (e.g., BASE, global temporary table).
083: * @param columnInfo Information on all the columns in the table.
084: * (REMIND tableDescriptor ignored)
085: * @param constraintActions CreateConstraintConstantAction[] for constraints
086: * @param properties Optional table properties
087: * @param lockGranularity The lock granularity.
088: * @param onCommitDeleteRows If true, on commit delete rows else on commit preserve rows of temporary table.
089: * @param onRollbackDeleteRows If true, on rollback, delete rows from temp tables which were logically modified. true is the only supported value
090: */
091: CreateTableConstantAction(String schemaName, String tableName,
092: int tableType, ColumnInfo[] columnInfo,
093: CreateConstraintConstantAction[] constraintActions,
094: Properties properties, char lockGranularity,
095: boolean onCommitDeleteRows, boolean onRollbackDeleteRows) {
096: this .schemaName = schemaName;
097: this .tableName = tableName;
098: this .tableType = tableType;
099: this .columnInfo = columnInfo;
100: this .constraintActions = constraintActions;
101: this .properties = properties;
102: this .lockGranularity = lockGranularity;
103: this .onCommitDeleteRows = onCommitDeleteRows;
104: this .onRollbackDeleteRows = onRollbackDeleteRows;
105:
106: if (SanityManager.DEBUG) {
107: if (tableType == TableDescriptor.BASE_TABLE_TYPE
108: && lockGranularity != TableDescriptor.TABLE_LOCK_GRANULARITY
109: && lockGranularity != TableDescriptor.ROW_LOCK_GRANULARITY) {
110: SanityManager
111: .THROWASSERT("Unexpected value for lockGranularity = "
112: + lockGranularity);
113: }
114: if (tableType == TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE
115: && onRollbackDeleteRows == false) {
116: SanityManager
117: .THROWASSERT("Unexpected value for onRollbackDeleteRows = "
118: + onRollbackDeleteRows);
119: }
120: SanityManager.ASSERT(schemaName != null,
121: "SchemaName is null");
122: }
123: }
124:
125: // OBJECT METHODS
126:
127: public String toString() {
128: if (tableType == TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE)
129: return constructToString("DECLARE GLOBAL TEMPORARY TABLE ",
130: tableName);
131: else
132: return constructToString("CREATE TABLE ", tableName);
133: }
134:
135: // INTERFACE METHODS
136:
137: /**
138: * This is the guts of the Execution-time logic for CREATE TABLE.
139: *
140: * @see ConstantAction#executeConstantAction
141: *
142: * @exception StandardException Thrown on failure
143: */
144: public void executeConstantAction(Activation activation)
145: throws StandardException {
146: TableDescriptor td;
147: UUID toid;
148: SchemaDescriptor schemaDescriptor;
149: ColumnDescriptor columnDescriptor;
150: ExecRow template;
151:
152: LanguageConnectionContext lcc = activation
153: .getLanguageConnectionContext();
154: DataDictionary dd = lcc.getDataDictionary();
155: DependencyManager dm = dd.getDependencyManager();
156: TransactionController tc = lcc.getTransactionExecute();
157:
158: /* Mark the activation as being for create table */
159: activation.setForCreateTable();
160:
161: /*
162: ** Create a row template to tell the store what type of rows this table
163: ** holds.
164: */
165: template = RowUtil.getEmptyValueRow(columnInfo.length, lcc);
166:
167: /* Get a template value for each column */
168: for (int ix = 0; ix < columnInfo.length; ix++) {
169: /* If there is a default value, use it, otherwise use null */
170: if (columnInfo[ix].defaultValue != null)
171: template.setColumn(ix + 1, columnInfo[ix].defaultValue);
172: else
173: template.setColumn(ix + 1, columnInfo[ix].dataType
174: .getNull());
175: }
176:
177: /* create the conglomerate to hold the table's rows
178: * RESOLVE - If we ever have a conglomerate creator
179: * that lets us specify the conglomerate number then
180: * we will need to handle it here.
181: */
182: long conglomId = tc
183: .createConglomerate(
184: "heap", // we're requesting a heap conglomerate
185: template.getRowArray(), // row template
186: null, //column sort order - not required for heap
187: properties, // properties
188: tableType == TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE ? (TransactionController.IS_TEMPORARY | TransactionController.IS_KEPT)
189: : TransactionController.IS_DEFAULT);
190:
191: /*
192: ** Inform the data dictionary that we are about to write to it.
193: ** There are several calls to data dictionary "get" methods here
194: ** that might be done in "read" mode in the data dictionary, but
195: ** it seemed safer to do this whole operation in "write" mode.
196: **
197: ** We tell the data dictionary we're done writing at the end of
198: ** the transaction.
199: */
200: if (tableType != TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE)
201: dd.startWriting(lcc);
202:
203: SchemaDescriptor sd;
204: if (tableType == TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE)
205: sd = dd.getSchemaDescriptor(schemaName, tc, true);
206: else
207: sd = DDLConstantAction.getSchemaDescriptorForCreate(dd,
208: activation, schemaName);
209:
210: //
211: // Create a new table descriptor.
212: //
213: DataDescriptorGenerator ddg = dd.getDataDescriptorGenerator();
214:
215: if (tableType != TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE) {
216: td = ddg.newTableDescriptor(tableName, sd, tableType,
217: lockGranularity);
218: dd.addDescriptor(td, sd,
219: DataDictionary.SYSTABLES_CATALOG_NUM, false, tc);
220: } else {
221: td = ddg.newTableDescriptor(tableName, sd, tableType,
222: onCommitDeleteRows, onRollbackDeleteRows);
223: td.setUUID(dd.getUUIDFactory().createUUID());
224: }
225: toid = td.getUUID();
226:
227: // Save the TableDescriptor off in the Activation
228: activation.setDDLTableDescriptor(td);
229:
230: /* NOTE: We must write the columns out to the system
231: * tables before any of the conglomerates, including
232: * the heap, since we read the columns before the
233: * conglomerates when building a TableDescriptor.
234: * This will hopefully reduce the probability of
235: * a deadlock involving those system tables.
236: */
237:
238: // for each column, stuff system.column
239: int index = 1;
240:
241: ColumnDescriptor[] cdlArray = new ColumnDescriptor[columnInfo.length];
242: for (int ix = 0; ix < columnInfo.length; ix++) {
243: UUID defaultUUID = columnInfo[ix].newDefaultUUID;
244:
245: /* Generate a UUID for the default, if one exists
246: * and there is no default id yet.
247: */
248: if (columnInfo[ix].defaultInfo != null
249: && defaultUUID == null) {
250: defaultUUID = dd.getUUIDFactory().createUUID();
251: }
252:
253: if (columnInfo[ix].autoincInc != 0)//dealing with autoinc column
254: columnDescriptor = new ColumnDescriptor(
255: columnInfo[ix].name,
256: index++,
257: columnInfo[ix].dataType,
258: columnInfo[ix].defaultValue,
259: columnInfo[ix].defaultInfo,
260: td,
261: defaultUUID,
262: columnInfo[ix].autoincStart,
263: columnInfo[ix].autoincInc,
264: columnInfo[ix].autoinc_create_or_modify_Start_Increment);
265: else
266: columnDescriptor = new ColumnDescriptor(
267: columnInfo[ix].name, index++,
268: columnInfo[ix].dataType,
269: columnInfo[ix].defaultValue,
270: columnInfo[ix].defaultInfo, td, defaultUUID,
271: columnInfo[ix].autoincStart,
272: columnInfo[ix].autoincInc);
273:
274: cdlArray[ix] = columnDescriptor;
275: }
276:
277: if (tableType != TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE) {
278: dd.addDescriptorArray(cdlArray, td,
279: DataDictionary.SYSCOLUMNS_CATALOG_NUM, false, tc);
280: }
281:
282: // now add the column descriptors to the table.
283: ColumnDescriptorList cdl = td.getColumnDescriptorList();
284: for (int i = 0; i < cdlArray.length; i++)
285: cdl.add(cdlArray[i]);
286:
287: //
288: // Create a conglomerate desciptor with the conglomId filled in and
289: // add it.
290: //
291: // RESOLVE: Get information from the conglomerate descriptor which
292: // was provided.
293: //
294: ConglomerateDescriptor cgd = ddg.newConglomerateDescriptor(
295: conglomId, null, false, null, false, null, toid, sd
296: .getUUID());
297: if (tableType != TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE) {
298: dd.addDescriptor(cgd, sd,
299: DataDictionary.SYSCONGLOMERATES_CATALOG_NUM, false,
300: tc);
301: }
302:
303: // add the newly added conglomerate to the table descriptor
304: ConglomerateDescriptorList conglomList = td
305: .getConglomerateDescriptorList();
306: conglomList.add(cgd);
307:
308: /* Create any constraints */
309: if (constraintActions != null) {
310: /*
311: ** Do everything but FK constraints first,
312: ** then FK constraints on 2nd pass.
313: */
314: for (int conIndex = 0; conIndex < constraintActions.length; conIndex++) {
315: // skip fks
316: if (!constraintActions[conIndex]
317: .isForeignKeyConstraint()) {
318: constraintActions[conIndex]
319: .executeConstantAction(activation);
320: }
321: }
322:
323: for (int conIndex = 0; conIndex < constraintActions.length; conIndex++) {
324: // only foreign keys
325: if (constraintActions[conIndex]
326: .isForeignKeyConstraint()) {
327: constraintActions[conIndex]
328: .executeConstantAction(activation);
329: }
330: }
331: }
332: if (tableType == TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE) {
333: lcc.addDeclaredGlobalTempTable(td);
334: }
335: }
336:
337: }
|