From 402d9101d94b081bc3f3caa01f1c9cffdbd0d2c8 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Wed, 14 Jun 2023 21:32:21 +0200 Subject: [PATCH] [jOOQ/jOOQ#9506] Various improvements This includes: - Add a default schema Settings - Add create schema if not exists logic and Settings - Fix issues in Mojos --- .../codegen/maven/AbstractMigrationsMojo.java | 32 ++++- .../org/jooq/codegen/maven/MigrateMojo.java | 11 +- .../src/main/java/org/jooq/conf/Settings.java | 121 ++++++++++++++++++ .../java/org/jooq/impl/MigrationImpl.java | 52 +++++--- .../org/jooq/xsd/jooq-runtime-3.19.0.xsd | 12 ++ 5 files changed, 207 insertions(+), 21 deletions(-) diff --git a/jOOQ-migrations-maven/src/main/java/org/jooq/codegen/maven/AbstractMigrationsMojo.java b/jOOQ-migrations-maven/src/main/java/org/jooq/codegen/maven/AbstractMigrationsMojo.java index aa94472fe9..f9eea1a806 100644 --- a/jOOQ-migrations-maven/src/main/java/org/jooq/codegen/maven/AbstractMigrationsMojo.java +++ b/jOOQ-migrations-maven/src/main/java/org/jooq/codegen/maven/AbstractMigrationsMojo.java @@ -109,6 +109,12 @@ abstract class AbstractMigrationsMojo extends AbstractMojo { @Parameter(property = "jooq.migrate.schemata") List schemata; + /** + * Whether to create a migration schema if it does not exist. + */ + @Parameter(property = "jooq.migrate.schemataCreateSchemaIfNotExists") + boolean schemataCreateSchemaIfNotExists; + /** * The default catalog among the migrated schemata. */ @@ -133,6 +139,12 @@ abstract class AbstractMigrationsMojo extends AbstractMojo { @Parameter(property = "jooq.migrate.historySchema") String historySchema; + /** + * Whether to create the history schema if it does not exist. + */ + @Parameter(property = "jooq.migrate.historySchemaCreateSchemaIfNotExists") + boolean historySchemaCreateSchemaIfNotExists; + @Override public void execute() throws MojoExecutionException { if (skip) { @@ -154,16 +166,27 @@ abstract class AbstractMigrationsMojo extends AbstractMojo { try (CloseableDSLContext ctx = DSL.using(jdbc.url, defaultIfNull(jdbc.user, jdbc.username), jdbc.password)) { // Initialise Settings - List s = ctx.settings().getMigrationSchemata(); - s.addAll(schemata); + // --------------------------------------------------------------------- + ctx.settings().getMigrationSchemata().addAll(schemata); if (defaultCatalog != null || defaultSchema != null) - s.add(new MigrationSchema().withCatalog(defaultIfNull(defaultCatalog, "")).withSchema(defaultIfNull(defaultSchema, ""))); + ctx.settings().setMigrationDefaultSchema(new MigrationSchema() + .withCatalog(defaultIfNull(defaultCatalog, "")) + .withSchema(defaultIfNull(defaultSchema, "")) + ); if (historyCatalog != null || historySchema != null) - ctx.settings().setMigrationHistorySchema(new MigrationSchema().withCatalog(defaultIfNull(historyCatalog, "")).withSchema(defaultIfNull(historySchema, ""))); + ctx.settings().setMigrationHistorySchema(new MigrationSchema() + .withCatalog(defaultIfNull(historyCatalog, "")) + .withSchema(defaultIfNull(historySchema, "")) + ); + + + ctx.settings().setMigrationSchemataCreateSchemaIfNotExists(schemataCreateSchemaIfNotExists); + ctx.settings().setMigrationHistorySchemaCreateSchemaIfNotExists(historySchemaCreateSchemaIfNotExists); // Initialise connection + // --------------------------------------------------------------------- if (!isBlank(defaultCatalog)) ctx.setCatalog(defaultCatalog).execute(); @@ -171,6 +194,7 @@ abstract class AbstractMigrationsMojo extends AbstractMojo { ctx.setSchema(defaultSchema).execute(); // Run migration + // --------------------------------------------------------------------- if (setupScript != null) ctx.execute(setupScript); diff --git a/jOOQ-migrations-maven/src/main/java/org/jooq/codegen/maven/MigrateMojo.java b/jOOQ-migrations-maven/src/main/java/org/jooq/codegen/maven/MigrateMojo.java index 8e6ee7622f..ca369c9e15 100644 --- a/jOOQ-migrations-maven/src/main/java/org/jooq/codegen/maven/MigrateMojo.java +++ b/jOOQ-migrations-maven/src/main/java/org/jooq/codegen/maven/MigrateMojo.java @@ -42,6 +42,7 @@ import static org.apache.maven.plugins.annotations.ResolutionScope.TEST; import java.io.File; +import org.jooq.CommitProvider; import org.jooq.Commits; import org.jooq.Configuration; import org.jooq.Migration; @@ -75,7 +76,14 @@ public class MigrateMojo extends AbstractMigrationsMojo { // [#9506] TODO: Support loading **/*.sql style paths // [#9506] TODO: Support relative paths, absolute paths, etc. commits.load(file(directory)); - Migration migration = migrations.migrateTo(commits.latest()); + + // [#9506] TODO: Having to use this CommitsProvider "trick" isn't really + // user friendly. There must be a better way + Migration migration = configuration + .derive((CommitProvider) () -> commits) + .dsl() + .migrations() + .migrateTo(commits.latest()); if (getLog().isInfoEnabled()) { getLog().info("Migration from version: " + migration.from()); @@ -86,6 +94,7 @@ public class MigrateMojo extends AbstractMigrationsMojo { migration.execute(); } + // [#9506] TODO: Move this utility into the library private File file(String file) { getLog().info("Reading migrations directory: " + file); File f = new File(file); diff --git a/jOOQ/src/main/java/org/jooq/conf/Settings.java b/jOOQ/src/main/java/org/jooq/conf/Settings.java index a6e54b38d1..be49ceb5a2 100644 --- a/jOOQ/src/main/java/org/jooq/conf/Settings.java +++ b/jOOQ/src/main/java/org/jooq/conf/Settings.java @@ -453,6 +453,11 @@ public class Settings protected Boolean metaIncludeSystemSequences = false; protected MigrationSchema migrationHistorySchema; @XmlElement(defaultValue = "false") + protected Boolean migrationHistorySchemaCreateSchemaIfNotExists = false; + protected MigrationSchema migrationDefaultSchema; + @XmlElement(defaultValue = "false") + protected Boolean migrationSchemataCreateSchemaIfNotExists = false; + @XmlElement(defaultValue = "false") protected Boolean migrationAllowsUndo = false; @XmlElement(defaultValue = "false") protected Boolean migrationRevertUntracked = false; @@ -5285,6 +5290,70 @@ public class Settings this.migrationHistorySchema = value; } + /** + * Whether {@link #getMigrationHistorySchema()} should be created if it doesn't exist. + * + * @return + * possible object is + * {@link Boolean } + * + */ + public Boolean isMigrationHistorySchemaCreateSchemaIfNotExists() { + return migrationHistorySchemaCreateSchemaIfNotExists; + } + + /** + * Sets the value of the migrationHistorySchemaCreateSchemaIfNotExists property. + * + * @param value + * allowed object is + * {@link Boolean } + * + */ + public void setMigrationHistorySchemaCreateSchemaIfNotExists(Boolean value) { + this.migrationHistorySchemaCreateSchemaIfNotExists = value; + } + + /** + * The default schema whose unqualified objects that are included in the migration. + * + */ + public MigrationSchema getMigrationDefaultSchema() { + return migrationDefaultSchema; + } + + /** + * The default schema whose unqualified objects that are included in the migration. + * + */ + public void setMigrationDefaultSchema(MigrationSchema value) { + this.migrationDefaultSchema = value; + } + + /** + * Whether {@link #getMigrationSchemata()} should be created if they don't exist. + * + * @return + * possible object is + * {@link Boolean } + * + */ + public Boolean isMigrationSchemataCreateSchemaIfNotExists() { + return migrationSchemataCreateSchemaIfNotExists; + } + + /** + * Sets the value of the migrationSchemataCreateSchemaIfNotExists property. + * + * @param value + * allowed object is + * {@link Boolean } + * + */ + public void setMigrationSchemataCreateSchemaIfNotExists(Boolean value) { + this.migrationSchemataCreateSchemaIfNotExists = value; + } + /** * Whether migrations are allowed to be executed in inverse order.

This is a potentially destructive feature, which should not be turned on in production. It is useful mostly to quickly switch between branches in a development environment. This feature is available only in commercial distributions. * @@ -7177,6 +7246,25 @@ public class Settings return this; } + public Settings withMigrationHistorySchemaCreateSchemaIfNotExists(Boolean value) { + setMigrationHistorySchemaCreateSchemaIfNotExists(value); + return this; + } + + /** + * The default schema whose unqualified objects that are included in the migration. + * + */ + public Settings withMigrationDefaultSchema(MigrationSchema value) { + setMigrationDefaultSchema(value); + return this; + } + + public Settings withMigrationSchemataCreateSchemaIfNotExists(Boolean value) { + setMigrationSchemataCreateSchemaIfNotExists(value); + return this; + } + public Settings withMigrationAllowsUndo(Boolean value) { setMigrationAllowsUndo(value); return this; @@ -7651,6 +7739,9 @@ public class Settings builder.append("metaIncludeSystemIndexes", metaIncludeSystemIndexes); builder.append("metaIncludeSystemSequences", metaIncludeSystemSequences); builder.append("migrationHistorySchema", migrationHistorySchema); + builder.append("migrationHistorySchemaCreateSchemaIfNotExists", migrationHistorySchemaCreateSchemaIfNotExists); + builder.append("migrationDefaultSchema", migrationDefaultSchema); + builder.append("migrationSchemataCreateSchemaIfNotExists", migrationSchemataCreateSchemaIfNotExists); builder.append("migrationAllowsUndo", migrationAllowsUndo); builder.append("migrationRevertUntracked", migrationRevertUntracked); builder.append("migrationAutoBaseline", migrationAutoBaseline); @@ -9377,6 +9468,33 @@ public class Settings return false; } } + if (migrationHistorySchemaCreateSchemaIfNotExists == null) { + if (other.migrationHistorySchemaCreateSchemaIfNotExists!= null) { + return false; + } + } else { + if (!migrationHistorySchemaCreateSchemaIfNotExists.equals(other.migrationHistorySchemaCreateSchemaIfNotExists)) { + return false; + } + } + if (migrationDefaultSchema == null) { + if (other.migrationDefaultSchema!= null) { + return false; + } + } else { + if (!migrationDefaultSchema.equals(other.migrationDefaultSchema)) { + return false; + } + } + if (migrationSchemataCreateSchemaIfNotExists == null) { + if (other.migrationSchemataCreateSchemaIfNotExists!= null) { + return false; + } + } else { + if (!migrationSchemataCreateSchemaIfNotExists.equals(other.migrationSchemataCreateSchemaIfNotExists)) { + return false; + } + } if (migrationAllowsUndo == null) { if (other.migrationAllowsUndo!= null) { return false; @@ -9849,6 +9967,9 @@ public class Settings result = ((prime*result)+((metaIncludeSystemIndexes == null)? 0 :metaIncludeSystemIndexes.hashCode())); result = ((prime*result)+((metaIncludeSystemSequences == null)? 0 :metaIncludeSystemSequences.hashCode())); result = ((prime*result)+((migrationHistorySchema == null)? 0 :migrationHistorySchema.hashCode())); + result = ((prime*result)+((migrationHistorySchemaCreateSchemaIfNotExists == null)? 0 :migrationHistorySchemaCreateSchemaIfNotExists.hashCode())); + result = ((prime*result)+((migrationDefaultSchema == null)? 0 :migrationDefaultSchema.hashCode())); + result = ((prime*result)+((migrationSchemataCreateSchemaIfNotExists == null)? 0 :migrationSchemataCreateSchemaIfNotExists.hashCode())); result = ((prime*result)+((migrationAllowsUndo == null)? 0 :migrationAllowsUndo.hashCode())); result = ((prime*result)+((migrationRevertUntracked == null)? 0 :migrationRevertUntracked.hashCode())); result = ((prime*result)+((migrationAutoBaseline == null)? 0 :migrationAutoBaseline.hashCode())); diff --git a/jOOQ/src/main/java/org/jooq/impl/MigrationImpl.java b/jOOQ/src/main/java/org/jooq/impl/MigrationImpl.java index d51cdc1f96..500cb155d8 100644 --- a/jOOQ/src/main/java/org/jooq/impl/MigrationImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/MigrationImpl.java @@ -70,6 +70,7 @@ import org.jooq.DSLContext; import org.jooq.Files; import org.jooq.Meta; import org.jooq.Migration; +import org.jooq.MigrationContext; import org.jooq.MigrationListener; import org.jooq.Queries; import org.jooq.Query; @@ -98,35 +99,36 @@ final class MigrationImpl extends AbstractScope implements Migration { Commits commits; MigrationImpl(Configuration configuration, Commit to) { - super(configuration.derive(new ThreadLocalTransactionProvider(configuration.systemConnectionProvider()))); + super(initCtx( + configuration.derive(new ThreadLocalTransactionProvider(configuration.systemConnectionProvider())), + configuration.settings().getMigrationDefaultSchema() + )); this.to = to; - this.historyCtx = initHistoryCtx(configuration()); + this.historyCtx = initCtx(configuration(), configuration.settings().getMigrationHistorySchema()).dsl(); } - private static final DSLContext initHistoryCtx(Configuration configuration) { - MigrationSchema m = configuration.settings().getMigrationHistorySchema(); + private static final Configuration initCtx(Configuration configuration, MigrationSchema defaultSchema) { + if (defaultSchema != null) { + Configuration result = configuration.derive(); - if (m != null) { - DSLContext result = configuration.derive().dsl(); - - if (!isBlank(m.getCatalog())) { + if (!isBlank(defaultSchema.getCatalog())) { result.settings().withRenderMapping(new RenderMapping() .withCatalogs(new MappedCatalog() .withInput("") - .withOutput(m.getCatalog()) + .withOutput(defaultSchema.getCatalog()) .withSchemata(new MappedSchema() .withInput("") - .withOutput(m.getSchema()) + .withOutput(defaultSchema.getSchema()) ) ) ); } - else if (!isBlank(m.getSchema())) { + else if (!isBlank(defaultSchema.getSchema())) { result.settings().withRenderMapping(new RenderMapping() .withSchemata(new MappedSchema() .withInput("") - .withOutput(m.getSchema()) + .withOutput(defaultSchema.getSchema()) ) ); } @@ -134,7 +136,7 @@ final class MigrationImpl extends AbstractScope implements Migration { return result; } else - return configuration.dsl(); + return configuration; } @Override @@ -273,11 +275,21 @@ final class MigrationImpl extends AbstractScope implements Migration { Set set = new LinkedHashSet<>(); for (MigrationSchema schema : configuration.settings().getMigrationSchemata()) - set.addAll(lookup(asList(schema(name(schema.getCatalog(), schema.getSchema()))))); + addSchema(set, schema); + + if (configuration.settings().getMigrationDefaultSchema() != null) { + addSchema(set, configuration.settings().getMigrationDefaultSchema()); + set.add(DSL.schema("")); + } return set; } + private final void addSchema(Set set, MigrationSchema schema) { + if (schema != null) + set.addAll(lookup(asList(schema(name(schema.getCatalog(), schema.getSchema()))))); + } + @Override public final void execute() { @@ -388,18 +400,26 @@ final class MigrationImpl extends AbstractScope implements Migration { * Initialise the underlying {@link Configuration} with the jOOQ Migrations * History. */ - public final void init() { + final void init() { // TODO: What to do when initialising jOOQ-migrations on an existing database? // - Should there be init() commands that can be run explicitly by the user? // - Will we reverse engineer the production Meta snapshot first? if (!existsHistory()) { + + // TODO: [#9506] Make this schema creation vendor agnostic // TODO: [#15225] This CREATE SCHEMA statement should never be necessary. - if (historyCtx.settings().getMigrationHistorySchema() != null) + if (TRUE.equals(historyCtx.settings().isMigrationHistorySchemaCreateSchemaIfNotExists()) + && historyCtx.settings().getMigrationHistorySchema() != null) historyCtx.createSchemaIfNotExists("").execute(); historyCtx.meta(HISTORY).ddl().executeBatch(); } + + MigrationContext ctx = migrationContext(); + if (TRUE.equals(ctx.settings().isMigrationSchemataCreateSchemaIfNotExists())) + for (Schema schema : ctx.migratedSchemas()) + dsl().createSchemaIfNotExists(schema).execute(); } private final boolean existsHistory() { diff --git a/jOOQ/src/main/resources/org/jooq/xsd/jooq-runtime-3.19.0.xsd b/jOOQ/src/main/resources/org/jooq/xsd/jooq-runtime-3.19.0.xsd index f59dca0556..cf3050d280 100644 --- a/jOOQ/src/main/resources/org/jooq/xsd/jooq-runtime-3.19.0.xsd +++ b/jOOQ/src/main/resources/org/jooq/xsd/jooq-runtime-3.19.0.xsd @@ -1448,11 +1448,23 @@ deployed on an RDBMS that does not.]]> + + + + + + + + + + + + This is a potentially destructive feature, which should not be turned on in production. It is useful mostly to quickly switch between branches in a development environment. This feature is available only in commercial distributions.]]>