This is an automated email from the ASF dual-hosted git repository.

laszlog pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/impala.git

commit 88275f327fb2b52db13d1ffa1db8fafd08875941
Author: Minghui Zhu <[email protected]>
AuthorDate: Wed Apr 19 11:54:25 2023 +0000

    IMPALA-12051: Propagate analytic tuple predicates of outer-joined InlineView
    
    In some cases, direct pushing down predicates that reference analytic
    tuple into inline view leads to incorrect query results. While pushing
    down analytic predicates (e.g. row_number() < 10), we should also divide
    them into two groups. Some of them can be migrated into the view so are
    removed in the current scope. Some of them can be copied into the view
    but still need to be evaluated in the current scope as demonstrated with
    the following query. The bug is due to we migrate all of them into the
    view.
    
      WITH detail_measure AS (
        SELECT
          *
        FROM
          (
            VALUES
              (
                1 AS `isqbiuar`,
                1 AS `bgsfrbun`,
                1 AS `result_type`,
                1 AS `bjuzzevg`
              ),
              (2, 2, 2, 2)
          ) a
      ),
      order_measure_sql0 AS (
        SELECT
          row_number() OVER (
            ORDER BY
              row_number_0 DESC NULLS LAST,
              isqbiuar ASC NULLS LAST
          ) AS `row_number_0`,
          `isqbiuar`
        FROM
          (
            VALUES
              (1 AS `row_number_0`, 1 AS `isqbiuar`),
              (2, 2)
          ) b
      )
      SELECT
        detail_measure.`isqbiuar` AS `isqbiuar`,
        detail_measure.`bgsfrbun` AS `bgsfrbun`,
        detail_measure.`result_type` AS `result_type`,
        detail_measure.`bjuzzevg` AS `bjuzzevg`,
        `row_number_0` AS `row_number_0`
      FROM
        detail_measure
        LEFT JOIN order_measure_sql0
        ON order_measure_sql0.isqbiuar = detail_measure.isqbiuar
      WHERE
        row_number_0 BETWEEN 1
        AND 1
      ORDER BY
        `row_number_0` ASC NULLS LAST,
        `bgsfrbun` ASC NULLS LAST
    
    The current incorrect result is:
    +----------+----------+-------------+----------+--------------+
    | isqbiuar | bgsfrbun | result_type | bjuzzevg | row_number_0 |
    +----------+----------+-------------+----------+--------------+
    | 2        | 2        | 2           | 2        | 1            |
    | 1        | 1        | 1           | 1        | NULL         |
    +----------+----------+-------------+----------+--------------+
    
    The correct result is:
    +----------+----------+-------------+----------+--------------+
    | isqbiuar | bgsfrbun | result_type | bjuzzevg | row_number_0 |
    +----------+----------+-------------+----------+--------------+
    | 2        | 2        | 2           | 2        | 1            |
    +----------+----------+-------------+----------+--------------+
    
    In the plan, the analysis predicate is pushed down to the TOP-N node,
    but not in the HASH JOIN node, which leads to incorrect results.
    
      ...
    
      05:HASH JOIN [RIGHT OUTER JOIN]
      |  hash predicates: isqbiuar = isqbiuar
      |  row-size=14B cardinality=2
    
      ...
    
      02:TOP-N [LIMIT=1]
      |  order by: row_number_0 DESC NULLS LAST, isqbiuar ASC NULLS LAST
      |  source expr: row_number() <= CAST(1 AS BIGINT)
      |  row-size=2B cardinality=1
    
      ...
    
    The HASH JOIN node shoud be:
    
      05:HASH JOIN [RIGHT OUTER JOIN]
      |  hash predicates: isqbiuar = isqbiuar
      |  other predicates: row_number() <= 1, row_number() >= 1
      |  row-size=14B cardinality=2
    
    Tests:
    * Add plan tests in analytic-rank-pushdown.test
    * Add e2e tests in analytic-fns.test
    
    Change-Id: If6c209b2a64bad37d893ba8b520342bf1f9a7513
    Reviewed-on: http://gerrit.cloudera.org:8080/19768
    Reviewed-by: Impala Public Jenkins <[email protected]>
    Tested-by: Impala Public Jenkins <[email protected]>
---
 .../apache/impala/planner/SingleNodePlanner.java   |  66 ++--
 .../PlannerTest/analytic-rank-pushdown.test        | 434 +++++++++++++++++++++
 .../queries/QueryTest/analytic-fns.test            |  84 ++++
 3 files changed, 553 insertions(+), 31 deletions(-)

diff --git a/fe/src/main/java/org/apache/impala/planner/SingleNodePlanner.java 
b/fe/src/main/java/org/apache/impala/planner/SingleNodePlanner.java
index 71c7af2e5..9437fddf6 100644
--- a/fe/src/main/java/org/apache/impala/planner/SingleNodePlanner.java
+++ b/fe/src/main/java/org/apache/impala/planner/SingleNodePlanner.java
@@ -1308,9 +1308,8 @@ public class SingleNodePlanner {
    * inline view, add it to 'evalAfterJoinPreds'.
    */
   private void getConjunctsToInlineView(final Analyzer analyzer, final String 
alias,
-      final List<TupleId> tupleIds, List<Expr> evalInInlineViewPreds,
-      List<Expr> evalAfterJoinPreds) {
-    List<Expr> unassignedConjuncts = analyzer.getUnassignedConjuncts(tupleIds, 
true);
+      final List<TupleId> tupleIds, final List<Expr> unassignedConjuncts,
+      List<Expr> evalInInlineViewPreds, List<Expr> evalAfterJoinPreds) {
     for (Expr e: unassignedConjuncts) {
       if (!e.isBoundByTupleIds(tupleIds)) continue;
       List<TupleId> tids = new ArrayList<>();
@@ -1391,37 +1390,14 @@ public class SingleNodePlanner {
       List<Expr> analyticPreds = findAnalyticConjunctsToMigrate(analyzer, 
inlineViewRef,
               unassignedConjuncts);
       if (analyticPreds.size() > 0) {
-        if (LOG.isTraceEnabled()) {
-          LOG.trace("Migrate analytic predicates into view " +
-              Expr.debugString(analyticPreds));
-        }
-        analyzer.markConjunctsAssigned(analyticPreds);
-        unassignedConjuncts.removeAll(analyticPreds);
-        addConjunctsIntoInlineView(analyzer, inlineViewRef, analyticPreds);
+        migrateOrCopyConjunctsToInlineView(analyzer, inlineViewRef, tids,
+            analyticPreds, unassignedConjuncts);
       }
-
-      // mark (fully resolve) slots referenced by unassigned conjuncts as
-      // materialized
-      List<Expr> substUnassigned = Expr.substituteList(unassignedConjuncts,
-          inlineViewRef.getBaseTblSmap(), analyzer, false);
-      analyzer.materializeSlots(substUnassigned);
-      return;
+    } else {
+      migrateOrCopyConjunctsToInlineView(analyzer, inlineViewRef, tids,
+          unassignedConjuncts, unassignedConjuncts);
     }
 
-    List<Expr> preds = new ArrayList<>();
-    List<Expr> evalAfterJoinPreds = new ArrayList<>();
-    getConjunctsToInlineView(analyzer, inlineViewRef.getExplicitAlias(), tids, 
preds,
-        evalAfterJoinPreds);
-    unassignedConjuncts.removeAll(preds);
-    // Migrate the conjuncts by marking the original ones as assigned. They 
will either
-    // be ignored if they are identity predicates (e.g. a = a), or be 
substituted into
-    // new ones (viewPredicates below). The substituted ones will be 
re-registered.
-    analyzer.markConjunctsAssigned(preds);
-    // Propagate the conjuncts evaluating the nullable side of outer-join.
-    // Don't mark them as assigned so they would be assigned at the JOIN node.
-    preds.addAll(evalAfterJoinPreds);
-    addConjunctsIntoInlineView(analyzer, inlineViewRef, preds);
-
     // mark (fully resolve) slots referenced by remaining unassigned conjuncts 
as
     // materialized
     List<Expr> substUnassigned = Expr.substituteList(unassignedConjuncts,
@@ -1429,6 +1405,34 @@ public class SingleNodePlanner {
     analyzer.materializeSlots(substUnassigned);
   }
 
+  /**
+   * Migrate or copy unassigned conjuncts into an inline view. Parameter 
evalPreds is
+   * analytic predicates when there has specific analytic, equals to 
unassignedConjuncts
+   * when there has no LIMIT/OFFSET or anylitic functions.
+   */
+  private void migrateOrCopyConjunctsToInlineView(final Analyzer analyzer,
+      final InlineViewRef inlineViewRef, final List<TupleId> tids,
+      List<Expr> evalPreds, List<Expr> unassignedConjuncts)
+      throws ImpalaException {
+    List<Expr> evalInInlineViewPreds = new ArrayList<>();
+    List<Expr> evalAfterJoinPreds = new ArrayList<>();
+    getConjunctsToInlineView(analyzer, inlineViewRef.getExplicitAlias(), tids,
+        evalPreds, evalInInlineViewPreds, evalAfterJoinPreds);
+    if (LOG.isTraceEnabled()) {
+      LOG.trace("Assign predicates for view: migrating {}, coping {}.",
+          Expr.debugString(evalInInlineViewPreds), 
Expr.debugString(evalAfterJoinPreds));
+    }
+    unassignedConjuncts.removeAll(evalInInlineViewPreds);
+    // Migrate the conjuncts by marking the original ones as assigned. They 
will either
+    // be ignored if they are identity predicates (e.g. a = a), or be 
substituted into
+    // new ones. The substituted ones will be re-registered.
+    analyzer.markConjunctsAssigned(evalInInlineViewPreds);
+    // Propagate the conjuncts evaluating the nullable side of outer-join.
+    // Don't mark them as assigned so they can be assigned at the JOIN node.
+    evalInInlineViewPreds.addAll(evalAfterJoinPreds);
+    addConjunctsIntoInlineView(analyzer, inlineViewRef, evalInInlineViewPreds);
+  }
+
   /**
    * Return any conjuncts in 'conjuncts' that reference analytic exprs in 
'inlineViewRef'
    * and can be safely migrated into 'inlineViewRef', even if
diff --git 
a/testdata/workloads/functional-planner/queries/PlannerTest/analytic-rank-pushdown.test
 
b/testdata/workloads/functional-planner/queries/PlannerTest/analytic-rank-pushdown.test
index 8ec8bd38e..63e728efd 100644
--- 
a/testdata/workloads/functional-planner/queries/PlannerTest/analytic-rank-pushdown.test
+++ 
b/testdata/workloads/functional-planner/queries/PlannerTest/analytic-rank-pushdown.test
@@ -1676,3 +1676,437 @@ PLAN-ROOT SINK
    predicates: int_col = 1
    row-size=23B cardinality=11
 ====
+# Analytic predicate can only be copied to inline view.
+select a.id, rnk from functional.alltypesagg a
+left join (
+    select id, row_number() over (order by string_col desc) as rnk
+    from functional.alltypesagg
+) b on a.id = b.id where rnk < 100
+---- PLAN
+PLAN-ROOT SINK
+|
+05:HASH JOIN [LEFT OUTER JOIN]
+|  hash predicates: a.id = id
+|  other predicates: row_number() < 100
+|  row-size=31B cardinality=11.00K
+|
+|--04:SELECT
+|  |  predicates: row_number() < 100
+|  |  row-size=27B cardinality=99
+|  |
+|  03:ANALYTIC
+|  |  functions: row_number()
+|  |  order by: string_col DESC
+|  |  window: ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
+|  |  row-size=27B cardinality=99
+|  |
+|  02:TOP-N [LIMIT=99]
+|  |  order by: string_col DESC
+|  |  source expr: row_number() < CAST(100 AS BIGINT)
+|  |  row-size=19B cardinality=99
+|  |
+|  01:SCAN HDFS [functional.alltypesagg]
+|     HDFS partitions=11/11 files=11 size=814.73KB
+|     row-size=19B cardinality=11.00K
+|
+00:SCAN HDFS [functional.alltypesagg a]
+   HDFS partitions=11/11 files=11 size=814.73KB
+   row-size=4B cardinality=11.00K
+---- DISTRIBUTEDPLAN
+PLAN-ROOT SINK
+|
+08:EXCHANGE [UNPARTITIONED]
+|
+05:HASH JOIN [LEFT OUTER JOIN, BROADCAST]
+|  hash predicates: a.id = id
+|  other predicates: row_number() < 100
+|  row-size=31B cardinality=11.00K
+|
+|--07:EXCHANGE [BROADCAST]
+|  |
+|  04:SELECT
+|  |  predicates: row_number() < 100
+|  |  row-size=27B cardinality=99
+|  |
+|  03:ANALYTIC
+|  |  functions: row_number()
+|  |  order by: string_col DESC
+|  |  window: ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
+|  |  row-size=27B cardinality=99
+|  |
+|  06:MERGING-EXCHANGE [UNPARTITIONED]
+|  |  order by: string_col DESC
+|  |  limit: 99
+|  |
+|  02:TOP-N [LIMIT=99]
+|  |  order by: string_col DESC
+|  |  source expr: row_number() < CAST(100 AS BIGINT)
+|  |  row-size=19B cardinality=99
+|  |
+|  01:SCAN HDFS [functional.alltypesagg]
+|     HDFS partitions=11/11 files=11 size=814.73KB
+|     row-size=19B cardinality=11.00K
+|
+00:SCAN HDFS [functional.alltypesagg a]
+   HDFS partitions=11/11 files=11 size=814.73KB
+   row-size=4B cardinality=11.00K
+====
+# Analytic predicate can only be copied when outer-joined inline view is with 
statement.
+with b as (select id, row_number() over (order by string_col desc) as rnk
+    from functional.alltypesagg)
+select a.id, rnk from functional.alltypesagg a
+left join b on a.id = b.id where rnk < 100
+---- PLAN
+PLAN-ROOT SINK
+|
+05:HASH JOIN [LEFT OUTER JOIN]
+|  hash predicates: a.id = id
+|  other predicates: row_number() < 100
+|  row-size=31B cardinality=11.00K
+|
+|--04:SELECT
+|  |  predicates: row_number() < 100
+|  |  row-size=27B cardinality=99
+|  |
+|  03:ANALYTIC
+|  |  functions: row_number()
+|  |  order by: string_col DESC
+|  |  window: ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
+|  |  row-size=27B cardinality=99
+|  |
+|  02:TOP-N [LIMIT=99]
+|  |  order by: string_col DESC
+|  |  source expr: row_number() < CAST(100 AS BIGINT)
+|  |  row-size=19B cardinality=99
+|  |
+|  01:SCAN HDFS [functional.alltypesagg]
+|     HDFS partitions=11/11 files=11 size=814.73KB
+|     row-size=19B cardinality=11.00K
+|
+00:SCAN HDFS [functional.alltypesagg a]
+   HDFS partitions=11/11 files=11 size=814.73KB
+   row-size=4B cardinality=11.00K
+---- DISTRIBUTEDPLAN
+PLAN-ROOT SINK
+|
+08:EXCHANGE [UNPARTITIONED]
+|
+05:HASH JOIN [LEFT OUTER JOIN, BROADCAST]
+|  hash predicates: a.id = id
+|  other predicates: row_number() < 100
+|  row-size=31B cardinality=11.00K
+|
+|--07:EXCHANGE [BROADCAST]
+|  |
+|  04:SELECT
+|  |  predicates: row_number() < 100
+|  |  row-size=27B cardinality=99
+|  |
+|  03:ANALYTIC
+|  |  functions: row_number()
+|  |  order by: string_col DESC
+|  |  window: ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
+|  |  row-size=27B cardinality=99
+|  |
+|  06:MERGING-EXCHANGE [UNPARTITIONED]
+|  |  order by: string_col DESC
+|  |  limit: 99
+|  |
+|  02:TOP-N [LIMIT=99]
+|  |  order by: string_col DESC
+|  |  source expr: row_number() < CAST(100 AS BIGINT)
+|  |  row-size=19B cardinality=99
+|  |
+|  01:SCAN HDFS [functional.alltypesagg]
+|     HDFS partitions=11/11 files=11 size=814.73KB
+|     row-size=19B cardinality=11.00K
+|
+00:SCAN HDFS [functional.alltypesagg a]
+   HDFS partitions=11/11 files=11 size=814.73KB
+   row-size=4B cardinality=11.00K
+====
+# Analytic predicate cannot be pushed down when outer-joined inline view is 
union statement.
+select * from functional.alltypesagg a
+left join
+(select a.id, row_number() over (order by a.string_col desc) as rnk from 
functional.alltypesagg a
+union select b.id, row_number() over (order by b.string_col desc) as rnk from 
functional.alltypesagg b) b
+on a.id = b.id
+where b.rnk < 100
+---- PLAN
+PLAN-ROOT SINK
+|
+09:HASH JOIN [LEFT OUTER JOIN]
+|  hash predicates: a.id = id
+|  other predicates: rnk < 100
+|  row-size=107B cardinality=11.00K
+|
+|--08:AGGREGATE [FINALIZE]
+|  |  group by: id, rnk
+|  |  having: rnk < 100
+|  |  row-size=12B cardinality=2.20K
+|  |
+|  01:UNION
+|  |  row-size=12B cardinality=22.00K
+|  |
+|  |--07:ANALYTIC
+|  |  |  functions: row_number()
+|  |  |  order by: string_col DESC
+|  |  |  window: ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
+|  |  |  row-size=27B cardinality=11.00K
+|  |  |
+|  |  06:SORT
+|  |  |  order by: string_col DESC
+|  |  |  row-size=19B cardinality=11.00K
+|  |  |
+|  |  05:SCAN HDFS [functional.alltypesagg b]
+|  |     HDFS partitions=11/11 files=11 size=814.73KB
+|  |     row-size=19B cardinality=11.00K
+|  |
+|  04:ANALYTIC
+|  |  functions: row_number()
+|  |  order by: string_col DESC
+|  |  window: ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
+|  |  row-size=27B cardinality=11.00K
+|  |
+|  03:SORT
+|  |  order by: string_col DESC
+|  |  row-size=19B cardinality=11.00K
+|  |
+|  02:SCAN HDFS [functional.alltypesagg a]
+|     HDFS partitions=11/11 files=11 size=814.73KB
+|     row-size=19B cardinality=11.00K
+|
+00:SCAN HDFS [functional.alltypesagg a]
+   HDFS partitions=11/11 files=11 size=814.73KB
+   row-size=95B cardinality=11.00K
+---- DISTRIBUTEDPLAN
+PLAN-ROOT SINK
+|
+13:EXCHANGE [UNPARTITIONED]
+|
+09:HASH JOIN [LEFT OUTER JOIN, BROADCAST]
+|  hash predicates: a.id = id
+|  other predicates: rnk < 100
+|  row-size=107B cardinality=11.00K
+|
+|--12:EXCHANGE [BROADCAST]
+|  |
+|  08:AGGREGATE [FINALIZE]
+|  |  group by: id, rnk
+|  |  having: rnk < 100
+|  |  row-size=12B cardinality=2.20K
+|  |
+|  01:UNION
+|  |  row-size=12B cardinality=22.00K
+|  |
+|  |--07:ANALYTIC
+|  |  |  functions: row_number()
+|  |  |  order by: string_col DESC
+|  |  |  window: ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
+|  |  |  row-size=27B cardinality=11.00K
+|  |  |
+|  |  11:MERGING-EXCHANGE [UNPARTITIONED]
+|  |  |  order by: string_col DESC
+|  |  |
+|  |  06:SORT
+|  |  |  order by: string_col DESC
+|  |  |  row-size=19B cardinality=11.00K
+|  |  |
+|  |  05:SCAN HDFS [functional.alltypesagg b]
+|  |     HDFS partitions=11/11 files=11 size=814.73KB
+|  |     row-size=19B cardinality=11.00K
+|  |
+|  04:ANALYTIC
+|  |  functions: row_number()
+|  |  order by: string_col DESC
+|  |  window: ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
+|  |  row-size=27B cardinality=11.00K
+|  |
+|  10:MERGING-EXCHANGE [UNPARTITIONED]
+|  |  order by: string_col DESC
+|  |
+|  03:SORT
+|  |  order by: string_col DESC
+|  |  row-size=19B cardinality=11.00K
+|  |
+|  02:SCAN HDFS [functional.alltypesagg a]
+|     HDFS partitions=11/11 files=11 size=814.73KB
+|     row-size=19B cardinality=11.00K
+|
+00:SCAN HDFS [functional.alltypesagg a]
+   HDFS partitions=11/11 files=11 size=814.73KB
+   row-size=95B cardinality=11.00K
+====
+# Analytic predicate can only be copied when inline view contains outer join.
+select * from functional.alltypesagg a
+left join
+(select a.id, row_number() over (order by a.string_col desc) as rnk from 
functional.alltypesagg a
+left join functional.alltypesagg b on a.id = b.id) b
+on a.id = b.id
+where b.rnk < 100
+---- PLAN
+PLAN-ROOT SINK
+|
+07:HASH JOIN [LEFT OUTER JOIN]
+|  hash predicates: a.id = id
+|  other predicates: row_number() < 100
+|  row-size=126B cardinality=11.00K
+|
+|--06:SELECT
+|  |  predicates: row_number() < 100
+|  |  row-size=31B cardinality=99
+|  |
+|  05:ANALYTIC
+|  |  functions: row_number()
+|  |  order by: string_col DESC
+|  |  window: ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
+|  |  row-size=31B cardinality=99
+|  |
+|  04:TOP-N [LIMIT=99]
+|  |  order by: string_col DESC
+|  |  source expr: row_number() < CAST(100 AS BIGINT)
+|  |  row-size=23B cardinality=99
+|  |
+|  03:HASH JOIN [LEFT OUTER JOIN]
+|  |  hash predicates: a.id = b.id
+|  |  row-size=23B cardinality=11.77K
+|  |
+|  |--02:SCAN HDFS [functional.alltypesagg b]
+|  |     HDFS partitions=11/11 files=11 size=814.73KB
+|  |     row-size=4B cardinality=11.00K
+|  |
+|  01:SCAN HDFS [functional.alltypesagg a]
+|     HDFS partitions=11/11 files=11 size=814.73KB
+|     row-size=19B cardinality=11.00K
+|
+00:SCAN HDFS [functional.alltypesagg a]
+   HDFS partitions=11/11 files=11 size=814.73KB
+   row-size=95B cardinality=11.00K
+---- DISTRIBUTEDPLAN
+PLAN-ROOT SINK
+|
+12:EXCHANGE [UNPARTITIONED]
+|
+07:HASH JOIN [LEFT OUTER JOIN, BROADCAST]
+|  hash predicates: a.id = id
+|  other predicates: row_number() < 100
+|  row-size=126B cardinality=11.00K
+|
+|--11:EXCHANGE [BROADCAST]
+|  |
+|  06:SELECT
+|  |  predicates: row_number() < 100
+|  |  row-size=31B cardinality=99
+|  |
+|  05:ANALYTIC
+|  |  functions: row_number()
+|  |  order by: string_col DESC
+|  |  window: ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
+|  |  row-size=31B cardinality=99
+|  |
+|  10:MERGING-EXCHANGE [UNPARTITIONED]
+|  |  order by: string_col DESC
+|  |  limit: 99
+|  |
+|  04:TOP-N [LIMIT=99]
+|  |  order by: string_col DESC
+|  |  source expr: row_number() < CAST(100 AS BIGINT)
+|  |  row-size=23B cardinality=99
+|  |
+|  03:HASH JOIN [LEFT OUTER JOIN, PARTITIONED]
+|  |  hash predicates: a.id = b.id
+|  |  row-size=23B cardinality=11.77K
+|  |
+|  |--09:EXCHANGE [HASH(b.id)]
+|  |  |
+|  |  02:SCAN HDFS [functional.alltypesagg b]
+|  |     HDFS partitions=11/11 files=11 size=814.73KB
+|  |     row-size=4B cardinality=11.00K
+|  |
+|  08:EXCHANGE [HASH(a.id)]
+|  |
+|  01:SCAN HDFS [functional.alltypesagg a]
+|     HDFS partitions=11/11 files=11 size=814.73KB
+|     row-size=19B cardinality=11.00K
+|
+00:SCAN HDFS [functional.alltypesagg a]
+   HDFS partitions=11/11 files=11 size=814.73KB
+   row-size=95B cardinality=11.00K
+====
+# Analytic predicate can be pushed down when there are more predicates.
+# Only the analytic predicate can be pushed down.
+select * from functional.alltypesagg a
+left join
+(select a.id + 1 as id, row_number() over (order by a.string_col desc) as rnk, 
length(string_col) AS len
+from functional.alltypesagg a) b
+on a.id = b.id
+where b.rnk < 100 and b.len = 0 and b.id > 0
+---- PLAN
+PLAN-ROOT SINK
+|
+05:HASH JOIN [LEFT OUTER JOIN]
+|  hash predicates: a.id = id + 1
+|  other predicates: row_number() < 100, length(string_col) = 0, id + 1 > 0
+|  row-size=122B cardinality=11.00K
+|
+|--04:SELECT
+|  |  predicates: row_number() < 100
+|  |  row-size=27B cardinality=99
+|  |
+|  03:ANALYTIC
+|  |  functions: row_number()
+|  |  order by: string_col DESC
+|  |  window: ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
+|  |  row-size=27B cardinality=99
+|  |
+|  02:TOP-N [LIMIT=99]
+|  |  order by: string_col DESC
+|  |  source expr: row_number() < CAST(100 AS BIGINT)
+|  |  row-size=19B cardinality=99
+|  |
+|  01:SCAN HDFS [functional.alltypesagg a]
+|     HDFS partitions=11/11 files=11 size=814.73KB
+|     row-size=19B cardinality=11.00K
+|
+00:SCAN HDFS [functional.alltypesagg a]
+   HDFS partitions=11/11 files=11 size=814.73KB
+   row-size=95B cardinality=11.00K
+---- DISTRIBUTEDPLAN
+PLAN-ROOT SINK
+|
+08:EXCHANGE [UNPARTITIONED]
+|
+05:HASH JOIN [LEFT OUTER JOIN, BROADCAST]
+|  hash predicates: a.id = id + 1
+|  other predicates: row_number() < 100, length(string_col) = 0, id + 1 > 0
+|  row-size=122B cardinality=11.00K
+|
+|--07:EXCHANGE [BROADCAST]
+|  |
+|  04:SELECT
+|  |  predicates: row_number() < 100
+|  |  row-size=27B cardinality=99
+|  |
+|  03:ANALYTIC
+|  |  functions: row_number()
+|  |  order by: string_col DESC
+|  |  window: ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
+|  |  row-size=27B cardinality=99
+|  |
+|  06:MERGING-EXCHANGE [UNPARTITIONED]
+|  |  order by: string_col DESC
+|  |  limit: 99
+|  |
+|  02:TOP-N [LIMIT=99]
+|  |  order by: string_col DESC
+|  |  source expr: row_number() < CAST(100 AS BIGINT)
+|  |  row-size=19B cardinality=99
+|  |
+|  01:SCAN HDFS [functional.alltypesagg a]
+|     HDFS partitions=11/11 files=11 size=814.73KB
+|     row-size=19B cardinality=11.00K
+|
+00:SCAN HDFS [functional.alltypesagg a]
+   HDFS partitions=11/11 files=11 size=814.73KB
+   row-size=95B cardinality=11.00K
+====
diff --git 
a/testdata/workloads/functional-query/queries/QueryTest/analytic-fns.test 
b/testdata/workloads/functional-query/queries/QueryTest/analytic-fns.test
index 1d2fa53a6..4c0162f2d 100644
--- a/testdata/workloads/functional-query/queries/QueryTest/analytic-fns.test
+++ b/testdata/workloads/functional-query/queries/QueryTest/analytic-fns.test
@@ -2230,3 +2230,87 @@ INT, STRING, BIGINT, BIGINT
 85,'0',86,11
 95,'0',96,12
 ====
+---- QUERY
+# IMPALA-11030: Propagate analytic tuple predicates of outer-joined InlineView
+select a.id, b.prime_rank from alltypessmall a
+left join
+ (select id, row_number() over (partition by string_col order by id) prime_rank
+ from alltypessmall) b on a.id = b.id where a.string_col = '0' and 
b.prime_rank <= 10
+---- TYPES
+INT, BIGINT
+---- RESULTS: VERIFY_IS_EQUAL_SORTED
+0,1
+10,2
+20,3
+25,4
+35,5
+45,6
+50,7
+60,8
+70,9
+75,10
+====
+---- QUERY
+# IMPALA-11030: Propagate analytic tuple predicates of outer-joined InlineView
+with b as (select id, row_number() over (partition by string_col order by id) 
prime_rank
+ from alltypessmall)
+select a.id, b.prime_rank from alltypessmall a
+left join b on a.id = b.id where a.string_col = '0' and b.prime_rank <= 10
+---- TYPES
+INT, BIGINT
+---- RESULTS: VERIFY_IS_EQUAL_SORTED
+0,1
+10,2
+20,3
+25,4
+35,5
+45,6
+50,7
+60,8
+70,9
+75,10
+====
+---- QUERY
+# IMPALA-11030: Propagate analytic tuple predicates of outer-joined InlineView
+select a.id, b.prime_rank from alltypessmall a
+left join
+(select id, row_number() over (partition by string_col order by id) prime_rank 
from alltypessmall a
+union select id, row_number() over (partition by string_col order by id) 
prime_rank from alltypessmall b) b
+on a.id = b.id
+where a.string_col = '0' and b.prime_rank <= 10
+---- TYPES
+INT, BIGINT
+---- RESULTS: VERIFY_IS_EQUAL_SORTED
+75,10
+35,5
+20,3
+0,1
+25,4
+10,2
+45,6
+70,9
+60,8
+50,7
+====
+---- QUERY
+# IMPALA-11030: Propagate analytic tuple predicates of outer-joined InlineView
+select a.id, b.prime_rank from alltypessmall a
+left join
+(select a.id, row_number() over (partition by a.string_col order by a.id) 
prime_rank from alltypessmall a
+left join alltypessmall b on a.id = b.id) b
+on a.id = b.id
+where a.string_col = '0' and b.prime_rank <= 10
+---- TYPES
+INT, BIGINT
+---- RESULTS: VERIFY_IS_EQUAL_SORTED
+0,1
+10,2
+20,3
+25,4
+35,5
+45,6
+50,7
+60,8
+70,9
+75,10
+====

Reply via email to