KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.compile.CreateIndexNode
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.context.ContextManager;
25
26 import org.apache.derby.iapi.sql.ResultSet;
27
28 import org.apache.derby.iapi.sql.compile.CompilerContext;
29
30 import org.apache.derby.iapi.sql.dictionary.ColumnDescriptor;
31 import org.apache.derby.iapi.sql.dictionary.DataDictionaryContext;
32 import org.apache.derby.iapi.sql.dictionary.DataDictionary;
33 import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
34 import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
35 import org.apache.derby.iapi.sql.dictionary.DataDescriptorGenerator;
36 import org.apache.derby.iapi.sql.dictionary.ColumnDescriptor;
37
38 import org.apache.derby.iapi.reference.SQLState;
39 import org.apache.derby.iapi.reference.Limits;
40 import org.apache.derby.iapi.reference.Property;
41
42 import org.apache.derby.iapi.sql.execute.ConstantAction;
43
44 import org.apache.derby.iapi.error.StandardException;
45
46 import org.apache.derby.iapi.services.monitor.Monitor;
47 import org.apache.derby.iapi.services.property.PropertyUtil;
48 import org.apache.derby.iapi.services.sanity.SanityManager;
49
50 import org.apache.derby.impl.sql.compile.ActivationClassBuilder;
51 import org.apache.derby.impl.sql.execute.BaseActivation;
52 import org.apache.derby.impl.sql.execute.ColumnInfo;
53 import org.apache.derby.iapi.types.DataTypeDescriptor;
54 import org.apache.derby.catalog.UUID;
55
56 import java.util.Hashtable JavaDoc;
57 import java.util.Properties JavaDoc;
58 import java.util.Vector JavaDoc;
59
60 /**
61  * A CreateIndexNode is the root of a QueryTree that represents a CREATE INDEX
62  * statement.
63  *
64  * @author Jeff Lichtman
65  */

