KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.compile.ActivationClassBuilder
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.compiler.ClassBuilder;
25 import org.apache.derby.iapi.services.compiler.MethodBuilder;
26 import org.apache.derby.iapi.services.compiler.LocalField;
27 import org.apache.derby.iapi.reference.ClassName;
28
29
30 import org.apache.derby.iapi.services.sanity.SanityManager;
31
32 import org.apache.derby.iapi.sql.compile.CompilerContext;
33 import org.apache.derby.iapi.sql.compile.CodeGeneration;
34
35 import org.apache.derby.iapi.sql.execute.CursorResultSet;
36
37 import org.apache.derby.iapi.sql.ResultSet;
38
39 import org.apache.derby.iapi.sql.execute.ExecRow;
40
41 import org.apache.derby.iapi.types.DataTypeDescriptor;
42 import org.apache.derby.iapi.types.TypeId;
43
44 import org.apache.derby.iapi.error.StandardException;
45
46 import org.apache.derby.iapi.services.loader.GeneratedMethod;
47 import org.apache.derby.iapi.services.classfile.VMOpcode;
48
49 import java.lang.reflect.Modifier JavaDoc;
50
51 import java.io.PrintWriter JavaDoc;
52
53 import java.io.File JavaDoc;
54 import java.io.FileOutputStream JavaDoc;
55 import java.io.ByteArrayOutputStream JavaDoc;
56 import java.io.IOException JavaDoc;
57 import java.util.Hashtable JavaDoc;
58
59 /**
60  * ActivationClassBuilder
61  * provides an interface to satisfy generation's
62  * common tasks in building an activation class,
63  * as well as a repository for the JavaFactory used
64  * to generate the basic language constructs for the methods in the class.
65  * Common tasks include the setting of a static field for each
66  * expression function that gets added, the creation
67  * of the execute method that gets expanded as the query tree
68  * is walked, setting the superclass.
69  * <p>
70  * An activation class is defined for each statement. It has
71  * the following basic layout: TBD
72  * See the document
73  * \\Jeeves\Unversioned Repository 1\Internal Technical Documents\Other\GenAndExec.doc
74  * for details.
75  * <p>
76  * We could also verify methods as they are
77  * added, to have 0 parameters, ...
78  *
79  * @author ames
80  */

