epilys

Example sqlite3 Dynamic Loadable Extension in Rust (vfs and vtab)

Repository: https://github.com/epilys/vfsstat.rs

This is an example of how to create a dynamic loadable extension for sqlite3 in Rust with its FFI capabilities by calling into the C sqlite3 API directly. As a proof of concept it implements a VFS and a VTAB.

VFS and virtual tables

A VFS is an OS interface for sqlite3; it handles IO with the system. For example, the unix vfs handles all the read, write, lock operations by translating them to appropriate libc, systemcall etc calls. Since we can chain VFSes, we can create a tree where the leafs are the default VFS (unix etc) and the intermediate nodes process all the information before passing them on to the next in the chain. The sqlite3 source distribution contains the vfsstat extension which implements a VFS that keeps track of all read/write etc operations, and puts them in a virtual SQL table using the vtab interface of sqlite3. Just like the original, vfsstat.rs keeps IO statistics.

The code was a port of the official ext/misc/vfsstat.c sqlite3 extension.

Build

cargo build --release

Output will be located at target/release/libvfsstat_rs.so

Use

Note: Query the virtual table by issuing SELECT * FROM vtabstat.

Assuming libvfsstat_rs.so is in current directory,

$ sqlite3
sqlite> .load ./libvfsstat_rs
sqlite> .open ../../test.db
sqlite> .schema
CREATE TABLE person (
                  id              INTEGER PRIMARY KEY,
                  name            TEXT NOT NULL UNIQUE,
                  data            BLOB
                  );
sqlite> select * from person;
id  name                              data
--  --------------------------------  -------------
1   Steven                            NULL
2   05504B041661AAD1320A8537EB8234D2  zÔ];[^;H
3   4967EEDBF69420D82C6B1BCFB31397DD  ?BiΘI
4   19D0F5974A48AA561B7097CDA39E4047
                                      l!Xk- 5
5   1F1FFD477777F5AA5CBFF916A4AF9593  + 텸vy\Y
6   0925676226D46FB4EC6DAEB11D130350  <</jޏ
7   5D6F4F219D2E3FAF7D61CA5237F106F8  (nlZ
8   FFD140BD25C1CA899446F2C9C2631A51  ,9^<      p
9   F9F66F44D64FC54FDFAEBD3750FD3513  [C@E
sqlite> select * from vtabstat;
file            stat         count
--------------  -----------  -----
main            bytesIn      12388
main            bytesOut     0
main            read         4
main            write        0
main            sync         0
main            open         1
main            lock         1
main            access       0
main            delete       0
main            fullPath     0
main            random       0
main            sleep        0
main            currentTime  0
journal         bytesIn      0
journal         bytesOut     0
journal         read         0
journal         write        0
journal         sync         0
journal         open         0
journal         lock         0
journal         access       0
journal         delete       0
journal         fullPath     0
journal         random       0
journal         sleep        0
journal         currentTime  0
wal             bytesIn      0
wal             bytesOut     0
wal             read         0
wal             write        0
wal             sync         0
wal             open         1
wal             lock         0
wal             access       0
wal             delete       0
wal             fullPath     0
wal             random       0
wal             sleep        0
wal             currentTime  0
master-journal  bytesIn      0
master-journal  bytesOut     0
master-journal  read         0
master-journal  write        0
master-journal  sync         0
master-journal  open         0
master-journal  lock         0
master-journal  access       0
master-journal  delete       0
master-journal  fullPath     0
master-journal  random       0
master-journal  sleep        0
master-journal  currentTime  0
sub-journal     bytesIn      0
sub-journal     bytesOut     0
sub-journal     read         0
sub-journal     write        0
sub-journal     sync         0
sub-journal     open         0
sub-journal     lock         0
sub-journal     access       0
sub-journal     delete       0
sub-journal     fullPath     0
sub-journal     random       0
sub-journal     sleep        0
sub-journal     currentTime  0
temp-database   bytesIn      0
temp-database   bytesOut     0
temp-database   read         0
temp-database   write        0
temp-database   sync         0
temp-database   open         0
temp-database   lock         0
temp-database   access       0
temp-database   delete       0
temp-database   fullPath     0
temp-database   random       0
temp-database   sleep        0
temp-database   currentTime  0
temp-journal    bytesIn      0
temp-journal    bytesOut     0
temp-journal    read         0
temp-journal    write        0
temp-journal    sync         0
temp-journal    open         0
temp-journal    lock         0
temp-journal    access       0
temp-journal    delete       0
temp-journal    fullPath     0
temp-journal    random       0
temp-journal    sleep        0
temp-journal    currentTime  0
transient-db    bytesIn      0
transient-db    bytesOut     0
transient-db    read         0
transient-db    write        0
transient-db    sync         0
transient-db    open         0
transient-db    lock         0
transient-db    access       0
transient-db    delete       0
transient-db    fullPath     0
transient-db    random       0
transient-db    sleep        0
transient-db    currentTime  0
*               bytesIn      0
*               bytesOut     0
*               read         0
*               write        0
*               sync         0
*               open         0
*               lock         0
*               access       2
*               delete       0
*               fullPath     1
*               random       0
*               sleep        0