question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Java-based flyway migrations scripts are applied to all schemas

See original GitHub issue

Describe the bug

In this blog post the flyway team describes the patterns that you can use for schema-based multi-tenancy. We tried to use the pattern with a single database, multiple schema with multiple histories. The migration table for each schema is stored in the schema itself. According to Quarkus guides this case is supported (in the quarkus-flyway guide)

For example, we have the following two schemas:

  1. “base” schema with its history defined from:
  • *.sql migration scripts in resources locations “database/base” (full project path “src/main/resources/database/base”)
  • Java migration scripts in source package “database/base” (full project path “src/main/java/database/base”)
  1. “mycompany” schema with its history defined from:
  • *.sql migration scripts in resources locations “database/mycompany” (full project path “src/main/resources/database/mycompany”)
  • Java migration scripts in source package “database/mycompany” (full project path “src/main/java/database/mycompany”)

So let’s say that we have the following scripts in our project:

  1. For the “base” history:
  • database/base/V1__FirstBaseMigration.sql (located in resources of the project)
  • database/base/V2__SecondBaseMigration.java (located in java sources of the project)
  1. For the “mycompany” history:
  • database/mycompany/V1__FirstMycompanyMigration.sql (located in resources of the project)
  • database/mycompany/V2__SecondMycompanyMigration.sql

The above setup is almost the same as the quarkus-quickstarts project “hibernate-orm-multi-tenancy-quickstart” (if you enable “database” profile) but it just includes both sql and java migrations (the quickstart contains only *.sql) and also instead of using two different databases (and their default schema) we are using a single database with two different schemas (“base” and “mycompany”) by pointing the two datasources to the same database and by setting the config options “quarkus.flyway.TENANT_ID.schemas” to the correct schema for each tenant id in application.properties:

quarkus.datasource.base.db-kind=postgresql
quarkus.datasource.base.jdbc.url=jdbc:postgresql://localhost:5432/quarkus_test
quarkus.flyway.base.schemas=base
quarkus.flyway.base.locations=classpath:database/base
quarkus.flyway.base.migrate-at-start=true

quarkus.datasource.mycompany.db-kind=postgresql
quarkus.datasource.mycompany.jdbc.url=jdbc:postgresql://localhost:5432/quarkus_test
quarkus.flyway.mycompany.schemas=mycompany
quarkus.flyway.mycompany.locations=classpath:database/mycompany
quarkus.flyway.mycompany.migrate-at-start=true

Expected behavior

I assume that the correct behavior is for the above two histories to applied correctly to their corresponding schema of the database (“base” history for “base” schema and the “mycompany” history for “mycompany” schema).

Actual behavior

If we restrict our two histories to use only .sql migration scripts then we get the expected behavior. But if we include at least one Java migration script to any of the two histories then the quarkus-flyway will try to apply this Java migration to both schema. For example in the above example case the quarkus-flyway will try to apply the “database/base/V2__SecondBaseMigration.java” migration script to both schema “base” and “mycompany”. Of-course because there is also a “V2__SecondMycompanyMigration.sql” migration script for the “mycompany” schema the quarkus-flyway will throw the following exception: Failed to start application: org.flywaydb.core.api.FlywayException: Found more than one migration with version 2 Offenders: -> ~/quarkus-quickstarts/hibernate-orm-multi-tenancy-quickstart/target/classes/ (JDBC) -> ~/quarkus-quickstarts/hibernate-orm-multi-tenancy-quickstart/target/classes/database/mycompany/V2__SecondMycompanyMigration.sql (SQL)

In the above case quarkus-flyway throws exception because there is also an sql migration with the same version for “mycompany” history but there are cases in which there is no conflict between versions and the Java migration of the “base” history could be wrongly applied to all schemas. I think that quarkus-flyway-deployment scans all classes that implement JavaMigration interface in the project and it does not filter the classes based on the package prefix for each tenant schema (it will include all JavaMigrations for each schema migration).

How to Reproduce?

Steps to reproduce:

  1. Go to quarkus-quickstarts project “hibernate-orm-multi-tenancy-quickstart” (the “database” profile)
  2. Set the two datasources to point to the same database and use different schemas by setting “quarkus.flyway.base.schemas=base” and “quarkus.flyway.mycompany.schemas=mycompany” in application.properties. Or you can also use the two databases setup with the default schema.
  3. Set the locations for flyway “quarkus.flyway.base.locations=classpath:database/base” and “quarkus.flyway.mycompany.locations=classpath:database/mycompany” in application.properties
  4. Create a Java migration script in the “database/base” java package and an sql script with the same version number in the “database/mycompany” resources.
  5. Run in dev mode

I have attached a patch file quarkus-schema-multi-tenancy.txt with the above steps for quarkus-quickstarts project “hibernate-orm-multi-tenancy-quickstart” (I removed “database” profile in the patch)

Output of uname -a or ver

Linux 5.11.0-38-generic 20.04 Ubuntu x86_64

Output of java -version

OpenJDK Runtime Environment Temurin-17+35 (build 17+35)

GraalVM version (if different from Java)

No response

Quarkus version or git rev

“2.3.1.Final” or “2.4.1.Final”

Build tool (ie. output of mvnw --version or gradlew --version)

Apache Maven 3.8.1

Additional information

No response

Issue Analytics

  • State:open
  • Created 2 years ago
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
mac-b-fergusoncommented, Jan 14, 2022

My understanding of the context is a little sketchy, but I’ll try and put together a fix and put up a PR

1reaction
geoandcommented, Jan 14, 2022

Thanks for the analysis.

As you seem to have got pretty far, mind providing a Pull Request?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Flyway by Redgate • Database Migrations Made Easy.
To keep track of which migrations have already been applied when and by whom, Flyway adds a schema history table to your schema....
Read more >
Schemas - Flyway by Redgate • Database Migrations Made ...
Comma-separated, case-sensitive list of schemas managed by Flyway. Flyway will attempt to create these schemas if they do not already exist, and will...
Read more >
Config Files - Flyway by Redgate • Database Migrations Made ...
Consequences: # - Flyway will automatically attempt to create all these schemas, unless they already exist. # - The schemas will be cleaned...
Read more >
Handling multiple schemas in the same database with Flyway
It is useful mostly in a development scenario; when you first migrate , all these schemas will be created if they didn't already...
Read more >
Tutorial: Repeatable Migrations - Flyway
Instead of being run just once, they are (re-)applied every time their ... version of schema "PUBLIC": 2 Migrating schema "PUBLIC" with repeatable...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found