KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > impl > sql > execute > CreateAliasConstantAction


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.execute.CreateAliasConstantAction
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.execute;
23
24 import org.apache.derby.iapi.services.loader.ClassFactory;
25
26 import org.apache.derby.iapi.store.access.TransactionController;
27
28 import org.apache.derby.iapi.sql.execute.ConstantAction;
29
30 import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
31 import org.apache.derby.iapi.sql.dictionary.AliasDescriptor;
32 import org.apache.derby.iapi.sql.dictionary.DataDescriptorGenerator;
33 import org.apache.derby.iapi.sql.dictionary.DataDictionary;
34 import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor;
35 import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
36 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
37
38 import org.apache.derby.iapi.types.DataValueFactory;
39
40 import org.apache.derby.iapi.reference.SQLState;
41
42 import org.apache.derby.iapi.sql.Activation;
43
44 import org.apache.derby.iapi.error.StandardException;
45
46 import org.apache.derby.iapi.services.context.ContextService;
47
48 import org.apache.derby.catalog.UUID;
49
50 import org.apache.derby.iapi.services.sanity.SanityManager;
51
52 import org.apache.derby.catalog.AliasInfo;
53 import org.apache.derby.catalog.types.RoutineAliasInfo;
54 import org.apache.derby.catalog.types.SynonymAliasInfo;
55
56 import java.lang.reflect.Method JavaDoc;
57 import java.lang.reflect.Modifier JavaDoc;
58
59 /**
60  * This class describes actions that are ALWAYS performed for a
61  * CREATE ALIAS Statement at Execution time.
62  *
63  * @author Jerry Brenner.
64  */

