Skip to content

fix(connector): iceberg dummy partition for every data - #3860

Open
ashudeqode wants to merge 3 commits into
apache:masterfrom
Alfred-hq:fix/iceberg-partition-issue
Open

fix(connector): iceberg dummy partition for every data#3860
ashudeqode wants to merge 3 commits into
apache:masterfrom
Alfred-hq:fix/iceberg-partition-issue

Conversation

@ashudeqode

@ashudeqode ashudeqode commented Aug 11, 2026

Copy link
Copy Markdown

Which issue does this PR address?
Closes #3853

Rationale
The Iceberg sink's write_data function had three critical bugs that caused all records to land in a single fake partition, regardless of the table's actual partition spec. Partition values were hardcoded to dummy zeros (e.g., Int(0), String("")), the partition spec was built from scratch as empty instead of read from table metadata, and there was no fan-out logic to route records from a mixed-partition batch to separate data files.

What changed?
The sink was populating a PartitionKey with static zero-value literals and pairing it with a newly-built empty PartitionSpec, so every record — regardless of its actual partition column values — was written under a single dummy partition (e.g., year=1970).

Now the sink reads the real partition spec from table.metadata().default_partition_spec(). For unpartitioned tables, the writer is built with None partition key (unchanged write path, zero overhead). For partitioned tables, a RecordBatchPartitionSplitter evaluates the table's partition transforms (day(), bucket(), identity(), etc.) against each Arrow RecordBatch, and a FanoutWriter fans records out to per-partition DataFileWriter instances. primitive_type_to_literal and get_partition_type_value were removed as dead code.

Local Execution
Passed: tested with a local iggy-connect runtime writing to a partitioned Iceberg table (REST catalog)
Verified that records with different partition values land in separate Parquet files under correct partition paths
Verified unpartitioned tables still work with no behavioral change
Pre-commit hooks ran
AI Usage
GitHub Copilot (VS Code)
API exploration of the iceberg 0.9.1 crate, code review of the fix, and generating this description
Compiled with cargo check -p iggy_connector_iceberg_sink, then built via Docker and tested against a live local Iceberg catalog
Yes

@github-actions

Copy link
Copy Markdown

Thanks for the PR. It is labeled S-waiting-on-review and queued for review.

Slash commands (own line, regular comment) move it around the queue:

  • /ready - back to S-waiting-on-review after addressing feedback
  • /author - flip to S-waiting-on-author while you finish changes
  • /request-review @user-or-team - request a reviewer

See CONTRIBUTING.md for details.

@github-actions github-actions Bot added the S-waiting-on-review PR is waiting on a reviewer label Aug 11, 2026
@ashudeqode ashudeqode changed the title fix: iceberg dummy partition for every data fix(connector): iceberg dummy partition for every data Aug 11, 2026
@hubcio

hubcio commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

@EdgarModesto23 could you please check this?

@codecov

codecov Bot commented Aug 11, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 8.00000% with 69 lines in your changes missing coverage. Please review.
✅ Project coverage is 76.81%. Comparing base (a3e256b) to head (dc10410).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
...re/connectors/sinks/iceberg_sink/src/router/mod.rs 8.00% 64 Missing and 5 partials ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##             master    #3860      +/-   ##
============================================
- Coverage     76.95%   76.81%   -0.15%     
  Complexity     1021     1021              
============================================
  Files          1366     1366              
  Lines        176130   175838     -292     
  Branches     146173   145881     -292     
============================================
- Hits         135547   135072     -475     
- Misses        36707    36885     +178     
- Partials       3876     3881       +5     
Components Coverage Δ
Rust Core 75.89% <8.00%> (-0.18%) ⬇️
Java SDK 63.22% <ø> (ø)
C# SDK 76.01% <ø> (ø)
Python SDK 89.98% <ø> (ø)
PHP SDK 84.26% <ø> (ø)
Node SDK 96.33% <ø> (ø)
Go SDK 69.13% <ø> (ø)
Files with missing lines Coverage Δ
...re/connectors/sinks/iceberg_sink/src/router/mod.rs 30.37% <8.00%> (-5.29%) ⬇️

... and 26 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@hubcio

hubcio commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

@ashudeqode please dont remove the PR template, fill it so we can see reasoning behind this change.

@ashudeqode

ashudeqode commented Aug 11, 2026

Copy link
Copy Markdown
Author

@ashudeqode please dont remove the PR template, fill it so we can see reasoning behind this change.

@hubcio Updated the description

})?;
let partition_spec = table.metadata().default_partition_spec();

let data_files = if partition_spec.is_unpartitioned() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we extract the shared batch-processing and writer-closing logic here? The partitioned and unpartitioned branches are nearly identical, with only the write operation differing. A small writer abstraction or helper could encapsulate that variance and make this easier to maintain.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure, I'll do it.

@github-actions github-actions Bot added S-waiting-on-author PR is waiting on author response and removed S-waiting-on-review PR is waiting on a reviewer labels Aug 12, 2026

@mattp5657 mattp5657 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@EdgarModesto23 I'm still pretty new here, but wanted to jump in and help review. Let me know if you agree with the comments below.

Also think we should probably add some regression testing here.

"Batch loop failed ({}), closing writer to release resources",
e
);
if let Err(close_err) = fanout_writer.close().await {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On a write failure we're possibly leaving orphaned files in the Iceberg table location. close() still finalizes whatever partitions already succeeded, but we never commit them and just throw away the result. Could we grab the files from close()'s return and delete them before returning the error?

@EdgarModesto23 EdgarModesto23 Aug 13, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are correct! This has been noted before as seen in #3194 (comment) and it's currently documented under https://github.com/apache/iggy/blob/master/core/connectors/sdk/src/lib.rs#L429. It's not an issue from this PR specifically so I wouldn't block for it, tho we would love to see this fixed either here or on a separate issue for sure :) Thank you for bringing this up! ❤️

"Batch loop failed ({}), closing writer to release resources",
e
);
if let Err(close_err) = writer.close().await {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same thing here as above comment:

On a write failure we're possibly leaving orphaned files in the Iceberg table location. close() still finalizes whatever partitions already succeeded, but we never commit them and just throw away the result. Could we grab the files from close()'s return and delete them before returning the error?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well in iceberg data warehouse we have to run compaction for tables as streaming data make tons of parquet files so we have to run compaction time to time which combines multiple files and leave the other files as it is and then we have to expire snapshots and then remove the orphaned file time to time so it is a three step process so this will cover in it but in this PR our main concern is that the data should go in correct partition

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-author PR is waiting on author response

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(connector-iceberg): partition logic hardcodes dummy values and ignores table spec

4 participants