Conversation
Signed-off-by: Andrew Xie <dev@xie.is>
27e2460 to
c5a11a6
Compare
…able-drop-partition
Signed-off-by: Andrew Xie <dev@xie.is>
4591889 to
953220d
Compare
CI triage for #2361 @
|
| Check | Result |
|---|---|
GrypeScanKeeper / Grype Scan (altinityinfra/clickhouse-keeper) |
fail — 1 high/critical |
GrypeScanServer (-alpine) / Grype Scan (altinityinfra/clickhouse-server:…-alpine) |
fail — 1 high/critical |
Both images fail on the same single High vulnerability, CVE-2026-85091 (an nvd:cpe match; the only other finding, CVE-2025-60876, is Medium and passes the threshold). Evidence it is not caused by this PR:
- The diff is C++ source + one test only —
src/Storages/ObjectStorage/DataLakes/Iceberg/*,StorageObjectStorage.*,IDataLakeMetadata.h, andtests/integration/.../test_drop_partition.py. NoDockerfile, no dependency/package manifest, no base-image change. Grype scans OS/runtime packages baked into the image, which this PR does not touch. - A fresh 2026 CVE.
CVE-2026-85091was published essentially now (today is 2026-09-23), so it lights up on every image built after the grype DB picked it up — independent of source changes. - Reproduces on an unrelated PR. Sibling PR Iceberg: reuse the Puffin object metadata across deletion-vector reads #2419 (Iceberg Puffin, no shared code) shows the identical two failures with the same "1 high/critical" message. Notably its ubuntu-based
clickhouse-serverimage passes with 0 high/critical — i.e. the CVE lives in the keeper + alpine base images, not in anything either PR wrote.
Suggested action: nothing to change in this PR. This is resolved at the CI/base-image level by Altinity infra — patch/rebuild the keeper and alpine base images, or add CVE-2026-85091 to the grype ignore list once triaged. Re-running the job won't clear it until the base image is updated, and it should not block review/merge of the code change.
Everything else so far: green
Finished and passing: Fast test (0 failed / 9392 passed), all Builds (amd debug/asan_ubsan/binary/release, arm release), Unit tests (asan_ubsan: 0/14839), Stateless (amd_debug parallel 0/11130; amd_asan_ubsan distributed-plan parallel 1/2 0/5550), both AST fuzzer (targeted) jobs, Integration tests (amd_asan_ubsan, targeted), Docker server/keeper images, Source upload.
PR workflow is still running — many jobs are PENDING/RUNNING (remaining Stateless shards, Integration db disk / old analyzer 1–8, Stress tests, Compatibility check, SQLLogic/SQLStorm, the RegressionTestsRelease / Iceberg regression suite, Finish Workflow). No functional failures have appeared yet, but the run isn't complete — worth a final glance once it settles, especially the Iceberg regression + integration jobs given what this PR changes.
— @blau-ai (analysis only; CI is the source of truth since I can't build/run ClickHouse here)
CI Failures AnalysisRun 35903013423, commit Related to this PRNone. Pre-existing Flaky Tests (Unrelated)
Infrastructure Issues (Unrelated)
Already-known broken tests (jobs stayed green)
Issue/Fix References
|
|
Regression tests for On REST, every scenario passed except format version 3. The suite's REST catalog rejects v3, so Spark never creates the table. On Glue that scenario is skipped for the same reason. On both catalogs the drop left the expected rows: identity and day partitions, a tuple key, an empty partition, purge on and off, IcebergS3 with no catalog, a mixed manifest, and a file written under a finer spec. Rejections also matched: unpartitioned tables, Glue scenarios that then read The new scenarios are skipped in clickhouse-regression until this is in a released build. CI failures are unrelated. Waiting on @arthurpassos for dev review. |
|
AI audit note: This review comment was generated by AI. Audit update for PR #2361 (Iceberg Confirmed defects: High: Partial manifest rewrite turns
High: A failed catalog commit deletes the manifest list the new metadata already names
Medium:
Medium: Successful drop leaves the cached “latest metadata” pointer on the pre-drop snapshot
Coverage summary:
|
|
@DimensionWieldr @xieandrew is it ready for review tho? I see "WIP: Add support for purging data files (physically delete)" |
|
@arthurpassos Yes it is ready for review. Sorry, forgot to update the description. |
arthurpassos
left a comment
There was a problem hiding this comment.
There is one fundamental issue I would like to discuss before proceeding with the review:
AFAIK, ClickHouse has two ways to drop partitions: by id and by value. By id is very simple, you provide the partition id and that is it. The value one is interesting, and is the one supported in this PR.
In ClickHouse MergeTree tables, the "value" for the drop partition is the value of each element of a partition expression tuple after it has gone through the "transforms".
You've implemented the opposite. On yours, you are required to provide the source values present in the columns.
For example:
CREATE TABLE xie_test
(
`id` UInt32,
`event_date` DateTime64
)
ENGINE = MergeTree
PARTITION BY (id, toYYYYMM(event_date))
INSERT INTO xie_test VALUES (1, now());
In the ClickHouse idiom, to drop such a partition by value you would do:
ALTER TABLE xie_test DROP PARTITION (1, toYYYYMM(now()))
On the other hand, with your implementation, you'd have to provide the raw source values.
ALTER TABLE xie_test DROP PARTITION (1, now())
I think both approaches have its pros and cons, but I would vote for keeping it consistent with MergeTree unless this is a limitation of Iceberg (tho I don't see how it could be).
Also, it would be great if you could add docs.
|
|
||
| /// Find the partition spec object with the given spec-id inside a metadata JSON document. | ||
| /// Throws METADATA_MISMATCH if the spec is not found (indicates metadata/spec-id mismatch). | ||
| Poco::JSON::Object::Ptr lookupPartitionSpec(const Poco::JSON::Object::Ptr & meta, Int64 spec_id) |
There was a problem hiding this comment.
Interesting to see this function being reused
| "Schema with id {} not found in table metadata", schema_id); | ||
| } | ||
|
|
||
| using PartitionSpecSignature = std::vector<std::pair<Int32, String>>; |
There was a problem hiding this comment.
Nit: I would say create a struct.
struct PartitionTerm
{
Int32 column_id;
String transform;
};
| auto metadata_object = getMetadataJSONObject(metadata_path, object_storage, persistent_components.metadata_cache, context, log, compression_method, persistent_components.table_uuid); | ||
|
|
||
| if (!metadata_object->has(f_current_snapshot_id)) | ||
| throw Exception(ErrorCodes::BAD_ARGUMENTS, "No snapshot exists for this Iceberg table"); |
There was a problem hiding this comment.
Is this really a bad_arguments error?
There was a problem hiding this comment.
Maybe it can just succeed with a no-op (and log info)? This doesn't mean the table is in an invalid state, there's just no data files yet. A non-empty table that doesn't match any files for drop partition already is a no-op right now.
There was a problem hiding this comment.
Hm.. I would say copy ClickHouse MergeTree behavior. What happens if we try to drop a partition that does not exist on MergeTree tables? If it is no-op, make this one no-op as well.
There was a problem hiding this comment.
Yes, MergeTree is a no-op as well
|
|
||
| const Int64 current_snapshot_id = metadata_object->getValue<Int64>(f_current_snapshot_id); | ||
| if (current_snapshot_id < 0) | ||
| throw Exception(ErrorCodes::BAD_ARGUMENTS, "No snapshot exists for this Iceberg table"); |
There was a problem hiding this comment.
| const Int32 format_version = metadata_object->getValue<Int32>(f_format_version); | ||
| if (format_version < 2) | ||
| throw Exception(ErrorCodes::SUPPORT_IS_DISABLED, "DROP PARTITION is supported only for Iceberg format version 2 and above"); | ||
|
|
||
| if (format_version >= 3) | ||
| throw Exception(ErrorCodes::SUPPORT_IS_DISABLED, | ||
| "DROP PARTITION is not supported for Iceberg format version {}. Dropping Puffin deletion vectors " | ||
| "is not implemented yet", format_version); |
There was a problem hiding this comment.
Perhaps just if (format_version != 2) { throw...
It might confuse users because you state it is only supported for version 2 and above, but then version 3 doesn't work.
| const auto target_partition_key = evaluateTargetPartitionKey(partitioner, partition_source_header, source_values); | ||
|
|
||
| LOG_INFO(log, "Iceberg DROP PARTITION requested for partition {} of spec {}", | ||
| dumpPartitionTuple(target_partition_key), partition_spec_id); |
There was a problem hiding this comment.
You call dumpPartitionTuple several times, do it only once
I can add support for dropping partition by id, but is the partition id for Iceberg tables actually exposed anywhere that the user would be able to know? It looks like
I agree that it should be consistent if possible. I'll change it and make sure the correct function for each transform from source -> iceberg partition format is documented somewhere. |
No need to, I was just putting context in the message. The real issue to be tackled is the below:
|
|
Is there a simpler way to pass a function in a single value partition? It looks like a bare function only works in a partition tuple, so I found |
Signed-off-by: Andrew Xie <dev@xie.is> - DELETED entries in partial manifests are now omitted, so they can't be turned back into live files - Failed catalog commit doesn't delete manifest list or leave orphaned files - Fix stale cache for latest metadata - Iceberg table with no snapshot now no-ops instead of throwing an exception to match MergeTree - A failure when purging data files now logs all the paths that could still exist
Signed-off-by: Andrew Xie <dev@xie.is> - Also remove a failed test that pyiceberg can't produce the right conditions for
d0cf3cf to
1407255
Compare
Changelog category (leave one):
Changelog entry (a user-readable short description of the changes that goes to CHANGELOG.md):
Adds support for
ALTER TABLE <table> DROP PARTITION <id>for Iceberg tables.Documentation entry for user-facing changes
Adds support for
ALTER TABLE <table> DROP PARTITION <id>for Iceberg tables. This resolves the correct partition to remove and writes a new Iceberg snapshot with the matching data files excluded.Data files are physically deleted if the option iceberg_delete_data_on_drop is enabled.
CI/CD Options
Exclude tests:
Regression jobs to run:
Closes #1046