ClickHouse / ClickHouse/ClickHouse
Row policy on the shard-local table is bypassed with `serialize_query_plan = 1` on a non-local replica
- Dominant language
- C++
- Stars
- 49.9k
- Forks
- 9k
- Avg merge
- 21h 32m
- Merged PRs (30d)
- 515
Description
🕵 **Describe the bug**
With `serialize_query_plan = 1`, a read shipped to a non-local replica of a `Distributed` table bypasses the row policy defined on the shard-local table: the receiving server deserializes an already-built read plan, so it never applies its own row policies. With `serialize_query_plan = 0` (text shipping) the same query is filtered correctly.
This matters because defining the policy on the underlying local table is the documented way to filter reads that go through a `Distributed` table (`docs/en/sql-reference/statements/create/row-policy.md`), so the workaround silently returns unfiltered rows in this mode.
**How to reproduce**
Version: 26.8.1.1 (reproduced on `master`, commit `bde560d7b00`).
Server config: a cluster `self` with one replica pointing back at the server itself, and `1`.
```sql
CREATE TABLE rp_leaf (x UInt32, y UInt32) ENGINE = MergeTree ORDER BY x;
INSERT INTO rp_leaf SELECT number, number FROM numbers(10);
CREATE TABLE rp_dist AS rp_leaf ENGINE = Distributed('self', currentDatabase(), rp_leaf);
CREATE ROW POLICY rp_l ON rp_leaf FOR SELECT USING y < 5 TO CURRENT_USER;
SELECT count() FROM rp_dist SETTINGS prefer_localhost_replica = 0, serialize_query_plan = 0; -- 5, correct
SELECT count() FROM rp_dist SETTINGS prefer_localhost_replica = 0, serialize_query_plan = 1; -- 10, policy skipped
SELECT count() FROM rp_leaf; -- 5, correct
```
**Expected behavior**
Both remote reads return `5`. Either the shipped plan carries the filter, or the receiving server re-applies its local row policies to the deserialized plan, or plan shipping is refused when the shard-local table has a row policy that applies (fail close).
**Additional context**
Two stateless tests already pin `serialize_query_plan = 0` for exactly this reason:
- `tests/queries/0_stateless/04498_row_policy_role_scope_interserver.sh`
- `tests/queries/0_stateless/04652_nested_merge_prewhere_type_mismatch.sql` (added by https://github.com/ClickHouse/ClickHouse/pull/112326)
Related: https://github.com/ClickHouse/ClickHouse/pull/112326
Contributor guide
Assessment
This issue has not been assessed yet.