Skip to content

Conversation

@ocean
Copy link
Owner

@ocean ocean commented Dec 25, 2025

Summary by CodeRabbit

  • New Features

    • SQLite extension loading with security safeguards
    • Statement parameter name introspection for prepared statements
    • Statement reset for efficient reuse
    • Statement column metadata retrieval
    • Remote encryption support for Turso-encrypted databases
  • Documentation

    • Documented unsupported update and authorizer hooks with recommended alternatives
    • Added an enhancements roadmap consolidating future improvements
  • Tests

    • Expanded test coverage for statement introspection, lifecycle and reset behaviour

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 25, 2025

Walkthrough

Adds SQLite extension loading and statement introspection NIFs/wrappers, introduces hooks NIFs that return :unsupported (documented alternatives), and expands tests and documentation (CHANGELOG, ENHANCEMENTS) for LibSQL/Turso features and statement metadata APIs.

Changes

Cohort / File(s) Summary
Docs & Roadmap
CHANGELOG.md, ENHANCEMENTS.md
New changelog entries and a consolidated ENHANCEMENTS.md describing features (extension loading, statement introspection, remote encryption), priorities, and implementation notes.
Elixir NIF Wrappers
lib/ecto_libsql/native.ex
Added public wrappers: enable_extensions/2, load_ext/2, add_update_hook/2, remove_update_hook/1, add_authorizer/2, and stmt_parameter_name/2 — wiring to new/updated NIFs with docs and defaults.
Rust — Connection / Extensions
native/ecto_libsql/src/connection.rs, native/ecto_libsql/src/constants.rs, native/ecto_libsql/src/lib.rs
Added NIFs enable_load_extension and load_extension (DirtyIo), added unsupported atom, and registered new hooks module in lib exports.
Rust — Hooks (Unsupported)
native/ecto_libsql/src/hooks.rs
New hooks module implementing set_update_hook, clear_update_hook, set_authorizer which unconditionally return :unsupported with documentation explaining Rustler/BEAM threading limitations and alternatives.
Rust — Statement Introspection
native/ecto_libsql/src/statement.rs
Added statement_parameter_name NIF to return parameter name by 1-based index (Option), with validation, ownership checks and documented behaviour.
Tests
test/hooks_test.exs, test/statement_features_test.exs
New hook tests asserting :unsupported; extensive statement parameter/column introspection tests, lifecycle/reset and edge-case coverage.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I hopped through code with nimble paws,
Loading extensions, reading clauses,
Hooks said "no" — threading's the key,
Parameters named, now plain to see,
Rabbit dances — tests agree! 🥕

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'feature: Add support for SQLite extensions' directly and clearly summarises the main change, which is the addition of SQLite extension loading support with enable_extensions and load_ext functionality.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch support-sqlite-extensions

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 10fd639 and 3a86263.

📒 Files selected for processing (4)
  • ENHANCEMENTS.md
  • lib/ecto_libsql/native.ex
  • native/ecto_libsql/src/hooks.rs
  • test/hooks_test.exs
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ex,exs,rs,md}

📄 CodeRabbit inference engine (CLAUDE.md)

ALWAYS use British/Australian English spelling and grammar for code, comments, and documentation, except where required for function calls, SQL keywords, error messages, or compatibility with external systems that may use US English

Files:

  • native/ecto_libsql/src/hooks.rs
  • lib/ecto_libsql/native.ex
  • ENHANCEMENTS.md
  • test/hooks_test.exs
native/**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

ALWAYS run the Rust Cargo formatter (cargo fmt) before committing changes and fix any issues

Files:

  • native/ecto_libsql/src/hooks.rs
**/*.{ex,exs}

📄 CodeRabbit inference engine (CLAUDE.md)

ALWAYS run the Elixir formatter (mix format --check-formatted) before committing changes and fix any issues

Files:

  • lib/ecto_libsql/native.ex
  • test/hooks_test.exs
lib/ecto_libsql/native.ex

📄 CodeRabbit inference engine (CLAUDE.md)

lib/ecto_libsql/native.ex: For each new Rust NIF function, add corresponding Elixir NIF stubs and safe wrapper functions in lib/ecto_libsql/native.ex, with proper state management via EctoLibSql.State
For explicitly unsupported functions, update the Elixir wrapper with comprehensive documentation explaining why the feature is unsupported, what architectural constraints prevent it, and what alternative approaches users can take

Files:

  • lib/ecto_libsql/native.ex
lib/**/*.ex

📄 CodeRabbit inference engine (CLAUDE.md)

lib/**/*.ex: When updating Elixir code, follow the pattern of case matching on NIF results: {:ok, _, result, new_state} for successful query execution or {:error, reason} for failures
In Elixir error handling, prefer with clauses for chaining multiple operations that return Result tuples, providing clear error handling with an else clause
In Ecto changesets, use the cast function to automatically attempt type conversions for fields, which will raise ChangeError if types don't match schema expectations
Use transactions with appropriate isolation behaviours when executing database operations: :deferred for mixed workloads, :immediate for write-heavy operations, :exclusive for critical operations requiring exclusive locks, :read_only for read-only queries
When working with database locks, use transactions with proper timeout configuration, ensure connections are properly closed in try-after blocks, and use immediate/exclusive transaction behaviours for write-heavy workloads to minimise lock contention
When handling vector search operations, verify LibSQL version supports vectors, use correct vector syntax with EctoLibSql.Native.vector() function, insert vectors with vector(?) SQL syntax, and query with vector distance functions like vector_distance_cos

Files:

  • lib/ecto_libsql/native.ex
**/*.ex

📄 CodeRabbit inference engine (AGENTS.md)

**/*.ex: Use prepared statements via EctoLibSql.Native.prepare/2 and EctoLibSql.Native.query_stmt/3 for repeated queries to improve performance by ~10-15x
Use batch operations with EctoLibSql.Native.batch_transactional/2 for bulk inserts/updates instead of individual statements
Implement proper error handling by pattern matching on {:ok, ...} and {:error, ...} tuples from all EctoLibSql operations
Use transactions with EctoLibSql.handle_begin/2, EctoLibSql.handle_commit/2, and EctoLibSql.handle_rollback/2 for multi-step database operations
Use cursor streaming with DBConnection.stream/3 for memory-efficient processing of large result sets
Use vector search with EctoLibSql.Native.vector/1, EctoLibSql.Native.vector_type/2, and EctoLibSql.Native.vector_distance_cos/2 for AI/ML features
Use EctoLibSql.Pragma.* functions to configure SQLite parameters such as foreign keys, journal mode, cache size, and synchronous level
Use savepoints with EctoLibSql.Native.create_savepoint/2, EctoLibSql.Native.release_savepoint_by_name/2, and EctoLibSql.Native.rollback_to_savepoint_by_name/2 for nested transactions
Use Ecto changesets for data validation before inserting or updating records
Use Ecto query composition with Ecto.Query for building complex queries incrementally
Preload associations with Repo.preload/2 to avoid N+1 query problems in Ecto applications
For remote replicas in production, use EctoLibSql.Native.sync/1, EctoLibSql.Native.get_frame_number_for_replica/1, EctoLibSql.Native.sync_until_frame/2, and EctoLibSql.Native.flush_and_get_frame/1 for replication management
Use busy timeout configuration with EctoLibSql.Native.busy_timeout/2 to handle database locking conflicts gracefully
Use statement introspection functions (EctoLibSql.Native.stmt_parameter_count/2, EctoLibSql.Native.stmt_column_count/2, EctoLibSql.Native.stmt_column_name/3) to validate prepared statement structure
Handle connection errors gracefully by ch...

Files:

  • lib/ecto_libsql/native.ex
test/**/*.exs

📄 CodeRabbit inference engine (CLAUDE.md)

test/**/*.exs: Add tests for all new features in appropriate Elixir test files (test/ecto_*_test.exs) and Rust test modules (native/ecto_libsql/src/tests/), covering happy path, error cases, edge cases, and type conversions
Add comprehensive tests for unsupported functions asserting that they always return {:error, :unsupported} and that they don't modify database state or corrupt connections

Files:

  • test/hooks_test.exs
