KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.compile.ExpressionClassBuilder
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
25 import org.apache.derby.iapi.services.compiler.ClassBuilder;
26 import org.apache.derby.iapi.services.compiler.MethodBuilder;
27 import org.apache.derby.iapi.services.compiler.JavaFactory;
28 import org.apache.derby.iapi.services.compiler.LocalField;
29 import org.apache.derby.iapi.reference.ClassName;
30
31 import org.apache.derby.iapi.services.sanity.SanityManager;
32
33 import org.apache.derby.iapi.sql.compile.CompilerContext;
34 import org.apache.derby.iapi.sql.compile.ExpressionClassBuilderInterface;
35
36 import org.apache.derby.iapi.sql.execute.ResultSetFactory;
37 import org.apache.derby.iapi.sql.execute.ExecutionFactory;
38 import org.apache.derby.iapi.sql.execute.ExecIndexRow;
39
40 import org.apache.derby.iapi.sql.Activation;
41 import org.apache.derby.iapi.sql.ParameterValueSet;
42 import org.apache.derby.iapi.sql.Row;
43
44 import org.apache.derby.iapi.sql.execute.ExecRow;
45
46 import org.apache.derby.impl.sql.compile.OrderedColumnList;
47 import org.apache.derby.impl.sql.compile.ResultColumnList;
48 import org.apache.derby.impl.sql.execute.IndexColumnOrder;
49 import org.apache.derby.iapi.store.access.ColumnOrdering;
50
51 import org.apache.derby.iapi.types.DataValueDescriptor;
52 import org.apache.derby.iapi.types.DataTypeDescriptor;
53 import org.apache.derby.iapi.types.DataValueFactory;
54 import org.apache.derby.iapi.types.TypeId;
55
56 import org.apache.derby.iapi.sql.compile.TypeCompiler;
57
58 import org.apache.derby.iapi.error.StandardException;
59 import org.apache.derby.iapi.util.ByteArray;
60
61 import org.apache.derby.iapi.services.loader.ClassFactory;
62 import org.apache.derby.iapi.services.loader.GeneratedClass;
63 import org.apache.derby.iapi.services.loader.GeneratedByteCode;
64 import org.apache.derby.iapi.services.loader.GeneratedMethod;
65
66 import java.lang.reflect.Modifier JavaDoc;
67 import org.apache.derby.iapi.services.classfile.VMOpcode;
68
69 import org.apache.derby.iapi.services.monitor.Monitor;
70
71 import org.apache.derby.iapi.services.io.FormatableArrayHolder;
72
73 import java.io.Serializable JavaDoc;
74
75 /**
76  * ExpressionClassBuilder
77  * provides an interface to satisfy generation's
78  * common tasks in building classes that involve expressions.
79  * This is the common superclass of ActivationClassBuilder and
80  * FilterClassBuilder. See the documentation on ActivationClassBuilder.
81  *
82  * @author Rick Extracted out of ActivationClassBuilder
83  */

