KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.execute.GenericTriggerExecutor
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.error.StandardException;
25 import org.apache.derby.iapi.sql.dictionary.SPSDescriptor;
26 import org.apache.derby.iapi.sql.dictionary.TriggerDescriptor;
27 import org.apache.derby.iapi.sql.execute.CursorResultSet;
28 import org.apache.derby.iapi.sql.execute.ExecPreparedStatement;
29 import org.apache.derby.iapi.sql.Activation;
30 import org.apache.derby.iapi.sql.ResultSet;
31 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
32 import org.apache.derby.iapi.sql.conn.StatementContext;
33
34 import org.apache.derby.iapi.reference.SQLState;
35
36 /**
37  * A trigger executor is an object that executes
38  * a trigger. It is subclassed by row and statement
39  * executors.
40  */

41 public abstract class GenericTriggerExecutor
42 {
43     protected InternalTriggerExecutionContext tec;
44     protected TriggerDescriptor triggerd;
45     protected Activation activation;
46     protected LanguageConnectionContext lcc;
47
48     private boolean whenClauseRetrieved;
49     private boolean actionRetrieved;
50     private SPSDescriptor whenClause;
51     private SPSDescriptor action;
52
53     private ExecPreparedStatement ps;
54     private Activation spsActivation;
55
56     /**
57      * Constructor
58      *
59      * @param tec the execution context
60      * @param triggerd the trigger descriptor
61      * @param activation the activation
62      * @param lcc the lcc
63      */

64     GenericTriggerExecutor
65     (
66         InternalTriggerExecutionContext tec,
67         TriggerDescriptor triggerd,
68         Activation activation,
69         LanguageConnectionContext lcc
70     )
71     {
72         this.tec = tec;
73         this.triggerd = triggerd;
74         this.activation = activation;
75         this.lcc = lcc;
76     }
77
78     /**
79      * Fire the trigger based on the event.
80      *
81      * @param event the trigger event
82      * @param brs the before result set
83      * @param ars the after result set
84      *
85      * @exception StandardException on error or user exception
86      * from trigger action
87      */

88     abstract void fireTrigger
89     (
90         TriggerEvent event,
91         CursorResultSet brs,
92         CursorResultSet ars
93     ) throws StandardException;
94
95     protected SPSDescriptor getWhenClause() throws StandardException
96     {
97         if (!whenClauseRetrieved)
98         {
99             whenClauseRetrieved = true;
100             whenClause = triggerd.getWhenClauseSPS();
101         }
102         return whenClause;
103     }
104
105     protected SPSDescriptor getAction() throws StandardException
106     {
107         if (!actionRetrieved)
108         {
109             actionRetrieved = true;
110             action = triggerd.getActionSPS(lcc);
111         }
112         return action;
113     }
114
115     /**
116      * Execute the given stored prepared statement. We
117      * just grab the prepared statement from the spsd,
118      * get a new activation holder and let er rip.
119      *
120      * @exception StandardException on error
121      */

122     protected void executeSPS(SPSDescriptor sps) throws StandardException
123     {
124         boolean recompile = false;
125
126         while (true) {
127             /*
128             ** Only grab the ps the 1st time through. This
129             ** way a row trigger doesn't do any unnecessary
130             ** setup work.
131             */

132             if (ps == null || recompile)
133             {
134                 /*
135                 ** We need to clone the prepared statement so we don't
136                 ** wind up marking that ps that is tied to sps as finished
137                 ** during the course of execution.
138                 */

139                 ps = sps.getPreparedStatement();
140                 ps = ps.getClone();
141                 // it should be valid since we've just prepared for it
142
ps.setValid();
143                 spsActivation = ps.getActivation(lcc, false);
144
145                 /*
146                 ** Normally, we want getSource() for an sps invocation
147                 ** to be EXEC STATEMENT xxx, but in this case, since
148                 ** we are executing the SPS in our own fashion, we want
149                 ** the text to be the trigger action. So set it accordingly.
150                 */

151                 ps.setSource(sps.getText());
152                 ps.setSPSAction();
153             }
154
155             /*
156             ** Execute the activation. If we have an error, we
157             ** are going to go to some extra work to pop off
158             ** our statement context. This is because we are
159             ** a nested statement (we have 2 activations), but
160             ** we aren't a nested connection, so we have to
161             ** pop off our statementcontext to get error handling
162             ** to work correctly. This is normally a no-no, but
163             ** we are an unusual case.
164             */

165             try
166             {
167                 // This is a substatement; for now, we do not set any timeout
168
// for it. We might change this behaviour later, by linking
169
// timeout to its parent statement's timeout settings.
170
ResultSet rs = ps.execute(spsActivation, false, 0L);
171                 if( rs.returnsRows())
172                 {
173                     // Fetch all the data to ensure that functions in the select list or values statement will
174
// be evaluated and side effects will happen. Why else would the trigger action return
175
// rows, but for side effects?
176
// The result set was opened in ps.execute()
177
while( rs.getNextRow() != null)
178                     {
179                     }
180                 }
181                 rs.close();
182             }
183             catch (StandardException e)
184             {
185                 /* Handle dynamic recompiles */
186                 if (e.getMessageId().equals(SQLState.LANG_STATEMENT_NEEDS_RECOMPILE))
187                 {
188                     StatementContext sc = lcc.getStatementContext();
189                     sc.cleanupOnError(e);
190                     recompile = true;
191                     sps.revalidate(lcc);
192                     continue;
193                 }
194                 lcc.popStatementContext(lcc.getStatementContext(), e);
195                 spsActivation.close();
196                 throw e;
197             }
198
199             /* Done with execution without any recompiles */
200             break;
201         }
202     }
203
204     /**
205      * Cleanup after executing an sps.
206      *
207      * @exception StandardException on error
208      */

209     protected void clearSPS() throws StandardException
210     {
211         if (spsActivation != null)
212         {
213             spsActivation.close();
214         }
215         ps = null;
216         spsActivation = null;
217     }
218 }
219
Popular Tags