66
67 public class CreateIndexNode extends DDLStatementNode
68 {
69     boolean unique;
70     DataDictionary dd = null;
71     Properties JavaDoc properties;
72     String JavaDoc indexType;
73     TableName indexName;
74     TableName tableName;
75     Vector JavaDoc columnNameList;
76     String JavaDoc[] columnNames = null;
77     boolean[] isAscending;
78     int[] boundColumnIDs;
79
80     TableDescriptor td;
81
82     /**
83      * Initializer for a CreateIndexNode
84      *
85      * @param unique True means it's a unique index
86      * @param indexType The type of index
87      * @param indexName The name of the index
88      * @param tableName The name of the table the index will be on
89      * @param columnNameList A list of column names, in the order they
90      * appear in the index.
91      * @param properties The optional properties list associated with the index.
92      *
93      * @exception StandardException Thrown on error
94      */

95     public void init(
96                     Object JavaDoc unique,
97                     Object JavaDoc indexType,
98                     Object JavaDoc indexName,
99                     Object JavaDoc tableName,
100                     Object JavaDoc columnNameList,
101                     Object JavaDoc properties)
102         throws StandardException
103     {
104         initAndCheck(indexName);
105         this.unique = ((Boolean JavaDoc) unique).booleanValue();
106         this.indexType = (String JavaDoc) indexType;
107         this.indexName = (TableName) indexName;
108         this.tableName = (TableName) tableName;
109         this.columnNameList = (Vector JavaDoc) columnNameList;
110         this.properties = (Properties JavaDoc) properties;
111     }
112
113     /**
114      * Convert this object to a String. See comments in QueryTreeNode.java
115      * for how this should be done for tree printing.
116      *
117      * @return This object as a String
118      */

119
120     public String JavaDoc toString()
121     {
122         if (SanityManager.DEBUG)
123         {
124             return super.toString() +
125                 "unique: " + unique + "\n" +
126                 "indexType: " + indexType + "\n" +
127                 "indexName: " + indexName + "\n" +
128                 "tableName: " + tableName + "\n" +
129                 "properties: " + properties + "\n";
130         }
131         else
132         {
133             return "";
134         }
135     }
136
137     public String JavaDoc statementToString()
138     {
139         return "CREATE INDEX";
140     }
141
142
143     public boolean getUniqueness() { return unique; }
144     public String JavaDoc getIndexType() { return indexType; }
145     public TableName getIndexName() { return indexName; }
146     public UUID getBoundTableID() { return td.getUUID(); }
147     public Properties JavaDoc getProperties() { return properties; }
148     public TableName getIndexTableName() {return tableName; }
149     public String JavaDoc[] getColumnNames() { return columnNames; }
150
151     // get 1-based column ids
152
public int[] getKeyColumnIDs() { return boundColumnIDs; }
153     public boolean[] getIsAscending() { return isAscending; }
154
155     // We inherit the generate() method from DDLStatementNode.
156

157     /**
158      * Bind this CreateIndexNode. This means doing any static error
159      * checking that can be done before actually creating the table.
160      * For example, verifying that the column name list does not
161      * contain any duplicate column names.
162      *
163      * @return The bound query tree
164      *
165      * @exception StandardException Thrown on error
166      */

167
168     public QueryTreeNode bind() throws StandardException
169     {
170         CompilerContext cc = getCompilerContext();
171         DataDictionary dd = getDataDictionary();
172         SchemaDescriptor sd;
173         int columnCount;
174
175         sd = getSchemaDescriptor();
176
177         td = getTableDescriptor(tableName);
178
179         //throw an exception if user is attempting to create an index on a temporary table
180
if (td.getTableType() == TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE)
181         {
182                 throw StandardException.newException(SQLState.LANG_NOT_ALLOWED_FOR_DECLARED_GLOBAL_TEMP_TABLE);
183         }
184
185         //If total number of indexes on the table so far is more than 32767, then we need to throw an exception
186
if (td.getTotalNumberOfIndexes() > Limits.DB2_MAX_INDEXES_ON_TABLE)
187         {
188             throw StandardException.newException(SQLState.LANG_TOO_MANY_INDEXES_ON_TABLE,
189                 String.valueOf(td.getTotalNumberOfIndexes()),
190                 tableName,
191                 String.valueOf(Limits.DB2_MAX_INDEXES_ON_TABLE));
192         }
193
194         /* Validate the column name list */
195         verifyAndGetUniqueNames();
196
197         columnCount = columnNames.length;
198         boundColumnIDs = new int[ columnCount ];
199
200         // Verify that the columns exist
201
for (int i = 0; i < columnCount; i++)
202         {
203             ColumnDescriptor columnDescriptor;
204
205             columnDescriptor = td.getColumnDescriptor(columnNames[i]);
206             if (columnDescriptor == null)
207             {
208                 throw StandardException.newException(SQLState.LANG_COLUMN_NOT_FOUND_IN_TABLE,
209                                                             columnNames[i],
210                                                             tableName);
211             }
212             boundColumnIDs[ i ] = columnDescriptor.getPosition();
213
214             // Don't allow a column to be created on a non-orderable type
215
if ( ! columnDescriptor.getType().getTypeId().
216                                                 orderable(getClassFactory()))
217             {
218                 throw StandardException.newException(SQLState.LANG_COLUMN_NOT_ORDERABLE_DURING_EXECUTION,
219                     columnDescriptor.getType().getTypeId().getSQLTypeName());
220             }
221         }
222
223         /* Check for number of key columns to be less than 16 to match DB2 */
224         if (columnCount > 16)
225             throw StandardException.newException(SQLState.LANG_TOO_MANY_INDEX_KEY_COLS);
226
227         /* See if the index already exists in this schema.
228          * NOTE: We still need to check at execution time
229          * since the index name is only unique to the schema,
230          * not the table.
231          */

232 // if (dd.getConglomerateDescriptor(indexName.getTableName(), sd, false) != null)
233
// {
234
// throw StandardException.newException(SQLState.LANG_OBJECT_ALREADY_EXISTS_IN_OBJECT,
235
// "Index",
236
// indexName.getTableName(),
237
// "schema",
238
// sd.getSchemaName());
239
// }
240

241         /* Statement is dependent on the TableDescriptor */
242         getCompilerContext().createDependency(td);
243
244         return this;
245     }
246
247     /**
248      * Return true if the node references SESSION schema tables (temporary or permanent)
249      *
250      * @return true if references SESSION schema tables, else false
251      *
252      * @exception StandardException Thrown on error
253      */

254     public boolean referencesSessionSchema()
255         throws StandardException
256     {
257         //If create index is on a SESSION schema table, then return true.
258
return isSessionSchema(td.getSchemaName());
259     }
260
261     /**
262      * Create the Constant information that will drive the guts of Execution.
263      *
264      * @exception StandardException Thrown on failure
265      */

266     public ConstantAction makeConstantAction() throws StandardException
267     {
268         long conglomId = 0;
269         SchemaDescriptor sd = getSchemaDescriptor();
270
271         int columnCount = columnNames.length;
272         int approxLength = 0;
273         boolean index_has_long_column = false;
274
275
276         // bump the page size for the index,
277
// if the approximate sizes of the columns in the key are
278
// greater than the bump threshold.
279
// Ideally, we would want to have atleast 2 or 3 keys fit in one page
280
// With fix for beetle 5728, indexes on long types is not allowed
281
// so we do not have to consider key columns of long types
282
for (int i = 0; i < columnCount; i++)
283         {
284             ColumnDescriptor columnDescriptor = td.getColumnDescriptor(columnNames[i]);
285             DataTypeDescriptor dts = columnDescriptor.getType();
286             approxLength += dts.getTypeId().getApproximateLengthInBytes(dts);
287         }
288
289
290         if (approxLength > Property.IDX_PAGE_SIZE_BUMP_THRESHOLD)
291         {
292
293             if (((properties == null) ||
294                  (properties.get(Property.PAGE_SIZE_PARAMETER) == null)) &&
295                 (PropertyUtil.getServiceProperty(
296                      getLanguageConnectionContext().getTransactionCompile(),
297                      Property.PAGE_SIZE_PARAMETER) == null))
298             {
299                 // do not override the user's choice of page size, whether it
300
// is set for the whole database or just set on this statement.
301

302                 if (properties == null)
303                     properties = new Properties JavaDoc();
304
305                 properties.put(
306                     Property.PAGE_SIZE_PARAMETER,
307                     Property.PAGE_SIZE_DEFAULT_LONG);
308
309             }
310         }
311
312
313         return getGenericConstantActionFactory().getCreateIndexConstantAction(unique,
314                                               indexType,
315                                               sd.getSchemaName(),
316                                               indexName.getTableName(),
317                                               tableName.getTableName(),
318                                               td.getUUID(),
319                                               conglomId,
320                                               columnNames,
321                                               isAscending,
322                                               false,
323                                               null,
324                                               properties);
325     }
326
327     /**
328      * Check the uniqueness of the column names within the derived column list.
329      *
330      * @exception StandardException Thrown if column list contains a
331      * duplicate name.
332      */

333     private void verifyAndGetUniqueNames()
334                 throws StandardException
335     {
336         int size = columnNameList.size();
337         Hashtable JavaDoc ht = new Hashtable JavaDoc(size + 2, (float) .999);
338         columnNames = new String JavaDoc[size];
339         isAscending = new boolean[size];
340
341         for (int index = 0; index < size; index++)
342         {
343             /* Verify that this column's name is unique within the list
344              * Having a space at the end meaning descending on the column
345              */

346             columnNames[index] = (String JavaDoc) columnNameList.elementAt(index);
347             if (columnNames[index].endsWith(" "))
348             {
349                 columnNames[index] = columnNames[index].substring(0, columnNames[index].length() - 1);
350                 isAscending[index] = false;
351             }
352             else
353                 isAscending[index] = true;
354
355             Object JavaDoc object = ht.put(columnNames[index], columnNames[index]);
356
357             if (object != null &&
358                 ((String JavaDoc) object).equals(columnNames[index]))
359             {
360                 throw StandardException.newException(SQLState.LANG_DUPLICATE_COLUMN_NAME_CREATE_INDEX, columnNames[index]);
361             }
362         }
363     }
364 }
365
Popular Tags