diff --git a/CHANGELOG.md b/CHANGELOG.md
index 57e32f49a..d6f263bd1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,10 @@ on [Keep a CHANGELOG](http://keepachangelog.com/). This project adheres to
## [Unreleased]
+## [2.0.19] - 2019-09-19
+### Added
+- New SystemCommands AddTrigger and RemoveTrigger to manage the trigger on the event_log table
+
## [2.0.18] - 2019-09-18
### Changed
- Use DefaultEnvelopeProvider in MetadataEventNumberUpdater directly to fix classloading errors during rebuild
diff --git a/event-store-management/src/main/java/uk/gov/justice/services/eventstore/management/untrigger/commands/AddRemoveTriggerCommandHandler.java b/event-store-management/src/main/java/uk/gov/justice/services/eventstore/management/untrigger/commands/AddRemoveTriggerCommandHandler.java
new file mode 100644
index 000000000..6ae82611a
--- /dev/null
+++ b/event-store-management/src/main/java/uk/gov/justice/services/eventstore/management/untrigger/commands/AddRemoveTriggerCommandHandler.java
@@ -0,0 +1,39 @@
+package uk.gov.justice.services.eventstore.management.untrigger.commands;
+
+import static java.lang.String.format;
+import static uk.gov.justice.services.jmx.api.command.AddTriggerCommand.ADD_TRIGGER;
+import static uk.gov.justice.services.jmx.api.command.RemoveTriggerCommand.REMOVE_TRIGGER;
+
+import uk.gov.justice.services.eventstore.management.untrigger.process.EventLogTriggerManipulator;
+import uk.gov.justice.services.jmx.api.command.AddTriggerCommand;
+import uk.gov.justice.services.jmx.api.command.RemoveTriggerCommand;
+import uk.gov.justice.services.jmx.command.HandlesSystemCommand;
+
+import javax.inject.Inject;
+
+import org.slf4j.Logger;
+
+public class AddRemoveTriggerCommandHandler {
+
+ @Inject
+ private EventLogTriggerManipulator eventLogTriggerManipulator;
+
+ @Inject
+ private Logger logger;
+
+ @HandlesSystemCommand(ADD_TRIGGER)
+ public void addTriggerToEventLogTable(final AddTriggerCommand addTriggerCommand) {
+
+ logger.info(format("Received command %s", addTriggerCommand.getName()));
+
+ eventLogTriggerManipulator.addTriggerToEventLogTable();
+ }
+
+ @HandlesSystemCommand(REMOVE_TRIGGER)
+ public void removeTriggerFromEventLogTable(final RemoveTriggerCommand removeTriggerCommand) {
+
+ logger.info(format("Received command %s", removeTriggerCommand.getName()));
+
+ eventLogTriggerManipulator.removeTriggerFromEventLogTable();
+ }
+}
diff --git a/event-store-management/src/main/java/uk/gov/justice/services/eventstore/management/untrigger/process/EventLogTriggerManipulator.java b/event-store-management/src/main/java/uk/gov/justice/services/eventstore/management/untrigger/process/EventLogTriggerManipulator.java
new file mode 100644
index 000000000..b9634f1c9
--- /dev/null
+++ b/event-store-management/src/main/java/uk/gov/justice/services/eventstore/management/untrigger/process/EventLogTriggerManipulator.java
@@ -0,0 +1,54 @@
+package uk.gov.justice.services.eventstore.management.untrigger.process;
+
+import static java.lang.String.format;
+
+import uk.gov.justice.services.eventsourcing.util.sql.triggers.DatabaseTriggerManipulator;
+
+import javax.inject.Inject;
+
+import org.slf4j.Logger;
+
+public class EventLogTriggerManipulator {
+
+ private static final String TRIGGER_NAME = "queue_publish_event";
+ private static final String TABLE_NAME = "event_log";
+ private static final String ACTION = "EXECUTE PROCEDURE update_publish_queue()";
+
+ @Inject
+ private EventStoreTriggerManipulatorProvider eventStoreTriggerManipulatorProvider;
+
+ @Inject
+ private Logger logger;
+
+ public void addTriggerToEventLogTable() {
+
+ final DatabaseTriggerManipulator databaseTriggerManipulator = eventStoreTriggerManipulatorProvider
+ .getDatabaseTriggerManipulator();
+
+ if (databaseTriggerManipulator.findTriggerOnTable(TRIGGER_NAME, TABLE_NAME).isPresent()) {
+ logger.warn(format("Trigger '%s' already exists on %s table", TRIGGER_NAME, TABLE_NAME));
+ } else {
+
+ databaseTriggerManipulator
+ .addInsertTriggerToTable(TRIGGER_NAME, TABLE_NAME, ACTION);
+
+ logger.info(format("Trigger '%s' successfully added to %s table", TRIGGER_NAME, TABLE_NAME));
+ }
+ }
+
+ public void removeTriggerFromEventLogTable() {
+
+ final DatabaseTriggerManipulator databaseTriggerManipulator = eventStoreTriggerManipulatorProvider
+ .getDatabaseTriggerManipulator();
+
+ if (databaseTriggerManipulator.findTriggerOnTable(TRIGGER_NAME, TABLE_NAME).isPresent()) {
+
+ databaseTriggerManipulator
+ .removeTriggerFromTable(TRIGGER_NAME, TABLE_NAME);
+
+ logger.info(format("Removed trigger '%s' from %s table", TRIGGER_NAME, TABLE_NAME));
+ } else {
+ logger.warn(format("No trigger named '%s' found on %s table", TRIGGER_NAME, TABLE_NAME));
+ }
+ }
+}
diff --git a/event-store-management/src/main/java/uk/gov/justice/services/eventstore/management/untrigger/process/EventStoreTriggerManipulatorProvider.java b/event-store-management/src/main/java/uk/gov/justice/services/eventstore/management/untrigger/process/EventStoreTriggerManipulatorProvider.java
new file mode 100644
index 000000000..0b2f573f4
--- /dev/null
+++ b/event-store-management/src/main/java/uk/gov/justice/services/eventstore/management/untrigger/process/EventStoreTriggerManipulatorProvider.java
@@ -0,0 +1,22 @@
+package uk.gov.justice.services.eventstore.management.untrigger.process;
+
+import uk.gov.justice.services.eventsourcing.source.core.EventStoreDataSourceProvider;
+import uk.gov.justice.services.eventsourcing.util.sql.triggers.DatabaseTriggerManipulator;
+import uk.gov.justice.services.eventsourcing.util.sql.triggers.DatabaseTriggerManipulatorFactory;
+
+import javax.inject.Inject;
+import javax.sql.DataSource;
+
+public class EventStoreTriggerManipulatorProvider {
+
+ @Inject
+ private EventStoreDataSourceProvider eventStoreDataSourceProvider;
+
+ @Inject
+ public DatabaseTriggerManipulatorFactory databaseTriggerManipulatorFactory;
+
+ public DatabaseTriggerManipulator getDatabaseTriggerManipulator() {
+ final DataSource defaultDataSource = eventStoreDataSourceProvider.getDefaultDataSource();
+ return databaseTriggerManipulatorFactory.databaseTriggerManipulator(defaultDataSource);
+ }
+}
diff --git a/event-store-management/src/main/java/uk/gov/justice/services/eventstore/management/validation/commands/ValidateCatchupCommandHandler.java b/event-store-management/src/main/java/uk/gov/justice/services/eventstore/management/validation/commands/ValidateCatchupCommandHandler.java
new file mode 100644
index 000000000..065dfed90
--- /dev/null
+++ b/event-store-management/src/main/java/uk/gov/justice/services/eventstore/management/validation/commands/ValidateCatchupCommandHandler.java
@@ -0,0 +1,22 @@
+package uk.gov.justice.services.eventstore.management.validation.commands;
+
+import static java.lang.String.format;
+import static uk.gov.justice.services.jmx.api.command.ValidateCatchupCommand.VALIDATE_CATCHUP;
+
+import uk.gov.justice.services.jmx.api.command.ValidateCatchupCommand;
+import uk.gov.justice.services.jmx.command.HandlesSystemCommand;
+
+import javax.inject.Inject;
+
+import org.slf4j.Logger;
+
+public class ValidateCatchupCommandHandler {
+
+ @Inject
+ private Logger logger;
+
+ @HandlesSystemCommand(VALIDATE_CATCHUP)
+ public void validateCatchup(final ValidateCatchupCommand validateCatchupCommand) {
+ logger.warn(format("Command %s not yet implemented", validateCatchupCommand.getName()));
+ }
+}
diff --git a/event-store-management/src/test/java/uk/gov/justice/services/eventstore/management/untrigger/commands/AddRemoveTriggerCommandHandlerTest.java b/event-store-management/src/test/java/uk/gov/justice/services/eventstore/management/untrigger/commands/AddRemoveTriggerCommandHandlerTest.java
new file mode 100644
index 000000000..c09195b61
--- /dev/null
+++ b/event-store-management/src/test/java/uk/gov/justice/services/eventstore/management/untrigger/commands/AddRemoveTriggerCommandHandlerTest.java
@@ -0,0 +1,65 @@
+package uk.gov.justice.services.eventstore.management.untrigger.commands;
+
+import static java.lang.String.format;
+import static org.junit.Assert.*;
+
+import org.junit.runner.RunWith;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.sameInstance;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.when;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.slf4j.Logger;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.*;
+
+import uk.gov.justice.services.eventstore.management.untrigger.process.EventLogTriggerManipulator;
+import uk.gov.justice.services.jmx.api.command.AddTriggerCommand;
+import uk.gov.justice.services.jmx.api.command.RemoveTriggerCommand;
+
+import javax.inject.Inject;
+
+@RunWith(MockitoJUnitRunner.class)
+public class AddRemoveTriggerCommandHandlerTest {
+
+ @Mock
+ private EventLogTriggerManipulator eventLogTriggerManipulator;
+
+ @Mock
+ private Logger logger;
+
+ @InjectMocks
+ private AddRemoveTriggerCommandHandler addRemoveTriggerCommandHandler;
+
+ @Test
+ public void shouldCallTheAddEventLogTriggerProcess() throws Exception {
+
+ final AddTriggerCommand addTriggerCommand = new AddTriggerCommand();
+
+ addRemoveTriggerCommandHandler.addTriggerToEventLogTable(addTriggerCommand);
+
+ verify(logger).info("Received command ADD_TRIGGER");
+ verify(eventLogTriggerManipulator).addTriggerToEventLogTable();
+ }
+
+ @Test
+ public void shouldCallTheRemoveEventLogTriggerProcess() throws Exception {
+
+ final RemoveTriggerCommand removeTriggerCommand = new RemoveTriggerCommand();
+
+ addRemoveTriggerCommandHandler.removeTriggerFromEventLogTable(removeTriggerCommand);
+
+ verify(logger).info("Received command REMOVE_TRIGGER");
+ verify(eventLogTriggerManipulator).removeTriggerFromEventLogTable();
+ }
+}
diff --git a/event-store-management/src/test/java/uk/gov/justice/services/eventstore/management/untrigger/process/EventLogTriggerManipulatorTest.java b/event-store-management/src/test/java/uk/gov/justice/services/eventstore/management/untrigger/process/EventLogTriggerManipulatorTest.java
new file mode 100644
index 000000000..cf6764372
--- /dev/null
+++ b/event-store-management/src/test/java/uk/gov/justice/services/eventstore/management/untrigger/process/EventLogTriggerManipulatorTest.java
@@ -0,0 +1,91 @@
+package uk.gov.justice.services.eventstore.management.untrigger.process;
+
+import static java.util.Optional.empty;
+import static java.util.Optional.of;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import uk.gov.justice.services.eventsourcing.util.sql.triggers.DatabaseTriggerManipulator;
+import uk.gov.justice.services.eventsourcing.util.sql.triggers.TriggerData;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.slf4j.Logger;
+
+@RunWith(MockitoJUnitRunner.class)
+public class EventLogTriggerManipulatorTest {
+
+ @Mock
+ private EventStoreTriggerManipulatorProvider eventStoreTriggerManipulatorProvider;
+
+ @Mock
+ private Logger logger;
+
+ @InjectMocks
+ private EventLogTriggerManipulator eventLogTriggerManipulator;
+
+ @Test
+ public void shouldAddTriggerToEventLogTable() throws Exception {
+
+ final DatabaseTriggerManipulator databaseTriggerManipulator = mock(DatabaseTriggerManipulator.class);
+
+ when(eventStoreTriggerManipulatorProvider.getDatabaseTriggerManipulator()).thenReturn(databaseTriggerManipulator);
+ when(databaseTriggerManipulator.findTriggerOnTable("queue_publish_event", "event_log")).thenReturn(empty());
+
+ eventLogTriggerManipulator.addTriggerToEventLogTable();
+
+ verify(databaseTriggerManipulator).addInsertTriggerToTable("queue_publish_event", "event_log", "EXECUTE PROCEDURE update_publish_queue()");
+ verify(logger).info("Trigger 'queue_publish_event' successfully added to event_log table");
+ }
+
+ @Test
+ public void shouldNotAddTriggerIfItAlreadyExists() throws Exception {
+
+ final TriggerData triggerData = mock(TriggerData.class);
+ final DatabaseTriggerManipulator databaseTriggerManipulator = mock(DatabaseTriggerManipulator.class);
+
+ when(eventStoreTriggerManipulatorProvider.getDatabaseTriggerManipulator()).thenReturn(databaseTriggerManipulator);
+ when(databaseTriggerManipulator.findTriggerOnTable("queue_publish_event", "event_log")).thenReturn(of(triggerData));
+
+ eventLogTriggerManipulator.addTriggerToEventLogTable();
+
+ verify(logger).warn("Trigger 'queue_publish_event' already exists on event_log table");
+ verify(databaseTriggerManipulator, never()).addInsertTriggerToTable(anyString(), anyString(), anyString());
+ }
+
+ @Test
+ public void shouldRemoveTriggerFromEventLogTable() throws Exception {
+
+ final DatabaseTriggerManipulator databaseTriggerManipulator = mock(DatabaseTriggerManipulator.class);
+ final TriggerData triggerData = mock(TriggerData.class);
+
+ when(eventStoreTriggerManipulatorProvider.getDatabaseTriggerManipulator()).thenReturn(databaseTriggerManipulator);
+ when(databaseTriggerManipulator.findTriggerOnTable("queue_publish_event", "event_log")).thenReturn(of(triggerData));
+
+ eventLogTriggerManipulator.removeTriggerFromEventLogTable();
+
+ verify(databaseTriggerManipulator).removeTriggerFromTable("queue_publish_event", "event_log");
+ verify(logger).info("Removed trigger 'queue_publish_event' from event_log table");
+ }
+
+ @Test
+ public void shouldNotRemoveTriggerIfItNoTriggerExists() throws Exception {
+
+ final DatabaseTriggerManipulator databaseTriggerManipulator = mock(DatabaseTriggerManipulator.class);
+
+ when(eventStoreTriggerManipulatorProvider.getDatabaseTriggerManipulator()).thenReturn(databaseTriggerManipulator);
+ when(databaseTriggerManipulator.findTriggerOnTable("queue_publish_event", "event_log")).thenReturn(empty());
+
+ eventLogTriggerManipulator.removeTriggerFromEventLogTable();
+
+ verify(logger).warn("No trigger named 'queue_publish_event' found on event_log table");
+ verify(databaseTriggerManipulator, never()).removeTriggerFromTable(anyString(), anyString());
+ }
+}
diff --git a/event-store-management/src/test/java/uk/gov/justice/services/eventstore/management/untrigger/process/EventStoreTriggerManipulatorProviderTest.java b/event-store-management/src/test/java/uk/gov/justice/services/eventstore/management/untrigger/process/EventStoreTriggerManipulatorProviderTest.java
new file mode 100644
index 000000000..df0e6f4a6
--- /dev/null
+++ b/event-store-management/src/test/java/uk/gov/justice/services/eventstore/management/untrigger/process/EventStoreTriggerManipulatorProviderTest.java
@@ -0,0 +1,54 @@
+package uk.gov.justice.services.eventstore.management.untrigger.process;
+
+import static org.junit.Assert.*;
+
+import org.junit.runner.RunWith;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.sameInstance;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.when;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.*;
+
+import uk.gov.justice.services.eventsourcing.source.core.EventStoreDataSourceProvider;
+import uk.gov.justice.services.eventsourcing.util.sql.triggers.DatabaseTriggerManipulator;
+import uk.gov.justice.services.eventsourcing.util.sql.triggers.DatabaseTriggerManipulatorFactory;
+
+import javax.inject.Inject;
+import javax.sql.DataSource;
+
+@RunWith(MockitoJUnitRunner.class)
+public class EventStoreTriggerManipulatorProviderTest {
+
+ @Mock
+ private EventStoreDataSourceProvider eventStoreDataSourceProvider;
+
+ @Mock
+ public DatabaseTriggerManipulatorFactory databaseTriggerManipulatorFactory;
+
+ @InjectMocks
+ private EventStoreTriggerManipulatorProvider eventStoreTriggerManipulatorProvider;
+
+ @Test
+ public void shouldCreateATriggerManipulaterWithTheCorrectEventStoreDataSource() throws Exception {
+
+ final DataSource eventStoreDataSource = mock(DataSource.class);
+ final DatabaseTriggerManipulator databaseTriggerManipulator = mock(DatabaseTriggerManipulator.class);
+
+ when(eventStoreDataSourceProvider.getDefaultDataSource()).thenReturn(eventStoreDataSource);
+ when(databaseTriggerManipulatorFactory.databaseTriggerManipulator(eventStoreDataSource)).thenReturn(databaseTriggerManipulator);
+
+ assertThat(eventStoreTriggerManipulatorProvider.getDatabaseTriggerManipulator(), is(databaseTriggerManipulator));
+ }
+}
diff --git a/event-store-management/src/test/java/uk/gov/justice/services/eventstore/management/validation/commands/ValidateCatchupCommandHandlerTest.java b/event-store-management/src/test/java/uk/gov/justice/services/eventstore/management/validation/commands/ValidateCatchupCommandHandlerTest.java
new file mode 100644
index 000000000..23d2a1abe
--- /dev/null
+++ b/event-store-management/src/test/java/uk/gov/justice/services/eventstore/management/validation/commands/ValidateCatchupCommandHandlerTest.java
@@ -0,0 +1,30 @@
+package uk.gov.justice.services.eventstore.management.validation.commands;
+
+import static org.mockito.Mockito.verify;
+
+import uk.gov.justice.services.jmx.api.command.ValidateCatchupCommand;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.slf4j.Logger;
+
+@RunWith(MockitoJUnitRunner.class)
+public class ValidateCatchupCommandHandlerTest {
+
+ @Mock
+ private Logger logger;
+
+ @InjectMocks
+ private ValidateCatchupCommandHandler validateCatchupCommandHandler;
+
+ @Test
+ public void shouldLogNotImplemented() throws Exception {
+
+ validateCatchupCommandHandler.validateCatchup(new ValidateCatchupCommand());
+
+ verify(logger).warn("Command VALIDATE_CATCHUP not yet implemented");
+ }
+}
diff --git a/event-store-util/pom.xml b/event-store-util/pom.xml
index e4c47dbdc..f935adac8 100644
--- a/event-store-util/pom.xml
+++ b/event-store-util/pom.xml
@@ -38,6 +38,12 @@
mockito-core
test
+
+ uk.gov.justice.event-store
+ test-utils-persistence
+ ${project.version}
+ test
+
diff --git a/event-store-util/src/main/java/uk/gov/justice/services/eventsourcing/util/sql/triggers/DatabaseTriggerManipulator.java b/event-store-util/src/main/java/uk/gov/justice/services/eventsourcing/util/sql/triggers/DatabaseTriggerManipulator.java
new file mode 100644
index 000000000..9c5777f34
--- /dev/null
+++ b/event-store-util/src/main/java/uk/gov/justice/services/eventsourcing/util/sql/triggers/DatabaseTriggerManipulator.java
@@ -0,0 +1,142 @@
+package uk.gov.justice.services.eventsourcing.util.sql.triggers;
+
+import static java.lang.String.format;
+import static java.util.Optional.empty;
+import static java.util.Optional.of;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+import javax.sql.DataSource;
+
+public class DatabaseTriggerManipulator {
+
+ private final DataSource dataSource;
+
+ public DatabaseTriggerManipulator(final DataSource dataSource) {
+ this.dataSource = dataSource;
+ }
+
+ public void removeTriggerFromTable(final String triggerName, final String tableName) {
+
+ executeStatement(format("DROP TRIGGER %s on %s CASCADE", triggerName, tableName));
+ }
+
+
+ public void addInsertTriggerToTable(final String triggerName, final String tableName, final String action) {
+
+ final String statement = format("CREATE TRIGGER %s AFTER INSERT ON %s FOR EACH ROW %s", triggerName, tableName, action);
+
+ executeStatement(statement);
+ }
+
+ public List listTriggersOnTable(final String tableName) {
+
+ final String statement =
+ "SELECT " +
+ "trigger_name, " +
+ "event_manipulation, " +
+ "action_statement, " +
+ "action_timing " +
+ "FROM information_schema.triggers " +
+ "WHERE event_object_table = ? " +
+ "ORDER BY event_object_table";
+
+ final List triggerDataList = new ArrayList<>();
+
+ try (final Connection connection = dataSource.getConnection();
+ final PreparedStatement preparedStatement = connection.prepareStatement(statement)) {
+
+ preparedStatement.setString(1, tableName);
+
+ try (final ResultSet resultSet = preparedStatement.executeQuery()) {
+
+ while (resultSet.next()) {
+ final String triggerName = resultSet.getString("trigger_name");
+ final String manipulationType = resultSet.getString("event_manipulation");
+ final String action = resultSet.getString("action_statement");
+ final String timing = resultSet.getString("action_timing");
+
+ final TriggerData triggerData = new TriggerData(
+ tableName,
+ triggerName,
+ manipulationType,
+ action,
+ timing
+ );
+
+ triggerDataList.add(triggerData);
+ }
+
+ }
+
+ } catch (final SQLException e) {
+ throw new TriggerManipulationFailedException(format("Failed to list triggers on %s table", tableName), e);
+ }
+
+ return triggerDataList;
+ }
+
+ public Optional findTriggerOnTable(final String triggerName, final String tableName) {
+
+ final String statement =
+ "SELECT " +
+ "event_object_table, " +
+ "event_manipulation, " +
+ "action_statement, " +
+ "action_timing " +
+ "FROM information_schema.triggers " +
+ "WHERE event_object_table = ? " +
+ "AND trigger_name = ? " +
+ "ORDER BY event_object_table";
+
+ try (final Connection connection = dataSource.getConnection();
+ final PreparedStatement preparedStatement = connection.prepareStatement(statement)) {
+
+ preparedStatement.setString(1, tableName);
+ preparedStatement.setString(2, triggerName);
+
+ try (final ResultSet resultSet = preparedStatement.executeQuery()) {
+
+ if (resultSet.next()) {
+ final String table = resultSet.getString("event_object_table");
+ final String manipulationType = resultSet.getString("event_manipulation");
+ final String action = resultSet.getString("action_statement");
+ final String timing = resultSet.getString("action_timing");
+
+ final TriggerData triggerData = new TriggerData(
+ table,
+ triggerName,
+ manipulationType,
+ action,
+ timing
+ );
+
+ return of(triggerData);
+ }
+ }
+
+ } catch (final SQLException e) {
+ throw new TriggerManipulationFailedException(format("Failed to find trigger on %s table", tableName), e);
+ }
+
+ return empty();
+ }
+
+ private void executeStatement(final String statement) {
+ try (final Connection connection = dataSource.getConnection();
+ final PreparedStatement preparedStatement = connection.prepareStatement(statement)) {
+
+ preparedStatement.execute();
+
+ } catch (final SQLException e) {
+ throw new TriggerManipulationFailedException(format("Failed to run statement '%s'", statement), e);
+ }
+
+ }
+}
diff --git a/event-store-util/src/main/java/uk/gov/justice/services/eventsourcing/util/sql/triggers/DatabaseTriggerManipulatorFactory.java b/event-store-util/src/main/java/uk/gov/justice/services/eventsourcing/util/sql/triggers/DatabaseTriggerManipulatorFactory.java
new file mode 100644
index 000000000..01ce23606
--- /dev/null
+++ b/event-store-util/src/main/java/uk/gov/justice/services/eventsourcing/util/sql/triggers/DatabaseTriggerManipulatorFactory.java
@@ -0,0 +1,10 @@
+package uk.gov.justice.services.eventsourcing.util.sql.triggers;
+
+import javax.sql.DataSource;
+
+public class DatabaseTriggerManipulatorFactory {
+
+ public DatabaseTriggerManipulator databaseTriggerManipulator(final DataSource dataSource) {
+ return new DatabaseTriggerManipulator(dataSource);
+ }
+}
diff --git a/event-store-util/src/main/java/uk/gov/justice/services/eventsourcing/util/sql/triggers/TriggerData.java b/event-store-util/src/main/java/uk/gov/justice/services/eventsourcing/util/sql/triggers/TriggerData.java
new file mode 100644
index 000000000..a0cf52120
--- /dev/null
+++ b/event-store-util/src/main/java/uk/gov/justice/services/eventsourcing/util/sql/triggers/TriggerData.java
@@ -0,0 +1,73 @@
+package uk.gov.justice.services.eventsourcing.util.sql.triggers;
+
+import java.util.Objects;
+
+public class TriggerData {
+
+ private final String tableName;
+ private final String triggerName;
+ private final String manipulationType;
+ private final String action;
+ private final String timing;
+
+ public TriggerData(
+ final String tableName,
+ final String triggerName,
+ final String manipulationType,
+ final String action,
+ final String timing) {
+ this.tableName = tableName;
+ this.triggerName = triggerName;
+ this.manipulationType = manipulationType;
+ this.action = action;
+ this.timing = timing;
+ }
+
+ public String getTableName() {
+ return tableName;
+ }
+
+ public String getTriggerName() {
+ return triggerName;
+ }
+
+ public String getManipulationType() {
+ return manipulationType;
+ }
+
+ public String getAction() {
+ return action;
+ }
+
+ public String getTiming() {
+ return timing;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (!(o instanceof TriggerData)) return false;
+ final TriggerData that = (TriggerData) o;
+ return Objects.equals(tableName, that.tableName) &&
+ Objects.equals(triggerName, that.triggerName) &&
+ Objects.equals(manipulationType, that.manipulationType) &&
+ Objects.equals(action, that.action) &&
+ Objects.equals(timing, that.timing);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(tableName, triggerName, manipulationType, action, timing);
+ }
+
+ @Override
+ public String toString() {
+ return "TriggerData{" +
+ "tableName='" + tableName + '\'' +
+ ", triggerName='" + triggerName + '\'' +
+ ", manipulationType='" + manipulationType + '\'' +
+ ", action='" + action + '\'' +
+ ", timing='" + timing + '\'' +
+ '}';
+ }
+}
diff --git a/event-store-util/src/main/java/uk/gov/justice/services/eventsourcing/util/sql/triggers/TriggerManipulationFailedException.java b/event-store-util/src/main/java/uk/gov/justice/services/eventsourcing/util/sql/triggers/TriggerManipulationFailedException.java
new file mode 100644
index 000000000..5f2672174
--- /dev/null
+++ b/event-store-util/src/main/java/uk/gov/justice/services/eventsourcing/util/sql/triggers/TriggerManipulationFailedException.java
@@ -0,0 +1,8 @@
+package uk.gov.justice.services.eventsourcing.util.sql.triggers;
+
+public class TriggerManipulationFailedException extends RuntimeException {
+
+ public TriggerManipulationFailedException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/event-store-util/src/test/java/uk/gov/justice/services/eventsourcing/util/sql/triggers/DatabaseTriggerManipulatorFactoryTest.java b/event-store-util/src/test/java/uk/gov/justice/services/eventsourcing/util/sql/triggers/DatabaseTriggerManipulatorFactoryTest.java
new file mode 100644
index 000000000..cd6e484da
--- /dev/null
+++ b/event-store-util/src/test/java/uk/gov/justice/services/eventsourcing/util/sql/triggers/DatabaseTriggerManipulatorFactoryTest.java
@@ -0,0 +1,32 @@
+package uk.gov.justice.services.eventsourcing.util.sql.triggers;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+
+import uk.gov.justice.services.test.utils.core.reflection.ReflectionUtil;
+
+import javax.sql.DataSource;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.runners.MockitoJUnitRunner;
+
+@RunWith(MockitoJUnitRunner.class)
+public class DatabaseTriggerManipulatorFactoryTest {
+
+ @InjectMocks
+ private DatabaseTriggerManipulatorFactory databaseTriggerManipulatorFactory;
+
+ @Test
+ public void shouldCreateDatabaseTriggerManipulator() throws Exception {
+
+ final DataSource dataSource = mock(DataSource.class);
+
+ final DatabaseTriggerManipulator databaseTriggerManipulator = databaseTriggerManipulatorFactory.databaseTriggerManipulator(dataSource);
+
+ assertThat(ReflectionUtil.getValueOfField(databaseTriggerManipulator, "dataSource", DataSource.class), is(dataSource));
+
+ }
+}
diff --git a/event-store-util/src/test/java/uk/gov/justice/services/eventsourcing/util/sql/triggers/DatabaseTriggerManipulatorIT.java b/event-store-util/src/test/java/uk/gov/justice/services/eventsourcing/util/sql/triggers/DatabaseTriggerManipulatorIT.java
new file mode 100644
index 000000000..8e24ca1c6
--- /dev/null
+++ b/event-store-util/src/test/java/uk/gov/justice/services/eventsourcing/util/sql/triggers/DatabaseTriggerManipulatorIT.java
@@ -0,0 +1,122 @@
+package uk.gov.justice.services.eventsourcing.util.sql.triggers;
+
+import static java.util.Optional.empty;
+import static org.junit.Assert.*;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.sameInstance;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.when;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.*;
+
+import uk.gov.justice.services.test.utils.persistence.TestJdbcDataSourceProvider;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.util.List;
+import java.util.Optional;
+
+import javax.sql.DataSource;
+
+
+public class DatabaseTriggerManipulatorIT {
+
+ private static final String CONTEXT_NAME = "framework";
+ private static final String TEMPORARY_TABLE_NAME = "for_testing_delete_me";
+
+ private final TestJdbcDataSourceProvider testJdbcDataSourceProvider = new TestJdbcDataSourceProvider();
+ private final DataSource eventStoreDataSource = testJdbcDataSourceProvider.getEventStoreDataSource(CONTEXT_NAME);
+
+ private DatabaseTriggerManipulator databaseTriggerManipulator = new DatabaseTriggerManipulator(eventStoreDataSource);
+
+ @Before
+ public void createTemporaryTable()throws Exception {
+
+ final String createTabelSql = "CREATE TABLE " + TEMPORARY_TABLE_NAME + " (name varchar(255))";
+
+ try(final Connection connection = eventStoreDataSource.getConnection();
+ final PreparedStatement preparedStatement = connection.prepareStatement(createTabelSql)) {
+ preparedStatement.execute();
+ }
+ }
+
+ @After
+ public void dropTemporaryTable()throws Exception {
+
+ final String dropTabelSql = "DROP TABLE " + TEMPORARY_TABLE_NAME;
+
+ try(final Connection connection = eventStoreDataSource.getConnection();
+ final PreparedStatement preparedStatement = connection.prepareStatement(dropTabelSql)) {
+ preparedStatement.execute();
+ }
+ }
+
+ @Test
+ public void shouldAddRemoveAndListTriggersOnTable() throws Exception {
+
+ final String triggerName = "temp_trigger";
+ final String action = "EXECUTE PROCEDURE update_publish_queue()";
+
+ assertThat(databaseTriggerManipulator.listTriggersOnTable(TEMPORARY_TABLE_NAME).isEmpty(), is(true));
+
+ databaseTriggerManipulator.addInsertTriggerToTable(triggerName, TEMPORARY_TABLE_NAME, action);
+
+ final List triggerData = databaseTriggerManipulator.listTriggersOnTable(TEMPORARY_TABLE_NAME);
+
+ assertThat(triggerData.size(), is(1));
+ assertThat(triggerData.get(0).getTriggerName(), is(triggerName));
+ assertThat(triggerData.get(0).getTableName(), is(TEMPORARY_TABLE_NAME));
+ assertThat(triggerData.get(0).getManipulationType(), is("INSERT"));
+ assertThat(triggerData.get(0).getAction(), is(action));
+ assertThat(triggerData.get(0).getTiming(), is("AFTER"));
+
+ databaseTriggerManipulator.removeTriggerFromTable(triggerName, TEMPORARY_TABLE_NAME);
+
+ assertThat(databaseTriggerManipulator.listTriggersOnTable(TEMPORARY_TABLE_NAME).isEmpty(), is(true));
+ }
+
+ @Test
+ public void shouldFindTriggerByItsName() throws Exception {
+
+ final String triggerName = "temp_trigger";
+ final String action = "EXECUTE PROCEDURE update_publish_queue()";
+
+ assertThat(databaseTriggerManipulator.listTriggersOnTable(TEMPORARY_TABLE_NAME).isEmpty(), is(true));
+
+ databaseTriggerManipulator.addInsertTriggerToTable(triggerName, TEMPORARY_TABLE_NAME, action);
+
+ final Optional triggerOnTable = databaseTriggerManipulator.findTriggerOnTable(triggerName, TEMPORARY_TABLE_NAME);
+
+ if(triggerOnTable.isPresent()) {
+
+ final TriggerData triggerData = triggerOnTable.get();
+
+ assertThat(triggerData.getTriggerName(), is(triggerName));
+ assertThat(triggerData.getTableName(), is(TEMPORARY_TABLE_NAME));
+ assertThat(triggerData.getManipulationType(), is("INSERT"));
+ assertThat(triggerData.getAction(), is(action));
+ assertThat(triggerData.getTiming(), is("AFTER"));
+ }
+ }
+
+ @Test
+ public void shouldReturnEmptyIfNoTriggerExists() throws Exception {
+
+ assertThat(databaseTriggerManipulator.findTriggerOnTable("some_other_trigger", TEMPORARY_TABLE_NAME), is(empty()));
+ }
+}
diff --git a/pom.xml b/pom.xml
index 6c3b0a207..7715856d6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -39,8 +39,8 @@
event-store
- 4.0.1
- 6.0.14
+ 4.1.0
+ 6.0.15
2.4.0
1.20.1
1.24.3