enum
CdcVersion
{
V1
=
1
,
V2
=
2
,
}
const
CDC_VERSION_CURRENT
:
CdcVersion
=
CdcVersion
::
V2
;
enum
CaptureDataChangesMode
{
Id
,
// capture only rowid
Before
,
// capture before-image
After
,
// capture after-image
Full
,
// before + after + updates
}
struct
CaptureDataChangesInfo
{
mode
:
CaptureDataChangesMode
,
table
:
String
,
// CDC table name
version
:
Option
<
CdcVersion
,
// schema version (V1 or V2)
}
The connection stores
Option
—
None
means CDC is off.
Key methods on
CdcVersion
:
has_commit_record()
—
self >= V2
, gates COMMIT record emission
Display
/
FromStr
— round-trips
"v1"
↔
V1
,
"v2"
↔
V2
Key methods on
CaptureDataChangesInfo
:
parse(value: &str, version: Option)
— parses PRAGMA argument
"[,]"
, returns
None
for "off"
cdc_version()
— returns
CdcVersion
(panics if version is None). Single accessor replacing old
is_v1()
/
is_v2()
/
version()
methods.
has_before()
/
has_after()
/
has_updates()
— mode capability checks
mode_name()
— returns mode as string
Convenience trait
CaptureDataChangesExt
on
Option
provides:
has_before()
/
has_after()
/
has_updates()
— delegates to inner, returns false for None
table()
— returns
Option<&str>
, None when CDC is off
CDC Table Schema v1
Default table name:
turso_cdc
(constant
TURSO_CDC_DEFAULT_TABLE_NAME
)
CREATE
TABLE
turso_cdc
(
change_id
INTEGER
PRIMARY
KEY
AUTOINCREMENT
,
change_time
INTEGER
,
-- unixepoch()
change_type
INTEGER
,
-- 1=INSERT, 0=UPDATE, -1=DELETE
table_name
TEXT
,
id
<
untyped
,
-- rowid of changed row
before
BLOB
,
-- binary record (before-image)
after
BLOB
,
-- binary record (after-image)
updates
BLOB
-- binary record of per-column changes
)
;
CDC Table Schema v2 (current)
CREATE
TABLE
turso_cdc
(
change_id
INTEGER
PRIMARY
KEY
AUTOINCREMENT
,
change_time
INTEGER
,
-- unixepoch()
change_type
INTEGER
,
-- 1=INSERT, 0=UPDATE, -1=DELETE, 2=COMMIT
table_name
TEXT
,
id
<
untyped
,
-- rowid of changed row
before
BLOB
,
-- binary record (before-image)
after
BLOB
,
-- binary record (after-image)
updates
BLOB
,
-- binary record of per-column changes
change_txn_id
INTEGER
-- transaction ID (groups rows into transactions)
)
;
v2 adds:
change_txn_id
column — groups CDC rows by transaction. Assigned via
conn_txn_id(candidate)
opcode which get-or-sets a per-connection transaction ID.
change_type=2
(COMMIT) records — mark transaction boundaries. Emitted once per statement in autocommit mode, or on explicit
COMMIT
.
The CDC table is created at runtime by the
InitCdcVersion
opcode via
CREATE TABLE IF NOT EXISTS
.
CDC Version Table
When CDC is first enabled, a version tracking table is created:
CREATE
TABLE
turso_cdc_version
(
table_name
TEXT
PRIMARY
KEY
,
version
TEXT
NOT
NULL
)
;
Current version:
CDC_VERSION_CURRENT = CdcVersion::V2
(defined in
core/lib.rs
, re-exported from
core/translate/pragma.rs
)
Version Detection in InitCdcVersion
The
InitCdcVersion
opcode detects v1 vs v2 by checking whether the CDC table already exists before creating it:
If CDC table already exists but has no version row → v1 (pre-existing table from before version tracking)
If CDC table doesn't exist → create with current version (v2)
If version row already exists → use that version as-is
DatabaseChange
—
sync/engine/src/types.rs:229-249
Sync engine's Rust representation of a CDC row. Has
into_apply()
and
into_revert()
methods
for forward/backward replay.
OperationMode
—
core/translate/emitter.rs
Used by
emit_cdc_insns()
to determine
change_type
value:
INSERT
→ 1
UPDATE
/
SELECT
→ 0
DELETE
→ -1
COMMIT
→ 2 (v2 only, emitted by
emit_cdc_commit_insns
)
Entry Points
1. PRAGMA — Enable/Disable CDC
Set:
core/translate/pragma.rs
Checks MVCC is not enabled (CDC and MVCC are mutually exclusive)
Parses mode string via
CaptureDataChangesInfo::parse()
with
CDC_VERSION_CURRENT
Emits a single
InitCdcVersion
opcode — all CDC setup (table creation, version tracking, state change) happens at execution time
Get (read current mode):
core/translate/pragma.rs
Returns 3 columns:
mode
,
table
,
version
When off: returns
("off", NULL, NULL)
When active: returns
(mode_name, table, version)
Pragma registration:
core/pragma.rs
—
CaptureDataChangesConn
(and deprecated alias
UnstableCaptureDataChangesConn
) with columns
["mode", "table", "version"]
2. Connection State
Field:
core/connection.rs
—
capture_data_changes: RwLock
[repr(u8)]
and
Ord
/
PartialOrd
enables feature gating via integer comparison (
has_commit_record()
=
self >= V2
).
Display
/
FromStr
handles database round-trip.
CDC and MVCC mutual exclusion.
Enabling CDC when MVCC is active (or vice versa) returns an error. Checked at PRAGMA set time and journal mode switch time.