84 abstract class ExpressionClassBuilder implements ExpressionClassBuilderInterface
85 {
86     ///////////////////////////////////////////////////////////////////////
87
//
88
// CONSTANTS
89
//
90
///////////////////////////////////////////////////////////////////////
91

92     static final protected String JavaDoc currentDatetimeFieldName = "cdt";
93
94     ///////////////////////////////////////////////////////////////////////
95
//
96
// STATE
97
//
98
///////////////////////////////////////////////////////////////////////
99

100     protected ClassBuilder cb;
101     protected GeneratedClass gc;
102     protected int nextExprNum;
103     protected int nextNonFastExpr;
104     protected int nextFieldNum;
105     protected MethodBuilder constructor;
106     CompilerContext myCompCtx;
107     MethodBuilder executeMethod; // to find it fast
108

109     protected LocalField cdtField;
110
111     //protected final JavaFactory javaFac;
112

113     private String JavaDoc currentRowScanResultSetName;
114
115
116     ///////////////////////////////////////////////////////////////////////
117
//
118
// CONSTRUCTORS
119
//
120
///////////////////////////////////////////////////////////////////////
121

122     /**
123      * By the time this is done, it has constructed the following class:
124      * <pre>
125      * public class #className extends #superClass {
126      * public #className() { super(); }
127      * }
128      * </pre>
129      *
130      * @exception StandardException thrown on failure
131      */

132     ExpressionClassBuilder (String JavaDoc superClass, String JavaDoc className, CompilerContext cc )
133         throws StandardException
134     {
135         int modifiers = Modifier.PUBLIC | Modifier.FINAL;
136
137         myCompCtx = cc;
138         JavaFactory javaFac = myCompCtx.getJavaFactory();
139
140         if ( className == null ) { className = myCompCtx.getUniqueClassName(); }
141
142         // start the class
143
cb = javaFac.newClassBuilder(myCompCtx.getClassFactory(),
144             getPackageName(), modifiers,
145             className, superClass);
146
147         beginConstructor();
148     }
149
150     ///////////////////////////////////////////////////////////////////////
151
//
152
// ABSTRACT METHODS TO BE IMPLEMENTED BY CHILDREN
153
//
154
///////////////////////////////////////////////////////////////////////
155

156     /**
157      * Get the name of the package that the generated class will live in.
158      *
159      * @return name of package that the generated class will live in.
160      */

161     abstract String JavaDoc getPackageName();
162
163     /**
164      * Get the number of ExecRows that must be allocated
165      *
166      * @return number of ExecRows that must be allocated
167      *
168      * @exception StandardException thrown on failure
169      */

170     abstract int getRowCount()
171          throws StandardException;
172
173     /**
174      * Sets the number of subqueries under this expression
175      *
176      *
177      * @exception StandardException thrown on failure
178      */

179     abstract void setNumSubqueries()
180          throws StandardException;
181
182     /**
183      * Build boiler plate for the Execute method
184      *
185      *
186      * @return a method builder containing boiler plate for the Execute method
187      *
188      * @exception StandardException thrown on failure
189      */

190     abstract MethodBuilder beginExecuteMethod()
191         throws StandardException;
192
193
194     /**
195      * Finish up the Execute method.
196      *
197      *
198      * @exception StandardException thrown on failure
199      */

200     abstract void finishExecuteMethod(boolean genMarkAsTopNode )
201         throws StandardException;
202
203
204     ///////////////////////////////////////////////////////////////////////
205
//
206
// ACCESSORS
207
//
208
///////////////////////////////////////////////////////////////////////
209

210     /**
211         Return the base class of the activation's hierarchy
212         (the subclass of Object).
213
214         This class is expected to hold methods used by all
215         compilation code, such as datatype compilation code,
216         e.g. getDataValueFactory.
217      */

218     abstract String JavaDoc getBaseClassName();
219
220     MethodBuilder getConstructor() {
221         return constructor;
222     }
223
224     ClassBuilder getClassBuilder() {
225         return cb;
226     }
227
228     /**
229      * The execute method returns a result set that will evaluate the
230      * statement this activation class is the compiled form of.
231      * REVISIT: do we need to give the caller the ability to touch it
232      * directly, or could we wrap the alterations to it in this class?
233      */

234     MethodBuilder getExecuteMethod() {
235         return executeMethod;
236     }
237
238
239     ///////////////////////////////////////////////////////////////////////
240
//
241
// CONSTRUCTOR MANAGEMENT
242
//
243
///////////////////////////////////////////////////////////////////////
244

245     private final void beginConstructor()
246     {
247         // create a constructor that just calls super.
248
MethodBuilder realConstructor =
249             cb.newConstructorBuilder(Modifier.PUBLIC);
250         realConstructor.callSuper();
251         realConstructor.methodReturn();
252         realConstructor.complete();
253
254         constructor = cb.newMethodBuilder(Modifier.PUBLIC, "void", "postConstructor");
255         constructor.addThrownException(ClassName.StandardException);
256     }
257
258     /**
259      * Finish the constructor by newing the array of Rows and putting a return
260      * at the end of it.
261      *
262      * @exception StandardException thrown on failure
263      */

264
265     void finishConstructor()
266          throws StandardException
267     {
268         int numResultSets;
269
270         /* Set the number of subqueries */
271         setNumSubqueries();
272
273         numResultSets = getRowCount();
274
275         /* Generate the new of ExecRow[numResultSets] when there are ResultSets
276          * which return Rows.
277          */

278         if (numResultSets >= 1)
279         {
280             addNewArrayOfRows(numResultSets);
281         }
282
283         /* Generated code is:
284          * return;
285          */

286         constructor.methodReturn();
287         constructor.complete();
288     }
289
290     /**
291      * Generate the assignment for row = new ExecRow[numResultSets]
292      *
293      * @param numResultSets The size of the array.
294      */

295     private void addNewArrayOfRows(int numResultSets)
296     {
297         /* Generated code is:
298          * row = new ExecRow[numResultSets];
299          */

300
301         constructor.pushThis();
302         constructor.pushNewArray(ClassName.ExecRow, numResultSets);
303         constructor.putField(ClassName.BaseActivation, "row", ClassName.ExecRow + "[]");
304         constructor.endStatement();
305     }
306
307     ///////////////////////////////////////////////////////////////////////
308
//
309
// ADD FIELDS TO GENERATED CLASS
310
//
311
///////////////////////////////////////////////////////////////////////
312

313     /**
314      * Add a field declaration to the generated class
315      *
316      * @param modifiers The | of the modifier values such as public, static, etc.
317      * @param type The type of the field in java language.
318      * @param name The name of the field.
319      *
320      * @return None.
321      */

322     LocalField newFieldDeclaration(int modifiers, String JavaDoc type, String JavaDoc name)
323     {
324         return cb.addField(type, name, modifiers);
325     }
326
327     /**
328      * Add an arbitrarily named field to the generated class.
329      *
330      * This is used to generate fields where the caller doesn't care what
331      * the field is named. It is especially useful for generating arbitrary
332      * numbers of fields, where the caller doesn't know in advance how many
333      * fields will be used. For example, it is used for generating fields
334      * to hold intermediate values from expressions.
335      *
336      * @param modifiers The | of the modifier values such as public, static, etc.
337      * @param type The type of the field in java language.
338      *
339      * @return The name of the new field
340      */

341
342     LocalField newFieldDeclaration(int modifiers, String JavaDoc type)
343     {
344         return cb.addField(type, newFieldName(), modifiers);
345     }
346
347     ///////////////////////////////////////////////////////////////////////
348
//
349
// ADD FUNCTIONS TO GENERATED CLASS
350
//
351
///////////////////////////////////////////////////////////////////////
352

353     /**
354      * Activations might have need of internal functions
355      * that are not used by the result sets, but by other
356      * activation functions. Thus, we make it possible
357      * for functions to be generated directly as well
358      * as through the newExprFun interface. newExprFun
359      * should be used when a static field pointing to the
360      * expression function is needed.
361      * <p>
362      * The generated function will generally have a generated name
363      * that can be viewed through the MethodBuilder interface.
364      * This name is generated to ensure uniqueness from other
365      * function names in the activation class. If you pass in a function
366      * name, think carefully about whether it will collide with other names.
367      *
368      * @param returnType the return type of the function
369      * @param modifiers the modifiers on the function
370      *
371      * @see #newExprFun
372      */

373     MethodBuilder newGeneratedFun(String JavaDoc returnType, int modifiers) {
374
375         return newGeneratedFun(returnType, modifiers,
376                                (String JavaDoc[]) null);
377     }
378
379     MethodBuilder newGeneratedFun(String JavaDoc returnType,
380                                          int modifiers,
381                                          String JavaDoc[] params) {
382
383         String JavaDoc exprName = "g".concat(Integer.toString(nextNonFastExpr++));
384         return newGeneratedFun(exprName, returnType, modifiers,
385                                params);
386
387     }
388
389     private MethodBuilder newGeneratedFun(String JavaDoc exprName, String JavaDoc returnType,
390                                          int modifiers,
391                                          String JavaDoc[] params) {
392
393
394
395         //
396
// create a new method supplying the given modifiers and return Type
397
// Java: #modifiers #returnType #exprName { }
398
//
399
MethodBuilder exprMethod;
400         if (params == null)
401         {
402             exprMethod = cb.newMethodBuilder(modifiers, returnType, exprName);
403         }
404         else
405         {
406             exprMethod = cb.newMethodBuilder(modifiers, returnType,
407                                              exprName, params);
408         }
409
410         //
411
// declare it to throw StandardException
412
// Java: #modifiers #returnType #exprName throws StandardException { }
413
//
414
exprMethod.addThrownException(ClassName.StandardException);
415
416         return exprMethod;
417     }
418
419     /**
420      * "ExprFun"s are the "expression functions" that
421      * are specific to a given JSQL statement. For example,
422      * an ExprFun is generated to evaluate the where clause
423      * of a select statement and return a boolean result.
424      * <p>
425      *
426      * All methods return by this are expected to be called
427      * via the GeneratedMethod interface. Thus the methods
428      * are public and return java.lang.Object.
429      * <p>
430      * Once the exprfun has been created, the
431      * caller will need to add statements to it,
432      * minimally a return statement.
433      * <p>
434      * ExprFuns return Object types, since they
435      * are invoked through reflection and thus their
436      * return type would get wrapped in an object anyway.
437      * For example: return java.lang.Boolean, not boolean.
438      */

439     MethodBuilder newExprFun()
440     {
441         // get next generated function
442
String JavaDoc exprName = "e".concat(Integer.toString(nextExprNum++));
443
444         return newGeneratedFun(exprName, "java.lang.Object", Modifier.PUBLIC, (String JavaDoc[]) null);
445     }
446
447     /**
448         Push an expression that is a GeneratedMethod reference to the
449         passed in method. aka. a "function pointer".
450     */

451     void pushMethodReference(MethodBuilder mb, MethodBuilder exprMethod) {
452
453         mb.pushThis(); // instance
454
mb.push(exprMethod.getName()); // arg
455
mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.GeneratedByteCode,
456                 "getMethod",
457                 ClassName.GeneratedMethod,
458                 1
459                 );
460     }
461
462     /**
463      * Start a user expression. The difference between a normal expression
464      * (returned by newExprFun)
465      * and a user expression is that a user expression catches all exceptions
466      * (because we don't want random exceptions thrown from user methods to
467      * propagate to the rest of the system.
468      *
469      * @return A new MethodBuilder
470      */

