sqlite3_ext

Build loadable extensions for SQLite using Rust


Keywords
database, sqlite, ffi
License
blessing

Documentation

sqlite3_ext

Crates.io docs.rs

Create SQLite loadable extensions in Rust. The design philosophy of the API is gradual enhancement: all use of SQLite features returns a Result, and an Err is returned when the host version of SQLite does not support the feature in question.

Early Version Warning

This crate is pre-1.0 and the API is allowed to change freely. In particular, if a safe API is found to be unsafe, it will be changed. Once the crate reaches version 1.0, the API will be subject to semantic versioning.

Being a pre-1.0, young crate, there may be bugs which have not yet been discovered. The crate comes with a modest test suite covering all of the features (over 100 tests currently).

Crate documentation is moderately covered, and there are example extensions in the repository that can serve as a guide. Also look at the integration test in the "test" folder at the root.

Multi-threading support is low-priority and untested. If your application-defined functions and virtual tables don't reference data outside of the database they are attached to, this will not cause issues because SQLite always does database operations in a single thread. However, the API needs to be evaluated through a multithreading lens to ensure that it is safe.

Features

Crate features

  • static - The consumer of this crate is a statically linked run-time loadable extension. SQLite will be provided by the linker. To avoid link errors, sqlite3_ext disables all APIs that are added after 3.6.8.
  • static_modern - Same as static, but sqlite3_ext does not disable any APIs. This will cause link errors if the linked version of SQLite is older than the version supported by sqlite3_ext.
  • bundled - Same as static_modern, but also statically link a bundled version of SQLite from libsqlite3-sys. Please do not activate this feature from library crates, so that the consumer of your crate can decide for themselves to enable it.
  • with_rusqlite - Adds support for registering your statically linked extension to a Rusqlite Connection object.

How to use

  • I want to create a loadable extension that can be used by any SQLite client, or from the sqlite3 shell.
    • Your crate should be crate-type = [ "cdylib" ].
    • Use sqlite3_ext_main to register your enhancements.
    • SQLite methods are provided by SQLite at run-time, and methods will return Error::VersionNotSatisfied if they are not available in the host SQLite.
  • I want to create a Rust binary that uses features not supported by rusqlite.
    • Your crate can be of any type. Enable the with_rusqlite and bundled features of this crate.
    • Use sqlite3_ext_init to create an initialization function. Call the function with the rusqlite Connection, as shown here.
    • SQLite methods will always be available, since the SQLite version is controlled by Rust.
  • I want to create a statically linked extension that can be used by a (potentially non-Rust) program.
    • Your crate should be crate-type = [ "staticlib" ]. Enable the static feature of this crate. Use sqlite3_ext_main to register your enhancements.
    • Call sqlite3_mycrate_init directly (the method name is derived from the crate name) as documented here, or use sqlite3_auto_extension.
    • The host system provides SQLite. SQLite methods not available in version 3.6.8 will always return Error::VersionNotSatisfied.
  • I want to create a statically linked extension with modern SQLite features that can be used by a (potentially non-Rust) program.
    • This is the same as above, but using the static_modern feature.
    • The version of SQLite being linked in must be the same or newer than the version supported by sqlite3_ext.
  • I want to create a Rust program that does not use rusqlite.
    • Your crate can be of any type. Enable the with_rusqlite and bundled features of this crate.
    • Use sqlite3_ext_init to create an initialization function. Use Database to open a connection to a database. Pass the Database to the init function.
    • SQLite methods will always be available, since the SQLite version is controlled by Rust.
    • Note: if you are publishing a library crate, use static_modern instead of bundled, to avoid corrupting the database of your library's consumer.

Test configurations

Tests run with modern SQLite:

  • All tests from Cargo.toml with crate feature static.
  • All tests from Cargo.toml with crate feature static_modern.

Todo:

  • Run tests against SQLite 3.6.8.

Interfaces supported

Here is a compatibility chart showing which parts of the SQLite API are currently covered by sqlite3_ext. Iconography:

  • βœ… - This API is fully exposed via an API in sqlite3_ext
  • ❕ - This API is available via unsafe ffi, but there are no plans to make an API for it in sqlite3_ext.
