From 91ed69fa1fb139587656402ac7c75ca7c5e485ec Mon Sep 17 00:00:00 2001 From: joshahicks Date: Wed, 6 Aug 2025 11:40:00 -0400 Subject: [PATCH 1/4] 0007015: DDL capture support for cross platform --- .../symmetric/db/mssql/MsSqlTriggerTemplate.java | 8 ++++++-- .../symmetric/common/ParameterConstants.java | 3 ++- .../extract/SelectFromSymDataSource.java | 8 ++++++++ .../symmetric/service/ITriggerRouterService.java | 2 ++ .../service/impl/TriggerRouterService.java | 6 +++++- .../main/resources/symmetric-default.properties | 11 +++++++++++ .../io/data/writer/DefaultDatabaseWriter.java | 15 +++++++++------ 7 files changed, 43 insertions(+), 10 deletions(-) diff --git a/symmetric-client/src/main/java/org/jumpmind/symmetric/db/mssql/MsSqlTriggerTemplate.java b/symmetric-client/src/main/java/org/jumpmind/symmetric/db/mssql/MsSqlTriggerTemplate.java index bbbcaf5825..4e3ae370e1 100644 --- a/symmetric-client/src/main/java/org/jumpmind/symmetric/db/mssql/MsSqlTriggerTemplate.java +++ b/symmetric-client/src/main/java/org/jumpmind/symmetric/db/mssql/MsSqlTriggerTemplate.java @@ -51,6 +51,10 @@ public MsSqlTriggerTemplate(ISymmetricDialect symmetricDialect) { String triggerExecuteAs = symmetricDialect.getParameterService().getString(ParameterConstants.MSSQL_TRIGGER_EXECUTE_AS, "self"); String defaultCatalog = symmetricDialect.getParameterService().is(ParameterConstants.MSSQL_INCLUDE_CATALOG_IN_TRIGGERS, true) ? "$(defaultCatalog)" : ""; + boolean ddlSendTable = symmetricDialect.getParameterService().is(ParameterConstants.TRIGGER_CAPTURE_DDL_SEND_TABLE); + String ddlEventType = ddlSendTable ? DataEventType.CREATE.getCode() : DataEventType.SQL.getCode(); + String ddlRowData = ddlSendTable ? "''" : " '\"delimiter " + delimiter + ";' + CHAR(13) + char(10) + replace(replace(@data.value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]', 'nvarchar(max)'),'\\','\\\\'),'\"','\\\"') + '\",ddl'"; + // @formatter:off emptyColumnTemplate = "''" ; stringColumnTemplate = "case when $(tableAlias).\"$(columnName)\" is null then '' else '\"' + replace(replace(convert("+ @@ -442,8 +446,8 @@ public MsSqlTriggerTemplate(ISymmetricDialect symmetricDialect) { " set @channelId = 'config'\n" + " insert into " + defaultCatalog + "$(defaultSchema)$(prefixName)_data\n" + " (table_name, event_type, trigger_hist_id, row_data, channel_id, source_node_id, create_time)\n" + -" values (@tableName, '" + DataEventType.SQL.getCode() + "', @histId,\n" + -" '\"delimiter " + delimiter + ";' + CHAR(13) + char(10) + replace(replace(@data.value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]', 'nvarchar(max)'),'\\','\\\\'),'\"','\\\"') + '\",ddl',\n" + +" values (@tableName, '" + ddlEventType + "', @histId,\n" + +" " + ddlRowData + ",\n" + " @channelId, " + defaultCatalog + "$(defaultSchema)$(prefixName)_node_disabled(), " + getCreateTimeExpression() + ")\n" + " end\n" + "end\n" + "---- go"); 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 001e5c3b8f..0a82ff839d 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 @@ -293,6 +293,7 @@ private ParameterConstants() { public final static String TRIGGER_CAPTURE_DDL_CHANGES = "trigger.capture.ddl.changes"; public final static String TRIGGER_CAPTURE_DDL_DELIMITER = "trigger.capture.ddl.delimiter"; public final static String TRIGGER_CAPTURE_DDL_CHECK_TRIGGER_HIST = "trigger.capture.ddl.check.trigger.hist"; + public final static String TRIGGER_CAPTURE_DDL_SEND_TABLE = "trigger.capture.ddl.send.table"; public final static String TRIGGER_USE_INSERT_DELETE_FOR_PRIMARY_KEY_CHANGES = "trigger.use.insert.delete.for.primary.key.changes"; public final static String DB_METADATA_IGNORE_CASE = "db.metadata.ignore.case"; public final static String DB_NATIVE_EXTRACTOR = "db.native.extractor"; @@ -481,7 +482,7 @@ private ParameterConstants() { public final static String SYNC_USE_READY_QUEUES = "sync.use.ready.queues"; public final static String KEEP_BULK_STAGING_FILES = "keep.bulk.staging.files"; public final static String MSSQL_BULK_LOAD_BCP_CODE_PAGE = "mssql.bulk.load.bcp.code.page"; - + public static Map getParameterMetaData() { return parameterMetaData; } diff --git a/symmetric-core/src/main/java/org/jumpmind/symmetric/extract/SelectFromSymDataSource.java b/symmetric-core/src/main/java/org/jumpmind/symmetric/extract/SelectFromSymDataSource.java index 44f8e10f3d..d9153e743d 100644 --- a/symmetric-core/src/main/java/org/jumpmind/symmetric/extract/SelectFromSymDataSource.java +++ b/symmetric-core/src/main/java/org/jumpmind/symmetric/extract/SelectFromSymDataSource.java @@ -21,6 +21,7 @@ package org.jumpmind.symmetric.extract; import java.sql.Types; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -275,6 +276,13 @@ protected boolean evaluateDeferTableLogging(OutgoingBatch batch, boolean deferIn } protected boolean processCreateEvent(TriggerHistory triggerHistory, String routerId, Data data) { + Trigger trigger = engine.getTriggerRouterService().getTriggerById(triggerHistory.getTriggerId()); + engine.getTriggerRouterService().syncTriggers(Collections.singletonList(trigger), null, true, false, false); + List latestTriggerHistory = engine.getTriggerRouterService().getActiveTriggerHistories(trigger); + for (TriggerHistory th : latestTriggerHistory) { + triggerHistory = th; + } + String oldData = data.getCsvData(CsvData.OLD_DATA); boolean sendSchemaExcludeIndices = false; boolean sendSchemaExcludeForeignKeys = false; diff --git a/symmetric-core/src/main/java/org/jumpmind/symmetric/service/ITriggerRouterService.java b/symmetric-core/src/main/java/org/jumpmind/symmetric/service/ITriggerRouterService.java index 200dcb842a..96b4cbda45 100644 --- a/symmetric-core/src/main/java/org/jumpmind/symmetric/service/ITriggerRouterService.java +++ b/symmetric-core/src/main/java/org/jumpmind/symmetric/service/ITriggerRouterService.java @@ -243,6 +243,8 @@ public String getTriggerName(DataEventType dml, int maxTriggerNameLength, Trigge public boolean syncTriggers(List triggers, ITriggerCreationListener listener, boolean force, boolean verifyInDatabase); + public boolean syncTriggers(List triggers, ITriggerCreationListener listener, boolean force, boolean verifyInDatabase, boolean useTableCache); + public boolean syncTriggers(Table table, boolean genAlways); public boolean syncTriggers(List tables, boolean genAlways); diff --git a/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/TriggerRouterService.java b/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/TriggerRouterService.java index 01b25f6493..9c34aeefbf 100644 --- a/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/TriggerRouterService.java +++ b/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/TriggerRouterService.java @@ -2224,6 +2224,10 @@ public void syncTrigger(Trigger trigger, ITriggerCreationListener listener, bool } public boolean syncTriggers(List triggers, ITriggerCreationListener listener, boolean force, boolean verifyInDatabase) { + return syncTriggers(triggers, listener, force, verifyInDatabase, true); + } + + public boolean syncTriggers(List triggers, ITriggerCreationListener listener, boolean force, boolean verifyInDatabase, boolean useTableCache) { if (clusterService.lock(ClusterConstants.SYNC_TRIGGERS)) { TriggerRouterContext context = new TriggerRouterContext(); long startTime = System.currentTimeMillis(); @@ -2290,7 +2294,7 @@ public boolean syncTriggers(List triggers, ITriggerCreationListener lis } } Map> triggerToTableSupportingInfo = getTriggerToTableSupportingInfo( - Collections.singletonList(trigger), allHistories, true, context); + Collections.singletonList(trigger), allHistories, useTableCache, context); updateOrCreateDatabaseTrigger(trigger, triggersForCurrentNode, null, force, verifyInDatabase, allHistories, false, triggerToTableSupportingInfo, context); } else { diff --git a/symmetric-core/src/main/resources/symmetric-default.properties b/symmetric-core/src/main/resources/symmetric-default.properties index 894aabe367..f7f4a26621 100644 --- a/symmetric-core/src/main/resources/symmetric-default.properties +++ b/symmetric-core/src/main/resources/symmetric-default.properties @@ -2402,6 +2402,17 @@ trigger.capture.ddl.delimiter=$ # Type: boolean trigger.capture.ddl.check.trigger.hist=true +# Determines if the DDL captured will be the actual ddl run against the source or if a Create table event +# will be captured for the changed table. This allows cross compatibility where an add columnn syntax +# may vary from one dialect to another. By sending a full create or alter table it will naturally apply +# the proper alters to match the target. + +# See: trigger.capture.ddl.changes +# DatabaseOverridable: false +# Tags: trigger +# Type: boolean +trigger.capture.ddl.send.table=false + # Enable or disabled use of create or replace syntax on Oracle and MS-SQL 2016 SP1 and newer. # # DatabaseOverridable: false 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 8ee2083aed..37d81598e9 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 @@ -88,7 +88,10 @@ public class DefaultDatabaseWriter extends AbstractDatabaseWriter { protected LogSqlBuilder logSqlBuilder = new LogSqlBuilder(); protected Boolean isCteExpression; protected boolean hasUncommittedDdl; - + protected List lookupKeys = null; + protected ArrayList changedColumnsList = new ArrayList<>(); + boolean[] nullKeyValues = null; + public DefaultDatabaseWriter(IDatabasePlatform platform) { this(platform, null, null); } @@ -345,7 +348,7 @@ protected LoadStatus delete(CsvData data, boolean useConflictDetection) { if (requireNewStatement(DmlType.DELETE, data, useConflictDetection, useConflictDetection, conflict.getDetectType())) { lastUseConflictDetection = useConflictDetection; - List lookupKeys = null; + lookupKeys = null; if (!useConflictDetection) { lookupKeys = targetTable.getPrimaryKeyColumnsAsList(); } else { @@ -408,7 +411,7 @@ protected LoadStatus delete(CsvData data, boolean useConflictDetection) { throw new IllegalStateException(msg); } lookupDataMap = getLookupDataMap(data, conflict); - boolean[] nullKeyValues = new boolean[lookupKeys.size()]; + nullKeyValues = new boolean[lookupKeys.size()]; for (int i = 0; i < lookupKeys.size(); i++) { Column column = lookupKeys.get(i); nullKeyValues[i] = !column.isRequired() @@ -467,7 +470,7 @@ protected LoadStatus update(CsvData data, boolean applyChangesOnly, boolean useC String[] rowData = getRowData(data, CsvData.ROW_DATA); String[] oldData = getRowData(data, CsvData.OLD_DATA); ArrayList changedColumnValueList = new ArrayList<>(); - ArrayList changedColumnsList = new ArrayList<>(); + changedColumnsList = new ArrayList<>(); for (int i = 0; i < targetTable.getColumnCount(); i++) { Column column = targetTable.getColumn(i); if (column != null) { @@ -484,7 +487,7 @@ protected LoadStatus update(CsvData data, boolean applyChangesOnly, boolean useC useConflictDetection, conflict.getDetectType())) { lastApplyChangesOnly = applyChangesOnly; lastUseConflictDetection = useConflictDetection; - List lookupKeys = null; + lookupKeys = null; if (!useConflictDetection) { lookupKeys = targetTable.getPrimaryKeyColumnsAsList(); } else { @@ -565,7 +568,7 @@ protected LoadStatus update(CsvData data, boolean applyChangesOnly, boolean useC throw new IllegalStateException(msg); } lookupDataMap = getLookupDataMap(data, conflict); - boolean[] nullKeyValues = new boolean[lookupKeys.size()]; + nullKeyValues = new boolean[lookupKeys.size()]; for (int i = 0; i < lookupKeys.size(); i++) { Column column = lookupKeys.get(i); // the isRequired is a bit of a hack. This nullKeyValues From df7559a0747eee8aaab9a78a94128a3cd0bc3b28 Mon Sep 17 00:00:00 2001 From: joshahicks Date: Mon, 11 Aug 2025 09:25:01 -0400 Subject: [PATCH 2/4] 0007015: DDL capture support for cross platform --- .../symmetric/db/mssql/MsSqlTriggerTemplate.java | 2 +- .../symmetric/db/AbstractTriggerTemplate.java | 1 + .../symmetric/extract/SelectFromSymDataSource.java | 14 +++++++++----- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/symmetric-client/src/main/java/org/jumpmind/symmetric/db/mssql/MsSqlTriggerTemplate.java b/symmetric-client/src/main/java/org/jumpmind/symmetric/db/mssql/MsSqlTriggerTemplate.java index 4e3ae370e1..ca324938fd 100644 --- a/symmetric-client/src/main/java/org/jumpmind/symmetric/db/mssql/MsSqlTriggerTemplate.java +++ b/symmetric-client/src/main/java/org/jumpmind/symmetric/db/mssql/MsSqlTriggerTemplate.java @@ -53,7 +53,7 @@ public MsSqlTriggerTemplate(ISymmetricDialect symmetricDialect) { : ""; boolean ddlSendTable = symmetricDialect.getParameterService().is(ParameterConstants.TRIGGER_CAPTURE_DDL_SEND_TABLE); String ddlEventType = ddlSendTable ? DataEventType.CREATE.getCode() : DataEventType.SQL.getCode(); - String ddlRowData = ddlSendTable ? "''" : " '\"delimiter " + delimiter + ";' + CHAR(13) + char(10) + replace(replace(@data.value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]', 'nvarchar(max)'),'\\','\\\\'),'\"','\\\"') + '\",ddl'"; + String ddlRowData = ddlSendTable ? "'" + AbstractTriggerTemplate.CREATE_EVENT_DDL_GENERATED + "'" : " '\"delimiter " + delimiter + ";' + CHAR(13) + char(10) + replace(replace(@data.value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]', 'nvarchar(max)'),'\\','\\\\'),'\"','\\\"') + '\",ddl'"; // @formatter:off emptyColumnTemplate = "''" ; diff --git a/symmetric-core/src/main/java/org/jumpmind/symmetric/db/AbstractTriggerTemplate.java b/symmetric-core/src/main/java/org/jumpmind/symmetric/db/AbstractTriggerTemplate.java index c1973f5562..7a56de38cd 100644 --- a/symmetric-core/src/main/java/org/jumpmind/symmetric/db/AbstractTriggerTemplate.java +++ b/symmetric-core/src/main/java/org/jumpmind/symmetric/db/AbstractTriggerTemplate.java @@ -62,6 +62,7 @@ abstract public class AbstractTriggerTemplate { protected static final String UPDATE_WITH_RELOAD_TRIGGER_TEMPLATE = "updateReloadTriggerTemplate"; protected static final String DELETE_TRIGGER_TEMPLATE = "deleteTriggerTemplate"; protected static final String INITIAL_LOAD_SQL_TEMPLATE = "initialLoadSqlTemplate"; + public static final String CREATE_EVENT_DDL_GENERATED = "ddl.generated"; protected Map sqlTemplates; protected String emptyColumnTemplate = "''"; protected String stringColumnTemplate; diff --git a/symmetric-core/src/main/java/org/jumpmind/symmetric/extract/SelectFromSymDataSource.java b/symmetric-core/src/main/java/org/jumpmind/symmetric/extract/SelectFromSymDataSource.java index d9153e743d..bc385d7f32 100644 --- a/symmetric-core/src/main/java/org/jumpmind/symmetric/extract/SelectFromSymDataSource.java +++ b/symmetric-core/src/main/java/org/jumpmind/symmetric/extract/SelectFromSymDataSource.java @@ -42,6 +42,7 @@ import org.jumpmind.symmetric.common.Constants; import org.jumpmind.symmetric.common.ErrorConstants; import org.jumpmind.symmetric.common.ParameterConstants; +import org.jumpmind.symmetric.db.AbstractTriggerTemplate; import org.jumpmind.symmetric.io.data.Batch; import org.jumpmind.symmetric.io.data.Batch.BatchType; import org.jumpmind.symmetric.io.data.CsvData; @@ -276,11 +277,14 @@ protected boolean evaluateDeferTableLogging(OutgoingBatch batch, boolean deferIn } protected boolean processCreateEvent(TriggerHistory triggerHistory, String routerId, Data data) { - Trigger trigger = engine.getTriggerRouterService().getTriggerById(triggerHistory.getTriggerId()); - engine.getTriggerRouterService().syncTriggers(Collections.singletonList(trigger), null, true, false, false); - List latestTriggerHistory = engine.getTriggerRouterService().getActiveTriggerHistories(trigger); - for (TriggerHistory th : latestTriggerHistory) { - triggerHistory = th; + if (data.getRowData() != null && data.getRowData().contains(AbstractTriggerTemplate.CREATE_EVENT_DDL_GENERATED)) { + data.putCsvData(CsvData.ROW_DATA, ""); + Trigger trigger = engine.getTriggerRouterService().getTriggerById(triggerHistory.getTriggerId()); + engine.getTriggerRouterService().syncTriggers(Collections.singletonList(trigger), null, true, false, false); + List latestTriggerHistory = engine.getTriggerRouterService().getActiveTriggerHistories(trigger); + for (TriggerHistory th : latestTriggerHistory) { + triggerHistory = th; + } } String oldData = data.getCsvData(CsvData.OLD_DATA); From a38f252b8f177a87eac1358d719490aaf4c03440 Mon Sep 17 00:00:00 2001 From: joshahicks Date: Wed, 27 Aug 2025 21:21:39 -0400 Subject: [PATCH 3/4] 0007015: DDL capture support for cross platform --- .../src/main/java/org/jumpmind/db/alter/ModelComparator.java | 2 +- .../java/org/jumpmind/db/platform/AbstractDdlBuilder.java | 5 +++++ .../src/main/java/org/jumpmind/db/platform/IDdlBuilder.java | 2 ++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/symmetric-db/src/main/java/org/jumpmind/db/alter/ModelComparator.java b/symmetric-db/src/main/java/org/jumpmind/db/alter/ModelComparator.java index 83e0c9371e..872ba31133 100644 --- a/symmetric-db/src/main/java/org/jumpmind/db/alter/ModelComparator.java +++ b/symmetric-db/src/main/java/org/jumpmind/db/alter/ModelComparator.java @@ -476,7 +476,7 @@ public List compareColumns(Table sourceTable, Column sourceColumn, changes.add(new ColumnSizeChange(sourceTable, sourceColumn, targetColumn.getSizeAsInt(), targetColumn.getScale())); } } - if (supportsDefaultValues() && !defaultValuesAreEqual(sourceColumn, targetColumn)) { + if (supportsDefaultValues() && ddlBuilder.supportDefaultValues() && !defaultValuesAreEqual(sourceColumn, targetColumn)) { log.info("The {} column on the {} table changed default value from {} to {} ", sourceColumn.getName(), sourceTable.getName(), sourceColumn.getDefaultValue(), targetColumn.getDefaultValue()); changes.add(new ColumnDefaultValueChange(sourceTable, sourceColumn, targetColumn.getDefaultValue())); diff --git a/symmetric-db/src/main/java/org/jumpmind/db/platform/AbstractDdlBuilder.java b/symmetric-db/src/main/java/org/jumpmind/db/platform/AbstractDdlBuilder.java index 3f58a2cd32..2d894dbda5 100644 --- a/symmetric-db/src/main/java/org/jumpmind/db/platform/AbstractDdlBuilder.java +++ b/symmetric-db/src/main/java/org/jumpmind/db/platform/AbstractDdlBuilder.java @@ -2735,4 +2735,9 @@ public String getTriggerDelimiterReplacementCharacters() { public void setTriggerDelimiterReplacementCharacters(String triggerDelimiterReplacementCharacters) { this.triggerDelimiterReplacementCharacters = triggerDelimiterReplacementCharacters; } + + @Override + public boolean supportDefaultValues() { + return true; + } } diff --git a/symmetric-db/src/main/java/org/jumpmind/db/platform/IDdlBuilder.java b/symmetric-db/src/main/java/org/jumpmind/db/platform/IDdlBuilder.java index ac827a69c8..91aeb09923 100644 --- a/symmetric-db/src/main/java/org/jumpmind/db/platform/IDdlBuilder.java +++ b/symmetric-db/src/main/java/org/jumpmind/db/platform/IDdlBuilder.java @@ -86,4 +86,6 @@ public interface IDdlBuilder { public void setTriggerDelimiterReplacementCharacters(String triggerDelimiterReplacementCharacters); public String getTriggerDelimiterReplacementCharacters(); + + public boolean supportDefaultValues(); } From 342aebfd7bda5ac7ad85963d618b86c07b6b99ac Mon Sep 17 00:00:00 2001 From: Andy W Date: Mon, 3 Nov 2025 10:23:47 -0500 Subject: [PATCH 4/4] 0007015: fix style violations --- .../db/mssql/MsSqlTriggerTemplate.java | 5 +++-- .../symmetric/common/ParameterConstants.java | 2 +- .../extract/SelectFromSymDataSource.java | 19 +++++++++---------- .../service/impl/TriggerRouterService.java | 4 ++-- .../db/platform/AbstractDdlBuilder.java | 4 ++-- .../org/jumpmind/db/platform/IDdlBuilder.java | 2 +- .../io/data/writer/DefaultDatabaseWriter.java | 2 +- 7 files changed, 19 insertions(+), 19 deletions(-) diff --git a/symmetric-client/src/main/java/org/jumpmind/symmetric/db/mssql/MsSqlTriggerTemplate.java b/symmetric-client/src/main/java/org/jumpmind/symmetric/db/mssql/MsSqlTriggerTemplate.java index 2a08604904..3ec6f70dd2 100644 --- a/symmetric-client/src/main/java/org/jumpmind/symmetric/db/mssql/MsSqlTriggerTemplate.java +++ b/symmetric-client/src/main/java/org/jumpmind/symmetric/db/mssql/MsSqlTriggerTemplate.java @@ -53,8 +53,9 @@ public MsSqlTriggerTemplate(ISymmetricDialect symmetricDialect) { : ""; boolean ddlSendTable = symmetricDialect.getParameterService().is(ParameterConstants.TRIGGER_CAPTURE_DDL_SEND_TABLE); String ddlEventType = ddlSendTable ? DataEventType.CREATE.getCode() : DataEventType.SQL.getCode(); - String ddlRowData = ddlSendTable ? "'" + AbstractTriggerTemplate.CREATE_EVENT_DDL_GENERATED + "'" : " '\"delimiter " + delimiter + ";' + CHAR(13) + char(10) + replace(replace(@data.value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]', 'nvarchar(max)'),'\\','\\\\'),'\"','\\\"') + '\",ddl'"; - + String ddlRowData = ddlSendTable ? "'" + AbstractTriggerTemplate.CREATE_EVENT_DDL_GENERATED + "'" + : " '\"delimiter " + delimiter + + ";' + CHAR(13) + char(10) + replace(replace(@data.value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]', 'nvarchar(max)'),'\\','\\\\'),'\"','\\\"') + '\",ddl'"; // @formatter:off emptyColumnTemplate = "''" ; stringColumnTemplate = "case when $(tableAlias).\"$(columnName)\" is null then '' else '\"' + replace(replace(convert("+ 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 52433c3a7e..a801dbe902 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 @@ -483,7 +483,7 @@ private ParameterConstants() { public final static String SYNC_USE_READY_QUEUES = "sync.use.ready.queues"; public final static String KEEP_BULK_STAGING_FILES = "keep.bulk.staging.files"; public final static String MSSQL_BULK_LOAD_BCP_CODE_PAGE = "mssql.bulk.load.bcp.code.page"; - + public static Map getParameterMetaData() { return parameterMetaData; } diff --git a/symmetric-core/src/main/java/org/jumpmind/symmetric/extract/SelectFromSymDataSource.java b/symmetric-core/src/main/java/org/jumpmind/symmetric/extract/SelectFromSymDataSource.java index d62a833f30..8c9af0b4c1 100644 --- a/symmetric-core/src/main/java/org/jumpmind/symmetric/extract/SelectFromSymDataSource.java +++ b/symmetric-core/src/main/java/org/jumpmind/symmetric/extract/SelectFromSymDataSource.java @@ -284,16 +284,15 @@ protected boolean evaluateDeferTableLogging(OutgoingBatch batch, boolean deferIn } protected boolean processCreateEvent(TriggerHistory triggerHistory, String routerId, Data data) { - if (data.getRowData() != null && data.getRowData().contains(AbstractTriggerTemplate.CREATE_EVENT_DDL_GENERATED)) { - data.putCsvData(CsvData.ROW_DATA, ""); - Trigger trigger = engine.getTriggerRouterService().getTriggerById(triggerHistory.getTriggerId()); - engine.getTriggerRouterService().syncTriggers(Collections.singletonList(trigger), null, true, false, false); - List latestTriggerHistory = engine.getTriggerRouterService().getActiveTriggerHistories(trigger); - for (TriggerHistory th : latestTriggerHistory) { - triggerHistory = th; - } - } - + if (data.getRowData() != null && data.getRowData().contains(AbstractTriggerTemplate.CREATE_EVENT_DDL_GENERATED)) { + data.putCsvData(CsvData.ROW_DATA, ""); + Trigger trigger = engine.getTriggerRouterService().getTriggerById(triggerHistory.getTriggerId()); + engine.getTriggerRouterService().syncTriggers(Collections.singletonList(trigger), null, true, false, false); + List latestTriggerHistory = engine.getTriggerRouterService().getActiveTriggerHistories(trigger); + for (TriggerHistory th : latestTriggerHistory) { + triggerHistory = th; + } + } String oldData = data.getCsvData(CsvData.OLD_DATA); boolean sendSchemaExcludeIndices = false; boolean sendSchemaExcludeForeignKeys = false; diff --git a/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/TriggerRouterService.java b/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/TriggerRouterService.java index cd81ac6154..3d22db89ef 100644 --- a/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/TriggerRouterService.java +++ b/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/TriggerRouterService.java @@ -2225,9 +2225,9 @@ public void syncTrigger(Trigger trigger, ITriggerCreationListener listener, bool } public boolean syncTriggers(List triggers, ITriggerCreationListener listener, boolean force, boolean verifyInDatabase) { - return syncTriggers(triggers, listener, force, verifyInDatabase, true); + return syncTriggers(triggers, listener, force, verifyInDatabase, true); } - + public boolean syncTriggers(List triggers, ITriggerCreationListener listener, boolean force, boolean verifyInDatabase, boolean useTableCache) { if (clusterService.lock(ClusterConstants.SYNC_TRIGGERS)) { TriggerRouterContext context = new TriggerRouterContext(); diff --git a/symmetric-db/src/main/java/org/jumpmind/db/platform/AbstractDdlBuilder.java b/symmetric-db/src/main/java/org/jumpmind/db/platform/AbstractDdlBuilder.java index 8cac8e0bde..199f5249ae 100644 --- a/symmetric-db/src/main/java/org/jumpmind/db/platform/AbstractDdlBuilder.java +++ b/symmetric-db/src/main/java/org/jumpmind/db/platform/AbstractDdlBuilder.java @@ -2737,9 +2737,9 @@ public String getTriggerDelimiterReplacementCharacters() { public void setTriggerDelimiterReplacementCharacters(String triggerDelimiterReplacementCharacters) { this.triggerDelimiterReplacementCharacters = triggerDelimiterReplacementCharacters; } - + @Override public boolean supportDefaultValues() { - return true; + return true; } } diff --git a/symmetric-db/src/main/java/org/jumpmind/db/platform/IDdlBuilder.java b/symmetric-db/src/main/java/org/jumpmind/db/platform/IDdlBuilder.java index 91aeb09923..3e975704f8 100644 --- a/symmetric-db/src/main/java/org/jumpmind/db/platform/IDdlBuilder.java +++ b/symmetric-db/src/main/java/org/jumpmind/db/platform/IDdlBuilder.java @@ -86,6 +86,6 @@ public interface IDdlBuilder { public void setTriggerDelimiterReplacementCharacters(String triggerDelimiterReplacementCharacters); public String getTriggerDelimiterReplacementCharacters(); - + public boolean supportDefaultValues(); } 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 ae72f567a2..65dc78dabd 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 @@ -92,7 +92,7 @@ public class DefaultDatabaseWriter extends AbstractDatabaseWriter { protected List lookupKeys = null; protected ArrayList changedColumnsList = new ArrayList<>(); boolean[] nullKeyValues = null; - + public DefaultDatabaseWriter(IDatabasePlatform platform) { this(platform, null, null); }