⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 internaltriggerexecutioncontext.java

📁 derby database source code.good for you.
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*   Derby - Class org.apache.derby.impl.sql.execute.InternalTriggerExecutionContext   Copyright 1999, 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.impl.sql.execute;import org.apache.derby.iapi.services.sanity.SanityManager;import org.apache.derby.iapi.error.PublicAPI;import org.apache.derby.iapi.db.TriggerExecutionContext;import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;import org.apache.derby.iapi.sql.ResultSet;import org.apache.derby.iapi.sql.execute.CursorResultSet;import org.apache.derby.iapi.sql.execute.ExecRow;import org.apache.derby.iapi.types.DataValueDescriptor;import org.apache.derby.iapi.sql.execute.ExecutionStmtValidator;import org.apache.derby.iapi.sql.execute.ConstantAction;import org.apache.derby.iapi.sql.dictionary.TriggerDescriptor;import org.apache.derby.iapi.error.StandardException;import org.apache.derby.iapi.services.i18n.MessageService;import org.apache.derby.iapi.reference.SQLState;import org.apache.derby.iapi.jdbc.ConnectionContext; import org.apache.derby.catalog.UUID;import java.util.Enumeration;import java.util.Vector;import java.util.Hashtable;import java.sql.Connection;import java.sql.SQLException;import java.sql.Statement;import org.apache.derby.iapi.error.ExceptionSeverity;/** * There is one of these beasts per INSERT/DELETE/UPDATE  * statement.  It fulfills the contract for the externally * visible trigger execution context and it validates * that a statement that is about to be executed doesn't * violate the restrictions placed upon what can be executed * from a trigger. * <p> * Note that it is crucial that cleanup() is called once * the DML has completed, cleanup() makes sure that users * can't do something invalid on a tec reference that they * were holding from when the trigger fired. * */public class InternalTriggerExecutionContext implements TriggerExecutionContext, ExecutionStmtValidator{	/*	** Immutable	*/	protected int[]					changedColIds;	protected String[]				changedColNames;	protected int					dmlType;	protected String				statementText;	protected ConnectionContext		cc;	protected UUID					targetTableId;	protected String				targetTableName;	protected LanguageConnectionContext lcc;	/*	** Mutable	*/	protected CursorResultSet		beforeResultSet;	protected CursorResultSet		afterResultSet;	/**	 * used exclusively for InsertResultSets which have autoincrement 	 * columns.	 */	protected ExecRow				afterRow;									protected boolean				cleanupCalled;	protected TriggerEvent			event;	protected TriggerDescriptor		triggerd;	/*	** Used to track all the result sets we have given out to	** users.  When the trigger context is no longer valid,	** we close all the result sets that may be in the user	** space because they can no longer provide meaningful	** results.	*/	private Vector	resultSetVector;	/**	 * aiCounters is a vector of AutoincrementCounters used to keep state which	 * might be used by the trigger. This is only used by Insert triggers--	 * Delete and Update triggers do not use this variable.	 * 	 * @see AutoincrementCounter	 * 	 */	private Vector aiCounters;		/**	 * aiHT is a hashtable of autincrement <key, value> pairs. This is used for	 * ai values generated by the trigger.	 */	private Hashtable aiHT;	/**	 * Build me a big old nasty trigger execution context.	 * Damnit.	 * <p>	 * About the only thing of real interest to outside observers	 * is that it pushes itself as the trigger execution context	 * in the lcc.  Be sure to call <i>cleanup()</i> when you	 * are done, or you will be flogged like the reprobate that	 * you are.	 *	 * @param lcc	the lcc	 * @param jdbcFactory	the jdbc factory	 * @param statementText	the text of the statement that caused the	 *		trigger to fire.  may be null if we are replicating	 * @param changedColIds	the list of columns that changed.  Null	 *		for all columns or INSERT/DELETE.	 * @param changedColNames	the names that correspond to changedColIds	 * @param targetTableId	the UUID of the table upon which the trigger	 *		fired	 * @param targetTableName	the name of the table upon which the trigger	 *		fired	 * @param aiCounters		A vector of AutoincrementCounters to keep state	 * 							of the ai columns in this insert trigger.a	 *	 * @exception StandardException on error	 */	public InternalTriggerExecutionContext	(		LanguageConnectionContext	lcc,		ConnectionContext			cc,		String 						statementText,		int 						dmlType,		int[]						changedColIds,		String[]					changedColNames,		UUID						targetTableId,		String						targetTableName,		Vector						aiCounters	) throws StandardException	{		this.dmlType = dmlType;		this.changedColIds = changedColIds;		this.changedColNames = changedColNames;		this.statementText = statementText;		this.cc = cc;		this.lcc = lcc;		this.targetTableId = targetTableId;		this.targetTableName = targetTableName;		this.resultSetVector = new Vector();		this.aiCounters = aiCounters;		if (SanityManager.DEBUG)		{				if ((changedColIds == null) != (changedColNames == null))			{				SanityManager.THROWASSERT("bad changed cols, "+					"(changedColsIds == null) = "+(changedColIds == null)+ 					"  (changedColsNames == null) = "+(changedColNames == null));			}			if (changedColIds != null)			{				SanityManager.ASSERT(changedColIds.length == changedColNames.length, 					"different number of changed col ids vs names");			}		}		lcc.pushTriggerExecutionContext(this);	}	void setBeforeResultSet(CursorResultSet rs)	{		beforeResultSet = rs;		}	void setAfterResultSet(CursorResultSet rs)	     throws StandardException	{		afterResultSet = rs;					if (aiCounters != null)		{			if (triggerd.isRowTrigger())			{				// An after row trigger needs to see the "first" row inserted 				rs.open();				afterRow = rs.getNextRow();				rs.close();			}			else 			{				// after statement trigger needs to look at the last value.				if (!triggerd.isBeforeTrigger())					resetAICounters(false);			}		}	}	void setCurrentTriggerEvent(TriggerEvent event)	{		this.event = event;	}	void clearCurrentTriggerEvent()	{		event = null;	}	void setTrigger(TriggerDescriptor triggerd)	{		this.triggerd = triggerd;	}		void clearTrigger() throws StandardException	{		event = null;		triggerd = null;		if (afterResultSet != null)		{			afterResultSet.close();			afterResultSet = null;		}		if (beforeResultSet != null)		{			beforeResultSet.close();			beforeResultSet = null;		}	}	/**	 * Cleanup the trigger execution context.  <B>MUST</B>	 * be called when the caller is done with the trigger	 * execution context.	 * <p>	 * We go to somewhat exaggerated lengths to free up	 * all our resources here because a user may hold on	 * to a TEC after it is valid, so we clean everything	 * up to be on the safe side.	 *	 * @exception StandardException on unexpected error	 */	protected void cleanup()		throws StandardException	{		lcc.popTriggerExecutionContext(this);		/*		** Explicitly close all result sets that we have		** given out to the user.  	 	*/		for (Enumeration e = resultSetVector.elements();			 e.hasMoreElements(); )		{			java.sql.ResultSet rs = (java.sql.ResultSet)e.nextElement();			try			{				rs.close();			} catch (SQLException se) {}		}		resultSetVector = null;			/*		** We should have already closed our underlying		** ExecResultSets by closing the jdbc result sets,		** but in case we got an error that we caught and		** ignored, explicitly close them.		*/			if (afterResultSet != null)		{			afterResultSet.close();			afterResultSet = null;		}		if (beforeResultSet != null)		{			beforeResultSet.close();			beforeResultSet = null;		}		lcc = null;		cleanupCalled = true;	}	/**	 * Make sure that the user isn't trying to get a result	 * set after we have cleaned up. 	 */	private void ensureProperContext() throws SQLException	{		if (cleanupCalled)		{			throw new SQLException(				MessageService.getTextMessage(									SQLState.LANG_STATEMENT_CLOSED_NO_REASON),									"XCL31",									ExceptionSeverity.STATEMENT_SEVERITY									);		}	}	/////////////////////////////////////////////////////////	//	// ExecutionStmtValidator	//	/////////////////////////////////////////////////////////	/**	 * Make sure that whatever statement is about to be executed	 * is ok from the context of this trigger.	 * <p>	 * Note that we are sub classed in replication for checks	 * for replication specific language.	 *	 * @param constantAction the constant action of the action	 *	that we are to validate	 *	 * @exception StandardException on error	 */	public void validateStatement(ConstantAction constantAction) throws StandardException	{		if (SanityManager.DEBUG)		{			if (constantAction instanceof DDLConstantAction)				SanityManager.THROWASSERT("DDL NOT SUPPORTED IN TRIGGER");		}		/*		** No INSERT/UPDATE/DELETE on trigger table		** for a before trigger.	 	*/		else if (triggerd.isBeforeTrigger() && 				constantAction instanceof WriteCursorConstantAction)		{			if (constantAction.modifiesTableId(targetTableId))			{				throw StandardException.newException(SQLState.LANG_NO_DML_IN_TRIGGER, triggerd.getName(), targetTableName);			}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -