Skip to content

feat: Add sqlite3 API extensions for single-file architecture#27

Open
russellromney wants to merge 5 commits intoasg017:mainfrom
russellromney:feat-sqlite-extensions
Open

feat: Add sqlite3 API extensions for single-file architecture#27
russellromney wants to merge 5 commits intoasg017:mainfrom
russellromney:feat-sqlite-extensions

Conversation

@russellromney
Copy link

Summary

Adds four essential sqlite3 API functions to support single-file architecture in sqlite extensions:

  • sqlite3ext_bind_blob: Bind binary data to SQL statement parameters
  • sqlite3ext_bind_null: Bind NULL values to SQL statement parameters
  • sqlite3ext_open_v2: Open database with specific flags (URI mode, shared cache, etc.)
  • sqlite3ext_db_filename: Get the filename of an attached database

These functions follow the same pattern as existing sqlite3ext_* wrappers, providing both static and dynamic loadable versions.

Motivation

These extensions enable sqlite-tantivy's single-file architecture, where Tantivy full-text search segments are stored as BLOBs in the main SQLite database instead of separate files.

Use Cases

  1. bind_blob / bind_null: Storing Tantivy segment files as BLOBs

    sqlite3ext_bind_blob(stmt, 1, data.as_ptr(), data.len(), SQLITE_TRANSIENT);
  2. open_v2: Opening segment database with URI mode and shared cache

    sqlite3ext_open_v2(filename, &mut db, SQLITE_OPEN_URI | SQLITE_OPEN_SHAREDCACHE, ptr::null());
  3. db_filename: Getting main database path to derive segment storage location

    let filename = sqlite3ext_db_filename(db, ptr::null());

Testing

Added comprehensive test suite in tests/test_extensions.rs:

  • ✅ Function existence verification
  • ✅ Type safety checks
  • ✅ Signature correctness
  • ✅ Documentation of usage patterns

Runtime functionality validated through sqlite-tantivy's integration tests, which successfully use these functions to:

  • Store 100+ documents with binary segment data
  • Enable true single-file databases (just cp database.db to backup)
  • Support Litestream replication

Impact

This PR enables single-file SQLite extensions that need to:

  • Store binary data efficiently (bind_blob)
  • Handle NULL values in parameters (bind_null)
  • Open databases with specific modes (open_v2)
  • Determine database file paths (db_filename)

All functions follow existing patterns and work in both static and dynamically-loaded modes.


Related: This PR complements #26 (INSERT fix) which resolved another issue discovered while building sqlite-tantivy.

russellromney and others added 5 commits January 18, 2026 16:34
The existing code checked argv[1] == NULL to detect INSERT operations,
but according to SQLite documentation, argv[0] == NULL indicates INSERT.

From SQLite xUpdate docs:
- DELETE: argc=1, argv[0] is the rowid to delete
- INSERT: argc>1, argv[0]=NULL, argv[1] is rowid (NULL for auto-generate)
- UPDATE: argc>1, argv[0]≠NULL, argv[0]=argv[1] (same rowid)

The bug caused INSERT with explicit rowid to fail (hit todo!()) because:
1. Code checked argv[1] for INSERT detection (should be argv[0])
2. With explicit rowid, argv[1] is the rowid value, not NULL
3. Falls through to unimplemented UPDATE-with-rowid-change branch

This fix:
- Checks argv[0] for NULL to detect INSERT (matches docs)
- Compares argv[0]/argv[1] values (not pointers) for UPDATE detection
- Removes todo!() by treating rowid-change as regular UPDATE

Fixes explicit rowid INSERT: INSERT INTO vtab(rowid, col) VALUES (1, 'x')
These functions are needed for sqlite-tantivy's segment database storage:
- bind_blob/bind_null: For proper parameter binding in SQL execution
- open_v2: For opening separate segment database with URI mode
- db_filename: For getting the main database path to derive segment db path

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Tests for bind_blob, bind_null, open_v2, and db_filename functions.

These tests verify:
- Function existence and correct signatures
- Type safety through compilation checks
- Documentation of usage in sqlite-tantivy

The functions enable sqlite-tantivy's single-file architecture by providing:
- bind_blob: Binary data binding for Tantivy segments
- bind_null: NULL value binding in SQL parameters
- open_v2: Database opening with flags (URI, shared cache)
- db_filename: Database path retrieval for segment storage

Runtime functionality is validated through sqlite-tantivy's integration tests.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
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.

1 participant