KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > impl > sql > GenericPreparedStatement


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.GenericPreparedStatement
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;
23
24 import org.apache.derby.catalog.Dependable;
25 import org.apache.derby.catalog.DependableFinder;
26
27 import org.apache.derby.iapi.services.context.ContextService;
28 import org.apache.derby.iapi.services.context.ContextManager;
29
30 import org.apache.derby.iapi.services.monitor.Monitor;
31
32 import org.apache.derby.iapi.services.sanity.SanityManager;
33
34 import org.apache.derby.iapi.services.stream.HeaderPrintWriter;
35 import org.apache.derby.iapi.services.cache.Cacheable;
36
37 import org.apache.derby.catalog.UUID;
38 import org.apache.derby.iapi.services.uuid.UUIDFactory;
39 import org.apache.derby.iapi.util.ByteArray;
40
41 import org.apache.derby.iapi.sql.dictionary.DataDictionary;
42 import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
43 import org.apache.derby.iapi.sql.dictionary.SPSDescriptor;
44
45 import org.apache.derby.iapi.sql.ParameterValueSet;
46 import org.apache.derby.iapi.sql.PreparedStatement;
47 import org.apache.derby.iapi.sql.Statement;
48 import org.apache.derby.iapi.types.DataTypeDescriptor;
49 import org.apache.derby.iapi.sql.ResultColumnDescriptor;
50 import org.apache.derby.iapi.sql.ResultDescription;
51 import org.apache.derby.iapi.sql.ResultSet;
52 import org.apache.derby.iapi.sql.Activation;
53
54 import org.apache.derby.iapi.sql.execute.ConstantAction;
55 import org.apache.derby.iapi.sql.execute.ExecCursorTableReference;
56 import org.apache.derby.iapi.sql.execute.ExecPreparedStatement;
57
58 import org.apache.derby.iapi.sql.depend.DependencyManager;
59 import org.apache.derby.iapi.sql.depend.Provider;
60
61 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
62 import org.apache.derby.iapi.sql.conn.StatementContext;
63
64 import org.apache.derby.impl.sql.compile.QueryTreeNode;
65 import org.apache.derby.impl.sql.compile.CursorNode;
66
67 import org.apache.derby.iapi.error.StandardException;
68
69 import org.apache.derby.iapi.reference.SQLState;
70
71 import org.apache.derby.iapi.services.loader.GeneratedClass;
72
73 import java.sql.Timestamp JavaDoc;
74 import java.sql.SQLWarning JavaDoc;
75 import java.util.List JavaDoc;
76
77 /**
78  * Basic implementation of prepared statement.
79  * relies on implementation of ResultDescription and Statement that
80  * are also in this package.
81  * <p>
82  * These are both dependents (of the schema objects and prepared statements
83  * they depend on) and providers. Prepared statements that are providers
84  * are cursors that end up being used in positioned delete and update
85  * statements (at present).
86  * <p>
87  * This is impl with the regular prepared statements; they will never
88  * have the cursor info fields set.
89  * <p>
90  * Stored prepared statements extend this implementation
91  *
92  * @author ames
93  */

94 public class GenericPreparedStatement
95     implements ExecPreparedStatement
96 {
97     ///////////////////////////////////////////////
98
//
99
// WARNING: when adding members to this class, be
100
// sure to do the right thing in getClone(): if
101
// it is PreparedStatement specific like finished,
102
// then it shouldn't be copied, but stuff like parameters
103
// must be copied.
104
//
105
////////////////////////////////////////////////
106

107     ////////////////////////////////////////////////
108
// STATE that is copied by getClone()
109
////////////////////////////////////////////////
110
public Statement statement;
111     protected GeneratedClass activationClass; // satisfies Activation
112
protected ResultDescription resultDesc;
113     protected DataTypeDescriptor[] paramTypeDescriptors;
114     private String JavaDoc spsName;
115     private SQLWarning JavaDoc warnings;
116
117     //If the query node for this statement references SESSION schema tables, mark it so in the boolean below
118
//This information will be used by EXECUTE STATEMENT if it is executing a statement that was created with NOCOMPILE. Because
119
//of NOCOMPILE, we could not catch SESSION schema table reference by the statement at CREATE STATEMENT time. Need to catch
120
//such statements at EXECUTE STATEMENT time when the query is getting compiled.
121
//This information will also be used to decide if the statement should be cached or not. Any statement referencing SESSION
122
//schema tables will not be cached.
123
private boolean referencesSessionSchema;
124
125     // fields used for cursors
126
protected ExecCursorTableReference targetTable;
127     protected ResultColumnDescriptor[] targetColumns;
128     protected String JavaDoc[] updateColumns;
129     protected int updateMode;
130
131     protected ConstantAction executionConstants;
132     protected Object JavaDoc[] savedObjects;
133     protected List JavaDoc requiredPermissionsList;
134
135     // fields for dependency tracking
136
protected String JavaDoc UUIDString;
137     protected UUID UUIDValue;
138
139     private boolean needsSavepoint;
140
141     private String JavaDoc execStmtName;
142     private String JavaDoc execSchemaName;
143     protected boolean isAtomic;
144     protected String JavaDoc sourceTxt;
145
146     private int inUseCount;
147
148     // true if the statement is being compiled.
149
boolean compilingStatement;
150
151
152     ////////////////////////////////////////////////
153
// STATE that is not copied by getClone()
154
////////////////////////////////////////////////
155
// fields for run time stats
156
protected long parseTime;
157     protected long bindTime;
158     protected long optimizeTime;
159     protected long generateTime;
160     protected long compileTime;
161     protected Timestamp JavaDoc beginCompileTimestamp;
162     protected Timestamp JavaDoc endCompileTimestamp;
163
164     //private boolean finished;
165
protected boolean isValid;
166     protected boolean spsAction;
167
168     // state for caching.
169
/**
170         If non-null then this object is the cacheable
171         that holds us in the cache.
172     */

173     private Cacheable cacheHolder;
174
175     //
176
// constructors
177
//
178

179     GenericPreparedStatement() {
180         /* Get the UUID for this prepared statement */
181         UUIDFactory uuidFactory =
182             Monitor.getMonitor().getUUIDFactory();
183
184         UUIDValue = uuidFactory.createUUID();
185         UUIDString = UUIDValue.toString();
186         spsAction = false;
187     }
188
189     /**
190      */

191     public GenericPreparedStatement(Statement st)
192     {
193         this();
194
195         statement = st;
196     }
197
198     //
199
// PreparedStatement interface
200
//
201
public synchronized boolean upToDate()
202         throws StandardException
203     {
204         return isValid && (activationClass != null) && !compilingStatement;
205     }
206
207     public void rePrepare(LanguageConnectionContext lcc)
208         throws StandardException {
209         if (!upToDate())
210             makeValid(lcc);
211     }
212
213     /**
214      * Get a new activation instance.
215      *
216      * @exception StandardException thrown if finished.
217      */

218     public synchronized Activation getActivation(LanguageConnectionContext lcc, boolean scrollable) throws StandardException
219     {
220         GeneratedClass gc = getActivationClass();
221
222         if (gc == null) {
223             rePrepare(lcc);
224             gc = getActivationClass();
225         }
226
227         Activation ac = new GenericActivationHolder(lcc, gc, this, scrollable);
228
229         inUseCount++;
230
231         return ac;
232     }
233
234     public ResultSet execute(LanguageConnectionContext lcc,
235                              boolean rollbackParentContext,
236                              long timeoutMillis)
237         throws StandardException
238     {
239         Activation a = getActivation(lcc, false);
240         a.setSingleExecution();
241         return execute(a, rollbackParentContext, timeoutMillis);
242     }
243
244     /**
245       * The guts of execution.
246       *
247       * @param activation the activation to run.
248       * @param rollbackParentContext True if 1) the statement context is
249       * NOT a top-level context, AND 2) in the event of a statement-level
250       * exception, the parent context needs to be rolled back, too.
251       * @param timeoutMillis timeout value in milliseconds.
252       * @return the result set to be pawed through
253       *
254       * @exception StandardException thrown on error
255       */

256
257     public ResultSet execute(Activation activation,
258                              boolean rollbackParentContext,
259                              long timeoutMillis)
260         throws
261             StandardException
262     {
263         boolean needToClearSavePoint = false;
264
265         if (activation == null || activation.getPreparedStatement() != this)
266         {
267             throw StandardException.newException(SQLState.LANG_WRONG_ACTIVATION, "execute");
268         }
269
270 recompileOutOfDatePlan:
271         while (true) {
272             // verify the activation is for me--somehow. NOTE: This is
273
// different from the above check for whether the activation is
274
// associated with the right PreparedStatement - it's conceivable
275
// that someone could construct an activation of the wrong type
276
// that points to the right PreparedStatement.
277
//
278
//SanityManager.ASSERT(activation instanceof activationClass, "executing wrong activation");
279

280             /* This is where we set and clear savepoints around each individual
281              * statement which needs one. We don't set savepoints for cursors because
282              * they're not needed and they wouldn't work in a read only database.
283              * We can't set savepoints for commit/rollback because they'll get
284              * blown away before we try to clear them.
285              */

286
287             LanguageConnectionContext lccToUse = activation.getLanguageConnectionContext();
288
289             if (lccToUse.getLogStatementText())
290             {
291                 HeaderPrintWriter istream = Monitor.getStream();
292                 String JavaDoc xactId = lccToUse.getTransactionExecute().getActiveStateTxIdString();
293                 String JavaDoc pvsString = "";
294                 ParameterValueSet pvs = activation.getParameterValueSet();
295                 if (pvs != null && pvs.getParameterCount() > 0)
296                 {
297                     pvsString = " with " + pvs.getParameterCount() +
298                             " parameters " + pvs.toString();
299                 }
300                 istream.printlnWithHeader(LanguageConnectionContext.xidStr +
301                                           xactId +
302                                           "), " +
303                                           LanguageConnectionContext.lccStr +
304                                           lccToUse.getInstanceNumber() +
305                                           "), " +
306                                           LanguageConnectionContext.dbnameStr +
307                                           lccToUse.getDbname() +
308                                           "), " +
309                                           LanguageConnectionContext.drdaStr +
310                                           lccToUse.getDrdaID() +
311                                           "), Executing prepared statement: " +
312                                           getSource() +
313                                           " :End prepared statement" +
314                                           pvsString);
315             }
316
317             ParameterValueSet pvs = activation.getParameterValueSet();
318
319             /* put it in try block to unlock the PS in any case
320              */

321             if (!spsAction) {
322             // only re-prepare if this isn't an SPS for a trigger-action;
323
// if it _is_ an SPS for a trigger action, then we can't just
324
// do a regular prepare because the statement might contain
325
// internal SQL that isn't allowed in other statements (such as a
326
// static method call to get the trigger context for retrieval
327
// of "new row" or "old row" values). So in that case we
328
// skip the call to 'rePrepare' and if the statement is out
329
// of date, we'll get a NEEDS_COMPILE exception when we try
330
// to execute. That exception will be caught by the executeSPS()
331
// method of the GenericTriggerExecutor class, and at that time
332
// the SPS action will be recompiled correctly.
333
rePrepare(lccToUse);
334             }
335
336             StatementContext statementContext = lccToUse.pushStatementContext(
337                 isAtomic, updateMode==CursorNode.READ_ONLY, getSource(), pvs, rollbackParentContext, timeoutMillis);
338
339             if (needsSavepoint())
340             {
341                 /* Mark this position in the log so that a statement
342                 * rollback will undo any changes.
343                 */

344                 statementContext.setSavePoint();
345                 needToClearSavePoint = true;
346             }
347
348             if (executionConstants != null)
349             {
350                 lccToUse.validateStmtExecution(executionConstants);
351             }
352
353             ResultSet resultSet = null;
354             try {
355     
356                 resultSet = activation.execute();
357
358                 resultSet.open();
359             } catch (StandardException se) {
360                 /* Cann't handle recompiling SPS action recompile here */
361                 if (!se.getMessageId().equals(SQLState.LANG_STATEMENT_NEEDS_RECOMPILE)
362                          || spsAction)
363                     throw se;
364                 statementContext.cleanupOnError(se);
365                 continue recompileOutOfDatePlan;
366
367             }
368
369
370             if (needToClearSavePoint)
371             {
372                 /* We're done with our updates */
373                 statementContext.clearSavePoint();
374             }
375
376             lccToUse.popStatementContext(statementContext, null);
377
378             if (activation.isSingleExecution() && resultSet.isClosed())
379             {
380                 // if the result set is 'done', i.e. not openable,
381
// then we can also release the activation.
382
// Note that a result set with output parameters
383
// or rows to return is explicitly finished
384
// by the user.
385
activation.close();
386             }
387
388             return resultSet;
389             
390         }
391     }
392
393     public ResultDescription getResultDescription() {
394         return resultDesc;
395     }
396
397     public DataTypeDescriptor[] getParameterTypes() {
398         return paramTypeDescriptors;
399     }
400
401     public String JavaDoc getSource() {
402         return (sourceTxt != null) ?
403             sourceTxt :
404             (statement == null) ?
405                 "null" :
406                 statement.getSource();
407     }
408
409     public void setSource(String JavaDoc text)
410     {
411         sourceTxt = text;
412     }
413
414     public final void setSPSName(String JavaDoc name) {
415         spsName = name;
416     }
417
418     public String JavaDoc getSPSName() {
419         return spsName;
420     }
421
422
423     /**
424      * Get the total compile time for the associated query in milliseconds.
425      * Compile time can be divided into parse, bind, optimize and generate times.
426      *
427      * @return long The total compile time for the associated query in milliseconds.
428      */

429     public long getCompileTimeInMillis()
430     {
431         return compileTime;
432     }
433
434     /**
435      * Get the parse time for the associated query in milliseconds.
436      *
437      * @return long The parse time for the associated query in milliseconds.
438      */

439     public long getParseTimeInMillis()
440     {
441         return parseTime;
442     }
443
444     /**
445      * Get the bind time for the associated query in milliseconds.
446      *
447      * @return long The bind time for the associated query in milliseconds.
448      */

449     public long getBindTimeInMillis()
450     {
451         return bindTime;
452     }
453
454     /**
455      * Get the optimize time for the associated query in milliseconds.
456      *
457      * @return long The optimize time for the associated query in milliseconds.
458      */

459     public long getOptimizeTimeInMillis()
460     {
461         return optimizeTime;
462     }
463
464     /**
465      * Get the generate time for the associated query in milliseconds.
466      *
467      * @return long The generate time for the associated query in milliseconds.
468      */

469     public long getGenerateTimeInMillis()
470     {
471         return generateTime;
472     }
473
474     /**
475      * Get the timestamp for the beginning of compilation
476      *
477      * @return Timestamp The timestamp for the beginning of compilation.
478      */

479     public Timestamp JavaDoc getBeginCompileTimestamp()
480     {
481         return beginCompileTimestamp;
482     }
483
484     /**
485      * Get the timestamp for the end of compilation
486      *
487      * @return Timestamp The timestamp for the end of compilation.
488      */

489     public Timestamp JavaDoc getEndCompileTimestamp()
490     {
491         return endCompileTimestamp;
492     }
493
494     void setCompileTimeWarnings(SQLWarning JavaDoc warnings) {
495         this.warnings = warnings;
496     }
497
498     public final SQLWarning JavaDoc getCompileTimeWarnings() {
499         return warnings;
500     }
501
502     /**
503      * Set the compile time for this prepared statement.
504      *
505      * @param compileTime The compile time
506      */

507     protected void setCompileTimeMillis(long parseTime, long bindTime,
508                                         long optimizeTime,
509                                         long generateTime,
510                                         long compileTime,
511                                         Timestamp JavaDoc beginCompileTimestamp,
512                                         Timestamp JavaDoc endCompileTimestamp)
513     {
514         this.parseTime = parseTime;
515         this.bindTime = bindTime;
516         this.optimizeTime = optimizeTime;
517         this.generateTime = generateTime;
518         this.compileTime = compileTime;
519         this.beginCompileTimestamp = beginCompileTimestamp;
520         this.endCompileTimestamp = endCompileTimestamp;
521     }
522
523
524     /**
525         Finish marks a statement as totally unusable.
526      */

527     public void finish(LanguageConnectionContext lcc) {
528
529         synchronized (this) {
530             inUseCount--;
531
532             if (cacheHolder != null)
533                 return;
534
535             if (inUseCount != 0) {
536                 //if (SanityManager.DEBUG) {
537
// if (inUseCount < 0)
538
// SanityManager.THROWASSERT("inUseCount is negative " + inUseCount + " for " + this);
539
//}
540
return;
541             }
542         }
543             
544         // invalidate any prepared statements that
545
// depended on this statement (including this one)
546
// prepareToInvalidate(this, DependencyManager.PREPARED_STATEMENT_INVALID);
547
try
548         {
549             /* NOTE: Since we are non-persistent, we "know" that no exception
550              * will be thrown under us.
551              */

552             makeInvalid(DependencyManager.PREPARED_STATEMENT_RELEASE, lcc);
553         }
554         catch (StandardException se)
555         {
556             if (SanityManager.DEBUG)
557             {
558                 se.printStackTrace(System.out);
559                 SanityManager.THROWASSERT(
560                     "Unexpected exception - " + se);
561             }
562         }
563     }
564
565     /**
566      * Set the Execution constants. This routine is called as we Prepare the
567      * statement.
568      *
569      * @param constantAction The big structure enclosing the Execution constants.
570      */

571     final void setConstantAction( ConstantAction constantAction )
572     {
573         executionConstants = constantAction;
574     }
575
576
577     /**
578      * Get the Execution constants. This routine is called at Execution time.
579      *
580      * @return ConstantAction The big structure enclosing the Execution constants.
581      */

582     public final ConstantAction getConstantAction()
583     {
584         return executionConstants;
585     }
586
587     /**
588      * Set the saved objects. Called when compilation completes.
589      *
590      * @param objects The objects to save from compilation
591      */

592     final void setSavedObjects( Object JavaDoc[] objects )
593     {
594         savedObjects = objects;
595     }
596
597     /**
598      * Get the specified saved object.
599      *
600      * @param objectNum The object to get.
601      * @return the requested saved object.
602      */

603     public final Object JavaDoc getSavedObject(int objectNum)
604     {
605         if (SanityManager.DEBUG) {
606             if (!(objectNum>=0 && objectNum<savedObjects.length))
607             SanityManager.THROWASSERT(
608                 "request for savedObject entry "+objectNum+" invalid; "+
609                 "savedObjects has "+savedObjects.length+" entries");
610         }
611         return savedObjects[objectNum];
612     }
613
614     /**
615      * Get the saved objects.
616      *
617      * @return all the saved objects
618      */

619     public final Object JavaDoc[] getSavedObjects()
620     {
621         return savedObjects;
622     }
623
624     //
625
// Dependent interface
626
//
627
/**
628         Check that all of the dependent's dependencies are valid.
629
630         @return true if the dependent is currently valid
631      */

632     public boolean isValid() {
633         return isValid;
634     }
635
636     /**
637      * set this prepared statement to be valid, currently used by
638      * GenericTriggerExecutor.
639      */

640     public void setValid()
641     {
642         isValid = true;
643     }
644
645     /**
646      * Indicate this prepared statement is an SPS action, currently used
647      * by GenericTriggerExecutor.
648      */

649     public void setSPSAction()
650     {
651         spsAction = true;
652     }
653
654     /**
655         Prepare to mark the dependent as invalid (due to at least one of
656         its dependencies being invalid).
657
658         @param action The action causing the invalidation
659         @param p the provider
660
661         @exception StandardException thrown if unable to make it invalid
662      */

663     public void prepareToInvalidate(Provider p, int action,
664                                     LanguageConnectionContext lcc)
665         throws StandardException {
666
667         /*
668             this statement can have other open result sets
669             if another one is closing without any problems.
670
671             It is not a problem to create an index when there is an open
672             result set, since it doesn't invalidate the access path that was
673             chosen for the result set.
674         */

675         switch (action) {
676         case DependencyManager.CHANGED_CURSOR:
677         case DependencyManager.CREATE_INDEX:
678             return;
679         }
680
681         /* Verify that there are no activations with open result sets
682          * on this prepared statement.
683          */

684         lcc.verifyNoOpenResultSets(this, p, action);
685     }
686
687
688     /**
689         Mark the dependent as invalid (due to at least one of
690         its dependencies being invalid).
691
692         @param action The action causing the invalidation
693
694         @exception StandardException Standard Cloudscape error policy.
695      */

696     public void makeInvalid(int action, LanguageConnectionContext lcc)
697          throws StandardException
698     {
699
700         boolean alreadyInvalid;
701         
702         synchronized (this) {
703
704             if (compilingStatement)
705                 return;
706
707             alreadyInvalid = !isValid;
708         
709             // make ourseleves invalid
710
isValid = false;
711
712             // block compiles while we are invalidating
713
compilingStatement = true;
714         }
715
716         try {
717
718             DependencyManager dm = lcc.getDataDictionary().getDependencyManager();
719
720             if (!alreadyInvalid)
721             {
722                 dm.invalidateFor(this, action, lcc);
723             }
724
725             /* Clear out the old dependencies on this statement as we
726              * will build the new set during the reprepare in makeValid().
727              */

728             dm.clearDependencies(lcc, this);
729
730             /*
731             ** If we are invalidating an EXECUTE STATEMENT because of a stale
732             ** plan, we also need to invalidate the stored prepared statement.
733             */

734             if (execStmtName != null) {
735                 switch (action) {
736                 case DependencyManager.INTERNAL_RECOMPILE_REQUEST:
737                 case DependencyManager.CHANGED_CURSOR:
738                 {
739                     /*
740                     ** Get the DataDictionary, so we can get the descriptor for
741                     ** the SPP to invalidate it.
742                     */

743                     DataDictionary dd = lcc.getDataDictionary();
744                         
745                     SchemaDescriptor sd = dd.getSchemaDescriptor(execSchemaName, lcc.getTransactionCompile(), true);
746                     SPSDescriptor spsd = dd.getSPSDescriptor(execStmtName, sd);
747                     spsd.makeInvalid(action, lcc);
748                     break;
749                 }
750                 }
751             }
752         } finally {
753             synchronized (this) {
754                 compilingStatement = false;
755                 notifyAll();
756             }
757         }
758     }
759
760     /**
761         Attempt to revalidate the dependent. For prepared statements,
762         this could go through its dependencies and check that they
763         are up to date; if not, it would recompile the statement.
764         Any failure during this attempt should throw
765         StandardException.unableToRevalidate().
766
767         @exception StandardException thrown if unable to make it valid
768      */

769     public void makeValid(LanguageConnectionContext lcc)
770         throws StandardException
771     {
772         PreparedStatement ps;
773
774         // REMIND: will want to go through dependency list
775
// and check if we can make it valid just on faith,
776
// i.e. when it was marked 'possibly invalid' due
777
// to a rollback or some similar action.
778

779         // this ends up calling makeValid(qt, ac) below:
780
ps = statement.prepare(lcc);
781         if (SanityManager.DEBUG)
782             SanityManager.ASSERT(ps == this, "ps != this");
783     }
784
785     /**
786      * Is this dependent persistent? A stored dependency will be required
787      * if both the dependent and provider are persistent.
788      *
789      * @return boolean Whether or not this dependent is persistent.
790      */

791     public boolean isPersistent()
792     {
793         /* Non-stored prepared statements are not persistent */
794         return false;
795     }
796
797     //
798
// Dependable interface
799
//
800

801     /**
802         @return the stored form of this Dependable
803
804         @see Dependable#getDependableFinder
805      */

806     public DependableFinder getDependableFinder()
807     {
808         return null;
809     }
810
811     /**
812      * Return the name of this Dependable. (Useful for errors.)
813      *
814      * @return String The name of this Dependable..
815      */

816     public String JavaDoc getObjectName()
817     {
818         return UUIDString;
819     }
820
821     /**
822      * Get the Dependable's UUID String.
823      *
824      * @return String The Dependable's UUID String.
825      */

826     public UUID getObjectID()
827     {
828         return UUIDValue;
829     }
830
831     /**
832      * Get the Dependable's class type.
833      *
834      * @return String Classname that this Dependable belongs to.
835      */

836     public String JavaDoc getClassType()
837     {
838         return Dependable.PREPARED_STATEMENT;
839     }
840
841     /**
842      * Return true if the query node for this statement references SESSION schema
843      * tables/views.
844      * This method gets called at the very beginning of the compile phase of any statement.
845      * If the statement which needs to be compiled is already found in cache, then there is
846      * no need to compile it again except the case when the statement is referencing SESSION
847      * schema objects. There is a small window where such a statement might get cached
848      * temporarily (a statement referencing SESSION schema object will be removed from the
849      * cache after the bind phase is over because that is when we know for sure that the
850      * statement is referencing SESSION schema objects.)
851      *
852      * @return true if references SESSION schema tables, else false
853      */

854     public boolean referencesSessionSchema()
855     {
856         return referencesSessionSchema;
857     }
858     
859     /**
860      * Return true if the QueryTreeNode references SESSION schema tables/views.
861      * The return value is also saved in the local field because it will be
862      * used by referencesSessionSchema() method.
863      * This method gets called when the statement is not found in cache and
864      * hence it is getting compiled.
865      * At the beginning of compilation for any statement, first we check if
866      * the statement's plan already exist in the cache. If not, then we add
867      * the statement to the cache and continue with the parsing and binding.
868      * At the end of the binding, this method gets called to see if the
869      * QueryTreeNode references a SESSION schema object. If it does, then
870      * we want to remove it from the cache, since any statements referencing
871      * SESSION schema objects should never get cached.
872      *
873      * @return true if references SESSION schema tables/views, else false
874      */

875     public boolean referencesSessionSchema(QueryTreeNode qt)
876     throws StandardException {
877         //If the query references a SESSION schema table (temporary or permanent), then
878
// mark so in this statement
879
referencesSessionSchema = qt.referencesSessionSchema();
880         return(referencesSessionSchema);
881     }
882
883     //
884
// class interface
885
//
886

887     /**
888         Makes the prepared statement valid, assigning
889         values for its query tree, generated class,
890         and associated information.
891
892         @param qt the query tree for this statement
893
894         @exception StandardException thrown on failure.
895      */

896     void completeCompile(QueryTreeNode qt)
897                         throws StandardException {
898         //if (finished)
899
// throw StandardException.newException(SQLState.LANG_STATEMENT_CLOSED, "completeCompile()");
900

901         paramTypeDescriptors = qt.getParameterTypes();
902
903         // erase cursor info in case statement text changed
904
if (targetTable!=null) {
905             targetTable = null;
906             updateMode = 0;
907             updateColumns = null;
908             targetColumns = null;
909         }
910
911         // get the result description (null for non-cursor statements)
912
// would we want to reuse an old resultDesc?
913
// or do we need to always replace in case this was select *?
914
resultDesc = qt.makeResultDescription();
915
916         // would look at resultDesc.getStatementType() but it
917
// doesn't call out cursors as such, so we check
918
// the root node type instead.
919

920         if (resultDesc != null)
921         {
922             /*
923                 For cursors, we carry around some extra information.
924              */

925             CursorInfo cursorInfo = (CursorInfo)qt.getCursorInfo();
926             if (cursorInfo != null)
927             {
928                 targetTable = cursorInfo.targetTable;
929                 targetColumns = cursorInfo.targetColumns;
930                 updateColumns = cursorInfo.updateColumns;
931                 updateMode = cursorInfo.updateMode;
932             }
933         }
934         isValid = true;
935
936         return;
937     }
938
939     public GeneratedClass getActivationClass()
940         throws StandardException
941     {
942         return activationClass;
943     }
944
945     void setActivationClass(GeneratedClass ac)
946     {
947         activationClass = ac;
948     }
949
950     //
951
// ExecPreparedStatement
952
//
953

954     /**
955      * the update mode of the cursor
956      *
957      * @return The update mode of the cursor
958      */

959     public int getUpdateMode() {
960         return updateMode;
961     }
962
963     /**
964      * the target table of the cursor
965      *
966      * @return target table of the cursor
967      */

968     public ExecCursorTableReference getTargetTable()
969     {
970         if (SanityManager.DEBUG)
971         {
972             SanityManager.ASSERT(targetTable!=null, "Not a cursor, no target table");
973         }
974         return targetTable;
975     }
976
977     /**
978      * the target columns of the cursor as a result column list
979      *
980      * @return target columns of the cursor as a result column list
981      */

982     public ResultColumnDescriptor[] getTargetColumns() {
983         return targetColumns;
984     }
985
986     /**
987      * the update columns of the cursor as a update column list
988      *
989      * @return update columns of the cursor as a array of strings
990      */

991     public String JavaDoc[] getUpdateColumns()
992     {
993         return updateColumns;
994     }
995
996     /**
997      * Return the cursor info in a single chunk. Used
998      * by StrorablePreparedStatement
999      */

1000    public Object JavaDoc getCursorInfo()
1001    {
1002        return new CursorInfo(
1003            updateMode,
1004            targetTable,
1005            targetColumns,
1006            updateColumns);
1007    }
1008
1009    void setCursorInfo(CursorInfo cursorInfo)
1010    {
1011        if (cursorInfo != null)
1012        {
1013            updateMode = cursorInfo.updateMode;
1014            targetTable = cursorInfo.targetTable;
1015            targetColumns = cursorInfo.targetColumns;
1016            updateColumns = cursorInfo.updateColumns;
1017        }
1018    }
1019
1020
1021    //
1022
// class implementation
1023
//
1024

1025    /**
1026     * Get the byte code saver for this statement.
1027     * Overridden for StorablePreparedStatement. We
1028     * don't want to save anything
1029     *
1030     * @return a byte code saver (null for us)
1031     */

1032    ByteArray getByteCodeSaver()
1033    {
1034        return null;
1035    }
1036
1037    /**
1038     * Does this statement need a savepoint?
1039     *
1040     * @return true if this statement needs a savepoint.
1041     */

1042    public boolean needsSavepoint()
1043    {
1044        return needsSavepoint;
1045    }
1046
1047    /**
1048     * Set the stmts 'needsSavepoint' state. Used
1049     * by an SPS to convey whether the underlying stmt
1050     * needs a savepoint or not.
1051     *
1052     * @param needsSavepoint true if this statement needs a savepoint.
1053     */

1054    void setNeedsSavepoint(boolean needsSavepoint)
1055    {
1056        this.needsSavepoint = needsSavepoint;
1057    }
1058
1059    /**
1060     * Set the stmts 'isAtomic' state.
1061     *
1062     * @param isAtomic true if this statement must be atomic
1063     * (i.e. it is not ok to do a commit/rollback in the middle)
1064     */

1065    void setIsAtomic(boolean isAtomic)
1066    {
1067        this.isAtomic = isAtomic;
1068    }
1069
1070    /**
1071     * Returns whether or not this Statement requires should
1072     * behave atomically -- i.e. whether a user is permitted
1073     * to do a commit/rollback during the execution of this
1074     * statement.
1075     *
1076     * @return boolean Whether or not this Statement is atomic
1077     */

1078    public boolean isAtomic()
1079    {
1080        return isAtomic;
1081    }
1082
1083    /**
1084     * Set the name of the statement and schema for an "execute statement"
1085     * command.
1086     */

1087    void setExecuteStatementNameAndSchema(String JavaDoc execStmtName,
1088                                                 String JavaDoc execSchemaName)
1089    {
1090        this.execStmtName = execStmtName;
1091        this.execSchemaName = execSchemaName;
1092    }
1093
1094    /**
1095     * Get a new prepared statement that is a shallow copy
1096     * of the current one.
1097     *
1098     * @return a new prepared statement
1099     *
1100     * @exception StandardException on error
1101     */

1102    public ExecPreparedStatement getClone() throws StandardException
1103    {
1104
1105        GenericPreparedStatement clone = new GenericPreparedStatement(statement);
1106
1107        clone.activationClass = getActivationClass();
1108        clone.resultDesc = resultDesc;
1109        clone.paramTypeDescriptors = paramTypeDescriptors;
1110        clone.executionConstants = executionConstants;
1111        clone.UUIDString = UUIDString;
1112        clone.UUIDValue = UUIDValue;
1113        clone.savedObjects = savedObjects;
1114        clone.execStmtName = execStmtName;
1115        clone.execSchemaName = execSchemaName;
1116        clone.isAtomic = isAtomic;
1117        clone.sourceTxt = sourceTxt;
1118        clone.targetTable = targetTable;
1119        clone.targetColumns = targetColumns;
1120        clone.updateColumns = updateColumns;
1121        clone.updateMode = updateMode;
1122        clone.needsSavepoint = needsSavepoint;
1123
1124        return clone;
1125    }
1126
1127    // cache holder stuff.
1128
public void setCacheHolder(Cacheable cacheHolder) {
1129
1130        this.cacheHolder = cacheHolder;
1131
1132        if (cacheHolder == null) {
1133
1134            // need to invalidate the statement
1135
if (!isValid || (inUseCount != 0))
1136                return;
1137
1138            ContextManager cm = ContextService.getFactory().getCurrentContextManager();
1139            LanguageConnectionContext lcc =
1140                (LanguageConnectionContext)
1141                (cm.getContext(LanguageConnectionContext.CONTEXT_ID));
1142
1143            // invalidate any prepared statements that
1144
// depended on this statement (including this one)
1145
// prepareToInvalidate(this, DependencyManager.PREPARED_STATEMENT_INVALID);
1146
try
1147            {
1148                /* NOTE: Since we are non-persistent, we "know" that no exception
1149                 * will be thrown under us.
1150                 */

1151                makeInvalid(DependencyManager.PREPARED_STATEMENT_RELEASE, lcc);
1152            }
1153            catch (StandardException se)
1154            {
1155                if (SanityManager.DEBUG)
1156                {
1157                    se.printStackTrace(System.out);
1158                    SanityManager.THROWASSERT(
1159                        "Unexpected exception - " + se);
1160                }
1161            }
1162        }
1163    }
1164
1165    public String JavaDoc toString() {
1166        return getObjectName();
1167    }
1168
1169    public boolean isStorable() {
1170        return false;
1171    }
1172
1173    public void setRequiredPermissionsList( List JavaDoc requiredPermissionsList)
1174    {
1175        this.requiredPermissionsList = requiredPermissionsList;
1176    }
1177
1178    public List JavaDoc getRequiredPermissionsList()
1179    {
1180        return requiredPermissionsList;
1181    }
1182}
1183
Popular Tags