KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.execute.CreateTriggerConstantAction
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.store.access.TransactionController;
25
26 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
27
28 import org.apache.derby.iapi.sql.execute.ConstantAction;
29
30 import org.apache.derby.iapi.sql.dictionary.DataDescriptorGenerator;
31 import org.apache.derby.iapi.sql.dictionary.DataDictionary;
32 import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
33 import org.apache.derby.iapi.sql.dictionary.SPSDescriptor;
34 import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
35 import org.apache.derby.iapi.sql.dictionary.TriggerDescriptor;
36
37 import org.apache.derby.iapi.types.DataValueFactory;
38
39 import org.apache.derby.iapi.sql.depend.DependencyManager;
40
41 import org.apache.derby.iapi.sql.execute.ExecutionFactory;
42
43 import org.apache.derby.iapi.sql.Activation;
44
45 import org.apache.derby.iapi.error.StandardException;
46 import org.apache.derby.iapi.reference.SQLState;
47
48 import org.apache.derby.iapi.services.context.ContextService;
49
50 import org.apache.derby.iapi.services.sanity.SanityManager;
51
52 import org.apache.derby.catalog.UUID;
53
54 import java.sql.Timestamp JavaDoc;
55
56 /**
57  * This class describes actions that are ALWAYS performed for a
58  * CREATE TRIGGER Statement at Execution time.
59  *
60  * @author Jamie
61  */

