dolthub / dolthub/dolt

Merge silently picks one expression when branches add the same generated column with different AS(...) definitions

Open
#11,367 0 comments 0 reactions 0 assignees View on GitHub
bug merge sql
Dominant language
Go
Stars
24.4k
Forks
873
Avg merge
1d 5h
Merged PRs (30d)
108

Description

### Description

When both branches add the **same-named generated column** with **different expressions**, a three-way merge succeeds with zero conflicts and silently keeps **ours**. The final table uses one expression only; the other is discarded with no schema conflict.

That means computed query results can change after a “clean” merge without any signal that the branches disagreed about the formula. For merge purposes, the generated expression should participate in schema conflict detection (same as any other divergent column definition), not only the column name / type prefix.

Related: #11362 (generated expression left invalid after rename), #11363 (plain vs generated same-name panic).

### Reproduction

```sh
dolt init --name oracle --email oracle@test

dolt sql <<'SQL'
CREATE TABLE t(id INTEGER PRIMARY KEY, a INT);
INSERT INTO t VALUES (1, 10);
CALL dolt_commit('-Am', 'ancestor');
CALL dolt_branch('feat');

CALL dolt_checkout('feat');
ALTER TABLE t ADD COLUMN computed INT AS (a * 2) VIRTUAL;
CALL dolt_commit('-Am', 'feat_expr');

CALL dolt_checkout('main');
ALTER TABLE t ADD COLUMN computed INT AS (a * 3) VIRTUAL;
CALL dolt_commit('-Am', 'main_expr');

CALL dolt_merge('feat');
SELECT * FROM dolt_schema_conflicts;
SELECT * FROM dolt_merge_status;
SHOW CREATE TABLE t;
SELECT id, a, computed FROM t;
SQL
```

### Observed

- Merge returns success (`conflicts = 0`).
- `dolt_schema_conflicts` is empty; merge status is not active.
- Final definition keeps **main’s** expression, e.g. `GENERATED ALWAYS AS ((a * 3))`.
- `SELECT` yields `computed = 30` for `a = 10`.

Same outcome if one side uses short `AS (...)` form and the other uses `GENERATED ALWAYS AS (...)` with a different body.

### Expected

A **schema conflict** on `t` / `computed` (or equivalent refusal to auto-merge), so the user must choose which expression wins. Divergent formulas should not be treated as merge-equivalent solely because both columns are generated with the same name/type.

### Notes

- Syntax variants that are **semantically identical** (e.g. `AS (a * 2) VIRTUAL` vs `GENERATED ALWAYS AS (a * 2) VIRTUAL`) can still auto-merge.
- DoltLite currently mirrors this silent ours-wins behavior for Dolt oracle parity (`generated_both_add_different_expression_ours_wins` in doltlite). Fixing Dolt first would let DoltLite follow.

### Impact

Silent selection of one formula after a clean merge can make merged data look valid while producing incorrect computed values; the chosen schema is committed and history looks conflict-free.

Contributor guide

No contributing guide indexed for this repository

Research direction

Reproduce the merge with the provided SQL, then trace Dolt's schema-merge handling for generated columns and schema conflicts. Use DoltLite's generated_both_add_different_expression_ours_wins test as a parity reference. Done means divergent generated expressions produce a schema conflict, while semantically identical syntax variants still auto-merge.

Written by the indexing model from the issue text.

Assessment

Tech stack
go, sql
Domain
databases
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.