471     MethodBuilder newUserExprFun() {
472
473         MethodBuilder mb = newExprFun();
474         mb.addThrownException("java.lang.Exception");
475         return mb;
476     }
477
478     ///////////////////////////////////////////////////////////////////////
479
//
480
// CURRENT DATE/TIME SUPPORT
481
//
482
///////////////////////////////////////////////////////////////////////
483

484     /**
485         This utility method returns an expression for CURRENT_DATE.
486         Get the expression this way, because the activation needs to
487         generate support information for CURRENT_DATE,
488         that would otherwise be painful to create manually.
489      */

490     void getCurrentDateExpression(MethodBuilder mb) {
491         // do any needed setup
492
LocalField lf = getCurrentSetup();
493
494         // generated Java:
495
// this.cdt.getCurrentDate();
496
mb.getField(lf);
497         mb.callMethod(VMOpcode.INVOKEVIRTUAL, (String JavaDoc) null, "getCurrentDate", "java.sql.Date", 0);
498     }
499
500     /**
501         This utility method returns an expression for CURRENT_TIME.
502         Get the expression this way, because the activation needs to
503         generate support information for CURRENT_TIME,
504         that would otherwise be painful to create manually.
505      */

506     void getCurrentTimeExpression(MethodBuilder mb) {
507         // do any needed setup
508
LocalField lf = getCurrentSetup();
509
510         // generated Java:
511
// this.cdt.getCurrentTime();
512
mb.getField(lf);
513         mb.callMethod(VMOpcode.INVOKEVIRTUAL, (String JavaDoc) null, "getCurrentTime", "java.sql.Time", 0);
514     }
515
516     /**
517         This utility method generates an expression for CURRENT_TIMESTAMP.
518         Get the expression this way, because the activation needs to
519         generate support information for CURRENT_TIMESTAMP,
520         that would otherwise be painful to create manually.
521      */

