From 79c122fc68c9005d0619827e1c64e651c01a00de Mon Sep 17 00:00:00 2001 From: Iwao AVE! Date: Tue, 7 Dec 2021 22:01:55 +0900 Subject: [PATCH] Add hooks for `script` command --- .../apache/ibatis/migration/Environment.java | 32 ++- .../migration/commands/ScriptCommand.java | 38 +++ .../migration/hook/ScriptHookContext.java | 40 +++ src/site/xdoc/hooks.xml | 28 +-- .../migration/script_hook/ScriptHookTest.java | 227 ++++++++++++++++++ .../environments/development.properties | 86 +++++++ .../script_hook/testdir/hooks/After.js | 17 ++ .../script_hook/testdir/hooks/AfterEach.js | 17 ++ .../script_hook/testdir/hooks/Before.js | 17 ++ .../script_hook/testdir/hooks/BeforeEach.js | 17 ++ .../testdir/scripts/001_create_changelog.sql | 21 ++ .../testdir/scripts/002_second_migration.sql | 21 ++ .../testdir/scripts/003_third_migration.sql | 21 ++ 13 files changed, 565 insertions(+), 17 deletions(-) create mode 100644 src/main/java/org/apache/ibatis/migration/hook/ScriptHookContext.java create mode 100644 src/test/java/org/apache/ibatis/migration/script_hook/ScriptHookTest.java create mode 100644 src/test/java/org/apache/ibatis/migration/script_hook/testdir/environments/development.properties create mode 100644 src/test/java/org/apache/ibatis/migration/script_hook/testdir/hooks/After.js create mode 100644 src/test/java/org/apache/ibatis/migration/script_hook/testdir/hooks/AfterEach.js create mode 100644 src/test/java/org/apache/ibatis/migration/script_hook/testdir/hooks/Before.js create mode 100644 src/test/java/org/apache/ibatis/migration/script_hook/testdir/hooks/BeforeEach.js create mode 100644 src/test/java/org/apache/ibatis/migration/script_hook/testdir/scripts/001_create_changelog.sql create mode 100644 src/test/java/org/apache/ibatis/migration/script_hook/testdir/scripts/002_second_migration.sql create mode 100644 src/test/java/org/apache/ibatis/migration/script_hook/testdir/scripts/003_third_migration.sql diff --git a/src/main/java/org/apache/ibatis/migration/Environment.java b/src/main/java/org/apache/ibatis/migration/Environment.java index 27d4fbf8..663a613c 100644 --- a/src/main/java/org/apache/ibatis/migration/Environment.java +++ b/src/main/java/org/apache/ibatis/migration/Environment.java @@ -55,7 +55,11 @@ private enum SETTING_KEY { hook_after_each_down, hook_after_down, hook_before_new, - hook_after_new + hook_after_new, + hook_before_script, + hook_before_each_script, + hook_after_each_script, + hook_after_script } private static final List SETTING_KEYS; @@ -95,6 +99,11 @@ private enum SETTING_KEY { private final String hookBeforeNew; private final String hookAfterNew; + private final String hookBeforeScript; + private final String hookBeforeEachScript; + private final String hookAfterEachScript; + private final String hookAfterScript; + /** * Prefix used to lookup environment variable or system property. */ @@ -135,6 +144,11 @@ public Environment(File file) { this.hookBeforeNew = readProperty(prop, SETTING_KEY.hook_before_new.name()); this.hookAfterNew = readProperty(prop, SETTING_KEY.hook_after_new.name()); + this.hookBeforeScript = readProperty(prop, SETTING_KEY.hook_before_script.name()); + this.hookBeforeEachScript = readProperty(prop, SETTING_KEY.hook_before_each_script.name()); + this.hookAfterEachScript = readProperty(prop, SETTING_KEY.hook_after_each_script.name()); + this.hookAfterScript = readProperty(prop, SETTING_KEY.hook_after_script.name()); + // User defined variables. prop.entrySet().stream().filter(e -> !SETTING_KEYS.contains(e.getKey())) .forEach(e -> variables.put(e.getKey(), parser.replace((String) e.getValue()))); @@ -273,6 +287,22 @@ public String getHookAfterNew() { return hookAfterNew; } + public String getHookBeforeScript() { + return hookBeforeScript; + } + + public String getHookBeforeEachScript() { + return hookBeforeEachScript; + } + + public String getHookAfterEachScript() { + return hookAfterEachScript; + } + + public String getHookAfterScript() { + return hookAfterScript; + } + public Properties getVariables() { return variables; } diff --git a/src/main/java/org/apache/ibatis/migration/commands/ScriptCommand.java b/src/main/java/org/apache/ibatis/migration/commands/ScriptCommand.java index 27657513..c2a71f2e 100644 --- a/src/main/java/org/apache/ibatis/migration/commands/ScriptCommand.java +++ b/src/main/java/org/apache/ibatis/migration/commands/ScriptCommand.java @@ -20,11 +20,15 @@ import java.math.BigDecimal; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.StringTokenizer; import org.apache.ibatis.migration.Change; import org.apache.ibatis.migration.MigrationException; +import org.apache.ibatis.migration.hook.MigrationHook; +import org.apache.ibatis.migration.hook.ScriptHookContext; import org.apache.ibatis.migration.operations.DatabaseOperation; import org.apache.ibatis.migration.operations.StatusOperation; import org.apache.ibatis.migration.options.SelectedOptions; @@ -70,6 +74,8 @@ public void execute(String... sparams) { undo = comparison > 0; } + Map hookBindings = new HashMap<>(); + MigrationHook hook = createScriptHook(); List migrations = (scriptPending || scriptPendingUndo) ? new StatusOperation() .operate(getConnectionProvider(), getMigrationLoader(), getDatabaseOperationOption(), null).getCurrentStatus() : getMigrationLoader().getMigrations(); @@ -77,9 +83,20 @@ public void execute(String... sparams) { if (undo) { Collections.reverse(migrations); } + int count = 0; for (int i = 0; i < migrations.size(); i++) { Change change = migrations.get(i); if (shouldRun(change, v1, v2, scriptPending || scriptPendingUndo)) { + if (count == 0 && hook != null) { + hookBindings.put(MigrationHook.HOOK_CONTEXT, new ScriptHookContext(null, undo)); + hook.before(hookBindings); + printStream.println(); + } + if (hook != null) { + hookBindings.put(MigrationHook.HOOK_CONTEXT, new ScriptHookContext(change.clone(), undo)); + hook.beforeEach(hookBindings); + printStream.println(); + } printStream.println("-- " + change.getFilename()); Reader migrationReader = getMigrationLoader().getScriptReader(change, undo); char[] cbuf = new char[1024]; @@ -87,6 +104,7 @@ public void execute(String... sparams) { while ((l = migrationReader.read(cbuf)) > -1) { printStream.print(l == cbuf.length ? cbuf : Arrays.copyOf(cbuf, l)); } + count++; printStream.println(); printStream.println(); if (!undo) { @@ -95,8 +113,18 @@ public void execute(String... sparams) { printStream.println(generateVersionDelete(change)); } printStream.println(); + if (hook != null) { + hookBindings.put(MigrationHook.HOOK_CONTEXT, new ScriptHookContext(change.clone(), undo)); + hook.afterEach(hookBindings); + printStream.println(); + } } } + if (count > 0 && hook != null) { + hookBindings.put(MigrationHook.HOOK_CONTEXT, new ScriptHookContext(null, undo)); + hook.after(hookBindings); + printStream.println(); + } } catch (IOException e) { throw new MigrationException("Error generating script. Cause: " + e, e); } @@ -135,4 +163,14 @@ private String getDelimiter() { return delimiter.toString(); } + private MigrationHook createScriptHook() { + String before = environment().getHookBeforeScript(); + String beforeEach = environment().getHookBeforeEachScript(); + String afterEach = environment().getHookAfterEachScript(); + String after = environment().getHookAfterScript(); + if (before == null && beforeEach == null && afterEach == null && after == null) { + return null; + } + return createFileMigrationHook(before, beforeEach, afterEach, after); + } } diff --git a/src/main/java/org/apache/ibatis/migration/hook/ScriptHookContext.java b/src/main/java/org/apache/ibatis/migration/hook/ScriptHookContext.java new file mode 100644 index 00000000..7648b728 --- /dev/null +++ b/src/main/java/org/apache/ibatis/migration/hook/ScriptHookContext.java @@ -0,0 +1,40 @@ +/* + * Copyright 2010-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ibatis.migration.hook; + +import org.apache.ibatis.migration.Change; + +/** + * Hook context object that is available to before_new and after_new hooks. + */ +public class ScriptHookContext { + private final Change change; + private final boolean undo; + + public ScriptHookContext(Change change, boolean undo) { + super(); + this.change = change; + this.undo = undo; + } + + public Change getChange() { + return change; + } + + public boolean isUndo() { + return undo; + } +} diff --git a/src/site/xdoc/hooks.xml b/src/site/xdoc/hooks.xml index 9f030c28..ac63f863 100644 --- a/src/site/xdoc/hooks.xml +++ b/src/site/xdoc/hooks.xml @@ -1,7 +1,7 @@