KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > iapi > sql > dictionary > SPSDescriptor


1 /*
2
3    Derby - Class org.apache.derby.iapi.sql.dictionary.SPSDescriptor
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.iapi.sql.dictionary;
23
24 import org.apache.derby.iapi.services.io.StoredFormatIds;
25
26 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
27 import org.apache.derby.iapi.sql.conn.LanguageConnectionFactory;
28 import org.apache.derby.iapi.sql.conn.StatementContext;
29
30 import org.apache.derby.iapi.store.access.TransactionController;
31
32 import org.apache.derby.iapi.sql.dictionary.DataDictionary;
33 import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
34 import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
35
36 import org.apache.derby.iapi.sql.execute.ConstantAction;
37 import org.apache.derby.iapi.sql.execute.ExecutionContext;
38
39 import org.apache.derby.iapi.sql.compile.CompilerContext;
40
41 import org.apache.derby.iapi.types.DataTypeDescriptor;
42 import org.apache.derby.iapi.sql.Statement;
43 import org.apache.derby.iapi.sql.StorablePreparedStatement;
44
45 import org.apache.derby.iapi.error.StandardException;
46 import org.apache.derby.iapi.reference.SQLState;
47
48 import org.apache.derby.iapi.services.context.ContextManager;
49 import org.apache.derby.iapi.services.loader.ClassFactory;
50 import org.apache.derby.iapi.services.context.ContextService;
51 import org.apache.derby.iapi.services.monitor.Monitor;
52
53 import org.apache.derby.iapi.sql.depend.DependencyManager;
54 import org.apache.derby.iapi.sql.depend.Dependent;
55 import org.apache.derby.iapi.sql.depend.Dependency;
56 import org.apache.derby.iapi.sql.depend.Provider;
57 import org.apache.derby.iapi.sql.depend.ProviderInfo;
58
59 import org.apache.derby.iapi.types.DataValueFactory;
60
61 import org.apache.derby.iapi.sql.execute.ExecPreparedStatement;
62
63 import org.apache.derby.iapi.services.sanity.SanityManager;
64 import org.apache.derby.iapi.services.loader.GeneratedClass;
65
66 import org.apache.derby.catalog.UUID;
67 import org.apache.derby.catalog.Dependable;
68 import org.apache.derby.catalog.DependableFinder;
69 import org.apache.derby.iapi.services.uuid.UUIDFactory;
70
71 import java.util.Enumeration JavaDoc;
72 import java.util.Vector JavaDoc;
73 import java.sql.Timestamp JavaDoc;
74
75 /**
76  * A SPSDescriptor describes a Stored Prepared Statement.
77  * It correlates to a row in SYS.SYSSTATEMENTS.
78  *
79  * <B>SYNCHRONIZATION</B>: Stored prepared statements
80  * may be cached. Thus they may be shared by multiple
81  * threads. It is very hard for two threads to try
82  * to muck with an sps simultaeously because all ddl
83  * (including sps recompilation) clears out the sps
84  * cache and invalidates whatever statement held a
85  * cached sps. But it is possible for two statements
86  * to do a prepare execute statment <x> at the exact
87  * same time, so both try to do an sps.prepare() at the
88  * same time during code generation, so we synchronize
89  * most everything except getters on immutable objects
90  * just to be on the safe side.
91  *
92  *
93  * @author jamie
94  */