Interface Object Status Details
sqlite3_aggregate_context sqlite3_context βœ… Arbitrary structs supported
sqlite3_auto_extension - βœ… Extension::register_auto
sqlite3_autovacuum_pages
sqlite3_backup_finish
sqlite3_backup_init
sqlite3_backup_pagecount
sqlite3_backup_remaining
sqlite3_backup_step
sqlite3_bind_blob sqlite3_stmt βœ… ToParam
sqlite3_bind_blob64 sqlite3_stmt βœ… ToParam
sqlite3_bind_double sqlite3_stmt βœ… ToParam
sqlite3_bind_int sqlite3_stmt ❕ Unnecessary
sqlite3_bind_int64 sqlite3_stmt βœ… ToParam
sqlite3_bind_null sqlite3_stmt βœ… ToParam
sqlite3_bind_parameter_count sqlite3_stmt βœ… Statement::parameter_count
sqlite3_bind_parameter_index sqlite3_stmt βœ… Statement::parameter_position
sqlite3_bind_parameter_name sqlite3_stmt βœ… Statement::parameter_name
sqlite3_bind_pointer sqlite3_stmt βœ… ToParam
sqlite3_bind_text sqlite3_stmt βœ… ToParam
sqlite3_bind_text16 sqlite3_stmt ❕ Use UTF-8 equivalent
sqlite3_bind_text64 sqlite3_stmt βœ… ToParam
sqlite3_bind_value sqlite3_stmt βœ… ToParam
sqlite3_bind_zeroblob sqlite3_stmt
sqlite3_bind_zeroblob64 sqlite3_stmt
sqlite3_blob_bytes
sqlite3_blob_close
sqlite3_blob_open
sqlite3_blob_read
sqlite3_blob_reopen
sqlite3_blob_write
sqlite3_busy_handler
sqlite3_busy_timeout
sqlite3_cancel_auto_extension - βœ… Extension::cancel_auto
sqlite3_changes βœ… Statement::execute
sqlite3_changes64 βœ… Statement::execute
sqlite3_clear_bindings sqlite3_stmt ❕ Unnecessary
sqlite3_close βœ… Database::close
sqlite3_close_v2 ❕ Unnecessary
sqlite3_collation_needed sqlite3 βœ… Connection::set_collation_needed_func
sqlite3_collation_needed16 sqlite3 ❕ Use UTF-8 equivalent
sqlite3_column_blob sqlite3_stmt βœ… Column::get_blob
sqlite3_column_bytes sqlite3_stmt ❕ Unnecessary
sqlite3_column_bytes16 sqlite3_stmt ❕ Use UTF-8 equivalent
sqlite3_column_count sqlite3_stmt βœ… Statement::column_count
sqlite3_column_database_name sqlite3_stmt βœ… Column::database_name
sqlite3_column_database_name16 sqlite3_stmt ❕ Use UTF-8 equivalent
sqlite3_column_decltype sqlite3_stmt βœ… Column::decltype
sqlite3_column_decltype16 sqlite3_stmt ❕ Use UTF-8 equivalent
sqlite3_column_double sqlite3_stmt βœ… Column::get_f64
sqlite3_column_int sqlite3_stmt βœ… Column::get_i32
sqlite3_column_int64 sqlite3_stmt βœ… Column::get_i64
sqlite3_column_name sqlite3_stmt βœ… Column::name
sqlite3_column_name16 sqlite3_stmt ❕ Use UTF-8 equivalent
sqlite3_column_origin_name sqlite3_stmt βœ… Column::origin_name
sqlite3_column_origin_name16 sqlite3_stmt ❕ Use UTF-8 equivalent
sqlite3_column_table_name sqlite3_stmt βœ… Column::table_name
sqlite3_column_table_name16 sqlite3_stmt ❕ Use UTF-8 equivalent
sqlite3_column_text sqlite3_stmt βœ… Column::get_str
sqlite3_column_text16 sqlite3_stmt ❕ Use UTF-8 equivalent
sqlite3_column_type sqlite3_stmt βœ… Column::value_type
sqlite3_column_value sqlite3_stmt βœ… Column::as_ref
sqlite3_commit_hook sqlite3
sqlite3_compileoption_get
sqlite3_compileoption_used
sqlite3_complete
sqlite3_complete16 ❕ Use UTF-8 equivalent
sqlite3_config
sqlite3_context_db_handle sqlite3_context βœ… Context::db
sqlite3_create_collation sqlite3 βœ… Connection::create_collation
sqlite3_create_collation16 sqlite3 ❕ Use UTF-8 equivalent
sqlite3_create_collation_v2 sqlite3 βœ… Connection::create_collation
sqlite3_create_filename
sqlite3_create_function sqlite3 βœ… Connection::create_scalar_function
sqlite3_create_function16 sqlite3 ❕ Use UTF-8 equivalent
sqlite3_create_function_v2 sqlite3 βœ… Connection::create_scalar_function
sqlite3_create_module sqlite3 βœ… Connection::create_module
sqlite3_create_module_v2 sqlite3 βœ… Connection::create_module
sqlite3_create_window_function sqlite3 βœ… Connection::create_aggregate_function
sqlite3_data_count sqlite3_stmt
sqlite3_database_file_object
sqlite3_db_cacheflush
sqlite3_db_config
sqlite3_db_filename
sqlite3_db_handle sqlite3_stmt βœ… Statement::db
sqlite3_db_mutex sqlite3 βœ… Connection::lock
sqlite3_db_readonly
sqlite3_db_release_memory
sqlite3_db_status
sqlite3_declare_vtab βœ… VTab::connect
sqlite3_deserialize
sqlite3_drop_modules
sqlite3_enable_load_extension sqlite3 ❕ Available via ffi
sqlite3_enable_shared_cache
sqlite3_errcode sqlite3
sqlite3_errmsg sqlite3
sqlite3_errmsg16 sqlite3 ❕ Use UTF-8 equivalent
sqlite3_error_offset sqlite3
sqlite3_errstr - βœ… Error::fmt
sqlite3_exec sqlite3 ❕ Unnecessary
sqlite3_expanded_sql sqlite3_stmt
sqlite3_extended_errcode sqlite3
sqlite3_extended_result_codes sqlite3
sqlite3_file_control
sqlite3_filename_database
sqlite3_filename_journal
sqlite3_filename_wal
sqlite3_finalize sqlite3_stmt ❕ Unnecessary
sqlite3_free ❕ Available via ffi
sqlite3_free_filename
sqlite3_free_table ❕ Available via ffi
sqlite3_get_autocommit
sqlite3_get_auxdata sqlite3_context βœ… Context::aux_data
sqlite3_get_table ❕ Available via ffi
sqlite3_hard_heap_limit64
sqlite3_initialize ❕ Available via ffi
sqlite3_interrupt
sqlite3_keyword_check
sqlite3_keyword_count
sqlite3_keyword_name
sqlite3_last_insert_rowid
sqlite3_libversion βœ… SQLITE_VERSION.as_str
sqlite3_libversion_number βœ… SQLITE_VERSION.get
sqlite3_limit sqlite3
sqlite3_load_extension sqlite3
sqlite3_log
sqlite3_malloc ❕ Available via ffi
sqlite3_malloc64 ❕ Available via ffi
sqlite3_memory_highwater
sqlite3_memory_used
sqlite3_mprintf char ❕ Available via ffi
sqlite3_msize ❕ Available via ffi
sqlite3_mutex_alloc ❕ Available via ffi
sqlite3_mutex_enter ❕ Available via ffi
sqlite3_mutex_free ❕ Available via ffi
sqlite3_mutex_held ❕ Available via ffi
sqlite3_mutex_leave ❕ Available via ffi
sqlite3_mutex_notheld ❕ Available via ffi
sqlite3_mutex_try ❕ Available via ffi
sqlite3_next_stmt
sqlite3_normalized_sql sqlite3_stmt
sqlite3_open sqlite3
sqlite3_open16 sqlite3 ❕ Use UTF-8 equivalent
sqlite3_open_v2 sqlite3
sqlite3_overload_function sqlite3 βœ… Connection::create_overloaded_function
sqlite3_prepare sqlite3_stmt ❕ Unnecessary
sqlite3_prepare16 sqlite3_stmt ❕ Use UTF-8 equivalent
sqlite3_prepare16_v2 sqlite3_stmt ❕ Use UTF-8 equivalent
sqlite3_prepare16_v3 sqlite3_stmt ❕ Use UTF-8 equivalent
sqlite3_prepare_v2 sqlite3_stmt βœ… Connection::prepare
sqlite3_prepare_v3 sqlite3_stmt βœ… Connection::prepare
sqlite3_preupdate_blobwrite
sqlite3_preupdate_count
sqlite3_preupdate_depth
sqlite3_preupdate_hook
sqlite3_preupdate_new
sqlite3_preupdate_old
sqlite3_profile
sqlite3_progress_handler
sqlite3_randomness βœ… sqlite3_randomness
sqlite3_realloc ❕ Available via ffi
sqlite3_realloc64 ❕ Available via ffi
sqlite3_release_memory
sqlite3_reset sqlite3_stmt βœ… Statement::query
sqlite3_reset_auto_extension βœ… Extension::reset_auto
sqlite3_result_blob sqlite3_context βœ… ToContextResult
sqlite3_result_blob64 sqlite3_context βœ… ToContextResult
sqlite3_result_double sqlite3_context βœ… ToContextResult
sqlite3_result_error sqlite3_context βœ… ToContextResult
sqlite3_result_error16 sqlite3_context ❕ Use UTF-8 equivalent
sqlite3_result_error_code sqlite3_context βœ… ToContextResult
sqlite3_result_error_nomem sqlite3_context
sqlite3_result_error_toobig sqlite3_context
sqlite3_result_int sqlite3_context βœ… ToContextResult
sqlite3_result_int64 sqlite3_context βœ… ToContextResult
sqlite3_result_null sqlite3_context βœ… ToContextResult
sqlite3_result_pointer sqlite3_context βœ… PassedRef
sqlite3_result_subtype sqlite3_context βœ… UnsafePtr
sqlite3_result_text sqlite3_context βœ… ToContextResult
sqlite3_result_text16 sqlite3_context ❕ Use UTF-8 equivalent
sqlite3_result_text16be sqlite3_context ❕ Use UTF-8 equivalent
sqlite3_result_text16le sqlite3_context ❕ Use UTF-8 equivalent
sqlite3_result_text64 sqlite3_context βœ… ToContextResult
sqlite3_result_value sqlite3_context βœ… ToContextResult
sqlite3_result_zeroblob sqlite3_context
sqlite3_result_zeroblob64 sqlite3_context
sqlite3_rollback_hook sqlite3
sqlite3_serialize
sqlite3_set_authorizer
sqlite3_set_auxdata sqlite3_context βœ… Context::set_aux_data
sqlite3_set_last_insert_rowid sqlite3 ❕ Available via ffi
sqlite3_shutdown ❕ Available via ffi
sqlite3_sleep ❕ Available via ffi
sqlite3_snapshot_cmp
sqlite3_snapshot_free
sqlite3_snapshot_get
sqlite3_snapshot_open
sqlite3_snapshot_recover
sqlite3_snprintf char ❕ Available via ffi
sqlite3_soft_heap_limit64
sqlite3_sourceid βœ… SQLITE_VERSION.sourceid
sqlite3_sql sqlite3_stmt βœ… Statement::sql
sqlite3_status
sqlite3_status64
sqlite3_step sqlite3_stmt βœ… ResultSet::next
sqlite3_stmt_busy sqlite3_stmt
sqlite3_stmt_isexplain sqlite3_stmt
sqlite3_stmt_readonly sqlite3_stmt
sqlite3_stmt_scanstatus sqlite3_stmt
sqlite3_stmt_scanstatus_reset sqlite3_stmt
sqlite3_stmt_status sqlite3_stmt
sqlite3_str_append sqlite3_str ❕ Available via ffi
sqlite3_str_appendall sqlite3_str ❕ Available via ffi
sqlite3_str_appendchar sqlite3_str ❕ Available via ffi
sqlite3_str_appendf sqlite3_str ❕ Available via ffi
sqlite3_str_errcode sqlite3_str ❕ Available via ffi
sqlite3_str_finish sqlite3_str ❕ Available via ffi
sqlite3_str_length sqlite3_str ❕ Available via ffi
sqlite3_str_new sqlite3_str ❕ Available via ffi
sqlite3_str_reset sqlite3_str ❕ Available via ffi
sqlite3_str_value sqlite3_str ❕ Available via ffi
sqlite3_str_vappendf sqlite3_str ❕ Available via ffi
sqlite3_strglob char βœ… sqlite3_strglob
sqlite3_stricmp char βœ… sqlite3_stricmp
sqlite3_strlike char βœ… sqlite3_strlike
sqlite3_strnicmp char ❕ Unnecessary
sqlite3_system_errno sqlite3 ❕ Available via ffi
sqlite3_table_column_metadata
sqlite3_threadsafe ❕ Available via ffi
sqlite3_total_changes sqlite3
sqlite3_total_changes64 sqlite3
sqlite3_trace
sqlite3_trace_v2
sqlite3_txn_state
sqlite3_unlock_notify
sqlite3_update_hook
sqlite3_uri_boolean ❕ Available via ffi
sqlite3_uri_int64 ❕ Available via ffi
sqlite3_uri_key ❕ Available via ffi
sqlite3_uri_parameter ❕ Available via ffi
sqlite3_user_data sqlite3_context βœ… Use a closure for the function
sqlite3_value_blob sqlite3_value βœ… ValueRef::get_blob
sqlite3_value_bytes sqlite3_value ❕ Unnecessary
sqlite3_value_bytes16 sqlite3_value ❕ Use UTF-8 equivalent
sqlite3_value_double sqlite3_value βœ… ValueRef::get_f64
sqlite3_value_dup sqlite3_value
sqlite3_value_free sqlite3_value ❕ Unnecesary
sqlite3_value_frombind sqlite3_value βœ… ValueRef::is_from_bind
sqlite3_value_int sqlite3_value βœ… ValueRef::get_i32
sqlite3_value_int64 sqlite3_value βœ… ValueRef::get_i64
sqlite3_value_nochange sqlite3_value βœ… ValueRef::nochange
sqlite3_value_numeric_type sqlite3_value βœ… ValueRef::numeric_type
sqlite3_value_pointer sqlite3_value βœ… ValueRef::get_ref
sqlite3_value_subtype sqlite3_value βœ… UnsafePtr
sqlite3_value_text sqlite3_value βœ… ValueRef::get_str
sqlite3_value_text16 sqlite3_value ❕ Use UTF-8 equivalent
sqlite3_value_text16be sqlite3_value ❕ Use UTF-8 equivalent
sqlite3_value_text16le sqlite3_value ❕ Use UTF-8 equivalent
sqlite3_value_type sqlite3_value βœ… ValueRef::value_type
sqlite3_vfs_find
sqlite3_vfs_register
sqlite3_vfs_unregister
sqlite3_vmprintf char ❕ Unnecessary
sqlite3_vsnprintf char ❕ Unnecessary
sqlite3_vtab_collation sqlite3_index_info βœ… IndexInfoConstraint::collation
sqlite3_vtab_config sqlite3 βœ… VTabConnection
sqlite3_vtab_distinct sqlite3_index_info βœ… IndexInfo::distinct_mode
sqlite3_vtab_in sqlite3_index_info βœ… IndexInfoConstraint::set_value_list_wanted
sqlite3_vtab_in_first sqlite3_value βœ… ValueList
sqlite3_vtab_in_next sqlite3_value βœ… ValueList
sqlite3_vtab_nochange sqlite3_context βœ… ColumnContext::nochange
sqlite3_vtab_on_conflict sqlite3 βœ… ChangeInfo::conflict_mode
sqlite3_vtab_rhs_value sqlite3_index_info βœ… IndexInfoConstraint::rhs
sqlite3_wal_autocheckpoint
sqlite3_wal_checkpoint
sqlite3_wal_checkpoint_v2
sqlite3_wal_hook
sqlite3_win32_set_directory
sqlite3_win32_set_directory16 ❕ Use UTF-8 equivalent
sqlite3_win32_set_directory8