pub struct DiffSetBuilder<F: Format<S, B>, T: SchemaWithPK, S, B> { /* private fields */ }Expand description
Builder for constructing changeset or patchset binary data.
DiffSetBuilder tracks rows in DML insertion order. When build
is called, it simulates SQLite’s session-extension hash table to produce
byte-identical output.
For parsed (frozen) data that should be emitted in its original order,
see DiffSet.
Generic over the format F (Changeset or Patchset), table schema T, and value types S, B.
Implementations§
Source§impl<F: Format<S, B>, T: SchemaWithPK, S: AsRef<str> + Hash + Eq, B: AsRef<[u8]> + Hash + Eq> DiffSetBuilder<F, T, S, B>
impl<F: Format<S, B>, T: SchemaWithPK, S: AsRef<str> + Hash + Eq, B: AsRef<[u8]> + Hash + Eq> DiffSetBuilder<F, T, S, B>
Sourcepub fn add_table(&mut self, table: &T) -> &mut Self
pub fn add_table(&mut self, table: &T) -> &mut Self
Register a table schema without adding any operations.
This is useful when you need the table present (e.g. before calling
DiffSetBuilder::digest_sql) but don’t have operations yet.
If the table is already registered, this is a no-op.
Source§impl<F, T, S, B> DiffSetBuilder<F, T, S, B>
impl<F, T, S, B> DiffSetBuilder<F, T, S, B>
Sourcepub fn digest<E, Sch, A>(
self,
event: &E,
schema: &Sch,
adapter: &A,
) -> Result<Self, E::Error>where
E: Digestable<F, T, S, B>,
Sch: WireSchema<Table = T>,
A: WireAdapter<E::Src, S, B>,
T: WireColumnTypes,
pub fn digest<E, Sch, A>(
self,
event: &E,
schema: &Sch,
adapter: &A,
) -> Result<Self, E::Error>where
E: Digestable<F, T, S, B>,
Sch: WireSchema<Table = T>,
A: WireAdapter<E::Src, S, B>,
T: WireColumnTypes,
Digest one CDC wire event, resolving each affected table via
schema and decoding column payloads via adapter.
§Errors
Whatever E::Error reports (per-source ConversionError).
Source§impl<T: NamedColumns, S: Clone + Hash + Eq + AsRef<str> + for<'a> From<&'a str>> DiffSetBuilder<PatchsetFormat, T, S, Vec<u8>>
impl<T: NamedColumns, S: Clone + Hash + Eq + AsRef<str> + for<'a> From<&'a str>> DiffSetBuilder<PatchsetFormat, T, S, Vec<u8>>
Sourcepub fn digest_sql<'input>(
&mut self,
input: &'input str,
) -> Result<&mut Self, ParseError<'input>>
pub fn digest_sql<'input>( &mut self, input: &'input str, ) -> Result<&mut Self, ParseError<'input>>
Digest a SQL string containing INSERT, UPDATE, and DELETE statements into this patchset builder.
The entire input is parsed before any change is applied. A parse error on any statement leaves the builder exactly as it was before this call.
§Supported subset
Each statement must be one of these forms:
INSERT INTO table (col1, col2, ...) VALUES (v1, v2, ...)
UPDATE table SET col1 = v1, ... WHERE pk1 = v1 AND pk2 = v2 ...
DELETE FROM table WHERE pk1 = v1 AND pk2 = v2 ...A WHERE clause is not a filter over stored rows. It is the only
way the parser can identify which row is targeted, because no table
data is available. Every WHERE must therefore name every primary
key column with equality predicates joined by AND. OR, >,
LIKE, subqueries, and IN are not supported.
Multiple statements can be separated by semicolons.
§Errors
Returns a crate::builders::sql::ParseError if any statement
cannot be parsed. The builder is left untouched in that case.
Source§impl<T: SchemaWithPK, S: Clone + Debug + Hash + Eq + AsRef<str>, B: Clone + Debug + Hash + Eq + AsRef<[u8]>> DiffSetBuilder<ChangesetFormat, T, S, B>
impl<T: SchemaWithPK, S: Clone + Debug + Hash + Eq + AsRef<str>, B: Clone + Debug + Hash + Eq + AsRef<[u8]>> DiffSetBuilder<ChangesetFormat, T, S, B>
Source§impl<T: SchemaWithPK, S: Clone + Debug + AsRef<str>, B: Clone + Debug + AsRef<[u8]>> DiffSetBuilder<ChangesetFormat, T, S, B>
impl<T: SchemaWithPK, S: Clone + Debug + AsRef<str>, B: Clone + Debug + AsRef<[u8]>> DiffSetBuilder<ChangesetFormat, T, S, B>
Sourcepub fn iter(&self) -> impl Iterator<Item = ChangesetOp<'_, T, S, B>>
pub fn iter(&self) -> impl Iterator<Item = ChangesetOp<'_, T, S, B>>
Walk operations grouped by table in DML insertion order.
Mirrors DiffSet::iter but keeps insertion order; the
session-extension hash ordering only applies at build
time.
Source§impl<T: SchemaWithPK, S: Clone + Hash + Eq + AsRef<str>, B: Clone + Hash + Eq + AsRef<[u8]>> DiffSetBuilder<PatchsetFormat, T, S, B>
impl<T: SchemaWithPK, S: Clone + Hash + Eq + AsRef<str>, B: Clone + Hash + Eq + AsRef<[u8]>> DiffSetBuilder<PatchsetFormat, T, S, B>
Source§impl<T: SchemaWithPK, S: Clone + AsRef<str>, B: Clone + AsRef<[u8]>> DiffSetBuilder<PatchsetFormat, T, S, B>
impl<T: SchemaWithPK, S: Clone + AsRef<str>, B: Clone + AsRef<[u8]>> DiffSetBuilder<PatchsetFormat, T, S, B>
Sourcepub fn iter(&self) -> impl Iterator<Item = PatchsetOp<'_, T, S, B>>
pub fn iter(&self) -> impl Iterator<Item = PatchsetOp<'_, T, S, B>>
Walk operations grouped by table in DML insertion order.
Mirrors DiffSet::iter but keeps insertion order; the
session-extension hash ordering only applies at build
time. With the diesel feature enabled, each item implements
QueryFragment and executes
via RunQueryDsl.
Source§impl<T: ColumnNames, S: AsRef<str> + Clone + Debug + Hash + Eq, B: AsRef<[u8]> + Clone + Debug + Hash + Eq> DiffSetBuilder<ChangesetFormat, T, S, B>
impl<T: ColumnNames, S: AsRef<str> + Clone + Debug + Hash + Eq, B: AsRef<[u8]> + Clone + Debug + Hash + Eq> DiffSetBuilder<ChangesetFormat, T, S, B>
Sourcepub fn sql_statements(&self) -> impl Iterator<Item = String> + '_
pub fn sql_statements(&self) -> impl Iterator<Item = String> + '_
Iterate over operations as SQL statements.
Each operation is converted to an INSERT, UPDATE, or DELETE statement. Identifiers (table and column names) are quoted with double quotes. Statements do not include trailing semicolons.
§Example
use sqlite_diff_rs::{SimpleTable, ChangeSet, DiffOps, Insert};
let table = SimpleTable::new("users", &["id", "name"], &[0]);
let insert = Insert::from(table.clone())
.set(0, 1i64).unwrap()
.set(1, "Alice").unwrap();
let changeset = ChangeSet::<SimpleTable, String, Vec<u8>>::new().insert(insert);
for sql in changeset.sql_statements() {
assert_eq!(sql, r#"INSERT INTO "users" ("id", "name") VALUES (1, 'Alice')"#);
}Source§impl<T: ColumnNames, S: AsRef<str> + Clone + Hash + Eq, B: AsRef<[u8]> + Clone + Hash + Eq> DiffSetBuilder<PatchsetFormat, T, S, B>
impl<T: ColumnNames, S: AsRef<str> + Clone + Hash + Eq, B: AsRef<[u8]> + Clone + Hash + Eq> DiffSetBuilder<PatchsetFormat, T, S, B>
Sourcepub fn sql_statements(&self) -> impl Iterator<Item = String> + '_
pub fn sql_statements(&self) -> impl Iterator<Item = String> + '_
Iterate over operations as SQL statements.
Each operation is converted to an INSERT, UPDATE, or DELETE statement. Identifiers (table and column names) are quoted with double quotes. Statements do not include trailing semicolons.
§Example
use sqlite_diff_rs::{SimpleTable, PatchSet, DiffOps, Insert};
let table = SimpleTable::new("users", &["id", "name"], &[0]);
let insert = Insert::from(table.clone())
.set(0, 1i64).unwrap()
.set(1, "Alice").unwrap();
let patchset = PatchSet::<SimpleTable, String, Vec<u8>>::new().insert(insert);
for sql in patchset.sql_statements() {
assert_eq!(sql, r#"INSERT INTO "users" ("id", "name") VALUES (1, 'Alice')"#);
}Trait Implementations§
Source§impl<F: Format<S, B>, T: SchemaWithPK, S: Clone + Hash + Eq + AsRef<str>, B: Clone + Hash + Eq + AsRef<[u8]>> BitOr for DiffSetBuilder<F, T, S, B>
impl<F: Format<S, B>, T: SchemaWithPK, S: Clone + Hash + Eq + AsRef<str>, B: Clone + Hash + Eq + AsRef<[u8]>> BitOr for DiffSetBuilder<F, T, S, B>
Source§impl<F: Format<S, B>, T: SchemaWithPK, S: Clone + Hash + Eq + AsRef<str>, B: Clone + Hash + Eq + AsRef<[u8]>> BitOrAssign for DiffSetBuilder<F, T, S, B>
impl<F: Format<S, B>, T: SchemaWithPK, S: Clone + Hash + Eq + AsRef<str>, B: Clone + Hash + Eq + AsRef<[u8]>> BitOrAssign for DiffSetBuilder<F, T, S, B>
Source§fn bitor_assign(&mut self, rhs: Self)
fn bitor_assign(&mut self, rhs: Self)
Merge another diff set into this one, consolidating operations on the same row.
Source§impl<F: Clone + Format<S, B>, T: Clone + SchemaWithPK, S: Clone, B: Clone> Clone for DiffSetBuilder<F, T, S, B>
impl<F: Clone + Format<S, B>, T: Clone + SchemaWithPK, S: Clone, B: Clone> Clone for DiffSetBuilder<F, T, S, B>
Source§fn clone(&self) -> DiffSetBuilder<F, T, S, B>
fn clone(&self) -> DiffSetBuilder<F, T, S, B>
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl<F: Debug + Format<S, B>, T: Debug + SchemaWithPK, S: Debug, B: Debug> Debug for DiffSetBuilder<F, T, S, B>
impl<F: Debug + Format<S, B>, T: Debug + SchemaWithPK, S: Debug, B: Debug> Debug for DiffSetBuilder<F, T, S, B>
Source§impl<F: Format<S, B>, T: SchemaWithPK, S: AsRef<str> + Hash + Eq, B: AsRef<[u8]> + Hash + Eq> Default for DiffSetBuilder<F, T, S, B>
impl<F: Format<S, B>, T: SchemaWithPK, S: AsRef<str> + Hash + Eq, B: AsRef<[u8]> + Hash + Eq> Default for DiffSetBuilder<F, T, S, B>
Source§impl<T: SchemaWithPK, S: Clone + Debug + Hash + Eq + AsRef<str>, B: Clone + Debug + Hash + Eq + AsRef<[u8]>> DiffOps<T, S, B> for DiffSetBuilder<ChangesetFormat, T, S, B>
impl<T: SchemaWithPK, S: Clone + Debug + Hash + Eq + AsRef<str>, B: Clone + Debug + Hash + Eq + AsRef<[u8]>> DiffOps<T, S, B> for DiffSetBuilder<ChangesetFormat, T, S, B>
Source§type Format = ChangesetFormat
type Format = ChangesetFormat
Source§fn delete(self, delete: ChangeDelete<T, S, B>) -> Self
fn delete(self, delete: ChangeDelete<T, S, B>) -> Self
Source§fn update(self, update: Update<T, ChangesetFormat, S, B>) -> Self
fn update(self, update: Update<T, ChangesetFormat, S, B>) -> Self
Source§impl<T: SchemaWithPK, S: Clone + Hash + Eq + AsRef<str>, B: Clone + Hash + Eq + AsRef<[u8]>> DiffOps<T, S, B> for DiffSetBuilder<PatchsetFormat, T, S, B>
impl<T: SchemaWithPK, S: Clone + Hash + Eq + AsRef<str>, B: Clone + Hash + Eq + AsRef<[u8]>> DiffOps<T, S, B> for DiffSetBuilder<PatchsetFormat, T, S, B>
Source§fn delete(self, delete: PatchDelete<T, S, B>) -> Self
fn delete(self, delete: PatchDelete<T, S, B>) -> Self
Delete by primary key.
§Example
use sqlite_diff_rs::{DiffOps, PatchDelete, PatchSet, SchemaWithPK, TableSchema};
// CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)
let schema: TableSchema<String> = TableSchema::new("users".into(), 2, vec![1, 0]);
// Delete row where id = 1
let patchset = PatchSet::<_, String, Vec<u8>>::new()
.delete(PatchDelete::new(schema, vec![1i64.into()]));Source§fn update(self, update: Update<T, PatchsetFormat, S, B>) -> Self
fn update(self, update: Update<T, PatchsetFormat, S, B>) -> Self
Update by primary key.
§Example
use sqlite_diff_rs::{DiffOps, PatchSet, PatchsetFormat, Update, TableSchema};
// CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)
let schema: TableSchema<String> = TableSchema::new("users".into(), 2, vec![1, 0]);
// UPDATE users SET name = 'Bob' WHERE id = 1
let update = Update::<_, PatchsetFormat, String, Vec<u8>>::from(schema)
.set(0, 1i64).unwrap() // PK value
.set(1, "Bob").unwrap();
let patchset = PatchSet::<_, String, Vec<u8>>::new()
.update(update);Source§type Format = PatchsetFormat
type Format = PatchsetFormat
impl<F: Format<S, B>, T: SchemaWithPK, S, B> Eq for DiffSetBuilder<F, T, S, B>
Source§impl<T: SchemaWithPK, S: Clone + Debug + Hash + Eq + AsRef<str>, B: Clone + Debug + Hash + Eq + AsRef<[u8]>> From<&DiffSetBuilder<ChangesetFormat, T, S, B>> for Vec<u8>
impl<T: SchemaWithPK, S: Clone + Debug + Hash + Eq + AsRef<str>, B: Clone + Debug + Hash + Eq + AsRef<[u8]>> From<&DiffSetBuilder<ChangesetFormat, T, S, B>> for Vec<u8>
Source§fn from(builder: &DiffSetBuilder<ChangesetFormat, T, S, B>) -> Self
fn from(builder: &DiffSetBuilder<ChangesetFormat, T, S, B>) -> Self
Source§impl<T: SchemaWithPK, S: AsRef<str> + Clone + Hash + Eq, B: AsRef<[u8]> + Clone + Hash + Eq> From<&DiffSetBuilder<PatchsetFormat, T, S, B>> for Vec<u8>
impl<T: SchemaWithPK, S: AsRef<str> + Clone + Hash + Eq, B: AsRef<[u8]> + Clone + Hash + Eq> From<&DiffSetBuilder<PatchsetFormat, T, S, B>> for Vec<u8>
Source§fn from(builder: &DiffSetBuilder<PatchsetFormat, T, S, B>) -> Self
fn from(builder: &DiffSetBuilder<PatchsetFormat, T, S, B>) -> Self
Source§impl<F: Format<S, B>, T: SchemaWithPK, S: Hash + Eq + AsRef<str>, B: Hash + Eq + AsRef<[u8]>> From<DiffSet<F, T, S, B>> for DiffSetBuilder<F, T, S, B>
impl<F: Format<S, B>, T: SchemaWithPK, S: Hash + Eq + AsRef<str>, B: Hash + Eq + AsRef<[u8]>> From<DiffSet<F, T, S, B>> for DiffSetBuilder<F, T, S, B>
Source§impl<T: SchemaWithPK, S: Clone + Debug + Hash + Eq + AsRef<str>, B: Clone + Debug + Hash + Eq + AsRef<[u8]>> From<DiffSetBuilder<ChangesetFormat, T, S, B>> for Vec<u8>
impl<T: SchemaWithPK, S: Clone + Debug + Hash + Eq + AsRef<str>, B: Clone + Debug + Hash + Eq + AsRef<[u8]>> From<DiffSetBuilder<ChangesetFormat, T, S, B>> for Vec<u8>
Source§fn from(builder: DiffSetBuilder<ChangesetFormat, T, S, B>) -> Self
fn from(builder: DiffSetBuilder<ChangesetFormat, T, S, B>) -> Self
Source§impl<F: Format<S, B>, T: SchemaWithPK, S: Hash + Eq + AsRef<str>, B: Hash + Eq + AsRef<[u8]>> From<DiffSetBuilder<F, T, S, B>> for DiffSet<F, T, S, B>
impl<F: Format<S, B>, T: SchemaWithPK, S: Hash + Eq + AsRef<str>, B: Hash + Eq + AsRef<[u8]>> From<DiffSetBuilder<F, T, S, B>> for DiffSet<F, T, S, B>
Source§fn from(builder: DiffSetBuilder<F, T, S, B>) -> Self
fn from(builder: DiffSetBuilder<F, T, S, B>) -> Self
Source§impl<T: SchemaWithPK, S: AsRef<str> + Clone + Hash + Eq, B: AsRef<[u8]> + Clone + Hash + Eq> From<DiffSetBuilder<PatchsetFormat, T, S, B>> for Vec<u8>
impl<T: SchemaWithPK, S: AsRef<str> + Clone + Hash + Eq, B: AsRef<[u8]> + Clone + Hash + Eq> From<DiffSetBuilder<PatchsetFormat, T, S, B>> for Vec<u8>
Source§fn from(builder: DiffSetBuilder<PatchsetFormat, T, S, B>) -> Self
fn from(builder: DiffSetBuilder<PatchsetFormat, T, S, B>) -> Self
Source§impl<F: Format<S, B>, T: SchemaWithPK, S, B> PartialEq for DiffSetBuilder<F, T, S, B>
Custom PartialEq that ignores tables with empty operations.
impl<F: Format<S, B>, T: SchemaWithPK, S, B> PartialEq for DiffSetBuilder<F, T, S, B>
Custom PartialEq that ignores tables with empty operations.
Tables with no operations are not serialized (skipped in build()), so after
roundtrip they won’t exist. This makes empty tables semantically equivalent
to non-existent tables for comparison purposes.
Verified: SQLite’s session extension does NOT include empty table entries in
changesets/patchsets when all operations cancel out. Our builder keeps them
in memory to preserve table ordering, but they are correctly excluded here
and in build().
Source§impl<T: SchemaWithPK, S: Clone + Debug + Hash + Eq + AsRef<str>, B: Clone + Debug + Hash + Eq + AsRef<[u8]>> Reverse for DiffSetBuilder<ChangesetFormat, T, S, B>
impl<T: SchemaWithPK, S: Clone + Debug + Hash + Eq + AsRef<str>, B: Clone + Debug + Hash + Eq + AsRef<[u8]>> Reverse for DiffSetBuilder<ChangesetFormat, T, S, B>
Source§type Output = DiffSetBuilder<ChangesetFormat, T, S, B>
type Output = DiffSetBuilder<ChangesetFormat, T, S, B>
Auto Trait Implementations§
impl<F, T, S, B> Freeze for DiffSetBuilder<F, T, S, B>where
IndexMap<T, IndexMap<Vec<Value<S, B>>, Operation<F, S, B>, DefaultHashBuilder>, DefaultHashBuilder>: Freeze,
impl<F, T, S, B> RefUnwindSafe for DiffSetBuilder<F, T, S, B>where
IndexMap<T, IndexMap<Vec<Value<S, B>>, Operation<F, S, B>, DefaultHashBuilder>, DefaultHashBuilder>: RefUnwindSafe,
impl<F, T, S, B> Send for DiffSetBuilder<F, T, S, B>where
IndexMap<T, IndexMap<Vec<Value<S, B>>, Operation<F, S, B>, DefaultHashBuilder>, DefaultHashBuilder>: Send,
impl<F, T, S, B> Sync for DiffSetBuilder<F, T, S, B>where
IndexMap<T, IndexMap<Vec<Value<S, B>>, Operation<F, S, B>, DefaultHashBuilder>, DefaultHashBuilder>: Sync,
impl<F, T, S, B> Unpin for DiffSetBuilder<F, T, S, B>where
IndexMap<T, IndexMap<Vec<Value<S, B>>, Operation<F, S, B>, DefaultHashBuilder>, DefaultHashBuilder>: Unpin,
impl<F, T, S, B> UnsafeUnpin for DiffSetBuilder<F, T, S, B>where
IndexMap<T, IndexMap<Vec<Value<S, B>>, Operation<F, S, B>, DefaultHashBuilder>, DefaultHashBuilder>: UnsafeUnpin,
impl<F, T, S, B> UnwindSafe for DiffSetBuilder<F, T, S, B>where
IndexMap<T, IndexMap<Vec<Value<S, B>>, Operation<F, S, B>, DefaultHashBuilder>, DefaultHashBuilder>: UnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.