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;
}
}