📄 spsdescriptor.java
字号:
/* Derby - Class org.apache.derby.iapi.sql.dictionary.SPSDescriptor Copyright 1998, 2004 The Apache Software Foundation or its licensors, as applicable. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */package org.apache.derby.iapi.sql.dictionary;import org.apache.derby.iapi.services.io.StoredFormatIds;import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;import org.apache.derby.iapi.sql.conn.LanguageConnectionFactory;import org.apache.derby.iapi.sql.conn.StatementContext;import org.apache.derby.iapi.store.access.TransactionController;import org.apache.derby.iapi.sql.dictionary.DataDictionary;import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;import org.apache.derby.iapi.sql.dictionary.TableDescriptor;import org.apache.derby.iapi.sql.execute.ConstantAction;import org.apache.derby.iapi.sql.execute.ExecutionContext;import org.apache.derby.iapi.sql.compile.CompilerContext;import org.apache.derby.iapi.types.DataTypeDescriptor;import org.apache.derby.iapi.sql.Statement;import org.apache.derby.iapi.sql.StorablePreparedStatement;import org.apache.derby.iapi.error.StandardException;import org.apache.derby.iapi.reference.SQLState;import org.apache.derby.iapi.services.context.ContextManager;import org.apache.derby.iapi.services.loader.ClassFactory;import org.apache.derby.iapi.services.context.ContextService;import org.apache.derby.iapi.services.monitor.Monitor;import org.apache.derby.iapi.sql.depend.DependencyManager;import org.apache.derby.iapi.sql.depend.Dependent;import org.apache.derby.iapi.sql.depend.Dependency;import org.apache.derby.iapi.sql.depend.Provider;import org.apache.derby.iapi.sql.depend.ProviderInfo;import org.apache.derby.iapi.types.DataValueFactory;import org.apache.derby.iapi.sql.execute.ExecPreparedStatement;import org.apache.derby.iapi.services.sanity.SanityManager;import org.apache.derby.iapi.services.loader.GeneratedClass;import org.apache.derby.catalog.UUID;import org.apache.derby.catalog.Dependable;import org.apache.derby.catalog.DependableFinder;import org.apache.derby.iapi.services.uuid.UUIDFactory;import java.util.Enumeration;import java.util.Vector;import java.sql.Timestamp;/** * A SPSDescriptor describes a Stored Prepared Statement. * It correlates to a row in SYS.SYSSTATEMENTS. * * <B>SYNCHRONIZATION</B>: Stored prepared statements * may be cached. Thus they may be shared by multiple * threads. It is very hard for two threads to try * to muck with an sps simultaeously because all ddl * (including sps recompilation) clears out the sps * cache and invalidates whatever statement held a * cached sps. But it is possible for two statements * to do a prepare execute statment <x> at the exact * same time, so both try to do an sps.prepare() at the * same time during code generation, so we synchronize * most everything except getters on immutable objects * just to be on the safe side. * * * @author jamie */public class SPSDescriptor extends TupleDescriptor implements UniqueSQLObjectDescriptor, Dependent, Provider{ /** * Statement types. * <UL> * <LI> SPS_TYPE_TRIGGER - trigger (<B>NOT IMPLEMENTED</B>) </LI> * <LI> SPS_TYPE_EXPLAIN - explain (<B>NOT IMPLEMENTED</B>) </LI> * <LI> SPS_TYPE_REGULAR - catchall</LI> * </UL> */ public static final char SPS_TYPE_TRIGGER = 'T'; public static final char SPS_TYPE_REGULAR = 'S'; public static final char SPS_TYPE_EXPLAIN = 'X'; /** interface to this class is: <ol> <li>public void prepare() throws StandardException; <li>public void prepareAndRelease(LanguageConnectionContext lcc) throws StandardException; <li>public void prepareAndRelease(...); <li>public String getQualifiedName(); <li>public char getType(); <li>public String getTypeAsString(); <li>public boolean isValid(); <li>public boolean initiallyCompilable(); <li>public java.sql.Timestamp getCompileTime(); <li>public void setCompileTime(); <li>public String getText(); <li>public String getUsingText(); <li>public void setUsingText(String usingText); <li>public void setUUID(UUID uuid); <li>public DataTypeDescriptor[] getParams() throws StandardException; <li>public void setParams(DataTypeDescriptor[] params); <li>Object[] getParameterDefaults() throws StandardException; <li>void setParameterDefaults(Object[] values); <li>public UUID getCompSchemaId(); <li>public ExecPreparedStatement getPreparedStatement() throws StandardException; <li>public ExecPreparedStatement getPreparedStatement(boolean recompIfInvalid) throws StandardException; <li>public void revalidate(LanguageConnectionContext lcc) throws StandardException; </ol> */ private static final int RECOMPILE = 1; private static final int INVALIDATE = 0; // Class contents private SchemaDescriptor sd; private String name; private UUID uuid; private UUID compSchemaId; private char type; private boolean valid; private String text; private String usingText; private ExecPreparedStatement preparedStatement; private DataTypeDescriptor params[]; private Timestamp compileTime; private Object paramDefaults[]; private boolean initiallyCompilable; private boolean lookedUpParams; private UUIDFactory uuidFactory; // constructors /** * Constructor for a SPS Descriptor * * @param dataDictionary The data dictionary that this descriptor lives in * @param name the SPS name * @param uuid the UUID * @param suuid the schema UUID * @param compSchemaUUID the schema UUID at compilation time * @param char type * @param valid is the sps valid * @param text the text for this statement * @param usingText the text for the USING clause supplied to * CREATE or ALTER STATEMENT * @param paramDefaults default values for the parameters (if * any) in this statement. Generated by a USING * clause, for use by the optimizer. * @param initiallyCompilable is the statement initially compilable? * * @exception StandardException on error */ public SPSDescriptor (DataDictionary dataDictionary, String name, UUID uuid, UUID suuid, UUID compSchemaUUID, char type, boolean valid, String text, String usingText, Object[] paramDefaults, boolean initiallyCompilable ) throws StandardException { this( dataDictionary, name, uuid, suuid, compSchemaUUID, type, valid, text, usingText, null, null, initiallyCompilable ); this.paramDefaults = paramDefaults; } /** * Constructor for a SPS Descriptor. Used when * constructing an SPS descriptor from a row * in SYSSTATEMENTS. * * @param dataDictionary The data dictionary that this descriptor lives in * @param name the SPS name * @param uuid the UUID * @param suuid the schema UUID * @param compSchemaUUID the schema UUID at compilation time * @param char type * @param valid is the sps valid * @param text the text for this statement * @param usingText the text for the USING clause supplied to * CREATE or ALTER STATEMENT * @param compileTime the time this was compiled * @param preparedStatement the PreparedStatement * @param initiallyCompilable is the statement initially compilable? * * @exception StandardException on error */ public SPSDescriptor (DataDictionary dataDictionary, String name, UUID uuid, UUID suuid, UUID compSchemaUUID, char type, boolean valid, String text, String usingText, Timestamp compileTime, ExecPreparedStatement preparedStatement, boolean initiallyCompilable ) throws StandardException { super( dataDictionary ); this.name = name; this.uuid = uuid; this.type = type; this.text = text; this.usingText = usingText; this.valid = valid; this.compileTime = compileTime; this.sd = dataDictionary.getSchemaDescriptor(suuid, null); this.preparedStatement = preparedStatement; this.compSchemaId = compSchemaUUID; this.initiallyCompilable = initiallyCompilable; } /** * FOR TRIGGERS ONLY * <p> * Generate the class for this SPS and immediately * release it. This is useful for cases where we * don't want to immediately execute the statement * corresponding to this sps (e.g. CREATE STATEMENT). * <p> * <I>SIDE EFFECTS</I>: will update and SYSDEPENDS * with the prepared statement dependency info. * * @param lcc the language connection context * @param triggerTable the table descriptor to bind against. Had * better be null if this isn't a trigger sps. * * @exception StandardException on error */ public final synchronized void prepareAndRelease ( LanguageConnectionContext lcc, TableDescriptor triggerTable ) throws StandardException { if (SanityManager.DEBUG) { if (triggerTable != null) { SanityManager.ASSERT(type == SPS_TYPE_TRIGGER, "only expect a table descriptor when we have a trigger"); } } compileStatement(lcc, triggerTable); preparedStatement.makeInvalid(DependencyManager.PREPARED_STATEMENT_RELEASE, lcc); } /** * Generate the class for this SPS and immediately * release it. This is useful for cases where we * don't want to immediately execute the statement * corresponding to this sps (e.g. CREATE STATEMENT). * <p> * <I>SIDE EFFECTS</I>: will update and SYSDEPENDS * with the prepared statement dependency info. * * @param lcc the language connection context * * @exception StandardException on error */ public final synchronized void prepareAndRelease(LanguageConnectionContext lcc) throws StandardException { prepareAndRelease(lcc, (TableDescriptor)null); } private void compileStatement ( LanguageConnectionContext lcc, TableDescriptor triggerTable ) throws StandardException { ContextManager cm = lcc.getContextManager(); DependencyManager dm; ProviderInfo[] providerInfo; LanguageConnectionFactory lcf = lcc.getLanguageConnectionFactory(); DataDictionary dd = getDataDictionary(); /* ** If we are a trigger, then we have to go ahead ** and locate the trigger's table descriptor and ** push it on the lcc. This is expensive, but ** pretty atypical since trigger actions aren't ** likely to be invalidated too often. Also, when ** possible, we already have the triggerTable. */ if (type == SPS_TYPE_TRIGGER && triggerTable == null) { String uuidStr = name.substring(49); triggerTable = dd.getTableDescriptor(recreateUUID(uuidStr)); if (SanityManager.DEBUG) { if (triggerTable == null) { SanityManager.THROWASSERT("couldn't find trigger table for trigger sps "+name); } } } if (triggerTable != null) { lcc.pushTriggerTable(triggerTable); } // stored statements always stored as unicode. Statement stmt = lcf.getStatement(dd.getSchemaDescriptor(compSchemaId, null), text); try { preparedStatement = (ExecPreparedStatement) stmt.prepareStorable( lcc, preparedStatement, getParameterDefaults(), getSchemaDescriptor(), type == SPS_TYPE_TRIGGER); } finally { if (triggerTable != null) { lcc.popTriggerTable(triggerTable); } } //If this references a SESSION schema table (temporary or permanent), then throw an exception //This is if EXECUTE STATEMENT executing a statement that was created with NOCOMPILE. Because //of NOCOMPILE, we could not catch SESSION schema table reference by the statement at //CREATE STATEMENT time. And hence need to catch such statements at EXECUTE STATEMENT time //when the query is getting compiled. if (preparedStatement.referencesSessionSchema()) throw StandardException.newException(SQLState.LANG_OPERATION_NOT_ALLOWED_ON_SESSION_SCHEMA_TABLES); setCompileTime(); setParams(preparedStatement.getParameterTypes()); if (!((org.apache.derby.impl.sql.catalog.DataDictionaryImpl) dd).readOnlyUpgrade) { /* ** Indicate that we are going to write the data ** dictionary. We have probably already done this ** but it is ok to call startWriting more than once. */ dd.startWriting(lcc); dm = dd.getDependencyManager(); /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -