You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@impala.apache.org by ta...@apache.org on 2020/07/02 21:18:05 UTC

[impala] branch master updated: IMPALA-9911: Fix IS [NOT] NULL predicate selectivity

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 08a7569  IMPALA-9911: Fix IS [NOT] NULL predicate selectivity
08a7569 is described below

commit 08a7569d4c372d6fb5003609c31c87a55db4e71b
Author: Aman Sinha <am...@cloudera.com>
AuthorDate: Wed Jul 1 10:45:00 2020 -0700

    IMPALA-9911: Fix IS [NOT] NULL predicate selectivity
    
    When null count is 0, the IsNullPredicate's selectivity
    was not being computed since it did not distinguish
    between a -1 (no stats) vs a 0 null count. This caused
    a default selectivity estimate being applied. This
    patch fixes it by explicitly checking whether nulls
    count stat is present and if so, use it regardless of
    whether it is 0 or more.
    
    Testing:
     - Added cardinality tests for IS NULL and IS NOT NULL.
     - Ran PlannerTest and updated baseline plans.
     - Updated expected selectivity for null predicate tests
       in ExprCardinalityTest.
     - Ran precommit tests through gerrit-verify-dryrun
    
    Change-Id: I46c084be780b8f5aead9e2b9656fbab6cc8c8874
    Reviewed-on: http://gerrit.cloudera.org:8080/16131
    Reviewed-by: Impala Public Jenkins <im...@cloudera.com>
    Tested-by: Impala Public Jenkins <im...@cloudera.com>
---
 .../apache/impala/analysis/IsNullPredicate.java    |   2 +-
 .../org/apache/impala/catalog/ColumnStats.java     |   1 +
 .../impala/analysis/ExprCardinalityTest.java       |  48 ++--
 .../org/apache/impala/planner/CardinalityTest.java |   6 +
 .../queries/PlannerTest/card-scan.test             |   4 +-
 .../queries/PlannerTest/kudu-selectivity.test      |   6 +-
 .../queries/PlannerTest/outer-joins.test           | 232 +++++++++---------
 .../queries/PlannerTest/predicate-propagation.test | 262 +++++++++++----------
 .../queries/PlannerTest/topn.test                  |  94 ++++----
 9 files changed, 326 insertions(+), 329 deletions(-)

