Skip to content

ALTER TABLE UPDATE freezes transitive MATERIALIZED columns at INSERT-time value (regression from #99281) #100613

@zlareb1

Description

@zlareb1

Description

PR #99281 introduced && affected_materialized.contains(column.name) at line 863 of MutationsInterpreter.cpp to avoid recalculating MATERIALIZED columns that depend on EPHEMERAL columns (which cannot be read from disk during mutations). However, this guard also silently skips transitively-dependent MATERIALIZED columns, freezing them at their INSERT-time value permanently.

How to reproduce

CREATE TABLE t_transitive (
    x Int32,
    m1 Int32 MATERIALIZED x + 1,
    m2 Int32 MATERIALIZED m1 + 1
) ENGINE = MergeTree ORDER BY tuple();

INSERT INTO t_transitive (x) VALUES (10);
-- m1=11, m2=12

SET mutations_sync = 1;
ALTER TABLE t_transitive UPDATE x = 20 WHERE 1;
ALTER TABLE t_transitive UPDATE x = 30 WHERE 1;

SELECT x, m1, m2 FROM t_transitive;
-- Returns:  30  31  12   ← m2 frozen at INSERT-time value
-- Expected: 30  31  32   (or at minimum 30  31  22 as before #99281)

Behavior before and after #99281

After mutation UPDATE x=30 x m1 m2
Before #99281 30 31 22 (recalculated each mutation using current on-disk m1)
After #99281 30 31 12 (frozen at INSERT-time, never recalculated again)

Before #99281, m2 was recalculated on every mutation (using the pre-stage m1 value — a pre-existing issue tracked in #50237). After #99281, m2 is never recalculated at all because m1 is not in updated_columns, so it never appears in affected_materialized, so the guard skips it.

Root cause

In MutationsInterpreter::prepare, affected_materialized is built from direct dependencies only (updated_columns → materialized columns). The new guard at line 863:

if (column.default_desc.kind == ColumnDefaultKind::Materialized
    && affected_materialized.contains(column.name))  // ← regression

was intended to exclude ephemeral-dependent MATERIALIZED columns from recalculation (which is correct — they cannot be recalculated from disk). But it also excludes all transitively-dependent MATERIALIZED columns that don't directly depend on an updated regular column.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    potential bugTo be reviewed by developers and confirmed/rejected.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions