Support ecto_libsql (libSQL) as an alternative adapter#212
Support ecto_libsql (libSQL) as an alternative adapter#212AlanMcCann wants to merge 1 commit intoash-project:mainfrom
Conversation
libSQL (github.com/tursodatabase/libsql) is an open-source fork of
SQLite that adds ALTER COLUMN, native vector search (DiskANN), and
embedded replicas while maintaining full backwards compatibility
with the SQLite file format and API.
Changes:
- verify_repo: accept Ecto.Adapters.LibSql alongside SQLite3
- repo: make adapter configurable via :adapter option (defaults
to Ecto.Adapters.SQLite3 for backwards compatibility)
- data_layer: add EctoLibSql.Error handlers (guarded by
Code.ensure_loaded? so ecto_libsql remains optional)
- mix.exs: add ecto_libsql as optional dependency
- tests: 6 tests covering adapter acceptance, backwards
compatibility, and constraint message parsing
Usage:
use AshSqlite.Repo,
otp_app: :my_app,
adapter: Ecto.Adapters.LibSql
All existing behavior is unchanged when using Ecto.Adapters.SQLite3.
The :adapter option defaults to Ecto.Adapters.SQLite3 when not
specified.
Tested against a production Ash application: 5877 tests, 5872
passed, 5 failures unrelated to the adapter change (DBConnection
ownership race conditions).
|
This is cool. Does libSQL also solve the semantics around parallel transactions such that they wait/go in sequence the way postgres does? |
|
Unfortunately not. libSQL inherits SQLite's single-writer model. One writer at a time, period. If two processes try to write simultaneously, one gets SQLITE_BUSY and has to retry. The busy_timeout setting (I have it at 5000ms in config) makes the second writer wait up to that duration for the lock to release. So in practice, writes serialize with a wait rather than an error. But it's not the same as PostgreSQL's MVCC where multiple transactions run concurrently and conflicts are resolved at commit time. I have an application with per-user SQLite databases, so in practice it won't matter much and why I'm testing out deployment with this versio Turso Database has it but is in beta and is missing ALTER TABLE which is a key reason (besides vector support) I'm testing out libSQL. |
|
So I'm wondering if it would be realistic to add some CI only integration tests here. Or even to swap out the adapter at compile time for our existing tests and run them to ensure all the tests pass. Because right now we provide this as an option but aren't actually validating in our tests that it works. |
|
Good idea.
Option 1 (swap at compile time, run existing suite) seems most practical. The test repo would check an env var and use the appropriate adapter:
# test/support/test_repo.ex
@adapter if System.get_env("ASH_SQLITE_ADAPTER") == "libsql",
do: Ecto.Adapters.LibSql,
else: Ecto.Adapters.SQLite3
use AshSqlite.Repo,
otp_app: :ash_sqlite,
adapter: @adapter
Then a second CI matrix entry with ASH_SQLITE_ADAPTER=libsql. The existing test failures are the same on both adapters (verified locally), so any new failures would be libSQL-specific regressions.
Option 2: Separate integration tests. A dedicated test file that specifically exercises libSQL features (modify migrations, constraint error handling, adapter acceptance). Lighter touch, but only covers what we explicitly test.
I'd lean toward option 1 since it validates everything without maintaining a separate test suite. One consideration: ecto_libsql uses Rust NIFs, but rustler_precompiled should handle CI without needing a Rust toolchain.
I would be happy to implement whichever you prefer or consider any other ideas you have
Alan
… On Apr 27, 2026, at 8:30 PM, Zach Daniel ***@***.***> wrote:
zachdaniel
left a comment
(ash-project/ash_sqlite#212)
<#212 (comment)>
So I'm wondering if it would be realistic to add some CI only integration tests here. Or even to swap out the adapter at compile time for our existing tests and run them to ensure all the tests pass. Because right now we provide this as an option but aren't actually validating in our tests that it works.
|
|
Yeah, I think option 1 is best 👍 |
|
I'll update the test matrix so you can pull main and try it. |
libSQL (github.com/tursodatabase/libsql) is an open-source fork of SQLite that adds ALTER COLUMN, native vector search (DiskANN), and embedded replicas while maintaining full backwards compatibility with the SQLite file format and API.
Changes:
Usage:
All existing behavior is unchanged when using Ecto.Adapters.SQLite3. The :adapter option defaults to Ecto.Adapters.SQLite3 when not specified.
Tested against a production Ash application: 5877 tests, 5872 passed, 5 failures unrelated to the adapter change (DBConnection ownership race conditions).
Contributor checklist
Leave anything that you believe does not apply unchecked.