Skip to main content

vrtb_core/
engine.rs

1use crate::error::Result;
2
3#[derive(Clone, Debug)]
4pub struct TableRef {
5    pub schema: Option<String>,
6    pub name: String,
7}
8
9#[derive(Clone, PartialEq, Eq, Debug)]
10pub enum LogicalType {
11    Int,
12    Decimal { scale: u8 },
13    Timestamp { precision: u8 },
14    String,
15    Boolean,
16    Binary,
17}
18
19#[derive(Clone, Debug)]
20pub struct ColumnSchema {
21    pub name: String,
22    pub ty: LogicalType,
23    pub nullable: bool,
24    pub default_value: Option<String>,
25    pub primary_key: bool,
26}
27
28#[derive(Debug)]
29pub struct TableSchema {
30    pub columns: Vec<ColumnSchema>,
31}
32
33#[derive(Clone, Debug)]
34pub struct ComparePlan {
35    pub key: ColumnSchema,
36    pub columns: Vec<ColumnSchema>,
37} // resolved shared cols
38
39#[derive(Debug)]
40pub enum KeyValue {
41    Int(i128),
42    Bytes(Vec<u8>),
43} // int or UUID-as-bytes
44
45// Segment / Checksum / DiffRow are forward-declared scaffolding for the
46// not-yet-implemented hashdiff/joindiff paths (docs/STATUS.md §5); their fields
47// aren't read yet.
48#[allow(dead_code)]
49pub struct Segment {
50    lo: KeyValue,
51    hi: KeyValue,
52} // half-open [lo, hi)
53
54#[allow(dead_code)]
55pub struct Checksum {
56    half1: u64,
57    half2: u64,
58    count: u64,
59} // 128-bit checksum + count of rows
60
61#[derive(Debug)]
62pub enum DiffOp {
63    Left,
64    Right,
65    Differ,
66} // Equivalent to classic diff '-', '+', '~'
67
68#[allow(dead_code)]
69pub struct DiffRow {
70    op: DiffOp,
71    key: KeyValue,
72    columns: Vec<Option<String>>,
73}
74
75#[derive(Debug)]
76pub struct JoinDiffQuery {
77    pub left_only: String,
78    pub right_only: String,
79    pub differing: String,
80}
81
82pub trait Engine {
83    fn name(&self) -> &str;
84    fn introspect(&self, table: &TableRef) -> Result<TableSchema>;
85    fn dialect(&self) -> &dyn Dialect;
86    fn execute(&self, sql: &str) -> Result<Vec<Vec<String>>>;
87}
88
89pub trait Dialect {
90    /// joindiff: fast-exit precheck (whole-table checksum + count)
91    fn whole_table_checksum_sql(&self, table: &TableRef, plan: &ComparePlan) -> Result<String>;
92
93    /// joindiff: full outer join
94    fn joindiff_sql(&self, a: &TableRef, b: &TableRef, plan: &ComparePlan) -> Result<JoinDiffQuery>;
95
96    /// materialize: one CREATE TABLE <target> AS … writing the joindiff result
97    /// (op / key / src_row / dst_row JSON) server-side. Plain CTAS: fails if
98    /// `target` exists — never drops or replaces (docs/superpowers spec, 2026-07-05).
99    fn materialize_sql(
100        &self,
101        a: &TableRef,
102        b: &TableRef,
103        plan: &ComparePlan,
104        target: &TableRef,
105    ) -> Result<String>;
106
107    /// hashdiff: normalization matrix - One column -> canonical SQL expression
108    fn normalize_column(&self, col: &ColumnSchema) -> Result<String>;
109
110    /// hashdiff: per-row digest from canonical expressions -> md5 -> two u64 halves
111    fn digest_expr(&self, canon_cols: &[String]) -> Result<String>;
112
113    /// hashdiff: bound the keyspace
114    fn keyspace_bounds_sql(&self, table: &TableRef, key: &ColumnSchema) -> Result<String>;
115
116    /// hashdiff: one segment's checksum tuple, server-side execution
117    fn segment_checksum_sql(
118        &self,
119        table: &TableRef,
120        plan: &ComparePlan,
121        segment: &Segment,
122    ) -> Result<String>;
123
124    /// hashdiff: leaf rows for a narrowed, still-disagreeing segment
125    fn segment_rows_sql(&self, table: &TableRef, plan: &ComparePlan) -> Result<String>;
126}