dongjoon-hyun commented on code in PR #59165:
URL: https://github.com/apache/spark/pull/59165#discussion_r4168744978


##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/plans/physical/partitioning.scala:
##########
@@ -2086,6 +2119,48 @@ case class KeyedShuffleSpec(
     }
   }
 
+  /**
+   * Whether every argument of `transform` is a bare column. 
`isExpressionCompatible` asks it of
+   * both sides before it compares anything, `canCreatePartitioning` asks it 
of a template, and
+   * `rebuiltOver` asserts it.
+   *
+   * `keyPositions` pairs two sides up by the column each expression 
references. That pairing
+   * describes one key space when the argument is the column itself. 
`bucket(4, b + 1)` is a
+   * function of `b`, but not the same function of it as `bucket(4, x)` is of 
`x`. Nor is
+   * `bucket(4, s.a)` the same function of `s` as `bucket(4, t.b)` is of `t`. 
So such a transform
+   * pairs only with a transform over the same `argumentShape`. Over the same 
shape, the two
+   * compare as two transforms of columns do, e.g. `bucket(4, b + 1)` with 
`bucket(4, c + 1)` on a
+   * join `b = c`. A reduce of `bucket(8, b + 1)` onto `bucket(4, c + 1)` is 
fine too, since it
+   * maps the partition keys and evaluates no argument. An identity side is 
not reduced onto such a
+   * transform, since that would evaluate `id + 1` on keys the query never 
computes it for, which
+   * can overflow.
+   */
+  private def argumentsAreColumns(transform: TransformExpression): Boolean =
+    transform.children.forall(_.isInstanceOf[Attribute])
+
+  /**
+   * `transform` with its argument replaced by `column`. Only a transform of 
bare columns can be
+   * rebuilt this way. Any other argument would lose what surrounds its 
column, e.g. the `+ 1` of
+   * `bucket(4, b + 1)`.
+   */
+  private def rebuiltOver(transform: TransformExpression, column: Expression)

Review Comment:
   Nit: the parameter name says that the replacement is a column, but only the 
source has to be one, which is what the assert checks. `createPartitioning` 
passes the other child's join key at L2298, and that is an expression in 
exactly the cases this PR handles: `bucket(4, t1.id)` becomes `bucket(4, p.b + 
1)`, as the same-shape tests in `KeyGroupedPartitioningSuite` expect. Could it 
be named `key`, with the doc saying "`transform`, whose arguments are bare 
columns, with each replaced by `key`, which may be any expression"?



##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/plans/physical/partitioning.scala:
##########
@@ -1941,8 +1949,20 @@ case class KeyedShuffleSpec(
    * `KeyedPartitioning.positionsCoveringClusterKeys` counts it. See that 
method for why the two
    * stay apart.
    *
-   * The assertion is what makes the reference reading sound. With one 
reference per expression,
-   * "some reference is a cluster key" and "every reference is" are the same 
statement.
+   * Only an expression with a single reference maps to a position. With one 
reference, "some
+   * reference is a cluster key" and "every reference is" are the same 
statement, which is what
+   * makes the reference reading sound. A scan reports no other expression
+   * (`KeyedPartitioning.supportsExpressions`), but two planner paths build 
one over the other

Review Comment:
   Minor: a scan cannot report a transform of a struct field either, so the 
cost that the PR description lists for "a scan that reports a bucket of a 
struct field, e.g. `bucket(4, s.a)`" does not seem to arise. 
`V2ExpressionUtils.resolveRef` resolves `s.a` through `LogicalPlan.resolve`, 
which wraps a nested field in an `Alias` (package.scala:405-410). So the scan's 
transform is over an `Alias`, which `supportsExpressions` (L1110-L1117) 
refuses, since it accepts only an `Attribute` or a `GetStructField` chain. 
`DataSourceV2ScanExecBase` then reports no `KeyedPartitioning` 
(DataSourceV2ScanExecBase.scala:105), and I found nothing in between that 
strips the alias. Such a table gets no storage-partitioned join on master 
either, which would also explain why the in-memory catalog cannot test it. 
Could the description drop that bullet, or say that such layouts come only from 
joins? I traced this but did not run it.



-- 
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]

Reply via email to