522     void getCurrentTimestampExpression(MethodBuilder mb) {
523         // do any needed setup
524
LocalField lf = getCurrentSetup();
525
526         // generated Java:
527
// this.cdt.getCurrentTimestamp();
528
mb.getField(lf);
529         mb.callMethod(VMOpcode.INVOKEVIRTUAL, (String JavaDoc) null,
530             "getCurrentTimestamp", "java.sql.Timestamp", 0);
531     }
532
533     ///////////////////////////////////////////////////////////////////////
534
//
535
// COLUMN ORDERING
536
//
537
///////////////////////////////////////////////////////////////////////
538

539     /**
540         These utility methods buffers compilation from the IndexColumnOrder
541         class.
542
543         They create an ordering based on their parameter, stuff that into
544         the prepared statement, and then return the entry # for
545         use in the generated code.
546
547         We could write another utility method to generate code to
548         turn an entry # back into an object, but so far no-one needs it.
549     
550         WARNING: this is a crafty method that ASSUMES that
551         you want every column in the list ordered, and that every
552         column in the list is the entire actual result colunm.
553         It is only useful for DISTINCT in select.
554      */

555     FormatableArrayHolder getColumnOrdering(ResultColumnList rclist)
556     {
557         IndexColumnOrder[] ordering;
558         int numCols = (rclist == null) ? 0 : rclist.size();
559         //skip the columns which are not exclusively part of the insert list
560
//ie columns with default and autoincrement. These columns will not
561
//be part of ordering.
562
int numRealCols = 0;
563         for (int i=0; i<numCols; i++)
564         {
565             if (!(rclist.getResultColumn(i+1).isGeneratedForUnmatchedColumnInInsert()))
566                 numRealCols++;
567         }
568
569         ordering = new IndexColumnOrder[numRealCols];
570         for (int i=0, j=0; i<numCols; i++)
571         {
572             if (!(rclist.getResultColumn(i+1).isGeneratedForUnmatchedColumnInInsert()))
573             {
574                 ordering[j] = new IndexColumnOrder(i);
575                 j++;
576             }
577         }
578         return new FormatableArrayHolder(ordering);
579     }
580
581     /**
582      * Add a column to the existing Ordering list. Takes
583      * a column id and only adds it if it isn't in the list.
584      *
585      *
586      * @return the ColumnOrdering array
587      */

