From b1614a01c853b8b1355b2f8023e65a6edd3e1b36 Mon Sep 17 00:00:00 2001 From: Philip Marzullo Date: Mon, 15 Jan 2024 13:02:33 -0500 Subject: [PATCH] 0006192: Adjusting unique indexes to non-unique when columns can be null should be able to be turned off by parameter --- .../symmetric/common/ParameterConstants.java | 1 + .../load/AbstractDataLoaderFactory.java | 2 + .../resources/symmetric-default.properties | 7 +++ .../data/writer/DatabaseWriterSettings.java | 9 ++++ .../io/data/writer/DefaultDatabaseWriter.java | 45 +++++++++++-------- 5 files changed, 45 insertions(+), 19 deletions(-) diff --git a/symmetric-core/src/main/java/org/jumpmind/symmetric/common/ParameterConstants.java b/symmetric-core/src/main/java/org/jumpmind/symmetric/common/ParameterConstants.java index 9c8c8f3b47..790e24f03a 100644 --- a/symmetric-core/src/main/java/org/jumpmind/symmetric/common/ParameterConstants.java +++ b/symmetric-core/src/main/java/org/jumpmind/symmetric/common/ParameterConstants.java @@ -176,6 +176,7 @@ private ParameterConstants() { public final static String CREATE_TABLE_WITHOUT_INDEXES = "create.table.without.indexes"; public final static String CREATE_TABLE_WITHOUT_PK_IF_SOURCE_WITHOUT_PK = "create.table.without.pk.if.source.without.pk"; public final static String CREATE_TABLE_NOT_NULL_COLUMNS = "create.table.not.null.columns.supported"; + public final static String CREATE_INDEX_CONVERT_UNIQUE_TO_NONUNIQUE_WHEN_COLUMNS_NOT_REQUIRED = "create.index.convert.unique.to.nonunique.when.columns.not.required"; public final static String STREAM_TO_FILE_ENABLED = "stream.to.file.enabled"; public final static String STREAM_TO_FILE_THRESHOLD = "stream.to.file.threshold.bytes"; public final static String STREAM_TO_FILE_TIME_TO_LIVE_MS = "stream.to.file.ttl.ms"; diff --git a/symmetric-core/src/main/java/org/jumpmind/symmetric/load/AbstractDataLoaderFactory.java b/symmetric-core/src/main/java/org/jumpmind/symmetric/load/AbstractDataLoaderFactory.java index 7d2e455a2b..33b370ee4f 100644 --- a/symmetric-core/src/main/java/org/jumpmind/symmetric/load/AbstractDataLoaderFactory.java +++ b/symmetric-core/src/main/java/org/jumpmind/symmetric/load/AbstractDataLoaderFactory.java @@ -70,6 +70,8 @@ public DatabaseWriterSettings buildParameterDatabaseWriterSettings(List byChannel = new HashMap(); Map byTable = new HashMap(); boolean multipleDefaultSettingsFound = false; diff --git a/symmetric-core/src/main/resources/symmetric-default.properties b/symmetric-core/src/main/resources/symmetric-default.properties index 9c485c74c3..2b60dcee70 100644 --- a/symmetric-core/src/main/resources/symmetric-default.properties +++ b/symmetric-core/src/main/resources/symmetric-default.properties @@ -1928,6 +1928,13 @@ create.table.without.pk.if.source.without.pk=true # Type: boolean create.table.not.null.columns.supported=true +# If set to true, then convert unique indexes to non-unique when one of the columns is defined +# as not required (defined with the NOT NULL constraint). +# +# DatabaseOverridable: true +# Type: boolean +create.index.convert.unique.to.nonunique.when.columns.not.required=true + # Indicates that the current value of the row should be recorded in the incoming_error table # # DatabaseOverridable: true diff --git a/symmetric-io/src/main/java/org/jumpmind/symmetric/io/data/writer/DatabaseWriterSettings.java b/symmetric-io/src/main/java/org/jumpmind/symmetric/io/data/writer/DatabaseWriterSettings.java index 9c372a1793..e082278b0a 100644 --- a/symmetric-io/src/main/java/org/jumpmind/symmetric/io/data/writer/DatabaseWriterSettings.java +++ b/symmetric-io/src/main/java/org/jumpmind/symmetric/io/data/writer/DatabaseWriterSettings.java @@ -62,6 +62,7 @@ public class DatabaseWriterSettings { protected IAlterDatabaseInterceptor[] alterDatabaseInterceptors; protected Set conflictLosingParentRows; protected boolean ignoreSqlDataEventFailures = false; + protected boolean createIndexConvertUniqueToNonuniqueWhenColumnsNotRequired = true; public void setAlterDatabaseInterceptors(IAlterDatabaseInterceptor[] alterDatabaseInterceptors) { this.alterDatabaseInterceptors = alterDatabaseInterceptors; @@ -357,4 +358,12 @@ public boolean isIgnoreSqlDataEventFailures() { public void setIgnoreSqlDataEventFailures(boolean ignoreSqlDataEventFailures) { this.ignoreSqlDataEventFailures = ignoreSqlDataEventFailures; } + + public boolean isCreateIndexConvertUniqueToNonuniqueWhenColumnsNotRequired() { + return createIndexConvertUniqueToNonuniqueWhenColumnsNotRequired; + } + + public void setCreateIndexConvertUniqueToNonuniqueWhenColumnsNotRequired(boolean createIndexConvertUniqueToNonuniqueWhenColumnsNotRequired) { + this.createIndexConvertUniqueToNonuniqueWhenColumnsNotRequired = createIndexConvertUniqueToNonuniqueWhenColumnsNotRequired; + } } diff --git a/symmetric-io/src/main/java/org/jumpmind/symmetric/io/data/writer/DefaultDatabaseWriter.java b/symmetric-io/src/main/java/org/jumpmind/symmetric/io/data/writer/DefaultDatabaseWriter.java index c189be12c2..97c3e6223a 100644 --- a/symmetric-io/src/main/java/org/jumpmind/symmetric/io/data/writer/DefaultDatabaseWriter.java +++ b/symmetric-io/src/main/java/org/jumpmind/symmetric/io/data/writer/DefaultDatabaseWriter.java @@ -39,6 +39,7 @@ import org.jumpmind.db.model.IIndex; import org.jumpmind.db.model.IndexColumn; import org.jumpmind.db.model.NonUniqueIndex; +import org.jumpmind.db.model.PlatformIndex; import org.jumpmind.db.model.Table; import org.jumpmind.db.model.TypeMap; import org.jumpmind.db.platform.DatabaseInfo; @@ -629,27 +630,33 @@ protected boolean create(CsvData data, boolean withoutDefaults) { table.removeAllColumnDefaults(); } } - if (!(getTargetPlatform().allowsUniqueIndexDuplicatesWithNulls())) { - for (Table table : db.getTables()) { - for (IIndex index : table.getUniqueIndices()) { - boolean needsFixed = false; - for (IndexColumn indexColumn : index.getColumns()) { - Column column = indexColumn.getColumn(); - if (column != null && !column.isRequired()) { - needsFixed = true; - log.warn( - "Detected Unique Index with potential for multiple null values in table: {} on column: {}. Adjusting index to be NonUnique.", - table.getName(), column.getName()); - break; - } - } - if (needsFixed) { - table.removeIndex(index); - IIndex newIndex = new NonUniqueIndex(index.getName()); + if (writerSettings.isCreateIndexConvertUniqueToNonuniqueWhenColumnsNotRequired()) { + if (!(getTargetPlatform().allowsUniqueIndexDuplicatesWithNulls())) { + for (Table table : db.getTables()) { + for (IIndex index : table.getUniqueIndices()) { + boolean needsFixed = false; for (IndexColumn indexColumn : index.getColumns()) { - newIndex.addColumn(indexColumn); + Column column = indexColumn.getColumn(); + if (column != null && !column.isRequired()) { + needsFixed = true; + log.warn( + "Detected Unique Index: {} with potential for multiple null values in table: {} on column: {}. Adjusting index to be NonUnique.", + index.getName(), table.getName(), column.getName()); + break; + } + } + if (needsFixed) { + table.removeIndex(index); + IIndex newIndex = new NonUniqueIndex(index.getName()); + for (IndexColumn indexColumn : index.getColumns()) { + newIndex.addColumn(indexColumn); + } + // Make sure to add the platform index info to the new non-unique index + for (PlatformIndex platformIndex : index.getPlatformIndexes().values()) { + newIndex.addPlatformIndex(platformIndex); + } + table.addIndex(newIndex); } - table.addIndex(newIndex); } } }