11package io .ebeaninternal .dbmigration ;
22
33import io .avaje .applog .AppLog ;
4+ import io .avaje .classpath .scanner .core .Location ;
45import io .ebean .DB ;
56import io .ebean .Database ;
67import io .ebean .DatabaseBuilder ;
1011import io .ebean .config .dbplatform .DatabasePlatformProvider ;
1112import io .ebean .dbmigration .DbMigration ;
1213import io .ebean .util .IOUtils ;
14+ import io .ebean .util .StringHelper ;
1315import io .ebeaninternal .api .DbOffline ;
1416import io .ebeaninternal .api .SpiEbeanServer ;
1517import io .ebeaninternal .dbmigration .ddlgeneration .DdlOptions ;
2426import java .io .File ;
2527import java .io .IOException ;
2628import java .io .Writer ;
27- import java .util .ArrayList ;
28- import java .util .List ;
29- import java .util .Properties ;
30- import java .util .ServiceLoader ;
29+ import java .util .*;
3130
3231import static io .ebeaninternal .api .PlatformMatch .matchPlatform ;
3332import static java .lang .System .Logger .Level .*;
@@ -59,8 +58,8 @@ public class DefaultDbMigration implements DbMigration {
5958 private static final String initialVersion = "1.0" ;
6059 private static final String GENERATED_COMMENT = "THIS IS A GENERATED FILE - DO NOT MODIFY" ;
6160
62- private final List <DatabasePlatformProvider > platformProviders = new ArrayList <>();
63- protected final boolean online ;
61+ private List <DatabasePlatformProvider > platformProviders = new ArrayList <>();
62+ protected boolean online ;
6463 private boolean logToSystemOut = true ;
6564 protected SpiEbeanServer server ;
6665 protected String pathToResources = "src/main/resources" ;
@@ -75,8 +74,10 @@ public class DefaultDbMigration implements DbMigration {
7574 protected List <Pair > platforms = new ArrayList <>();
7675 protected DatabaseBuilder .Settings databaseBuilder ;
7776 protected DbConstraintNaming constraintNaming ;
77+ @ Deprecated
7878 protected Boolean strictMode ;
79- protected Boolean includeGeneratedFileComment ;
79+ protected boolean includeGeneratedFileComment ;
80+ @ Deprecated
8081 protected String header ;
8182 protected String applyPrefix = "" ;
8283 protected String version ;
@@ -86,6 +87,9 @@ public class DefaultDbMigration implements DbMigration {
8687 private int lockTimeoutSeconds ;
8788 protected boolean includeBuiltInPartitioning = true ;
8889 protected boolean includeIndex ;
90+ protected boolean generate = false ;
91+ protected boolean generateInit = false ;
92+ private boolean keepLastInit = true ;
8993
9094 /**
9195 * Create for offline migration generation.
@@ -122,12 +126,66 @@ public void setServerConfig(DatabaseBuilder builder) {
122126 if (constraintNaming == null ) {
123127 this .constraintNaming = databaseBuilder .getConstraintNaming ();
124128 }
129+ if (databasePlatform == null ) {
130+ this .databasePlatform = databaseBuilder .getDatabasePlatform ();
131+ }
125132 Properties properties = config .getProperties ();
126133 if (properties != null ) {
127- PropertiesWrapper props = new PropertiesWrapper ("ebean" , config .getName (), properties , null );
134+ PropertiesWrapper props = new PropertiesWrapper ("ebean" , config .getName (), properties , config . getClassLoadConfig () );
128135 migrationPath = props .get ("migration.migrationPath" , migrationPath );
129136 migrationInitPath = props .get ("migration.migrationInitPath" , migrationInitPath );
130137 pathToResources = props .get ("migration.pathToResources" , pathToResources );
138+ addForeignKeySkipCheck = props .getBoolean ("migration.addForeignKeySkipCheck" , addForeignKeySkipCheck );
139+ applyPrefix = props .get ("migration.applyPrefix" , applyPrefix );
140+ databasePlatform = props .createInstance (DatabasePlatform .class , "migration.databasePlatform" , databasePlatform );
141+ generatePendingDrop = props .get ("migration.generatePendingDrop" , generatePendingDrop );
142+ includeBuiltInPartitioning = props .getBoolean ("migration.includeBuiltInPartitioning" , includeBuiltInPartitioning );
143+ includeGeneratedFileComment = props .getBoolean ("migration.includeGeneratedFileComment" , includeGeneratedFileComment );
144+ includeIndex = props .getBoolean ("migration.includeIndex" , includeIndex );
145+ lockTimeoutSeconds = props .getInt ("migration.lockTimeoutSeconds" , lockTimeoutSeconds );
146+ logToSystemOut = props .getBoolean ("migration.logToSystemOut" , logToSystemOut );
147+ modelPath = props .get ("migration.modelPath" , modelPath );
148+ modelSuffix = props .get ("migration.modelSuffix" , modelSuffix );
149+ name = props .get ("migration.name" , name );
150+ online = props .getBoolean ("migration.online" , online );
151+ vanillaPlatform = props .getBoolean ("migration.vanillaPlatform" , vanillaPlatform );
152+ version = props .get ("migration.version" , version );
153+ generate = props .getBoolean ("migration.generate" , generate );
154+ generateInit = props .getBoolean ("migration.generateInit" , generateInit );
155+ // header & strictMode must be configured at DatabaseConfig level
156+ parsePlatforms (props , config );
157+ }
158+ }
159+
160+ protected void parsePlatforms (PropertiesWrapper props , DatabaseBuilder .Settings config ) {
161+ String platforms = props .get ("migration.platforms" );
162+ if (platforms == null || platforms .isEmpty ()) {
163+ return ;
164+ }
165+ String [] tmp = StringHelper .splitNames (platforms );
166+ for (String plat : tmp ) {
167+ DatabasePlatform dbPlatform ;
168+ String platformName = plat ;
169+ String platformPrefix = null ;
170+ int pos = plat .indexOf ('=' );
171+ if (pos != -1 ) {
172+ platformName = plat .substring (0 , pos );
173+ platformPrefix = plat .substring (pos + 1 );
174+ }
175+
176+ if (platformName .indexOf ('.' ) == -1 ) {
177+ // parse platform as enum value
178+ Platform platform = Enum .valueOf (Platform .class , platformName .toUpperCase ());
179+ dbPlatform = platform (platform );
180+ } else {
181+ // parse platform as class
182+ dbPlatform = (DatabasePlatform ) config .getClassLoadConfig ().newInstance (platformName );
183+ }
184+ if (platformPrefix == null ) {
185+ platformPrefix = dbPlatform .platform ().name ().toLowerCase ();
186+ }
187+
188+ addDatabasePlatform (dbPlatform , platformPrefix );
131189 }
132190 }
133191
@@ -318,7 +376,18 @@ private String generateMigrationFor(boolean initMigration) throws IOException {
318376 }
319377
320378 String pendingVersion = generatePendingDrop ();
321- if (pendingVersion != null ) {
379+ if ("auto" .equals (pendingVersion )) {
380+ StringJoiner sj = new StringJoiner ("," );
381+ String diff = generateDiff (request );
382+ if (diff != null ) {
383+ sj .add (diff );
384+ request = createRequest (initMigration );
385+ }
386+ for (String pendingDrop : request .getPendingDrops ()) {
387+ sj .add (generatePendingDrop (request , pendingDrop ));
388+ }
389+ return sj .length () == 0 ? null : sj .toString ();
390+ } else if (pendingVersion != null ) {
322391 return generatePendingDrop (request , pendingVersion );
323392 } else {
324393 return generateDiff (request );
@@ -553,7 +622,7 @@ private String generateMigration(Request request, Migration dbMigration, String
553622 return null ;
554623 } else {
555624 if (!platforms .isEmpty ()) {
556- writeExtraPlatformDdl (fullVersion , request .currentModel , dbMigration , request .migrationDir );
625+ writeExtraPlatformDdl (fullVersion , request .currentModel , dbMigration , request .migrationDir , request . initMigration && keepLastInit );
557626
558627 } else if (databasePlatform != null ) {
559628 // writer needs the current model to provide table/column details for
@@ -633,12 +702,17 @@ private String toUnderScore(String name) {
633702 /**
634703 * Write any extra platform ddl.
635704 */
636- private void writeExtraPlatformDdl (String fullVersion , CurrentModel currentModel , Migration dbMigration , File writePath ) throws IOException {
705+ private void writeExtraPlatformDdl (String fullVersion , CurrentModel currentModel , Migration dbMigration , File writePath , boolean clear ) throws IOException {
637706 DdlOptions options = new DdlOptions (addForeignKeySkipCheck );
638707 for (Pair pair : platforms ) {
639708 DdlWrite writer = new DdlWrite (new MConfiguration (), currentModel .read (), options );
640709 PlatformDdlWriter platformWriter = createDdlWriter (pair .platform );
641710 File subPath = platformWriter .subPath (writePath , pair .prefix );
711+ if (clear ) {
712+ for (File existing : subPath .listFiles ()) {
713+ existing .delete ();
714+ }
715+ }
642716 platformWriter .processMigration (dbMigration , writer , subPath , fullVersion );
643717 }
644718 }
@@ -656,7 +730,7 @@ private boolean writeMigrationXml(Migration dbMigration, File resourcePath, Stri
656730 if (file .exists ()) {
657731 return false ;
658732 }
659- String comment = Boolean . TRUE . equals ( includeGeneratedFileComment ) ? GENERATED_COMMENT : null ;
733+ String comment = includeGeneratedFileComment ? GENERATED_COMMENT : null ;
660734 MigrationXmlWriter xmlWriter = new MigrationXmlWriter (comment );
661735 xmlWriter .write (dbMigration , file );
662736 return true ;
@@ -674,11 +748,14 @@ private void setDefaults() {
674748 databasePlatform = server .databasePlatform ();
675749 }
676750 if (databaseBuilder != null ) {
751+ // FIXME: StrictMode and header may be defined HERE and in DatabaseConfig.
752+ // We shoild change either DefaultDbMigration or databaseConfig, so that it is only
753+ // defined on one place
677754 if (strictMode != null ) {
678- databaseBuilder .setDdlStrictMode (strictMode );
755+ databaseBuilder .ddlStrictMode (strictMode );
679756 }
680757 if (header != null ) {
681- databaseBuilder .setDdlHeader (header );
758+ databaseBuilder .ddlHeader (header );
682759 }
683760 }
684761 }
@@ -748,15 +825,20 @@ public File migrationDirectory() {
748825 * Return the file path to write the xml and sql to.
749826 */
750827 File migrationDirectory (boolean initMigration ) {
751- // path to src/main/resources in typical maven project
752- File resourceRootDir = new File (pathToResources );
753- if (!resourceRootDir .exists ()) {
754- String msg = String .format ("Error - path to resources %s does not exist. Absolute path is %s" , pathToResources , resourceRootDir .getAbsolutePath ());
755- throw new UnknownResourcePathException (msg );
756- }
757- String resourcePath = migrationPath (initMigration );
828+ Location resourcePath = migrationPath (initMigration );
758829 // expect to be a path to something like - src/main/resources/dbmigration
759- File path = new File (resourceRootDir , resourcePath );
830+ File path ;
831+ if (resourcePath .isClassPath ()) {
832+ // path to src/main/resources in typical maven project
833+ File resourceRootDir = new File (pathToResources );
834+ if (!resourceRootDir .exists ()) {
835+ String msg = String .format ("Error - path to resources %s does not exist. Absolute path is %s" , pathToResources , resourceRootDir .getAbsolutePath ());
836+ throw new UnknownResourcePathException (msg );
837+ }
838+ path = new File (resourceRootDir , resourcePath .path ());
839+ } else {
840+ path = new File (resourcePath .path ());
841+ }
760842 if (!path .exists ()) {
761843 if (!path .mkdirs ()) {
762844 logInfo ("Warning - Unable to ensure migration directory exists at %s" , path .getAbsolutePath ());
@@ -765,8 +847,9 @@ File migrationDirectory(boolean initMigration) {
765847 return path ;
766848 }
767849
768- private String migrationPath (boolean initMigration ) {
769- return initMigration ? migrationInitPath : migrationPath ;
850+ private Location migrationPath (boolean initMigration ) {
851+ // remove classpath: or filesystem: prefix
852+ return new Location (initMigration ? migrationInitPath : migrationPath );
770853 }
771854
772855 /**
0 commit comments