Peter Toth created SPARK-59176:
----------------------------------

             Summary: Reduced partition keys report the un-reduced data types 
when the partitioning has no key
                 Key: SPARK-59176
                 URL: https://issues.apache.org/jira/browse/SPARK-59176
             Project: Spark
          Issue Type: Bug
          Components: SQL
    Affects Versions: 5.0.0
            Reporter: Peter Toth


{{KeyedPartitioning.keyDataTypes}} falls back to the partition expressions' own 
data types when the partitioning has no partition key:

{code:scala}
@transient lazy val keyDataTypes: Seq[DataType] =
  partitionKeys.headOption.map(_.dataTypes).getOrElse(expressionDataTypes)
{code}

That fallback is not truthful once a storage-partitioned join has reduced both 
sides' keys onto a common key space. The partitioning then reports an 
expression that no longer describes its keys, so the fallback hands back the 
un-reduced transform's type while the other leg of the same reduce reports the 
reducer's result type.

A partitioning can reach that state with no key at all: with 
{{spark.sql.sources.v2.bucketing.partition.filter.enabled}} an inner join whose 
two sides hold disjoint keys intersects to none.

h3. Repro

Four tables over {{(id, ts)}}, with a {{days}} and a {{years}} function whose 
reducers both produce {{LongType}}:

* {{days1}} and {{years1}} hold 2020 and 2021, so that leg keeps its keys.
* {{days2}} holds only 2020 and {{years2}} only 2021, so that leg intersects to 
no key.

Join {{days1}} to {{years1}} and {{days2}} to {{years2}}, then join the two 
legs on {{ts}}, with {{pushPartValues}}, {{partition.filter.enabled}}, 
{{allowKeysSubsetOfPartitionKeys}} and {{allowCompatibleTransforms}} all 
enabled.

The correct answer is empty. Instead the query fails at planning with 
{{STORAGE_PARTITION_JOIN_INCOMPATIBLE_REDUCED_TYPES}}: the empty leg 
contributes {{DateType}} from {{days(ts)}}, the other {{LongType}} from the 
reducer, and {{EnsureRequirements}}' reduced-types check compares the two.

h3. Notes

The untruthful fallback arrived with SPARK-59120. The failure at the 
reduced-types check becomes reachable through SPARK-59121, which stops deriving 
a second reducer from an already reduced pair, so both sides read 
{{keyDataTypes}} directly. Before SPARK-59121 the same query failed too, with a 
{{ClassCastException}} from applying a reducer to already reduced values, so 
this is not a regression in either change. Found while reviewing SPARK-59121 
(apache/spark#58447) and documented in the {{keyDataTypes}} scaladoc there.

h3. Two ways to fix it

# Record the reducer's {{resultType()}} alongside the pairing in 
{{TransformExpression.reducedWith}}, so {{keyDataTypes}} stays truthful with no 
key to read.
# Let the reduced-types check in {{EnsureRequirements}} tolerate a side that 
has no partition key, since such a side has no key type to contribute.




--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to