You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by rh...@apache.org on 2009/12/09 15:22:48 UTC
svn commit: r888811 - in /db/derby/code/trunk/java:
engine/org/apache/derby/catalog/types/
engine/org/apache/derby/iapi/sql/depend/
engine/org/apache/derby/iapi/sql/dictionary/
engine/org/apache/derby/impl/sql/catalog/
engine/org/apache/derby/impl/sql/...
Author: rhillegas
Date: Wed Dec 9 14:22:46 2009
New Revision: 888811
URL: http://svn.apache.org/viewvc?rev=888811&view=rev
Log:
DERBY-651: Add dependency tracking between tables and UDTs.
Modified:
db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/BaseTypeIdImpl.java
db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/depend/DependencyManager.java
db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/AliasDescriptor.java
db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/DataDictionary.java
db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/TableDescriptor.java
db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/catalog/DataDictionaryImpl.java
db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/AlterTableNode.java
db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ColumnDefinitionNode.java
db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CreateTableNode.java
db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TableElementList.java
db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TableElementNode.java
db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/depend/BasicDependencyManager.java
db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/AlterTableConstantAction.java
db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/CreateTableConstantAction.java
db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/DDLConstantAction.java
db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml
db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java
db/derby/code/trunk/java/storeless/org/apache/derby/impl/storeless/EmptyDictionary.java
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/UDTTest.java
Modified: db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/BaseTypeIdImpl.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/BaseTypeIdImpl.java?rev=888811&r1=888810&r2=888811&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/BaseTypeIdImpl.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/BaseTypeIdImpl.java Wed Dec 9 14:22:46 2009
@@ -148,6 +148,9 @@
*/
public String getUnqualifiedName() { return unqualifiedName; }
+ /** Return true if this is this type id describes an ANSI UDT */
+ public boolean isAnsiUDT() { return (schemaName != null); }
+
/**
* Get the jdbc type id for this type. JDBC type can be
* found in java.sql.Types.
Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/depend/DependencyManager.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/depend/DependencyManager.java?rev=888811&r1=888810&r2=888811&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/depend/DependencyManager.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/depend/DependencyManager.java Wed Dec 9 14:22:46 2009
@@ -337,6 +337,8 @@
public static final int DROP_SEQUENCE = 49;
+ public static final int DROP_UDT = 50;
+
/**
* Extensions to this interface may use action codes > MAX_ACTION_CODE without fear of
* clashing with action codes in this base interface.
Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/AliasDescriptor.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/AliasDescriptor.java?rev=888811&r1=888810&r2=888811&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/AliasDescriptor.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/AliasDescriptor.java Wed Dec 9 14:22:46 2009
@@ -380,6 +380,10 @@
case AliasInfo.ALIAS_TYPE_SYNONYM_AS_CHAR:
invalidationType = DependencyManager.DROP_SYNONYM;
break;
+
+ case AliasInfo.ALIAS_TYPE_UDT_AS_CHAR:
+ invalidationType = DependencyManager.DROP_UDT;
+ break;
}
dm.invalidateFor(this, invalidationType, lcc);
Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/DataDictionary.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/DataDictionary.java?rev=888811&r1=888810&r2=888811&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/DataDictionary.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/DataDictionary.java Wed Dec 9 14:22:46 2009
@@ -1475,6 +1475,16 @@
*/
UUIDFactory getUUIDFactory();
+ /**
+ * Get the alias descriptor for an ANSI UDT.
+ *
+ * @param tc The transaction to use: if null, use the compilation transaction
+ * @param dtd The UDT's type descriptor
+ *
+ * @return The UDT's alias descriptor if it is an ANSI UDT; null otherwise.
+ */
+ public AliasDescriptor getAliasDescriptorForUDT( TransactionController tc, DataTypeDescriptor dtd ) throws StandardException;
+
/**
* Get an AliasDescriptor given its UUID.
*
Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/TableDescriptor.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/TableDescriptor.java?rev=888811&r1=888810&r2=888811&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/TableDescriptor.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/TableDescriptor.java Wed Dec 9 14:22:46 2009
@@ -30,10 +30,14 @@
import org.apache.derby.catalog.DependableFinder;
import org.apache.derby.catalog.UUID;
import org.apache.derby.iapi.error.StandardException;
+import org.apache.derby.iapi.reference.SQLState;
import org.apache.derby.iapi.services.io.FormatableBitSet;
import org.apache.derby.iapi.services.io.StoredFormatIds;
import org.apache.derby.iapi.services.sanity.SanityManager;
import org.apache.derby.iapi.sql.StatementType;
+import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
+import org.apache.derby.iapi.sql.depend.DependencyManager;
+import org.apache.derby.iapi.sql.depend.Dependent;
import org.apache.derby.iapi.sql.depend.Provider;
import org.apache.derby.iapi.sql.execute.ExecRow;
import org.apache.derby.iapi.types.DataValueDescriptor;
@@ -83,7 +87,7 @@
*/
public class TableDescriptor extends TupleDescriptor
- implements UniqueSQLObjectDescriptor, Provider
+ implements UniqueSQLObjectDescriptor, Provider, Dependent
{
public static final int BASE_TABLE_TYPE = 0;
public static final int SYSTEM_TABLE_TYPE = 1;
@@ -1383,4 +1387,79 @@
{
return (tableType == TableDescriptor.SYNONYM_TYPE) ? "Synonym" : "Table/View";
}
+
+ //////////////////////////////////////////////////////
+ //
+ // DEPENDENT INTERFACE
+ //
+ //////////////////////////////////////////////////////
+ /**
+ * Check that all of the dependent's dependencies are valid.
+ *
+ * @return true if the dependent is currently valid
+ */
+ public synchronized boolean isValid()
+ {
+ return true;
+ }
+
+ /**
+ * Prepare to mark the dependent as invalid (due to at least one of
+ * its dependencies being invalid).
+ *
+ * @param action The action causing the invalidation
+ * @param p the provider
+ *
+ * @exception StandardException thrown if unable to make it invalid
+ */
+ public void prepareToInvalidate(Provider p, int action,
+ LanguageConnectionContext lcc)
+ throws StandardException
+ {
+ DependencyManager dm = getDataDictionary().getDependencyManager();
+
+ switch (action)
+ {
+ /*
+ ** Currently, the only thing we are dependent
+ ** on is an alias descriptor for an ANSI UDT.
+ */
+ default:
+
+ throw StandardException.newException(SQLState.LANG_PROVIDER_HAS_DEPENDENT_TABLE,
+ dm.getActionString(action),
+ p.getObjectName(),
+ getQualifiedName());
+ }
+ }
+
+ /**
+ * Mark the dependent as invalid (due to at least one of
+ * its dependencies being invalid). Always an error
+ * for a table -- should never have gotten here.
+ *
+ * @param action The action causing the invalidation
+ *
+ * @exception StandardException thrown if called in sanity mode
+ */
+ public void makeInvalid(int action, LanguageConnectionContext lcc)
+ throws StandardException
+ {
+ /*
+ ** We should never get here, we should have barfed on
+ ** prepareToInvalidate().
+ */
+ if (SanityManager.DEBUG)
+ {
+ DependencyManager dm;
+
+ dm = getDataDictionary().getDependencyManager();
+
+ SanityManager.THROWASSERT("makeInvalid("+
+ dm.getActionString(action)+
+ ") not expected to get called");
+ }
+ }
+
}
+
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/catalog/DataDictionaryImpl.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/catalog/DataDictionaryImpl.java?rev=888811&r1=888810&r2=888811&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/catalog/DataDictionaryImpl.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/catalog/DataDictionaryImpl.java Wed Dec 9 14:22:46 2009
@@ -134,6 +134,7 @@
import org.apache.derby.catalog.DefaultInfo;
import org.apache.derby.catalog.TypeDescriptor;
import org.apache.derby.catalog.UUID;
+import org.apache.derby.catalog.types.BaseTypeIdImpl;
import org.apache.derby.catalog.types.RoutineAliasInfo;
import org.apache.derby.iapi.services.io.FormatableBitSet;
@@ -6675,8 +6676,6 @@
ddlList,
false);
-
-
return ddlList;
}
@@ -6827,6 +6826,30 @@
return uuidFactory;
}
+ /**
+ * Get the alias descriptor for an ANSI UDT.
+ *
+ * @param tc The transaction to use: if null, use the compilation transaction
+ * @param dtd The UDT's type descriptor
+ *
+ * @return The UDT's alias descriptor if it is an ANSI UDT; null otherwise.
+ */
+ public AliasDescriptor getAliasDescriptorForUDT( TransactionController tc, DataTypeDescriptor dtd ) throws StandardException
+ {
+ if ( tc == null ) { tc = getTransactionCompile(); }
+
+ if ( dtd == null ) { return null; }
+
+ BaseTypeIdImpl btii = dtd.getTypeId().getBaseTypeId();
+ if ( !btii.isAnsiUDT() ) { return null; }
+
+ SchemaDescriptor sd = getSchemaDescriptor( btii.getSchemaName(), tc, true );
+ AliasDescriptor ad = getAliasDescriptor
+ ( sd.getUUID().toString(), btii.getUnqualifiedName(), AliasInfo.ALIAS_NAME_SPACE_UDT_AS_CHAR );
+
+ return ad;
+ }
+
/**
* Get a AliasDescriptor given its UUID.
*
@@ -8310,7 +8333,7 @@
else
{
if (SanityManager.DEBUG)
- {
+ {
SanityManager.ASSERT(! booting, "booting is expected to be false");
}
{
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/AlterTableNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/AlterTableNode.java?rev=888811&r1=888810&r2=888811&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/AlterTableNode.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/AlterTableNode.java Wed Dec 9 14:22:46 2009
@@ -30,6 +30,8 @@
import org.apache.derby.iapi.error.StandardException;
import org.apache.derby.iapi.sql.compile.C_NodeTypes;
+import org.apache.derby.iapi.sql.compile.Visitable;
+import org.apache.derby.iapi.sql.compile.Visitor;
import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor;
import org.apache.derby.iapi.sql.dictionary.ConstraintDescriptorList;
@@ -566,6 +568,24 @@
}
+ /**
+ * Accept the visitor for all visitable children of this node.
+ *
+ * @param v the visitor
+ *
+ * @exception StandardException on error
+ */
+ void acceptChildren(Visitor v)
+ throws StandardException
+ {
+ super.acceptChildren(v);
+
+ if (tableElementList != null)
+ {
+ tableElementList.accept(v);
+ }
+ }
+
/*
* class interface
*/
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ColumnDefinitionNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ColumnDefinitionNode.java?rev=888811&r1=888810&r2=888811&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ColumnDefinitionNode.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ColumnDefinitionNode.java Wed Dec 9 14:22:46 2009
@@ -199,7 +199,7 @@
{
if (SanityManager.DEBUG)
{
- return "type: " + getType().toString() + "\n" +
+ return "type: " + getType() + "\n" +
"defaultValue: " + defaultValue + "\n" +
super.toString();
}
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CreateTableNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CreateTableNode.java?rev=888811&r1=888810&r2=888811&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CreateTableNode.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CreateTableNode.java Wed Dec 9 14:22:46 2009
@@ -38,6 +38,8 @@
import org.apache.derby.iapi.sql.compile.C_NodeTypes;
import org.apache.derby.iapi.sql.compile.CompilerContext;
+import org.apache.derby.iapi.sql.compile.Visitable;
+import org.apache.derby.iapi.sql.compile.Visitor;
import org.apache.derby.iapi.sql.conn.Authorizer;
import org.apache.derby.iapi.error.StandardException;
@@ -563,4 +565,23 @@
onCommitDeleteRows,
onRollbackDeleteRows));
}
+
+ /**
+ * Accept the visitor for all visitable children of this node.
+ *
+ * @param v the visitor
+ *
+ * @exception StandardException on error
+ */
+ void acceptChildren(Visitor v)
+ throws StandardException
+ {
+ super.acceptChildren(v);
+
+ if (tableElementList != null)
+ {
+ tableElementList.accept(v);
+ }
+ }
+
}
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TableElementList.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TableElementList.java?rev=888811&r1=888810&r2=888811&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TableElementList.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TableElementList.java Wed Dec 9 14:22:46 2009
@@ -224,8 +224,9 @@
ModifyColumnNode mcdn = (ModifyColumnNode)cdn;
mcdn.checkExistingConstraints(td);
mcdn.useExistingCollation(td);
+
} else if (cdn.isAutoincrementColumn())
- numAutoCols ++;
+ { numAutoCols ++; }
}
else if (tableElement.getElementType() == TableElementNode.AT_DROP_COLUMN)
{
@@ -483,9 +484,12 @@
{
if (((TableElementNode) elementAt(index)).getElementType() == TableElementNode.AT_DROP_COLUMN)
{
+ String columnName = ((TableElementNode) elementAt(index)).getName();
+
colInfos[index] = new ColumnInfo(
- ((TableElementNode) elementAt(index)).getName(),
- null, null, null, null, null, null,
+ columnName,
+ td.getColumnDescriptor( columnName ).getType(),
+ null, null, null, null, null,
ColumnInfo.DROP, 0, 0, 0);
break;
}
@@ -521,7 +525,7 @@
DependencyManager dm = getDataDictionary().getDependencyManager();
providerInfos = dm.getPersistentProviderInfos(apl);
}
-
+
colInfos[index - numConstraints] =
new ColumnInfo(coldef.getColumnName(),
coldef.getType(),
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TableElementNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TableElementNode.java?rev=888811&r1=888810&r2=888811&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TableElementNode.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/TableElementNode.java Wed Dec 9 14:22:46 2009
@@ -22,6 +22,7 @@
package org.apache.derby.impl.sql.compile;
import org.apache.derby.iapi.services.sanity.SanityManager;
+import org.apache.derby.iapi.sql.compile.C_NodeTypes;
/**
* A TableElementNode is an item in a TableElementList, and represents
@@ -101,6 +102,7 @@
if (SanityManager.DEBUG)
{
return "name: " + name + "\n" +
+ "elementType: " + getElementType() + "\n" +
super.toString();
}
else
@@ -181,7 +183,11 @@
else if ( hasUniqueKeyConstraint() ) { return AT_ADD_UNIQUE_CONSTRAINT; }
else if ( hasCheckConstraint() ) { return AT_ADD_CHECK_CONSTRAINT; }
else if ( this instanceof ConstraintDefinitionNode ) { return AT_DROP_CONSTRAINT; }
- else if ( this instanceof ModifyColumnNode ) { return AT_MODIFY_COLUMN; }
+ else if ( this instanceof ModifyColumnNode )
+ {
+ if ( getNodeType() == C_NodeTypes.DROP_COLUMN_NODE ) { return AT_DROP_COLUMN; }
+ else { return AT_MODIFY_COLUMN; }
+ }
else { return elementType; }
}
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/depend/BasicDependencyManager.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/depend/BasicDependencyManager.java?rev=888811&r1=888810&r2=888811&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/depend/BasicDependencyManager.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/depend/BasicDependencyManager.java Wed Dec 9 14:22:46 2009
@@ -264,6 +264,7 @@
throws StandardException
{
List list = getDependents(p);
+
if (list == null)
{
return;
@@ -889,6 +890,9 @@
case DROP_SEQUENCE:
return "DROP SEQUENCE";
+ case DROP_UDT:
+ return "DROP TYPE";
+
default:
if (SanityManager.DEBUG)
{
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/AlterTableConstantAction.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/AlterTableConstantAction.java?rev=888811&r1=888810&r2=888811&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/AlterTableConstantAction.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/AlterTableConstantAction.java Wed Dec 9 14:22:46 2009
@@ -510,6 +510,9 @@
}
}
+ // adjust dependencies on user defined types
+ adjustUDTDependencies( lcc, dd, td, columnInfo );
+
/* Create/Drop any constraints */
if (constraintActions != null)
{
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/CreateTableConstantAction.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/CreateTableConstantAction.java?rev=888811&r1=888810&r2=888811&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/CreateTableConstantAction.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/CreateTableConstantAction.java Wed Dec 9 14:22:46 2009
@@ -366,6 +366,11 @@
{
addColumnDependencies( lcc, dd, td, columnInfo[ ix ] );
}
+
+ //
+ // The table itself can depend on the user defined types of its columns.
+ //
+ adjustUDTDependencies( lcc, dd, td, columnInfo );
if ( tableType == TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE )
{
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/DDLConstantAction.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/DDLConstantAction.java?rev=888811&r1=888810&r2=888811&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/DDLConstantAction.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/DDLConstantAction.java Wed Dec 9 14:22:46 2009
@@ -21,9 +21,12 @@
package org.apache.derby.impl.sql.execute;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import org.apache.derby.catalog.AliasInfo;
import org.apache.derby.catalog.DependableFinder;
import org.apache.derby.catalog.UUID;
import org.apache.derby.iapi.error.StandardException;
@@ -37,9 +40,12 @@
import org.apache.derby.iapi.sql.depend.Dependent;
import org.apache.derby.iapi.sql.depend.Provider;
import org.apache.derby.iapi.sql.depend.ProviderInfo;
+import org.apache.derby.iapi.sql.dictionary.AliasDescriptor;
import org.apache.derby.iapi.sql.dictionary.ColPermsDescriptor;
import org.apache.derby.iapi.sql.dictionary.ColumnDescriptor;
+import org.apache.derby.iapi.sql.dictionary.ColumnDescriptorList;
import org.apache.derby.iapi.sql.dictionary.DefaultDescriptor;
+import org.apache.derby.iapi.sql.dictionary.DependencyDescriptor;
import org.apache.derby.iapi.sql.dictionary.DataDictionary;
import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
import org.apache.derby.iapi.sql.dictionary.PermissionsDescriptor;
@@ -56,6 +62,7 @@
import org.apache.derby.iapi.store.access.ConglomerateController;
import org.apache.derby.iapi.store.access.TransactionController;
import org.apache.derby.iapi.services.sanity.SanityManager;
+import org.apache.derby.iapi.types.DataTypeDescriptor;
/**
* Abstract class that has actions that are across
@@ -805,6 +812,122 @@
}
}
+ /**
+ * Adjust dependencies of a table on ANSI UDTs. We only add one dependency
+ * between a table and a UDT. If the table already depends on the UDT, we don't add
+ * a redundant dependency.
+ */
+ protected void adjustUDTDependencies
+ (
+ LanguageConnectionContext lcc,
+ DataDictionary dd,
+ TableDescriptor td,
+ ColumnInfo[] columnInfos
+ )
+ throws StandardException
+ {
+ if ( columnInfos == null ) { return; }
+
+ TransactionController tc = lcc.getTransactionExecute();
+
+ int changedColumnCount = columnInfos.length;
+ HashMap addUdtMap = new HashMap();
+ HashMap dropUdtMap = new HashMap();
+ HashSet addColumnNames = new HashSet();
+ HashSet dropColumnNames = new HashSet();
+
+ // first find all of the new ansi udts which the table must depend on
+ // and the old ones which are candidates for removal
+ for ( int i = 0; i < changedColumnCount; i++ )
+ {
+ ColumnInfo ci = columnInfos[ i ];
+
+ // skip this column if it is not a UDT
+ AliasDescriptor ad = dd.getAliasDescriptorForUDT( tc, columnInfos[ i ].dataType );
+ if ( ad == null ) { continue; }
+
+ String key = ad.getObjectID().toString();
+
+ if ( ci.action == ColumnInfo.CREATE )
+ {
+ addColumnNames.add( ci.name);
+
+ // no need to add the descriptor if it is already on the list
+ if ( addUdtMap.get( key ) != null ) { continue; }
+
+ addUdtMap.put( key, ad );
+ }
+ else if ( ci.action == ColumnInfo.DROP )
+ {
+ dropColumnNames.add( ci.name );
+ dropUdtMap.put( key, ad );
+ }
+ }
+
+ // nothing to do if there are no columns of udt type
+ if ( (addUdtMap.size() == 0) && (dropUdtMap.size() == 0) ) { return; }
+
+ //
+ // Now prune from the add list all udt descriptors for which we already have dependencies.
+ // These are the udts for old columns. This supports the ALTER TABLE ADD COLUMN
+ // case.
+ //
+ // Also prune from the drop list add udt descriptors which will still be
+ // referenced by the remaining columns.
+ //
+ ColumnDescriptorList cdl = td.getColumnDescriptorList();
+ int totalColumnCount = cdl.size();
+
+ for ( int i = 0; i < totalColumnCount; i++ )
+ {
+ ColumnDescriptor cd = cdl.elementAt( i );
+
+ // skip columns that are being added and dropped. we only want the untouched columns
+ if (
+ addColumnNames.contains( cd.getColumnName() ) ||
+ dropColumnNames.contains( cd.getColumnName() )
+ ) { continue; }
+
+ // nothing to do if the old column isn't a UDT
+ AliasDescriptor ad = dd.getAliasDescriptorForUDT( tc, cd.getType() );
+ if ( ad == null ) { continue; }
+
+ String key = ad.getObjectID().toString();
+
+ // ha, it is a UDT. remove the UDT from the list of dependencies to
+ // add and drop
+ if ( addUdtMap.get( key ) != null ) { addUdtMap.remove( key ); }
+ if ( dropUdtMap.get( key ) != null ) { dropUdtMap.remove( key ); }
+ }
+
+ // again, nothing to do if there are no columns of udt type
+ if ( (addUdtMap.size() == 0) && (dropUdtMap.size() == 0) ) { return; }
+
+ DependencyManager dm = dd.getDependencyManager();
+ ContextManager cm = lcc.getContextManager();
+
+ // add new dependencies
+ Iterator addIterator = addUdtMap.values().iterator();
+ while( addIterator.hasNext() )
+ {
+ AliasDescriptor ad = (AliasDescriptor) addIterator.next();
+
+ dm.addDependency( td, ad, cm );
+ }
+
+ // drop dependencies that are orphaned
+ Iterator dropIterator = dropUdtMap.values().iterator();
+ while( dropIterator.hasNext() )
+ {
+ AliasDescriptor ad = (AliasDescriptor) dropIterator.next();
+
+ DependencyDescriptor dependency = new DependencyDescriptor( td, ad );
+
+ dd.dropStoredDependency( dependency, tc );
+ }
+ }
+
+
/**
* Mutable Boolean wrapper, initially false
*/
Modified: db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml?rev=888811&r1=888810&r2=888811&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml Wed Dec 9 14:22:46 2009
@@ -3136,6 +3136,14 @@
</msg>
<msg>
+ <name>X0Y29.S</name>
+ <text>Operation '{0}' cannot be performed on object '{1}' because TABLE '{2}' is dependent on that object.</text>
+ <arg>operationName</arg>
+ <arg>objectName</arg>
+ <arg>viewName</arg>
+ </msg>
+
+ <msg>
<name>X0Y32.S</name>
<text>{0} '{1}' already exists in {2} '{3}'.</text>
<arg>value</arg>
Modified: db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java?rev=888811&r1=888810&r2=888811&view=diff
==============================================================================
--- db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java (original)
+++ db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java Wed Dec 9 14:22:46 2009
@@ -1321,6 +1321,7 @@
String LANG_PROVIDER_HAS_DEPENDENT_OBJECT = "X0Y25.S";
String LANG_INDEX_AND_TABLE_IN_DIFFERENT_SCHEMAS = "X0Y26.S";
String LANG_CREATE_SYSTEM_INDEX_ATTEMPTED = "X0Y28.S";
+ String LANG_PROVIDER_HAS_DEPENDENT_TABLE = "X0Y29.S";
String LANG_OBJECT_ALREADY_EXISTS_IN_OBJECT = "X0Y32.S";
String LANG_CREATE_INDEX_NO_TABLE = "X0Y38.S";
String LANG_INVALID_FK_NO_PK = "X0Y41.S";
Modified: db/derby/code/trunk/java/storeless/org/apache/derby/impl/storeless/EmptyDictionary.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/storeless/org/apache/derby/impl/storeless/EmptyDictionary.java?rev=888811&r1=888810&r2=888811&view=diff
==============================================================================
--- db/derby/code/trunk/java/storeless/org/apache/derby/impl/storeless/EmptyDictionary.java (original)
+++ db/derby/code/trunk/java/storeless/org/apache/derby/impl/storeless/EmptyDictionary.java Wed Dec 9 14:22:46 2009
@@ -614,6 +614,12 @@
return null;
}
+ public AliasDescriptor getAliasDescriptorForUDT( TransactionController tc, DataTypeDescriptor dtd )
+ throws StandardException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
public AliasDescriptor getAliasDescriptor(UUID uuid)
throws StandardException {
// TODO Auto-generated method stub
Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/UDTTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/UDTTest.java?rev=888811&r1=888810&r2=888811&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/UDTTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/UDTTest.java Wed Dec 9 14:22:46 2009
@@ -51,6 +51,7 @@
public static final String OBJECT_EXISTS = "X0Y68";
public static final String NONEXISTENT_OBJECT = "42Y55";
public static final String SYNTAX_ERROR = "42X01";
+ public static final String TABLE_DEPENDS_ON_TYPE = "X0Y29";
///////////////////////////////////////////////////////////////////////////////////
//
@@ -226,10 +227,159 @@
);
}
+ /**
+ * <p>
+ * Adding and dropping udt columns.
+ * </p>
+ */
+ public void test_03_addDropColumn() throws Exception
+ {
+ Connection conn = getConnection();
+ String tableName1 = "UDTCOLUMNS";
+ String tableName2 = "UDTCOLUMNS2";
+
+ goodStatement
+ ( conn,
+ "create type price_03 external name 'org.apache.derbyTesting.functionTests.tests.lang.Price' language java\n" );
+
+ // even though there are 2 price_03 columns, we only create 1 dependency
+ goodStatement
+ ( conn,
+ "create table " + tableName1 + "\n" +
+ "(\n" +
+ " a int, b int,\n" +
+ " price1 price_03,\n" +
+ " price2 price_03\n" +
+ ")\n"
+ );
+ assertEquals( 1, countTableDependencies( conn, tableName1 ) );
+
+ // verify that we can't drop the type while the table depends on it
+ expectExecutionError( conn, TABLE_DEPENDS_ON_TYPE, "drop type Price_03 restrict\n" );
+
+ // add another price_03 column. should not add another dependency
+ goodStatement
+ ( conn,
+ "alter table udtColumns add column price3 price_03\n" );
+ assertEquals( 1, countTableDependencies( conn, tableName1 ) );
+ expectExecutionError( conn, TABLE_DEPENDS_ON_TYPE, "drop type Price_03 restrict\n" );
+
+ // drop one of the price_03 column. there should still be a dependency
+ goodStatement
+ ( conn,
+ "alter table udtColumns drop column price3\n" );
+ assertEquals( 1, countTableDependencies( conn, tableName1 ) );
+ expectExecutionError( conn, TABLE_DEPENDS_ON_TYPE, "drop type Price_03 restrict\n" );
+
+ // drop another column. same story.
+ goodStatement
+ ( conn,
+ "alter table udtColumns drop column price2\n" );
+ assertEquals( 1, countTableDependencies( conn, tableName1 ) );
+ expectExecutionError( conn, TABLE_DEPENDS_ON_TYPE, "drop type Price_03 restrict\n" );
+
+ // drop the last udt column. dependency should disappear
+ goodStatement
+ ( conn,
+ "alter table udtColumns drop column price1\n" );
+ assertEquals( 0, countTableDependencies( conn, tableName1 ) );
+ goodStatement
+ ( conn,
+ "drop type Price_03 restrict\n" );
+
+ // similar experiments with more types
+ goodStatement
+ ( conn,
+ "create type price_03_a external name 'org.apache.derbyTesting.functionTests.tests.lang.Price' language java\n" );
+ goodStatement
+ ( conn,
+ "create type price_03_b external name 'org.apache.derbyTesting.functionTests.tests.lang.Price' language java\n" );
+ goodStatement
+ ( conn,
+ "create type price_03_c external name 'org.apache.derbyTesting.functionTests.tests.lang.Price' language java\n" );
+
+ goodStatement
+ ( conn,
+ "create table udtColumns2\n" +
+ "(\n" +
+ " a int, b int,\n" +
+ " price1 price_03_a,\n" +
+ " price2 price_03_b\n" +
+ ")\n"
+ );
+ assertEquals( 2, countTableDependencies( conn, tableName2 ) );
+ expectExecutionError( conn, TABLE_DEPENDS_ON_TYPE, "drop type Price_03_a restrict\n" );
+ expectExecutionError( conn, TABLE_DEPENDS_ON_TYPE, "drop type Price_03_b restrict\n" );
+
+ goodStatement
+ ( conn,
+ "alter table udtColumns2 add column price3 price_03_c\n" );
+ assertEquals( 3, countTableDependencies( conn, tableName2 ) );
+ expectExecutionError( conn, TABLE_DEPENDS_ON_TYPE, "drop type Price_03_a restrict\n" );
+ expectExecutionError( conn, TABLE_DEPENDS_ON_TYPE, "drop type Price_03_b restrict\n" );
+ expectExecutionError( conn, TABLE_DEPENDS_ON_TYPE, "drop type Price_03_c restrict\n" );
+
+ goodStatement
+ ( conn,
+ "alter table udtColumns2 drop column b\n" );
+ assertEquals( 3, countTableDependencies( conn, tableName2 ) );
+ expectExecutionError( conn, TABLE_DEPENDS_ON_TYPE, "drop type Price_03_a restrict\n" );
+ expectExecutionError( conn, TABLE_DEPENDS_ON_TYPE, "drop type Price_03_b restrict\n" );
+ expectExecutionError( conn, TABLE_DEPENDS_ON_TYPE, "drop type Price_03_c restrict\n" );
+
+ goodStatement
+ ( conn,
+ "alter table udtColumns2 drop column price3\n" );
+ assertEquals( 2, countTableDependencies( conn, tableName2 ) );
+ goodStatement
+ ( conn,
+ "drop type Price_03_c restrict\n" );
+
+ goodStatement
+ ( conn,
+ "alter table udtColumns2 drop column price2\n" );
+ assertEquals( 1, countTableDependencies( conn, tableName2 ) );
+ goodStatement
+ ( conn,
+ "drop type Price_03_b restrict\n" );
+
+ goodStatement
+ ( conn,
+ "alter table udtColumns2 drop column price1\n" );
+ assertEquals( 0, countTableDependencies( conn, tableName2 ) );
+ goodStatement
+ ( conn,
+ "drop type Price_03_a restrict\n" );
+
+ }
+
///////////////////////////////////////////////////////////////////////////////////
//
// MINIONS
//
///////////////////////////////////////////////////////////////////////////////////
+ /** Get the number of dependencies that a table has */
+ private int countTableDependencies( Connection conn, String tableName ) throws Exception
+ {
+ PreparedStatement ps = chattyPrepare
+ ( conn, "select count(*) from sys.sysdepends d, sys.systables t where d.dependentid = t.tableid and t.tablename = ?" );
+ ps.setString( 1, tableName );
+
+ return getScalarInteger( ps );
+ }
+
+ /** Get a scalar integer result from a query */
+ private int getScalarInteger( PreparedStatement ps ) throws Exception
+ {
+ ResultSet rs = ps.executeQuery();
+ rs.next();
+ int retval = rs.getInt( 1 );
+
+ rs.close();
+ ps.close();
+
+ return retval;
+ }
+
}