Antalya 26.1 - Add ALTER TABLE MODIFY SETTING support for Hybrid watermarks #1659
Antalya 26.1 - Add ALTER TABLE MODIFY SETTING support for Hybrid watermarks #1659zvonand merged 4 commits intoantalya-26.1from
Conversation
Introduce hybridParam('name', 'type') pseudo-function for Hybrid engine
predicates, allowing segment boundaries to be changed at runtime via
ALTER TABLE ... MODIFY SETTING without recreating the table.
Key design decisions:
- hybridParam() takes exactly two arguments (name, type); all values
must be provided via ENGINE SETTINGS, keeping the API surface minimal
and eliminating default-value complexity.
- Watermark names must start with 'hybrid_watermark_' and exactly match
a declared hybridParam() in the predicates. Typos in both CREATE
SETTINGS and ALTER are rejected.
- Values are validated against the declared type at CREATE and ALTER
time, so invalid values never reach the runtime substitution path.
- Only hybrid_watermark_* settings are allowed on Hybrid tables;
regular DistributedSettings and RESET SETTING are rejected.
- Runtime watermark state uses MultiVersion<std::map> for lock-free
reads and deterministic serialization order in SHOW CREATE TABLE.
- In StorageDistributed::alter(), the watermark snapshot is published
before in-memory metadata to prevent concurrent readers from
observing new metadata with stale watermark values.
- Predicate validation at CREATE time substitutes the effective
SETTINGS value (not the type default) so value-sensitive expressions
are checked against realistic data.
Tests:
- Stateless tests covering CREATE, ALTER, DETACH/ATTACH persistence,
multi-watermark, type conflict, invalid values, typo rejection,
RESET SETTING rejection, and DistributedSettings rejection.
- Integration tests covering single-node, cross-node, and cluster()
table function flows, each self-contained with own setup/teardown.
Documentation updated with hybridParam() syntax, ALTER examples,
multi-watermark usage, and restriction notes.
Made-with: Cursor
|
AI audit note: This review comment was generated by AI (gpt-5.4). Audit update for PR #1659 (ALTER TABLE MODIFY SETTING support for Hybrid watermarks): Confirmed defects:Medium: ALTER MODIFY SETTING skips full predicate revalidation Example: CREATE TABLE t
ENGINE = Hybrid(
remote('localhost:9000', currentDatabase(), 'hot'),
dateDiff(hybridParam('hybrid_watermark_unit', 'String'), ts, now()) < 30,
remote('localhost:9000', currentDatabase(), 'cold'),
dateDiff(hybridParam('hybrid_watermark_unit', 'String'), ts, now()) >= 30
)
SETTINGS hybrid_watermark_unit = 'day'
AS hot;This CREATE should pass because But this ALTER is currently accepted too: ALTER TABLE t MODIFY SETTING hybrid_watermark_unit = 'banana';ALTER only validates that dateDiff('banana', ts, now()) < 30which is semantically invalid for Coverage summary: |
|
The above comment is a very good point by FWIW the previous |
|
Kinda work with ALIAS column, but it's not smart enough to correctly recognize (_table = xxxx AND ....) OR (_table = yyy AND ....) https://fiddle.clickhouse.com/c667b318-1b36-45e7-ad14-b6db1fb55ff7 |
Usability Audit: ALTER TABLE MODIFY SETTING for Hybrid watermarks (PR #1659)Scope: Summary of dedup vs PR commentsBefore filing, every issue below was checked against the full PR thread (
Other PR-thread items noted but not listed above:
Primary flows (ranked by expected usage)
IssuesFlow 2: Runtime watermark modification2.1 ALTER accepts a watermark value that makes the predicate semantically invalid; next read failsStatus: already raised (AI
2.2 Failure from a bad ALTER surfaces as a cryptic function-level error on readStatus: new in this audit. Not in PR comments.
2.3 Once set, a watermark cannot be removed except by recreating the tableStatus: new in this audit. Not in PR comments.
Flow 1: Default Hybrid with watermark (create + SELECT)1.1 Read path indexes
|
|
I have an update on The premise
The first half is correct: CREATE does run Why
|
|
@alsugiliazova I'll try to briefly address all of the found bulletpoints in your report. As sources, I used discussions with Misha and summaries of planning in Cursor.
See the explanation above. At this point it's going to probably stay as a known limitation.
This should probably also stay as a known limitation for now due to CH implementation limitations.
This should be fine as this ultimately changes the table itself. In that case it should be re-created from scratch.
Fixed
Fixed
This is quite a significant change outside the scope of this PR, I would leave it as-is for now.
It's quite simple to implement, but the change would be within several hundreds lines of new code. I would personally defer it to a follow-up PR for the next refresh. If strongly needed, I can implement it here. But I doubt it considering the Low priority of the issue in the report.
This is also fine since it requires changing a predicate and hence the whole table. |
|
Verification report: Altinity/ClickHouse PR #1659PR #1659 CI triageSummary
Flakiness and “related to PR #1659?” (
|
| Failing item | Window / scope | Stats | Related to PR #1659? |
|---|---|---|---|
test_storage_delta/test_cdf.py::test_cdf[] (Integration amd_asan family: check_name LIKE 'Integration tests (amd_asan%') |
gh-data.checks, last 60d |
17 FAIL, 250 OK → ~6.4% of outcomes FAIL; failures spread across 69 distinct pull_request_number values; PR 0: 9 FAILs; PR 1659: 1 FAIL |
No — not PR-specific. Same test fails routinely on branch/PR 0 and other PRs. |
test_storage_delta/test_cdf.py::test_cdf[] |
play.clickhouse.com default.checks, last 30d |
28 FAIL, 24609 OK, 4679 SKIPPED |
No — upstream history is low-rate but non-zero FAIL, consistent with flake. |
test_export_replicated_mt_partition_to_object_storage/test.py::test_concurrent_exports_to_different_targets |
gh-data.checks, last 60d |
14 FAIL, 880 OK → ~1.6% FAIL rate; PR 0: 4 FAILs; other PRs (e.g. 1390, 1517) multiple FAILs; PR 1659: 1 FAIL |
Unlikely — not PR-specific (same pattern on 0 and unrelated PRs). Optional: read log once because PR touches StorageDistributed (overlap only; history does not implicate 1659). |
BuzzHouse (amd_debug) |
gh-data.checks, last 60d |
58 rows with test_status = 'FAIL' vs 132 total rows in quick aggregate; PR 0: 9 FAILs (by-PR breakdown); PR 1659: 1 FAIL (test_name = Unknown error in DB) |
No — typical fuzzer / debug noise shared across many PRs; not evidence Hybrid caused it without the artifact error string. |
Stateless tests (amd_tsan, s3 storage, parallel, 2/2) (job row: empty test_name) |
gh-data.checks, last 60d |
check_status = error: 14 vs success: 52 on job-level rows → ~21% job error rate |
No — infrastructure / timeout class, not a deterministic “this PR broke one test” signal. |
Plain-language summary: Failing jobs are not shown to be caused by PR #1659 when measured against months of CI database history; they align with pre-existing flakiness, BuzzHouse noise, and infra timeouts. A rerun remains reasonable because the HTML report can still mark tests “new vs base” for a single run.
Introduce
hybridParam('name', 'type')pseudo-function for Hybrid enginepredicates, allowing segment boundaries to be changed at runtime via
ALTER TABLE ... MODIFY SETTINGwithout recreating the table.Key design decisions:
hybridParam()takes exactly two arguments (name,type); all valuesmust be provided via ENGINE SETTINGS, keeping the API surface minimal
and eliminating default-value complexity.
'hybrid_watermark_'and exactly matcha declared
hybridParam()in the predicates. Typos in bothCREATE SETTINGSandALTERare rejected.CREATEand ALTERtime, so invalid values never reach the runtime substitution path.
regular DistributedSettings and RESET SETTING are rejected.
reads and deterministic serialization order in SHOW CREATE TABLE.
before in-memory metadata to prevent concurrent readers from
observing new metadata with stale watermark values.
SETTINGS value (not the type default) so value-sensitive expressions
are checked against realistic data.
Example:
Syntax sugar:
Changelog category (leave one):
Changelog entry (a user-readable short description of the changes that goes to CHANGELOG.md):
Added support for moving Hybrid table watermarks
CI/CD Options
Exclude tests:
Regression jobs to run: