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 ab...@apache.org on 2008/02/15 22:55:16 UTC

svn commit: r628181 - in /db/derby/code/trunk/java/engine/org/apache/derby: iapi/sql/dictionary/ConglomerateDescriptor.java iapi/sql/dictionary/ConstraintDescriptor.java impl/sql/execute/DDLSingleTableConstantAction.java

Author: abrown
Date: Fri Feb 15 13:55:14 2008
New Revision: 628181

URL: http://svn.apache.org/viewvc?rev=628181&view=rev
Log:
DERBY-3299 (incremental): Add several utility methods to
DDLSingleTableConstantAction.java that can be called by the various
ConstantAction subclasses to drop a constraint and/or a conglomerate
descriptor. In addition to performing the drop as before, these
utility methods also check to see if dropping the constraint or
index necessitates the "update" of a shared physical conglomerate.
If so, the new methods will take the necessary steps to create
create a new ("replacement") physical conglomerate that correctly
satisfies all remaining conglomerate descriptors--i.e. all of the
ones that were sharing the dropped physical conglomerate.

Note that a) Derby does not currently have logic to recognize when
a shared physical conglomerate needs to be updated (that's coming
in a subsequent patch), and b) there are currently no calls to the
new utility methods.  Thus this commit should not have any effect
on Derby yet (incremental development).

Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/ConglomerateDescriptor.java
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/ConstraintDescriptor.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/DDLSingleTableConstantAction.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/ConglomerateDescriptor.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/ConglomerateDescriptor.java?rev=628181&r1=628180&r2=628181&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/ConglomerateDescriptor.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/ConglomerateDescriptor.java Fri Feb 15 13:55:14 2008
@@ -348,14 +348,26 @@
      * a physical index then the physical index (conglomerate)
      * and its descriptor will be dropped.
      * 
-     * @param lcc
-     * @param td
+     * @param lcc Connection context to use for dropping
+     * @param td TableDescriptor for the table to which this
+     *  conglomerate belongs
+     * @return If the conglomerate described by this descriptor
+     *  is an index conglomerate that is shared by multiple
+     *  constraints/indexes, then we may have to create a new
+     *  conglomerate to satisfy the constraints/indexes which
+     *  remain after we drop the existing conglomerate.  If that's
+     *  needed then we'll return a conglomerate descriptor which
+     *  describes what the new conglomerate must look like.  It
+     *  is then up to the caller of this method to create a new
+     *  corresponding conglomerate.  We don't create the index
+     *  here because depending on who called us, it might not
+     *  make sense to create it--esp. if we get here because of
+     *  a DROP TABLE.
      * @throws StandardException
      */
-	public void drop(LanguageConnectionContext lcc,
-	        TableDescriptor td)
-	throws StandardException
-	{     
+	public ConglomerateDescriptor drop(LanguageConnectionContext lcc,
+		TableDescriptor td) throws StandardException
+	{
         DataDictionary dd = getDataDictionary();
         DependencyManager dm = dd.getDependencyManager();
         TransactionController tc = lcc.getTransactionExecute();
@@ -383,6 +395,11 @@
 	     ** table descriptor
 	     */
 	    td.removeConglomerateDescriptor(this);
+
+	    /* TODO: DERBY-3299 incremental development; just return null
+	     * for now.
+	     */
+	    return null;
 	}
 	
 }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/ConstraintDescriptor.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/ConstraintDescriptor.java?rev=628181&r1=628180&r2=628181&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/ConstraintDescriptor.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/ConstraintDescriptor.java Fri Feb 15 13:55:14 2008
@@ -641,10 +641,22 @@
      * the backing index and removes the constraint
      * from the list on the table descriptor.  Does NOT
      * do an dm.invalidateFor()
+     *
+     * @return If the backing conglomerate for this constraint
+     *  was a) dropped and b) shared by other constraints/indexes,
+     *  then this method will return a ConglomerateDescriptor that
+     *  describes what a new backing conglomerate must look like
+     *  to stay "sharable" across the remaining constraints/indexes.
+     *  It is then up to the caller to create a corresponding 
+     *  conglomerate.  We don't create the conglomerate here
+     *  because depending on who called us, it might not make
+     *  sense to create it--ex. if we get here because of a DROP
+     *  TABLE, the DropTable action doesn't need to create a
+     *  new backing conglomerate since the table (and all of
+     *  its constraints/indexes) are going to disappear anyway.
      */
-    public void drop(LanguageConnectionContext lcc,
-            boolean clearDependencies)
-        throws StandardException
+    public ConglomerateDescriptor drop(LanguageConnectionContext lcc,
+        boolean clearDependencies) throws StandardException
     {       
         DataDictionary dd = getDataDictionary();
         DependencyManager dm = dd.getDependencyManager();
@@ -667,6 +679,7 @@
          * force the constraint to exist at bind time, so we always
          * generate one.
          */
+        ConglomerateDescriptor newBackingConglomCD = null;
         if (hasBackingIndex())
         {
 
@@ -689,7 +702,7 @@
                 {
                     if (conglomDescs[i].isConstraint())
                     {
-                        conglomDescs[i].drop(lcc, table);
+                        newBackingConglomCD = conglomDescs[i].drop(lcc, table);
                         break;
                     }
                 }
@@ -697,6 +710,7 @@
         }
 
         table.removeConstraintDescriptor(this);
+        return newBackingConglomCD;
     }
 	
 	/** @see TupleDescriptor#getDescriptorName */

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/DDLSingleTableConstantAction.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/DDLSingleTableConstantAction.java?rev=628181&r1=628180&r2=628181&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/DDLSingleTableConstantAction.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/DDLSingleTableConstantAction.java Fri Feb 15 13:55:14 2008
@@ -21,8 +21,26 @@
 
 package org.apache.derby.impl.sql.execute;
 
+import java.util.List;
+import java.util.Properties;
+
 import org.apache.derby.catalog.UUID;
 
