diff --git a/jOOQ-migrations-maven/src/main/java/org/jooq/migrations/maven/AddSnapshotMojo.java b/jOOQ-migrations-maven/src/main/java/org/jooq/migrations/maven/AddSnapshotMojo.java
index 1664949e0b..a4ffea314d 100644
--- a/jOOQ-migrations-maven/src/main/java/org/jooq/migrations/maven/AddSnapshotMojo.java
+++ b/jOOQ-migrations-maven/src/main/java/org/jooq/migrations/maven/AddSnapshotMojo.java
@@ -38,14 +38,14 @@
package org.jooq.migrations.maven;
import static java.lang.Boolean.TRUE;
+import static java.util.Arrays.asList;
import static org.apache.maven.plugins.annotations.LifecyclePhase.GENERATE_SOURCES;
import static org.apache.maven.plugins.annotations.ResolutionScope.TEST;
import java.io.File;
-import java.io.FileWriter;
-import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
+import java.util.Arrays;
import java.util.EnumSet;
import org.jooq.DDLExportConfiguration;
@@ -55,7 +55,6 @@ import org.jooq.HistoryVersion;
import org.jooq.Meta;
import org.jooq.Migration;
import org.jooq.Queries;
-import org.jooq.exception.DataMigrationVerificationException;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
@@ -106,6 +105,6 @@ public class AddSnapshotMojo extends AbstractMigrateMojo {
if (getLog().isInfoEnabled())
getLog().info("Writing snapshot to: " + file + "\n" + export);
- Files.writeString(file.toPath(), export, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
+ Files.write(file.toPath(), asList(export), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
}
}
diff --git a/jOOQ-migrations-maven/src/main/java/org/jooq/migrations/maven/AddUntrackedMojo.java b/jOOQ-migrations-maven/src/main/java/org/jooq/migrations/maven/AddUntrackedMojo.java
index 756b9e3e56..1504963f0f 100644
--- a/jOOQ-migrations-maven/src/main/java/org/jooq/migrations/maven/AddUntrackedMojo.java
+++ b/jOOQ-migrations-maven/src/main/java/org/jooq/migrations/maven/AddUntrackedMojo.java
@@ -37,23 +37,17 @@
*/
package org.jooq.migrations.maven;
-import static java.lang.Boolean.TRUE;
+import static java.util.Arrays.asList;
import static org.apache.maven.plugins.annotations.LifecyclePhase.GENERATE_SOURCES;
import static org.apache.maven.plugins.annotations.ResolutionScope.TEST;
import java.io.File;
-import java.io.FileWriter;
-import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
-import java.util.EnumSet;
+import java.util.Arrays;
import org.jooq.Commit;
-import org.jooq.DDLExportConfiguration;
-import org.jooq.DDLFlag;
import org.jooq.History;
-import org.jooq.HistoryVersion;
-import org.jooq.Meta;
import org.jooq.Migration;
import org.jooq.Queries;
@@ -103,7 +97,7 @@ public class AddUntrackedMojo extends AbstractMigrateMojo {
sb.append(untracked);
sb.append("\n");
- Files.writeString(file.toPath(), sb.toString(), StandardOpenOption.CREATE, StandardOpenOption.APPEND);
+ Files.write(file.toPath(), asList(sb.toString()), StandardOpenOption.CREATE, StandardOpenOption.APPEND);
}
}
diff --git a/jOOQ/src/main/java/org/jooq/ContentType.java b/jOOQ/src/main/java/org/jooq/ContentType.java
index a3fb1d647f..d74e70f658 100644
--- a/jOOQ/src/main/java/org/jooq/ContentType.java
+++ b/jOOQ/src/main/java/org/jooq/ContentType.java
@@ -46,8 +46,18 @@ import org.jetbrains.annotations.ApiStatus.Experimental;
* contained in {@link Commit#delta()} will be processed in the following order:
*
*
- * - {@link ContentType#INCREMENT}
- * - {@link ContentType#SCHEMA}
+ * - {@link #SNAPSHOT} (replacing all other contents of this {@link Commit} as
+ * well as previous commits, if migrating from {@link Commit#root()})
+ * - {@link #INCREMENT}
+ * - {@link #SCRIPT}
+ * - {@link #SCHEMA}
+ *
+ *
+ * When undoing a migration, the order is:
+ *
+ * - {@link #SCHEMA}
+ * - {@link #DECREMENT}
+ *
*
*/
@Experimental
@@ -102,6 +112,9 @@ public enum ContentType {
*
* In order to restore a database, or install a new one, we don't have to go
* back any further than the snapshot.
+ *
+ * This API is part of a commercial only feature. To use this feature,
+ * please use the jOOQ Professional Edition or the jOOQ Enterprise Edition.
*/
SNAPSHOT,
diff --git a/jOOQ/src/main/java/org/jooq/Files.java b/jOOQ/src/main/java/org/jooq/Files.java
index 9cc57dd915..9d40922df2 100644
--- a/jOOQ/src/main/java/org/jooq/Files.java
+++ b/jOOQ/src/main/java/org/jooq/Files.java
@@ -69,6 +69,9 @@ public interface Files extends Iterable {
*
* This is EXPERIMENTAL functionality and subject to change in future jOOQ
* versions.
+ *
+ * This API is part of a commercial only feature. To use this feature,
+ * please use the jOOQ Professional Edition or the jOOQ Enterprise Edition.
*/
@Nullable
@Experimental
diff --git a/jOOQ/src/main/java/org/jooq/Migration.java b/jOOQ/src/main/java/org/jooq/Migration.java
index 75413982e0..01b09cc990 100644
--- a/jOOQ/src/main/java/org/jooq/Migration.java
+++ b/jOOQ/src/main/java/org/jooq/Migration.java
@@ -68,6 +68,9 @@ public interface Migration extends Scope {
/**
* The last {@link ContentType#SNAPSHOT} commit that is being migrated from,
* or null if there's no snapshot.
+ *
+ * This API is part of a commercial only feature. To use this feature,
+ * please use the jOOQ Professional Edition or the jOOQ Enterprise Edition.
*/
@Nullable
Commit fromSnapshot();
diff --git a/jOOQ/src/main/java/org/jooq/impl/CommitImpl.java b/jOOQ/src/main/java/org/jooq/impl/CommitImpl.java
index ec35e0f3c8..593af622e6 100644
--- a/jOOQ/src/main/java/org/jooq/impl/CommitImpl.java
+++ b/jOOQ/src/main/java/org/jooq/impl/CommitImpl.java
@@ -40,10 +40,12 @@ package org.jooq.impl;
import static org.jooq.ContentType.DECREMENT;
import static org.jooq.ContentType.INCREMENT;
import static org.jooq.ContentType.SCHEMA;
+import static org.jooq.ContentType.SCRIPT;
import static org.jooq.ContentType.SNAPSHOT;
import static org.jooq.impl.Tools.EMPTY_SOURCE;
import static org.jooq.impl.Tools.anyMatch;
import static org.jooq.impl.Tools.filter;
+import static org.jooq.impl.Tools.iterable;
import static org.jooq.tools.StringUtils.isBlank;
import java.util.ArrayDeque;
@@ -74,6 +76,7 @@ import org.jooq.Source;
import org.jooq.Tag;
import org.jooq.Version;
import org.jooq.exception.DataMigrationVerificationException;
+import org.jooq.impl.DefaultParseContext.IgnoreQuery;
import org.jooq.tools.StringUtils;
/**
@@ -108,6 +111,20 @@ final class CommitImpl extends AbstractNode implements Commit {
this.tags = new ArrayList<>();
this.delta = map(delta, false);
this.valid = valid;
+
+ if (delta.size() > this.delta.size()) {
+ throw new DataMigrationVerificationException("Path is ambiguous within commit: " + duplicatePath(delta));
+ }
+ }
+
+ private static final String duplicatePath(Collection extends File> files) {
+ Set paths = new HashSet<>();
+
+ for (File file : files)
+ if (!paths.add(file.path()))
+ return file.path();
+
+ return null;
}
private CommitImpl(CommitImpl copy, boolean newValid) {
@@ -397,21 +414,6 @@ final class CommitImpl extends AbstractNode implements Commit {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -490,74 +492,70 @@ final class CommitImpl extends AbstractNode implements Commit {
for (Commit commit : commitHistory) {
List commitFiles = new ArrayList<>(commit.delta());
- // [#9506] Migrations from root to a snapshot can be skipped
- // TODO: effectively skip all intermediary steps
-
-
-
if (isRoot && anyMatch(commitFiles, f -> f.type() == SNAPSHOT)) {
- result.clear();
+ configuration().requireCommercial(() -> "Snapshots are a commercial only feature. Please upgrade to the jOOQ Professional Edition or jOOQ Enterprise Edition.");
+
+
+
+
+
+
+
+
+
+
+
+
+
- // [#9506] TODO: Are there impacts on other maps?
- for (File f : commitFiles)
- if (f.type() == SNAPSHOT)
- result.put(f.path(), f);
- fromSnapshotCommit = commit;
- continue commitLoop;
}
// Deletions
- Iterator deletions = commitFiles.iterator();
- while (deletions.hasNext()) {
- File file = deletions.next();
+ Iterator deletions = filter(commitFiles.iterator(), f -> f.content() == null);
+ for (File file : iterable(deletions)) {
+ hasDeletions |= true;
+ String path = file.path();
+ String tempKey = tempHistoryKeys.remove(path);
+ String tempRemove = tempKey != null ? tempKey : path;
+ String key = historyKeys.remove(path);
+ String remove = key != null ? key : path;
- if (file.content() == null) {
- hasDeletions |= true;
- String path = file.path();
- String tempKey = tempHistoryKeys.remove(path);
- String tempRemove = tempKey != null ? tempKey : path;
- String key = historyKeys.remove(path);
- String remove = key != null ? key : path;
+ if (recordingResult && result.remove(tempRemove) == null && file.type() == INCREMENT && history.containsKey(tempRemove))
+ result.put(tempRemove, file);
- if (recordingResult && result.remove(tempRemove) == null && file.type() == INCREMENT && history.containsKey(tempRemove))
- result.put(tempRemove, file);
- else if (recordingResult && result.remove(remove) == null && file.type() == SCHEMA && history.containsKey(remove))
- result.put(remove, file);
- else
- history.remove(tempRemove);
+ // TODO: Support deletions of scripts
+ else if (recordingResult && result.remove(remove) == null && file.type() == SCHEMA && history.containsKey(remove))
+ result.put(remove, file);
+ else
+ history.remove(tempRemove);
- tempHistory.remove(path);
- deletions.remove();
+ tempHistory.remove(path);
+ deletions.remove();
- }
}
// Increments
- Iterator increments = commitFiles.iterator();
- while (increments.hasNext()) {
- File file = increments.next();
+ Iterator increments = filter(commitFiles.iterator(), f -> f.type() == INCREMENT);
+ for (File file : iterable(increments)) {
+ String path = file.path();
+ File oldFile = recordingResult ? history.get(path) : history.put(path, file);
- if (file.type() == INCREMENT) {
- String path = file.path();
- File oldFile = recordingResult ? history.get(path) : history.put(path, file);
+ if (oldFile == null && !tempHistory.isEmpty() && !result.containsKey(path))
+ move(tempHistory, result, tempHistoryKeys);
- if (oldFile == null && !tempHistory.isEmpty() && !result.containsKey(path))
- move(tempHistory, result, tempHistoryKeys);
+ if (recordingResult)
+ result.put(path, file);
- if (recordingResult)
- result.put(path, file);
-
- increments.remove();
+ increments.remove();
- }
}
@@ -572,34 +570,45 @@ final class CommitImpl extends AbstractNode implements Commit {
+ // Script files
+ Iterator scripts = filter(commitFiles.iterator(), f -> f.type() == SCRIPT);
+ for (File file : iterable(scripts)) {
+ String path = file.path();
+ File oldFile = recordingResult ? history.get(path) : history.put(path, file);
+
+ if (oldFile == null && !tempHistory.isEmpty() && !result.containsKey(path))
+ move(tempHistory, result, tempHistoryKeys);
+
+ if (recordingResult)
+ result.put(path, file);
+
+ scripts.remove();
+ }
+
// Schema files
- Iterator schemas = commitFiles.iterator();
- while (schemas.hasNext()) {
- File file = schemas.next();
-
- if (file.type() == SCHEMA) {
- String path = file.path();
- String key = commit.id() + "-" + path;
-
- if (recordingResult) {
- tempHistory.put(path, file);
- tempHistoryKeys.put(path, key);
- }
- else {
- history.put(key, file);
- historyKeys.put(path, key);
- }
-
- schemas.remove();
-
-
-
-
+ Iterator schemas = filter(commitFiles.iterator(), f -> f.type() == SCHEMA);
+ for (File file : iterable(schemas)) {
+ String path = file.path();
+ String key = commit.id() + "-" + path;
+ if (recordingResult) {
+ tempHistory.put(path, file);
+ tempHistoryKeys.put(path, key);
}
+ else {
+ history.put(key, file);
+ historyKeys.put(path, key);
+ }
+
+ schemas.remove();
+
+
+
+
+
}
recordingResult |= id().equals(commit.id());
@@ -649,9 +658,13 @@ final class CommitImpl extends AbstractNode implements Commit {
Map versionFiles = new HashMap<>();
Version from = version(ctx.migrations().version(ROOT), id(), versionFiles, history.values());
- Version fromSnapshot = fromSnapshotCommit != null
- ? version(from, fromSnapshotCommit.id(), versionFiles, filter(fromSnapshotCommit.delta(), f -> f.type() == SNAPSHOT))
- : null;
+ Version fromSnapshot = null;
+
+
+
+
+
+
Version to = version(from, resultCommit.id(), versionFiles, result.values());
return new MigrationHistory(
pathHistory,
@@ -682,7 +695,7 @@ final class CommitImpl extends AbstractNode implements Commit {
}
}
- private static final Version version(Version from, String newId, Map files, Iterable result) {
+ private final Version version(Version from, String newId, Map files, Iterable result) {
Version to = from;
for (File file : result) {
@@ -693,6 +706,10 @@ final class CommitImpl extends AbstractNode implements Commit {
if (file.type() == SCHEMA)
to = to.commit(newId, sources(apply(files, file, true).values()).toArray(EMPTY_SOURCE));
+
+ // [#9506] Scripts must be ignored by the interpreter
+ else if (file.type() == SCRIPT)
+ to = to.apply(newId, new IgnoreQuery(file.content(), ctx.configuration()));
else
to = to.apply(newId, file.content());
}
diff --git a/jOOQ/src/main/java/org/jooq/impl/MigrationImpl.java b/jOOQ/src/main/java/org/jooq/impl/MigrationImpl.java
index 9a42abd28d..168514010b 100644
--- a/jOOQ/src/main/java/org/jooq/impl/MigrationImpl.java
+++ b/jOOQ/src/main/java/org/jooq/impl/MigrationImpl.java
@@ -131,8 +131,13 @@ final class MigrationImpl extends AbstractScope implements Migration {
@Override
public final Commit fromSnapshot() {
- Version version = from().migrateTo(to()).fromSnapshot();
- return version != null ? commits().get(version.id()) : null;
+ if (!configuration().commercial())
+ return null;
+
+
+
+
+
}
@Override
diff --git a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java
index 9c1b522eba..0069193c61 100644
--- a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java
+++ b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java
@@ -15828,7 +15828,11 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
}
IgnoreQuery(String sql) {
- super(CONFIG.get());
+ this(sql, CONFIG.get());
+ }
+
+ IgnoreQuery(String sql, Configuration configuration) {
+ super(configuration);
this.sql = sql;
}
diff --git a/jOOQ/src/main/java/org/jooq/impl/Tools.java b/jOOQ/src/main/java/org/jooq/impl/Tools.java
index 135b34a711..c52083aa53 100644
--- a/jOOQ/src/main/java/org/jooq/impl/Tools.java
+++ b/jOOQ/src/main/java/org/jooq/impl/Tools.java
@@ -2744,6 +2744,10 @@ final class Tools {
return array;
}
+ static final Iterable iterable(Iterator iterator) {
+ return () -> iterator;
+ }
+
static final Iterator iterator(Iterator extends T> iterator, Function super T, ? extends U> mapper) {
return new Iterator() {
@Override
@@ -6871,6 +6875,11 @@ final class Tools {
uptodate = false;
return next;
}
+
+ @Override
+ public void remove() {
+ iterator.remove();
+ }
};
}