diff --git a/fe/src/main/java/org/apache/impala/analysis/IsNullPredicate.java b/fe/src/main/java/org/apache/impala/analysis/IsNullPredicate.java
index 180209e..dc897f4 100644
--- a/fe/src/main/java/org/apache/impala/analysis/IsNullPredicate.java
+++ b/fe/src/main/java/org/apache/impala/analysis/IsNullPredicate.java
@@ -141,7 +141,7 @@ public class IsNullPredicate extends Predicate {
     Reference<SlotRef> slotRefRef = new Reference<SlotRef>();
     if (isSingleColumnPredicate(slotRefRef, null)) {
       SlotDescriptor slotDesc = slotRefRef.getRef().getDesc();
-      if (!slotDesc.getStats().hasNulls()) return;
+      if (!slotDesc.getStats().hasNullsStats()) return;
       FeTable table = slotDesc.getParent().getTable();
       if (table != null && table.getNumRows() > 0) {
         long numRows = table.getNumRows();
diff --git a/fe/src/main/java/org/apache/impala/catalog/ColumnStats.java b/fe/src/main/java/org/apache/impala/catalog/ColumnStats.java
index 7b08d25..da2a75b 100644
--- a/fe/src/main/java/org/apache/impala/catalog/ColumnStats.java
+++ b/fe/src/main/java/org/apache/impala/catalog/ColumnStats.java
@@ -194,6 +194,7 @@ public class ColumnStats {
   public double getAvgSize() { return avgSize_; }
   public long getMaxSize() { return maxSize_; }
   public boolean hasNulls() { return numNulls_ > 0; }
+  public boolean hasNullsStats() { return numNulls_ != -1; }
   public long getNumNulls() { return numNulls_; }
   // True iff getAvgSize() and getAvgSerializedSize() will return valid values.
   public boolean hasAvgSize() { return avgSize_ >= 0; }
diff --git a/fe/src/test/java/org/apache/impala/analysis/ExprCardinalityTest.java b/fe/src/test/java/org/apache/impala/analysis/ExprCardinalityTest.java
index 0657e2d..ce1e326 100644
--- a/fe/src/test/java/org/apache/impala/analysis/ExprCardinalityTest.java
+++ b/fe/src/test/java/org/apache/impala/analysis/ExprCardinalityTest.java
@@ -410,24 +410,14 @@ public class ExprCardinalityTest {
    */
   @Test
   public void testIsNullSelectivity() throws ImpalaException {
-    // Bug: No estimated selectivity for IS NULL (IMPALA-8050)
-    // Should be null count / |table|
-    // Bug: NDV of IS NULL is 3, should be 2 since IS NULL will
-    // never itself return NULL
-    //verifySelectExpr("alltypes", "id is null", 2, 0);
-    verifySelectExpr("alltypes", "id is null", 3, -1);
-    //verifySelectExpr("alltypes", "bool_col is null", 2, 0);
-    verifySelectExpr("alltypes", "bool_col is null", 3, -1);
-    //verifySelectExpr("alltypes", "int_col is null", 2, 0);
-    verifySelectExpr("alltypes", "int_col is null", 3, -1);
-
-    //verifySelectExpr("nullrows", "id is null", 2, 0);
-    verifySelectExpr("nullrows", "id is null", 3, -1);
-     //verifySelectExpr("nullrows", "null_str is null", 2, 1);
+    // TODO: IMPALA-9915: NDV of IS NULL should be 2
+    verifySelectExpr("alltypes", "id is null", 3, 0);
+    verifySelectExpr("alltypes", "bool_col is null", 3, 0);
+    verifySelectExpr("alltypes", "int_col is null", 3, 0);
+
+    verifySelectExpr("nullrows", "id is null", 3, 0);
     verifySelectExpr("nullrows", "null_str is null", 3, 1);
-    //verifySelectExpr("nullrows", "group_str is null", 2, 0);
-    verifySelectExpr("nullrows", "group_str is null", 3, -1);
-    //verifySelectExpr("nullrows", "some_nulls is null", 2, 20.0/26);
+    verifySelectExpr("nullrows", "group_str is null", 3, 0);
     verifySelectExpr("nullrows", "some_nulls is null", 3, 20.0/26);
     verifySelectExpr("nullrows", "bool_nulls is not null", 3, 1 - 15.0/26);
 
@@ -441,24 +431,14 @@ public class ExprCardinalityTest {
    */
   @Test
   public void testNotNullSelectivity() throws ImpalaException {
-    // Bug: No estimated selectivity for IS NOT NULL (IMPALA-8050)
-    // Should be 1 - null count / |table|
-    // Bug: NDV of IS NULL is 3, should be 2 since IS NOT NULL will
-    // never itself return NULL
-    //verifySelectExpr("alltypes", "id is not null", 2, 1);
-    verifySelectExpr("alltypes", "id is null", 3, -1);
-    //verifySelectExpr("alltypes", "bool_col is not null", 2, 1);
-    verifySelectExpr("alltypes", "bool_col is null", 3, -1);
-    //verifySelectExpr("alltypes", "int_col is not null", 2, 1);
-    verifySelectExpr("alltypes", "int_col is not null", 3, -1);
-
-    //verifySelectExpr("nullrows", "id is not null", 2, 1);
-    verifySelectExpr("nullrows", "id is not null", 3, -1);
-     //verifySelectExpr("nullrows", "null_str is not null", 2, 0);
+    // TODO: IMPALA-9915: NDV of IS NOT NULL should be 2
+    verifySelectExpr("alltypes", "id is not null", 3, 1);
+    verifySelectExpr("alltypes", "bool_col is not null", 3, 1);
+    verifySelectExpr("alltypes", "int_col is not null", 3, 1);
+
+    verifySelectExpr("nullrows", "id is not null", 3, 1);
     verifySelectExpr("nullrows", "null_str is not null", 3, 0);
-    //verifySelectExpr("nullrows", "group_str is not null", 2, 1);
-    verifySelectExpr("nullrows", "group_str is not null", 3, -1);
-    //verifySelectExpr("nullrows", "some_nulls is not null", 2, 1 - 20.0/26);
+    verifySelectExpr("nullrows", "group_str is not null", 3, 1);
     verifySelectExpr("nullrows", "some_nulls is not null", 3, 1 - 20.0/26);
     verifySelectExpr("nullrows", "bool_nulls is not null", 3, 1 - 15.0/26);
 
diff --git a/fe/src/test/java/org/apache/impala/planner/CardinalityTest.java b/fe/src/test/java/org/apache/impala/planner/CardinalityTest.java
index 7666364..c8c9d7f 100644
--- a/fe/src/test/java/org/apache/impala/planner/CardinalityTest.java
+++ b/fe/src/test/java/org/apache/impala/planner/CardinalityTest.java
@@ -90,6 +90,12 @@ public class CardinalityTest extends PlannerTestBase {
     verifyCardinality(
         "select id from functional.alltypesagg where tinyint_col IS NOT NULL", 9000);
 
+    verifyCardinality(
+        "select id from functional.alltypesaggnonulls where int_col IS NULL", 1);
+    verifyCardinality(
+        "select id from functional.alltypesaggnonulls where int_col IS NOT NULL",
+        10000);
+
     // Grouping should reduce cardinality
     verifyCardinality(
         "SELECT COUNT(*) FROM functional.alltypes GROUP BY int_col", 10);
diff --git a/testdata/workloads/functional-planner/queries/PlannerTest/card-scan.test b/testdata/workloads/functional-planner/queries/PlannerTest/card-scan.test
index 0987b27..cf4c316 100644
--- a/testdata/workloads/functional-planner/queries/PlannerTest/card-scan.test
+++ b/testdata/workloads/functional-planner/queries/PlannerTest/card-scan.test
@@ -352,7 +352,7 @@ PLAN-ROOT SINK
 00:SCAN HDFS [tpch.customer c]
    HDFS partitions=1/1 files=1 size=23.08MB
    predicates: c.c_mktsegment IS NULL
-   row-size=218B cardinality=15.00K
+   row-size=218B cardinality=1
 ====
 # IS NOT NULL
 # Similar to above.
@@ -366,7 +366,7 @@ PLAN-ROOT SINK
 00:SCAN HDFS [tpch.customer c]
    HDFS partitions=1/1 files=1 size=23.08MB
    predicates: c.c_mktsegment IS NOT NULL
-   row-size=218B cardinality=15.00K
+   row-size=218B cardinality=150.00K
 ====
 # |alltypesagg| = 11K. Null count of tinyint_col = 2000.
 select *
diff --git a/testdata/workloads/functional-planner/queries/PlannerTest/kudu-selectivity.test b/testdata/workloads/functional-planner/queries/PlannerTest/kudu-selectivity.test
index 281a396..87356bc 100644
--- a/testdata/workloads/functional-planner/queries/PlannerTest/kudu-selectivity.test
+++ b/testdata/workloads/functional-planner/queries/PlannerTest/kudu-selectivity.test
@@ -208,10 +208,10 @@ Per-Host Resources: mem-estimate=9.75MB mem-reservation=0B thread-reservation=2
   |  mem-estimate=0B mem-reservation=0B thread-reservation=0
   |
   00:SCAN KUDU [functional_kudu.alltypes]
-     predicates: timestamp_col < NULL, CAST(date_string_col AS TINYINT) IS NULL
-     kudu predicates: smallint_col IS NULL, tinyint_col IS NOT NULL, timestamp_col > TIMESTAMP '1987-05-19 00:00:00.000000010'
+     predicates: CAST(date_string_col AS TINYINT) IS NULL, timestamp_col < NULL
+     kudu predicates: smallint_col IS NULL, timestamp_col > TIMESTAMP '1987-05-19 00:00:00.000000010', tinyint_col IS NOT NULL
      mem-estimate=9.75MB mem-reservation=0B thread-reservation=1
-     tuple-ids=0 row-size=97B cardinality=730
+     tuple-ids=0 row-size=97B cardinality=1
      in pipelines: 00(GETNEXT)
 ====
 select * from functional_kudu.alltypes where
diff --git a/testdata/workloads/functional-planner/queries/PlannerTest/outer-joins.test b/testdata/workloads/functional-planner/queries/PlannerTest/outer-joins.test
index 5841f8d..45e2503 100644
--- a/testdata/workloads/functional-planner/queries/PlannerTest/outer-joins.test
+++ b/testdata/workloads/functional-planner/queries/PlannerTest/outer-joins.test
@@ -36,7 +36,7 @@ PLAN-ROOT SINK
 |  row-size=72B cardinality=0
 |
 |--02:SCAN HDFS [functional.testtbl t3]
-|     partitions=1/1 files=0 size=0B
+|     HDFS partitions=1/1 files=0 size=0B
 |     predicates: t3.id IS NOT NULL, t3.id > 0, t3.zip = 94720
 |     row-size=24B cardinality=0
 |
@@ -47,12 +47,12 @@ PLAN-ROOT SINK
 |  row-size=48B cardinality=0
 |
 |--01:SCAN HDFS [functional.testtbl t2]
-|     partitions=1/1 files=0 size=0B
+|     HDFS partitions=1/1 files=0 size=0B
 |     predicates: t2.zip = 94104
 |     row-size=24B cardinality=0
 |
 00:SCAN HDFS [functional.testtbl t1]
-   partitions=1/1 files=0 size=0B
+   HDFS partitions=1/1 files=0 size=0B
    predicates: t1.id > 0
    row-size=24B cardinality=0
 ---- DISTRIBUTEDPLAN
@@ -69,7 +69,7 @@ PLAN-ROOT SINK
 |--06:EXCHANGE [BROADCAST]
 |  |
 |  02:SCAN HDFS [functional.testtbl t3]
-|     partitions=1/1 files=0 size=0B
+|     HDFS partitions=1/1 files=0 size=0B
 |     predicates: t3.id IS NOT NULL, t3.id > 0, t3.zip = 94720
 |     row-size=24B cardinality=0
 |
@@ -82,12 +82,12 @@ PLAN-ROOT SINK
 |--05:EXCHANGE [BROADCAST]
 |  |
 |  01:SCAN HDFS [functional.testtbl t2]
-|     partitions=1/1 files=0 size=0B
+|     HDFS partitions=1/1 files=0 size=0B
 |     predicates: t2.zip = 94104
 |     row-size=24B cardinality=0
 |
 00:SCAN HDFS [functional.testtbl t1]
-   partitions=1/1 files=0 size=0B
+   HDFS partitions=1/1 files=0 size=0B
    predicates: t1.id > 0
    row-size=24B cardinality=0
 ====
@@ -110,7 +110,7 @@ PLAN-ROOT SINK
 |  row-size=72B cardinality=0
 |
 |--02:SCAN HDFS [functional.testtbl a3]
-|     partitions=1/1 files=0 size=0B
+|     HDFS partitions=1/1 files=0 size=0B
 |     predicates: a3.id IS NOT NULL, a3.id > 0, a3.zip = 94720
 |     row-size=24B cardinality=0
 |
@@ -121,12 +121,12 @@ PLAN-ROOT SINK
 |  row-size=48B cardinality=0
 |
 |--01:SCAN HDFS [functional.testtbl a2]
-|     partitions=1/1 files=0 size=0B
+|     HDFS partitions=1/1 files=0 size=0B
 |     predicates: a2.zip = 94104
 |     row-size=24B cardinality=0
 |
 00:SCAN HDFS [functional.testtbl a1]
-   partitions=1/1 files=0 size=0B
+   HDFS partitions=1/1 files=0 size=0B
    predicates: a1.id > 0
    row-size=24B cardinality=0
 ---- DISTRIBUTEDPLAN
@@ -143,7 +143,7 @@ PLAN-ROOT SINK
 |--06:EXCHANGE [BROADCAST]
 |  |
 |  02:SCAN HDFS [functional.testtbl a3]
-|     partitions=1/1 files=0 size=0B
+|     HDFS partitions=1/1 files=0 size=0B
 |     predicates: a3.id IS NOT NULL, a3.id > 0, a3.zip = 94720
 |     row-size=24B cardinality=0
 |
@@ -156,12 +156,12 @@ PLAN-ROOT SINK
 |--05:EXCHANGE [BROADCAST]
 |  |
 |  01:SCAN HDFS [functional.testtbl a2]
-|     partitions=1/1 files=0 size=0B
+|     HDFS partitions=1/1 files=0 size=0B
 |     predicates: a2.zip = 94104
 |     row-size=24B cardinality=0
 |
 00:SCAN HDFS [functional.testtbl a1]
-   partitions=1/1 files=0 size=0B
+   HDFS partitions=1/1 files=0 size=0B
    predicates: a1.id > 0
    row-size=24B cardinality=0
 ====
@@ -181,7 +181,7 @@ PLAN-ROOT SINK
 |  row-size=72B cardinality=0
 |
 |--02:SCAN HDFS [functional.testtbl t3]
-|     partitions=1/1 files=0 size=0B
+|     HDFS partitions=1/1 files=0 size=0B
 |     row-size=24B cardinality=0
 |
 03:HASH JOIN [LEFT OUTER JOIN]
@@ -190,13 +190,13 @@ PLAN-ROOT SINK
 |  row-size=48B cardinality=0
 |
 |--01:SCAN HDFS [functional.testtbl t2]
-|     partitions=1/1 files=0 size=0B
+|     HDFS partitions=1/1 files=0 size=0B
 |     predicates: t2.id = 17
 |     runtime filters: RF000 -> t2.id
 |     row-size=24B cardinality=0
 |
 00:SCAN HDFS [functional.testtbl t1]
-   partitions=1/1 files=0 size=0B
+   HDFS partitions=1/1 files=0 size=0B
    runtime filters: RF000 -> t1.id
    row-size=24B cardinality=0
 ====
@@ -240,7 +240,7 @@ PLAN-ROOT SINK
 |  row-size=72B cardinality=0
 |
 |--02:SCAN HDFS [functional.testtbl t3]
-|     partitions=1/1 files=0 size=0B
+|     HDFS partitions=1/1 files=0 size=0B
 |     predicates: t3.id IS NOT NULL
 |     row-size=24B cardinality=0
 |
@@ -251,12 +251,12 @@ PLAN-ROOT SINK
 |  row-size=48B cardinality=0
 |
 |--01:SCAN HDFS [functional.testtbl t2]
-|     partitions=1/1 files=0 size=0B
+|     HDFS partitions=1/1 files=0 size=0B
 |     predicates: t2.id = 15
 |     row-size=24B cardinality=0
 |
 00:SCAN HDFS [functional.testtbl t1]
-   partitions=1/1 files=0 size=0B
+   HDFS partitions=1/1 files=0 size=0B
    predicates: t1.id IS NOT NULL, t1.id > 0
    runtime filters: RF000 -> t1.id, RF002 -> t1.id - 1
    row-size=24B cardinality=0
@@ -275,7 +275,7 @@ PLAN-ROOT SINK
 |--08:EXCHANGE [HASH(t3.id)]
 |  |
 |  02:SCAN HDFS [functional.testtbl t3]
-|     partitions=1/1 files=0 size=0B
+|     HDFS partitions=1/1 files=0 size=0B
 |     predicates: t3.id IS NOT NULL
 |     row-size=24B cardinality=0
 |
@@ -290,14 +290,14 @@ PLAN-ROOT SINK
 |--06:EXCHANGE [HASH(t2.id + 1)]
 |  |
 |  01:SCAN HDFS [functional.testtbl t2]
-|     partitions=1/1 files=0 size=0B
+|     HDFS partitions=1/1 files=0 size=0B
 |     predicates: t2.id = 15
 |     row-size=24B cardinality=0
 |
 05:EXCHANGE [HASH(t1.id - 1)]
 |
 00:SCAN HDFS [functional.testtbl t1]
-   partitions=1/1 files=0 size=0B
+   HDFS partitions=1/1 files=0 size=0B
    predicates: t1.id IS NOT NULL, t1.id > 0
    runtime filters: RF000 -> t1.id, RF002 -> t1.id - 1
    row-size=24B cardinality=0
@@ -321,7 +321,7 @@ PLAN-ROOT SINK
 |  row-size=72B cardinality=0
 |
 |--02:SCAN HDFS [functional.testtbl a3]
-|     partitions=1/1 files=0 size=0B
+|     HDFS partitions=1/1 files=0 size=0B
 |     predicates: a3.id IS NOT NULL
 |     row-size=24B cardinality=0
 |
@@ -332,12 +332,12 @@ PLAN-ROOT SINK
 |  row-size=48B cardinality=0
 |
 |--01:SCAN HDFS [functional.testtbl a2]
-|     partitions=1/1 files=0 size=0B
+|     HDFS partitions=1/1 files=0 size=0B
 |     predicates: a2.id = 15
 |     row-size=24B cardinality=0
 |
 00:SCAN HDFS [functional.testtbl a1]
-   partitions=1/1 files=0 size=0B
+   HDFS partitions=1/1 files=0 size=0B
    predicates: a1.id IS NOT NULL, a1.id > 0
    runtime filters: RF000 -> a1.id, RF002 -> a1.id - 1
    row-size=24B cardinality=0
@@ -356,7 +356,7 @@ PLAN-ROOT SINK
 |--08:EXCHANGE [HASH(a3.id)]
 |  |
 |  02:SCAN HDFS [functional.testtbl a3]
-|     partitions=1/1 files=0 size=0B
+|     HDFS partitions=1/1 files=0 size=0B
 |     predicates: a3.id IS NOT NULL
 |     row-size=24B cardinality=0
 |
@@ -371,14 +371,14 @@ PLAN-ROOT SINK
 |--06:EXCHANGE [HASH(a2.id + 1)]
 |  |
 |  01:SCAN HDFS [functional.testtbl a2]
-|     partitions=1/1 files=0 size=0B
+|     HDFS partitions=1/1 files=0 size=0B
 |     predicates: a2.id = 15
 |     row-size=24B cardinality=0
 |
 05:EXCHANGE [HASH(a1.id - 1)]
 |
 00:SCAN HDFS [functional.testtbl a1]
-   partitions=1/1 files=0 size=0B
+   HDFS partitions=1/1 files=0 size=0B
    predicates: a1.id IS NOT NULL, a1.id > 0
    runtime filters: RF000 -> a1.id, RF002 -> a1.id - 1
    row-size=24B cardinality=0
@@ -399,11 +399,11 @@ PLAN-ROOT SINK
 |  row-size=5B cardinality=9.78K
 |
 |--01:SCAN HDFS [functional.alltypestiny b]
-|     partitions=4/4 files=4 size=460B
+|     HDFS partitions=4/4 files=4 size=460B
 |     row-size=4B cardinality=8
 |
 00:SCAN HDFS [functional.alltypesagg a]
-   partitions=11/11 files=11 size=814.73KB
+   HDFS partitions=11/11 files=11 size=814.73KB
    runtime filters: RF000 -> a.tinyint_col
    row-size=1B cardinality=11.00K
 ---- DISTRIBUTEDPLAN
@@ -420,13 +420,13 @@ PLAN-ROOT SINK
 |--04:EXCHANGE [HASH(b.id)]
 |  |
 |  01:SCAN HDFS [functional.alltypestiny b]
-|     partitions=4/4 files=4 size=460B
+|     HDFS partitions=4/4 files=4 size=460B
 |     row-size=4B cardinality=8
 |
 03:EXCHANGE [HASH(a.tinyint_col)]
 |
 00:SCAN HDFS [functional.alltypesagg a]
-   partitions=11/11 files=11 size=814.73KB
+   HDFS partitions=11/11 files=11 size=814.73KB
    runtime filters: RF000 -> a.tinyint_col
    row-size=1B cardinality=11.00K
 ====
@@ -444,11 +444,11 @@ PLAN-ROOT SINK
 |  row-size=5B cardinality=11.01K
 |
 |--01:SCAN HDFS [functional.alltypestiny b]
-|     partitions=4/4 files=4 size=460B
+|     HDFS partitions=4/4 files=4 size=460B
 |     row-size=4B cardinality=8
 |
 00:SCAN HDFS [functional.alltypesagg a]
-   partitions=11/11 files=11 size=814.73KB
+   HDFS partitions=11/11 files=11 size=814.73KB
    row-size=1B cardinality=11.00K
 ---- DISTRIBUTEDPLAN
 PLAN-ROOT SINK
@@ -463,13 +463,13 @@ PLAN-ROOT SINK
 |--04:EXCHANGE [HASH(b.id)]
 |  |
 |  01:SCAN HDFS [functional.alltypestiny b]
-|     partitions=4/4 files=4 size=460B
+|     HDFS partitions=4/4 files=4 size=460B
 |     row-size=4B cardinality=8
 |
 03:EXCHANGE [HASH(a.tinyint_col)]
 |
 00:SCAN HDFS [functional.alltypesagg a]
-   partitions=11/11 files=11 size=814.73KB
+   HDFS partitions=11/11 files=11 size=814.73KB
    row-size=1B cardinality=11.00K
 ====
 # Predicate assignment when query has a full outer join (IMPALA-1371)
@@ -490,12 +490,12 @@ PLAN-ROOT SINK
 |  row-size=178B cardinality=8.03K
 |
 |--01:SCAN HDFS [functional.alltypes b]
-|     partitions=24/24 files=24 size=478.45KB
+|     HDFS partitions=24/24 files=24 size=478.45KB
 |     predicates: b.bigint_col > 10
 |     row-size=89B cardinality=730
 |
 00:SCAN HDFS [functional.alltypes a]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    row-size=89B cardinality=7.30K
 ====
 # Predicate assignment when query has a full outer followed by an inner join
@@ -522,17 +522,17 @@ PLAN-ROOT SINK
 |  |  row-size=178B cardinality=1.46K
 |  |
 |  |--01:SCAN HDFS [functional.alltypes b]
-|  |     partitions=24/24 files=24 size=478.45KB
+|  |     HDFS partitions=24/24 files=24 size=478.45KB
 |  |     predicates: b.tinyint_col > 20
 |  |     row-size=89B cardinality=730
 |  |
 |  00:SCAN HDFS [functional.alltypes a]
-|     partitions=24/24 files=24 size=478.45KB
+|     HDFS partitions=24/24 files=24 size=478.45KB
 |     predicates: a.tinyint_col < 10
 |     row-size=89B cardinality=730
 |
 02:SCAN HDFS [functional.alltypes c]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    runtime filters: RF000 -> c.int_col
    row-size=89B cardinality=7.30K
 ====
@@ -562,17 +562,17 @@ PLAN-ROOT SINK
 |  |  row-size=178B cardinality=730
 |  |
 |  |--00:SCAN HDFS [functional.alltypes a]
-|  |     partitions=24/24 files=24 size=478.45KB
+|  |     HDFS partitions=24/24 files=24 size=478.45KB
 |  |     predicates: a.smallint_col = 100
 |  |     row-size=89B cardinality=730
 |  |
 |  01:SCAN HDFS [functional.alltypes b]
-|     partitions=24/24 files=24 size=478.45KB
+|     HDFS partitions=24/24 files=24 size=478.45KB
 |     runtime filters: RF000 -> b.id
 |     row-size=89B cardinality=7.30K
 |
 02:SCAN HDFS [functional.alltypes c]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    row-size=89B cardinality=7.30K
 ====
 # Predicate assignment when query has a sequence of full outer joins interleaved with
@@ -598,7 +598,7 @@ PLAN-ROOT SINK
 |  row-size=356B cardinality=2.33G
 |
 |--03:SCAN HDFS [functional.alltypes d]
-|     partitions=24/24 files=24 size=478.45KB
+|     HDFS partitions=24/24 files=24 size=478.45KB
 |     row-size=89B cardinality=7.30K
 |
 06:HASH JOIN [INNER JOIN]
@@ -608,7 +608,7 @@ PLAN-ROOT SINK
 |  row-size=267B cardinality=3.20M
 |
 |--02:SCAN HDFS [functional.alltypes c]
-|     partitions=24/24 files=24 size=478.45KB
+|     HDFS partitions=24/24 files=24 size=478.45KB
 |     row-size=89B cardinality=7.30K
 |
 05:HASH JOIN [FULL OUTER JOIN]
@@ -617,12 +617,12 @@ PLAN-ROOT SINK
 |  row-size=178B cardinality=4.38K
 |
 |--01:SCAN HDFS [functional.alltypes b]
-|     partitions=24/24 files=24 size=478.45KB
+|     HDFS partitions=24/24 files=24 size=478.45KB
 |     predicates: b.int_col > 10
 |     row-size=89B cardinality=730
 |
 00:SCAN HDFS [functional.alltypes a]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    predicates: a.bool_col = FALSE
    runtime filters: RF000 -> a.tinyint_col
    row-size=89B cardinality=3.65K
@@ -656,7 +656,7 @@ PLAN-ROOT SINK
 |  row-size=46B cardinality=5.87M
 |
 |--03:SCAN HDFS [functional.alltypes d]
-|     partitions=24/24 files=24 size=478.45KB
+|     HDFS partitions=24/24 files=24 size=478.45KB
 |     row-size=4B cardinality=7.30K
 |
 05:HASH JOIN [INNER JOIN]
@@ -666,7 +666,7 @@ PLAN-ROOT SINK
 |  row-size=42B cardinality=5.86M
 |
 |--02:SCAN HDFS [functional.alltypes c]
-|     partitions=24/24 files=24 size=478.45KB
+|     HDFS partitions=24/24 files=24 size=478.45KB
 |     row-size=6B cardinality=7.30K
 |
 04:HASH JOIN [FULL OUTER JOIN]
@@ -674,13 +674,13 @@ PLAN-ROOT SINK
 |  row-size=36B cardinality=8.03K
 |
 |--01:SCAN HDFS [functional.alltypes b]
-|     partitions=24/24 files=24 size=478.45KB
+|     HDFS partitions=24/24 files=24 size=478.45KB
 |     predicates: b.id < 10
 |     runtime filters: RF000 -> b.smallint_col
 |     row-size=19B cardinality=730
 |
 00:SCAN HDFS [functional.alltypes a]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    row-size=17B cardinality=7.30K
 ====
 # Predicate assignment when query has an inner join followed by full outer join
@@ -703,7 +703,7 @@ PLAN-ROOT SINK
 |  row-size=34B cardinality=5.33M
 |
 |--02:SCAN HDFS [functional.alltypes c]
-|     partitions=24/24 files=24 size=478.45KB
+|     HDFS partitions=24/24 files=24 size=478.45KB
 |     row-size=4B cardinality=7.30K
 |
 03:HASH JOIN [INNER JOIN]
@@ -712,11 +712,11 @@ PLAN-ROOT SINK
 |  row-size=30B cardinality=7.30K
 |
 |--00:SCAN HDFS [functional.alltypes a]
-|     partitions=24/24 files=24 size=478.45KB
+|     HDFS partitions=24/24 files=24 size=478.45KB
 |     row-size=13B cardinality=7.30K
 |
 01:SCAN HDFS [functional.alltypes b]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    runtime filters: RF000 -> b.id
    row-size=17B cardinality=7.30K
 ====
@@ -741,7 +741,7 @@ PLAN-ROOT SINK
 |  row-size=56B cardinality=38.90M
 |
 |--03:SCAN HDFS [functional.alltypes d]
-|     partitions=24/24 files=24 size=478.45KB
+|     HDFS partitions=24/24 files=24 size=478.45KB
 |     predicates: d.tinyint_col < 10
 |     row-size=14B cardinality=730
 |
@@ -757,17 +757,17 @@ PLAN-ROOT SINK
 |  |  row-size=37B cardinality=730
 |  |
 |  |--01:SCAN HDFS [functional.alltypes b]
-|  |     partitions=24/24 files=24 size=478.45KB
+|  |     HDFS partitions=24/24 files=24 size=478.45KB
 |  |     predicates: b.smallint_col = 1
 |  |     row-size=24B cardinality=730
 |  |
 |  00:SCAN HDFS [functional.alltypes a]
-|     partitions=24/24 files=24 size=478.45KB
+|     HDFS partitions=24/24 files=24 size=478.45KB
 |     runtime filters: RF002 -> a.id
 |     row-size=13B cardinality=7.30K
 |
 02:SCAN HDFS [functional.alltypes c]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    runtime filters: RF000 -> c.int_col
    row-size=5B cardinality=7.30K
 ====
@@ -786,21 +786,23 @@ PLAN-ROOT SINK
 |  output: sum(b.double_col)
 |  group by: a.bool_col, a.int_col, b.bool_col, b.int_col
 |  having: b.bool_col IS NULL, b.int_col IS NOT NULL
-|  row-size=18B cardinality=8
+|  row-size=18B cardinality=1
 |
-02:HASH JOIN [LEFT OUTER JOIN]
-|  hash predicates: a.id = b.id
-|  row-size=26B cardinality=730
+02:HASH JOIN [RIGHT OUTER JOIN]
+|  hash predicates: b.id = a.id
+|  runtime filters: RF000 <- a.id
+|  row-size=26B cardinality=1
 |
-|--01:SCAN HDFS [functional.alltypestiny b]
-|     partitions=4/4 files=4 size=460B
-|     predicates: b.int_col IS NOT NULL
-|     row-size=17B cardinality=1
+|--00:SCAN HDFS [functional.alltypes a]
+|     HDFS partitions=24/24 files=24 size=478.45KB
+|     predicates: a.bool_col IS NULL, a.int_col IS NOT NULL
+|     row-size=9B cardinality=1
 |
-00:SCAN HDFS [functional.alltypes a]
-   partitions=24/24 files=24 size=478.45KB
-   predicates: a.bool_col IS NULL, a.int_col IS NOT NULL
-   row-size=9B cardinality=730
+01:SCAN HDFS [functional.alltypestiny b]
+   HDFS partitions=4/4 files=4 size=460B
+   predicates: b.int_col IS NOT NULL
+   runtime filters: RF000 -> b.id
+   row-size=17B cardinality=8
 ====
 # IMPALA-2144: Same as above but with a full outer join.
 select b.int_col, sum(b.double_col)
@@ -815,22 +817,22 @@ PLAN-ROOT SINK
 03:AGGREGATE [FINALIZE]
 |  output: sum(b.double_col)
 |  group by: a.bool_col, a.int_col, b.bool_col, b.int_col
-|  having: a.bool_col IS NULL, a.int_col IS NOT NULL, b.bool_col IS NULL, b.int_col IS NOT NULL
-|  row-size=18B cardinality=8
+|  having: a.bool_col IS NULL, b.bool_col IS NULL, a.int_col IS NOT NULL, b.int_col IS NOT NULL
+|  row-size=18B cardinality=1
 |
 02:HASH JOIN [FULL OUTER JOIN]
 |  hash predicates: a.id = b.id
-|  row-size=26B cardinality=731
+|  row-size=26B cardinality=7.31K
 |
 |--01:SCAN HDFS [functional.alltypestiny b]
-|     partitions=4/4 files=4 size=460B
+|     HDFS partitions=4/4 files=4 size=460B
 |     predicates: b.int_col IS NOT NULL
-|     row-size=17B cardinality=1
+|     row-size=17B cardinality=8
 |
 00:SCAN HDFS [functional.alltypes a]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    predicates: a.int_col IS NOT NULL
-   row-size=9B cardinality=730
+   row-size=9B cardinality=7.30K
 ====
 # IMPALA-2765: Predicate assignment when outer joins have case expressions as predicates
 select *
@@ -852,12 +854,12 @@ PLAN-ROOT SINK
 |  row-size=178B cardinality=730
 |
 |--00:SCAN HDFS [functional.alltypes a]
-|     partitions=24/24 files=24 size=478.45KB
+|     HDFS partitions=24/24 files=24 size=478.45KB
 |     predicates: (CASE WHEN a.id > 100 THEN a.timestamp_col ELSE a.timestamp_col END) >= TIMESTAMP '2001-01-01 00:00:00'
 |     row-size=89B cardinality=730
 |
 01:SCAN HDFS [functional.alltypes b]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    runtime filters: RF000 -> b.id
    row-size=89B cardinality=7.30K
 ====
@@ -882,17 +884,17 @@ PLAN-ROOT SINK
 |  |  row-size=16B cardinality=1
 |  |
 |  |--01:SCAN HDFS [functional.alltypestiny b]
-|  |     partitions=4/4 files=4 size=460B
+|  |     HDFS partitions=4/4 files=4 size=460B
 |  |     predicates: b.int_col < 0
 |  |     row-size=8B cardinality=1
 |  |
 |  00:SCAN HDFS [functional.alltypestiny a]
-|     partitions=4/4 files=4 size=460B
+|     HDFS partitions=4/4 files=4 size=460B
 |     predicates: a.int_col > 10
 |     row-size=8B cardinality=1
 |
 02:SCAN HDFS [functional.alltypestiny c]
-   partitions=4/4 files=4 size=460B
+   HDFS partitions=4/4 files=4 size=460B
    runtime filters: RF000 -> c.id
    row-size=4B cardinality=8
 ====
@@ -917,18 +919,18 @@ PLAN-ROOT SINK
 |  |  row-size=16B cardinality=1
 |  |
 |  |--01:SCAN HDFS [functional.alltypestiny b]
-|  |     partitions=4/4 files=4 size=460B
+|  |     HDFS partitions=4/4 files=4 size=460B
 |  |     predicates: b.int_col < 0
 |  |     row-size=8B cardinality=1
 |  |
 |  00:SCAN HDFS [functional.alltypestiny a]
-|     partitions=4/4 files=4 size=460B
+|     HDFS partitions=4/4 files=4 size=460B
 |     predicates: a.int_col > 10
 |     runtime filters: RF002 -> a.id
 |     row-size=8B cardinality=1
 |
 02:SCAN HDFS [functional.alltypestiny c]
-   partitions=4/4 files=4 size=460B
+   HDFS partitions=4/4 files=4 size=460B
    runtime filters: RF000 -> c.id
    row-size=4B cardinality=8
 ====
@@ -948,7 +950,7 @@ PLAN-ROOT SINK
 |  row-size=20B cardinality=2
 |
 |--02:SCAN HDFS [functional.alltypestiny c]
-|     partitions=4/4 files=4 size=460B
+|     HDFS partitions=4/4 files=4 size=460B
 |     row-size=4B cardinality=8
 |
 04:HASH JOIN [FULL OUTER JOIN]
@@ -956,13 +958,13 @@ PLAN-ROOT SINK
 |  row-size=16B cardinality=2
 |
 |--01:SCAN HDFS [functional.alltypestiny b]
-|     partitions=4/4 files=4 size=460B
+|     HDFS partitions=4/4 files=4 size=460B
 |     predicates: b.int_col < 0
 |     runtime filters: RF000 -> b.id
 |     row-size=8B cardinality=1
 |
 00:SCAN HDFS [functional.alltypestiny a]
-   partitions=4/4 files=4 size=460B
+   HDFS partitions=4/4 files=4 size=460B
    predicates: a.int_col > 10
    row-size=8B cardinality=1
 ====
@@ -998,26 +1000,26 @@ PLAN-ROOT SINK
 |  |  |  |  row-size=16B cardinality=1
 |  |  |  |
 |  |  |  |--01:SCAN HDFS [functional.alltypestiny b]
-|  |  |  |     partitions=4/4 files=4 size=460B
+|  |  |  |     HDFS partitions=4/4 files=4 size=460B
 |  |  |  |     predicates: b.int_col < 0
 |  |  |  |     row-size=8B cardinality=1
 |  |  |  |
 |  |  |  00:SCAN HDFS [functional.alltypestiny a]
-|  |  |     partitions=4/4 files=4 size=460B
+|  |  |     HDFS partitions=4/4 files=4 size=460B
 |  |  |     predicates: a.int_col > 10
 |  |  |     row-size=8B cardinality=1
 |  |  |
 |  |  02:SCAN HDFS [functional.alltypestiny c]
-|  |     partitions=4/4 files=4 size=460B
+|  |     HDFS partitions=4/4 files=4 size=460B
 |  |     runtime filters: RF000 -> c.id
 |  |     row-size=4B cardinality=8
 |  |
 |  03:SCAN HDFS [functional.alltypestiny d]
-|     partitions=4/4 files=4 size=460B
+|     HDFS partitions=4/4 files=4 size=460B
 |     row-size=4B cardinality=8
 |
 04:SCAN HDFS [functional.alltypestiny e]
-   partitions=4/4 files=4 size=460B
+   HDFS partitions=4/4 files=4 size=460B
    row-size=4B cardinality=8
 ====
 # IMPALA-3125: Test that the On-clause predicates from an outer join are assigned to the
@@ -1037,7 +1039,7 @@ PLAN-ROOT SINK
 |  row-size=32B cardinality=3.89G
 |
 |--02:SCAN HDFS [functional.alltypes c]
-|     partitions=24/24 files=24 size=478.45KB
+|     HDFS partitions=24/24 files=24 size=478.45KB
 |     row-size=8B cardinality=7.30K
 |
 03:HASH JOIN [INNER JOIN]
@@ -1046,11 +1048,11 @@ PLAN-ROOT SINK
 |  row-size=24B cardinality=5.33M
 |
 |--00:SCAN HDFS [functional.alltypes a]
-|     partitions=24/24 files=24 size=478.45KB
+|     HDFS partitions=24/24 files=24 size=478.45KB
 |     row-size=8B cardinality=7.30K
 |
 01:SCAN HDFS [functional.alltypes b]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    runtime filters: RF000 -> b.int_col
    row-size=16B cardinality=7.30K
 ====
@@ -1079,12 +1081,12 @@ PLAN-ROOT SINK
 |  row-size=20B cardinality=7.30K
 |
 |--01:SCAN HDFS [functional.alltypessmall t2]
-|     partitions=4/4 files=4 size=6.32KB
+|     HDFS partitions=4/4 files=4 size=6.32KB
 |     predicates: t2.id < 10
 |     row-size=8B cardinality=10
 |
 00:SCAN HDFS [functional.alltypes t1]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    row-size=12B cardinality=7.30K
 ====
 # IMPALA-3126: Test assignment of an inner join On-clause predicate. The predicate
@@ -1104,7 +1106,7 @@ PLAN-ROOT SINK
 |  row-size=20B cardinality=7.30K
 |
 |--03:SCAN HDFS [functional.alltypes d]
-|     partitions=24/24 files=24 size=478.45KB
+|     HDFS partitions=24/24 files=24 size=478.45KB
 |     row-size=0B cardinality=7.30K
 |
 05:HASH JOIN [RIGHT OUTER JOIN]
@@ -1113,7 +1115,7 @@ PLAN-ROOT SINK
 |  row-size=20B cardinality=7.30K
 |
 |--02:SCAN HDFS [functional.alltypes c]
-|     partitions=24/24 files=24 size=478.45KB
+|     HDFS partitions=24/24 files=24 size=478.45KB
 |     row-size=4B cardinality=7.30K
 |
 04:HASH JOIN [LEFT OUTER JOIN]
@@ -1121,12 +1123,12 @@ PLAN-ROOT SINK
 |  row-size=16B cardinality=7.30K
 |
 |--01:SCAN HDFS [functional.alltypes b]
-|     partitions=24/24 files=24 size=478.45KB
+|     HDFS partitions=24/24 files=24 size=478.45KB
 |     runtime filters: RF000 -> b.id
 |     row-size=8B cardinality=7.30K
 |
 00:SCAN HDFS [functional.alltypes a]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    row-size=8B cardinality=7.30K
 ====
 # IMPALA-3126: Same as above but with a semi join at the end.
@@ -1145,7 +1147,7 @@ PLAN-ROOT SINK
 |  row-size=20B cardinality=7.30K
 |
 |--03:SCAN HDFS [functional.alltypes d]
-|     partitions=24/24 files=24 size=478.45KB
+|     HDFS partitions=24/24 files=24 size=478.45KB
 |     row-size=0B cardinality=7.30K
 |
 05:HASH JOIN [RIGHT OUTER JOIN]
@@ -1154,7 +1156,7 @@ PLAN-ROOT SINK
 |  row-size=20B cardinality=7.30K
 |
 |--02:SCAN HDFS [functional.alltypes c]
-|     partitions=24/24 files=24 size=478.45KB
+|     HDFS partitions=24/24 files=24 size=478.45KB
 |     row-size=4B cardinality=7.30K
 |
 04:HASH JOIN [LEFT OUTER JOIN]
@@ -1162,12 +1164,12 @@ PLAN-ROOT SINK
 |  row-size=16B cardinality=7.30K
 |
 |--01:SCAN HDFS [functional.alltypes b]
-|     partitions=24/24 files=24 size=478.45KB
+|     HDFS partitions=24/24 files=24 size=478.45KB
 |     runtime filters: RF000 -> b.id
 |     row-size=8B cardinality=7.30K
 |
 00:SCAN HDFS [functional.alltypes a]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    row-size=8B cardinality=7.30K
 ====
 # IMPALA-5856: Test correct assignment of a join predicate with the following properties:
@@ -1191,7 +1193,7 @@ PLAN-ROOT SINK
 |  row-size=267B cardinality=7.40K
 |
 |--02:SCAN HDFS [functional.alltypestiny t3]
-|     partitions=4/4 files=4 size=460B
+|     HDFS partitions=4/4 files=4 size=460B
 |     predicates: t3.string_col = 'test2'
 |     row-size=89B cardinality=4
 |
@@ -1201,11 +1203,11 @@ PLAN-ROOT SINK
 |  row-size=178B cardinality=7.40K
 |
 |--01:SCAN HDFS [functional.alltypessmall t2]
-|     partitions=4/4 files=4 size=6.32KB
+|     HDFS partitions=4/4 files=4 size=6.32KB
 |     row-size=89B cardinality=100
 |
 00:SCAN HDFS [functional.alltypes t1]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    row-size=89B cardinality=7.30K
 ====
 # IMPALA-6123: Test the partition compatibility check with consecutive outer joins.
@@ -1246,7 +1248,7 @@ PLAN-ROOT SINK
 |--09:EXCHANGE [HASH(t3.id)]
 |  |
 |  02:SCAN HDFS [functional.alltypestiny t3]
-|     partitions=4/4 files=4 size=460B
+|     HDFS partitions=4/4 files=4 size=460B
 |     row-size=4B cardinality=8
 |
 08:EXCHANGE [HASH(t2.id)]
@@ -1258,14 +1260,14 @@ PLAN-ROOT SINK
 |--07:EXCHANGE [HASH(t2.int_col)]
 |  |
 |  01:SCAN HDFS [functional.alltypessmall t2]
-|     partitions=4/4 files=4 size=6.32KB
+|     HDFS partitions=4/4 files=4 size=6.32KB
 |     runtime filters: RF000 -> t2.id
 |     row-size=8B cardinality=100
 |
 06:EXCHANGE [HASH(t1.int_col)]
 |
 00:SCAN HDFS [functional.alltypes t1]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    row-size=4B cardinality=7.30K
 ====
 # IMPALA-6123: Test the partition compatibility check with consecutive outer joins.
@@ -1304,7 +1306,7 @@ PLAN-ROOT SINK
 |--09:EXCHANGE [HASH(t3.int_col)]
 |  |
 |  02:SCAN HDFS [functional.alltypes t3]
-|     partitions=24/24 files=24 size=478.45KB
+|     HDFS partitions=24/24 files=24 size=478.45KB
 |     row-size=4B cardinality=7.30K
 |
 08:EXCHANGE [HASH(t1.int_col)]
@@ -1317,13 +1319,13 @@ PLAN-ROOT SINK
 |--07:EXCHANGE [HASH(t2.smallint_col)]
 |  |
 |  01:SCAN HDFS [functional.alltypes t2]
-|     partitions=24/24 files=24 size=478.45KB
+|     HDFS partitions=24/24 files=24 size=478.45KB
 |     row-size=2B cardinality=7.30K
 |
 06:EXCHANGE [HASH(t1.smallint_col)]
 |
 00:SCAN HDFS [functional.alltypes t1]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    runtime filters: RF000 -> t1.smallint_col
    row-size=6B cardinality=7.30K
 ====
diff --git a/testdata/workloads/functional-planner/queries/PlannerTest/predicate-propagation.test b/testdata/workloads/functional-planner/queries/PlannerTest/predicate-propagation.test
index a969846..b977b98 100644
--- a/testdata/workloads/functional-planner/queries/PlannerTest/predicate-propagation.test
+++ b/testdata/workloads/functional-planner/queries/PlannerTest/predicate-propagation.test
@@ -15,12 +15,12 @@ PLAN-ROOT SINK
 |  row-size=16B cardinality=532.90K
 |
 |--01:SCAN HDFS [functional.alltypes b]
-|     partitions=24/24 files=24 size=478.45KB
+|     HDFS partitions=24/24 files=24 size=478.45KB
 |     predicates: b.bigint_col DIV 2 = 0
 |     row-size=8B cardinality=730
 |
 00:SCAN HDFS [functional.alltypes a]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    runtime filters: RF000 -> a.double_col
    row-size=8B cardinality=7.30K
 ====
@@ -39,7 +39,7 @@ PLAN-ROOT SINK
 |  row-size=21B cardinality=10
 |
 |--02:SCAN HDFS [functional.alltypessmall b]
-|     partitions=4/4 files=4 size=6.32KB
+|     HDFS partitions=4/4 files=4 size=6.32KB
 |     predicates: b.id < 10
 |     row-size=8B cardinality=10
 |
@@ -50,7 +50,7 @@ PLAN-ROOT SINK
 |  row-size=13B cardinality=10
 |
 00:SCAN HDFS [functional.alltypes]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    row-size=9B cardinality=7.30K
 ====
 # single-table test case: partitions are pruned due to predicate inference
@@ -65,7 +65,7 @@ PLAN-ROOT SINK
 |
 00:SCAN HDFS [functional.alltypes]
    partition predicates: functional.alltypes.month < 2
-   partitions=2/24 files=2 size=40.32KB
+   HDFS partitions=2/24 files=2 size=40.32KB
    predicates: `month` = id, functional.alltypes.id < 2, functional.alltypes.tinyint_col < 2, id = int_col, int_col < 2, tinyint_col = int_col
    row-size=13B cardinality=62
 ====
@@ -85,12 +85,12 @@ PLAN-ROOT SINK
 |  row-size=38B cardinality=7.30K
 |
 |--01:SCAN HDFS [functional.alltypes]
-|     partitions=24/24 files=24 size=478.45KB
+|     HDFS partitions=24/24 files=24 size=478.45KB
 |     predicates: string_col = 'b'
 |     row-size=17B cardinality=730
 |
 00:SCAN HDFS [functional.alltypes]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    row-size=21B cardinality=7.30K
 ====
 # variation with Where clause; "b.string_col = 'b'" still needs to be applied
@@ -110,12 +110,12 @@ PLAN-ROOT SINK
 |  row-size=38B cardinality=730
 |
 |--01:SCAN HDFS [functional.alltypes]
-|     partitions=24/24 files=24 size=478.45KB
+|     HDFS partitions=24/24 files=24 size=478.45KB
 |     predicates: functional.alltypes.string_col = 'b'
 |     row-size=17B cardinality=730
 |
 00:SCAN HDFS [functional.alltypes]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    predicates: functional.alltypes.string_col = 'a'
    row-size=21B cardinality=730
 ====
@@ -132,12 +132,12 @@ PLAN-ROOT SINK
 |  row-size=30B cardinality=532.90K
 |
 |--01:SCAN HDFS [functional.alltypes]
-|     partitions=24/24 files=24 size=478.45KB
+|     HDFS partitions=24/24 files=24 size=478.45KB
 |     predicates: functional.alltypes.string_col = 'b'
 |     row-size=13B cardinality=730
 |
 00:SCAN HDFS [functional.alltypes]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    predicates: functional.alltypes.string_col = 'a'
    row-size=17B cardinality=730
 ---- DISTRIBUTEDPLAN
@@ -151,12 +151,12 @@ PLAN-ROOT SINK
 |--03:EXCHANGE [BROADCAST]
 |  |
 |  01:SCAN HDFS [functional.alltypes]
-|     partitions=24/24 files=24 size=478.45KB
+|     HDFS partitions=24/24 files=24 size=478.45KB
 |     predicates: functional.alltypes.string_col = 'b'
 |     row-size=13B cardinality=730
 |
 00:SCAN HDFS [functional.alltypes]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    predicates: functional.alltypes.string_col = 'a'
    row-size=17B cardinality=730
 ====
@@ -192,7 +192,7 @@ PLAN-ROOT SINK
 |  row-size=9B cardinality=100
 |
 00:SCAN HDFS [functional.alltypessmall]
-   partitions=4/4 files=4 size=6.32KB
+   HDFS partitions=4/4 files=4 size=6.32KB
    row-size=9B cardinality=100
 ====
 # same for with clause variant
@@ -227,7 +227,7 @@ PLAN-ROOT SINK
 |  row-size=9B cardinality=100
 |
 00:SCAN HDFS [functional.alltypessmall]
-   partitions=4/4 files=4 size=6.32KB
+   HDFS partitions=4/4 files=4 size=6.32KB
    row-size=9B cardinality=100
 ====
 # basic propagation between equivalence classes, with partition pruning
@@ -249,7 +249,7 @@ PLAN-ROOT SINK
 |
 |--02:SCAN HDFS [functional.alltypestiny c]
 |     partition predicates: c.year = 2009, c.month + 2 <= 4
-|     partitions=2/4 files=2 size=230B
+|     HDFS partitions=2/4 files=2 size=230B
 |     predicates: c.id = 17, CAST(sin(c.int_col) AS BOOLEAN) = TRUE
 |     row-size=16B cardinality=1
 |
@@ -260,14 +260,14 @@ PLAN-ROOT SINK
 |
 |--01:SCAN HDFS [functional.alltypessmall b]
 |     partition predicates: b.year = 2009, b.`month` + 2 <= 4
-|     partitions=2/4 files=2 size=3.16KB
+|     HDFS partitions=2/4 files=2 size=3.16KB
 |     predicates: b.id = 17, CAST(sin(b.smallint_col) AS BOOLEAN) = TRUE
 |     runtime filters: RF000 -> b.`month`, RF001 -> b.`year`, RF002 -> b.id, RF003 -> b.smallint_col
 |     row-size=14B cardinality=1
 |
 00:SCAN HDFS [functional.alltypes a]
    partition predicates: a.`year` = 2009, a.month + 2 <= 4
-   partitions=2/24 files=2 size=38.07KB
+   HDFS partitions=2/24 files=2 size=38.07KB
    predicates: a.id = 17, CAST(sin(a.tinyint_col) AS BOOLEAN) = TRUE
    runtime filters: RF000 -> a.month, RF001 -> a.year, RF002 -> a.id, RF003 -> a.tinyint_col, RF008 -> a.`month`, RF009 -> a.`year`, RF010 -> a.id, RF011 -> a.tinyint_col
    row-size=13B cardinality=1
@@ -295,7 +295,7 @@ PLAN-ROOT SINK
 |  |
 |  02:SCAN HDFS [functional.alltypestiny c]
 |     partition predicates: c.year = 2009, c.month + 2 <= 4
-|     partitions=2/4 files=2 size=230B
+|     HDFS partitions=2/4 files=2 size=230B
 |     predicates: c.id = 17, CAST(sin(c.int_col) AS BOOLEAN) = TRUE
 |     row-size=16B cardinality=1
 |
@@ -308,7 +308,7 @@ PLAN-ROOT SINK
 |  |
 |  01:SCAN HDFS [functional.alltypessmall b]
 |     partition predicates: b.year = 2009, b.`month` + 2 <= 4
-|     partitions=2/4 files=2 size=3.16KB
+|     HDFS partitions=2/4 files=2 size=3.16KB
 |     predicates: b.id = 17, CAST(sin(b.smallint_col) AS BOOLEAN) = TRUE
 |     runtime filters: RF000 -> b.`month`, RF001 -> b.`year`, RF002 -> b.id, RF003 -> b.smallint_col
 |     row-size=14B cardinality=1
@@ -317,7 +317,7 @@ PLAN-ROOT SINK
 |
 00:SCAN HDFS [functional.alltypes a]
    partition predicates: a.`year` = 2009, a.month + 2 <= 4
-   partitions=2/24 files=2 size=38.07KB
+   HDFS partitions=2/24 files=2 size=38.07KB
    predicates: a.id = 17, CAST(sin(a.tinyint_col) AS BOOLEAN) = TRUE
    runtime filters: RF000 -> a.month, RF001 -> a.year, RF002 -> a.id, RF003 -> a.tinyint_col, RF008 -> a.`month`, RF009 -> a.`year`, RF010 -> a.id, RF011 -> a.tinyint_col
    row-size=13B cardinality=1
@@ -342,7 +342,7 @@ PLAN-ROOT SINK
 |
 |--02:SCAN HDFS [functional.alltypestiny]
 |     partition predicates: functional.alltypestiny.year = 2009, functional.alltypestiny.month + 2 <= 4
-|     partitions=2/4 files=2 size=230B
+|     HDFS partitions=2/4 files=2 size=230B
 |     predicates: functional.alltypestiny.id = 17, CAST(sin(functional.alltypestiny.int_col) AS BOOLEAN) = TRUE
 |     row-size=16B cardinality=1
 |
@@ -353,14 +353,14 @@ PLAN-ROOT SINK
 |
 |--01:SCAN HDFS [functional.alltypessmall]
 |     partition predicates: functional.alltypessmall.year = 2009, functional.alltypessmall.month + 2 <= 4
-|     partitions=2/4 files=2 size=3.16KB
+|     HDFS partitions=2/4 files=2 size=3.16KB
 |     predicates: functional.alltypessmall.id = 17, CAST(sin(functional.alltypessmall.smallint_col) AS BOOLEAN) = TRUE
 |     runtime filters: RF000 -> functional.alltypessmall.id, RF001 -> functional.alltypessmall.month, RF002 -> functional.alltypessmall.year, RF003 -> functional.alltypessmall.smallint_col
 |     row-size=14B cardinality=1
 |
 00:SCAN HDFS [functional.alltypes]
    partition predicates: functional.alltypes.year = 2009, functional.alltypes.month + 2 <= 4
-   partitions=2/24 files=2 size=38.07KB
+   HDFS partitions=2/24 files=2 size=38.07KB
    predicates: functional.alltypes.id = 17, CAST(sin(functional.alltypes.tinyint_col) AS BOOLEAN) = TRUE
    runtime filters: RF000 -> functional.alltypes.id, RF001 -> functional.alltypes.month, RF002 -> functional.alltypes.year, RF003 -> functional.alltypes.tinyint_col, RF008 -> functional.alltypes.id, RF009 -> functional.alltypes.month, RF010 -> functional.alltypes.year, RF011 -> functional.alltypes.tinyint_col
    row-size=13B cardinality=1
@@ -388,7 +388,7 @@ PLAN-ROOT SINK
 |  |
 |  02:SCAN HDFS [functional.alltypestiny]
 |     partition predicates: functional.alltypestiny.year = 2009, functional.alltypestiny.month + 2 <= 4
-|     partitions=2/4 files=2 size=230B
+|     HDFS partitions=2/4 files=2 size=230B
 |     predicates: functional.alltypestiny.id = 17, CAST(sin(functional.alltypestiny.int_col) AS BOOLEAN) = TRUE
 |     row-size=16B cardinality=1
 |
@@ -401,7 +401,7 @@ PLAN-ROOT SINK
 |  |
 |  01:SCAN HDFS [functional.alltypessmall]
 |     partition predicates: functional.alltypessmall.year = 2009, functional.alltypessmall.month + 2 <= 4
-|     partitions=2/4 files=2 size=3.16KB
+|     HDFS partitions=2/4 files=2 size=3.16KB
 |     predicates: functional.alltypessmall.id = 17, CAST(sin(functional.alltypessmall.smallint_col) AS BOOLEAN) = TRUE
 |     runtime filters: RF000 -> functional.alltypessmall.id, RF001 -> functional.alltypessmall.month, RF002 -> functional.alltypessmall.year, RF003 -> functional.alltypessmall.smallint_col
 |     row-size=14B cardinality=1
@@ -410,7 +410,7 @@ PLAN-ROOT SINK
 |
 00:SCAN HDFS [functional.alltypes]
    partition predicates: functional.alltypes.year = 2009, functional.alltypes.month + 2 <= 4
-   partitions=2/24 files=2 size=38.07KB
+   HDFS partitions=2/24 files=2 size=38.07KB
    predicates: functional.alltypes.id = 17, CAST(sin(functional.alltypes.tinyint_col) AS BOOLEAN) = TRUE
    runtime filters: RF000 -> functional.alltypes.id, RF001 -> functional.alltypes.month, RF002 -> functional.alltypes.year, RF003 -> functional.alltypes.tinyint_col, RF008 -> functional.alltypes.id, RF009 -> functional.alltypes.month, RF010 -> functional.alltypes.year, RF011 -> functional.alltypes.tinyint_col
    row-size=13B cardinality=1
@@ -436,19 +436,19 @@ PLAN-ROOT SINK
 02:HASH JOIN [LEFT OUTER JOIN]
 |  hash predicates: a.`month` = b.`month`, a.`year` = b.`year`, a.id = b.id, a.tinyint_col = b.tinyint_col
 |  other predicates: b.int_col IS NULL, b.id = 17
-|  row-size=30B cardinality=115
+|  row-size=30B cardinality=1
 |
 |--01:SCAN HDFS [functional.alltypessmall b]
 |     partition predicates: b.`month` + 1 = 2, b.year = 2009
-|     partitions=1/4 files=1 size=1.57KB
+|     HDFS partitions=1/4 files=1 size=1.57KB
 |     predicates: b.id = 17, b.tinyint_col = 7
 |     row-size=17B cardinality=1
 |
 00:SCAN HDFS [functional.alltypes a]
    partition predicates: a.`year` = 2009
-   partitions=12/24 files=12 size=238.68KB
+   HDFS partitions=12/24 files=12 size=238.68KB
    predicates: a.id IS NULL, a.tinyint_col = 7
-   row-size=13B cardinality=115
+   row-size=13B cardinality=1
 ---- SCANRANGELOCATIONS
 NODE 0:
   HDFS SPLIT hdfs://localhost:20500/test-warehouse/alltypes/year=2009/month=1/090101.txt 0:20433
@@ -468,26 +468,28 @@ NODE 1:
 ---- DISTRIBUTEDPLAN
 PLAN-ROOT SINK
 |
-04:EXCHANGE [UNPARTITIONED]
+05:EXCHANGE [UNPARTITIONED]
 |
-02:HASH JOIN [LEFT OUTER JOIN, BROADCAST]
+02:HASH JOIN [LEFT OUTER JOIN, PARTITIONED]
 |  hash predicates: a.`month` = b.`month`, a.`year` = b.`year`, a.id = b.id, a.tinyint_col = b.tinyint_col
 |  other predicates: b.int_col IS NULL, b.id = 17
-|  row-size=30B cardinality=115
+|  row-size=30B cardinality=1
 |
-|--03:EXCHANGE [BROADCAST]
+|--04:EXCHANGE [HASH(b.`month`,b.`year`,b.id,b.tinyint_col)]
 |  |
 |  01:SCAN HDFS [functional.alltypessmall b]
 |     partition predicates: b.`month` + 1 = 2, b.year = 2009
-|     partitions=1/4 files=1 size=1.57KB
+|     HDFS partitions=1/4 files=1 size=1.57KB
 |     predicates: b.id = 17, b.tinyint_col = 7
 |     row-size=17B cardinality=1
 |
+03:EXCHANGE [HASH(a.`month`,a.`year`,a.id,a.tinyint_col)]
+|
 00:SCAN HDFS [functional.alltypes a]
    partition predicates: a.`year` = 2009
-   partitions=12/24 files=12 size=238.68KB
+   HDFS partitions=12/24 files=12 size=238.68KB
    predicates: a.id IS NULL, a.tinyint_col = 7
-   row-size=13B cardinality=115
+   row-size=13B cardinality=1
 ====
 # propagation between outer-joined tables only goes in one direction:
 # - predicates on b.year, b.tinyint_col are propagated to a
@@ -511,17 +513,17 @@ PLAN-ROOT SINK
 |  hash predicates: a.`month` = b.`month`, a.`year` = b.`year`, a.id = b.id, a.tinyint_col = b.tinyint_col
 |  other predicates: a.int_col IS NULL, a.id = 17
 |  runtime filters: RF000 <- b.`month`, RF001 <- b.`year`, RF002 <- b.id, RF003 <- b.tinyint_col
-|  row-size=30B cardinality=115
+|  row-size=30B cardinality=1
 |
 |--01:SCAN HDFS [functional.alltypes b]
 |     partition predicates: b.`year` = 2009
-|     partitions=12/24 files=12 size=238.68KB
+|     HDFS partitions=12/24 files=12 size=238.68KB
 |     predicates: b.id IS NULL, b.tinyint_col = 7
-|     row-size=13B cardinality=115
+|     row-size=13B cardinality=1
 |
 00:SCAN HDFS [functional.alltypessmall a]
    partition predicates: a.`month` + 1 = 2, a.year = 2009
-   partitions=1/4 files=1 size=1.57KB
+   HDFS partitions=1/4 files=1 size=1.57KB
    predicates: a.id = 17, a.tinyint_col = 7
    runtime filters: RF000 -> a.`month`, RF001 -> a.`year`, RF002 -> a.id, RF003 -> a.tinyint_col
    row-size=17B cardinality=1
@@ -534,21 +536,21 @@ PLAN-ROOT SINK
 |  hash predicates: a.`month` = b.`month`, a.`year` = b.`year`, a.id = b.id, a.tinyint_col = b.tinyint_col
 |  other predicates: a.int_col IS NULL, a.id = 17
 |  runtime filters: RF000 <- b.`month`, RF001 <- b.`year`, RF002 <- b.id, RF003 <- b.tinyint_col
-|  row-size=30B cardinality=115
+|  row-size=30B cardinality=1
 |
 |--04:EXCHANGE [HASH(b.`month`,b.`year`,b.id,b.tinyint_col)]
 |  |
 |  01:SCAN HDFS [functional.alltypes b]
 |     partition predicates: b.`year` = 2009
-|     partitions=12/24 files=12 size=238.68KB
+|     HDFS partitions=12/24 files=12 size=238.68KB
 |     predicates: b.id IS NULL, b.tinyint_col = 7
-|     row-size=13B cardinality=115
+|     row-size=13B cardinality=1
 |
 03:EXCHANGE [HASH(a.`month`,a.`year`,a.id,a.tinyint_col)]
 |
 00:SCAN HDFS [functional.alltypessmall a]
    partition predicates: a.`month` + 1 = 2, a.year = 2009
-   partitions=1/4 files=1 size=1.57KB
+   HDFS partitions=1/4 files=1 size=1.57KB
    predicates: a.id = 17, a.tinyint_col = 7
    runtime filters: RF000 -> a.`month`, RF001 -> a.`year`, RF002 -> a.id, RF003 -> a.tinyint_col
    row-size=17B cardinality=1
@@ -578,17 +580,17 @@ PLAN-ROOT SINK
 |  |  output: count(*)
 |  |  group by: `year`, `month`, id, int_col
 |  |  having: count(*) + 1 = 17
-|  |  row-size=24B cardinality=5
+|  |  row-size=24B cardinality=1
 |  |
 |  01:SCAN HDFS [functional.alltypessmall]
 |     partition predicates: functional.alltypessmall.year = 2009, functional.alltypessmall.month <= 2
-|     partitions=2/4 files=2 size=3.16KB
+|     HDFS partitions=2/4 files=2 size=3.16KB
 |     predicates: functional.alltypessmall.int_col != 5, id > 11
 |     row-size=16B cardinality=5
 |
 00:SCAN HDFS [functional.alltypes a]
    partition predicates: a.`year` = 2009, a.month <= 2
-   partitions=2/24 files=2 size=38.07KB
+   HDFS partitions=2/24 files=2 size=38.07KB
    predicates: a.id > 11, a.tinyint_col != 5
    runtime filters: RF000 -> a.`month`, RF001 -> a.`year`, RF002 -> a.id, RF003 -> a.tinyint_col
    row-size=13B cardinality=59
@@ -615,7 +617,7 @@ PLAN-ROOT SINK
 |  |  output: count:merge(*)
 |  |  group by: `year`, `month`, id, int_col
 |  |  having: count(*) + 1 = 17
-|  |  row-size=24B cardinality=5
+|  |  row-size=24B cardinality=1
 |  |
 |  04:EXCHANGE [HASH(`year`,`month`,id,int_col)]
 |  |
@@ -626,13 +628,13 @@ PLAN-ROOT SINK
 |  |
 |  01:SCAN HDFS [functional.alltypessmall]
 |     partition predicates: functional.alltypessmall.year = 2009, functional.alltypessmall.month <= 2
-|     partitions=2/4 files=2 size=3.16KB
+|     HDFS partitions=2/4 files=2 size=3.16KB
 |     predicates: functional.alltypessmall.int_col != 5, id > 11
 |     row-size=16B cardinality=5
 |
 00:SCAN HDFS [functional.alltypes a]
    partition predicates: a.`year` = 2009, a.month <= 2
-   partitions=2/24 files=2 size=38.07KB
+   HDFS partitions=2/24 files=2 size=38.07KB
    predicates: a.id > 11, a.tinyint_col != 5
    runtime filters: RF000 -> a.`month`, RF001 -> a.`year`, RF002 -> a.id, RF003 -> a.tinyint_col
    row-size=13B cardinality=59
@@ -665,17 +667,17 @@ PLAN-ROOT SINK
 |  |  output: count(*)
 |  |  group by: `year`, `month`, id, int_col
 |  |  having: count(*) + 1 = 17
-|  |  row-size=24B cardinality=5
+|  |  row-size=24B cardinality=1
 |  |
 |  01:SCAN HDFS [functional.alltypessmall]
 |     partition predicates: functional.alltypessmall.year = 2009, functional.alltypessmall.month <= 2
-|     partitions=2/4 files=2 size=3.16KB
+|     HDFS partitions=2/4 files=2 size=3.16KB
 |     predicates: functional.alltypessmall.int_col != 5, id > 11
 |     row-size=16B cardinality=5
 |
 00:SCAN HDFS [functional.alltypes a]
    partition predicates: a.`year` = 2009, a.month <= 2
-   partitions=2/24 files=2 size=38.07KB
+   HDFS partitions=2/24 files=2 size=38.07KB
    predicates: a.id > 11, a.tinyint_col != 5
    runtime filters: RF000 -> a.`month`, RF001 -> a.`year`, RF002 -> a.id, RF003 -> a.tinyint_col
    row-size=13B cardinality=59
@@ -695,7 +697,7 @@ PLAN-ROOT SINK
 |  |  output: count:merge(*)
 |  |  group by: `year`, `month`, id, int_col
 |  |  having: count(*) + 1 = 17
-|  |  row-size=24B cardinality=5
+|  |  row-size=24B cardinality=1
 |  |
 |  04:EXCHANGE [HASH(`year`,`month`,id,int_col)]
 |  |
@@ -706,13 +708,13 @@ PLAN-ROOT SINK
 |  |
 |  01:SCAN HDFS [functional.alltypessmall]
 |     partition predicates: functional.alltypessmall.year = 2009, functional.alltypessmall.month <= 2
-|     partitions=2/4 files=2 size=3.16KB
+|     HDFS partitions=2/4 files=2 size=3.16KB
 |     predicates: functional.alltypessmall.int_col != 5, id > 11
 |     row-size=16B cardinality=5
 |
 00:SCAN HDFS [functional.alltypes a]
    partition predicates: a.`year` = 2009, a.month <= 2
-   partitions=2/24 files=2 size=38.07KB
+   HDFS partitions=2/24 files=2 size=38.07KB
    predicates: a.id > 11, a.tinyint_col != 5
    runtime filters: RF000 -> a.`month`, RF001 -> a.`year`, RF002 -> a.id, RF003 -> a.tinyint_col
    row-size=13B cardinality=59
@@ -750,13 +752,13 @@ PLAN-ROOT SINK
 |  |  row-size=24B cardinality=5
 |  |
 |  01:SCAN HDFS [functional.alltypessmall]
-|     partitions=4/4 files=4 size=6.32KB
+|     HDFS partitions=4/4 files=4 size=6.32KB
 |     predicates: id > 11
 |     row-size=16B cardinality=10
 |
 00:SCAN HDFS [functional.alltypes a]
    partition predicates: a.`year` = 2009, a.month <= 2
-   partitions=2/24 files=2 size=38.07KB
+   HDFS partitions=2/24 files=2 size=38.07KB
    predicates: a.id > 11, a.tinyint_col != 5
    runtime filters: RF000 -> a.`month`, RF001 -> a.`year`, RF002 -> a.id, RF003 -> a.tinyint_col
    row-size=13B cardinality=59
@@ -802,13 +804,13 @@ PLAN-ROOT SINK
 |  |  row-size=24B cardinality=10
 |  |
 |  01:SCAN HDFS [functional.alltypessmall]
-|     partitions=4/4 files=4 size=6.32KB
+|     HDFS partitions=4/4 files=4 size=6.32KB
 |     predicates: id > 11
 |     row-size=16B cardinality=10
 |
 00:SCAN HDFS [functional.alltypes a]
    partition predicates: a.`year` = 2009, a.month <= 2
-   partitions=2/24 files=2 size=38.07KB
+   HDFS partitions=2/24 files=2 size=38.07KB
    predicates: a.id > 11, a.tinyint_col != 5
    runtime filters: RF000 -> a.`month`, RF001 -> a.`year`, RF002 -> a.id, RF003 -> a.tinyint_col
    row-size=13B cardinality=59
@@ -849,13 +851,13 @@ PLAN-ROOT SINK
 |  |  row-size=24B cardinality=5
 |  |
 |  01:SCAN HDFS [functional.alltypessmall]
-|     partitions=4/4 files=4 size=6.32KB
+|     HDFS partitions=4/4 files=4 size=6.32KB
 |     predicates: id > 11
 |     row-size=16B cardinality=10
 |
 00:SCAN HDFS [functional.alltypes a]
    partition predicates: a.`year` = 2009, a.month <= 2
-   partitions=2/24 files=2 size=38.07KB
+   HDFS partitions=2/24 files=2 size=38.07KB
    predicates: a.id > 11, a.tinyint_col != 5
    runtime filters: RF000 -> a.`month`, RF001 -> a.`year`, RF002 -> a.id, RF003 -> a.tinyint_col
    row-size=13B cardinality=59
@@ -892,13 +894,13 @@ PLAN-ROOT SINK
 |  |  row-size=24B cardinality=10
 |  |
 |  01:SCAN HDFS [functional.alltypessmall]
-|     partitions=4/4 files=4 size=6.32KB
+|     HDFS partitions=4/4 files=4 size=6.32KB
 |     predicates: id > 11
 |     row-size=16B cardinality=10
 |
 00:SCAN HDFS [functional.alltypes a]
    partition predicates: a.`year` = 2009, a.month <= 2
-   partitions=2/24 files=2 size=38.07KB
+   HDFS partitions=2/24 files=2 size=38.07KB
    predicates: a.id > 11, a.tinyint_col != 5
    runtime filters: RF000 -> a.`month`, RF001 -> a.`year`, RF002 -> a.id, RF003 -> a.tinyint_col
    row-size=13B cardinality=59
@@ -923,13 +925,13 @@ PLAN-ROOT SINK
 |  |  row-size=12B cardinality=10
 |  |
 |  01:SCAN HDFS [functional.alltypesagg]
-|     partitions=11/11 files=11 size=814.73KB
+|     HDFS partitions=11/11 files=11 size=814.73KB
 |     limit: 10
 |     row-size=12B cardinality=10
 |
 00:SCAN HDFS [functional.alltypes]
    partition predicates: functional.alltypes.year = 2009
-   partitions=12/24 files=12 size=238.68KB
+   HDFS partitions=12/24 files=12 size=238.68KB
    runtime filters: RF000 -> functional.alltypes.id
    row-size=8B cardinality=3.65K
 ====
@@ -962,7 +964,7 @@ PLAN-ROOT SINK
 |  |  row-size=12B cardinality=10
 |  |
 |  03:SCAN HDFS [functional.alltypesagg]
-|     partitions=11/11 files=11 size=814.73KB
+|     HDFS partitions=11/11 files=11 size=814.73KB
 |     limit: 10
 |     row-size=12B cardinality=10
 |
@@ -974,12 +976,12 @@ PLAN-ROOT SINK
 |
 |--01:SCAN HDFS [functional.alltypessmall b]
 |     partition predicates: b.year = 2009
-|     partitions=4/4 files=4 size=6.32KB
+|     HDFS partitions=4/4 files=4 size=6.32KB
 |     row-size=12B cardinality=100
 |
 00:SCAN HDFS [functional.alltypes a]
    partition predicates: a.year = 2009
-   partitions=12/24 files=12 size=238.68KB
+   HDFS partitions=12/24 files=12 size=238.68KB
    runtime filters: RF000 -> a.id, RF002 -> a.`year`, RF003 -> a.int_col
    row-size=12B cardinality=3.65K
 ====
@@ -994,7 +996,7 @@ PLAN-ROOT SINK
 03:HASH JOIN [LEFT OUTER JOIN]
 |  hash predicates: a.id = id
 |  other predicates: int_col = 17, isnull(id, 0) = 0
-|  row-size=12B cardinality=730
+|  row-size=12B cardinality=1
 |
 |--02:AGGREGATE [FINALIZE]
 |  |  group by: id, int_col
@@ -1002,14 +1004,14 @@ PLAN-ROOT SINK
 |  |  row-size=8B cardinality=73
 |  |
 |  01:SCAN HDFS [functional.alltypes]
-|     partitions=24/24 files=24 size=478.45KB
+|     HDFS partitions=24/24 files=24 size=478.45KB
 |     predicates: functional.alltypes.int_col = 17
 |     row-size=8B cardinality=730
 |
 00:SCAN HDFS [functional.alltypes a]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    predicates: a.id IS NULL
-   row-size=4B cardinality=730
+   row-size=4B cardinality=1
 ====
 select straight_join a.id, b.id
 from functional.alltypes a left outer join
@@ -1034,7 +1036,7 @@ PLAN-ROOT SINK
 |  |  |  row-size=8B cardinality=10
 |  |  |
 |  |  04:SCAN HDFS [functional.alltypessmall]
-|  |     partitions=4/4 files=4 size=6.32KB
+|  |     HDFS partitions=4/4 files=4 size=6.32KB
 |  |     predicates: functional.alltypessmall.int_col = 17
 |  |     row-size=8B cardinality=10
 |  |
@@ -1043,12 +1045,12 @@ PLAN-ROOT SINK
 |  |  row-size=8B cardinality=730
 |  |
 |  02:SCAN HDFS [functional.alltypes]
-|     partitions=24/24 files=24 size=478.45KB
+|     HDFS partitions=24/24 files=24 size=478.45KB
 |     predicates: functional.alltypes.int_col = 17
 |     row-size=8B cardinality=730
 |
 00:SCAN HDFS [functional.alltypes a]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    predicates: isnull(a.id, 0) = 0
    row-size=4B cardinality=730
 ====
@@ -1060,25 +1062,27 @@ where a.id is null and isnull(b.id, 0) = 0 and b.int_col = 17
 ---- PLAN
 PLAN-ROOT SINK
 |
-03:HASH JOIN [LEFT OUTER JOIN]
-|  hash predicates: a.id = id
+03:HASH JOIN [RIGHT OUTER JOIN]
+|  hash predicates: id = a.id
 |  other predicates: int_col = 17, isnull(id, 0) = 0
-|  row-size=12B cardinality=730
+|  runtime filters: RF000 <- a.id
+|  row-size=12B cardinality=1
 |
-|--01:AGGREGATE [FINALIZE]
-|  |  group by: id, int_col
-|  |  having: int_col = 17
-|  |  row-size=8B cardinality=73
-|  |
-|  00:SCAN HDFS [functional.alltypes]
+|--02:SCAN HDFS [functional.alltypes a]
 |     HDFS partitions=24/24 files=24 size=478.45KB
-|     predicates: functional.alltypes.int_col = 17
-|     row-size=8B cardinality=730
+|     predicates: a.id IS NULL
+|     row-size=4B cardinality=1
+|
+01:AGGREGATE [FINALIZE]
+|  group by: id, int_col
+|  having: int_col = 17
+|  row-size=8B cardinality=73
 |
-02:SCAN HDFS [functional.alltypes a]
+00:SCAN HDFS [functional.alltypes]
    HDFS partitions=24/24 files=24 size=478.45KB
-   predicates: a.id IS NULL
-   row-size=4B cardinality=730
+   predicates: functional.alltypes.int_col = 17
+   runtime filters: RF000 -> functional.alltypes.id
+   row-size=8B cardinality=730
 ====
 select straight_join a.id, b.id
 from
@@ -1096,7 +1100,7 @@ PLAN-ROOT SINK
 |  row-size=12B cardinality=740
 |
 |--05:SCAN HDFS [functional.alltypes a]
-|     partitions=24/24 files=24 size=478.45KB
+|     HDFS partitions=24/24 files=24 size=478.45KB
 |     predicates: isnull(a.id, 0) = 0
 |     row-size=4B cardinality=730
 |
@@ -1109,7 +1113,7 @@ PLAN-ROOT SINK
 |  |  row-size=8B cardinality=10
 |  |
 |  03:SCAN HDFS [functional.alltypessmall]
-|     partitions=4/4 files=4 size=6.32KB
+|     HDFS partitions=4/4 files=4 size=6.32KB
 |     predicates: functional.alltypessmall.int_col = 17
 |     runtime filters: RF000 -> functional.alltypessmall.id
 |     row-size=8B cardinality=10
@@ -1119,7 +1123,7 @@ PLAN-ROOT SINK
 |  row-size=8B cardinality=730
 |
 01:SCAN HDFS [functional.alltypes]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    predicates: functional.alltypes.int_col = 17
    runtime filters: RF000 -> functional.alltypes.id
    row-size=8B cardinality=730
@@ -1136,12 +1140,12 @@ PLAN-ROOT SINK
 |  row-size=21B cardinality=7.31K
 |
 |--01:SCAN HDFS [functional.alltypessmall]
-|     partitions=4/4 files=4 size=6.32KB
+|     HDFS partitions=4/4 files=4 size=6.32KB
 |     predicates: id > 0
 |     row-size=4B cardinality=10
 |
 00:SCAN HDFS [functional.alltypes a]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    row-size=17B cardinality=7.30K
 ====
 # TODO: Remove the following limitation in our predicate propagation:
@@ -1169,17 +1173,17 @@ PLAN-ROOT SINK
 |  |  row-size=8B cardinality=1
 |  |
 |  |--02:SCAN HDFS [functional.alltypestiny y]
-|  |     partitions=4/4 files=4 size=460B
+|  |     HDFS partitions=4/4 files=4 size=460B
 |  |     row-size=4B cardinality=8
 |  |
 |  01:SCAN HDFS [functional.alltypessmall x]
-|     partitions=4/4 files=4 size=6.32KB
+|     HDFS partitions=4/4 files=4 size=6.32KB
 |     predicates: x.id IS NULL
 |     runtime filters: RF000 -> x.id
-|     row-size=4B cardinality=10
+|     row-size=4B cardinality=1
 |
 00:SCAN HDFS [functional.alltypes a]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    row-size=17B cardinality=7.30K
 ====
 # Test proper assignment of Having-clause predicates (IMPALA-820):
@@ -1199,7 +1203,7 @@ PLAN-ROOT SINK
 |  row-size=13B cardinality=2
 |
 00:SCAN HDFS [functional.alltypes]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    predicates: functional.alltypes.int_col > 0, functional.alltypes.bool_col = FALSE
    row-size=13B cardinality=516
 ====
@@ -1229,7 +1233,7 @@ PLAN-ROOT SINK
 |  row-size=35B cardinality=1
 |
 |--02:SCAN HDFS [functional.alltypestiny]
-|     partitions=4/4 files=4 size=460B
+|     HDFS partitions=4/4 files=4 size=460B
 |     predicates: functional.alltypestiny.id + functional.alltypestiny.bigint_col > 20, functional.alltypestiny.id + functional.alltypestiny.int_col > 10, functional.alltypestiny.id + functional.alltypestiny.int_col + functional.alltypestiny.bigint_col > 30
 |     row-size=16B cardinality=1
 |
@@ -1239,13 +1243,13 @@ PLAN-ROOT SINK
 |  row-size=19B cardinality=1
 |
 |--01:SCAN HDFS [functional.alltypessmall t2]
-|     partitions=4/4 files=4 size=6.32KB
+|     HDFS partitions=4/4 files=4 size=6.32KB
 |     predicates: t2.id + t2.bigint_col > 20, t2.id + t2.smallint_col > 10, t2.id + t2.smallint_col + t2.bigint_col > 30
 |     runtime filters: RF000 -> t2.bigint_col, RF001 -> t2.id, RF002 -> t2.smallint_col
 |     row-size=14B cardinality=10
 |
 00:SCAN HDFS [functional.alltypes t1]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    predicates: t1.id + t1.tinyint_col > 10
    runtime filters: RF001 -> t1.id, RF002 -> t1.tinyint_col, RF006 -> t1.id, RF007 -> t1.tinyint_col
    row-size=5B cardinality=730
@@ -1278,10 +1282,10 @@ PLAN-ROOT SINK
 |--04:AGGREGATE [FINALIZE]
 |  |  output: max(smallint_col), min(int_col)
 |  |  having: max(smallint_col) + min(int_col) > 30
-|  |  row-size=6B cardinality=0
+|  |  row-size=6B cardinality=1
 |  |
 |  03:SCAN HDFS [functional.alltypestiny]
-|     partitions=4/4 files=4 size=460B
+|     HDFS partitions=4/4 files=4 size=460B
 |     row-size=6B cardinality=8
 |
 05:HASH JOIN [INNER JOIN]
@@ -1296,11 +1300,11 @@ PLAN-ROOT SINK
 |  |  row-size=22B cardinality=1
 |  |
 |  01:SCAN HDFS [functional.alltypessmall]
-|     partitions=4/4 files=4 size=6.32KB
+|     HDFS partitions=4/4 files=4 size=6.32KB
 |     row-size=15B cardinality=100
 |
 00:SCAN HDFS [functional.alltypes t1]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    predicates: t1.id + t1.tinyint_col > 10, t1.id + t1.tinyint_col > 20
    runtime filters: RF000 -> t1.tinyint_col, RF002 -> t1.id, RF003 -> t1.tinyint_col
    row-size=5B cardinality=730
@@ -1332,7 +1336,7 @@ PLAN-ROOT SINK
 |  row-size=46B cardinality=730
 |
 |--02:SCAN HDFS [functional.alltypestiny]
-|     partitions=4/4 files=4 size=460B
+|     HDFS partitions=4/4 files=4 size=460B
 |     predicates: functional.alltypestiny.id * functional.alltypestiny.int_col < 100, functional.alltypestiny.tinyint_col + functional.alltypestiny.smallint_col + functional.alltypestiny.int_col > 10
 |     row-size=19B cardinality=1
 |
@@ -1342,12 +1346,12 @@ PLAN-ROOT SINK
 |  row-size=27B cardinality=730
 |
 |--01:SCAN HDFS [functional.alltypessmall t2]
-|     partitions=4/4 files=4 size=6.32KB
+|     HDFS partitions=4/4 files=4 size=6.32KB
 |     predicates: t2.tinyint_col = t2.smallint_col, t2.id * t2.int_col < 100
 |     row-size=19B cardinality=10
 |
 00:SCAN HDFS [functional.alltypes t1]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    predicates: t1.id * t1.int_col < 100
    row-size=8B cardinality=730
 ====
@@ -1368,11 +1372,11 @@ PLAN-ROOT SINK
 |
 |--01:SCAN HDFS [functional.alltypessmall t2]
 |     partition predicates: t2.`year` + t2.`month` > 10
-|     partitions=4/4 files=4 size=6.32KB
+|     HDFS partitions=4/4 files=4 size=6.32KB
 |     row-size=89B cardinality=100
 |
 00:SCAN HDFS [functional.alltypes t1]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    predicates: t1.id = t1.month, t1.year + t1.id > 10
    runtime filters: RF000 -> t1.`year`, RF001 -> t1.id
    row-size=89B cardinality=730
@@ -1396,12 +1400,12 @@ PLAN-ROOT SINK
 |  row-size=178B cardinality=1
 |
 |--01:SCAN HDFS [functional.alltypessmall t2]
-|     partitions=4/4 files=4 size=6.32KB
+|     HDFS partitions=4/4 files=4 size=6.32KB
 |     predicates: t2.id = t2.smallint_col, t2.tinyint_col = t2.int_col, t2.id + t2.tinyint_col > 10
 |     row-size=89B cardinality=10
 |
 00:SCAN HDFS [functional.alltypes t1]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    predicates: t1.id + t1.tinyint_col > 10
    runtime filters: RF000 -> t1.id, RF001 -> t1.tinyint_col
    row-size=89B cardinality=730
@@ -1431,11 +1435,11 @@ PLAN-ROOT SINK
 |  |  row-size=16B cardinality=10
 |  |
 |  01:SCAN HDFS [functional.alltypessmall]
-|     partitions=4/4 files=4 size=6.32KB
+|     HDFS partitions=4/4 files=4 size=6.32KB
 |     row-size=12B cardinality=100
 |
 00:SCAN HDFS [functional.alltypes t1]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    predicates: t1.id + t1.int_col > 10
    runtime filters: RF000 -> t1.int_col, RF001 -> t1.id
    row-size=89B cardinality=730
@@ -1456,12 +1460,12 @@ PLAN-ROOT SINK
 |  row-size=89B cardinality=730
 |
 |--01:SCAN HDFS [functional.alltypestiny]
-|     partitions=4/4 files=4 size=460B
+|     HDFS partitions=4/4 files=4 size=460B
 |     predicates: functional.alltypestiny.id < 10, id > -20
 |     row-size=4B cardinality=1
 |
 00:SCAN HDFS [functional.alltypes a]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    predicates: a.id < 10
    row-size=89B cardinality=730
 ====
@@ -1480,12 +1484,12 @@ PLAN-ROOT SINK
 |  row-size=89B cardinality=1
 |
 |--01:SCAN HDFS [functional.alltypestiny b]
-|     partitions=4/4 files=4 size=460B
+|     HDFS partitions=4/4 files=4 size=460B
 |     predicates: b.id < 10
 |     row-size=89B cardinality=1
 |
 00:SCAN HDFS [functional.alltypes]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    predicates: functional.alltypes.id < 10, id > -20
    row-size=4B cardinality=730
 ====
@@ -1513,11 +1517,11 @@ PLAN-ROOT SINK
 |  row-size=13B cardinality=9
 |
 |--00:SCAN HDFS [functional.alltypestiny a]
-|     partitions=4/4 files=4 size=460B
+|     HDFS partitions=4/4 files=4 size=460B
 |     row-size=5B cardinality=8
 |
 01:SCAN HDFS [functional.alltypesagg b]
-   partitions=11/11 files=11 size=814.73KB
+   HDFS partitions=11/11 files=11 size=814.73KB
    predicates: b.int_col = 10
    runtime filters: RF000 -> b.id
    row-size=8B cardinality=11
@@ -1540,11 +1544,11 @@ PLAN-ROOT SINK
 |  row-size=13B cardinality=9
 |
 |--00:SCAN HDFS [functional.alltypestiny a]
-|     partitions=4/4 files=4 size=460B
+|     HDFS partitions=4/4 files=4 size=460B
 |     row-size=5B cardinality=8
 |
 01:SCAN HDFS [functional.alltypesagg b]
-   partitions=11/11 files=11 size=814.73KB
+   HDFS partitions=11/11 files=11 size=814.73KB
    predicates: b.int_col = 10
    runtime filters: RF000 -> b.id
    row-size=8B cardinality=11
@@ -1569,7 +1573,7 @@ PLAN-ROOT SINK
 |  row-size=31B cardinality=15.00K
 |
 |--03:SCAN HDFS [tpch_parquet.region r]
-|     partitions=1/1 files=1 size=1.34KB
+|     HDFS partitions=1/1 files=1 size=1.57KB
 |     predicates: r.r_regionkey = 1
 |     row-size=2B cardinality=1
 |
@@ -1577,12 +1581,12 @@ PLAN-ROOT SINK
 |  row-size=29B cardinality=15.00K
 |
 |--01:SCAN HDFS [tpch_parquet.nation n]
-|     partitions=1/1 files=1 size=2.75KB
+|     HDFS partitions=1/1 files=1 size=3.04KB
 |     predicates: n_regionkey = 1, n_name = 'BRAZIL'
 |     row-size=21B cardinality=1
 |
 00:SCAN HDFS [tpch_parquet.customer c]
-   partitions=1/1 files=1 size=12.31MB
+   HDFS partitions=1/1 files=1 size=12.34MB
    predicates: c_custkey % 2 = 0
    row-size=8B cardinality=15.00K
 ====
diff --git a/testdata/workloads/functional-planner/queries/PlannerTest/topn.test b/testdata/workloads/functional-planner/queries/PlannerTest/topn.test
index 5ff642c..ee859b4 100644
--- a/testdata/workloads/functional-planner/queries/PlannerTest/topn.test
+++ b/testdata/workloads/functional-planner/queries/PlannerTest/topn.test
@@ -10,7 +10,7 @@ PLAN-ROOT SINK
 |  row-size=16B cardinality=0
 |
 00:SCAN HDFS [functional.testtbl]
-   partitions=1/1 files=0 size=0B
+   HDFS partitions=1/1 files=0 size=0B
    row-size=16B cardinality=0
 ---- DISTRIBUTEDPLAN
 PLAN-ROOT SINK
@@ -24,7 +24,7 @@ PLAN-ROOT SINK
 |  row-size=16B cardinality=0
 |
 00:SCAN HDFS [functional.testtbl]
-   partitions=1/1 files=0 size=0B
+   HDFS partitions=1/1 files=0 size=0B
    row-size=16B cardinality=0
 ====
 select zip, count(*)
@@ -46,7 +46,7 @@ PLAN-ROOT SINK
 |  row-size=12B cardinality=0
 |
 00:SCAN HDFS [functional.testtbl]
-   partitions=1/1 files=0 size=0B
+   HDFS partitions=1/1 files=0 size=0B
    predicates: name LIKE 'm%'
    row-size=16B cardinality=0
 ---- DISTRIBUTEDPLAN
@@ -73,7 +73,7 @@ PLAN-ROOT SINK
 |  row-size=12B cardinality=0
 |
 00:SCAN HDFS [functional.testtbl]
-   partitions=1/1 files=0 size=0B
+   HDFS partitions=1/1 files=0 size=0B
    predicates: name LIKE 'm%'
    row-size=16B cardinality=0
 ====
@@ -157,21 +157,21 @@ PLAN-ROOT SINK
 02:HASH JOIN [INNER JOIN]
 |  hash predicates: t1.id = t2.id
 |  runtime filters: RF000 <- t2.id
-|  row-size=16B cardinality=10
+|  row-size=16B cardinality=100
 |
 |--01:SCAN HDFS [functional.alltypessmall t2]
-|     partitions=4/4 files=4 size=6.32KB
+|     HDFS partitions=4/4 files=4 size=6.32KB
 |     predicates: t2.int_col IS NOT NULL
-|     row-size=8B cardinality=10
+|     row-size=8B cardinality=100
 |
 00:SCAN HDFS [functional.alltypessmall t1]
-   partitions=4/4 files=4 size=6.32KB
+   HDFS partitions=4/4 files=4 size=6.32KB
    runtime filters: RF000 -> t1.id
    row-size=8B cardinality=100
 ---- DISTRIBUTEDPLAN
 PLAN-ROOT SINK
 |
-05:MERGING-EXCHANGE [UNPARTITIONED]
+06:MERGING-EXCHANGE [UNPARTITIONED]
 |  order by: int_col ASC
 |  limit: 2
 |
@@ -179,20 +179,22 @@ PLAN-ROOT SINK
 |  order by: int_col ASC
 |  row-size=4B cardinality=2
 |
-02:HASH JOIN [INNER JOIN, BROADCAST]
+02:HASH JOIN [INNER JOIN, PARTITIONED]
 |  hash predicates: t1.id = t2.id
 |  runtime filters: RF000 <- t2.id
-|  row-size=16B cardinality=10
+|  row-size=16B cardinality=100
 |
-|--04:EXCHANGE [BROADCAST]
+|--05:EXCHANGE [HASH(t2.id)]
 |  |
 |  01:SCAN HDFS [functional.alltypessmall t2]
-|     partitions=4/4 files=4 size=6.32KB
+|     HDFS partitions=4/4 files=4 size=6.32KB
 |     predicates: t2.int_col IS NOT NULL
-|     row-size=8B cardinality=10
+|     row-size=8B cardinality=100
+|
+04:EXCHANGE [HASH(t1.id)]
 |
 00:SCAN HDFS [functional.alltypessmall t1]
-   partitions=4/4 files=4 size=6.32KB
+   HDFS partitions=4/4 files=4 size=6.32KB
    runtime filters: RF000 -> t1.id
    row-size=8B cardinality=100
 ====
@@ -206,7 +208,7 @@ PLAN-ROOT SINK
 |  row-size=4B cardinality=2
 |
 00:SCAN HDFS [functional.alltypessmall]
-   partitions=4/4 files=4 size=6.32KB
+   HDFS partitions=4/4 files=4 size=6.32KB
    row-size=4B cardinality=100
 ---- DISTRIBUTEDPLAN
 PLAN-ROOT SINK
@@ -220,7 +222,7 @@ PLAN-ROOT SINK
 |  row-size=4B cardinality=2
 |
 00:SCAN HDFS [functional.alltypessmall]
-   partitions=4/4 files=4 size=6.32KB
+   HDFS partitions=4/4 files=4 size=6.32KB
    row-size=4B cardinality=100
 ====
 # Test that the top-n is on id and not on int_col
@@ -233,7 +235,7 @@ PLAN-ROOT SINK
 |  row-size=8B cardinality=2
 |
 00:SCAN HDFS [functional.alltypessmall]
-   partitions=4/4 files=4 size=6.32KB
+   HDFS partitions=4/4 files=4 size=6.32KB
    row-size=8B cardinality=100
 ---- DISTRIBUTEDPLAN
 PLAN-ROOT SINK
@@ -247,7 +249,7 @@ PLAN-ROOT SINK
 |  row-size=8B cardinality=2
 |
 00:SCAN HDFS [functional.alltypessmall]
-   partitions=4/4 files=4 size=6.32KB
+   HDFS partitions=4/4 files=4 size=6.32KB
    row-size=8B cardinality=100
 ====
 # Test that the limit/offset is propagated correctly to child nodes. The TOP-N node
@@ -267,15 +269,15 @@ PLAN-ROOT SINK
 02:HASH JOIN [INNER JOIN]
 |  hash predicates: t1.id = t2.id
 |  runtime filters: RF000 <- t2.id
-|  row-size=16B cardinality=10
+|  row-size=16B cardinality=100
 |
 |--01:SCAN HDFS [functional.alltypessmall t2]
-|     partitions=4/4 files=4 size=6.32KB
+|     HDFS partitions=4/4 files=4 size=6.32KB
 |     predicates: t2.int_col IS NOT NULL
-|     row-size=8B cardinality=10
+|     row-size=8B cardinality=100
 |
 00:SCAN HDFS [functional.alltypessmall t1]
-   partitions=4/4 files=4 size=6.32KB
+   HDFS partitions=4/4 files=4 size=6.32KB
    runtime filters: RF000 -> t1.id
    row-size=8B cardinality=100
 ---- SCANRANGELOCATIONS
@@ -292,29 +294,31 @@ NODE 1:
 ---- DISTRIBUTEDPLAN
 PLAN-ROOT SINK
 |
-05:MERGING-EXCHANGE [UNPARTITIONED]
+06:MERGING-EXCHANGE [UNPARTITIONED]
 |  offset: 5
 |  order by: int_col ASC
 |  limit: 10
 |
 03:TOP-N [LIMIT=15]
 |  order by: int_col ASC
-|  row-size=4B cardinality=10
+|  row-size=4B cardinality=15
 |
-02:HASH JOIN [INNER JOIN, BROADCAST]
+02:HASH JOIN [INNER JOIN, PARTITIONED]
 |  hash predicates: t1.id = t2.id
 |  runtime filters: RF000 <- t2.id
-|  row-size=16B cardinality=10
+|  row-size=16B cardinality=100
 |
-|--04:EXCHANGE [BROADCAST]
+|--05:EXCHANGE [HASH(t2.id)]
 |  |
 |  01:SCAN HDFS [functional.alltypessmall t2]
-|     partitions=4/4 files=4 size=6.32KB
+|     HDFS partitions=4/4 files=4 size=6.32KB
 |     predicates: t2.int_col IS NOT NULL
-|     row-size=8B cardinality=10
+|     row-size=8B cardinality=100
+|
+04:EXCHANGE [HASH(t1.id)]
 |
 00:SCAN HDFS [functional.alltypessmall t1]
-   partitions=4/4 files=4 size=6.32KB
+   HDFS partitions=4/4 files=4 size=6.32KB
    runtime filters: RF000 -> t1.id
    row-size=8B cardinality=100
 ====
@@ -336,11 +340,11 @@ PLAN-ROOT SINK
 |  row-size=12B cardinality=7.40K
 |
 |--02:SCAN HDFS [functional.alltypessmall]
-|     partitions=4/4 files=4 size=6.32KB
+|     HDFS partitions=4/4 files=4 size=6.32KB
 |     row-size=12B cardinality=100
 |
 01:SCAN HDFS [functional.alltypes]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    row-size=12B cardinality=7.30K
 ---- DISTRIBUTEDPLAN
 PLAN-ROOT SINK
@@ -359,11 +363,11 @@ PLAN-ROOT SINK
 |  row-size=12B cardinality=7.40K
 |
 |--02:SCAN HDFS [functional.alltypessmall]
-|     partitions=4/4 files=4 size=6.32KB
+|     HDFS partitions=4/4 files=4 size=6.32KB
 |     row-size=12B cardinality=100
 |
 01:SCAN HDFS [functional.alltypes]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    row-size=12B cardinality=7.30K
 ====
 # test distributed top-n over a union distinct (IMPALA-831)
@@ -388,11 +392,11 @@ PLAN-ROOT SINK
 |  row-size=89B cardinality=7.40K
 |
 |--02:SCAN HDFS [functional.alltypessmall]
-|     partitions=4/4 files=4 size=6.32KB
+|     HDFS partitions=4/4 files=4 size=6.32KB
 |     row-size=89B cardinality=100
 |
 01:SCAN HDFS [functional.alltypes]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    row-size=89B cardinality=7.30K
 ---- DISTRIBUTEDPLAN
 PLAN-ROOT SINK
@@ -421,11 +425,11 @@ PLAN-ROOT SINK
 |  row-size=89B cardinality=7.40K
 |
 |--02:SCAN HDFS [functional.alltypessmall]
-|     partitions=4/4 files=4 size=6.32KB
+|     HDFS partitions=4/4 files=4 size=6.32KB
 |     row-size=89B cardinality=100
 |
 01:SCAN HDFS [functional.alltypes]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    row-size=89B cardinality=7.30K
 ====
 # test that top-n is not placed below an unpartitioned exchange with a limit
@@ -439,7 +443,7 @@ PLAN-ROOT SINK
 |  row-size=89B cardinality=10
 |
 00:SCAN HDFS [functional.alltypes]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    limit: 10
    row-size=89B cardinality=10
 ---- DISTRIBUTEDPLAN
@@ -453,7 +457,7 @@ PLAN-ROOT SINK
 |  limit: 10
 |
 00:SCAN HDFS [functional.alltypes]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    limit: 10
    row-size=89B cardinality=10
 ====
@@ -476,11 +480,11 @@ PLAN-ROOT SINK
 |  row-size=89B cardinality=10
 |
 |--02:SCAN HDFS [functional.alltypessmall]
-|     partitions=4/4 files=4 size=6.32KB
+|     HDFS partitions=4/4 files=4 size=6.32KB
 |     row-size=89B cardinality=100
 |
 01:SCAN HDFS [functional.alltypes]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    row-size=89B cardinality=7.30K
 ---- DISTRIBUTEDPLAN
 PLAN-ROOT SINK
@@ -498,10 +502,10 @@ PLAN-ROOT SINK
 |  row-size=89B cardinality=10
 |
 |--02:SCAN HDFS [functional.alltypessmall]
-|     partitions=4/4 files=4 size=6.32KB
+|     HDFS partitions=4/4 files=4 size=6.32KB
 |     row-size=89B cardinality=100
 |
 01:SCAN HDFS [functional.alltypes]
-   partitions=24/24 files=24 size=478.45KB
+   HDFS partitions=24/24 files=24 size=478.45KB
    row-size=89B cardinality=7.30K
 ====