Skip to main content

sqlite_objs_sys/
lib.rs

1//! Raw FFI bindings to the sqlite-objs C library.
2//!
3//! This crate provides low-level unsafe bindings to the sqlite-objs VFS.
4//! Most users should use the `sqlite-objs` crate instead, which provides
5//! a safe, idiomatic Rust API.
6
7#![allow(non_camel_case_types)]
8
9use libc::{c_char, c_int, c_void};
10
11/// Opaque type for Azure operations vtable (defined in azure_client.h)
12#[repr(C)]
13pub struct azure_ops_t {
14    _private: [u8; 0],
15}
16
17/// Configuration for the sqlite-objs VFS.
18///
19/// This struct maps directly to the C `sqlite_objs_config_t` type.
20#[repr(C)]
21#[derive(Debug)]
22pub struct sqlite_objs_config_t {
23    /// Azure Storage account name
24    pub account: *const c_char,
25    /// Blob container name
26    pub container: *const c_char,
27    /// SAS token (preferred), or NULL
28    pub sas_token: *const c_char,
29    /// Shared Key (fallback), or NULL
30    pub account_key: *const c_char,
31    /// Optional custom endpoint (for Azurite), or NULL for Azure
32    pub endpoint: *const c_char,
33    /// Optional: override the Azure operations vtable
34    pub ops: *const azure_ops_t,
35    /// Opaque context pointer passed to ops functions
36    pub ops_ctx: *mut c_void,
37}
38
39extern "C" {
40    /// Register the "sqlite-objs" VFS.
41    ///
42    /// Reads configuration from environment variables:
43    /// - AZURE_STORAGE_ACCOUNT
44    /// - AZURE_STORAGE_CONTAINER
45    /// - AZURE_STORAGE_SAS (checked first)
46    /// - AZURE_STORAGE_KEY (fallback)
47    ///
48    /// If `makeDefault` is non-zero, this VFS becomes the default.
49    /// Returns SQLITE_OK (0) on success, or an appropriate error code.
50    pub fn sqlite_objs_vfs_register(makeDefault: c_int) -> c_int;
51
52    /// Register the "sqlite-objs" VFS with an explicit configuration.
53    ///
54    /// The config struct is copied — the caller may free it after this call.
55    /// If `makeDefault` is non-zero, this VFS becomes the default.
56    /// Returns SQLITE_OK (0) on success, or an appropriate error code.
57    pub fn sqlite_objs_vfs_register_with_config(
58        config: *const sqlite_objs_config_t,
59        makeDefault: c_int,
60    ) -> c_int;
61
62    /// Register the "sqlite-objs" VFS with an explicit ops vtable and context.
63    ///
64    /// Convenience wrapper for test code.
65    pub fn sqlite_objs_vfs_register_with_ops(
66        ops: *mut azure_ops_t,
67        ctx: *mut c_void,
68        makeDefault: c_int,
69    ) -> c_int;
70
71    /// Register the "sqlite-objs" VFS with no global Azure client.
72    ///
73    /// All databases MUST provide Azure credentials via URI parameters:
74    /// `file:mydb.db?azure_account=acct&azure_container=cont&azure_sas=token`
75    ///
76    /// Supported URI parameters:
77    /// - azure_account (required)
78    /// - azure_container
79    /// - azure_sas
80    /// - azure_key
81    /// - azure_endpoint
82    ///
83    /// If `makeDefault` is non-zero, this VFS becomes the default.
84    /// Returns SQLITE_OK (0) on success, or an appropriate error code.
85    pub fn sqlite_objs_vfs_register_uri(makeDefault: c_int) -> c_int;
86}
87
88// SQLite constants
89pub const SQLITE_OK: c_int = 0;
90pub const SQLITE_ERROR: c_int = 1;
91pub const SQLITE_CANTOPEN: c_int = 14;
92pub const SQLITE_NOMEM: c_int = 7;
93
94// sqlite-objs custom file-control opcodes.
95// These must match the #define values in sqlite_objs.h.
96
97/// FCNTL opcode: query the number of full blob downloads (int* arg).
98/// ETag cache hits do not increment the counter.
99pub const SQLITE_OBJS_FCNTL_DOWNLOAD_COUNT: c_int = 200;
100
101/// FCNTL opcode: retrieve all VFS activity metrics as a `key=value\n` string.
102/// The returned `char*` is allocated with `sqlite3_malloc`; the caller must
103/// free it with `sqlite3_free`.
104pub const SQLITE_OBJS_FCNTL_STATS: c_int = 201;
105
106/// FCNTL opcode: reset all VFS activity metrics to zero. Pass NULL as arg.
107pub const SQLITE_OBJS_FCNTL_STATS_RESET: c_int = 202;
108
109#[cfg(test)]
110mod tests {
111    use super::*;
112
113    #[test]
114    fn test_config_size() {
115        // Ensure the struct layout matches C expectations
116        assert!(std::mem::size_of::<sqlite_objs_config_t>() > 0);
117    }
118
119    #[test]
120    fn test_register_uri() {
121        // Test that we can call the FFI function (registration will fail
122        // without Azure config, but linkage should work)
123        unsafe {
124            let result = sqlite_objs_vfs_register_uri(0);
125            // Should return SQLITE_OK since URI mode doesn't require config upfront
126            assert_eq!(result, SQLITE_OK);
127        }
128    }
129
130    #[test]
131    fn test_fcntl_constants_match_header() {
132        // Values must stay in sync with sqlite_objs.h #defines
133        assert_eq!(SQLITE_OBJS_FCNTL_DOWNLOAD_COUNT, 200);
134        assert_eq!(SQLITE_OBJS_FCNTL_STATS, 201);
135        assert_eq!(SQLITE_OBJS_FCNTL_STATS_RESET, 202);
136    }
137}