szehon-ho commented on code in PR #58002:
URL: https://github.com/apache/spark/pull/58002#discussion_r3807143300


##########
sql/catalyst/src/main/java/org/apache/spark/sql/connector/catalog/functions/BoundFunction.java:
##########
@@ -90,6 +90,41 @@ default boolean isDeterministic() {
    * functions in other catalogs. For example, many catalogs may define a 
"bucket" function with a
    * different implementation. Adding context, like 
"com.mycompany.bucket(string)", is recommended
    * to avoid unintentional collisions.
+   * <p>
+   * Two functions that partition data DIFFERENTLY must NOT return the same 
name. They are
+   * indistinguishable to Spark, which can then treat unrelated data as 
co-partitioned and produce
+   * a join with wrong results, so include whatever tells them apart -- 
argument types, for
+   * instance -- in the name. This is the only requirement here that guards 
results rather than
+   * performance.
+   * <p>
+   * An overriding implementation should keep the name stable across calls, 
and across separate
+   * {@code bind} calls for the same function: Spark binds a function afresh 
every time it converts
+   * a partitioning or ordering reported by a source, so when the two 
instances are not the same
+   * object it has only this name to relate them by when deciding whether two 
sides of a join are
+   * co-partitioned, and so whether a storage-partitioned join can avoid a 
shuffle. An unstable name
+   * is not unsafe -- it just makes overriding pointless, since it relates 
nothing to anything.
+   * <p>
+   * This name answers only that question -- whether two transforms are the 
same PARTITION FUNCTION,
+   * ignoring their arguments, which a join needs because it compares {@code 
bucket(4, left.id)}
+   * against {@code bucket(4, right.id)}. It is deliberately not a complete 
identity for the bound
+   * function: it says nothing about {@link #inputTypes()}, {@link 
#resultType()},
+   * {@link #isResultNullable()}, {@link #isDeterministic()}, a {@link 
ReducibleFunction}'s
+   * reducers, or any other state the implementation carries. For the separate 
question of whether
+   * two partition transform expressions are the same expression, see {@link 
#equals(Object)}.
+   * <p>
+   * The two questions are related in one direction: this name is the COARSER 
of the two, so two
+   * functions that compare equal must return the same canonical name, while 
the same name does not
+   * make them equal. An implementation that overrides {@link #equals(Object)} 
should therefore
+   * override this method as well -- keeping the default while claiming two 
instances are equal says
+   * they are the same expression but not the same partition function, which 
costs it exactly the
+   * co-partitioning the name exists to enable.
+   * <p>
+   * Leaving the default in place is allowed: it opts the function out of 
being recognized as
+   * equivalent to anything, which costs optimizations and nothing else. Two 
instances are never
+   * equivalent, so Spark forgoes co-partitioning between them; and because 
the default is not even
+   * stable across two calls on ONE instance, such a function is not the same 
partition function as
+   * itself, so a partitioning it takes part in can cost a shuffle that a 
stable name would have
+   * avoided. Overriding it is the way out of all of that.

Review Comment:
   can it be shorter like:
   
   ```
   * <p>
   * Two functions that partition data differently must not return the same 
name;
   * Spark may otherwise treat them as co-partitioned.
   * An override should return a stable name across {@code bind} calls.
   * Equal functions must share the same canonical name; the reverse is not 
true.
   * For whether two transform expressions are the same expression, see
   * {@link #equals(Object)}.
   ```



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