62 class CreateTriggerConstantAction extends DDLSingleTableConstantAction
63 {
64
65     private String JavaDoc triggerName;
66     private String JavaDoc triggerSchemaName;
67     private TableDescriptor triggerTable; // null after readExternal
68
private UUID triggerTableId; // set in readExternal
69
private int eventMask;
70     private boolean isBefore;
71     private boolean isRow;
72     private boolean isEnabled;
73     private boolean referencingOld;
74     private boolean referencingNew;
75     private UUID whenSPSId;
76     private String JavaDoc whenText;
77     private UUID actionSPSId;
78     private String JavaDoc actionText;
79     private String JavaDoc originalActionText;
80     private String JavaDoc oldReferencingName;
81     private String JavaDoc newReferencingName;
82     private UUID spsCompSchemaId;
83     private Timestamp JavaDoc creationTimestamp;
84     private int[] referencedCols;
85
86     // CONSTRUCTORS
87

88     /**
89      * Make the ConstantAction for a CREATE TRIGGER statement.
90      *
91      * @param triggerSchemaName name for the schema that trigger lives in.
92      * @param triggerName Name of trigger
93      * @param eventMask TriggerDescriptor.TRIGGER_EVENT_XXXX
94      * @param isBefore is this a before (as opposed to after) trigger
95      * @param isRow is this a row trigger or statement trigger
96      * @param isEnabled is this trigger enabled or disabled
97      * @param triggerTable the table upon which this trigger is defined
98      * @param whenSPSId the sps id for the when clause (may be null)
99      * @param whenText the text of the when clause (may be null)
100      * @param actionSPSId the spsid for the trigger action (may be null)
101      * @param actionText the text of the trigger action
102      * @param spsCompSchemaId the compilation schema for the action and when
103      * spses. If null, will be set to the current default
104      * schema
105      * @param creationTimestamp when was this trigger created? if null, will be
106      * set to the time that executeConstantAction() is invoked
107      * @param referencedCols what columns does this trigger reference (may be null)
108      * @param originalActionText The original user text of the trigger action
109      * @param referencingOld whether or not OLD appears in REFERENCING clause
110      * @param referencingNew whether or not NEW appears in REFERENCING clause
111      * @param oldReferencingName old referencing table name, if any, that appears in REFERENCING clause
112      * @param newReferencingName new referencing table name, if any, that appears in REFERENCING clause
113      */

114     CreateTriggerConstantAction
115     (
116         String JavaDoc triggerSchemaName,
117         String JavaDoc triggerName,
118         int eventMask,
119         boolean isBefore,
120         boolean isRow,
121         boolean isEnabled,
122         TableDescriptor triggerTable,
123         UUID whenSPSId,
124         String JavaDoc whenText,
125         UUID actionSPSId,
126         String JavaDoc actionText,
127         UUID spsCompSchemaId,
128         Timestamp JavaDoc creationTimestamp,
129         int[] referencedCols,
130         String JavaDoc originalActionText,
131         boolean referencingOld,
132         boolean referencingNew,
133         String JavaDoc oldReferencingName,
134         String JavaDoc newReferencingName
135     )
136     {
137         super(triggerTable.getUUID());
138         this.triggerName = triggerName;
139         this.triggerSchemaName = triggerSchemaName;
140         this.triggerTable = triggerTable;
141         this.eventMask = eventMask;
142         this.isBefore = isBefore;
143         this.isRow = isRow;
144         this.isEnabled = isEnabled;
145         this.whenSPSId = whenSPSId;
146         this.whenText = whenText;
147         this.actionSPSId = actionSPSId;
148         this.actionText = actionText;
149         this.spsCompSchemaId = spsCompSchemaId;
150         this.creationTimestamp = creationTimestamp;
151         this.referencedCols = referencedCols;
152         this.originalActionText = originalActionText;
153         this.referencingOld = referencingOld;
154         this.referencingNew = referencingNew;
155         this.oldReferencingName = oldReferencingName;
156         this.newReferencingName = newReferencingName;
157         if (SanityManager.DEBUG)
158         {
159             SanityManager.ASSERT(triggerSchemaName != null, "triggerSchemaName sd is null");
160             SanityManager.ASSERT(triggerName != null, "trigger name is null");
161             SanityManager.ASSERT(triggerTable != null, "triggerTable is null");
162             SanityManager.ASSERT(actionText != null, "actionText is null");
163         }
164     }
165
166     /**
167      * This is the guts of the Execution-time logic for CREATE TRIGGER.
168      *
169      * @see ConstantAction#executeConstantAction
170      *
171      * @exception StandardException Thrown on failure
172      */

173     public void executeConstantAction(Activation activation)
174                         throws StandardException
175     {
176         SPSDescriptor whenspsd = null;
177         SPSDescriptor actionspsd;
178
179         LanguageConnectionContext lcc = activation.getLanguageConnectionContext();
180         DataDictionary dd = lcc.getDataDictionary();
181         DependencyManager dm = dd.getDependencyManager();
182         TransactionController tc = lcc.getTransactionExecute();
183
184         /*
185         ** Indicate that we are about to modify the data dictionary.
186         **
187         ** We tell the data dictionary we're done writing at the end of
188         ** the transaction.
189         */

190         dd.startWriting(lcc);
191
192         SchemaDescriptor triggerSd = getSchemaDescriptorForCreate(dd, activation, triggerSchemaName);
193
194         if (spsCompSchemaId == null) {
195             SchemaDescriptor def = lcc.getDefaultSchema();
196             if (def.getUUID() == null) {
197                 // Descriptor for default schema is stale,
198
// look it up in the dictionary
199
def = dd.getSchemaDescriptor(def.getDescriptorName(), tc,
200                                              false);
201             }
202             spsCompSchemaId = def.getUUID();
203         }
204         if (SanityManager.DEBUG) {
205             SanityManager.ASSERT(spsCompSchemaId != null,
206                                  "spsCompSchemaId is null");
207         }
208
209         String JavaDoc tabName;
210         if (triggerTable != null)
211         {
212             triggerTableId = triggerTable.getUUID();
213             tabName = triggerTable.getName();
214         }
215         else
216             tabName = "with UUID " + triggerTableId;
217
218         /* We need to get table descriptor again. We simply can't trust the
219          * one we got at compile time, the lock on system table was released
220          * when compile was done, and the table might well have been dropped.
221          */

222         triggerTable = dd.getTableDescriptor(triggerTableId);
223         if (triggerTable == null)
224         {
225             throw StandardException.newException(
226                                 SQLState.LANG_TABLE_NOT_FOUND_DURING_EXECUTION,
227                                 tabName);
228         }
229         /* Lock the table for DDL. Otherwise during our execution, the table
230          * might be changed, even dropped. Beetle 4269
231          */

232         lockTableForDDL(tc, triggerTable.getHeapConglomerateId(), true);
233         /* get triggerTable again for correctness, in case it's changed before
234          * the lock is aquired
235          */

236         triggerTable = dd.getTableDescriptor(triggerTableId);
237         if (triggerTable == null)
238         {
239             throw StandardException.newException(
240                                 SQLState.LANG_TABLE_NOT_FOUND_DURING_EXECUTION,
241                                 tabName);
242         }
243
244         /*
245         ** Send an invalidate on the table from which
246         ** the triggering event emanates. This it
247         ** to make sure that DML statements on this table
248         ** will be recompiled. Do this before we create
249         ** our trigger spses lest we invalidate them just
250         ** after creating them.
251         */

252         dm.invalidateFor(triggerTable, DependencyManager.CREATE_TRIGGER, lcc);
253
254         /*
255         ** Lets get our trigger id up front, we'll use it when
256         ** we create our spses.
257         */

258         UUID tmpTriggerId = dd.getUUIDFactory().createUUID();
259
260         actionSPSId = (actionSPSId == null) ?
261             dd.getUUIDFactory().createUUID() : actionSPSId;
262  
263         DataDescriptorGenerator ddg = dd.getDataDescriptorGenerator();
264
265         /*
266         ** Create the trigger descriptor first so the trigger action
267         ** compilation can pick up the relevant trigger especially in
268         ** the case of self triggering.
269         */

270         TriggerDescriptor triggerd =
271                 ddg.newTriggerDescriptor(
272                                     triggerSd,
273                                     tmpTriggerId,
274                                     triggerName,
275                                     eventMask,
276                                     isBefore,
277                                     isRow,
278                                     isEnabled,
279                                     triggerTable,
280                                     whenspsd == null ? null : whenspsd.getUUID(),
281                                     actionSPSId,
282                                     creationTimestamp == null ? new Timestamp JavaDoc(System.currentTimeMillis()) : creationTimestamp,
283                                     referencedCols,
284                                     originalActionText,
285                                     referencingOld,
286                                     referencingNew,
287                                     oldReferencingName,
288                                     newReferencingName);
289
290
291         dd.addDescriptor(triggerd, triggerSd,
292                                 DataDictionary.SYSTRIGGERS_CATALOG_NUM, false,
293                                 tc);
294
295
296         /*
297         ** If we have a WHEN action we create it now.
298         */

299         if (whenText != null)
300         {
301             whenspsd = createSPS(lcc, ddg, dd, tc, tmpTriggerId, triggerSd,
302                         whenSPSId, spsCompSchemaId, whenText, true, triggerTable);
303         }
304
305         /*
306         ** Create the trigger action
307         */

308         actionspsd = createSPS(lcc, ddg, dd, tc, tmpTriggerId, triggerSd,
309                         actionSPSId, spsCompSchemaId, actionText, false, triggerTable);
310         
311         /*
312         ** Make underlying spses dependent on the trigger.
313         */

314         if (whenspsd != null)
315         {
316             dm.addDependency(triggerd, whenspsd, lcc.getContextManager());
317         }
318         dm.addDependency(triggerd, actionspsd, lcc.getContextManager());
319         dm.addDependency(triggerd, triggerTable, lcc.getContextManager());
320         dm.addDependency(actionspsd, triggerTable, lcc.getContextManager());
321         //store trigger's dependency on various privileges in the dependeny system
322
storeViewTriggerDependenciesOnPrivileges(activation, triggerd);
323     }
324
325
326     /*
327     ** Create an sps that is used by the trigger.
328     */

329     private SPSDescriptor createSPS
330     (
331         LanguageConnectionContext lcc,
332         DataDescriptorGenerator ddg,
333         DataDictionary dd,
334         TransactionController tc,
335         UUID triggerId,
336         SchemaDescriptor sd,
337         UUID spsId,
338         UUID compSchemaId,
339         String JavaDoc text,
340         boolean isWhen,
341         TableDescriptor triggerTable
342     ) throws StandardException
343     {
344         if (text == null)
345         {
346             return null;
347         }
348
349         /*
350         ** Note: the format of this string is very important.
351         ** Dont change it arbitrarily -- see sps code.
352         */

353         String JavaDoc spsName = "TRIGGER" +
354                         (isWhen ? "WHEN_" : "ACTN_") +
355                         triggerId + "_" + triggerTable.getUUID().toString();
356
357         SPSDescriptor spsd = new SPSDescriptor(dd, spsName,
358                                     (spsId == null) ?
359                                         dd.getUUIDFactory().createUUID() :
360                                         spsId,
361                                     sd.getUUID(),
362                                     compSchemaId == null ?
363                                         lcc.getDefaultSchema().getUUID() :
364                                         compSchemaId,
365                                     SPSDescriptor.SPS_TYPE_TRIGGER,
366                                     true, // it is valid
367
text, // the text
368
true ); // no defaults
369

370         /*
371         ** Prepared the stored prepared statement
372         ** and release the activation class -- we
373         ** know we aren't going to execute statement
374         ** after create it, so for now we are finished.
375         */

376         spsd.prepareAndRelease(lcc, triggerTable);
377
378
379         dd.addSPSDescriptor(spsd, tc, true);
380
381         return spsd;
382     }
383
384     public String JavaDoc toString()
385     {
386         return constructToString("CREATE TRIGGER ", triggerName);
387     }
388 }
389
390
391
Popular Tags