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

📄 ddutils.java

📁 derby database source code.good for you.
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*   Derby - Class org.apache.derby.iapi.sql.dictionary.DDUtils   Copyright 2000, 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.error.StandardException;import org.apache.derby.iapi.reference.SQLState;import org.apache.derby.iapi.sql.StatementType;import java.util.Hashtable;import org.apache.derby.iapi.services.sanity.SanityManager;import org.apache.derby.iapi.services.i18n.MessageService;import java.util.Enumeration;/** *	Static Data dictionary utilities. * * @version 0.1 * @author Rick Hillegas */public	class	DDUtils{	/*	** For a foreign key, this is used to locate the referenced	** key using the ConstraintInfo.  If it doesn't find the	** correct constraint it will throw an error.	*/	public	static ReferencedKeyConstraintDescriptor locateReferencedConstraint	(		DataDictionary	dd,		TableDescriptor	td,		String			myConstraintName,	// for error messages		String[]		myColumnNames,		ConsInfo		otherConstraintInfo	)		throws StandardException	{		TableDescriptor refTd = otherConstraintInfo.getReferencedTableDescriptor(dd);		if (refTd == null)		{				throw StandardException.newException(SQLState.LANG_INVALID_FK_NO_REF_TAB, 												myConstraintName, 												otherConstraintInfo.getReferencedTableName());		}		ReferencedKeyConstraintDescriptor refCd = null;		/*		** There were no column names specified, just find		** the primary key on the table in question		*/		String[]	refColumnNames = otherConstraintInfo.getReferencedColumnNames();		if (refColumnNames == null ||			refColumnNames.length == 0)		{			refCd = refTd.getPrimaryKey();			if (refCd == null)			{				throw StandardException.newException(SQLState.LANG_INVALID_FK_NO_PK, 												myConstraintName, 												refTd.getQualifiedName());			}			ColumnDescriptorList cdl = getColumnDescriptors(dd, td, myColumnNames);			/*			** Check the column list length to give a more informative			** error in case they aren't the same.			*/			if (cdl.size() != refCd.getColumnDescriptors().size())			{				throw StandardException.newException(SQLState.LANG_INVALID_FK_DIFFERENT_COL_COUNT, 												myConstraintName, String.valueOf(cdl.size()), 												String.valueOf(refCd.getColumnDescriptors().size())); 			}				/*			** Make sure all types are the same.			*/				if (!refCd.areColumnsComparable(cdl))			{				throw StandardException.newException(SQLState.LANG_INVALID_FK_COL_TYPES_DO_NOT_MATCH, 												myConstraintName);			}			return refCd;			}		/*		** Check the referenced columns vs. each unique or primary key to		** see if they match the foreign key.		*/		else		{			ConstraintDescriptor cd;			ColumnDescriptorList colDl = getColumnDescriptors(dd, td, myColumnNames);			ConstraintDescriptorList refCDL = dd.getConstraintDescriptors(refTd);			int refCDLSize = refCDL.size();			for (int index = 0; index < refCDLSize; index++)			{				cd = refCDL.elementAt(index);				/*				** Matches if it is not a check or fk, and				** all the types line up.				*/				if ((cd instanceof ReferencedKeyConstraintDescriptor) &&					 cd.areColumnsComparable(colDl) &&					 columnNamesMatch(refColumnNames, 										cd.getColumnDescriptors()))				{					return (ReferencedKeyConstraintDescriptor)cd;				}			}			/*			** If we got here, we didn't find anything			*/			throw StandardException.newException(SQLState.LANG_INVALID_FK_NO_REF_KEY, myConstraintName, 														refTd.getQualifiedName());		}	}    public	static ColumnDescriptorList getColumnDescriptors	(		DataDictionary	dd,		TableDescriptor td,		String[] 		columnNames	)		throws StandardException	{		ColumnDescriptorList cdl = new ColumnDescriptorList();		for (int colCtr = 0; colCtr < columnNames.length; colCtr++)		{			ColumnDescriptor cd = td.getColumnDescriptor(columnNames[colCtr]);			cdl.add(td.getUUID(), cd);		}		return cdl;	}	public	static boolean columnNamesMatch(String []columnNames, ColumnDescriptorList cdl)		throws StandardException	{		if (columnNames.length != cdl.size())		{			return false;		}				String name;		for (int index = 0; index < columnNames.length; index++)		{			name = ((ColumnDescriptor) cdl.elementAt(index)).getColumnName();			if (!name.equals(columnNames[index]))			{				return false;			}		}		return true;	}	/*	**checks whether the foreign key relation ships referential action	**is violating the restrictions we have in the current system.	**/	public static void validateReferentialActions    (		DataDictionary	dd,		TableDescriptor	td,		String			myConstraintName,	// for error messages		ConsInfo		otherConstraintInfo,		String[]        columnNames	)		throws StandardException	{		int refAction = otherConstraintInfo.getReferentialActionDeleteRule();		//Do not allow ON DELETE SET NULL as a referential action 		//if none of the foreign key columns are  nullable.		if(refAction == StatementType.RA_SETNULL)		{			boolean foundNullableColumn = false;			//check if we have a nullable foreign key column			for (int colCtr = 0; colCtr < columnNames.length; colCtr++)			{				ColumnDescriptor cd = td.getColumnDescriptor(columnNames[colCtr]);				if ((cd.getType().isNullable()))				{					foundNullableColumn = true;					break;				}			}			if(!foundNullableColumn)			{				throw StandardException.newException(SQLState.LANG_INVALID_FK_COL_FOR_SETNULL, 													 myConstraintName);			}		}		//check whether the foreign key relation ships referential action		//is not violating the restrictions we have in the current system.		TableDescriptor refTd = otherConstraintInfo.getReferencedTableDescriptor(dd);		Hashtable deleteConnHashtable = new Hashtable();		//find whether the foreign key is self referencing.		boolean isSelfReferencingFk = (refTd.getUUID().equals(td.getUUID()));		String refTableName = refTd.getSchemaName() + "." + refTd.getName();		//look for the other foreign key constraints on this table first		int currentSelfRefValue = getCurrentDeleteConnections(dd, td, -1, deleteConnHashtable, false, true);		validateDeleteConnection(dd, td, refTd, 								 refAction, 								 deleteConnHashtable, (Hashtable) deleteConnHashtable.clone(),								 true, myConstraintName, false , 								 new StringBuffer(0), refTableName,								 isSelfReferencingFk,								 currentSelfRefValue);		//if it not a selfreferencing key check for violation of exiting connections.		if(!isSelfReferencingFk)		{			checkForAnyExistingDeleteConnectionViolations(dd, td,														  refAction, 														  deleteConnHashtable, 														  myConstraintName);		}		}	/*	** Finds the existing delete connection for the table and the referential	** actions that will occur  and stores the information in the hash table.	** HashTable (key , value) = ( table name that this table is delete	** connected to, referential action that will occur if there is a delete on	** the table this table connected to[CASACDE, SETNULL , RESTRICT ...etc).)	**/	private	static int  getCurrentDeleteConnections	(	 DataDictionary	dd,	 TableDescriptor	td,	 int refActionType,	 Hashtable dch,	 boolean prevNotCascade,	 boolean findSelfRef	 )		throws StandardException	{		int selfRefValue = -1; //store the self reference referential action 		//make sure we get any foreign key constraints added earlier in the same statement.		td.emptyConstraintDescriptorList();		ConstraintDescriptorList cdl = dd.getConstraintDescriptors(td);		int cdlSize = cdl.size();		boolean passedInPrevNotCascade = prevNotCascade;		for (int index = 0; index < cdlSize; index++)		{				ConstraintDescriptor cd = cdl.elementAt(index);				//look for  foreign keys				if ((cd instanceof ForeignKeyConstraintDescriptor))				{					ForeignKeyConstraintDescriptor fkcd = (ForeignKeyConstraintDescriptor) cd;					String constraintName = fkcd.getConstraintName();					int raDeleteRule = fkcd.getRaDeleteRule();					int raUpdateRule = fkcd.getRaUpdateRule();					 if(findSelfRef && fkcd.isSelfReferencingFK())					 {						 //All self references will have same  referential actions type						 selfRefValue = raDeleteRule;						 findSelfRef = false;					 }					ReferencedKeyConstraintDescriptor refcd =						fkcd.getReferencedConstraint(); 					TableDescriptor refTd = refcd.getTableDescriptor();					int childRefAction = refActionType == -1 ? raDeleteRule : refActionType;				   					String refTableName = refTd.getSchemaName() + "." + refTd.getName();					//check with  the existing references.					Integer rAction = ((Integer)dch.get(refTableName));					if(rAction != null) // we already looked at this table					{						prevNotCascade = passedInPrevNotCascade;						continue;					}					//if we are not cascading, check whether the link before					//this was cascade or not. If we travel through  two NON CASCADE ACTION					//links then the  delete connection is broken(only a delete can have further					// referential effects)					if(raDeleteRule != StatementType.RA_CASCADE)					{						if(prevNotCascade)						{							prevNotCascade = passedInPrevNotCascade;							continue;						}						else							prevNotCascade = true;					}					//store the delete connection info in the hash table,					//note that the referential action value is not what is					//not specified on the current link. It is actually the 					//value of what happens to the table whose delete					// connections we are finding.					dch.put(refTableName, (new Integer(childRefAction)));										//find the next delete conectiions on this path for non					//self referencig delete connections.					if(!fkcd.isSelfReferencingFK())						getCurrentDeleteConnections(dd , refTd, childRefAction,													dch, true, false);					prevNotCascade = passedInPrevNotCascade;				}		}				return selfRefValue;	}	/*	** Following function validates whether the new foreign key relation ship	** violates any restriction on the referential actions. Current refAction	** implementation does not allow cases where we can possible land up	** having multiple action for the same row in a table, this happens becase	** user can possibly define differential action through multiple paths.	** Following function throws error while creating foreign keys if the new	** releations ship leads to any such conditions.	** NOTE : SQL99 standard also does not cleary says what we are suppose to do	** in these non determenistic cases. 	** Our implementation just follows what is did in DB2 and throws error	** messaged similar to DB2 (sql0632N, sql0633N, sql0634N)	*/	private	static void validateDeleteConnection	(		DataDictionary	dd,		TableDescriptor actualTd,  // the table we are adding the foriegn key.		TableDescriptor	refTd,		int refActionType,		Hashtable dch,		Hashtable ech,  //existing delete connections		boolean checkImmediateRefTable,		String myConstraintName,		boolean prevNotCascade,		StringBuffer cycleString, 		String currentRefTableName, //the name of the table we are referring too.		boolean isSelfReferencingFk,		int currentSelfRefValue		)		throws StandardException	{		Integer rAction;		String refTableName = refTd.getSchemaName() + "." + refTd.getName();		/*		** Validate the new referentail action value with respect to the 		** already existing connections to this table we gathered  from		** the getCurrentDeleteConnections() call.		*/		if(checkImmediateRefTable)		{			rAction = ((Integer)dch.get(refTableName));						// check possible invalide cases incase of self referencing foreign key			if(isSelfReferencingFk)			{				//All the relation ship referring to a table should have the				//same refaction except incase of SET NULL. In this case				//it is the same table , so we have to check with existing self				//referencing actions.				if(currentSelfRefValue !=  -1)				{					if(currentSelfRefValue != refActionType)					{						//If there is a SET NULL relation ship we can not have any						// other relation ship with it.						if(currentSelfRefValue == StatementType.RA_SETNULL)							throw								generateError(SQLState.LANG_CANT_BE_DEPENDENT_ESELF, 										  myConstraintName, currentRefTableName);						else						{								/*								** case where we can cleary say what the								** referential actions should be. Like,	   								** if there is NO ACTION relationsip								**already, new relation ship also shold be NO ACTION. 								*/							throw								generateError(SQLState.LANG_DELETE_RULE_MUSTBE_ESELF,											  myConstraintName, currentSelfRefValue);						}					}else					{						//more than one  ON DELET SET NULL to the same table is not allowed						if(currentSelfRefValue == StatementType.RA_SETNULL &&						   refActionType == StatementType.RA_SETNULL)						{							throw								generateError(SQLState.LANG_CANT_BE_DEPENDENT_ESELF,											  myConstraintName, currentRefTableName);						}					}				}				/*				** If the new releation ship is self referencing and if				** the current existing relation ship to other tables is				** CASCADE type them  new self reference should be of type				** CASCADE, otherwise we should throw error.				*/				if(isSelfReferencingFk && dch.contains(new Integer(StatementType.RA_CASCADE)) && 				   refActionType!=  StatementType.RA_CASCADE)				{					throw						generateError(SQLState.LANG_DELETE_RULE_MUSTBE_ECASCADE,									  myConstraintName,StatementType.RA_CASCADE);					}				//end of possible error case scenarios for self reference key additions				return;			}					//cases where the new  reference is referring to  another table

⌨️ 快捷键说明

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