DATA BRANCH DIFF¶
The DATA BRANCH DIFF statement is used to compare data differences between two tables.
Description¶
The DATA BRANCH DIFF statement is used to compare data differences between two tables. This feature is similar to Git’s diff command and can display insert, delete, and update operations between two data branches.
The system automatically identifies the Lowest Common Ancestor (LCA) between two tables and calculates lineage-aware differences when one exists. In that case, the difference results include:
INSERT: Rows that exist in the target table but not in the base table
DELETE: Rows that exist in the base table but not in the target table
UPDATE: Rows with the same primary key in both tables but different values in other columns
If the tables have no common ancestor, both sides are treated as independent images: a row that exists on only one side, or has a different value on each side, is emitted as an INSERT for the side that supplies that image. DELETE and UPDATE describe lineage-aware changes, not the no-LCA fallback.
Syntax¶
DATA BRANCH DIFF target_table [{ SNAPSHOT = 'snapshot_name' }]
AGAINST base_table [{ SNAPSHOT = 'snapshot_name' }]
[COLUMNS ( col1 [, col2 ...] )]
[OUTPUT output_option]
COLUMNS projection¶
COLUMNS (col1, col2, ...) restricts the visible value columns returned per diff row to exactly the requested subset. Primary-key columns are still used internally for matching and final ordering, but are not added to the output unless explicitly listed. Column names are matched and deduplicated case-insensitively, preserving the first occurrence, so COLUMNS(name, NAME, name) emits one name column. COLUMNS cannot be combined with OUTPUT FILE.
Output Options¶
output_option:
COUNT -- Return only the count of different rows
| LIMIT number -- Limit the number of returned difference rows
| FILE 'directory_path' -- Export differences as SQL file
| AS table_name -- Persist differences in a new ordinary table
| SUMMARY -- Return aggregated INSERT / DELETE / UPDATE counts
Arguments¶
Parameter Description¶
Parameter |
Description |
|---|---|
|
Target table (the table to compare) |
|
Base table (the table used as comparison baseline) |
|
Optional parameter to specify using data at a snapshot point for comparison |
|
Return only the count of differences |
|
Return at most |
|
Export differences as SQL file to specified directory, supports local path or Stage path (e.g., |
|
Create a persistent ordinary table containing the diff. The table contains |
|
Return three rows ( |
|
Return exactly the listed value columns; primary-key columns are not implicitly included. Cannot be combined with |
Output Column Description¶
Default output includes the following columns:
Column Name |
Description |
|---|---|
|
Shows the table names being compared |
|
Difference type: INSERT, DELETE, or UPDATE |
Other columns |
All visible columns of the table |
OUTPUT AS¶
OUTPUT AS table_name materializes the diff as a persistent ordinary table. It does not create a data branch and is visible to other sessions after the statement commits. The output keeps the requested value-column order and types, and adds two metadata columns populated by the diff operation:
__mo_diff_source: the source table name for the row in the diff.__mo_diff_flag:INSERT,DELETE, orUPDATE.
If a user column has one of these names, MatrixOne chooses a collision-safe suffixed name. COLUMNS (...) controls the visible value columns in the same way as a result-set diff; primary-key columns are not added unless explicitly requested. The destination may be qualified with a database name, must not already exist, and cannot be a snapshot. Normal CREATE TABLE privileges are checked. If schema validation or table creation fails, the partially created output table is removed atomically.
DROP DATABASE IF EXISTS diff_output_demo;
CREATE DATABASE diff_output_demo;
USE diff_output_demo;
CREATE TABLE base (id INT PRIMARY KEY, value VARCHAR(20));
INSERT INTO base VALUES (1, 'old');
CREATE TABLE target (id INT PRIMARY KEY, value VARCHAR(20));
INSERT INTO target VALUES (1, 'new'), (2, 'added');
DATA BRANCH DIFF target AGAINST base COLUMNS (value) OUTPUT AS diff_rows;
SHOW COLUMNS FROM diff_rows;
SELECT __mo_diff_flag, __mo_diff_source, value FROM diff_rows ORDER BY value;
DROP TABLE diff_rows;
DROP TABLE target;
DROP TABLE base;
DROP DATABASE diff_output_demo;
Usage Notes¶
LCA (Lowest Common Ancestor)¶
The system automatically detects the branch relationship between two tables:
No LCA: Two tables have no common ancestor, directly compare all data
Has LCA: Two tables have a common ancestor, calculate incremental differences based on ancestor
Self as LCA: One table is the ancestor of the other
For no-LCA comparisons, rows unique to either side and differing images of the same key are labeled as that side’s INSERT. For lineage-aware comparisons, INSERT, DELETE, and UPDATE describe changes relative to the common ancestor.
Persisting and ordering output¶
OUTPUT ASmaterializes the result as a normal table. It fails if the destination already exists, if a destination snapshot is specified, or if the caller lacksCREATE TABLEon the destination database.The persisted table exposes
__mo_diff_sourceand__mo_diff_flagin place of the display-only source/flag headings.OUTPUT ASparticipates in an explicit transaction: both the table and its materialized rows persist onCOMMITand disappear onROLLBACK. An empty diff still creates an empty table on commit.If source columns already use
__mo_diff_sourceor__mo_diff_flag, the generated metadata columns are renamed with an available numeric suffix such as__mo_diff_source_1; the source columns keep their names. Snapshot comparisons materialize the schema visible at the selected historical endpoint, and an incompatible historical mapping fails before the destination table is created.OUTPUT LIMIT Napplies to the final result ordered by the table primary key; it does not expose internal storage order.OUTPUT SUMMARYreturns columnsmetric,<target_table>, and<base_table>, with rowsINSERTED,DELETED, andUPDATED. It does not return row images.
The LCA resolution and collect-range computation work across branches of arbitrary DAG depth, not just direct parent-child relationships. Multi-fork trees with complex branching histories produce correct diffs across any pair of nodes (siblings, cousins, cross-subtree).
Supported Table Types¶
Tables with primary key (recommended)
Tables with composite primary key
Tables without primary key (using hidden fake primary key)
Examples¶
Example 1: Basic Difference Comparison¶
Compare two tables without a common ancestor:
-- Expected-Rows: 0
CREATE DATABASE test;
-- Expected-Rows: 0
USE test;
-- Expected-Rows: 0
CREATE TABLE test.t1 (a INT PRIMARY KEY, b VARCHAR(10));
-- Expected-Rows: 0
INSERT INTO test.t1 VALUES (1, '1'), (2, '2'), (3, '3');
-- Expected-Rows: 0
CREATE TABLE test.t2 (a INT PRIMARY KEY, b VARCHAR(10));
-- Expected-Rows: 0
INSERT INTO test.t2 VALUES (1, '1'), (2, '2'), (4, '4');
-- Expected-Rows: 2
DATA BRANCH DIFF test.t2 AGAINST test.t1;
+-------------------+--------+------+------+
| diff t2 against t1 | flag | a | b |
+-------------------+--------+------+------+
| t1 | INSERT | 3 | 3 |
| t2 | INSERT | 4 | 4 |
+-------------------+--------+------+------+
-- Expected-Rows: 2
DATA BRANCH DIFF test.t1 AGAINST test.t2;
+-------------------+--------+------+------+
| diff t1 against t2 | flag | a | b |
+-------------------+--------+------+------+
| t1 | INSERT | 3 | 3 |
| t2 | INSERT | 4 | 4 |
+-------------------+--------+------+------+
-- Expected-Rows: 0
DROP TABLE test.t1;
-- Expected-Rows: 0
DROP TABLE test.t2;
Example 2: Compare Branch Tables (With Common Ancestor)¶
-- Expected-Rows: 0
CREATE TABLE test.t0 (a INT PRIMARY KEY, b INT);
-- Expected-Rows: 0
INSERT INTO test.t0 VALUES (1, 1), (2, 2), (3, 3);
-- Expected-Rows: 0
DATA BRANCH CREATE TABLE test.t1 FROM test.t0;
-- Expected-Rows: 0
INSERT INTO test.t1 VALUES (4, 4);
-- Expected-Rows: 0
DATA BRANCH CREATE TABLE test.t2 FROM test.t0;
-- Expected-Rows: 0
INSERT INTO test.t2 VALUES (5, 5);
-- Expected-Rows: 2
DATA BRANCH DIFF test.t2 AGAINST test.t1;
+-------------------+--------+------+------+
| diff t2 against t1 | flag | a | b |
+-------------------+--------+------+------+
| t1 | INSERT | 4 | 4 |
| t2 | INSERT | 5 | 5 |
+-------------------+--------+------+------+
-- Expected-Rows: 0
DROP TABLE test.t0;
-- Expected-Rows: 0
DROP TABLE test.t1;
-- Expected-Rows: 0
DROP TABLE test.t2;
Example 3: Compare Using Snapshots¶
-- Expected-Rows: 0
CREATE TABLE test.t1 (a INT PRIMARY KEY, b INT);
-- Expected-Rows: 0
INSERT INTO test.t1 VALUES (1, 1), (2, 2);
-- Expected-Rows: 0
CREATE SNAPSHOT sp1 FOR TABLE test t1;
-- Expected-Rows: 0
INSERT INTO test.t1 VALUES (3, 3);
-- Expected-Rows: 1
UPDATE test.t1 SET b = 10 WHERE a = 1;
-- Expected-Rows: 0
CREATE SNAPSHOT sp2 FOR TABLE test t1;
-- Expected-Rows: 2
DATA BRANCH DIFF test.t1{SNAPSHOT='sp2'} AGAINST test.t1{SNAPSHOT='sp1'};
+--------------------+--------+------+------+
| diff t1 against t1 | flag | a | b |
+--------------------+--------+------+------+
| t1 | UPDATE | 1 | 10 |
| t1 | INSERT | 3 | 3 |
+--------------------+--------+------+------+
-- Expected-Rows: 0
DROP SNAPSHOT sp1;
-- Expected-Rows: 0
DROP SNAPSHOT sp2;
-- Expected-Rows: 0
DROP TABLE test.t1;
Note
When comparing two snapshots of the same table, the system compares the data images captured at the two snapshot points. Rows are returned in ascending primary-key order: the UPDATE for a=1 (with the new value b=10) appears first, followed by the newly inserted row a=3.
Example 4: Get Only Difference Count¶
-- Expected-Rows: 0
CREATE TABLE test.t1 (a INT PRIMARY KEY, b INT);
-- Expected-Rows: 0
INSERT INTO test.t1 SELECT result, result FROM generate_series(1, 1000) g;
-- Expected-Rows: 0
DATA BRANCH CREATE TABLE test.t2 FROM test.t1;
-- Expected-Rows: 0
INSERT INTO test.t2 SELECT result, result FROM generate_series(1001, 2000) g;
-- Expected-Rows: 100
DELETE FROM test.t2 WHERE a <= 100;
-- Expected-Rows: 1
DATA BRANCH DIFF test.t2 AGAINST test.t1 OUTPUT COUNT;
+----------+
| COUNT(*) |
+----------+
| 1100 |
+----------+
-- Expected-Rows: 0
DROP TABLE test.t1;
-- Expected-Rows: 0
DROP TABLE test.t2;
Example 5: Limit Returned Rows¶
-- Expected-Rows: 0
CREATE TABLE test.t1 (a INT PRIMARY KEY, b INT);
-- Expected-Rows: 0
INSERT INTO test.t1 SELECT result, result FROM generate_series(1, 100) g;
-- Expected-Rows: 0
DATA BRANCH CREATE TABLE test.t2 FROM test.t1;
-- Expected-Rows: 0
INSERT INTO test.t2 SELECT result, result FROM generate_series(101, 200) g;
-- Expected-Rows: 5
DATA BRANCH DIFF test.t2 AGAINST test.t1 OUTPUT LIMIT 5;
+--------------------+--------+------+------+
| diff t2 against t1 | flag | a | b |
+--------------------+--------+------+------+
| t2 | INSERT | 101 | 101 |
| t2 | INSERT | 102 | 102 |
| t2 | INSERT | 103 | 103 |
| t2 | INSERT | 104 | 104 |
| t2 | INSERT | 105 | 105 |
+--------------------+--------+------+------+
-- Expected-Rows: 0
DROP TABLE test.t1;
-- Expected-Rows: 0
DROP TABLE test.t2;
Note
OUTPUT LIMIT returns the first N rows after final primary-key ordering.
Example 6: Export Differences as SQL File¶
-- Expected-Rows: 0
CREATE TABLE test.t1 (a INT PRIMARY KEY, b INT);
-- Expected-Rows: 0
INSERT INTO test.t1 VALUES (1, 1), (2, 2);
-- Expected-Rows: 0
DATA BRANCH CREATE TABLE test.t2 FROM test.t1;
-- Expected-Rows: 0
INSERT INTO test.t2 VALUES (3, 3);
-- Expected-Rows: 1
UPDATE test.t2 SET b = 10 WHERE a = 1;
-- Expected-Rows: 1
DELETE FROM test.t2 WHERE a = 2;
-- Expected-Rows: 1
DATA BRANCH DIFF test.t2 AGAINST test.t1 OUTPUT FILE '/tmp/';
+------------------------------------------------------------------------------------------+-----------------------------------------------+
| FILE SAVED TO | HINT |
+------------------------------------------------------------------------------------------+-----------------------------------------------+
| /tmp/diff_t2_t1_<UTC-YYYYMMDD_HHMMSS>_<UUID>.sql | DELETE FROM `test`.`t1`, INSERT INTO `test`.`t1` |
+------------------------------------------------------------------------------------------+-----------------------------------------------+
-- Expected-Rows: 0
DROP TABLE test.t1;
-- Expected-Rows: 0
DROP TABLE test.t2;
The shown path is a pattern: MatrixOne generates the UTC timestamp and UUID for every invocation. The v4.2 output is a .sql patch containing the required DELETE FROM ... and INSERT INTO ... statements.
Replaying Patch Files¶
Replay SQL file (incremental sync):
mysql -h <mo_host> -P <mo_port> -u <user> -p <db_name> < diff_t2_t1_<UTC-YYYYMMDD_HHMMSS>_<UUID>.sql
Example 6b: Export Differences to Stage (Object Storage)¶
Stage is a logical object in MatrixOne for connecting to external storage (such as S3, HDFS). You can output difference files directly to object storage for cross-cluster/cross-environment data synchronization.
-- Expected-Rows: 0
CREATE STAGE my_stage URL = 's3://my-bucket/diff-output/?region=us-east-1&access_key_id=xxx&secret_access_key=yyy';
DATA BRANCH DIFF test.t2 AGAINST test.t1 OUTPUT FILE 'stage://my_stage/';
+-------------------------------------------------+------------------------------------------+
| FILE SAVED TO | HINT |
+-------------------------------------------------+------------------------------------------+
| stage://my_stage/diff_t2_t1_<UTC-YYYYMMDD_HHMMSS>_<UUID>.sql | DELETE FROM `test`.`t1`, INSERT INTO `test`.`t1` |
+-------------------------------------------------+------------------------------------------+
SELECT load_file(CAST('stage://my_stage/diff_t2_t1_<UTC-YYYYMMDD_HHMMSS>_<UUID>.sql' AS DATALINK));
-- Expected-Rows: 0
DROP STAGE my_stage;
Advantages of using Stage:
Security: No need to expose AK/SK in every SQL statement; administrators configure once
Convenience: Encapsulate complex URL paths into simple object names
Cross-cluster sync: Source writes to object storage, target reads and executes directly
Example 7: Detect Update Operations¶
-- Expected-Rows: 0
CREATE TABLE test.t0 (a INT PRIMARY KEY, b INT, c INT);
-- Expected-Rows: 0
INSERT INTO test.t0 SELECT result, result, result FROM generate_series(1, 100) g;
-- Expected-Rows: 0
DATA BRANCH CREATE TABLE test.t1 FROM test.t0;
-- Expected-Rows: 3
UPDATE test.t1 SET c = c + 1 WHERE a IN (1, 50, 100);
-- Expected-Rows: 0
DATA BRANCH CREATE TABLE test.t2 FROM test.t0;
-- Expected-Rows: 3
UPDATE test.t2 SET c = c + 2 WHERE a IN (1, 25, 75);
-- Compare differences, will detect conflicting updates
-- Expected-Rows: 6
DATA BRANCH DIFF test.t2 AGAINST test.t1;
+--------------------+--------+------+------+------+
| diff t2 against t1 | flag | a | b | c |
+--------------------+--------+------+------+------+
| t2 | UPDATE | 1 | 1 | 3 |
| t1 | UPDATE | 1 | 1 | 2 |
| t2 | UPDATE | 25 | 25 | 27 |
| t1 | UPDATE | 50 | 50 | 51 |
| t2 | UPDATE | 75 | 75 | 77 |
| t1 | UPDATE | 100 | 100 | 101 |
+--------------------+--------+------+------+------+
-- Expected-Rows: 0
DROP TABLE test.t0;
-- Expected-Rows: 0
DROP TABLE test.t1;
-- Expected-Rows: 0
DROP TABLE test.t2;
Example 8: Difference Comparison for Composite Primary Key Tables¶
-- Expected-Rows: 0
CREATE TABLE test.orders (
tenant_id INT,
order_code VARCHAR(8),
amount DECIMAL(12,2),
PRIMARY KEY (tenant_id, order_code)
);
-- Expected-Rows: 0
INSERT INTO test.orders VALUES
(100, 'A100', 120.50),
(100, 'A101', 80.00),
(101, 'B200', 305.75);
-- Expected-Rows: 0
DATA BRANCH CREATE TABLE test.orders_branch FROM test.orders;
-- Make modifications on branch
-- Expected-Rows: 1
UPDATE test.orders_branch SET amount = 130.50 WHERE tenant_id = 100 AND order_code = 'A100';
-- Expected-Rows: 1
DELETE FROM test.orders_branch WHERE tenant_id = 100 AND order_code = 'A101';
-- Expected-Rows: 0
INSERT INTO test.orders_branch VALUES (102, 'C300', 512.25);
-- Compare differences
-- Expected-Rows: 3
DATA BRANCH DIFF test.orders_branch AGAINST test.orders;
+-----------------------------------+--------+-----------+------------+--------+
| diff orders_branch against orders | flag | tenant_id | order_code | amount |
+-----------------------------------+--------+-----------+------------+--------+
| orders_branch | UPDATE | 100 | A100 | 130.50 |
| orders_branch | DELETE | 100 | A101 | 80.00 |
| orders_branch | INSERT | 102 | C300 | 512.25 |
+-----------------------------------+--------+-----------+------------+--------+
-- Expected-Rows: 0
DROP TABLE test.orders;
-- Expected-Rows: 0
DROP TABLE test.orders_branch;
-- Expected-Rows: 0
DROP DATABASE test;
Example 9: COLUMNS projection¶
COLUMNS (col1, ..., colN) returns exactly the requested value columns. Primary-key columns remain part of internal matching and ordering, but appear only when explicitly requested.
DROP DATABASE IF EXISTS data_branch_diff_columns_demo;
CREATE DATABASE data_branch_diff_columns_demo;
USE data_branch_diff_columns_demo;
CREATE TABLE c1 (
id INT PRIMARY KEY,
name VARCHAR(30),
balance DECIMAL(12,2),
created_at TIMESTAMP,
birthday DATE
);
INSERT INTO c1 VALUES
(1, 'alice', 1000.50, '2024-01-01 10:00:00', '1990-03-15'),
(2, 'bob', 2000.75, '2024-01-02 11:00:00', '1985-07-20'),
(3, 'carol', 3000.00, '2024-01-03 12:00:00', '1992-11-08');
DATA BRANCH CREATE TABLE c1_br FROM c1;
UPDATE c1_br SET balance = 1500.50, name = 'alice_v2' WHERE id = 1;
DELETE FROM c1_br WHERE id = 2;
INSERT INTO c1_br VALUES (4, 'dave', 4000.00, '2024-02-01 09:00:00', '1988-12-25');
-- Full diff, all columns.
DATA BRANCH DIFF c1_br AGAINST c1;
-- Project only the "name" column: id is not included in the visible result.
DATA BRANCH DIFF c1_br AGAINST c1 COLUMNS (name);
-- Project two non-PK columns.
DATA BRANCH DIFF c1_br AGAINST c1 COLUMNS (name, balance);
-- Request the PK explicitly when it must appear in the result.
DATA BRANCH DIFF c1_br AGAINST c1 COLUMNS (id, balance);
-- Combine COLUMNS with OUTPUT LIMIT.
DATA BRANCH DIFF c1_br AGAINST c1 COLUMNS (balance) OUTPUT LIMIT 5;
DROP TABLE c1_br;
DROP TABLE c1;
DROP DATABASE data_branch_diff_columns_demo;
Example 10: Linear Chain Diff (Non-Adjacent Branches)¶
DATA BRANCH DIFF works across non-adjacent levels of a linear branch chain (e.g., t0 -> t1 -> t2 -> t3). When diffing t3 against t0, the LCA is resolved to t0 by walking through the intermediate clone edges. The chain shape exercises a different LCA code path than a flat fork. Wrap-around intermediates (t1, t2) may be invisible to the diff: only mutations on t0 and t3 that occurred after the relevant branch points are surfaced.
DROP DATABASE IF EXISTS test_chain_diff;
CREATE DATABASE test_chain_diff;
USE test_chain_diff;
CREATE TABLE t0(a INT PRIMARY KEY, b INT);
INSERT INTO t0 VALUES (1, 1), (2, 2), (3, 3);
DATA BRANCH CREATE TABLE t1 FROM t0;
DATA BRANCH CREATE TABLE t2 FROM t1;
-- Write on leaf t2 only
INSERT INTO t2 VALUES (4, 4), (5, 5);
UPDATE t2 SET b = b + 100 WHERE a = 1;
DELETE FROM t2 WHERE a = 2;
-- Non-adjacent diff: t2 against t0 (LCA = t0)
DATA BRANCH DIFF t2 AGAINST t0 OUTPUT SUMMARY;
-- Adjacent diff: t2 against t1 (LCA = t1)
DATA BRANCH DIFF t2 AGAINST t1 OUTPUT SUMMARY;
-- Reverse direction
DATA BRANCH DIFF t0 AGAINST t2 OUTPUT SUMMARY;
DROP TABLE t2;
DROP TABLE t1;
DROP TABLE t0;
DROP DATABASE test_chain_diff;
Example 11: Multi-Fork Tree Diff¶
DATA BRANCH DIFF works across complex multi-fork branch trees (arbitrary DAG depth). The LCA resolution handles sibling leaves, cousins, cross-subtree pairs, and pairs at different depths. Each diff pair exercises a structurally distinct cross-section of the tree. The following is abbreviated pseudocode, not a directly executable SQL script: nodes t3 through t18 are intentionally omitted. See test/distributed/cases/git4data/branch/diff/diff_13.sql in the MatrixOne source tree for the complete executable setup.
Tree shape (4 levels, 19 nodes):
t0 (root)
/ | \\
t1 t2 t3 (level 2)
/ \\ | / \\
t4 t5 t6 t7 t8 (level 3)
/ \\ / \\ / \\ / \\ / \\
t9 t10 t11 t12 t13 t14 t15 t16 t17 t18 (level 4, 10 leaves)
DROP DATABASE IF EXISTS test_tree_diff;
CREATE DATABASE test_tree_diff;
USE test_tree_diff;
CREATE TABLE t0(a INT PRIMARY KEY, b INT);
INSERT INTO t0 SELECT *, * FROM generate_series(1, 20) g;
-- Build tree top-down with IUD on each node
DATA BRANCH CREATE TABLE t1 FROM t0;
INSERT INTO t1 VALUES (101, 101);
UPDATE t1 SET b = 10000 WHERE a = 1;
DATA BRANCH CREATE TABLE t2 FROM t0;
INSERT INTO t2 VALUES (102, 102);
UPDATE t2 SET b = 20000 WHERE a = 2;
-- Pseudocode: create t3, t4-t8, and leaves t9-t18 as shown in diff_13.sql.
-- Leaf vs root: skip 3 edges
DATA BRANCH DIFF t9 AGAINST t0 OUTPUT SUMMARY;
-- Leaf vs sibling leaf: share grandparent
DATA BRANCH DIFF t9 AGAINST t10 OUTPUT SUMMARY;
-- Leaf vs cousin leaf: share great-grandparent
DATA BRANCH DIFF t9 AGAINST t11 OUTPUT SUMMARY;
-- Leaf vs cross-subtree cousin: opposite subtrees
DATA BRANCH DIFF t9 AGAINST t13 OUTPUT SUMMARY;
-- Reverse-direction deep cross-subtree pair
DATA BRANCH DIFF t18 AGAINST t9 OUTPUT SUMMARY;
DROP DATABASE test_tree_diff;
Note
The full tree construction and diff pairs are shown in the test suite. The key properties are:
LCA resolution works for any pair of nodes regardless of depth difference.
Diffs are mirror images when reversing direction.
Snapshot-scoped chain diffs replay at specific time points on each side.
The DAG walk is stable at arbitrary depths (depth 3 and beyond).
Notes¶
Schema evolution compatibility: DIFF accepts schema evolution only when column identity and key semantics remain provable. The following matrix applies to both DIFF and MERGE; for MERGE, the source table is merged into the destination table.
Schema change
DIFF/MERGE behavior
Pure column reorder with unchanged identities and attributes
Supported
Column rename with lineage that MatrixOne can prove
Supported
Target/source-only visible column with an explicit primary key and compatible definition
Supported; DIFF includes it, while MERGE writes only columns shared with the destination
A source/base column is missing from the target
Rejected
Drop and add a column with the same name (new identity)
Rejected
Type, nullability, generated-column definition, or primary-key mismatch
Rejected
Target-only column on a table that uses a hidden fake primary key
Rejected
A destination table named by
OUTPUT ASis a new ordinary table and is not part of this schema-compatibility check.Primary Key Requirement: Although tables without primary keys are supported, it is recommended to use tables with primary keys for more accurate difference results.
Performance Considerations: For large tables, difference comparison may take a long time. It is recommended to use
OUTPUT COUNTfirst to understand the scale of differences.Snapshot Validity: When comparing using snapshots, ensure the snapshots exist and are valid.
Output File: For a local path, MatrixOne creates missing parent directories with
MkdirAllwhen the service process has permission; the resulting path must be writable. Each generated SQL filename includes a UTC timestamp and UUID and can be replayed to synchronize data.LCA Detection: The system automatically detects LCA without manual specification. The existence of LCA affects how differences are calculated.