|
21 | 21 | import org.apache.maven.project.MavenProject; |
22 | 22 |
|
23 | 23 | import java.io.File; |
| 24 | +import java.io.IOException; |
24 | 25 | import java.net.URL; |
25 | 26 | import java.net.URLClassLoader; |
26 | 27 | import java.nio.file.Files; |
@@ -112,6 +113,23 @@ public class MetaDataMigrateMojo extends AbstractMojo { |
112 | 113 | @Parameter(property = "allowTypeChange", defaultValue = "false") |
113 | 114 | private boolean allowTypeChange; |
114 | 115 |
|
| 116 | + /** |
| 117 | + * When true, emit migrations into a Flyway-conventional directory using |
| 118 | + * {@code <prefix><N>__<slug>.sql} naming (e.g., {@code V003__add_author_phone_field.sql}). |
| 119 | + * The next version number is the highest existing {@code <prefix><N>__*.sql} file + 1. |
| 120 | + */ |
| 121 | + @Parameter(property = "meta.migrate.flyway", defaultValue = "false") |
| 122 | + private boolean flyway; |
| 123 | + |
| 124 | + /** Flyway migrations directory (relative to project basedir). Only used when {@link #flyway} is true. */ |
| 125 | + @Parameter(property = "meta.migrate.flywayDir", |
| 126 | + defaultValue = "src/main/resources/db/migration") |
| 127 | + private String flywayDir; |
| 128 | + |
| 129 | + /** Flyway version prefix (e.g., "V" or "U"). Only used when {@link #flyway} is true. */ |
| 130 | + @Parameter(property = "meta.migrate.flywayPrefix", defaultValue = "V") |
| 131 | + private String flywayPrefix; |
| 132 | + |
115 | 133 | /** |
116 | 134 | * Metadata loader configuration (mirrors {@code AbstractMetaDataMojo}'s {@code <loader>} |
117 | 135 | * element). |
@@ -213,11 +231,44 @@ private void runEmit(SchemaMigrationEngine engine, Connection c, AllowOptions al |
213 | 231 | getLog().info("Nothing to emit — schema is already in sync."); |
214 | 232 | return; |
215 | 233 | } |
216 | | - Path dir = Path.of(outputDir, timestamp() + "-" + sanitize(slug)); |
217 | | - Files.createDirectories(dir); |
218 | 234 | String content = up.endsWith("\n") ? up : up + "\n"; |
219 | | - Files.writeString(dir.resolve("up.sql"), content); |
220 | | - getLog().info("Wrote migration script: " + dir.resolve("up.sql")); |
| 235 | + |
| 236 | + Path target; |
| 237 | + if (flyway) { |
| 238 | + Path dir = Path.of(flywayDir); |
| 239 | + Files.createDirectories(dir); |
| 240 | + int nextVersion = nextFlywayVersion(dir, flywayPrefix); |
| 241 | + String filename = String.format("%s%03d__%s.sql", |
| 242 | + flywayPrefix, nextVersion, sanitize(slug)); |
| 243 | + target = dir.resolve(filename); |
| 244 | + } else { |
| 245 | + Path dir = Path.of(outputDir, timestamp() + "-" + sanitize(slug)); |
| 246 | + Files.createDirectories(dir); |
| 247 | + target = dir.resolve("up.sql"); |
| 248 | + } |
| 249 | + Files.writeString(target, content); |
| 250 | + getLog().info("Wrote migration script: " + target); |
| 251 | + } |
| 252 | + |
| 253 | + /** |
| 254 | + * Inspect {@code dir} for existing {@code <prefix><N>__*.sql} files and return the next |
| 255 | + * unused version number. Returns 1 when the directory does not exist or contains no matches. |
| 256 | + */ |
| 257 | + static int nextFlywayVersion(Path dir, String prefix) throws IOException { |
| 258 | + if (!Files.isDirectory(dir)) return 1; |
| 259 | + java.util.regex.Pattern p = java.util.regex.Pattern.compile( |
| 260 | + "^" + java.util.regex.Pattern.quote(prefix) + "(\\d+)__.*\\.sql$"); |
| 261 | + int max = 0; |
| 262 | + try (var stream = Files.list(dir)) { |
| 263 | + for (Path f : stream.toList()) { |
| 264 | + var m = p.matcher(f.getFileName().toString()); |
| 265 | + if (m.matches()) { |
| 266 | + int v = Integer.parseInt(m.group(1)); |
| 267 | + if (v > max) max = v; |
| 268 | + } |
| 269 | + } |
| 270 | + } |
| 271 | + return max + 1; |
221 | 272 | } |
222 | 273 |
|
223 | 274 | private void runApply(SchemaMigrationEngine engine, Connection c, AllowOptions allow) |
|
0 commit comments