🧠 Learnings (29)
📓 Common learnings
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to lib/ecto/adapters/libsql/connection.ex : In lib/ecto/adapters/libsql/connection.ex, implement SQL expression handlers for SQLite functions by pattern matching on function names and converting them to SQL fragments, respecting SQLite syntax and limitations
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to lib/ecto_libsql/native.ex : For explicitly unsupported functions, update the Elixir wrapper with comprehensive documentation explaining why the feature is unsupported, what architectural constraints prevent it, and what alternative approaches users can take
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-17T11:58:46.019Z
Learning: Applies to **/*.ex : Use `EctoLibSql.Pragma.*` functions to configure SQLite parameters such as foreign keys, journal mode, cache size, and synchronous level
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to test/**/*.exs : Add comprehensive tests for unsupported functions asserting that they always return {:error, :unsupported} and that they don't modify database state or corrupt connections
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to lib/ecto/adapters/libsql.ex : When implementing Ecto storage operations (create, drop, status) in lib/ecto/adapters/libsql.ex, ensure they properly handle both local SQLite and remote Turso databases via the connection mode in EctoLibSql.State
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to lib/ecto_libsql/native.ex : For each new Rust NIF function, add corresponding Elixir NIF stubs and safe wrapper functions in lib/ecto_libsql/native.ex, with proper state management via EctoLibSql.State
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to native/ecto_libsql/src/!(tests)/**/*.rs : Include comprehensive Rust documentation comments (/// comments) on all public NIF functions explaining purpose, arguments, return values (success and error cases), and usage examples
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-17T11:58:46.019Z
Learning: Applies to **/*.ex : Use statement introspection functions (`EctoLibSql.Native.stmt_parameter_count/2`, `EctoLibSql.Native.stmt_column_count/2`, `EctoLibSql.Native.stmt_column_name/3`) to validate prepared statement structure
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to lib/ecto/adapters/libsql.ex : In type loaders/dumpers in lib/ecto/adapters/libsql.ex, ensure bidirectional conversion: loaders convert SQLite values to Elixir types on retrieval, dumpers convert Elixir types to SQLite on storage
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to lib/**/*.ex : When handling vector search operations, verify LibSQL version supports vectors, use correct vector syntax with `EctoLibSql.Native.vector()` function, insert vectors with `vector(?)` SQL syntax, and query with vector distance functions like `vector_distance_cos`
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to native/ecto_libsql/src/!(tests)/**/*.rs : When adding a new NIF function in Rust, place it in the appropriate module based on functionality: connection.rs (lifecycle), query.rs (execution), transaction.rs (transactions), batch.rs (batch operations), statement.rs (prepared statements), cursor.rs (streaming), replication.rs (replica sync), metadata.rs (metadata access), or savepoint.rs (nested transactions)
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to native/ecto_libsql/src/!(tests)/**/*.rs : When adding a new NIF function in Rust, place it in the appropriate module based on functionality: connection.rs (lifecycle), query.rs (execution), transaction.rs (transactions), batch.rs (batch operations), statement.rs (prepared statements), cursor.rs (streaming), replication.rs (replica sync), metadata.rs (metadata access), or savepoint.rs (nested transactions)

Applied to files:

  • native/ecto_libsql/src/hooks.rs
  • lib/ecto_libsql/native.ex
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to native/ecto_libsql/src/!(tests)/**/*.rs : Include comprehensive Rust documentation comments (/// comments) on all public NIF functions explaining purpose, arguments, return values (success and error cases), and usage examples

Applied to files:

  • native/ecto_libsql/src/hooks.rs
  • lib/ecto_libsql/native.ex
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to native/ecto_libsql/src/!(tests)/**/*.rs : Modern Rustler (used in this project) automatically detects all NIFs annotated with `#[rustler::nif]`; the `rustler::init!` macro in `lib.rs` automatically discovers and registers these functions without manual registration

Applied to files:

  • native/ecto_libsql/src/hooks.rs
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to lib/ecto_libsql/native.ex : For each new Rust NIF function, add corresponding Elixir NIF stubs and safe wrapper functions in lib/ecto_libsql/native.ex, with proper state management via EctoLibSql.State

Applied to files:

  • native/ecto_libsql/src/hooks.rs
  • lib/ecto_libsql/native.ex
  • test/hooks_test.exs
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to native/ecto_libsql/src/!(tests)/**/*.rs : In Rust async blocks within NIFs, drop registry locks before entering the `TOKIO_RUNTIME.block_on(async { ... })` call to prevent deadlocks, then re-acquire locks if needed after the async block completes

Applied to files:

  • native/ecto_libsql/src/hooks.rs
  • test/hooks_test.exs
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to native/ecto_libsql/src/!(tests)/**/*.rs : In Rust, all non-test code must have no `.unwrap()` calls; this was a critical refactoring in v0.5.0 to eliminate 146 unwrap calls and prevent BEAM VM crashes from panics in native code

Applied to files:

  • native/ecto_libsql/src/hooks.rs
  • test/hooks_test.exs
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to lib/ecto_libsql/native.ex : For explicitly unsupported functions, update the Elixir wrapper with comprehensive documentation explaining why the feature is unsupported, what architectural constraints prevent it, and what alternative approaches users can take

Applied to files:

  • native/ecto_libsql/src/hooks.rs
  • lib/ecto_libsql/native.ex
  • test/hooks_test.exs
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to native/ecto_libsql/src/!(tests)/**/*.rs : In Rust NIF signatures, convert async/await Result<T, E> errors to String via `.map_err(|e| format!("{:?}", e))` before returning from async blocks within `block_on`

Applied to files:

  • native/ecto_libsql/src/hooks.rs
  • test/hooks_test.exs
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to native/ecto_libsql/src/!(tests)/**/*.rs : In Rust, use the `safe_lock_arc(&arc_mutex, "context_description")` helper function instead of directly calling `.lock().unwrap()` on Arc<Mutex<T>> types to safely acquire locks with proper error handling

Applied to files:

  • native/ecto_libsql/src/hooks.rs
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to native/ecto_libsql/src/!(tests)/**/*.rs : In Rust, use the `safe_lock(&REGISTRY, "context_description")` helper function instead of directly calling `.lock().unwrap()` on Mutex types to safely acquire locks with proper error handling

Applied to files:

  • native/ecto_libsql/src/hooks.rs
📚 Learning: 2025-12-17T11:58:46.019Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-17T11:58:46.019Z
Learning: Applies to **/*.ex : Use prepared statements via `EctoLibSql.Native.prepare/2` and `EctoLibSql.Native.query_stmt/3` for repeated queries to improve performance by ~10-15x

Applied to files:

  • lib/ecto_libsql/native.ex
  • ENHANCEMENTS.md
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to lib/**/*.ex : When handling vector search operations, verify LibSQL version supports vectors, use correct vector syntax with `EctoLibSql.Native.vector()` function, insert vectors with `vector(?)` SQL syntax, and query with vector distance functions like `vector_distance_cos`

Applied to files:

  • lib/ecto_libsql/native.ex
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to lib/ecto/adapters/libsql/connection.ex : In lib/ecto/adapters/libsql/connection.ex, implement SQL expression handlers for SQLite functions by pattern matching on function names and converting them to SQL fragments, respecting SQLite syntax and limitations

Applied to files:

  • lib/ecto_libsql/native.ex
📚 Learning: 2025-12-17T11:58:46.019Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-17T11:58:46.019Z
Learning: Applies to **/*.ex : Use statement introspection functions (`EctoLibSql.Native.stmt_parameter_count/2`, `EctoLibSql.Native.stmt_column_count/2`, `EctoLibSql.Native.stmt_column_name/3`) to validate prepared statement structure

Applied to files:

  • lib/ecto_libsql/native.ex
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to lib/**/*.ex : When updating Elixir code, follow the pattern of case matching on NIF results: `{:ok, _, result, new_state}` for successful query execution or `{:error, reason}` for failures

Applied to files:

  • lib/ecto_libsql/native.ex
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to lib/ecto/adapters/libsql.ex : When implementing Ecto storage operations (create, drop, status) in lib/ecto/adapters/libsql.ex, ensure they properly handle both local SQLite and remote Turso databases via the connection mode in EctoLibSql.State

Applied to files:

  • lib/ecto_libsql/native.ex
📚 Learning: 2025-12-17T11:58:46.019Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-17T11:58:46.019Z
Learning: Applies to **/*.ex : Use transactions with `EctoLibSql.handle_begin/2`, `EctoLibSql.handle_commit/2`, and `EctoLibSql.handle_rollback/2` for multi-step database operations

Applied to files:

  • lib/ecto_libsql/native.ex
  • test/hooks_test.exs
📚 Learning: 2025-12-17T11:58:46.019Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-17T11:58:46.019Z
Learning: Applies to **/*.ex : Use batch operations with `EctoLibSql.Native.batch_transactional/2` for bulk inserts/updates instead of individual statements

Applied to files:

  • lib/ecto_libsql/native.ex
📚 Learning: 2025-12-17T11:58:46.019Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-17T11:58:46.019Z
Learning: Applies to **/*.ex : Use `EctoLibSql.Pragma.*` functions to configure SQLite parameters such as foreign keys, journal mode, cache size, and synchronous level

Applied to files:

  • lib/ecto_libsql/native.ex
📚 Learning: 2025-12-17T11:58:46.019Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-17T11:58:46.019Z
Learning: Applies to **/*.ex : Use savepoints with `EctoLibSql.Native.create_savepoint/2`, `EctoLibSql.Native.release_savepoint_by_name/2`, and `EctoLibSql.Native.rollback_to_savepoint_by_name/2` for nested transactions

Applied to files:

  • lib/ecto_libsql/native.ex
  • test/hooks_test.exs
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to native/ecto_libsql/src/savepoint.rs : In savepoint operations in native/ecto_libsql/src/savepoint.rs, validate that the transaction belongs to the connection by comparing entry.conn_id with the provided conn_id parameter

Applied to files:

  • lib/ecto_libsql/native.ex
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to test/**/*.exs : Add comprehensive tests for unsupported functions asserting that they always return {:error, :unsupported} and that they don't modify database state or corrupt connections

Applied to files:

  • test/hooks_test.exs
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to test/**/*.exs : Add tests for all new features in appropriate Elixir test files (test/ecto_*_test.exs) and Rust test modules (native/ecto_libsql/src/tests/), covering happy path, error cases, edge cases, and type conversions

Applied to files:

  • test/hooks_test.exs
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to test/**/*migration*test.exs : For SQLite migrations that require column type changes or drops (which SQLite doesn't support via ALTER), use the table recreation pattern: create new table, copy data with transformations, swap tables, and recreate indexes

Applied to files:

  • test/hooks_test.exs
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: When a function cannot be implemented due to architectural constraints, explicitly mark it as unsupported by returning an `:unsupported` atom error rather than returning vague errors or silently failing

Applied to files:

  • test/hooks_test.exs
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: When debugging failing tests, run with trace (`mix test file.exs --trace`), verify NIF compilation (`File.exists?("priv/native/ecto_libsql.so")`), check Rust output with `cargo test -- --nocapture`, and run Rust tests independently to isolate issues

Applied to files:

  • test/hooks_test.exs
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to native/ecto_libsql/src/!(tests)/**/*.rs : In Rust NIFs marked with `#[rustler::nif]`, always use the `?` operator for error propagation to automatically convert errors to NifResult and return them to Elixir callers

Applied to files:

  • test/hooks_test.exs
📚 Learning: 2025-12-17T11:58:46.019Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-17T11:58:46.019Z
Learning: Applies to **/*.ex : Implement proper error handling by pattern matching on `{:ok, ...}` and `{:error, ...}` tuples from all EctoLibSql operations

Applied to files:

  • test/hooks_test.exs
🧬 Code graph analysis (2)
lib/ecto_libsql/native.ex (3)
native/ecto_libsql/src/connection.rs (2)
  • enable_load_extension (371-402)
  • load_extension (427-450)
native/ecto_libsql/src/hooks.rs (3)
  • set_update_hook (65-70)
  • clear_update_hook (82-87)
  • set_authorizer (157-162)
native/ecto_libsql/src/statement.rs (1)
  • statement_parameter_name (349-379)
test/hooks_test.exs (1)
lib/ecto_libsql/native.ex (3)
  • add_update_hook (995-997)
  • remove_update_hook (1008-1010)
  • add_authorizer (1072-1074)
🪛 LanguageTool
ENHANCEMENTS.md

[style] ~160-~160: Consider using a different verb for a more formal wording.
Context: ...GH - Significant performance issue (NOW FIXED) Implementation: `reset_statement/2...

(FIX_RESOLVE)


[uncategorized] ~166-~166: Use a comma before ‘but’ if it connects two independent clauses (unless they are closely connected and short).
Context: ...ements - Ecto caches prepared statements but we ignore the cache - Significant perfo...

(COMMA_COMPOUND_SENTENCE)


[typographical] ~269-~269: If specifying a range, consider using an en dash instead of a hyphen.
Context: ... read performance Estimated Effort: 2-3 days Why Important: - Multi-Versio...

(HYPHEN_TO_EN)


[grammar] ~454-~454: A determiner may be missing.
Context: ...ons - Delivery optimisation: Locate nearest warehouse to customer location - **Regi...

(THE_SUPERLATIVE)


[grammar] ~455-~455: A determiner may be missing.
Context: ...location - Regional analytics: Find closest office/branch in each region - **Social...

(THE_SUPERLATIVE)


[grammar] ~457-~457: A determiner may be missing.
Context: ...tup groups - Asset tracking: Locate nearest available equipment or resources - **Em...

(THE_SUPERLATIVE)


[grammar] ~458-~458: A determiner may be missing.
Context: ...esources - Emergency services: Find nearest hospital, fire station, or police - **R...

(THE_SUPERLATIVE)


[misspelling] ~475-~475: Use “a” instead of ‘an’ if the following word doesn’t start with a vowel sound, e.g. ‘a sentence’, ‘a university’.
Context: ...Entryto hold theTransactionbehind anArc<Mutex>` - Look up and...

(EN_A_VS_AN)


[uncategorized] ~476-~476: When ‘Look-up’ is used as a noun or modifier, it needs to be hyphenated.
Context: ...behind anArc<Mutex>` - Look up and ownership-check under TXN_REGISTRY ...

(VERB_NOUN_CONFUSION)


[typographical] ~481-~481: If specifying a range, consider using an en dash instead of a hyphen.
Context: ...cy, reduced lock contention Effort: 3-4 days ### 2. Complete Phase 2-5 Refacto...

(HYPHEN_TO_EN)


[typographical] ~493-~493: If specifying a range, consider using an en dash instead of a hyphen.
Context: ...de organisation - Reduced module sizes (150-350 lines vs 2500+) - Improved maintainabil...

(HYPHEN_TO_EN)


[typographical] ~497-~497: If specifying a range, consider using an en dash instead of a hyphen.
Context: ...rer separation of concerns Effort: 10-15 days total ### 3. Add Structured Error...

(HYPHEN_TO_EN)


[typographical] ~509-~509: If specifying a range, consider using an en dash instead of a hyphen.
Context: ...asier to document and test Effort: 5-7 days ### 4. Transaction & Concurrency ...

(HYPHEN_TO_EN)


[typographical] ~549-~549: If specifying a range, consider using an en dash instead of a hyphen.
Context: ...e - Replication edge cases Effort: 5-10 days ### 2. Performance Benchmark Test...

(HYPHEN_TO_EN)


[typographical] ~558-~558: If specifying a range, consider using an en dash instead of a hyphen.
Context: ...vs immediate vs exclusive) Effort: 3-5 days ### 3. Documentation Improvements...

(HYPHEN_TO_EN)


[typographical] ~568-~568: If specifying a range, consider using an en dash instead of a hyphen.
Context: ...eate troubleshooting guide Effort: 5-7 days ### 4. Test Infrastructure Enhanc...

(HYPHEN_TO_EN)


[typographical] ~705-~705: If specifying a range, consider using an en dash instead of a hyphen.
Context: ...iling identifies bottleneck Effort: 3-5 days #### 5b. Lookup Table Pre-computa...

(HYPHEN_TO_EN)


[typographical] ~723-~723: If specifying a range, consider using an en dash instead of a hyphen.
Context: ...it Effort: 1 day Total Effort: 5-7 days (investigate via profiling first) ...

(HYPHEN_TO_EN)


[typographical] ~736-~736: If specifying a range, consider using an en dash instead of a hyphen.
Context: ...ackoff) - Mutex contention Effort: 3-5 days ### 2. Telemetry Events **Add Tel...

(HYPHEN_TO_EN)


[uncategorized] ~882-~882: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...visibility, NIF pattern review) 5. P1 High Priority Features (query_row, named parameters...

(EN_COMPOUND_ADJECTIVE_INTERNAL)


[uncategorized] ~884-~884: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...benchmarks, coverage reporting) 7. P2 Medium Priority Features 8. **Ecto Integration Improv...

(EN_COMPOUND_ADJECTIVE_INTERNAL)


[uncategorized] ~886-~886: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...Ecto Integration Improvements** 9. P3 Low Priority Features This prioritisation ensures...

(EN_COMPOUND_ADJECTIVE_INTERNAL)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Elixir 1.18.0 / OTP 27.0 / macos-latest
  • GitHub Check: Elixir 1.18.0 / OTP 27.0 / ubuntu-latest
  • GitHub Check: Analyze (rust)
🔇 Additional comments (14)
ENHANCEMENTS.md (1)

1-888: Comprehensive and well-structured enhancement documentation.

The document effectively consolidates all planned improvements with clear prioritisation, effort estimates, and implementation status tracking. British English spelling is correctly used throughout (optimisations, behaviour, organisation).

A few minor observations from static analysis:

  • Lines 454-458: Missing determiners ("the nearest warehouse", "the closest office") would be more grammatically correct
  • Line 475: "an Arc<Mutex<Transaction>>" is actually correct since "Arc" is pronounced starting with a vowel sound

These are very minor and don't affect comprehension.

native/ecto_libsql/src/hooks.rs (3)

1-70: Excellent documentation and implementation for unsupported hook.

The set_update_hook function follows project conventions well:

  • Comprehensive /// documentation explaining the threading limitation
  • Clear alternatives provided (application-level events, triggers, polling CDC)
  • Parameters correctly prefixed with _ to indicate intentional non-use
  • Returns {:error, :unsupported} tuple as expected

As per coding guidelines, unsupported functions should have comprehensive documentation explaining why the feature is unsupported and what alternatives exist - this is well done.


72-87: LGTM - Consistent implementation.

The clear_update_hook function follows the same pattern as set_update_hook, correctly returning {:error, :unsupported}.


89-162: Well-documented authorizer hook with clear alternatives.

The set_authorizer function documentation thoroughly explains:

  • Why synchronous Rust→Elixir→Rust calls are unsafe
  • The deadlock risks with Erlang scheduler threads
  • Practical alternatives (application-level auth, views, query rewriting)

This aligns with the coding guidelines for explicitly unsupported functions.

test/hooks_test.exs (4)

1-12: Well-structured test setup.

The test module correctly:

  • Uses async: true for parallel test execution
  • Sets up an in-memory database connection
  • Properly cleans up with on_exit callback

14-46: Comprehensive tests for add_update_hook/2.

The tests correctly verify:

  1. Returns {:error, :unsupported} (line 16)
  2. Works with custom PID parameter (line 21)
  3. Database operations remain unaffected (lines 24-45)

This follows the coding guidelines for testing unsupported functions. The assertions now correctly use {:error, :unsupported} pattern matching.


48-57: Good coverage for remove_update_hook/1.

Tests verify:

  • Returns {:error, :unsupported}
  • Can be called multiple times safely (idempotent behaviour)

59-91: Thorough tests for add_authorizer/2.

Tests mirror the add_update_hook/2 pattern correctly:

  • Verifies {:error, :unsupported} return
  • Tests with custom PID
  • Confirms database operations are unaffected
lib/ecto_libsql/native.ex (6)

133-147: NIF stubs correctly added for new functions.

The NIF stubs follow the established pattern:

  • enable_load_extension/2 - extension control
  • load_extension/3 - extension loading
  • set_update_hook/2, clear_update_hook/1, set_authorizer/2 - hooks (unsupported)

All correctly return :erlang.nif_error(:nif_not_loaded) as fallback.


166-168: NIF stub for statement parameter name introspection.

Correctly added following the existing pattern for statement introspection functions.


856-944: Excellent documentation and implementation for extension loading.

The enable_extensions/2 and load_ext/3 functions:

  • Have comprehensive documentation with examples
  • Include critical security warnings (⚠️) about loading untrusted extensions
  • Document the proper workflow (enable → load → disable)
  • List common extensions (FTS5, JSON1, R-Tree, PCRE)
  • Note platform-specific file extensions

This follows the coding guidelines for proper documentation of new features.


946-1010: Comprehensive documentation for unsupported add_update_hook/2.

Per the coding guidelines for explicitly unsupported functions, this implementation:

  • Clearly marks the function as NOT SUPPORTED
  • Explains why (Rustler threading model limitations)
  • Provides 4 practical alternatives (Phoenix.PubSub, triggers, polling CDC, Phoenix.Tracker)
  • Documents the return value correctly as {:error, :unsupported}

The implementation at lines 995-997 correctly passes the pid parameter to the NIF (the past review comment about parameter mismatch has been addressed).


1012-1074: Well-documented unsupported authorizer hook.

The add_authorizer/2 function documentation:

  • Explains the synchronous bidirectional communication limitation
  • Documents deadlock risks
  • Provides 4 alternatives (application-level auth, database views, query rewriting, connection-level restrictions)

The implementation correctly uses the pid parameter.


1234-1279: Complete implementation for statement parameter name introspection.

The stmt_parameter_name/3 function:

  • Documents the 1-based indexing (following SQLite convention)
  • Explains all three named parameter styles (:name, @name, $name)
  • Correctly handles the NIF return value pattern (binary, nil, or error tuple)
  • Includes guard clause for idx >= 1

This aligns well with the learnings about using statement introspection functions.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
ENHANCEMENTS.md (2)

380-381: Inconsistent spelling: use British English throughout.

The document mixes "authorization" (US) and "authorisation" (British). Per coding guidelines, use British/Australian English spelling consistently.

🔎 Suggested fix
-For **Row-Level Security / Authorization**:
-- Application-level authorization checks before queries
+For **Row-Level Security / Authorisation**:
+- Application-level authorisation checks before queries

448-458: Inconsistent spelling: "Optimization" should be "Optimisation".

Per coding guidelines, use British/Australian English. Change "Optimization" to "Optimisation" for consistency with the rest of the document.

🔎 Suggested fix
-3. **Index Optimization**: Add spatial indexes for performance on large datasets
+3. **Index Optimisation**: Add spatial indexes for performance on large datasets

Also update line 454:

-- **Delivery optimization**: Locate nearest warehouse to customer location
+- **Delivery optimisation**: Locate the nearest warehouse to customer location
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 81b1c19 and 10fd639.

📒 Files selected for processing (10)
  • CHANGELOG.md
  • ENHANCEMENTS.md
  • lib/ecto_libsql/native.ex
  • native/ecto_libsql/src/connection.rs
  • native/ecto_libsql/src/constants.rs
  • native/ecto_libsql/src/hooks.rs
  • native/ecto_libsql/src/lib.rs
  • native/ecto_libsql/src/statement.rs
  • test/hooks_test.exs
  • test/statement_features_test.exs
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ex,exs,rs,md}

📄 CodeRabbit inference engine (CLAUDE.md)

ALWAYS use British/Australian English spelling and grammar for code, comments, and documentation, except where required for function calls, SQL keywords, error messages, or compatibility with external systems that may use US English

Files:

  • native/ecto_libsql/src/constants.rs
  • ENHANCEMENTS.md
  • native/ecto_libsql/src/hooks.rs
  • native/ecto_libsql/src/statement.rs
  • native/ecto_libsql/src/connection.rs
  • native/ecto_libsql/src/lib.rs
  • CHANGELOG.md
  • test/statement_features_test.exs
  • lib/ecto_libsql/native.ex
  • test/hooks_test.exs
native/**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

ALWAYS run the Rust Cargo formatter (cargo fmt) before committing changes and fix any issues

Files:

  • native/ecto_libsql/src/constants.rs
  • native/ecto_libsql/src/hooks.rs
  • native/ecto_libsql/src/statement.rs
  • native/ecto_libsql/src/connection.rs
  • native/ecto_libsql/src/lib.rs
**/*.{ex,exs}

📄 CodeRabbit inference engine (CLAUDE.md)

ALWAYS run the Elixir formatter (mix format --check-formatted) before committing changes and fix any issues

Files:

  • test/statement_features_test.exs
  • lib/ecto_libsql/native.ex
  • test/hooks_test.exs
test/**/*.exs

📄 CodeRabbit inference engine (CLAUDE.md)

test/**/*.exs: Add tests for all new features in appropriate Elixir test files (test/ecto_*_test.exs) and Rust test modules (native/ecto_libsql/src/tests/), covering happy path, error cases, edge cases, and type conversions
Add comprehensive tests for unsupported functions asserting that they always return {:error, :unsupported} and that they don't modify database state or corrupt connections

Files:

  • test/statement_features_test.exs
  • test/hooks_test.exs
lib/ecto_libsql/native.ex

📄 CodeRabbit inference engine (CLAUDE.md)

lib/ecto_libsql/native.ex: For each new Rust NIF function, add corresponding Elixir NIF stubs and safe wrapper functions in lib/ecto_libsql/native.ex, with proper state management via EctoLibSql.State
For explicitly unsupported functions, update the Elixir wrapper with comprehensive documentation explaining why the feature is unsupported, what architectural constraints prevent it, and what alternative approaches users can take

Files:

  • lib/ecto_libsql/native.ex
lib/**/*.ex

📄 CodeRabbit inference engine (CLAUDE.md)

lib/**/*.ex: When updating Elixir code, follow the pattern of case matching on NIF results: {:ok, _, result, new_state} for successful query execution or {:error, reason} for failures
In Elixir error handling, prefer with clauses for chaining multiple operations that return Result tuples, providing clear error handling with an else clause
In Ecto changesets, use the cast function to automatically attempt type conversions for fields, which will raise ChangeError if types don't match schema expectations
Use transactions with appropriate isolation behaviours when executing database operations: :deferred for mixed workloads, :immediate for write-heavy operations, :exclusive for critical operations requiring exclusive locks, :read_only for read-only queries
When working with database locks, use transactions with proper timeout configuration, ensure connections are properly closed in try-after blocks, and use immediate/exclusive transaction behaviours for write-heavy workloads to minimise lock contention
When handling vector search operations, verify LibSQL version supports vectors, use correct vector syntax with EctoLibSql.Native.vector() function, insert vectors with vector(?) SQL syntax, and query with vector distance functions like vector_distance_cos

Files:

  • lib/ecto_libsql/native.ex
**/*.ex

📄 CodeRabbit inference engine (AGENTS.md)

**/*.ex: Use prepared statements via EctoLibSql.Native.prepare/2 and EctoLibSql.Native.query_stmt/3 for repeated queries to improve performance by ~10-15x
Use batch operations with EctoLibSql.Native.batch_transactional/2 for bulk inserts/updates instead of individual statements
Implement proper error handling by pattern matching on {:ok, ...} and {:error, ...} tuples from all EctoLibSql operations
Use transactions with EctoLibSql.handle_begin/2, EctoLibSql.handle_commit/2, and EctoLibSql.handle_rollback/2 for multi-step database operations
Use cursor streaming with DBConnection.stream/3 for memory-efficient processing of large result sets
Use vector search with EctoLibSql.Native.vector/1, EctoLibSql.Native.vector_type/2, and EctoLibSql.Native.vector_distance_cos/2 for AI/ML features
Use EctoLibSql.Pragma.* functions to configure SQLite parameters such as foreign keys, journal mode, cache size, and synchronous level
Use savepoints with EctoLibSql.Native.create_savepoint/2, EctoLibSql.Native.release_savepoint_by_name/2, and EctoLibSql.Native.rollback_to_savepoint_by_name/2 for nested transactions
Use Ecto changesets for data validation before inserting or updating records
Use Ecto query composition with Ecto.Query for building complex queries incrementally
Preload associations with Repo.preload/2 to avoid N+1 query problems in Ecto applications
For remote replicas in production, use EctoLibSql.Native.sync/1, EctoLibSql.Native.get_frame_number_for_replica/1, EctoLibSql.Native.sync_until_frame/2, and EctoLibSql.Native.flush_and_get_frame/1 for replication management
Use busy timeout configuration with EctoLibSql.Native.busy_timeout/2 to handle database locking conflicts gracefully
Use statement introspection functions (EctoLibSql.Native.stmt_parameter_count/2, EctoLibSql.Native.stmt_column_count/2, EctoLibSql.Native.stmt_column_name/3) to validate prepared statement structure
Handle connection errors gracefully by ch...

Files:

  • lib/ecto_libsql/native.ex
🧠 Learnings (31)
📓 Common learnings
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to lib/ecto/adapters/libsql/connection.ex : In lib/ecto/adapters/libsql/connection.ex, implement SQL expression handlers for SQLite functions by pattern matching on function names and converting them to SQL fragments, respecting SQLite syntax and limitations
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to lib/ecto_libsql/native.ex : For explicitly unsupported functions, update the Elixir wrapper with comprehensive documentation explaining why the feature is unsupported, what architectural constraints prevent it, and what alternative approaches users can take
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-17T11:58:46.019Z
Learning: Applies to **/*.ex : Use `EctoLibSql.Pragma.*` functions to configure SQLite parameters such as foreign keys, journal mode, cache size, and synchronous level
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to lib/ecto_libsql/native.ex : For each new Rust NIF function, add corresponding Elixir NIF stubs and safe wrapper functions in lib/ecto_libsql/native.ex, with proper state management via EctoLibSql.State
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to lib/ecto/adapters/libsql.ex : In type loaders/dumpers in lib/ecto/adapters/libsql.ex, ensure bidirectional conversion: loaders convert SQLite values to Elixir types on retrieval, dumpers convert Elixir types to SQLite on storage
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-17T11:58:46.019Z
Learning: Applies to **/*.ex : Use statement introspection functions (`EctoLibSql.Native.stmt_parameter_count/2`, `EctoLibSql.Native.stmt_column_count/2`, `EctoLibSql.Native.stmt_column_name/3`) to validate prepared statement structure
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-17T11:58:46.019Z
Learning: Applies to **/*.ex : Use prepared statements via `EctoLibSql.Native.prepare/2` and `EctoLibSql.Native.query_stmt/3` for repeated queries to improve performance by ~10-15x
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to native/ecto_libsql/src/!(tests)/**/*.rs : Include comprehensive Rust documentation comments (/// comments) on all public NIF functions explaining purpose, arguments, return values (success and error cases), and usage examples
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to native/ecto_libsql/src/!(tests)/**/*.rs : When adding a new NIF function in Rust, place it in the appropriate module based on functionality: connection.rs (lifecycle), query.rs (execution), transaction.rs (transactions), batch.rs (batch operations), statement.rs (prepared statements), cursor.rs (streaming), replication.rs (replica sync), metadata.rs (metadata access), or savepoint.rs (nested transactions)
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to lib/**/*.ex : When handling vector search operations, verify LibSQL version supports vectors, use correct vector syntax with `EctoLibSql.Native.vector()` function, insert vectors with `vector(?)` SQL syntax, and query with vector distance functions like `vector_distance_cos`
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to lib/ecto_libsql/native.ex : For explicitly unsupported functions, update the Elixir wrapper with comprehensive documentation explaining why the feature is unsupported, what architectural constraints prevent it, and what alternative approaches users can take

Applied to files:

  • native/ecto_libsql/src/constants.rs
  • native/ecto_libsql/src/hooks.rs
  • native/ecto_libsql/src/connection.rs
  • CHANGELOG.md
  • test/statement_features_test.exs
  • lib/ecto_libsql/native.ex
  • test/hooks_test.exs
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: When a function cannot be implemented due to architectural constraints, explicitly mark it as unsupported by returning an `:unsupported` atom error rather than returning vague errors or silently failing

Applied to files:

  • native/ecto_libsql/src/constants.rs
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to lib/ecto_libsql/native.ex : For each new Rust NIF function, add corresponding Elixir NIF stubs and safe wrapper functions in lib/ecto_libsql/native.ex, with proper state management via EctoLibSql.State

Applied to files:

  • native/ecto_libsql/src/constants.rs
  • native/ecto_libsql/src/hooks.rs
  • native/ecto_libsql/src/statement.rs
  • native/ecto_libsql/src/connection.rs
  • native/ecto_libsql/src/lib.rs
  • CHANGELOG.md
  • lib/ecto_libsql/native.ex
  • test/hooks_test.exs
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to native/ecto_libsql/src/!(tests)/**/*.rs : In Rust, all non-test code must have no `.unwrap()` calls; this was a critical refactoring in v0.5.0 to eliminate 146 unwrap calls and prevent BEAM VM crashes from panics in native code

Applied to files:

  • native/ecto_libsql/src/constants.rs
  • native/ecto_libsql/src/hooks.rs
  • native/ecto_libsql/src/lib.rs
  • CHANGELOG.md
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to native/ecto_libsql/src/!(tests)/**/*.rs : Include comprehensive Rust documentation comments (/// comments) on all public NIF functions explaining purpose, arguments, return values (success and error cases), and usage examples

Applied to files:

  • native/ecto_libsql/src/constants.rs
  • native/ecto_libsql/src/hooks.rs
  • native/ecto_libsql/src/statement.rs
  • native/ecto_libsql/src/connection.rs
  • native/ecto_libsql/src/lib.rs
  • CHANGELOG.md
  • lib/ecto_libsql/native.ex
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to test/**/*.exs : Add comprehensive tests for unsupported functions asserting that they always return {:error, :unsupported} and that they don't modify database state or corrupt connections

Applied to files:

  • native/ecto_libsql/src/constants.rs
  • test/statement_features_test.exs
  • test/hooks_test.exs
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to native/ecto_libsql/src/!(tests)/**/*.rs : In Rust NIF signatures, convert async/await Result<T, E> errors to String via `.map_err(|e| format!("{:?}", e))` before returning from async blocks within `block_on`

Applied to files:

  • native/ecto_libsql/src/constants.rs
  • native/ecto_libsql/src/hooks.rs
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to native/ecto_libsql/src/!(tests)/**/*.rs : In Rust NIFs marked with `#[rustler::nif]`, always use the `?` operator for error propagation to automatically convert errors to NifResult and return them to Elixir callers

Applied to files:

  • native/ecto_libsql/src/constants.rs
📚 Learning: 2025-12-17T11:58:46.019Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-17T11:58:46.019Z
Learning: Applies to **/*.ex : Use prepared statements via `EctoLibSql.Native.prepare/2` and `EctoLibSql.Native.query_stmt/3` for repeated queries to improve performance by ~10-15x

Applied to files:

  • ENHANCEMENTS.md
  • CHANGELOG.md
  • test/statement_features_test.exs
  • lib/ecto_libsql/native.ex
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to native/ecto_libsql/src/!(tests)/**/*.rs : When adding a new NIF function in Rust, place it in the appropriate module based on functionality: connection.rs (lifecycle), query.rs (execution), transaction.rs (transactions), batch.rs (batch operations), statement.rs (prepared statements), cursor.rs (streaming), replication.rs (replica sync), metadata.rs (metadata access), or savepoint.rs (nested transactions)

Applied to files:

  • native/ecto_libsql/src/hooks.rs
  • native/ecto_libsql/src/statement.rs
  • native/ecto_libsql/src/connection.rs
  • native/ecto_libsql/src/lib.rs
  • CHANGELOG.md
  • lib/ecto_libsql/native.ex
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to native/ecto_libsql/src/!(tests)/**/*.rs : Modern Rustler (used in this project) automatically detects all NIFs annotated with `#[rustler::nif]`; the `rustler::init!` macro in `lib.rs` automatically discovers and registers these functions without manual registration

Applied to files:

  • native/ecto_libsql/src/hooks.rs
  • native/ecto_libsql/src/connection.rs
  • native/ecto_libsql/src/lib.rs
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to native/ecto_libsql/src/!(tests)/**/*.rs : In Rust async blocks within NIFs, drop registry locks before entering the `TOKIO_RUNTIME.block_on(async { ... })` call to prevent deadlocks, then re-acquire locks if needed after the async block completes

Applied to files:

  • native/ecto_libsql/src/hooks.rs
  • native/ecto_libsql/src/connection.rs
  • test/hooks_test.exs
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to native/ecto_libsql/src/!(tests)/**/*.rs : In Rust, use the `safe_lock(&REGISTRY, "context_description")` helper function instead of directly calling `.lock().unwrap()` on Mutex types to safely acquire locks with proper error handling

Applied to files:

  • native/ecto_libsql/src/hooks.rs
  • native/ecto_libsql/src/connection.rs
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to native/ecto_libsql/src/!(tests)/**/*.rs : In Rust, use the `safe_lock_arc(&arc_mutex, "context_description")` helper function instead of directly calling `.lock().unwrap()` on Arc<Mutex<T>> types to safely acquire locks with proper error handling

Applied to files:

  • native/ecto_libsql/src/hooks.rs
  • native/ecto_libsql/src/connection.rs
📚 Learning: 2025-12-17T11:58:46.019Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-17T11:58:46.019Z
Learning: Applies to **/*.ex : Use statement introspection functions (`EctoLibSql.Native.stmt_parameter_count/2`, `EctoLibSql.Native.stmt_column_count/2`, `EctoLibSql.Native.stmt_column_name/3`) to validate prepared statement structure

Applied to files:

  • native/ecto_libsql/src/statement.rs
  • CHANGELOG.md
  • test/statement_features_test.exs
  • lib/ecto_libsql/native.ex
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to lib/ecto/adapters/libsql/connection.ex : In lib/ecto/adapters/libsql/connection.ex, implement SQL expression handlers for SQLite functions by pattern matching on function names and converting them to SQL fragments, respecting SQLite syntax and limitations

Applied to files:

  • native/ecto_libsql/src/statement.rs
  • CHANGELOG.md
  • test/statement_features_test.exs
  • lib/ecto_libsql/native.ex
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to native/ecto_libsql/src/savepoint.rs : In savepoint operations in native/ecto_libsql/src/savepoint.rs, validate that the transaction belongs to the connection by comparing entry.conn_id with the provided conn_id parameter

Applied to files:

  • native/ecto_libsql/src/statement.rs
  • native/ecto_libsql/src/connection.rs
  • lib/ecto_libsql/native.ex
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to native/ecto_libsql/src/transaction.rs : Use the TransactionEntry struct in Rust transaction operations to track which connection owns each transaction, validating ownership in savepoint and transaction operations to prevent cross-connection misuse

Applied to files:

  • native/ecto_libsql/src/connection.rs
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to lib/**/*.ex : When handling vector search operations, verify LibSQL version supports vectors, use correct vector syntax with `EctoLibSql.Native.vector()` function, insert vectors with `vector(?)` SQL syntax, and query with vector distance functions like `vector_distance_cos`

Applied to files:

  • CHANGELOG.md
  • lib/ecto_libsql/native.ex
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to lib/ecto/adapters/libsql.ex : When implementing Ecto storage operations (create, drop, status) in lib/ecto/adapters/libsql.ex, ensure they properly handle both local SQLite and remote Turso databases via the connection mode in EctoLibSql.State

Applied to files:

  • CHANGELOG.md
  • lib/ecto_libsql/native.ex
📚 Learning: 2025-12-17T11:58:46.019Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-17T11:58:46.019Z
Learning: Applies to **/*.ex : Use `EctoLibSql.Pragma.*` functions to configure SQLite parameters such as foreign keys, journal mode, cache size, and synchronous level

Applied to files:

  • CHANGELOG.md
  • lib/ecto_libsql/native.ex
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to test/**/*migration*test.exs : For SQLite migrations that require column type changes or drops (which SQLite doesn't support via ALTER), use the table recreation pattern: create new table, copy data with transformations, swap tables, and recreate indexes

Applied to files:

  • CHANGELOG.md
  • test/statement_features_test.exs
  • test/hooks_test.exs
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to lib/ecto/adapters/libsql.ex : In type loaders/dumpers in lib/ecto/adapters/libsql.ex, ensure bidirectional conversion: loaders convert SQLite values to Elixir types on retrieval, dumpers convert Elixir types to SQLite on storage

Applied to files:

  • CHANGELOG.md
  • lib/ecto_libsql/native.ex
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to test/**/*.exs : Add tests for all new features in appropriate Elixir test files (test/ecto_*_test.exs) and Rust test modules (native/ecto_libsql/src/tests/), covering happy path, error cases, edge cases, and type conversions

Applied to files:

  • test/statement_features_test.exs
  • test/hooks_test.exs
📚 Learning: 2025-12-17T11:58:46.019Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-17T11:58:46.019Z
Learning: Applies to **/*.ex : Use savepoints with `EctoLibSql.Native.create_savepoint/2`, `EctoLibSql.Native.release_savepoint_by_name/2`, and `EctoLibSql.Native.rollback_to_savepoint_by_name/2` for nested transactions

Applied to files:

  • lib/ecto_libsql/native.ex
  • test/hooks_test.exs
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: Applies to lib/**/*.ex : When updating Elixir code, follow the pattern of case matching on NIF results: `{:ok, _, result, new_state}` for successful query execution or `{:error, reason}` for failures

Applied to files:

  • lib/ecto_libsql/native.ex
📚 Learning: 2025-12-17T11:58:46.019Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-17T11:58:46.019Z
Learning: Applies to **/*.ex : Use transactions with `EctoLibSql.handle_begin/2`, `EctoLibSql.handle_commit/2`, and `EctoLibSql.handle_rollback/2` for multi-step database operations

Applied to files:

  • lib/ecto_libsql/native.ex
  • test/hooks_test.exs
📚 Learning: 2025-12-17T11:58:46.019Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-17T11:58:46.019Z
Learning: Applies to **/*.ex : Use batch operations with `EctoLibSql.Native.batch_transactional/2` for bulk inserts/updates instead of individual statements

Applied to files:

  • lib/ecto_libsql/native.ex
📚 Learning: 2025-12-17T11:58:46.019Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-17T11:58:46.019Z
Learning: Applies to **/*.ex : Implement proper error handling by pattern matching on `{:ok, ...}` and `{:error, ...}` tuples from all EctoLibSql operations

Applied to files:

  • test/hooks_test.exs
📚 Learning: 2025-12-17T11:58:26.477Z
Learnt from: CR
Repo: ocean/ecto_libsql PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T11:58:26.477Z
Learning: When debugging failing tests, run with trace (`mix test file.exs --trace`), verify NIF compilation (`File.exists?("priv/native/ecto_libsql.so")`), check Rust output with `cargo test -- --nocapture`, and run Rust tests independently to isolate issues

Applied to files:

  • test/hooks_test.exs
🧬 Code graph analysis (5)
native/ecto_libsql/src/statement.rs (2)
native/ecto_libsql/src/utils.rs (2)
  • safe_lock (16-23)
  • safe_lock_arc (28-38)
native/ecto_libsql/src/decode.rs (1)
  • verify_statement_ownership (47-54)
native/ecto_libsql/src/connection.rs (2)
native/ecto_libsql/src/utils.rs (2)
  • safe_lock (16-23)
  • safe_lock_arc (28-38)
native/ecto_libsql/src/models.rs (1)
  • LibSQLConn (14-19)
test/statement_features_test.exs (1)
lib/ecto_libsql/native.ex (2)
  • prepare (496-504)
  • close_stmt (580-582)
lib/ecto_libsql/native.ex (3)
native/ecto_libsql/src/connection.rs (2)
  • enable_load_extension (371-402)
  • load_extension (427-450)
native/ecto_libsql/src/hooks.rs (3)
  • set_update_hook (65-67)
  • clear_update_hook (79-81)
  • set_authorizer (151-153)
native/ecto_libsql/src/statement.rs (1)
  • statement_parameter_name (349-379)
test/hooks_test.exs (2)
lib/ecto_libsql.ex (2)
  • disconnect (124-127)
  • handle_execute (134-151)
lib/ecto_libsql/native.ex (3)
  • add_update_hook (995-997)
  • remove_update_hook (1008-1010)
  • add_authorizer (1072-1074)
🪛 LanguageTool
ENHANCEMENTS.md

[style] ~160-~160: Consider using a different verb for a more formal wording.
Context: ...GH - Significant performance issue (NOW FIXED) Implementation: `reset_statement/2...

(FIX_RESOLVE)


[uncategorized] ~166-~166: Use a comma before ‘but’ if it connects two independent clauses (unless they are closely connected and short).
Context: ...ements - Ecto caches prepared statements but we ignore the cache - Significant perfo...

(COMMA_COMPOUND_SENTENCE)


[typographical] ~269-~269: If specifying a range, consider using an en dash instead of a hyphen.
Context: ... read performance Estimated Effort: 2-3 days Why Important: - Multi-Versio...

(HYPHEN_TO_EN)


[uncategorized] ~380-~380: Do not mix variants of the same word (‘authorization’ and ‘authorisation’) within a single text.
Context: ...te tracking For Row-Level Security / Authorization: - Application-level authorization ch...

(EN_WORD_COHERENCY)


[uncategorized] ~381-~381: Do not mix variants of the same word (‘authorization’ and ‘authorisation’) within a single text.
Context: ... / Authorization**: - Application-level authorization checks before queries - Database views ...

(EN_WORD_COHERENCY)


[uncategorized] ~448-~448: Do not mix variants of the same word (‘optimization’ and ‘optimisation’) within a single text.
Context: ...data (elevation, time, etc.) 3. Index Optimization: Add spatial indexes for performance ...

(EN_WORD_COHERENCY)


[uncategorized] ~454-~454: Do not mix variants of the same word (‘optimization’ and ‘optimisation’) within a single text.
Context: ...ants, hotels, gas stations - Delivery optimization: Locate nearest warehouse to customer...

(EN_WORD_COHERENCY)


[grammar] ~454-~454: A determiner may be missing.
Context: ...ons - Delivery optimization: Locate nearest warehouse to customer location - **Regi...

(THE_SUPERLATIVE)


[grammar] ~455-~455: A determiner may be missing.
Context: ...location - Regional analytics: Find closest office/branch in each region - **Social...

(THE_SUPERLATIVE)


[grammar] ~457-~457: A determiner may be missing.
Context: ...tup groups - Asset tracking: Locate nearest available equipment or resources - **Em...

(THE_SUPERLATIVE)


[grammar] ~458-~458: A determiner may be missing.
Context: ...esources - Emergency services: Find nearest hospital, fire station, or police - **R...

(THE_SUPERLATIVE)


[misspelling] ~475-~475: Use “a” instead of ‘an’ if the following word doesn’t start with a vowel sound, e.g. ‘a sentence’, ‘a university’.
Context: ...Entryto hold theTransactionbehind anArc<Mutex>` - Look up and...

(EN_A_VS_AN)


[uncategorized] ~476-~476: When ‘Look-up’ is used as a noun or modifier, it needs to be hyphenated.
Context: ...behind anArc<Mutex>` - Look up and ownership-check under TXN_REGISTRY ...

(VERB_NOUN_CONFUSION)


[typographical] ~481-~481: If specifying a range, consider using an en dash instead of a hyphen.
Context: ...cy, reduced lock contention Effort: 3-4 days ### 2. Complete Phase 2-5 Refacto...

(HYPHEN_TO_EN)


[typographical] ~493-~493: If specifying a range, consider using an en dash instead of a hyphen.
Context: ...de organisation - Reduced module sizes (150-350 lines vs 2500+) - Improved maintainabil...

(HYPHEN_TO_EN)


[typographical] ~497-~497: If specifying a range, consider using an en dash instead of a hyphen.
Context: ...rer separation of concerns Effort: 10-15 days total ### 3. Add Structured Error...

(HYPHEN_TO_EN)


[typographical] ~509-~509: If specifying a range, consider using an en dash instead of a hyphen.
Context: ...asier to document and test Effort: 5-7 days ### 4. Transaction & Concurrency ...

(HYPHEN_TO_EN)


[typographical] ~549-~549: If specifying a range, consider using an en dash instead of a hyphen.
Context: ...e - Replication edge cases Effort: 5-10 days ### 2. Performance Benchmark Test...

(HYPHEN_TO_EN)


[typographical] ~558-~558: If specifying a range, consider using an en dash instead of a hyphen.
Context: ...vs immediate vs exclusive) Effort: 3-5 days ### 3. Documentation Improvements...

(HYPHEN_TO_EN)


[typographical] ~568-~568: If specifying a range, consider using an en dash instead of a hyphen.
Context: ...eate troubleshooting guide Effort: 5-7 days ### 4. Test Infrastructure Enhanc...

(HYPHEN_TO_EN)


[typographical] ~705-~705: If specifying a range, consider using an en dash instead of a hyphen.
Context: ...iling identifies bottleneck Effort: 3-5 days #### 5b. Lookup Table Pre-computa...

(HYPHEN_TO_EN)


[typographical] ~723-~723: If specifying a range, consider using an en dash instead of a hyphen.
Context: ...it Effort: 1 day Total Effort: 5-7 days (investigate via profiling first) ...

(HYPHEN_TO_EN)


[typographical] ~736-~736: If specifying a range, consider using an en dash instead of a hyphen.
Context: ...ackoff) - Mutex contention Effort: 3-5 days ### 2. Telemetry Events **Add Tel...

(HYPHEN_TO_EN)


[uncategorized] ~882-~882: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...visibility, NIF pattern review) 5. P1 High Priority Features (query_row, named parameters...

(EN_COMPOUND_ADJECTIVE_INTERNAL)


[uncategorized] ~884-~884: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...benchmarks, coverage reporting) 7. P2 Medium Priority Features 8. **Ecto Integration Improv...

(EN_COMPOUND_ADJECTIVE_INTERNAL)


[uncategorized] ~886-~886: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...Ecto Integration Improvements** 9. P3 Low Priority Features This prioritization ensures...

(EN_COMPOUND_ADJECTIVE_INTERNAL)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Elixir 1.18.0 / OTP 27.0 / macos-latest
  • GitHub Check: Elixir 1.18.0 / OTP 27.0 / ubuntu-latest
  • GitHub Check: Analyze (rust)
🔇 Additional comments (22)
native/ecto_libsql/src/connection.rs (2)

353-402: Well-structured extension loading toggle implementation.

The enable_load_extension NIF follows the established patterns in this codebase:

  • Proper lock acquisition and release before operations
  • Comprehensive documentation with security warnings
  • Descriptive error messages
  • No .unwrap() calls, using safe error propagation

404-450: Extension loading implementation looks solid with appropriate security warnings.

The load_extension NIF correctly:

  • Validates the connection exists before proceeding
  • Uses PathBuf for cross-platform path handling
  • Supports optional entry point parameter
  • Includes comprehensive security documentation with clear warnings about trusted sources

The error handling appropriately delegates to libsql::Connection::load_extension, which will provide informative error messages for missing files or other issues. No additional path validation is necessary.

CHANGELOG.md (2)

10-25: Excellent documentation of unsupported hooks with clear reasoning.

The changelog entry thoroughly explains:

  • Why hooks cannot be implemented (Rustler threading limitations)
  • The specific technical constraints (managed vs unmanaged threads, synchronous callback requirements)
  • Links to the relevant Rustler issue for further context
  • Practical alternatives for users (CDC patterns, RLS approaches)

This level of documentation helps users understand the limitation and find suitable workarounds.


29-60: Comprehensive feature documentation for extension loading and parameter introspection.

The changelog entries clearly document:

  • Security-first design with extension loading disabled by default
  • API workflow and platform support
  • Parameter indexing convention (1-based following SQLite)
  • Test coverage details
native/ecto_libsql/src/constants.rs (1)

78-79: Appropriate atom addition for signalling unsupported features.

Adding the unsupported atom follows the project's established pattern for explicit error signalling. As per learnings, returning an :unsupported atom is the correct approach for features that cannot be implemented due to architectural constraints.

native/ecto_libsql/src/lib.rs (1)

10-10: Module export follows established pattern.

The hooks module is correctly declared as public, allowing Rustler to automatically discover and register the NIFs annotated with #[rustler::nif] in that module.

native/ecto_libsql/src/statement.rs (1)

328-379: Well-implemented parameter name introspection with correct indexing semantics.

The implementation correctly:

  • Documents the 1-based indexing convention (following SQLite)
  • Returns Option<String> to distinguish named vs positional parameters
  • Follows the established lock-clone-drop-operate pattern
  • Verifies statement ownership before accessing

The use of i32 for the index parameter aligns with SQLite's C API which uses int for parameter indices. The documentation clearly explains the indexing behaviour.

ENHANCEMENTS.md (1)

1-17: Comprehensive enhancement tracking document.

This document provides excellent visibility into:

  • Feature prioritisation and status tracking
  • Estimated effort for planning purposes
  • Clear categorisation by impact and use case
  • Implementation notes and security considerations

This will be valuable for contributors and users understanding the project's roadmap.

test/statement_features_test.exs (3)

464-539: Excellent parameter name introspection test coverage.

The tests comprehensively cover:

  • All three SQLite named parameter styles (:name, $name, @name)
  • Positional parameters returning nil
  • Mixed positional and named parameters
  • 1-based indexing convention

This aligns with the coding guidelines requiring tests for happy path, edge cases, and type conversions. Based on learnings, the statement introspection functions are correctly validated.


546-686: Thorough column introspection edge case coverage.

The tests cover important edge cases:

  • SELECT * column count
  • INSERT/UPDATE/DELETE without RETURNING (0 columns)
  • Aggregate functions with aliases
  • Multi-table JOINs
  • Subqueries
  • Computed expressions

This provides good confidence that the column introspection features work correctly across various SQL constructs.


400-406: Good edge case test for zero parameters.

Testing the zero-parameter case ensures the function handles the boundary condition correctly.

test/hooks_test.exs (2)

24-45: Good test verifying database operations remain unaffected.

This test correctly validates that calling unsupported hook functions does not corrupt the connection state or affect subsequent database operations. This aligns with the coding guidelines requiring tests to verify unsupported functions "don't modify database state or corrupt connections".


53-56: Good idempotency test for remove_update_hook.

Testing that the function can be called multiple times safely ensures robust handling of the unsupported case without side effects.

native/ecto_libsql/src/hooks.rs (4)

1-8: Excellent documentation of unsupported features.

The module-level documentation clearly explains the current status and fundamental limitations. This aligns with the learnings requirement to provide comprehensive documentation for explicitly unsupported functions, including architectural constraints and alternatives.

Based on learnings, this follows the documented pattern for unsupported features.


10-67: LGTM! Comprehensive documentation with practical alternatives.

The function documentation thoroughly explains the threading limitations and provides four practical alternatives (application-level events, database triggers, polling-based CDC, and Phoenix.Tracker). The implementation correctly returns an error for the unsupported feature.

Based on learnings, this follows the pattern for explicitly unsupported functions with comprehensive documentation.


69-81: LGTM! Consistent error handling.

The function correctly returns unsupported and references the main documentation in set_update_hook for details.


83-153: LGTM! Thorough explanation of synchronous communication limitations.

The documentation clearly explains why authoriser hooks require synchronous bidirectional communication, which isn't feasible with Rustler's threading model. The four alternatives (application-level authorisation, database views, query rewriting, connection-level restrictions) provide comprehensive guidance for implementing row-level security.

Based on learnings, this follows the documented pattern for explicitly unsupported functions.

lib/ecto_libsql/native.ex (5)

133-146: LGTM! NIF stubs follow established patterns.

The NIF stub declarations are consistent with existing stubs in the file and properly marked with @doc false.

Based on learnings, these correspond to the new Rust NIF functions.

Also applies to: 166-167


856-944: LGTM! Extension loading functions are well-documented with security warnings.

The enable_extensions/2 and load_ext/3 functions properly extract connection IDs from state, include appropriate guards, and provide comprehensive documentation with security warnings and practical examples.

Based on learnings, these wrappers correctly integrate with state management.


999-1010: LGTM! Correctly extracts connection ID from state.


1012-1074: LGTM! Comprehensive documentation and correct parameter usage.

The add_authorizer/2 function correctly uses the pid parameter (unlike add_update_hook/2) and provides extensive documentation explaining the threading limitations and four practical alternatives for implementing row-level security.

Based on learnings, this wrapper provides comprehensive documentation for the unsupported feature.


1234-1279: LGTM! Correctly implements 1-based parameter indexing and handles optional names.

The function properly validates that the parameter index is 1-based (matching SQLite convention), extracts the connection ID from state, and handles the Option<String> return type from Rust (binary name, nil for positional, or error).

Based on learnings, this wrapper correctly integrates with statement introspection capabilities.

@ocean ocean merged commit 88a46cb into main Dec 26, 2025
13 checks passed
@ocean ocean deleted the support-sqlite-extensions branch December 26, 2025 06:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants