From a1661a94e21efaf9072d06690f63df5eda297cac Mon Sep 17 00:00:00 2001 From: Magnus Persson <1431685+magnusp@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:40:54 +0100 Subject: [PATCH 1/3] docs: document the Flyway bootstrap for jdbc:libsql URLs Flyway resolves its plugin and driver from the URL before connecting. Document the DataSource path, the explicit-driver jdbc:sqlite: alias for URL configuration, and why jdbc:libsql: cannot use URL configuration. Record that auto-commit session state survives on one connection and that clean() is supported. Closes #263. --- README.md | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/README.md b/README.md index 01c42fd..e2e0a97 100644 --- a/README.md +++ b/README.md @@ -186,6 +186,73 @@ Use the `jdbc:sqlite:` prefix so Liquibase's SQLite implementation claims the UR `jdbc:libsql:` also reaches the driver, but Liquibase cannot resolve a driver from it and still needs the explicit driver class. +### Flyway + +Flyway selects its database plugin from the URL before it opens a connection. Its +SQLite plugin claims `jdbc:sqlite:`, `jdbc:sqldroid:`, and the p6spy prefixes, so a +`jdbc:libsql:` URL is rejected with: + +```text +No Flyway database plugin found to handle jdbc:libsql:******** +``` + +The `jdbc:sqlite:` alias is claimed, but its plugin resolves the driver to +`org.sqlite.JDBC`. Programmatic `Flyway.configure().dataSource(url, ...)` builds a +`DriverDataSource` eagerly with a null driver class, so a later `driver(...)` call is +ignored. + +Use one of these configurations: + +**DataSource with either URL form (recommended)** + +`jdbc:libsql:` works when Flyway receives a `DataSource`, because the plugin lookup +has already happened by the time the connection is opened: + +```java +Flyway flyway = Flyway.configure() + .dataSource(dataSource) // any pool or DriverManager-backed DataSource + .locations("classpath:db/migration") + .load(); +flyway.migrate(); +``` + +Spring Boot configuration, using the application `DataSource` that Flyway receives +automatically: + +```properties +spring.datasource.url=jdbc:libsql:http://localhost:8080 +spring.datasource.driver-class-name=io.github.magnusp.libsql.jdbc.LibsqlDriver +``` + +**URL configuration with an explicit driver** + +URL-based configuration must use the `jdbc:sqlite:` alias and name the driver +explicitly. This mirrors the Flyway Maven plugin and `flyway.properties` path: + +```java +ClassicConfiguration configuration = new ClassicConfiguration(); +configuration.setUrl("jdbc:sqlite:http://localhost:8080"); +configuration.setDriver("io.github.magnusp.libsql.jdbc.LibsqlDriver"); +Flyway flyway = new Flyway(configuration); +``` + +```properties +# flyway.properties +url=jdbc:sqlite:http://localhost:8080 +driver=io.github.magnusp.libsql.jdbc.LibsqlDriver +``` + +`jdbc:libsql:` cannot be used with URL-based configuration at all, even with an +explicit driver, because the plugin lookup fails first. + +Auto-commit statements on one JDBC connection share a Hrana stream, so `initSql` and +`afterConnect` statements that set session state such as `PRAGMA foreign_keys` apply +to the migrations that follow on that connection. sqld expires an idle stream after +about ten seconds and the state resets with it; for deterministic state, set it in +the pool's connection initialization instead. Flyway's `clean()` is supported +through multi-statement script splitting (see +[#258](https://github.com/magnusp/libsql-java/issues/258)). + ## Contributing We welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for contribution guidelines and development workflow, and [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) for community standards. From fde75a6f98d9c920c03816d5cfc6ccf07ffcee21 Mon Sep 17 00:00:00 2001 From: Magnus Persson <1431685+magnusp@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:58:43 +0100 Subject: [PATCH 2/3] docs(flyway): explain the foreign-key setup clean() needs Flyway wraps clean() in a transaction and SQLite ignores PRAGMA foreign_keys inside one. Document initSql as the supported way to disable foreign keys before that transaction, alongside the multi-statement splitting that runs Flyway's PRAGMA/DROP scripts on one stream. --- README.md | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index e2e0a97..a146cc3 100644 --- a/README.md +++ b/README.md @@ -247,11 +247,27 @@ explicit driver, because the plugin lookup fails first. Auto-commit statements on one JDBC connection share a Hrana stream, so `initSql` and `afterConnect` statements that set session state such as `PRAGMA foreign_keys` apply -to the migrations that follow on that connection. sqld expires an idle stream after -about ten seconds and the state resets with it; for deterministic state, set it in -the pool's connection initialization instead. Flyway's `clean()` is supported -through multi-statement script splitting (see -[#258](https://github.com/magnusp/libsql-java/issues/258)). +to the migrations that follow on that connection. + +Flyway wraps `clean()` in a transaction, and SQLite ignores `PRAGMA foreign_keys` +inside a transaction. Set the pragma when the connection is initialized, before +Flyway begins that transaction: + +```properties +# flyway.properties +initSql=PRAGMA foreign_keys = OFF +``` + +```properties +# Spring Boot +spring.flyway.init-sql=PRAGMA foreign_keys = OFF +``` + +The driver splits Flyway's `PRAGMA foreign_keys = OFF; DROP TABLE ...; PRAGMA +foreign_keys = ON` scripts and runs every statement on the connection's stream (see +[#258](https://github.com/magnusp/libsql-java/issues/258)). sqld expires an idle +stream after about ten seconds and session state resets with it, so configure state +that must outlive an idle period in the pool's connection initialization. ## Contributing From 6e1bc129f62af9a99c913dd7f20e6b9f87110bcf Mon Sep 17 00:00:00 2001 From: Magnus Persson <1431685+magnusp@users.noreply.github.com> Date: Sat, 31 Oct 2026 02:48:21 +0100 Subject: [PATCH 3/3] docs(flyway): use the spring.flyway.init-sqls property Spring Boot maps the initSql list to spring.flyway.init-sqls, not spring.flyway.init-sql. Correct the clean() setup snippet. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a146cc3..31643ad 100644 --- a/README.md +++ b/README.md @@ -260,7 +260,7 @@ initSql=PRAGMA foreign_keys = OFF ```properties # Spring Boot -spring.flyway.init-sql=PRAGMA foreign_keys = OFF +spring.flyway.init-sqls=PRAGMA foreign_keys = OFF ``` The driver splits Flyway's `PRAGMA foreign_keys = OFF; DROP TABLE ...; PRAGMA