Skip to main content

Crate sqlite_diff_rs

Crate sqlite_diff_rs 

Source
Expand description

§sqlite-diff-rs

Crates.io Documentation CI AddressSanitizer Codecov License: MIT

A Rust library for building SQLite changeset and patchset binary formats programmatically.

§Overview

SQLite’s session extension defines a binary format for tracking and applying database changes. This crate constructs that binary data without linking SQLite, which is useful for offline sync (build a changeset on a server and apply it on a SQLite client), CDC pipelines (produce the input expected by sqlite3_changeset_apply() from your own change events), cross-database sync (convert PostgreSQL change streams from wal2json, Debezium, or Maxwell into the SQLite format), and generating test fixtures for changeset processing code.

This crate is not the SQLite sqldiff tool, which compares two existing database files. This library constructs the changeset and patchset binary format programmatically from your own change data.

§Installation

Add to your Cargo.toml:

[dependencies]
sqlite-diff-rs = "0.1"

§Quick Start

use sqlite_diff_rs::{DiffOps, Insert, PatchSet, SimpleTable};

// Define a table schema: "users" with columns (id, name), PK at index 0
let users = SimpleTable::new("users", &["id", "name"], &[0]);

// Build a patchset with an INSERT
let patchset = PatchSet::<_, String, Vec<u8>>::new()
    .insert(
        Insert::from(users)
            .set(0, 1i64).unwrap()      // id = 1
            .set(1, "Alice").unwrap()   // name = "Alice"
    );

// Encode to binary format
let bytes: Vec<u8> = patchset.into();

// Apply with sqlite3_changeset_apply() or sqlite3session_patchset_apply()

§Features

FeatureDescription
testingEnables rusqlite integration for differential testing
wal2jsonParse PostgreSQL wal2json output into changesets
pg-walstreamIntegration with pg_walstream crate
debeziumParse Debezium CDC JSON events
maxwellParse Maxwell CDC JSON events

Enable features in Cargo.toml:

[dependencies]
sqlite-diff-rs = { version = "0.1", features = ["wal2json"] }

§Binary Format Reference

Changeset vs Patchset binary wire format

Both formats share the same container structure: one or more table sections, each with a table header followed by change records. The key difference is how much old-row data each operation carries.

Changesets ('T' / 0x54) store the complete old state of every column. This makes them reversible, so INSERTs can be turned into DELETEs and vice versa.

Patchsets ('P' / 0x50) omit old values for non-PK columns, producing a smaller, forward-only encoding that cannot be reversed.

AspectChangeset ('T')Patchset ('P')
INSERTAll column valuesAll column values
DELETEAll old column valuesPK values only
UPDATE oldAll old column valuesPK values + Undefined for non-PK
UPDATE newAll new column valuesAll new column values
ReversibleYesNo
Wire sizeLarger (carries full old state)Smaller (omits non-PK old values)

See the SQLite session extension docs for the full specification.

§no_std Support

This crate is no_std compatible (requires alloc). It can be used in embedded or WebAssembly environments.

§Live demo

A serverless, two-peer chat demo lives at https://lucacappelletti94.github.io/sqlite-diff-rs/. Each browser runs its own SQLite (via sqlite-wasm-rs) accessed through diesel-sqlite-session, and the two peers exchange changeset bytes directly over a WebRTC data channel. There is no backend, no signaling server, and no STUN configuration beyond Google’s public STUN endpoint.

To connect two browsers:

  1. Open the demo URL in tab A and pick a display name. Click Create room.
  2. The tab shows an offer URL containing the full SDP in its fragment (#o=...). Send it to tab B (chat app, paste, QR code).
  3. Tab B opens the URL, picks its own name, and clicks Generate reply code. Send the resulting base64 blob back to tab A by any means (paste, chat app, QR code).
  4. Tab A pastes the reply code into the “Paste their reply” box and clicks Connect. The data channel opens.
  5. Every message, edit, and delete in either tab is captured as a SQLite session changeset and applied on the other side. The diff inspector at the bottom shows the wire bytes parsed back through sqlite-diff-rs.

The demo source is at examples/web-demo/.

§License

MIT License, see LICENSE for details.

Re-exports§

pub use builders::ChangeDelete;
pub use builders::ChangeSet;
pub use builders::ChangesetFormat;
pub use builders::ChangesetOp;
pub use builders::ChangesetUpdatePair;
pub use builders::ColumnNames;
pub use builders::DiffOps;
pub use builders::DiffSet;
pub use builders::DiffSetBuilder;
pub use builders::Indirect;
pub use builders::Insert;
pub use builders::PatchDelete;
pub use builders::PatchSet;
pub use builders::PatchsetFormat;
pub use builders::PatchsetOp;
pub use builders::PatchsetUpdateEntry;
pub use builders::Reverse;
pub use builders::Update;
pub use parser::FormatMarker;
pub use parser::ParseError;
pub use parser::ParsedDiffSet;
pub use parser::TableSchema;
pub use schema::DynTable;
pub use schema::NamedColumns;
pub use schema::SchemaWithPK;
pub use schema::SimpleTable;
pub use errors::Error;

Modules§

builders
Builder for constructing changesets and patchsets.
errors
Submodule defining the errors used across the crate.
parser
Parser for SQLite changeset/patchset binary format.
schema
Schema traits for compile-time and runtime table definitions.

Enums§

Value
A value that can be encoded in SQLite changeset format.

Type Aliases§

ChangeUpdate
Type alias for Update<T, ChangesetFormat, S, B>.
PatchUpdate
Type alias for Update<T, PatchsetFormat, S, B>.