Status: Ready for Implementation Version: 2.1.0 (Aligned with Ecto Adapter API) Last Updated: 2025-12-02 Based on: Gap Analysis v3.2.0
This document outlines the implementation plan for closing the feature gap between ecto_libsql and the Turso/LibSQL Rust API, while ensuring full compliance with the Ecto Adapter specification.
Target Date: Immediate Goal: Stability, SQLite Compatibility, and Ecto Integration.
Problem: Concurrent writes fail immediately with "database is locked".
Ecto Integration: Must be supported in Ecto.Adapters.SQL.connect/1 options.
Solution: Expose sqlite3_busy_timeout.
- Rust: Add
set_busy_timeout(conn_id, ms)NIF.- Use
conn.busy_timeout(Duration::from_millis(ms)).
- Use
- Elixir: Update
EctoLibSql.Protocol.connect/1to parse:busy_timeoutoption.- Default to
5000(5 seconds) if not specified, matching standard Ecto/SQLite behaviour. - Call the NIF immediately after connection establishment.
- Default to
Problem: Configuring WAL, foreign keys, etc. is verbose.
Ecto Integration: Often done in init/1 or migration scripts.
Solution: Add EctoLibSql.Pragma module.
- Rust: Add
pragma_query(conn_id, pragma_stmt)NIF. - Elixir: Create
EctoLibSql.Pragmamodule.enable_foreign_keys(state)/disable_foreign_keys(state)/foreign_keys(state)set_journal_mode(state, mode)/journal_mode(state)set_synchronous(state, level)/synchronous(state)table_info(state, table_name)/table_list(state)user_version(state)/set_user_version(state, version)query(state, pragma_stmt)- Generic PRAGMA execution
Problem: Need ability to reset connection state and interrupt long-running operations.
Ecto Integration: DBConnection expects connections to be reset when checked back into the pool.
Solution: Implement connection-level reset and interrupt.
- Rust: Add
reset_connection(conn_id)NIF. - Rust: Add
interrupt_connection(conn_id)NIF. - Elixir: Add
reset(state)wrapper inEctoLibSql.Native. - Elixir: Add
interrupt(state)wrapper inEctoLibSql.Native.
Problem: Need efficient multi-statement execution. Ecto Integration: Useful for migrations and bulk operations. Solution: Implement native batch execution with transactional option.
- Rust: Add
execute_batch_native(conn_id, sql)NIF. - Rust: Add
execute_transactional_batch_native(conn_id, sql)NIF. - Elixir: Add
execute_batch_sql(state, sql)wrapper. - Elixir: Add
execute_transactional_batch_sql(state, sql)wrapper.
Problem: ecto_libsql re-prepares statements on every execution.
Ecto Integration: Ecto expects adapters to cache prepared statements.
Solution: Implement statement-level reset and fix statement lifecycle.
- Rust: Add
reset_statement(stmt_id)NIF. - Rust: Update
query_preparedandexecute_preparedto NOT re-prepare. - Elixir: Implement
DBConnection.Queryprotocol correctly to reuse cached statements.
Target Date: Next Release Goal: Better developer experience and Ecto Query compatibility.
Problem: Inefficient single-row fetches.
Ecto Integration: Used by Ecto.Repo.get/3 and one/2.
Solution: Implement query_row for efficiency.
- Rust: Add
query_row(conn_id, stmt_id, args)NIF. - Elixir: Optimise
EctoLibSql.Connection.execute/4to usequery_rowwhenlimit: 1is detected (if possible via adapter flags).
Problem: Missing metadata.
Ecto Integration: Useful for Ecto.Adapters.SQL.explain/4 and debugging.
Solution: Expose metadata.
- Rust: Add
statement_columns(stmt_id)NIF. - Rust: Add
statement_params_count(stmt_id)NIF.
Problem: Only positional ? parameters.
Ecto Integration: Ecto typically uses positional parameters internally, but raw SQL queries might use named params.
Solution: Support :name style parameters.
- Rust: Update query NIFs to accept map/keyword list for params.
Target Date: Future Goal: Advanced capabilities.
-
sync_until(index) -
flush_replicator() -
freeze()
-
authorizercallback -
update_hookcallback
-
load_extension(path)
- No Unwraps: Continue the v0.5.0 pattern. Return
Result<T, rustler::Error>. - Async/Await: Use
TOKIO_RUNTIME.block_onfor all async LibSQL calls. - Thread Safety: Always use
safe_lockandsafe_lock_arc. - Testing:
- Add Rust unit tests in
native/ecto_libsql/src/tests.rs. - Add Elixir integration tests in
test/verifyingEcto.Repobehavior.
- Add Rust unit tests in