diff --git a/api/src/org/labkey/api/data/DatabaseMigrationService.java b/api/src/org/labkey/api/data/DatabaseMigrationService.java index 39099c7aac7..09bed1b6008 100644 --- a/api/src/org/labkey/api/data/DatabaseMigrationService.java +++ b/api/src/org/labkey/api/data/DatabaseMigrationService.java @@ -4,6 +4,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.labkey.api.data.DatabaseMigrationConfiguration.DefaultDatabaseMigrationConfiguration; +import org.labkey.api.data.DatabaseMigrationService.MigrationSchemaHandler.Sequence; import org.labkey.api.data.SimpleFilter.AndClause; import org.labkey.api.data.SimpleFilter.FilterClause; import org.labkey.api.data.SimpleFilter.InClause; @@ -21,6 +22,7 @@ import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.stream.Collectors; @@ -62,11 +64,18 @@ default void registerMigrationFilter(MigrationFilter filter) {} return null; } + default void copySourceTableToTargetTable(DatabaseMigrationConfiguration configuration, TableInfo sourceTable, TableInfo targetTable, DbSchemaType schemaType, Map schemaSequenceMap, MigrationSchemaHandler schemaHandler) {}; + interface MigrationSchemaHandler { + record Sequence(String schemaName, String tableName, String columnName, long lastValue) {} + // Marker for tables to declare themselves as site-wide (no container filtering) FieldKey SITE_WIDE_TABLE = FieldKey.fromParts("site-wide"); + // Dummy value returned from getContainerFieldKey() to ensure that custom getContainerClause() method is called + FieldKey DUMMY_FIELD_KEY = FieldKey.fromParts("DUMMY"); + DbSchema getSchema(); void beforeVerification(); @@ -86,7 +95,7 @@ interface MigrationSchemaHandler // and/or domain data filtering.) void afterTable(TableInfo sourceTable, TableInfo targetTable, SimpleFilter notCopiedFilter); - void afterSchema(); + void afterSchema(DatabaseMigrationConfiguration configuration, DbSchema sourceSchema, DbSchema targetSchema, Map> sequenceMap); } class DefaultMigrationSchemaHandler implements MigrationSchemaHandler @@ -248,7 +257,7 @@ public void afterTable(TableInfo sourceTable, TableInfo targetTable, SimpleFilte } @Override - public void afterSchema() + public void afterSchema(DatabaseMigrationConfiguration configuration, DbSchema sourceSchema, DbSchema targetSchema, Map> sequenceMap) { } } diff --git a/api/src/org/labkey/api/dataiterator/StatementDataIterator.java b/api/src/org/labkey/api/dataiterator/StatementDataIterator.java index 656689741df..8fb94466ab5 100644 --- a/api/src/org/labkey/api/dataiterator/StatementDataIterator.java +++ b/api/src/org/labkey/api/dataiterator/StatementDataIterator.java @@ -214,7 +214,7 @@ void init() _currentBinding = _bindings[0]; if (_batchSize < 1 && null == _rowIdIndex && null == _objectIdIndex && null == _objectUriIndex) - _batchSize = Math.max(10, 10000/Math.max(2,_bindings.length)); + _batchSize = Math.max(10, 10000/Math.max(2, _currentBinding.length)); Integer contextTxSize = null; if (_context.getConfigParameters() != null) diff --git a/core/src/org/labkey/core/CoreMigrationSchemaHandler.java b/core/src/org/labkey/core/CoreMigrationSchemaHandler.java index 00bb23ed590..8a786b2be35 100644 --- a/core/src/org/labkey/core/CoreMigrationSchemaHandler.java +++ b/core/src/org/labkey/core/CoreMigrationSchemaHandler.java @@ -3,6 +3,7 @@ import org.jetbrains.annotations.Nullable; import org.labkey.api.data.CompareType; import org.labkey.api.data.CoreSchema; +import org.labkey.api.data.DatabaseMigrationConfiguration; import org.labkey.api.data.DatabaseMigrationService; import org.labkey.api.data.DbSchema; import org.labkey.api.data.DbSchemaType; @@ -20,6 +21,7 @@ import org.labkey.api.util.GUID; import java.util.List; +import java.util.Map; import java.util.Set; class CoreMigrationSchemaHandler extends DatabaseMigrationService.DefaultMigrationSchemaHandler implements DatabaseMigrationService.MigrationFilter @@ -158,7 +160,7 @@ public SimpleFilter.FilterClause getContainerClause(TableInfo sourceTable, Field } @Override - public void afterSchema() + public void afterSchema(DatabaseMigrationConfiguration configuration, DbSchema sourceSchema, DbSchema targetSchema, Map> sequenceMap) { new SqlExecutor(getSchema()).execute("ALTER TABLE core.Containers ADD CONSTRAINT FK_Containers_Containers FOREIGN KEY (Parent) REFERENCES core.Containers(EntityId)"); new SqlExecutor(getSchema()).execute("ALTER TABLE core.ViewCategory ADD CONSTRAINT FK_ViewCategory_Parent FOREIGN KEY (Parent) REFERENCES core.ViewCategory(RowId)"); diff --git a/experiment/src/org/labkey/experiment/DataClassMigrationSchemaHandler.java b/experiment/src/org/labkey/experiment/DataClassMigrationSchemaHandler.java new file mode 100644 index 00000000000..ed1f80f9099 --- /dev/null +++ b/experiment/src/org/labkey/experiment/DataClassMigrationSchemaHandler.java @@ -0,0 +1,139 @@ +package org.labkey.experiment; + +import org.apache.logging.log4j.Logger; +import org.jetbrains.annotations.Nullable; +import org.labkey.api.collections.Sets; +import org.labkey.api.data.DatabaseMigrationConfiguration; +import org.labkey.api.data.DatabaseMigrationService; +import org.labkey.api.data.DatabaseMigrationService.DefaultMigrationSchemaHandler; +import org.labkey.api.data.DatabaseMigrationService.DomainFilter; +import org.labkey.api.data.DbSchema; +import org.labkey.api.data.DbSchemaType; +import org.labkey.api.data.DbScope; +import org.labkey.api.data.SQLFragment; +import org.labkey.api.data.SimpleFilter; +import org.labkey.api.data.SimpleFilter.FilterClause; +import org.labkey.api.data.SimpleFilter.InClause; +import org.labkey.api.data.SimpleFilter.OrClause; +import org.labkey.api.data.SimpleFilter.SQLClause; +import org.labkey.api.data.TableInfo; +import org.labkey.api.data.TableSelector; +import org.labkey.api.query.FieldKey; +import org.labkey.api.util.Formats; +import org.labkey.api.util.GUID; +import org.labkey.api.util.logging.LogHelper; +import org.labkey.experiment.api.DataClassDomainKind; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +class DataClassMigrationSchemaHandler extends DefaultMigrationSchemaHandler +{ + private static final Logger LOG = LogHelper.getLogger(DataClassMigrationSchemaHandler.class, "Data class migration status"); + + public DataClassMigrationSchemaHandler() + { + super(DataClassDomainKind.getSchema()); + } + + @Override + public @Nullable FieldKey getContainerFieldKey(TableInfo table) + { + FieldKey fieldKey = super.getContainerFieldKey(table); + return fieldKey != null ? fieldKey : DUMMY_FIELD_KEY; // "DUMMY" case is a data class that lacks an FK + } + + @Override + public FilterClause getContainerClause(TableInfo sourceTable, FieldKey containerFieldKey, Set containers) + { + final FilterClause clause; + + if (containerFieldKey != DUMMY_FIELD_KEY) + { + clause = super.getContainerClause(sourceTable, containerFieldKey, containers); + } + else + { + // There are a couple bad data class provisioned tables that lack an FK to exp.Data. In that case, craft the + // FilterClause explicitly. + clause = new SQLClause( + new SQLFragment("LSID IN (SELECT LSID FROM exp.Data WHERE Container") + .appendInClause(containers, sourceTable.getSqlDialect()) + .append(")") + ); + } + + return clause; + } + + @Override + public void addDomainDataFilter(OrClause orClause, DomainFilter filter, TableInfo sourceTable, FieldKey fKey, Set selectColumnNames) + { + // Data classes have a built-in Flag field + addDomainDataFlagFilter(orClause, filter, sourceTable, fKey, selectColumnNames); + } + + private static final Set SEQUENCE_TABLES = Sets.newCaseInsensitiveHashSet("protsequence", "nucsequence", "molecule"); + private static final Set SEQUENCE_IDS = new HashSet<>(); + + @Override + public void afterTable(TableInfo sourceTable, TableInfo targetTable, SimpleFilter notCopiedFilter) + { + // TODO: delete orphaned rows in exp.Data and exp.Object + Collection notCopiedLsids = new TableSelector(sourceTable, Collections.singleton("LSID"), notCopiedFilter, null).getCollection(String.class); + if (!notCopiedLsids.isEmpty()) + LOG.info(" {} rows not copied", Formats.commaf0.format(notCopiedLsids.size())); + + String name = sourceTable.getName(); + int idx = name.indexOf('_'); + name = name.substring(idx + 1); + + if (SEQUENCE_TABLES.contains(name)) + { + int startSize = SEQUENCE_IDS.size(); + new TableSelector(targetTable, Collections.singleton("Ident")).stream(String.class) + .map(ident -> { + int i = ident.indexOf(':'); + try + { + return Long.parseLong(ident.substring(i + 1)); + } + catch (Exception e) + { + throw new RuntimeException("Exception trying to split ident on ':' (" + ident + ")", e); + } + }) + .forEach(SEQUENCE_IDS::add); + LOG.info(" {} unique SequenceIds were added to the SequenceIdentity set", SEQUENCE_IDS.size() - startSize); + } + } + + @Override + public void afterSchema(DatabaseMigrationConfiguration configuration, DbSchema sourceSchema, DbSchema targetSchema, Map> sequenceMap) + { + // Experiment shouldn't mess with Biologics tables, but it gets the job done + + DbScope sourceScope = configuration.getSourceScope(); + DbScope targetScope = configuration.getTargetScope(); + DbSchema biologicsSourceSchema = sourceScope.getSchema("biologics", DbSchemaType.Migration); + DbSchema biologicsTargetSchema = targetScope.getSchema("biologics", DbSchemaType.Module); + + if (biologicsSourceSchema.existsInDatabase() && biologicsTargetSchema.existsInDatabase()) + { + TableInfo sourceTable = biologicsSourceSchema.getTable("SequenceIdentity"); + TableInfo targetTable = biologicsTargetSchema.getTable("SequenceIdentity"); + + DatabaseMigrationService.get().copySourceTableToTargetTable(configuration, sourceTable, targetTable, DbSchemaType.Module, sequenceMap.get("biologics"), new DefaultMigrationSchemaHandler(biologicsTargetSchema) + { + @Override + public FilterClause getContainerClause(TableInfo sourceTable, FieldKey containerFieldKey, Set containers) + { + return new InClause(FieldKey.fromParts("SequenceId"), SEQUENCE_IDS); + } + }); + } + } +} diff --git a/experiment/src/org/labkey/experiment/ExperimentMigrationSchemaHandler.java b/experiment/src/org/labkey/experiment/ExperimentMigrationSchemaHandler.java index 15fd0c3c177..24efd1d0426 100644 --- a/experiment/src/org/labkey/experiment/ExperimentMigrationSchemaHandler.java +++ b/experiment/src/org/labkey/experiment/ExperimentMigrationSchemaHandler.java @@ -3,7 +3,9 @@ import org.jetbrains.annotations.Nullable; import org.labkey.api.data.CompareType; import org.labkey.api.data.CompareType.CompareClause; -import org.labkey.api.data.DatabaseMigrationService; +import org.labkey.api.data.DatabaseMigrationConfiguration; +import org.labkey.api.data.DatabaseMigrationService.DefaultMigrationSchemaHandler; +import org.labkey.api.data.DbSchema; import org.labkey.api.data.SQLFragment; import org.labkey.api.data.SimpleFilter.AndClause; import org.labkey.api.data.SimpleFilter.FilterClause; @@ -15,10 +17,13 @@ import org.labkey.api.exp.OntologyManager; import org.labkey.api.query.FieldKey; import org.labkey.api.util.GUID; +import org.labkey.experiment.api.ExperimentServiceImpl; +import java.util.List; +import java.util.Map; import java.util.Set; -class ExperimentMigrationSchemaHandler extends DatabaseMigrationService.DefaultMigrationSchemaHandler +class ExperimentMigrationSchemaHandler extends DefaultMigrationSchemaHandler { public ExperimentMigrationSchemaHandler() { @@ -42,7 +47,7 @@ public void beforeSchema() { return switch (table.getName()) { - case "Alias", "ObjectLegacyNames" -> FieldKey.fromParts("DUMMY"); // Unused dummy value -- see override below + case "Alias", "ObjectLegacyNames" -> DUMMY_FIELD_KEY; // Unused dummy value -- see override below case "DataTypeExclusion" -> FieldKey.fromParts("ExcludedContainer"); case "PropertyDomain" -> FieldKey.fromParts("DomainId", "Container"); case "ProtocolApplication" -> FieldKey.fromParts("RunId", "Container"); @@ -50,6 +55,15 @@ public void beforeSchema() }; } + @Override + public List getTablesToCopy() + { + // No need to populate the MaterialIndexed table -- new server should be completely re-indexed after migration + List tables = super.getTablesToCopy(); + tables.remove(ExperimentServiceImpl.get().getTinfoMaterialIndexed()); + return tables; + } + @Override public FilterClause getContainerClause(TableInfo sourceTable, FieldKey containerFieldKey, Set containers) { @@ -104,7 +118,7 @@ public FilterClause getContainerClause(TableInfo sourceTable, FieldKey container } @Override - public void afterSchema() + public void afterSchema(DatabaseMigrationConfiguration configuration, DbSchema sourceSchema, DbSchema targetSchema, Map> sequenceMap) { new SqlExecutor(getSchema()).execute("ALTER TABLE exp.ExperimentRun ADD CONSTRAINT FK_Run_WorfklowTask FOREIGN KEY (WorkflowTask) REFERENCES exp.ProtocolApplication (RowId) MATCH SIMPLE ON DELETE SET NULL"); new SqlExecutor(getSchema()).execute("ALTER TABLE exp.Object ADD CONSTRAINT FK_Object_Object FOREIGN KEY (OwnerObjectId) REFERENCES exp.Object (ObjectId)"); diff --git a/experiment/src/org/labkey/experiment/ExperimentModule.java b/experiment/src/org/labkey/experiment/ExperimentModule.java index 3a7ee963ba6..7c57a79c011 100644 --- a/experiment/src/org/labkey/experiment/ExperimentModule.java +++ b/experiment/src/org/labkey/experiment/ExperimentModule.java @@ -25,24 +25,16 @@ import org.labkey.api.attachments.AttachmentService; import org.labkey.api.audit.AuditLogService; import org.labkey.api.audit.SampleTimelineAuditEvent; -import org.labkey.api.collections.CsvSet; import org.labkey.api.collections.LongHashMap; -import org.labkey.api.collections.Sets; import org.labkey.api.data.Container; import org.labkey.api.data.ContainerFilter; import org.labkey.api.data.ContainerManager; import org.labkey.api.data.CoreSchema; import org.labkey.api.data.DatabaseMigrationService; -import org.labkey.api.data.DatabaseMigrationService.DefaultMigrationSchemaHandler; -import org.labkey.api.data.DatabaseMigrationService.DomainFilter; import org.labkey.api.data.DbSchema; import org.labkey.api.data.JdbcType; import org.labkey.api.data.NameGenerator; import org.labkey.api.data.SQLFragment; -import org.labkey.api.data.SimpleFilter; -import org.labkey.api.data.SimpleFilter.FilterClause; -import org.labkey.api.data.SimpleFilter.OrClause; -import org.labkey.api.data.SimpleFilter.SQLClause; import org.labkey.api.data.SqlSelector; import org.labkey.api.data.TableInfo; import org.labkey.api.data.TableSelector; @@ -89,7 +81,6 @@ import org.labkey.api.ontology.Quantity; import org.labkey.api.ontology.Unit; import org.labkey.api.pipeline.PipelineService; -import org.labkey.api.query.FieldKey; import org.labkey.api.query.FilteredTable; import org.labkey.api.query.QueryService; import org.labkey.api.query.UserSchema; @@ -99,8 +90,6 @@ import org.labkey.api.settings.AppProps; import org.labkey.api.settings.OptionalFeatureService; import org.labkey.api.usageMetrics.UsageMetricsService; -import org.labkey.api.util.Formats; -import org.labkey.api.util.GUID; import org.labkey.api.util.JspTestCase; import org.labkey.api.util.PageFlowUtil; import org.labkey.api.util.StringUtilsLabKey; @@ -886,103 +875,8 @@ SELECT COUNT(DISTINCT DD.DomainURI) FROM } DatabaseMigrationService.get().registerSchemaHandler(new ExperimentMigrationSchemaHandler()); - - // Sample set materialized tables join on RowId to exp.Material. They also have a built-in Flag field. - DatabaseMigrationService.get().registerSchemaHandler(new DefaultMigrationSchemaHandler(SampleTypeDomainKind.getSchema()) { - @Override - public @Nullable FieldKey getContainerFieldKey(TableInfo table) - { - return FieldKey.fromParts("DUMMY"); // Unused dummy value -- see override below - } - - @Override - public FilterClause getContainerClause(TableInfo sourceTable, FieldKey containerFieldKey, Set containers) - { - return new SQLClause( - new SQLFragment("RowId IN (SELECT RowId FROM exp.Material WHERE Container") - .appendInClause(containers, sourceTable.getSqlDialect()) - .append(")") - ); - } - - @Override - public void addDomainDataFilter(OrClause orClause, DomainFilter filter, TableInfo sourceTable, FieldKey fKey, Set selectColumnNames) - { - // Sample-type-specific optimization - if (filter.column().equalsIgnoreCase("Flag")) - { - // Select all rows where the built-in flag column equals the filter value - orClause.addClause( - new SQLClause(new SQLFragment( - "RowId IN (SELECT RowId FROM exp.Material WHERE Container") - .appendInClause(filter.containers(), sourceTable.getSqlDialect()) - .append(" AND ObjectId IN (SELECT ObjectId FROM exp.ObjectProperty WHERE StringValue = ? AND PropertyId = ?))") - .add(filter.condition().getParamVals()[0]) - .add(getCommentPropertyId(sourceTable)) - ) - ); - } - else - { - addDomainDataStandardFilter(orClause, filter, sourceTable, fKey, selectColumnNames); - } - } - - @Override - public void afterTable(TableInfo sourceTable, TableInfo targetTable, SimpleFilter notCopiedFilter) - { - Collection notCopiedLsids = new TableSelector(sourceTable, new CsvSet("LSID, RowId"), notCopiedFilter, null).getCollection(String.class); - if (!notCopiedLsids.isEmpty()) - LOG.info(" {} rows not copied", Formats.commaf0.format(notCopiedLsids.size())); - } - }); - - DatabaseMigrationService.get().registerSchemaHandler(new DefaultMigrationSchemaHandler(DataClassDomainKind.getSchema()) { - @Override - public void addDomainDataFilter(OrClause orClause, DomainFilter filter, TableInfo sourceTable, FieldKey fKey, Set selectColumnNames) - { - // Data classes have a built-in Flag field - addDomainDataFlagFilter(orClause, filter, sourceTable, fKey, selectColumnNames); - } - - private static final Set SEQUENCE_TABLES = Sets.newCaseInsensitiveHashSet("protsequence", "nucsequence", "molecule"); - private static final Set SEQUENCE_IDS = new HashSet<>(); - - @Override - public void afterTable(TableInfo sourceTable, TableInfo targetTable, SimpleFilter notCopiedFilter) - { - Collection notCopiedLsids = new TableSelector(sourceTable, Collections.singleton("LSID"), notCopiedFilter, null).getCollection(String.class); - if (!notCopiedLsids.isEmpty()) - LOG.info(" {} rows not copied", Formats.commaf0.format(notCopiedLsids.size())); - - String name = sourceTable.getName(); - int idx = name.indexOf('_'); - name = name.substring(idx + 1); - - if (SEQUENCE_TABLES.contains(name)) - { - new TableSelector(targetTable, Collections.singleton("Ident")).stream(String.class) - .map(ident -> { - int i = ident.indexOf(':'); - try - { - return Long.parseLong(ident.substring(i + 1)); - } - catch (Exception e) - { - throw new RuntimeException("Exception trying to split ident on ':' (" + ident + ")", e); - } - }) - .forEach(SEQUENCE_IDS::add); - } - } - - @Override - public void afterSchema() - { - LOG.info("This is where we'll copy {} sequences into biologics.SequenceIdentity", SEQUENCE_IDS.size()); - } - }); + DatabaseMigrationService.get().registerSchemaHandler(new SampleTypeMigrationSchemaHandler()); + DatabaseMigrationService.get().registerSchemaHandler(new DataClassMigrationSchemaHandler()); } @Override diff --git a/experiment/src/org/labkey/experiment/SampleTypeMigrationSchemaHandler.java b/experiment/src/org/labkey/experiment/SampleTypeMigrationSchemaHandler.java new file mode 100644 index 00000000000..563b4304431 --- /dev/null +++ b/experiment/src/org/labkey/experiment/SampleTypeMigrationSchemaHandler.java @@ -0,0 +1,96 @@ +package org.labkey.experiment; + +import org.apache.logging.log4j.Logger; +import org.jetbrains.annotations.Nullable; +import org.labkey.api.collections.CsvSet; +import org.labkey.api.data.DatabaseMigrationService.DefaultMigrationSchemaHandler; +import org.labkey.api.data.DatabaseMigrationService.DomainFilter; +import org.labkey.api.data.SQLFragment; +import org.labkey.api.data.SimpleFilter; +import org.labkey.api.data.SimpleFilter.FilterClause; +import org.labkey.api.data.SimpleFilter.OrClause; +import org.labkey.api.data.SimpleFilter.SQLClause; +import org.labkey.api.data.TableInfo; +import org.labkey.api.data.TableSelector; +import org.labkey.api.exp.api.SampleTypeDomainKind; +import org.labkey.api.query.FieldKey; +import org.labkey.api.util.Formats; +import org.labkey.api.util.GUID; +import org.labkey.api.util.logging.LogHelper; + +import java.util.Collection; +import java.util.Set; + +class SampleTypeMigrationSchemaHandler extends DefaultMigrationSchemaHandler +{ + private static final Logger LOG = LogHelper.getLogger(SampleTypeMigrationSchemaHandler.class, "Sample type migration status"); + + public SampleTypeMigrationSchemaHandler() + { + super(SampleTypeDomainKind.getSchema()); + } + + @Override + public @Nullable FieldKey getContainerFieldKey(TableInfo table) + { + return DUMMY_FIELD_KEY; // Unused dummy value -- see override below + } + + @Override + public FilterClause getContainerClause(TableInfo sourceTable, FieldKey containerFieldKey, Set containers) + { + String joinColumnName = getJoinColumnName(sourceTable); + + return new SQLClause(new SQLFragment() + .appendIdentifier(joinColumnName) + .append(" IN (SELECT ") + .appendIdentifier(joinColumnName) + .append(" FROM exp.Material WHERE Container") + .appendInClause(containers, sourceTable.getSqlDialect()) + .append(")") + ); + } + + @Override + public void addDomainDataFilter(OrClause orClause, DomainFilter filter, TableInfo sourceTable, FieldKey fKey, Set selectColumnNames) + { + // Sample-type-specific optimization - joining to exp.Material instead of exp.Object is much faster + if (filter.column().equalsIgnoreCase("Flag")) + { + String joinColumnName = getJoinColumnName(sourceTable); + + // Select all rows where the built-in flag column equals the filter value + orClause.addClause( + new SQLClause(new SQLFragment() + .appendIdentifier(joinColumnName) + .append(" IN (SELECT ") + .appendIdentifier(joinColumnName) + .append(" FROM exp.Material WHERE Container") + .appendInClause(filter.containers(), sourceTable.getSqlDialect()) + .append(" AND ObjectId IN (SELECT ObjectId FROM exp.ObjectProperty WHERE StringValue = ? AND PropertyId = ?))") + .add(filter.condition().getParamVals()[0]) + .add(getCommentPropertyId(sourceTable)) + ) + ); + } + else + { + addDomainDataStandardFilter(orClause, filter, sourceTable, fKey, selectColumnNames); + } + } + + private String getJoinColumnName(TableInfo sourceTable) + { + // Provisioned sample type tables occasionally have no RowId column; hopefully they have an LSID column. + return sourceTable.getColumn("RowId") != null ? "RowId" : "LSID"; + } + + @Override + public void afterTable(TableInfo sourceTable, TableInfo targetTable, SimpleFilter notCopiedFilter) + { + // TODO: delete orphaned rows in exp.Material and exp.Object. Be sure to handle no RowId case. + Collection notCopiedLsids = new TableSelector(sourceTable, new CsvSet("LSID, RowId"), notCopiedFilter, null).getCollection(String.class); + if (!notCopiedLsids.isEmpty()) + LOG.info(" {} rows not copied", Formats.commaf0.format(notCopiedLsids.size())); + } +} diff --git a/wiki/src/org/labkey/wiki/WikiModule.java b/wiki/src/org/labkey/wiki/WikiModule.java index 8fe79a2adcf..c4e297f05cf 100644 --- a/wiki/src/org/labkey/wiki/WikiModule.java +++ b/wiki/src/org/labkey/wiki/WikiModule.java @@ -25,8 +25,10 @@ import org.labkey.api.attachments.AttachmentService; import org.labkey.api.data.Container; import org.labkey.api.data.ContainerManager; +import org.labkey.api.data.DatabaseMigrationConfiguration; import org.labkey.api.data.DatabaseMigrationService; import org.labkey.api.data.DatabaseMigrationService.DefaultMigrationSchemaHandler; +import org.labkey.api.data.DbSchema; import org.labkey.api.data.SqlExecutor; import org.labkey.api.data.TableInfo; import org.labkey.api.module.CodeOnlyModule; @@ -140,7 +142,7 @@ public List getTablesToCopy() } @Override - public void afterSchema() + public void afterSchema(DatabaseMigrationConfiguration configuration, DbSchema sourceSchema, DbSchema targetSchema, Map> sequenceMap) { new SqlExecutor(getSchema()).execute("ALTER TABLE comm.Pages ADD CONSTRAINT FK_Pages_PageVersions FOREIGN KEY (PageVersionId) REFERENCES comm.PageVersions (RowId)"); new SqlExecutor(getSchema()).execute("ALTER TABLE comm.Pages ADD CONSTRAINT FK_Pages_Parent FOREIGN KEY (Parent) REFERENCES comm.Pages (RowId)");