Skip to content

[SPARK-58323][SQL][4.0] Materialize AliasAware output ordering and partitioning to avoid StackOverflowError#57532

Closed
peter-toth wants to merge 1 commit into
apache:branch-4.0from
peter-toth:SPARK-58323-aliasaware-strict-ordering-partitioning-4.0
Closed

[SPARK-58323][SQL][4.0] Materialize AliasAware output ordering and partitioning to avoid StackOverflowError#57532
peter-toth wants to merge 1 commit into
apache:branch-4.0from
peter-toth:SPARK-58323-aliasaware-strict-ordering-partitioning-4.0

Conversation

@peter-toth

Copy link
Copy Markdown
Contributor

What changes were proposed in this pull request?

Backport of SPARK-58323 (#57502) to branch-4.0.

AliasAwareQueryOutputOrdering.outputOrdering and BroadcastHashJoinExec's output-partitioning expansion build their results with multiTransform, which returns a LazyList, and store the bounded result unforced. This forces them into strict collections with .toList, right after the existing .take(...) so the lazy short-circuit during candidate generation is preserved.

Tailored for branch-4.0 (differs from the master PR):

  • The PartitioningPreservingUnaryExecNode.outputPartitioning change is omitted: on branch-4.0 that method already materializes a strict collection (...iterator.flatMap(...).take(...).toSeq over an Iterator), so there is no unforced LazyList to fix.
  • The BroadcastJoinSuite single-element assertion change is omitted: on branch-4.0 expandOutputPartitioning always returns a PartitioningCollection (no case p :: Nil unwrap), so the single-element output shape is unchanged.

Why are the changes needed?

Each plan node re-wraps the child ordering/partitioning's unforced LazyList, so across a deep projection chain the deferred nesting grows unbounded and overflows the stack when the ordering/partitioning is later serialized or deeply traversed. On master this was observed as a driver StackOverflowError at DAGScheduler.submitMissingTasks during task serialization of a SortedMergeCoalescedRDD (SPARK-55715) on a large bucketed MERGE. That RDD and code path do not exist on branch-4.0, so this backport is defensive hardening of the same latent lazy-collection-in-output-ordering/partitioning hazard, which has existed since the multiTransform path was introduced in SPARK-42049.

Does this PR introduce any user-facing change?

No.

How was this patch tested?

New test in ProjectedOrderingAndPartitioningSuite asserting sameOrderExpressions is strict (not a LazyList); it fails before this change and passes after. Existing ProjectedOrderingAndPartitioningSuite / BroadcastJoinSuite / BroadcastJoinSuiteAE pass.

Was this patch authored or co-authored using generative AI tooling?

Generated-by: Claude Opus 4.8

…rtitioning to avoid StackOverflowError

### What changes were proposed in this pull request?

Backport of SPARK-58323 (apache#57502) to branch-4.0.

`AliasAwareQueryOutputOrdering.outputOrdering` and `BroadcastHashJoinExec`'s
output-partitioning expansion build their results with `multiTransform`, which
returns a `LazyList`, and store the bounded result unforced. This forces them
into strict collections with `.toList`, right after the existing `.take(...)`
so the lazy short-circuit during candidate generation is preserved.

Tailored for branch-4.0 (differs from the master PR):
- The `PartitioningPreservingUnaryExecNode.outputPartitioning` change is omitted:
  on branch-4.0 that method already materializes a strict collection
  (`...iterator.flatMap(...).take(...).toSeq` over an `Iterator`), so there is no
  unforced `LazyList` to fix.
- The `BroadcastJoinSuite` single-element assertion change is omitted: on
  branch-4.0 `expandOutputPartitioning` always returns a `PartitioningCollection`
  (no `case p :: Nil` unwrap), so the single-element output shape is unchanged.

### Why are the changes needed?

Each plan node re-wraps the child ordering/partitioning's unforced `LazyList`, so
across a deep projection chain the deferred nesting grows unbounded and overflows
the stack when the ordering/partitioning is later serialized or deeply traversed.
On master this was observed as a driver `StackOverflowError` at
`DAGScheduler.submitMissingTasks` during task serialization of a
`SortedMergeCoalescedRDD` (SPARK-55715) on a large bucketed `MERGE`. That RDD and
code path do not exist on branch-4.0, so this backport is defensive hardening of
the same latent lazy-collection-in-output-ordering/partitioning hazard, which has
existed since the `multiTransform` path was introduced in SPARK-42049.

### Does this PR introduce _any_ user-facing change?

No.

### How was this patch tested?

New test in `ProjectedOrderingAndPartitioningSuite` asserting `sameOrderExpressions`
is strict (not a `LazyList`); it fails before this change and passes after. Existing
`ProjectedOrderingAndPartitioningSuite` / `BroadcastJoinSuite` / `BroadcastJoinSuiteAE`
pass.

### Was this patch authored or co-authored using generative AI tooling?

Generated-by: Claude Opus 4.8
peter-toth added a commit that referenced this pull request Jul 26, 2026
…rtitioning to avoid StackOverflowError

### What changes were proposed in this pull request?

Backport of SPARK-58323 (#57502) to branch-4.0.

`AliasAwareQueryOutputOrdering.outputOrdering` and `BroadcastHashJoinExec`'s output-partitioning expansion build their results with `multiTransform`, which returns a `LazyList`, and store the bounded result unforced. This forces them into strict collections with `.toList`, right after the existing `.take(...)` so the lazy short-circuit during candidate generation is preserved.

Tailored for branch-4.0 (differs from the master PR):
- The `PartitioningPreservingUnaryExecNode.outputPartitioning` change is omitted: on branch-4.0 that method already materializes a strict collection (`...iterator.flatMap(...).take(...).toSeq` over an `Iterator`), so there is no unforced `LazyList` to fix.
- The `BroadcastJoinSuite` single-element assertion change is omitted: on branch-4.0 `expandOutputPartitioning` always returns a `PartitioningCollection` (no `case p :: Nil` unwrap), so the single-element output shape is unchanged.

### Why are the changes needed?

Each plan node re-wraps the child ordering/partitioning's unforced `LazyList`, so across a deep projection chain the deferred nesting grows unbounded and overflows the stack when the ordering/partitioning is later serialized or deeply traversed. On master this was observed as a driver `StackOverflowError` at `DAGScheduler.submitMissingTasks` during task serialization of a `SortedMergeCoalescedRDD` (SPARK-55715) on a large bucketed `MERGE`. That RDD and code path do not exist on branch-4.0, so this backport is defensive hardening of the same latent lazy-collection-in-output-ordering/partitioning hazard, which has existed since the `multiTransform` path was introduced in SPARK-42049.

### Does this PR introduce _any_ user-facing change?

No.

### How was this patch tested?

New test in `ProjectedOrderingAndPartitioningSuite` asserting `sameOrderExpressions` is strict (not a `LazyList`); it fails before this change and passes after. Existing `ProjectedOrderingAndPartitioningSuite` / `BroadcastJoinSuite` / `BroadcastJoinSuiteAE` pass.

### Was this patch authored or co-authored using generative AI tooling?

Generated-by: Claude Opus 4.8

Closes #57532 from peter-toth/SPARK-58323-aliasaware-strict-ordering-partitioning-4.0.

Authored-by: Peter Toth <peter.toth@gmail.com>
Signed-off-by: Peter Toth <peter.toth@gmail.com>
@peter-toth peter-toth closed this Jul 26, 2026
@peter-toth

Copy link
Copy Markdown
Contributor Author

Merge Summary:

Posted by merge_spark_pr.py

@peter-toth

Copy link
Copy Markdown
Contributor Author

Thank you @dongjoon-hyun for the review.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants