yashmayya commented on code in PR #19988:
URL: https://github.com/apache/pinot/pull/19988#discussion_r4393063450


##########
pinot-query-planner/src/main/java/org/apache/pinot/calcite/rel/rules/PinotRuleUtils.java:
##########
@@ -85,6 +89,45 @@ public static RelNode unboxRel(RelNode rel) {
     }
   }
 
+  /// Appends aggregate literal arguments without hiding literals already 
projected beneath a union. If a union has
+  /// no projected literals, keeps one project above it; otherwise recurses 
through nested unions to their projects.
+  public static RelNode appendAggregateLiterals(RelNode input, List<RexNode> 
literals) {
+    return appendAggregateLiterals(input, literals, false);
+  }
+
+  private static RelNode appendAggregateLiterals(RelNode input, List<RexNode> 
literals, boolean insideUnion) {
+    RelNode rel = unboxRel(input);
+    if (rel instanceof Union && (insideUnion || hasProjectedLiterals(rel))) {

Review Comment:
   `hasProjectedLiterals` is true for any literal in any union input, for 
example a tag column `'a' AS src`. In that case the type and approx literals 
move into the union inputs, and these queries that work on master now fail:
   ```sql
   -- planning error: ANYVALUE expects a literal data type argument, got: null
   SET inferAnyValueType=true;
   SELECT src, ANY_VALUE(x) FROM (SELECT 'a' src, int_col x FROM t UNION ALL 
SELECT 'b', int_col FROM t2) GROUP BY src
   
   -- NPE "blockTimeSet is null": findImmediateProjects uses input 0's literal 
for every input
   SELECT LASTWITHTIME(x, t) FROM (SELECT int_col x, CAST('2019-01-01 00:00:00' 
AS TIMESTAMP) t FROM t
     UNION ALL SELECT int_col, ts_col FROM t2)
   
   -- approx params on, NPE "blockValSet is null"
   SELECT DISTINCTCOUNT(x), COVARPOP(x, y) FROM (SELECT int_col x, 1.0 y FROM t
     UNION ALL SELECT int_col, CAST(long_col AS DOUBLE) FROM t2)
   
   -- v1 skip-leaf: Invalid aggregation function: mode($1,$2,$3)
   SELECT /*+ aggOptions(is_skip_leaf_stage_group_by='true') */ src, k, MODE(s) 
FROM (
     SELECT 'a' src, int_col k, string_col s FROM t UNION ALL SELECT 'b', 
int_col, string_col FROM t2)
   WHERE k = 2 GROUP BY src, k
   ```
   Other tagged-union queries give the same results, but each row now carries 
the constant columns through every union-input exchange.
   
   Suggestion, either:
   - push into the union inputs only when an aggregate call already has a 
literal argument (position 1 or later) that `findImmediateProjects` reads 
through the union, not for any projected literal; or
   - never push into the inputs: keep one project above the union, and write a 
column there as a literal when every input projects the same literal for it.
   
   I tested both locally. Each gives 0 regressions against master and keeps all 
your fixes. Please add these queries as tests.



##########
pinot-core/src/main/java/org/apache/pinot/core/query/optimizer/statement/AggregateFunctionRewriteOptimizer.java:
##########
@@ -112,6 +113,10 @@ private static void rewrite(@Nullable Expression 
expression, Schema schema, bool
       }
       return;
     }
+    if (normalizedName.equals(AggregationFunctionType.ARRAYAGG.name()) && 
isArrayAggWithoutDataType(function)) {

Review Comment:
   SSE wrong results: `SELECT ARRAY_AGG(DISTINCT intCol) FROM t` now runs but 
returns duplicates. On master it fails with `expects 2 or 3 arguments`. 
`CalciteSqlParser` drops the DISTINCT quantifier for `SqlKind.ARRAY_AGG` (it 
handles DISTINCT only for OTHER_FUNCTION), so this rewrite makes it a plain 
`arrayagg(intCol,'INT')`. The GROUP BY form and `ARRAY_AGG(DISTINCT intCol, 
false)` have the same problem. MSE now returns distinct values for the same 
SQL, so the two engines disagree.
   
   Suggestion: in `CalciteSqlParser`, turn DISTINCT on ARRAY_AGG into 
`isDistinct = true` (append the flag or replace it), as MSE does. That also 
fixes `ARRAY_AGG(DISTINCT col, 'INT')`, which returns duplicates on master. To 
keep the explicit form unchanged instead, reject DISTINCT on ARRAY_AGG in SSE. 
Please add an SSE test.



##########
pinot-query-planner/src/main/java/org/apache/pinot/query/QueryEnvironment.java:
##########
@@ -610,10 +610,14 @@ private static HepProgram getOptProgram(PinotRuleSet 
ruleSet, Set<String> skipRu
     // Run the Calcite CORE rules using 1 HepInstruction per rule. We use 1 
HepInstruction per rule for simplicity:
     // the rules used here can rest assured that they are the only ones 
evaluated in a dedicated graph-traversal.
     for (RelOptRule relOptRule : basicRules) {
+      // Supplies the data type argument before AggregateCaseToFilter, which 
rewrites only one-argument calls: its
+      // ARRAY_AGG(expression) FILTER (WHERE condition) form of ARRAY_AGG(CASE 
WHEN ...) fails at runtime.
+      if 
(relOptRule.toString().equals(CommonConstants.Broker.PlannerRuleNames.AGGREGATE_CASE_TO_FILTER))
 {
+        
hepProgramBuilder.addRuleInstance(PinotAggregateTypeArgumentRewriteRule.WITHOUT_ANY_VALUE);

Review Comment:
   Wrong results: this early instance also rewrites `MODE(stringExpr)` to 3 
args before `AggregateCaseToFilter` runs. So `MODE(CASE WHEN c THEN s END)` 
keeps its CASE and does not become `MODE(s) FILTER (WHERE c)`. With null 
handling off (the default), the rows that do not match count as `''`:
   ```sql
   SELECT MODE(CASE WHEN int_col > 3 THEN string_col END) FROM tbl   -- master: 
'c', PR: ''
   ```
   The GROUP BY, skip-leaf, FILTER and JSON forms change the same way in v1, v2 
and lite mode.
   
   Suggestion: make the early instance rewrite only ARRAY_AGG, for example with 
a separate rule instance. Then MODE and FIRST/LAST_WITH_TIME plan as on master.



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