Skip to content

[spark] Fix V2 write with Hive dynamic partition column order#8414

Merged
YannByron merged 1 commit into
apache:masterfrom
kerwin-zk:fix-spark-v2-hive-dynamic-partition-order
Jul 3, 2026
Merged

[spark] Fix V2 write with Hive dynamic partition column order#8414
YannByron merged 1 commit into
apache:masterfrom
kerwin-zk:fix-spark-v2-hive-dynamic-partition-order

Conversation

@kerwin-zk

Copy link
Copy Markdown
Contributor

Purpose

Fix V2 write with Hive dynamic partition column order

Tests

CI

@kerwin-zk kerwin-zk force-pushed the fix-spark-v2-hive-dynamic-partition-order branch 3 times, most recently from 9459c61 to 4505435 Compare July 1, 2026 14:14
@kerwin-zk kerwin-zk marked this pull request as draft July 2, 2026 03:23
@kerwin-zk kerwin-zk marked this pull request as ready for review July 2, 2026 04:12
@YannByron YannByron requested a review from Copilot July 2, 2026 04:26

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses incorrect handling of Hive-style dynamic partition column ordering during Spark V2 writes, ensuring Paimon can accept queries whose partition columns appear in Hive’s expected positions without breaking non-Paimon inserts.

Changes:

  • Adds a parser/analyzer rule that marks INSERT statements containing Hive-style dynamic partitions.
  • Extends Paimon write analysis to strip the marker and resolve output columns correctly for dynamic partition overwrites (including Hive ordering).
  • Adds regression tests covering both non-Paimon inserts and Paimon V2 dynamic overwrite scenarios.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
paimon-spark/paimon-spark-ut/src/test/scala/org/apache/paimon/spark/sql/InsertOverwriteTableTestBase.scala Adds regression tests for non-Paimon dynamic partition inserts and Paimon V2 dynamic overwrite with Hive partition column order.
paimon-spark/paimon-spark-common/src/main/scala/org/apache/spark/sql/catalyst/parser/extensions/AbstractPaimonSparkSqlExtensionsParser.scala Introduces a rule to tag Hive dynamic partition INSERTs by wrapping the query plan.
paimon-spark/paimon-spark-common/src/main/scala/org/apache/paimon/spark/catalyst/plans/logical/PaimonHiveDynamicPartitionQuery.scala Adds a lightweight logical wrapper node to carry dynamic partition column metadata through analysis.
paimon-spark/paimon-spark-common/src/main/scala/org/apache/paimon/spark/catalyst/analysis/PaimonAnalysis.scala Updates V2 write resolution to detect/strip the wrapper and apply Hive-style output ordering when needed.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +390 to +395
private def withNewQuery(insert: InsertIntoStatement, query: LogicalPlan): InsertIntoStatement = {
insert.getClass
.getMethod("withNewChildInternal", classOf[LogicalPlan])
.invoke(insert, query)
.asInstanceOf[InsertIntoStatement]
}

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.

+1

}
}

test("Paimon parser: dynamic partition marker is removed for non-Paimon inserts") {

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.

maybe “Paimon Insert: overwrite format(parquet) table in static mode”?

query.transformDown { case PaimonHiveDynamicPartitionQuery(_, child) => child }
}

private def resolveHiveDynamicPartitionWrite(

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.

resolveHiveDynamicPartitionWrite and resolveDynamicPartitionOverwrite are near duplicates. Both methods share the same shape: check hiveStyleDynamicPartitionOutput, and on match do "by-position → by-name", otherwise a single by-name resolve. Only the way dynamicPartitionColumns is obtained differs (from the marker vs. from table.partitionKeys()).

table: DataSourceV2Relation,
dynamicPartitionColumns: Seq[String]): Option[Seq[Attribute]] = {
val partitionKeys = table.table.asInstanceOf[SparkTable].getTable.partitionKeys().asScala.toSeq
val dynamicPartitionSet = dynamicPartitionColumns

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.

It is a misleading no-op alias.

@YannByron

Copy link
Copy Markdown
Contributor

@kerwin-zk left some comments.

@kerwin-zk kerwin-zk force-pushed the fix-spark-v2-hive-dynamic-partition-order branch from 4505435 to c2ee502 Compare July 2, 2026 08:55
@kerwin-zk

Copy link
Copy Markdown
Contributor Author

@YannByron done

@YannByron

Copy link
Copy Markdown
Contributor

+1

@YannByron YannByron merged commit ce92c8a into apache:master Jul 3, 2026
12 checks passed
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.

3 participants