+import org.apache.derby.iapi.error.StandardException;
+
+import org.apache.derby.iapi.services.sanity.SanityManager;
+
+import org.apache.derby.iapi.sql.Activation;
+import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
+import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor;
+import org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor;
+import org.apache.derby.iapi.sql.dictionary.KeyConstraintDescriptor;
+import org.apache.derby.iapi.sql.dictionary.DataDictionary;
+import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
+import org.apache.derby.iapi.sql.execute.ConstantAction;
+import org.apache.derby.iapi.store.access.ConglomerateController;
+import org.apache.derby.iapi.store.access.TransactionController;
+
 /**
  * Abstract class that has actions that are across
  * all DDL actions that are tied to a table.  An example
@@ -45,5 +63,308 @@
 	{
 		super();
 		this.tableId = tableId;
+	}
+
+	/**
+	 * Drop the constraint corresponding to the received descriptor.
+	 * If in doing so we also drop a backing conglomerate that is
+	 * shared by other constraints/indexes, then we have to create
+	 * a new conglomerate to fill the gap.
+	 *
+	 * This method exists here as a "utility" method for the various
+	 * constant actions that may drop constraints in one way or
+	 * another (there are several that do).
+	 *
+	 * @param consDesc ConstraintDescriptor for the constraint to drop
+	 * @param activation Activation used when creating a new backing
+	 *  index (if a new backing index is needed)
+	 * @param lcc LanguageConnectionContext used for dropping
+	 * @param clearDeps Whether or not to clear dependencies when
+	 *   dropping the constraint
+	 */
+	void dropConstraint(ConstraintDescriptor consDesc,
+		Activation activation, LanguageConnectionContext lcc,
+		boolean clearDeps) throws StandardException
+	{
+		dropConstraint(consDesc, (TableDescriptor)null,
+			(List)null, activation, lcc, clearDeps);
+	}
+
+	/**
+	 * See "dropConstraint(...") above.
+	 *
+	 * @param skipCreate Optional TableDescriptor.  If non-null
+	 *  then we will skip the "create new conglomerate" processing
+	 *  *IF* the constraint that we drop came from the table
+	 *  described by skipCreate.
+	 */
+	void dropConstraint(ConstraintDescriptor consDesc,
+		TableDescriptor skipCreate, Activation activation,
+		LanguageConnectionContext lcc, boolean clearDeps)
+		throws StandardException
+	{
+		dropConstraint(consDesc, skipCreate,
+			(List)null, activation, lcc, clearDeps);
+	}
+
+	/**
+	 * See "dropConstraint(...") above.
+	 *
+	 * @param newConglomActions Optional List.  If non-null then
+	 *  for each ConglomerateDescriptor for which we skip the
+	 *  "create new conglomerate" processing we will add a
+	 *  ConstantAction to this list.  The constant action can
+	 *  then be executed later (esp. by the caller) to create the
+	 *  new conglomerate, if needed.  If this argument is null and
+	 *  we skip creation of a new conglomerate, the new conglomerate
+	 *  is effectively ignored (which may be fine in some cases--
+	 *  ex. when dropping a table).
+	 */
+	void dropConstraint(ConstraintDescriptor consDesc,
+		TableDescriptor skipCreate, List newConglomActions,
+		Activation activation, LanguageConnectionContext lcc,
+		boolean clearDeps) throws StandardException
+	{
+		/* Get the properties on the old backing conglomerate before
+		 * dropping the constraint, since we can't get them later if
+		 * dropping the constraint causes us to drop the backing
+		 * conglomerate.
+		 */
+		Properties ixProps = null;
+		if (consDesc instanceof KeyConstraintDescriptor)
+		{
+			ixProps = new Properties();
+			loadIndexProperties(lcc,
+				((KeyConstraintDescriptor)consDesc)
+					.getIndexConglomerateDescriptor(lcc.getDataDictionary()),
+				ixProps);
+		}
+
+		ConglomerateDescriptor newBackingConglomCD = consDesc.drop(lcc, clearDeps);
+
+		/* If we don't need a new conglomerate then there's nothing
+		 * else to do.
+		 */
+		if (newBackingConglomCD == null)
+			return;
+
+		/* Only create the new conglomerate if it is NOT for the table
+		 * described by skipCreate.
+		 */
+		if ((skipCreate != null) &&
+			skipCreate.getUUID().equals(
+				consDesc.getTableDescriptor().getUUID()))
+		{
+			/* We're skipping the "create new conglom" phase; if we have
+			 * a list in which to store the ConstantAction, then store it;
+			 * otherwise, the new conglomerate is effectively ignored.
+			 */
+			if (newConglomActions != null)
+			{
+				newConglomActions.add(
+					getConglomReplacementAction(newBackingConglomCD,
+						consDesc.getTableDescriptor(), ixProps));
+			}
+		}
+		else
+		{
+			executeConglomReplacement(
+				getConglomReplacementAction(newBackingConglomCD,
+					consDesc.getTableDescriptor(), ixProps),
+				activation);
+		}
+
+		return;
+	}
+
+	/**
+	 * Similar to dropConstraint(...) above, except this method
+	 * drops a conglomerate directly instead of going through
+	 * a ConstraintDescriptor.
+	 *
+	 * @param congDesc ConglomerateDescriptor for the conglom to drop
+	 * @param td TableDescriptor for the table on which congDesc exists
+	 * @param activation Activation used when creating a new backing
+	 *  index (if a new backing index is needed)
+	 * @param lcc LanguageConnectionContext used for dropping
+	 */
+	void dropConglomerate(
+		ConglomerateDescriptor congDesc, TableDescriptor td,
+		Activation activation, LanguageConnectionContext lcc)
+		throws StandardException
+	{
+		dropConglomerate(congDesc, td,
+			false, (List)null, activation, lcc);
+	}
+
+	/**
+	 * See "dropConglomerate(...)" above.
+	 *	
+	 * @param skipCreate If true then we will skip the "create
+	 *  new conglomerate" processing for the dropped conglom.
+	 * @param newConglomActions Optional List.  If non-null then
+	 *  for each ConglomerateDescriptor for which we skip the
+	 *  "create new conglomerate" processing we will add a
+	 *  ConstantAction to this list.  The constant action can
+	 *  then be executed later (esp. by the caller) to create the
+	 *  new conglomerate, if needed.  If this argument is null and
+	 *  we skip creation of a new conglomerate, the new conglomerate
+	 *  is effectively ignored (which may be fine in some cases--
+	 *  ex. when dropping a table).
+	 */
+	void dropConglomerate(
+		ConglomerateDescriptor congDesc, TableDescriptor td,
+		boolean skipCreate, List newConglomActions,
+		Activation activation, LanguageConnectionContext lcc)
+		throws StandardException
+	{
+		// Get the properties on the old index before dropping.
+		Properties ixProps = new Properties();
+		loadIndexProperties(lcc, congDesc, ixProps);
+
+		// Drop the conglomerate.
+		ConglomerateDescriptor newBackingConglomCD = congDesc.drop(lcc, td);
+
+		/* If we don't need a new conglomerate then there's nothing
+		 * else to do.
+		 */
+		if (newBackingConglomCD == null)
+			return;
+
+		if (skipCreate)
+		{
+			/* We're skipping the "create new conglom" phase; if we have
+			 * a list in which to store the ConstantAction, then store it;
+			 * otherwise, the new conglomerate is effectively ignored.
+			 */
+			if (newConglomActions != null)
+			{
+				newConglomActions.add(
+					getConglomReplacementAction(
+						newBackingConglomCD, td, ixProps));
+			}
+		}
+		else
+		{
+			executeConglomReplacement(
+				getConglomReplacementAction(newBackingConglomCD, td, ixProps),
+				activation);
+		}
+
+		return;
+	}
+
+	/**
+	 * Get any table properties that exist for the received
+	 * index descriptor.
+	 */
+	private void loadIndexProperties(LanguageConnectionContext lcc,
+		ConglomerateDescriptor congDesc, Properties ixProps)
+		throws StandardException
+	{
+	   	ConglomerateController cc = 
+		   	lcc.getTransactionExecute().openConglomerate(
+			   	congDesc.getConglomerateNumber(),
+			   	false,
+			   	TransactionController.OPENMODE_FORUPDATE,
+			   	TransactionController.MODE_TABLE,
+			   	TransactionController.ISOLATION_SERIALIZABLE);
+
+		cc.getInternalTablePropertySet(ixProps);
+		cc.close();
+		return;
+	}
+
+	/**
+	 * Create a ConstantAction which, when executed, will create a
+	 * new conglomerate whose attributes match those of the received
+	 * ConglomerateDescriptor.
+	 *
+	 * @param srcCD Descriptor describing what the replacement
+	 *   physical conglomerate should look like
+	 * @param td Table descriptor for the table to which srcCD belongs
+	 * @param properties Properties from the old (dropped) conglom
+	 *  that should be "forwarded" to the new (replacement) conglom.
+	 */
+	ConstantAction getConglomReplacementAction(ConglomerateDescriptor srcCD,
+		TableDescriptor td, Properties properties) throws StandardException
+	{
+		/* Re-use CreateIndexActionConstantAction to do the work
+		 * of creating a new conglomerate.  The big difference
+		 * between creating an _index_ and creating an index
+		 * _conglomerate_ is that we don't need to create a new
+		 * ConglomerateDescriptor in the latter case.  Use of the
+		 * following constructor dictates that we want to create
+		 * a _conglomerate_ only--i.e. that no new conglomerate
+		 * descriptor is necessary.
+		 */
+		return new CreateIndexConstantAction(srcCD, td, properties);
+	}
+
+	/**
+	 * Execute the received ConstantAction, which will create a
+	 * new physical conglomerate (or find an existing physical
+	 * conglomerate that is "sharable") to replace some dropped
+	 * physical conglomerate.  Then find any conglomerate descriptors
+	 * which still reference the dropped physical conglomerate and
+	 * update them all to have a conglomerate number that points
+	 * to the conglomerate created by the ConstantAction.
+	 *
+	 * This method is called as part of DROP processing to handle
+	 * cases where a physical conglomerate that was shared by
+	 * multiple descriptors is dropped--in which case a new physical
+	 * conglomerate must be created to support the remaining
+	 * descriptors.
+	 *
+	 * @param replaceConglom Constant action which, when executed,
+	 *  will either create a new conglomerate or find an existing
+	 *  one that satisfies the ConstantAction's requirements.
+	 * @param activation Activation used when creating the conglom
+	 */
+	void executeConglomReplacement(ConstantAction replaceConglom,
+		Activation activation) throws StandardException
+	{
+		CreateIndexConstantAction replaceConglomAction =
+			(CreateIndexConstantAction)replaceConglom;
+
+		LanguageConnectionContext lcc =
+			activation.getLanguageConnectionContext();
+
+		DataDictionary dd = lcc.getDataDictionary();
+
+		// Create the new (replacment) backing conglomerate...
+		replaceConglomAction.executeConstantAction(activation);
+
+		/* Find all conglomerate descriptors that referenced the
+		 * old backing conglomerate and update them to have the
+		 * conglomerate number for the new backing conglomerate.
+		 */
+		ConglomerateDescriptor [] congDescs =
+			dd.getConglomerateDescriptors(
+				replaceConglomAction.getReplacedConglomNumber());
+
+		if (SanityManager.DEBUG)
+		{
+			/* There should be at least one descriptor requiring
+			 * an updated conglomerate number--namely, the one
+			 * corresponding to "srcCD" for which the constant
+			 * action was created (see getConglomReplacementAction()
+			 * above). There may be others, as well.
+			 */
+			if (congDescs.length < 1)
+			{
+				SanityManager.THROWASSERT(
+					"Should have found at least one conglomerate " +
+					"descriptor that needs an updated conglomerate " +
+					"number (due to a dropped index), but only " +
+					"found " + congDescs.length);
+			}
+		}
+
+		dd.updateConglomerateDescriptor(congDescs,
+			replaceConglomAction.getCreatedConglomNumber(),
+			lcc.getTransactionExecute());
+
+		return;
 	}
 }