KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.compile.FromVTI
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.loader.ClassInspector;
25 import org.apache.derby.iapi.services.loader.GeneratedMethod;
26
27 import org.apache.derby.iapi.services.context.ContextManager;
28
29 import org.apache.derby.iapi.services.compiler.MethodBuilder;
30 import org.apache.derby.iapi.services.compiler.LocalField;
31
32 import org.apache.derby.iapi.services.sanity.SanityManager;
33
34 import org.apache.derby.iapi.error.StandardException;
35
36 import org.apache.derby.iapi.sql.compile.CompilerContext;
37 import org.apache.derby.iapi.sql.compile.OptimizablePredicateList;
38 import org.apache.derby.iapi.sql.compile.Optimizer;
39 import org.apache.derby.iapi.sql.compile.OptimizablePredicate;
40 import org.apache.derby.iapi.sql.compile.Optimizable;
41 import org.apache.derby.iapi.sql.compile.CostEstimate;
42 import org.apache.derby.iapi.sql.compile.Visitable;
43 import org.apache.derby.iapi.sql.compile.Visitor;
44 import org.apache.derby.iapi.sql.compile.RowOrdering;
45 import org.apache.derby.iapi.sql.compile.C_NodeTypes;
46
47 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
48
49 import org.apache.derby.iapi.sql.dictionary.DataDictionary;
50 import org.apache.derby.iapi.sql.dictionary.ColumnDescriptor;
51 import org.apache.derby.iapi.sql.dictionary.ColumnDescriptorList;
52 import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor;
53 import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
54
55 import org.apache.derby.iapi.reference.ClassName;
56 import org.apache.derby.iapi.reference.JDBC20Translation;
57 import org.apache.derby.iapi.reference.SQLState;
58
59 import org.apache.derby.iapi.sql.Activation;
60
61 import org.apache.derby.catalog.UUID;
62
63 import org.apache.derby.vti.DeferModification;
64 import org.apache.derby.vti.VTICosting;
65 import org.apache.derby.vti.VTIEnvironment;
66
67 import org.apache.derby.iapi.util.JBitSet;
68 import org.apache.derby.iapi.services.io.FormatableBitSet;
69 import org.apache.derby.iapi.services.classfile.VMOpcode;
70 import org.apache.derby.iapi.services.info.JVMInfo;
71
72 import org.apache.derby.impl.sql.compile.ActivationClassBuilder;
73 import org.apache.derby.iapi.sql.execute.ExecutionContext;
74
75 import java.lang.reflect.Constructor JavaDoc;
76 import java.lang.reflect.InvocationTargetException JavaDoc;
77
78 import java.sql.PreparedStatement JavaDoc;
79 import java.sql.ResultSet JavaDoc;
80 import java.sql.ResultSetMetaData JavaDoc;
81 import java.sql.SQLException JavaDoc;
82 import java.sql.Types JavaDoc;
83
84 import java.util.Enumeration JavaDoc;
85 import java.util.Properties JavaDoc;
86 import java.util.Vector JavaDoc;
87 import org.apache.derby.iapi.services.io.FormatableHashtable;
88
89 import java.lang.reflect.Modifier JavaDoc;
90
91 /**
92  * A FromVTI represents a VTI in the FROM list of a DML statement.
93  *
94  * @author Jerry Brenner
95  */

96 public class FromVTI extends FromTable implements VTIEnvironment
97 {
98
99     JBitSet correlationMap;
100     JBitSet dependencyMap;
101     NewInvocationNode newInvocation;
102     TableName exposedName;
103     SubqueryList subqueryList;
104     boolean implementsVTICosting;
105     boolean optimized;
106     boolean materializable;
107     boolean isTarget;
108     ResultSet JavaDoc rs;
109
110     private FormatableHashtable compileTimeConstants;
111
112     // Number of columns returned by the VTI
113
protected int numVTICols;
114
115     private PredicateList restrictionList;
116
117
118     /**
119         Was a FOR UPDATE clause specified in a SELECT statement.
120     */

121     private boolean forUpdatePresent;
122
123
124     /**
125         Was the FOR UPDATE clause empty (no columns specified).
126     */

127     private boolean emptyForUpdate;
128
129
130     /*
131     ** We don't know how expensive a virtual table will be.
132     ** Let's say it has 10000 rows with a cost of 100000.
133     */

134     double estimatedCost = VTICosting.defaultEstimatedCost;
135     double estimatedRowCount = VTICosting.defaultEstimatedRowCount;
136     boolean supportsMultipleInstantiations = true;
137     boolean vtiCosted;
138
139     /* Version 1 or 2 VTI*/
140     protected boolean version2;
141     private boolean implementsPushable;
142     private PreparedStatement JavaDoc ps;
143
144     private JavaValueNode[] methodParms;
145     
146     private boolean controlsDeferral;
147     private boolean isInsensitive;
148     private int resultSetType = ResultSet.TYPE_FORWARD_ONLY;
149
150     /**
151      * @param newInvocation The constructor for the VTI
152      * @param correlationName The correlation name
153      * @param derivedRCL The derived column list
154      * @param tableProperties Properties list associated with the table
155      *
156      * @exception StandardException Thrown on error
157      */

158     public void init(
159                     Object JavaDoc newInvocation,
160                     Object JavaDoc correlationName,
161                     Object JavaDoc derivedRCL,
162                     Object JavaDoc tableProperties)
163         throws StandardException
164     {
165         init( newInvocation,
166               correlationName,
167               derivedRCL,
168               tableProperties,
169               makeTableName(null, (String JavaDoc) correlationName));
170     }
171
172     /**
173      * @param newInvocation The constructor for the VTI
174      * @param correlationName The correlation name
175      * @param derivedRCL The derived column list
176      * @param tableProperties Properties list associated with the table
177      * @param exposedTableName The table name (TableName class)
178      *
179      * @exception StandardException Thrown on error
180      */

181     public void init(
182                     Object JavaDoc newInvocation,
183                     Object JavaDoc correlationName,
184                     Object JavaDoc derivedRCL,
185                     Object JavaDoc tableProperties,
186                     Object JavaDoc exposedTableName)
187         throws StandardException
188     {
189         super.init(correlationName, tableProperties);
190         this.newInvocation = (NewInvocationNode) newInvocation;
191         resultColumns = (ResultColumnList) derivedRCL;
192         subqueryList = (SubqueryList) getNodeFactory().getNode(
193                                             C_NodeTypes.SUBQUERY_LIST,
194                                             getContextManager());
195
196         /* Cache exposed name for this table.
197          * The exposed name becomes the qualifier for each column
198          * in the expanded list.
199          */

200         this.exposedName = (TableName) exposedTableName;
201     }
202
203     // Optimizable interface
204

205     /**
206      * @see Optimizable#estimateCost
207      *
208      * @exception StandardException Thrown on error
209      */

210     public CostEstimate estimateCost(
211                 OptimizablePredicateList predList,
212                 ConglomerateDescriptor cd,
213                 CostEstimate outerCost,
214                 Optimizer optimizer,
215                 RowOrdering rowOrdering)
216             throws StandardException
217     {
218         costEstimate = getCostEstimate(optimizer);
219
220         /* Cost the VTI if it implements VTICosting.
221          * Otherwise we use the defaults.
222          * NOTE: We only cost the VTI once.
223          */

224         if (implementsVTICosting && ! vtiCosted)
225         {
226             try
227             {
228                 VTICosting vtic = (version2) ? (VTICosting) ps : (VTICosting) rs;
229                 estimatedCost = vtic.getEstimatedCostPerInstantiation(this);
230                 estimatedRowCount = vtic.getEstimatedRowCount(this);
231                 supportsMultipleInstantiations = vtic.supportsMultipleInstantiations(this);
232
233                 if (ps != null) {
234                     ps.close();
235                     ps = null;
236                 }
237                 if (rs != null) {
238                     rs.close();
239                     rs = null;
240                 }
241             }
242             catch (SQLException JavaDoc sqle)
243             {
244                 throw StandardException.unexpectedUserException(sqle);
245             }
246             vtiCosted = true;
247         }
248
249         costEstimate.setCost(estimatedCost, estimatedRowCount, estimatedRowCount);
250
251         /*
252         ** Let the join strategy decide whether the cost of the base
253         ** scan is a single scan, or a scan per outer row.
254         ** NOTE: The multiplication should only be done against the
255         ** total row count, not the singleScanRowCount.
256         ** RESOLVE - If the join strategy does not do materialization,
257         ** the VTI does not support multiple instantiations and the
258         ** outer row count is not exactly 1 row, then we need to change
259         ** the costing formula to take into account the cost of creating
260         ** the temp conglomerate, writing to it and reading from it
261         ** outerCost.rowCount() - 1 times.
262         */

263         if (getCurrentAccessPath().
264                 getJoinStrategy().
265                     multiplyBaseCostByOuterRows())
266         {
267             costEstimate.multiply(outerCost.rowCount(), costEstimate);
268         }
269
270         if ( ! optimized)
271         {
272             subqueryList.optimize(optimizer.getDataDictionary(),
273                                     costEstimate.rowCount());
274             subqueryList.modifyAccessPaths();
275         }
276
277         optimized = true;
278
279         return costEstimate;
280     }
281
282     /**
283      * @see Optimizable#legalJoinOrder
284      */

285     public boolean legalJoinOrder(JBitSet assignedTableMap)
286     {
287         /* In order to tell if this is a legal join order, we
288          * need to see if the assignedTableMap, ORed with the
289          * outer tables that we are correlated with, contains
290          * our dependency map.
291          */

292         JBitSet tempBitSet = (JBitSet) assignedTableMap;
293         tempBitSet.or(correlationMap);
294
295         /* Have all of our dependencies been satisified? */
296         return tempBitSet.contains(dependencyMap);
297     }
298
299
300     /** @see Optimizable#isMaterializable
301      *
302      */

303     public boolean isMaterializable()
304     {
305         return materializable;
306     }
307
308     /** @see Optimizable#supportsMultipleInstantiations */
309     public boolean supportsMultipleInstantiations()
310     {
311         return supportsMultipleInstantiations;
312     }
313
314     /**
315      * @see Optimizable#modifyAccessPath
316      *
317      * @exception StandardException Thrown on error
318      */

319     public Optimizable modifyAccessPath(JBitSet outerTables) throws StandardException
320     {
321         /* Close the rs if one was instantiated */
322         if (rs != null)
323         {
324             try
325             {
326                 rs.close();
327                 rs = null;
328             }
329             catch(Throwable JavaDoc t)
330             {
331                 throw StandardException.unexpectedUserException(t);
332             }
333         }
334
335         return super.modifyAccessPath(outerTables);
336     }
337
338     public boolean pushOptPredicate(OptimizablePredicate optimizablePredicate)
339         throws StandardException
340     {
341         if (!implementsPushable)
342             return false;
343
344         // Do not push down join predicates: those referencing more than one table.
345
if( ! optimizablePredicate.getReferencedMap().hasSingleBitSet())
346             return false;
347         
348         if (restrictionList == null) {
349             restrictionList = (PredicateList) getNodeFactory().getNode(
350                                             C_NodeTypes.PREDICATE_LIST,
351                                             getContextManager());
352         }
353
354         restrictionList.addPredicate((Predicate) optimizablePredicate);
355         return true;
356     }
357
358
359     /**
360      * Convert this object to a String. See comments in QueryTreeNode.java
361      * for how this should be done for tree printing.
362      *
363      * @return This object as a String
364      */

365
366     public String JavaDoc toString()
367     {
368         if (SanityManager.DEBUG)
369         {
370             return "materializable: " + materializable + "\n" +
371               super.toString();
372         }
373         else
374         {
375             return "";
376         }
377     }
378
379     /**
380      * Prints the sub-nodes of this object. See QueryTreeNode.java for
381      * how tree printing is supposed to work.
382      *
383      * @param depth The depth of this node in the tree
384      */

385
386     public void printSubNodes(int depth)
387     {
388         if (SanityManager.DEBUG) {
389             super.printSubNodes(depth);
390
391             if (newInvocation != null)
392             {
393                 printLabel(depth, "newInvocation: ");
394                 newInvocation.treePrint(depth + 1);
395             }
396
397             if (exposedName != null)
398             {
399                 printLabel(depth, "exposedName: ");
400                 exposedName.treePrint(depth + 1);
401             }
402
403             if (subqueryList != null)
404             {
405                 printLabel(depth, "subqueryList: ");
406                 subqueryList.treePrint(depth + 1);
407             }
408         }
409     }
410
411     /**
412      * Return the new invocation from this node.
413      *
414      * @return ResultSetNode The new invocation from this node.
415      */

416     public NewInvocationNode getNewInvocation()
417     {
418         return newInvocation;
419     }
420
421     /**
422      * Get the exposed name for this table, which is the name that can
423      * be used to refer to it in the rest of the query.
424      *
425      * @return The exposed name for this table.
426      */

427
428     public String JavaDoc getExposedName()
429     {
430         return correlationName;
431     }
432
433     /**
434      * @return the table name used for matching with column references.
435      *
436      */

437     public TableName getExposedTableName()
438     {
439         return exposedName;
440     }
441
442     /**
443      * Mark this VTI as the target of a delete or update.
444      */

445     void setTarget()
446     {
447         isTarget = true;
448         version2 = true;
449     }
450
451     /**
452      * Bind the non VTI tables in this ResultSetNode. This includes getting their
453      * descriptors from the data dictionary and numbering them.
454      *
455      * @param dataDictionary The DataDictionary to use for binding
456      * @param fromListParam FromList to use/append to.
457      *
458      * @return ResultSetNode
459      *
460      * @exception StandardException Thrown on error
461      */

462
463     public ResultSetNode bindNonVTITables(DataDictionary dataDictionary,
464                             FromList fromListParam)
465                     throws StandardException
466     {
467
468         /* Assign the tableNumber. (All other work done in bindVTITables() */
469         if (tableNumber == -1) // allow re-bind, in which case use old number
470
tableNumber = getCompilerContext().getNextTableNumber();
471         return this;
472     }
473
474     /**
475      * @return The name of the VTI, mainly for debugging and error messages.
476      */

477     String JavaDoc getVTIName()
478     {
479         return newInvocation.getJavaClassName();
480     } // end of getVTIName
481

482     /**
483      * Bind this VTI that appears in the FROM list.
484      *
485      * @param fromListParam FromList to use/append to.
486      *
487      * @return ResultSetNode The bound FromVTI.
488      *
489      * @exception StandardException Thrown on error
490      */

491
492     public ResultSetNode bindVTITables(FromList fromListParam)
493                             throws StandardException
494     {
495         ResultColumnList derivedRCL = resultColumns;
496
497         LanguageConnectionContext lcc = getLanguageConnectionContext();
498
499         /* NOTE - setting of table number moved to FromList.bindTables()
500          * in order to avoid an ordering problem with join columns in
501          * parameters.
502          */

503
504         /* Bind the constructor - does basic error checking.
505          * Correlated subqueries are not allowed as parameters to
506          * a VTI, so pass an empty FromList.
507          */

508         Vector JavaDoc aggregateVector = new Vector JavaDoc();
509         newInvocation.bindExpression(fromListParam,
510                                      subqueryList,
511                                      aggregateVector);
512
513         /* We have a valid constructor. Does class implement the correct interface?
514          * If version2 is true, then it must implement PreparedStatement, otherwise
515          * it can implement either PreparedStatement or ResultSet. (We check for
516          * PreparedStatement first.)
517          */

518
519         if (!newInvocation.assignableTo("java.sql.PreparedStatement"))
520         {
521             if (version2)
522             {
523                 throw StandardException.newException(SQLState.LANG_DOES_NOT_IMPLEMENT,
524                                         getVTIName(),
525                                         "java.sql.PreparedStatement");
526             }
527             else if (! newInvocation.assignableTo("java.sql.ResultSet"))
528             {
529                 throw StandardException.newException(SQLState.LANG_DOES_NOT_IMPLEMENT,
530                                         getVTIName(),
531                                         "java.sql.ResultSet");
532             }
533         }
534         else
535         {
536             version2 = true;
537         }
538         
539         /* If this is a version 2 VTI */
540         if (version2)
541         {
542             // Does it support predicates
543
implementsPushable = newInvocation.assignableTo("org.apache.derby.vti.IQualifyable");
544         }
545
546         // Remember whether or not the VTI implements the VTICosting interface
547
implementsVTICosting = newInvocation.assignableTo(ClassName.VTICosting);
548
549
550         // Is the parameter list to the constructor valid for a VTI?
551
methodParms = newInvocation.getMethodParms();
552
553         /* Build the RCL for this VTI. We instantiate an object in order
554          * to get the ResultSetMetaData.
555          *
556          * If we have a special trigger vti, then we branch off and get
557          * its rcl from the trigger table that is waiting for us in
558          * the compiler context.
559          */

560         UUID triggerTableId;
561         if ((triggerTableId = getSpecialTriggerVTITableName(lcc, newInvocation.getJavaClassName())) != null)
562         {
563             TableDescriptor td = getDataDictionary().getTableDescriptor(triggerTableId);
564             resultColumns = genResultColList(td);
565
566             // costing info
567
vtiCosted = true;
568             estimatedCost = 50d;
569             estimatedRowCount = 5d;
570             supportsMultipleInstantiations = true;
571         }
572         else
573         {
574             ResultSetMetaData JavaDoc rsmd = getResultSetMetaData();
575     
576             /* Wouldn't it be nice if we knew that the class/object would never
577              * return a null ResultSetMetaData.
578              */

579             if (rsmd == null)
580             {
581                 throw StandardException.newException(SQLState.LANG_NULL_RESULT_SET_META_DATA,
582                                             getVTIName());
583             }
584     
585             // Remember how many columns VTI returns for partial row calculation
586
try
587             {
588                 numVTICols = rsmd.getColumnCount();
589             }
590             catch (SQLException JavaDoc sqle)
591             {
592                 numVTICols = 0;
593             }
594
595             try
596             {
597                 for( int i = 1; i <= numVTICols; i++)
598                 {
599                     int columnType = rsmd.getColumnType(i);
600                     if( columnType == Types.BLOB || columnType == Types.CLOB)
601                         throw StandardException.newException(SQLState.LANG_VTI_BLOB_CLOB_UNSUPPORTED,
602                                                              getVTIName(), rsmd.getColumnName( i));
603                 }
604             }
605             catch( SQLException JavaDoc sqle)
606             {
607                 throw StandardException.unexpectedUserException(sqle);
608             }
609
610             resultColumns = (ResultColumnList) getNodeFactory().getNode(
611                                                 C_NodeTypes.RESULT_COLUMN_LIST,
612                                                 getContextManager());
613             resultColumns.createListFromResultSetMetaData(rsmd, exposedName,
614                                                           newInvocation.getJavaClassName());
615         }
616         numVTICols = resultColumns.size();
617     
618         /* Propagate the name info from the derived column list */
619         if (derivedRCL != null)
620         {
621              resultColumns.propagateDCLInfo(derivedRCL, correlationName);
622         }
623
624         return this;
625     }
626
627     /**
628      * Get the ResultSetMetaData for the class/object. We first look for
629      * the optional static method which has the same signature as the constructor.
630      * If it doesn't exist, then we instantiate an object and get the ResultSetMetaData
631      * from that object.
632      *
633      * @return The ResultSetMetaData from the class/object.
634      *
635      * @exception StandardException Thrown on error
636      */

637     public ResultSetMetaData JavaDoc getResultSetMetaData()
638         throws StandardException
639     {
640         // Get the actual
641
ResultSetMetaData JavaDoc rsmd = null;
642
643         try
644         {
645             if (version2)
646             {
647                 ps = (PreparedStatement JavaDoc) getNewInstance();
648
649                 if (ps.getResultSetConcurrency() != JDBC20Translation.CONCUR_UPDATABLE)
650                 {
651                     throw StandardException.newException(SQLState.LANG_UPDATABLE_VTI_NON_UPDATABLE_RS,
652                                                          getVTIName());
653                 }
654
655                 rsmd = ps.getMetaData();
656
657                 controlsDeferral = (ps instanceof DeferModification);
658
659                 /* See if the result set is known to be insensitive or not.
660                  *
661                  * Some older VTI implementations do not implement getResultSetType(). UpdatableVTITemplate
662                  * does not implement it at all. UpdatableVTITemplate.getResultSetType throws an
663                  * exception. In either of these cases make the conservative assumption that the result set is sensitive.
664                  */

665                 try
666                 {
667                     resultSetType = ps.getResultSetType();
668                 }
669                 catch( SQLException JavaDoc sqle){}
670                 catch( java.lang.AbstractMethodError JavaDoc ame){}
671                 catch( java.lang.NoSuchMethodError JavaDoc nsme){}
672                 isInsensitive = (resultSetType == ResultSet.TYPE_SCROLL_INSENSITIVE);
673
674                 if (!implementsVTICosting) {
675                     ps.close();
676                     ps = null;
677                 }
678
679             }
680             else
681             {
682                 rs = (ResultSet JavaDoc) getNewInstance();
683
684                 rsmd = rs.getMetaData();
685
686                 if (!implementsVTICosting) {
687                     rs.close();
688                     rs = null;
689                 }
690             }
691         }
692         catch(Throwable JavaDoc t)
693         {
694             throw StandardException.unexpectedUserException(t);
695         }
696
697         return rsmd;
698     }
699
700     private Object JavaDoc getNewInstance()
701         throws StandardException
702     {
703         Class JavaDoc[] paramTypeClasses = newInvocation.getMethodParameterClasses();
704         Object JavaDoc[] paramObjects = null;
705
706         if (paramTypeClasses != null)
707         {
708             paramObjects = new Object JavaDoc[paramTypeClasses.length];
709
710             for (int index = 0; index < paramTypeClasses.length; index++)
711             {
712                 Class JavaDoc paramClass = paramTypeClasses[index];
713
714                 paramObjects[index] = methodParms[index].getConstantValueAsObject();
715
716                 // As-per the JDBC spec SMALLINT and TINYINT map to java.lang.Integer
717
// as objects. This means if getConstantValueAsObject() has returned an
718
// Integer obejct in these cases, whereas Java method calling requires
719
// Short or Byte object.
720
if ((paramObjects[index] != null) && paramClass.isPrimitive()) {
721
722                     if (paramClass.equals(Short.TYPE)) {
723                         paramObjects[index] =
724                             new Short JavaDoc(((Integer JavaDoc) paramObjects[index]).shortValue());
725                     } else if (paramClass.equals(Byte.TYPE)) {
726                         paramObjects[index] =
727                             new Byte JavaDoc(((Integer JavaDoc) paramObjects[index]).byteValue());
728                     }
729                 }
730
731                 // Pass defaults for unknown primitive values
732
if (paramObjects[index] == null &&
733                     paramClass.isPrimitive())
734                 {
735                     if (paramClass.equals(Integer.TYPE))
736                     {
737                         paramObjects[index] = new Integer JavaDoc(0);
738                     }
739                     else if (paramClass.equals(Short.TYPE))
740                     {
741                         paramObjects[index] = new Short JavaDoc((short) 0);
742                     }
743                     else if (paramClass.equals(Byte.TYPE))
744                     {
745                         paramObjects[index] = new Byte JavaDoc((byte) 0);
746                     }
747                     else if (paramClass.equals(Long.TYPE))
748                     {
749                         paramObjects[index] = new Long JavaDoc((long) 0);
750                     }
751                     else if (paramClass.equals(Float.TYPE))
752                     {
753                         paramObjects[index] = new Float JavaDoc((float) 0);
754                     }
755                     else if (paramClass.equals(Double.TYPE))
756                     {
757                         paramObjects[index] = new Double JavaDoc((double) 0);
758                     }
759                     else if (paramClass.equals(Boolean.TYPE))
760                     {
761                         paramObjects[index] = Boolean.FALSE;
762                     }
763                     else if (paramClass.equals(Character.TYPE))
764                     {
765                         paramObjects[index] = new Character JavaDoc(Character.MIN_VALUE);
766                     }
767                 }
768             }
769         }
770         else
771         {
772             paramTypeClasses = new Class JavaDoc[0];
773             paramObjects = new Object JavaDoc[0];
774         }
775
776         try
777         {
778             ClassInspector classInspector = getClassFactory().getClassInspector();
779             String JavaDoc javaClassName = newInvocation.getJavaClassName();
780             Constructor JavaDoc constructor = classInspector.getClass(javaClassName).getConstructor(paramTypeClasses);
781
782             return constructor.newInstance(paramObjects);
783         }
784         catch(Throwable JavaDoc t)
785         {
786             if( t instanceof InvocationTargetException JavaDoc)
787             {
788                 InvocationTargetException JavaDoc ite = (InvocationTargetException JavaDoc) t;
789                 Throwable JavaDoc wrappedThrowable = ite.getTargetException();
790                 if( wrappedThrowable instanceof StandardException)
791                     throw (StandardException) wrappedThrowable;
792             }
793             throw StandardException.unexpectedUserException(t);
794         }
795     } // end of getNewInstance
796

797     /**
798      * Get the DeferModification interface associated with this VTI
799      *
800      * @return null if the VTI uses the default modification deferral
801      */

802     public DeferModification getDeferralControl( )
803         throws StandardException
804     {
805         if( ! controlsDeferral)
806             return null;
807         try
808         {
809             return (DeferModification) getNewInstance();
810         }
811         catch(Throwable JavaDoc t)
812         {
813             throw StandardException.unexpectedUserException(t);
814         }
815     } // end of getDeferralControl
816

817     /**
818      * @return the ResultSet type of the VTI, TYPE_FORWARD_ONLY if the getResultSetType() method
819      * of the VTI class throws an exception.
820      */

821     public int getResultSetType()
822     {
823         return resultSetType;
824     }
825
826     /**
827      * Bind the expressions in this VTI. This means
828      * binding the sub-expressions, as well as figuring out what the return
829      * type is for each expression.
830      *
831      *
832      * @exception StandardException Thrown on error
833      */

834
835     public void bindExpressions(FromList fromListParam)
836                     throws StandardException
837     {
838         ResultColumnList derivedRCL = resultColumns;
839
840         /* Figure out if the VTIs parameters are QUERY_INVARIANT. If so,
841          * then the VTI is a candidate for materialization at execution time
842          * if it is the inner table of a join or in a subquery.
843          */

844         materializable = newInvocation.areParametersQueryInvariant();
845
846         /* NOTE: We need to rebind any ColumnReferences that are parameters and are
847          * from other VTIs that appear after this one in the FROM list.
848          * These CRs will have uninitialized column and table numbers.
849          */

850         Vector JavaDoc colRefs = getNodesFromParameters(ColumnReference.class);
851         Vector JavaDoc aggregateVector = null;
852         for (Enumeration JavaDoc e = colRefs.elements(); e.hasMoreElements(); )
853         {
854             ColumnReference ref = (ColumnReference)e.nextElement();
855
856             // Rebind the CR if the tableNumber is uninitialized
857
if (ref.getTableNumber() == -1)
858             {
859                 // we need a fake agg list
860
if (aggregateVector == null)
861                 {
862                     aggregateVector = new Vector JavaDoc();
863                 }
864                 ref.bindExpression(fromListParam,
865                                     subqueryList,
866                                     aggregateVector);
867             }
868         }
869     }
870
871     /**
872      * Get all of the nodes of the specified class
873      * from the parameters to this VTI.
874      *
875      * @param nodeClass The Class of interest.
876      *
877      * @return A vector containing all of the nodes of interest.
878      *
879      * @exception StandardException Thrown on error
880      */

881     Vector JavaDoc getNodesFromParameters(Class JavaDoc nodeClass)
882         throws StandardException
883     {
884         CollectNodesVisitor getCRs = new CollectNodesVisitor(nodeClass);
885         newInvocation.accept(getCRs);
886         return getCRs.getList();
887     }
888
889     /**
890      * Expand a "*" into a ResultColumnList with all of the
891      * result columns from the subquery.
892      * @exception StandardException Thrown on error
893      */

894     public ResultColumnList getAllResultColumns(TableName allTableName)
895             throws StandardException
896     {
897         ResultColumnList rcList = null;
898         ResultColumn resultColumn;
899         ValueNode valueNode;
900         String JavaDoc columnName;
901         TableName toCompare;
902
903         if(allTableName != null)
904              toCompare = makeTableName(allTableName.getSchemaName(),correlationName);
905         else
906             toCompare = makeTableName(null,correlationName);
907
908         if ( allTableName != null &&
909              ! allTableName.equals(toCompare))
910         {
911             return null;
912         }
913
914         rcList = (ResultColumnList) getNodeFactory().getNode(
915                                         C_NodeTypes.RESULT_COLUMN_LIST,
916                                         getContextManager());
917
918         /* Build a new result column list based off of resultColumns.
919          * NOTE: This method will capture any column renaming due to
920          * a derived column list.
921          */

922         int rclSize = resultColumns.size();
923         for (int index = 0; index < rclSize; index++)
924         {
925             resultColumn = (ResultColumn) resultColumns.elementAt(index);
926
927             if (resultColumn.isGenerated())
928             {
929                 continue;
930             }
931
932             // Build a ResultColumn/ColumnReference pair for the column //
933
columnName = resultColumn.getName();
934             valueNode = (ValueNode) getNodeFactory().getNode(
935                                             C_NodeTypes.COLUMN_REFERENCE,
936                                             columnName,
937                                             exposedName,
938                                             getContextManager());
939             resultColumn = (ResultColumn) getNodeFactory().getNode(
940                                             C_NodeTypes.RESULT_COLUMN,
941                                             columnName,
942                                             valueNode,
943                                             getContextManager());
944
945             // Build the ResultColumnList to return //
946
rcList.addResultColumn(resultColumn);
947         }
948         return rcList;
949     }
950
951     /**
952      * Try to find a ResultColumn in the table represented by this FromBaseTable
953      * that matches the name in the given ColumnReference.
954      *
955      * @param columnReference The columnReference whose name we're looking
956      * for in the given table.
957      *
958      * @return A ResultColumn whose expression is the ColumnNode
959      * that matches the ColumnReference.
960      * Returns null if there is no match.
961      *
962      * @exception StandardException Thrown on error
963      */

964
965     public ResultColumn getMatchingColumn(ColumnReference columnReference) throws StandardException
966     {
967         /* We could get called before our RCL is built. That's okay, we'll
968          * just say that we don't match.
969          */

970         if (resultColumns == null)
971         {
972             return null;
973         }
974
975         ResultColumn resultColumn = null;
976         TableName columnsTableName;
977         TableName exposedTableName;
978
979         columnsTableName = columnReference.getTableNameNode();
980
981         /*
982         ** If the column did not specify a name, or the specified name
983         ** matches the table we're looking at, see whether the column
984         ** is in this table.
985         */

986         if (columnsTableName == null || columnsTableName.equals(exposedName))
987         {
988             resultColumn = resultColumns.getResultColumn(columnReference.getColumnName());
989             /* Did we find a match? */
990             if (resultColumn != null)
991             {
992                 columnReference.setTableNumber(tableNumber);
993             }
994         }
995
996         return resultColumn;
997     }
998
999     /**
1000     * Preprocess a ResultSetNode - this currently means:
1001     * o Generating a referenced table map for each ResultSetNode.
1002     * o Putting the WHERE and HAVING clauses in conjunctive normal form (CNF).
1003     * o Converting the WHERE and HAVING clauses into PredicateLists and
1004     * classifying them.
1005     * o Ensuring that a ProjectRestrictNode is generated on top of every
1006     * FromBaseTable and generated in place of every FromSubquery.
1007     * o Pushing single table predicates down to the new ProjectRestrictNodes.
1008     *
1009     * @param numTables The number of tables in the DML Statement
1010     * @param gbl The group by list, if any
1011     * @param fromList The from list, if any
1012     *
1013     * @return ResultSetNode at top of preprocessed tree.
1014     *
1015     * @exception StandardException Thrown on error
1016     */

1017
1018    public ResultSetNode preprocess(int numTables,
1019                                    GroupByList gbl,
1020                                    FromList fromList)
1021                                throws StandardException
1022    {
1023        newInvocation.preprocess(
1024                                numTables,
1025                                (FromList) getNodeFactory().getNode(
1026                                    C_NodeTypes.FROM_LIST,
1027                                    getNodeFactory().doJoinOrderOptimization(),
1028                                    getContextManager()),
1029                                 (SubqueryList) getNodeFactory().getNode(
1030                                                    C_NodeTypes.SUBQUERY_LIST,
1031                                                    getContextManager()),
1032                                 (PredicateList) getNodeFactory().getNode(
1033                                                    C_NodeTypes.PREDICATE_LIST,
1034                                                    getContextManager()));
1035        /* Generate the referenced table map */
1036        referencedTableMap = new JBitSet(numTables);
1037        referencedTableMap.set(tableNumber);
1038        newInvocation.categorize(referencedTableMap, false);
1039
1040        // Create the dependency map
1041
dependencyMap = new JBitSet(numTables);
1042        for (int index = 0; index < numTables; index++)
1043        {
1044            if ((index != tableNumber) && referencedTableMap.get(index))
1045            {
1046                dependencyMap.set(index);
1047            }
1048        }
1049
1050        // Get a JBitSet of the outer tables represented in the parameter list
1051
correlationMap = new JBitSet(numTables);
1052        newInvocation.getCorrelationTables(correlationMap);
1053
1054        return genProjectRestrict(numTables);
1055    }
1056
1057    /**
1058     * Put a ProjectRestrictNode on top of each FromTable in the FromList.
1059     * ColumnReferences must continue to point to the same ResultColumn, so
1060     * that ResultColumn must percolate up to the new PRN. However,
1061     * that ResultColumn will point to a new expression, a VirtualColumnNode,
1062     * which points to the FromTable and the ResultColumn that is the source for
1063     * the ColumnReference.
1064     * (The new PRN will have the original of the ResultColumnList and
1065     * the ResultColumns from that list. The FromTable will get shallow copies
1066     * of the ResultColumnList and its ResultColumns. ResultColumn.expression
1067     * will remain at the FromTable, with the PRN getting a new
1068     * VirtualColumnNode for each ResultColumn.expression.)
1069     * We then project out the non-referenced columns. If there are no referenced
1070     * columns, then the PRN's ResultColumnList will consist of a single ResultColumn
1071     * whose expression is 1.
1072     *
1073     * @param numTables Number of tables in the DML Statement
1074     *
1075     * @return The generated ProjectRestrictNode atop the original FromTable.
1076     *
1077     * @exception StandardException Thrown on error
1078     */

1079
1080    protected ResultSetNode genProjectRestrict(int numTables)
1081                throws StandardException
1082    {
1083        ResultColumnList prRCList;
1084
1085        /* We get a shallow copy of the ResultColumnList and its
1086         * ResultColumns. (Copy maintains ResultColumn.expression for now.)
1087         */

1088        prRCList = resultColumns;
1089        resultColumns = resultColumns.copyListAndObjects();
1090
1091        /* Replace ResultColumn.expression with new VirtualColumnNodes
1092         * in the ProjectRestrictNode's ResultColumnList. (VirtualColumnNodes include
1093         * pointers to source ResultSetNode, this, and source ResultColumn.)
1094         * NOTE: We don't want to mark the underlying RCs as referenced, otherwise
1095         * we won't be able to project out any of them.
1096         */

1097        prRCList.genVirtualColumnNodes(this, resultColumns, false);
1098
1099        /* Project out any unreferenced columns. If there are no referenced
1100         * columns, generate and bind a single ResultColumn whose expression is 1.
1101         */

1102        prRCList.doProjection();
1103
1104        /* Finally, we create the new ProjectRestrictNode */
1105        return (ResultSetNode) getNodeFactory().getNode(
1106                                C_NodeTypes.PROJECT_RESTRICT_NODE,
1107                                this,
1108                                prRCList,
1109                                null, /* Restriction */
1110                                null, /* Restriction as PredicateList */
1111                                null, /* Project subquery list */
1112                                null, /* Restrict subquery list */
1113                                tableProperties,
1114                                getContextManager() );
1115    }
1116
1117    /**
1118     * Return whether or not to materialize this ResultSet tree.
1119     *
1120     * @return Whether or not to materialize this ResultSet tree.
1121     * would return valid results.
1122     *
1123     * @exception StandardException Thrown on error
1124     */

1125    public boolean performMaterialization(JBitSet outerTables)
1126        throws StandardException
1127    {
1128        /* We need to materialize the VTI iff:
1129         * o It is an inner table.
1130         * o The VTI can be materialized.
1131         * o The VTI cannot be instantiated multiple times.
1132         * o The join strategy does not do materialization.
1133         * RESOLVE - We don't have to materialize if all of the
1134         * outer tables are 1 row tables.
1135         */

1136        return (outerTables.getFirstSetBit() != -1 &&
1137                ! outerTables.hasSingleBitSet() && // Not the outer table
1138
(! getTrulyTheBestAccessPath().
1139                    getJoinStrategy().
1140                        doesMaterialization()) && // Join strategy does not do materialization
1141
isMaterializable() && // VTI can be materialized
1142
! supportsMultipleInstantiations // VTI does not support multiple instantiations
1143
);
1144    }
1145
1146    /**
1147     * Generation on a FromVTI creates a wrapper around
1148     * the user's java.sql.ResultSet
1149     *
1150     * @param acb The ActivationClassBuilder for the class being built
1151     * @param mb The MethodBuilder for the execute() method to be built
1152     *
1153     * @exception StandardException Thrown on error
1154     */

1155    public void generate(ActivationClassBuilder acb,
1156                                MethodBuilder mb)
1157                            throws StandardException
1158    {
1159        /* NOTE: We need to remap any CRs within the parameters
1160         * so that we get their values from the right source
1161         * row. For example, if a CR is a join column, we need
1162         * to get the value from the source table and not the
1163         * join row since the join row hasn't been filled in yet.
1164         */

1165        RemapCRsVisitor rcrv = new RemapCRsVisitor(true);
1166        newInvocation.accept(rcrv);
1167
1168        /* Get the next ResultSet #, so that we can number this ResultSetNode, its
1169         * ResultColumnList and ResultSet.
1170         */

1171        assignResultSetNumber();
1172
1173        acb.pushGetResultSetFactoryExpression(mb);
1174        int nargs = getScanArguments(acb, mb);
1175        mb.callMethod(VMOpcode.INVOKEINTERFACE, (String JavaDoc) null, "getVTIResultSet",ClassName.NoPutResultSet, nargs);
1176    }
1177
1178    private int getScanArguments(ActivationClassBuilder acb,
1179                                          MethodBuilder mb)
1180        throws StandardException
1181    {
1182        int rclSize = resultColumns.size();
1183        FormatableBitSet referencedCols = new FormatableBitSet(rclSize);
1184        int erdNumber = -1;
1185        int numSet = 0;
1186
1187        // Get our final cost estimate.
1188
costEstimate = getFinalCostEstimate();
1189
1190        for (int index = 0; index < rclSize; index++)
1191        {
1192            ResultColumn rc = (ResultColumn) resultColumns.elementAt(index);
1193            if (rc.isReferenced())
1194            {
1195                referencedCols.set(index);
1196                numSet++;
1197            }
1198        }
1199
1200        // Only add referencedCols if not all columns are accessed
1201
if (numSet != numVTICols)
1202        {
1203            erdNumber = acb.addItem(referencedCols);
1204        }
1205
1206        // compileTimeConstants can be null
1207
int ctcNumber = acb.addItem(compileTimeConstants);
1208
1209        acb.pushThisAsActivation(mb); // arg 1
1210

1211        // get a function to allocate scan rows of the right shape and size
1212
resultColumns.generateHolder(acb, mb); // arg 2
1213

1214        // For a Version 2 VTI we never maintain the java.sql.PreparedStatement
1215
// from compile time to execute time. This would rquire the PreparedStatement
1216
// to be shareable across multiple connections, which is not the model for
1217
// java.sql.PreparedStatement.
1218

1219        // For a Version 2 VTI we do pass onto the ResultSet the re-useability
1220
// of the java.sql.PreparedStatement at runtime. The java.sql.PreparedStatement
1221
// is re-uesable if
1222
//
1223
// o No ? or ColumnReferences in parameters
1224

1225        boolean reuseablePs = version2 &&
1226            (getNodesFromParameters(ParameterNode.class).size() == 0) &&
1227            (getNodesFromParameters(ColumnReference.class).size() == 0);
1228
1229
1230
1231        mb.push(resultSetNumber); // arg 3
1232

1233        // The generated method for the constructor
1234
generateConstructor(acb, mb, reuseablePs); // arg 4
1235

1236        // Pass in the class name
1237
mb.push(newInvocation.getJavaClassName()); // arg 5
1238

1239        if (restrictionList != null) {
1240            restrictionList.generateQualifiers(acb, mb, this, true);
1241        }
1242        else
1243            mb.pushNull(ClassName.Qualifier + "[][]");
1244
1245        // Pass in the erdNumber for the referenced column FormatableBitSet
1246
mb.push(erdNumber); // arg 6
1247

1248        // Whether or not this is a version 2 VTI
1249
mb.push(version2);
1250
1251        mb.push(reuseablePs);
1252
1253        mb.push(ctcNumber);
1254
1255        // Whether or not this is a target VTI
1256
mb.push(isTarget);
1257
1258        // isolation level of the scan (if specified)
1259
mb.push(getCompilerContext().getScanIsolationLevel());
1260
1261        // estimated row count
1262
mb.push(costEstimate.rowCount());
1263
1264        // estimated cost
1265
mb.push(costEstimate.getEstimatedCost());
1266
1267        return 14;
1268    }
1269
1270    private void generateConstructor(ActivationClassBuilder acb,
1271                                           MethodBuilder mb, boolean reuseablePs)
1272        throws StandardException
1273    {
1274        
1275        String JavaDoc vtiType = version2 ?
1276                "java.sql.PreparedStatement" : "java.sql.ResultSet";
1277        // this sets up the method and the static field.
1278
// generates:
1279
// java.sql.ResultSet userExprFun { }
1280
MethodBuilder userExprFun = acb.newGeneratedFun(
1281                vtiType, Modifier.PUBLIC);
1282        userExprFun.addThrownException("java.lang.Exception");
1283
1284
1285        // If it's a re-useable PreparedStatement then hold onto it.
1286
LocalField psHolder = reuseablePs ? acb.newFieldDeclaration(Modifier.PRIVATE, "java.sql.PreparedStatement") : null;
1287
1288        if (reuseablePs) {
1289
1290            userExprFun.getField(psHolder);
1291            userExprFun.conditionalIfNull();
1292        }
1293
1294        newInvocation.generateExpression(acb, userExprFun);
1295        userExprFun.upCast(vtiType);
1296
1297        if (reuseablePs) {
1298
1299            userExprFun.putField(psHolder);
1300
1301            userExprFun.startElseCode();
1302
1303            userExprFun.getField(psHolder);
1304
1305            userExprFun.completeConditional();
1306        }
1307
1308        userExprFun.methodReturn();
1309
1310
1311
1312        // newInvocation knows it is returning its value;
1313

1314        /* generates:
1315         * return <newInvocation.generate(acb)>;
1316         */

1317        // we are done modifying userExprFun, complete it.
1318
userExprFun.complete();
1319
1320        // constructor is used in the final result set as an access of the new static
1321
// field holding a reference to this new method.
1322
// generates:
1323
// ActivationClass.userExprFun
1324
// which is the static field that "points" to the userExprFun
1325
// that evaluates the where clause.
1326
acb.pushMethodReference(mb, userExprFun);
1327
1328
1329        // now add in code to close the reusable PreparedStatement when
1330
// the activation is closed.
1331
if (reuseablePs) {
1332            MethodBuilder closeActivationMethod = acb.getCloseActivationMethod();
1333
1334            closeActivationMethod.getField(psHolder);
1335            closeActivationMethod.conditionalIfNull();
1336              // do nothing
1337
closeActivationMethod.push(0); // work around for no support for real if statements
1338
closeActivationMethod.startElseCode();
1339              closeActivationMethod.getField(psHolder);
1340              closeActivationMethod.callMethod(VMOpcode.INVOKEINTERFACE, "java.sql.Statement",
1341                  "close", "void", 0);
1342              closeActivationMethod.push(0);
1343
1344            closeActivationMethod.completeConditional();
1345            closeActivationMethod.endStatement();
1346        }
1347
1348    }
1349
1350    /**
1351     * Search to see if a query references the specifed table name.
1352     *
1353     * @param name Table name (String) to search for.
1354     * @param baseTable Whether or not name is for a base table
1355     *
1356     * @return true if found, else false
1357     *
1358     * @exception StandardException Thrown on error
1359     */

1360    public boolean referencesTarget(String JavaDoc name, boolean baseTable)
1361        throws StandardException
1362    {
1363        return (! baseTable) && name.equals(newInvocation.getJavaClassName());
1364    }
1365
1366    /**
1367     * Accept a visitor, and call v.visit()
1368     * on child nodes as necessary.
1369     *
1370     * @param v the visitor
1371     *
1372     * @exception StandardException on error
1373     */

1374    public Visitable accept(Visitor v)
1375        throws StandardException
1376    {
1377        if (v.skipChildren(this))
1378        {
1379            return v.visit(this);
1380        }
1381
1382        Visitable returnNode = super.accept(v);
1383
1384        if (!v.stopTraversal())
1385        {
1386            newInvocation = (NewInvocationNode) newInvocation.accept(v);
1387        }
1388
1389        return returnNode;
1390    }
1391
1392    /**
1393     * Check and see if we have a special trigger VTI.
1394     * If it cannot be bound (because we aren't actually
1395     * compiling or executing a trigger), then throw
1396     * an exception.
1397     *
1398     * @return null if not a special trigger vti, or the table
1399     * id if it is
1400     */

1401    private UUID getSpecialTriggerVTITableName(LanguageConnectionContext lcc, String JavaDoc className)
1402        throws StandardException
1403    {
1404        if (className.equals(ClassName.TriggerNewTransitionRows) ||
1405            className.equals(ClassName.TriggerOldTransitionRows))
1406        {
1407            // if there isn't an active trigger being compiled, error
1408
if (lcc.getTriggerTable() != null)
1409            {
1410                return lcc.getTriggerTable().getUUID();
1411            }
1412            else if (lcc.getTriggerExecutionContext() != null)
1413            {
1414                return lcc.getTriggerExecutionContext().getTargetTableId();
1415            }
1416            else
1417            {
1418                throw StandardException.newException(SQLState.LANG_CANNOT_BIND_TRIGGER_V_T_I, className);
1419            }
1420        }
1421        return (UUID)null;
1422    }
1423
1424    private ResultColumnList genResultColList(TableDescriptor td)
1425            throws StandardException
1426    {
1427        ResultColumnList rcList = null;
1428        ResultColumn resultColumn;
1429        ValueNode valueNode;
1430        ColumnDescriptor colDesc = null;
1431
1432
1433        TableName tableName = makeTableName(td.getSchemaName(),
1434                                            td.getName());
1435
1436        /* Add all of the columns in the table */
1437        rcList = (ResultColumnList) getNodeFactory().getNode(
1438                                        C_NodeTypes.RESULT_COLUMN_LIST,
1439                                        getContextManager());
1440        ColumnDescriptorList cdl = td.getColumnDescriptorList();
1441        int cdlSize = cdl.size();
1442
1443        for (int index = 0; index < cdlSize; index++)
1444        {
1445            /* Build a ResultColumn/BaseColumnNode pair for the column */
1446            colDesc = (ColumnDescriptor) cdl.elementAt(index);
1447
1448            valueNode = (ValueNode) getNodeFactory().getNode(
1449                                            C_NodeTypes.BASE_COLUMN_NODE,
1450                                            colDesc.getColumnName(),
1451                                            exposedName,
1452                                            colDesc.getType(),
1453                                            getContextManager());
1454            resultColumn = (ResultColumn) getNodeFactory().getNode(
1455                                            C_NodeTypes.RESULT_COLUMN,
1456                                            colDesc,
1457                                            valueNode,
1458                                            getContextManager());
1459
1460            /* Build the ResultColumnList to return */
1461            rcList.addResultColumn(resultColumn);
1462        }
1463
1464        return rcList;
1465    }
1466    
1467    public boolean needsSpecialRCLBinding()
1468    {
1469        return true;
1470    }
1471
1472    boolean isUpdatableCursor() throws StandardException {
1473        return true;
1474    }
1475
1476    protected void markUpdatableByCursor(Vector JavaDoc updateColumns) {
1477        super.markUpdatableByCursor(updateColumns);
1478        forUpdatePresent = true;
1479        emptyForUpdate = ((updateColumns == null) || (updateColumns.size() == 0));
1480    }
1481
1482    private int[] getForUpdateColumnList() {
1483
1484        int[] tempList = new int[getNumColumnsReturned()];
1485        int offset = 0;
1486
1487        for (int col = 0; col < tempList.length; col++)
1488        {
1489            if (resultColumns.updatableByCursor(col))
1490                tempList[offset++] = col + 1; // JDBC id
1491
}
1492
1493        int[] list;
1494
1495        if (offset == tempList.length)
1496            list = tempList;
1497        else {
1498            list = new int[offset];
1499            System.arraycopy(tempList, 0, list, 0, offset);
1500        }
1501
1502        return list;
1503    }
1504
1505    /*
1506    ** VTIEnvironment
1507    */

1508    public final boolean isCompileTime() {
1509        return true;
1510    }
1511
1512    public String JavaDoc getOriginalSQL() {
1513        return getCompilerContext().getParser().getSQLtext();
1514    }
1515    
1516    public final int getStatementIsolationLevel() {
1517        return ExecutionContext.CS_TO_JDBC_ISOLATION_LEVEL_MAP[getCompilerContext().getScanIsolationLevel()];
1518    }
1519
1520    public void setSharedState(String JavaDoc key, java.io.Serializable JavaDoc value) {
1521
1522        if (key == null)
1523            return;
1524
1525        if (compileTimeConstants == null)
1526            compileTimeConstants = new FormatableHashtable();
1527
1528        compileTimeConstants.put(key, value);
1529    }
1530
1531    public Object JavaDoc getSharedState(String JavaDoc key) {
1532        if ((key == null) || (compileTimeConstants == null))
1533            return null;
1534
1535        return compileTimeConstants.get(key);
1536    }
1537}
1538
Popular Tags