1 /*
2 * Copyright 2010-2020 Redgate Software Ltd
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.flywaydb.core.api.configuration;
17
18 import org.flywaydb.core.api.ErrorCode;
19 import org.flywaydb.core.api.FlywayException;
20 import org.flywaydb.core.api.Location;
21 import org.flywaydb.core.api.MigrationVersion;
22 import org.flywaydb.core.api.callback.Callback;
23 import org.flywaydb.core.api.logging.Log;
24 import org.flywaydb.core.api.logging.LogFactory;
25 import org.flywaydb.core.api.migration.JavaMigration;
26 import org.flywaydb.core.api.resolver.MigrationResolver;
27 import org.flywaydb.core.internal.configuration.ConfigUtils;
28 import org.flywaydb.core.internal.jdbc.DriverDataSource;
29 import org.flywaydb.core.internal.license.Edition;
30 import org.flywaydb.core.internal.util.ClassUtils;
31 import org.flywaydb.core.internal.util.Locations;
32 import org.flywaydb.core.internal.util.StringUtils;
33
34 import javax.sql.DataSource;
35 import java.io.File;
36 import java.io.FileNotFoundException;
37 import java.io.FileOutputStream;
38 import java.io.IOException;
39 import java.io.OutputStream;
40 import java.nio.charset.Charset;
41 import java.nio.charset.StandardCharsets;
42 import java.util.ArrayList;
43 import java.util.Arrays;
44 import java.util.HashMap;
45 import java.util.Iterator;
46 import java.util.List;
47 import java.util.Map;
48 import java.util.Properties;
49
50 import static org.flywaydb.core.internal.configuration.ConfigUtils.removeBoolean;
51 import static org.flywaydb.core.internal.configuration.ConfigUtils.removeInteger;
52
53 /**
54 * JavaBean-style configuration for Flyway. This is primarily meant for compatibility with scenarios where the
55 * new FluentConfiguration isn't an easy fit, such as Spring XML bean configuration.
56 * <p>
57 * This configuration can then be passed to Flyway using the <code>new Flyway(Configuration)</code> constructor.
58 * </p>
59 */
60 public class ClassicConfiguration implements Configuration {
61 private static final Log LOG = LogFactory.getLog(ClassicConfiguration.class);
62
63 private String driver;
64 private String url;
65 private String user;
66 private String password;
67
68 /**
69 * The dataSource to use to access the database. Must have the necessary privileges to execute ddl.
70 */
71 private DataSource dataSource;
72
73 /**
74 * The maximum number of retries when attempting to connect to the database. After each failed attempt, Flyway will
75 * wait 1 second before attempting to connect again, up to the maximum number of times specified by connectRetries.
76 * (default: 0)
77 */
78 private int connectRetries;
79
80 /**
81 * The SQL statements to run to initialize a new database connection immediately after opening it.
82 * (default: {@code null})
83 */
84 private String initSql;
85
86 /**
87 * The ClassLoader to use for resolving migrations on the classpath. (default: Thread.currentThread().getContextClassLoader() )
88 */
89 private ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
90
91 /**
92 * The locations to scan recursively for migrations.
93 * <p>The location type is determined by its prefix.
94 * Unprefixed locations or locations starting with {@code classpath:} point to a package on the classpath and may
95 * contain both sql and java-based migrations.
96 * Locations starting with {@code filesystem:} point to a directory on the filesystem and may only contain sql
97 * migrations.</p>
98 * <p>
99 * (default: db/migration)
100 */
101 private Locations locations = new Locations("db/migration");
102
103 /**
104 * The encoding of Sql migrations. (default: UTF-8)
105 */
106 private Charset encoding = StandardCharsets.UTF_8;
107
108 /**
109 * The default schema managed by Flyway. This schema name is case-sensitive. If not specified, but
110 * <i>schemaNames</i> is, Flyway uses the first schema in that list. If that is also not specified, Flyway uses
111 * the default schema for the database connection.
112 * <p>Consequences:</p>
113 * <ul>
114 * <li>This schema will be the one containing the schema history table.</li>
115 * <li>This schema will be the default for the database connection (provided the database supports this concept).</li>
116 * </ul>
117 */
118 private String defaultSchemaName = null;
119
120 /**
121 * The schemas managed by Flyway. These schema names are case-sensitive. If not specified, Flyway uses
122 * the default schema for the database connection. If <i>defaultSchemaName</i> is not specified, then the first of
123 * this list also acts as default schema.
124 * <p>Consequences:</p>
125 * <ul>
126 * <li>Flyway will automatically attempt to create all these schemas, unless they already exist.</li>
127 * <li>The schemas will be cleaned in the order of this list.</li>
128 * <li>If Flyway created them, the schemas themselves will be dropped when cleaning.</li>
129 * </ul>
130 */
131 private String[] schemaNames = {};
132
133 /**
134 * <p>The name of the schema history table that will be used by Flyway. (default: flyway_schema_history)</p><p> By default
135 * (single-schema mode) the schema history table is placed in the default schema for the connection provided by the
136 * datasource. </p> <p>When the <i>flyway.schemas</i> property is set (multi-schema mode), the schema history table is
137 * placed in the first schema of the list. </p>
138 */
139 private String table = "flyway_schema_history";
140
141 /**
142 * <p>The tablespace where to create the schema history table that will be used by Flyway.</p>
143 * <p>If not specified, Flyway uses the default tablespace for the database connection.
144 * This setting is only relevant for databases that do support the notion of tablespaces. Its value is simply
145 * ignored for all others.</p>
146 */
147 private String tablespace;
148
149 /**
150 * The target version up to which Flyway should consider migrations.
151 * Migrations with a higher version number will be ignored.
152 * Special values:
153 * <ul>
154 * <li>{@code current}: designates the current version of the schema</li>
155 * <li>{@code latest}: the latest version of the schema, as defined by the migration with the highest version</li>
156 * </ul>
157 * Defaults to {@code latest}.
158 */
159 private MigrationVersion target;
160
161 /**
162 * Whether placeholders should be replaced. (default: true)
163 */
164 private boolean placeholderReplacement = true;
165
166 /**
167 * The map of <placeholder, replacementValue> to apply to sql migration scripts.
168 */
169 private Map<String, String> placeholders = new HashMap<>();
170
171 /**
172 * The prefix of every placeholder. (default: ${ )
173 */
174 private String placeholderPrefix = "${";
175
176 /**
177 * The suffix of every placeholder. (default: } )
178 */
179 private String placeholderSuffix = "}";
180
181 /**
182 * The file name prefix for versioned SQL migrations. (default: V)
183 * <p>
184 * <p>Versioned SQL migrations have the following file name structure: prefixVERSIONseparatorDESCRIPTIONsuffix ,
185 * which using the defaults translates to V1_1__My_description.sql</p>
186 */
187 private String sqlMigrationPrefix = "V";
188
189
190
191
192
193
194
195
196
197
198
199
200 /**
201 * The file name prefix for repeatable SQL migrations. (default: R)
202 * <p>
203 * <p>Repeatable sql migrations have the following file name structure: prefixSeparatorDESCRIPTIONsuffix ,
204 * which using the defaults translates to R__My_description.sql</p>
205 */
206 private String repeatableSqlMigrationPrefix = "R";
207
208 /**
209 * The file name separator for sql migrations. (default: __)
210 * <p>
211 * <p>Sql migrations have the following file name structure: prefixVERSIONseparatorDESCRIPTIONsuffix ,
212 * which using the defaults translates to V1_1__My_description.sql</p>
213 */
214 private String sqlMigrationSeparator = "__";
215
216 /**
217 * The file name suffixes for SQL migrations. (default: .sql)
218 * <p>SQL migrations have the following file name structure: prefixVERSIONseparatorDESCRIPTIONsuffix ,
219 * which using the defaults translates to V1_1__My_description.sql</p>
220 * <p>Multiple suffixes (like .sql,.pkg,.pkb) can be specified for easier compatibility with other tools such as
221 * editors with specific file associations.</p>
222 */
223 private String[] sqlMigrationSuffixes = {".sql"};
224
225 /**
226 * The manually added Java-based migrations. These are not Java-based migrations discovered through classpath
227 * scanning and instantiated by Flyway. Instead these are manually added instances of JavaMigration.
228 * This is particularly useful when working with a dependency injection container, where you may want the DI
229 * container to instantiate the class and wire up its dependencies for you. (default: none)
230 */
231 private JavaMigration[] javaMigrations = {};
232
233 /**
234 * Ignore missing migrations when reading the schema history table. These are migrations that were performed by an
235 * older deployment of the application that are no longer available in this version. For example: we have migrations
236 * available on the classpath with versions 1.0 and 3.0. The schema history table indicates that a migration with version 2.0
237 * (unknown to us) has also been applied. Instead of bombing out (fail fast) with an exception, a
238 * warning is logged and Flyway continues normally. This is useful for situations where one must be able to deploy
239 * a newer version of the application even though it doesn't contain migrations included with an older one anymore.
240 * Note that if the most recently applied migration is removed, Flyway has no way to know it is missing and will
241 * mark it as future instead.
242 * <p>
243 * {@code true} to continue normally and log a warning, {@code false} to fail fast with an exception.
244 * (default: {@code false})
245 */
246 private boolean ignoreMissingMigrations;
247
248 /**
249 * Ignore ignored migrations when reading the schema history table. These are migrations that were added in between
250 * already migrated migrations in this version. For example: we have migrations available on the classpath with
251 * versions from 1.0 to 3.0. The schema history table indicates that version 1 was finished on 1.0.15, and the next
252 * one was 2.0.0. But with the next release a new migration was added to version 1: 1.0.16. Such scenario is ignored
253 * by migrate command, but by default is rejected by validate. When ignoreIgnoredMigrations is enabled, such case
254 * will not be reported by validate command. This is useful for situations where one must be able to deliver
255 * complete set of migrations in a delivery package for multiple versions of the product, and allows for further
256 * development of older versions.
257 * <p>
258 * {@code true} to continue normally, {@code false} to fail fast with an exception.
259 * (default: {@code false})
260 */
261 private boolean ignoreIgnoredMigrations;
262
263 /**
264 * Ignore pending migrations when reading the schema history table. These are migrations that are available on the
265 * classpath but have not yet been performed by an application deployment.
266 * This can be useful for verifying that in-development migration changes don't contain any validation-breaking changes
267 * of migrations that have already been applied to a production environment, e.g. as part of a CI/CD process, without
268 * failing because of the existence of new migration versions.
269 * <p>
270 * {@code true} to continue normally, {@code false} to fail fast with an exception.
271 * (default: {@code false})
272 */
273 private boolean ignorePendingMigrations;
274
275 /**
276 * Ignore future migrations when reading the schema history table. These are migrations that were performed by a
277 * newer deployment of the application that are not yet available in this version. For example: we have migrations
278 * available on the classpath up to version 3.0. The schema history table indicates that a migration to version 4.0
279 * (unknown to us) has already been applied. Instead of bombing out (fail fast) with an exception, a
280 * warning is logged and Flyway continues normally. This is useful for situations where one must be able to redeploy
281 * an older version of the application after the database has been migrated by a newer one. (default: {@code true})
282 */
283 private boolean ignoreFutureMigrations = true;
284
285 /**
286 * Whether to validate migrations and callbacks whose scripts do not obey the correct naming convention. A failure can be
287 * useful to check that errors such as case sensitivity in migration prefixes have been corrected.
288 * {@code false} to continue normally, {@code true} to fail fast with an exception. (default: {@code false})
289 */
290 private boolean validateMigrationNaming = false;
291
292 /**
293 * Whether to automatically call validate or not when running migrate. (default: {@code true})
294 */
295 private boolean validateOnMigrate = true;
296
297 /**
298 * Whether to automatically call clean or not when a validation error occurs. (default: {@code false})
299 * <p> This is exclusively intended as a convenience for development. even though we
300 * strongly recommend not to change migration scripts once they have been checked into SCM and run, this provides a
301 * way of dealing with this case in a smooth manner. The database will be wiped clean automatically, ensuring that
302 * the next migration will bring you back to the state checked into SCM.</p>
303 * <p><b>Warning ! Do not enable in production !</b></p>
304 */
305 private boolean cleanOnValidationError;
306
307 /**
308 * Whether to disable clean. (default: {@code false})
309 * <p>This is especially useful for production environments where running clean can be quite a career limiting move.</p>
310 */
311 private boolean cleanDisabled;
312
313 /**
314 * The version to tag an existing schema with when executing baseline. (default: 1)
315 */
316 private MigrationVersion baselineVersion = MigrationVersion.fromVersion("1");
317
318 /**
319 * The description to tag an existing schema with when executing baseline. (default: << Flyway Baseline >>)
320 */
321 private String baselineDescription = "<< Flyway Baseline >>";
322
323 /**
324 * <p>
325 * Whether to automatically call baseline when migrate is executed against a non-empty schema with no schema history table.
326 * This schema will then be initialized with the {@code baselineVersion} before executing the migrations.
327 * Only migrations above {@code baselineVersion} will then be applied.
328 * </p>
329 * <p>
330 * This is useful for initial Flyway production deployments on projects with an existing DB.
331 * </p>
332 * <p>
333 * Be careful when enabling this as it removes the safety net that ensures
334 * Flyway does not migrate the wrong database in case of a configuration mistake! (default: {@code false})
335 * </p>
336 */
337 private boolean baselineOnMigrate;
338
339 /**
340 * Allows migrations to be run "out of order".
341 * <p>If you already have versions 1 and 3 applied, and now a version 2 is found,
342 * it will be applied too instead of being ignored.</p>
343 * <p>(default: {@code false})</p>
344 */
345 private boolean outOfOrder;
346
347 /**
348 * This is a list of custom callbacks that fire before and after tasks are executed. You can
349 * add as many custom callbacks as you want. (default: none)
350 */
351 private final List<Callback> callbacks = new ArrayList<>();
352
353 /**
354 * Whether Flyway should skip the default callbacks. If true, only custom callbacks are used.
355 * <p>(default: false)</p>
356 */
357 private boolean skipDefaultCallbacks;
358
359 /**
360 * The custom MigrationResolvers to be used in addition to the built-in ones for resolving Migrations to apply.
361 * <p>(default: none)</p>
362 */
363 private MigrationResolver[] resolvers = new MigrationResolver[0];
364
365 /**
366 * Whether Flyway should skip the default resolvers. If true, only custom resolvers are used.
367 * <p>(default: false)</p>
368 */
369 private boolean skipDefaultResolvers;
370
371 /**
372 * Whether to allow mixing transactional and non-transactional statements within the same migration.
373 * <p>
374 * {@code true} if mixed migrations should be allowed. {@code false} if an error should be thrown instead. (default: {@code false})
375 */
376 private boolean mixed;
377
378 /**
379 * Whether to group all pending migrations together in the same transaction when applying them (only recommended for databases with support for DDL transactions).
380 * <p>
381 * {@code true} if migrations should be grouped. {@code false} if they should be applied individually instead. (default: {@code false})
382 */
383 private boolean group;
384
385 /**
386 * The username that will be recorded in the schema history table as having applied the migration.
387 * <p>
388 * {@code null} for the current database user of the connection. (default: {@code null}).
389 */
390 private String installedBy;
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467 /**
468 * Creates a new default configuration.
469 */
470 public ClassicConfiguration() {
471 // Nothing to do.
472 }
473
474 /**
475 * Creates a new default configuration with this classloader.
476 *
477 * @param classLoader The ClassLoader to use for loading migrations, resolvers, etc from the classpath. (default: Thread.currentThread().getContextClassLoader() )
478 */
479 public ClassicConfiguration(ClassLoader classLoader) {
480 if (classLoader != null) {
481 this.classLoader = classLoader;
482 }
483 }
484
485 /**
486 * Creates a new configuration with the same values as this existing one.
487 *
488 * @param configuration The configuration to use.
489 */
490 public ClassicConfiguration(Configuration configuration) {
491 this(configuration.getClassLoader());
492 configure(configuration);
493 }
494
495 @Override
496 public Location[] getLocations() {
497 return locations.getLocations().toArray(new Location[0]);
498 }
499
500 @Override
501 public Charset getEncoding() {
502 return encoding;
503 }
504
505 @Override
506 public String getDefaultSchema() { return defaultSchemaName; }
507
508 @Override
509 public String[] getSchemas() { return schemaNames; }
510
511 @Override
512 public String getTable() {
513 return table;
514 }
515
516 @Override
517 public String getTablespace() {
518 return tablespace;
519 }
520
521 @Override
522 public MigrationVersion getTarget() {
523 return target;
524 }
525
526 @Override
527 public boolean isPlaceholderReplacement() {
528 return placeholderReplacement;
529 }
530
531 @Override
532 public Map<String, String> getPlaceholders() {
533 return placeholders;
534 }
535
536 @Override
537 public String getPlaceholderPrefix() {
538 return placeholderPrefix;
539 }
540
541 @Override
542 public String getPlaceholderSuffix() {
543 return placeholderSuffix;
544 }
545
546 @Override
547 public String getSqlMigrationPrefix() {
548 return sqlMigrationPrefix;
549 }
550
551 @Override
552 public String getRepeatableSqlMigrationPrefix() {
553 return repeatableSqlMigrationPrefix;
554 }
555
556 @Override
557 public String getSqlMigrationSeparator() {
558 return sqlMigrationSeparator;
559 }
560
561 @Override
562 public String[] getSqlMigrationSuffixes() {
563 return sqlMigrationSuffixes;
564 }
565
566 @Override
567 public JavaMigration[] getJavaMigrations() {
568 return javaMigrations;
569 }
570
571 @Override
572 public boolean isIgnoreMissingMigrations() {
573 return ignoreMissingMigrations;
574 }
575
576 @Override
577 public boolean isIgnoreIgnoredMigrations() {
578 return ignoreIgnoredMigrations;
579 }
580
581 @Override
582 public boolean isIgnorePendingMigrations() {
583 return ignorePendingMigrations;
584 }
585
586 @Override
587 public boolean isIgnoreFutureMigrations() {
588 return ignoreFutureMigrations;
589 }
590
591 @Override
592 public boolean isValidateMigrationNaming() {
593 return validateMigrationNaming;
594 }
595
596 @Override
597 public boolean isValidateOnMigrate() {
598 return validateOnMigrate;
599 }
600
601 @Override
602 public boolean isCleanOnValidationError() {
603 return cleanOnValidationError;
604 }
605
606 @Override
607 public boolean isCleanDisabled() {
608 return cleanDisabled;
609 }
610
611 @Override
612 public MigrationVersion getBaselineVersion() {
613 return baselineVersion;
614 }
615
616 @Override
617 public String getBaselineDescription() {
618 return baselineDescription;
619 }
620
621 @Override
622 public boolean isBaselineOnMigrate() {
623 return baselineOnMigrate;
624 }
625
626 @Override
627 public boolean isOutOfOrder() {
628 return outOfOrder;
629 }
630
631 @Override
632 public MigrationResolver[] getResolvers() {
633 return resolvers;
634 }
635
636 @Override
637 public boolean isSkipDefaultResolvers() {
638 return skipDefaultResolvers;
639 }
640
641 @Override
642 public DataSource getDataSource() {
643 if (dataSource == null &&
644 (StringUtils.hasLength(driver) || StringUtils.hasLength(user) || StringUtils.hasLength(password))) {
645 LOG.warn("Discarding INCOMPLETE dataSource configuration! " + ConfigUtils.URL + " must be set.");
646 }
647 return dataSource;
648 }
649
650 @Override
651 public int getConnectRetries() {
652 return connectRetries;
653 }
654
655 @Override
656 public String getInitSql() {
657 return initSql;
658 }
659
660 @Override
661 public ClassLoader getClassLoader() {
662 return classLoader;
663 }
664
665 @Override
666 public boolean isMixed() {
667 return mixed;
668 }
669
670 @Override
671 public String getInstalledBy() {
672 return installedBy;
673 }
674
675 @Override
676 public boolean isGroup() {
677 return group;
678 }
679
680 @Override
681 public String[] getErrorOverrides() {
682
683 throw new org.flywaydb.core.internal.license.FlywayProUpgradeRequiredException("errorOverrides");
684
685
686
687
688 }
689
690 @Override
691 public OutputStream getDryRunOutput() {
692
693 throw new org.flywaydb.core.internal.license.FlywayProUpgradeRequiredException("dryRunOutput");
694
695
696
697
698 }
699
700 @Override
701 public String getLicenseKey() {
702
703 throw new org.flywaydb.core.internal.license.FlywayProUpgradeRequiredException("licenseKey");
704
705
706
707
708 }
709
710 /**
711 * Whether Flyway should output a table with the results of queries when executing migrations.
712 *
713 * <p><i>Flyway Pro and Flyway Enterprise only</i></p>
714 *
715 * @return {@code true} to output the results table (default: {@code true})
716 */
717 @Override
718 public boolean outputQueryResults() {
719
720 throw new org.flywaydb.core.internal.license.FlywayProUpgradeRequiredException("outputQueryResults");
721
722
723
724
725 }
726
727 /**
728 * Sets the stream where to output the SQL statements of a migration dry run. {@code null} to execute the SQL statements
729 * directly against the database. The stream when be closing when Flyway finishes writing the output.
730 * <p><i>Flyway Pro and Flyway Enterprise only</i></p>
731 *
732 * @param dryRunOutput The output file or {@code null} to execute the SQL statements directly against the database.
733 */
734 public void setDryRunOutput(OutputStream dryRunOutput) {
735
736 throw new org.flywaydb.core.internal.license.FlywayProUpgradeRequiredException("dryRunOutput");
737
738
739
740
741 }
742
743 /**
744 * Sets the file where to output the SQL statements of a migration dry run. {@code null} to execute the SQL statements
745 * directly against the database. If the file specified is in a non-existent directory, Flyway will create all
746 * directories and parent directories as needed.
747 * <p><i>Flyway Pro and Flyway Enterprise only</i></p>
748 *
749 * @param dryRunOutput The output file or {@code null} to execute the SQL statements directly against the database.
750 */
751 public void setDryRunOutputAsFile(File dryRunOutput) {
752
753 throw new org.flywaydb.core.internal.license.FlywayProUpgradeRequiredException("dryRunOutput");
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797 }
798
799 /**
800 * Sets the file where to output the SQL statements of a migration dry run. {@code null} to execute the SQL statements
801 * directly against the database. If the file specified is in a non-existent directory, Flyway will create all
802 * directories and parent directories as needed.
803 * <p><i>Flyway Pro and Flyway Enterprise only</i></p>
804 *
805 * @param dryRunOutputFileName The name of the output file or {@code null} to execute the SQL statements directly
806 * against the database.
807 */
808 public void setDryRunOutputAsFileName(String dryRunOutputFileName) {
809
810 throw new org.flywaydb.core.internal.license.FlywayProUpgradeRequiredException("dryRunOutput");
811
812
813
814
815 }
816
817 /**
818 * Rules for the built-in error handler that let you override specific SQL states and errors codes in order to force
819 * specific errors or warnings to be treated as debug messages, info messages, warnings or errors.
820 * <p>Each error override has the following format: {@code STATE:12345:W}.
821 * It is a 5 character SQL state (or * to match all SQL states), a colon,
822 * the SQL error code (or * to match all SQL error codes), a colon and finally
823 * the desired behavior that should override the initial one.</p>
824 * <p>The following behaviors are accepted:</p>
825 * <ul>
826 * <li>{@code D} to force a debug message</li>
827 * <li>{@code D-} to force a debug message, but do not show the original sql state and error code</li>
828 * <li>{@code I} to force an info message</li>
829 * <li>{@code I-} to force an info message, but do not show the original sql state and error code</li>
830 * <li>{@code W} to force a warning</li>
831 * <li>{@code W-} to force a warning, but do not show the original sql state and error code</li>
832 * <li>{@code E} to force an error</li>
833 * <li>{@code E-} to force an error, but do not show the original sql state and error code</li>
834 * </ul>
835 * <p>Example 1: to force Oracle stored procedure compilation issues to produce
836 * errors instead of warnings, the following errorOverride can be used: {@code 99999:17110:E}</p>
837 * <p>Example 2: to force SQL Server PRINT messages to be displayed as info messages (without SQL state and error
838 * code details) instead of warnings, the following errorOverride can be used: {@code S0001:0:I-}</p>
839 * <p>Example 3: to force all errors with SQL error code 123 to be treated as warnings instead,
840 * the following errorOverride can be used: {@code *:123:W}</p>
841 * <p><i>Flyway Pro and Flyway Enterprise only</i></p>
842 *
843 * @param errorOverrides The ErrorOverrides or an empty array if none are defined. (default: none)
844 */
845 public void setErrorOverrides(String... errorOverrides) {
846
847 throw new org.flywaydb.core.internal.license.FlywayProUpgradeRequiredException("errorOverrides");
848
849
850
851
852 }
853
854 /**
855 * Whether to group all pending migrations together in the same transaction when applying them (only recommended for databases with support for DDL transactions).
856 *
857 * @param group {@code true} if migrations should be grouped. {@code false} if they should be applied individually instead. (default: {@code false})
858 */
859 public void setGroup(boolean group) {
860 this.group = group;
861 }
862
863 /**
864 * The username that will be recorded in the schema history table as having applied the migration.
865 *
866 * @param installedBy The username or {@code null} for the current database user of the connection. (default: {@code null}).
867 */
868 public void setInstalledBy(String installedBy) {
869 if ("".equals(installedBy)) {
870 installedBy = null;
871 }
872 this.installedBy = installedBy;
873 }
874
875 /**
876 * Whether to allow mixing transactional and non-transactional statements within the same migration. Enabling this
877 * automatically causes the entire affected migration to be run without a transaction.
878 *
879 * <p>Note that this is only applicable for PostgreSQL, Aurora PostgreSQL, SQL Server and SQLite which all have
880 * statements that do not run at all within a transaction.</p>
881 * <p>This is not to be confused with implicit transaction, as they occur in MySQL or Oracle, where even though a
882 * DDL statement was run within a transaction, the database will issue an implicit commit before and after
883 * its execution.</p>
884 *
885 * @param mixed {@code true} if mixed migrations should be allowed. {@code false} if an error should be thrown instead. (default: {@code false})
886 */
887 public void setMixed(boolean mixed) {
888 this.mixed = mixed;
889 }
890
891 /**
892 * Ignore missing migrations when reading the schema history table. These are migrations that were performed by an
893 * older deployment of the application that are no longer available in this version. For example: we have migrations
894 * available on the classpath with versions 1.0 and 3.0. The schema history table indicates that a migration with version 2.0
895 * (unknown to us) has also been applied. Instead of bombing out (fail fast) with an exception, a
896 * warning is logged and Flyway continues normally. This is useful for situations where one must be able to deploy
897 * a newer version of the application even though it doesn't contain migrations included with an older one anymore.
898 * Note that if the most recently applied migration is removed, Flyway has no way to know it is missing and will
899 * mark it as future instead.
900 *
901 * @param ignoreMissingMigrations {@code true} to continue normally and log a warning, {@code false} to fail fast with an exception.
902 * (default: {@code false})
903 */
904 public void setIgnoreMissingMigrations(boolean ignoreMissingMigrations) {
905 this.ignoreMissingMigrations = ignoreMissingMigrations;
906 }
907
908 /**
909 * Ignore ignored migrations when reading the schema history table. These are migrations that were added in between
910 * already migrated migrations in this version. For example: we have migrations available on the classpath with
911 * versions from 1.0 to 3.0. The schema history table indicates that version 1 was finished on 1.0.15, and the next
912 * one was 2.0.0. But with the next release a new migration was added to version 1: 1.0.16. Such scenario is ignored
913 * by migrate command, but by default is rejected by validate. When ignoreIgnoredMigrations is enabled, such case
914 * will not be reported by validate command. This is useful for situations where one must be able to deliver
915 * complete set of migrations in a delivery package for multiple versions of the product, and allows for further
916 * development of older versions.
917 *
918 * @param ignoreIgnoredMigrations {@code true} to continue normally, {@code false} to fail fast with an exception.
919 * (default: {@code false})
920 */
921 public void setIgnoreIgnoredMigrations(boolean ignoreIgnoredMigrations) {
922 this.ignoreIgnoredMigrations = ignoreIgnoredMigrations;
923 }
924
925 /**
926 * Ignore pending migrations when reading the schema history table. These are migrations that are available
927 * but have not yet been applied. This can be useful for verifying that in-development migration changes
928 * don't contain any validation-breaking changes of migrations that have already been applied to a production
929 * environment, e.g. as part of a CI/CD process, without failing because of the existence of new migration versions.
930 *
931 * @param ignorePendingMigrations {@code true} to continue normally, {@code false} to fail fast with an exception.
932 * (default: {@code false})
933 */
934 public void setIgnorePendingMigrations(boolean ignorePendingMigrations) {
935 this.ignorePendingMigrations = ignorePendingMigrations;
936 }
937
938 /**
939 * Whether to ignore future migrations when reading the schema history table. These are migrations that were performed by a
940 * newer deployment of the application that are not yet available in this version. For example: we have migrations
941 * available on the classpath up to version 3.0. The schema history table indicates that a migration to version 4.0
942 * (unknown to us) has already been applied. Instead of bombing out (fail fast) with an exception, a
943 * warning is logged and Flyway continues normally. This is useful for situations where one must be able to redeploy
944 * an older version of the application after the database has been migrated by a newer one.
945 *
946 * @param ignoreFutureMigrations {@code true} to continue normally and log a warning, {@code false} to fail
947 * fast with an exception. (default: {@code true})
948 */
949 public void setIgnoreFutureMigrations(boolean ignoreFutureMigrations) {
950 this.ignoreFutureMigrations = ignoreFutureMigrations;
951 }
952
953 /**
954 * Whether to validate migrations and callbacks whose scripts do not obey the correct naming convention. A failure can be
955 * useful to check that errors such as case sensitivity in migration prefixes have been corrected.
956 *
957 * @param validateMigrationNaming {@code false} to continue normally, {@code true} to fail
958 * fast with an exception. (default: {@code false})
959 */
960 public void setValidateMigrationNaming(boolean validateMigrationNaming) {
961 this.validateMigrationNaming = validateMigrationNaming;
962 }
963
964 /**
965 * Whether to automatically call validate or not when running migrate.
966 *
967 * @param validateOnMigrate {@code true} if validate should be called. {@code false} if not. (default: {@code true})
968 */
969 public void setValidateOnMigrate(boolean validateOnMigrate) {
970 this.validateOnMigrate = validateOnMigrate;
971 }
972
973 /**
974 * Whether to automatically call clean or not when a validation error occurs.
975 * <p> This is exclusively intended as a convenience for development. even though we
976 * strongly recommend not to change migration scripts once they have been checked into SCM and run, this provides a
977 * way of dealing with this case in a smooth manner. The database will be wiped clean automatically, ensuring that
978 * the next migration will bring you back to the state checked into SCM.</p>
979 * <p><b>Warning ! Do not enable in production !</b></p>
980 *
981 * @param cleanOnValidationError {@code true} if clean should be called. {@code false} if not. (default: {@code false})
982 */
983 public void setCleanOnValidationError(boolean cleanOnValidationError) {
984 this.cleanOnValidationError = cleanOnValidationError;
985 }
986
987 /**
988 * Whether to disable clean.
989 * <p>This is especially useful for production environments where running clean can be quite a career limiting move.</p>
990 *
991 * @param cleanDisabled {@code true} to disable clean. {@code false} to leave it enabled. (default: {@code false})
992 */
993 public void setCleanDisabled(boolean cleanDisabled) {
994 this.cleanDisabled = cleanDisabled;
995 }
996
997 /**
998 * Sets the locations to scan recursively for migrations.
999 * <p>The location type is determined by its prefix.
1000 * Unprefixed locations or locations starting with {@code classpath:} point to a package on the classpath and may
1001 * contain both SQL and Java-based migrations.
1002 * Locations starting with {@code filesystem:} point to a directory on the filesystem, may only
1003 * contain SQL migrations and are only scanned recursively down non-hidden directories.</p>
1004 *
1005 * @param locations Locations to scan recursively for migrations. (default: db/migration)
1006 */
1007 public void setLocationsAsStrings(String... locations) {
1008 this.locations = new Locations(locations);
1009 }
1010
1011 /**
1012 * Sets the locations to scan recursively for migrations.
1013 * <p>The location type is determined by its prefix.
1014 * Unprefixed locations or locations starting with {@code classpath:} point to a package on the classpath and may
1015 * contain both SQL and Java-based migrations.
1016 * Locations starting with {@code filesystem:} point to a directory on the filesystem, may only
1017 * contain SQL migrations and are only scanned recursively down non-hidden directories.</p>
1018 *
1019 * @param locations Locations to scan recursively for migrations. (default: db/migration)
1020 */
1021 public void setLocations(Location... locations) {
1022 this.locations = new Locations(Arrays.asList(locations));
1023 }
1024
1025 /**
1026 * Sets the encoding of Sql migrations.
1027 *
1028 * @param encoding The encoding of Sql migrations. (default: UTF-8)
1029 */
1030 public void setEncoding(Charset encoding) {
1031 this.encoding = encoding;
1032 }
1033
1034 /**
1035 * Sets the encoding of Sql migrations.
1036 *
1037 * @param encoding The encoding of Sql migrations. (default: UTF-8)
1038 */
1039 public void setEncodingAsString(String encoding) {
1040 this.encoding = Charset.forName(encoding);
1041 }
1042
1043 /**
1044 * Sets the default schema managed by Flyway. This schema name is case-sensitive. If not specified, but
1045 * <i>Schemas</i> is, Flyway uses the first schema in that list. If that is also not specified, Flyway uses the default
1046 * schema for the database connection.
1047 * <p>Consequences:</p>
1048 * <ul>
1049 * <li>This schema will be the one containing the schema history table.</li>
1050 * <li>This schema will be the default for the database connection (provided the database supports this concept).</li>
1051 * </ul>
1052 *
1053 * @param schema The default schema managed by Flyway.
1054 */
1055 public void setDefaultSchema(String schema) {
1056 this.defaultSchemaName = schema;
1057 }
1058
1059 /**
1060 * Sets the schemas managed by Flyway. These schema names are case-sensitive. If not specified, Flyway uses
1061 * the default schema for the database connection. If <i>defaultSchema</i> is not specified, then the first of
1062 * this list also acts as default schema.
1063 * <p>Consequences:</p>
1064 * <ul>
1065 * <li>Flyway will automatically attempt to create all these schemas, unless they already exist.</li>
1066 * <li>The schemas will be cleaned in the order of this list.</li>
1067 * <li>If Flyway created them, the schemas themselves will be dropped when cleaning.</li>
1068 * </ul>
1069 *
1070 * @param schemas The schemas managed by Flyway. May not be {@code null}. Must contain at least one element.
1071 */
1072 public void setSchemas(String... schemas) {
1073 this.schemaNames = schemas;
1074 }
1075
1076 /**
1077 * <p>Sets the name of the schema history table that will be used by Flyway. </p><p> By default (single-schema mode)
1078 * the schema history table is placed in the default schema for the connection provided by the datasource. </p> <p> When
1079 * the <i>flyway.schemas</i> property is set (multi-schema mode), the schema history table is placed in the first schema
1080 * of the list. </p>
1081 *
1082 * @param table The name of the schema history table that will be used by Flyway. (default: flyway_schema_history)
1083 */
1084 public void setTable(String table) {
1085 this.table = table;
1086 }
1087
1088 /**
1089 * <p>Sets the tablespace where to create the schema history table that will be used by Flyway.</p>
1090 * <p>If not specified, Flyway uses the default tablespace for the database connection.This setting is only relevant
1091 * for databases that do support the notion of tablespaces. Its value is simply
1092 * ignored for all others.</p>
1093 *
1094 * @param tablespace The tablespace where to create the schema history table that will be used by Flyway.
1095 */
1096 public void setTablespace(String tablespace) {
1097 this.tablespace = tablespace;
1098 }
1099
1100 /**
1101 * Sets the target version up to which Flyway should consider migrations.
1102 * Migrations with a higher version number will be ignored.
1103 * Special values:
1104 * <ul>
1105 * <li>{@code current}: designates the current version of the schema</li>
1106 * <li>{@code latest}: the latest version of the schema, as defined by the migration with the highest version</li>
1107 * </ul>
1108 * Defaults to {@code latest}.
1109 */
1110 public void setTarget(MigrationVersion target) {
1111 this.target = target;
1112 }
1113
1114 /**
1115 * Sets the target version up to which Flyway should consider migrations.
1116 * Migrations with a higher version number will be ignored.
1117 * Special values:
1118 * <ul>
1119 * <li>{@code current}: designates the current version of the schema</li>
1120 * <li>{@code latest}: the latest version of the schema, as defined by the migration with the highest version</li>
1121 * </ul>
1122 * Defaults to {@code latest}.
1123 */
1124 public void setTargetAsString(String target) {
1125 this.target = MigrationVersion.fromVersion(target);
1126 }
1127
1128 /**
1129 * Sets whether placeholders should be replaced.
1130 *
1131 * @param placeholderReplacement Whether placeholders should be replaced. (default: true)
1132 */
1133 public void setPlaceholderReplacement(boolean placeholderReplacement) {
1134 this.placeholderReplacement = placeholderReplacement;
1135 }
1136
1137 /**
1138 * Sets the placeholders to replace in sql migration scripts.
1139 *
1140 * @param placeholders The map of <placeholder, replacementValue> to apply to sql migration scripts.
1141 */
1142 public void setPlaceholders(Map<String, String> placeholders) {
1143 this.placeholders = placeholders;
1144 }
1145
1146 /**
1147 * Sets the prefix of every placeholder.
1148 *
1149 * @param placeholderPrefix The prefix of every placeholder. (default: ${ )
1150 */
1151 public void setPlaceholderPrefix(String placeholderPrefix) {
1152 if (!StringUtils.hasLength(placeholderPrefix)) {
1153 throw new FlywayException("placeholderPrefix cannot be empty!", ErrorCode.CONFIGURATION);
1154 }
1155 this.placeholderPrefix = placeholderPrefix;
1156 }
1157
1158 /**
1159 * Sets the suffix of every placeholder.
1160 *
1161 * @param placeholderSuffix The suffix of every placeholder. (default: } )
1162 */
1163 public void setPlaceholderSuffix(String placeholderSuffix) {
1164 if (!StringUtils.hasLength(placeholderSuffix)) {
1165 throw new FlywayException("placeholderSuffix cannot be empty!", ErrorCode.CONFIGURATION);
1166 }
1167 this.placeholderSuffix = placeholderSuffix;
1168 }
1169
1170 /**
1171 * Sets the file name prefix for sql migrations.
1172 * <p>Sql migrations have the following file name structure: prefixVERSIONseparatorDESCRIPTIONsuffix ,
1173 * which using the defaults translates to V1_1__My_description.sql</p>
1174 *
1175 * @param sqlMigrationPrefix The file name prefix for sql migrations (default: V)
1176 */
1177 public void setSqlMigrationPrefix(String sqlMigrationPrefix) {
1178 this.sqlMigrationPrefix = sqlMigrationPrefix;
1179 }
1180
1181 @Override
1182 public String getUndoSqlMigrationPrefix() {
1183
1184 throw new org.flywaydb.core.internal.license.FlywayProUpgradeRequiredException("undoSqlMigrationPrefix");
1185
1186
1187
1188
1189 }
1190
1191 /**
1192 * Sets the file name prefix for undo SQL migrations. (default: U)
1193 * <p>Undo SQL migrations are responsible for undoing the effects of the versioned migration with the same version.</p>
1194 * <p>They have the following file name structure: prefixVERSIONseparatorDESCRIPTIONsuffix ,
1195 * which using the defaults translates to U1.1__My_description.sql</p>
1196 * <p><i>Flyway Pro and Flyway Enterprise only</i></p>
1197 *
1198 * @param undoSqlMigrationPrefix The file name prefix for undo SQL migrations. (default: U)
1199 */
1200 public void setUndoSqlMigrationPrefix(String undoSqlMigrationPrefix) {
1201
1202 throw new org.flywaydb.core.internal.license.FlywayProUpgradeRequiredException("undoSqlMigrationPrefix");
1203
1204
1205
1206
1207 }
1208
1209 /**
1210 * The manually added Java-based migrations. These are not Java-based migrations discovered through classpath
1211 * scanning and instantiated by Flyway. Instead these are manually added instances of JavaMigration.
1212 * This is particularly useful when working with a dependency injection container, where you may want the DI
1213 * container to instantiate the class and wire up its dependencies for you.
1214 *
1215 * @param javaMigrations The manually added Java-based migrations. An empty array if none. (default: none)
1216 */
1217 public void setJavaMigrations(JavaMigration... javaMigrations) {
1218 if (javaMigrations == null) {
1219 throw new FlywayException("javaMigrations cannot be null", ErrorCode.CONFIGURATION);
1220 }
1221 this.javaMigrations = javaMigrations;
1222 }
1223
1224 @Override
1225 public boolean isStream() {
1226
1227 throw new org.flywaydb.core.internal.license.FlywayProUpgradeRequiredException("stream");
1228
1229
1230
1231
1232 }
1233
1234 /**
1235 * Whether to stream SQL migrations when executing them. Streaming doesn't load the entire migration in memory at
1236 * once. Instead each statement is loaded individually. This is particularly useful for very large SQL migrations
1237 * composed of multiple MB or even GB of reference data, as this dramatically reduces Flyway's memory consumption.
1238 * <p><i>Flyway Pro and Flyway Enterprise only</i></p>
1239 *
1240 * @param stream {@code true} to stream SQL migrations. {@code false} to fully loaded them in memory instead. (default: {@code false})
1241 */
1242 public void setStream(boolean stream) {
1243
1244 throw new org.flywaydb.core.internal.license.FlywayProUpgradeRequiredException("stream");
1245
1246
1247
1248
1249 }
1250
1251 @Override
1252 public boolean isBatch() {
1253
1254 throw new org.flywaydb.core.internal.license.FlywayProUpgradeRequiredException("batch");
1255
1256
1257
1258
1259 }
1260
1261 /**
1262 * Whether to batch SQL statements when executing them. Batching can save up to 99 percent of network roundtrips by
1263 * sending up to 100 statements at once over the network to the database, instead of sending each statement
1264 * individually. This is particularly useful for very large SQL migrations composed of multiple MB or even GB of
1265 * reference data, as this can dramatically reduce the network overhead. This is supported for INSERT, UPDATE,
1266 * DELETE, MERGE and UPSERT statements. All other statements are automatically executed without batching.
1267 * <p><i>Flyway Pro and Flyway Enterprise only</i></p>
1268 *
1269 * @param batch {@code true} to batch SQL statements. {@code false} to execute them individually instead. (default: {@code false})
1270 */
1271 public void setBatch(boolean batch) {
1272
1273 throw new org.flywaydb.core.internal.license.FlywayProUpgradeRequiredException("batch");
1274
1275
1276
1277
1278 }
1279
1280 /**
1281 * Sets the file name prefix for repeatable sql migrations.
1282 * <p>Repeatable sql migrations have the following file name structure: prefixSeparatorDESCRIPTIONsuffix ,
1283 * which using the defaults translates to R__My_description.sql</p>
1284 *
1285 * @param repeatableSqlMigrationPrefix The file name prefix for repeatable sql migrations (default: R)
1286 */
1287 public void setRepeatableSqlMigrationPrefix(String repeatableSqlMigrationPrefix) {
1288 this.repeatableSqlMigrationPrefix = repeatableSqlMigrationPrefix;
1289 }
1290
1291 /**
1292 * Sets the file name separator for sql migrations.
1293 * <p>Sql migrations have the following file name structure: prefixVERSIONseparatorDESCRIPTIONsuffix ,
1294 * which using the defaults translates to V1_1__My_description.sql</p>
1295 *
1296 * @param sqlMigrationSeparator The file name separator for sql migrations (default: __)
1297 */
1298 public void setSqlMigrationSeparator(String sqlMigrationSeparator) {
1299 if (!StringUtils.hasLength(sqlMigrationSeparator)) {
1300 throw new FlywayException("sqlMigrationSeparator cannot be empty!", ErrorCode.CONFIGURATION);
1301 }
1302
1303 this.sqlMigrationSeparator = sqlMigrationSeparator;
1304 }
1305
1306 /**
1307 * The file name suffixes for SQL migrations. (default: .sql)
1308 * <p>SQL migrations have the following file name structure: prefixVERSIONseparatorDESCRIPTIONsuffix ,
1309 * which using the defaults translates to V1_1__My_description.sql</p>
1310 * <p>Multiple suffixes (like .sql,.pkg,.pkb) can be specified for easier compatibility with other tools such as
1311 * editors with specific file associations.</p>
1312 *
1313 * @param sqlMigrationSuffixes The file name suffixes for SQL migrations.
1314 */
1315 public void setSqlMigrationSuffixes(String... sqlMigrationSuffixes) {
1316 this.sqlMigrationSuffixes = sqlMigrationSuffixes;
1317 }
1318
1319 /**
1320 * Sets the datasource to use. Must have the necessary privileges to execute ddl.
1321 *
1322 * @param dataSource The datasource to use. Must have the necessary privileges to execute ddl.
1323 */
1324 public void setDataSource(DataSource dataSource) {
1325 driver = null;
1326 url = null;
1327 user = null;
1328 password = null;
1329 this.dataSource = dataSource;
1330 }
1331
1332 /**
1333 * Sets the datasource to use. Must have the necessary privileges to execute ddl.
1334 * <p>To use a custom ClassLoader, setClassLoader() must be called prior to calling this method.</p>
1335 *
1336 * @param url The JDBC URL of the database.
1337 * @param user The user of the database.
1338 * @param password The password of the database.
1339 */
1340 public void setDataSource(String url, String user, String password) {
1341 this.dataSource = new DriverDataSource(classLoader, null, url, user, password);
1342 }
1343
1344 /**
1345 * The maximum number of retries when attempting to connect to the database. After each failed attempt, Flyway will
1346 * wait 1 second before attempting to connect again, up to the maximum number of times specified by connectRetries.
1347 *
1348 * @param connectRetries The maximum number of retries (default: 0).
1349 */
1350 public void setConnectRetries(int connectRetries) {
1351 if (connectRetries < 0) {
1352 throw new FlywayException("Invalid number of connectRetries (must be 0 or greater): " + connectRetries, ErrorCode.CONFIGURATION);
1353 }
1354 this.connectRetries = connectRetries;
1355 }
1356
1357 /**
1358 * The SQL statements to run to initialize a new database connection immediately after opening it.
1359 *
1360 * @param initSql The SQL statements. (default: {@code null})
1361 */
1362 public void setInitSql(String initSql) {
1363 this.initSql = initSql;
1364 }
1365
1366 /**
1367 * Sets the version to tag an existing schema with when executing baseline.
1368 *
1369 * @param baselineVersion The version to tag an existing schema with when executing baseline. (default: 1)
1370 */
1371 public void setBaselineVersion(MigrationVersion baselineVersion) {
1372 this.baselineVersion = baselineVersion;
1373 }
1374
1375 /**
1376 * Sets the version to tag an existing schema with when executing baseline.
1377 *
1378 * @param baselineVersion The version to tag an existing schema with when executing baseline. (default: 1)
1379 */
1380 public void setBaselineVersionAsString(String baselineVersion) {
1381 this.baselineVersion = MigrationVersion.fromVersion(baselineVersion);
1382 }
1383
1384 /**
1385 * Sets the description to tag an existing schema with when executing baseline.
1386 *
1387 * @param baselineDescription The description to tag an existing schema with when executing baseline. (default: << Flyway Baseline >>)
1388 */
1389 public void setBaselineDescription(String baselineDescription) {
1390 this.baselineDescription = baselineDescription;
1391 }
1392
1393 /**
1394 * <p>
1395 * Whether to automatically call baseline when migrate is executed against a non-empty schema with no schema history table.
1396 * This schema will then be baselined with the {@code baselineVersion} before executing the migrations.
1397 * Only migrations above {@code baselineVersion} will then be applied.
1398 * </p>
1399 * <p>
1400 * This is useful for initial Flyway production deployments on projects with an existing DB.
1401 * </p>
1402 * <p>
1403 * Be careful when enabling this as it removes the safety net that ensures
1404 * Flyway does not migrate the wrong database in case of a configuration mistake!
1405 * </p>
1406 *
1407 * @param baselineOnMigrate {@code true} if baseline should be called on migrate for non-empty schemas, {@code false} if not. (default: {@code false})
1408 */
1409 public void setBaselineOnMigrate(boolean baselineOnMigrate) {
1410 this.baselineOnMigrate = baselineOnMigrate;
1411 }
1412
1413 /**
1414 * Allows migrations to be run "out of order".
1415 * <p>If you already have versions 1 and 3 applied, and now a version 2 is found,
1416 * it will be applied too instead of being ignored.</p>
1417 *
1418 * @param outOfOrder {@code true} if outOfOrder migrations should be applied, {@code false} if not. (default: {@code false})
1419 */
1420 public void setOutOfOrder(boolean outOfOrder) {
1421 this.outOfOrder = outOfOrder;
1422 }
1423
1424 /**
1425 * Gets the callbacks for lifecycle notifications.
1426 *
1427 * @return The callbacks for lifecycle notifications. An empty array if none. (default: none)
1428 */
1429 @Override
1430 public Callback[] getCallbacks() {
1431 return callbacks.toArray(new Callback[0]);
1432 }
1433
1434 @Override
1435 public boolean isSkipDefaultCallbacks() {
1436 return skipDefaultCallbacks;
1437 }
1438
1439 /**
1440 * Set the callbacks for lifecycle notifications.
1441 *
1442 * @param callbacks The callbacks for lifecycle notifications. (default: none)
1443 */
1444 public void setCallbacks(Callback... callbacks) {
1445 this.callbacks.clear();
1446 this.callbacks.addAll(Arrays.asList(callbacks));
1447 }
1448
1449 /**
1450 * Set the callbacks for lifecycle notifications.
1451 *
1452 * @param callbacks The fully qualified class names of the callbacks for lifecycle notifications. (default: none)
1453 */
1454 public void setCallbacksAsClassNames(String... callbacks) {
1455 this.callbacks.clear();
1456 for (String callback : callbacks) {
1457 Object o = ClassUtils.instantiate(callback, classLoader);
1458 if (o instanceof Callback) {
1459 this.callbacks.add((Callback) o);
1460 } else {
1461 throw new FlywayException("Invalid callback: " + callback + " (must implement org.flywaydb.core.api.callback.Callback)", ErrorCode.CONFIGURATION);
1462 }
1463 }
1464 }
1465
1466 /**
1467 * Whether Flyway should skip the default callbacks. If true, only custom callbacks are used.
1468 *
1469 * @param skipDefaultCallbacks Whether default built-in callbacks should be skipped. <p>(default: false)</p>
1470 */
1471 public void setSkipDefaultCallbacks(boolean skipDefaultCallbacks) {
1472 this.skipDefaultCallbacks = skipDefaultCallbacks;
1473 }
1474
1475 /**
1476 * Sets custom MigrationResolvers to be used in addition to the built-in ones for resolving Migrations to apply.
1477 *
1478 * @param resolvers The custom MigrationResolvers to be used in addition to the built-in ones for resolving Migrations to apply. (default: empty list)
1479 */
1480 public void setResolvers(MigrationResolver... resolvers) {
1481 this.resolvers = resolvers;
1482 }
1483
1484 /**
1485 * Sets custom MigrationResolvers to be used in addition to the built-in ones for resolving Migrations to apply.
1486 *
1487 * @param resolvers The fully qualified class names of the custom MigrationResolvers to be used in addition to the built-in ones for resolving Migrations to apply. (default: empty list)
1488 */
1489 public void setResolversAsClassNames(String... resolvers) {
1490 List<MigrationResolver> resolverList = ClassUtils.instantiateAll(resolvers, classLoader);
1491 setResolvers(resolverList.toArray(new MigrationResolver[resolvers.length]));
1492 }
1493
1494 /**
1495 * Whether Flyway should skip the default resolvers. If true, only custom resolvers are used.
1496 *
1497 * @param skipDefaultResolvers Whether default built-in resolvers should be skipped. <p>(default: false)</p>
1498 */
1499 public void setSkipDefaultResolvers(boolean skipDefaultResolvers) {
1500 this.skipDefaultResolvers = skipDefaultResolvers;
1501 }
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520 @Override
1521 public boolean isOracleSqlplus() {
1522
1523 throw new org.flywaydb.core.internal.license.FlywayProUpgradeRequiredException("oracle.sqlplus");
1524
1525
1526
1527
1528 }
1529
1530 /**
1531 * Whether to Flyway's support for Oracle SQL*Plus commands should be activated.
1532 * <p><i>Flyway Pro and Flyway Enterprise only</i></p>
1533 *
1534 * @param oracleSqlplus {@code true} to active SQL*Plus support. {@code false} to fail fast instead. (default: {@code false})
1535 */
1536 public void setOracleSqlplus(boolean oracleSqlplus) {
1537
1538 throw new org.flywaydb.core.internal.license.FlywayProUpgradeRequiredException("oracle.sqlplus");
1539
1540
1541
1542
1543 }
1544
1545 @Override
1546 public boolean isOracleSqlplusWarn() {
1547
1548 throw new org.flywaydb.core.internal.license.FlywayProUpgradeRequiredException("oracle.sqlplusWarn");
1549
1550
1551
1552
1553 }
1554
1555 /**
1556 * Whether Flyway should issue a warning instead of an error whenever it encounters an Oracle SQL*Plus statement
1557 * it doesn't yet support.
1558 *
1559 * <p><i>Flyway Pro and Flyway Enterprise only</i></p>
1560 *
1561 * @param oracleSqlplusWarn {@code true} to issue a warning. {@code false} to fail fast instead. (default: {@code false})
1562 */
1563 public void setOracleSqlplusWarn(boolean oracleSqlplusWarn) {
1564
1565 throw new org.flywaydb.core.internal.license.FlywayProUpgradeRequiredException("oracle.sqlplusWarn");
1566
1567
1568
1569
1570 }
1571
1572 /**
1573 * Your Flyway license key (FL01...). Not yet a Flyway Pro or Enterprise Edition customer?
1574 * Request your <a href="https://flywaydb.org/download/">Flyway trial license key</a>
1575 * to try out Flyway Pro and Enterprise Edition features free for 30 days.
1576 *
1577 * <p><i>Flyway Pro and Flyway Enterprise only</i></p>
1578 *
1579 * @param licenseKey Your Flyway license key.
1580 */
1581 public void setLicenseKey(String licenseKey) {
1582
1583 LOG.warn(Edition.PRO + " or " + Edition.ENTERPRISE + " upgrade required: " + licenseKey
1584 + " is not supported by " + Edition.COMMUNITY + ".");
1585
1586
1587
1588
1589 }
1590
1591 /**
1592 * Configure with the same values as this existing configuration.
1593 *
1594 * @param configuration The configuration to use.
1595 */
1596 public void configure(Configuration configuration) {
1597 setBaselineDescription(configuration.getBaselineDescription());
1598 setBaselineOnMigrate(configuration.isBaselineOnMigrate());
1599 setBaselineVersion(configuration.getBaselineVersion());
1600 setCallbacks(configuration.getCallbacks());
1601 setCleanDisabled(configuration.isCleanDisabled());
1602 setCleanOnValidationError(configuration.isCleanOnValidationError());
1603 setDataSource(configuration.getDataSource());
1604 setConnectRetries(configuration.getConnectRetries());
1605 setInitSql(configuration.getInitSql());
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617 setEncoding(configuration.getEncoding());
1618 setGroup(configuration.isGroup());
1619 setValidateMigrationNaming(configuration.isValidateMigrationNaming());
1620 setIgnoreFutureMigrations(configuration.isIgnoreFutureMigrations());
1621 setIgnoreMissingMigrations(configuration.isIgnoreMissingMigrations());
1622 setIgnoreIgnoredMigrations(configuration.isIgnoreIgnoredMigrations());
1623 setIgnorePendingMigrations(configuration.isIgnorePendingMigrations());
1624 setInstalledBy(configuration.getInstalledBy());
1625 setJavaMigrations(configuration.getJavaMigrations());
1626 setLocations(configuration.getLocations());
1627 setMixed(configuration.isMixed());
1628 setOutOfOrder(configuration.isOutOfOrder());
1629 setPlaceholderPrefix(configuration.getPlaceholderPrefix());
1630 setPlaceholderReplacement(configuration.isPlaceholderReplacement());
1631 setPlaceholders(configuration.getPlaceholders());
1632 setPlaceholderSuffix(configuration.getPlaceholderSuffix());
1633 setRepeatableSqlMigrationPrefix(configuration.getRepeatableSqlMigrationPrefix());
1634 setResolvers(configuration.getResolvers());
1635 setDefaultSchema(configuration.getDefaultSchema());
1636 setSchemas(configuration.getSchemas());
1637 setSkipDefaultCallbacks(configuration.isSkipDefaultCallbacks());
1638 setSkipDefaultResolvers(configuration.isSkipDefaultResolvers());
1639 setSqlMigrationPrefix(configuration.getSqlMigrationPrefix());
1640 setSqlMigrationSeparator(configuration.getSqlMigrationSeparator());
1641 setSqlMigrationSuffixes(configuration.getSqlMigrationSuffixes());
1642 setTable(configuration.getTable());
1643 setTablespace(configuration.getTablespace());
1644 setTarget(configuration.getTarget());
1645 setValidateOnMigrate(configuration.isValidateOnMigrate());
1646 }
1647
1648 /**
1649 * Whether Flyway should output a table with the results of queries when executing migrations.
1650 *
1651 * <p><i>Flyway Pro and Flyway Enterprise only</i></p>
1652 *
1653 * @return {@code true} to output the results table (default: {@code true})
1654 */
1655 private void setOutputQueryResults(boolean outputQueryResults) {
1656
1657 throw new org.flywaydb.core.internal.license.FlywayProUpgradeRequiredException("outputQueryResults");
1658
1659
1660
1661
1662 }
1663
1664 /**
1665 * Configures Flyway with these properties. This overwrites any existing configuration. Property names are
1666 * documented in the flyway maven plugin.
1667 * <p>To use a custom ClassLoader, setClassLoader() must be called prior to calling this method.</p>
1668 *
1669 * @param properties Properties used for configuration.
1670 * @throws FlywayException when the configuration failed.
1671 */
1672 public void configure(Properties properties) {
1673 configure(ConfigUtils.propertiesToMap(properties));
1674 }
1675
1676 /**
1677 * Configures Flyway with these properties. This overwrites any existing configuration. Property names are
1678 * documented in the flyway maven plugin.
1679 * <p>To use a custom ClassLoader, it must be passed to the Flyway constructor prior to calling this method.</p>
1680 *
1681 * @param props Properties used for configuration.
1682 * @throws FlywayException when the configuration failed.
1683 */
1684 public void configure(Map<String, String> props) {
1685 // Make copy to prevent removing elements from the original.
1686 props = new HashMap<>(props);
1687
1688 String driverProp = props.remove(ConfigUtils.DRIVER);
1689 if (driverProp != null) {
1690 dataSource = null;
1691 driver = driverProp;
1692 }
1693 String urlProp = props.remove(ConfigUtils.URL);
1694 if (urlProp != null) {
1695 dataSource = null;
1696 url = urlProp;
1697 }
1698 String userProp = props.remove(ConfigUtils.USER);
1699 if (userProp != null) {
1700 dataSource = null;
1701 user = userProp;
1702 }
1703 String passwordProp = props.remove(ConfigUtils.PASSWORD);
1704 if (passwordProp != null) {
1705 dataSource = null;
1706 password = passwordProp;
1707 }
1708 if (StringUtils.hasText(url) && (StringUtils.hasText(urlProp) ||
1709 StringUtils.hasText(driverProp) || StringUtils.hasText(userProp) || StringUtils.hasText(passwordProp))) {
1710 setDataSource(new DriverDataSource(classLoader, driver, url, user, password));
1711 }
1712 Integer connectRetriesProp = removeInteger(props, ConfigUtils.CONNECT_RETRIES);
1713 if (connectRetriesProp != null) {
1714 setConnectRetries(connectRetriesProp);
1715 }
1716 String initSqlProp = props.remove(ConfigUtils.INIT_SQL);
1717 if (initSqlProp != null) {
1718 setInitSql(initSqlProp);
1719 }
1720 String locationsProp = props.remove(ConfigUtils.LOCATIONS);
1721 if (locationsProp != null) {
1722 setLocationsAsStrings(StringUtils.tokenizeToStringArray(locationsProp, ","));
1723 }
1724 Boolean placeholderReplacementProp = removeBoolean(props, ConfigUtils.PLACEHOLDER_REPLACEMENT);
1725 if (placeholderReplacementProp != null) {
1726 setPlaceholderReplacement(placeholderReplacementProp);
1727 }
1728 String placeholderPrefixProp = props.remove(ConfigUtils.PLACEHOLDER_PREFIX);
1729 if (placeholderPrefixProp != null) {
1730 setPlaceholderPrefix(placeholderPrefixProp);
1731 }
1732 String placeholderSuffixProp = props.remove(ConfigUtils.PLACEHOLDER_SUFFIX);
1733 if (placeholderSuffixProp != null) {
1734 setPlaceholderSuffix(placeholderSuffixProp);
1735 }
1736 String sqlMigrationPrefixProp = props.remove(ConfigUtils.SQL_MIGRATION_PREFIX);
1737 if (sqlMigrationPrefixProp != null) {
1738 setSqlMigrationPrefix(sqlMigrationPrefixProp);
1739 }
1740 String undoSqlMigrationPrefixProp = props.remove(ConfigUtils.UNDO_SQL_MIGRATION_PREFIX);
1741 if (undoSqlMigrationPrefixProp != null) {
1742 setUndoSqlMigrationPrefix(undoSqlMigrationPrefixProp);
1743 }
1744 String repeatableSqlMigrationPrefixProp = props.remove(ConfigUtils.REPEATABLE_SQL_MIGRATION_PREFIX);
1745 if (repeatableSqlMigrationPrefixProp != null) {
1746 setRepeatableSqlMigrationPrefix(repeatableSqlMigrationPrefixProp);
1747 }
1748 String sqlMigrationSeparatorProp = props.remove(ConfigUtils.SQL_MIGRATION_SEPARATOR);
1749 if (sqlMigrationSeparatorProp != null) {
1750 setSqlMigrationSeparator(sqlMigrationSeparatorProp);
1751 }
1752 String sqlMigrationSuffixesProp = props.remove(ConfigUtils.SQL_MIGRATION_SUFFIXES);
1753 if (sqlMigrationSuffixesProp != null) {
1754 setSqlMigrationSuffixes(StringUtils.tokenizeToStringArray(sqlMigrationSuffixesProp, ","));
1755 }
1756 String encodingProp = props.remove(ConfigUtils.ENCODING);
1757 if (encodingProp != null) {
1758 setEncodingAsString(encodingProp);
1759 }
1760 String defaultSchemaProp = props.remove(ConfigUtils.DEFAULT_SCHEMA);
1761 if (defaultSchemaProp != null) {
1762 setDefaultSchema(defaultSchemaProp);
1763 }
1764 String schemasProp = props.remove(ConfigUtils.SCHEMAS);
1765 if (schemasProp != null) {
1766 setSchemas(StringUtils.tokenizeToStringArray(schemasProp, ","));
1767 }
1768 String tableProp = props.remove(ConfigUtils.TABLE);
1769 if (tableProp != null) {
1770 setTable(tableProp);
1771 }
1772 String tablespaceProp = props.remove(ConfigUtils.TABLESPACE);
1773 if (tablespaceProp != null) {
1774 setTablespace(tablespaceProp);
1775 }
1776 Boolean cleanOnValidationErrorProp = removeBoolean(props, ConfigUtils.CLEAN_ON_VALIDATION_ERROR);
1777 if (cleanOnValidationErrorProp != null) {
1778 setCleanOnValidationError(cleanOnValidationErrorProp);
1779 }
1780 Boolean cleanDisabledProp = removeBoolean(props, ConfigUtils.CLEAN_DISABLED);
1781 if (cleanDisabledProp != null) {
1782 setCleanDisabled(cleanDisabledProp);
1783 }
1784 Boolean validateOnMigrateProp = removeBoolean(props, ConfigUtils.VALIDATE_ON_MIGRATE);
1785 if (validateOnMigrateProp != null) {
1786 setValidateOnMigrate(validateOnMigrateProp);
1787 }
1788 String baselineVersionProp = props.remove(ConfigUtils.BASELINE_VERSION);
1789 if (baselineVersionProp != null) {
1790 setBaselineVersion(MigrationVersion.fromVersion(baselineVersionProp));
1791 }
1792 String baselineDescriptionProp = props.remove(ConfigUtils.BASELINE_DESCRIPTION);
1793 if (baselineDescriptionProp != null) {
1794 setBaselineDescription(baselineDescriptionProp);
1795 }
1796 Boolean baselineOnMigrateProp = removeBoolean(props, ConfigUtils.BASELINE_ON_MIGRATE);
1797 if (baselineOnMigrateProp != null) {
1798 setBaselineOnMigrate(baselineOnMigrateProp);
1799 }
1800 Boolean ignoreMissingMigrationsProp = removeBoolean(props, ConfigUtils.IGNORE_MISSING_MIGRATIONS);
1801 if (ignoreMissingMigrationsProp != null) {
1802 setIgnoreMissingMigrations(ignoreMissingMigrationsProp);
1803 }
1804 Boolean ignoreIgnoredMigrationsProp = removeBoolean(props, ConfigUtils.IGNORE_IGNORED_MIGRATIONS);
1805 if (ignoreIgnoredMigrationsProp != null) {
1806 setIgnoreIgnoredMigrations(ignoreIgnoredMigrationsProp);
1807 }
1808 Boolean ignorePendingMigrationsProp = removeBoolean(props, ConfigUtils.IGNORE_PENDING_MIGRATIONS);
1809 if (ignorePendingMigrationsProp != null) {
1810 setIgnorePendingMigrations(ignorePendingMigrationsProp);
1811 }
1812 Boolean ignoreFutureMigrationsProp = removeBoolean(props, ConfigUtils.IGNORE_FUTURE_MIGRATIONS);
1813 if (ignoreFutureMigrationsProp != null) {
1814 setIgnoreFutureMigrations(ignoreFutureMigrationsProp);
1815 }
1816 Boolean validateMigrationNamingProp = removeBoolean(props, ConfigUtils.VALIDATE_MIGRATION_NAMING);
1817 if (validateMigrationNamingProp != null) {
1818 setValidateMigrationNaming(validateMigrationNamingProp);
1819 }
1820 String targetProp = props.remove(ConfigUtils.TARGET);
1821 if (targetProp != null) {
1822 setTarget(MigrationVersion.fromVersion(targetProp));
1823 }
1824 Boolean outOfOrderProp = removeBoolean(props, ConfigUtils.OUT_OF_ORDER);
1825 if (outOfOrderProp != null) {
1826 setOutOfOrder(outOfOrderProp);
1827 }
1828 Boolean outputQueryResultsProp = removeBoolean(props, ConfigUtils.OUTPUT_QUERY_RESULTS);
1829 if (outputQueryResultsProp != null) {
1830 setOutputQueryResults(outputQueryResultsProp);
1831 }
1832 String resolversProp = props.remove(ConfigUtils.RESOLVERS);
1833 if (StringUtils.hasLength(resolversProp)) {
1834 setResolversAsClassNames(StringUtils.tokenizeToStringArray(resolversProp, ","));
1835 }
1836 Boolean skipDefaultResolversProp = removeBoolean(props, ConfigUtils.SKIP_DEFAULT_RESOLVERS);
1837 if (skipDefaultResolversProp != null) {
1838 setSkipDefaultResolvers(skipDefaultResolversProp);
1839 }
1840 String callbacksProp = props.remove(ConfigUtils.CALLBACKS);
1841 if (StringUtils.hasLength(callbacksProp)) {
1842 setCallbacksAsClassNames(StringUtils.tokenizeToStringArray(callbacksProp, ","));
1843 }
1844 Boolean skipDefaultCallbacksProp = removeBoolean(props, ConfigUtils.SKIP_DEFAULT_CALLBACKS);
1845 if (skipDefaultCallbacksProp != null) {
1846 setSkipDefaultCallbacks(skipDefaultCallbacksProp);
1847 }
1848
1849 Map<String, String> placeholdersFromProps = new HashMap<>(getPlaceholders());
1850 Iterator<Map.Entry<String, String>> iterator = props.entrySet().iterator();
1851 while (iterator.hasNext()) {
1852 Map.Entry<String, String> entry = iterator.next();
1853 String propertyName = entry.getKey();
1854
1855 if (propertyName.startsWith(ConfigUtils.PLACEHOLDERS_PROPERTY_PREFIX)
1856 && propertyName.length() > ConfigUtils.PLACEHOLDERS_PROPERTY_PREFIX.length()) {
1857 String placeholderName = propertyName.substring(ConfigUtils.PLACEHOLDERS_PROPERTY_PREFIX.length());
1858 String placeholderValue = entry.getValue();
1859 placeholdersFromProps.put(placeholderName, placeholderValue);
1860 iterator.remove();
1861 }
1862 }
1863 setPlaceholders(placeholdersFromProps);
1864
1865 Boolean mixedProp = removeBoolean(props, ConfigUtils.MIXED);
1866 if (mixedProp != null) {
1867 setMixed(mixedProp);
1868 }
1869
1870 Boolean groupProp = removeBoolean(props, ConfigUtils.GROUP);
1871 if (groupProp != null) {
1872 setGroup(groupProp);
1873 }
1874
1875 String installedByProp = props.remove(ConfigUtils.INSTALLED_BY);
1876 if (installedByProp != null) {
1877 setInstalledBy(installedByProp);
1878 }
1879
1880 String dryRunOutputProp = props.remove(ConfigUtils.DRYRUN_OUTPUT);
1881 if (dryRunOutputProp != null) {
1882 setDryRunOutputAsFileName(dryRunOutputProp);
1883 }
1884
1885 String errorOverridesProp = props.remove(ConfigUtils.ERROR_OVERRIDES);
1886 if (errorOverridesProp != null) {
1887 setErrorOverrides(StringUtils.tokenizeToStringArray(errorOverridesProp, ","));
1888 }
1889
1890 Boolean streamProp = removeBoolean(props, ConfigUtils.STREAM);
1891 if (streamProp != null) {
1892 setStream(streamProp);
1893 }
1894
1895 Boolean batchProp = removeBoolean(props, ConfigUtils.BATCH);
1896 if (batchProp != null) {
1897 setBatch(batchProp);
1898 }
1899
1900 Boolean oracleSqlplusProp = removeBoolean(props, ConfigUtils.ORACLE_SQLPLUS);
1901 if (oracleSqlplusProp != null) {
1902 setOracleSqlplus(oracleSqlplusProp);
1903 }
1904
1905 Boolean oracleSqlplusWarnProp = removeBoolean(props, ConfigUtils.ORACLE_SQLPLUS_WARN);
1906 if (oracleSqlplusWarnProp != null) {
1907 setOracleSqlplusWarn(oracleSqlplusWarnProp);
1908 }
1909
1910 String licenseKeyProp = props.remove(ConfigUtils.LICENSE_KEY);
1911 if (licenseKeyProp != null) {
1912 setLicenseKey(licenseKeyProp);
1913 }
1914
1915 ConfigUtils.checkConfigurationForUnrecognisedProperties(props, "flyway.");
1916 }
1917
1918 /**
1919 * Configures Flyway using FLYWAY_* environment variables.
1920 */
1921 public void configureUsingEnvVars() {
1922 configure(ConfigUtils.environmentVariablesToPropertyMap());
1923 }
1924 }