81 class ActivationClassBuilder extends ExpressionClassBuilder
82 {
83     ///////////////////////////////////////////////////////////////////////
84
//
85
// CONSTANTS
86
//
87
///////////////////////////////////////////////////////////////////////
88

89     ///////////////////////////////////////////////////////////////////////
90
//
91
// STATE
92
//
93
///////////////////////////////////////////////////////////////////////
94

95     private LocalField targetResultSetField;
96     private LocalField cursorResultSetField;
97
98     private MethodBuilder closeActivationMethod;
99
100
101     ///////////////////////////////////////////////////////////////////////
102
//
103
// CONSTRUCTOR
104
//
105
///////////////////////////////////////////////////////////////////////
106

107     /**
108      * By the time this is done, it has constructed the following class:
109      * <pre>
110      * public class #className extends #superClass {
111      * // public void reset() { return; }
112      * public ResultSet execute() throws StandardException {
113      * throwIfClosed("execute");
114      * // statements must be added here
115      * }
116      * public #className() { super(); }
117      * }
118      * </pre>
119      *
120      * @exception StandardException thrown on failure
121      */

122     ActivationClassBuilder (String JavaDoc superClass, CompilerContext cc) throws StandardException
123     {
124         super( superClass, (String JavaDoc) null, cc );
125         executeMethod = beginExecuteMethod();
126     }
127
128     ///////////////////////////////////////////////////////////////////////
129
//
130
// ACCESSORS
131
//
132
///////////////////////////////////////////////////////////////////////
133

134     /**
135       * Get the package name that this generated class lives in
136       *
137       * @return package name
138       */

139     public String JavaDoc getPackageName()
140     { return CodeGeneration.GENERATED_PACKAGE_PREFIX; }
141
142     /**
143         The base class for activations is BaseActivation
144      */

145     String JavaDoc getBaseClassName() {
146         return ClassName.BaseActivation;
147     }
148
149
150     /**
151       * Get the number of ExecRows to allocate
152       *
153       * @exception StandardException thrown on failure
154       * @return package name
155       */

156     public int getRowCount()
157          throws StandardException
158     {
159         return myCompCtx.getNumResultSets();
160     }
161
162     /**
163      * Generate the assignment for numSubqueries = x
164      *
165      * @exception StandardException thrown on failure
166      */

167     public void setNumSubqueries()
168     {
169         int numSubqueries = myCompCtx.getNumSubquerys();
170
171         // If there are no subqueries then
172
// the field is set to the correctly
173
// value (0) by java.
174
if (numSubqueries == 0)
175             return;
176
177         /* Generated code is:
178          * numSubqueries = x;
179          */

180         constructor.pushThis();
181         constructor.push(numSubqueries);
182         constructor.putField(ClassName.BaseActivation, "numSubqueries", "int");
183         constructor.endStatement();
184     }
185
186
187     ///////////////////////////////////////////////////////////////////////
188
//
189
// EXECUTE METHODS
190
//
191
///////////////////////////////////////////////////////////////////////
192

193     /**
194      * By the time this is done, it has generated the following code
195      * <pre>
196      * public ResultSet execute() throws StandardException {
197      * throwIfClosed("execute");
198      * // statements must be added here
199      * }
200      * }
201      * </pre>
202      *
203      * @exception StandardException thrown on failure
204      */

205     public MethodBuilder beginExecuteMethod()
206         throws StandardException
207     {
208         // create a reset method that does nothing.
209
// REVISIT: this might better belong in the Activation
210
// superclasses ?? not clear yet what it needs to do.
211

212         // don't yet need a reset method here. when we do,
213
// it will need to call super.reset() as well as
214
// whatever it does.
215
// mb = cb.newMethodBuilder(
216
// Modifier.PUBLIC, "void", "reset");
217
// mb.addStatement(javaFac.newStatement(
218
// javaFac.newSpecialMethodCall(
219
// thisExpression(),
220
// BaseActivation.CLASS_NAME,
221
// "reset", "void")));
222
// mb.addStatement(javaFac.newReturnStatement());
223
// mb.complete(); // there is nothing else.
224

225
226         // This method is an implementation of the interface method
227
// Activation - ResultSet execute()
228

229         // create an empty execute method
230
MethodBuilder mb = cb.newMethodBuilder(Modifier.PUBLIC,
231             ClassName.ResultSet, "execute");
232         mb.addThrownException(ClassName.StandardException);
233
234         // put a 'throwIfClosed("execute");' statement into the execute method.
235
mb.pushThis(); // instance
236
mb.push("execute");
237         mb.callMethod(VMOpcode.INVOKEVIRTUAL, ClassName.BaseActivation, "throwIfClosed", "void", 1);
238
239         // call this.startExecution(), so the parent class can know an execution
240
// has begun.
241

242         mb.pushThis(); // instance
243
mb.callMethod(VMOpcode.INVOKEVIRTUAL, ClassName.BaseActivation, "startExecution", "void", 0);
244
245         return mb;
246     }
247
248     MethodBuilder startResetMethod() {
249         MethodBuilder mb = cb.newMethodBuilder(Modifier.PUBLIC,
250             "void", "reset");
251
252         mb.addThrownException(ClassName.StandardException);
253         mb.pushThis();
254         mb.callMethod(VMOpcode.INVOKESPECIAL, ClassName.BaseActivation, "reset", "void", 0);
255
256
257         return mb;
258     }
259
260     /**
261      * An execute method always ends in a return statement, returning
262      * the result set that has been constructed. We want to
263      * do some bookkeeping on that statement, so we generate
264      * the return given the result set.
265
266        Upon entry the only word on the stack is the result set expression
267      */

268     void finishExecuteMethod(boolean genMarkAsTopNode) {
269
270         executeMethod.pushThis();
271         executeMethod.getField(ClassName.BaseActivation, "resultSet", ClassName.ResultSet);
272
273         /* We only call markAsTopResultSet() for selects.
274          * Non-select DML marks the top NoPutResultSet in the constructor.
275          * Needed for closing down resultSet on an error.
276          */

277         if (genMarkAsTopNode)
278         {
279             // dup the result set to leave one for the return and one for this call
280
executeMethod.dup();
281             executeMethod.cast(ClassName.NoPutResultSet);
282             executeMethod.callMethod(VMOpcode.INVOKEINTERFACE, (String JavaDoc) null, "markAsTopResultSet", "void", 0);
283         }
284
285         /* return resultSet */
286         executeMethod.methodReturn();
287         executeMethod.complete();
288
289         getClassBuilder().newFieldWithAccessors("getExecutionCount", "setExecutionCount",
290             Modifier.PROTECTED, true, "int");
291
292         getClassBuilder().newFieldWithAccessors("getRowCountCheckVector", "setRowCountCheckVector",
293             Modifier.PROTECTED, true, "java.util.Vector");
294
295         getClassBuilder().newFieldWithAccessors("getStalePlanCheckInterval", "setStalePlanCheckInterval",
296             Modifier.PROTECTED, true, "int");
297
298         if (closeActivationMethod != null) {
299             closeActivationMethod.methodReturn();
300             closeActivationMethod.complete();
301         }
302     }
303
304     ///////////////////////////////////////////////////////////////////////
305
//
306
// CURSOR SUPPORT
307
//
308
///////////////////////////////////////////////////////////////////////
309

310     /**
311      * Updatable cursors
312      * need to add a getter method for use in BaseActivation to access
313      * the result set that identifies target rows for a positioned
314      * update or delete.
315      * <p>
316      * The code that is generated is:
317      * <pre><verbatim>
318      * public CursorResultSet getTargetResultSet() {
319      * return targetResultSet;
320      * }
321      *
322      * public CursorResultSet getCursorResultSet() {
323      * return cursorResultSet;
324      * }
325      * </verbatim></pre>
326      *
327      */

328     void addCursorPositionCode() {
329
330         // the getter
331
// This method is an implementation of the interface method
332
// CursorActivation - CursorResultSet getTargetResultSet()
333
MethodBuilder getter = cb.newMethodBuilder(Modifier.PUBLIC,
334             ClassName.CursorResultSet, "getTargetResultSet");
335
336         getter.getField(targetResultSetField);
337         getter.methodReturn();
338         getter.complete();
339
340         // This method is an implementation of the interface method
341
// CursorActivation - CursorResultSet getCursorResultSet()
342

343         getter = cb.newMethodBuilder(Modifier.PUBLIC,
344             ClassName.CursorResultSet, "getCursorResultSet");
345
346         getter.getField(cursorResultSetField);
347         getter.methodReturn();
348         getter.complete();
349     }
350
351     /**
352      * Updatable cursors
353      * need to add a field and its initialization
354      * for use in BaseActivation to access the result set that
355      * identifies target rows for a positioned update or delete.
356      * <p>
357      * The code that is generated is:
358      * <pre><verbatim>
359      * private CursorResultSet targetResultSet;
360      *
361      * </verbatim></pre>
362      *
363      * The expression that is generated is:
364      * <pre><verbatim>
365      * (ResultSet) (targetResultSet = (CursorResultSet) #expression#)
366      * </verbatim></pre>
367      *
368      */

369     void rememberCursorTarget(MethodBuilder mb) {
370
371         // the field
372
targetResultSetField = cb.addField(ClassName.CursorResultSet,
373                     "targetResultSet",
374                     Modifier.PRIVATE);
375
376         mb.cast(ClassName.CursorResultSet);
377         mb.putField(targetResultSetField);
378         mb.cast(ClassName.NoPutResultSet);
379     }
380
381     /**
382      * Updatable cursors
383      * need to add a field and its initialization
384      * for use in BaseActivation to access the result set that
385      * identifies cursor result rows for a positioned update or delete.
386      * <p>
387      * The code that is generated is:
388      * <pre><verbatim>
389      * private CursorResultSet cursorResultSet;
390      *
391      * </verbatim></pre>
392      *
393      * The expression that is generated is:
394      * <pre><verbatim>
395      * (ResultSet) (cursorResultSet = (CursorResultSet) #expression#)
396      * </verbatim></pre>
397
398        The expression must be the top stack word when this method is called.
399      *
400      */

401     void rememberCursor(MethodBuilder mb) {
402
403         // the field
404
cursorResultSetField = cb.addField(ClassName.CursorResultSet,
405                     "cursorResultSet",
406                     Modifier.PRIVATE);
407
408         mb.cast(ClassName.CursorResultSet);
409         mb.putField(cursorResultSetField);
410         mb.cast(ClassName.ResultSet);
411     }
412
413     ///////////////////////////////////////////////////////////////////////
414
//
415
// CURRENT DATE/TIME SUPPORT
416
//
417
///////////////////////////////////////////////////////////////////////
418

419     /*
420         The first time a current datetime is needed, create the class
421         level support for it. The first half of the logic is in our parent
422         class.
423      */

424     protected LocalField getCurrentSetup()
425     {
426         if (cdtField != null) return cdtField;
427
428         LocalField lf = super.getCurrentSetup();
429
430         // 3) the execute method gets a statement (prior to the return)
431
// to tell cdt to restart:
432
// cdt.forget();
433

434         executeMethod.getField(lf);
435         executeMethod.callMethod(VMOpcode.INVOKEVIRTUAL, (String JavaDoc) null, "forget", "void", 0);
436
437         return lf;
438     }
439
440     MethodBuilder getCloseActivationMethod() {
441
442         if (closeActivationMethod == null) {
443             closeActivationMethod = cb.newMethodBuilder(Modifier.PUBLIC, "void", "closeActivationAction");
444             closeActivationMethod.addThrownException("java.lang.Exception");
445         }
446         return closeActivationMethod;
447     }
448 }
449
450
Popular Tags