588     FormatableArrayHolder addColumnToOrdering(
589                         FormatableArrayHolder orderingHolder,
590                         int columnNum)
591     {
592         /*
593         ** We don't expect a lot of order by columns, so
594         ** linear search.
595         */

596         ColumnOrdering[] ordering = (ColumnOrdering[])orderingHolder.
597                                         getArray(ColumnOrdering.class);
598         int length = ordering.length;
599         for (int i = 0; i < length; i++)
600         {
601             if (ordering[i].getColumnId() == columnNum)
602                 return orderingHolder;
603         }
604
605         /*
606         ** Didn't find it. Allocate a bigger array
607         ** and add it to the end
608         */

609         IndexColumnOrder[] newOrdering = new IndexColumnOrder[length+1];
610         System.arraycopy(ordering, 0, newOrdering, 0, length);
611         newOrdering[length] = new IndexColumnOrder(columnNum);
612         
613         return new FormatableArrayHolder(newOrdering);
614     }
615
616
617     FormatableArrayHolder getColumnOrdering(OrderedColumnList oclist) {
618         int numCols = (oclist == null) ? 0 : oclist.size();
619
620         if (numCols == 0)
621         {
622             return new FormatableArrayHolder(new IndexColumnOrder[0]);
623         }
624
625         return new FormatableArrayHolder(oclist.getColumnOrdering());
626     }
627
628     int addItem(Object JavaDoc o)
629     {
630         if (SanityManager.DEBUG)
631         {
632             if ((o != null) && !(o instanceof Serializable JavaDoc))
633             {
634                 SanityManager.THROWASSERT(
635                     "o (" + o.getClass().getName() +
636                     ") expected to be instanceof java.io.Serializable");
637             }
638         }
639         return myCompCtx.addSavedObject(o);
640     }
641
642     ///////////////////////////////////////////////////////////////////////
643
//
644
// Caching resuable Expressions
645
//
646
///////////////////////////////////////////////////////////////////////
647

648     /**
649      * Get/reuse the Expression for getting the DataValueFactory
650      */

651     private Object JavaDoc getDVF;
652     void pushDataValueFactory(MethodBuilder mb)
653     {
654         // generates:
655
// getDataValueFactory()
656
//
657

658         if (getDVF == null) {
659             getDVF = mb.describeMethod(VMOpcode.INVOKEVIRTUAL,
660                                         getBaseClassName(),
661                                         "getDataValueFactory",
662                                         ClassName.DataValueFactory);
663         }
664
665         mb.pushThis();
666         mb.callMethod(getDVF);
667     }
668
669     ///////////////////////////////////////////////////////////////////////
670
//
671
// RESULT SET SUPPORT
672
//
673
///////////////////////////////////////////////////////////////////////
674

