andygrove opened a new issue, #5815:
URL: https://github.com/apache/datafusion-comet/issues/5815
## Describe the problem
`branch-1.0` was cut at `af534e0f` (2026-08-03). Since then, 192 commits
have landed on `main` and only three
backport batches have gone to `branch-1.0` (#5261, #5321, #5480). I went
through every one of those 192
commits to work out which are genuine backport candidates for a 1.0.x patch
release — pure bug fixes and
performance improvements that neither add features nor change intended
behaviour — and which are not, and why.
This issue is the resulting list. It is a triage record, not a decision: the
recommendations still need
someone to agree with them and open the backport PRs.
### How the list was produced
- Range: `git log af534e0f..main`, 192 commits.
- 85 carry a `fix:` or `perf:` prefix. I also checked all 47 `feat:` /
`refactor:` / `deps:` commits for ones
that close a `bug`-labelled issue, which is how #5602 ended up in tier 1
despite its `feat:` prefix.
- Prefixes are not trustworthy on their own in either direction, so every
candidate was checked against the
label on the issue it closes. Five `fix:`-prefixed PRs close `enhancement`
issues and are excluded below.
- Applicability was checked mechanically: each commit was cherry-picked onto
a pristine `branch-1.0` worktree,
and every conflicting path was tested for existence on `branch-1.0`. A
conflict in a file that does not
exist on `branch-1.0` means the PR fixes code that only exists on `main` —
not a candidate. A conflict in a
file that does exist is ordinary context drift and still a candidate.
- `branch-1.0` is on DataFusion 54.1.0 / Arrow 58.4.0; `main` is on 55.0.0 /
59.2.0 since #5262. That rules
out at least one otherwise-attractive fix.
Applying the recommended set as a stack in merge order, 27 of 37 commits
cherry-pick clean and 10 need small
manual resolution. Cherry-picking clean is not the same as compiling — #5461
is a known example — so each
backport PR still needs `cargo check --workspace --all-targets` plus `./mvnw
test-compile` before it goes up.
## Tier 1 — correctness, crashes and hangs
These change observable results, fail tasks, leak, or hang. I would take all
of these.
| PR | What it fixes | Why it matters on 1.0.x | Cherry-pick |
| --- | --- | --- | --- |
| #5602 | Unicode case-insensitive Parquet field matching | Closes #5495 —
`bug`, `correctness`, `priority:critical`, and already in the 1.0.1 milestone.
Non-ASCII case pairs silently read as NULL | clean |
| #5623 | Codegen dispatcher null short-circuit skipped when a foldable
subtree can raise | Closes #5608 — `bug`, `correctness`, `priority:high`.
Swallows ANSI errors | clean |
| #5159 | `collect_list` / `collect_set` argument coercion made a
normalization barrier | Closes #5158 — `bug`, `priority:high`. Grouped
aggregate fails validating its own output batch | clean |
| #5757 | Dictionary hash fast path kept off nested and reseeded buffers |
Dictionary-encoded values hashed differently from identical decoded values —
wrong join/aggregate results and wrong shuffle partitioning | clean |
| #5754 | Parent struct's null mask applied before hashing its fields |
Wrong answers from `hash` / `xxhash64` on a null struct; the same decision
feeds shuffle partitioning | apply after #5757 |
| #5684 | Correctly rounded decimal to double/float cast | Last-ulp wrong
answers for essentially every `DECIMAL(38,18)` value above 0.01 | clean |
| #5683 | ANSI bound check for float/double to integral casts | Spurious
`CAST_OVERFLOW` for exactly representable `Int.MaxValue` / `Long.MaxValue` |
clean |
| #5752 | ANSI errors preserved for rejected `TIMESTAMP_NTZ` casts | Closes
#5749 — `bug`, `correctness`. Returns NULL where Spark raises
`CAST_INVALID_INPUT` | clean |
| #5177 | Checked `TIMESTAMP_MILLIS` conversion in Parquet reads | Silently
wraps overflowing values; Spark throws regardless of ANSI mode | rebase
(`parquet_support.rs`) |
| #5740 | Same check for nested `TIMESTAMP_MILLIS` in unfiltered scans |
Companion to #5177; take the two together | rebase (`parquet_support.rs`) |
| #5680 | `rpad` / `lpad` return NULL for a NULL length instead of panicking
| Enabled by default; a NULL in the length column fails the task with
`CometNativeException` | clean |
| #5630 | Map offsets rebased in `mapsort` | A sliced map fails the task
with "Max offset exceeds length of entries" | rebase (test file only) |
| #5679 | `concat_ws` with array arguments falls back instead of failing
natively | Query fails natively where Spark returns a result | clean |
| #5357 | Spark type names in ANSI `abs` overflow errors | Reports `Int64
overflow` where Spark reports `long overflow` | clean |
| #5747 | `copy_array` propagates offset-overflow errors instead of
panicking | Closes #5706 — `bug`. Panic instead of a clean error | rebase
(`copy.rs`) |
| #5539 | Arrow vector import rollback on failure | Closes #5534 — `bug`,
`correctness`, `priority:medium`. Leaks native buffers, adding allocator
pressure while the query is already failing | rebase (test file only) |
| #5748 | Tokio runtime threads attached to the JVM as daemon threads | The
JVM hangs forever if an app returns from `main` without calling `spark.stop()`.
#4734, which is on `branch-1.0`, does not cover this case | rebase (CI yml
only) |
| #5561 | Spark 4.2 Python worker configuration | `branch-1.0` ships a
`spark-4.2` profile and writes `workerConf` inside `writeCommand`, so
accelerated `mapInArrow` / `mapInPandas` fails outright on 4.2 | clean |
| #5759 | Iceberg tables partitioned by an unknown transform | Read fails
with `Invalid Iceberg scan task`; this is Iceberg's forward-compatibility
contract, and it is what turned Iceberg CI red on `main` | rebase |
| #5493 | `CometDiskBlockWriter` spill registry made per-task | The registry
is `static`, so task A force-spills task B's buffered bytes from A's thread and
charges them to A | clean |
| #5494 | Task-shared memory pool as a ref-counted RAII guard | A stranded
entry holds a JNI global ref to `CometTaskMemoryManager`, pinning
`TaskMemoryManager` and `TaskContext` for the executor's lifetime. Nothing
prunes the map | rebase (CI yml, `jni_api.rs`) |
| #5461 | Native shuffle reservation released after spill failure |
Reservation, pinned buffers and repeated-spill bytes leak after a failed
partition write | clean, but does **not** compile as-is: its inline test needs
metric fields from #5370, so the test needs adapting |
## Tier 2 — performance, no behaviour change
| PR | What it does | Cherry-pick |
| --- | --- | --- |
| #4885 | `spark_base64`: 11–21% faster, bit-identical output | clean |
| #4911 | `spark_floor`: up to 4x faster on decimals | clean |
| #4939 | Vectorized integer-to-decimal cast — the second most frequent cast
in TPC-DS | rebase (bench registration in `Cargo.toml`) |
| #5233 | `spark_size` list lengths via Arrow's `length` kernel | clean |
| #5395 | `spark_size` Map via the offset buffer; follow-up to #5233, take
them together | after #5233 |
| #5046 | `ArrowWriter` preallocates fixed-width vectors from the known
batch size | clean |
| #5442 | `ArrowWriter` bulk-copies fixed-width columns; follow-up to #5046,
take them together | after #5046 |
| #5440 | Arrow cast for the decimal rescale check, replacing duplicated
arithmetic | clean |
| #5735 | Arrow cast for date to `TIMESTAMP_NTZ` | rebase (`temporal.rs`) |
| #5737 | `posexplode` array expression evaluated once per batch instead of
twice | clean |
| #5222 | Iceberg reflection lookups cached on the planning path — currently
O(files) `Class.getMethod` per scan, and on the Spark 3.4 profile (Iceberg <
1.7) every call constructs a `NoSuchMethodException` | clean |
| #5568 | Per-partition scratch reused in the shuffle write path | rebase |
| #5038 | Arrow IPC compression context reused across shuffle blocks | clean
|
Two caveats in this tier. #5038's measured benefit is narrower than it
looks: the follow-up measurement in
#5727 shows 2.0–16.8% faster block encoding for 128-row batches and
approximately no change for full-size
compressed batches. And #5368 (serialize Python input directly from Comet
Arrow vectors) is the largest win
available here, but it is 10 files, it regressed timezone aliases, and the
fix for that (#5556) is a separate
PR — take both or neither.
## Tier 3 — needs a decision before it can be classified
- **#5558** (`array_join` null short-circuiting) is a real correctness fix —
Spark returns NULL whenever
`nullReplacement` is NULL, Comet returned the joined string — but it is
bundled with flipping `array_join`
from `Incompatible` to natively enabled. Backporting as-is changes a
compatibility flag in a patch release.
Worth splitting.
- **#5469** (normalize scalar float sort and window rank keys) is half
applicable. The sort-key normalization
for signed zeros and NaN is a genuine correctness fix that applies to
`branch-1.0`; the window-rank half
follows `WindowGroupLimitExec` (#4870), which is `main`-only. Needs
splitting.
- **#5362** ("make `CometExplodeExec` respect batch size") is a real bug —
`UnnestExec` never consults
`datafusion.execution.batch_size`, so an 8192-row batch of 100-element
arrays comes back as one
819,200-row batch and peak memory scales with it. But the fix lands a new
1,491-line native `ExplodeExec`.
That is feature-sized for a patch release.
- **#5726** (pathless spill backend writes an index claiming bytes that
never landed) would be a corrupt
shuffle file. On `branch-1.0` the only spill backend is local and always
has a path, so as far as I can
tell the bug is latent there. Backport only if we want the invariant
rather than the fix.
- **#5653** bundles three unrelated core fixes. One of them is genuinely
user-visible — `Configuration#get`
expands `${...}` references and `Configuration.Entry#getValue` does not,
so an object store option composed
from another property reached native unexpanded. Extract that hunk rather
than cherry-picking the PR.
- **#5464** (RAII for tracing memory pool registration) is a real leak, but
only reachable with native tracing
enabled. Low value for a patch release.
- **#5552** (preserve Arrow `Field` metadata across C Data exports) closes
an `enhancement` (#5547) and is
part one of the Variant series. Nothing on `branch-1.0` consumes `Field`
metadata, so there is no
observable effect there.
## Excluded, with reasons
Recording these so they do not get re-litigated for the next patch release.
**Fixes code that only exists on `main`.** The feature landed after the
branch cut, so the fix has nothing to
apply to:
- Celeborn / RSS shuffle (features #5473, #5476, #5481, #5491, #5501, #5513,
#5531, #5537): fixes #5475,
#5627, #5650, #5665, #5668, #5722, #5727
- Native Iceberg V2 writer (#5361) and the split writer/committer work
(#4658, #5298): fixes #5410, #5651,
#5696, #5729, #5779
- Iceberg system functions (#5638): fix #5773
- Experimental native in-memory cache (#5051): fixes #5733, #5734
- Native `ExplodeExec` (#5362): fix #5667
- `CreateArray` map literal (#5452): fix #5766 — #5544 only becomes
reachable once a folded map literal is
admitted natively
**Blocked on the dependency upgrade.** #5041 (enable FIRST/LAST partial
merge) depends on the root fix in
DataFusion 55.0.0, which reached `main` via #5262. `branch-1.0` is on 54.1.0.
**Spark UI metrics accuracy only** — same call as for 1.0.1, these do not
change query results or stability:
#5370, #5398, #5408, #5445, #5463, #5497, #5516, #5554, #5628.
**`fix:` prefix but closes an `enhancement` issue:** #5045 (#3389), #5225
(#5190), #5234 (#5096), #5359
(#5074), #5412 (#5258).
**Test, benchmark or CI only:** #5388, #5439, #5718, #5727, plus every
`test:`, `chore:`, `chore(deps)`,
`docs:` and `ci:` commit in the range.
**Previously decided.** #5369 (preserve Catalyst nullability and field IDs
in native Parquet writes) is a real
bug, but `spark.comet.parquet.write.enabled` defaults to `false` and is
documented as experimental on
`branch-1.0`.
**Already on `branch-1.0`** via #5261, #5321 and #5480: #5138, #5162, #5167,
#5185, #5192, #5282, #5315,
#5364, #5376, #5392, #5400, #5443.
## Additional context
Related open 1.0.1 items with no fix on `main` to backport: #5366 (`to_time`
/ `try_to_time` still rejects
`'T12'` and `'12:30:45.'`; #5364 fixed only the whitespace half) and #4412
(`CometHashAggregateExec` and
`AQEPropagateEmptyRelation`).
Optional companion: #5769 refactors #5754 and #5757 into a shared helper.
Not required, but it keeps
`branch-1.0` closer to `main`'s shape if we want that.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]