morningman opened a new issue, #68742: URL: https://github.com/apache/doris/issues/68742
### Search before asking - [x] I had searched in the [issues](https://github.com/apache/doris/issues?q=is%3Aissue) and found no similar issues. ### Version master @ 7ac0eb2fdb4 (2026-10-04). The IVM code used by the reproduction below is identical to this commit. ### What's Wrong? An IVM materialized view whose select list wraps an aggregate result in an expression, for example `SUM(v) * 100`, is accepted by `CREATE MATERIALIZED VIEW ... REFRESH INCREMENTAL`, and its first `COMPLETE` refresh succeeds. Every later incremental refresh fails: ```text IVM incremental refresh failed for mv=mv_expr_over_agg, reason=PLAN_REWRITE_FAILED, detail=IVM failed to find slot: sum(v) ``` A strict `REFRESH ... INCREMENTAL` task fails, and `REFRESH ... INCREMENTAL FALLBACK` falls back to `COMPLETE` on every run (`IvmFallbackReason = PLAN_REWRITE_FAILED`), so the MV is never maintained incrementally. ### What You Expected? Either the definition is maintained incrementally, or `CREATE MATERIALIZED VIEW ... REFRESH INCREMENTAL` rejects it at creation time, as it already does for other unsupported shapes (for example `HAVING`, which fails with `IVM aggregate must be the top-level operator`). Today it creates an MV whose incremental refresh can never succeed. ### How to Reproduce? FE configured with `enable_feature_binlog = true` and `enable_table_stream = true`. ```sql CREATE TABLE t ( k INT, g VARCHAR(16), v INT ) UNIQUE KEY(k) DISTRIBUTED BY HASH(k) BUCKETS 1 PROPERTIES ( "replication_num" = "1", "enable_unique_key_merge_on_write" = "true", "binlog.enable" = "true", "binlog.format" = "ROW", "binlog.need_historical_value" = "true" ); INSERT INTO t VALUES (1, 'a', 10), (2, 'a', 20), (3, 'b', 30); CREATE MATERIALIZED VIEW mv_expr_over_agg BUILD DEFERRED REFRESH INCREMENTAL ON MANUAL DISTRIBUTED BY RANDOM BUCKETS 1 PROPERTIES ("replication_num" = "1") AS SELECT g, SUM(v) * 100 AS s100 FROM t GROUP BY g; REFRESH MATERIALIZED VIEW mv_expr_over_agg COMPLETE; -- SUCCESS INSERT INTO t VALUES (4, 'b', 40); REFRESH MATERIALIZED VIEW mv_expr_over_agg INCREMENTAL; -- FAILED, PLAN_REWRITE_FAILED SELECT Status, RefreshMode, IvmFallbackReason, ErrorMsg FROM tasks('type'='mv') WHERE MvName = 'mv_expr_over_agg' ORDER BY CreateTime DESC LIMIT 1; ``` ```text +--------+-------------+---------------------+----------------------------------------------------------------------------------------------------------------------------+ | Status | RefreshMode | IvmFallbackReason | ErrorMsg | +--------+-------------+---------------------+----------------------------------------------------------------------------------------------------------------------------+ | FAILED | \N | PLAN_REWRITE_FAILED | IVM incremental refresh failed for mv=mv_expr_over_agg, reason=PLAN_REWRITE_FAILED, detail=IVM failed to find slot: sum(v) | +--------+-------------+---------------------+----------------------------------------------------------------------------------------------------------------------------+ ``` `REFRESH MATERIALIZED VIEW mv_expr_over_agg INCREMENTAL FALLBACK` then succeeds with `RefreshMode = COMPLETE` and `IvmFallbackReason = PLAN_REWRITE_FAILED`, and keeps doing so on every later refresh. ### Anything Else? Same steps (baseline `COMPLETE`, insert one row, strict `INCREMENTAL`) with other select lists: | Select list | Incremental refresh | |---|---| | `SUM(v) * 100`, `CAST(SUM(v) AS DOUBLE)`, `SUM(v) / COUNT(*)` | fails: `IVM failed to find slot: sum(v)` | | `COUNT(v) + 1` | fails: `IVM failed to find slot: count(v)` | | `MIN(v) * 2`, `MAX(v) + 1` | fails: `IVM failed to find slot: min(v)` / `max(v)` | | `ARRAY_SIZE(COLLECT_LIST(v))` | fails: `IVM failed to find slot: collect_list(v)` | | `COUNT(*) * 2`, `AVG(v) * 2`, `ROUND(AVG(v), 2)`, `BITMAP_UNION_COUNT(TO_BITMAP(v)) + 0` | OK | | `SUM(v) AS s, SUM(v) * 100 AS s100` (the bare aggregate is selected as well) | OK | | `SUM(v * 100)` (the expression is inside the aggregate) | OK | | `UPPER(g)` over a `GROUP BY g` key | OK | The failing functions are the ones whose visible MV column holds the aggregate state itself (`SUM`, `COUNT(expr)`, `MIN`, `MAX`, `COLLECT_LIST`). `COUNT(*)`, `AVG` and `BITMAP_UNION_COUNT` are maintained through hidden state columns and are not affected. The apply step appears to resolve the MV column by the aggregate's generated name (`sum(v)`; the message comes from `findSlotByName`), and that column does not exist once the aggregate is wrapped in an expression. ### Are you willing to submit PR? - [ ] Yes I am willing to submit a PR! ### Code of Conduct - [x] I agree to follow this project's [Code of Conduct](https://www.apache.org/foundation/policies/conduct) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