675     /**
676         This is a utility method to get a common expression --
677         "BaseActivation.getResultSetFactory()".
678         <p>
679         BaseActivation gets the factory from the context and
680         caches it for faster retrieval.
681      */

682     private Object JavaDoc getRSF;
683     void pushGetResultSetFactoryExpression(MethodBuilder mb) {
684         // generated Java:
685
// this.getResultSetFactory()
686
//
687
if (getRSF == null) {
688             getRSF = mb.describeMethod(VMOpcode.INVOKEVIRTUAL, getBaseClassName(),
689                     "getResultSetFactory",
690                     ClassName.ResultSetFactory);
691         }
692         mb.pushThis();
693         mb.callMethod(getRSF);
694     }
695
696     /**
697         This is a utility method to get a common expression --
698         "BaseActivation.getExecutionFactory()".
699         REVISIT: could the same expression objects be reused within
700         the tree and have the correct java generated each time?
701         <p>
702         BaseActivation gets the factory from the context and
703         caches it for faster retrieval.
704      */

705     private Object JavaDoc getEF;
706     void pushGetExecutionFactoryExpression(MethodBuilder mb) {
707         if (getEF == null) {
708             getEF = mb.describeMethod(VMOpcode.INVOKEVIRTUAL, getBaseClassName(),
709                     "getExecutionFactory",
710                     ClassName.ExecutionFactory);
711         }
712
713         // generated Java:
714
// this.getExecutionFactory()
715
//
716
mb.pushThis();
717         mb.callMethod(getEF);
718     }
719
720     /**
721      * Generate a reference to the row array that
722      * all activations use.
723      *
724      * @param eb the expression block
725      *
726      * @return expression
727      */

728     //private void pushRowArrayReference(MethodBuilder mb)
729
//{
730
// PUSHCOMPILE - cache
731
// mb.pushThis();
732
// mb.getField(ClassName.BaseActivation, "row", ClassName.ExecRow + "[]");
733
//}
734

735     /**
736      * Generate a reference to a colunm in a result set.
737      *
738      * @param rsNumber the result set number
739      * @param colId the column number
740      */

741     void pushColumnReference(MethodBuilder mb, int rsNumber, int colId)
742     {
743         mb.pushThis();
744         mb.push(rsNumber);
745         mb.push(colId);
746         mb.callMethod(VMOpcode.INVOKEVIRTUAL, ClassName.BaseActivation, "getColumnFromRow",
747                         ClassName.DataValueDescriptor, 2);
748
749         //System.out.println("pushColumnReference ");
750
//pushRowArrayReference(mb);
751
//mb.getArrayElement(rsNumber); // instance for getColumn
752
//mb.push(colId); // first arg
753
//mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.Row, "getColumn", ClassName.DataValueDescriptor, 1);
754
}
755
756     /**
757      * Generate a reference to the parameter value
758      * set that all activations use.
759      *
760      */

761     void pushPVSReference(MethodBuilder mb)
762     {
763         // PUSHCOMPILER-WASCACHED
764
mb.pushThis();
765         mb.getField(ClassName.BaseActivation, "pvs", ClassName.ParameterValueSet);
766     }
767
768     ///////////////////////////////////////////////////////////////////////
769
//
770
// CLASS IMPLEMENTATION
771
//
772
///////////////////////////////////////////////////////////////////////
773

774     /*
775         The first time a current datetime is needed, create the class
776         level support for it.
777      */

778     protected LocalField getCurrentSetup() {
779         if (cdtField != null)
780             return cdtField;
781
782         // generated Java:
783
// 1) the field "cdt" is created:
784
// private CurrentDatetime cdt;
785
cdtField = newFieldDeclaration(
786             Modifier.PRIVATE,
787             ClassName.CurrentDatetime,
788             currentDatetimeFieldName);
789
790         // 2) the constructor gets a statement to init CurrentDatetime:
791
// cdt = new CurrentDatetime();
792

793         constructor.pushNewStart(ClassName.CurrentDatetime);
794         constructor.pushNewComplete(0);
795         constructor.setField(cdtField);
796
797         return cdtField;
798     }
799
800     /**
801      * generated the next field name available.
802      * these are of the form 'e#', where # is
803      * incremented each time.
804      * This shares the name space with the expression methods
805      * as Java allows names and fields to have the same name.
806      * This reduces the number of constant pool entries created
807      * for a generated class file.
808      */