65 class CreateAliasConstantAction extends DDLConstantAction
66 {
67
68     private final String JavaDoc aliasName;
69     private final String JavaDoc schemaName;
70     private final String JavaDoc javaClassName;
71     private final char aliasType;
72     private final char nameSpace;
73     private final AliasInfo aliasInfo;
74
75     // CONSTRUCTORS
76

77     /**
78      * Make the ConstantAction for a CREATE ALIAS statement.
79      *
80      * @param aliasName Name of alias.
81      * @param schemaName Name of alias's schema.
82      * @param javaClassName Name of java class.
83      * @param aliasInfo AliasInfo
84      * @param aliasType The type of the alias
85      */

86     CreateAliasConstantAction(
87                                 String JavaDoc aliasName,
88                                 String JavaDoc schemaName,
89                                 String JavaDoc javaClassName,
90                                 AliasInfo aliasInfo,
91                                 char aliasType)
92     {
93         this.aliasName = aliasName;
94         this.schemaName = schemaName;
95         this.javaClassName = javaClassName;
96         this.aliasInfo = aliasInfo;
97         this.aliasType = aliasType;
98         switch (aliasType)
99         {
100             case AliasInfo.ALIAS_TYPE_PROCEDURE_AS_CHAR:
101                 nameSpace = AliasInfo.ALIAS_NAME_SPACE_PROCEDURE_AS_CHAR;
102                 break;
103
104             case AliasInfo.ALIAS_TYPE_FUNCTION_AS_CHAR:
105                 nameSpace = AliasInfo.ALIAS_NAME_SPACE_FUNCTION_AS_CHAR;
106                 break;
107
108             case AliasInfo.ALIAS_TYPE_SYNONYM_AS_CHAR:
109                 nameSpace = AliasInfo.ALIAS_NAME_SPACE_SYNONYM_AS_CHAR;
110                 break;
111
112             default:
113                 if (SanityManager.DEBUG)
114                 {
115                     SanityManager.THROWASSERT(
116                         "Unexpected value for aliasType (" + aliasType + ")");
117                 }
118                 nameSpace = '\0';
119                 break;
120         }
121     }
122
123     // OBJECT SHADOWS
124

125     public String JavaDoc toString()
126     {
127         // Do not put this under SanityManager.DEBUG - it is needed for
128
// error reporting.
129
String JavaDoc type = null;
130
131         switch (aliasType)
132         {
133             case AliasInfo.ALIAS_TYPE_PROCEDURE_AS_CHAR:
134                 type = "CREATE PROCEDURE ";
135                 break;
136
137             case AliasInfo.ALIAS_TYPE_FUNCTION_AS_CHAR:
138                 type = "CREATE FUNCTION ";
139                 break;
140
141             case AliasInfo.ALIAS_TYPE_SYNONYM_AS_CHAR:
142                 type = "CREATE SYNONYM ";
143                 break;
144
145             default:
146                 if (SanityManager.DEBUG)
147                 {
148                     SanityManager.THROWASSERT(
149                         "Unexpected value for aliasType (" + aliasType + ")");
150                 }
151         }
152
153         return type + aliasName;
154     }
155
156     // INTERFACE METHODS
157

158
159     /**
160      * This is the guts of the Execution-time logic for CREATE ALIAS.
161      *
162      * @see ConstantAction#executeConstantAction
163      *
164      * @exception StandardException Thrown on failure
165      */

166     public void executeConstantAction( Activation activation )
167                         throws StandardException
168     {
169         LanguageConnectionContext lcc;
170         if (activation != null)
171         {
172             lcc = activation.getLanguageConnectionContext();
173         }
174         else // only for direct executions by the database meta data
175
{
176             lcc = (LanguageConnectionContext) ContextService.getContext
177                         (LanguageConnectionContext.CONTEXT_ID);
178         }
179         DataDictionary dd = lcc.getDataDictionary();
180         TransactionController tc = lcc.getTransactionExecute();
181
182         /* Verify the method alias:
183         ** Aggregates - just verify the class
184         ** Method alias - verify the class and method
185         ** Work units - verify the class and method
186         ** (depends on whether we're at a source or target)
187         */

188         String JavaDoc checkMethodName = null;
189
190         String JavaDoc checkClassName = javaClassName;
191
192         if (aliasInfo != null)
193             checkMethodName = aliasInfo.getMethodName();
194
195         // Procedures do not check class or method validity until runtime execution of the procedure.
196
// This matches DB2 behaviour
197
switch (aliasType)
198         {
199         case AliasInfo.ALIAS_TYPE_PROCEDURE_AS_CHAR:
200         case AliasInfo.ALIAS_TYPE_FUNCTION_AS_CHAR:
201         case AliasInfo.ALIAS_TYPE_SYNONYM_AS_CHAR:
202             break;
203
204         default:
205         {
206
207             ClassFactory cf = lcc.getLanguageConnectionFactory().getClassFactory();
208
209             Class JavaDoc realClass = null;
210             try
211             {
212                 // Does the class exist?
213
realClass = cf.loadApplicationClass(checkClassName);
214             }
215             catch (ClassNotFoundException JavaDoc t)
216             {
217                 throw StandardException.newException(SQLState.LANG_TYPE_DOESNT_EXIST2, t, checkClassName);
218             }
219
220             if (! Modifier.isPublic(realClass.getModifiers()))
221             {
222                 throw StandardException.newException(SQLState.LANG_TYPE_DOESNT_EXIST2, checkClassName);
223             }
224
225             if (checkMethodName != null)
226             {
227                 // Is the method public and static
228
Method JavaDoc[] methods = realClass.getMethods();
229                 
230                 int index = 0;
231                 for ( ; index < methods.length; index++)
232                 {
233                     if (!Modifier.isStatic(methods[index].getModifiers()))
234                     {
235                         continue;
236                     }
237
238                     if (checkMethodName.equals(methods[index].getName()))
239                     {
240                         break;
241                     }
242                 }
243
244                 if (index == methods.length)
245                 {
246                     throw StandardException.newException(SQLState.LANG_NO_METHOD_MATCHING_ALIAS,
247                                     checkMethodName, checkClassName);
248                 }
249             }
250         }
251         }
252             
253
254         /*
255         ** Inform the data dictionary that we are about to write to it.
256         ** There are several calls to data dictionary "get" methods here
257         ** that might be done in "read" mode in the data dictionary, but
258         ** it seemed safer to do this whole operation in "write" mode.
259         **
260         ** We tell the data dictionary we're done writing at the end of
261         ** the transaction.
262         */

263         dd.startWriting(lcc);
264
265         
266         SchemaDescriptor sd = null;
267         if (activation == null)
268             sd = dd.getSysIBMSchemaDescriptor();
269         else if (schemaName != null)
270             sd = DDLConstantAction.getSchemaDescriptorForCreate(dd, activation, schemaName);
271
272         //
273
// Create a new method alias descriptor with aliasID filled in.
274
//
275
UUID aliasID = dd.getUUIDFactory().createUUID();
276
277         AliasDescriptor ads = new AliasDescriptor(dd, aliasID,
278                                      aliasName,
279                                      sd != null ? sd.getUUID() : null,
280                                      javaClassName,
281                                      aliasType,
282                                      nameSpace,
283                                      false,
284                                      aliasInfo, null);
285
286         // perform duplicate rule checking
287
switch (aliasType) {
288         case AliasInfo.ALIAS_TYPE_PROCEDURE_AS_CHAR:
289         case AliasInfo.ALIAS_TYPE_FUNCTION_AS_CHAR:
290         {
291
292             java.util.List JavaDoc list = dd.getRoutineList(
293                 sd.getUUID().toString(), aliasName, aliasType);
294             for (int i = list.size() - 1; i >= 0; i--) {
295
296                 AliasDescriptor proc = (AliasDescriptor) list.get(i);
297
298                 RoutineAliasInfo procedureInfo = (RoutineAliasInfo) proc.getAliasInfo();
299                 int parameterCount = procedureInfo.getParameterCount();
300                 if (parameterCount != ((RoutineAliasInfo) aliasInfo).getParameterCount())
301                     continue;
302
303                 // procedure duplicate checking is simple, only
304
// one procedure with a given number of parameters.
305
throw StandardException.newException(SQLState.LANG_OBJECT_ALREADY_EXISTS,
306                                                 ads.getDescriptorType(),
307                                                 aliasName);
308             }
309         }
310         break;
311         case AliasInfo.ALIAS_TYPE_SYNONYM_AS_CHAR:
312             // If target table/view exists already, error.
313
TableDescriptor targetTD = dd.getTableDescriptor(aliasName, sd);
314             if (targetTD != null)
315             {
316                 throw StandardException.newException(
317                                 SQLState.LANG_OBJECT_ALREADY_EXISTS,
318                                 targetTD.getDescriptorType(),
319                                 targetTD.getDescriptorName());
320             }
321
322             // Detect synonym cycles, if present.
323
String JavaDoc nextSynTable = ((SynonymAliasInfo)aliasInfo).getSynonymTable();
324             String JavaDoc nextSynSchema = ((SynonymAliasInfo)aliasInfo).getSynonymSchema();
325             SchemaDescriptor nextSD;
326             for (;;)
327             {
328                 nextSD = dd.getSchemaDescriptor(nextSynSchema, tc, false);
329                 if (nextSD == null)
330                     break;
331                 
332                 AliasDescriptor nextAD = dd.getAliasDescriptor(nextSD.getUUID().toString(),
333                          nextSynTable, nameSpace);
334                 if (nextAD == null)
335                     break;
336
337                 SynonymAliasInfo info = (SynonymAliasInfo) nextAD.getAliasInfo();
338                 nextSynTable = info.getSynonymTable();
339                 nextSynSchema = info.getSynonymSchema();
340
341                 if (aliasName.equals(nextSynTable) && schemaName.equals(nextSynSchema))
342                     throw StandardException.newException(SQLState.LANG_SYNONYM_CIRCULAR,
343                             aliasName, ((SynonymAliasInfo)aliasInfo).getSynonymTable());
344             }
345
346             // If synonym final target is not present, raise a warning
347
if (nextSD != null)
348                 targetTD = dd.getTableDescriptor(nextSynTable, nextSD);
349             if (nextSD == null || targetTD == null)
350                 activation.addWarning(
351                     StandardException.newWarning(SQLState.LANG_SYNONYM_UNDEFINED,
352                                 aliasName, nextSynSchema+"."+nextSynTable));
353
354             // To prevent any possible deadlocks with SYSTABLES, we insert a row into
355
// SYSTABLES also for synonyms. This also ensures tables/views/synonyms share
356
// same namespace
357
TableDescriptor td;
358             DataDescriptorGenerator ddg = dd.getDataDescriptorGenerator();
359             td = ddg.newTableDescriptor(aliasName, sd, TableDescriptor.SYNONYM_TYPE,
360                         TableDescriptor.DEFAULT_LOCK_GRANULARITY);
361             dd.addDescriptor(td, sd, DataDictionary.SYSTABLES_CATALOG_NUM, false, tc);
362         
363         default:
364             break;
365         }
366
367         dd.addDescriptor(ads, null, DataDictionary.SYSALIASES_CATALOG_NUM,
368                          false, lcc.getTransactionExecute());
369     }
370 }
371
Popular Tags