[spark] Resolve primary-key and bucket-key properties like other identifiers - #9372
Open
zhuxiangyi wants to merge 1 commit into
Open
[spark] Resolve primary-key and bucket-key properties like other identifiers#9372zhuxiangyi wants to merge 1 commit into
zhuxiangyi wants to merge 1 commit into
Conversation
…tifiers
`primary-key` and `bucket-key` are plain strings in TBLPROPERTIES, so they
reached Paimon exactly as typed and were then matched against the schema
exactly. Every other identifier in the same statement follows
`spark.sql.caseSensitive` -- the partition columns in particular, because
Spark's analyzer has already resolved them -- which left one statement obeying
two different rules:
CREATE TABLE t (Id INT, Pt STRING) PARTITIONED BY (pt) -- worked
CREATE TABLE t (Id INT, A INT) TBLPROPERTIES ('primary-key'='id') -- failed
Resolve both properties against the schema in `SparkCatalog`, honouring the
session's case-sensitivity setting. When case-sensitive analysis is on nothing
changes, and a name matching no column is passed through untouched so Paimon
still reports it as the user wrote it.
This stays on the Spark side on purpose: the exact matching in core is correct
for Flink, whose identifiers are case-sensitive and whose primary keys come from
the resolved DDL constraint rather than an option string.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Purpose
primary-keyandbucket-keyare plain strings inTBLPROPERTIES, so they reach Paimon exactly asthe user typed them and are then matched against the schema exactly. Every other identifier in the
same statement follows
spark.sql.caseSensitive— the partition columns in particular, becauseSpark's analyzer has already resolved them by the time the catalog sees them. That leaves a single
statement obeying two different rules:
Since
spark.sql.caseSensitiveisfalseby default,Idandidare the same identifiereverywhere else in Spark, so this is surprising.
Fix. Resolve both properties against the schema in
SparkCatalog, honouring the session'scase-sensitivity setting:
toInitialSchema— for theprimary-keylist and thebucket-keyoption value.alterTable— forbucket-keyonly;primary-keycannot reach there becausevalidateAlterPropertyalready rejects altering it. The table is loaded only when the propertybeing set is
bucket-key, so otherSET TBLPROPERTIEScalls are unaffected.Two deliberate choices:
spark.sql.caseSensitive=truenothing changes — the exact-match requirement stays.the user wrote it instead of a rewritten one.
Why this stays on the Spark side. The exact matching in core is correct for Flink: its
identifiers are case-sensitive, so
Idandidreally are two different identifiers there, and itsprimary keys come from the resolved
PRIMARY KEYDDL constraint (FlinkCatalogbuilder.primaryKey(table.primaryKeys())) rather than an option string. Changing core would breakthat. This mirrors how Iceberg handles it — a case-sensitivity flag plumbed through the connector
(
SparkUtil.caseSensitive,PartitionSpec.Builder#caseSensitive) rather than exact matching pusheddown into the format. Paimon already has the same precedent on the Spark write path, where
SchemaEvolutionHelperreadsconf.caseSensitiveAnalysis.Side effect worth noting.
bucket-keyvalues are now split on,and trimmed before beingstored, which
primary-keyalready did.'bucket-key' = 'id, sub'previously failed, becauseTableSchema#originalBucketKeyssplits on,without trimming and then looked for a column named" sub". It now works, making the two properties consistent.Not covered here: other options whose values name columns (for example
sequence.field) have thesame shape and could be given the same treatment as a follow-up.
Tests
New
KeyPropertyCaseResolutionTestBasewith concrete suites for Spark 3.2, 3.3, 3.4, 3.5, 4.0 and4.1 — 7 cases, asserting the stored key uses the column's real spelling and that the table is
actually writable and readable afterwards:
primary-key/bucket-keyresolve like every other identifier'primary-key'='id,sub,pt')ALTER TABLE SET TBLPROPERTIESresolvesbucket-keyspark.sql.caseSensitive=truekeeps the exact-match requirementVerified green on Spark 3.2, 3.3, 3.4, 3.5 and 4.0 (7/7 each), and the full
paimon-spark-utmoduleshows no new failures.