809     private String JavaDoc newFieldName()
810     {
811         return "e".concat(Integer.toString(nextFieldNum++));
812     }
813
814
815     ///////////////////////////////////////////////////////////////////////
816
//
817
// DEBUG
818
//
819
///////////////////////////////////////////////////////////////////////
820

821
822     ///////////////////////////////////////////////////////////////////////
823
//
824
// DATATYPES
825
//
826
///////////////////////////////////////////////////////////////////////
827
/**
828      * Get the TypeCompiler associated with the given TypeId
829      *
830      * @param typeId The TypeId to get a TypeCompiler for
831      *
832      * @return The corresponding TypeCompiler
833      *
834      */

835     protected TypeCompiler getTypeCompiler(TypeId typeId)
836     {
837         return myCompCtx.getTypeCompilerFactory().getTypeCompiler(typeId);
838     }
839
840     ///////////////////////////////////////////////////////////////////////
841
//
842
// GENERATE BYTE CODE
843
//
844
///////////////////////////////////////////////////////////////////////
845

846     /**
847      * Take the generated class, and turn it into an
848      * actual class.
849      * <p> This method assumes, does not check, that
850      * the class and its parts are all complete.
851      *
852      * @param savedBytes place to save generated bytes.
853      * if null, it is ignored
854      * @exception StandardException thrown when exception occurs
855      */

856     GeneratedClass getGeneratedClass(ByteArray savedBytes) throws StandardException {
857         if (gc != null) return gc;
858
859         if (savedBytes != null)
860         {
861             ByteArray classBytecode = cb.getClassBytecode();
862
863             // note: be sure to set the length since
864
// the class builder allocates the byte array
865
// in big chunks
866
savedBytes.setBytes(classBytecode.getArray());
867             savedBytes.setLength(classBytecode.getLength());
868         }
869
870         gc = cb.getGeneratedClass();
871
872         return gc; // !! yippee !! here it is...
873
}
874
875     /**
876      * Get a "this" expression declared as an Activation.
877      * This is the commonly used type of the this expression.
878      *
879      */

880     void pushThisAsActivation(MethodBuilder mb) {
881         // PUSHCOMPILER - WASCACHED
882
mb.pushThis();
883         mb.upCast(ClassName.Activation);
884     }
885
886     /**
887         Generate a Null data value.
888         Nothing is required on the stack, a SQL null data value
889         is pushed.
890     */

891     void generateNull(MethodBuilder mb, TypeCompiler tc) {
892         pushDataValueFactory(mb);
893         mb.pushNull(tc.interfaceName());
894         tc.generateNull(mb);
895     }
896
897     /**
898         Generate a Null data value.
899         The express value is required on the stack and will be popped, a SQL null data value
900         is pushed.
901     */

902     void generateNullWithExpress(MethodBuilder mb, TypeCompiler tc) {
903         pushDataValueFactory(mb);
904         mb.swap(); // need the dvf as the instance
905
mb.cast(tc.interfaceName());
906         tc.generateNull(mb);
907     }
908
909     /**
910         Generate a data value.
911         The value is to be set in the SQL data value is required
912         on the stack and will be popped, a SQL data value
913         is pushed.
914     */

915     void generateDataValue(MethodBuilder mb, TypeCompiler tc, LocalField field) {
916         pushDataValueFactory(mb);
917         mb.swap(); // need the dvf as the instance
918
tc.generateDataValue(mb, field);
919     }
920
921     
922     /**
923      *generates a variable name for the rowscanresultset.
924      *This can not be a fixed name because in cases like
925      *cascade delete same activation class will be dealing
926      * more than one RowScanResultSets for dependent tables.
927     */

928
929     String JavaDoc newRowLocationScanResultSetName()
930     {
931         currentRowScanResultSetName = newFieldName();
932         return currentRowScanResultSetName;
933     }
934
935     // return the Name of ResultSet with the RowLocations to be modified (deleted or updated).
936
String JavaDoc getRowLocationScanResultSetName()
937     {
938         return currentRowScanResultSetName;
939     }
940
941     
942 }
943
944
945
946
947
948
949
950
951
952
Popular Tags