KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.compile.RenameNode
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.SQLState;
25
26 import org.apache.derby.iapi.sql.compile.CompilerContext;
27 import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor;
28 import org.apache.derby.iapi.sql.dictionary.DataDictionary;
29 import org.apache.derby.iapi.sql.dictionary.TupleDescriptor;
30 import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
31 import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
32 import org.apache.derby.iapi.sql.dictionary.ColumnDescriptor;
33 import org.apache.derby.iapi.sql.dictionary.ColumnDescriptorList;
34 import org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor;
35 import org.apache.derby.iapi.sql.dictionary.ConstraintDescriptorList;
36 import org.apache.derby.iapi.sql.dictionary.CheckConstraintDescriptor;
37 import org.apache.derby.iapi.sql.execute.ConstantAction;
38
39 import org.apache.derby.iapi.error.StandardException;
40
41 import org.apache.derby.iapi.services.sanity.SanityManager;
42
43 import org.apache.derby.iapi.sql.StatementType;
44
45 /**
46  * A RenameNode is the root of a QueryTree that represents a
47  * RENAME TABLE/COLUMN/INDEX statement.
48  *
49  * @author Mamta Satoor
50  */

51
52 public class RenameNode extends DDLStatementNode
53 {
54     protected TableName newTableName;
55
56     // original name of the object being renamed
57
protected String JavaDoc oldObjectName;
58     // original name for that object
59
protected String JavaDoc newObjectName;
60
61     protected TableDescriptor td;
62     private long conglomerateNumber;
63
64     /* You can rename using either alter table or rename command to
65      * rename a table/column. An index can only be renamed with rename
66      * command. usedAlterTable flag is used to keep that information.
67      */

68     protected boolean usedAlterTable;
69
70     /* renamingWhat will be set to 1 if user is renaming a table.
71      * Will be set to 2 if user is renaming a column and will be
72      * set to 3 if user is renaming an index
73      */

74     protected int renamingWhat;
75
76     /**
77      * Initializer for a RenameNode
78      *
79      * @param tableName The name of the table. This is the table which is
80      * being renamed in case of rename table. In case of rename
81      * column, the column being renamed belongs to this table.
82      * In case of rename index, this is null because index name
83      * is unique within a schema and doesn't have to be
84      * associated with a table name
85      * @param oldObjectName This is either the name of column/index in case
86      * of rename column/index. For rename table, this is null.
87      * @param newObjectName This is new name for table/column/index
88      * @param usedAlterTable True-Used Alter Table, False-Used Rename.
89      * For rename index, this will always be false because
90      * there is no alter table command to rename index
91      * @param renamingWhat Rename a 1 - table, 2 - column, 3 - index
92      *
93      * @exception StandardException Thrown on error
94      */

95     public void init(Object JavaDoc tableName,
96                    Object JavaDoc oldObjectName,
97                    Object JavaDoc newObjectName,
98                    Object JavaDoc usedAlterTable,
99                    Object JavaDoc renamingWhat)
100         throws StandardException
101     {
102         this.usedAlterTable = ((Boolean JavaDoc) usedAlterTable).booleanValue();
103         this.renamingWhat = ((Integer JavaDoc) renamingWhat).intValue();
104
105         switch (this.renamingWhat)
106         {
107             case StatementType.RENAME_TABLE:
108                 initAndCheck((TableName) tableName);
109                 this.newTableName =
110                     makeTableName(getObjectName().getSchemaName(),(String JavaDoc)newObjectName);
111                 this.oldObjectName = null;
112                 this.newObjectName = this.newTableName.getTableName();
113                 break;
114
115             case StatementType.RENAME_COLUMN:
116                 /* coming from ALTER TABLE path, tableName will
117                  * be TableName object. Coming from RENAME COLUMN
118                  * path, tableName will be just a String.
119                  */

120                 TableName actingObjectName;
121                 if (tableName instanceof TableName)
122                     actingObjectName = (TableName) tableName;
123                 else
124                     actingObjectName = makeTableName(null,
125                     (String JavaDoc)tableName);
126                 initAndCheck(actingObjectName);
127
128
129                 this.oldObjectName = (String JavaDoc)oldObjectName;
130                 this.newObjectName = (String JavaDoc)newObjectName;
131                 break;
132
133             case StatementType.RENAME_INDEX:
134                 this.oldObjectName = (String JavaDoc)oldObjectName;
135                 this.newObjectName = (String JavaDoc)newObjectName;
136                 break;
137
138             default:
139                 if (SanityManager.DEBUG)
140                 SanityManager.THROWASSERT(
141                 "Unexpected rename action in RenameNode");
142         }
143     }
144
145     /**
146      * Convert this object to a String. See comments in QueryTreeNode.java
147      * for how this should be done for tree printing.
148      *
149      * @return This object as a String
150      */

151
152     public String JavaDoc toString()
153     {
154         if (SanityManager.DEBUG) {
155
156         switch (renamingWhat)
157         {
158             case StatementType.RENAME_TABLE:
159                 return super.toString() +
160                 "oldTableName: " + "\n" + getRelativeName() + "\n" +
161                 "newTableName: " + "\n" + newTableName + "\n" ;
162
163             case StatementType.RENAME_COLUMN:
164                 return super.toString() +
165                 "oldTableName.oldColumnName:" + "\n" +
166                 getRelativeName() + "." + oldObjectName + "\n" +
167                 "newColumnName: " + "\n" + newObjectName + "\n" ;
168
169             case StatementType.RENAME_INDEX:
170                 return super.toString() +
171                 "oldIndexName:" + "\n" + oldObjectName + "\n" +
172                 "newIndexName: " + "\n" + newObjectName + "\n" ;
173
174             default:
175                 SanityManager.THROWASSERT(
176                 "Unexpected rename action in RenameNode");
177                 return "UNKNOWN";
178         }
179         } else {
180             return "";
181         }
182     }
183
184     public String JavaDoc statementToString()
185     {
186         if (usedAlterTable)
187             return "ALTER TABLE";
188         else {
189             switch (renamingWhat)
190             {
191                 case StatementType.RENAME_TABLE:
192                     return "RENAME TABLE";
193
194                 case StatementType.RENAME_COLUMN:
195                     return "RENAME COLUMN";
196
197                 case StatementType.RENAME_INDEX:
198                     return "RENAME INDEX";
199
200                 default:
201                     if (SanityManager.DEBUG)
202                         SanityManager.THROWASSERT(
203                         "Unexpected rename action in RenameNode");
204                     return "UNKNOWN";
205             }
206     }
207     }
208
209     // We inherit the generate() method from DDLStatementNode.
210

211     /**
212      * Bind this node. This means doing any static error checking that
213      * can be done before actually renaming the table/column/index.
214      *
215      * For a table rename: looking up the from table, verifying it exists
216      * verifying it's not a system table, verifying it's not view
217      * and looking up to table, verifying it doesn't exist.
218      *
219      * For a column rename: looking up the table, verifying it exists,
220      * verifying it's not a system table, verifying it's not view, verifying
221      * the from column exists, verifying the to column doesn't exist.
222      *
223      * For a index rename: looking up the table, verifying it exists,
224      * verifying it's not a system table, verifying it's not view, verifying
225      * the from index exists, verifying the to index doesn't exist.
226      *
227      * @return The bound query tree
228      *
229      * @exception StandardException Thrown on error
230      */

231
232     public QueryTreeNode bind() throws StandardException
233     {
234         CompilerContext cc = getCompilerContext();
235         DataDictionary dd = getDataDictionary();
236         ConglomerateDescriptor cd;
237         SchemaDescriptor sd;
238
239         /* in case of rename index, the only thing we get from parser is
240          * current and new index names with no information about the
241          * table it belongs to. This is because index names are unique
242          * within a schema and hence then is no need to qualify an index
243          * name with a table name which we have to do for rename column.
244          * But from the index name, using the data dictionary, you can
245          * find the table it belongs to. Since most of the checking
246          * in bind is done using table descriptor, in the following if
247          * statement, we are trying to get the table information from the
248          * index name so it is available for the rest of he bind code.
249          */

250         TableName baseTable;
251
252         if (renamingWhat == StatementType.RENAME_INDEX) {
253
254             sd = getSchemaDescriptor((String JavaDoc)null);
255
256             ConglomerateDescriptor indexDescriptor =
257                 dd.getConglomerateDescriptor(oldObjectName, sd, false);
258             if (indexDescriptor == null)
259                 throw StandardException.newException(
260                                      SQLState.LANG_INDEX_NOT_FOUND, oldObjectName);
261             /* Get the table descriptor */
262             td = dd.getTableDescriptor(indexDescriptor.getTableID());
263             initAndCheck(makeTableName(td.getSchemaName(),
264                                        td.getName()));
265         } else
266             sd = getSchemaDescriptor();
267
268         td = getTableDescriptor();
269
270         //throw an exception if user is attempting a rename on temporary table
271
if (td.getTableType() == TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE)
272         {
273                 throw StandardException.newException(SQLState.LANG_NOT_ALLOWED_FOR_DECLARED_GLOBAL_TEMP_TABLE);
274         }
275
276         switch (this.renamingWhat)
277         {
278             case StatementType.RENAME_TABLE:
279                 /* Verify that new table name does not exist in the database */
280                 TableDescriptor td = getTableDescriptor(newObjectName, sd);
281                 if (td != null)
282                     throw descriptorExistsException(td, sd);
283                 renameTableBind(dd);
284                 break;
285
286             case StatementType.RENAME_COLUMN:
287                 renameColumnBind(dd);
288                 break;
289
290             case StatementType.RENAME_INDEX:
291                 ConglomerateDescriptor conglomDesc = dd.getConglomerateDescriptor(newObjectName, sd, false);
292                 if (conglomDesc != null)
293                     throw descriptorExistsException(conglomDesc, sd);
294                 break;
295
296             default:
297                 if (SanityManager.DEBUG)
298                     SanityManager.THROWASSERT(
299                             "Unexpected rename action in RenameNode");
300                 break;
301         }
302
303         conglomerateNumber = td.getHeapConglomerateId();
304
305         /* Get the base conglomerate descriptor */
306         cd = td.getConglomerateDescriptor(conglomerateNumber);
307
308         /* Statement is dependent on the TableDescriptor and ConglomerateDescriptor */
309         cc.createDependency(td);
310         cc.createDependency(cd);
311
312         return this;
313     }
314
315     /**
316      * Return true if the node references SESSION schema tables (temporary or permanent)
317      *
318      * @return true if references SESSION schema tables, else false
319      *
320      * @exception StandardException Thrown on error
321      */

322     public boolean referencesSessionSchema()
323         throws StandardException
324     {
325         //If rename is on a SESSION schema table, then return true.
326
if (isSessionSchema(td.getSchemaName()))//existing table with rename action
327
return true;
328
329         //new name in rename action
330
if (renamingWhat == StatementType.RENAME_TABLE && isSessionSchema(getSchemaDescriptor()))
331             return true;
332
333         return false;
334     }
335
336     //do any checking needs to be done at bind time for rename table
337
private void renameTableBind(DataDictionary dd)
338         throws StandardException
339     {
340         /* Verify that there are no check constraints on the table */
341         ConstraintDescriptorList constraintDescriptorList = dd.getConstraintDescriptors(td);
342         int size =
343             constraintDescriptorList == null ? 0 : constraintDescriptorList.size();
344
345         ConstraintDescriptor constraintDescriptor;
346
347         // go through all the constraints defined on the table
348
for (int index = 0; index < size; index++)
349         {
350             constraintDescriptor = constraintDescriptorList.elementAt(index);
351             // if it is a check constraint, error
352
if (constraintDescriptor.getConstraintType() == DataDictionary.CHECK_CONSTRAINT)
353             {
354                 throw StandardException.newException(
355                         SQLState.LANG_PROVIDER_HAS_DEPENDENT_OBJECT,
356                         "RENAME",
357                         td.getName(),
358                         "CONSTRAINT",
359                         constraintDescriptor.getConstraintName());
360             }
361         }
362     }
363                            
364     //do any checking needs to be done at bind time for rename column
365
private void renameColumnBind(DataDictionary dd)
366         throws StandardException
367     {
368         ColumnDescriptor columnDescriptor = td.getColumnDescriptor(oldObjectName);
369
370         /* Verify that old column name does exist in the table */
371         if (columnDescriptor == null)
372             throw StandardException.newException(SQLState.LANG_COLUMN_NOT_FOUND_IN_TABLE,
373             oldObjectName, getFullName());
374
375         /* Verify that new column name does not exist in the table */
376         ColumnDescriptor cd = td.getColumnDescriptor(newObjectName);
377         if (cd != null)
378             throw descriptorExistsException(cd, td);
379
380         /* Verify that there are no check constraints using the column being renamed */
381         ConstraintDescriptorList constraintDescriptorList =
382             dd.getConstraintDescriptors(td);
383         int size =
384             constraintDescriptorList == null ? 0 : constraintDescriptorList.size();
385
386         ConstraintDescriptor constraintDescriptor;
387         ColumnDescriptorList checkConstraintCDL;
388         int checkConstraintCDLSize;
389
390         // go through all the constraints defined on the table
391
for (int index = 0; index < size; index++)
392         {
393             constraintDescriptor = constraintDescriptorList.elementAt(index);
394             // if it is a check constraint, verify that column being
395
// renamed is not used in it's sql
396
if (constraintDescriptor.getConstraintType() == DataDictionary.CHECK_CONSTRAINT)
397             {
398                 checkConstraintCDL = constraintDescriptor.getColumnDescriptors();
399                 checkConstraintCDLSize = checkConstraintCDL.size();
400
401                 for (int index2 = 0; index2 < checkConstraintCDLSize; index2++)
402                     if (checkConstraintCDL.elementAt( index2 ) == columnDescriptor)
403                         throw StandardException.newException(
404                         SQLState.LANG_RENAME_COLUMN_WILL_BREAK_CHECK_CONSTRAINT,
405                         oldObjectName,
406                         constraintDescriptor.getConstraintName());
407             }
408         }
409     }
410                            
411     /**
412      * Create the Constant information that will drive the guts of Execution
413      *
414      * @exception StandardException Thrown on failure
415      */

416     public ConstantAction makeConstantAction()
417         throws StandardException
418     {
419         return getGenericConstantActionFactory().getRenameConstantAction(getFullName(),
420             getRelativeName(),
421             oldObjectName,
422             newObjectName,
423             getSchemaDescriptor(),
424             td.getUUID(),
425             usedAlterTable,
426             renamingWhat);
427     }
428
429     private StandardException descriptorExistsException(TupleDescriptor tuple,
430                                                         TupleDescriptor parent)
431     {
432         return
433             StandardException.newException(SQLState.LANG_OBJECT_ALREADY_EXISTS_IN_OBJECT,
434                                            tuple.getDescriptorType(),
435                                            tuple.getDescriptorName(),
436                                            parent.getDescriptorType(),
437                                            parent.getDescriptorName());
438     }
439 }
440
Popular Tags