Skip to content

Row Diff Engine

The row diff engine compares SQLite snapshots and attempts to describe changes in logical table terms. It exists so repository diffs and merge UI can show more than “the database file changed.”

Use repository-level row diff for product integrations:

Terminal window
graft diff --rows HEAD~1 HEAD data.sqlite
graft diff --json --rows HEAD~1 HEAD data.sqlite

Low-level storage diagnostics can compare raw storage LSNs:

PRAGMA graft_debug_log_lsn;
PRAGMA graft_debug_volume_diff = '2,4,rows';
PRAGMA graft_debug_volume_json_diff = '2,4,rows';

These are for implementation work and storage debugging. They should not be the normal application API.

JSON row diff output can include:

{
"path": "data.sqlite",
"change": "modified",
"row_diff_available": true,
"logical_status": "logical_changes",
"capabilities": ["rowid_table_rows", "primary_key_table_rows", "schema_entries"],
"limitations": [],
"tables": []
}

logical_status lets applications distinguish supported logical row changes from conservative or unavailable cases.

The engine uses the direct page parser for supported 4 KiB rowid-table paths. It materializes snapshots through SQLite when native page size differs or a WITHOUT ROWID table needs declared-primary-key identity. This keeps the fast path while covering legal physical page sizes, STRICT schemas, and typed composite primary keys.

During merge, the same analysis can produce:

  • row conflicts
  • schema conflicts
  • opaque changes
  • resolved internal changes
  • limitations
  • blocked reasons
  • apply policy and validation details

This output feeds graft conflicts --json.

The row diff engine works below repository revspecs. Repository commands resolve HEAD, branches, tags, and commit ids into the snapshot objects the row engine can compare. Applications should keep using repository-level commands so the UI stays aligned with branches, refs, and path state.