GeezerVison is showing github.com — [connectors] Update iceberg-rust to 4dd8c946 by swanandx · Pull Request #7721 · feldera/feldera
Conversation
swanandx
commented
Oct 29, 2026
•
edited
Loading
Uh oh!
There was an error while loading. Please reload this page.
Describe Manual Test Plan
The fork now matches upstream with no patches. The Iceberg unit, file system
and follow tests pass, and so do the Delta and Parquet tests.
The new test localfs_input_test_add_files reads a table made with add_files,
with a page index, under 9 filters. It fails when the upstream nested-column fix
is reverted, and when page pruning or the LIKE unescape fix is broken.
Breaking Changes?
Nested columns in data files without field ids, such as files added with
add_files, now read their real values instead of NULL. If the table has no
name mapping, these columns now read as NULL instead of values matched by
position. A follow pipeline that read such a file before the upgrade can show
wrong rows when the file is deleted later. The changelog says the same.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
What I ran
| Check |
Result |
cargo check --locked -p feldera-iceberg --tests |
✅ |
cargo test --locked -p feldera-iceberg |
✅ 24 passed |
Stale refs to datafusion-iceberg, old revs |
none left |
feldera/iceberg-rust@4dd8c946 vs apache/iceberg-rust@main |
identical, so the fork has no patches, as the PR says |
| Stall fix upstream |
✅ upstream fixes it differently: #3277 spawns the file open on the IO runtime instead of opening inside the read stream, and has its own regression test. Feldera's Runtime::try_current() gives it a working IO handle. |
Pitfall (medium): unrelated lockfile downgrades. Besides the iceberg and avro bumps, Cargo.lock re-resolves crates that have nothing to do with this change: hyper-util, quinn and quinn-udp drop from socket2 0.6.5 to 0.5.10, bindgen and prost-derive drop from itertools 0.13/0.14 to 0.10.5, and windows-sys/windows-targets/windows-core also go down. The hyper-util change affects every HTTP client in the product. It probably comes from how the lock was regenerated. Please run cargo update -p iceberg -p iceberg-datafusion … against the main lockfile, so the only changes are the ones the bump needs.
Observation: iceberg brings in new transitive deps (syn 3, wkb, geo-traits, parquet-geospatial, moka, typetag, ouroboros, zmij). All are MIT/Apache-2.0, and none are crypto crates. apache-avro goes from 0.21 to 0.22, but only iceberg uses that copy.
Not covered: no Feldera-side test checks that a scan does not stall when many data files are open; the only coverage is the upstream test. Otherwise LGTM.
|
swanandx reacted with thumbs up emoji
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
|
What I ran: cargo check --locked -p feldera-iceberg passed and cargo test --locked -p feldera-iceberg passed (24/24). I confirmed 4dd8c946 is identical to apache/iceberg-rust main. The stall fix moved upstream (#3277) with its own tests there. All new transitive crates are MIT, Apache-2.0 or Zlib, and there is no new crypto.
| Label |
Severity |
Finding |
| bug / breaking (undocumented) |
high |
The lockfile bumps serde_json 1.0.145 → 1.0.154 for the whole workspace, and 1.0.154 switches float formatting from ryu to zmij. I checked this with a scratch test in sqllib: TO_JSON(CAST(1e20 AS DOUBLE) AS VARIANT) used to return 1e20 and now returns 1e+20. REAL 3.4e38 goes from 3.4e38 to 3.4e+38. JSON output connectors and the REST egress for DOUBLE/REAL columns go through the same serializer, so their output changes too. No test caught it: grep finds no SQL-compiler or Python test that checks exponent formatting. Either pin serde_json back (cargo update -p serde_json --precise 1.0.145, if iceberg-datafusion allows it), or treat this as a deliberate output change: add a test that pins the format and update the "Breaking Changes" section. |
| missing |
medium |
The commit message is a one-liner for a change that swaps the crate and pulls 19 iceberg-datafusion commits (see the inline comment), apache-avro 0.22 and syn 3. The body should explain the why and list the behaviour changes. |
| missing test |
medium |
Nothing in this repo exercises the new snapshot read path (DataSource refactor, page-index pruning, the LIKE pushdown fix). Please add or extend a python/tests/platform/test_iceberg_input.py case with a snapshot_filter that uses LIKE 'a\_%' and a range predicate, and check the row counts. |
|
swanandx reacted with eyes emoji
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
fred is right, fixing this
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
should be fixed and safe to bump after #7735
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
|
What I ran
| Check |
Result |
cargo check --locked -p feldera-iceberg |
✅ |
cargo test --locked -p feldera-iceberg |
✅ 24 passed |
pre-commit run on changed files (clippy, fmt, machete, crypto deps) |
✅ |
Fork compare ba063f0...4dd8c94 |
the old stall patch was replaced by upstream #3277 (spawn opens on the IO runtime) ✅; one iceberg in the lockfile, no openssl; new transitive crates (wkb, geo-traits, parquet-geospatial, darling 0.24, zmij) are all MIT/Apache |
I could not run python/tests/platform here because it needs a pipeline-manager.
missing (high): no changelog entry for a declared breaking change. The PR body has a good table and says follow pipelines must be restarted from a new snapshot, but none of this is in docs.feldera.com/docs/changelog.md under ## Unreleased. Users only see the changelog. Please move the table and the restart advice there.
missing (medium): no test for the changed behaviour. test_iceberg_snapshot_all_types only writes files that have field ids. Neither case from the breaking-change table is tested:
- A Parquet file without field ids, added with a name mapping (
add_files), that has a ROW column → the struct now reads real values.
- The same file without a name mapping → the struct now reads NULL instead of matching by position.
- Follow mode: delete such a file after the upgrade and check that the retraction matches what was ingested.
Cases 1 and 2 fit next to the all-types test in python/tests/platform/test_iceberg_input.py. Write the file with pyarrow and no PARQUET:field_id metadata, then call table.add_files([...]) with and without schema.name-mapping.default set.
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
Review of the iceberg-rust bump to 4dd8c946
What I ran: cargo test --locked -p feldera-iceberg (debug) builds the renamed iceberg-datafusion and passes 24/24. The pre-commit run timed out here while setting up its hooks, so that check is still open.
| Area |
Severity |
Finding |
| missing: docs / breaking change |
high |
The PR description lists a breaking change: nested columns in files without field ids now read as real values or as NULL, which flips the old behaviour. A follow pipeline may also need a restart from a new snapshot. None of this is in docs.feldera.com/docs/changelog.md (## Unreleased is empty) or in connectors/sources/iceberg.md. Users only learn about it from the PR description. This fails the "docs for user-visible changes" and "no undocumented breaking changes" gates. |
| missing: tests |
medium |
Read behaviour changes, but no test covers it. python/tests/platform/test_iceberg_input.py only writes files that have field ids. Cases with no coverage: (1) nested struct/list/map in a file added via add_files with a name mapping, which should give values; (2) the same file without a name mapping, which should give NULL; (3) page-index pruning with LIKE 'a\_%' (escaped prefix), a range and NOT IN, compared against an unfiltered read. A pyiceberg add_files fixture next to the existing nested-type test would cover (1) and (2). |
| pitfall: deps |
medium |
apache-avro moves to 0.22, which brings in rand 0.10, digest 0.11 and miniz_oxide 0.9. bon moves to 3.10, which pulls in syn 3 / darling 0.24 / prettyplease 0.3 alongside the existing syn 2. That means two copies of several crates and longer build times. The new crates (zmij, wkb, geo-traits, parquet-geospatial, ouroboros) are MIT/Apache-licensed, and none of them is crypto/TLS, so the FIPS rule is not affected. |
| observation |
– |
The serde_json 1.0.154 float-text change is handled by #7735, which is merged. |
Once the changelog entry with migration guidance and the tests for cases (1) and (2) are in, I'm happy to approve.
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
|
What I ran
| Command |
Result |
cargo test --locked -p feldera-iceberg |
✅ 24/24 |
cargo test -p static-connectors --features iceberg-tests-fs --test connector_suites -- localfs_input (pyiceberg 0.11.1 from requirements.ci.txt) |
✅ 12/12, including the new localfs_input_test_add_files |
Extra LIKE-pushdown test (diff below) |
✅ |
New crates in the lock file (wkb, geo-traits, parquet-geospatial, zmij, darling 0.24): MIT/Apache, no crypto. ✅
Missing (medium): no tests for the new scan behaviour. The bump changes how DataFusion pushes down filters: LIKE prefixes are now unescaped, and Parquet pages are pruned with the page index. Both change which rows a snapshot_filter returns, but the only check is the manual 22-filter run. Please add at least a LIKE filter case. This one passes:
+/// A `LIKE` prefix filter is pushed down to the scan and must keep exactly the matching rows.
+#[engine_test(cfg(feature = "iceberg-tests-fs"))]
+pub fn localfs_input_test_like_filter(engine: &dyn PipelineTestEngine) {
+ iceberg_localfs_input_test(
+ engine,
+ 100_000,
+ json!({ "snapshot_filter": "s LIKE 's1%' AND NOT (i IN (1, 10, 100))" }),
+ &|x| {
+ let i = x["i"].as_i64().unwrap();
+ x["s"].as_str().unwrap().starts_with("s1") && ![1, 10, 100].contains(&i)
+ },
+ );
+}
The test data has no literal _ or %, so an escaped prefix such as 's\_%' would need a row like that before it can catch the unescape fix itself.
Missing (medium): the other side of the breaking change has no test. The changelog says that a table with no name mapping now reads nested columns as NULL. Nothing tests that path. A --add-files variant that removes schema.name-mapping.default would pin it down.
Pitfall (low): the commit says apache-avro 0.22 needs serde_json >= 1.0.150, but the workspace still declares 1.0.132. Consider raising the floor.
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
Skipping the other points:
LIKE test: without an escaped _ or % it passes before and after the bump, so it catches nothing.
- No-name-mapping test: our test fields are NOT NULL, so the read fails instead of giving NULL. Upstream tests this case (Only pull the full pipeline if refresh_version changed #3437).
serde_json floor: the lock already has 1.0.154, and apache-avro forces 1.0.150 or later.
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
|
field ids, such as files added with `add_files`, now read their real values
|
|
|
instead of NULL. If the table has no name mapping, these columns now read as
|
|
|
NULL. A follow pipeline that read such a file before the upgrade can show
|
|
|
wrong rows when the file is deleted later.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pitfall (medium): This entry tells users that a follow pipeline can show wrong rows, but not what to do about it. Add the action, e.g. "if a follow pipeline read add_files data before upgrading, restart it from a fresh snapshot (clear its storage/checkpoint)". Also, "these columns now read as NULL" leaves out what they read before (nothing? an error? positional values?). Say what changed so users can tell whether their data is affected.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
What I ran
| Check |
Result |
cargo test --locked -p feldera-iceberg |
24/24 pass |
cargo test -p static-connectors --features iceberg-tests-fs --test connector_suites -- iceberg::localfs (pyiceberg 0.11.1) |
12/12 pass, including the new localfs_input_test_add_files |
pre-commit run --files <changed> |
pass (clippy, fmt, machete, crypto-deps, openapi) |
New transitive crates (zmij, wkb, geo-traits, parquet-geospatial, darling 0.24) |
MIT/Apache, no new crypto |
missing (medium): tests for the new read-path behaviour. The commit says reads now unescape LIKE prefixes before pushdown and prune pages with the page index. No test in the repo covers either one; the PR only mentions a local check of 22 filters. I added a LIKE + NOT snapshot filter locally and it passes:
+#[engine_test(cfg(feature = "iceberg-tests-fs"))]
+pub fn localfs_input_test_like_filter(engine: &dyn PipelineTestEngine) {
+ iceberg_localfs_input_test(
+ engine,
+ 100_000,
+ json!({ "snapshot_filter": "s LIKE 's12%' AND NOT (i < 1250)" }),
+ &|x| x["s"].as_str().unwrap().starts_with("s12") && x["i"].as_i64().unwrap() >= 1250,
+ );
+}
That test doesn't catch an unescape bug, though, because the test strings contain no _ or %. A useful regression test needs a --like-strings style flag in create_test_table_s3.py that writes values like a_b/a%b, plus a filter such as s LIKE 'a\_b%'. Please commit the 22-filter check as a test.
Cases not covered by the PR's tests
add_files table without a name mapping. The changelog says nested columns read NULL; that is untested.
add_files data in follow mode, including a delete of the added file, which is the scenario the changelog warns about.
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
|
field ids, such as files added with `add_files`, now read their real values
|
|
|
instead of NULL. If the table has no name mapping, these columns now read as
|
|
|
NULL instead of values matched by position. A follow pipeline that read such
|
|
|
a file before the upgrade can show wrong rows when the file is deleted later.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pitfall (medium): This tells users a follow pipeline can show wrong rows, but not what to do about it. Add the action, e.g. "restart affected follow pipelines from a fresh snapshot (clear storage) after upgrading". Also, nested columns that silently turn NULL when there's no name mapping are hard to notice. Could the connector log a warning once per file when it falls back to NULL for want of field ids and a name mapping?
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
What I ran
| Check |
Result |
cargo check --locked -p feldera-iceberg |
✅ |
cargo test -p static-connectors --features iceberg-tests-fs --test connector_suites iceberg::localfs (pyiceberg 0.12 + pyiceberg-core) |
✅ 12/12, including the new localfs_input_test_add_files |
pre-commit run --files <changed files> |
✅ |
New lockfile crates (geo-traits, wkb, parquet-geospatial, zmij, darling 0.24, …) |
MIT/Apache, no new crypto |
Missing tests (medium)
- The commit says LIKE prefixes are now unescaped before pushdown, but
s LIKE 's4999%' has nothing to unescape. I added an escaped-prefix case locally and it passes. Please add it:
- let filters: [(&str, Keep); 8] = [
+ let filters: [(&str, Keep); 9] = [
@@
("b AND i < 1000", &|x| i(x) % 2 == 1 && i(x) < 1000),
+ // Escaped prefix: pushdown must unescape `\9` to `9` before pruning.
+ ("s LIKE 's4\\9%'", &|x| x["s"].as_str().unwrap().starts_with("s49")),
];
- Nothing tests the other half of the behaviour change: a file without field ids and no name mapping, where nested columns now read as NULL instead of matching by position. One more
create_test_table_s3.py flag that removes schema.name-mapping.default after add_files would pin this down.
I didn't check the upstream iceberg-rust diff line by line. I relied on the fork now matching upstream and on the test results above.
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
|
field ids, such as files added with `add_files`, now read their real values
|
|
|
instead of NULL. If the table has no name mapping, these columns now read as
|
|
|
NULL instead of values matched by position. A follow pipeline that read such
|
|
|
a file before the upgrade can show wrong rows when the file is deleted later.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing (medium): this names two silent data changes but gives the user nothing to do about them.
- Follow pipelines: say what to do, e.g. "rebuild the pipeline from a fresh snapshot (clear storage) after upgrading if the table has files without field ids".
- Tables without a name mapping: say how to fix it, e.g. "set
schema.name-mapping.default on the table". Better still, have the connector log a warning when it opens such a table, so the NULLs are not silent.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
What I ran
| Check |
Result |
cargo check --locked -p feldera-iceberg --tests |
✅ |
cargo test --locked -p feldera-iceberg |
✅ 24 passed |
cargo test -p static-connectors --features iceberg-tests-fs --test connector_suites -- iceberg (pyiceberg 0.11.1, pyarrow 23.0.1) |
✅ 12 passed, including localfs_input_test_add_files |
pre-commit run --files <changed> |
✅ |
--add-files fixture checked by hand |
✅ the Parquet file has no field ids and has a column/offset index; the table has schema.name-mapping.default |
Gates: tests, docs (changelog) and licences (new transitive crates are MIT/Apache) pass. The apache-avro 0.22 bump comes in only through iceberg; Feldera's Avro format stays on 0.18.
Missing (medium): test cases not covered
- The other side of the behaviour change: a file without field ids in a table without a name mapping now reads NULL. It is in the changelog but no test pins it. Strip
schema.name-mapping.default after add_files and assert NULL nested columns.
- An ordered read (
timestamp_column) of the add_files table. Only unordered snapshot_filter reads are tested.
- A distributed read (
share.rs) of the add_files table. The name mapping travels with each FileScanTask, so it should work, but no test checks it.
Tech-debt (low): share.rs builds its ArrowReader without with_row_selection_enabled, so distributed reads still skip page pruning. The single-host DataSource path now uses it.
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Verdict: flaky test, not this PR — merge queue should pass on re-queue
Failed job: Adapter Tests / Test Adapters (amd64)
|
|
| Failing test |
transport::nats::input::test::hardening_tests::library_recreated_consumer_is_deleted_on_pause |
| Error |
Connector's own count reached 1, but the server disagrees: found 0 consumers on stream 'str': [] (log L2548) |
| PR diff touches |
crates/iceberg, crates/connectors/src/test/iceberg.rs, lockfile/deps — no NATS code |
Already tracked as a known flake: #7820 (filed yesterday from a different PR, same assertion, same line, arm64 runner). This run reproduces it on amd64 with the same preceding burst of client error: nats: IO error reconnects before the 5s WaitForConsumerCount timeout — added a confirming comment there.
Next step: no fix needed here; re-queueing the PR should pass. If it fails again on this same test, that's issue #7820, not a new problem.
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
|
Verdict: flaky test, not this PR. Merge queue run failed in Unit Tests / Rust Unit Tests (aarch64), unrelated to the iceberg bump.
|
|
| Job |
Unit Tests / Rust Unit Tests (aarch64) |
| Test |
operator::dynamic::sharded_accumulator::tests::sharded_accumulator_multihost_gather_to_first_host |
| Log line 3426 |
panicked at crates/dbsp/src/utils/test/multihost.rs:535:57: ... UnknownExchange(0) |
This PR's diff only touches crates/iceberg, crates/connectors/src/test/iceberg.rs and crates/adapterlib — nothing in crates/dbsp. The panic is a registration/teardown race in the multihost exchange test harness, already tracked in #7800 (same UnknownExchange(0) message, same harness, a different test in the same suite hit it on a prior PR). Added this run as a repeat occurrence there rather than filing a new issue.
Next step: re-queueing should pass — nothing in the failure touches code this PR changed.
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
If the fork now matches upstream, why are we still using the fork?
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
The fork now matches upstream, which merged our reader stall fix.
The DataFusion integration crate is renamed back to iceberg-datafusion.
Its snapshot reads now run as a DataSource, prune Parquet pages with
the page index, and unescape LIKE prefixes before pushdown.
Nested columns in files without field ids now read their real values.
A new test reads such a table, with a page index, under 9 filters.
The changelog notes the change.
apache-avro 0.22 needs serde_json 1.0.150 or later. The JSON text of
floats does not change because of #7735.
serde_json now writes 1e40 as 1e+40 in parsed number text, so one
test error text changes.
Signed-off-by: Swanand Mulay <[email protected]>
If the fork now matches upstream, why are we still using the fork?
upstream release process is quite slow, and lot of times we want the latest main ( say to use bumped dependecies ) or have some patches until our PRs get accepted upstream. hence sticking to fork
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Assignees
No one assigned
Milestone
No milestone
Development
Successfully merging this pull request may close these issues.
Uh oh!
There was an error while loading. Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
|