95 public class SPSDescriptor extends TupleDescriptor
96     implements UniqueSQLObjectDescriptor, Dependent, Provider
97 {
98     /**
99      * Statement types.
100      * <UL>
101      * <LI> SPS_TYPE_TRIGGER - trigger (<B>NOT IMPLEMENTED</B>) </LI>
102      * <LI> SPS_TYPE_EXPLAIN - explain (<B>NOT IMPLEMENTED</B>) </LI>
103      * <LI> SPS_TYPE_REGULAR - catchall</LI>
104      * </UL>
105      */

106     public static final char SPS_TYPE_TRIGGER = 'T';
107     public static final char SPS_TYPE_REGULAR = 'S';
108     public static final char SPS_TYPE_EXPLAIN = 'X';
109
110     /**
111        interface to this class is:
112        <ol>
113        <li>public void prepare() throws StandardException;
114        <li>public void prepareAndRelease(LanguageConnectionContext lcc)
115        throws StandardException;
116        <li>public void prepareAndRelease(...);
117        <li>public String getQualifiedName();
118        <li>public char getType();
119        <li>public String getTypeAsString();
120        <li>public boolean isValid();
121        <li>public boolean initiallyCompilable();
122        <li>public java.sql.Timestamp getCompileTime();
123        <li>public void setCompileTime();
124        <li>public String getText();
125        <li>public String getUsingText();
126        <li>public void setUsingText(String usingText);
127        <li>public void setUUID(UUID uuid);
128        <li>public DataTypeDescriptor[] getParams() throws StandardException;
129        <li>public void setParams(DataTypeDescriptor[] params);
130        <li>Object[] getParameterDefaults() throws StandardException;
131        <li>void setParameterDefaults(Object[] values);
132        <li>public UUID getCompSchemaId();
133        <li>public ExecPreparedStatement getPreparedStatement()
134        throws StandardException;
135        <li>public ExecPreparedStatement getPreparedStatement(boolean recompIfInvalid)
136        throws StandardException;
137        <li>public void revalidate(LanguageConnectionContext lcc)
138             throws StandardException;
139             </ol>
140     */

141
142     private static final int RECOMPILE = 1;
143     private static final int INVALIDATE = 0;
144
145         
146     // Class contents
147
private SchemaDescriptor sd;
148     private String JavaDoc name;
149     private UUID uuid;
150     private UUID compSchemaId;
151     private char type;
152     private boolean valid;
153     private String JavaDoc text;
154     private String JavaDoc usingText;
155     private ExecPreparedStatement preparedStatement;
156     private DataTypeDescriptor params[];
157     private Timestamp JavaDoc compileTime;
158     /**
159      * Old code - never used.
160      */

161     private Object JavaDoc paramDefaults[];
162     private boolean initiallyCompilable;
163     private boolean lookedUpParams;
164     
165     private UUIDFactory uuidFactory;
166
167
168     // constructors
169
/**
170      * Constructor for a SPS Descriptor
171      *
172      * @param dataDictionary The data dictionary that this descriptor lives in
173      * @param name the SPS name
174      * @param uuid the UUID
175      * @param suuid the schema UUID
176      * @param compSchemaUUID the schema UUID at compilation time
177      * @param type type
178      * @param valid is the sps valid
179      * @param text the text for this statement
180      * @param initiallyCompilable is the statement initially compilable?
181      *
182      * @exception StandardException on error
183      */

184     public SPSDescriptor
185                 (DataDictionary dataDictionary,
186                 String JavaDoc name,
187                 UUID uuid,
188                 UUID suuid,
189                 UUID compSchemaUUID,
190                 char type,
191                 boolean valid,
192                 String JavaDoc text,
193                 boolean initiallyCompilable ) throws StandardException
194     {
195         this( dataDictionary, name, uuid, suuid, compSchemaUUID,
196                 type, valid, text, (String JavaDoc) null, null, null, initiallyCompilable );
197     }
198
199     /**
200      * Constructor for a SPS Descriptor. Used when
201      * constructing an SPS descriptor from a row
202      * in SYSSTATEMENTS.
203      *
204      * @param dataDictionary The data dictionary that this descriptor lives in
205      * @param name the SPS name
206      * @param uuid the UUID
207      * @param suuid the schema UUID
208      * @param compSchemaUUID the schema UUID at compilation time
209      * @param type type
210      * @param valid is the sps valid
211      * @param text the text for this statement
212      * @param usingText the text for the USING clause supplied to
213      * CREATE or ALTER STATEMENT
214      * @param compileTime the time this was compiled
215      * @param preparedStatement the PreparedStatement
216      * @param initiallyCompilable is the statement initially compilable?
217      *
218      * @exception StandardException on error
219      */

220     public SPSDescriptor
221                 (DataDictionary dataDictionary,
222                 String JavaDoc name,
223                 UUID uuid,
224                 UUID suuid,
225                 UUID compSchemaUUID,
226                 char type,
227                 boolean valid,
228                 String JavaDoc text,
229                 String JavaDoc usingText,
230                 Timestamp JavaDoc compileTime,
231                 ExecPreparedStatement preparedStatement,
232                 boolean initiallyCompilable ) throws StandardException
233     {
234         super( dataDictionary );
235
236         this.name = name;
237         this.uuid = uuid;
238         this.type = type;
239         this.text = text;
240         this.usingText = usingText;
241         this.valid = valid;
242         this.compileTime = compileTime;
243         this.sd = dataDictionary.getSchemaDescriptor(suuid, null);
244         this.preparedStatement = preparedStatement;
245         this.compSchemaId = compSchemaUUID;
246         this.initiallyCompilable = initiallyCompilable;
247     }
248
249     /**
250      * FOR TRIGGERS ONLY
251      * <p>
252      * Generate the class for this SPS and immediately
253      * release it. This is useful for cases where we
254      * don't want to immediately execute the statement
255      * corresponding to this sps (e.g. CREATE STATEMENT).
256      * <p>
257      * <I>SIDE EFFECTS</I>: will update and SYSDEPENDS
258      * with the prepared statement dependency info.
259      *
260      * @param lcc the language connection context
261      * @param triggerTable the table descriptor to bind against. Had
262      * better be null if this isn't a trigger sps.
263      * @param tc the transaction controller
264      *
265      * @exception StandardException on error
266      */

267     public final synchronized void prepareAndRelease
268     (
269         LanguageConnectionContext lcc,
270         TableDescriptor triggerTable,
271         TransactionController tc
272     ) throws StandardException
273     {
274         if (SanityManager.DEBUG)
275         {
276             if (triggerTable != null)
277             {
278                 SanityManager.ASSERT(type == SPS_TYPE_TRIGGER, "only expect a table descriptor when we have a trigger");
279             }
280         }
281         
282         compileStatement(lcc, triggerTable, tc);
283     
284         preparedStatement.makeInvalid(DependencyManager.PREPARED_STATEMENT_RELEASE, lcc);
285     }
286     
287     /**
288      * FOR TRIGGERS ONLY
289      * <p>
290      * Generate the class for this SPS and immediately
291      * release it. This is useful for cases where we
292      * don't want to immediately execute the statement
293      * corresponding to this sps (e.g. CREATE STATEMENT).
294      * <p>
295      * <I>SIDE EFFECTS</I>: will update and SYSDEPENDS
296      * with the prepared statement dependency info.
297      *
298      * @param lcc the language connection context
299      * @param triggerTable the table descriptor to bind against. Had
300      * better be null if this isn't a trigger sps.
301      *
302      * @exception StandardException on error
303      */

304     public final synchronized void prepareAndRelease
305     (
306         LanguageConnectionContext lcc,
307         TableDescriptor triggerTable
308     ) throws StandardException
309     {
310         prepareAndRelease(lcc, triggerTable, (TransactionController)null);
311     }
312
313     /**
314      * Generate the class for this SPS and immediately
315      * release it. This is useful for cases where we
316      * don't want to immediately execute the statement
317      * corresponding to this sps (e.g. CREATE STATEMENT).
318      * <p>
319      * <I>SIDE EFFECTS</I>: will update and SYSDEPENDS
320      * with the prepared statement dependency info.
321      *
322      * @param lcc the language connection context
323      *
324      * @exception StandardException on error
325      */

326     public final synchronized void prepareAndRelease(LanguageConnectionContext lcc) throws StandardException
327     {
328         prepareAndRelease(lcc, (TableDescriptor)null, (TransactionController)null);
329     }
330
331     private void compileStatement
332     (
333         LanguageConnectionContext lcc,
334         TableDescriptor triggerTable,
335         TransactionController tc
336     )
337         throws StandardException
338     {
339         ContextManager cm = lcc.getContextManager();
340         DependencyManager dm;
341         ProviderInfo[] providerInfo;
342
343         LanguageConnectionFactory lcf = lcc.getLanguageConnectionFactory();
344
345         DataDictionary dd = getDataDictionary();
346
347
348         /*
349         ** If we are a trigger, then we have to go ahead
350         ** and locate the trigger's table descriptor and
351         ** push it on the lcc. This is expensive, but
352         ** pretty atypical since trigger actions aren't
353         ** likely to be invalidated too often. Also, when
354         ** possible, we already have the triggerTable.
355         */

356         if (type == SPS_TYPE_TRIGGER && triggerTable == null)
357         {
358             String JavaDoc uuidStr = name.substring(49);
359             triggerTable = dd.getTableDescriptor(recreateUUID(uuidStr));
360             if (SanityManager.DEBUG)
361             {
362                 if (triggerTable == null)
363                 {
364                     SanityManager.THROWASSERT("couldn't find trigger table for trigger sps "+name);
365                 }
366             }
367         }
368
369         if (triggerTable != null)
370         {
371             lcc.pushTriggerTable(triggerTable);
372         }
373
374         // stored statements always stored as unicode.
375
Statement stmt = lcf.getStatement(dd.getSchemaDescriptor(compSchemaId, null), text, true);
376
377         try
378         {
379             preparedStatement = (ExecPreparedStatement) stmt.prepareStorable(
380                                 lcc,
381                                 preparedStatement,
382                                 getParameterDefaults(),
383                                 getSchemaDescriptor(),
384                                 type == SPS_TYPE_TRIGGER);
385         }
386         finally
387         {
388             if (triggerTable != null)
389             {
390                 lcc.popTriggerTable(triggerTable);
391             }
392         }
393
394         //If this references a SESSION schema table (temporary or permanent), then throw an exception
395
//This is if EXECUTE STATEMENT executing a statement that was created with NOCOMPILE. Because
396
//of NOCOMPILE, we could not catch SESSION schema table reference by the statement at
397
//CREATE STATEMENT time. And hence need to catch such statements at EXECUTE STATEMENT time
398
//when the query is getting compiled.
399
if (preparedStatement.referencesSessionSchema())
400             throw StandardException.newException(SQLState.LANG_OPERATION_NOT_ALLOWED_ON_SESSION_SCHEMA_TABLES);
401       
402         setCompileTime();
403         setParams(preparedStatement.getParameterTypes());
404
405         if (!((org.apache.derby.impl.sql.catalog.DataDictionaryImpl) dd).readOnlyUpgrade) {
406
407             /*
408             ** Indicate that we are going to write the data
409             ** dictionary. We have probably already done this
410             ** but it is ok to call startWriting more than once.
411             */

412             dd.startWriting(lcc);
413
414             dm = dd.getDependencyManager();
415             /*
416             ** Clear out all the dependencies that exist
417             ** before we recreate them so we don't grow
418             ** SYS.SYSDEPENDS forever.
419             */

420             dm.clearDependencies(lcc, this, tc);
421
422             /*
423             ** Copy over all the dependencies to me
424             */

425             dm.copyDependencies(preparedStatement, // from
426
this, // to
427
false, // persistent only
428
cm,
429                                             tc);
430         }
431
432         // mark it as valid
433
valid = true;
434     }
435
436     /**
437      * Gets the name of the sps.
438      *
439      * @return A String containing the name of the statement.
440      */

441     public final String JavaDoc getName()
442     {
443         return name;
444     }
445
446     /**
447      * Gets the full, qualified name of the statement.
448      *
449      * @return A String containing the name of the statement.
450      */

451     public final String JavaDoc getQualifiedName()
452     {
453         return sd.getSchemaName() + "." + name;
454     }
455
456     /**
457      * Gets the SchemaDescriptor for this SPS Descriptor.
458      *
459      * @return SchemaDescriptor The SchemaDescriptor.
460      */

461     public final SchemaDescriptor getSchemaDescriptor()
462     {
463         return sd;
464     }
465
466     /**
467      * Gets an identifier telling what type of table this is.
468      * Types match final ints in this interface. Currently
469      * returns SPS_TYPE_REGULAR or SPS_TYPE_TRIGGER.
470      *
471      * @return An identifier telling what type of statement
472      * we are.
473      */

474     public final char getType()
475     {
476         return type;
477     }
478
479     /**
480      * Simple little helper function to convert your type
481      * to a string, which is easier to use.
482      *
483      * @return type as a string
484      */

485     public final String JavaDoc getTypeAsString()
486     {
487         char[] charArray = new char[1];
488         charArray[0] = type;
489         return new String JavaDoc(charArray);
490     }
491
492     /**
493      * Is the statement initially compilable?
494      *
495      * @return false if statement was created with the NOCOMPILE flag
496      * true otherwise
497      */

498     public boolean initiallyCompilable() { return initiallyCompilable; }
499     
500     /**
501      * Validate the type. <B>NOTE</B>: Only SPS_TYPE_REGULAR
502      * and SPS_TYPE_TRIGGER are currently valid.
503      *
504      * @param type the type
505      *
506      * @return true/false
507      */

508     public final static boolean validType(char type)
509     {
510         return (type == SPSDescriptor.SPS_TYPE_REGULAR) ||
511                 (type == SPSDescriptor.SPS_TYPE_TRIGGER);
512     }
513
514     /**
515      * The time this prepared statement was compiled
516      *
517      * @return the time this class was last compiled
518      */

519     public final synchronized Timestamp JavaDoc getCompileTime()
520     {
521         return compileTime;
522     }
523
524     /**
525      * Set the compile time to now
526      *
527      */

528     public final synchronized void setCompileTime()
529     {
530         compileTime = new Timestamp JavaDoc(System.currentTimeMillis());
531     }
532      
533     /**
534      * Get the text used to create this statement.
535      * Returns original text in a cleartext string.
536      *
537      * @return The text
538      */

539     public final String JavaDoc getText()
540     {
541         return text;
542     }
543
544     /**
545      * Get the text of the USING clause used on CREATE
546      * or ALTER statement.
547      *
548      * @return The text
549      */

550     public final synchronized String JavaDoc getUsingText()
551     {
552         return usingText;
553     }
554
555     /**
556      * Sets the UUID of the SPS.
557      *
558      * @param uuid The UUID of the SPS to be set in the descriptor
559      */

560     public final synchronized void setUUID(UUID uuid)
561     {
562         this.uuid = uuid;
563     }
564
565     /**
566      * Gets the UUID of the SPS.
567      *
568      * @return the uuid
569      */

570     public final UUID getUUID()
571     {
572         return uuid;
573     }
574     
575     /**
576      * Get the array of date type descriptors for
577      * this statement. Currently, we do a lookup
578      * if we don't already have the parameters saved.
579      * When SPSes are cached, the parameters should
580      * be set up when the sps is constructed.
581      *
582      * @return the array of data type descriptors
583      *
584      * @exception StandardException on error
585      */

586     public final synchronized DataTypeDescriptor[] getParams()
587         throws StandardException
588     {
589         if (params == null && !lookedUpParams)
590         {
591             Vector JavaDoc v = new Vector JavaDoc();
592             params = getDataDictionary().getSPSParams(this, v);
593             paramDefaults = new Object JavaDoc[v.size()];
594             Enumeration JavaDoc iterator = v.elements();
595             for (int i = 0; iterator.hasMoreElements(); i++)
596             {
597                 paramDefaults[i] = iterator.nextElement();
598             }
599
600             lookedUpParams = true;
601         }
602
603         return params;
604     }
605
606     /**
607      * Set the list of parameters for this statement
608      *
609      * @param params the parameter list
610      */

611     public final synchronized void setParams(DataTypeDescriptor params[])
612     {
613         this.params = params;
614     }
615
616     /**
617      * Get the default parameter values for this
618      * statement. Default parameter values are
619      * supplied by a USING clause on either a
620      * CREATE or ALTER STATEMENT statement.
621      *
622      * @return the default parameter values
623      *
624      * @exception StandardException on error
625      */

626     public final synchronized Object JavaDoc[] getParameterDefaults()
627         throws StandardException
628     {
629         if (paramDefaults == null)
630             getParams();
631
632         return paramDefaults;
633     }
634
635     /**
636      * Set the parameter defaults for this statement.
637      *
638      * @param values the parameter defaults
639      */

640     public final synchronized void setParameterDefaults(Object JavaDoc[] values)
641     {
642         this.paramDefaults = values;
643     }
644     
645     /**
646      * Get the constant action for this statement
647      *
648      * @return the constant action
649      */

650     //public final synchronized ConstantAction getConstantAction()
651
//{
652
// return preparedStatement.getConstantAction();
653
//}
654

655     /**
656      * Get the preparedStatement for this statement.
657      * If stmt is invalid or hasn't been compiled yet,
658      * it will be recompiled.
659      *
660      * @return the preparedStatement
661      *
662      * @exception StandardException on error
663      */

664     public final ExecPreparedStatement getPreparedStatement()
665         throws StandardException
666     {
667         return getPreparedStatement(true);
668     }
669
670     /**
671      * Get the preparedStatement for this statement.
672      * Expects the prepared statement to have already
673      * been added to SYS.SYSSTATEMENTS.
674      * <p>
675      * Side Effects: will update SYS.SYSSTATEMENTS with
676      * the new plan if it needs to be recompiled.
677      *
678      * @param recompIfInvalid if false, never recompile even
679      * if statement is invalid
680      *
681      * @return the preparedStatement
682      *
683      * @exception StandardException on error
684      */

685     public final synchronized ExecPreparedStatement getPreparedStatement(boolean recompIfInvalid)
686         throws StandardException
687     {
688         //System.out.println("preparedStatement = " + preparedStatement);
689
/*
690         ** Recompile if we are invalid, we don't have
691         ** a prepared statement, or the statements activation
692         ** has been cleared and cannot be reconstituted.
693         */

694         if (recompIfInvalid &&
695             (!valid ||
696              (preparedStatement == null)))
697         {
698             ContextManager cm = ContextService.getFactory().getCurrentContextManager();
699
700             /*
701             ** Find the language connection context. Get
702             ** it each time in case a connection is dropped.
703             */

704             LanguageConnectionContext lcc = (LanguageConnectionContext)
705                     cm.getContext(LanguageConnectionContext.CONTEXT_ID);
706             
707
708
709             if (!((org.apache.derby.impl.sql.catalog.DataDictionaryImpl) (lcc.getDataDictionary())).readOnlyUpgrade) {
710
711                 //bug 4821 - First try compiling on a nested transaction so we can release
712
//the locks after the compilation. But if we get lock time out on the
713
//nested transaction, then go ahead and do the compilation on the user
714
//transaction. When doing the compilation on user transaction, the locks
715
//acquired for recompilation will be released at the end of the user transaction.
716
TransactionController nestedTC;
717                 try
718                 {
719                     nestedTC = lcc.getTransactionCompile().startNestedUserTransaction(false);
720                 }
721                 catch (StandardException se)
722                 {
723                     // If I cannot start a Nested User Transaction use the parent
724
// transaction to do all the work.
725
nestedTC = null;
726                 }
727
728                 try
729                 {
730                     prepareAndRelease(lcc, null, nestedTC);
731                     updateSYSSTATEMENTS(lcc, RECOMPILE, nestedTC);
732                 }
733                 catch (StandardException se)
734                 {
735                     if (se.getMessageId().equals(SQLState.LOCK_TIMEOUT))
736                     {
737                         if (nestedTC != null)
738                         {
739                         nestedTC.commit();
740                         nestedTC.destroy();
741                         nestedTC = null;
742                         }
743                         // if we couldn't do this with a nested xaction, retry with
744
// parent-- we need to wait this time!
745
prepareAndRelease(lcc, null, null);
746                         updateSYSSTATEMENTS(lcc, RECOMPILE, null);
747                     }
748                     else throw se;
749                 }
750                 finally
751                 {
752                     // no matter what, commit the nested transaction; if something
753
// bad happened in the child xaction lets not abort the parent
754
// here.
755
if (nestedTC != null)
756                     {
757                         nestedTC.commit();
758                         nestedTC.destroy();
759                     }
760                 }
761             }
762         }
763
764         return preparedStatement;
765     }
766
767     /**
768      * Get the compilation type schema id when this view
769      * was first bound.
770      *
771      * @return the schema UUID
772      */

773     public final UUID getCompSchemaId()
774     {
775         return compSchemaId;
776     }
777
778     /**
779      * Prints the contents of the TableDescriptor
780      *
781      * @return The contents as a String
782      */

783     public final String JavaDoc toString()
784     {
785         if (SanityManager.DEBUG)
786         {
787             return "SPSDescriptor:\n"+
788                 "\tname: "+sd.getSchemaName()+"."+name+"\n"+
789                 "\tuuid: "+uuid+"\n"+
790                 "\ttext: "+text+"\n"+
791                 "\tvalid: "+((valid) ? "TRUE" : "FALSE")+"\n" +
792                 "\tpreparedStatement: "+preparedStatement+"\n";
793         }
794         else
795         {
796             return "";
797         }
798     }
799
800     //////////////////////////////////////////////////////
801
//
802
// PROVIDER INTERFACE
803
//
804
//////////////////////////////////////////////////////
805

806     /**
807      * Return the stored form of this provider
808      *
809      * @see Dependable#getDependableFinder
810      */

811     public final DependableFinder getDependableFinder()
812     {
813         return getDependableFinder(StoredFormatIds.SPS_DESCRIPTOR_FINDER_V01_ID);
814     }
815
816     /**
817      * Return the name of this Provider. (Useful for errors.)
818      *
819      * @return String The name of this provider.
820      */

821     public final String JavaDoc getObjectName()
822     {
823         return name;
824     }
825
826     /**
827      * Get the provider's UUID
828      *
829      * @return String The provider's UUID
830      */

831     public final UUID getObjectID()
832     {
833         return uuid;
834     }
835
836     /**
837      * Get the provider's type.
838      *
839      * @return String The provider's type.
840      */

841     public final String JavaDoc getClassType()
842     {
843         return Dependable.STORED_PREPARED_STATEMENT;
844     }
845
846     //////////////////////////////////////////////////////
847
//
848
// DEPENDENT INTERFACE
849
//
850
//////////////////////////////////////////////////////
851
/**
852      * Check that all of the dependent's dependencies are valid.
853      *
854      * @return true if the dependent is currently valid
855      */

856     public final synchronized boolean isValid()
857     {
858         return valid;
859     }
860
861     /**
862      * Prepare to mark the dependent as invalid (due to at least one of
863      * its dependencies being invalid).
864      *
865      * @param action The action causing the invalidation
866      * @param p the provider
867      *
868      * @exception StandardException thrown if unable to make it invalid
869      */

870     public final synchronized void prepareToInvalidate(
871                                     Provider p, int action,
872                                     LanguageConnectionContext lcc)
873         throws StandardException
874     {
875         switch (action)
876         {
877             /*
878             ** Things that don't affect us
879             */

880             case DependencyManager.CREATE_VIEW:
881     
882             /*
883             ** Things that force a recompile, but are
884             ** allowed.
885             */

886             case DependencyManager.CREATE_INDEX:
887             case DependencyManager.CREATE_CONSTRAINT:
888             case DependencyManager.DROP_CONSTRAINT:
889             case DependencyManager.DROP_INDEX:
890             case DependencyManager.DROP_TABLE:
891             case DependencyManager.DROP_VIEW:
892             case DependencyManager.DROP_METHOD_ALIAS:
893             case DependencyManager.DROP_SYNONYM:
894             case DependencyManager.ALTER_TABLE:
895             case DependencyManager.RENAME:
896             case DependencyManager.RENAME_INDEX:
897             case DependencyManager.PREPARED_STATEMENT_RELEASE:
898             case DependencyManager.USER_RECOMPILE_REQUEST:
899             case DependencyManager.CHANGED_CURSOR:
900             case DependencyManager.BULK_INSERT:
901             case DependencyManager.COMPRESS_TABLE:
902             case DependencyManager.SET_CONSTRAINTS_ENABLE:
903             case DependencyManager.SET_CONSTRAINTS_DISABLE:
904             case DependencyManager.SET_TRIGGERS_ENABLE:
905             case DependencyManager.SET_TRIGGERS_DISABLE:
906             case DependencyManager.ROLLBACK:
907             case DependencyManager.INTERNAL_RECOMPILE_REQUEST:
908             case DependencyManager.CREATE_TRIGGER:
909             case DependencyManager.DROP_TRIGGER:
910             case DependencyManager.DROP_COLUMN:
911             case DependencyManager.UPDATE_STATISTICS:
912             case DependencyManager.DROP_STATISTICS:
913             case DependencyManager.TRUNCATE_TABLE:
914                 break;
915
916             /*
917             ** The rest are errors
918             */

919             default:
920
921                 DependencyManager dm;
922
923                 dm = getDataDictionary().getDependencyManager();
924                 throw StandardException.newException(SQLState.LANG_PROVIDER_HAS_DEPENDENT_S_P_S,
925                     dm.getActionString(action),
926                     p.getObjectName(), name);
927
928         }
929     }
930
931     /**
932      * Mark the dependent as invalid (due to at least one of
933      * its dependencies being invalid).
934      *
935      * @param action The action causing the invalidation
936      *
937      * @exception StandardException thrown if unable to make it invalid
938      */

939     public final synchronized void makeInvalid(int action,
940                                                LanguageConnectionContext lcc)
941         throws StandardException
942     {
943         DependencyManager dm;
944
945         dm = getDataDictionary().getDependencyManager();
946
947         switch (action)
948         {
949             /*
950             ** Some things that don't affect stored prepared
951             ** statements.
952             */

953             case DependencyManager.PREPARED_STATEMENT_RELEASE:
954             case DependencyManager.CREATE_VIEW:
955                 break;
956
957             /*
958             ** Things that can invalidate a stored
959             ** prepared statement.
960             */

961             case DependencyManager.CREATE_INDEX:
962             case DependencyManager.CREATE_CONSTRAINT:
963             case DependencyManager.DROP_CONSTRAINT:
964             case DependencyManager.DROP_TABLE:
965             case DependencyManager.DROP_INDEX:
966             case DependencyManager.DROP_VIEW:
967             case DependencyManager.DROP_METHOD_ALIAS:
968             case DependencyManager.DROP_SYNONYM:
969             case DependencyManager.ALTER_TABLE:
970             case DependencyManager.RENAME:
971             case DependencyManager.RENAME_INDEX:
972             case DependencyManager.USER_RECOMPILE_REQUEST:
973             case DependencyManager.CHANGED_CURSOR:
974             case DependencyManager.BULK_INSERT:
975             case DependencyManager.COMPRESS_TABLE:
976             case DependencyManager.SET_CONSTRAINTS_ENABLE:
977             case DependencyManager.SET_CONSTRAINTS_DISABLE:
978             case DependencyManager.SET_TRIGGERS_ENABLE:
979             case DependencyManager.SET_TRIGGERS_DISABLE:
980             case DependencyManager.ROLLBACK:
981             case DependencyManager.INTERNAL_RECOMPILE_REQUEST:
982             case DependencyManager.CREATE_TRIGGER:
983             case DependencyManager.DROP_TRIGGER:
984             case DependencyManager.DROP_COLUMN:
985             case DependencyManager.UPDATE_STATISTICS:
986             case DependencyManager.DROP_STATISTICS:
987             case DependencyManager.TRUNCATE_TABLE:
988                 /*
989                 ** If we are already invalid, don't write ourselves
990                 ** out. Just to be safe, we'll send out an invalidate
991                 ** to our dependents either way.
992                 */

993                 if (valid == true)
994                 {
995                     valid = false;
996                     updateSYSSTATEMENTS(lcc, INVALIDATE, null);
997                 }
998                 dm.invalidateFor(this, dm.USER_RECOMPILE_REQUEST, lcc);
999                 break;
1000            case DependencyManager.DROP_SPS:
1001                //System.out.println("SPSD " + preparedStatement);
1002
dm.clearDependencies(lcc, this);
1003                break;
1004    
1005            default:
1006
1007                /*
1008                ** We should never get here, since we can't have dangling references
1009                */

1010                if (SanityManager.DEBUG)
1011                {
1012                    SanityManager.THROWASSERT("makeInvalid("+
1013                        dm.getActionString(action)+
1014                        ") not expected to get called; should have failed in "+
1015                        "prepareToInvalidate()");
1016                }
1017                break;
1018
1019        }
1020
1021    }
1022
1023    /**
1024     * Attempt to revalidate the dependent. For prepared statements,
1025     * this could go through its dependencies and check that they
1026     * are up to date; if not, it would recompile the statement.
1027     * Any failure during this attempt should throw
1028     * StandardException.unableToRevalidate().
1029     *
1030     * @exception StandardException thrown if unable to make it valid
1031     */

1032    public final synchronized void makeValid(LanguageConnectionContext lcc)
1033        throws StandardException
1034    {
1035        if (valid)
1036        {
1037            return;
1038        }
1039        prepareAndRelease(lcc);
1040
1041        updateSYSSTATEMENTS(lcc, RECOMPILE, null);
1042        
1043    }
1044
1045    /**
1046     * Invalidate and revalidate. The functional equivalent
1047     * of calling makeInvalid() and makeValid(), except it
1048     * is optimized.
1049     *
1050     * @exception StandardException on error
1051     */

1052    public final synchronized void revalidate(LanguageConnectionContext lcc)
1053        throws StandardException
1054    {
1055        /*
1056        ** Mark it as invalid first to ensure that
1057        ** we don't write SYSSTATEMENTS 2x.
1058        */

1059        valid = false;
1060        makeInvalid(DependencyManager.USER_RECOMPILE_REQUEST, lcc);
1061        prepareAndRelease(lcc);
1062        updateSYSSTATEMENTS(lcc, RECOMPILE, null);
1063    }
1064
1065    /**
1066     * Load the underlying generatd class. This is not expected
1067     * to be used outside of the datadictionary package. It
1068     * is used for optimizing class loading for sps
1069     * cacheing.
1070     *
1071     * @exception StandardException on error
1072     */

1073    public void loadGeneratedClass() throws StandardException
1074    {
1075        /*
1076        ** On upgrade, we null out the statement body,
1077        ** so handle that here.
1078        */

1079        if (preparedStatement != null)
1080        {
1081            ((StorablePreparedStatement)preparedStatement).loadGeneratedClass();
1082        }
1083    }
1084
1085    /*
1086    ** Update SYSSTATEMENTS with the changed the descriptor.
1087    ** Always done in the user XACT.
1088    ** <p>
1089    ** Ideally, the changes to SYSSTATEMENTS would be made
1090    ** in a separate xact as the current user xact, but this
1091    ** is painful (you'ld need to get a new ContextManager
1092    ** and then push all of the usual langauge contexts
1093    ** onto it and THEN call AccessManager.getTransaction()),
1094    ** and it wont work, because the xact is in a different
1095    ** compatibility space and will self deadlock (e.g.
1096    ** in the process of call DependencyManager.makeInvalid()
1097    ** we first did a DDdependableFinder.getDependable()
1098    ** which called DataDictionaryImpl.getSPSDescriptor()
1099    ** so we hold a lock on SYS.SYSSTATEMENTS by the
1100    ** time we get a 2nd xact and try to drop the statement).
1101    */

1102    private void updateSYSSTATEMENTS(LanguageConnectionContext lcc, int mode, TransactionController tc)
1103        throws StandardException
1104    {
1105        int[] colsToUpdate;
1106        boolean updateSYSCOLUMNS, recompile;
1107        //bug 4821 - we want to wait for locks if updating sysstatements on parent transaction
1108
boolean wait = false;
1109        boolean firstCompilation = false;
1110        if (mode == RECOMPILE)
1111        {
1112            recompile = true;
1113            updateSYSCOLUMNS = true;
1114            if(!initiallyCompilable)
1115            {
1116                firstCompilation = true;
1117                initiallyCompilable = true;
1118            }
1119        }
1120        else
1121        {
1122            recompile = false;
1123            updateSYSCOLUMNS = false;
1124        }
1125
1126        DataDictionary dd = getDataDictionary();
1127
1128        if (((org.apache.derby.impl.sql.catalog.DataDictionaryImpl) dd).readOnlyUpgrade)
1129            return;
1130
1131
1132        /*
1133        ** Get busy time
1134        */

1135        dd.startWriting(lcc);
1136
1137        if (tc == null) { //bug 4821 - tc will passed null if we want to use the user transaction
1138
tc = lcc.getTransactionExecute();
1139            wait = true;
1140        }
1141
1142        dd.updateSPS(this,
1143                     tc,
1144                     recompile,
1145                     updateSYSCOLUMNS,
1146                     wait,
1147                     firstCompilation);
1148    }
1149
1150    /**
1151     * Get the UUID for the given string
1152     *
1153     * @param idString the string
1154     *
1155     * @return the UUID
1156     */

1157    private UUID recreateUUID(String JavaDoc idString)
1158    {
1159        if (uuidFactory == null)
1160        {
1161            uuidFactory = Monitor.getMonitor().getUUIDFactory();
1162        }
1163        return uuidFactory.recreateUUID(idString);
1164    }
1165
1166    /** @see TupleDescriptor#getDescriptorType */
1167    public String JavaDoc getDescriptorType() { return "Statement"; }
1168
1169    /** @see TupleDescriptor#getDescriptorName */
1170    // RESOLVE: some descriptors have getName. some descriptors have
1171
// getTableName, getColumnName whatever! try and unify all of this to one
1172
// getDescriptorName!
1173
public String JavaDoc getDescriptorName() { return name; }
1174    
1175}
1176
1177
Popular Tags