[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
This commit is contained in:
Lukas Eder 2023-06-14 21:32:21 +02:00
parent 25f023ebe5
commit 402d9101d9
5 changed files with 207 additions and 21 deletions

View File

@ -109,6 +109,12 @@ abstract class AbstractMigrationsMojo extends AbstractMojo {
@Parameter(property = "jooq.migrate.schemata")
List<MigrationSchema> 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<MigrationSchema> 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);

View File

@ -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);

View File

@ -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.<p><strong>This is a potentially destructive feature, which should not be turned on in production</strong>. 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()));

View File

@ -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<Schema> 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<Schema> 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() {

View File

@ -1448,11 +1448,23 @@ deployed on an RDBMS that does not.]]></jxb:javadoc></jxb:property></appinfo></a
<element name="migrationHistorySchema" type="jooq-runtime:MigrationSchema" minOccurs="0" maxOccurs="1">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[The database schema where the migration history is located.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="migrationHistorySchemaCreateSchemaIfNotExists" type="boolean" minOccurs="0" maxOccurs="1" default="false">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Whether {@link #getMigrationHistorySchema()} should be created if it doesn't exist.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="migrationDefaultSchema" type="jooq-runtime:MigrationSchema" minOccurs="0" maxOccurs="1">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[The default schema whose unqualified objects that are included in the migration.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="migrationSchemata" type="jooq-runtime:MigrationSchemata" minOccurs="0" maxOccurs="1">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[The database objects that are included in the migration.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="migrationSchemataCreateSchemaIfNotExists" type="boolean" minOccurs="0" maxOccurs="1" default="false">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Whether {@link #getMigrationSchemata()} should be created if they don't exist.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="migrationAllowsUndo" type="boolean" minOccurs="0" maxOccurs="1" default="false">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Whether migrations are allowed to be executed in inverse order.<p><strong>This is a potentially destructive feature, which should not be turned on in production</strong>. It is useful mostly to quickly switch between branches in a development environment. This feature is available only in commercial distributions.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>