From 7af6d0c19e877c80f0ec60575f5dc677f2cc2307 Mon Sep 17 00:00:00 2001 From: Binjie Yang Date: Thu, 29 Feb 2024 09:23:45 +0800 Subject: [PATCH] [GLUTEN-4398][IT] Add Golden Files for TPC-H Spark32 + Gluten Execution Plan (#4432) --- .github/workflows/velox_be.yml | 15 + .../tpch-approved-plan/v1-bhj/spark322/1.txt | 154 +++ .../tpch-approved-plan/v1-bhj/spark322/10.txt | 367 +++++++ .../tpch-approved-plan/v1-bhj/spark322/11.txt | 314 ++++++ .../tpch-approved-plan/v1-bhj/spark322/12.txt | 229 +++++ .../tpch-approved-plan/v1-bhj/spark322/13.txt | 286 ++++++ .../tpch-approved-plan/v1-bhj/spark322/14.txt | 192 ++++ .../tpch-approved-plan/v1-bhj/spark322/15.txt | 239 +++++ .../tpch-approved-plan/v1-bhj/spark322/16.txt | 312 ++++++ .../tpch-approved-plan/v1-bhj/spark322/17.txt | 200 ++++ .../tpch-approved-plan/v1-bhj/spark322/18.txt | 476 +++++++++ .../tpch-approved-plan/v1-bhj/spark322/19.txt | 187 ++++ .../tpch-approved-plan/v1-bhj/spark322/20.txt | 568 +++++++++++ .../tpch-approved-plan/v1-bhj/spark322/21.txt | 500 ++++++++++ .../tpch-approved-plan/v1-bhj/spark322/22.txt | 207 ++++ .../tpch-approved-plan/v1-bhj/spark322/3.txt | 292 ++++++ .../tpch-approved-plan/v1-bhj/spark322/4.txt | 239 +++++ .../tpch-approved-plan/v1-bhj/spark322/5.txt | 539 +++++++++++ .../tpch-approved-plan/v1-bhj/spark322/6.txt | 112 +++ .../tpch-approved-plan/v1-bhj/spark322/7.txt | 501 ++++++++++ .../tpch-approved-plan/v1-bhj/spark322/8.txt | 694 +++++++++++++ .../tpch-approved-plan/v1-bhj/spark322/9.txt | 529 ++++++++++ .../tpch-approved-plan/v1/spark322/1.txt | 154 +++ .../tpch-approved-plan/v1/spark322/10.txt | 458 +++++++++ .../tpch-approved-plan/v1/spark322/11.txt | 378 ++++++++ .../tpch-approved-plan/v1/spark322/12.txt | 261 +++++ .../tpch-approved-plan/v1/spark322/13.txt | 286 ++++++ .../tpch-approved-plan/v1/spark322/14.txt | 197 ++++ .../tpch-approved-plan/v1/spark322/15.txt | 244 +++++ .../tpch-approved-plan/v1/spark322/16.txt | 349 +++++++ .../tpch-approved-plan/v1/spark322/17.txt | 324 +++++++ .../tpch-approved-plan/v1/spark322/18.txt | 531 ++++++++++ .../tpch-approved-plan/v1/spark322/19.txt | 192 ++++ .../tpch-approved-plan/v1/spark322/20.txt | 654 +++++++++++++ .../tpch-approved-plan/v1/spark322/21.txt | 623 ++++++++++++ .../tpch-approved-plan/v1/spark322/22.txt | 244 +++++ .../tpch-approved-plan/v1/spark322/3.txt | 319 ++++++ .../tpch-approved-plan/v1/spark322/4.txt | 266 +++++ .../tpch-approved-plan/v1/spark322/5.txt | 694 +++++++++++++ .../tpch-approved-plan/v1/spark322/6.txt | 112 +++ .../tpch-approved-plan/v1/spark322/7.txt | 661 +++++++++++++ .../tpch-approved-plan/v1/spark322/8.txt | 913 ++++++++++++++++++ .../tpch-approved-plan/v1/spark322/9.txt | 689 +++++++++++++ .../execution/VeloxTPCHSuite.scala | 116 ++- docs/developers/NewToGluten.md | 19 + docs/image/gluten_golden_file_upload.png | Bin 0 -> 28636435 bytes tools/gluten-te/centos/gha/gha-checkout/cp.sh | 29 + tools/gluten-te/ubuntu/gha/gha-checkout/cp.sh | 29 + 48 files changed, 15871 insertions(+), 23 deletions(-) create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/1.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/10.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/11.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/12.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/13.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/14.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/15.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/16.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/17.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/18.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/19.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/20.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/21.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/22.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/3.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/4.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/5.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/6.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/7.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/8.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/9.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/1.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/10.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/11.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/12.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/13.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/14.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/15.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/16.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/17.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/18.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/19.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/20.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/21.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/22.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/3.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/4.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/5.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/6.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/7.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/8.txt create mode 100644 backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/9.txt create mode 100644 docs/image/gluten_golden_file_upload.png create mode 100755 tools/gluten-te/centos/gha/gha-checkout/cp.sh create mode 100755 tools/gluten-te/ubuntu/gha/gha-checkout/cp.sh diff --git a/.github/workflows/velox_be.yml b/.github/workflows/velox_be.yml index df13d0de5371..41348331fef1 100644 --- a/.github/workflows/velox_be.yml +++ b/.github/workflows/velox_be.yml @@ -91,6 +91,21 @@ jobs: run: | $PATH_TO_GLUTEN_TE/$OS_IMAGE_NAME/gha/gha-checkout/exec.sh 'cd /opt/gluten/cpp/build/velox/benchmarks && \ ./generic_benchmark --run-example --with-shuffle --threads 1 --iterations 1' + - name: Copy golden files from container to host + if: failure() + run: | + $PATH_TO_GLUTEN_TE/$OS_IMAGE_NAME/gha/gha-checkout/cp.sh /tmp/tpch-approved-plan/ /tmp/$GITHUB_RUN_ID/tpch-approved-plan + - name: Upload golden files + if: failure() + uses: actions/upload-artifact@v4 + with: + name: golden-files-spark32 + path: | + /tmp/${{ github.run_id }}/tpch-approved-plan/** + - name: Clean temp golden files + if: failure() + run: | + rm -rf /tmp/$GITHUB_RUN_ID/tpch-approved-plan - name: Exit docker container if: ${{ always() }} run: | diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/1.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/1.txt new file mode 100644 index 000000000000..b0dc59acfebc --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/1.txt @@ -0,0 +1,154 @@ +== Physical Plan == +AdaptiveSparkPlan (28) ++- == Final Plan == + VeloxColumnarToRowExec (19) + +- ^ SortExecTransformer (17) + +- ^ InputIteratorTransformer (16) + +- ^ InputAdapter (15) + +- ^ ShuffleQueryStage (14) + +- ColumnarExchange (13) + +- ^ RegularHashAggregateExecTransformer (11) + +- ^ InputIteratorTransformer (10) + +- ^ InputAdapter (9) + +- ^ ShuffleQueryStage (8) + +- ColumnarExchange (7) + +- ^ ProjectExecTransformer (5) + +- ^ FlushableHashAggregateExecTransformer (4) + +- ^ ProjectExecTransformer (3) + +- ^ FilterExecTransformer (2) + +- ^ Scan parquet (1) ++- == Initial Plan == + Sort (27) + +- Exchange (26) + +- HashAggregate (25) + +- Exchange (24) + +- HashAggregate (23) + +- Project (22) + +- Filter (21) + +- Scan parquet (20) + + +(1) Scan parquet +Output [7]: [l_quantity#X, l_extendedprice#X, l_discount#X, l_tax#X, l_returnflag#X, l_linestatus#X, l_shipdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_shipdate), LessThanOrEqual(l_shipdate,1998-09-02)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [7]: [l_quantity#X, l_extendedprice#X, l_discount#X, l_tax#X, l_returnflag#X, l_linestatus#X, l_shipdate#X] +Arguments: (isnotnull(l_shipdate#X) AND (l_shipdate#X <= 1998-09-02)) + +(3) ProjectExecTransformer +Output [8]: [l_quantity#X, l_extendedprice#X, l_discount#X, l_tax#X, l_returnflag#X, l_linestatus#X, CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) AS _pre_124#X, CheckOverflow((promote_precision(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true)) * promote_precision(cast(CheckOverflow((1.00 + promote_precision(cast(l_tax#X as decimal(13,2)))), DecimalType(13,2), true) as decimal(26,4)))), DecimalType(38,6), true) AS _pre_125#X] +Input [7]: [l_quantity#X, l_extendedprice#X, l_discount#X, l_tax#X, l_returnflag#X, l_linestatus#X, l_shipdate#X] + +(4) FlushableHashAggregateExecTransformer +Input [8]: [l_quantity#X, l_extendedprice#X, l_discount#X, l_tax#X, l_returnflag#X, l_linestatus#X, _pre_124#X, _pre_125#X] +Keys [2]: [l_returnflag#X, l_linestatus#X] +Functions [8]: [partial_sum(l_quantity#X), partial_sum(l_extendedprice#X), partial_sum(_pre_124#X), partial_sum(_pre_125#X), partial_avg(l_quantity#X), partial_avg(l_extendedprice#X), partial_avg(l_discount#X), partial_count(1)] +Aggregate Attributes [15]: [sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, count#X, sum#X, count#X, sum#X, count#X, count#X] +Results [17]: [l_returnflag#X, l_linestatus#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, count#X, sum#X, count#X, sum#X, count#X, count#X] + +(5) ProjectExecTransformer +Output [18]: [hash(l_returnflag#X, l_linestatus#X, 42) AS hash_partition_key#X, l_returnflag#X, l_linestatus#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, count#X, sum#X, count#X, sum#X, count#X, count#X] +Input [17]: [l_returnflag#X, l_linestatus#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, count#X, sum#X, count#X, sum#X, count#X, count#X] + +(6) WholeStageCodegenTransformer (X) +Input [18]: [hash_partition_key#X, l_returnflag#X, l_linestatus#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, count#X, sum#X, count#X, sum#X, count#X, count#X] +Arguments: false + +(7) ColumnarExchange +Input [18]: [hash_partition_key#X, l_returnflag#X, l_linestatus#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, count#X, sum#X, count#X, sum#X, count#X, count#X] +Arguments: hashpartitioning(l_returnflag#X, l_linestatus#X, 1), ENSURE_REQUIREMENTS, [l_returnflag#X, l_linestatus#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, count#X, sum#X, count#X, sum#X, count#X, count#X], [plan_id=X], [id=#X] + +(8) ShuffleQueryStage +Output [17]: [l_returnflag#X, l_linestatus#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, count#X, sum#X, count#X, sum#X, count#X, count#X] +Arguments: X + +(9) InputAdapter +Input [17]: [l_returnflag#X, l_linestatus#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, count#X, sum#X, count#X, sum#X, count#X, count#X] + +(10) InputIteratorTransformer +Input [17]: [l_returnflag#X, l_linestatus#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, count#X, sum#X, count#X, sum#X, count#X, count#X] + +(11) RegularHashAggregateExecTransformer +Input [17]: [l_returnflag#X, l_linestatus#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, count#X, sum#X, count#X, sum#X, count#X, count#X] +Keys [2]: [l_returnflag#X, l_linestatus#X] +Functions [8]: [sum(l_quantity#X), sum(l_extendedprice#X), sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true)), sum(CheckOverflow((promote_precision(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true)) * promote_precision(cast(CheckOverflow((1.00 + promote_precision(cast(l_tax#X as decimal(13,2)))), DecimalType(13,2), true) as decimal(26,4)))), DecimalType(38,6), true)), avg(l_quantity#X), avg(l_extendedprice#X), avg(l_discount#X), count(1)] +Aggregate Attributes [8]: [sum(l_quantity#X)#X, sum(l_extendedprice#X)#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X, sum(CheckOverflow((promote_precision(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true)) * promote_precision(cast(CheckOverflow((1.00 + promote_precision(cast(l_tax#X as decimal(13,2)))), DecimalType(13,2), true) as decimal(26,4)))), DecimalType(38,6), true))#X, avg(l_quantity#X)#X, avg(l_extendedprice#X)#X, avg(l_discount#X)#X, count(1)#X] +Results [10]: [l_returnflag#X, l_linestatus#X, sum(l_quantity#X)#X AS sum_qty#X, sum(l_extendedprice#X)#X AS sum_base_price#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X AS sum_disc_price#X, sum(CheckOverflow((promote_precision(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true)) * promote_precision(cast(CheckOverflow((1.00 + promote_precision(cast(l_tax#X as decimal(13,2)))), DecimalType(13,2), true) as decimal(26,4)))), DecimalType(38,6), true))#X AS sum_charge#X, avg(l_quantity#X)#X AS avg_qty#X, avg(l_extendedprice#X)#X AS avg_price#X, avg(l_discount#X)#X AS avg_disc#X, count(1)#X AS count_order#X] + +(12) WholeStageCodegenTransformer (X) +Input [10]: [l_returnflag#X, l_linestatus#X, sum_qty#X, sum_base_price#X, sum_disc_price#X, sum_charge#X, avg_qty#X, avg_price#X, avg_disc#X, count_order#X] +Arguments: false + +(13) ColumnarExchange +Input [10]: [l_returnflag#X, l_linestatus#X, sum_qty#X, sum_base_price#X, sum_disc_price#X, sum_charge#X, avg_qty#X, avg_price#X, avg_disc#X, count_order#X] +Arguments: rangepartitioning(l_returnflag#X ASC NULLS FIRST, l_linestatus#X ASC NULLS FIRST, 1), ENSURE_REQUIREMENTS, [plan_id=X], [id=#X] + +(14) ShuffleQueryStage +Output [10]: [l_returnflag#X, l_linestatus#X, sum_qty#X, sum_base_price#X, sum_disc_price#X, sum_charge#X, avg_qty#X, avg_price#X, avg_disc#X, count_order#X] +Arguments: X + +(15) InputAdapter +Input [10]: [l_returnflag#X, l_linestatus#X, sum_qty#X, sum_base_price#X, sum_disc_price#X, sum_charge#X, avg_qty#X, avg_price#X, avg_disc#X, count_order#X] + +(16) InputIteratorTransformer +Input [10]: [l_returnflag#X, l_linestatus#X, sum_qty#X, sum_base_price#X, sum_disc_price#X, sum_charge#X, avg_qty#X, avg_price#X, avg_disc#X, count_order#X] + +(17) SortExecTransformer +Input [10]: [l_returnflag#X, l_linestatus#X, sum_qty#X, sum_base_price#X, sum_disc_price#X, sum_charge#X, avg_qty#X, avg_price#X, avg_disc#X, count_order#X] +Arguments: [l_returnflag#X ASC NULLS FIRST, l_linestatus#X ASC NULLS FIRST], true, 0 + +(18) WholeStageCodegenTransformer (X) +Input [10]: [l_returnflag#X, l_linestatus#X, sum_qty#X, sum_base_price#X, sum_disc_price#X, sum_charge#X, avg_qty#X, avg_price#X, avg_disc#X, count_order#X] +Arguments: false + +(19) VeloxColumnarToRowExec +Input [10]: [l_returnflag#X, l_linestatus#X, sum_qty#X, sum_base_price#X, sum_disc_price#X, sum_charge#X, avg_qty#X, avg_price#X, avg_disc#X, count_order#X] + +(20) Scan parquet +Output [7]: [l_quantity#X, l_extendedprice#X, l_discount#X, l_tax#X, l_returnflag#X, l_linestatus#X, l_shipdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_shipdate), LessThanOrEqual(l_shipdate,1998-09-02)] +ReadSchema: struct + +(21) Filter +Input [7]: [l_quantity#X, l_extendedprice#X, l_discount#X, l_tax#X, l_returnflag#X, l_linestatus#X, l_shipdate#X] +Condition : (isnotnull(l_shipdate#X) AND (l_shipdate#X <= 1998-09-02)) + +(22) Project +Output [6]: [l_quantity#X, l_extendedprice#X, l_discount#X, l_tax#X, l_returnflag#X, l_linestatus#X] +Input [7]: [l_quantity#X, l_extendedprice#X, l_discount#X, l_tax#X, l_returnflag#X, l_linestatus#X, l_shipdate#X] + +(23) HashAggregate +Input [6]: [l_quantity#X, l_extendedprice#X, l_discount#X, l_tax#X, l_returnflag#X, l_linestatus#X] +Keys [2]: [l_returnflag#X, l_linestatus#X] +Functions [8]: [partial_sum(l_quantity#X), partial_sum(l_extendedprice#X), partial_sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true)), partial_sum(CheckOverflow((promote_precision(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true)) * promote_precision(cast(CheckOverflow((1.00 + promote_precision(cast(l_tax#X as decimal(13,2)))), DecimalType(13,2), true) as decimal(26,4)))), DecimalType(38,6), true)), partial_avg(l_quantity#X), partial_avg(l_extendedprice#X), partial_avg(l_discount#X), partial_count(1)] +Aggregate Attributes [15]: [sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, count#X, sum#X, count#X, sum#X, count#X, count#X] +Results [17]: [l_returnflag#X, l_linestatus#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, count#X, sum#X, count#X, sum#X, count#X, count#X] + +(24) Exchange +Input [17]: [l_returnflag#X, l_linestatus#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, count#X, sum#X, count#X, sum#X, count#X, count#X] +Arguments: hashpartitioning(l_returnflag#X, l_linestatus#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(25) HashAggregate +Input [17]: [l_returnflag#X, l_linestatus#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, count#X, sum#X, count#X, sum#X, count#X, count#X] +Keys [2]: [l_returnflag#X, l_linestatus#X] +Functions [8]: [sum(l_quantity#X), sum(l_extendedprice#X), sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true)), sum(CheckOverflow((promote_precision(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true)) * promote_precision(cast(CheckOverflow((1.00 + promote_precision(cast(l_tax#X as decimal(13,2)))), DecimalType(13,2), true) as decimal(26,4)))), DecimalType(38,6), true)), avg(l_quantity#X), avg(l_extendedprice#X), avg(l_discount#X), count(1)] +Aggregate Attributes [8]: [sum(l_quantity#X)#X, sum(l_extendedprice#X)#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X, sum(CheckOverflow((promote_precision(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true)) * promote_precision(cast(CheckOverflow((1.00 + promote_precision(cast(l_tax#X as decimal(13,2)))), DecimalType(13,2), true) as decimal(26,4)))), DecimalType(38,6), true))#X, avg(l_quantity#X)#X, avg(l_extendedprice#X)#X, avg(l_discount#X)#X, count(1)#X] +Results [10]: [l_returnflag#X, l_linestatus#X, sum(l_quantity#X)#X AS sum_qty#X, sum(l_extendedprice#X)#X AS sum_base_price#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X AS sum_disc_price#X, sum(CheckOverflow((promote_precision(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true)) * promote_precision(cast(CheckOverflow((1.00 + promote_precision(cast(l_tax#X as decimal(13,2)))), DecimalType(13,2), true) as decimal(26,4)))), DecimalType(38,6), true))#X AS sum_charge#X, avg(l_quantity#X)#X AS avg_qty#X, avg(l_extendedprice#X)#X AS avg_price#X, avg(l_discount#X)#X AS avg_disc#X, count(1)#X AS count_order#X] + +(26) Exchange +Input [10]: [l_returnflag#X, l_linestatus#X, sum_qty#X, sum_base_price#X, sum_disc_price#X, sum_charge#X, avg_qty#X, avg_price#X, avg_disc#X, count_order#X] +Arguments: rangepartitioning(l_returnflag#X ASC NULLS FIRST, l_linestatus#X ASC NULLS FIRST, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(27) Sort +Input [10]: [l_returnflag#X, l_linestatus#X, sum_qty#X, sum_base_price#X, sum_disc_price#X, sum_charge#X, avg_qty#X, avg_price#X, avg_disc#X, count_order#X] +Arguments: [l_returnflag#X ASC NULLS FIRST, l_linestatus#X ASC NULLS FIRST], true, 0 + +(28) AdaptiveSparkPlan +Output [10]: [l_returnflag#X, l_linestatus#X, sum_qty#X, sum_base_price#X, sum_disc_price#X, sum_charge#X, avg_qty#X, avg_price#X, avg_disc#X, count_order#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/10.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/10.txt new file mode 100644 index 000000000000..5d4082af6fc4 --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/10.txt @@ -0,0 +1,367 @@ +== Physical Plan == +AdaptiveSparkPlan (67) ++- == Final Plan == + VeloxColumnarToRowExec (43) + +- TakeOrderedAndProjectExecTransformer (42) + +- ^ ProjectExecTransformer (40) + +- ^ RegularHashAggregateExecTransformer (39) + +- ^ InputIteratorTransformer (38) + +- ^ InputAdapter (37) + +- ^ ShuffleQueryStage (36) + +- ColumnarExchange (35) + +- ^ ProjectExecTransformer (33) + +- ^ FlushableHashAggregateExecTransformer (32) + +- ^ ProjectExecTransformer (31) + +- ^ GlutenBroadcastHashJoinExecTransformer Inner (30) + :- ^ ProjectExecTransformer (22) + : +- ^ GlutenBroadcastHashJoinExecTransformer Inner (21) + : :- ^ ProjectExecTransformer (12) + : : +- ^ GlutenBroadcastHashJoinExecTransformer Inner (11) + : : :- ^ FilterExecTransformer (2) + : : : +- ^ Scan parquet (1) + : : +- ^ InputIteratorTransformer (10) + : : +- ^ InputAdapter (9) + : : +- ^ BroadcastQueryStage (8) + : : +- ColumnarBroadcastExchange (7) + : : +- ^ ProjectExecTransformer (5) + : : +- ^ FilterExecTransformer (4) + : : +- ^ Scan parquet (3) + : +- ^ InputIteratorTransformer (20) + : +- ^ InputAdapter (19) + : +- ^ BroadcastQueryStage (18) + : +- ColumnarBroadcastExchange (17) + : +- ^ ProjectExecTransformer (15) + : +- ^ FilterExecTransformer (14) + : +- ^ Scan parquet (13) + +- ^ InputIteratorTransformer (29) + +- ^ InputAdapter (28) + +- ^ BroadcastQueryStage (27) + +- ColumnarBroadcastExchange (26) + +- ^ FilterExecTransformer (24) + +- ^ Scan parquet (23) ++- == Initial Plan == + TakeOrderedAndProject (66) + +- HashAggregate (65) + +- Exchange (64) + +- HashAggregate (63) + +- Project (62) + +- BroadcastHashJoin Inner BuildRight (61) + :- Project (57) + : +- BroadcastHashJoin Inner BuildRight (56) + : :- Project (51) + : : +- BroadcastHashJoin Inner BuildRight (50) + : : :- Filter (45) + : : : +- Scan parquet (44) + : : +- BroadcastExchange (49) + : : +- Project (48) + : : +- Filter (47) + : : +- Scan parquet (46) + : +- BroadcastExchange (55) + : +- Project (54) + : +- Filter (53) + : +- Scan parquet (52) + +- BroadcastExchange (60) + +- Filter (59) + +- Scan parquet (58) + + +(1) Scan parquet +Output [7]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(c_custkey), IsNotNull(c_nationkey)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [7]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X] +Arguments: (isnotnull(c_custkey#X) AND isnotnull(c_nationkey#X)) + +(3) Scan parquet +Output [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_orderdate), GreaterThanOrEqual(o_orderdate,1993-10-01), LessThan(o_orderdate,1994-01-01), IsNotNull(o_custkey), IsNotNull(o_orderkey)] +ReadSchema: struct + +(4) FilterExecTransformer +Input [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] +Arguments: ((((isnotnull(o_orderdate#X) AND (o_orderdate#X >= 1993-10-01)) AND (o_orderdate#X < 1994-01-01)) AND isnotnull(o_custkey#X)) AND isnotnull(o_orderkey#X)) + +(5) ProjectExecTransformer +Output [2]: [o_orderkey#X, o_custkey#X] +Input [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] + +(6) WholeStageCodegenTransformer (X) +Input [2]: [o_orderkey#X, o_custkey#X] +Arguments: false + +(7) ColumnarBroadcastExchange +Input [2]: [o_orderkey#X, o_custkey#X] +Arguments: HashedRelationBroadcastMode(List(input[1, bigint, true]),false), [plan_id=X] + +(8) BroadcastQueryStage +Output [2]: [o_orderkey#X, o_custkey#X] +Arguments: X + +(9) InputAdapter +Input [2]: [o_orderkey#X, o_custkey#X] + +(10) InputIteratorTransformer +Input [2]: [o_orderkey#X, o_custkey#X] + +(11) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [c_custkey#X] +Right keys [1]: [o_custkey#X] +Join condition: None + +(12) ProjectExecTransformer +Output [8]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X, o_orderkey#X] +Input [9]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X, o_orderkey#X, o_custkey#X] + +(13) Scan parquet +Output [4]: [l_orderkey#X, l_extendedprice#X, l_discount#X, l_returnflag#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_returnflag), EqualTo(l_returnflag,R), IsNotNull(l_orderkey)] +ReadSchema: struct + +(14) FilterExecTransformer +Input [4]: [l_orderkey#X, l_extendedprice#X, l_discount#X, l_returnflag#X] +Arguments: ((isnotnull(l_returnflag#X) AND (l_returnflag#X = R)) AND isnotnull(l_orderkey#X)) + +(15) ProjectExecTransformer +Output [3]: [l_orderkey#X, l_extendedprice#X, l_discount#X] +Input [4]: [l_orderkey#X, l_extendedprice#X, l_discount#X, l_returnflag#X] + +(16) WholeStageCodegenTransformer (X) +Input [3]: [l_orderkey#X, l_extendedprice#X, l_discount#X] +Arguments: false + +(17) ColumnarBroadcastExchange +Input [3]: [l_orderkey#X, l_extendedprice#X, l_discount#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(18) BroadcastQueryStage +Output [3]: [l_orderkey#X, l_extendedprice#X, l_discount#X] +Arguments: X + +(19) InputAdapter +Input [3]: [l_orderkey#X, l_extendedprice#X, l_discount#X] + +(20) InputIteratorTransformer +Input [3]: [l_orderkey#X, l_extendedprice#X, l_discount#X] + +(21) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [o_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: None + +(22) ProjectExecTransformer +Output [9]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X, l_extendedprice#X, l_discount#X] +Input [11]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X, o_orderkey#X, l_orderkey#X, l_extendedprice#X, l_discount#X] + +(23) Scan parquet +Output [2]: [n_nationkey#X, n_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_nationkey)] +ReadSchema: struct + +(24) FilterExecTransformer +Input [2]: [n_nationkey#X, n_name#X] +Arguments: isnotnull(n_nationkey#X) + +(25) WholeStageCodegenTransformer (X) +Input [2]: [n_nationkey#X, n_name#X] +Arguments: false + +(26) ColumnarBroadcastExchange +Input [2]: [n_nationkey#X, n_name#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(27) BroadcastQueryStage +Output [2]: [n_nationkey#X, n_name#X] +Arguments: X + +(28) InputAdapter +Input [2]: [n_nationkey#X, n_name#X] + +(29) InputIteratorTransformer +Input [2]: [n_nationkey#X, n_name#X] + +(30) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [c_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: None + +(31) ProjectExecTransformer +Output [10]: [c_custkey#X, c_name#X, c_address#X, c_phone#X, c_acctbal#X, c_comment#X, l_extendedprice#X, l_discount#X, n_name#X, CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) AS _pre_130#X] +Input [11]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X, l_extendedprice#X, l_discount#X, n_nationkey#X, n_name#X] + +(32) FlushableHashAggregateExecTransformer +Input [10]: [c_custkey#X, c_name#X, c_address#X, c_phone#X, c_acctbal#X, c_comment#X, l_extendedprice#X, l_discount#X, n_name#X, _pre_130#X] +Keys [7]: [c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X] +Functions [1]: [partial_sum(_pre_130#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [9]: [c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X, sum#X, isEmpty#X] + +(33) ProjectExecTransformer +Output [10]: [hash(c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X, 42) AS hash_partition_key#X, c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X, sum#X, isEmpty#X] +Input [9]: [c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X, sum#X, isEmpty#X] + +(34) WholeStageCodegenTransformer (X) +Input [10]: [hash_partition_key#X, c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X, sum#X, isEmpty#X] +Arguments: false + +(35) ColumnarExchange +Input [10]: [hash_partition_key#X, c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X, 1), ENSURE_REQUIREMENTS, [c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X, sum#X, isEmpty#X], [plan_id=X], [id=#X] + +(36) ShuffleQueryStage +Output [9]: [c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X, sum#X, isEmpty#X] +Arguments: X + +(37) InputAdapter +Input [9]: [c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X, sum#X, isEmpty#X] + +(38) InputIteratorTransformer +Input [9]: [c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X, sum#X, isEmpty#X] + +(39) RegularHashAggregateExecTransformer +Input [9]: [c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X, sum#X, isEmpty#X] +Keys [7]: [c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X] +Functions [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))] +Aggregate Attributes [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X] +Results [8]: [c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X] + +(40) ProjectExecTransformer +Output [8]: [c_custkey#X, c_name#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X AS revenue#X, c_acctbal#X, n_name#X, c_address#X, c_phone#X, c_comment#X] +Input [8]: [c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X] + +(41) WholeStageCodegenTransformer (X) +Input [8]: [c_custkey#X, c_name#X, revenue#X, c_acctbal#X, n_name#X, c_address#X, c_phone#X, c_comment#X] +Arguments: false + +(42) TakeOrderedAndProjectExecTransformer +Input [8]: [c_custkey#X, c_name#X, revenue#X, c_acctbal#X, n_name#X, c_address#X, c_phone#X, c_comment#X] +Arguments: X, [revenue#X DESC NULLS LAST], [c_custkey#X, c_name#X, revenue#X, c_acctbal#X, n_name#X, c_address#X, c_phone#X, c_comment#X], 0 + +(43) VeloxColumnarToRowExec +Input [8]: [c_custkey#X, c_name#X, revenue#X, c_acctbal#X, n_name#X, c_address#X, c_phone#X, c_comment#X] + +(44) Scan parquet +Output [7]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(c_custkey), IsNotNull(c_nationkey)] +ReadSchema: struct + +(45) Filter +Input [7]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X] +Condition : (isnotnull(c_custkey#X) AND isnotnull(c_nationkey#X)) + +(46) Scan parquet +Output [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_orderdate), GreaterThanOrEqual(o_orderdate,1993-10-01), LessThan(o_orderdate,1994-01-01), IsNotNull(o_custkey), IsNotNull(o_orderkey)] +ReadSchema: struct + +(47) Filter +Input [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] +Condition : ((((isnotnull(o_orderdate#X) AND (o_orderdate#X >= 1993-10-01)) AND (o_orderdate#X < 1994-01-01)) AND isnotnull(o_custkey#X)) AND isnotnull(o_orderkey#X)) + +(48) Project +Output [2]: [o_orderkey#X, o_custkey#X] +Input [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] + +(49) BroadcastExchange +Input [2]: [o_orderkey#X, o_custkey#X] +Arguments: HashedRelationBroadcastMode(List(input[1, bigint, true]),false), [plan_id=X] + +(50) BroadcastHashJoin +Left keys [1]: [c_custkey#X] +Right keys [1]: [o_custkey#X] +Join condition: None + +(51) Project +Output [8]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X, o_orderkey#X] +Input [9]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X, o_orderkey#X, o_custkey#X] + +(52) Scan parquet +Output [4]: [l_orderkey#X, l_extendedprice#X, l_discount#X, l_returnflag#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_returnflag), EqualTo(l_returnflag,R), IsNotNull(l_orderkey)] +ReadSchema: struct + +(53) Filter +Input [4]: [l_orderkey#X, l_extendedprice#X, l_discount#X, l_returnflag#X] +Condition : ((isnotnull(l_returnflag#X) AND (l_returnflag#X = R)) AND isnotnull(l_orderkey#X)) + +(54) Project +Output [3]: [l_orderkey#X, l_extendedprice#X, l_discount#X] +Input [4]: [l_orderkey#X, l_extendedprice#X, l_discount#X, l_returnflag#X] + +(55) BroadcastExchange +Input [3]: [l_orderkey#X, l_extendedprice#X, l_discount#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(56) BroadcastHashJoin +Left keys [1]: [o_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: None + +(57) Project +Output [9]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X, l_extendedprice#X, l_discount#X] +Input [11]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X, o_orderkey#X, l_orderkey#X, l_extendedprice#X, l_discount#X] + +(58) Scan parquet +Output [2]: [n_nationkey#X, n_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_nationkey)] +ReadSchema: struct + +(59) Filter +Input [2]: [n_nationkey#X, n_name#X] +Condition : isnotnull(n_nationkey#X) + +(60) BroadcastExchange +Input [2]: [n_nationkey#X, n_name#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(61) BroadcastHashJoin +Left keys [1]: [c_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: None + +(62) Project +Output [9]: [c_custkey#X, c_name#X, c_address#X, c_phone#X, c_acctbal#X, c_comment#X, l_extendedprice#X, l_discount#X, n_name#X] +Input [11]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X, l_extendedprice#X, l_discount#X, n_nationkey#X, n_name#X] + +(63) HashAggregate +Input [9]: [c_custkey#X, c_name#X, c_address#X, c_phone#X, c_acctbal#X, c_comment#X, l_extendedprice#X, l_discount#X, n_name#X] +Keys [7]: [c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X] +Functions [1]: [partial_sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [9]: [c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X, sum#X, isEmpty#X] + +(64) Exchange +Input [9]: [c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(65) HashAggregate +Input [9]: [c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X, sum#X, isEmpty#X] +Keys [7]: [c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X] +Functions [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))] +Aggregate Attributes [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X] +Results [8]: [c_custkey#X, c_name#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X AS revenue#X, c_acctbal#X, n_name#X, c_address#X, c_phone#X, c_comment#X] + +(66) TakeOrderedAndProject +Input [8]: [c_custkey#X, c_name#X, revenue#X, c_acctbal#X, n_name#X, c_address#X, c_phone#X, c_comment#X] +Arguments: X, [revenue#X DESC NULLS LAST], [c_custkey#X, c_name#X, revenue#X, c_acctbal#X, n_name#X, c_address#X, c_phone#X, c_comment#X] + +(67) AdaptiveSparkPlan +Output [8]: [c_custkey#X, c_name#X, revenue#X, c_acctbal#X, n_name#X, c_address#X, c_phone#X, c_comment#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/11.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/11.txt new file mode 100644 index 000000000000..8ec00b24c368 --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/11.txt @@ -0,0 +1,314 @@ +== Physical Plan == +AdaptiveSparkPlan (58) ++- == Final Plan == + VeloxColumnarToRowExec (38) + +- ^ SortExecTransformer (36) + +- ^ InputIteratorTransformer (35) + +- ^ InputAdapter (34) + +- ^ ShuffleQueryStage (33) + +- ColumnarExchange (32) + +- ^ FilterExecTransformer (30) + +- ^ RegularHashAggregateExecTransformer (29) + +- ^ InputIteratorTransformer (28) + +- ^ InputAdapter (27) + +- ^ ShuffleQueryStage (26) + +- ColumnarExchange (25) + +- ^ ProjectExecTransformer (23) + +- ^ FlushableHashAggregateExecTransformer (22) + +- ^ ProjectExecTransformer (21) + +- ^ GlutenBroadcastHashJoinExecTransformer Inner (20) + :- ^ ProjectExecTransformer (11) + : +- ^ GlutenBroadcastHashJoinExecTransformer Inner (10) + : :- ^ FilterExecTransformer (2) + : : +- ^ Scan parquet (1) + : +- ^ InputIteratorTransformer (9) + : +- ^ InputAdapter (8) + : +- ^ BroadcastQueryStage (7) + : +- ColumnarBroadcastExchange (6) + : +- ^ FilterExecTransformer (4) + : +- ^ Scan parquet (3) + +- ^ InputIteratorTransformer (19) + +- ^ InputAdapter (18) + +- ^ BroadcastQueryStage (17) + +- ColumnarBroadcastExchange (16) + +- ^ ProjectExecTransformer (14) + +- ^ FilterExecTransformer (13) + +- ^ Scan parquet (12) ++- == Initial Plan == + Sort (57) + +- Exchange (56) + +- Filter (55) + +- HashAggregate (54) + +- Exchange (53) + +- HashAggregate (52) + +- Project (51) + +- BroadcastHashJoin Inner BuildRight (50) + :- Project (45) + : +- BroadcastHashJoin Inner BuildRight (44) + : :- Filter (40) + : : +- Scan parquet (39) + : +- BroadcastExchange (43) + : +- Filter (42) + : +- Scan parquet (41) + +- BroadcastExchange (49) + +- Project (48) + +- Filter (47) + +- Scan parquet (46) + + +(1) Scan parquet +Output [4]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X, ps_supplycost#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(ps_suppkey)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [4]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X, ps_supplycost#X] +Arguments: isnotnull(ps_suppkey#X) + +(3) Scan parquet +Output [2]: [s_suppkey#X, s_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(s_suppkey), IsNotNull(s_nationkey)] +ReadSchema: struct + +(4) FilterExecTransformer +Input [2]: [s_suppkey#X, s_nationkey#X] +Arguments: (isnotnull(s_suppkey#X) AND isnotnull(s_nationkey#X)) + +(5) WholeStageCodegenTransformer (X) +Input [2]: [s_suppkey#X, s_nationkey#X] +Arguments: false + +(6) ColumnarBroadcastExchange +Input [2]: [s_suppkey#X, s_nationkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(7) BroadcastQueryStage +Output [2]: [s_suppkey#X, s_nationkey#X] +Arguments: X + +(8) InputAdapter +Input [2]: [s_suppkey#X, s_nationkey#X] + +(9) InputIteratorTransformer +Input [2]: [s_suppkey#X, s_nationkey#X] + +(10) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [ps_suppkey#X] +Right keys [1]: [s_suppkey#X] +Join condition: None + +(11) ProjectExecTransformer +Output [4]: [ps_partkey#X, ps_availqty#X, ps_supplycost#X, s_nationkey#X] +Input [6]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X, ps_supplycost#X, s_suppkey#X, s_nationkey#X] + +(12) Scan parquet +Output [2]: [n_nationkey#X, n_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_name), EqualTo(n_name,GERMANY), IsNotNull(n_nationkey)] +ReadSchema: struct + +(13) FilterExecTransformer +Input [2]: [n_nationkey#X, n_name#X] +Arguments: ((isnotnull(n_name#X) AND (n_name#X = GERMANY)) AND isnotnull(n_nationkey#X)) + +(14) ProjectExecTransformer +Output [1]: [n_nationkey#X] +Input [2]: [n_nationkey#X, n_name#X] + +(15) WholeStageCodegenTransformer (X) +Input [1]: [n_nationkey#X] +Arguments: false + +(16) ColumnarBroadcastExchange +Input [1]: [n_nationkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(17) BroadcastQueryStage +Output [1]: [n_nationkey#X] +Arguments: X + +(18) InputAdapter +Input [1]: [n_nationkey#X] + +(19) InputIteratorTransformer +Input [1]: [n_nationkey#X] + +(20) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [s_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: None + +(21) ProjectExecTransformer +Output [4]: [ps_partkey#X, ps_availqty#X, ps_supplycost#X, CheckOverflow((promote_precision(ps_supplycost#X) * promote_precision(cast(cast(ps_availqty#X as decimal(10,0)) as decimal(12,2)))), DecimalType(23,2), true) AS _pre_131#X] +Input [5]: [ps_partkey#X, ps_availqty#X, ps_supplycost#X, s_nationkey#X, n_nationkey#X] + +(22) FlushableHashAggregateExecTransformer +Input [4]: [ps_partkey#X, ps_availqty#X, ps_supplycost#X, _pre_131#X] +Keys [1]: [ps_partkey#X] +Functions [1]: [partial_sum(_pre_131#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [3]: [ps_partkey#X, sum#X, isEmpty#X] + +(23) ProjectExecTransformer +Output [4]: [hash(ps_partkey#X, 42) AS hash_partition_key#X, ps_partkey#X, sum#X, isEmpty#X] +Input [3]: [ps_partkey#X, sum#X, isEmpty#X] + +(24) WholeStageCodegenTransformer (X) +Input [4]: [hash_partition_key#X, ps_partkey#X, sum#X, isEmpty#X] +Arguments: false + +(25) ColumnarExchange +Input [4]: [hash_partition_key#X, ps_partkey#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(ps_partkey#X, 1), ENSURE_REQUIREMENTS, [ps_partkey#X, sum#X, isEmpty#X], [plan_id=X], [id=#X] + +(26) ShuffleQueryStage +Output [3]: [ps_partkey#X, sum#X, isEmpty#X] +Arguments: X + +(27) InputAdapter +Input [3]: [ps_partkey#X, sum#X, isEmpty#X] + +(28) InputIteratorTransformer +Input [3]: [ps_partkey#X, sum#X, isEmpty#X] + +(29) RegularHashAggregateExecTransformer +Input [3]: [ps_partkey#X, sum#X, isEmpty#X] +Keys [1]: [ps_partkey#X] +Functions [1]: [sum(CheckOverflow((promote_precision(ps_supplycost#X) * promote_precision(cast(cast(ps_availqty#X as decimal(10,0)) as decimal(12,2)))), DecimalType(23,2), true))] +Aggregate Attributes [1]: [sum(CheckOverflow((promote_precision(ps_supplycost#X) * promote_precision(cast(cast(ps_availqty#X as decimal(10,0)) as decimal(12,2)))), DecimalType(23,2), true))#X] +Results [2]: [ps_partkey#X, sum(CheckOverflow((promote_precision(ps_supplycost#X) * promote_precision(cast(cast(ps_availqty#X as decimal(10,0)) as decimal(12,2)))), DecimalType(23,2), true))#X AS value#X] + +(30) FilterExecTransformer +Input [2]: [ps_partkey#X, value#X] +Arguments: (isnotnull(value#X) AND (cast(value#X as decimal(38,6)) > Subquery subquery#X, [id=#X])) + +(31) WholeStageCodegenTransformer (X) +Input [2]: [ps_partkey#X, value#X] +Arguments: false + +(32) ColumnarExchange +Input [2]: [ps_partkey#X, value#X] +Arguments: rangepartitioning(value#X DESC NULLS LAST, 1), ENSURE_REQUIREMENTS, [plan_id=X], [id=#X] + +(33) ShuffleQueryStage +Output [2]: [ps_partkey#X, value#X] +Arguments: X + +(34) InputAdapter +Input [2]: [ps_partkey#X, value#X] + +(35) InputIteratorTransformer +Input [2]: [ps_partkey#X, value#X] + +(36) SortExecTransformer +Input [2]: [ps_partkey#X, value#X] +Arguments: [value#X DESC NULLS LAST], true, 0 + +(37) WholeStageCodegenTransformer (X) +Input [2]: [ps_partkey#X, value#X] +Arguments: false + +(38) VeloxColumnarToRowExec +Input [2]: [ps_partkey#X, value#X] + +(39) Scan parquet +Output [4]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X, ps_supplycost#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(ps_suppkey)] +ReadSchema: struct + +(40) Filter +Input [4]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X, ps_supplycost#X] +Condition : isnotnull(ps_suppkey#X) + +(41) Scan parquet +Output [2]: [s_suppkey#X, s_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(s_suppkey), IsNotNull(s_nationkey)] +ReadSchema: struct + +(42) Filter +Input [2]: [s_suppkey#X, s_nationkey#X] +Condition : (isnotnull(s_suppkey#X) AND isnotnull(s_nationkey#X)) + +(43) BroadcastExchange +Input [2]: [s_suppkey#X, s_nationkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(44) BroadcastHashJoin +Left keys [1]: [ps_suppkey#X] +Right keys [1]: [s_suppkey#X] +Join condition: None + +(45) Project +Output [4]: [ps_partkey#X, ps_availqty#X, ps_supplycost#X, s_nationkey#X] +Input [6]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X, ps_supplycost#X, s_suppkey#X, s_nationkey#X] + +(46) Scan parquet +Output [2]: [n_nationkey#X, n_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_name), EqualTo(n_name,GERMANY), IsNotNull(n_nationkey)] +ReadSchema: struct + +(47) Filter +Input [2]: [n_nationkey#X, n_name#X] +Condition : ((isnotnull(n_name#X) AND (n_name#X = GERMANY)) AND isnotnull(n_nationkey#X)) + +(48) Project +Output [1]: [n_nationkey#X] +Input [2]: [n_nationkey#X, n_name#X] + +(49) BroadcastExchange +Input [1]: [n_nationkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(50) BroadcastHashJoin +Left keys [1]: [s_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: None + +(51) Project +Output [3]: [ps_partkey#X, ps_availqty#X, ps_supplycost#X] +Input [5]: [ps_partkey#X, ps_availqty#X, ps_supplycost#X, s_nationkey#X, n_nationkey#X] + +(52) HashAggregate +Input [3]: [ps_partkey#X, ps_availqty#X, ps_supplycost#X] +Keys [1]: [ps_partkey#X] +Functions [1]: [partial_sum(CheckOverflow((promote_precision(ps_supplycost#X) * promote_precision(cast(cast(ps_availqty#X as decimal(10,0)) as decimal(12,2)))), DecimalType(23,2), true))] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [3]: [ps_partkey#X, sum#X, isEmpty#X] + +(53) Exchange +Input [3]: [ps_partkey#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(ps_partkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(54) HashAggregate +Input [3]: [ps_partkey#X, sum#X, isEmpty#X] +Keys [1]: [ps_partkey#X] +Functions [1]: [sum(CheckOverflow((promote_precision(ps_supplycost#X) * promote_precision(cast(cast(ps_availqty#X as decimal(10,0)) as decimal(12,2)))), DecimalType(23,2), true))] +Aggregate Attributes [1]: [sum(CheckOverflow((promote_precision(ps_supplycost#X) * promote_precision(cast(cast(ps_availqty#X as decimal(10,0)) as decimal(12,2)))), DecimalType(23,2), true))#X] +Results [2]: [ps_partkey#X, sum(CheckOverflow((promote_precision(ps_supplycost#X) * promote_precision(cast(cast(ps_availqty#X as decimal(10,0)) as decimal(12,2)))), DecimalType(23,2), true))#X AS value#X] + +(55) Filter +Input [2]: [ps_partkey#X, value#X] +Condition : (isnotnull(value#X) AND (cast(value#X as decimal(38,6)) > Subquery subquery#X, [id=#X])) + +(56) Exchange +Input [2]: [ps_partkey#X, value#X] +Arguments: rangepartitioning(value#X DESC NULLS LAST, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(57) Sort +Input [2]: [ps_partkey#X, value#X] +Arguments: [value#X DESC NULLS LAST], true, 0 + +(58) AdaptiveSparkPlan +Output [2]: [ps_partkey#X, value#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/12.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/12.txt new file mode 100644 index 000000000000..ae3e0f0df9a7 --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/12.txt @@ -0,0 +1,229 @@ +== Physical Plan == +AdaptiveSparkPlan (42) ++- == Final Plan == + VeloxColumnarToRowExec (28) + +- ^ SortExecTransformer (26) + +- ^ InputIteratorTransformer (25) + +- ^ InputAdapter (24) + +- ^ ShuffleQueryStage (23) + +- ColumnarExchange (22) + +- ^ RegularHashAggregateExecTransformer (20) + +- ^ InputIteratorTransformer (19) + +- ^ InputAdapter (18) + +- ^ ShuffleQueryStage (17) + +- ColumnarExchange (16) + +- ^ ProjectExecTransformer (14) + +- ^ FlushableHashAggregateExecTransformer (13) + +- ^ ProjectExecTransformer (12) + +- ^ GlutenBroadcastHashJoinExecTransformer Inner (11) + :- ^ InputIteratorTransformer (7) + : +- ^ InputAdapter (6) + : +- ^ BroadcastQueryStage (5) + : +- ColumnarBroadcastExchange (4) + : +- ^ FilterExecTransformer (2) + : +- ^ Scan parquet (1) + +- ^ ProjectExecTransformer (10) + +- ^ FilterExecTransformer (9) + +- ^ Scan parquet (8) ++- == Initial Plan == + Sort (41) + +- Exchange (40) + +- HashAggregate (39) + +- Exchange (38) + +- HashAggregate (37) + +- Project (36) + +- BroadcastHashJoin Inner BuildLeft (35) + :- BroadcastExchange (31) + : +- Filter (30) + : +- Scan parquet (29) + +- Project (34) + +- Filter (33) + +- Scan parquet (32) + + +(1) Scan parquet +Output [2]: [o_orderkey#X, o_orderpriority#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_orderkey)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [2]: [o_orderkey#X, o_orderpriority#X] +Arguments: isnotnull(o_orderkey#X) + +(3) WholeStageCodegenTransformer (X) +Input [2]: [o_orderkey#X, o_orderpriority#X] +Arguments: false + +(4) ColumnarBroadcastExchange +Input [2]: [o_orderkey#X, o_orderpriority#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(5) BroadcastQueryStage +Output [2]: [o_orderkey#X, o_orderpriority#X] +Arguments: X + +(6) InputAdapter +Input [2]: [o_orderkey#X, o_orderpriority#X] + +(7) InputIteratorTransformer +Input [2]: [o_orderkey#X, o_orderpriority#X] + +(8) Scan parquet +Output [5]: [l_orderkey#X, l_shipdate#X, l_commitdate#X, l_receiptdate#X, l_shipmode#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_commitdate), IsNotNull(l_receiptdate), IsNotNull(l_shipdate), In(l_shipmode, [MAIL,SHIP]), GreaterThanOrEqual(l_receiptdate,1994-01-01), LessThan(l_receiptdate,1995-01-01), IsNotNull(l_orderkey)] +ReadSchema: struct + +(9) FilterExecTransformer +Input [5]: [l_orderkey#X, l_shipdate#X, l_commitdate#X, l_receiptdate#X, l_shipmode#X] +Arguments: ((((((((isnotnull(l_commitdate#X) AND isnotnull(l_receiptdate#X)) AND isnotnull(l_shipdate#X)) AND l_shipmode#X IN (MAIL,SHIP)) AND (l_commitdate#X < l_receiptdate#X)) AND (l_shipdate#X < l_commitdate#X)) AND (l_receiptdate#X >= 1994-01-01)) AND (l_receiptdate#X < 1995-01-01)) AND isnotnull(l_orderkey#X)) + +(10) ProjectExecTransformer +Output [2]: [l_orderkey#X, l_shipmode#X] +Input [5]: [l_orderkey#X, l_shipdate#X, l_commitdate#X, l_receiptdate#X, l_shipmode#X] + +(11) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [o_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: None + +(12) ProjectExecTransformer +Output [4]: [o_orderpriority#X, l_shipmode#X, CASE WHEN ((o_orderpriority#X = 1-URGENT) OR (o_orderpriority#X = 2-HIGH)) THEN 1 ELSE 0 END AS _pre_133#X, CASE WHEN (NOT (o_orderpriority#X = 1-URGENT) AND NOT (o_orderpriority#X = 2-HIGH)) THEN 1 ELSE 0 END AS _pre_134#X] +Input [4]: [o_orderkey#X, o_orderpriority#X, l_orderkey#X, l_shipmode#X] + +(13) FlushableHashAggregateExecTransformer +Input [4]: [o_orderpriority#X, l_shipmode#X, _pre_133#X, _pre_134#X] +Keys [1]: [l_shipmode#X] +Functions [2]: [partial_sum(_pre_133#X), partial_sum(_pre_134#X)] +Aggregate Attributes [2]: [sum#X, sum#X] +Results [3]: [l_shipmode#X, sum#X, sum#X] + +(14) ProjectExecTransformer +Output [4]: [hash(l_shipmode#X, 42) AS hash_partition_key#X, l_shipmode#X, sum#X, sum#X] +Input [3]: [l_shipmode#X, sum#X, sum#X] + +(15) WholeStageCodegenTransformer (X) +Input [4]: [hash_partition_key#X, l_shipmode#X, sum#X, sum#X] +Arguments: false + +(16) ColumnarExchange +Input [4]: [hash_partition_key#X, l_shipmode#X, sum#X, sum#X] +Arguments: hashpartitioning(l_shipmode#X, 1), ENSURE_REQUIREMENTS, [l_shipmode#X, sum#X, sum#X], [plan_id=X], [id=#X] + +(17) ShuffleQueryStage +Output [3]: [l_shipmode#X, sum#X, sum#X] +Arguments: X + +(18) InputAdapter +Input [3]: [l_shipmode#X, sum#X, sum#X] + +(19) InputIteratorTransformer +Input [3]: [l_shipmode#X, sum#X, sum#X] + +(20) RegularHashAggregateExecTransformer +Input [3]: [l_shipmode#X, sum#X, sum#X] +Keys [1]: [l_shipmode#X] +Functions [2]: [sum(CASE WHEN ((o_orderpriority#X = 1-URGENT) OR (o_orderpriority#X = 2-HIGH)) THEN 1 ELSE 0 END), sum(CASE WHEN (NOT (o_orderpriority#X = 1-URGENT) AND NOT (o_orderpriority#X = 2-HIGH)) THEN 1 ELSE 0 END)] +Aggregate Attributes [2]: [sum(CASE WHEN ((o_orderpriority#X = 1-URGENT) OR (o_orderpriority#X = 2-HIGH)) THEN 1 ELSE 0 END)#X, sum(CASE WHEN (NOT (o_orderpriority#X = 1-URGENT) AND NOT (o_orderpriority#X = 2-HIGH)) THEN 1 ELSE 0 END)#X] +Results [3]: [l_shipmode#X, sum(CASE WHEN ((o_orderpriority#X = 1-URGENT) OR (o_orderpriority#X = 2-HIGH)) THEN 1 ELSE 0 END)#X AS high_line_count#X, sum(CASE WHEN (NOT (o_orderpriority#X = 1-URGENT) AND NOT (o_orderpriority#X = 2-HIGH)) THEN 1 ELSE 0 END)#X AS low_line_count#X] + +(21) WholeStageCodegenTransformer (X) +Input [3]: [l_shipmode#X, high_line_count#X, low_line_count#X] +Arguments: false + +(22) ColumnarExchange +Input [3]: [l_shipmode#X, high_line_count#X, low_line_count#X] +Arguments: rangepartitioning(l_shipmode#X ASC NULLS FIRST, 1), ENSURE_REQUIREMENTS, [plan_id=X], [id=#X] + +(23) ShuffleQueryStage +Output [3]: [l_shipmode#X, high_line_count#X, low_line_count#X] +Arguments: X + +(24) InputAdapter +Input [3]: [l_shipmode#X, high_line_count#X, low_line_count#X] + +(25) InputIteratorTransformer +Input [3]: [l_shipmode#X, high_line_count#X, low_line_count#X] + +(26) SortExecTransformer +Input [3]: [l_shipmode#X, high_line_count#X, low_line_count#X] +Arguments: [l_shipmode#X ASC NULLS FIRST], true, 0 + +(27) WholeStageCodegenTransformer (X) +Input [3]: [l_shipmode#X, high_line_count#X, low_line_count#X] +Arguments: false + +(28) VeloxColumnarToRowExec +Input [3]: [l_shipmode#X, high_line_count#X, low_line_count#X] + +(29) Scan parquet +Output [2]: [o_orderkey#X, o_orderpriority#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_orderkey)] +ReadSchema: struct + +(30) Filter +Input [2]: [o_orderkey#X, o_orderpriority#X] +Condition : isnotnull(o_orderkey#X) + +(31) BroadcastExchange +Input [2]: [o_orderkey#X, o_orderpriority#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(32) Scan parquet +Output [5]: [l_orderkey#X, l_shipdate#X, l_commitdate#X, l_receiptdate#X, l_shipmode#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_commitdate), IsNotNull(l_receiptdate), IsNotNull(l_shipdate), In(l_shipmode, [MAIL,SHIP]), GreaterThanOrEqual(l_receiptdate,1994-01-01), LessThan(l_receiptdate,1995-01-01), IsNotNull(l_orderkey)] +ReadSchema: struct + +(33) Filter +Input [5]: [l_orderkey#X, l_shipdate#X, l_commitdate#X, l_receiptdate#X, l_shipmode#X] +Condition : ((((((((isnotnull(l_commitdate#X) AND isnotnull(l_receiptdate#X)) AND isnotnull(l_shipdate#X)) AND l_shipmode#X IN (MAIL,SHIP)) AND (l_commitdate#X < l_receiptdate#X)) AND (l_shipdate#X < l_commitdate#X)) AND (l_receiptdate#X >= 1994-01-01)) AND (l_receiptdate#X < 1995-01-01)) AND isnotnull(l_orderkey#X)) + +(34) Project +Output [2]: [l_orderkey#X, l_shipmode#X] +Input [5]: [l_orderkey#X, l_shipdate#X, l_commitdate#X, l_receiptdate#X, l_shipmode#X] + +(35) BroadcastHashJoin +Left keys [1]: [o_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: None + +(36) Project +Output [2]: [o_orderpriority#X, l_shipmode#X] +Input [4]: [o_orderkey#X, o_orderpriority#X, l_orderkey#X, l_shipmode#X] + +(37) HashAggregate +Input [2]: [o_orderpriority#X, l_shipmode#X] +Keys [1]: [l_shipmode#X] +Functions [2]: [partial_sum(CASE WHEN ((o_orderpriority#X = 1-URGENT) OR (o_orderpriority#X = 2-HIGH)) THEN 1 ELSE 0 END), partial_sum(CASE WHEN (NOT (o_orderpriority#X = 1-URGENT) AND NOT (o_orderpriority#X = 2-HIGH)) THEN 1 ELSE 0 END)] +Aggregate Attributes [2]: [sum#X, sum#X] +Results [3]: [l_shipmode#X, sum#X, sum#X] + +(38) Exchange +Input [3]: [l_shipmode#X, sum#X, sum#X] +Arguments: hashpartitioning(l_shipmode#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(39) HashAggregate +Input [3]: [l_shipmode#X, sum#X, sum#X] +Keys [1]: [l_shipmode#X] +Functions [2]: [sum(CASE WHEN ((o_orderpriority#X = 1-URGENT) OR (o_orderpriority#X = 2-HIGH)) THEN 1 ELSE 0 END), sum(CASE WHEN (NOT (o_orderpriority#X = 1-URGENT) AND NOT (o_orderpriority#X = 2-HIGH)) THEN 1 ELSE 0 END)] +Aggregate Attributes [2]: [sum(CASE WHEN ((o_orderpriority#X = 1-URGENT) OR (o_orderpriority#X = 2-HIGH)) THEN 1 ELSE 0 END)#X, sum(CASE WHEN (NOT (o_orderpriority#X = 1-URGENT) AND NOT (o_orderpriority#X = 2-HIGH)) THEN 1 ELSE 0 END)#X] +Results [3]: [l_shipmode#X, sum(CASE WHEN ((o_orderpriority#X = 1-URGENT) OR (o_orderpriority#X = 2-HIGH)) THEN 1 ELSE 0 END)#X AS high_line_count#X, sum(CASE WHEN (NOT (o_orderpriority#X = 1-URGENT) AND NOT (o_orderpriority#X = 2-HIGH)) THEN 1 ELSE 0 END)#X AS low_line_count#X] + +(40) Exchange +Input [3]: [l_shipmode#X, high_line_count#X, low_line_count#X] +Arguments: rangepartitioning(l_shipmode#X ASC NULLS FIRST, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(41) Sort +Input [3]: [l_shipmode#X, high_line_count#X, low_line_count#X] +Arguments: [l_shipmode#X ASC NULLS FIRST], true, 0 + +(42) AdaptiveSparkPlan +Output [3]: [l_shipmode#X, high_line_count#X, low_line_count#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/13.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/13.txt new file mode 100644 index 000000000000..59cad7d05318 --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/13.txt @@ -0,0 +1,286 @@ +== Physical Plan == +AdaptiveSparkPlan (52) ++- == Final Plan == + VeloxColumnarToRowExec (36) + +- ^ SortExecTransformer (34) + +- ^ InputIteratorTransformer (33) + +- ^ InputAdapter (32) + +- ^ ShuffleQueryStage (31) + +- ColumnarExchange (30) + +- ^ RegularHashAggregateExecTransformer (28) + +- ^ InputIteratorTransformer (27) + +- ^ InputAdapter (26) + +- ^ ShuffleQueryStage (25) + +- ColumnarExchange (24) + +- ^ ProjectExecTransformer (22) + +- ^ FlushableHashAggregateExecTransformer (21) + +- ^ ProjectExecTransformer (20) + +- ^ RegularHashAggregateExecTransformer (19) + +- ^ InputIteratorTransformer (18) + +- ^ InputAdapter (17) + +- ^ ShuffleQueryStage (16) + +- ColumnarExchange (15) + +- ^ ProjectExecTransformer (13) + +- ^ FlushableHashAggregateExecTransformer (12) + +- ^ ProjectExecTransformer (11) + +- ^ GlutenBroadcastHashJoinExecTransformer LeftOuter (10) + :- ^ Scan parquet (1) + +- ^ InputIteratorTransformer (9) + +- ^ InputAdapter (8) + +- ^ BroadcastQueryStage (7) + +- ColumnarBroadcastExchange (6) + +- ^ ProjectExecTransformer (4) + +- ^ FilterExecTransformer (3) + +- ^ Scan parquet (2) ++- == Initial Plan == + Sort (51) + +- Exchange (50) + +- HashAggregate (49) + +- Exchange (48) + +- HashAggregate (47) + +- HashAggregate (46) + +- Exchange (45) + +- HashAggregate (44) + +- Project (43) + +- BroadcastHashJoin LeftOuter BuildRight (42) + :- Scan parquet (37) + +- BroadcastExchange (41) + +- Project (40) + +- Filter (39) + +- Scan parquet (38) + + +(1) Scan parquet +Output [1]: [c_custkey#X] +Batched: true +Location: InMemoryFileIndex [*] +ReadSchema: struct + +(2) Scan parquet +Output [3]: [o_orderkey#X, o_custkey#X, o_comment#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_comment), IsNotNull(o_custkey)] +ReadSchema: struct + +(3) FilterExecTransformer +Input [3]: [o_orderkey#X, o_custkey#X, o_comment#X] +Arguments: ((isnotnull(o_comment#X) AND NOT o_comment#X LIKE %special%requests%) AND isnotnull(o_custkey#X)) + +(4) ProjectExecTransformer +Output [2]: [o_orderkey#X, o_custkey#X] +Input [3]: [o_orderkey#X, o_custkey#X, o_comment#X] + +(5) WholeStageCodegenTransformer (X) +Input [2]: [o_orderkey#X, o_custkey#X] +Arguments: false + +(6) ColumnarBroadcastExchange +Input [2]: [o_orderkey#X, o_custkey#X] +Arguments: HashedRelationBroadcastMode(List(input[1, bigint, true]),false), [plan_id=X] + +(7) BroadcastQueryStage +Output [2]: [o_orderkey#X, o_custkey#X] +Arguments: X + +(8) InputAdapter +Input [2]: [o_orderkey#X, o_custkey#X] + +(9) InputIteratorTransformer +Input [2]: [o_orderkey#X, o_custkey#X] + +(10) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [c_custkey#X] +Right keys [1]: [o_custkey#X] +Join condition: None + +(11) ProjectExecTransformer +Output [2]: [c_custkey#X, o_orderkey#X] +Input [3]: [c_custkey#X, o_orderkey#X, o_custkey#X] + +(12) FlushableHashAggregateExecTransformer +Input [2]: [c_custkey#X, o_orderkey#X] +Keys [1]: [c_custkey#X] +Functions [1]: [partial_count(o_orderkey#X)] +Aggregate Attributes [1]: [count#X] +Results [2]: [c_custkey#X, count#X] + +(13) ProjectExecTransformer +Output [3]: [hash(c_custkey#X, 42) AS hash_partition_key#X, c_custkey#X, count#X] +Input [2]: [c_custkey#X, count#X] + +(14) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, c_custkey#X, count#X] +Arguments: false + +(15) ColumnarExchange +Input [3]: [hash_partition_key#X, c_custkey#X, count#X] +Arguments: hashpartitioning(c_custkey#X, 1), ENSURE_REQUIREMENTS, [c_custkey#X, count#X], [plan_id=X], [id=#X] + +(16) ShuffleQueryStage +Output [2]: [c_custkey#X, count#X] +Arguments: X + +(17) InputAdapter +Input [2]: [c_custkey#X, count#X] + +(18) InputIteratorTransformer +Input [2]: [c_custkey#X, count#X] + +(19) RegularHashAggregateExecTransformer +Input [2]: [c_custkey#X, count#X] +Keys [1]: [c_custkey#X] +Functions [1]: [count(o_orderkey#X)] +Aggregate Attributes [1]: [count(o_orderkey#X)#X] +Results [2]: [c_custkey#X, count(o_orderkey#X)#X] + +(20) ProjectExecTransformer +Output [1]: [count(o_orderkey#X)#X AS c_count#X] +Input [2]: [c_custkey#X, count(o_orderkey#X)#X] + +(21) FlushableHashAggregateExecTransformer +Input [1]: [c_count#X] +Keys [1]: [c_count#X] +Functions [1]: [partial_count(1)] +Aggregate Attributes [1]: [count#X] +Results [2]: [c_count#X, count#X] + +(22) ProjectExecTransformer +Output [3]: [hash(c_count#X, 42) AS hash_partition_key#X, c_count#X, count#X] +Input [2]: [c_count#X, count#X] + +(23) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, c_count#X, count#X] +Arguments: false + +(24) ColumnarExchange +Input [3]: [hash_partition_key#X, c_count#X, count#X] +Arguments: hashpartitioning(c_count#X, 1), ENSURE_REQUIREMENTS, [c_count#X, count#X], [plan_id=X], [id=#X] + +(25) ShuffleQueryStage +Output [2]: [c_count#X, count#X] +Arguments: X + +(26) InputAdapter +Input [2]: [c_count#X, count#X] + +(27) InputIteratorTransformer +Input [2]: [c_count#X, count#X] + +(28) RegularHashAggregateExecTransformer +Input [2]: [c_count#X, count#X] +Keys [1]: [c_count#X] +Functions [1]: [count(1)] +Aggregate Attributes [1]: [count(1)#X] +Results [2]: [c_count#X, count(1)#X AS custdist#X] + +(29) WholeStageCodegenTransformer (X) +Input [2]: [c_count#X, custdist#X] +Arguments: false + +(30) ColumnarExchange +Input [2]: [c_count#X, custdist#X] +Arguments: rangepartitioning(custdist#X DESC NULLS LAST, c_count#X DESC NULLS LAST, 1), ENSURE_REQUIREMENTS, [plan_id=X], [id=#X] + +(31) ShuffleQueryStage +Output [2]: [c_count#X, custdist#X] +Arguments: X + +(32) InputAdapter +Input [2]: [c_count#X, custdist#X] + +(33) InputIteratorTransformer +Input [2]: [c_count#X, custdist#X] + +(34) SortExecTransformer +Input [2]: [c_count#X, custdist#X] +Arguments: [custdist#X DESC NULLS LAST, c_count#X DESC NULLS LAST], true, 0 + +(35) WholeStageCodegenTransformer (X) +Input [2]: [c_count#X, custdist#X] +Arguments: false + +(36) VeloxColumnarToRowExec +Input [2]: [c_count#X, custdist#X] + +(37) Scan parquet +Output [1]: [c_custkey#X] +Batched: true +Location: InMemoryFileIndex [*] +ReadSchema: struct + +(38) Scan parquet +Output [3]: [o_orderkey#X, o_custkey#X, o_comment#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_comment), IsNotNull(o_custkey)] +ReadSchema: struct + +(39) Filter +Input [3]: [o_orderkey#X, o_custkey#X, o_comment#X] +Condition : ((isnotnull(o_comment#X) AND NOT o_comment#X LIKE %special%requests%) AND isnotnull(o_custkey#X)) + +(40) Project +Output [2]: [o_orderkey#X, o_custkey#X] +Input [3]: [o_orderkey#X, o_custkey#X, o_comment#X] + +(41) BroadcastExchange +Input [2]: [o_orderkey#X, o_custkey#X] +Arguments: HashedRelationBroadcastMode(List(input[1, bigint, true]),false), [plan_id=X] + +(42) BroadcastHashJoin +Left keys [1]: [c_custkey#X] +Right keys [1]: [o_custkey#X] +Join condition: None + +(43) Project +Output [2]: [c_custkey#X, o_orderkey#X] +Input [3]: [c_custkey#X, o_orderkey#X, o_custkey#X] + +(44) HashAggregate +Input [2]: [c_custkey#X, o_orderkey#X] +Keys [1]: [c_custkey#X] +Functions [1]: [partial_count(o_orderkey#X)] +Aggregate Attributes [1]: [count#X] +Results [2]: [c_custkey#X, count#X] + +(45) Exchange +Input [2]: [c_custkey#X, count#X] +Arguments: hashpartitioning(c_custkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(46) HashAggregate +Input [2]: [c_custkey#X, count#X] +Keys [1]: [c_custkey#X] +Functions [1]: [count(o_orderkey#X)] +Aggregate Attributes [1]: [count(o_orderkey#X)#X] +Results [1]: [count(o_orderkey#X)#X AS c_count#X] + +(47) HashAggregate +Input [1]: [c_count#X] +Keys [1]: [c_count#X] +Functions [1]: [partial_count(1)] +Aggregate Attributes [1]: [count#X] +Results [2]: [c_count#X, count#X] + +(48) Exchange +Input [2]: [c_count#X, count#X] +Arguments: hashpartitioning(c_count#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(49) HashAggregate +Input [2]: [c_count#X, count#X] +Keys [1]: [c_count#X] +Functions [1]: [count(1)] +Aggregate Attributes [1]: [count(1)#X] +Results [2]: [c_count#X, count(1)#X AS custdist#X] + +(50) Exchange +Input [2]: [c_count#X, custdist#X] +Arguments: rangepartitioning(custdist#X DESC NULLS LAST, c_count#X DESC NULLS LAST, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(51) Sort +Input [2]: [c_count#X, custdist#X] +Arguments: [custdist#X DESC NULLS LAST, c_count#X DESC NULLS LAST], true, 0 + +(52) AdaptiveSparkPlan +Output [2]: [c_count#X, custdist#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/14.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/14.txt new file mode 100644 index 000000000000..35b4a3384271 --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/14.txt @@ -0,0 +1,192 @@ +== Physical Plan == +AdaptiveSparkPlan (34) ++- == Final Plan == + VeloxColumnarToRowExec (22) + +- ^ ProjectExecTransformer (20) + +- ^ RegularHashAggregateExecTransformer (19) + +- ^ InputIteratorTransformer (18) + +- ^ InputAdapter (17) + +- ^ ShuffleQueryStage (16) + +- ColumnarExchange (15) + +- ^ FlushableHashAggregateExecTransformer (13) + +- ^ ProjectExecTransformer (12) + +- ^ GlutenBroadcastHashJoinExecTransformer Inner (11) + :- ^ ProjectExecTransformer (3) + : +- ^ FilterExecTransformer (2) + : +- ^ Scan parquet (1) + +- ^ InputIteratorTransformer (10) + +- ^ InputAdapter (9) + +- ^ BroadcastQueryStage (8) + +- ColumnarBroadcastExchange (7) + +- ^ FilterExecTransformer (5) + +- ^ Scan parquet (4) ++- == Initial Plan == + HashAggregate (33) + +- Exchange (32) + +- HashAggregate (31) + +- Project (30) + +- BroadcastHashJoin Inner BuildRight (29) + :- Project (25) + : +- Filter (24) + : +- Scan parquet (23) + +- BroadcastExchange (28) + +- Filter (27) + +- Scan parquet (26) + + +(1) Scan parquet +Output [4]: [l_partkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_shipdate), GreaterThanOrEqual(l_shipdate,1995-09-01), LessThan(l_shipdate,1995-10-01), IsNotNull(l_partkey)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [4]: [l_partkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Arguments: (((isnotnull(l_shipdate#X) AND (l_shipdate#X >= 1995-09-01)) AND (l_shipdate#X < 1995-10-01)) AND isnotnull(l_partkey#X)) + +(3) ProjectExecTransformer +Output [3]: [l_partkey#X, l_extendedprice#X, l_discount#X] +Input [4]: [l_partkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] + +(4) Scan parquet +Output [2]: [p_partkey#X, p_type#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(p_partkey)] +ReadSchema: struct + +(5) FilterExecTransformer +Input [2]: [p_partkey#X, p_type#X] +Arguments: isnotnull(p_partkey#X) + +(6) WholeStageCodegenTransformer (X) +Input [2]: [p_partkey#X, p_type#X] +Arguments: false + +(7) ColumnarBroadcastExchange +Input [2]: [p_partkey#X, p_type#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(8) BroadcastQueryStage +Output [2]: [p_partkey#X, p_type#X] +Arguments: X + +(9) InputAdapter +Input [2]: [p_partkey#X, p_type#X] + +(10) InputIteratorTransformer +Input [2]: [p_partkey#X, p_type#X] + +(11) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [l_partkey#X] +Right keys [1]: [p_partkey#X] +Join condition: None + +(12) ProjectExecTransformer +Output [5]: [l_extendedprice#X, l_discount#X, p_type#X, CASE WHEN StartsWith(p_type#X, PROMO) THEN CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) ELSE 0.0000 END AS _pre_135#X, CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) AS _pre_136#X] +Input [5]: [l_partkey#X, l_extendedprice#X, l_discount#X, p_partkey#X, p_type#X] + +(13) FlushableHashAggregateExecTransformer +Input [5]: [l_extendedprice#X, l_discount#X, p_type#X, _pre_135#X, _pre_136#X] +Keys: [] +Functions [2]: [partial_sum(_pre_135#X), partial_sum(_pre_136#X)] +Aggregate Attributes [4]: [sum#X, isEmpty#X, sum#X, isEmpty#X] +Results [4]: [sum#X, isEmpty#X, sum#X, isEmpty#X] + +(14) WholeStageCodegenTransformer (X) +Input [4]: [sum#X, isEmpty#X, sum#X, isEmpty#X] +Arguments: false + +(15) ColumnarExchange +Input [4]: [sum#X, isEmpty#X, sum#X, isEmpty#X] +Arguments: SinglePartition, ENSURE_REQUIREMENTS, [plan_id=X], [id=#X] + +(16) ShuffleQueryStage +Output [4]: [sum#X, isEmpty#X, sum#X, isEmpty#X] +Arguments: X + +(17) InputAdapter +Input [4]: [sum#X, isEmpty#X, sum#X, isEmpty#X] + +(18) InputIteratorTransformer +Input [4]: [sum#X, isEmpty#X, sum#X, isEmpty#X] + +(19) RegularHashAggregateExecTransformer +Input [4]: [sum#X, isEmpty#X, sum#X, isEmpty#X] +Keys: [] +Functions [2]: [sum(CASE WHEN StartsWith(p_type#X, PROMO) THEN CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) ELSE 0.0000 END), sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))] +Aggregate Attributes [2]: [sum(CASE WHEN StartsWith(p_type#X, PROMO) THEN CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) ELSE 0.0000 END)#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X] +Results [2]: [sum(CASE WHEN StartsWith(p_type#X, PROMO) THEN CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) ELSE 0.0000 END)#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X] + +(20) ProjectExecTransformer +Output [1]: [CheckOverflow((promote_precision(CheckOverflow((100.0000 * promote_precision(sum(CASE WHEN StartsWith(p_type#X, PROMO) THEN CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) ELSE 0.0000 END)#X)), DecimalType(38,6), true)) / promote_precision(cast(sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X as decimal(38,6)))), DecimalType(38,6), true) AS promo_revenue#X] +Input [2]: [sum(CASE WHEN StartsWith(p_type#X, PROMO) THEN CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) ELSE 0.0000 END)#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X] + +(21) WholeStageCodegenTransformer (X) +Input [1]: [promo_revenue#X] +Arguments: false + +(22) VeloxColumnarToRowExec +Input [1]: [promo_revenue#X] + +(23) Scan parquet +Output [4]: [l_partkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_shipdate), GreaterThanOrEqual(l_shipdate,1995-09-01), LessThan(l_shipdate,1995-10-01), IsNotNull(l_partkey)] +ReadSchema: struct + +(24) Filter +Input [4]: [l_partkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Condition : (((isnotnull(l_shipdate#X) AND (l_shipdate#X >= 1995-09-01)) AND (l_shipdate#X < 1995-10-01)) AND isnotnull(l_partkey#X)) + +(25) Project +Output [3]: [l_partkey#X, l_extendedprice#X, l_discount#X] +Input [4]: [l_partkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] + +(26) Scan parquet +Output [2]: [p_partkey#X, p_type#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(p_partkey)] +ReadSchema: struct + +(27) Filter +Input [2]: [p_partkey#X, p_type#X] +Condition : isnotnull(p_partkey#X) + +(28) BroadcastExchange +Input [2]: [p_partkey#X, p_type#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(29) BroadcastHashJoin +Left keys [1]: [l_partkey#X] +Right keys [1]: [p_partkey#X] +Join condition: None + +(30) Project +Output [3]: [l_extendedprice#X, l_discount#X, p_type#X] +Input [5]: [l_partkey#X, l_extendedprice#X, l_discount#X, p_partkey#X, p_type#X] + +(31) HashAggregate +Input [3]: [l_extendedprice#X, l_discount#X, p_type#X] +Keys: [] +Functions [2]: [partial_sum(CASE WHEN StartsWith(p_type#X, PROMO) THEN CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) ELSE 0.0000 END), partial_sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))] +Aggregate Attributes [4]: [sum#X, isEmpty#X, sum#X, isEmpty#X] +Results [4]: [sum#X, isEmpty#X, sum#X, isEmpty#X] + +(32) Exchange +Input [4]: [sum#X, isEmpty#X, sum#X, isEmpty#X] +Arguments: SinglePartition, ENSURE_REQUIREMENTS, [plan_id=X] + +(33) HashAggregate +Input [4]: [sum#X, isEmpty#X, sum#X, isEmpty#X] +Keys: [] +Functions [2]: [sum(CASE WHEN StartsWith(p_type#X, PROMO) THEN CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) ELSE 0.0000 END), sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))] +Aggregate Attributes [2]: [sum(CASE WHEN StartsWith(p_type#X, PROMO) THEN CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) ELSE 0.0000 END)#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X] +Results [1]: [CheckOverflow((promote_precision(CheckOverflow((100.0000 * promote_precision(sum(CASE WHEN StartsWith(p_type#X, PROMO) THEN CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) ELSE 0.0000 END)#X)), DecimalType(38,6), true)) / promote_precision(cast(sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X as decimal(38,6)))), DecimalType(38,6), true) AS promo_revenue#X] + +(34) AdaptiveSparkPlan +Output [1]: [promo_revenue#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/15.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/15.txt new file mode 100644 index 000000000000..71f5cba2029b --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/15.txt @@ -0,0 +1,239 @@ +== Physical Plan == +AdaptiveSparkPlan (44) ++- == Final Plan == + VeloxColumnarToRowExec (29) + +- ^ SortExecTransformer (27) + +- ^ InputIteratorTransformer (26) + +- ^ InputAdapter (25) + +- ^ ShuffleQueryStage (24) + +- ColumnarExchange (23) + +- ^ ProjectExecTransformer (21) + +- ^ GlutenBroadcastHashJoinExecTransformer Inner (20) + :- ^ InputIteratorTransformer (7) + : +- ^ InputAdapter (6) + : +- ^ BroadcastQueryStage (5) + : +- ColumnarBroadcastExchange (4) + : +- ^ FilterExecTransformer (2) + : +- ^ Scan parquet (1) + +- ^ FilterExecTransformer (19) + +- ^ RegularHashAggregateExecTransformer (18) + +- ^ InputIteratorTransformer (17) + +- ^ InputAdapter (16) + +- ^ ShuffleQueryStage (15) + +- ColumnarExchange (14) + +- ^ ProjectExecTransformer (12) + +- ^ FlushableHashAggregateExecTransformer (11) + +- ^ ProjectExecTransformer (10) + +- ^ FilterExecTransformer (9) + +- ^ Scan parquet (8) ++- == Initial Plan == + Sort (43) + +- Exchange (42) + +- Project (41) + +- BroadcastHashJoin Inner BuildLeft (40) + :- BroadcastExchange (32) + : +- Filter (31) + : +- Scan parquet (30) + +- Filter (39) + +- HashAggregate (38) + +- Exchange (37) + +- HashAggregate (36) + +- Project (35) + +- Filter (34) + +- Scan parquet (33) + + +(1) Scan parquet +Output [4]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(s_suppkey)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [4]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X] +Arguments: isnotnull(s_suppkey#X) + +(3) WholeStageCodegenTransformer (X) +Input [4]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X] +Arguments: false + +(4) ColumnarBroadcastExchange +Input [4]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(5) BroadcastQueryStage +Output [4]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X] +Arguments: X + +(6) InputAdapter +Input [4]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X] + +(7) InputIteratorTransformer +Input [4]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X] + +(8) Scan parquet +Output [4]: [l_suppkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_shipdate), GreaterThanOrEqual(l_shipdate,1996-01-01), LessThan(l_shipdate,1996-04-01), IsNotNull(l_suppkey)] +ReadSchema: struct + +(9) FilterExecTransformer +Input [4]: [l_suppkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Arguments: (((isnotnull(l_shipdate#X) AND (l_shipdate#X >= 1996-01-01)) AND (l_shipdate#X < 1996-04-01)) AND isnotnull(l_suppkey#X)) + +(10) ProjectExecTransformer +Output [4]: [l_suppkey#X, l_extendedprice#X, l_discount#X, CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) AS _pre_137#X] +Input [4]: [l_suppkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] + +(11) FlushableHashAggregateExecTransformer +Input [4]: [l_suppkey#X, l_extendedprice#X, l_discount#X, _pre_137#X] +Keys [1]: [l_suppkey#X] +Functions [1]: [partial_sum(_pre_137#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [3]: [l_suppkey#X, sum#X, isEmpty#X] + +(12) ProjectExecTransformer +Output [4]: [hash(l_suppkey#X, 42) AS hash_partition_key#X, l_suppkey#X, sum#X, isEmpty#X] +Input [3]: [l_suppkey#X, sum#X, isEmpty#X] + +(13) WholeStageCodegenTransformer (X) +Input [4]: [hash_partition_key#X, l_suppkey#X, sum#X, isEmpty#X] +Arguments: false + +(14) ColumnarExchange +Input [4]: [hash_partition_key#X, l_suppkey#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(l_suppkey#X, 1), ENSURE_REQUIREMENTS, [l_suppkey#X, sum#X, isEmpty#X], [plan_id=X], [id=#X] + +(15) ShuffleQueryStage +Output [3]: [l_suppkey#X, sum#X, isEmpty#X] +Arguments: X + +(16) InputAdapter +Input [3]: [l_suppkey#X, sum#X, isEmpty#X] + +(17) InputIteratorTransformer +Input [3]: [l_suppkey#X, sum#X, isEmpty#X] + +(18) RegularHashAggregateExecTransformer +Input [3]: [l_suppkey#X, sum#X, isEmpty#X] +Keys [1]: [l_suppkey#X] +Functions [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))] +Aggregate Attributes [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X] +Results [2]: [l_suppkey#X AS supplier_no#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X AS total_revenue#X] + +(19) FilterExecTransformer +Input [2]: [supplier_no#X, total_revenue#X] +Arguments: (isnotnull(total_revenue#X) AND (total_revenue#X = Subquery subquery#X, [id=#X])) + +(20) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [s_suppkey#X] +Right keys [1]: [supplier_no#X] +Join condition: None + +(21) ProjectExecTransformer +Output [5]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X, total_revenue#X] +Input [6]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X, supplier_no#X, total_revenue#X] + +(22) WholeStageCodegenTransformer (X) +Input [5]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X, total_revenue#X] +Arguments: false + +(23) ColumnarExchange +Input [5]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X, total_revenue#X] +Arguments: rangepartitioning(s_suppkey#X ASC NULLS FIRST, 1), ENSURE_REQUIREMENTS, [plan_id=X], [id=#X] + +(24) ShuffleQueryStage +Output [5]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X, total_revenue#X] +Arguments: X + +(25) InputAdapter +Input [5]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X, total_revenue#X] + +(26) InputIteratorTransformer +Input [5]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X, total_revenue#X] + +(27) SortExecTransformer +Input [5]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X, total_revenue#X] +Arguments: [s_suppkey#X ASC NULLS FIRST], true, 0 + +(28) WholeStageCodegenTransformer (X) +Input [5]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X, total_revenue#X] +Arguments: false + +(29) VeloxColumnarToRowExec +Input [5]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X, total_revenue#X] + +(30) Scan parquet +Output [4]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(s_suppkey)] +ReadSchema: struct + +(31) Filter +Input [4]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X] +Condition : isnotnull(s_suppkey#X) + +(32) BroadcastExchange +Input [4]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(33) Scan parquet +Output [4]: [l_suppkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_shipdate), GreaterThanOrEqual(l_shipdate,1996-01-01), LessThan(l_shipdate,1996-04-01), IsNotNull(l_suppkey)] +ReadSchema: struct + +(34) Filter +Input [4]: [l_suppkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Condition : (((isnotnull(l_shipdate#X) AND (l_shipdate#X >= 1996-01-01)) AND (l_shipdate#X < 1996-04-01)) AND isnotnull(l_suppkey#X)) + +(35) Project +Output [3]: [l_suppkey#X, l_extendedprice#X, l_discount#X] +Input [4]: [l_suppkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] + +(36) HashAggregate +Input [3]: [l_suppkey#X, l_extendedprice#X, l_discount#X] +Keys [1]: [l_suppkey#X] +Functions [1]: [partial_sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [3]: [l_suppkey#X, sum#X, isEmpty#X] + +(37) Exchange +Input [3]: [l_suppkey#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(l_suppkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(38) HashAggregate +Input [3]: [l_suppkey#X, sum#X, isEmpty#X] +Keys [1]: [l_suppkey#X] +Functions [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))] +Aggregate Attributes [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X] +Results [2]: [l_suppkey#X AS supplier_no#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X AS total_revenue#X] + +(39) Filter +Input [2]: [supplier_no#X, total_revenue#X] +Condition : (isnotnull(total_revenue#X) AND (total_revenue#X = Subquery subquery#X, [id=#X])) + +(40) BroadcastHashJoin +Left keys [1]: [s_suppkey#X] +Right keys [1]: [supplier_no#X] +Join condition: None + +(41) Project +Output [5]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X, total_revenue#X] +Input [6]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X, supplier_no#X, total_revenue#X] + +(42) Exchange +Input [5]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X, total_revenue#X] +Arguments: rangepartitioning(s_suppkey#X ASC NULLS FIRST, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(43) Sort +Input [5]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X, total_revenue#X] +Arguments: [s_suppkey#X ASC NULLS FIRST], true, 0 + +(44) AdaptiveSparkPlan +Output [5]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X, total_revenue#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/16.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/16.txt new file mode 100644 index 000000000000..b741d2617f55 --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/16.txt @@ -0,0 +1,312 @@ +== Physical Plan == +AdaptiveSparkPlan (56) ++- == Final Plan == + VeloxColumnarToRowExec (35) + +- ^ SortExecTransformer (33) + +- ^ InputIteratorTransformer (32) + +- ^ InputAdapter (31) + +- ^ ShuffleQueryStage (30) + +- ColumnarExchange (29) + +- ^ RegularHashAggregateExecTransformer (27) + +- ^ InputIteratorTransformer (26) + +- ^ InputAdapter (25) + +- ^ ShuffleQueryStage (24) + +- ColumnarExchange (23) + +- ^ ProjectExecTransformer (21) + +- ^ FlushableHashAggregateExecTransformer (20) + +- ^ RegularHashAggregateExecTransformer (19) + +- ^ InputIteratorTransformer (18) + +- ^ InputAdapter (17) + +- ^ ShuffleQueryStage (16) + +- ColumnarExchange (15) + +- ^ ProjectExecTransformer (13) + +- ^ FlushableHashAggregateExecTransformer (12) + +- ^ ProjectExecTransformer (11) + +- ^ GlutenBroadcastHashJoinExecTransformer Inner (10) + :- ^ FilterExecTransformer (2) + : +- ^ Scan parquet (1) + +- ^ InputIteratorTransformer (9) + +- ^ InputAdapter (8) + +- ^ BroadcastQueryStage (7) + +- ColumnarBroadcastExchange (6) + +- ^ FilterExecTransformer (4) + +- ^ Scan parquet (3) ++- == Initial Plan == + Sort (55) + +- Exchange (54) + +- HashAggregate (53) + +- Exchange (52) + +- HashAggregate (51) + +- HashAggregate (50) + +- Exchange (49) + +- HashAggregate (48) + +- Project (47) + +- BroadcastHashJoin Inner BuildRight (46) + :- BroadcastHashJoin LeftAnti BuildRight (42) + : :- Filter (37) + : : +- Scan parquet (36) + : +- BroadcastExchange (41) + : +- Project (40) + : +- Filter (39) + : +- Scan parquet (38) + +- BroadcastExchange (45) + +- Filter (44) + +- Scan parquet (43) + + +(1) Scan parquet +Output [2]: [ps_partkey#X, ps_suppkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(ps_partkey)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [2]: [ps_partkey#X, ps_suppkey#X] +Arguments: isnotnull(ps_partkey#X) + +(3) Scan parquet +Output [4]: [p_partkey#X, p_brand#X, p_type#X, p_size#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(p_brand), IsNotNull(p_type), Not(EqualTo(p_brand,Brand#X)), Not(StringStartsWith(p_type,MEDIUM POLISHED)), In(p_size, [14,19,23,3,36,45,49,9]), IsNotNull(p_partkey)] +ReadSchema: struct + +(4) FilterExecTransformer +Input [4]: [p_partkey#X, p_brand#X, p_type#X, p_size#X] +Arguments: (((((isnotnull(p_brand#X) AND isnotnull(p_type#X)) AND NOT (p_brand#X = Brand#X)) AND NOT StartsWith(p_type#X, MEDIUM POLISHED)) AND p_size#X IN (49,14,23,45,19,3,36,9)) AND isnotnull(p_partkey#X)) + +(5) WholeStageCodegenTransformer (X) +Input [4]: [p_partkey#X, p_brand#X, p_type#X, p_size#X] +Arguments: false + +(6) ColumnarBroadcastExchange +Input [4]: [p_partkey#X, p_brand#X, p_type#X, p_size#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(7) BroadcastQueryStage +Output [4]: [p_partkey#X, p_brand#X, p_type#X, p_size#X] +Arguments: X + +(8) InputAdapter +Input [4]: [p_partkey#X, p_brand#X, p_type#X, p_size#X] + +(9) InputIteratorTransformer +Input [4]: [p_partkey#X, p_brand#X, p_type#X, p_size#X] + +(10) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [ps_partkey#X] +Right keys [1]: [p_partkey#X] +Join condition: None + +(11) ProjectExecTransformer +Output [4]: [ps_suppkey#X, p_brand#X, p_type#X, p_size#X] +Input [6]: [ps_partkey#X, ps_suppkey#X, p_partkey#X, p_brand#X, p_type#X, p_size#X] + +(12) FlushableHashAggregateExecTransformer +Input [4]: [ps_suppkey#X, p_brand#X, p_type#X, p_size#X] +Keys [4]: [p_brand#X, p_type#X, p_size#X, ps_suppkey#X] +Functions: [] +Aggregate Attributes: [] +Results [4]: [p_brand#X, p_type#X, p_size#X, ps_suppkey#X] + +(13) ProjectExecTransformer +Output [5]: [hash(p_brand#X, p_type#X, p_size#X, ps_suppkey#X, 42) AS hash_partition_key#X, p_brand#X, p_type#X, p_size#X, ps_suppkey#X] +Input [4]: [p_brand#X, p_type#X, p_size#X, ps_suppkey#X] + +(14) WholeStageCodegenTransformer (X) +Input [5]: [hash_partition_key#X, p_brand#X, p_type#X, p_size#X, ps_suppkey#X] +Arguments: false + +(15) ColumnarExchange +Input [5]: [hash_partition_key#X, p_brand#X, p_type#X, p_size#X, ps_suppkey#X] +Arguments: hashpartitioning(p_brand#X, p_type#X, p_size#X, ps_suppkey#X, 1), ENSURE_REQUIREMENTS, [p_brand#X, p_type#X, p_size#X, ps_suppkey#X], [plan_id=X], [id=#X] + +(16) ShuffleQueryStage +Output [4]: [p_brand#X, p_type#X, p_size#X, ps_suppkey#X] +Arguments: X + +(17) InputAdapter +Input [4]: [p_brand#X, p_type#X, p_size#X, ps_suppkey#X] + +(18) InputIteratorTransformer +Input [4]: [p_brand#X, p_type#X, p_size#X, ps_suppkey#X] + +(19) RegularHashAggregateExecTransformer +Input [4]: [p_brand#X, p_type#X, p_size#X, ps_suppkey#X] +Keys [4]: [p_brand#X, p_type#X, p_size#X, ps_suppkey#X] +Functions: [] +Aggregate Attributes: [] +Results [4]: [p_brand#X, p_type#X, p_size#X, ps_suppkey#X] + +(20) FlushableHashAggregateExecTransformer +Input [4]: [p_brand#X, p_type#X, p_size#X, ps_suppkey#X] +Keys [3]: [p_brand#X, p_type#X, p_size#X] +Functions [1]: [partial_count(distinct ps_suppkey#X)] +Aggregate Attributes [1]: [count(ps_suppkey#X)#X] +Results [4]: [p_brand#X, p_type#X, p_size#X, count#X] + +(21) ProjectExecTransformer +Output [5]: [hash(p_brand#X, p_type#X, p_size#X, 42) AS hash_partition_key#X, p_brand#X, p_type#X, p_size#X, count#X] +Input [4]: [p_brand#X, p_type#X, p_size#X, count#X] + +(22) WholeStageCodegenTransformer (X) +Input [5]: [hash_partition_key#X, p_brand#X, p_type#X, p_size#X, count#X] +Arguments: false + +(23) ColumnarExchange +Input [5]: [hash_partition_key#X, p_brand#X, p_type#X, p_size#X, count#X] +Arguments: hashpartitioning(p_brand#X, p_type#X, p_size#X, 1), ENSURE_REQUIREMENTS, [p_brand#X, p_type#X, p_size#X, count#X], [plan_id=X], [id=#X] + +(24) ShuffleQueryStage +Output [4]: [p_brand#X, p_type#X, p_size#X, count#X] +Arguments: X + +(25) InputAdapter +Input [4]: [p_brand#X, p_type#X, p_size#X, count#X] + +(26) InputIteratorTransformer +Input [4]: [p_brand#X, p_type#X, p_size#X, count#X] + +(27) RegularHashAggregateExecTransformer +Input [4]: [p_brand#X, p_type#X, p_size#X, count#X] +Keys [3]: [p_brand#X, p_type#X, p_size#X] +Functions [1]: [count(distinct ps_suppkey#X)] +Aggregate Attributes [1]: [count(ps_suppkey#X)#X] +Results [4]: [p_brand#X, p_type#X, p_size#X, count(ps_suppkey#X)#X AS supplier_cnt#X] + +(28) WholeStageCodegenTransformer (X) +Input [4]: [p_brand#X, p_type#X, p_size#X, supplier_cnt#X] +Arguments: false + +(29) ColumnarExchange +Input [4]: [p_brand#X, p_type#X, p_size#X, supplier_cnt#X] +Arguments: rangepartitioning(supplier_cnt#X DESC NULLS LAST, p_brand#X ASC NULLS FIRST, p_type#X ASC NULLS FIRST, p_size#X ASC NULLS FIRST, 1), ENSURE_REQUIREMENTS, [plan_id=X], [id=#X] + +(30) ShuffleQueryStage +Output [4]: [p_brand#X, p_type#X, p_size#X, supplier_cnt#X] +Arguments: X + +(31) InputAdapter +Input [4]: [p_brand#X, p_type#X, p_size#X, supplier_cnt#X] + +(32) InputIteratorTransformer +Input [4]: [p_brand#X, p_type#X, p_size#X, supplier_cnt#X] + +(33) SortExecTransformer +Input [4]: [p_brand#X, p_type#X, p_size#X, supplier_cnt#X] +Arguments: [supplier_cnt#X DESC NULLS LAST, p_brand#X ASC NULLS FIRST, p_type#X ASC NULLS FIRST, p_size#X ASC NULLS FIRST], true, 0 + +(34) WholeStageCodegenTransformer (X) +Input [4]: [p_brand#X, p_type#X, p_size#X, supplier_cnt#X] +Arguments: false + +(35) VeloxColumnarToRowExec +Input [4]: [p_brand#X, p_type#X, p_size#X, supplier_cnt#X] + +(36) Scan parquet +Output [2]: [ps_partkey#X, ps_suppkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(ps_partkey)] +ReadSchema: struct + +(37) Filter +Input [2]: [ps_partkey#X, ps_suppkey#X] +Condition : isnotnull(ps_partkey#X) + +(38) Scan parquet +Output [2]: [s_suppkey#X, s_comment#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(s_comment)] +ReadSchema: struct + +(39) Filter +Input [2]: [s_suppkey#X, s_comment#X] +Condition : (isnotnull(s_comment#X) AND s_comment#X LIKE %Customer%Complaints%) + +(40) Project +Output [1]: [s_suppkey#X] +Input [2]: [s_suppkey#X, s_comment#X] + +(41) BroadcastExchange +Input [1]: [s_suppkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),true), [plan_id=X] + +(42) BroadcastHashJoin +Left keys [1]: [ps_suppkey#X] +Right keys [1]: [s_suppkey#X] +Join condition: None + +(43) Scan parquet +Output [4]: [p_partkey#X, p_brand#X, p_type#X, p_size#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(p_brand), IsNotNull(p_type), Not(EqualTo(p_brand,Brand#X)), Not(StringStartsWith(p_type,MEDIUM POLISHED)), In(p_size, [14,19,23,3,36,45,49,9]), IsNotNull(p_partkey)] +ReadSchema: struct + +(44) Filter +Input [4]: [p_partkey#X, p_brand#X, p_type#X, p_size#X] +Condition : (((((isnotnull(p_brand#X) AND isnotnull(p_type#X)) AND NOT (p_brand#X = Brand#X)) AND NOT StartsWith(p_type#X, MEDIUM POLISHED)) AND p_size#X IN (49,14,23,45,19,3,36,9)) AND isnotnull(p_partkey#X)) + +(45) BroadcastExchange +Input [4]: [p_partkey#X, p_brand#X, p_type#X, p_size#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(46) BroadcastHashJoin +Left keys [1]: [ps_partkey#X] +Right keys [1]: [p_partkey#X] +Join condition: None + +(47) Project +Output [4]: [ps_suppkey#X, p_brand#X, p_type#X, p_size#X] +Input [6]: [ps_partkey#X, ps_suppkey#X, p_partkey#X, p_brand#X, p_type#X, p_size#X] + +(48) HashAggregate +Input [4]: [ps_suppkey#X, p_brand#X, p_type#X, p_size#X] +Keys [4]: [p_brand#X, p_type#X, p_size#X, ps_suppkey#X] +Functions: [] +Aggregate Attributes: [] +Results [4]: [p_brand#X, p_type#X, p_size#X, ps_suppkey#X] + +(49) Exchange +Input [4]: [p_brand#X, p_type#X, p_size#X, ps_suppkey#X] +Arguments: hashpartitioning(p_brand#X, p_type#X, p_size#X, ps_suppkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(50) HashAggregate +Input [4]: [p_brand#X, p_type#X, p_size#X, ps_suppkey#X] +Keys [4]: [p_brand#X, p_type#X, p_size#X, ps_suppkey#X] +Functions: [] +Aggregate Attributes: [] +Results [4]: [p_brand#X, p_type#X, p_size#X, ps_suppkey#X] + +(51) HashAggregate +Input [4]: [p_brand#X, p_type#X, p_size#X, ps_suppkey#X] +Keys [3]: [p_brand#X, p_type#X, p_size#X] +Functions [1]: [partial_count(distinct ps_suppkey#X)] +Aggregate Attributes [1]: [count(ps_suppkey#X)#X] +Results [4]: [p_brand#X, p_type#X, p_size#X, count#X] + +(52) Exchange +Input [4]: [p_brand#X, p_type#X, p_size#X, count#X] +Arguments: hashpartitioning(p_brand#X, p_type#X, p_size#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(53) HashAggregate +Input [4]: [p_brand#X, p_type#X, p_size#X, count#X] +Keys [3]: [p_brand#X, p_type#X, p_size#X] +Functions [1]: [count(distinct ps_suppkey#X)] +Aggregate Attributes [1]: [count(ps_suppkey#X)#X] +Results [4]: [p_brand#X, p_type#X, p_size#X, count(ps_suppkey#X)#X AS supplier_cnt#X] + +(54) Exchange +Input [4]: [p_brand#X, p_type#X, p_size#X, supplier_cnt#X] +Arguments: rangepartitioning(supplier_cnt#X DESC NULLS LAST, p_brand#X ASC NULLS FIRST, p_type#X ASC NULLS FIRST, p_size#X ASC NULLS FIRST, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(55) Sort +Input [4]: [p_brand#X, p_type#X, p_size#X, supplier_cnt#X] +Arguments: [supplier_cnt#X DESC NULLS LAST, p_brand#X ASC NULLS FIRST, p_type#X ASC NULLS FIRST, p_size#X ASC NULLS FIRST], true, 0 + +(56) AdaptiveSparkPlan +Output [4]: [p_brand#X, p_type#X, p_size#X, supplier_cnt#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/17.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/17.txt new file mode 100644 index 000000000000..d806c8c2577b --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/17.txt @@ -0,0 +1,200 @@ +== Physical Plan == +AdaptiveSparkPlan (35) ++- == Final Plan == + VeloxColumnarToRowExec (14) + +- ^ ProjectExecTransformer (12) + +- ^ RegularHashAggregateExecTransformer (11) + +- ^ InputIteratorTransformer (10) + +- ^ InputAdapter (9) + +- ^ ShuffleQueryStage (8) + +- ColumnarExchange (7) + +- ^ FlushableHashAggregateExecTransformer (5) + +- ^ InputIteratorTransformer (4) + +- ^ InputAdapter (3) + +- ^ RowToVeloxColumnar (2) + +- ^ LocalTableScan (1) ++- == Initial Plan == + HashAggregate (34) + +- Exchange (33) + +- HashAggregate (32) + +- Project (31) + +- BroadcastHashJoin Inner BuildRight (30) + :- Project (22) + : +- BroadcastHashJoin Inner BuildRight (21) + : :- Filter (16) + : : +- Scan parquet (15) + : +- BroadcastExchange (20) + : +- Project (19) + : +- Filter (18) + : +- Scan parquet (17) + +- BroadcastExchange (29) + +- Filter (28) + +- HashAggregate (27) + +- Exchange (26) + +- HashAggregate (25) + +- Filter (24) + +- Scan parquet (23) + + +(1) LocalTableScan +Output [1]: [l_extendedprice#X] +Arguments: , [l_extendedprice#X] + +(2) RowToVeloxColumnar +Input [1]: [l_extendedprice#X] + +(3) InputAdapter +Input [1]: [l_extendedprice#X] + +(4) InputIteratorTransformer +Input [1]: [l_extendedprice#X] + +(5) FlushableHashAggregateExecTransformer +Input [1]: [l_extendedprice#X] +Keys: [] +Functions [1]: [partial_sum(l_extendedprice#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [2]: [sum#X, isEmpty#X] + +(6) WholeStageCodegenTransformer (X) +Input [2]: [sum#X, isEmpty#X] +Arguments: false + +(7) ColumnarExchange +Input [2]: [sum#X, isEmpty#X] +Arguments: SinglePartition, ENSURE_REQUIREMENTS, [plan_id=X], [id=#X] + +(8) ShuffleQueryStage +Output [2]: [sum#X, isEmpty#X] +Arguments: X + +(9) InputAdapter +Input [2]: [sum#X, isEmpty#X] + +(10) InputIteratorTransformer +Input [2]: [sum#X, isEmpty#X] + +(11) RegularHashAggregateExecTransformer +Input [2]: [sum#X, isEmpty#X] +Keys: [] +Functions [1]: [sum(l_extendedprice#X)] +Aggregate Attributes [1]: [sum(l_extendedprice#X)#X] +Results [1]: [sum(l_extendedprice#X)#X] + +(12) ProjectExecTransformer +Output [1]: [CheckOverflow((promote_precision(sum(l_extendedprice#X)#X) / 7.00), DecimalType(27,6), true) AS avg_yearly#X] +Input [1]: [sum(l_extendedprice#X)#X] + +(13) WholeStageCodegenTransformer (X) +Input [1]: [avg_yearly#X] +Arguments: false + +(14) VeloxColumnarToRowExec +Input [1]: [avg_yearly#X] + +(15) Scan parquet +Output [3]: [l_partkey#X, l_quantity#X, l_extendedprice#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_partkey), IsNotNull(l_quantity)] +ReadSchema: struct + +(16) Filter +Input [3]: [l_partkey#X, l_quantity#X, l_extendedprice#X] +Condition : (isnotnull(l_partkey#X) AND isnotnull(l_quantity#X)) + +(17) Scan parquet +Output [3]: [p_partkey#X, p_brand#X, p_container#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(p_brand), IsNotNull(p_container), EqualTo(p_brand,Brand#X), EqualTo(p_container,MED BOX), IsNotNull(p_partkey)] +ReadSchema: struct + +(18) Filter +Input [3]: [p_partkey#X, p_brand#X, p_container#X] +Condition : ((((isnotnull(p_brand#X) AND isnotnull(p_container#X)) AND (p_brand#X = Brand#X)) AND (p_container#X = MED BOX)) AND isnotnull(p_partkey#X)) + +(19) Project +Output [1]: [p_partkey#X] +Input [3]: [p_partkey#X, p_brand#X, p_container#X] + +(20) BroadcastExchange +Input [1]: [p_partkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(21) BroadcastHashJoin +Left keys [1]: [l_partkey#X] +Right keys [1]: [p_partkey#X] +Join condition: None + +(22) Project +Output [3]: [l_quantity#X, l_extendedprice#X, p_partkey#X] +Input [4]: [l_partkey#X, l_quantity#X, l_extendedprice#X, p_partkey#X] + +(23) Scan parquet +Output [2]: [l_partkey#X, l_quantity#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_partkey)] +ReadSchema: struct + +(24) Filter +Input [2]: [l_partkey#X, l_quantity#X] +Condition : isnotnull(l_partkey#X) + +(25) HashAggregate +Input [2]: [l_partkey#X, l_quantity#X] +Keys [1]: [l_partkey#X] +Functions [1]: [partial_avg(l_quantity#X)] +Aggregate Attributes [2]: [sum#X, count#X] +Results [3]: [l_partkey#X, sum#X, count#X] + +(26) Exchange +Input [3]: [l_partkey#X, sum#X, count#X] +Arguments: hashpartitioning(l_partkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(27) HashAggregate +Input [3]: [l_partkey#X, sum#X, count#X] +Keys [1]: [l_partkey#X] +Functions [1]: [avg(l_quantity#X)] +Aggregate Attributes [1]: [avg(l_quantity#X)#X] +Results [2]: [CheckOverflow((0.200000 * promote_precision(avg(l_quantity#X)#X)), DecimalType(18,7), true) AS (0.2 * avg(l_quantity))#X, l_partkey#X] + +(28) Filter +Input [2]: [(0.2 * avg(l_quantity))#X, l_partkey#X] +Condition : isnotnull((0.2 * avg(l_quantity))#X) + +(29) BroadcastExchange +Input [2]: [(0.2 * avg(l_quantity))#X, l_partkey#X] +Arguments: HashedRelationBroadcastMode(List(input[1, bigint, true]),false), [plan_id=X] + +(30) BroadcastHashJoin +Left keys [1]: [p_partkey#X] +Right keys [1]: [l_partkey#X] +Join condition: (cast(l_quantity#X as decimal(18,7)) < (0.2 * avg(l_quantity))#X) + +(31) Project +Output [1]: [l_extendedprice#X] +Input [5]: [l_quantity#X, l_extendedprice#X, p_partkey#X, (0.2 * avg(l_quantity))#X, l_partkey#X] + +(32) HashAggregate +Input [1]: [l_extendedprice#X] +Keys: [] +Functions [1]: [partial_sum(l_extendedprice#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [2]: [sum#X, isEmpty#X] + +(33) Exchange +Input [2]: [sum#X, isEmpty#X] +Arguments: SinglePartition, ENSURE_REQUIREMENTS, [plan_id=X] + +(34) HashAggregate +Input [2]: [sum#X, isEmpty#X] +Keys: [] +Functions [1]: [sum(l_extendedprice#X)] +Aggregate Attributes [1]: [sum(l_extendedprice#X)#X] +Results [1]: [CheckOverflow((promote_precision(sum(l_extendedprice#X)#X) / 7.00), DecimalType(27,6), true) AS avg_yearly#X] + +(35) AdaptiveSparkPlan +Output [1]: [avg_yearly#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/18.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/18.txt new file mode 100644 index 000000000000..99c5812e2072 --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/18.txt @@ -0,0 +1,476 @@ +== Physical Plan == +AdaptiveSparkPlan (86) ++- == Final Plan == + VeloxColumnarToRowExec (53) + +- TakeOrderedAndProjectExecTransformer (52) + +- ^ RegularHashAggregateExecTransformer (50) + +- ^ InputIteratorTransformer (49) + +- ^ InputAdapter (48) + +- ^ ShuffleQueryStage (47) + +- ColumnarExchange (46) + +- ^ ProjectExecTransformer (44) + +- ^ FlushableHashAggregateExecTransformer (43) + +- ^ ProjectExecTransformer (42) + +- ^ GlutenBroadcastHashJoinExecTransformer Inner (41) + :- ^ ProjectExecTransformer (28) + : +- ^ GlutenBroadcastHashJoinExecTransformer Inner (27) + : :- ^ InputIteratorTransformer (7) + : : +- ^ InputAdapter (6) + : : +- ^ BroadcastQueryStage (5) + : : +- ColumnarBroadcastExchange (4) + : : +- ^ FilterExecTransformer (2) + : : +- ^ Scan parquet (1) + : +- ^ GlutenBroadcastHashJoinExecTransformer LeftSemi (26) + : :- ^ FilterExecTransformer (9) + : : +- ^ Scan parquet (8) + : +- ^ InputIteratorTransformer (25) + : +- ^ InputAdapter (24) + : +- ^ BroadcastQueryStage (23) + : +- ColumnarBroadcastExchange (22) + : +- ^ ProjectExecTransformer (20) + : +- ^ FilterExecTransformer (19) + : +- ^ RegularHashAggregateExecTransformer (18) + : +- ^ InputIteratorTransformer (17) + : +- ^ InputAdapter (16) + : +- ^ ShuffleQueryStage (15) + : +- ColumnarExchange (14) + : +- ^ ProjectExecTransformer (12) + : +- ^ FlushableHashAggregateExecTransformer (11) + : +- ^ Scan parquet (10) + +- ^ InputIteratorTransformer (40) + +- ^ InputAdapter (39) + +- ^ BroadcastQueryStage (38) + +- ColumnarBroadcastExchange (37) + +- ^ GlutenBroadcastHashJoinExecTransformer LeftSemi (35) + :- ^ FilterExecTransformer (30) + : +- ^ Scan parquet (29) + +- ^ InputIteratorTransformer (34) + +- ^ InputAdapter (33) + +- ^ BroadcastQueryStage (32) + +- ReusedExchange (31) ++- == Initial Plan == + TakeOrderedAndProject (85) + +- HashAggregate (84) + +- Exchange (83) + +- HashAggregate (82) + +- Project (81) + +- BroadcastHashJoin Inner BuildRight (80) + :- Project (68) + : +- BroadcastHashJoin Inner BuildLeft (67) + : :- BroadcastExchange (56) + : : +- Filter (55) + : : +- Scan parquet (54) + : +- BroadcastHashJoin LeftSemi BuildRight (66) + : :- Filter (58) + : : +- Scan parquet (57) + : +- BroadcastExchange (65) + : +- Project (64) + : +- Filter (63) + : +- HashAggregate (62) + : +- Exchange (61) + : +- HashAggregate (60) + : +- Scan parquet (59) + +- BroadcastExchange (79) + +- BroadcastHashJoin LeftSemi BuildRight (78) + :- Filter (70) + : +- Scan parquet (69) + +- BroadcastExchange (77) + +- Project (76) + +- Filter (75) + +- HashAggregate (74) + +- Exchange (73) + +- HashAggregate (72) + +- Scan parquet (71) + + +(1) Scan parquet +Output [2]: [c_custkey#X, c_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(c_custkey)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [2]: [c_custkey#X, c_name#X] +Arguments: isnotnull(c_custkey#X) + +(3) WholeStageCodegenTransformer (X) +Input [2]: [c_custkey#X, c_name#X] +Arguments: false + +(4) ColumnarBroadcastExchange +Input [2]: [c_custkey#X, c_name#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(5) BroadcastQueryStage +Output [2]: [c_custkey#X, c_name#X] +Arguments: X + +(6) InputAdapter +Input [2]: [c_custkey#X, c_name#X] + +(7) InputIteratorTransformer +Input [2]: [c_custkey#X, c_name#X] + +(8) Scan parquet +Output [4]: [o_orderkey#X, o_custkey#X, o_totalprice#X, o_orderdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_custkey), IsNotNull(o_orderkey)] +ReadSchema: struct + +(9) FilterExecTransformer +Input [4]: [o_orderkey#X, o_custkey#X, o_totalprice#X, o_orderdate#X] +Arguments: (isnotnull(o_custkey#X) AND isnotnull(o_orderkey#X)) + +(10) Scan parquet +Output [2]: [l_orderkey#X, l_quantity#X] +Batched: true +Location: InMemoryFileIndex [*] +ReadSchema: struct + +(11) FlushableHashAggregateExecTransformer +Input [2]: [l_orderkey#X, l_quantity#X] +Keys [1]: [l_orderkey#X] +Functions [1]: [partial_sum(l_quantity#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [3]: [l_orderkey#X, sum#X, isEmpty#X] + +(12) ProjectExecTransformer +Output [4]: [hash(l_orderkey#X, 42) AS hash_partition_key#X, l_orderkey#X, sum#X, isEmpty#X] +Input [3]: [l_orderkey#X, sum#X, isEmpty#X] + +(13) WholeStageCodegenTransformer (X) +Input [4]: [hash_partition_key#X, l_orderkey#X, sum#X, isEmpty#X] +Arguments: false + +(14) ColumnarExchange +Input [4]: [hash_partition_key#X, l_orderkey#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(l_orderkey#X, 1), ENSURE_REQUIREMENTS, [l_orderkey#X, sum#X, isEmpty#X], [plan_id=X], [id=#X] + +(15) ShuffleQueryStage +Output [3]: [l_orderkey#X, sum#X, isEmpty#X] +Arguments: X + +(16) InputAdapter +Input [3]: [l_orderkey#X, sum#X, isEmpty#X] + +(17) InputIteratorTransformer +Input [3]: [l_orderkey#X, sum#X, isEmpty#X] + +(18) RegularHashAggregateExecTransformer +Input [3]: [l_orderkey#X, sum#X, isEmpty#X] +Keys [1]: [l_orderkey#X] +Functions [1]: [sum(l_quantity#X)] +Aggregate Attributes [1]: [sum(l_quantity#X)#X] +Results [2]: [l_orderkey#X, sum(l_quantity#X)#X AS sum(l_quantity#X)#X] + +(19) FilterExecTransformer +Input [2]: [l_orderkey#X, sum(l_quantity#X)#X] +Arguments: (isnotnull(sum(l_quantity#X)#X) AND (sum(l_quantity#X)#X > 300.00)) + +(20) ProjectExecTransformer +Output [1]: [l_orderkey#X] +Input [2]: [l_orderkey#X, sum(l_quantity#X)#X] + +(21) WholeStageCodegenTransformer (X) +Input [1]: [l_orderkey#X] +Arguments: false + +(22) ColumnarBroadcastExchange +Input [1]: [l_orderkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(23) BroadcastQueryStage +Output [1]: [l_orderkey#X] +Arguments: X + +(24) InputAdapter +Input [1]: [l_orderkey#X] + +(25) InputIteratorTransformer +Input [1]: [l_orderkey#X] + +(26) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [o_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: None + +(27) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [c_custkey#X] +Right keys [1]: [o_custkey#X] +Join condition: None + +(28) ProjectExecTransformer +Output [5]: [c_custkey#X, c_name#X, o_orderkey#X, o_totalprice#X, o_orderdate#X] +Input [6]: [c_custkey#X, c_name#X, o_orderkey#X, o_custkey#X, o_totalprice#X, o_orderdate#X] + +(29) Scan parquet +Output [2]: [l_orderkey#X, l_quantity#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_orderkey)] +ReadSchema: struct + +(30) FilterExecTransformer +Input [2]: [l_orderkey#X, l_quantity#X] +Arguments: isnotnull(l_orderkey#X) + +(31) ReusedExchange [Reuses operator id: 22] +Output [1]: [l_orderkey#X] + +(32) BroadcastQueryStage +Output [1]: [l_orderkey#X] +Arguments: X + +(33) InputAdapter +Input [1]: [l_orderkey#X] + +(34) InputIteratorTransformer +Input [1]: [l_orderkey#X] + +(35) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [l_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: None + +(36) WholeStageCodegenTransformer (X) +Input [2]: [l_orderkey#X, l_quantity#X] +Arguments: false + +(37) ColumnarBroadcastExchange +Input [2]: [l_orderkey#X, l_quantity#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(38) BroadcastQueryStage +Output [2]: [l_orderkey#X, l_quantity#X] +Arguments: X + +(39) InputAdapter +Input [2]: [l_orderkey#X, l_quantity#X] + +(40) InputIteratorTransformer +Input [2]: [l_orderkey#X, l_quantity#X] + +(41) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [o_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: None + +(42) ProjectExecTransformer +Output [6]: [c_custkey#X, c_name#X, o_orderkey#X, o_totalprice#X, o_orderdate#X, l_quantity#X] +Input [7]: [c_custkey#X, c_name#X, o_orderkey#X, o_totalprice#X, o_orderdate#X, l_orderkey#X, l_quantity#X] + +(43) FlushableHashAggregateExecTransformer +Input [6]: [c_custkey#X, c_name#X, o_orderkey#X, o_totalprice#X, o_orderdate#X, l_quantity#X] +Keys [5]: [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X] +Functions [1]: [partial_sum(l_quantity#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [7]: [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, sum#X, isEmpty#X] + +(44) ProjectExecTransformer +Output [8]: [hash(c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, 42) AS hash_partition_key#X, c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, sum#X, isEmpty#X] +Input [7]: [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, sum#X, isEmpty#X] + +(45) WholeStageCodegenTransformer (X) +Input [8]: [hash_partition_key#X, c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, sum#X, isEmpty#X] +Arguments: false + +(46) ColumnarExchange +Input [8]: [hash_partition_key#X, c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, 1), ENSURE_REQUIREMENTS, [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, sum#X, isEmpty#X], [plan_id=X], [id=#X] + +(47) ShuffleQueryStage +Output [7]: [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, sum#X, isEmpty#X] +Arguments: X + +(48) InputAdapter +Input [7]: [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, sum#X, isEmpty#X] + +(49) InputIteratorTransformer +Input [7]: [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, sum#X, isEmpty#X] + +(50) RegularHashAggregateExecTransformer +Input [7]: [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, sum#X, isEmpty#X] +Keys [5]: [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X] +Functions [1]: [sum(l_quantity#X)] +Aggregate Attributes [1]: [sum(l_quantity#X)#X] +Results [6]: [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, sum(l_quantity#X)#X AS sum(l_quantity)#X] + +(51) WholeStageCodegenTransformer (X) +Input [6]: [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, sum(l_quantity)#X] +Arguments: false + +(52) TakeOrderedAndProjectExecTransformer +Input [6]: [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, sum(l_quantity)#X] +Arguments: X, [o_totalprice#X DESC NULLS LAST, o_orderdate#X ASC NULLS FIRST], [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, sum(l_quantity)#X], 0 + +(53) VeloxColumnarToRowExec +Input [6]: [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, sum(l_quantity)#X] + +(54) Scan parquet +Output [2]: [c_custkey#X, c_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(c_custkey)] +ReadSchema: struct + +(55) Filter +Input [2]: [c_custkey#X, c_name#X] +Condition : isnotnull(c_custkey#X) + +(56) BroadcastExchange +Input [2]: [c_custkey#X, c_name#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(57) Scan parquet +Output [4]: [o_orderkey#X, o_custkey#X, o_totalprice#X, o_orderdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_custkey), IsNotNull(o_orderkey)] +ReadSchema: struct + +(58) Filter +Input [4]: [o_orderkey#X, o_custkey#X, o_totalprice#X, o_orderdate#X] +Condition : (isnotnull(o_custkey#X) AND isnotnull(o_orderkey#X)) + +(59) Scan parquet +Output [2]: [l_orderkey#X, l_quantity#X] +Batched: true +Location: InMemoryFileIndex [*] +ReadSchema: struct + +(60) HashAggregate +Input [2]: [l_orderkey#X, l_quantity#X] +Keys [1]: [l_orderkey#X] +Functions [1]: [partial_sum(l_quantity#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [3]: [l_orderkey#X, sum#X, isEmpty#X] + +(61) Exchange +Input [3]: [l_orderkey#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(l_orderkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(62) HashAggregate +Input [3]: [l_orderkey#X, sum#X, isEmpty#X] +Keys [1]: [l_orderkey#X] +Functions [1]: [sum(l_quantity#X)] +Aggregate Attributes [1]: [sum(l_quantity#X)#X] +Results [2]: [l_orderkey#X, sum(l_quantity#X)#X AS sum(l_quantity#X)#X] + +(63) Filter +Input [2]: [l_orderkey#X, sum(l_quantity#X)#X] +Condition : (isnotnull(sum(l_quantity#X)#X) AND (sum(l_quantity#X)#X > 300.00)) + +(64) Project +Output [1]: [l_orderkey#X] +Input [2]: [l_orderkey#X, sum(l_quantity#X)#X] + +(65) BroadcastExchange +Input [1]: [l_orderkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(66) BroadcastHashJoin +Left keys [1]: [o_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: None + +(67) BroadcastHashJoin +Left keys [1]: [c_custkey#X] +Right keys [1]: [o_custkey#X] +Join condition: None + +(68) Project +Output [5]: [c_custkey#X, c_name#X, o_orderkey#X, o_totalprice#X, o_orderdate#X] +Input [6]: [c_custkey#X, c_name#X, o_orderkey#X, o_custkey#X, o_totalprice#X, o_orderdate#X] + +(69) Scan parquet +Output [2]: [l_orderkey#X, l_quantity#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_orderkey)] +ReadSchema: struct + +(70) Filter +Input [2]: [l_orderkey#X, l_quantity#X] +Condition : isnotnull(l_orderkey#X) + +(71) Scan parquet +Output [2]: [l_orderkey#X, l_quantity#X] +Batched: true +Location: InMemoryFileIndex [*] +ReadSchema: struct + +(72) HashAggregate +Input [2]: [l_orderkey#X, l_quantity#X] +Keys [1]: [l_orderkey#X] +Functions [1]: [partial_sum(l_quantity#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [3]: [l_orderkey#X, sum#X, isEmpty#X] + +(73) Exchange +Input [3]: [l_orderkey#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(l_orderkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(74) HashAggregate +Input [3]: [l_orderkey#X, sum#X, isEmpty#X] +Keys [1]: [l_orderkey#X] +Functions [1]: [sum(l_quantity#X)] +Aggregate Attributes [1]: [sum(l_quantity#X)#X] +Results [2]: [l_orderkey#X, sum(l_quantity#X)#X AS sum(l_quantity#X)#X] + +(75) Filter +Input [2]: [l_orderkey#X, sum(l_quantity#X)#X] +Condition : (isnotnull(sum(l_quantity#X)#X) AND (sum(l_quantity#X)#X > 300.00)) + +(76) Project +Output [1]: [l_orderkey#X] +Input [2]: [l_orderkey#X, sum(l_quantity#X)#X] + +(77) BroadcastExchange +Input [1]: [l_orderkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(78) BroadcastHashJoin +Left keys [1]: [l_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: None + +(79) BroadcastExchange +Input [2]: [l_orderkey#X, l_quantity#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(80) BroadcastHashJoin +Left keys [1]: [o_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: None + +(81) Project +Output [6]: [c_custkey#X, c_name#X, o_orderkey#X, o_totalprice#X, o_orderdate#X, l_quantity#X] +Input [7]: [c_custkey#X, c_name#X, o_orderkey#X, o_totalprice#X, o_orderdate#X, l_orderkey#X, l_quantity#X] + +(82) HashAggregate +Input [6]: [c_custkey#X, c_name#X, o_orderkey#X, o_totalprice#X, o_orderdate#X, l_quantity#X] +Keys [5]: [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X] +Functions [1]: [partial_sum(l_quantity#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [7]: [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, sum#X, isEmpty#X] + +(83) Exchange +Input [7]: [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(84) HashAggregate +Input [7]: [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, sum#X, isEmpty#X] +Keys [5]: [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X] +Functions [1]: [sum(l_quantity#X)] +Aggregate Attributes [1]: [sum(l_quantity#X)#X] +Results [6]: [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, sum(l_quantity#X)#X AS sum(l_quantity)#X] + +(85) TakeOrderedAndProject +Input [6]: [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, sum(l_quantity)#X] +Arguments: X, [o_totalprice#X DESC NULLS LAST, o_orderdate#X ASC NULLS FIRST], [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, sum(l_quantity)#X] + +(86) AdaptiveSparkPlan +Output [6]: [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, sum(l_quantity)#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/19.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/19.txt new file mode 100644 index 000000000000..f0340bdd9163 --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/19.txt @@ -0,0 +1,187 @@ +== Physical Plan == +AdaptiveSparkPlan (33) ++- == Final Plan == + VeloxColumnarToRowExec (21) + +- ^ RegularHashAggregateExecTransformer (19) + +- ^ InputIteratorTransformer (18) + +- ^ InputAdapter (17) + +- ^ ShuffleQueryStage (16) + +- ColumnarExchange (15) + +- ^ FlushableHashAggregateExecTransformer (13) + +- ^ ProjectExecTransformer (12) + +- ^ GlutenBroadcastHashJoinExecTransformer Inner (11) + :- ^ ProjectExecTransformer (3) + : +- ^ FilterExecTransformer (2) + : +- ^ Scan parquet (1) + +- ^ InputIteratorTransformer (10) + +- ^ InputAdapter (9) + +- ^ BroadcastQueryStage (8) + +- ColumnarBroadcastExchange (7) + +- ^ FilterExecTransformer (5) + +- ^ Scan parquet (4) ++- == Initial Plan == + HashAggregate (32) + +- Exchange (31) + +- HashAggregate (30) + +- Project (29) + +- BroadcastHashJoin Inner BuildRight (28) + :- Project (24) + : +- Filter (23) + : +- Scan parquet (22) + +- BroadcastExchange (27) + +- Filter (26) + +- Scan parquet (25) + + +(1) Scan parquet +Output [6]: [l_partkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, l_shipinstruct#X, l_shipmode#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_shipinstruct), In(l_shipmode, [AIR,AIR REG]), EqualTo(l_shipinstruct,DELIVER IN PERSON), IsNotNull(l_partkey), Or(Or(And(GreaterThanOrEqual(l_quantity,1.00),LessThanOrEqual(l_quantity,11.00)),And(GreaterThanOrEqual(l_quantity,10.00),LessThanOrEqual(l_quantity,20.00))),And(GreaterThanOrEqual(l_quantity,20.00),LessThanOrEqual(l_quantity,30.00)))] +ReadSchema: struct + +(2) FilterExecTransformer +Input [6]: [l_partkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, l_shipinstruct#X, l_shipmode#X] +Arguments: ((((isnotnull(l_shipinstruct#X) AND l_shipmode#X IN (AIR,AIR REG)) AND (l_shipinstruct#X = DELIVER IN PERSON)) AND isnotnull(l_partkey#X)) AND ((((l_quantity#X >= 1.00) AND (l_quantity#X <= 11.00)) OR ((l_quantity#X >= 10.00) AND (l_quantity#X <= 20.00))) OR ((l_quantity#X >= 20.00) AND (l_quantity#X <= 30.00)))) + +(3) ProjectExecTransformer +Output [4]: [l_partkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] +Input [6]: [l_partkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, l_shipinstruct#X, l_shipmode#X] + +(4) Scan parquet +Output [4]: [p_partkey#X, p_brand#X, p_size#X, p_container#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(p_size), GreaterThanOrEqual(p_size,1), IsNotNull(p_partkey), Or(Or(And(And(EqualTo(p_brand,Brand#X),In(p_container, [SM BOX,SM CASE,SM PACK,SM PKG])),LessThanOrEqual(p_size,5)),And(And(EqualTo(p_brand,Brand#X),In(p_container, [MED BAG,MED BOX,MED PACK,MED PKG])),LessThanOrEqual(p_size,10))),And(And(EqualTo(p_brand,Brand#X),In(p_container, [LG BOX,LG CASE,LG PACK,LG PKG])),LessThanOrEqual(p_size,15)))] +ReadSchema: struct + +(5) FilterExecTransformer +Input [4]: [p_partkey#X, p_brand#X, p_size#X, p_container#X] +Arguments: (((isnotnull(p_size#X) AND (p_size#X >= 1)) AND isnotnull(p_partkey#X)) AND (((((p_brand#X = Brand#X) AND p_container#X IN (SM CASE,SM BOX,SM PACK,SM PKG)) AND (p_size#X <= 5)) OR (((p_brand#X = Brand#X) AND p_container#X IN (MED BAG,MED BOX,MED PKG,MED PACK)) AND (p_size#X <= 10))) OR (((p_brand#X = Brand#X) AND p_container#X IN (LG CASE,LG BOX,LG PACK,LG PKG)) AND (p_size#X <= 15)))) + +(6) WholeStageCodegenTransformer (X) +Input [4]: [p_partkey#X, p_brand#X, p_size#X, p_container#X] +Arguments: false + +(7) ColumnarBroadcastExchange +Input [4]: [p_partkey#X, p_brand#X, p_size#X, p_container#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(8) BroadcastQueryStage +Output [4]: [p_partkey#X, p_brand#X, p_size#X, p_container#X] +Arguments: X + +(9) InputAdapter +Input [4]: [p_partkey#X, p_brand#X, p_size#X, p_container#X] + +(10) InputIteratorTransformer +Input [4]: [p_partkey#X, p_brand#X, p_size#X, p_container#X] + +(11) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [l_partkey#X] +Right keys [1]: [p_partkey#X] +Join condition: (((((((p_brand#X = Brand#X) AND p_container#X IN (SM CASE,SM BOX,SM PACK,SM PKG)) AND (l_quantity#X >= 1.00)) AND (l_quantity#X <= 11.00)) AND (p_size#X <= 5)) OR (((((p_brand#X = Brand#X) AND p_container#X IN (MED BAG,MED BOX,MED PKG,MED PACK)) AND (l_quantity#X >= 10.00)) AND (l_quantity#X <= 20.00)) AND (p_size#X <= 10))) OR (((((p_brand#X = Brand#X) AND p_container#X IN (LG CASE,LG BOX,LG PACK,LG PKG)) AND (l_quantity#X >= 20.00)) AND (l_quantity#X <= 30.00)) AND (p_size#X <= 15))) + +(12) ProjectExecTransformer +Output [3]: [l_extendedprice#X, l_discount#X, CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) AS _pre_139#X] +Input [8]: [l_partkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, p_partkey#X, p_brand#X, p_size#X, p_container#X] + +(13) FlushableHashAggregateExecTransformer +Input [3]: [l_extendedprice#X, l_discount#X, _pre_139#X] +Keys: [] +Functions [1]: [partial_sum(_pre_139#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [2]: [sum#X, isEmpty#X] + +(14) WholeStageCodegenTransformer (X) +Input [2]: [sum#X, isEmpty#X] +Arguments: false + +(15) ColumnarExchange +Input [2]: [sum#X, isEmpty#X] +Arguments: SinglePartition, ENSURE_REQUIREMENTS, [plan_id=X], [id=#X] + +(16) ShuffleQueryStage +Output [2]: [sum#X, isEmpty#X] +Arguments: X + +(17) InputAdapter +Input [2]: [sum#X, isEmpty#X] + +(18) InputIteratorTransformer +Input [2]: [sum#X, isEmpty#X] + +(19) RegularHashAggregateExecTransformer +Input [2]: [sum#X, isEmpty#X] +Keys: [] +Functions [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))] +Aggregate Attributes [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X] +Results [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X AS revenue#X] + +(20) WholeStageCodegenTransformer (X) +Input [1]: [revenue#X] +Arguments: false + +(21) VeloxColumnarToRowExec +Input [1]: [revenue#X] + +(22) Scan parquet +Output [6]: [l_partkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, l_shipinstruct#X, l_shipmode#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_shipinstruct), In(l_shipmode, [AIR,AIR REG]), EqualTo(l_shipinstruct,DELIVER IN PERSON), IsNotNull(l_partkey), Or(Or(And(GreaterThanOrEqual(l_quantity,1.00),LessThanOrEqual(l_quantity,11.00)),And(GreaterThanOrEqual(l_quantity,10.00),LessThanOrEqual(l_quantity,20.00))),And(GreaterThanOrEqual(l_quantity,20.00),LessThanOrEqual(l_quantity,30.00)))] +ReadSchema: struct + +(23) Filter +Input [6]: [l_partkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, l_shipinstruct#X, l_shipmode#X] +Condition : ((((isnotnull(l_shipinstruct#X) AND l_shipmode#X IN (AIR,AIR REG)) AND (l_shipinstruct#X = DELIVER IN PERSON)) AND isnotnull(l_partkey#X)) AND ((((l_quantity#X >= 1.00) AND (l_quantity#X <= 11.00)) OR ((l_quantity#X >= 10.00) AND (l_quantity#X <= 20.00))) OR ((l_quantity#X >= 20.00) AND (l_quantity#X <= 30.00)))) + +(24) Project +Output [4]: [l_partkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] +Input [6]: [l_partkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, l_shipinstruct#X, l_shipmode#X] + +(25) Scan parquet +Output [4]: [p_partkey#X, p_brand#X, p_size#X, p_container#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(p_size), GreaterThanOrEqual(p_size,1), IsNotNull(p_partkey), Or(Or(And(And(EqualTo(p_brand,Brand#X),In(p_container, [SM BOX,SM CASE,SM PACK,SM PKG])),LessThanOrEqual(p_size,5)),And(And(EqualTo(p_brand,Brand#X),In(p_container, [MED BAG,MED BOX,MED PACK,MED PKG])),LessThanOrEqual(p_size,10))),And(And(EqualTo(p_brand,Brand#X),In(p_container, [LG BOX,LG CASE,LG PACK,LG PKG])),LessThanOrEqual(p_size,15)))] +ReadSchema: struct + +(26) Filter +Input [4]: [p_partkey#X, p_brand#X, p_size#X, p_container#X] +Condition : (((isnotnull(p_size#X) AND (p_size#X >= 1)) AND isnotnull(p_partkey#X)) AND (((((p_brand#X = Brand#X) AND p_container#X IN (SM CASE,SM BOX,SM PACK,SM PKG)) AND (p_size#X <= 5)) OR (((p_brand#X = Brand#X) AND p_container#X IN (MED BAG,MED BOX,MED PKG,MED PACK)) AND (p_size#X <= 10))) OR (((p_brand#X = Brand#X) AND p_container#X IN (LG CASE,LG BOX,LG PACK,LG PKG)) AND (p_size#X <= 15)))) + +(27) BroadcastExchange +Input [4]: [p_partkey#X, p_brand#X, p_size#X, p_container#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(28) BroadcastHashJoin +Left keys [1]: [l_partkey#X] +Right keys [1]: [p_partkey#X] +Join condition: (((((((p_brand#X = Brand#X) AND p_container#X IN (SM CASE,SM BOX,SM PACK,SM PKG)) AND (l_quantity#X >= 1.00)) AND (l_quantity#X <= 11.00)) AND (p_size#X <= 5)) OR (((((p_brand#X = Brand#X) AND p_container#X IN (MED BAG,MED BOX,MED PKG,MED PACK)) AND (l_quantity#X >= 10.00)) AND (l_quantity#X <= 20.00)) AND (p_size#X <= 10))) OR (((((p_brand#X = Brand#X) AND p_container#X IN (LG CASE,LG BOX,LG PACK,LG PKG)) AND (l_quantity#X >= 20.00)) AND (l_quantity#X <= 30.00)) AND (p_size#X <= 15))) + +(29) Project +Output [2]: [l_extendedprice#X, l_discount#X] +Input [8]: [l_partkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, p_partkey#X, p_brand#X, p_size#X, p_container#X] + +(30) HashAggregate +Input [2]: [l_extendedprice#X, l_discount#X] +Keys: [] +Functions [1]: [partial_sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [2]: [sum#X, isEmpty#X] + +(31) Exchange +Input [2]: [sum#X, isEmpty#X] +Arguments: SinglePartition, ENSURE_REQUIREMENTS, [plan_id=X] + +(32) HashAggregate +Input [2]: [sum#X, isEmpty#X] +Keys: [] +Functions [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))] +Aggregate Attributes [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X] +Results [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X AS revenue#X] + +(33) AdaptiveSparkPlan +Output [1]: [revenue#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/20.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/20.txt new file mode 100644 index 000000000000..9b090e08662f --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/20.txt @@ -0,0 +1,568 @@ +== Physical Plan == +AdaptiveSparkPlan (107) ++- == Final Plan == + VeloxColumnarToRowExec (70) + +- ^ SortExecTransformer (68) + +- ^ InputIteratorTransformer (67) + +- ^ InputAdapter (66) + +- ^ ShuffleQueryStage (65) + +- ColumnarExchange (64) + +- ^ ProjectExecTransformer (62) + +- ^ GlutenBroadcastHashJoinExecTransformer Inner (61) + :- ^ ProjectExecTransformer (52) + : +- ^ GlutenBroadcastHashJoinExecTransformer LeftSemi (51) + : :- ^ InputIteratorTransformer (9) + : : +- ^ InputAdapter (8) + : : +- ^ AQEShuffleRead (7) + : : +- ^ ShuffleQueryStage (6) + : : +- ColumnarExchange (5) + : : +- ^ ProjectExecTransformer (3) + : : +- ^ FilterExecTransformer (2) + : : +- ^ Scan parquet (1) + : +- ^ InputIteratorTransformer (50) + : +- ^ InputAdapter (49) + : +- ^ BroadcastQueryStage (48) + : +- ColumnarBroadcastExchange (47) + : +- ^ ProjectExecTransformer (45) + : +- ^ GlutenBroadcastHashJoinExecTransformer Inner (44) + : :- ^ InputIteratorTransformer (25) + : : +- ^ InputAdapter (24) + : : +- ^ BroadcastQueryStage (23) + : : +- ColumnarBroadcastExchange (22) + : : +- ^ GlutenBroadcastHashJoinExecTransformer LeftSemi (20) + : : :- ^ FilterExecTransformer (11) + : : : +- ^ Scan parquet (10) + : : +- ^ InputIteratorTransformer (19) + : : +- ^ InputAdapter (18) + : : +- ^ BroadcastQueryStage (17) + : : +- ColumnarBroadcastExchange (16) + : : +- ^ ProjectExecTransformer (14) + : : +- ^ FilterExecTransformer (13) + : : +- ^ Scan parquet (12) + : +- ^ FilterExecTransformer (43) + : +- ^ ProjectExecTransformer (42) + : +- ^ RegularHashAggregateExecTransformer (41) + : +- ^ InputIteratorTransformer (40) + : +- ^ InputAdapter (39) + : +- ^ ShuffleQueryStage (38) + : +- ColumnarExchange (37) + : +- ^ ProjectExecTransformer (35) + : +- ^ FlushableHashAggregateExecTransformer (34) + : +- ^ GlutenBroadcastHashJoinExecTransformer LeftSemi (33) + : :- ^ ProjectExecTransformer (28) + : : +- ^ FilterExecTransformer (27) + : : +- ^ Scan parquet (26) + : +- ^ InputIteratorTransformer (32) + : +- ^ InputAdapter (31) + : +- ^ BroadcastQueryStage (30) + : +- ReusedExchange (29) + +- ^ InputIteratorTransformer (60) + +- ^ InputAdapter (59) + +- ^ BroadcastQueryStage (58) + +- ColumnarBroadcastExchange (57) + +- ^ ProjectExecTransformer (55) + +- ^ FilterExecTransformer (54) + +- ^ Scan parquet (53) ++- == Initial Plan == + Sort (106) + +- Exchange (105) + +- Project (104) + +- BroadcastHashJoin Inner BuildRight (103) + :- Project (98) + : +- ShuffledHashJoin LeftSemi BuildRight (97) + : :- Exchange (73) + : : +- Filter (72) + : : +- Scan parquet (71) + : +- Exchange (96) + : +- Project (95) + : +- BroadcastHashJoin Inner BuildLeft (94) + : :- BroadcastExchange (81) + : : +- BroadcastHashJoin LeftSemi BuildRight (80) + : : :- Filter (75) + : : : +- Scan parquet (74) + : : +- BroadcastExchange (79) + : : +- Project (78) + : : +- Filter (77) + : : +- Scan parquet (76) + : +- Filter (93) + : +- HashAggregate (92) + : +- Exchange (91) + : +- HashAggregate (90) + : +- BroadcastHashJoin LeftSemi BuildRight (89) + : :- Project (84) + : : +- Filter (83) + : : +- Scan parquet (82) + : +- BroadcastExchange (88) + : +- Project (87) + : +- Filter (86) + : +- Scan parquet (85) + +- BroadcastExchange (102) + +- Project (101) + +- Filter (100) + +- Scan parquet (99) + + +(1) Scan parquet +Output [4]: [s_suppkey#X, s_name#X, s_address#X, s_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(s_nationkey)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [4]: [s_suppkey#X, s_name#X, s_address#X, s_nationkey#X] +Arguments: isnotnull(s_nationkey#X) + +(3) ProjectExecTransformer +Output [5]: [hash(s_suppkey#X, 42) AS hash_partition_key#X, s_suppkey#X, s_name#X, s_address#X, s_nationkey#X] +Input [4]: [s_suppkey#X, s_name#X, s_address#X, s_nationkey#X] + +(4) WholeStageCodegenTransformer (X) +Input [5]: [hash_partition_key#X, s_suppkey#X, s_name#X, s_address#X, s_nationkey#X] +Arguments: false + +(5) ColumnarExchange +Input [5]: [hash_partition_key#X, s_suppkey#X, s_name#X, s_address#X, s_nationkey#X] +Arguments: hashpartitioning(s_suppkey#X, 1), ENSURE_REQUIREMENTS, [s_suppkey#X, s_name#X, s_address#X, s_nationkey#X], [plan_id=X], [id=#X] + +(6) ShuffleQueryStage +Output [4]: [s_suppkey#X, s_name#X, s_address#X, s_nationkey#X] +Arguments: X + +(7) AQEShuffleRead +Input [4]: [s_suppkey#X, s_name#X, s_address#X, s_nationkey#X] +Arguments: local + +(8) InputAdapter +Input [4]: [s_suppkey#X, s_name#X, s_address#X, s_nationkey#X] + +(9) InputIteratorTransformer +Input [4]: [s_suppkey#X, s_name#X, s_address#X, s_nationkey#X] + +(10) Scan parquet +Output [3]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(ps_availqty), IsNotNull(ps_partkey), IsNotNull(ps_suppkey)] +ReadSchema: struct + +(11) FilterExecTransformer +Input [3]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X] +Arguments: ((isnotnull(ps_availqty#X) AND isnotnull(ps_partkey#X)) AND isnotnull(ps_suppkey#X)) + +(12) Scan parquet +Output [2]: [p_partkey#X, p_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(p_name), StringStartsWith(p_name,forest)] +ReadSchema: struct + +(13) FilterExecTransformer +Input [2]: [p_partkey#X, p_name#X] +Arguments: (isnotnull(p_name#X) AND StartsWith(p_name#X, forest)) + +(14) ProjectExecTransformer +Output [1]: [p_partkey#X] +Input [2]: [p_partkey#X, p_name#X] + +(15) WholeStageCodegenTransformer (X) +Input [1]: [p_partkey#X] +Arguments: false + +(16) ColumnarBroadcastExchange +Input [1]: [p_partkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(17) BroadcastQueryStage +Output [1]: [p_partkey#X] +Arguments: X + +(18) InputAdapter +Input [1]: [p_partkey#X] + +(19) InputIteratorTransformer +Input [1]: [p_partkey#X] + +(20) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [ps_partkey#X] +Right keys [1]: [p_partkey#X] +Join condition: None + +(21) WholeStageCodegenTransformer (X) +Input [3]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X] +Arguments: false + +(22) ColumnarBroadcastExchange +Input [3]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false], input[1, bigint, false]),false), [plan_id=X] + +(23) BroadcastQueryStage +Output [3]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X] +Arguments: X + +(24) InputAdapter +Input [3]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X] + +(25) InputIteratorTransformer +Input [3]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X] + +(26) Scan parquet +Output [4]: [l_partkey#X, l_suppkey#X, l_quantity#X, l_shipdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_shipdate), GreaterThanOrEqual(l_shipdate,1994-01-01), LessThan(l_shipdate,1995-01-01), IsNotNull(l_partkey), IsNotNull(l_suppkey)] +ReadSchema: struct + +(27) FilterExecTransformer +Input [4]: [l_partkey#X, l_suppkey#X, l_quantity#X, l_shipdate#X] +Arguments: ((((isnotnull(l_shipdate#X) AND (l_shipdate#X >= 1994-01-01)) AND (l_shipdate#X < 1995-01-01)) AND isnotnull(l_partkey#X)) AND isnotnull(l_suppkey#X)) + +(28) ProjectExecTransformer +Output [3]: [l_partkey#X, l_suppkey#X, l_quantity#X] +Input [4]: [l_partkey#X, l_suppkey#X, l_quantity#X, l_shipdate#X] + +(29) ReusedExchange [Reuses operator id: 16] +Output [1]: [p_partkey#X] + +(30) BroadcastQueryStage +Output [1]: [p_partkey#X] +Arguments: X + +(31) InputAdapter +Input [1]: [p_partkey#X] + +(32) InputIteratorTransformer +Input [1]: [p_partkey#X] + +(33) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [l_partkey#X] +Right keys [1]: [p_partkey#X] +Join condition: None + +(34) FlushableHashAggregateExecTransformer +Input [3]: [l_partkey#X, l_suppkey#X, l_quantity#X] +Keys [2]: [l_partkey#X, l_suppkey#X] +Functions [1]: [partial_sum(l_quantity#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [4]: [l_partkey#X, l_suppkey#X, sum#X, isEmpty#X] + +(35) ProjectExecTransformer +Output [5]: [hash(l_partkey#X, l_suppkey#X, 42) AS hash_partition_key#X, l_partkey#X, l_suppkey#X, sum#X, isEmpty#X] +Input [4]: [l_partkey#X, l_suppkey#X, sum#X, isEmpty#X] + +(36) WholeStageCodegenTransformer (X) +Input [5]: [hash_partition_key#X, l_partkey#X, l_suppkey#X, sum#X, isEmpty#X] +Arguments: false + +(37) ColumnarExchange +Input [5]: [hash_partition_key#X, l_partkey#X, l_suppkey#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(l_partkey#X, l_suppkey#X, 1), ENSURE_REQUIREMENTS, [l_partkey#X, l_suppkey#X, sum#X, isEmpty#X], [plan_id=X], [id=#X] + +(38) ShuffleQueryStage +Output [4]: [l_partkey#X, l_suppkey#X, sum#X, isEmpty#X] +Arguments: X + +(39) InputAdapter +Input [4]: [l_partkey#X, l_suppkey#X, sum#X, isEmpty#X] + +(40) InputIteratorTransformer +Input [4]: [l_partkey#X, l_suppkey#X, sum#X, isEmpty#X] + +(41) RegularHashAggregateExecTransformer +Input [4]: [l_partkey#X, l_suppkey#X, sum#X, isEmpty#X] +Keys [2]: [l_partkey#X, l_suppkey#X] +Functions [1]: [sum(l_quantity#X)] +Aggregate Attributes [1]: [sum(l_quantity#X)#X] +Results [3]: [l_partkey#X, l_suppkey#X, sum(l_quantity#X)#X] + +(42) ProjectExecTransformer +Output [3]: [CheckOverflow((0.50 * promote_precision(sum(l_quantity#X)#X)), DecimalType(24,3), true) AS (0.5 * sum(l_quantity))#X, l_partkey#X, l_suppkey#X] +Input [3]: [l_partkey#X, l_suppkey#X, sum(l_quantity#X)#X] + +(43) FilterExecTransformer +Input [3]: [(0.5 * sum(l_quantity))#X, l_partkey#X, l_suppkey#X] +Arguments: isnotnull((0.5 * sum(l_quantity))#X) + +(44) GlutenBroadcastHashJoinExecTransformer +Left keys [2]: [ps_partkey#X, ps_suppkey#X] +Right keys [2]: [l_partkey#X, l_suppkey#X] +Join condition: (cast(cast(ps_availqty#X as decimal(10,0)) as decimal(24,3)) > (0.5 * sum(l_quantity))#X) + +(45) ProjectExecTransformer +Output [1]: [ps_suppkey#X] +Input [6]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X, (0.5 * sum(l_quantity))#X, l_partkey#X, l_suppkey#X] + +(46) WholeStageCodegenTransformer (X) +Input [1]: [ps_suppkey#X] +Arguments: false + +(47) ColumnarBroadcastExchange +Input [1]: [ps_suppkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(48) BroadcastQueryStage +Output [1]: [ps_suppkey#X] +Arguments: X + +(49) InputAdapter +Input [1]: [ps_suppkey#X] + +(50) InputIteratorTransformer +Input [1]: [ps_suppkey#X] + +(51) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [s_suppkey#X] +Right keys [1]: [ps_suppkey#X] +Join condition: None + +(52) ProjectExecTransformer +Output [3]: [s_name#X, s_address#X, s_nationkey#X] +Input [4]: [s_suppkey#X, s_name#X, s_address#X, s_nationkey#X] + +(53) Scan parquet +Output [2]: [n_nationkey#X, n_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_name), EqualTo(n_name,CANADA), IsNotNull(n_nationkey)] +ReadSchema: struct + +(54) FilterExecTransformer +Input [2]: [n_nationkey#X, n_name#X] +Arguments: ((isnotnull(n_name#X) AND (n_name#X = CANADA)) AND isnotnull(n_nationkey#X)) + +(55) ProjectExecTransformer +Output [1]: [n_nationkey#X] +Input [2]: [n_nationkey#X, n_name#X] + +(56) WholeStageCodegenTransformer (X) +Input [1]: [n_nationkey#X] +Arguments: false + +(57) ColumnarBroadcastExchange +Input [1]: [n_nationkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(58) BroadcastQueryStage +Output [1]: [n_nationkey#X] +Arguments: X + +(59) InputAdapter +Input [1]: [n_nationkey#X] + +(60) InputIteratorTransformer +Input [1]: [n_nationkey#X] + +(61) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [s_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: None + +(62) ProjectExecTransformer +Output [2]: [s_name#X, s_address#X] +Input [4]: [s_name#X, s_address#X, s_nationkey#X, n_nationkey#X] + +(63) WholeStageCodegenTransformer (X) +Input [2]: [s_name#X, s_address#X] +Arguments: false + +(64) ColumnarExchange +Input [2]: [s_name#X, s_address#X] +Arguments: rangepartitioning(s_name#X ASC NULLS FIRST, 1), ENSURE_REQUIREMENTS, [plan_id=X], [id=#X] + +(65) ShuffleQueryStage +Output [2]: [s_name#X, s_address#X] +Arguments: X + +(66) InputAdapter +Input [2]: [s_name#X, s_address#X] + +(67) InputIteratorTransformer +Input [2]: [s_name#X, s_address#X] + +(68) SortExecTransformer +Input [2]: [s_name#X, s_address#X] +Arguments: [s_name#X ASC NULLS FIRST], true, 0 + +(69) WholeStageCodegenTransformer (X) +Input [2]: [s_name#X, s_address#X] +Arguments: false + +(70) VeloxColumnarToRowExec +Input [2]: [s_name#X, s_address#X] + +(71) Scan parquet +Output [4]: [s_suppkey#X, s_name#X, s_address#X, s_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(s_nationkey)] +ReadSchema: struct + +(72) Filter +Input [4]: [s_suppkey#X, s_name#X, s_address#X, s_nationkey#X] +Condition : isnotnull(s_nationkey#X) + +(73) Exchange +Input [4]: [s_suppkey#X, s_name#X, s_address#X, s_nationkey#X] +Arguments: hashpartitioning(s_suppkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(74) Scan parquet +Output [3]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(ps_availqty), IsNotNull(ps_partkey), IsNotNull(ps_suppkey)] +ReadSchema: struct + +(75) Filter +Input [3]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X] +Condition : ((isnotnull(ps_availqty#X) AND isnotnull(ps_partkey#X)) AND isnotnull(ps_suppkey#X)) + +(76) Scan parquet +Output [2]: [p_partkey#X, p_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(p_name), StringStartsWith(p_name,forest)] +ReadSchema: struct + +(77) Filter +Input [2]: [p_partkey#X, p_name#X] +Condition : (isnotnull(p_name#X) AND StartsWith(p_name#X, forest)) + +(78) Project +Output [1]: [p_partkey#X] +Input [2]: [p_partkey#X, p_name#X] + +(79) BroadcastExchange +Input [1]: [p_partkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(80) BroadcastHashJoin +Left keys [1]: [ps_partkey#X] +Right keys [1]: [p_partkey#X] +Join condition: None + +(81) BroadcastExchange +Input [3]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false], input[1, bigint, false]),false), [plan_id=X] + +(82) Scan parquet +Output [4]: [l_partkey#X, l_suppkey#X, l_quantity#X, l_shipdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_shipdate), GreaterThanOrEqual(l_shipdate,1994-01-01), LessThan(l_shipdate,1995-01-01), IsNotNull(l_partkey), IsNotNull(l_suppkey)] +ReadSchema: struct + +(83) Filter +Input [4]: [l_partkey#X, l_suppkey#X, l_quantity#X, l_shipdate#X] +Condition : ((((isnotnull(l_shipdate#X) AND (l_shipdate#X >= 1994-01-01)) AND (l_shipdate#X < 1995-01-01)) AND isnotnull(l_partkey#X)) AND isnotnull(l_suppkey#X)) + +(84) Project +Output [3]: [l_partkey#X, l_suppkey#X, l_quantity#X] +Input [4]: [l_partkey#X, l_suppkey#X, l_quantity#X, l_shipdate#X] + +(85) Scan parquet +Output [2]: [p_partkey#X, p_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(p_name), StringStartsWith(p_name,forest)] +ReadSchema: struct + +(86) Filter +Input [2]: [p_partkey#X, p_name#X] +Condition : (isnotnull(p_name#X) AND StartsWith(p_name#X, forest)) + +(87) Project +Output [1]: [p_partkey#X] +Input [2]: [p_partkey#X, p_name#X] + +(88) BroadcastExchange +Input [1]: [p_partkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(89) BroadcastHashJoin +Left keys [1]: [l_partkey#X] +Right keys [1]: [p_partkey#X] +Join condition: None + +(90) HashAggregate +Input [3]: [l_partkey#X, l_suppkey#X, l_quantity#X] +Keys [2]: [l_partkey#X, l_suppkey#X] +Functions [1]: [partial_sum(l_quantity#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [4]: [l_partkey#X, l_suppkey#X, sum#X, isEmpty#X] + +(91) Exchange +Input [4]: [l_partkey#X, l_suppkey#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(l_partkey#X, l_suppkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(92) HashAggregate +Input [4]: [l_partkey#X, l_suppkey#X, sum#X, isEmpty#X] +Keys [2]: [l_partkey#X, l_suppkey#X] +Functions [1]: [sum(l_quantity#X)] +Aggregate Attributes [1]: [sum(l_quantity#X)#X] +Results [3]: [CheckOverflow((0.50 * promote_precision(sum(l_quantity#X)#X)), DecimalType(24,3), true) AS (0.5 * sum(l_quantity))#X, l_partkey#X, l_suppkey#X] + +(93) Filter +Input [3]: [(0.5 * sum(l_quantity))#X, l_partkey#X, l_suppkey#X] +Condition : isnotnull((0.5 * sum(l_quantity))#X) + +(94) BroadcastHashJoin +Left keys [2]: [ps_partkey#X, ps_suppkey#X] +Right keys [2]: [l_partkey#X, l_suppkey#X] +Join condition: (cast(cast(ps_availqty#X as decimal(10,0)) as decimal(24,3)) > (0.5 * sum(l_quantity))#X) + +(95) Project +Output [1]: [ps_suppkey#X] +Input [6]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X, (0.5 * sum(l_quantity))#X, l_partkey#X, l_suppkey#X] + +(96) Exchange +Input [1]: [ps_suppkey#X] +Arguments: hashpartitioning(ps_suppkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(97) ShuffledHashJoin +Left keys [1]: [s_suppkey#X] +Right keys [1]: [ps_suppkey#X] +Join condition: None + +(98) Project +Output [3]: [s_name#X, s_address#X, s_nationkey#X] +Input [4]: [s_suppkey#X, s_name#X, s_address#X, s_nationkey#X] + +(99) Scan parquet +Output [2]: [n_nationkey#X, n_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_name), EqualTo(n_name,CANADA), IsNotNull(n_nationkey)] +ReadSchema: struct + +(100) Filter +Input [2]: [n_nationkey#X, n_name#X] +Condition : ((isnotnull(n_name#X) AND (n_name#X = CANADA)) AND isnotnull(n_nationkey#X)) + +(101) Project +Output [1]: [n_nationkey#X] +Input [2]: [n_nationkey#X, n_name#X] + +(102) BroadcastExchange +Input [1]: [n_nationkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(103) BroadcastHashJoin +Left keys [1]: [s_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: None + +(104) Project +Output [2]: [s_name#X, s_address#X] +Input [4]: [s_name#X, s_address#X, s_nationkey#X, n_nationkey#X] + +(105) Exchange +Input [2]: [s_name#X, s_address#X] +Arguments: rangepartitioning(s_name#X ASC NULLS FIRST, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(106) Sort +Input [2]: [s_name#X, s_address#X] +Arguments: [s_name#X ASC NULLS FIRST], true, 0 + +(107) AdaptiveSparkPlan +Output [2]: [s_name#X, s_address#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/21.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/21.txt new file mode 100644 index 000000000000..cd3cbef62819 --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/21.txt @@ -0,0 +1,500 @@ +== Physical Plan == +AdaptiveSparkPlan (92) ++- == Final Plan == + VeloxColumnarToRowExec (59) + +- TakeOrderedAndProjectExecTransformer (58) + +- ^ RegularHashAggregateExecTransformer (56) + +- ^ InputIteratorTransformer (55) + +- ^ InputAdapter (54) + +- ^ ShuffleQueryStage (53) + +- ColumnarExchange (52) + +- ^ ProjectExecTransformer (50) + +- ^ FlushableHashAggregateExecTransformer (49) + +- ^ ProjectExecTransformer (48) + +- ^ GlutenBroadcastHashJoinExecTransformer Inner (47) + :- ^ ProjectExecTransformer (38) + : +- ^ GlutenBroadcastHashJoinExecTransformer Inner (37) + : :- ^ ProjectExecTransformer (28) + : : +- ^ GlutenBroadcastHashJoinExecTransformer Inner (27) + : : :- ^ InputIteratorTransformer (7) + : : : +- ^ InputAdapter (6) + : : : +- ^ BroadcastQueryStage (5) + : : : +- ColumnarBroadcastExchange (4) + : : : +- ^ FilterExecTransformer (2) + : : : +- ^ Scan parquet (1) + : : +- ^ GlutenBroadcastHashJoinExecTransformer LeftAnti (26) + : : :- ^ GlutenBroadcastHashJoinExecTransformer LeftSemi (17) + : : : :- ^ ProjectExecTransformer (10) + : : : : +- ^ FilterExecTransformer (9) + : : : : +- ^ Scan parquet (8) + : : : +- ^ InputIteratorTransformer (16) + : : : +- ^ InputAdapter (15) + : : : +- ^ BroadcastQueryStage (14) + : : : +- ColumnarBroadcastExchange (13) + : : : +- ^ Scan parquet (11) + : : +- ^ InputIteratorTransformer (25) + : : +- ^ InputAdapter (24) + : : +- ^ BroadcastQueryStage (23) + : : +- ColumnarBroadcastExchange (22) + : : +- ^ ProjectExecTransformer (20) + : : +- ^ FilterExecTransformer (19) + : : +- ^ Scan parquet (18) + : +- ^ InputIteratorTransformer (36) + : +- ^ InputAdapter (35) + : +- ^ BroadcastQueryStage (34) + : +- ColumnarBroadcastExchange (33) + : +- ^ ProjectExecTransformer (31) + : +- ^ FilterExecTransformer (30) + : +- ^ Scan parquet (29) + +- ^ InputIteratorTransformer (46) + +- ^ InputAdapter (45) + +- ^ BroadcastQueryStage (44) + +- ColumnarBroadcastExchange (43) + +- ^ ProjectExecTransformer (41) + +- ^ FilterExecTransformer (40) + +- ^ Scan parquet (39) ++- == Initial Plan == + TakeOrderedAndProject (91) + +- HashAggregate (90) + +- Exchange (89) + +- HashAggregate (88) + +- Project (87) + +- BroadcastHashJoin Inner BuildRight (86) + :- Project (81) + : +- BroadcastHashJoin Inner BuildRight (80) + : :- Project (75) + : : +- BroadcastHashJoin Inner BuildLeft (74) + : : :- BroadcastExchange (62) + : : : +- Filter (61) + : : : +- Scan parquet (60) + : : +- BroadcastHashJoin LeftAnti BuildRight (73) + : : :- BroadcastHashJoin LeftSemi BuildRight (68) + : : : :- Project (65) + : : : : +- Filter (64) + : : : : +- Scan parquet (63) + : : : +- BroadcastExchange (67) + : : : +- Scan parquet (66) + : : +- BroadcastExchange (72) + : : +- Project (71) + : : +- Filter (70) + : : +- Scan parquet (69) + : +- BroadcastExchange (79) + : +- Project (78) + : +- Filter (77) + : +- Scan parquet (76) + +- BroadcastExchange (85) + +- Project (84) + +- Filter (83) + +- Scan parquet (82) + + +(1) Scan parquet +Output [3]: [s_suppkey#X, s_name#X, s_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(s_suppkey), IsNotNull(s_nationkey)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [3]: [s_suppkey#X, s_name#X, s_nationkey#X] +Arguments: (isnotnull(s_suppkey#X) AND isnotnull(s_nationkey#X)) + +(3) WholeStageCodegenTransformer (X) +Input [3]: [s_suppkey#X, s_name#X, s_nationkey#X] +Arguments: false + +(4) ColumnarBroadcastExchange +Input [3]: [s_suppkey#X, s_name#X, s_nationkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(5) BroadcastQueryStage +Output [3]: [s_suppkey#X, s_name#X, s_nationkey#X] +Arguments: X + +(6) InputAdapter +Input [3]: [s_suppkey#X, s_name#X, s_nationkey#X] + +(7) InputIteratorTransformer +Input [3]: [s_suppkey#X, s_name#X, s_nationkey#X] + +(8) Scan parquet +Output [4]: [l_orderkey#X, l_suppkey#X, l_commitdate#X, l_receiptdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_receiptdate), IsNotNull(l_commitdate), IsNotNull(l_suppkey), IsNotNull(l_orderkey)] +ReadSchema: struct + +(9) FilterExecTransformer +Input [4]: [l_orderkey#X, l_suppkey#X, l_commitdate#X, l_receiptdate#X] +Arguments: ((((isnotnull(l_receiptdate#X) AND isnotnull(l_commitdate#X)) AND (l_receiptdate#X > l_commitdate#X)) AND isnotnull(l_suppkey#X)) AND isnotnull(l_orderkey#X)) + +(10) ProjectExecTransformer +Output [2]: [l_orderkey#X, l_suppkey#X] +Input [4]: [l_orderkey#X, l_suppkey#X, l_commitdate#X, l_receiptdate#X] + +(11) Scan parquet +Output [2]: [l_orderkey#X, l_suppkey#X] +Batched: true +Location: InMemoryFileIndex [*] +ReadSchema: struct + +(12) WholeStageCodegenTransformer (X) +Input [2]: [l_orderkey#X, l_suppkey#X] +Arguments: false + +(13) ColumnarBroadcastExchange +Input [2]: [l_orderkey#X, l_suppkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(14) BroadcastQueryStage +Output [2]: [l_orderkey#X, l_suppkey#X] +Arguments: X + +(15) InputAdapter +Input [2]: [l_orderkey#X, l_suppkey#X] + +(16) InputIteratorTransformer +Input [2]: [l_orderkey#X, l_suppkey#X] + +(17) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [l_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: NOT (l_suppkey#X = l_suppkey#X) + +(18) Scan parquet +Output [4]: [l_orderkey#X, l_suppkey#X, l_commitdate#X, l_receiptdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_receiptdate), IsNotNull(l_commitdate)] +ReadSchema: struct + +(19) FilterExecTransformer +Input [4]: [l_orderkey#X, l_suppkey#X, l_commitdate#X, l_receiptdate#X] +Arguments: ((isnotnull(l_receiptdate#X) AND isnotnull(l_commitdate#X)) AND (l_receiptdate#X > l_commitdate#X)) + +(20) ProjectExecTransformer +Output [2]: [l_orderkey#X, l_suppkey#X] +Input [4]: [l_orderkey#X, l_suppkey#X, l_commitdate#X, l_receiptdate#X] + +(21) WholeStageCodegenTransformer (X) +Input [2]: [l_orderkey#X, l_suppkey#X] +Arguments: false + +(22) ColumnarBroadcastExchange +Input [2]: [l_orderkey#X, l_suppkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(23) BroadcastQueryStage +Output [2]: [l_orderkey#X, l_suppkey#X] +Arguments: X + +(24) InputAdapter +Input [2]: [l_orderkey#X, l_suppkey#X] + +(25) InputIteratorTransformer +Input [2]: [l_orderkey#X, l_suppkey#X] + +(26) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [l_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: NOT (l_suppkey#X = l_suppkey#X) + +(27) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [s_suppkey#X] +Right keys [1]: [l_suppkey#X] +Join condition: None + +(28) ProjectExecTransformer +Output [3]: [s_name#X, s_nationkey#X, l_orderkey#X] +Input [5]: [s_suppkey#X, s_name#X, s_nationkey#X, l_orderkey#X, l_suppkey#X] + +(29) Scan parquet +Output [2]: [o_orderkey#X, o_orderstatus#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_orderstatus), EqualTo(o_orderstatus,F), IsNotNull(o_orderkey)] +ReadSchema: struct + +(30) FilterExecTransformer +Input [2]: [o_orderkey#X, o_orderstatus#X] +Arguments: ((isnotnull(o_orderstatus#X) AND (o_orderstatus#X = F)) AND isnotnull(o_orderkey#X)) + +(31) ProjectExecTransformer +Output [1]: [o_orderkey#X] +Input [2]: [o_orderkey#X, o_orderstatus#X] + +(32) WholeStageCodegenTransformer (X) +Input [1]: [o_orderkey#X] +Arguments: false + +(33) ColumnarBroadcastExchange +Input [1]: [o_orderkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(34) BroadcastQueryStage +Output [1]: [o_orderkey#X] +Arguments: X + +(35) InputAdapter +Input [1]: [o_orderkey#X] + +(36) InputIteratorTransformer +Input [1]: [o_orderkey#X] + +(37) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [l_orderkey#X] +Right keys [1]: [o_orderkey#X] +Join condition: None + +(38) ProjectExecTransformer +Output [2]: [s_name#X, s_nationkey#X] +Input [4]: [s_name#X, s_nationkey#X, l_orderkey#X, o_orderkey#X] + +(39) Scan parquet +Output [2]: [n_nationkey#X, n_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_name), EqualTo(n_name,SAUDI ARABIA), IsNotNull(n_nationkey)] +ReadSchema: struct + +(40) FilterExecTransformer +Input [2]: [n_nationkey#X, n_name#X] +Arguments: ((isnotnull(n_name#X) AND (n_name#X = SAUDI ARABIA)) AND isnotnull(n_nationkey#X)) + +(41) ProjectExecTransformer +Output [1]: [n_nationkey#X] +Input [2]: [n_nationkey#X, n_name#X] + +(42) WholeStageCodegenTransformer (X) +Input [1]: [n_nationkey#X] +Arguments: false + +(43) ColumnarBroadcastExchange +Input [1]: [n_nationkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(44) BroadcastQueryStage +Output [1]: [n_nationkey#X] +Arguments: X + +(45) InputAdapter +Input [1]: [n_nationkey#X] + +(46) InputIteratorTransformer +Input [1]: [n_nationkey#X] + +(47) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [s_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: None + +(48) ProjectExecTransformer +Output [1]: [s_name#X] +Input [3]: [s_name#X, s_nationkey#X, n_nationkey#X] + +(49) FlushableHashAggregateExecTransformer +Input [1]: [s_name#X] +Keys [1]: [s_name#X] +Functions [1]: [partial_count(1)] +Aggregate Attributes [1]: [count#X] +Results [2]: [s_name#X, count#X] + +(50) ProjectExecTransformer +Output [3]: [hash(s_name#X, 42) AS hash_partition_key#X, s_name#X, count#X] +Input [2]: [s_name#X, count#X] + +(51) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, s_name#X, count#X] +Arguments: false + +(52) ColumnarExchange +Input [3]: [hash_partition_key#X, s_name#X, count#X] +Arguments: hashpartitioning(s_name#X, 1), ENSURE_REQUIREMENTS, [s_name#X, count#X], [plan_id=X], [id=#X] + +(53) ShuffleQueryStage +Output [2]: [s_name#X, count#X] +Arguments: X + +(54) InputAdapter +Input [2]: [s_name#X, count#X] + +(55) InputIteratorTransformer +Input [2]: [s_name#X, count#X] + +(56) RegularHashAggregateExecTransformer +Input [2]: [s_name#X, count#X] +Keys [1]: [s_name#X] +Functions [1]: [count(1)] +Aggregate Attributes [1]: [count(1)#X] +Results [2]: [s_name#X, count(1)#X AS numwait#X] + +(57) WholeStageCodegenTransformer (X) +Input [2]: [s_name#X, numwait#X] +Arguments: false + +(58) TakeOrderedAndProjectExecTransformer +Input [2]: [s_name#X, numwait#X] +Arguments: X, [numwait#X DESC NULLS LAST, s_name#X ASC NULLS FIRST], [s_name#X, numwait#X], 0 + +(59) VeloxColumnarToRowExec +Input [2]: [s_name#X, numwait#X] + +(60) Scan parquet +Output [3]: [s_suppkey#X, s_name#X, s_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(s_suppkey), IsNotNull(s_nationkey)] +ReadSchema: struct + +(61) Filter +Input [3]: [s_suppkey#X, s_name#X, s_nationkey#X] +Condition : (isnotnull(s_suppkey#X) AND isnotnull(s_nationkey#X)) + +(62) BroadcastExchange +Input [3]: [s_suppkey#X, s_name#X, s_nationkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(63) Scan parquet +Output [4]: [l_orderkey#X, l_suppkey#X, l_commitdate#X, l_receiptdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_receiptdate), IsNotNull(l_commitdate), IsNotNull(l_suppkey), IsNotNull(l_orderkey)] +ReadSchema: struct + +(64) Filter +Input [4]: [l_orderkey#X, l_suppkey#X, l_commitdate#X, l_receiptdate#X] +Condition : ((((isnotnull(l_receiptdate#X) AND isnotnull(l_commitdate#X)) AND (l_receiptdate#X > l_commitdate#X)) AND isnotnull(l_suppkey#X)) AND isnotnull(l_orderkey#X)) + +(65) Project +Output [2]: [l_orderkey#X, l_suppkey#X] +Input [4]: [l_orderkey#X, l_suppkey#X, l_commitdate#X, l_receiptdate#X] + +(66) Scan parquet +Output [2]: [l_orderkey#X, l_suppkey#X] +Batched: true +Location: InMemoryFileIndex [*] +ReadSchema: struct + +(67) BroadcastExchange +Input [2]: [l_orderkey#X, l_suppkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(68) BroadcastHashJoin +Left keys [1]: [l_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: NOT (l_suppkey#X = l_suppkey#X) + +(69) Scan parquet +Output [4]: [l_orderkey#X, l_suppkey#X, l_commitdate#X, l_receiptdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_receiptdate), IsNotNull(l_commitdate)] +ReadSchema: struct + +(70) Filter +Input [4]: [l_orderkey#X, l_suppkey#X, l_commitdate#X, l_receiptdate#X] +Condition : ((isnotnull(l_receiptdate#X) AND isnotnull(l_commitdate#X)) AND (l_receiptdate#X > l_commitdate#X)) + +(71) Project +Output [2]: [l_orderkey#X, l_suppkey#X] +Input [4]: [l_orderkey#X, l_suppkey#X, l_commitdate#X, l_receiptdate#X] + +(72) BroadcastExchange +Input [2]: [l_orderkey#X, l_suppkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(73) BroadcastHashJoin +Left keys [1]: [l_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: NOT (l_suppkey#X = l_suppkey#X) + +(74) BroadcastHashJoin +Left keys [1]: [s_suppkey#X] +Right keys [1]: [l_suppkey#X] +Join condition: None + +(75) Project +Output [3]: [s_name#X, s_nationkey#X, l_orderkey#X] +Input [5]: [s_suppkey#X, s_name#X, s_nationkey#X, l_orderkey#X, l_suppkey#X] + +(76) Scan parquet +Output [2]: [o_orderkey#X, o_orderstatus#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_orderstatus), EqualTo(o_orderstatus,F), IsNotNull(o_orderkey)] +ReadSchema: struct + +(77) Filter +Input [2]: [o_orderkey#X, o_orderstatus#X] +Condition : ((isnotnull(o_orderstatus#X) AND (o_orderstatus#X = F)) AND isnotnull(o_orderkey#X)) + +(78) Project +Output [1]: [o_orderkey#X] +Input [2]: [o_orderkey#X, o_orderstatus#X] + +(79) BroadcastExchange +Input [1]: [o_orderkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(80) BroadcastHashJoin +Left keys [1]: [l_orderkey#X] +Right keys [1]: [o_orderkey#X] +Join condition: None + +(81) Project +Output [2]: [s_name#X, s_nationkey#X] +Input [4]: [s_name#X, s_nationkey#X, l_orderkey#X, o_orderkey#X] + +(82) Scan parquet +Output [2]: [n_nationkey#X, n_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_name), EqualTo(n_name,SAUDI ARABIA), IsNotNull(n_nationkey)] +ReadSchema: struct + +(83) Filter +Input [2]: [n_nationkey#X, n_name#X] +Condition : ((isnotnull(n_name#X) AND (n_name#X = SAUDI ARABIA)) AND isnotnull(n_nationkey#X)) + +(84) Project +Output [1]: [n_nationkey#X] +Input [2]: [n_nationkey#X, n_name#X] + +(85) BroadcastExchange +Input [1]: [n_nationkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(86) BroadcastHashJoin +Left keys [1]: [s_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: None + +(87) Project +Output [1]: [s_name#X] +Input [3]: [s_name#X, s_nationkey#X, n_nationkey#X] + +(88) HashAggregate +Input [1]: [s_name#X] +Keys [1]: [s_name#X] +Functions [1]: [partial_count(1)] +Aggregate Attributes [1]: [count#X] +Results [2]: [s_name#X, count#X] + +(89) Exchange +Input [2]: [s_name#X, count#X] +Arguments: hashpartitioning(s_name#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(90) HashAggregate +Input [2]: [s_name#X, count#X] +Keys [1]: [s_name#X] +Functions [1]: [count(1)] +Aggregate Attributes [1]: [count(1)#X] +Results [2]: [s_name#X, count(1)#X AS numwait#X] + +(91) TakeOrderedAndProject +Input [2]: [s_name#X, numwait#X] +Arguments: X, [numwait#X DESC NULLS LAST, s_name#X ASC NULLS FIRST], [s_name#X, numwait#X] + +(92) AdaptiveSparkPlan +Output [2]: [s_name#X, numwait#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/22.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/22.txt new file mode 100644 index 000000000000..90409e13e7f4 --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/22.txt @@ -0,0 +1,207 @@ +== Physical Plan == +AdaptiveSparkPlan (38) ++- == Final Plan == + VeloxColumnarToRowExec (26) + +- ^ SortExecTransformer (24) + +- ^ InputIteratorTransformer (23) + +- ^ InputAdapter (22) + +- ^ ShuffleQueryStage (21) + +- ColumnarExchange (20) + +- ^ RegularHashAggregateExecTransformer (18) + +- ^ InputIteratorTransformer (17) + +- ^ InputAdapter (16) + +- ^ ShuffleQueryStage (15) + +- ColumnarExchange (14) + +- ^ ProjectExecTransformer (12) + +- ^ FlushableHashAggregateExecTransformer (11) + +- ^ ProjectExecTransformer (10) + +- ^ GlutenBroadcastHashJoinExecTransformer LeftAnti (9) + :- ^ FilterExecTransformer (2) + : +- ^ Scan parquet (1) + +- ^ InputIteratorTransformer (8) + +- ^ InputAdapter (7) + +- ^ BroadcastQueryStage (6) + +- ColumnarBroadcastExchange (5) + +- ^ Scan parquet (3) ++- == Initial Plan == + Sort (37) + +- Exchange (36) + +- HashAggregate (35) + +- Exchange (34) + +- HashAggregate (33) + +- Project (32) + +- BroadcastHashJoin LeftAnti BuildRight (31) + :- Filter (28) + : +- Scan parquet (27) + +- BroadcastExchange (30) + +- Scan parquet (29) + + +(1) Scan parquet +Output [3]: [c_custkey#X, c_phone#X, c_acctbal#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(c_acctbal)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [3]: [c_custkey#X, c_phone#X, c_acctbal#X] +Arguments: ((isnotnull(c_acctbal#X) AND substring(c_phone#X, 1, 2) IN (13,31,23,29,30,18,17)) AND (cast(c_acctbal#X as decimal(16,6)) > Subquery subquery#X, [id=#X])) + +(3) Scan parquet +Output [1]: [o_custkey#X] +Batched: true +Location: InMemoryFileIndex [*] +ReadSchema: struct + +(4) WholeStageCodegenTransformer (X) +Input [1]: [o_custkey#X] +Arguments: false + +(5) ColumnarBroadcastExchange +Input [1]: [o_custkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(6) BroadcastQueryStage +Output [1]: [o_custkey#X] +Arguments: X + +(7) InputAdapter +Input [1]: [o_custkey#X] + +(8) InputIteratorTransformer +Input [1]: [o_custkey#X] + +(9) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [c_custkey#X] +Right keys [1]: [o_custkey#X] +Join condition: None + +(10) ProjectExecTransformer +Output [2]: [substring(c_phone#X, 1, 2) AS cntrycode#X, c_acctbal#X] +Input [3]: [c_custkey#X, c_phone#X, c_acctbal#X] + +(11) FlushableHashAggregateExecTransformer +Input [2]: [cntrycode#X, c_acctbal#X] +Keys [1]: [cntrycode#X] +Functions [2]: [partial_count(1), partial_sum(c_acctbal#X)] +Aggregate Attributes [3]: [count#X, sum#X, isEmpty#X] +Results [4]: [cntrycode#X, count#X, sum#X, isEmpty#X] + +(12) ProjectExecTransformer +Output [5]: [hash(cntrycode#X, 42) AS hash_partition_key#X, cntrycode#X, count#X, sum#X, isEmpty#X] +Input [4]: [cntrycode#X, count#X, sum#X, isEmpty#X] + +(13) WholeStageCodegenTransformer (X) +Input [5]: [hash_partition_key#X, cntrycode#X, count#X, sum#X, isEmpty#X] +Arguments: false + +(14) ColumnarExchange +Input [5]: [hash_partition_key#X, cntrycode#X, count#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(cntrycode#X, 1), ENSURE_REQUIREMENTS, [cntrycode#X, count#X, sum#X, isEmpty#X], [plan_id=X], [id=#X] + +(15) ShuffleQueryStage +Output [4]: [cntrycode#X, count#X, sum#X, isEmpty#X] +Arguments: X + +(16) InputAdapter +Input [4]: [cntrycode#X, count#X, sum#X, isEmpty#X] + +(17) InputIteratorTransformer +Input [4]: [cntrycode#X, count#X, sum#X, isEmpty#X] + +(18) RegularHashAggregateExecTransformer +Input [4]: [cntrycode#X, count#X, sum#X, isEmpty#X] +Keys [1]: [cntrycode#X] +Functions [2]: [count(1), sum(c_acctbal#X)] +Aggregate Attributes [2]: [count(1)#X, sum(c_acctbal#X)#X] +Results [3]: [cntrycode#X, count(1)#X AS numcust#X, sum(c_acctbal#X)#X AS totacctbal#X] + +(19) WholeStageCodegenTransformer (X) +Input [3]: [cntrycode#X, numcust#X, totacctbal#X] +Arguments: false + +(20) ColumnarExchange +Input [3]: [cntrycode#X, numcust#X, totacctbal#X] +Arguments: rangepartitioning(cntrycode#X ASC NULLS FIRST, 1), ENSURE_REQUIREMENTS, [plan_id=X], [id=#X] + +(21) ShuffleQueryStage +Output [3]: [cntrycode#X, numcust#X, totacctbal#X] +Arguments: X + +(22) InputAdapter +Input [3]: [cntrycode#X, numcust#X, totacctbal#X] + +(23) InputIteratorTransformer +Input [3]: [cntrycode#X, numcust#X, totacctbal#X] + +(24) SortExecTransformer +Input [3]: [cntrycode#X, numcust#X, totacctbal#X] +Arguments: [cntrycode#X ASC NULLS FIRST], true, 0 + +(25) WholeStageCodegenTransformer (X) +Input [3]: [cntrycode#X, numcust#X, totacctbal#X] +Arguments: false + +(26) VeloxColumnarToRowExec +Input [3]: [cntrycode#X, numcust#X, totacctbal#X] + +(27) Scan parquet +Output [3]: [c_custkey#X, c_phone#X, c_acctbal#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(c_acctbal)] +ReadSchema: struct + +(28) Filter +Input [3]: [c_custkey#X, c_phone#X, c_acctbal#X] +Condition : ((isnotnull(c_acctbal#X) AND substring(c_phone#X, 1, 2) IN (13,31,23,29,30,18,17)) AND (cast(c_acctbal#X as decimal(16,6)) > Subquery subquery#X, [id=#X])) + +(29) Scan parquet +Output [1]: [o_custkey#X] +Batched: true +Location: InMemoryFileIndex [*] +ReadSchema: struct + +(30) BroadcastExchange +Input [1]: [o_custkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(31) BroadcastHashJoin +Left keys [1]: [c_custkey#X] +Right keys [1]: [o_custkey#X] +Join condition: None + +(32) Project +Output [2]: [substring(c_phone#X, 1, 2) AS cntrycode#X, c_acctbal#X] +Input [3]: [c_custkey#X, c_phone#X, c_acctbal#X] + +(33) HashAggregate +Input [2]: [cntrycode#X, c_acctbal#X] +Keys [1]: [cntrycode#X] +Functions [2]: [partial_count(1), partial_sum(c_acctbal#X)] +Aggregate Attributes [3]: [count#X, sum#X, isEmpty#X] +Results [4]: [cntrycode#X, count#X, sum#X, isEmpty#X] + +(34) Exchange +Input [4]: [cntrycode#X, count#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(cntrycode#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(35) HashAggregate +Input [4]: [cntrycode#X, count#X, sum#X, isEmpty#X] +Keys [1]: [cntrycode#X] +Functions [2]: [count(1), sum(c_acctbal#X)] +Aggregate Attributes [2]: [count(1)#X, sum(c_acctbal#X)#X] +Results [3]: [cntrycode#X, count(1)#X AS numcust#X, sum(c_acctbal#X)#X AS totacctbal#X] + +(36) Exchange +Input [3]: [cntrycode#X, numcust#X, totacctbal#X] +Arguments: rangepartitioning(cntrycode#X ASC NULLS FIRST, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(37) Sort +Input [3]: [cntrycode#X, numcust#X, totacctbal#X] +Arguments: [cntrycode#X ASC NULLS FIRST], true, 0 + +(38) AdaptiveSparkPlan +Output [3]: [cntrycode#X, numcust#X, totacctbal#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/3.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/3.txt new file mode 100644 index 000000000000..8c606b32e2ff --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/3.txt @@ -0,0 +1,292 @@ +== Physical Plan == +AdaptiveSparkPlan (53) ++- == Final Plan == + VeloxColumnarToRowExec (34) + +- TakeOrderedAndProjectExecTransformer (33) + +- ^ ProjectExecTransformer (31) + +- ^ RegularHashAggregateExecTransformer (30) + +- ^ InputIteratorTransformer (29) + +- ^ InputAdapter (28) + +- ^ ShuffleQueryStage (27) + +- ColumnarExchange (26) + +- ^ ProjectExecTransformer (24) + +- ^ FlushableHashAggregateExecTransformer (23) + +- ^ ProjectExecTransformer (22) + +- ^ GlutenBroadcastHashJoinExecTransformer Inner (21) + :- ^ ProjectExecTransformer (12) + : +- ^ GlutenBroadcastHashJoinExecTransformer Inner (11) + : :- ^ InputIteratorTransformer (8) + : : +- ^ InputAdapter (7) + : : +- ^ BroadcastQueryStage (6) + : : +- ColumnarBroadcastExchange (5) + : : +- ^ ProjectExecTransformer (3) + : : +- ^ FilterExecTransformer (2) + : : +- ^ Scan parquet (1) + : +- ^ FilterExecTransformer (10) + : +- ^ Scan parquet (9) + +- ^ InputIteratorTransformer (20) + +- ^ InputAdapter (19) + +- ^ BroadcastQueryStage (18) + +- ColumnarBroadcastExchange (17) + +- ^ ProjectExecTransformer (15) + +- ^ FilterExecTransformer (14) + +- ^ Scan parquet (13) ++- == Initial Plan == + TakeOrderedAndProject (52) + +- HashAggregate (51) + +- Exchange (50) + +- HashAggregate (49) + +- Project (48) + +- BroadcastHashJoin Inner BuildRight (47) + :- Project (42) + : +- BroadcastHashJoin Inner BuildLeft (41) + : :- BroadcastExchange (38) + : : +- Project (37) + : : +- Filter (36) + : : +- Scan parquet (35) + : +- Filter (40) + : +- Scan parquet (39) + +- BroadcastExchange (46) + +- Project (45) + +- Filter (44) + +- Scan parquet (43) + + +(1) Scan parquet +Output [2]: [c_custkey#X, c_mktsegment#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(c_mktsegment), EqualTo(c_mktsegment,BUILDING), IsNotNull(c_custkey)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [2]: [c_custkey#X, c_mktsegment#X] +Arguments: ((isnotnull(c_mktsegment#X) AND (c_mktsegment#X = BUILDING)) AND isnotnull(c_custkey#X)) + +(3) ProjectExecTransformer +Output [1]: [c_custkey#X] +Input [2]: [c_custkey#X, c_mktsegment#X] + +(4) WholeStageCodegenTransformer (X) +Input [1]: [c_custkey#X] +Arguments: false + +(5) ColumnarBroadcastExchange +Input [1]: [c_custkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(6) BroadcastQueryStage +Output [1]: [c_custkey#X] +Arguments: X + +(7) InputAdapter +Input [1]: [c_custkey#X] + +(8) InputIteratorTransformer +Input [1]: [c_custkey#X] + +(9) Scan parquet +Output [4]: [o_orderkey#X, o_custkey#X, o_orderdate#X, o_shippriority#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_orderdate), LessThan(o_orderdate,1995-03-15), IsNotNull(o_custkey), IsNotNull(o_orderkey)] +ReadSchema: struct + +(10) FilterExecTransformer +Input [4]: [o_orderkey#X, o_custkey#X, o_orderdate#X, o_shippriority#X] +Arguments: (((isnotnull(o_orderdate#X) AND (o_orderdate#X < 1995-03-15)) AND isnotnull(o_custkey#X)) AND isnotnull(o_orderkey#X)) + +(11) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [c_custkey#X] +Right keys [1]: [o_custkey#X] +Join condition: None + +(12) ProjectExecTransformer +Output [3]: [o_orderkey#X, o_orderdate#X, o_shippriority#X] +Input [5]: [c_custkey#X, o_orderkey#X, o_custkey#X, o_orderdate#X, o_shippriority#X] + +(13) Scan parquet +Output [4]: [l_orderkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_shipdate), GreaterThan(l_shipdate,1995-03-15), IsNotNull(l_orderkey)] +ReadSchema: struct + +(14) FilterExecTransformer +Input [4]: [l_orderkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Arguments: ((isnotnull(l_shipdate#X) AND (l_shipdate#X > 1995-03-15)) AND isnotnull(l_orderkey#X)) + +(15) ProjectExecTransformer +Output [3]: [l_orderkey#X, l_extendedprice#X, l_discount#X] +Input [4]: [l_orderkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] + +(16) WholeStageCodegenTransformer (X) +Input [3]: [l_orderkey#X, l_extendedprice#X, l_discount#X] +Arguments: false + +(17) ColumnarBroadcastExchange +Input [3]: [l_orderkey#X, l_extendedprice#X, l_discount#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(18) BroadcastQueryStage +Output [3]: [l_orderkey#X, l_extendedprice#X, l_discount#X] +Arguments: X + +(19) InputAdapter +Input [3]: [l_orderkey#X, l_extendedprice#X, l_discount#X] + +(20) InputIteratorTransformer +Input [3]: [l_orderkey#X, l_extendedprice#X, l_discount#X] + +(21) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [o_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: None + +(22) ProjectExecTransformer +Output [6]: [o_orderdate#X, o_shippriority#X, l_orderkey#X, l_extendedprice#X, l_discount#X, CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) AS _pre_126#X] +Input [6]: [o_orderkey#X, o_orderdate#X, o_shippriority#X, l_orderkey#X, l_extendedprice#X, l_discount#X] + +(23) FlushableHashAggregateExecTransformer +Input [6]: [o_orderdate#X, o_shippriority#X, l_orderkey#X, l_extendedprice#X, l_discount#X, _pre_126#X] +Keys [3]: [l_orderkey#X, o_orderdate#X, o_shippriority#X] +Functions [1]: [partial_sum(_pre_126#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [5]: [l_orderkey#X, o_orderdate#X, o_shippriority#X, sum#X, isEmpty#X] + +(24) ProjectExecTransformer +Output [6]: [hash(l_orderkey#X, o_orderdate#X, o_shippriority#X, 42) AS hash_partition_key#X, l_orderkey#X, o_orderdate#X, o_shippriority#X, sum#X, isEmpty#X] +Input [5]: [l_orderkey#X, o_orderdate#X, o_shippriority#X, sum#X, isEmpty#X] + +(25) WholeStageCodegenTransformer (X) +Input [6]: [hash_partition_key#X, l_orderkey#X, o_orderdate#X, o_shippriority#X, sum#X, isEmpty#X] +Arguments: false + +(26) ColumnarExchange +Input [6]: [hash_partition_key#X, l_orderkey#X, o_orderdate#X, o_shippriority#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(l_orderkey#X, o_orderdate#X, o_shippriority#X, 1), ENSURE_REQUIREMENTS, [l_orderkey#X, o_orderdate#X, o_shippriority#X, sum#X, isEmpty#X], [plan_id=X], [id=#X] + +(27) ShuffleQueryStage +Output [5]: [l_orderkey#X, o_orderdate#X, o_shippriority#X, sum#X, isEmpty#X] +Arguments: X + +(28) InputAdapter +Input [5]: [l_orderkey#X, o_orderdate#X, o_shippriority#X, sum#X, isEmpty#X] + +(29) InputIteratorTransformer +Input [5]: [l_orderkey#X, o_orderdate#X, o_shippriority#X, sum#X, isEmpty#X] + +(30) RegularHashAggregateExecTransformer +Input [5]: [l_orderkey#X, o_orderdate#X, o_shippriority#X, sum#X, isEmpty#X] +Keys [3]: [l_orderkey#X, o_orderdate#X, o_shippriority#X] +Functions [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))] +Aggregate Attributes [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X] +Results [4]: [l_orderkey#X, o_orderdate#X, o_shippriority#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X] + +(31) ProjectExecTransformer +Output [4]: [l_orderkey#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X AS revenue#X, o_orderdate#X, o_shippriority#X] +Input [4]: [l_orderkey#X, o_orderdate#X, o_shippriority#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X] + +(32) WholeStageCodegenTransformer (X) +Input [4]: [l_orderkey#X, revenue#X, o_orderdate#X, o_shippriority#X] +Arguments: false + +(33) TakeOrderedAndProjectExecTransformer +Input [4]: [l_orderkey#X, revenue#X, o_orderdate#X, o_shippriority#X] +Arguments: X, [revenue#X DESC NULLS LAST, o_orderdate#X ASC NULLS FIRST], [l_orderkey#X, revenue#X, o_orderdate#X, o_shippriority#X], 0 + +(34) VeloxColumnarToRowExec +Input [4]: [l_orderkey#X, revenue#X, o_orderdate#X, o_shippriority#X] + +(35) Scan parquet +Output [2]: [c_custkey#X, c_mktsegment#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(c_mktsegment), EqualTo(c_mktsegment,BUILDING), IsNotNull(c_custkey)] +ReadSchema: struct + +(36) Filter +Input [2]: [c_custkey#X, c_mktsegment#X] +Condition : ((isnotnull(c_mktsegment#X) AND (c_mktsegment#X = BUILDING)) AND isnotnull(c_custkey#X)) + +(37) Project +Output [1]: [c_custkey#X] +Input [2]: [c_custkey#X, c_mktsegment#X] + +(38) BroadcastExchange +Input [1]: [c_custkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(39) Scan parquet +Output [4]: [o_orderkey#X, o_custkey#X, o_orderdate#X, o_shippriority#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_orderdate), LessThan(o_orderdate,1995-03-15), IsNotNull(o_custkey), IsNotNull(o_orderkey)] +ReadSchema: struct + +(40) Filter +Input [4]: [o_orderkey#X, o_custkey#X, o_orderdate#X, o_shippriority#X] +Condition : (((isnotnull(o_orderdate#X) AND (o_orderdate#X < 1995-03-15)) AND isnotnull(o_custkey#X)) AND isnotnull(o_orderkey#X)) + +(41) BroadcastHashJoin +Left keys [1]: [c_custkey#X] +Right keys [1]: [o_custkey#X] +Join condition: None + +(42) Project +Output [3]: [o_orderkey#X, o_orderdate#X, o_shippriority#X] +Input [5]: [c_custkey#X, o_orderkey#X, o_custkey#X, o_orderdate#X, o_shippriority#X] + +(43) Scan parquet +Output [4]: [l_orderkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_shipdate), GreaterThan(l_shipdate,1995-03-15), IsNotNull(l_orderkey)] +ReadSchema: struct + +(44) Filter +Input [4]: [l_orderkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Condition : ((isnotnull(l_shipdate#X) AND (l_shipdate#X > 1995-03-15)) AND isnotnull(l_orderkey#X)) + +(45) Project +Output [3]: [l_orderkey#X, l_extendedprice#X, l_discount#X] +Input [4]: [l_orderkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] + +(46) BroadcastExchange +Input [3]: [l_orderkey#X, l_extendedprice#X, l_discount#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(47) BroadcastHashJoin +Left keys [1]: [o_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: None + +(48) Project +Output [5]: [o_orderdate#X, o_shippriority#X, l_orderkey#X, l_extendedprice#X, l_discount#X] +Input [6]: [o_orderkey#X, o_orderdate#X, o_shippriority#X, l_orderkey#X, l_extendedprice#X, l_discount#X] + +(49) HashAggregate +Input [5]: [o_orderdate#X, o_shippriority#X, l_orderkey#X, l_extendedprice#X, l_discount#X] +Keys [3]: [l_orderkey#X, o_orderdate#X, o_shippriority#X] +Functions [1]: [partial_sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [5]: [l_orderkey#X, o_orderdate#X, o_shippriority#X, sum#X, isEmpty#X] + +(50) Exchange +Input [5]: [l_orderkey#X, o_orderdate#X, o_shippriority#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(l_orderkey#X, o_orderdate#X, o_shippriority#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(51) HashAggregate +Input [5]: [l_orderkey#X, o_orderdate#X, o_shippriority#X, sum#X, isEmpty#X] +Keys [3]: [l_orderkey#X, o_orderdate#X, o_shippriority#X] +Functions [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))] +Aggregate Attributes [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X] +Results [4]: [l_orderkey#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X AS revenue#X, o_orderdate#X, o_shippriority#X] + +(52) TakeOrderedAndProject +Input [4]: [l_orderkey#X, revenue#X, o_orderdate#X, o_shippriority#X] +Arguments: X, [revenue#X DESC NULLS LAST, o_orderdate#X ASC NULLS FIRST], [l_orderkey#X, revenue#X, o_orderdate#X, o_shippriority#X] + +(53) AdaptiveSparkPlan +Output [4]: [l_orderkey#X, revenue#X, o_orderdate#X, o_shippriority#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/4.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/4.txt new file mode 100644 index 000000000000..d179e6f7ff73 --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/4.txt @@ -0,0 +1,239 @@ +== Physical Plan == +AdaptiveSparkPlan (44) ++- == Final Plan == + VeloxColumnarToRowExec (29) + +- ^ SortExecTransformer (27) + +- ^ InputIteratorTransformer (26) + +- ^ InputAdapter (25) + +- ^ ShuffleQueryStage (24) + +- ColumnarExchange (23) + +- ^ RegularHashAggregateExecTransformer (21) + +- ^ InputIteratorTransformer (20) + +- ^ InputAdapter (19) + +- ^ ShuffleQueryStage (18) + +- ColumnarExchange (17) + +- ^ ProjectExecTransformer (15) + +- ^ FlushableHashAggregateExecTransformer (14) + +- ^ ProjectExecTransformer (13) + +- ^ GlutenBroadcastHashJoinExecTransformer LeftSemi (12) + :- ^ ProjectExecTransformer (3) + : +- ^ FilterExecTransformer (2) + : +- ^ Scan parquet (1) + +- ^ InputIteratorTransformer (11) + +- ^ InputAdapter (10) + +- ^ BroadcastQueryStage (9) + +- ColumnarBroadcastExchange (8) + +- ^ ProjectExecTransformer (6) + +- ^ FilterExecTransformer (5) + +- ^ Scan parquet (4) ++- == Initial Plan == + Sort (43) + +- Exchange (42) + +- HashAggregate (41) + +- Exchange (40) + +- HashAggregate (39) + +- Project (38) + +- BroadcastHashJoin LeftSemi BuildRight (37) + :- Project (32) + : +- Filter (31) + : +- Scan parquet (30) + +- BroadcastExchange (36) + +- Project (35) + +- Filter (34) + +- Scan parquet (33) + + +(1) Scan parquet +Output [3]: [o_orderkey#X, o_orderdate#X, o_orderpriority#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_orderdate), GreaterThanOrEqual(o_orderdate,1993-07-01), LessThan(o_orderdate,1993-10-01)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [3]: [o_orderkey#X, o_orderdate#X, o_orderpriority#X] +Arguments: ((isnotnull(o_orderdate#X) AND (o_orderdate#X >= 1993-07-01)) AND (o_orderdate#X < 1993-10-01)) + +(3) ProjectExecTransformer +Output [2]: [o_orderkey#X, o_orderpriority#X] +Input [3]: [o_orderkey#X, o_orderdate#X, o_orderpriority#X] + +(4) Scan parquet +Output [3]: [l_orderkey#X, l_commitdate#X, l_receiptdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_commitdate), IsNotNull(l_receiptdate)] +ReadSchema: struct + +(5) FilterExecTransformer +Input [3]: [l_orderkey#X, l_commitdate#X, l_receiptdate#X] +Arguments: ((isnotnull(l_commitdate#X) AND isnotnull(l_receiptdate#X)) AND (l_commitdate#X < l_receiptdate#X)) + +(6) ProjectExecTransformer +Output [1]: [l_orderkey#X] +Input [3]: [l_orderkey#X, l_commitdate#X, l_receiptdate#X] + +(7) WholeStageCodegenTransformer (X) +Input [1]: [l_orderkey#X] +Arguments: false + +(8) ColumnarBroadcastExchange +Input [1]: [l_orderkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(9) BroadcastQueryStage +Output [1]: [l_orderkey#X] +Arguments: X + +(10) InputAdapter +Input [1]: [l_orderkey#X] + +(11) InputIteratorTransformer +Input [1]: [l_orderkey#X] + +(12) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [o_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: None + +(13) ProjectExecTransformer +Output [1]: [o_orderpriority#X] +Input [2]: [o_orderkey#X, o_orderpriority#X] + +(14) FlushableHashAggregateExecTransformer +Input [1]: [o_orderpriority#X] +Keys [1]: [o_orderpriority#X] +Functions [1]: [partial_count(1)] +Aggregate Attributes [1]: [count#X] +Results [2]: [o_orderpriority#X, count#X] + +(15) ProjectExecTransformer +Output [3]: [hash(o_orderpriority#X, 42) AS hash_partition_key#X, o_orderpriority#X, count#X] +Input [2]: [o_orderpriority#X, count#X] + +(16) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, o_orderpriority#X, count#X] +Arguments: false + +(17) ColumnarExchange +Input [3]: [hash_partition_key#X, o_orderpriority#X, count#X] +Arguments: hashpartitioning(o_orderpriority#X, 1), ENSURE_REQUIREMENTS, [o_orderpriority#X, count#X], [plan_id=X], [id=#X] + +(18) ShuffleQueryStage +Output [2]: [o_orderpriority#X, count#X] +Arguments: X + +(19) InputAdapter +Input [2]: [o_orderpriority#X, count#X] + +(20) InputIteratorTransformer +Input [2]: [o_orderpriority#X, count#X] + +(21) RegularHashAggregateExecTransformer +Input [2]: [o_orderpriority#X, count#X] +Keys [1]: [o_orderpriority#X] +Functions [1]: [count(1)] +Aggregate Attributes [1]: [count(1)#X] +Results [2]: [o_orderpriority#X, count(1)#X AS order_count#X] + +(22) WholeStageCodegenTransformer (X) +Input [2]: [o_orderpriority#X, order_count#X] +Arguments: false + +(23) ColumnarExchange +Input [2]: [o_orderpriority#X, order_count#X] +Arguments: rangepartitioning(o_orderpriority#X ASC NULLS FIRST, 1), ENSURE_REQUIREMENTS, [plan_id=X], [id=#X] + +(24) ShuffleQueryStage +Output [2]: [o_orderpriority#X, order_count#X] +Arguments: X + +(25) InputAdapter +Input [2]: [o_orderpriority#X, order_count#X] + +(26) InputIteratorTransformer +Input [2]: [o_orderpriority#X, order_count#X] + +(27) SortExecTransformer +Input [2]: [o_orderpriority#X, order_count#X] +Arguments: [o_orderpriority#X ASC NULLS FIRST], true, 0 + +(28) WholeStageCodegenTransformer (X) +Input [2]: [o_orderpriority#X, order_count#X] +Arguments: false + +(29) VeloxColumnarToRowExec +Input [2]: [o_orderpriority#X, order_count#X] + +(30) Scan parquet +Output [3]: [o_orderkey#X, o_orderdate#X, o_orderpriority#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_orderdate), GreaterThanOrEqual(o_orderdate,1993-07-01), LessThan(o_orderdate,1993-10-01)] +ReadSchema: struct + +(31) Filter +Input [3]: [o_orderkey#X, o_orderdate#X, o_orderpriority#X] +Condition : ((isnotnull(o_orderdate#X) AND (o_orderdate#X >= 1993-07-01)) AND (o_orderdate#X < 1993-10-01)) + +(32) Project +Output [2]: [o_orderkey#X, o_orderpriority#X] +Input [3]: [o_orderkey#X, o_orderdate#X, o_orderpriority#X] + +(33) Scan parquet +Output [3]: [l_orderkey#X, l_commitdate#X, l_receiptdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_commitdate), IsNotNull(l_receiptdate)] +ReadSchema: struct + +(34) Filter +Input [3]: [l_orderkey#X, l_commitdate#X, l_receiptdate#X] +Condition : ((isnotnull(l_commitdate#X) AND isnotnull(l_receiptdate#X)) AND (l_commitdate#X < l_receiptdate#X)) + +(35) Project +Output [1]: [l_orderkey#X] +Input [3]: [l_orderkey#X, l_commitdate#X, l_receiptdate#X] + +(36) BroadcastExchange +Input [1]: [l_orderkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(37) BroadcastHashJoin +Left keys [1]: [o_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: None + +(38) Project +Output [1]: [o_orderpriority#X] +Input [2]: [o_orderkey#X, o_orderpriority#X] + +(39) HashAggregate +Input [1]: [o_orderpriority#X] +Keys [1]: [o_orderpriority#X] +Functions [1]: [partial_count(1)] +Aggregate Attributes [1]: [count#X] +Results [2]: [o_orderpriority#X, count#X] + +(40) Exchange +Input [2]: [o_orderpriority#X, count#X] +Arguments: hashpartitioning(o_orderpriority#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(41) HashAggregate +Input [2]: [o_orderpriority#X, count#X] +Keys [1]: [o_orderpriority#X] +Functions [1]: [count(1)] +Aggregate Attributes [1]: [count(1)#X] +Results [2]: [o_orderpriority#X, count(1)#X AS order_count#X] + +(42) Exchange +Input [2]: [o_orderpriority#X, order_count#X] +Arguments: rangepartitioning(o_orderpriority#X ASC NULLS FIRST, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(43) Sort +Input [2]: [o_orderpriority#X, order_count#X] +Arguments: [o_orderpriority#X ASC NULLS FIRST], true, 0 + +(44) AdaptiveSparkPlan +Output [2]: [o_orderpriority#X, order_count#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/5.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/5.txt new file mode 100644 index 000000000000..a6fcbb77e9da --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/5.txt @@ -0,0 +1,539 @@ +== Physical Plan == +AdaptiveSparkPlan (100) ++- == Final Plan == + VeloxColumnarToRowExec (65) + +- ^ SortExecTransformer (63) + +- ^ InputIteratorTransformer (62) + +- ^ InputAdapter (61) + +- ^ ShuffleQueryStage (60) + +- ColumnarExchange (59) + +- ^ RegularHashAggregateExecTransformer (57) + +- ^ InputIteratorTransformer (56) + +- ^ InputAdapter (55) + +- ^ ShuffleQueryStage (54) + +- ColumnarExchange (53) + +- ^ ProjectExecTransformer (51) + +- ^ FlushableHashAggregateExecTransformer (50) + +- ^ ProjectExecTransformer (49) + +- ^ GlutenBroadcastHashJoinExecTransformer Inner (48) + :- ^ ProjectExecTransformer (39) + : +- ^ GlutenBroadcastHashJoinExecTransformer Inner (38) + : :- ^ ProjectExecTransformer (30) + : : +- ^ GlutenBroadcastHashJoinExecTransformer Inner (29) + : : :- ^ ProjectExecTransformer (21) + : : : +- ^ GlutenBroadcastHashJoinExecTransformer Inner (20) + : : : :- ^ ProjectExecTransformer (12) + : : : : +- ^ GlutenBroadcastHashJoinExecTransformer Inner (11) + : : : : :- ^ InputIteratorTransformer (7) + : : : : : +- ^ InputAdapter (6) + : : : : : +- ^ BroadcastQueryStage (5) + : : : : : +- ColumnarBroadcastExchange (4) + : : : : : +- ^ FilterExecTransformer (2) + : : : : : +- ^ Scan parquet (1) + : : : : +- ^ ProjectExecTransformer (10) + : : : : +- ^ FilterExecTransformer (9) + : : : : +- ^ Scan parquet (8) + : : : +- ^ InputIteratorTransformer (19) + : : : +- ^ InputAdapter (18) + : : : +- ^ BroadcastQueryStage (17) + : : : +- ColumnarBroadcastExchange (16) + : : : +- ^ FilterExecTransformer (14) + : : : +- ^ Scan parquet (13) + : : +- ^ InputIteratorTransformer (28) + : : +- ^ InputAdapter (27) + : : +- ^ BroadcastQueryStage (26) + : : +- ColumnarBroadcastExchange (25) + : : +- ^ FilterExecTransformer (23) + : : +- ^ Scan parquet (22) + : +- ^ InputIteratorTransformer (37) + : +- ^ InputAdapter (36) + : +- ^ BroadcastQueryStage (35) + : +- ColumnarBroadcastExchange (34) + : +- ^ FilterExecTransformer (32) + : +- ^ Scan parquet (31) + +- ^ InputIteratorTransformer (47) + +- ^ InputAdapter (46) + +- ^ BroadcastQueryStage (45) + +- ColumnarBroadcastExchange (44) + +- ^ ProjectExecTransformer (42) + +- ^ FilterExecTransformer (41) + +- ^ Scan parquet (40) ++- == Initial Plan == + Sort (99) + +- Exchange (98) + +- HashAggregate (97) + +- Exchange (96) + +- HashAggregate (95) + +- Project (94) + +- BroadcastHashJoin Inner BuildRight (93) + :- Project (88) + : +- BroadcastHashJoin Inner BuildRight (87) + : :- Project (83) + : : +- BroadcastHashJoin Inner BuildRight (82) + : : :- Project (78) + : : : +- BroadcastHashJoin Inner BuildRight (77) + : : : :- Project (73) + : : : : +- BroadcastHashJoin Inner BuildLeft (72) + : : : : :- BroadcastExchange (68) + : : : : : +- Filter (67) + : : : : : +- Scan parquet (66) + : : : : +- Project (71) + : : : : +- Filter (70) + : : : : +- Scan parquet (69) + : : : +- BroadcastExchange (76) + : : : +- Filter (75) + : : : +- Scan parquet (74) + : : +- BroadcastExchange (81) + : : +- Filter (80) + : : +- Scan parquet (79) + : +- BroadcastExchange (86) + : +- Filter (85) + : +- Scan parquet (84) + +- BroadcastExchange (92) + +- Project (91) + +- Filter (90) + +- Scan parquet (89) + + +(1) Scan parquet +Output [2]: [c_custkey#X, c_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(c_custkey), IsNotNull(c_nationkey)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [2]: [c_custkey#X, c_nationkey#X] +Arguments: (isnotnull(c_custkey#X) AND isnotnull(c_nationkey#X)) + +(3) WholeStageCodegenTransformer (X) +Input [2]: [c_custkey#X, c_nationkey#X] +Arguments: false + +(4) ColumnarBroadcastExchange +Input [2]: [c_custkey#X, c_nationkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(5) BroadcastQueryStage +Output [2]: [c_custkey#X, c_nationkey#X] +Arguments: X + +(6) InputAdapter +Input [2]: [c_custkey#X, c_nationkey#X] + +(7) InputIteratorTransformer +Input [2]: [c_custkey#X, c_nationkey#X] + +(8) Scan parquet +Output [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_orderdate), GreaterThanOrEqual(o_orderdate,1994-01-01), LessThan(o_orderdate,1995-01-01), IsNotNull(o_custkey), IsNotNull(o_orderkey)] +ReadSchema: struct + +(9) FilterExecTransformer +Input [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] +Arguments: ((((isnotnull(o_orderdate#X) AND (o_orderdate#X >= 1994-01-01)) AND (o_orderdate#X < 1995-01-01)) AND isnotnull(o_custkey#X)) AND isnotnull(o_orderkey#X)) + +(10) ProjectExecTransformer +Output [2]: [o_orderkey#X, o_custkey#X] +Input [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] + +(11) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [c_custkey#X] +Right keys [1]: [o_custkey#X] +Join condition: None + +(12) ProjectExecTransformer +Output [2]: [c_nationkey#X, o_orderkey#X] +Input [4]: [c_custkey#X, c_nationkey#X, o_orderkey#X, o_custkey#X] + +(13) Scan parquet +Output [4]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_orderkey), IsNotNull(l_suppkey)] +ReadSchema: struct + +(14) FilterExecTransformer +Input [4]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Arguments: (isnotnull(l_orderkey#X) AND isnotnull(l_suppkey#X)) + +(15) WholeStageCodegenTransformer (X) +Input [4]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Arguments: false + +(16) ColumnarBroadcastExchange +Input [4]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(17) BroadcastQueryStage +Output [4]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Arguments: X + +(18) InputAdapter +Input [4]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] + +(19) InputIteratorTransformer +Input [4]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] + +(20) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [o_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: None + +(21) ProjectExecTransformer +Output [4]: [c_nationkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Input [6]: [c_nationkey#X, o_orderkey#X, l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] + +(22) Scan parquet +Output [2]: [s_suppkey#X, s_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(s_suppkey), IsNotNull(s_nationkey)] +ReadSchema: struct + +(23) FilterExecTransformer +Input [2]: [s_suppkey#X, s_nationkey#X] +Arguments: (isnotnull(s_suppkey#X) AND isnotnull(s_nationkey#X)) + +(24) WholeStageCodegenTransformer (X) +Input [2]: [s_suppkey#X, s_nationkey#X] +Arguments: false + +(25) ColumnarBroadcastExchange +Input [2]: [s_suppkey#X, s_nationkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false], input[1, bigint, false]),false), [plan_id=X] + +(26) BroadcastQueryStage +Output [2]: [s_suppkey#X, s_nationkey#X] +Arguments: X + +(27) InputAdapter +Input [2]: [s_suppkey#X, s_nationkey#X] + +(28) InputIteratorTransformer +Input [2]: [s_suppkey#X, s_nationkey#X] + +(29) GlutenBroadcastHashJoinExecTransformer +Left keys [2]: [l_suppkey#X, c_nationkey#X] +Right keys [2]: [s_suppkey#X, s_nationkey#X] +Join condition: None + +(30) ProjectExecTransformer +Output [3]: [l_extendedprice#X, l_discount#X, s_nationkey#X] +Input [6]: [c_nationkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X, s_suppkey#X, s_nationkey#X] + +(31) Scan parquet +Output [3]: [n_nationkey#X, n_name#X, n_regionkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_nationkey), IsNotNull(n_regionkey)] +ReadSchema: struct + +(32) FilterExecTransformer +Input [3]: [n_nationkey#X, n_name#X, n_regionkey#X] +Arguments: (isnotnull(n_nationkey#X) AND isnotnull(n_regionkey#X)) + +(33) WholeStageCodegenTransformer (X) +Input [3]: [n_nationkey#X, n_name#X, n_regionkey#X] +Arguments: false + +(34) ColumnarBroadcastExchange +Input [3]: [n_nationkey#X, n_name#X, n_regionkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(35) BroadcastQueryStage +Output [3]: [n_nationkey#X, n_name#X, n_regionkey#X] +Arguments: X + +(36) InputAdapter +Input [3]: [n_nationkey#X, n_name#X, n_regionkey#X] + +(37) InputIteratorTransformer +Input [3]: [n_nationkey#X, n_name#X, n_regionkey#X] + +(38) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [s_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: None + +(39) ProjectExecTransformer +Output [4]: [l_extendedprice#X, l_discount#X, n_name#X, n_regionkey#X] +Input [6]: [l_extendedprice#X, l_discount#X, s_nationkey#X, n_nationkey#X, n_name#X, n_regionkey#X] + +(40) Scan parquet +Output [2]: [r_regionkey#X, r_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(r_name), EqualTo(r_name,ASIA), IsNotNull(r_regionkey)] +ReadSchema: struct + +(41) FilterExecTransformer +Input [2]: [r_regionkey#X, r_name#X] +Arguments: ((isnotnull(r_name#X) AND (r_name#X = ASIA)) AND isnotnull(r_regionkey#X)) + +(42) ProjectExecTransformer +Output [1]: [r_regionkey#X] +Input [2]: [r_regionkey#X, r_name#X] + +(43) WholeStageCodegenTransformer (X) +Input [1]: [r_regionkey#X] +Arguments: false + +(44) ColumnarBroadcastExchange +Input [1]: [r_regionkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(45) BroadcastQueryStage +Output [1]: [r_regionkey#X] +Arguments: X + +(46) InputAdapter +Input [1]: [r_regionkey#X] + +(47) InputIteratorTransformer +Input [1]: [r_regionkey#X] + +(48) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [n_regionkey#X] +Right keys [1]: [r_regionkey#X] +Join condition: None + +(49) ProjectExecTransformer +Output [4]: [l_extendedprice#X, l_discount#X, n_name#X, CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) AS _pre_127#X] +Input [5]: [l_extendedprice#X, l_discount#X, n_name#X, n_regionkey#X, r_regionkey#X] + +(50) FlushableHashAggregateExecTransformer +Input [4]: [l_extendedprice#X, l_discount#X, n_name#X, _pre_127#X] +Keys [1]: [n_name#X] +Functions [1]: [partial_sum(_pre_127#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [3]: [n_name#X, sum#X, isEmpty#X] + +(51) ProjectExecTransformer +Output [4]: [hash(n_name#X, 42) AS hash_partition_key#X, n_name#X, sum#X, isEmpty#X] +Input [3]: [n_name#X, sum#X, isEmpty#X] + +(52) WholeStageCodegenTransformer (X) +Input [4]: [hash_partition_key#X, n_name#X, sum#X, isEmpty#X] +Arguments: false + +(53) ColumnarExchange +Input [4]: [hash_partition_key#X, n_name#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(n_name#X, 1), ENSURE_REQUIREMENTS, [n_name#X, sum#X, isEmpty#X], [plan_id=X], [id=#X] + +(54) ShuffleQueryStage +Output [3]: [n_name#X, sum#X, isEmpty#X] +Arguments: X + +(55) InputAdapter +Input [3]: [n_name#X, sum#X, isEmpty#X] + +(56) InputIteratorTransformer +Input [3]: [n_name#X, sum#X, isEmpty#X] + +(57) RegularHashAggregateExecTransformer +Input [3]: [n_name#X, sum#X, isEmpty#X] +Keys [1]: [n_name#X] +Functions [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))] +Aggregate Attributes [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X] +Results [2]: [n_name#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X AS revenue#X] + +(58) WholeStageCodegenTransformer (X) +Input [2]: [n_name#X, revenue#X] +Arguments: false + +(59) ColumnarExchange +Input [2]: [n_name#X, revenue#X] +Arguments: rangepartitioning(revenue#X DESC NULLS LAST, 1), ENSURE_REQUIREMENTS, [plan_id=X], [id=#X] + +(60) ShuffleQueryStage +Output [2]: [n_name#X, revenue#X] +Arguments: X + +(61) InputAdapter +Input [2]: [n_name#X, revenue#X] + +(62) InputIteratorTransformer +Input [2]: [n_name#X, revenue#X] + +(63) SortExecTransformer +Input [2]: [n_name#X, revenue#X] +Arguments: [revenue#X DESC NULLS LAST], true, 0 + +(64) WholeStageCodegenTransformer (X) +Input [2]: [n_name#X, revenue#X] +Arguments: false + +(65) VeloxColumnarToRowExec +Input [2]: [n_name#X, revenue#X] + +(66) Scan parquet +Output [2]: [c_custkey#X, c_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(c_custkey), IsNotNull(c_nationkey)] +ReadSchema: struct + +(67) Filter +Input [2]: [c_custkey#X, c_nationkey#X] +Condition : (isnotnull(c_custkey#X) AND isnotnull(c_nationkey#X)) + +(68) BroadcastExchange +Input [2]: [c_custkey#X, c_nationkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(69) Scan parquet +Output [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_orderdate), GreaterThanOrEqual(o_orderdate,1994-01-01), LessThan(o_orderdate,1995-01-01), IsNotNull(o_custkey), IsNotNull(o_orderkey)] +ReadSchema: struct + +(70) Filter +Input [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] +Condition : ((((isnotnull(o_orderdate#X) AND (o_orderdate#X >= 1994-01-01)) AND (o_orderdate#X < 1995-01-01)) AND isnotnull(o_custkey#X)) AND isnotnull(o_orderkey#X)) + +(71) Project +Output [2]: [o_orderkey#X, o_custkey#X] +Input [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] + +(72) BroadcastHashJoin +Left keys [1]: [c_custkey#X] +Right keys [1]: [o_custkey#X] +Join condition: None + +(73) Project +Output [2]: [c_nationkey#X, o_orderkey#X] +Input [4]: [c_custkey#X, c_nationkey#X, o_orderkey#X, o_custkey#X] + +(74) Scan parquet +Output [4]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_orderkey), IsNotNull(l_suppkey)] +ReadSchema: struct + +(75) Filter +Input [4]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Condition : (isnotnull(l_orderkey#X) AND isnotnull(l_suppkey#X)) + +(76) BroadcastExchange +Input [4]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(77) BroadcastHashJoin +Left keys [1]: [o_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: None + +(78) Project +Output [4]: [c_nationkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Input [6]: [c_nationkey#X, o_orderkey#X, l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] + +(79) Scan parquet +Output [2]: [s_suppkey#X, s_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(s_suppkey), IsNotNull(s_nationkey)] +ReadSchema: struct + +(80) Filter +Input [2]: [s_suppkey#X, s_nationkey#X] +Condition : (isnotnull(s_suppkey#X) AND isnotnull(s_nationkey#X)) + +(81) BroadcastExchange +Input [2]: [s_suppkey#X, s_nationkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false], input[1, bigint, false]),false), [plan_id=X] + +(82) BroadcastHashJoin +Left keys [2]: [l_suppkey#X, c_nationkey#X] +Right keys [2]: [s_suppkey#X, s_nationkey#X] +Join condition: None + +(83) Project +Output [3]: [l_extendedprice#X, l_discount#X, s_nationkey#X] +Input [6]: [c_nationkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X, s_suppkey#X, s_nationkey#X] + +(84) Scan parquet +Output [3]: [n_nationkey#X, n_name#X, n_regionkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_nationkey), IsNotNull(n_regionkey)] +ReadSchema: struct + +(85) Filter +Input [3]: [n_nationkey#X, n_name#X, n_regionkey#X] +Condition : (isnotnull(n_nationkey#X) AND isnotnull(n_regionkey#X)) + +(86) BroadcastExchange +Input [3]: [n_nationkey#X, n_name#X, n_regionkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(87) BroadcastHashJoin +Left keys [1]: [s_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: None + +(88) Project +Output [4]: [l_extendedprice#X, l_discount#X, n_name#X, n_regionkey#X] +Input [6]: [l_extendedprice#X, l_discount#X, s_nationkey#X, n_nationkey#X, n_name#X, n_regionkey#X] + +(89) Scan parquet +Output [2]: [r_regionkey#X, r_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(r_name), EqualTo(r_name,ASIA), IsNotNull(r_regionkey)] +ReadSchema: struct + +(90) Filter +Input [2]: [r_regionkey#X, r_name#X] +Condition : ((isnotnull(r_name#X) AND (r_name#X = ASIA)) AND isnotnull(r_regionkey#X)) + +(91) Project +Output [1]: [r_regionkey#X] +Input [2]: [r_regionkey#X, r_name#X] + +(92) BroadcastExchange +Input [1]: [r_regionkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(93) BroadcastHashJoin +Left keys [1]: [n_regionkey#X] +Right keys [1]: [r_regionkey#X] +Join condition: None + +(94) Project +Output [3]: [l_extendedprice#X, l_discount#X, n_name#X] +Input [5]: [l_extendedprice#X, l_discount#X, n_name#X, n_regionkey#X, r_regionkey#X] + +(95) HashAggregate +Input [3]: [l_extendedprice#X, l_discount#X, n_name#X] +Keys [1]: [n_name#X] +Functions [1]: [partial_sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [3]: [n_name#X, sum#X, isEmpty#X] + +(96) Exchange +Input [3]: [n_name#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(n_name#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(97) HashAggregate +Input [3]: [n_name#X, sum#X, isEmpty#X] +Keys [1]: [n_name#X] +Functions [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))] +Aggregate Attributes [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X] +Results [2]: [n_name#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X AS revenue#X] + +(98) Exchange +Input [2]: [n_name#X, revenue#X] +Arguments: rangepartitioning(revenue#X DESC NULLS LAST, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(99) Sort +Input [2]: [n_name#X, revenue#X] +Arguments: [revenue#X DESC NULLS LAST], true, 0 + +(100) AdaptiveSparkPlan +Output [2]: [n_name#X, revenue#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/6.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/6.txt new file mode 100644 index 000000000000..c6385c42eb48 --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/6.txt @@ -0,0 +1,112 @@ +== Physical Plan == +AdaptiveSparkPlan (19) ++- == Final Plan == + VeloxColumnarToRowExec (12) + +- ^ RegularHashAggregateExecTransformer (10) + +- ^ InputIteratorTransformer (9) + +- ^ InputAdapter (8) + +- ^ ShuffleQueryStage (7) + +- ColumnarExchange (6) + +- ^ FlushableHashAggregateExecTransformer (4) + +- ^ ProjectExecTransformer (3) + +- ^ FilterExecTransformer (2) + +- ^ Scan parquet (1) ++- == Initial Plan == + HashAggregate (18) + +- Exchange (17) + +- HashAggregate (16) + +- Project (15) + +- Filter (14) + +- Scan parquet (13) + + +(1) Scan parquet +Output [4]: [l_quantity#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_shipdate), IsNotNull(l_discount), IsNotNull(l_quantity), GreaterThanOrEqual(l_shipdate,1994-01-01), LessThan(l_shipdate,1995-01-01), GreaterThanOrEqual(l_discount,0.05), LessThanOrEqual(l_discount,0.07), LessThan(l_quantity,24.00)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [4]: [l_quantity#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Arguments: (((((((isnotnull(l_shipdate#X) AND isnotnull(l_discount#X)) AND isnotnull(l_quantity#X)) AND (l_shipdate#X >= 1994-01-01)) AND (l_shipdate#X < 1995-01-01)) AND (l_discount#X >= 0.05)) AND (l_discount#X <= 0.07)) AND (l_quantity#X < 24.00)) + +(3) ProjectExecTransformer +Output [3]: [l_extendedprice#X, l_discount#X, CheckOverflow((promote_precision(l_extendedprice#X) * promote_precision(l_discount#X)), DecimalType(25,4), true) AS _pre_128#X] +Input [4]: [l_quantity#X, l_extendedprice#X, l_discount#X, l_shipdate#X] + +(4) FlushableHashAggregateExecTransformer +Input [3]: [l_extendedprice#X, l_discount#X, _pre_128#X] +Keys: [] +Functions [1]: [partial_sum(_pre_128#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [2]: [sum#X, isEmpty#X] + +(5) WholeStageCodegenTransformer (X) +Input [2]: [sum#X, isEmpty#X] +Arguments: false + +(6) ColumnarExchange +Input [2]: [sum#X, isEmpty#X] +Arguments: SinglePartition, ENSURE_REQUIREMENTS, [plan_id=X], [id=#X] + +(7) ShuffleQueryStage +Output [2]: [sum#X, isEmpty#X] +Arguments: X + +(8) InputAdapter +Input [2]: [sum#X, isEmpty#X] + +(9) InputIteratorTransformer +Input [2]: [sum#X, isEmpty#X] + +(10) RegularHashAggregateExecTransformer +Input [2]: [sum#X, isEmpty#X] +Keys: [] +Functions [1]: [sum(CheckOverflow((promote_precision(l_extendedprice#X) * promote_precision(l_discount#X)), DecimalType(25,4), true))] +Aggregate Attributes [1]: [sum(CheckOverflow((promote_precision(l_extendedprice#X) * promote_precision(l_discount#X)), DecimalType(25,4), true))#X] +Results [1]: [sum(CheckOverflow((promote_precision(l_extendedprice#X) * promote_precision(l_discount#X)), DecimalType(25,4), true))#X AS revenue#X] + +(11) WholeStageCodegenTransformer (X) +Input [1]: [revenue#X] +Arguments: false + +(12) VeloxColumnarToRowExec +Input [1]: [revenue#X] + +(13) Scan parquet +Output [4]: [l_quantity#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_shipdate), IsNotNull(l_discount), IsNotNull(l_quantity), GreaterThanOrEqual(l_shipdate,1994-01-01), LessThan(l_shipdate,1995-01-01), GreaterThanOrEqual(l_discount,0.05), LessThanOrEqual(l_discount,0.07), LessThan(l_quantity,24.00)] +ReadSchema: struct + +(14) Filter +Input [4]: [l_quantity#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Condition : (((((((isnotnull(l_shipdate#X) AND isnotnull(l_discount#X)) AND isnotnull(l_quantity#X)) AND (l_shipdate#X >= 1994-01-01)) AND (l_shipdate#X < 1995-01-01)) AND (l_discount#X >= 0.05)) AND (l_discount#X <= 0.07)) AND (l_quantity#X < 24.00)) + +(15) Project +Output [2]: [l_extendedprice#X, l_discount#X] +Input [4]: [l_quantity#X, l_extendedprice#X, l_discount#X, l_shipdate#X] + +(16) HashAggregate +Input [2]: [l_extendedprice#X, l_discount#X] +Keys: [] +Functions [1]: [partial_sum(CheckOverflow((promote_precision(l_extendedprice#X) * promote_precision(l_discount#X)), DecimalType(25,4), true))] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [2]: [sum#X, isEmpty#X] + +(17) Exchange +Input [2]: [sum#X, isEmpty#X] +Arguments: SinglePartition, ENSURE_REQUIREMENTS, [plan_id=X] + +(18) HashAggregate +Input [2]: [sum#X, isEmpty#X] +Keys: [] +Functions [1]: [sum(CheckOverflow((promote_precision(l_extendedprice#X) * promote_precision(l_discount#X)), DecimalType(25,4), true))] +Aggregate Attributes [1]: [sum(CheckOverflow((promote_precision(l_extendedprice#X) * promote_precision(l_discount#X)), DecimalType(25,4), true))#X] +Results [1]: [sum(CheckOverflow((promote_precision(l_extendedprice#X) * promote_precision(l_discount#X)), DecimalType(25,4), true))#X AS revenue#X] + +(19) AdaptiveSparkPlan +Output [1]: [revenue#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/7.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/7.txt new file mode 100644 index 000000000000..d17de78601ed --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/7.txt @@ -0,0 +1,501 @@ +== Physical Plan == +AdaptiveSparkPlan (93) ++- == Final Plan == + VeloxColumnarToRowExec (60) + +- ^ SortExecTransformer (58) + +- ^ InputIteratorTransformer (57) + +- ^ InputAdapter (56) + +- ^ ShuffleQueryStage (55) + +- ColumnarExchange (54) + +- ^ RegularHashAggregateExecTransformer (52) + +- ^ InputIteratorTransformer (51) + +- ^ InputAdapter (50) + +- ^ ShuffleQueryStage (49) + +- ColumnarExchange (48) + +- ^ ProjectExecTransformer (46) + +- ^ FlushableHashAggregateExecTransformer (45) + +- ^ ProjectExecTransformer (44) + +- ^ GlutenBroadcastHashJoinExecTransformer Inner (43) + :- ^ ProjectExecTransformer (38) + : +- ^ GlutenBroadcastHashJoinExecTransformer Inner (37) + : :- ^ ProjectExecTransformer (29) + : : +- ^ GlutenBroadcastHashJoinExecTransformer Inner (28) + : : :- ^ ProjectExecTransformer (20) + : : : +- ^ GlutenBroadcastHashJoinExecTransformer Inner (19) + : : : :- ^ ProjectExecTransformer (11) + : : : : +- ^ GlutenBroadcastHashJoinExecTransformer Inner (10) + : : : : :- ^ InputIteratorTransformer (7) + : : : : : +- ^ InputAdapter (6) + : : : : : +- ^ BroadcastQueryStage (5) + : : : : : +- ColumnarBroadcastExchange (4) + : : : : : +- ^ FilterExecTransformer (2) + : : : : : +- ^ Scan parquet (1) + : : : : +- ^ FilterExecTransformer (9) + : : : : +- ^ Scan parquet (8) + : : : +- ^ InputIteratorTransformer (18) + : : : +- ^ InputAdapter (17) + : : : +- ^ BroadcastQueryStage (16) + : : : +- ColumnarBroadcastExchange (15) + : : : +- ^ FilterExecTransformer (13) + : : : +- ^ Scan parquet (12) + : : +- ^ InputIteratorTransformer (27) + : : +- ^ InputAdapter (26) + : : +- ^ BroadcastQueryStage (25) + : : +- ColumnarBroadcastExchange (24) + : : +- ^ FilterExecTransformer (22) + : : +- ^ Scan parquet (21) + : +- ^ InputIteratorTransformer (36) + : +- ^ InputAdapter (35) + : +- ^ BroadcastQueryStage (34) + : +- ColumnarBroadcastExchange (33) + : +- ^ FilterExecTransformer (31) + : +- ^ Scan parquet (30) + +- ^ InputIteratorTransformer (42) + +- ^ InputAdapter (41) + +- ^ BroadcastQueryStage (40) + +- ReusedExchange (39) ++- == Initial Plan == + Sort (92) + +- Exchange (91) + +- HashAggregate (90) + +- Exchange (89) + +- HashAggregate (88) + +- Project (87) + +- BroadcastHashJoin Inner BuildRight (86) + :- Project (82) + : +- BroadcastHashJoin Inner BuildRight (81) + : :- Project (77) + : : +- BroadcastHashJoin Inner BuildRight (76) + : : :- Project (72) + : : : +- BroadcastHashJoin Inner BuildRight (71) + : : : :- Project (67) + : : : : +- BroadcastHashJoin Inner BuildLeft (66) + : : : : :- BroadcastExchange (63) + : : : : : +- Filter (62) + : : : : : +- Scan parquet (61) + : : : : +- Filter (65) + : : : : +- Scan parquet (64) + : : : +- BroadcastExchange (70) + : : : +- Filter (69) + : : : +- Scan parquet (68) + : : +- BroadcastExchange (75) + : : +- Filter (74) + : : +- Scan parquet (73) + : +- BroadcastExchange (80) + : +- Filter (79) + : +- Scan parquet (78) + +- BroadcastExchange (85) + +- Filter (84) + +- Scan parquet (83) + + +(1) Scan parquet +Output [2]: [s_suppkey#X, s_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(s_suppkey), IsNotNull(s_nationkey)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [2]: [s_suppkey#X, s_nationkey#X] +Arguments: (isnotnull(s_suppkey#X) AND isnotnull(s_nationkey#X)) + +(3) WholeStageCodegenTransformer (X) +Input [2]: [s_suppkey#X, s_nationkey#X] +Arguments: false + +(4) ColumnarBroadcastExchange +Input [2]: [s_suppkey#X, s_nationkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(5) BroadcastQueryStage +Output [2]: [s_suppkey#X, s_nationkey#X] +Arguments: X + +(6) InputAdapter +Input [2]: [s_suppkey#X, s_nationkey#X] + +(7) InputIteratorTransformer +Input [2]: [s_suppkey#X, s_nationkey#X] + +(8) Scan parquet +Output [5]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_shipdate), GreaterThanOrEqual(l_shipdate,1995-01-01), LessThanOrEqual(l_shipdate,1996-12-31), IsNotNull(l_suppkey), IsNotNull(l_orderkey)] +ReadSchema: struct + +(9) FilterExecTransformer +Input [5]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Arguments: ((((isnotnull(l_shipdate#X) AND (l_shipdate#X >= 1995-01-01)) AND (l_shipdate#X <= 1996-12-31)) AND isnotnull(l_suppkey#X)) AND isnotnull(l_orderkey#X)) + +(10) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [s_suppkey#X] +Right keys [1]: [l_suppkey#X] +Join condition: None + +(11) ProjectExecTransformer +Output [5]: [s_nationkey#X, l_orderkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Input [7]: [s_suppkey#X, s_nationkey#X, l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] + +(12) Scan parquet +Output [2]: [o_orderkey#X, o_custkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_orderkey), IsNotNull(o_custkey)] +ReadSchema: struct + +(13) FilterExecTransformer +Input [2]: [o_orderkey#X, o_custkey#X] +Arguments: (isnotnull(o_orderkey#X) AND isnotnull(o_custkey#X)) + +(14) WholeStageCodegenTransformer (X) +Input [2]: [o_orderkey#X, o_custkey#X] +Arguments: false + +(15) ColumnarBroadcastExchange +Input [2]: [o_orderkey#X, o_custkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(16) BroadcastQueryStage +Output [2]: [o_orderkey#X, o_custkey#X] +Arguments: X + +(17) InputAdapter +Input [2]: [o_orderkey#X, o_custkey#X] + +(18) InputIteratorTransformer +Input [2]: [o_orderkey#X, o_custkey#X] + +(19) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [l_orderkey#X] +Right keys [1]: [o_orderkey#X] +Join condition: None + +(20) ProjectExecTransformer +Output [5]: [s_nationkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X, o_custkey#X] +Input [7]: [s_nationkey#X, l_orderkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X, o_orderkey#X, o_custkey#X] + +(21) Scan parquet +Output [2]: [c_custkey#X, c_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(c_custkey), IsNotNull(c_nationkey)] +ReadSchema: struct + +(22) FilterExecTransformer +Input [2]: [c_custkey#X, c_nationkey#X] +Arguments: (isnotnull(c_custkey#X) AND isnotnull(c_nationkey#X)) + +(23) WholeStageCodegenTransformer (X) +Input [2]: [c_custkey#X, c_nationkey#X] +Arguments: false + +(24) ColumnarBroadcastExchange +Input [2]: [c_custkey#X, c_nationkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(25) BroadcastQueryStage +Output [2]: [c_custkey#X, c_nationkey#X] +Arguments: X + +(26) InputAdapter +Input [2]: [c_custkey#X, c_nationkey#X] + +(27) InputIteratorTransformer +Input [2]: [c_custkey#X, c_nationkey#X] + +(28) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [o_custkey#X] +Right keys [1]: [c_custkey#X] +Join condition: None + +(29) ProjectExecTransformer +Output [5]: [s_nationkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X, c_nationkey#X] +Input [7]: [s_nationkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X, o_custkey#X, c_custkey#X, c_nationkey#X] + +(30) Scan parquet +Output [2]: [n_nationkey#X, n_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_nationkey), Or(EqualTo(n_name,FRANCE),EqualTo(n_name,GERMANY))] +ReadSchema: struct + +(31) FilterExecTransformer +Input [2]: [n_nationkey#X, n_name#X] +Arguments: (isnotnull(n_nationkey#X) AND ((n_name#X = FRANCE) OR (n_name#X = GERMANY))) + +(32) WholeStageCodegenTransformer (X) +Input [2]: [n_nationkey#X, n_name#X] +Arguments: false + +(33) ColumnarBroadcastExchange +Input [2]: [n_nationkey#X, n_name#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(34) BroadcastQueryStage +Output [2]: [n_nationkey#X, n_name#X] +Arguments: X + +(35) InputAdapter +Input [2]: [n_nationkey#X, n_name#X] + +(36) InputIteratorTransformer +Input [2]: [n_nationkey#X, n_name#X] + +(37) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [s_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: None + +(38) ProjectExecTransformer +Output [5]: [l_extendedprice#X, l_discount#X, l_shipdate#X, c_nationkey#X, n_name#X] +Input [7]: [s_nationkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X, c_nationkey#X, n_nationkey#X, n_name#X] + +(39) ReusedExchange [Reuses operator id: 33] +Output [2]: [n_nationkey#X, n_name#X] + +(40) BroadcastQueryStage +Output [2]: [n_nationkey#X, n_name#X] +Arguments: X + +(41) InputAdapter +Input [2]: [n_nationkey#X, n_name#X] + +(42) InputIteratorTransformer +Input [2]: [n_nationkey#X, n_name#X] + +(43) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [c_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: (((n_name#X = FRANCE) AND (n_name#X = GERMANY)) OR ((n_name#X = GERMANY) AND (n_name#X = FRANCE))) + +(44) ProjectExecTransformer +Output [4]: [n_name#X AS supp_nation#X, n_name#X AS cust_nation#X, year(l_shipdate#X) AS l_year#X, CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) AS volume#X] +Input [7]: [l_extendedprice#X, l_discount#X, l_shipdate#X, c_nationkey#X, n_name#X, n_nationkey#X, n_name#X] + +(45) FlushableHashAggregateExecTransformer +Input [4]: [supp_nation#X, cust_nation#X, l_year#X, volume#X] +Keys [3]: [supp_nation#X, cust_nation#X, l_year#X] +Functions [1]: [partial_sum(volume#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [5]: [supp_nation#X, cust_nation#X, l_year#X, sum#X, isEmpty#X] + +(46) ProjectExecTransformer +Output [6]: [hash(supp_nation#X, cust_nation#X, l_year#X, 42) AS hash_partition_key#X, supp_nation#X, cust_nation#X, l_year#X, sum#X, isEmpty#X] +Input [5]: [supp_nation#X, cust_nation#X, l_year#X, sum#X, isEmpty#X] + +(47) WholeStageCodegenTransformer (X) +Input [6]: [hash_partition_key#X, supp_nation#X, cust_nation#X, l_year#X, sum#X, isEmpty#X] +Arguments: false + +(48) ColumnarExchange +Input [6]: [hash_partition_key#X, supp_nation#X, cust_nation#X, l_year#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(supp_nation#X, cust_nation#X, l_year#X, 1), ENSURE_REQUIREMENTS, [supp_nation#X, cust_nation#X, l_year#X, sum#X, isEmpty#X], [plan_id=X], [id=#X] + +(49) ShuffleQueryStage +Output [5]: [supp_nation#X, cust_nation#X, l_year#X, sum#X, isEmpty#X] +Arguments: X + +(50) InputAdapter +Input [5]: [supp_nation#X, cust_nation#X, l_year#X, sum#X, isEmpty#X] + +(51) InputIteratorTransformer +Input [5]: [supp_nation#X, cust_nation#X, l_year#X, sum#X, isEmpty#X] + +(52) RegularHashAggregateExecTransformer +Input [5]: [supp_nation#X, cust_nation#X, l_year#X, sum#X, isEmpty#X] +Keys [3]: [supp_nation#X, cust_nation#X, l_year#X] +Functions [1]: [sum(volume#X)] +Aggregate Attributes [1]: [sum(volume#X)#X] +Results [4]: [supp_nation#X, cust_nation#X, l_year#X, sum(volume#X)#X AS revenue#X] + +(53) WholeStageCodegenTransformer (X) +Input [4]: [supp_nation#X, cust_nation#X, l_year#X, revenue#X] +Arguments: false + +(54) ColumnarExchange +Input [4]: [supp_nation#X, cust_nation#X, l_year#X, revenue#X] +Arguments: rangepartitioning(supp_nation#X ASC NULLS FIRST, cust_nation#X ASC NULLS FIRST, l_year#X ASC NULLS FIRST, 1), ENSURE_REQUIREMENTS, [plan_id=X], [id=#X] + +(55) ShuffleQueryStage +Output [4]: [supp_nation#X, cust_nation#X, l_year#X, revenue#X] +Arguments: X + +(56) InputAdapter +Input [4]: [supp_nation#X, cust_nation#X, l_year#X, revenue#X] + +(57) InputIteratorTransformer +Input [4]: [supp_nation#X, cust_nation#X, l_year#X, revenue#X] + +(58) SortExecTransformer +Input [4]: [supp_nation#X, cust_nation#X, l_year#X, revenue#X] +Arguments: [supp_nation#X ASC NULLS FIRST, cust_nation#X ASC NULLS FIRST, l_year#X ASC NULLS FIRST], true, 0 + +(59) WholeStageCodegenTransformer (X) +Input [4]: [supp_nation#X, cust_nation#X, l_year#X, revenue#X] +Arguments: false + +(60) VeloxColumnarToRowExec +Input [4]: [supp_nation#X, cust_nation#X, l_year#X, revenue#X] + +(61) Scan parquet +Output [2]: [s_suppkey#X, s_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(s_suppkey), IsNotNull(s_nationkey)] +ReadSchema: struct + +(62) Filter +Input [2]: [s_suppkey#X, s_nationkey#X] +Condition : (isnotnull(s_suppkey#X) AND isnotnull(s_nationkey#X)) + +(63) BroadcastExchange +Input [2]: [s_suppkey#X, s_nationkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(64) Scan parquet +Output [5]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_shipdate), GreaterThanOrEqual(l_shipdate,1995-01-01), LessThanOrEqual(l_shipdate,1996-12-31), IsNotNull(l_suppkey), IsNotNull(l_orderkey)] +ReadSchema: struct + +(65) Filter +Input [5]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Condition : ((((isnotnull(l_shipdate#X) AND (l_shipdate#X >= 1995-01-01)) AND (l_shipdate#X <= 1996-12-31)) AND isnotnull(l_suppkey#X)) AND isnotnull(l_orderkey#X)) + +(66) BroadcastHashJoin +Left keys [1]: [s_suppkey#X] +Right keys [1]: [l_suppkey#X] +Join condition: None + +(67) Project +Output [5]: [s_nationkey#X, l_orderkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Input [7]: [s_suppkey#X, s_nationkey#X, l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] + +(68) Scan parquet +Output [2]: [o_orderkey#X, o_custkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_orderkey), IsNotNull(o_custkey)] +ReadSchema: struct + +(69) Filter +Input [2]: [o_orderkey#X, o_custkey#X] +Condition : (isnotnull(o_orderkey#X) AND isnotnull(o_custkey#X)) + +(70) BroadcastExchange +Input [2]: [o_orderkey#X, o_custkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(71) BroadcastHashJoin +Left keys [1]: [l_orderkey#X] +Right keys [1]: [o_orderkey#X] +Join condition: None + +(72) Project +Output [5]: [s_nationkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X, o_custkey#X] +Input [7]: [s_nationkey#X, l_orderkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X, o_orderkey#X, o_custkey#X] + +(73) Scan parquet +Output [2]: [c_custkey#X, c_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(c_custkey), IsNotNull(c_nationkey)] +ReadSchema: struct + +(74) Filter +Input [2]: [c_custkey#X, c_nationkey#X] +Condition : (isnotnull(c_custkey#X) AND isnotnull(c_nationkey#X)) + +(75) BroadcastExchange +Input [2]: [c_custkey#X, c_nationkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(76) BroadcastHashJoin +Left keys [1]: [o_custkey#X] +Right keys [1]: [c_custkey#X] +Join condition: None + +(77) Project +Output [5]: [s_nationkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X, c_nationkey#X] +Input [7]: [s_nationkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X, o_custkey#X, c_custkey#X, c_nationkey#X] + +(78) Scan parquet +Output [2]: [n_nationkey#X, n_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_nationkey), Or(EqualTo(n_name,FRANCE),EqualTo(n_name,GERMANY))] +ReadSchema: struct + +(79) Filter +Input [2]: [n_nationkey#X, n_name#X] +Condition : (isnotnull(n_nationkey#X) AND ((n_name#X = FRANCE) OR (n_name#X = GERMANY))) + +(80) BroadcastExchange +Input [2]: [n_nationkey#X, n_name#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(81) BroadcastHashJoin +Left keys [1]: [s_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: None + +(82) Project +Output [5]: [l_extendedprice#X, l_discount#X, l_shipdate#X, c_nationkey#X, n_name#X] +Input [7]: [s_nationkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X, c_nationkey#X, n_nationkey#X, n_name#X] + +(83) Scan parquet +Output [2]: [n_nationkey#X, n_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_nationkey), Or(EqualTo(n_name,GERMANY),EqualTo(n_name,FRANCE))] +ReadSchema: struct + +(84) Filter +Input [2]: [n_nationkey#X, n_name#X] +Condition : (isnotnull(n_nationkey#X) AND ((n_name#X = GERMANY) OR (n_name#X = FRANCE))) + +(85) BroadcastExchange +Input [2]: [n_nationkey#X, n_name#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(86) BroadcastHashJoin +Left keys [1]: [c_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: (((n_name#X = FRANCE) AND (n_name#X = GERMANY)) OR ((n_name#X = GERMANY) AND (n_name#X = FRANCE))) + +(87) Project +Output [4]: [n_name#X AS supp_nation#X, n_name#X AS cust_nation#X, year(l_shipdate#X) AS l_year#X, CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) AS volume#X] +Input [7]: [l_extendedprice#X, l_discount#X, l_shipdate#X, c_nationkey#X, n_name#X, n_nationkey#X, n_name#X] + +(88) HashAggregate +Input [4]: [supp_nation#X, cust_nation#X, l_year#X, volume#X] +Keys [3]: [supp_nation#X, cust_nation#X, l_year#X] +Functions [1]: [partial_sum(volume#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [5]: [supp_nation#X, cust_nation#X, l_year#X, sum#X, isEmpty#X] + +(89) Exchange +Input [5]: [supp_nation#X, cust_nation#X, l_year#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(supp_nation#X, cust_nation#X, l_year#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(90) HashAggregate +Input [5]: [supp_nation#X, cust_nation#X, l_year#X, sum#X, isEmpty#X] +Keys [3]: [supp_nation#X, cust_nation#X, l_year#X] +Functions [1]: [sum(volume#X)] +Aggregate Attributes [1]: [sum(volume#X)#X] +Results [4]: [supp_nation#X, cust_nation#X, l_year#X, sum(volume#X)#X AS revenue#X] + +(91) Exchange +Input [4]: [supp_nation#X, cust_nation#X, l_year#X, revenue#X] +Arguments: rangepartitioning(supp_nation#X ASC NULLS FIRST, cust_nation#X ASC NULLS FIRST, l_year#X ASC NULLS FIRST, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(92) Sort +Input [4]: [supp_nation#X, cust_nation#X, l_year#X, revenue#X] +Arguments: [supp_nation#X ASC NULLS FIRST, cust_nation#X ASC NULLS FIRST, l_year#X ASC NULLS FIRST], true, 0 + +(93) AdaptiveSparkPlan +Output [4]: [supp_nation#X, cust_nation#X, l_year#X, revenue#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/8.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/8.txt new file mode 100644 index 000000000000..aa6ded6ff2d6 --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/8.txt @@ -0,0 +1,694 @@ +== Physical Plan == +AdaptiveSparkPlan (129) ++- == Final Plan == + VeloxColumnarToRowExec (84) + +- ^ SortExecTransformer (82) + +- ^ InputIteratorTransformer (81) + +- ^ InputAdapter (80) + +- ^ ShuffleQueryStage (79) + +- ColumnarExchange (78) + +- ^ ProjectExecTransformer (76) + +- ^ RegularHashAggregateExecTransformer (75) + +- ^ InputIteratorTransformer (74) + +- ^ InputAdapter (73) + +- ^ ShuffleQueryStage (72) + +- ColumnarExchange (71) + +- ^ ProjectExecTransformer (69) + +- ^ FlushableHashAggregateExecTransformer (68) + +- ^ ProjectExecTransformer (67) + +- ^ GlutenBroadcastHashJoinExecTransformer Inner (66) + :- ^ ProjectExecTransformer (57) + : +- ^ GlutenBroadcastHashJoinExecTransformer Inner (56) + : :- ^ ProjectExecTransformer (48) + : : +- ^ GlutenBroadcastHashJoinExecTransformer Inner (47) + : : :- ^ ProjectExecTransformer (39) + : : : +- ^ GlutenBroadcastHashJoinExecTransformer Inner (38) + : : : :- ^ ProjectExecTransformer (30) + : : : : +- ^ GlutenBroadcastHashJoinExecTransformer Inner (29) + : : : : :- ^ ProjectExecTransformer (21) + : : : : : +- ^ GlutenBroadcastHashJoinExecTransformer Inner (20) + : : : : : :- ^ ProjectExecTransformer (12) + : : : : : : +- ^ GlutenBroadcastHashJoinExecTransformer Inner (11) + : : : : : : :- ^ InputIteratorTransformer (8) + : : : : : : : +- ^ InputAdapter (7) + : : : : : : : +- ^ BroadcastQueryStage (6) + : : : : : : : +- ColumnarBroadcastExchange (5) + : : : : : : : +- ^ ProjectExecTransformer (3) + : : : : : : : +- ^ FilterExecTransformer (2) + : : : : : : : +- ^ Scan parquet (1) + : : : : : : +- ^ FilterExecTransformer (10) + : : : : : : +- ^ Scan parquet (9) + : : : : : +- ^ InputIteratorTransformer (19) + : : : : : +- ^ InputAdapter (18) + : : : : : +- ^ BroadcastQueryStage (17) + : : : : : +- ColumnarBroadcastExchange (16) + : : : : : +- ^ FilterExecTransformer (14) + : : : : : +- ^ Scan parquet (13) + : : : : +- ^ InputIteratorTransformer (28) + : : : : +- ^ InputAdapter (27) + : : : : +- ^ BroadcastQueryStage (26) + : : : : +- ColumnarBroadcastExchange (25) + : : : : +- ^ FilterExecTransformer (23) + : : : : +- ^ Scan parquet (22) + : : : +- ^ InputIteratorTransformer (37) + : : : +- ^ InputAdapter (36) + : : : +- ^ BroadcastQueryStage (35) + : : : +- ColumnarBroadcastExchange (34) + : : : +- ^ FilterExecTransformer (32) + : : : +- ^ Scan parquet (31) + : : +- ^ InputIteratorTransformer (46) + : : +- ^ InputAdapter (45) + : : +- ^ BroadcastQueryStage (44) + : : +- ColumnarBroadcastExchange (43) + : : +- ^ FilterExecTransformer (41) + : : +- ^ Scan parquet (40) + : +- ^ InputIteratorTransformer (55) + : +- ^ InputAdapter (54) + : +- ^ BroadcastQueryStage (53) + : +- ColumnarBroadcastExchange (52) + : +- ^ FilterExecTransformer (50) + : +- ^ Scan parquet (49) + +- ^ InputIteratorTransformer (65) + +- ^ InputAdapter (64) + +- ^ BroadcastQueryStage (63) + +- ColumnarBroadcastExchange (62) + +- ^ ProjectExecTransformer (60) + +- ^ FilterExecTransformer (59) + +- ^ Scan parquet (58) ++- == Initial Plan == + Sort (128) + +- Exchange (127) + +- HashAggregate (126) + +- Exchange (125) + +- HashAggregate (124) + +- Project (123) + +- BroadcastHashJoin Inner BuildRight (122) + :- Project (117) + : +- BroadcastHashJoin Inner BuildRight (116) + : :- Project (112) + : : +- BroadcastHashJoin Inner BuildRight (111) + : : :- Project (107) + : : : +- BroadcastHashJoin Inner BuildRight (106) + : : : :- Project (102) + : : : : +- BroadcastHashJoin Inner BuildRight (101) + : : : : :- Project (97) + : : : : : +- BroadcastHashJoin Inner BuildRight (96) + : : : : : :- Project (92) + : : : : : : +- BroadcastHashJoin Inner BuildLeft (91) + : : : : : : :- BroadcastExchange (88) + : : : : : : : +- Project (87) + : : : : : : : +- Filter (86) + : : : : : : : +- Scan parquet (85) + : : : : : : +- Filter (90) + : : : : : : +- Scan parquet (89) + : : : : : +- BroadcastExchange (95) + : : : : : +- Filter (94) + : : : : : +- Scan parquet (93) + : : : : +- BroadcastExchange (100) + : : : : +- Filter (99) + : : : : +- Scan parquet (98) + : : : +- BroadcastExchange (105) + : : : +- Filter (104) + : : : +- Scan parquet (103) + : : +- BroadcastExchange (110) + : : +- Filter (109) + : : +- Scan parquet (108) + : +- BroadcastExchange (115) + : +- Filter (114) + : +- Scan parquet (113) + +- BroadcastExchange (121) + +- Project (120) + +- Filter (119) + +- Scan parquet (118) + + +(1) Scan parquet +Output [2]: [p_partkey#X, p_type#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(p_type), EqualTo(p_type,ECONOMY ANODIZED STEEL), IsNotNull(p_partkey)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [2]: [p_partkey#X, p_type#X] +Arguments: ((isnotnull(p_type#X) AND (p_type#X = ECONOMY ANODIZED STEEL)) AND isnotnull(p_partkey#X)) + +(3) ProjectExecTransformer +Output [1]: [p_partkey#X] +Input [2]: [p_partkey#X, p_type#X] + +(4) WholeStageCodegenTransformer (X) +Input [1]: [p_partkey#X] +Arguments: false + +(5) ColumnarBroadcastExchange +Input [1]: [p_partkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(6) BroadcastQueryStage +Output [1]: [p_partkey#X] +Arguments: X + +(7) InputAdapter +Input [1]: [p_partkey#X] + +(8) InputIteratorTransformer +Input [1]: [p_partkey#X] + +(9) Scan parquet +Output [5]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_partkey), IsNotNull(l_suppkey), IsNotNull(l_orderkey)] +ReadSchema: struct + +(10) FilterExecTransformer +Input [5]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Arguments: ((isnotnull(l_partkey#X) AND isnotnull(l_suppkey#X)) AND isnotnull(l_orderkey#X)) + +(11) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [p_partkey#X] +Right keys [1]: [l_partkey#X] +Join condition: None + +(12) ProjectExecTransformer +Output [4]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Input [6]: [p_partkey#X, l_orderkey#X, l_partkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] + +(13) Scan parquet +Output [2]: [s_suppkey#X, s_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(s_suppkey), IsNotNull(s_nationkey)] +ReadSchema: struct + +(14) FilterExecTransformer +Input [2]: [s_suppkey#X, s_nationkey#X] +Arguments: (isnotnull(s_suppkey#X) AND isnotnull(s_nationkey#X)) + +(15) WholeStageCodegenTransformer (X) +Input [2]: [s_suppkey#X, s_nationkey#X] +Arguments: false + +(16) ColumnarBroadcastExchange +Input [2]: [s_suppkey#X, s_nationkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(17) BroadcastQueryStage +Output [2]: [s_suppkey#X, s_nationkey#X] +Arguments: X + +(18) InputAdapter +Input [2]: [s_suppkey#X, s_nationkey#X] + +(19) InputIteratorTransformer +Input [2]: [s_suppkey#X, s_nationkey#X] + +(20) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [l_suppkey#X] +Right keys [1]: [s_suppkey#X] +Join condition: None + +(21) ProjectExecTransformer +Output [4]: [l_orderkey#X, l_extendedprice#X, l_discount#X, s_nationkey#X] +Input [6]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X, s_suppkey#X, s_nationkey#X] + +(22) Scan parquet +Output [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_orderdate), GreaterThanOrEqual(o_orderdate,1995-01-01), LessThanOrEqual(o_orderdate,1996-12-31), IsNotNull(o_orderkey), IsNotNull(o_custkey)] +ReadSchema: struct + +(23) FilterExecTransformer +Input [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] +Arguments: ((((isnotnull(o_orderdate#X) AND (o_orderdate#X >= 1995-01-01)) AND (o_orderdate#X <= 1996-12-31)) AND isnotnull(o_orderkey#X)) AND isnotnull(o_custkey#X)) + +(24) WholeStageCodegenTransformer (X) +Input [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] +Arguments: false + +(25) ColumnarBroadcastExchange +Input [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(26) BroadcastQueryStage +Output [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] +Arguments: X + +(27) InputAdapter +Input [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] + +(28) InputIteratorTransformer +Input [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] + +(29) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [l_orderkey#X] +Right keys [1]: [o_orderkey#X] +Join condition: None + +(30) ProjectExecTransformer +Output [5]: [l_extendedprice#X, l_discount#X, s_nationkey#X, o_custkey#X, o_orderdate#X] +Input [7]: [l_orderkey#X, l_extendedprice#X, l_discount#X, s_nationkey#X, o_orderkey#X, o_custkey#X, o_orderdate#X] + +(31) Scan parquet +Output [2]: [c_custkey#X, c_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(c_custkey), IsNotNull(c_nationkey)] +ReadSchema: struct + +(32) FilterExecTransformer +Input [2]: [c_custkey#X, c_nationkey#X] +Arguments: (isnotnull(c_custkey#X) AND isnotnull(c_nationkey#X)) + +(33) WholeStageCodegenTransformer (X) +Input [2]: [c_custkey#X, c_nationkey#X] +Arguments: false + +(34) ColumnarBroadcastExchange +Input [2]: [c_custkey#X, c_nationkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(35) BroadcastQueryStage +Output [2]: [c_custkey#X, c_nationkey#X] +Arguments: X + +(36) InputAdapter +Input [2]: [c_custkey#X, c_nationkey#X] + +(37) InputIteratorTransformer +Input [2]: [c_custkey#X, c_nationkey#X] + +(38) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [o_custkey#X] +Right keys [1]: [c_custkey#X] +Join condition: None + +(39) ProjectExecTransformer +Output [5]: [l_extendedprice#X, l_discount#X, s_nationkey#X, o_orderdate#X, c_nationkey#X] +Input [7]: [l_extendedprice#X, l_discount#X, s_nationkey#X, o_custkey#X, o_orderdate#X, c_custkey#X, c_nationkey#X] + +(40) Scan parquet +Output [2]: [n_nationkey#X, n_regionkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_nationkey), IsNotNull(n_regionkey)] +ReadSchema: struct + +(41) FilterExecTransformer +Input [2]: [n_nationkey#X, n_regionkey#X] +Arguments: (isnotnull(n_nationkey#X) AND isnotnull(n_regionkey#X)) + +(42) WholeStageCodegenTransformer (X) +Input [2]: [n_nationkey#X, n_regionkey#X] +Arguments: false + +(43) ColumnarBroadcastExchange +Input [2]: [n_nationkey#X, n_regionkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(44) BroadcastQueryStage +Output [2]: [n_nationkey#X, n_regionkey#X] +Arguments: X + +(45) InputAdapter +Input [2]: [n_nationkey#X, n_regionkey#X] + +(46) InputIteratorTransformer +Input [2]: [n_nationkey#X, n_regionkey#X] + +(47) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [c_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: None + +(48) ProjectExecTransformer +Output [5]: [l_extendedprice#X, l_discount#X, s_nationkey#X, o_orderdate#X, n_regionkey#X] +Input [7]: [l_extendedprice#X, l_discount#X, s_nationkey#X, o_orderdate#X, c_nationkey#X, n_nationkey#X, n_regionkey#X] + +(49) Scan parquet +Output [2]: [n_nationkey#X, n_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_nationkey)] +ReadSchema: struct + +(50) FilterExecTransformer +Input [2]: [n_nationkey#X, n_name#X] +Arguments: isnotnull(n_nationkey#X) + +(51) WholeStageCodegenTransformer (X) +Input [2]: [n_nationkey#X, n_name#X] +Arguments: false + +(52) ColumnarBroadcastExchange +Input [2]: [n_nationkey#X, n_name#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(53) BroadcastQueryStage +Output [2]: [n_nationkey#X, n_name#X] +Arguments: X + +(54) InputAdapter +Input [2]: [n_nationkey#X, n_name#X] + +(55) InputIteratorTransformer +Input [2]: [n_nationkey#X, n_name#X] + +(56) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [s_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: None + +(57) ProjectExecTransformer +Output [5]: [l_extendedprice#X, l_discount#X, o_orderdate#X, n_regionkey#X, n_name#X] +Input [7]: [l_extendedprice#X, l_discount#X, s_nationkey#X, o_orderdate#X, n_regionkey#X, n_nationkey#X, n_name#X] + +(58) Scan parquet +Output [2]: [r_regionkey#X, r_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(r_name), EqualTo(r_name,AMERICA), IsNotNull(r_regionkey)] +ReadSchema: struct + +(59) FilterExecTransformer +Input [2]: [r_regionkey#X, r_name#X] +Arguments: ((isnotnull(r_name#X) AND (r_name#X = AMERICA)) AND isnotnull(r_regionkey#X)) + +(60) ProjectExecTransformer +Output [1]: [r_regionkey#X] +Input [2]: [r_regionkey#X, r_name#X] + +(61) WholeStageCodegenTransformer (X) +Input [1]: [r_regionkey#X] +Arguments: false + +(62) ColumnarBroadcastExchange +Input [1]: [r_regionkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(63) BroadcastQueryStage +Output [1]: [r_regionkey#X] +Arguments: X + +(64) InputAdapter +Input [1]: [r_regionkey#X] + +(65) InputIteratorTransformer +Input [1]: [r_regionkey#X] + +(66) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [n_regionkey#X] +Right keys [1]: [r_regionkey#X] +Join condition: None + +(67) ProjectExecTransformer +Output [4]: [year(o_orderdate#X) AS o_year#X, CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) AS volume#X, n_name#X AS nation#X, CASE WHEN (n_name#X = BRAZIL) THEN CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) ELSE 0.0000 END AS _pre_129#X] +Input [6]: [l_extendedprice#X, l_discount#X, o_orderdate#X, n_regionkey#X, n_name#X, r_regionkey#X] + +(68) FlushableHashAggregateExecTransformer +Input [4]: [o_year#X, volume#X, nation#X, _pre_129#X] +Keys [1]: [o_year#X] +Functions [2]: [partial_sum(_pre_129#X), partial_sum(volume#X)] +Aggregate Attributes [4]: [sum#X, isEmpty#X, sum#X, isEmpty#X] +Results [5]: [o_year#X, sum#X, isEmpty#X, sum#X, isEmpty#X] + +(69) ProjectExecTransformer +Output [6]: [hash(o_year#X, 42) AS hash_partition_key#X, o_year#X, sum#X, isEmpty#X, sum#X, isEmpty#X] +Input [5]: [o_year#X, sum#X, isEmpty#X, sum#X, isEmpty#X] + +(70) WholeStageCodegenTransformer (X) +Input [6]: [hash_partition_key#X, o_year#X, sum#X, isEmpty#X, sum#X, isEmpty#X] +Arguments: false + +(71) ColumnarExchange +Input [6]: [hash_partition_key#X, o_year#X, sum#X, isEmpty#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(o_year#X, 1), ENSURE_REQUIREMENTS, [o_year#X, sum#X, isEmpty#X, sum#X, isEmpty#X], [plan_id=X], [id=#X] + +(72) ShuffleQueryStage +Output [5]: [o_year#X, sum#X, isEmpty#X, sum#X, isEmpty#X] +Arguments: X + +(73) InputAdapter +Input [5]: [o_year#X, sum#X, isEmpty#X, sum#X, isEmpty#X] + +(74) InputIteratorTransformer +Input [5]: [o_year#X, sum#X, isEmpty#X, sum#X, isEmpty#X] + +(75) RegularHashAggregateExecTransformer +Input [5]: [o_year#X, sum#X, isEmpty#X, sum#X, isEmpty#X] +Keys [1]: [o_year#X] +Functions [2]: [sum(CASE WHEN (nation#X = BRAZIL) THEN volume#X ELSE 0.0000 END), sum(volume#X)] +Aggregate Attributes [2]: [sum(CASE WHEN (nation#X = BRAZIL) THEN volume#X ELSE 0.0000 END)#X, sum(volume#X)#X] +Results [3]: [o_year#X, sum(CASE WHEN (nation#X = BRAZIL) THEN volume#X ELSE 0.0000 END)#X, sum(volume#X)#X] + +(76) ProjectExecTransformer +Output [2]: [o_year#X, CheckOverflow((promote_precision(sum(CASE WHEN (nation#X = BRAZIL) THEN volume#X ELSE 0.0000 END)#X) / promote_precision(sum(volume#X)#X)), DecimalType(38,6), true) AS mkt_share#X] +Input [3]: [o_year#X, sum(CASE WHEN (nation#X = BRAZIL) THEN volume#X ELSE 0.0000 END)#X, sum(volume#X)#X] + +(77) WholeStageCodegenTransformer (X) +Input [2]: [o_year#X, mkt_share#X] +Arguments: false + +(78) ColumnarExchange +Input [2]: [o_year#X, mkt_share#X] +Arguments: rangepartitioning(o_year#X ASC NULLS FIRST, 1), ENSURE_REQUIREMENTS, [plan_id=X], [id=#X] + +(79) ShuffleQueryStage +Output [2]: [o_year#X, mkt_share#X] +Arguments: X + +(80) InputAdapter +Input [2]: [o_year#X, mkt_share#X] + +(81) InputIteratorTransformer +Input [2]: [o_year#X, mkt_share#X] + +(82) SortExecTransformer +Input [2]: [o_year#X, mkt_share#X] +Arguments: [o_year#X ASC NULLS FIRST], true, 0 + +(83) WholeStageCodegenTransformer (X) +Input [2]: [o_year#X, mkt_share#X] +Arguments: false + +(84) VeloxColumnarToRowExec +Input [2]: [o_year#X, mkt_share#X] + +(85) Scan parquet +Output [2]: [p_partkey#X, p_type#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(p_type), EqualTo(p_type,ECONOMY ANODIZED STEEL), IsNotNull(p_partkey)] +ReadSchema: struct + +(86) Filter +Input [2]: [p_partkey#X, p_type#X] +Condition : ((isnotnull(p_type#X) AND (p_type#X = ECONOMY ANODIZED STEEL)) AND isnotnull(p_partkey#X)) + +(87) Project +Output [1]: [p_partkey#X] +Input [2]: [p_partkey#X, p_type#X] + +(88) BroadcastExchange +Input [1]: [p_partkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(89) Scan parquet +Output [5]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_partkey), IsNotNull(l_suppkey), IsNotNull(l_orderkey)] +ReadSchema: struct + +(90) Filter +Input [5]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Condition : ((isnotnull(l_partkey#X) AND isnotnull(l_suppkey#X)) AND isnotnull(l_orderkey#X)) + +(91) BroadcastHashJoin +Left keys [1]: [p_partkey#X] +Right keys [1]: [l_partkey#X] +Join condition: None + +(92) Project +Output [4]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Input [6]: [p_partkey#X, l_orderkey#X, l_partkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] + +(93) Scan parquet +Output [2]: [s_suppkey#X, s_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(s_suppkey), IsNotNull(s_nationkey)] +ReadSchema: struct + +(94) Filter +Input [2]: [s_suppkey#X, s_nationkey#X] +Condition : (isnotnull(s_suppkey#X) AND isnotnull(s_nationkey#X)) + +(95) BroadcastExchange +Input [2]: [s_suppkey#X, s_nationkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(96) BroadcastHashJoin +Left keys [1]: [l_suppkey#X] +Right keys [1]: [s_suppkey#X] +Join condition: None + +(97) Project +Output [4]: [l_orderkey#X, l_extendedprice#X, l_discount#X, s_nationkey#X] +Input [6]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X, s_suppkey#X, s_nationkey#X] + +(98) Scan parquet +Output [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_orderdate), GreaterThanOrEqual(o_orderdate,1995-01-01), LessThanOrEqual(o_orderdate,1996-12-31), IsNotNull(o_orderkey), IsNotNull(o_custkey)] +ReadSchema: struct + +(99) Filter +Input [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] +Condition : ((((isnotnull(o_orderdate#X) AND (o_orderdate#X >= 1995-01-01)) AND (o_orderdate#X <= 1996-12-31)) AND isnotnull(o_orderkey#X)) AND isnotnull(o_custkey#X)) + +(100) BroadcastExchange +Input [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(101) BroadcastHashJoin +Left keys [1]: [l_orderkey#X] +Right keys [1]: [o_orderkey#X] +Join condition: None + +(102) Project +Output [5]: [l_extendedprice#X, l_discount#X, s_nationkey#X, o_custkey#X, o_orderdate#X] +Input [7]: [l_orderkey#X, l_extendedprice#X, l_discount#X, s_nationkey#X, o_orderkey#X, o_custkey#X, o_orderdate#X] + +(103) Scan parquet +Output [2]: [c_custkey#X, c_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(c_custkey), IsNotNull(c_nationkey)] +ReadSchema: struct + +(104) Filter +Input [2]: [c_custkey#X, c_nationkey#X] +Condition : (isnotnull(c_custkey#X) AND isnotnull(c_nationkey#X)) + +(105) BroadcastExchange +Input [2]: [c_custkey#X, c_nationkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(106) BroadcastHashJoin +Left keys [1]: [o_custkey#X] +Right keys [1]: [c_custkey#X] +Join condition: None + +(107) Project +Output [5]: [l_extendedprice#X, l_discount#X, s_nationkey#X, o_orderdate#X, c_nationkey#X] +Input [7]: [l_extendedprice#X, l_discount#X, s_nationkey#X, o_custkey#X, o_orderdate#X, c_custkey#X, c_nationkey#X] + +(108) Scan parquet +Output [2]: [n_nationkey#X, n_regionkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_nationkey), IsNotNull(n_regionkey)] +ReadSchema: struct + +(109) Filter +Input [2]: [n_nationkey#X, n_regionkey#X] +Condition : (isnotnull(n_nationkey#X) AND isnotnull(n_regionkey#X)) + +(110) BroadcastExchange +Input [2]: [n_nationkey#X, n_regionkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(111) BroadcastHashJoin +Left keys [1]: [c_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: None + +(112) Project +Output [5]: [l_extendedprice#X, l_discount#X, s_nationkey#X, o_orderdate#X, n_regionkey#X] +Input [7]: [l_extendedprice#X, l_discount#X, s_nationkey#X, o_orderdate#X, c_nationkey#X, n_nationkey#X, n_regionkey#X] + +(113) Scan parquet +Output [2]: [n_nationkey#X, n_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_nationkey)] +ReadSchema: struct + +(114) Filter +Input [2]: [n_nationkey#X, n_name#X] +Condition : isnotnull(n_nationkey#X) + +(115) BroadcastExchange +Input [2]: [n_nationkey#X, n_name#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(116) BroadcastHashJoin +Left keys [1]: [s_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: None + +(117) Project +Output [5]: [l_extendedprice#X, l_discount#X, o_orderdate#X, n_regionkey#X, n_name#X] +Input [7]: [l_extendedprice#X, l_discount#X, s_nationkey#X, o_orderdate#X, n_regionkey#X, n_nationkey#X, n_name#X] + +(118) Scan parquet +Output [2]: [r_regionkey#X, r_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(r_name), EqualTo(r_name,AMERICA), IsNotNull(r_regionkey)] +ReadSchema: struct + +(119) Filter +Input [2]: [r_regionkey#X, r_name#X] +Condition : ((isnotnull(r_name#X) AND (r_name#X = AMERICA)) AND isnotnull(r_regionkey#X)) + +(120) Project +Output [1]: [r_regionkey#X] +Input [2]: [r_regionkey#X, r_name#X] + +(121) BroadcastExchange +Input [1]: [r_regionkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(122) BroadcastHashJoin +Left keys [1]: [n_regionkey#X] +Right keys [1]: [r_regionkey#X] +Join condition: None + +(123) Project +Output [3]: [year(o_orderdate#X) AS o_year#X, CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) AS volume#X, n_name#X AS nation#X] +Input [6]: [l_extendedprice#X, l_discount#X, o_orderdate#X, n_regionkey#X, n_name#X, r_regionkey#X] + +(124) HashAggregate +Input [3]: [o_year#X, volume#X, nation#X] +Keys [1]: [o_year#X] +Functions [2]: [partial_sum(CASE WHEN (nation#X = BRAZIL) THEN volume#X ELSE 0.0000 END), partial_sum(volume#X)] +Aggregate Attributes [4]: [sum#X, isEmpty#X, sum#X, isEmpty#X] +Results [5]: [o_year#X, sum#X, isEmpty#X, sum#X, isEmpty#X] + +(125) Exchange +Input [5]: [o_year#X, sum#X, isEmpty#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(o_year#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(126) HashAggregate +Input [5]: [o_year#X, sum#X, isEmpty#X, sum#X, isEmpty#X] +Keys [1]: [o_year#X] +Functions [2]: [sum(CASE WHEN (nation#X = BRAZIL) THEN volume#X ELSE 0.0000 END), sum(volume#X)] +Aggregate Attributes [2]: [sum(CASE WHEN (nation#X = BRAZIL) THEN volume#X ELSE 0.0000 END)#X, sum(volume#X)#X] +Results [2]: [o_year#X, CheckOverflow((promote_precision(sum(CASE WHEN (nation#X = BRAZIL) THEN volume#X ELSE 0.0000 END)#X) / promote_precision(sum(volume#X)#X)), DecimalType(38,6), true) AS mkt_share#X] + +(127) Exchange +Input [2]: [o_year#X, mkt_share#X] +Arguments: rangepartitioning(o_year#X ASC NULLS FIRST, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(128) Sort +Input [2]: [o_year#X, mkt_share#X] +Arguments: [o_year#X ASC NULLS FIRST], true, 0 + +(129) AdaptiveSparkPlan +Output [2]: [o_year#X, mkt_share#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/9.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/9.txt new file mode 100644 index 000000000000..1bc815000473 --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1-bhj/spark322/9.txt @@ -0,0 +1,529 @@ +== Physical Plan == +AdaptiveSparkPlan (98) ++- == Final Plan == + VeloxColumnarToRowExec (64) + +- ^ SortExecTransformer (62) + +- ^ InputIteratorTransformer (61) + +- ^ InputAdapter (60) + +- ^ ShuffleQueryStage (59) + +- ColumnarExchange (58) + +- ^ RegularHashAggregateExecTransformer (56) + +- ^ InputIteratorTransformer (55) + +- ^ InputAdapter (54) + +- ^ ShuffleQueryStage (53) + +- ColumnarExchange (52) + +- ^ ProjectExecTransformer (50) + +- ^ FlushableHashAggregateExecTransformer (49) + +- ^ ProjectExecTransformer (48) + +- ^ GlutenBroadcastHashJoinExecTransformer Inner (47) + :- ^ ProjectExecTransformer (39) + : +- ^ GlutenBroadcastHashJoinExecTransformer Inner (38) + : :- ^ ProjectExecTransformer (30) + : : +- ^ GlutenBroadcastHashJoinExecTransformer Inner (29) + : : :- ^ ProjectExecTransformer (21) + : : : +- ^ GlutenBroadcastHashJoinExecTransformer Inner (20) + : : : :- ^ ProjectExecTransformer (12) + : : : : +- ^ GlutenBroadcastHashJoinExecTransformer Inner (11) + : : : : :- ^ InputIteratorTransformer (8) + : : : : : +- ^ InputAdapter (7) + : : : : : +- ^ BroadcastQueryStage (6) + : : : : : +- ColumnarBroadcastExchange (5) + : : : : : +- ^ ProjectExecTransformer (3) + : : : : : +- ^ FilterExecTransformer (2) + : : : : : +- ^ Scan parquet (1) + : : : : +- ^ FilterExecTransformer (10) + : : : : +- ^ Scan parquet (9) + : : : +- ^ InputIteratorTransformer (19) + : : : +- ^ InputAdapter (18) + : : : +- ^ BroadcastQueryStage (17) + : : : +- ColumnarBroadcastExchange (16) + : : : +- ^ FilterExecTransformer (14) + : : : +- ^ Scan parquet (13) + : : +- ^ InputIteratorTransformer (28) + : : +- ^ InputAdapter (27) + : : +- ^ BroadcastQueryStage (26) + : : +- ColumnarBroadcastExchange (25) + : : +- ^ FilterExecTransformer (23) + : : +- ^ Scan parquet (22) + : +- ^ InputIteratorTransformer (37) + : +- ^ InputAdapter (36) + : +- ^ BroadcastQueryStage (35) + : +- ColumnarBroadcastExchange (34) + : +- ^ FilterExecTransformer (32) + : +- ^ Scan parquet (31) + +- ^ InputIteratorTransformer (46) + +- ^ InputAdapter (45) + +- ^ BroadcastQueryStage (44) + +- ColumnarBroadcastExchange (43) + +- ^ FilterExecTransformer (41) + +- ^ Scan parquet (40) ++- == Initial Plan == + Sort (97) + +- Exchange (96) + +- HashAggregate (95) + +- Exchange (94) + +- HashAggregate (93) + +- Project (92) + +- BroadcastHashJoin Inner BuildRight (91) + :- Project (87) + : +- BroadcastHashJoin Inner BuildRight (86) + : :- Project (82) + : : +- BroadcastHashJoin Inner BuildRight (81) + : : :- Project (77) + : : : +- BroadcastHashJoin Inner BuildRight (76) + : : : :- Project (72) + : : : : +- BroadcastHashJoin Inner BuildLeft (71) + : : : : :- BroadcastExchange (68) + : : : : : +- Project (67) + : : : : : +- Filter (66) + : : : : : +- Scan parquet (65) + : : : : +- Filter (70) + : : : : +- Scan parquet (69) + : : : +- BroadcastExchange (75) + : : : +- Filter (74) + : : : +- Scan parquet (73) + : : +- BroadcastExchange (80) + : : +- Filter (79) + : : +- Scan parquet (78) + : +- BroadcastExchange (85) + : +- Filter (84) + : +- Scan parquet (83) + +- BroadcastExchange (90) + +- Filter (89) + +- Scan parquet (88) + + +(1) Scan parquet +Output [2]: [p_partkey#X, p_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(p_name), StringContains(p_name,green), IsNotNull(p_partkey)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [2]: [p_partkey#X, p_name#X] +Arguments: ((isnotnull(p_name#X) AND Contains(p_name#X, green)) AND isnotnull(p_partkey#X)) + +(3) ProjectExecTransformer +Output [1]: [p_partkey#X] +Input [2]: [p_partkey#X, p_name#X] + +(4) WholeStageCodegenTransformer (X) +Input [1]: [p_partkey#X] +Arguments: false + +(5) ColumnarBroadcastExchange +Input [1]: [p_partkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(6) BroadcastQueryStage +Output [1]: [p_partkey#X] +Arguments: X + +(7) InputAdapter +Input [1]: [p_partkey#X] + +(8) InputIteratorTransformer +Input [1]: [p_partkey#X] + +(9) Scan parquet +Output [6]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_partkey), IsNotNull(l_suppkey), IsNotNull(l_orderkey)] +ReadSchema: struct + +(10) FilterExecTransformer +Input [6]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] +Arguments: ((isnotnull(l_partkey#X) AND isnotnull(l_suppkey#X)) AND isnotnull(l_orderkey#X)) + +(11) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [p_partkey#X] +Right keys [1]: [l_partkey#X] +Join condition: None + +(12) ProjectExecTransformer +Output [6]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] +Input [7]: [p_partkey#X, l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] + +(13) Scan parquet +Output [2]: [s_suppkey#X, s_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(s_suppkey), IsNotNull(s_nationkey)] +ReadSchema: struct + +(14) FilterExecTransformer +Input [2]: [s_suppkey#X, s_nationkey#X] +Arguments: (isnotnull(s_suppkey#X) AND isnotnull(s_nationkey#X)) + +(15) WholeStageCodegenTransformer (X) +Input [2]: [s_suppkey#X, s_nationkey#X] +Arguments: false + +(16) ColumnarBroadcastExchange +Input [2]: [s_suppkey#X, s_nationkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(17) BroadcastQueryStage +Output [2]: [s_suppkey#X, s_nationkey#X] +Arguments: X + +(18) InputAdapter +Input [2]: [s_suppkey#X, s_nationkey#X] + +(19) InputIteratorTransformer +Input [2]: [s_suppkey#X, s_nationkey#X] + +(20) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [l_suppkey#X] +Right keys [1]: [s_suppkey#X] +Join condition: None + +(21) ProjectExecTransformer +Output [7]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X] +Input [8]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_suppkey#X, s_nationkey#X] + +(22) Scan parquet +Output [3]: [ps_partkey#X, ps_suppkey#X, ps_supplycost#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(ps_suppkey), IsNotNull(ps_partkey)] +ReadSchema: struct + +(23) FilterExecTransformer +Input [3]: [ps_partkey#X, ps_suppkey#X, ps_supplycost#X] +Arguments: (isnotnull(ps_suppkey#X) AND isnotnull(ps_partkey#X)) + +(24) WholeStageCodegenTransformer (X) +Input [3]: [ps_partkey#X, ps_suppkey#X, ps_supplycost#X] +Arguments: false + +(25) ColumnarBroadcastExchange +Input [3]: [ps_partkey#X, ps_suppkey#X, ps_supplycost#X] +Arguments: HashedRelationBroadcastMode(List(input[1, bigint, false], input[0, bigint, false]),false), [plan_id=X] + +(26) BroadcastQueryStage +Output [3]: [ps_partkey#X, ps_suppkey#X, ps_supplycost#X] +Arguments: X + +(27) InputAdapter +Input [3]: [ps_partkey#X, ps_suppkey#X, ps_supplycost#X] + +(28) InputIteratorTransformer +Input [3]: [ps_partkey#X, ps_suppkey#X, ps_supplycost#X] + +(29) GlutenBroadcastHashJoinExecTransformer +Left keys [2]: [l_suppkey#X, l_partkey#X] +Right keys [2]: [ps_suppkey#X, ps_partkey#X] +Join condition: None + +(30) ProjectExecTransformer +Output [6]: [l_orderkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X, ps_supplycost#X] +Input [10]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X, ps_partkey#X, ps_suppkey#X, ps_supplycost#X] + +(31) Scan parquet +Output [2]: [o_orderkey#X, o_orderdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_orderkey)] +ReadSchema: struct + +(32) FilterExecTransformer +Input [2]: [o_orderkey#X, o_orderdate#X] +Arguments: isnotnull(o_orderkey#X) + +(33) WholeStageCodegenTransformer (X) +Input [2]: [o_orderkey#X, o_orderdate#X] +Arguments: false + +(34) ColumnarBroadcastExchange +Input [2]: [o_orderkey#X, o_orderdate#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(35) BroadcastQueryStage +Output [2]: [o_orderkey#X, o_orderdate#X] +Arguments: X + +(36) InputAdapter +Input [2]: [o_orderkey#X, o_orderdate#X] + +(37) InputIteratorTransformer +Input [2]: [o_orderkey#X, o_orderdate#X] + +(38) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [l_orderkey#X] +Right keys [1]: [o_orderkey#X] +Join condition: None + +(39) ProjectExecTransformer +Output [6]: [l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X, ps_supplycost#X, o_orderdate#X] +Input [8]: [l_orderkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X, ps_supplycost#X, o_orderkey#X, o_orderdate#X] + +(40) Scan parquet +Output [2]: [n_nationkey#X, n_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_nationkey)] +ReadSchema: struct + +(41) FilterExecTransformer +Input [2]: [n_nationkey#X, n_name#X] +Arguments: isnotnull(n_nationkey#X) + +(42) WholeStageCodegenTransformer (X) +Input [2]: [n_nationkey#X, n_name#X] +Arguments: false + +(43) ColumnarBroadcastExchange +Input [2]: [n_nationkey#X, n_name#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(44) BroadcastQueryStage +Output [2]: [n_nationkey#X, n_name#X] +Arguments: X + +(45) InputAdapter +Input [2]: [n_nationkey#X, n_name#X] + +(46) InputIteratorTransformer +Input [2]: [n_nationkey#X, n_name#X] + +(47) GlutenBroadcastHashJoinExecTransformer +Left keys [1]: [s_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: None + +(48) ProjectExecTransformer +Output [3]: [n_name#X AS nation#X, year(o_orderdate#X) AS o_year#X, CheckOverflow((promote_precision(cast(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) as decimal(27,4))) - promote_precision(cast(CheckOverflow((promote_precision(ps_supplycost#X) * promote_precision(l_quantity#X)), DecimalType(25,4), true) as decimal(27,4)))), DecimalType(27,4), true) AS amount#X] +Input [8]: [l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X, ps_supplycost#X, o_orderdate#X, n_nationkey#X, n_name#X] + +(49) FlushableHashAggregateExecTransformer +Input [3]: [nation#X, o_year#X, amount#X] +Keys [2]: [nation#X, o_year#X] +Functions [1]: [partial_sum(amount#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [4]: [nation#X, o_year#X, sum#X, isEmpty#X] + +(50) ProjectExecTransformer +Output [5]: [hash(nation#X, o_year#X, 42) AS hash_partition_key#X, nation#X, o_year#X, sum#X, isEmpty#X] +Input [4]: [nation#X, o_year#X, sum#X, isEmpty#X] + +(51) WholeStageCodegenTransformer (X) +Input [5]: [hash_partition_key#X, nation#X, o_year#X, sum#X, isEmpty#X] +Arguments: false + +(52) ColumnarExchange +Input [5]: [hash_partition_key#X, nation#X, o_year#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(nation#X, o_year#X, 1), ENSURE_REQUIREMENTS, [nation#X, o_year#X, sum#X, isEmpty#X], [plan_id=X], [id=#X] + +(53) ShuffleQueryStage +Output [4]: [nation#X, o_year#X, sum#X, isEmpty#X] +Arguments: X + +(54) InputAdapter +Input [4]: [nation#X, o_year#X, sum#X, isEmpty#X] + +(55) InputIteratorTransformer +Input [4]: [nation#X, o_year#X, sum#X, isEmpty#X] + +(56) RegularHashAggregateExecTransformer +Input [4]: [nation#X, o_year#X, sum#X, isEmpty#X] +Keys [2]: [nation#X, o_year#X] +Functions [1]: [sum(amount#X)] +Aggregate Attributes [1]: [sum(amount#X)#X] +Results [3]: [nation#X, o_year#X, sum(amount#X)#X AS sum_profit#X] + +(57) WholeStageCodegenTransformer (X) +Input [3]: [nation#X, o_year#X, sum_profit#X] +Arguments: false + +(58) ColumnarExchange +Input [3]: [nation#X, o_year#X, sum_profit#X] +Arguments: rangepartitioning(nation#X ASC NULLS FIRST, o_year#X DESC NULLS LAST, 1), ENSURE_REQUIREMENTS, [plan_id=X], [id=#X] + +(59) ShuffleQueryStage +Output [3]: [nation#X, o_year#X, sum_profit#X] +Arguments: X + +(60) InputAdapter +Input [3]: [nation#X, o_year#X, sum_profit#X] + +(61) InputIteratorTransformer +Input [3]: [nation#X, o_year#X, sum_profit#X] + +(62) SortExecTransformer +Input [3]: [nation#X, o_year#X, sum_profit#X] +Arguments: [nation#X ASC NULLS FIRST, o_year#X DESC NULLS LAST], true, 0 + +(63) WholeStageCodegenTransformer (X) +Input [3]: [nation#X, o_year#X, sum_profit#X] +Arguments: false + +(64) VeloxColumnarToRowExec +Input [3]: [nation#X, o_year#X, sum_profit#X] + +(65) Scan parquet +Output [2]: [p_partkey#X, p_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(p_name), StringContains(p_name,green), IsNotNull(p_partkey)] +ReadSchema: struct + +(66) Filter +Input [2]: [p_partkey#X, p_name#X] +Condition : ((isnotnull(p_name#X) AND Contains(p_name#X, green)) AND isnotnull(p_partkey#X)) + +(67) Project +Output [1]: [p_partkey#X] +Input [2]: [p_partkey#X, p_name#X] + +(68) BroadcastExchange +Input [1]: [p_partkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),false), [plan_id=X] + +(69) Scan parquet +Output [6]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_partkey), IsNotNull(l_suppkey), IsNotNull(l_orderkey)] +ReadSchema: struct + +(70) Filter +Input [6]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] +Condition : ((isnotnull(l_partkey#X) AND isnotnull(l_suppkey#X)) AND isnotnull(l_orderkey#X)) + +(71) BroadcastHashJoin +Left keys [1]: [p_partkey#X] +Right keys [1]: [l_partkey#X] +Join condition: None + +(72) Project +Output [6]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] +Input [7]: [p_partkey#X, l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] + +(73) Scan parquet +Output [2]: [s_suppkey#X, s_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(s_suppkey), IsNotNull(s_nationkey)] +ReadSchema: struct + +(74) Filter +Input [2]: [s_suppkey#X, s_nationkey#X] +Condition : (isnotnull(s_suppkey#X) AND isnotnull(s_nationkey#X)) + +(75) BroadcastExchange +Input [2]: [s_suppkey#X, s_nationkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(76) BroadcastHashJoin +Left keys [1]: [l_suppkey#X] +Right keys [1]: [s_suppkey#X] +Join condition: None + +(77) Project +Output [7]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X] +Input [8]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_suppkey#X, s_nationkey#X] + +(78) Scan parquet +Output [3]: [ps_partkey#X, ps_suppkey#X, ps_supplycost#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(ps_suppkey), IsNotNull(ps_partkey)] +ReadSchema: struct + +(79) Filter +Input [3]: [ps_partkey#X, ps_suppkey#X, ps_supplycost#X] +Condition : (isnotnull(ps_suppkey#X) AND isnotnull(ps_partkey#X)) + +(80) BroadcastExchange +Input [3]: [ps_partkey#X, ps_suppkey#X, ps_supplycost#X] +Arguments: HashedRelationBroadcastMode(List(input[1, bigint, false], input[0, bigint, false]),false), [plan_id=X] + +(81) BroadcastHashJoin +Left keys [2]: [l_suppkey#X, l_partkey#X] +Right keys [2]: [ps_suppkey#X, ps_partkey#X] +Join condition: None + +(82) Project +Output [6]: [l_orderkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X, ps_supplycost#X] +Input [10]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X, ps_partkey#X, ps_suppkey#X, ps_supplycost#X] + +(83) Scan parquet +Output [2]: [o_orderkey#X, o_orderdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_orderkey)] +ReadSchema: struct + +(84) Filter +Input [2]: [o_orderkey#X, o_orderdate#X] +Condition : isnotnull(o_orderkey#X) + +(85) BroadcastExchange +Input [2]: [o_orderkey#X, o_orderdate#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(86) BroadcastHashJoin +Left keys [1]: [l_orderkey#X] +Right keys [1]: [o_orderkey#X] +Join condition: None + +(87) Project +Output [6]: [l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X, ps_supplycost#X, o_orderdate#X] +Input [8]: [l_orderkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X, ps_supplycost#X, o_orderkey#X, o_orderdate#X] + +(88) Scan parquet +Output [2]: [n_nationkey#X, n_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_nationkey)] +ReadSchema: struct + +(89) Filter +Input [2]: [n_nationkey#X, n_name#X] +Condition : isnotnull(n_nationkey#X) + +(90) BroadcastExchange +Input [2]: [n_nationkey#X, n_name#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, false]),false), [plan_id=X] + +(91) BroadcastHashJoin +Left keys [1]: [s_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: None + +(92) Project +Output [3]: [n_name#X AS nation#X, year(o_orderdate#X) AS o_year#X, CheckOverflow((promote_precision(cast(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) as decimal(27,4))) - promote_precision(cast(CheckOverflow((promote_precision(ps_supplycost#X) * promote_precision(l_quantity#X)), DecimalType(25,4), true) as decimal(27,4)))), DecimalType(27,4), true) AS amount#X] +Input [8]: [l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X, ps_supplycost#X, o_orderdate#X, n_nationkey#X, n_name#X] + +(93) HashAggregate +Input [3]: [nation#X, o_year#X, amount#X] +Keys [2]: [nation#X, o_year#X] +Functions [1]: [partial_sum(amount#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [4]: [nation#X, o_year#X, sum#X, isEmpty#X] + +(94) Exchange +Input [4]: [nation#X, o_year#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(nation#X, o_year#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(95) HashAggregate +Input [4]: [nation#X, o_year#X, sum#X, isEmpty#X] +Keys [2]: [nation#X, o_year#X] +Functions [1]: [sum(amount#X)] +Aggregate Attributes [1]: [sum(amount#X)#X] +Results [3]: [nation#X, o_year#X, sum(amount#X)#X AS sum_profit#X] + +(96) Exchange +Input [3]: [nation#X, o_year#X, sum_profit#X] +Arguments: rangepartitioning(nation#X ASC NULLS FIRST, o_year#X DESC NULLS LAST, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(97) Sort +Input [3]: [nation#X, o_year#X, sum_profit#X] +Arguments: [nation#X ASC NULLS FIRST, o_year#X DESC NULLS LAST], true, 0 + +(98) AdaptiveSparkPlan +Output [3]: [nation#X, o_year#X, sum_profit#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/1.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/1.txt new file mode 100644 index 000000000000..842321b2bdd7 --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/1.txt @@ -0,0 +1,154 @@ +== Physical Plan == +AdaptiveSparkPlan (28) ++- == Final Plan == + VeloxColumnarToRowExec (19) + +- ^ SortExecTransformer (17) + +- ^ InputIteratorTransformer (16) + +- ^ InputAdapter (15) + +- ^ ShuffleQueryStage (14) + +- ColumnarExchange (13) + +- ^ RegularHashAggregateExecTransformer (11) + +- ^ InputIteratorTransformer (10) + +- ^ InputAdapter (9) + +- ^ ShuffleQueryStage (8) + +- ColumnarExchange (7) + +- ^ ProjectExecTransformer (5) + +- ^ FlushableHashAggregateExecTransformer (4) + +- ^ ProjectExecTransformer (3) + +- ^ FilterExecTransformer (2) + +- ^ Scan parquet (1) ++- == Initial Plan == + Sort (27) + +- Exchange (26) + +- HashAggregate (25) + +- Exchange (24) + +- HashAggregate (23) + +- Project (22) + +- Filter (21) + +- Scan parquet (20) + + +(1) Scan parquet +Output [7]: [l_quantity#X, l_extendedprice#X, l_discount#X, l_tax#X, l_returnflag#X, l_linestatus#X, l_shipdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_shipdate), LessThanOrEqual(l_shipdate,1998-09-02)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [7]: [l_quantity#X, l_extendedprice#X, l_discount#X, l_tax#X, l_returnflag#X, l_linestatus#X, l_shipdate#X] +Arguments: (isnotnull(l_shipdate#X) AND (l_shipdate#X <= 1998-09-02)) + +(3) ProjectExecTransformer +Output [8]: [l_quantity#X, l_extendedprice#X, l_discount#X, l_tax#X, l_returnflag#X, l_linestatus#X, CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) AS _pre_108#X, CheckOverflow((promote_precision(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true)) * promote_precision(cast(CheckOverflow((1.00 + promote_precision(cast(l_tax#X as decimal(13,2)))), DecimalType(13,2), true) as decimal(26,4)))), DecimalType(38,6), true) AS _pre_109#X] +Input [7]: [l_quantity#X, l_extendedprice#X, l_discount#X, l_tax#X, l_returnflag#X, l_linestatus#X, l_shipdate#X] + +(4) FlushableHashAggregateExecTransformer +Input [8]: [l_quantity#X, l_extendedprice#X, l_discount#X, l_tax#X, l_returnflag#X, l_linestatus#X, _pre_108#X, _pre_109#X] +Keys [2]: [l_returnflag#X, l_linestatus#X] +Functions [8]: [partial_sum(l_quantity#X), partial_sum(l_extendedprice#X), partial_sum(_pre_108#X), partial_sum(_pre_109#X), partial_avg(l_quantity#X), partial_avg(l_extendedprice#X), partial_avg(l_discount#X), partial_count(1)] +Aggregate Attributes [15]: [sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, count#X, sum#X, count#X, sum#X, count#X, count#X] +Results [17]: [l_returnflag#X, l_linestatus#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, count#X, sum#X, count#X, sum#X, count#X, count#X] + +(5) ProjectExecTransformer +Output [18]: [hash(l_returnflag#X, l_linestatus#X, 42) AS hash_partition_key#X, l_returnflag#X, l_linestatus#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, count#X, sum#X, count#X, sum#X, count#X, count#X] +Input [17]: [l_returnflag#X, l_linestatus#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, count#X, sum#X, count#X, sum#X, count#X, count#X] + +(6) WholeStageCodegenTransformer (X) +Input [18]: [hash_partition_key#X, l_returnflag#X, l_linestatus#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, count#X, sum#X, count#X, sum#X, count#X, count#X] +Arguments: false + +(7) ColumnarExchange +Input [18]: [hash_partition_key#X, l_returnflag#X, l_linestatus#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, count#X, sum#X, count#X, sum#X, count#X, count#X] +Arguments: hashpartitioning(l_returnflag#X, l_linestatus#X, 1), ENSURE_REQUIREMENTS, [l_returnflag#X, l_linestatus#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, count#X, sum#X, count#X, sum#X, count#X, count#X], [plan_id=X], [id=#X] + +(8) ShuffleQueryStage +Output [17]: [l_returnflag#X, l_linestatus#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, count#X, sum#X, count#X, sum#X, count#X, count#X] +Arguments: X + +(9) InputAdapter +Input [17]: [l_returnflag#X, l_linestatus#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, count#X, sum#X, count#X, sum#X, count#X, count#X] + +(10) InputIteratorTransformer +Input [17]: [l_returnflag#X, l_linestatus#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, count#X, sum#X, count#X, sum#X, count#X, count#X] + +(11) RegularHashAggregateExecTransformer +Input [17]: [l_returnflag#X, l_linestatus#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, count#X, sum#X, count#X, sum#X, count#X, count#X] +Keys [2]: [l_returnflag#X, l_linestatus#X] +Functions [8]: [sum(l_quantity#X), sum(l_extendedprice#X), sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true)), sum(CheckOverflow((promote_precision(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true)) * promote_precision(cast(CheckOverflow((1.00 + promote_precision(cast(l_tax#X as decimal(13,2)))), DecimalType(13,2), true) as decimal(26,4)))), DecimalType(38,6), true)), avg(l_quantity#X), avg(l_extendedprice#X), avg(l_discount#X), count(1)] +Aggregate Attributes [8]: [sum(l_quantity#X)#X, sum(l_extendedprice#X)#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X, sum(CheckOverflow((promote_precision(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true)) * promote_precision(cast(CheckOverflow((1.00 + promote_precision(cast(l_tax#X as decimal(13,2)))), DecimalType(13,2), true) as decimal(26,4)))), DecimalType(38,6), true))#X, avg(l_quantity#X)#X, avg(l_extendedprice#X)#X, avg(l_discount#X)#X, count(1)#X] +Results [10]: [l_returnflag#X, l_linestatus#X, sum(l_quantity#X)#X AS sum_qty#X, sum(l_extendedprice#X)#X AS sum_base_price#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X AS sum_disc_price#X, sum(CheckOverflow((promote_precision(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true)) * promote_precision(cast(CheckOverflow((1.00 + promote_precision(cast(l_tax#X as decimal(13,2)))), DecimalType(13,2), true) as decimal(26,4)))), DecimalType(38,6), true))#X AS sum_charge#X, avg(l_quantity#X)#X AS avg_qty#X, avg(l_extendedprice#X)#X AS avg_price#X, avg(l_discount#X)#X AS avg_disc#X, count(1)#X AS count_order#X] + +(12) WholeStageCodegenTransformer (X) +Input [10]: [l_returnflag#X, l_linestatus#X, sum_qty#X, sum_base_price#X, sum_disc_price#X, sum_charge#X, avg_qty#X, avg_price#X, avg_disc#X, count_order#X] +Arguments: false + +(13) ColumnarExchange +Input [10]: [l_returnflag#X, l_linestatus#X, sum_qty#X, sum_base_price#X, sum_disc_price#X, sum_charge#X, avg_qty#X, avg_price#X, avg_disc#X, count_order#X] +Arguments: rangepartitioning(l_returnflag#X ASC NULLS FIRST, l_linestatus#X ASC NULLS FIRST, 1), ENSURE_REQUIREMENTS, [plan_id=X], [id=#X] + +(14) ShuffleQueryStage +Output [10]: [l_returnflag#X, l_linestatus#X, sum_qty#X, sum_base_price#X, sum_disc_price#X, sum_charge#X, avg_qty#X, avg_price#X, avg_disc#X, count_order#X] +Arguments: X + +(15) InputAdapter +Input [10]: [l_returnflag#X, l_linestatus#X, sum_qty#X, sum_base_price#X, sum_disc_price#X, sum_charge#X, avg_qty#X, avg_price#X, avg_disc#X, count_order#X] + +(16) InputIteratorTransformer +Input [10]: [l_returnflag#X, l_linestatus#X, sum_qty#X, sum_base_price#X, sum_disc_price#X, sum_charge#X, avg_qty#X, avg_price#X, avg_disc#X, count_order#X] + +(17) SortExecTransformer +Input [10]: [l_returnflag#X, l_linestatus#X, sum_qty#X, sum_base_price#X, sum_disc_price#X, sum_charge#X, avg_qty#X, avg_price#X, avg_disc#X, count_order#X] +Arguments: [l_returnflag#X ASC NULLS FIRST, l_linestatus#X ASC NULLS FIRST], true, 0 + +(18) WholeStageCodegenTransformer (X) +Input [10]: [l_returnflag#X, l_linestatus#X, sum_qty#X, sum_base_price#X, sum_disc_price#X, sum_charge#X, avg_qty#X, avg_price#X, avg_disc#X, count_order#X] +Arguments: false + +(19) VeloxColumnarToRowExec +Input [10]: [l_returnflag#X, l_linestatus#X, sum_qty#X, sum_base_price#X, sum_disc_price#X, sum_charge#X, avg_qty#X, avg_price#X, avg_disc#X, count_order#X] + +(20) Scan parquet +Output [7]: [l_quantity#X, l_extendedprice#X, l_discount#X, l_tax#X, l_returnflag#X, l_linestatus#X, l_shipdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_shipdate), LessThanOrEqual(l_shipdate,1998-09-02)] +ReadSchema: struct + +(21) Filter +Input [7]: [l_quantity#X, l_extendedprice#X, l_discount#X, l_tax#X, l_returnflag#X, l_linestatus#X, l_shipdate#X] +Condition : (isnotnull(l_shipdate#X) AND (l_shipdate#X <= 1998-09-02)) + +(22) Project +Output [6]: [l_quantity#X, l_extendedprice#X, l_discount#X, l_tax#X, l_returnflag#X, l_linestatus#X] +Input [7]: [l_quantity#X, l_extendedprice#X, l_discount#X, l_tax#X, l_returnflag#X, l_linestatus#X, l_shipdate#X] + +(23) HashAggregate +Input [6]: [l_quantity#X, l_extendedprice#X, l_discount#X, l_tax#X, l_returnflag#X, l_linestatus#X] +Keys [2]: [l_returnflag#X, l_linestatus#X] +Functions [8]: [partial_sum(l_quantity#X), partial_sum(l_extendedprice#X), partial_sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true)), partial_sum(CheckOverflow((promote_precision(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true)) * promote_precision(cast(CheckOverflow((1.00 + promote_precision(cast(l_tax#X as decimal(13,2)))), DecimalType(13,2), true) as decimal(26,4)))), DecimalType(38,6), true)), partial_avg(l_quantity#X), partial_avg(l_extendedprice#X), partial_avg(l_discount#X), partial_count(1)] +Aggregate Attributes [15]: [sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, count#X, sum#X, count#X, sum#X, count#X, count#X] +Results [17]: [l_returnflag#X, l_linestatus#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, count#X, sum#X, count#X, sum#X, count#X, count#X] + +(24) Exchange +Input [17]: [l_returnflag#X, l_linestatus#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, count#X, sum#X, count#X, sum#X, count#X, count#X] +Arguments: hashpartitioning(l_returnflag#X, l_linestatus#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(25) HashAggregate +Input [17]: [l_returnflag#X, l_linestatus#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, isEmpty#X, sum#X, count#X, sum#X, count#X, sum#X, count#X, count#X] +Keys [2]: [l_returnflag#X, l_linestatus#X] +Functions [8]: [sum(l_quantity#X), sum(l_extendedprice#X), sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true)), sum(CheckOverflow((promote_precision(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true)) * promote_precision(cast(CheckOverflow((1.00 + promote_precision(cast(l_tax#X as decimal(13,2)))), DecimalType(13,2), true) as decimal(26,4)))), DecimalType(38,6), true)), avg(l_quantity#X), avg(l_extendedprice#X), avg(l_discount#X), count(1)] +Aggregate Attributes [8]: [sum(l_quantity#X)#X, sum(l_extendedprice#X)#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X, sum(CheckOverflow((promote_precision(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true)) * promote_precision(cast(CheckOverflow((1.00 + promote_precision(cast(l_tax#X as decimal(13,2)))), DecimalType(13,2), true) as decimal(26,4)))), DecimalType(38,6), true))#X, avg(l_quantity#X)#X, avg(l_extendedprice#X)#X, avg(l_discount#X)#X, count(1)#X] +Results [10]: [l_returnflag#X, l_linestatus#X, sum(l_quantity#X)#X AS sum_qty#X, sum(l_extendedprice#X)#X AS sum_base_price#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X AS sum_disc_price#X, sum(CheckOverflow((promote_precision(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true)) * promote_precision(cast(CheckOverflow((1.00 + promote_precision(cast(l_tax#X as decimal(13,2)))), DecimalType(13,2), true) as decimal(26,4)))), DecimalType(38,6), true))#X AS sum_charge#X, avg(l_quantity#X)#X AS avg_qty#X, avg(l_extendedprice#X)#X AS avg_price#X, avg(l_discount#X)#X AS avg_disc#X, count(1)#X AS count_order#X] + +(26) Exchange +Input [10]: [l_returnflag#X, l_linestatus#X, sum_qty#X, sum_base_price#X, sum_disc_price#X, sum_charge#X, avg_qty#X, avg_price#X, avg_disc#X, count_order#X] +Arguments: rangepartitioning(l_returnflag#X ASC NULLS FIRST, l_linestatus#X ASC NULLS FIRST, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(27) Sort +Input [10]: [l_returnflag#X, l_linestatus#X, sum_qty#X, sum_base_price#X, sum_disc_price#X, sum_charge#X, avg_qty#X, avg_price#X, avg_disc#X, count_order#X] +Arguments: [l_returnflag#X ASC NULLS FIRST, l_linestatus#X ASC NULLS FIRST], true, 0 + +(28) AdaptiveSparkPlan +Output [10]: [l_returnflag#X, l_linestatus#X, sum_qty#X, sum_base_price#X, sum_disc_price#X, sum_charge#X, avg_qty#X, avg_price#X, avg_disc#X, count_order#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/10.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/10.txt new file mode 100644 index 000000000000..19932443845a --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/10.txt @@ -0,0 +1,458 @@ +== Physical Plan == +AdaptiveSparkPlan (87) ++- == Final Plan == + VeloxColumnarToRowExec (60) + +- TakeOrderedAndProjectExecTransformer (59) + +- ^ ProjectExecTransformer (57) + +- ^ RegularHashAggregateExecTransformer (56) + +- ^ InputIteratorTransformer (55) + +- ^ InputAdapter (54) + +- ^ ShuffleQueryStage (53) + +- ColumnarExchange (52) + +- ^ ProjectExecTransformer (50) + +- ^ FlushableHashAggregateExecTransformer (49) + +- ^ ProjectExecTransformer (48) + +- ^ ShuffledHashJoinExecTransformer Inner (47) + :- ^ InputIteratorTransformer (38) + : +- ^ InputAdapter (37) + : +- ^ ShuffleQueryStage (36) + : +- ColumnarExchange (35) + : +- ^ ProjectExecTransformer (33) + : +- ^ ShuffledHashJoinExecTransformer Inner (32) + : :- ^ InputIteratorTransformer (23) + : : +- ^ InputAdapter (22) + : : +- ^ ShuffleQueryStage (21) + : : +- ColumnarExchange (20) + : : +- ^ ProjectExecTransformer (18) + : : +- ^ ShuffledHashJoinExecTransformer Inner (17) + : : :- ^ InputIteratorTransformer (8) + : : : +- ^ InputAdapter (7) + : : : +- ^ ShuffleQueryStage (6) + : : : +- ColumnarExchange (5) + : : : +- ^ ProjectExecTransformer (3) + : : : +- ^ FilterExecTransformer (2) + : : : +- ^ Scan parquet (1) + : : +- ^ InputIteratorTransformer (16) + : : +- ^ InputAdapter (15) + : : +- ^ ShuffleQueryStage (14) + : : +- ColumnarExchange (13) + : : +- ^ ProjectExecTransformer (11) + : : +- ^ FilterExecTransformer (10) + : : +- ^ Scan parquet (9) + : +- ^ InputIteratorTransformer (31) + : +- ^ InputAdapter (30) + : +- ^ ShuffleQueryStage (29) + : +- ColumnarExchange (28) + : +- ^ ProjectExecTransformer (26) + : +- ^ FilterExecTransformer (25) + : +- ^ Scan parquet (24) + +- ^ InputIteratorTransformer (46) + +- ^ InputAdapter (45) + +- ^ ShuffleQueryStage (44) + +- ColumnarExchange (43) + +- ^ ProjectExecTransformer (41) + +- ^ FilterExecTransformer (40) + +- ^ Scan parquet (39) ++- == Initial Plan == + TakeOrderedAndProject (86) + +- HashAggregate (85) + +- Exchange (84) + +- HashAggregate (83) + +- Project (82) + +- ShuffledHashJoin Inner BuildRight (81) + :- Exchange (77) + : +- Project (76) + : +- ShuffledHashJoin Inner BuildRight (75) + : :- Exchange (70) + : : +- Project (69) + : : +- ShuffledHashJoin Inner BuildRight (68) + : : :- Exchange (63) + : : : +- Filter (62) + : : : +- Scan parquet (61) + : : +- Exchange (67) + : : +- Project (66) + : : +- Filter (65) + : : +- Scan parquet (64) + : +- Exchange (74) + : +- Project (73) + : +- Filter (72) + : +- Scan parquet (71) + +- Exchange (80) + +- Filter (79) + +- Scan parquet (78) + + +(1) Scan parquet +Output [7]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(c_custkey), IsNotNull(c_nationkey)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [7]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X] +Arguments: (isnotnull(c_custkey#X) AND isnotnull(c_nationkey#X)) + +(3) ProjectExecTransformer +Output [8]: [hash(c_custkey#X, 42) AS hash_partition_key#X, c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X] +Input [7]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X] + +(4) WholeStageCodegenTransformer (X) +Input [8]: [hash_partition_key#X, c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X] +Arguments: false + +(5) ColumnarExchange +Input [8]: [hash_partition_key#X, c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X] +Arguments: hashpartitioning(c_custkey#X, 1), ENSURE_REQUIREMENTS, [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X], [plan_id=X], [id=#X] + +(6) ShuffleQueryStage +Output [7]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X] +Arguments: X + +(7) InputAdapter +Input [7]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X] + +(8) InputIteratorTransformer +Input [7]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X] + +(9) Scan parquet +Output [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_orderdate), GreaterThanOrEqual(o_orderdate,1993-10-01), LessThan(o_orderdate,1994-01-01), IsNotNull(o_custkey), IsNotNull(o_orderkey)] +ReadSchema: struct + +(10) FilterExecTransformer +Input [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] +Arguments: ((((isnotnull(o_orderdate#X) AND (o_orderdate#X >= 1993-10-01)) AND (o_orderdate#X < 1994-01-01)) AND isnotnull(o_custkey#X)) AND isnotnull(o_orderkey#X)) + +(11) ProjectExecTransformer +Output [3]: [hash(o_custkey#X, 42) AS hash_partition_key#X, o_orderkey#X, o_custkey#X] +Input [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] + +(12) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, o_orderkey#X, o_custkey#X] +Arguments: false + +(13) ColumnarExchange +Input [3]: [hash_partition_key#X, o_orderkey#X, o_custkey#X] +Arguments: hashpartitioning(o_custkey#X, 1), ENSURE_REQUIREMENTS, [o_orderkey#X, o_custkey#X], [plan_id=X], [id=#X] + +(14) ShuffleQueryStage +Output [2]: [o_orderkey#X, o_custkey#X] +Arguments: X + +(15) InputAdapter +Input [2]: [o_orderkey#X, o_custkey#X] + +(16) InputIteratorTransformer +Input [2]: [o_orderkey#X, o_custkey#X] + +(17) ShuffledHashJoinExecTransformer +Left keys [1]: [c_custkey#X] +Right keys [1]: [o_custkey#X] +Join condition: None + +(18) ProjectExecTransformer +Output [9]: [hash(o_orderkey#X, 42) AS hash_partition_key#X, c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X, o_orderkey#X] +Input [9]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X, o_orderkey#X, o_custkey#X] + +(19) WholeStageCodegenTransformer (X) +Input [9]: [hash_partition_key#X, c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X, o_orderkey#X] +Arguments: false + +(20) ColumnarExchange +Input [9]: [hash_partition_key#X, c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X, o_orderkey#X] +Arguments: hashpartitioning(o_orderkey#X, 1), ENSURE_REQUIREMENTS, [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X, o_orderkey#X], [plan_id=X], [id=#X] + +(21) ShuffleQueryStage +Output [8]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X, o_orderkey#X] +Arguments: X + +(22) InputAdapter +Input [8]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X, o_orderkey#X] + +(23) InputIteratorTransformer +Input [8]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X, o_orderkey#X] + +(24) Scan parquet +Output [4]: [l_orderkey#X, l_extendedprice#X, l_discount#X, l_returnflag#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_returnflag), EqualTo(l_returnflag,R), IsNotNull(l_orderkey)] +ReadSchema: struct + +(25) FilterExecTransformer +Input [4]: [l_orderkey#X, l_extendedprice#X, l_discount#X, l_returnflag#X] +Arguments: ((isnotnull(l_returnflag#X) AND (l_returnflag#X = R)) AND isnotnull(l_orderkey#X)) + +(26) ProjectExecTransformer +Output [4]: [hash(l_orderkey#X, 42) AS hash_partition_key#X, l_orderkey#X, l_extendedprice#X, l_discount#X] +Input [4]: [l_orderkey#X, l_extendedprice#X, l_discount#X, l_returnflag#X] + +(27) WholeStageCodegenTransformer (X) +Input [4]: [hash_partition_key#X, l_orderkey#X, l_extendedprice#X, l_discount#X] +Arguments: false + +(28) ColumnarExchange +Input [4]: [hash_partition_key#X, l_orderkey#X, l_extendedprice#X, l_discount#X] +Arguments: hashpartitioning(l_orderkey#X, 1), ENSURE_REQUIREMENTS, [l_orderkey#X, l_extendedprice#X, l_discount#X], [plan_id=X], [id=#X] + +(29) ShuffleQueryStage +Output [3]: [l_orderkey#X, l_extendedprice#X, l_discount#X] +Arguments: X + +(30) InputAdapter +Input [3]: [l_orderkey#X, l_extendedprice#X, l_discount#X] + +(31) InputIteratorTransformer +Input [3]: [l_orderkey#X, l_extendedprice#X, l_discount#X] + +(32) ShuffledHashJoinExecTransformer +Left keys [1]: [o_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: None + +(33) ProjectExecTransformer +Output [10]: [hash(c_nationkey#X, 42) AS hash_partition_key#X, c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X, l_extendedprice#X, l_discount#X] +Input [11]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X, o_orderkey#X, l_orderkey#X, l_extendedprice#X, l_discount#X] + +(34) WholeStageCodegenTransformer (X) +Input [10]: [hash_partition_key#X, c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X, l_extendedprice#X, l_discount#X] +Arguments: false + +(35) ColumnarExchange +Input [10]: [hash_partition_key#X, c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X, l_extendedprice#X, l_discount#X] +Arguments: hashpartitioning(c_nationkey#X, 1), ENSURE_REQUIREMENTS, [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X, l_extendedprice#X, l_discount#X], [plan_id=X], [id=#X] + +(36) ShuffleQueryStage +Output [9]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X, l_extendedprice#X, l_discount#X] +Arguments: X + +(37) InputAdapter +Input [9]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X, l_extendedprice#X, l_discount#X] + +(38) InputIteratorTransformer +Input [9]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X, l_extendedprice#X, l_discount#X] + +(39) Scan parquet +Output [2]: [n_nationkey#X, n_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_nationkey)] +ReadSchema: struct + +(40) FilterExecTransformer +Input [2]: [n_nationkey#X, n_name#X] +Arguments: isnotnull(n_nationkey#X) + +(41) ProjectExecTransformer +Output [3]: [hash(n_nationkey#X, 42) AS hash_partition_key#X, n_nationkey#X, n_name#X] +Input [2]: [n_nationkey#X, n_name#X] + +(42) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, n_nationkey#X, n_name#X] +Arguments: false + +(43) ColumnarExchange +Input [3]: [hash_partition_key#X, n_nationkey#X, n_name#X] +Arguments: hashpartitioning(n_nationkey#X, 1), ENSURE_REQUIREMENTS, [n_nationkey#X, n_name#X], [plan_id=X], [id=#X] + +(44) ShuffleQueryStage +Output [2]: [n_nationkey#X, n_name#X] +Arguments: X + +(45) InputAdapter +Input [2]: [n_nationkey#X, n_name#X] + +(46) InputIteratorTransformer +Input [2]: [n_nationkey#X, n_name#X] + +(47) ShuffledHashJoinExecTransformer +Left keys [1]: [c_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: None + +(48) ProjectExecTransformer +Output [10]: [c_custkey#X, c_name#X, c_address#X, c_phone#X, c_acctbal#X, c_comment#X, l_extendedprice#X, l_discount#X, n_name#X, CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) AS _pre_114#X] +Input [11]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X, l_extendedprice#X, l_discount#X, n_nationkey#X, n_name#X] + +(49) FlushableHashAggregateExecTransformer +Input [10]: [c_custkey#X, c_name#X, c_address#X, c_phone#X, c_acctbal#X, c_comment#X, l_extendedprice#X, l_discount#X, n_name#X, _pre_114#X] +Keys [7]: [c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X] +Functions [1]: [partial_sum(_pre_114#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [9]: [c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X, sum#X, isEmpty#X] + +(50) ProjectExecTransformer +Output [10]: [hash(c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X, 42) AS hash_partition_key#X, c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X, sum#X, isEmpty#X] +Input [9]: [c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X, sum#X, isEmpty#X] + +(51) WholeStageCodegenTransformer (X) +Input [10]: [hash_partition_key#X, c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X, sum#X, isEmpty#X] +Arguments: false + +(52) ColumnarExchange +Input [10]: [hash_partition_key#X, c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X, 1), ENSURE_REQUIREMENTS, [c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X, sum#X, isEmpty#X], [plan_id=X], [id=#X] + +(53) ShuffleQueryStage +Output [9]: [c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X, sum#X, isEmpty#X] +Arguments: X + +(54) InputAdapter +Input [9]: [c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X, sum#X, isEmpty#X] + +(55) InputIteratorTransformer +Input [9]: [c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X, sum#X, isEmpty#X] + +(56) RegularHashAggregateExecTransformer +Input [9]: [c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X, sum#X, isEmpty#X] +Keys [7]: [c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X] +Functions [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))] +Aggregate Attributes [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X] +Results [8]: [c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X] + +(57) ProjectExecTransformer +Output [8]: [c_custkey#X, c_name#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X AS revenue#X, c_acctbal#X, n_name#X, c_address#X, c_phone#X, c_comment#X] +Input [8]: [c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X] + +(58) WholeStageCodegenTransformer (X) +Input [8]: [c_custkey#X, c_name#X, revenue#X, c_acctbal#X, n_name#X, c_address#X, c_phone#X, c_comment#X] +Arguments: false + +(59) TakeOrderedAndProjectExecTransformer +Input [8]: [c_custkey#X, c_name#X, revenue#X, c_acctbal#X, n_name#X, c_address#X, c_phone#X, c_comment#X] +Arguments: X, [revenue#X DESC NULLS LAST], [c_custkey#X, c_name#X, revenue#X, c_acctbal#X, n_name#X, c_address#X, c_phone#X, c_comment#X], 0 + +(60) VeloxColumnarToRowExec +Input [8]: [c_custkey#X, c_name#X, revenue#X, c_acctbal#X, n_name#X, c_address#X, c_phone#X, c_comment#X] + +(61) Scan parquet +Output [7]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(c_custkey), IsNotNull(c_nationkey)] +ReadSchema: struct + +(62) Filter +Input [7]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X] +Condition : (isnotnull(c_custkey#X) AND isnotnull(c_nationkey#X)) + +(63) Exchange +Input [7]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X] +Arguments: hashpartitioning(c_custkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(64) Scan parquet +Output [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_orderdate), GreaterThanOrEqual(o_orderdate,1993-10-01), LessThan(o_orderdate,1994-01-01), IsNotNull(o_custkey), IsNotNull(o_orderkey)] +ReadSchema: struct + +(65) Filter +Input [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] +Condition : ((((isnotnull(o_orderdate#X) AND (o_orderdate#X >= 1993-10-01)) AND (o_orderdate#X < 1994-01-01)) AND isnotnull(o_custkey#X)) AND isnotnull(o_orderkey#X)) + +(66) Project +Output [2]: [o_orderkey#X, o_custkey#X] +Input [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] + +(67) Exchange +Input [2]: [o_orderkey#X, o_custkey#X] +Arguments: hashpartitioning(o_custkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(68) ShuffledHashJoin +Left keys [1]: [c_custkey#X] +Right keys [1]: [o_custkey#X] +Join condition: None + +(69) Project +Output [8]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X, o_orderkey#X] +Input [9]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X, o_orderkey#X, o_custkey#X] + +(70) Exchange +Input [8]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X, o_orderkey#X] +Arguments: hashpartitioning(o_orderkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(71) Scan parquet +Output [4]: [l_orderkey#X, l_extendedprice#X, l_discount#X, l_returnflag#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_returnflag), EqualTo(l_returnflag,R), IsNotNull(l_orderkey)] +ReadSchema: struct + +(72) Filter +Input [4]: [l_orderkey#X, l_extendedprice#X, l_discount#X, l_returnflag#X] +Condition : ((isnotnull(l_returnflag#X) AND (l_returnflag#X = R)) AND isnotnull(l_orderkey#X)) + +(73) Project +Output [3]: [l_orderkey#X, l_extendedprice#X, l_discount#X] +Input [4]: [l_orderkey#X, l_extendedprice#X, l_discount#X, l_returnflag#X] + +(74) Exchange +Input [3]: [l_orderkey#X, l_extendedprice#X, l_discount#X] +Arguments: hashpartitioning(l_orderkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(75) ShuffledHashJoin +Left keys [1]: [o_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: None + +(76) Project +Output [9]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X, l_extendedprice#X, l_discount#X] +Input [11]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X, o_orderkey#X, l_orderkey#X, l_extendedprice#X, l_discount#X] + +(77) Exchange +Input [9]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X, l_extendedprice#X, l_discount#X] +Arguments: hashpartitioning(c_nationkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(78) Scan parquet +Output [2]: [n_nationkey#X, n_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_nationkey)] +ReadSchema: struct + +(79) Filter +Input [2]: [n_nationkey#X, n_name#X] +Condition : isnotnull(n_nationkey#X) + +(80) Exchange +Input [2]: [n_nationkey#X, n_name#X] +Arguments: hashpartitioning(n_nationkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(81) ShuffledHashJoin +Left keys [1]: [c_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: None + +(82) Project +Output [9]: [c_custkey#X, c_name#X, c_address#X, c_phone#X, c_acctbal#X, c_comment#X, l_extendedprice#X, l_discount#X, n_name#X] +Input [11]: [c_custkey#X, c_name#X, c_address#X, c_nationkey#X, c_phone#X, c_acctbal#X, c_comment#X, l_extendedprice#X, l_discount#X, n_nationkey#X, n_name#X] + +(83) HashAggregate +Input [9]: [c_custkey#X, c_name#X, c_address#X, c_phone#X, c_acctbal#X, c_comment#X, l_extendedprice#X, l_discount#X, n_name#X] +Keys [7]: [c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X] +Functions [1]: [partial_sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [9]: [c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X, sum#X, isEmpty#X] + +(84) Exchange +Input [9]: [c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(85) HashAggregate +Input [9]: [c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X, sum#X, isEmpty#X] +Keys [7]: [c_custkey#X, c_name#X, c_acctbal#X, c_phone#X, n_name#X, c_address#X, c_comment#X] +Functions [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))] +Aggregate Attributes [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X] +Results [8]: [c_custkey#X, c_name#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X AS revenue#X, c_acctbal#X, n_name#X, c_address#X, c_phone#X, c_comment#X] + +(86) TakeOrderedAndProject +Input [8]: [c_custkey#X, c_name#X, revenue#X, c_acctbal#X, n_name#X, c_address#X, c_phone#X, c_comment#X] +Arguments: X, [revenue#X DESC NULLS LAST], [c_custkey#X, c_name#X, revenue#X, c_acctbal#X, n_name#X, c_address#X, c_phone#X, c_comment#X] + +(87) AdaptiveSparkPlan +Output [8]: [c_custkey#X, c_name#X, revenue#X, c_acctbal#X, n_name#X, c_address#X, c_phone#X, c_comment#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/11.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/11.txt new file mode 100644 index 000000000000..6afdd883861c --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/11.txt @@ -0,0 +1,378 @@ +== Physical Plan == +AdaptiveSparkPlan (72) ++- == Final Plan == + VeloxColumnarToRowExec (50) + +- ^ SortExecTransformer (48) + +- ^ InputIteratorTransformer (47) + +- ^ InputAdapter (46) + +- ^ ShuffleQueryStage (45) + +- ColumnarExchange (44) + +- ^ FilterExecTransformer (42) + +- ^ RegularHashAggregateExecTransformer (41) + +- ^ InputIteratorTransformer (40) + +- ^ InputAdapter (39) + +- ^ ShuffleQueryStage (38) + +- ColumnarExchange (37) + +- ^ ProjectExecTransformer (35) + +- ^ FlushableHashAggregateExecTransformer (34) + +- ^ ProjectExecTransformer (33) + +- ^ ShuffledHashJoinExecTransformer Inner (32) + :- ^ InputIteratorTransformer (23) + : +- ^ InputAdapter (22) + : +- ^ ShuffleQueryStage (21) + : +- ColumnarExchange (20) + : +- ^ ProjectExecTransformer (18) + : +- ^ ShuffledHashJoinExecTransformer Inner (17) + : :- ^ InputIteratorTransformer (8) + : : +- ^ InputAdapter (7) + : : +- ^ ShuffleQueryStage (6) + : : +- ColumnarExchange (5) + : : +- ^ ProjectExecTransformer (3) + : : +- ^ FilterExecTransformer (2) + : : +- ^ Scan parquet (1) + : +- ^ InputIteratorTransformer (16) + : +- ^ InputAdapter (15) + : +- ^ ShuffleQueryStage (14) + : +- ColumnarExchange (13) + : +- ^ ProjectExecTransformer (11) + : +- ^ FilterExecTransformer (10) + : +- ^ Scan parquet (9) + +- ^ InputIteratorTransformer (31) + +- ^ InputAdapter (30) + +- ^ ShuffleQueryStage (29) + +- ColumnarExchange (28) + +- ^ ProjectExecTransformer (26) + +- ^ FilterExecTransformer (25) + +- ^ Scan parquet (24) ++- == Initial Plan == + Sort (71) + +- Exchange (70) + +- Filter (69) + +- HashAggregate (68) + +- Exchange (67) + +- HashAggregate (66) + +- Project (65) + +- ShuffledHashJoin Inner BuildRight (64) + :- Exchange (59) + : +- Project (58) + : +- ShuffledHashJoin Inner BuildRight (57) + : :- Exchange (53) + : : +- Filter (52) + : : +- Scan parquet (51) + : +- Exchange (56) + : +- Filter (55) + : +- Scan parquet (54) + +- Exchange (63) + +- Project (62) + +- Filter (61) + +- Scan parquet (60) + + +(1) Scan parquet +Output [4]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X, ps_supplycost#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(ps_suppkey)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [4]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X, ps_supplycost#X] +Arguments: isnotnull(ps_suppkey#X) + +(3) ProjectExecTransformer +Output [5]: [hash(ps_suppkey#X, 42) AS hash_partition_key#X, ps_partkey#X, ps_suppkey#X, ps_availqty#X, ps_supplycost#X] +Input [4]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X, ps_supplycost#X] + +(4) WholeStageCodegenTransformer (X) +Input [5]: [hash_partition_key#X, ps_partkey#X, ps_suppkey#X, ps_availqty#X, ps_supplycost#X] +Arguments: false + +(5) ColumnarExchange +Input [5]: [hash_partition_key#X, ps_partkey#X, ps_suppkey#X, ps_availqty#X, ps_supplycost#X] +Arguments: hashpartitioning(ps_suppkey#X, 1), ENSURE_REQUIREMENTS, [ps_partkey#X, ps_suppkey#X, ps_availqty#X, ps_supplycost#X], [plan_id=X], [id=#X] + +(6) ShuffleQueryStage +Output [4]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X, ps_supplycost#X] +Arguments: X + +(7) InputAdapter +Input [4]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X, ps_supplycost#X] + +(8) InputIteratorTransformer +Input [4]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X, ps_supplycost#X] + +(9) Scan parquet +Output [2]: [s_suppkey#X, s_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(s_suppkey), IsNotNull(s_nationkey)] +ReadSchema: struct + +(10) FilterExecTransformer +Input [2]: [s_suppkey#X, s_nationkey#X] +Arguments: (isnotnull(s_suppkey#X) AND isnotnull(s_nationkey#X)) + +(11) ProjectExecTransformer +Output [3]: [hash(s_suppkey#X, 42) AS hash_partition_key#X, s_suppkey#X, s_nationkey#X] +Input [2]: [s_suppkey#X, s_nationkey#X] + +(12) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, s_suppkey#X, s_nationkey#X] +Arguments: false + +(13) ColumnarExchange +Input [3]: [hash_partition_key#X, s_suppkey#X, s_nationkey#X] +Arguments: hashpartitioning(s_suppkey#X, 1), ENSURE_REQUIREMENTS, [s_suppkey#X, s_nationkey#X], [plan_id=X], [id=#X] + +(14) ShuffleQueryStage +Output [2]: [s_suppkey#X, s_nationkey#X] +Arguments: X + +(15) InputAdapter +Input [2]: [s_suppkey#X, s_nationkey#X] + +(16) InputIteratorTransformer +Input [2]: [s_suppkey#X, s_nationkey#X] + +(17) ShuffledHashJoinExecTransformer +Left keys [1]: [ps_suppkey#X] +Right keys [1]: [s_suppkey#X] +Join condition: None + +(18) ProjectExecTransformer +Output [5]: [hash(s_nationkey#X, 42) AS hash_partition_key#X, ps_partkey#X, ps_availqty#X, ps_supplycost#X, s_nationkey#X] +Input [6]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X, ps_supplycost#X, s_suppkey#X, s_nationkey#X] + +(19) WholeStageCodegenTransformer (X) +Input [5]: [hash_partition_key#X, ps_partkey#X, ps_availqty#X, ps_supplycost#X, s_nationkey#X] +Arguments: false + +(20) ColumnarExchange +Input [5]: [hash_partition_key#X, ps_partkey#X, ps_availqty#X, ps_supplycost#X, s_nationkey#X] +Arguments: hashpartitioning(s_nationkey#X, 1), ENSURE_REQUIREMENTS, [ps_partkey#X, ps_availqty#X, ps_supplycost#X, s_nationkey#X], [plan_id=X], [id=#X] + +(21) ShuffleQueryStage +Output [4]: [ps_partkey#X, ps_availqty#X, ps_supplycost#X, s_nationkey#X] +Arguments: X + +(22) InputAdapter +Input [4]: [ps_partkey#X, ps_availqty#X, ps_supplycost#X, s_nationkey#X] + +(23) InputIteratorTransformer +Input [4]: [ps_partkey#X, ps_availqty#X, ps_supplycost#X, s_nationkey#X] + +(24) Scan parquet +Output [2]: [n_nationkey#X, n_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_name), EqualTo(n_name,GERMANY), IsNotNull(n_nationkey)] +ReadSchema: struct + +(25) FilterExecTransformer +Input [2]: [n_nationkey#X, n_name#X] +Arguments: ((isnotnull(n_name#X) AND (n_name#X = GERMANY)) AND isnotnull(n_nationkey#X)) + +(26) ProjectExecTransformer +Output [2]: [hash(n_nationkey#X, 42) AS hash_partition_key#X, n_nationkey#X] +Input [2]: [n_nationkey#X, n_name#X] + +(27) WholeStageCodegenTransformer (X) +Input [2]: [hash_partition_key#X, n_nationkey#X] +Arguments: false + +(28) ColumnarExchange +Input [2]: [hash_partition_key#X, n_nationkey#X] +Arguments: hashpartitioning(n_nationkey#X, 1), ENSURE_REQUIREMENTS, [n_nationkey#X], [plan_id=X], [id=#X] + +(29) ShuffleQueryStage +Output [1]: [n_nationkey#X] +Arguments: X + +(30) InputAdapter +Input [1]: [n_nationkey#X] + +(31) InputIteratorTransformer +Input [1]: [n_nationkey#X] + +(32) ShuffledHashJoinExecTransformer +Left keys [1]: [s_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: None + +(33) ProjectExecTransformer +Output [4]: [ps_partkey#X, ps_availqty#X, ps_supplycost#X, CheckOverflow((promote_precision(ps_supplycost#X) * promote_precision(cast(cast(ps_availqty#X as decimal(10,0)) as decimal(12,2)))), DecimalType(23,2), true) AS _pre_115#X] +Input [5]: [ps_partkey#X, ps_availqty#X, ps_supplycost#X, s_nationkey#X, n_nationkey#X] + +(34) FlushableHashAggregateExecTransformer +Input [4]: [ps_partkey#X, ps_availqty#X, ps_supplycost#X, _pre_115#X] +Keys [1]: [ps_partkey#X] +Functions [1]: [partial_sum(_pre_115#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [3]: [ps_partkey#X, sum#X, isEmpty#X] + +(35) ProjectExecTransformer +Output [4]: [hash(ps_partkey#X, 42) AS hash_partition_key#X, ps_partkey#X, sum#X, isEmpty#X] +Input [3]: [ps_partkey#X, sum#X, isEmpty#X] + +(36) WholeStageCodegenTransformer (X) +Input [4]: [hash_partition_key#X, ps_partkey#X, sum#X, isEmpty#X] +Arguments: false + +(37) ColumnarExchange +Input [4]: [hash_partition_key#X, ps_partkey#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(ps_partkey#X, 1), ENSURE_REQUIREMENTS, [ps_partkey#X, sum#X, isEmpty#X], [plan_id=X], [id=#X] + +(38) ShuffleQueryStage +Output [3]: [ps_partkey#X, sum#X, isEmpty#X] +Arguments: X + +(39) InputAdapter +Input [3]: [ps_partkey#X, sum#X, isEmpty#X] + +(40) InputIteratorTransformer +Input [3]: [ps_partkey#X, sum#X, isEmpty#X] + +(41) RegularHashAggregateExecTransformer +Input [3]: [ps_partkey#X, sum#X, isEmpty#X] +Keys [1]: [ps_partkey#X] +Functions [1]: [sum(CheckOverflow((promote_precision(ps_supplycost#X) * promote_precision(cast(cast(ps_availqty#X as decimal(10,0)) as decimal(12,2)))), DecimalType(23,2), true))] +Aggregate Attributes [1]: [sum(CheckOverflow((promote_precision(ps_supplycost#X) * promote_precision(cast(cast(ps_availqty#X as decimal(10,0)) as decimal(12,2)))), DecimalType(23,2), true))#X] +Results [2]: [ps_partkey#X, sum(CheckOverflow((promote_precision(ps_supplycost#X) * promote_precision(cast(cast(ps_availqty#X as decimal(10,0)) as decimal(12,2)))), DecimalType(23,2), true))#X AS value#X] + +(42) FilterExecTransformer +Input [2]: [ps_partkey#X, value#X] +Arguments: (isnotnull(value#X) AND (cast(value#X as decimal(38,6)) > Subquery subquery#X, [id=#X])) + +(43) WholeStageCodegenTransformer (X) +Input [2]: [ps_partkey#X, value#X] +Arguments: false + +(44) ColumnarExchange +Input [2]: [ps_partkey#X, value#X] +Arguments: rangepartitioning(value#X DESC NULLS LAST, 1), ENSURE_REQUIREMENTS, [plan_id=X], [id=#X] + +(45) ShuffleQueryStage +Output [2]: [ps_partkey#X, value#X] +Arguments: X + +(46) InputAdapter +Input [2]: [ps_partkey#X, value#X] + +(47) InputIteratorTransformer +Input [2]: [ps_partkey#X, value#X] + +(48) SortExecTransformer +Input [2]: [ps_partkey#X, value#X] +Arguments: [value#X DESC NULLS LAST], true, 0 + +(49) WholeStageCodegenTransformer (X) +Input [2]: [ps_partkey#X, value#X] +Arguments: false + +(50) VeloxColumnarToRowExec +Input [2]: [ps_partkey#X, value#X] + +(51) Scan parquet +Output [4]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X, ps_supplycost#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(ps_suppkey)] +ReadSchema: struct + +(52) Filter +Input [4]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X, ps_supplycost#X] +Condition : isnotnull(ps_suppkey#X) + +(53) Exchange +Input [4]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X, ps_supplycost#X] +Arguments: hashpartitioning(ps_suppkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(54) Scan parquet +Output [2]: [s_suppkey#X, s_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(s_suppkey), IsNotNull(s_nationkey)] +ReadSchema: struct + +(55) Filter +Input [2]: [s_suppkey#X, s_nationkey#X] +Condition : (isnotnull(s_suppkey#X) AND isnotnull(s_nationkey#X)) + +(56) Exchange +Input [2]: [s_suppkey#X, s_nationkey#X] +Arguments: hashpartitioning(s_suppkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(57) ShuffledHashJoin +Left keys [1]: [ps_suppkey#X] +Right keys [1]: [s_suppkey#X] +Join condition: None + +(58) Project +Output [4]: [ps_partkey#X, ps_availqty#X, ps_supplycost#X, s_nationkey#X] +Input [6]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X, ps_supplycost#X, s_suppkey#X, s_nationkey#X] + +(59) Exchange +Input [4]: [ps_partkey#X, ps_availqty#X, ps_supplycost#X, s_nationkey#X] +Arguments: hashpartitioning(s_nationkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(60) Scan parquet +Output [2]: [n_nationkey#X, n_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_name), EqualTo(n_name,GERMANY), IsNotNull(n_nationkey)] +ReadSchema: struct + +(61) Filter +Input [2]: [n_nationkey#X, n_name#X] +Condition : ((isnotnull(n_name#X) AND (n_name#X = GERMANY)) AND isnotnull(n_nationkey#X)) + +(62) Project +Output [1]: [n_nationkey#X] +Input [2]: [n_nationkey#X, n_name#X] + +(63) Exchange +Input [1]: [n_nationkey#X] +Arguments: hashpartitioning(n_nationkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(64) ShuffledHashJoin +Left keys [1]: [s_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: None + +(65) Project +Output [3]: [ps_partkey#X, ps_availqty#X, ps_supplycost#X] +Input [5]: [ps_partkey#X, ps_availqty#X, ps_supplycost#X, s_nationkey#X, n_nationkey#X] + +(66) HashAggregate +Input [3]: [ps_partkey#X, ps_availqty#X, ps_supplycost#X] +Keys [1]: [ps_partkey#X] +Functions [1]: [partial_sum(CheckOverflow((promote_precision(ps_supplycost#X) * promote_precision(cast(cast(ps_availqty#X as decimal(10,0)) as decimal(12,2)))), DecimalType(23,2), true))] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [3]: [ps_partkey#X, sum#X, isEmpty#X] + +(67) Exchange +Input [3]: [ps_partkey#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(ps_partkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(68) HashAggregate +Input [3]: [ps_partkey#X, sum#X, isEmpty#X] +Keys [1]: [ps_partkey#X] +Functions [1]: [sum(CheckOverflow((promote_precision(ps_supplycost#X) * promote_precision(cast(cast(ps_availqty#X as decimal(10,0)) as decimal(12,2)))), DecimalType(23,2), true))] +Aggregate Attributes [1]: [sum(CheckOverflow((promote_precision(ps_supplycost#X) * promote_precision(cast(cast(ps_availqty#X as decimal(10,0)) as decimal(12,2)))), DecimalType(23,2), true))#X] +Results [2]: [ps_partkey#X, sum(CheckOverflow((promote_precision(ps_supplycost#X) * promote_precision(cast(cast(ps_availqty#X as decimal(10,0)) as decimal(12,2)))), DecimalType(23,2), true))#X AS value#X] + +(69) Filter +Input [2]: [ps_partkey#X, value#X] +Condition : (isnotnull(value#X) AND (cast(value#X as decimal(38,6)) > Subquery subquery#X, [id=#X])) + +(70) Exchange +Input [2]: [ps_partkey#X, value#X] +Arguments: rangepartitioning(value#X DESC NULLS LAST, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(71) Sort +Input [2]: [ps_partkey#X, value#X] +Arguments: [value#X DESC NULLS LAST], true, 0 + +(72) AdaptiveSparkPlan +Output [2]: [ps_partkey#X, value#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/12.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/12.txt new file mode 100644 index 000000000000..5e95a073fb3e --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/12.txt @@ -0,0 +1,261 @@ +== Physical Plan == +AdaptiveSparkPlan (49) ++- == Final Plan == + VeloxColumnarToRowExec (34) + +- ^ SortExecTransformer (32) + +- ^ InputIteratorTransformer (31) + +- ^ InputAdapter (30) + +- ^ ShuffleQueryStage (29) + +- ColumnarExchange (28) + +- ^ RegularHashAggregateExecTransformer (26) + +- ^ InputIteratorTransformer (25) + +- ^ InputAdapter (24) + +- ^ ShuffleQueryStage (23) + +- ColumnarExchange (22) + +- ^ ProjectExecTransformer (20) + +- ^ FlushableHashAggregateExecTransformer (19) + +- ^ ProjectExecTransformer (18) + +- ^ ShuffledHashJoinExecTransformer Inner (17) + :- ^ InputIteratorTransformer (8) + : +- ^ InputAdapter (7) + : +- ^ ShuffleQueryStage (6) + : +- ColumnarExchange (5) + : +- ^ ProjectExecTransformer (3) + : +- ^ FilterExecTransformer (2) + : +- ^ Scan parquet (1) + +- ^ InputIteratorTransformer (16) + +- ^ InputAdapter (15) + +- ^ ShuffleQueryStage (14) + +- ColumnarExchange (13) + +- ^ ProjectExecTransformer (11) + +- ^ FilterExecTransformer (10) + +- ^ Scan parquet (9) ++- == Initial Plan == + Sort (48) + +- Exchange (47) + +- HashAggregate (46) + +- Exchange (45) + +- HashAggregate (44) + +- Project (43) + +- ShuffledHashJoin Inner BuildLeft (42) + :- Exchange (37) + : +- Filter (36) + : +- Scan parquet (35) + +- Exchange (41) + +- Project (40) + +- Filter (39) + +- Scan parquet (38) + + +(1) Scan parquet +Output [2]: [o_orderkey#X, o_orderpriority#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_orderkey)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [2]: [o_orderkey#X, o_orderpriority#X] +Arguments: isnotnull(o_orderkey#X) + +(3) ProjectExecTransformer +Output [3]: [hash(o_orderkey#X, 42) AS hash_partition_key#X, o_orderkey#X, o_orderpriority#X] +Input [2]: [o_orderkey#X, o_orderpriority#X] + +(4) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, o_orderkey#X, o_orderpriority#X] +Arguments: false + +(5) ColumnarExchange +Input [3]: [hash_partition_key#X, o_orderkey#X, o_orderpriority#X] +Arguments: hashpartitioning(o_orderkey#X, 1), ENSURE_REQUIREMENTS, [o_orderkey#X, o_orderpriority#X], [plan_id=X], [id=#X] + +(6) ShuffleQueryStage +Output [2]: [o_orderkey#X, o_orderpriority#X] +Arguments: X + +(7) InputAdapter +Input [2]: [o_orderkey#X, o_orderpriority#X] + +(8) InputIteratorTransformer +Input [2]: [o_orderkey#X, o_orderpriority#X] + +(9) Scan parquet +Output [5]: [l_orderkey#X, l_shipdate#X, l_commitdate#X, l_receiptdate#X, l_shipmode#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_commitdate), IsNotNull(l_receiptdate), IsNotNull(l_shipdate), In(l_shipmode, [MAIL,SHIP]), GreaterThanOrEqual(l_receiptdate,1994-01-01), LessThan(l_receiptdate,1995-01-01), IsNotNull(l_orderkey)] +ReadSchema: struct + +(10) FilterExecTransformer +Input [5]: [l_orderkey#X, l_shipdate#X, l_commitdate#X, l_receiptdate#X, l_shipmode#X] +Arguments: ((((((((isnotnull(l_commitdate#X) AND isnotnull(l_receiptdate#X)) AND isnotnull(l_shipdate#X)) AND l_shipmode#X IN (MAIL,SHIP)) AND (l_commitdate#X < l_receiptdate#X)) AND (l_shipdate#X < l_commitdate#X)) AND (l_receiptdate#X >= 1994-01-01)) AND (l_receiptdate#X < 1995-01-01)) AND isnotnull(l_orderkey#X)) + +(11) ProjectExecTransformer +Output [3]: [hash(l_orderkey#X, 42) AS hash_partition_key#X, l_orderkey#X, l_shipmode#X] +Input [5]: [l_orderkey#X, l_shipdate#X, l_commitdate#X, l_receiptdate#X, l_shipmode#X] + +(12) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, l_orderkey#X, l_shipmode#X] +Arguments: false + +(13) ColumnarExchange +Input [3]: [hash_partition_key#X, l_orderkey#X, l_shipmode#X] +Arguments: hashpartitioning(l_orderkey#X, 1), ENSURE_REQUIREMENTS, [l_orderkey#X, l_shipmode#X], [plan_id=X], [id=#X] + +(14) ShuffleQueryStage +Output [2]: [l_orderkey#X, l_shipmode#X] +Arguments: X + +(15) InputAdapter +Input [2]: [l_orderkey#X, l_shipmode#X] + +(16) InputIteratorTransformer +Input [2]: [l_orderkey#X, l_shipmode#X] + +(17) ShuffledHashJoinExecTransformer +Left keys [1]: [o_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: None + +(18) ProjectExecTransformer +Output [4]: [o_orderpriority#X, l_shipmode#X, CASE WHEN ((o_orderpriority#X = 1-URGENT) OR (o_orderpriority#X = 2-HIGH)) THEN 1 ELSE 0 END AS _pre_117#X, CASE WHEN (NOT (o_orderpriority#X = 1-URGENT) AND NOT (o_orderpriority#X = 2-HIGH)) THEN 1 ELSE 0 END AS _pre_118#X] +Input [4]: [o_orderkey#X, o_orderpriority#X, l_orderkey#X, l_shipmode#X] + +(19) FlushableHashAggregateExecTransformer +Input [4]: [o_orderpriority#X, l_shipmode#X, _pre_117#X, _pre_118#X] +Keys [1]: [l_shipmode#X] +Functions [2]: [partial_sum(_pre_117#X), partial_sum(_pre_118#X)] +Aggregate Attributes [2]: [sum#X, sum#X] +Results [3]: [l_shipmode#X, sum#X, sum#X] + +(20) ProjectExecTransformer +Output [4]: [hash(l_shipmode#X, 42) AS hash_partition_key#X, l_shipmode#X, sum#X, sum#X] +Input [3]: [l_shipmode#X, sum#X, sum#X] + +(21) WholeStageCodegenTransformer (X) +Input [4]: [hash_partition_key#X, l_shipmode#X, sum#X, sum#X] +Arguments: false + +(22) ColumnarExchange +Input [4]: [hash_partition_key#X, l_shipmode#X, sum#X, sum#X] +Arguments: hashpartitioning(l_shipmode#X, 1), ENSURE_REQUIREMENTS, [l_shipmode#X, sum#X, sum#X], [plan_id=X], [id=#X] + +(23) ShuffleQueryStage +Output [3]: [l_shipmode#X, sum#X, sum#X] +Arguments: X + +(24) InputAdapter +Input [3]: [l_shipmode#X, sum#X, sum#X] + +(25) InputIteratorTransformer +Input [3]: [l_shipmode#X, sum#X, sum#X] + +(26) RegularHashAggregateExecTransformer +Input [3]: [l_shipmode#X, sum#X, sum#X] +Keys [1]: [l_shipmode#X] +Functions [2]: [sum(CASE WHEN ((o_orderpriority#X = 1-URGENT) OR (o_orderpriority#X = 2-HIGH)) THEN 1 ELSE 0 END), sum(CASE WHEN (NOT (o_orderpriority#X = 1-URGENT) AND NOT (o_orderpriority#X = 2-HIGH)) THEN 1 ELSE 0 END)] +Aggregate Attributes [2]: [sum(CASE WHEN ((o_orderpriority#X = 1-URGENT) OR (o_orderpriority#X = 2-HIGH)) THEN 1 ELSE 0 END)#X, sum(CASE WHEN (NOT (o_orderpriority#X = 1-URGENT) AND NOT (o_orderpriority#X = 2-HIGH)) THEN 1 ELSE 0 END)#X] +Results [3]: [l_shipmode#X, sum(CASE WHEN ((o_orderpriority#X = 1-URGENT) OR (o_orderpriority#X = 2-HIGH)) THEN 1 ELSE 0 END)#X AS high_line_count#X, sum(CASE WHEN (NOT (o_orderpriority#X = 1-URGENT) AND NOT (o_orderpriority#X = 2-HIGH)) THEN 1 ELSE 0 END)#X AS low_line_count#X] + +(27) WholeStageCodegenTransformer (X) +Input [3]: [l_shipmode#X, high_line_count#X, low_line_count#X] +Arguments: false + +(28) ColumnarExchange +Input [3]: [l_shipmode#X, high_line_count#X, low_line_count#X] +Arguments: rangepartitioning(l_shipmode#X ASC NULLS FIRST, 1), ENSURE_REQUIREMENTS, [plan_id=X], [id=#X] + +(29) ShuffleQueryStage +Output [3]: [l_shipmode#X, high_line_count#X, low_line_count#X] +Arguments: X + +(30) InputAdapter +Input [3]: [l_shipmode#X, high_line_count#X, low_line_count#X] + +(31) InputIteratorTransformer +Input [3]: [l_shipmode#X, high_line_count#X, low_line_count#X] + +(32) SortExecTransformer +Input [3]: [l_shipmode#X, high_line_count#X, low_line_count#X] +Arguments: [l_shipmode#X ASC NULLS FIRST], true, 0 + +(33) WholeStageCodegenTransformer (X) +Input [3]: [l_shipmode#X, high_line_count#X, low_line_count#X] +Arguments: false + +(34) VeloxColumnarToRowExec +Input [3]: [l_shipmode#X, high_line_count#X, low_line_count#X] + +(35) Scan parquet +Output [2]: [o_orderkey#X, o_orderpriority#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_orderkey)] +ReadSchema: struct + +(36) Filter +Input [2]: [o_orderkey#X, o_orderpriority#X] +Condition : isnotnull(o_orderkey#X) + +(37) Exchange +Input [2]: [o_orderkey#X, o_orderpriority#X] +Arguments: hashpartitioning(o_orderkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(38) Scan parquet +Output [5]: [l_orderkey#X, l_shipdate#X, l_commitdate#X, l_receiptdate#X, l_shipmode#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_commitdate), IsNotNull(l_receiptdate), IsNotNull(l_shipdate), In(l_shipmode, [MAIL,SHIP]), GreaterThanOrEqual(l_receiptdate,1994-01-01), LessThan(l_receiptdate,1995-01-01), IsNotNull(l_orderkey)] +ReadSchema: struct + +(39) Filter +Input [5]: [l_orderkey#X, l_shipdate#X, l_commitdate#X, l_receiptdate#X, l_shipmode#X] +Condition : ((((((((isnotnull(l_commitdate#X) AND isnotnull(l_receiptdate#X)) AND isnotnull(l_shipdate#X)) AND l_shipmode#X IN (MAIL,SHIP)) AND (l_commitdate#X < l_receiptdate#X)) AND (l_shipdate#X < l_commitdate#X)) AND (l_receiptdate#X >= 1994-01-01)) AND (l_receiptdate#X < 1995-01-01)) AND isnotnull(l_orderkey#X)) + +(40) Project +Output [2]: [l_orderkey#X, l_shipmode#X] +Input [5]: [l_orderkey#X, l_shipdate#X, l_commitdate#X, l_receiptdate#X, l_shipmode#X] + +(41) Exchange +Input [2]: [l_orderkey#X, l_shipmode#X] +Arguments: hashpartitioning(l_orderkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(42) ShuffledHashJoin +Left keys [1]: [o_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: None + +(43) Project +Output [2]: [o_orderpriority#X, l_shipmode#X] +Input [4]: [o_orderkey#X, o_orderpriority#X, l_orderkey#X, l_shipmode#X] + +(44) HashAggregate +Input [2]: [o_orderpriority#X, l_shipmode#X] +Keys [1]: [l_shipmode#X] +Functions [2]: [partial_sum(CASE WHEN ((o_orderpriority#X = 1-URGENT) OR (o_orderpriority#X = 2-HIGH)) THEN 1 ELSE 0 END), partial_sum(CASE WHEN (NOT (o_orderpriority#X = 1-URGENT) AND NOT (o_orderpriority#X = 2-HIGH)) THEN 1 ELSE 0 END)] +Aggregate Attributes [2]: [sum#X, sum#X] +Results [3]: [l_shipmode#X, sum#X, sum#X] + +(45) Exchange +Input [3]: [l_shipmode#X, sum#X, sum#X] +Arguments: hashpartitioning(l_shipmode#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(46) HashAggregate +Input [3]: [l_shipmode#X, sum#X, sum#X] +Keys [1]: [l_shipmode#X] +Functions [2]: [sum(CASE WHEN ((o_orderpriority#X = 1-URGENT) OR (o_orderpriority#X = 2-HIGH)) THEN 1 ELSE 0 END), sum(CASE WHEN (NOT (o_orderpriority#X = 1-URGENT) AND NOT (o_orderpriority#X = 2-HIGH)) THEN 1 ELSE 0 END)] +Aggregate Attributes [2]: [sum(CASE WHEN ((o_orderpriority#X = 1-URGENT) OR (o_orderpriority#X = 2-HIGH)) THEN 1 ELSE 0 END)#X, sum(CASE WHEN (NOT (o_orderpriority#X = 1-URGENT) AND NOT (o_orderpriority#X = 2-HIGH)) THEN 1 ELSE 0 END)#X] +Results [3]: [l_shipmode#X, sum(CASE WHEN ((o_orderpriority#X = 1-URGENT) OR (o_orderpriority#X = 2-HIGH)) THEN 1 ELSE 0 END)#X AS high_line_count#X, sum(CASE WHEN (NOT (o_orderpriority#X = 1-URGENT) AND NOT (o_orderpriority#X = 2-HIGH)) THEN 1 ELSE 0 END)#X AS low_line_count#X] + +(47) Exchange +Input [3]: [l_shipmode#X, high_line_count#X, low_line_count#X] +Arguments: rangepartitioning(l_shipmode#X ASC NULLS FIRST, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(48) Sort +Input [3]: [l_shipmode#X, high_line_count#X, low_line_count#X] +Arguments: [l_shipmode#X ASC NULLS FIRST], true, 0 + +(49) AdaptiveSparkPlan +Output [3]: [l_shipmode#X, high_line_count#X, low_line_count#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/13.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/13.txt new file mode 100644 index 000000000000..14f2b770f996 --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/13.txt @@ -0,0 +1,286 @@ +== Physical Plan == +AdaptiveSparkPlan (52) ++- == Final Plan == + VeloxColumnarToRowExec (36) + +- ^ SortExecTransformer (34) + +- ^ InputIteratorTransformer (33) + +- ^ InputAdapter (32) + +- ^ ShuffleQueryStage (31) + +- ColumnarExchange (30) + +- ^ RegularHashAggregateExecTransformer (28) + +- ^ InputIteratorTransformer (27) + +- ^ InputAdapter (26) + +- ^ ShuffleQueryStage (25) + +- ColumnarExchange (24) + +- ^ ProjectExecTransformer (22) + +- ^ FlushableHashAggregateExecTransformer (21) + +- ^ ProjectExecTransformer (20) + +- ^ RegularHashAggregateExecTransformer (19) + +- ^ RegularHashAggregateExecTransformer (18) + +- ^ ProjectExecTransformer (17) + +- ^ ShuffledHashJoinExecTransformer LeftOuter (16) + :- ^ InputIteratorTransformer (7) + : +- ^ InputAdapter (6) + : +- ^ ShuffleQueryStage (5) + : +- ColumnarExchange (4) + : +- ^ ProjectExecTransformer (2) + : +- ^ Scan parquet (1) + +- ^ InputIteratorTransformer (15) + +- ^ InputAdapter (14) + +- ^ ShuffleQueryStage (13) + +- ColumnarExchange (12) + +- ^ ProjectExecTransformer (10) + +- ^ FilterExecTransformer (9) + +- ^ Scan parquet (8) ++- == Initial Plan == + Sort (51) + +- Exchange (50) + +- HashAggregate (49) + +- Exchange (48) + +- HashAggregate (47) + +- HashAggregate (46) + +- HashAggregate (45) + +- Project (44) + +- ShuffledHashJoin LeftOuter BuildRight (43) + :- Exchange (38) + : +- Scan parquet (37) + +- Exchange (42) + +- Project (41) + +- Filter (40) + +- Scan parquet (39) + + +(1) Scan parquet +Output [1]: [c_custkey#X] +Batched: true +Location: InMemoryFileIndex [*] +ReadSchema: struct + +(2) ProjectExecTransformer +Output [2]: [hash(c_custkey#X, 42) AS hash_partition_key#X, c_custkey#X] +Input [1]: [c_custkey#X] + +(3) WholeStageCodegenTransformer (X) +Input [2]: [hash_partition_key#X, c_custkey#X] +Arguments: false + +(4) ColumnarExchange +Input [2]: [hash_partition_key#X, c_custkey#X] +Arguments: hashpartitioning(c_custkey#X, 1), ENSURE_REQUIREMENTS, [c_custkey#X], [plan_id=X], [id=#X] + +(5) ShuffleQueryStage +Output [1]: [c_custkey#X] +Arguments: X + +(6) InputAdapter +Input [1]: [c_custkey#X] + +(7) InputIteratorTransformer +Input [1]: [c_custkey#X] + +(8) Scan parquet +Output [3]: [o_orderkey#X, o_custkey#X, o_comment#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_comment), IsNotNull(o_custkey)] +ReadSchema: struct + +(9) FilterExecTransformer +Input [3]: [o_orderkey#X, o_custkey#X, o_comment#X] +Arguments: ((isnotnull(o_comment#X) AND NOT o_comment#X LIKE %special%requests%) AND isnotnull(o_custkey#X)) + +(10) ProjectExecTransformer +Output [3]: [hash(o_custkey#X, 42) AS hash_partition_key#X, o_orderkey#X, o_custkey#X] +Input [3]: [o_orderkey#X, o_custkey#X, o_comment#X] + +(11) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, o_orderkey#X, o_custkey#X] +Arguments: false + +(12) ColumnarExchange +Input [3]: [hash_partition_key#X, o_orderkey#X, o_custkey#X] +Arguments: hashpartitioning(o_custkey#X, 1), ENSURE_REQUIREMENTS, [o_orderkey#X, o_custkey#X], [plan_id=X], [id=#X] + +(13) ShuffleQueryStage +Output [2]: [o_orderkey#X, o_custkey#X] +Arguments: X + +(14) InputAdapter +Input [2]: [o_orderkey#X, o_custkey#X] + +(15) InputIteratorTransformer +Input [2]: [o_orderkey#X, o_custkey#X] + +(16) ShuffledHashJoinExecTransformer +Left keys [1]: [c_custkey#X] +Right keys [1]: [o_custkey#X] +Join condition: None + +(17) ProjectExecTransformer +Output [2]: [c_custkey#X, o_orderkey#X] +Input [3]: [c_custkey#X, o_orderkey#X, o_custkey#X] + +(18) RegularHashAggregateExecTransformer +Input [2]: [c_custkey#X, o_orderkey#X] +Keys [1]: [c_custkey#X] +Functions [1]: [partial_count(o_orderkey#X)] +Aggregate Attributes [1]: [count#X] +Results [2]: [c_custkey#X, count#X] + +(19) RegularHashAggregateExecTransformer +Input [2]: [c_custkey#X, count#X] +Keys [1]: [c_custkey#X] +Functions [1]: [count(o_orderkey#X)] +Aggregate Attributes [1]: [count(o_orderkey#X)#X] +Results [2]: [c_custkey#X, count(o_orderkey#X)#X] + +(20) ProjectExecTransformer +Output [1]: [count(o_orderkey#X)#X AS c_count#X] +Input [2]: [c_custkey#X, count(o_orderkey#X)#X] + +(21) FlushableHashAggregateExecTransformer +Input [1]: [c_count#X] +Keys [1]: [c_count#X] +Functions [1]: [partial_count(1)] +Aggregate Attributes [1]: [count#X] +Results [2]: [c_count#X, count#X] + +(22) ProjectExecTransformer +Output [3]: [hash(c_count#X, 42) AS hash_partition_key#X, c_count#X, count#X] +Input [2]: [c_count#X, count#X] + +(23) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, c_count#X, count#X] +Arguments: false + +(24) ColumnarExchange +Input [3]: [hash_partition_key#X, c_count#X, count#X] +Arguments: hashpartitioning(c_count#X, 1), ENSURE_REQUIREMENTS, [c_count#X, count#X], [plan_id=X], [id=#X] + +(25) ShuffleQueryStage +Output [2]: [c_count#X, count#X] +Arguments: X + +(26) InputAdapter +Input [2]: [c_count#X, count#X] + +(27) InputIteratorTransformer +Input [2]: [c_count#X, count#X] + +(28) RegularHashAggregateExecTransformer +Input [2]: [c_count#X, count#X] +Keys [1]: [c_count#X] +Functions [1]: [count(1)] +Aggregate Attributes [1]: [count(1)#X] +Results [2]: [c_count#X, count(1)#X AS custdist#X] + +(29) WholeStageCodegenTransformer (X) +Input [2]: [c_count#X, custdist#X] +Arguments: false + +(30) ColumnarExchange +Input [2]: [c_count#X, custdist#X] +Arguments: rangepartitioning(custdist#X DESC NULLS LAST, c_count#X DESC NULLS LAST, 1), ENSURE_REQUIREMENTS, [plan_id=X], [id=#X] + +(31) ShuffleQueryStage +Output [2]: [c_count#X, custdist#X] +Arguments: X + +(32) InputAdapter +Input [2]: [c_count#X, custdist#X] + +(33) InputIteratorTransformer +Input [2]: [c_count#X, custdist#X] + +(34) SortExecTransformer +Input [2]: [c_count#X, custdist#X] +Arguments: [custdist#X DESC NULLS LAST, c_count#X DESC NULLS LAST], true, 0 + +(35) WholeStageCodegenTransformer (X) +Input [2]: [c_count#X, custdist#X] +Arguments: false + +(36) VeloxColumnarToRowExec +Input [2]: [c_count#X, custdist#X] + +(37) Scan parquet +Output [1]: [c_custkey#X] +Batched: true +Location: InMemoryFileIndex [*] +ReadSchema: struct + +(38) Exchange +Input [1]: [c_custkey#X] +Arguments: hashpartitioning(c_custkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(39) Scan parquet +Output [3]: [o_orderkey#X, o_custkey#X, o_comment#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_comment), IsNotNull(o_custkey)] +ReadSchema: struct + +(40) Filter +Input [3]: [o_orderkey#X, o_custkey#X, o_comment#X] +Condition : ((isnotnull(o_comment#X) AND NOT o_comment#X LIKE %special%requests%) AND isnotnull(o_custkey#X)) + +(41) Project +Output [2]: [o_orderkey#X, o_custkey#X] +Input [3]: [o_orderkey#X, o_custkey#X, o_comment#X] + +(42) Exchange +Input [2]: [o_orderkey#X, o_custkey#X] +Arguments: hashpartitioning(o_custkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(43) ShuffledHashJoin +Left keys [1]: [c_custkey#X] +Right keys [1]: [o_custkey#X] +Join condition: None + +(44) Project +Output [2]: [c_custkey#X, o_orderkey#X] +Input [3]: [c_custkey#X, o_orderkey#X, o_custkey#X] + +(45) HashAggregate +Input [2]: [c_custkey#X, o_orderkey#X] +Keys [1]: [c_custkey#X] +Functions [1]: [partial_count(o_orderkey#X)] +Aggregate Attributes [1]: [count#X] +Results [2]: [c_custkey#X, count#X] + +(46) HashAggregate +Input [2]: [c_custkey#X, count#X] +Keys [1]: [c_custkey#X] +Functions [1]: [count(o_orderkey#X)] +Aggregate Attributes [1]: [count(o_orderkey#X)#X] +Results [1]: [count(o_orderkey#X)#X AS c_count#X] + +(47) HashAggregate +Input [1]: [c_count#X] +Keys [1]: [c_count#X] +Functions [1]: [partial_count(1)] +Aggregate Attributes [1]: [count#X] +Results [2]: [c_count#X, count#X] + +(48) Exchange +Input [2]: [c_count#X, count#X] +Arguments: hashpartitioning(c_count#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(49) HashAggregate +Input [2]: [c_count#X, count#X] +Keys [1]: [c_count#X] +Functions [1]: [count(1)] +Aggregate Attributes [1]: [count(1)#X] +Results [2]: [c_count#X, count(1)#X AS custdist#X] + +(50) Exchange +Input [2]: [c_count#X, custdist#X] +Arguments: rangepartitioning(custdist#X DESC NULLS LAST, c_count#X DESC NULLS LAST, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(51) Sort +Input [2]: [c_count#X, custdist#X] +Arguments: [custdist#X DESC NULLS LAST, c_count#X DESC NULLS LAST], true, 0 + +(52) AdaptiveSparkPlan +Output [2]: [c_count#X, custdist#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/14.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/14.txt new file mode 100644 index 000000000000..b683435e06c5 --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/14.txt @@ -0,0 +1,197 @@ +== Physical Plan == +AdaptiveSparkPlan (35) ++- == Final Plan == + VeloxColumnarToRowExec (23) + +- ^ ProjectExecTransformer (21) + +- ^ RegularHashAggregateExecTransformer (20) + +- ^ RegularHashAggregateExecTransformer (19) + +- ^ ProjectExecTransformer (18) + +- ^ ShuffledHashJoinExecTransformer Inner (17) + :- ^ InputIteratorTransformer (8) + : +- ^ InputAdapter (7) + : +- ^ ShuffleQueryStage (6) + : +- ColumnarExchange (5) + : +- ^ ProjectExecTransformer (3) + : +- ^ FilterExecTransformer (2) + : +- ^ Scan parquet (1) + +- ^ InputIteratorTransformer (16) + +- ^ InputAdapter (15) + +- ^ ShuffleQueryStage (14) + +- ColumnarExchange (13) + +- ^ ProjectExecTransformer (11) + +- ^ FilterExecTransformer (10) + +- ^ Scan parquet (9) ++- == Initial Plan == + HashAggregate (34) + +- HashAggregate (33) + +- Project (32) + +- ShuffledHashJoin Inner BuildRight (31) + :- Exchange (27) + : +- Project (26) + : +- Filter (25) + : +- Scan parquet (24) + +- Exchange (30) + +- Filter (29) + +- Scan parquet (28) + + +(1) Scan parquet +Output [4]: [l_partkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_shipdate), GreaterThanOrEqual(l_shipdate,1995-09-01), LessThan(l_shipdate,1995-10-01), IsNotNull(l_partkey)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [4]: [l_partkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Arguments: (((isnotnull(l_shipdate#X) AND (l_shipdate#X >= 1995-09-01)) AND (l_shipdate#X < 1995-10-01)) AND isnotnull(l_partkey#X)) + +(3) ProjectExecTransformer +Output [4]: [hash(l_partkey#X, 42) AS hash_partition_key#X, l_partkey#X, l_extendedprice#X, l_discount#X] +Input [4]: [l_partkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] + +(4) WholeStageCodegenTransformer (X) +Input [4]: [hash_partition_key#X, l_partkey#X, l_extendedprice#X, l_discount#X] +Arguments: false + +(5) ColumnarExchange +Input [4]: [hash_partition_key#X, l_partkey#X, l_extendedprice#X, l_discount#X] +Arguments: hashpartitioning(l_partkey#X, 1), ENSURE_REQUIREMENTS, [l_partkey#X, l_extendedprice#X, l_discount#X], [plan_id=X], [id=#X] + +(6) ShuffleQueryStage +Output [3]: [l_partkey#X, l_extendedprice#X, l_discount#X] +Arguments: X + +(7) InputAdapter +Input [3]: [l_partkey#X, l_extendedprice#X, l_discount#X] + +(8) InputIteratorTransformer +Input [3]: [l_partkey#X, l_extendedprice#X, l_discount#X] + +(9) Scan parquet +Output [2]: [p_partkey#X, p_type#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(p_partkey)] +ReadSchema: struct + +(10) FilterExecTransformer +Input [2]: [p_partkey#X, p_type#X] +Arguments: isnotnull(p_partkey#X) + +(11) ProjectExecTransformer +Output [3]: [hash(p_partkey#X, 42) AS hash_partition_key#X, p_partkey#X, p_type#X] +Input [2]: [p_partkey#X, p_type#X] + +(12) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, p_partkey#X, p_type#X] +Arguments: false + +(13) ColumnarExchange +Input [3]: [hash_partition_key#X, p_partkey#X, p_type#X] +Arguments: hashpartitioning(p_partkey#X, 1), ENSURE_REQUIREMENTS, [p_partkey#X, p_type#X], [plan_id=X], [id=#X] + +(14) ShuffleQueryStage +Output [2]: [p_partkey#X, p_type#X] +Arguments: X + +(15) InputAdapter +Input [2]: [p_partkey#X, p_type#X] + +(16) InputIteratorTransformer +Input [2]: [p_partkey#X, p_type#X] + +(17) ShuffledHashJoinExecTransformer +Left keys [1]: [l_partkey#X] +Right keys [1]: [p_partkey#X] +Join condition: None + +(18) ProjectExecTransformer +Output [5]: [l_extendedprice#X, l_discount#X, p_type#X, CASE WHEN StartsWith(p_type#X, PROMO) THEN CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) ELSE 0.0000 END AS _pre_119#X, CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) AS _pre_120#X] +Input [5]: [l_partkey#X, l_extendedprice#X, l_discount#X, p_partkey#X, p_type#X] + +(19) RegularHashAggregateExecTransformer +Input [5]: [l_extendedprice#X, l_discount#X, p_type#X, _pre_119#X, _pre_120#X] +Keys: [] +Functions [2]: [partial_sum(_pre_119#X), partial_sum(_pre_120#X)] +Aggregate Attributes [4]: [sum#X, isEmpty#X, sum#X, isEmpty#X] +Results [4]: [sum#X, isEmpty#X, sum#X, isEmpty#X] + +(20) RegularHashAggregateExecTransformer +Input [4]: [sum#X, isEmpty#X, sum#X, isEmpty#X] +Keys: [] +Functions [2]: [sum(CASE WHEN StartsWith(p_type#X, PROMO) THEN CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) ELSE 0.0000 END), sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))] +Aggregate Attributes [2]: [sum(CASE WHEN StartsWith(p_type#X, PROMO) THEN CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) ELSE 0.0000 END)#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X] +Results [2]: [sum(CASE WHEN StartsWith(p_type#X, PROMO) THEN CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) ELSE 0.0000 END)#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X] + +(21) ProjectExecTransformer +Output [1]: [CheckOverflow((promote_precision(CheckOverflow((100.0000 * promote_precision(sum(CASE WHEN StartsWith(p_type#X, PROMO) THEN CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) ELSE 0.0000 END)#X)), DecimalType(38,6), true)) / promote_precision(cast(sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X as decimal(38,6)))), DecimalType(38,6), true) AS promo_revenue#X] +Input [2]: [sum(CASE WHEN StartsWith(p_type#X, PROMO) THEN CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) ELSE 0.0000 END)#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X] + +(22) WholeStageCodegenTransformer (X) +Input [1]: [promo_revenue#X] +Arguments: false + +(23) VeloxColumnarToRowExec +Input [1]: [promo_revenue#X] + +(24) Scan parquet +Output [4]: [l_partkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_shipdate), GreaterThanOrEqual(l_shipdate,1995-09-01), LessThan(l_shipdate,1995-10-01), IsNotNull(l_partkey)] +ReadSchema: struct + +(25) Filter +Input [4]: [l_partkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Condition : (((isnotnull(l_shipdate#X) AND (l_shipdate#X >= 1995-09-01)) AND (l_shipdate#X < 1995-10-01)) AND isnotnull(l_partkey#X)) + +(26) Project +Output [3]: [l_partkey#X, l_extendedprice#X, l_discount#X] +Input [4]: [l_partkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] + +(27) Exchange +Input [3]: [l_partkey#X, l_extendedprice#X, l_discount#X] +Arguments: hashpartitioning(l_partkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(28) Scan parquet +Output [2]: [p_partkey#X, p_type#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(p_partkey)] +ReadSchema: struct + +(29) Filter +Input [2]: [p_partkey#X, p_type#X] +Condition : isnotnull(p_partkey#X) + +(30) Exchange +Input [2]: [p_partkey#X, p_type#X] +Arguments: hashpartitioning(p_partkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(31) ShuffledHashJoin +Left keys [1]: [l_partkey#X] +Right keys [1]: [p_partkey#X] +Join condition: None + +(32) Project +Output [3]: [l_extendedprice#X, l_discount#X, p_type#X] +Input [5]: [l_partkey#X, l_extendedprice#X, l_discount#X, p_partkey#X, p_type#X] + +(33) HashAggregate +Input [3]: [l_extendedprice#X, l_discount#X, p_type#X] +Keys: [] +Functions [2]: [partial_sum(CASE WHEN StartsWith(p_type#X, PROMO) THEN CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) ELSE 0.0000 END), partial_sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))] +Aggregate Attributes [4]: [sum#X, isEmpty#X, sum#X, isEmpty#X] +Results [4]: [sum#X, isEmpty#X, sum#X, isEmpty#X] + +(34) HashAggregate +Input [4]: [sum#X, isEmpty#X, sum#X, isEmpty#X] +Keys: [] +Functions [2]: [sum(CASE WHEN StartsWith(p_type#X, PROMO) THEN CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) ELSE 0.0000 END), sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))] +Aggregate Attributes [2]: [sum(CASE WHEN StartsWith(p_type#X, PROMO) THEN CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) ELSE 0.0000 END)#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X] +Results [1]: [CheckOverflow((promote_precision(CheckOverflow((100.0000 * promote_precision(sum(CASE WHEN StartsWith(p_type#X, PROMO) THEN CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) ELSE 0.0000 END)#X)), DecimalType(38,6), true)) / promote_precision(cast(sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X as decimal(38,6)))), DecimalType(38,6), true) AS promo_revenue#X] + +(35) AdaptiveSparkPlan +Output [1]: [promo_revenue#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/15.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/15.txt new file mode 100644 index 000000000000..050c90945e90 --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/15.txt @@ -0,0 +1,244 @@ +== Physical Plan == +AdaptiveSparkPlan (45) ++- == Final Plan == + VeloxColumnarToRowExec (30) + +- ^ SortExecTransformer (28) + +- ^ InputIteratorTransformer (27) + +- ^ InputAdapter (26) + +- ^ ShuffleQueryStage (25) + +- ColumnarExchange (24) + +- ^ ProjectExecTransformer (22) + +- ^ ShuffledHashJoinExecTransformer Inner (21) + :- ^ InputIteratorTransformer (8) + : +- ^ InputAdapter (7) + : +- ^ ShuffleQueryStage (6) + : +- ColumnarExchange (5) + : +- ^ ProjectExecTransformer (3) + : +- ^ FilterExecTransformer (2) + : +- ^ Scan parquet (1) + +- ^ FilterExecTransformer (20) + +- ^ RegularHashAggregateExecTransformer (19) + +- ^ InputIteratorTransformer (18) + +- ^ InputAdapter (17) + +- ^ ShuffleQueryStage (16) + +- ColumnarExchange (15) + +- ^ ProjectExecTransformer (13) + +- ^ FlushableHashAggregateExecTransformer (12) + +- ^ ProjectExecTransformer (11) + +- ^ FilterExecTransformer (10) + +- ^ Scan parquet (9) ++- == Initial Plan == + Sort (44) + +- Exchange (43) + +- Project (42) + +- ShuffledHashJoin Inner BuildLeft (41) + :- Exchange (33) + : +- Filter (32) + : +- Scan parquet (31) + +- Filter (40) + +- HashAggregate (39) + +- Exchange (38) + +- HashAggregate (37) + +- Project (36) + +- Filter (35) + +- Scan parquet (34) + + +(1) Scan parquet +Output [4]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(s_suppkey)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [4]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X] +Arguments: isnotnull(s_suppkey#X) + +(3) ProjectExecTransformer +Output [5]: [hash(s_suppkey#X, 42) AS hash_partition_key#X, s_suppkey#X, s_name#X, s_address#X, s_phone#X] +Input [4]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X] + +(4) WholeStageCodegenTransformer (X) +Input [5]: [hash_partition_key#X, s_suppkey#X, s_name#X, s_address#X, s_phone#X] +Arguments: false + +(5) ColumnarExchange +Input [5]: [hash_partition_key#X, s_suppkey#X, s_name#X, s_address#X, s_phone#X] +Arguments: hashpartitioning(s_suppkey#X, 1), ENSURE_REQUIREMENTS, [s_suppkey#X, s_name#X, s_address#X, s_phone#X], [plan_id=X], [id=#X] + +(6) ShuffleQueryStage +Output [4]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X] +Arguments: X + +(7) InputAdapter +Input [4]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X] + +(8) InputIteratorTransformer +Input [4]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X] + +(9) Scan parquet +Output [4]: [l_suppkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_shipdate), GreaterThanOrEqual(l_shipdate,1996-01-01), LessThan(l_shipdate,1996-04-01), IsNotNull(l_suppkey)] +ReadSchema: struct + +(10) FilterExecTransformer +Input [4]: [l_suppkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Arguments: (((isnotnull(l_shipdate#X) AND (l_shipdate#X >= 1996-01-01)) AND (l_shipdate#X < 1996-04-01)) AND isnotnull(l_suppkey#X)) + +(11) ProjectExecTransformer +Output [4]: [l_suppkey#X, l_extendedprice#X, l_discount#X, CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) AS _pre_121#X] +Input [4]: [l_suppkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] + +(12) FlushableHashAggregateExecTransformer +Input [4]: [l_suppkey#X, l_extendedprice#X, l_discount#X, _pre_121#X] +Keys [1]: [l_suppkey#X] +Functions [1]: [partial_sum(_pre_121#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [3]: [l_suppkey#X, sum#X, isEmpty#X] + +(13) ProjectExecTransformer +Output [4]: [hash(l_suppkey#X, 42) AS hash_partition_key#X, l_suppkey#X, sum#X, isEmpty#X] +Input [3]: [l_suppkey#X, sum#X, isEmpty#X] + +(14) WholeStageCodegenTransformer (X) +Input [4]: [hash_partition_key#X, l_suppkey#X, sum#X, isEmpty#X] +Arguments: false + +(15) ColumnarExchange +Input [4]: [hash_partition_key#X, l_suppkey#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(l_suppkey#X, 1), ENSURE_REQUIREMENTS, [l_suppkey#X, sum#X, isEmpty#X], [plan_id=X], [id=#X] + +(16) ShuffleQueryStage +Output [3]: [l_suppkey#X, sum#X, isEmpty#X] +Arguments: X + +(17) InputAdapter +Input [3]: [l_suppkey#X, sum#X, isEmpty#X] + +(18) InputIteratorTransformer +Input [3]: [l_suppkey#X, sum#X, isEmpty#X] + +(19) RegularHashAggregateExecTransformer +Input [3]: [l_suppkey#X, sum#X, isEmpty#X] +Keys [1]: [l_suppkey#X] +Functions [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))] +Aggregate Attributes [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X] +Results [2]: [l_suppkey#X AS supplier_no#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X AS total_revenue#X] + +(20) FilterExecTransformer +Input [2]: [supplier_no#X, total_revenue#X] +Arguments: (isnotnull(total_revenue#X) AND (total_revenue#X = Subquery subquery#X, [id=#X])) + +(21) ShuffledHashJoinExecTransformer +Left keys [1]: [s_suppkey#X] +Right keys [1]: [supplier_no#X] +Join condition: None + +(22) ProjectExecTransformer +Output [5]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X, total_revenue#X] +Input [6]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X, supplier_no#X, total_revenue#X] + +(23) WholeStageCodegenTransformer (X) +Input [5]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X, total_revenue#X] +Arguments: false + +(24) ColumnarExchange +Input [5]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X, total_revenue#X] +Arguments: rangepartitioning(s_suppkey#X ASC NULLS FIRST, 1), ENSURE_REQUIREMENTS, [plan_id=X], [id=#X] + +(25) ShuffleQueryStage +Output [5]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X, total_revenue#X] +Arguments: X + +(26) InputAdapter +Input [5]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X, total_revenue#X] + +(27) InputIteratorTransformer +Input [5]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X, total_revenue#X] + +(28) SortExecTransformer +Input [5]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X, total_revenue#X] +Arguments: [s_suppkey#X ASC NULLS FIRST], true, 0 + +(29) WholeStageCodegenTransformer (X) +Input [5]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X, total_revenue#X] +Arguments: false + +(30) VeloxColumnarToRowExec +Input [5]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X, total_revenue#X] + +(31) Scan parquet +Output [4]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(s_suppkey)] +ReadSchema: struct + +(32) Filter +Input [4]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X] +Condition : isnotnull(s_suppkey#X) + +(33) Exchange +Input [4]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X] +Arguments: hashpartitioning(s_suppkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(34) Scan parquet +Output [4]: [l_suppkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_shipdate), GreaterThanOrEqual(l_shipdate,1996-01-01), LessThan(l_shipdate,1996-04-01), IsNotNull(l_suppkey)] +ReadSchema: struct + +(35) Filter +Input [4]: [l_suppkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Condition : (((isnotnull(l_shipdate#X) AND (l_shipdate#X >= 1996-01-01)) AND (l_shipdate#X < 1996-04-01)) AND isnotnull(l_suppkey#X)) + +(36) Project +Output [3]: [l_suppkey#X, l_extendedprice#X, l_discount#X] +Input [4]: [l_suppkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] + +(37) HashAggregate +Input [3]: [l_suppkey#X, l_extendedprice#X, l_discount#X] +Keys [1]: [l_suppkey#X] +Functions [1]: [partial_sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [3]: [l_suppkey#X, sum#X, isEmpty#X] + +(38) Exchange +Input [3]: [l_suppkey#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(l_suppkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(39) HashAggregate +Input [3]: [l_suppkey#X, sum#X, isEmpty#X] +Keys [1]: [l_suppkey#X] +Functions [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))] +Aggregate Attributes [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X] +Results [2]: [l_suppkey#X AS supplier_no#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X AS total_revenue#X] + +(40) Filter +Input [2]: [supplier_no#X, total_revenue#X] +Condition : (isnotnull(total_revenue#X) AND (total_revenue#X = Subquery subquery#X, [id=#X])) + +(41) ShuffledHashJoin +Left keys [1]: [s_suppkey#X] +Right keys [1]: [supplier_no#X] +Join condition: None + +(42) Project +Output [5]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X, total_revenue#X] +Input [6]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X, supplier_no#X, total_revenue#X] + +(43) Exchange +Input [5]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X, total_revenue#X] +Arguments: rangepartitioning(s_suppkey#X ASC NULLS FIRST, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(44) Sort +Input [5]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X, total_revenue#X] +Arguments: [s_suppkey#X ASC NULLS FIRST], true, 0 + +(45) AdaptiveSparkPlan +Output [5]: [s_suppkey#X, s_name#X, s_address#X, s_phone#X, total_revenue#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/16.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/16.txt new file mode 100644 index 000000000000..4eff981d78bd --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/16.txt @@ -0,0 +1,349 @@ +== Physical Plan == +AdaptiveSparkPlan (64) ++- == Final Plan == + VeloxColumnarToRowExec (42) + +- ^ SortExecTransformer (40) + +- ^ InputIteratorTransformer (39) + +- ^ InputAdapter (38) + +- ^ ShuffleQueryStage (37) + +- ColumnarExchange (36) + +- ^ RegularHashAggregateExecTransformer (34) + +- ^ InputIteratorTransformer (33) + +- ^ InputAdapter (32) + +- ^ ShuffleQueryStage (31) + +- ColumnarExchange (30) + +- ^ ProjectExecTransformer (28) + +- ^ FlushableHashAggregateExecTransformer (27) + +- ^ RegularHashAggregateExecTransformer (26) + +- ^ InputIteratorTransformer (25) + +- ^ InputAdapter (24) + +- ^ ShuffleQueryStage (23) + +- ColumnarExchange (22) + +- ^ ProjectExecTransformer (20) + +- ^ FlushableHashAggregateExecTransformer (19) + +- ^ ProjectExecTransformer (18) + +- ^ ShuffledHashJoinExecTransformer Inner (17) + :- ^ InputIteratorTransformer (8) + : +- ^ InputAdapter (7) + : +- ^ ShuffleQueryStage (6) + : +- ColumnarExchange (5) + : +- ^ ProjectExecTransformer (3) + : +- ^ FilterExecTransformer (2) + : +- ^ Scan parquet (1) + +- ^ InputIteratorTransformer (16) + +- ^ InputAdapter (15) + +- ^ ShuffleQueryStage (14) + +- ColumnarExchange (13) + +- ^ ProjectExecTransformer (11) + +- ^ FilterExecTransformer (10) + +- ^ Scan parquet (9) ++- == Initial Plan == + Sort (63) + +- Exchange (62) + +- HashAggregate (61) + +- Exchange (60) + +- HashAggregate (59) + +- HashAggregate (58) + +- Exchange (57) + +- HashAggregate (56) + +- Project (55) + +- ShuffledHashJoin Inner BuildRight (54) + :- Exchange (50) + : +- BroadcastHashJoin LeftAnti BuildRight (49) + : :- Filter (44) + : : +- Scan parquet (43) + : +- BroadcastExchange (48) + : +- Project (47) + : +- Filter (46) + : +- Scan parquet (45) + +- Exchange (53) + +- Filter (52) + +- Scan parquet (51) + + +(1) Scan parquet +Output [2]: [ps_partkey#X, ps_suppkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(ps_partkey)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [2]: [ps_partkey#X, ps_suppkey#X] +Arguments: isnotnull(ps_partkey#X) + +(3) ProjectExecTransformer +Output [3]: [hash(ps_partkey#X, 42) AS hash_partition_key#X, ps_partkey#X, ps_suppkey#X] +Input [2]: [ps_partkey#X, ps_suppkey#X] + +(4) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, ps_partkey#X, ps_suppkey#X] +Arguments: false + +(5) ColumnarExchange +Input [3]: [hash_partition_key#X, ps_partkey#X, ps_suppkey#X] +Arguments: hashpartitioning(ps_partkey#X, 1), ENSURE_REQUIREMENTS, [ps_partkey#X, ps_suppkey#X], [plan_id=X], [id=#X] + +(6) ShuffleQueryStage +Output [2]: [ps_partkey#X, ps_suppkey#X] +Arguments: X + +(7) InputAdapter +Input [2]: [ps_partkey#X, ps_suppkey#X] + +(8) InputIteratorTransformer +Input [2]: [ps_partkey#X, ps_suppkey#X] + +(9) Scan parquet +Output [4]: [p_partkey#X, p_brand#X, p_type#X, p_size#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(p_brand), IsNotNull(p_type), Not(EqualTo(p_brand,Brand#X)), Not(StringStartsWith(p_type,MEDIUM POLISHED)), In(p_size, [14,19,23,3,36,45,49,9]), IsNotNull(p_partkey)] +ReadSchema: struct + +(10) FilterExecTransformer +Input [4]: [p_partkey#X, p_brand#X, p_type#X, p_size#X] +Arguments: (((((isnotnull(p_brand#X) AND isnotnull(p_type#X)) AND NOT (p_brand#X = Brand#X)) AND NOT StartsWith(p_type#X, MEDIUM POLISHED)) AND p_size#X IN (49,14,23,45,19,3,36,9)) AND isnotnull(p_partkey#X)) + +(11) ProjectExecTransformer +Output [5]: [hash(p_partkey#X, 42) AS hash_partition_key#X, p_partkey#X, p_brand#X, p_type#X, p_size#X] +Input [4]: [p_partkey#X, p_brand#X, p_type#X, p_size#X] + +(12) WholeStageCodegenTransformer (X) +Input [5]: [hash_partition_key#X, p_partkey#X, p_brand#X, p_type#X, p_size#X] +Arguments: false + +(13) ColumnarExchange +Input [5]: [hash_partition_key#X, p_partkey#X, p_brand#X, p_type#X, p_size#X] +Arguments: hashpartitioning(p_partkey#X, 1), ENSURE_REQUIREMENTS, [p_partkey#X, p_brand#X, p_type#X, p_size#X], [plan_id=X], [id=#X] + +(14) ShuffleQueryStage +Output [4]: [p_partkey#X, p_brand#X, p_type#X, p_size#X] +Arguments: X + +(15) InputAdapter +Input [4]: [p_partkey#X, p_brand#X, p_type#X, p_size#X] + +(16) InputIteratorTransformer +Input [4]: [p_partkey#X, p_brand#X, p_type#X, p_size#X] + +(17) ShuffledHashJoinExecTransformer +Left keys [1]: [ps_partkey#X] +Right keys [1]: [p_partkey#X] +Join condition: None + +(18) ProjectExecTransformer +Output [4]: [ps_suppkey#X, p_brand#X, p_type#X, p_size#X] +Input [6]: [ps_partkey#X, ps_suppkey#X, p_partkey#X, p_brand#X, p_type#X, p_size#X] + +(19) FlushableHashAggregateExecTransformer +Input [4]: [ps_suppkey#X, p_brand#X, p_type#X, p_size#X] +Keys [4]: [p_brand#X, p_type#X, p_size#X, ps_suppkey#X] +Functions: [] +Aggregate Attributes: [] +Results [4]: [p_brand#X, p_type#X, p_size#X, ps_suppkey#X] + +(20) ProjectExecTransformer +Output [5]: [hash(p_brand#X, p_type#X, p_size#X, ps_suppkey#X, 42) AS hash_partition_key#X, p_brand#X, p_type#X, p_size#X, ps_suppkey#X] +Input [4]: [p_brand#X, p_type#X, p_size#X, ps_suppkey#X] + +(21) WholeStageCodegenTransformer (X) +Input [5]: [hash_partition_key#X, p_brand#X, p_type#X, p_size#X, ps_suppkey#X] +Arguments: false + +(22) ColumnarExchange +Input [5]: [hash_partition_key#X, p_brand#X, p_type#X, p_size#X, ps_suppkey#X] +Arguments: hashpartitioning(p_brand#X, p_type#X, p_size#X, ps_suppkey#X, 1), ENSURE_REQUIREMENTS, [p_brand#X, p_type#X, p_size#X, ps_suppkey#X], [plan_id=X], [id=#X] + +(23) ShuffleQueryStage +Output [4]: [p_brand#X, p_type#X, p_size#X, ps_suppkey#X] +Arguments: X + +(24) InputAdapter +Input [4]: [p_brand#X, p_type#X, p_size#X, ps_suppkey#X] + +(25) InputIteratorTransformer +Input [4]: [p_brand#X, p_type#X, p_size#X, ps_suppkey#X] + +(26) RegularHashAggregateExecTransformer +Input [4]: [p_brand#X, p_type#X, p_size#X, ps_suppkey#X] +Keys [4]: [p_brand#X, p_type#X, p_size#X, ps_suppkey#X] +Functions: [] +Aggregate Attributes: [] +Results [4]: [p_brand#X, p_type#X, p_size#X, ps_suppkey#X] + +(27) FlushableHashAggregateExecTransformer +Input [4]: [p_brand#X, p_type#X, p_size#X, ps_suppkey#X] +Keys [3]: [p_brand#X, p_type#X, p_size#X] +Functions [1]: [partial_count(distinct ps_suppkey#X)] +Aggregate Attributes [1]: [count(ps_suppkey#X)#X] +Results [4]: [p_brand#X, p_type#X, p_size#X, count#X] + +(28) ProjectExecTransformer +Output [5]: [hash(p_brand#X, p_type#X, p_size#X, 42) AS hash_partition_key#X, p_brand#X, p_type#X, p_size#X, count#X] +Input [4]: [p_brand#X, p_type#X, p_size#X, count#X] + +(29) WholeStageCodegenTransformer (X) +Input [5]: [hash_partition_key#X, p_brand#X, p_type#X, p_size#X, count#X] +Arguments: false + +(30) ColumnarExchange +Input [5]: [hash_partition_key#X, p_brand#X, p_type#X, p_size#X, count#X] +Arguments: hashpartitioning(p_brand#X, p_type#X, p_size#X, 1), ENSURE_REQUIREMENTS, [p_brand#X, p_type#X, p_size#X, count#X], [plan_id=X], [id=#X] + +(31) ShuffleQueryStage +Output [4]: [p_brand#X, p_type#X, p_size#X, count#X] +Arguments: X + +(32) InputAdapter +Input [4]: [p_brand#X, p_type#X, p_size#X, count#X] + +(33) InputIteratorTransformer +Input [4]: [p_brand#X, p_type#X, p_size#X, count#X] + +(34) RegularHashAggregateExecTransformer +Input [4]: [p_brand#X, p_type#X, p_size#X, count#X] +Keys [3]: [p_brand#X, p_type#X, p_size#X] +Functions [1]: [count(distinct ps_suppkey#X)] +Aggregate Attributes [1]: [count(ps_suppkey#X)#X] +Results [4]: [p_brand#X, p_type#X, p_size#X, count(ps_suppkey#X)#X AS supplier_cnt#X] + +(35) WholeStageCodegenTransformer (X) +Input [4]: [p_brand#X, p_type#X, p_size#X, supplier_cnt#X] +Arguments: false + +(36) ColumnarExchange +Input [4]: [p_brand#X, p_type#X, p_size#X, supplier_cnt#X] +Arguments: rangepartitioning(supplier_cnt#X DESC NULLS LAST, p_brand#X ASC NULLS FIRST, p_type#X ASC NULLS FIRST, p_size#X ASC NULLS FIRST, 1), ENSURE_REQUIREMENTS, [plan_id=X], [id=#X] + +(37) ShuffleQueryStage +Output [4]: [p_brand#X, p_type#X, p_size#X, supplier_cnt#X] +Arguments: X + +(38) InputAdapter +Input [4]: [p_brand#X, p_type#X, p_size#X, supplier_cnt#X] + +(39) InputIteratorTransformer +Input [4]: [p_brand#X, p_type#X, p_size#X, supplier_cnt#X] + +(40) SortExecTransformer +Input [4]: [p_brand#X, p_type#X, p_size#X, supplier_cnt#X] +Arguments: [supplier_cnt#X DESC NULLS LAST, p_brand#X ASC NULLS FIRST, p_type#X ASC NULLS FIRST, p_size#X ASC NULLS FIRST], true, 0 + +(41) WholeStageCodegenTransformer (X) +Input [4]: [p_brand#X, p_type#X, p_size#X, supplier_cnt#X] +Arguments: false + +(42) VeloxColumnarToRowExec +Input [4]: [p_brand#X, p_type#X, p_size#X, supplier_cnt#X] + +(43) Scan parquet +Output [2]: [ps_partkey#X, ps_suppkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(ps_partkey)] +ReadSchema: struct + +(44) Filter +Input [2]: [ps_partkey#X, ps_suppkey#X] +Condition : isnotnull(ps_partkey#X) + +(45) Scan parquet +Output [2]: [s_suppkey#X, s_comment#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(s_comment)] +ReadSchema: struct + +(46) Filter +Input [2]: [s_suppkey#X, s_comment#X] +Condition : (isnotnull(s_comment#X) AND s_comment#X LIKE %Customer%Complaints%) + +(47) Project +Output [1]: [s_suppkey#X] +Input [2]: [s_suppkey#X, s_comment#X] + +(48) BroadcastExchange +Input [1]: [s_suppkey#X] +Arguments: HashedRelationBroadcastMode(List(input[0, bigint, true]),true), [plan_id=X] + +(49) BroadcastHashJoin +Left keys [1]: [ps_suppkey#X] +Right keys [1]: [s_suppkey#X] +Join condition: None + +(50) Exchange +Input [2]: [ps_partkey#X, ps_suppkey#X] +Arguments: hashpartitioning(ps_partkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(51) Scan parquet +Output [4]: [p_partkey#X, p_brand#X, p_type#X, p_size#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(p_brand), IsNotNull(p_type), Not(EqualTo(p_brand,Brand#X)), Not(StringStartsWith(p_type,MEDIUM POLISHED)), In(p_size, [14,19,23,3,36,45,49,9]), IsNotNull(p_partkey)] +ReadSchema: struct + +(52) Filter +Input [4]: [p_partkey#X, p_brand#X, p_type#X, p_size#X] +Condition : (((((isnotnull(p_brand#X) AND isnotnull(p_type#X)) AND NOT (p_brand#X = Brand#X)) AND NOT StartsWith(p_type#X, MEDIUM POLISHED)) AND p_size#X IN (49,14,23,45,19,3,36,9)) AND isnotnull(p_partkey#X)) + +(53) Exchange +Input [4]: [p_partkey#X, p_brand#X, p_type#X, p_size#X] +Arguments: hashpartitioning(p_partkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(54) ShuffledHashJoin +Left keys [1]: [ps_partkey#X] +Right keys [1]: [p_partkey#X] +Join condition: None + +(55) Project +Output [4]: [ps_suppkey#X, p_brand#X, p_type#X, p_size#X] +Input [6]: [ps_partkey#X, ps_suppkey#X, p_partkey#X, p_brand#X, p_type#X, p_size#X] + +(56) HashAggregate +Input [4]: [ps_suppkey#X, p_brand#X, p_type#X, p_size#X] +Keys [4]: [p_brand#X, p_type#X, p_size#X, ps_suppkey#X] +Functions: [] +Aggregate Attributes: [] +Results [4]: [p_brand#X, p_type#X, p_size#X, ps_suppkey#X] + +(57) Exchange +Input [4]: [p_brand#X, p_type#X, p_size#X, ps_suppkey#X] +Arguments: hashpartitioning(p_brand#X, p_type#X, p_size#X, ps_suppkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(58) HashAggregate +Input [4]: [p_brand#X, p_type#X, p_size#X, ps_suppkey#X] +Keys [4]: [p_brand#X, p_type#X, p_size#X, ps_suppkey#X] +Functions: [] +Aggregate Attributes: [] +Results [4]: [p_brand#X, p_type#X, p_size#X, ps_suppkey#X] + +(59) HashAggregate +Input [4]: [p_brand#X, p_type#X, p_size#X, ps_suppkey#X] +Keys [3]: [p_brand#X, p_type#X, p_size#X] +Functions [1]: [partial_count(distinct ps_suppkey#X)] +Aggregate Attributes [1]: [count(ps_suppkey#X)#X] +Results [4]: [p_brand#X, p_type#X, p_size#X, count#X] + +(60) Exchange +Input [4]: [p_brand#X, p_type#X, p_size#X, count#X] +Arguments: hashpartitioning(p_brand#X, p_type#X, p_size#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(61) HashAggregate +Input [4]: [p_brand#X, p_type#X, p_size#X, count#X] +Keys [3]: [p_brand#X, p_type#X, p_size#X] +Functions [1]: [count(distinct ps_suppkey#X)] +Aggregate Attributes [1]: [count(ps_suppkey#X)#X] +Results [4]: [p_brand#X, p_type#X, p_size#X, count(ps_suppkey#X)#X AS supplier_cnt#X] + +(62) Exchange +Input [4]: [p_brand#X, p_type#X, p_size#X, supplier_cnt#X] +Arguments: rangepartitioning(supplier_cnt#X DESC NULLS LAST, p_brand#X ASC NULLS FIRST, p_type#X ASC NULLS FIRST, p_size#X ASC NULLS FIRST, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(63) Sort +Input [4]: [p_brand#X, p_type#X, p_size#X, supplier_cnt#X] +Arguments: [supplier_cnt#X DESC NULLS LAST, p_brand#X ASC NULLS FIRST, p_type#X ASC NULLS FIRST, p_size#X ASC NULLS FIRST], true, 0 + +(64) AdaptiveSparkPlan +Output [4]: [p_brand#X, p_type#X, p_size#X, supplier_cnt#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/17.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/17.txt new file mode 100644 index 000000000000..04f31f2d7a90 --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/17.txt @@ -0,0 +1,324 @@ +== Physical Plan == +AdaptiveSparkPlan (57) ++- == Final Plan == + VeloxColumnarToRowExec (37) + +- ^ ProjectExecTransformer (35) + +- ^ RegularHashAggregateExecTransformer (34) + +- ^ RegularHashAggregateExecTransformer (33) + +- ^ ProjectExecTransformer (32) + +- ^ ShuffledHashJoinExecTransformer Inner (31) + :- ^ ProjectExecTransformer (18) + : +- ^ ShuffledHashJoinExecTransformer Inner (17) + : :- ^ InputIteratorTransformer (8) + : : +- ^ InputAdapter (7) + : : +- ^ ShuffleQueryStage (6) + : : +- ColumnarExchange (5) + : : +- ^ ProjectExecTransformer (3) + : : +- ^ FilterExecTransformer (2) + : : +- ^ Scan parquet (1) + : +- ^ InputIteratorTransformer (16) + : +- ^ InputAdapter (15) + : +- ^ ShuffleQueryStage (14) + : +- ColumnarExchange (13) + : +- ^ ProjectExecTransformer (11) + : +- ^ FilterExecTransformer (10) + : +- ^ Scan parquet (9) + +- ^ FilterExecTransformer (30) + +- ^ ProjectExecTransformer (29) + +- ^ RegularHashAggregateExecTransformer (28) + +- ^ InputIteratorTransformer (27) + +- ^ InputAdapter (26) + +- ^ ShuffleQueryStage (25) + +- ColumnarExchange (24) + +- ^ ProjectExecTransformer (22) + +- ^ FlushableHashAggregateExecTransformer (21) + +- ^ FilterExecTransformer (20) + +- ^ Scan parquet (19) ++- == Initial Plan == + HashAggregate (56) + +- HashAggregate (55) + +- Project (54) + +- ShuffledHashJoin Inner BuildRight (53) + :- Project (46) + : +- ShuffledHashJoin Inner BuildRight (45) + : :- Exchange (40) + : : +- Filter (39) + : : +- Scan parquet (38) + : +- Exchange (44) + : +- Project (43) + : +- Filter (42) + : +- Scan parquet (41) + +- Filter (52) + +- HashAggregate (51) + +- Exchange (50) + +- HashAggregate (49) + +- Filter (48) + +- Scan parquet (47) + + +(1) Scan parquet +Output [3]: [l_partkey#X, l_quantity#X, l_extendedprice#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_partkey), IsNotNull(l_quantity)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [3]: [l_partkey#X, l_quantity#X, l_extendedprice#X] +Arguments: (isnotnull(l_partkey#X) AND isnotnull(l_quantity#X)) + +(3) ProjectExecTransformer +Output [4]: [hash(l_partkey#X, 42) AS hash_partition_key#X, l_partkey#X, l_quantity#X, l_extendedprice#X] +Input [3]: [l_partkey#X, l_quantity#X, l_extendedprice#X] + +(4) WholeStageCodegenTransformer (X) +Input [4]: [hash_partition_key#X, l_partkey#X, l_quantity#X, l_extendedprice#X] +Arguments: false + +(5) ColumnarExchange +Input [4]: [hash_partition_key#X, l_partkey#X, l_quantity#X, l_extendedprice#X] +Arguments: hashpartitioning(l_partkey#X, 1), ENSURE_REQUIREMENTS, [l_partkey#X, l_quantity#X, l_extendedprice#X], [plan_id=X], [id=#X] + +(6) ShuffleQueryStage +Output [3]: [l_partkey#X, l_quantity#X, l_extendedprice#X] +Arguments: X + +(7) InputAdapter +Input [3]: [l_partkey#X, l_quantity#X, l_extendedprice#X] + +(8) InputIteratorTransformer +Input [3]: [l_partkey#X, l_quantity#X, l_extendedprice#X] + +(9) Scan parquet +Output [3]: [p_partkey#X, p_brand#X, p_container#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(p_brand), IsNotNull(p_container), EqualTo(p_brand,Brand#X), EqualTo(p_container,MED BOX), IsNotNull(p_partkey)] +ReadSchema: struct + +(10) FilterExecTransformer +Input [3]: [p_partkey#X, p_brand#X, p_container#X] +Arguments: ((((isnotnull(p_brand#X) AND isnotnull(p_container#X)) AND (p_brand#X = Brand#X)) AND (p_container#X = MED BOX)) AND isnotnull(p_partkey#X)) + +(11) ProjectExecTransformer +Output [2]: [hash(p_partkey#X, 42) AS hash_partition_key#X, p_partkey#X] +Input [3]: [p_partkey#X, p_brand#X, p_container#X] + +(12) WholeStageCodegenTransformer (X) +Input [2]: [hash_partition_key#X, p_partkey#X] +Arguments: false + +(13) ColumnarExchange +Input [2]: [hash_partition_key#X, p_partkey#X] +Arguments: hashpartitioning(p_partkey#X, 1), ENSURE_REQUIREMENTS, [p_partkey#X], [plan_id=X], [id=#X] + +(14) ShuffleQueryStage +Output [1]: [p_partkey#X] +Arguments: X + +(15) InputAdapter +Input [1]: [p_partkey#X] + +(16) InputIteratorTransformer +Input [1]: [p_partkey#X] + +(17) ShuffledHashJoinExecTransformer +Left keys [1]: [l_partkey#X] +Right keys [1]: [p_partkey#X] +Join condition: None + +(18) ProjectExecTransformer +Output [3]: [l_quantity#X, l_extendedprice#X, p_partkey#X] +Input [4]: [l_partkey#X, l_quantity#X, l_extendedprice#X, p_partkey#X] + +(19) Scan parquet +Output [2]: [l_partkey#X, l_quantity#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_partkey)] +ReadSchema: struct + +(20) FilterExecTransformer +Input [2]: [l_partkey#X, l_quantity#X] +Arguments: isnotnull(l_partkey#X) + +(21) FlushableHashAggregateExecTransformer +Input [2]: [l_partkey#X, l_quantity#X] +Keys [1]: [l_partkey#X] +Functions [1]: [partial_avg(l_quantity#X)] +Aggregate Attributes [2]: [sum#X, count#X] +Results [3]: [l_partkey#X, sum#X, count#X] + +(22) ProjectExecTransformer +Output [4]: [hash(l_partkey#X, 42) AS hash_partition_key#X, l_partkey#X, sum#X, count#X] +Input [3]: [l_partkey#X, sum#X, count#X] + +(23) WholeStageCodegenTransformer (X) +Input [4]: [hash_partition_key#X, l_partkey#X, sum#X, count#X] +Arguments: false + +(24) ColumnarExchange +Input [4]: [hash_partition_key#X, l_partkey#X, sum#X, count#X] +Arguments: hashpartitioning(l_partkey#X, 1), ENSURE_REQUIREMENTS, [l_partkey#X, sum#X, count#X], [plan_id=X], [id=#X] + +(25) ShuffleQueryStage +Output [3]: [l_partkey#X, sum#X, count#X] +Arguments: X + +(26) InputAdapter +Input [3]: [l_partkey#X, sum#X, count#X] + +(27) InputIteratorTransformer +Input [3]: [l_partkey#X, sum#X, count#X] + +(28) RegularHashAggregateExecTransformer +Input [3]: [l_partkey#X, sum#X, count#X] +Keys [1]: [l_partkey#X] +Functions [1]: [avg(l_quantity#X)] +Aggregate Attributes [1]: [avg(l_quantity#X)#X] +Results [2]: [l_partkey#X, avg(l_quantity#X)#X] + +(29) ProjectExecTransformer +Output [2]: [CheckOverflow((0.200000 * promote_precision(avg(l_quantity#X)#X)), DecimalType(18,7), true) AS (0.2 * avg(l_quantity))#X, l_partkey#X] +Input [2]: [l_partkey#X, avg(l_quantity#X)#X] + +(30) FilterExecTransformer +Input [2]: [(0.2 * avg(l_quantity))#X, l_partkey#X] +Arguments: isnotnull((0.2 * avg(l_quantity))#X) + +(31) ShuffledHashJoinExecTransformer +Left keys [1]: [p_partkey#X] +Right keys [1]: [l_partkey#X] +Join condition: (cast(l_quantity#X as decimal(18,7)) < (0.2 * avg(l_quantity))#X) + +(32) ProjectExecTransformer +Output [1]: [l_extendedprice#X] +Input [5]: [l_quantity#X, l_extendedprice#X, p_partkey#X, (0.2 * avg(l_quantity))#X, l_partkey#X] + +(33) RegularHashAggregateExecTransformer +Input [1]: [l_extendedprice#X] +Keys: [] +Functions [1]: [partial_sum(l_extendedprice#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [2]: [sum#X, isEmpty#X] + +(34) RegularHashAggregateExecTransformer +Input [2]: [sum#X, isEmpty#X] +Keys: [] +Functions [1]: [sum(l_extendedprice#X)] +Aggregate Attributes [1]: [sum(l_extendedprice#X)#X] +Results [1]: [sum(l_extendedprice#X)#X] + +(35) ProjectExecTransformer +Output [1]: [CheckOverflow((promote_precision(sum(l_extendedprice#X)#X) / 7.00), DecimalType(27,6), true) AS avg_yearly#X] +Input [1]: [sum(l_extendedprice#X)#X] + +(36) WholeStageCodegenTransformer (X) +Input [1]: [avg_yearly#X] +Arguments: false + +(37) VeloxColumnarToRowExec +Input [1]: [avg_yearly#X] + +(38) Scan parquet +Output [3]: [l_partkey#X, l_quantity#X, l_extendedprice#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_partkey), IsNotNull(l_quantity)] +ReadSchema: struct + +(39) Filter +Input [3]: [l_partkey#X, l_quantity#X, l_extendedprice#X] +Condition : (isnotnull(l_partkey#X) AND isnotnull(l_quantity#X)) + +(40) Exchange +Input [3]: [l_partkey#X, l_quantity#X, l_extendedprice#X] +Arguments: hashpartitioning(l_partkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(41) Scan parquet +Output [3]: [p_partkey#X, p_brand#X, p_container#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(p_brand), IsNotNull(p_container), EqualTo(p_brand,Brand#X), EqualTo(p_container,MED BOX), IsNotNull(p_partkey)] +ReadSchema: struct + +(42) Filter +Input [3]: [p_partkey#X, p_brand#X, p_container#X] +Condition : ((((isnotnull(p_brand#X) AND isnotnull(p_container#X)) AND (p_brand#X = Brand#X)) AND (p_container#X = MED BOX)) AND isnotnull(p_partkey#X)) + +(43) Project +Output [1]: [p_partkey#X] +Input [3]: [p_partkey#X, p_brand#X, p_container#X] + +(44) Exchange +Input [1]: [p_partkey#X] +Arguments: hashpartitioning(p_partkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(45) ShuffledHashJoin +Left keys [1]: [l_partkey#X] +Right keys [1]: [p_partkey#X] +Join condition: None + +(46) Project +Output [3]: [l_quantity#X, l_extendedprice#X, p_partkey#X] +Input [4]: [l_partkey#X, l_quantity#X, l_extendedprice#X, p_partkey#X] + +(47) Scan parquet +Output [2]: [l_partkey#X, l_quantity#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_partkey)] +ReadSchema: struct + +(48) Filter +Input [2]: [l_partkey#X, l_quantity#X] +Condition : isnotnull(l_partkey#X) + +(49) HashAggregate +Input [2]: [l_partkey#X, l_quantity#X] +Keys [1]: [l_partkey#X] +Functions [1]: [partial_avg(l_quantity#X)] +Aggregate Attributes [2]: [sum#X, count#X] +Results [3]: [l_partkey#X, sum#X, count#X] + +(50) Exchange +Input [3]: [l_partkey#X, sum#X, count#X] +Arguments: hashpartitioning(l_partkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(51) HashAggregate +Input [3]: [l_partkey#X, sum#X, count#X] +Keys [1]: [l_partkey#X] +Functions [1]: [avg(l_quantity#X)] +Aggregate Attributes [1]: [avg(l_quantity#X)#X] +Results [2]: [CheckOverflow((0.200000 * promote_precision(avg(l_quantity#X)#X)), DecimalType(18,7), true) AS (0.2 * avg(l_quantity))#X, l_partkey#X] + +(52) Filter +Input [2]: [(0.2 * avg(l_quantity))#X, l_partkey#X] +Condition : isnotnull((0.2 * avg(l_quantity))#X) + +(53) ShuffledHashJoin +Left keys [1]: [p_partkey#X] +Right keys [1]: [l_partkey#X] +Join condition: (cast(l_quantity#X as decimal(18,7)) < (0.2 * avg(l_quantity))#X) + +(54) Project +Output [1]: [l_extendedprice#X] +Input [5]: [l_quantity#X, l_extendedprice#X, p_partkey#X, (0.2 * avg(l_quantity))#X, l_partkey#X] + +(55) HashAggregate +Input [1]: [l_extendedprice#X] +Keys: [] +Functions [1]: [partial_sum(l_extendedprice#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [2]: [sum#X, isEmpty#X] + +(56) HashAggregate +Input [2]: [sum#X, isEmpty#X] +Keys: [] +Functions [1]: [sum(l_extendedprice#X)] +Aggregate Attributes [1]: [sum(l_extendedprice#X)#X] +Results [1]: [CheckOverflow((promote_precision(sum(l_extendedprice#X)#X) / 7.00), DecimalType(27,6), true) AS avg_yearly#X] + +(57) AdaptiveSparkPlan +Output [1]: [avg_yearly#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/18.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/18.txt new file mode 100644 index 000000000000..ac59fbf6e10f --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/18.txt @@ -0,0 +1,531 @@ +== Physical Plan == +AdaptiveSparkPlan (97) ++- == Final Plan == + VeloxColumnarToRowExec (64) + +- TakeOrderedAndProjectExecTransformer (63) + +- ^ RegularHashAggregateExecTransformer (61) + +- ^ RegularHashAggregateExecTransformer (60) + +- ^ ProjectExecTransformer (59) + +- ^ ShuffledHashJoinExecTransformer Inner (58) + :- ^ InputIteratorTransformer (41) + : +- ^ InputAdapter (40) + : +- ^ ShuffleQueryStage (39) + : +- ColumnarExchange (38) + : +- ^ ProjectExecTransformer (36) + : +- ^ ShuffledHashJoinExecTransformer Inner (35) + : :- ^ InputIteratorTransformer (8) + : : +- ^ InputAdapter (7) + : : +- ^ ShuffleQueryStage (6) + : : +- ColumnarExchange (5) + : : +- ^ ProjectExecTransformer (3) + : : +- ^ FilterExecTransformer (2) + : : +- ^ Scan parquet (1) + : +- ^ InputIteratorTransformer (34) + : +- ^ InputAdapter (33) + : +- ^ ShuffleQueryStage (32) + : +- ColumnarExchange (31) + : +- ^ ProjectExecTransformer (29) + : +- ^ ShuffledHashJoinExecTransformer LeftSemi (28) + : :- ^ InputIteratorTransformer (16) + : : +- ^ InputAdapter (15) + : : +- ^ ShuffleQueryStage (14) + : : +- ColumnarExchange (13) + : : +- ^ ProjectExecTransformer (11) + : : +- ^ FilterExecTransformer (10) + : : +- ^ Scan parquet (9) + : +- ^ ProjectExecTransformer (27) + : +- ^ FilterExecTransformer (26) + : +- ^ RegularHashAggregateExecTransformer (25) + : +- ^ InputIteratorTransformer (24) + : +- ^ InputAdapter (23) + : +- ^ ShuffleQueryStage (22) + : +- ColumnarExchange (21) + : +- ^ ProjectExecTransformer (19) + : +- ^ FlushableHashAggregateExecTransformer (18) + : +- ^ Scan parquet (17) + +- ^ ShuffledHashJoinExecTransformer LeftSemi (57) + :- ^ InputIteratorTransformer (49) + : +- ^ InputAdapter (48) + : +- ^ ShuffleQueryStage (47) + : +- ColumnarExchange (46) + : +- ^ ProjectExecTransformer (44) + : +- ^ FilterExecTransformer (43) + : +- ^ Scan parquet (42) + +- ^ ProjectExecTransformer (56) + +- ^ FilterExecTransformer (55) + +- ^ RegularHashAggregateExecTransformer (54) + +- ^ InputIteratorTransformer (53) + +- ^ InputAdapter (52) + +- ^ ShuffleQueryStage (51) + +- ReusedExchange (50) ++- == Initial Plan == + TakeOrderedAndProject (96) + +- HashAggregate (95) + +- HashAggregate (94) + +- Project (93) + +- ShuffledHashJoin Inner BuildRight (92) + :- Exchange (81) + : +- Project (80) + : +- ShuffledHashJoin Inner BuildLeft (79) + : :- Exchange (67) + : : +- Filter (66) + : : +- Scan parquet (65) + : +- Exchange (78) + : +- ShuffledHashJoin LeftSemi BuildRight (77) + : :- Exchange (70) + : : +- Filter (69) + : : +- Scan parquet (68) + : +- Project (76) + : +- Filter (75) + : +- HashAggregate (74) + : +- Exchange (73) + : +- HashAggregate (72) + : +- Scan parquet (71) + +- ShuffledHashJoin LeftSemi BuildRight (91) + :- Exchange (84) + : +- Filter (83) + : +- Scan parquet (82) + +- Project (90) + +- Filter (89) + +- HashAggregate (88) + +- Exchange (87) + +- HashAggregate (86) + +- Scan parquet (85) + + +(1) Scan parquet +Output [2]: [c_custkey#X, c_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(c_custkey)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [2]: [c_custkey#X, c_name#X] +Arguments: isnotnull(c_custkey#X) + +(3) ProjectExecTransformer +Output [3]: [hash(c_custkey#X, 42) AS hash_partition_key#X, c_custkey#X, c_name#X] +Input [2]: [c_custkey#X, c_name#X] + +(4) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, c_custkey#X, c_name#X] +Arguments: false + +(5) ColumnarExchange +Input [3]: [hash_partition_key#X, c_custkey#X, c_name#X] +Arguments: hashpartitioning(c_custkey#X, 1), ENSURE_REQUIREMENTS, [c_custkey#X, c_name#X], [plan_id=X], [id=#X] + +(6) ShuffleQueryStage +Output [2]: [c_custkey#X, c_name#X] +Arguments: X + +(7) InputAdapter +Input [2]: [c_custkey#X, c_name#X] + +(8) InputIteratorTransformer +Input [2]: [c_custkey#X, c_name#X] + +(9) Scan parquet +Output [4]: [o_orderkey#X, o_custkey#X, o_totalprice#X, o_orderdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_custkey), IsNotNull(o_orderkey)] +ReadSchema: struct + +(10) FilterExecTransformer +Input [4]: [o_orderkey#X, o_custkey#X, o_totalprice#X, o_orderdate#X] +Arguments: (isnotnull(o_custkey#X) AND isnotnull(o_orderkey#X)) + +(11) ProjectExecTransformer +Output [5]: [hash(o_orderkey#X, 42) AS hash_partition_key#X, o_orderkey#X, o_custkey#X, o_totalprice#X, o_orderdate#X] +Input [4]: [o_orderkey#X, o_custkey#X, o_totalprice#X, o_orderdate#X] + +(12) WholeStageCodegenTransformer (X) +Input [5]: [hash_partition_key#X, o_orderkey#X, o_custkey#X, o_totalprice#X, o_orderdate#X] +Arguments: false + +(13) ColumnarExchange +Input [5]: [hash_partition_key#X, o_orderkey#X, o_custkey#X, o_totalprice#X, o_orderdate#X] +Arguments: hashpartitioning(o_orderkey#X, 1), ENSURE_REQUIREMENTS, [o_orderkey#X, o_custkey#X, o_totalprice#X, o_orderdate#X], [plan_id=X], [id=#X] + +(14) ShuffleQueryStage +Output [4]: [o_orderkey#X, o_custkey#X, o_totalprice#X, o_orderdate#X] +Arguments: X + +(15) InputAdapter +Input [4]: [o_orderkey#X, o_custkey#X, o_totalprice#X, o_orderdate#X] + +(16) InputIteratorTransformer +Input [4]: [o_orderkey#X, o_custkey#X, o_totalprice#X, o_orderdate#X] + +(17) Scan parquet +Output [2]: [l_orderkey#X, l_quantity#X] +Batched: true +Location: InMemoryFileIndex [*] +ReadSchema: struct + +(18) FlushableHashAggregateExecTransformer +Input [2]: [l_orderkey#X, l_quantity#X] +Keys [1]: [l_orderkey#X] +Functions [1]: [partial_sum(l_quantity#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [3]: [l_orderkey#X, sum#X, isEmpty#X] + +(19) ProjectExecTransformer +Output [4]: [hash(l_orderkey#X, 42) AS hash_partition_key#X, l_orderkey#X, sum#X, isEmpty#X] +Input [3]: [l_orderkey#X, sum#X, isEmpty#X] + +(20) WholeStageCodegenTransformer (X) +Input [4]: [hash_partition_key#X, l_orderkey#X, sum#X, isEmpty#X] +Arguments: false + +(21) ColumnarExchange +Input [4]: [hash_partition_key#X, l_orderkey#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(l_orderkey#X, 1), ENSURE_REQUIREMENTS, [l_orderkey#X, sum#X, isEmpty#X], [plan_id=X], [id=#X] + +(22) ShuffleQueryStage +Output [3]: [l_orderkey#X, sum#X, isEmpty#X] +Arguments: X + +(23) InputAdapter +Input [3]: [l_orderkey#X, sum#X, isEmpty#X] + +(24) InputIteratorTransformer +Input [3]: [l_orderkey#X, sum#X, isEmpty#X] + +(25) RegularHashAggregateExecTransformer +Input [3]: [l_orderkey#X, sum#X, isEmpty#X] +Keys [1]: [l_orderkey#X] +Functions [1]: [sum(l_quantity#X)] +Aggregate Attributes [1]: [sum(l_quantity#X)#X] +Results [2]: [l_orderkey#X, sum(l_quantity#X)#X AS sum(l_quantity#X)#X] + +(26) FilterExecTransformer +Input [2]: [l_orderkey#X, sum(l_quantity#X)#X] +Arguments: (isnotnull(sum(l_quantity#X)#X) AND (sum(l_quantity#X)#X > 300.00)) + +(27) ProjectExecTransformer +Output [1]: [l_orderkey#X] +Input [2]: [l_orderkey#X, sum(l_quantity#X)#X] + +(28) ShuffledHashJoinExecTransformer +Left keys [1]: [o_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: None + +(29) ProjectExecTransformer +Output [5]: [hash(o_custkey#X, 42) AS hash_partition_key#X, o_orderkey#X, o_custkey#X, o_totalprice#X, o_orderdate#X] +Input [4]: [o_orderkey#X, o_custkey#X, o_totalprice#X, o_orderdate#X] + +(30) WholeStageCodegenTransformer (X) +Input [5]: [hash_partition_key#X, o_orderkey#X, o_custkey#X, o_totalprice#X, o_orderdate#X] +Arguments: false + +(31) ColumnarExchange +Input [5]: [hash_partition_key#X, o_orderkey#X, o_custkey#X, o_totalprice#X, o_orderdate#X] +Arguments: hashpartitioning(o_custkey#X, 1), ENSURE_REQUIREMENTS, [o_orderkey#X, o_custkey#X, o_totalprice#X, o_orderdate#X], [plan_id=X], [id=#X] + +(32) ShuffleQueryStage +Output [4]: [o_orderkey#X, o_custkey#X, o_totalprice#X, o_orderdate#X] +Arguments: X + +(33) InputAdapter +Input [4]: [o_orderkey#X, o_custkey#X, o_totalprice#X, o_orderdate#X] + +(34) InputIteratorTransformer +Input [4]: [o_orderkey#X, o_custkey#X, o_totalprice#X, o_orderdate#X] + +(35) ShuffledHashJoinExecTransformer +Left keys [1]: [c_custkey#X] +Right keys [1]: [o_custkey#X] +Join condition: None + +(36) ProjectExecTransformer +Output [6]: [hash(o_orderkey#X, 42) AS hash_partition_key#X, c_custkey#X, c_name#X, o_orderkey#X, o_totalprice#X, o_orderdate#X] +Input [6]: [c_custkey#X, c_name#X, o_orderkey#X, o_custkey#X, o_totalprice#X, o_orderdate#X] + +(37) WholeStageCodegenTransformer (X) +Input [6]: [hash_partition_key#X, c_custkey#X, c_name#X, o_orderkey#X, o_totalprice#X, o_orderdate#X] +Arguments: false + +(38) ColumnarExchange +Input [6]: [hash_partition_key#X, c_custkey#X, c_name#X, o_orderkey#X, o_totalprice#X, o_orderdate#X] +Arguments: hashpartitioning(o_orderkey#X, 1), ENSURE_REQUIREMENTS, [c_custkey#X, c_name#X, o_orderkey#X, o_totalprice#X, o_orderdate#X], [plan_id=X], [id=#X] + +(39) ShuffleQueryStage +Output [5]: [c_custkey#X, c_name#X, o_orderkey#X, o_totalprice#X, o_orderdate#X] +Arguments: X + +(40) InputAdapter +Input [5]: [c_custkey#X, c_name#X, o_orderkey#X, o_totalprice#X, o_orderdate#X] + +(41) InputIteratorTransformer +Input [5]: [c_custkey#X, c_name#X, o_orderkey#X, o_totalprice#X, o_orderdate#X] + +(42) Scan parquet +Output [2]: [l_orderkey#X, l_quantity#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_orderkey)] +ReadSchema: struct + +(43) FilterExecTransformer +Input [2]: [l_orderkey#X, l_quantity#X] +Arguments: isnotnull(l_orderkey#X) + +(44) ProjectExecTransformer +Output [3]: [hash(l_orderkey#X, 42) AS hash_partition_key#X, l_orderkey#X, l_quantity#X] +Input [2]: [l_orderkey#X, l_quantity#X] + +(45) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, l_orderkey#X, l_quantity#X] +Arguments: false + +(46) ColumnarExchange +Input [3]: [hash_partition_key#X, l_orderkey#X, l_quantity#X] +Arguments: hashpartitioning(l_orderkey#X, 1), ENSURE_REQUIREMENTS, [l_orderkey#X, l_quantity#X], [plan_id=X], [id=#X] + +(47) ShuffleQueryStage +Output [2]: [l_orderkey#X, l_quantity#X] +Arguments: X + +(48) InputAdapter +Input [2]: [l_orderkey#X, l_quantity#X] + +(49) InputIteratorTransformer +Input [2]: [l_orderkey#X, l_quantity#X] + +(50) ReusedExchange [Reuses operator id: 21] +Output [3]: [l_orderkey#X, sum#X, isEmpty#X] + +(51) ShuffleQueryStage +Output [3]: [l_orderkey#X, sum#X, isEmpty#X] +Arguments: X + +(52) InputAdapter +Input [3]: [l_orderkey#X, sum#X, isEmpty#X] + +(53) InputIteratorTransformer +Input [3]: [l_orderkey#X, sum#X, isEmpty#X] + +(54) RegularHashAggregateExecTransformer +Input [3]: [l_orderkey#X, sum#X, isEmpty#X] +Keys [1]: [l_orderkey#X] +Functions [1]: [sum(l_quantity#X)] +Aggregate Attributes [1]: [sum(l_quantity#X)#X] +Results [2]: [l_orderkey#X, sum(l_quantity#X)#X AS sum(l_quantity#X)#X] + +(55) FilterExecTransformer +Input [2]: [l_orderkey#X, sum(l_quantity#X)#X] +Arguments: (isnotnull(sum(l_quantity#X)#X) AND (sum(l_quantity#X)#X > 300.00)) + +(56) ProjectExecTransformer +Output [1]: [l_orderkey#X] +Input [2]: [l_orderkey#X, sum(l_quantity#X)#X] + +(57) ShuffledHashJoinExecTransformer +Left keys [1]: [l_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: None + +(58) ShuffledHashJoinExecTransformer +Left keys [1]: [o_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: None + +(59) ProjectExecTransformer +Output [6]: [c_custkey#X, c_name#X, o_orderkey#X, o_totalprice#X, o_orderdate#X, l_quantity#X] +Input [7]: [c_custkey#X, c_name#X, o_orderkey#X, o_totalprice#X, o_orderdate#X, l_orderkey#X, l_quantity#X] + +(60) RegularHashAggregateExecTransformer +Input [6]: [c_custkey#X, c_name#X, o_orderkey#X, o_totalprice#X, o_orderdate#X, l_quantity#X] +Keys [5]: [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X] +Functions [1]: [partial_sum(l_quantity#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [7]: [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, sum#X, isEmpty#X] + +(61) RegularHashAggregateExecTransformer +Input [7]: [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, sum#X, isEmpty#X] +Keys [5]: [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X] +Functions [1]: [sum(l_quantity#X)] +Aggregate Attributes [1]: [sum(l_quantity#X)#X] +Results [6]: [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, sum(l_quantity#X)#X AS sum(l_quantity)#X] + +(62) WholeStageCodegenTransformer (X) +Input [6]: [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, sum(l_quantity)#X] +Arguments: false + +(63) TakeOrderedAndProjectExecTransformer +Input [6]: [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, sum(l_quantity)#X] +Arguments: X, [o_totalprice#X DESC NULLS LAST, o_orderdate#X ASC NULLS FIRST], [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, sum(l_quantity)#X], 0 + +(64) VeloxColumnarToRowExec +Input [6]: [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, sum(l_quantity)#X] + +(65) Scan parquet +Output [2]: [c_custkey#X, c_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(c_custkey)] +ReadSchema: struct + +(66) Filter +Input [2]: [c_custkey#X, c_name#X] +Condition : isnotnull(c_custkey#X) + +(67) Exchange +Input [2]: [c_custkey#X, c_name#X] +Arguments: hashpartitioning(c_custkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(68) Scan parquet +Output [4]: [o_orderkey#X, o_custkey#X, o_totalprice#X, o_orderdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_custkey), IsNotNull(o_orderkey)] +ReadSchema: struct + +(69) Filter +Input [4]: [o_orderkey#X, o_custkey#X, o_totalprice#X, o_orderdate#X] +Condition : (isnotnull(o_custkey#X) AND isnotnull(o_orderkey#X)) + +(70) Exchange +Input [4]: [o_orderkey#X, o_custkey#X, o_totalprice#X, o_orderdate#X] +Arguments: hashpartitioning(o_orderkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(71) Scan parquet +Output [2]: [l_orderkey#X, l_quantity#X] +Batched: true +Location: InMemoryFileIndex [*] +ReadSchema: struct + +(72) HashAggregate +Input [2]: [l_orderkey#X, l_quantity#X] +Keys [1]: [l_orderkey#X] +Functions [1]: [partial_sum(l_quantity#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [3]: [l_orderkey#X, sum#X, isEmpty#X] + +(73) Exchange +Input [3]: [l_orderkey#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(l_orderkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(74) HashAggregate +Input [3]: [l_orderkey#X, sum#X, isEmpty#X] +Keys [1]: [l_orderkey#X] +Functions [1]: [sum(l_quantity#X)] +Aggregate Attributes [1]: [sum(l_quantity#X)#X] +Results [2]: [l_orderkey#X, sum(l_quantity#X)#X AS sum(l_quantity#X)#X] + +(75) Filter +Input [2]: [l_orderkey#X, sum(l_quantity#X)#X] +Condition : (isnotnull(sum(l_quantity#X)#X) AND (sum(l_quantity#X)#X > 300.00)) + +(76) Project +Output [1]: [l_orderkey#X] +Input [2]: [l_orderkey#X, sum(l_quantity#X)#X] + +(77) ShuffledHashJoin +Left keys [1]: [o_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: None + +(78) Exchange +Input [4]: [o_orderkey#X, o_custkey#X, o_totalprice#X, o_orderdate#X] +Arguments: hashpartitioning(o_custkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(79) ShuffledHashJoin +Left keys [1]: [c_custkey#X] +Right keys [1]: [o_custkey#X] +Join condition: None + +(80) Project +Output [5]: [c_custkey#X, c_name#X, o_orderkey#X, o_totalprice#X, o_orderdate#X] +Input [6]: [c_custkey#X, c_name#X, o_orderkey#X, o_custkey#X, o_totalprice#X, o_orderdate#X] + +(81) Exchange +Input [5]: [c_custkey#X, c_name#X, o_orderkey#X, o_totalprice#X, o_orderdate#X] +Arguments: hashpartitioning(o_orderkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(82) Scan parquet +Output [2]: [l_orderkey#X, l_quantity#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_orderkey)] +ReadSchema: struct + +(83) Filter +Input [2]: [l_orderkey#X, l_quantity#X] +Condition : isnotnull(l_orderkey#X) + +(84) Exchange +Input [2]: [l_orderkey#X, l_quantity#X] +Arguments: hashpartitioning(l_orderkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(85) Scan parquet +Output [2]: [l_orderkey#X, l_quantity#X] +Batched: true +Location: InMemoryFileIndex [*] +ReadSchema: struct + +(86) HashAggregate +Input [2]: [l_orderkey#X, l_quantity#X] +Keys [1]: [l_orderkey#X] +Functions [1]: [partial_sum(l_quantity#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [3]: [l_orderkey#X, sum#X, isEmpty#X] + +(87) Exchange +Input [3]: [l_orderkey#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(l_orderkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(88) HashAggregate +Input [3]: [l_orderkey#X, sum#X, isEmpty#X] +Keys [1]: [l_orderkey#X] +Functions [1]: [sum(l_quantity#X)] +Aggregate Attributes [1]: [sum(l_quantity#X)#X] +Results [2]: [l_orderkey#X, sum(l_quantity#X)#X AS sum(l_quantity#X)#X] + +(89) Filter +Input [2]: [l_orderkey#X, sum(l_quantity#X)#X] +Condition : (isnotnull(sum(l_quantity#X)#X) AND (sum(l_quantity#X)#X > 300.00)) + +(90) Project +Output [1]: [l_orderkey#X] +Input [2]: [l_orderkey#X, sum(l_quantity#X)#X] + +(91) ShuffledHashJoin +Left keys [1]: [l_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: None + +(92) ShuffledHashJoin +Left keys [1]: [o_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: None + +(93) Project +Output [6]: [c_custkey#X, c_name#X, o_orderkey#X, o_totalprice#X, o_orderdate#X, l_quantity#X] +Input [7]: [c_custkey#X, c_name#X, o_orderkey#X, o_totalprice#X, o_orderdate#X, l_orderkey#X, l_quantity#X] + +(94) HashAggregate +Input [6]: [c_custkey#X, c_name#X, o_orderkey#X, o_totalprice#X, o_orderdate#X, l_quantity#X] +Keys [5]: [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X] +Functions [1]: [partial_sum(l_quantity#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [7]: [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, sum#X, isEmpty#X] + +(95) HashAggregate +Input [7]: [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, sum#X, isEmpty#X] +Keys [5]: [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X] +Functions [1]: [sum(l_quantity#X)] +Aggregate Attributes [1]: [sum(l_quantity#X)#X] +Results [6]: [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, sum(l_quantity#X)#X AS sum(l_quantity)#X] + +(96) TakeOrderedAndProject +Input [6]: [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, sum(l_quantity)#X] +Arguments: X, [o_totalprice#X DESC NULLS LAST, o_orderdate#X ASC NULLS FIRST], [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, sum(l_quantity)#X] + +(97) AdaptiveSparkPlan +Output [6]: [c_name#X, c_custkey#X, o_orderkey#X, o_orderdate#X, o_totalprice#X, sum(l_quantity)#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/19.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/19.txt new file mode 100644 index 000000000000..a487e53d23b9 --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/19.txt @@ -0,0 +1,192 @@ +== Physical Plan == +AdaptiveSparkPlan (34) ++- == Final Plan == + VeloxColumnarToRowExec (22) + +- ^ RegularHashAggregateExecTransformer (20) + +- ^ RegularHashAggregateExecTransformer (19) + +- ^ ProjectExecTransformer (18) + +- ^ ShuffledHashJoinExecTransformer Inner (17) + :- ^ InputIteratorTransformer (8) + : +- ^ InputAdapter (7) + : +- ^ ShuffleQueryStage (6) + : +- ColumnarExchange (5) + : +- ^ ProjectExecTransformer (3) + : +- ^ FilterExecTransformer (2) + : +- ^ Scan parquet (1) + +- ^ InputIteratorTransformer (16) + +- ^ InputAdapter (15) + +- ^ ShuffleQueryStage (14) + +- ColumnarExchange (13) + +- ^ ProjectExecTransformer (11) + +- ^ FilterExecTransformer (10) + +- ^ Scan parquet (9) ++- == Initial Plan == + HashAggregate (33) + +- HashAggregate (32) + +- Project (31) + +- ShuffledHashJoin Inner BuildRight (30) + :- Exchange (26) + : +- Project (25) + : +- Filter (24) + : +- Scan parquet (23) + +- Exchange (29) + +- Filter (28) + +- Scan parquet (27) + + +(1) Scan parquet +Output [6]: [l_partkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, l_shipinstruct#X, l_shipmode#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_shipinstruct), In(l_shipmode, [AIR,AIR REG]), EqualTo(l_shipinstruct,DELIVER IN PERSON), IsNotNull(l_partkey), Or(Or(And(GreaterThanOrEqual(l_quantity,1.00),LessThanOrEqual(l_quantity,11.00)),And(GreaterThanOrEqual(l_quantity,10.00),LessThanOrEqual(l_quantity,20.00))),And(GreaterThanOrEqual(l_quantity,20.00),LessThanOrEqual(l_quantity,30.00)))] +ReadSchema: struct + +(2) FilterExecTransformer +Input [6]: [l_partkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, l_shipinstruct#X, l_shipmode#X] +Arguments: ((((isnotnull(l_shipinstruct#X) AND l_shipmode#X IN (AIR,AIR REG)) AND (l_shipinstruct#X = DELIVER IN PERSON)) AND isnotnull(l_partkey#X)) AND ((((l_quantity#X >= 1.00) AND (l_quantity#X <= 11.00)) OR ((l_quantity#X >= 10.00) AND (l_quantity#X <= 20.00))) OR ((l_quantity#X >= 20.00) AND (l_quantity#X <= 30.00)))) + +(3) ProjectExecTransformer +Output [5]: [hash(l_partkey#X, 42) AS hash_partition_key#X, l_partkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] +Input [6]: [l_partkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, l_shipinstruct#X, l_shipmode#X] + +(4) WholeStageCodegenTransformer (X) +Input [5]: [hash_partition_key#X, l_partkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] +Arguments: false + +(5) ColumnarExchange +Input [5]: [hash_partition_key#X, l_partkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] +Arguments: hashpartitioning(l_partkey#X, 1), ENSURE_REQUIREMENTS, [l_partkey#X, l_quantity#X, l_extendedprice#X, l_discount#X], [plan_id=X], [id=#X] + +(6) ShuffleQueryStage +Output [4]: [l_partkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] +Arguments: X + +(7) InputAdapter +Input [4]: [l_partkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] + +(8) InputIteratorTransformer +Input [4]: [l_partkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] + +(9) Scan parquet +Output [4]: [p_partkey#X, p_brand#X, p_size#X, p_container#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(p_size), GreaterThanOrEqual(p_size,1), IsNotNull(p_partkey), Or(Or(And(And(EqualTo(p_brand,Brand#X),In(p_container, [SM BOX,SM CASE,SM PACK,SM PKG])),LessThanOrEqual(p_size,5)),And(And(EqualTo(p_brand,Brand#X),In(p_container, [MED BAG,MED BOX,MED PACK,MED PKG])),LessThanOrEqual(p_size,10))),And(And(EqualTo(p_brand,Brand#X),In(p_container, [LG BOX,LG CASE,LG PACK,LG PKG])),LessThanOrEqual(p_size,15)))] +ReadSchema: struct + +(10) FilterExecTransformer +Input [4]: [p_partkey#X, p_brand#X, p_size#X, p_container#X] +Arguments: (((isnotnull(p_size#X) AND (p_size#X >= 1)) AND isnotnull(p_partkey#X)) AND (((((p_brand#X = Brand#X) AND p_container#X IN (SM CASE,SM BOX,SM PACK,SM PKG)) AND (p_size#X <= 5)) OR (((p_brand#X = Brand#X) AND p_container#X IN (MED BAG,MED BOX,MED PKG,MED PACK)) AND (p_size#X <= 10))) OR (((p_brand#X = Brand#X) AND p_container#X IN (LG CASE,LG BOX,LG PACK,LG PKG)) AND (p_size#X <= 15)))) + +(11) ProjectExecTransformer +Output [5]: [hash(p_partkey#X, 42) AS hash_partition_key#X, p_partkey#X, p_brand#X, p_size#X, p_container#X] +Input [4]: [p_partkey#X, p_brand#X, p_size#X, p_container#X] + +(12) WholeStageCodegenTransformer (X) +Input [5]: [hash_partition_key#X, p_partkey#X, p_brand#X, p_size#X, p_container#X] +Arguments: false + +(13) ColumnarExchange +Input [5]: [hash_partition_key#X, p_partkey#X, p_brand#X, p_size#X, p_container#X] +Arguments: hashpartitioning(p_partkey#X, 1), ENSURE_REQUIREMENTS, [p_partkey#X, p_brand#X, p_size#X, p_container#X], [plan_id=X], [id=#X] + +(14) ShuffleQueryStage +Output [4]: [p_partkey#X, p_brand#X, p_size#X, p_container#X] +Arguments: X + +(15) InputAdapter +Input [4]: [p_partkey#X, p_brand#X, p_size#X, p_container#X] + +(16) InputIteratorTransformer +Input [4]: [p_partkey#X, p_brand#X, p_size#X, p_container#X] + +(17) ShuffledHashJoinExecTransformer +Left keys [1]: [l_partkey#X] +Right keys [1]: [p_partkey#X] +Join condition: (((((((p_brand#X = Brand#X) AND p_container#X IN (SM CASE,SM BOX,SM PACK,SM PKG)) AND (l_quantity#X >= 1.00)) AND (l_quantity#X <= 11.00)) AND (p_size#X <= 5)) OR (((((p_brand#X = Brand#X) AND p_container#X IN (MED BAG,MED BOX,MED PKG,MED PACK)) AND (l_quantity#X >= 10.00)) AND (l_quantity#X <= 20.00)) AND (p_size#X <= 10))) OR (((((p_brand#X = Brand#X) AND p_container#X IN (LG CASE,LG BOX,LG PACK,LG PKG)) AND (l_quantity#X >= 20.00)) AND (l_quantity#X <= 30.00)) AND (p_size#X <= 15))) + +(18) ProjectExecTransformer +Output [3]: [l_extendedprice#X, l_discount#X, CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) AS _pre_123#X] +Input [8]: [l_partkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, p_partkey#X, p_brand#X, p_size#X, p_container#X] + +(19) RegularHashAggregateExecTransformer +Input [3]: [l_extendedprice#X, l_discount#X, _pre_123#X] +Keys: [] +Functions [1]: [partial_sum(_pre_123#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [2]: [sum#X, isEmpty#X] + +(20) RegularHashAggregateExecTransformer +Input [2]: [sum#X, isEmpty#X] +Keys: [] +Functions [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))] +Aggregate Attributes [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X] +Results [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X AS revenue#X] + +(21) WholeStageCodegenTransformer (X) +Input [1]: [revenue#X] +Arguments: false + +(22) VeloxColumnarToRowExec +Input [1]: [revenue#X] + +(23) Scan parquet +Output [6]: [l_partkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, l_shipinstruct#X, l_shipmode#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_shipinstruct), In(l_shipmode, [AIR,AIR REG]), EqualTo(l_shipinstruct,DELIVER IN PERSON), IsNotNull(l_partkey), Or(Or(And(GreaterThanOrEqual(l_quantity,1.00),LessThanOrEqual(l_quantity,11.00)),And(GreaterThanOrEqual(l_quantity,10.00),LessThanOrEqual(l_quantity,20.00))),And(GreaterThanOrEqual(l_quantity,20.00),LessThanOrEqual(l_quantity,30.00)))] +ReadSchema: struct + +(24) Filter +Input [6]: [l_partkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, l_shipinstruct#X, l_shipmode#X] +Condition : ((((isnotnull(l_shipinstruct#X) AND l_shipmode#X IN (AIR,AIR REG)) AND (l_shipinstruct#X = DELIVER IN PERSON)) AND isnotnull(l_partkey#X)) AND ((((l_quantity#X >= 1.00) AND (l_quantity#X <= 11.00)) OR ((l_quantity#X >= 10.00) AND (l_quantity#X <= 20.00))) OR ((l_quantity#X >= 20.00) AND (l_quantity#X <= 30.00)))) + +(25) Project +Output [4]: [l_partkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] +Input [6]: [l_partkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, l_shipinstruct#X, l_shipmode#X] + +(26) Exchange +Input [4]: [l_partkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] +Arguments: hashpartitioning(l_partkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(27) Scan parquet +Output [4]: [p_partkey#X, p_brand#X, p_size#X, p_container#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(p_size), GreaterThanOrEqual(p_size,1), IsNotNull(p_partkey), Or(Or(And(And(EqualTo(p_brand,Brand#X),In(p_container, [SM BOX,SM CASE,SM PACK,SM PKG])),LessThanOrEqual(p_size,5)),And(And(EqualTo(p_brand,Brand#X),In(p_container, [MED BAG,MED BOX,MED PACK,MED PKG])),LessThanOrEqual(p_size,10))),And(And(EqualTo(p_brand,Brand#X),In(p_container, [LG BOX,LG CASE,LG PACK,LG PKG])),LessThanOrEqual(p_size,15)))] +ReadSchema: struct + +(28) Filter +Input [4]: [p_partkey#X, p_brand#X, p_size#X, p_container#X] +Condition : (((isnotnull(p_size#X) AND (p_size#X >= 1)) AND isnotnull(p_partkey#X)) AND (((((p_brand#X = Brand#X) AND p_container#X IN (SM CASE,SM BOX,SM PACK,SM PKG)) AND (p_size#X <= 5)) OR (((p_brand#X = Brand#X) AND p_container#X IN (MED BAG,MED BOX,MED PKG,MED PACK)) AND (p_size#X <= 10))) OR (((p_brand#X = Brand#X) AND p_container#X IN (LG CASE,LG BOX,LG PACK,LG PKG)) AND (p_size#X <= 15)))) + +(29) Exchange +Input [4]: [p_partkey#X, p_brand#X, p_size#X, p_container#X] +Arguments: hashpartitioning(p_partkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(30) ShuffledHashJoin +Left keys [1]: [l_partkey#X] +Right keys [1]: [p_partkey#X] +Join condition: (((((((p_brand#X = Brand#X) AND p_container#X IN (SM CASE,SM BOX,SM PACK,SM PKG)) AND (l_quantity#X >= 1.00)) AND (l_quantity#X <= 11.00)) AND (p_size#X <= 5)) OR (((((p_brand#X = Brand#X) AND p_container#X IN (MED BAG,MED BOX,MED PKG,MED PACK)) AND (l_quantity#X >= 10.00)) AND (l_quantity#X <= 20.00)) AND (p_size#X <= 10))) OR (((((p_brand#X = Brand#X) AND p_container#X IN (LG CASE,LG BOX,LG PACK,LG PKG)) AND (l_quantity#X >= 20.00)) AND (l_quantity#X <= 30.00)) AND (p_size#X <= 15))) + +(31) Project +Output [2]: [l_extendedprice#X, l_discount#X] +Input [8]: [l_partkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, p_partkey#X, p_brand#X, p_size#X, p_container#X] + +(32) HashAggregate +Input [2]: [l_extendedprice#X, l_discount#X] +Keys: [] +Functions [1]: [partial_sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [2]: [sum#X, isEmpty#X] + +(33) HashAggregate +Input [2]: [sum#X, isEmpty#X] +Keys: [] +Functions [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))] +Aggregate Attributes [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X] +Results [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X AS revenue#X] + +(34) AdaptiveSparkPlan +Output [1]: [revenue#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/20.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/20.txt new file mode 100644 index 000000000000..15ea12dd248e --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/20.txt @@ -0,0 +1,654 @@ +== Physical Plan == +AdaptiveSparkPlan (126) ++- == Final Plan == + VeloxColumnarToRowExec (86) + +- ^ SortExecTransformer (84) + +- ^ InputIteratorTransformer (83) + +- ^ InputAdapter (82) + +- ^ ShuffleQueryStage (81) + +- ColumnarExchange (80) + +- ^ ProjectExecTransformer (78) + +- ^ ShuffledHashJoinExecTransformer Inner (77) + :- ^ InputIteratorTransformer (68) + : +- ^ InputAdapter (67) + : +- ^ ShuffleQueryStage (66) + : +- ColumnarExchange (65) + : +- ^ ProjectExecTransformer (63) + : +- ^ ShuffledHashJoinExecTransformer LeftSemi (62) + : :- ^ InputIteratorTransformer (8) + : : +- ^ InputAdapter (7) + : : +- ^ ShuffleQueryStage (6) + : : +- ColumnarExchange (5) + : : +- ^ ProjectExecTransformer (3) + : : +- ^ FilterExecTransformer (2) + : : +- ^ Scan parquet (1) + : +- ^ InputIteratorTransformer (61) + : +- ^ InputAdapter (60) + : +- ^ ShuffleQueryStage (59) + : +- ColumnarExchange (58) + : +- ^ ProjectExecTransformer (56) + : +- ^ ShuffledHashJoinExecTransformer Inner (55) + : :- ^ InputIteratorTransformer (31) + : : +- ^ InputAdapter (30) + : : +- ^ ShuffleQueryStage (29) + : : +- ColumnarExchange (28) + : : +- ^ ProjectExecTransformer (26) + : : +- ^ ShuffledHashJoinExecTransformer LeftSemi (25) + : : :- ^ InputIteratorTransformer (16) + : : : +- ^ InputAdapter (15) + : : : +- ^ ShuffleQueryStage (14) + : : : +- ColumnarExchange (13) + : : : +- ^ ProjectExecTransformer (11) + : : : +- ^ FilterExecTransformer (10) + : : : +- ^ Scan parquet (9) + : : +- ^ InputIteratorTransformer (24) + : : +- ^ InputAdapter (23) + : : +- ^ ShuffleQueryStage (22) + : : +- ColumnarExchange (21) + : : +- ^ ProjectExecTransformer (19) + : : +- ^ FilterExecTransformer (18) + : : +- ^ Scan parquet (17) + : +- ^ InputIteratorTransformer (54) + : +- ^ InputAdapter (53) + : +- ^ ShuffleQueryStage (52) + : +- ColumnarExchange (51) + : +- ^ ProjectExecTransformer (49) + : +- ^ FilterExecTransformer (48) + : +- ^ ProjectExecTransformer (47) + : +- ^ RegularHashAggregateExecTransformer (46) + : +- ^ RegularHashAggregateExecTransformer (45) + : +- ^ ShuffledHashJoinExecTransformer LeftSemi (44) + : :- ^ InputIteratorTransformer (39) + : : +- ^ InputAdapter (38) + : : +- ^ ShuffleQueryStage (37) + : : +- ColumnarExchange (36) + : : +- ^ ProjectExecTransformer (34) + : : +- ^ FilterExecTransformer (33) + : : +- ^ Scan parquet (32) + : +- ^ InputIteratorTransformer (43) + : +- ^ InputAdapter (42) + : +- ^ ShuffleQueryStage (41) + : +- ReusedExchange (40) + +- ^ InputIteratorTransformer (76) + +- ^ InputAdapter (75) + +- ^ ShuffleQueryStage (74) + +- ColumnarExchange (73) + +- ^ ProjectExecTransformer (71) + +- ^ FilterExecTransformer (70) + +- ^ Scan parquet (69) ++- == Initial Plan == + Sort (125) + +- Exchange (124) + +- Project (123) + +- ShuffledHashJoin Inner BuildRight (122) + :- Exchange (117) + : +- Project (116) + : +- ShuffledHashJoin LeftSemi BuildRight (115) + : :- Exchange (89) + : : +- Filter (88) + : : +- Scan parquet (87) + : +- Exchange (114) + : +- Project (113) + : +- ShuffledHashJoin Inner BuildLeft (112) + : :- Exchange (98) + : : +- ShuffledHashJoin LeftSemi BuildRight (97) + : : :- Exchange (92) + : : : +- Filter (91) + : : : +- Scan parquet (90) + : : +- Exchange (96) + : : +- Project (95) + : : +- Filter (94) + : : +- Scan parquet (93) + : +- Exchange (111) + : +- Filter (110) + : +- HashAggregate (109) + : +- HashAggregate (108) + : +- ShuffledHashJoin LeftSemi BuildRight (107) + : :- Exchange (102) + : : +- Project (101) + : : +- Filter (100) + : : +- Scan parquet (99) + : +- Exchange (106) + : +- Project (105) + : +- Filter (104) + : +- Scan parquet (103) + +- Exchange (121) + +- Project (120) + +- Filter (119) + +- Scan parquet (118) + + +(1) Scan parquet +Output [4]: [s_suppkey#X, s_name#X, s_address#X, s_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(s_nationkey)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [4]: [s_suppkey#X, s_name#X, s_address#X, s_nationkey#X] +Arguments: isnotnull(s_nationkey#X) + +(3) ProjectExecTransformer +Output [5]: [hash(s_suppkey#X, 42) AS hash_partition_key#X, s_suppkey#X, s_name#X, s_address#X, s_nationkey#X] +Input [4]: [s_suppkey#X, s_name#X, s_address#X, s_nationkey#X] + +(4) WholeStageCodegenTransformer (X) +Input [5]: [hash_partition_key#X, s_suppkey#X, s_name#X, s_address#X, s_nationkey#X] +Arguments: false + +(5) ColumnarExchange +Input [5]: [hash_partition_key#X, s_suppkey#X, s_name#X, s_address#X, s_nationkey#X] +Arguments: hashpartitioning(s_suppkey#X, 1), ENSURE_REQUIREMENTS, [s_suppkey#X, s_name#X, s_address#X, s_nationkey#X], [plan_id=X], [id=#X] + +(6) ShuffleQueryStage +Output [4]: [s_suppkey#X, s_name#X, s_address#X, s_nationkey#X] +Arguments: X + +(7) InputAdapter +Input [4]: [s_suppkey#X, s_name#X, s_address#X, s_nationkey#X] + +(8) InputIteratorTransformer +Input [4]: [s_suppkey#X, s_name#X, s_address#X, s_nationkey#X] + +(9) Scan parquet +Output [3]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(ps_availqty), IsNotNull(ps_partkey), IsNotNull(ps_suppkey)] +ReadSchema: struct + +(10) FilterExecTransformer +Input [3]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X] +Arguments: ((isnotnull(ps_availqty#X) AND isnotnull(ps_partkey#X)) AND isnotnull(ps_suppkey#X)) + +(11) ProjectExecTransformer +Output [4]: [hash(ps_partkey#X, 42) AS hash_partition_key#X, ps_partkey#X, ps_suppkey#X, ps_availqty#X] +Input [3]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X] + +(12) WholeStageCodegenTransformer (X) +Input [4]: [hash_partition_key#X, ps_partkey#X, ps_suppkey#X, ps_availqty#X] +Arguments: false + +(13) ColumnarExchange +Input [4]: [hash_partition_key#X, ps_partkey#X, ps_suppkey#X, ps_availqty#X] +Arguments: hashpartitioning(ps_partkey#X, 1), ENSURE_REQUIREMENTS, [ps_partkey#X, ps_suppkey#X, ps_availqty#X], [plan_id=X], [id=#X] + +(14) ShuffleQueryStage +Output [3]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X] +Arguments: X + +(15) InputAdapter +Input [3]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X] + +(16) InputIteratorTransformer +Input [3]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X] + +(17) Scan parquet +Output [2]: [p_partkey#X, p_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(p_name), StringStartsWith(p_name,forest)] +ReadSchema: struct + +(18) FilterExecTransformer +Input [2]: [p_partkey#X, p_name#X] +Arguments: (isnotnull(p_name#X) AND StartsWith(p_name#X, forest)) + +(19) ProjectExecTransformer +Output [2]: [hash(p_partkey#X, 42) AS hash_partition_key#X, p_partkey#X] +Input [2]: [p_partkey#X, p_name#X] + +(20) WholeStageCodegenTransformer (X) +Input [2]: [hash_partition_key#X, p_partkey#X] +Arguments: false + +(21) ColumnarExchange +Input [2]: [hash_partition_key#X, p_partkey#X] +Arguments: hashpartitioning(p_partkey#X, 1), ENSURE_REQUIREMENTS, [p_partkey#X], [plan_id=X], [id=#X] + +(22) ShuffleQueryStage +Output [1]: [p_partkey#X] +Arguments: X + +(23) InputAdapter +Input [1]: [p_partkey#X] + +(24) InputIteratorTransformer +Input [1]: [p_partkey#X] + +(25) ShuffledHashJoinExecTransformer +Left keys [1]: [ps_partkey#X] +Right keys [1]: [p_partkey#X] +Join condition: None + +(26) ProjectExecTransformer +Output [4]: [hash(ps_partkey#X, ps_suppkey#X, 42) AS hash_partition_key#X, ps_partkey#X, ps_suppkey#X, ps_availqty#X] +Input [3]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X] + +(27) WholeStageCodegenTransformer (X) +Input [4]: [hash_partition_key#X, ps_partkey#X, ps_suppkey#X, ps_availqty#X] +Arguments: false + +(28) ColumnarExchange +Input [4]: [hash_partition_key#X, ps_partkey#X, ps_suppkey#X, ps_availqty#X] +Arguments: hashpartitioning(ps_partkey#X, ps_suppkey#X, 1), ENSURE_REQUIREMENTS, [ps_partkey#X, ps_suppkey#X, ps_availqty#X], [plan_id=X], [id=#X] + +(29) ShuffleQueryStage +Output [3]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X] +Arguments: X + +(30) InputAdapter +Input [3]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X] + +(31) InputIteratorTransformer +Input [3]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X] + +(32) Scan parquet +Output [4]: [l_partkey#X, l_suppkey#X, l_quantity#X, l_shipdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_shipdate), GreaterThanOrEqual(l_shipdate,1994-01-01), LessThan(l_shipdate,1995-01-01), IsNotNull(l_partkey), IsNotNull(l_suppkey)] +ReadSchema: struct + +(33) FilterExecTransformer +Input [4]: [l_partkey#X, l_suppkey#X, l_quantity#X, l_shipdate#X] +Arguments: ((((isnotnull(l_shipdate#X) AND (l_shipdate#X >= 1994-01-01)) AND (l_shipdate#X < 1995-01-01)) AND isnotnull(l_partkey#X)) AND isnotnull(l_suppkey#X)) + +(34) ProjectExecTransformer +Output [4]: [hash(l_partkey#X, 42) AS hash_partition_key#X, l_partkey#X, l_suppkey#X, l_quantity#X] +Input [4]: [l_partkey#X, l_suppkey#X, l_quantity#X, l_shipdate#X] + +(35) WholeStageCodegenTransformer (X) +Input [4]: [hash_partition_key#X, l_partkey#X, l_suppkey#X, l_quantity#X] +Arguments: false + +(36) ColumnarExchange +Input [4]: [hash_partition_key#X, l_partkey#X, l_suppkey#X, l_quantity#X] +Arguments: hashpartitioning(l_partkey#X, 1), ENSURE_REQUIREMENTS, [l_partkey#X, l_suppkey#X, l_quantity#X], [plan_id=X], [id=#X] + +(37) ShuffleQueryStage +Output [3]: [l_partkey#X, l_suppkey#X, l_quantity#X] +Arguments: X + +(38) InputAdapter +Input [3]: [l_partkey#X, l_suppkey#X, l_quantity#X] + +(39) InputIteratorTransformer +Input [3]: [l_partkey#X, l_suppkey#X, l_quantity#X] + +(40) ReusedExchange [Reuses operator id: 21] +Output [1]: [p_partkey#X] + +(41) ShuffleQueryStage +Output [1]: [p_partkey#X] +Arguments: X + +(42) InputAdapter +Input [1]: [p_partkey#X] + +(43) InputIteratorTransformer +Input [1]: [p_partkey#X] + +(44) ShuffledHashJoinExecTransformer +Left keys [1]: [l_partkey#X] +Right keys [1]: [p_partkey#X] +Join condition: None + +(45) RegularHashAggregateExecTransformer +Input [3]: [l_partkey#X, l_suppkey#X, l_quantity#X] +Keys [2]: [l_partkey#X, l_suppkey#X] +Functions [1]: [partial_sum(l_quantity#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [4]: [l_partkey#X, l_suppkey#X, sum#X, isEmpty#X] + +(46) RegularHashAggregateExecTransformer +Input [4]: [l_partkey#X, l_suppkey#X, sum#X, isEmpty#X] +Keys [2]: [l_partkey#X, l_suppkey#X] +Functions [1]: [sum(l_quantity#X)] +Aggregate Attributes [1]: [sum(l_quantity#X)#X] +Results [3]: [l_partkey#X, l_suppkey#X, sum(l_quantity#X)#X] + +(47) ProjectExecTransformer +Output [3]: [CheckOverflow((0.50 * promote_precision(sum(l_quantity#X)#X)), DecimalType(24,3), true) AS (0.5 * sum(l_quantity))#X, l_partkey#X, l_suppkey#X] +Input [3]: [l_partkey#X, l_suppkey#X, sum(l_quantity#X)#X] + +(48) FilterExecTransformer +Input [3]: [(0.5 * sum(l_quantity))#X, l_partkey#X, l_suppkey#X] +Arguments: isnotnull((0.5 * sum(l_quantity))#X) + +(49) ProjectExecTransformer +Output [4]: [hash(l_partkey#X, l_suppkey#X, 42) AS hash_partition_key#X, (0.5 * sum(l_quantity))#X, l_partkey#X, l_suppkey#X] +Input [3]: [(0.5 * sum(l_quantity))#X, l_partkey#X, l_suppkey#X] + +(50) WholeStageCodegenTransformer (X) +Input [4]: [hash_partition_key#X, (0.5 * sum(l_quantity))#X, l_partkey#X, l_suppkey#X] +Arguments: false + +(51) ColumnarExchange +Input [4]: [hash_partition_key#X, (0.5 * sum(l_quantity))#X, l_partkey#X, l_suppkey#X] +Arguments: hashpartitioning(l_partkey#X, l_suppkey#X, 1), ENSURE_REQUIREMENTS, [(0.5 * sum(l_quantity))#X, l_partkey#X, l_suppkey#X], [plan_id=X], [id=#X] + +(52) ShuffleQueryStage +Output [3]: [(0.5 * sum(l_quantity))#X, l_partkey#X, l_suppkey#X] +Arguments: X + +(53) InputAdapter +Input [3]: [(0.5 * sum(l_quantity))#X, l_partkey#X, l_suppkey#X] + +(54) InputIteratorTransformer +Input [3]: [(0.5 * sum(l_quantity))#X, l_partkey#X, l_suppkey#X] + +(55) ShuffledHashJoinExecTransformer +Left keys [2]: [ps_partkey#X, ps_suppkey#X] +Right keys [2]: [l_partkey#X, l_suppkey#X] +Join condition: (cast(cast(ps_availqty#X as decimal(10,0)) as decimal(24,3)) > (0.5 * sum(l_quantity))#X) + +(56) ProjectExecTransformer +Output [2]: [hash(ps_suppkey#X, 42) AS hash_partition_key#X, ps_suppkey#X] +Input [6]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X, (0.5 * sum(l_quantity))#X, l_partkey#X, l_suppkey#X] + +(57) WholeStageCodegenTransformer (X) +Input [2]: [hash_partition_key#X, ps_suppkey#X] +Arguments: false + +(58) ColumnarExchange +Input [2]: [hash_partition_key#X, ps_suppkey#X] +Arguments: hashpartitioning(ps_suppkey#X, 1), ENSURE_REQUIREMENTS, [ps_suppkey#X], [plan_id=X], [id=#X] + +(59) ShuffleQueryStage +Output [1]: [ps_suppkey#X] +Arguments: X + +(60) InputAdapter +Input [1]: [ps_suppkey#X] + +(61) InputIteratorTransformer +Input [1]: [ps_suppkey#X] + +(62) ShuffledHashJoinExecTransformer +Left keys [1]: [s_suppkey#X] +Right keys [1]: [ps_suppkey#X] +Join condition: None + +(63) ProjectExecTransformer +Output [4]: [hash(s_nationkey#X, 42) AS hash_partition_key#X, s_name#X, s_address#X, s_nationkey#X] +Input [4]: [s_suppkey#X, s_name#X, s_address#X, s_nationkey#X] + +(64) WholeStageCodegenTransformer (X) +Input [4]: [hash_partition_key#X, s_name#X, s_address#X, s_nationkey#X] +Arguments: false + +(65) ColumnarExchange +Input [4]: [hash_partition_key#X, s_name#X, s_address#X, s_nationkey#X] +Arguments: hashpartitioning(s_nationkey#X, 1), ENSURE_REQUIREMENTS, [s_name#X, s_address#X, s_nationkey#X], [plan_id=X], [id=#X] + +(66) ShuffleQueryStage +Output [3]: [s_name#X, s_address#X, s_nationkey#X] +Arguments: X + +(67) InputAdapter +Input [3]: [s_name#X, s_address#X, s_nationkey#X] + +(68) InputIteratorTransformer +Input [3]: [s_name#X, s_address#X, s_nationkey#X] + +(69) Scan parquet +Output [2]: [n_nationkey#X, n_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_name), EqualTo(n_name,CANADA), IsNotNull(n_nationkey)] +ReadSchema: struct + +(70) FilterExecTransformer +Input [2]: [n_nationkey#X, n_name#X] +Arguments: ((isnotnull(n_name#X) AND (n_name#X = CANADA)) AND isnotnull(n_nationkey#X)) + +(71) ProjectExecTransformer +Output [2]: [hash(n_nationkey#X, 42) AS hash_partition_key#X, n_nationkey#X] +Input [2]: [n_nationkey#X, n_name#X] + +(72) WholeStageCodegenTransformer (X) +Input [2]: [hash_partition_key#X, n_nationkey#X] +Arguments: false + +(73) ColumnarExchange +Input [2]: [hash_partition_key#X, n_nationkey#X] +Arguments: hashpartitioning(n_nationkey#X, 1), ENSURE_REQUIREMENTS, [n_nationkey#X], [plan_id=X], [id=#X] + +(74) ShuffleQueryStage +Output [1]: [n_nationkey#X] +Arguments: X + +(75) InputAdapter +Input [1]: [n_nationkey#X] + +(76) InputIteratorTransformer +Input [1]: [n_nationkey#X] + +(77) ShuffledHashJoinExecTransformer +Left keys [1]: [s_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: None + +(78) ProjectExecTransformer +Output [2]: [s_name#X, s_address#X] +Input [4]: [s_name#X, s_address#X, s_nationkey#X, n_nationkey#X] + +(79) WholeStageCodegenTransformer (X) +Input [2]: [s_name#X, s_address#X] +Arguments: false + +(80) ColumnarExchange +Input [2]: [s_name#X, s_address#X] +Arguments: rangepartitioning(s_name#X ASC NULLS FIRST, 1), ENSURE_REQUIREMENTS, [plan_id=X], [id=#X] + +(81) ShuffleQueryStage +Output [2]: [s_name#X, s_address#X] +Arguments: X + +(82) InputAdapter +Input [2]: [s_name#X, s_address#X] + +(83) InputIteratorTransformer +Input [2]: [s_name#X, s_address#X] + +(84) SortExecTransformer +Input [2]: [s_name#X, s_address#X] +Arguments: [s_name#X ASC NULLS FIRST], true, 0 + +(85) WholeStageCodegenTransformer (X) +Input [2]: [s_name#X, s_address#X] +Arguments: false + +(86) VeloxColumnarToRowExec +Input [2]: [s_name#X, s_address#X] + +(87) Scan parquet +Output [4]: [s_suppkey#X, s_name#X, s_address#X, s_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(s_nationkey)] +ReadSchema: struct + +(88) Filter +Input [4]: [s_suppkey#X, s_name#X, s_address#X, s_nationkey#X] +Condition : isnotnull(s_nationkey#X) + +(89) Exchange +Input [4]: [s_suppkey#X, s_name#X, s_address#X, s_nationkey#X] +Arguments: hashpartitioning(s_suppkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(90) Scan parquet +Output [3]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(ps_availqty), IsNotNull(ps_partkey), IsNotNull(ps_suppkey)] +ReadSchema: struct + +(91) Filter +Input [3]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X] +Condition : ((isnotnull(ps_availqty#X) AND isnotnull(ps_partkey#X)) AND isnotnull(ps_suppkey#X)) + +(92) Exchange +Input [3]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X] +Arguments: hashpartitioning(ps_partkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(93) Scan parquet +Output [2]: [p_partkey#X, p_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(p_name), StringStartsWith(p_name,forest)] +ReadSchema: struct + +(94) Filter +Input [2]: [p_partkey#X, p_name#X] +Condition : (isnotnull(p_name#X) AND StartsWith(p_name#X, forest)) + +(95) Project +Output [1]: [p_partkey#X] +Input [2]: [p_partkey#X, p_name#X] + +(96) Exchange +Input [1]: [p_partkey#X] +Arguments: hashpartitioning(p_partkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(97) ShuffledHashJoin +Left keys [1]: [ps_partkey#X] +Right keys [1]: [p_partkey#X] +Join condition: None + +(98) Exchange +Input [3]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X] +Arguments: hashpartitioning(ps_partkey#X, ps_suppkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(99) Scan parquet +Output [4]: [l_partkey#X, l_suppkey#X, l_quantity#X, l_shipdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_shipdate), GreaterThanOrEqual(l_shipdate,1994-01-01), LessThan(l_shipdate,1995-01-01), IsNotNull(l_partkey), IsNotNull(l_suppkey)] +ReadSchema: struct + +(100) Filter +Input [4]: [l_partkey#X, l_suppkey#X, l_quantity#X, l_shipdate#X] +Condition : ((((isnotnull(l_shipdate#X) AND (l_shipdate#X >= 1994-01-01)) AND (l_shipdate#X < 1995-01-01)) AND isnotnull(l_partkey#X)) AND isnotnull(l_suppkey#X)) + +(101) Project +Output [3]: [l_partkey#X, l_suppkey#X, l_quantity#X] +Input [4]: [l_partkey#X, l_suppkey#X, l_quantity#X, l_shipdate#X] + +(102) Exchange +Input [3]: [l_partkey#X, l_suppkey#X, l_quantity#X] +Arguments: hashpartitioning(l_partkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(103) Scan parquet +Output [2]: [p_partkey#X, p_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(p_name), StringStartsWith(p_name,forest)] +ReadSchema: struct + +(104) Filter +Input [2]: [p_partkey#X, p_name#X] +Condition : (isnotnull(p_name#X) AND StartsWith(p_name#X, forest)) + +(105) Project +Output [1]: [p_partkey#X] +Input [2]: [p_partkey#X, p_name#X] + +(106) Exchange +Input [1]: [p_partkey#X] +Arguments: hashpartitioning(p_partkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(107) ShuffledHashJoin +Left keys [1]: [l_partkey#X] +Right keys [1]: [p_partkey#X] +Join condition: None + +(108) HashAggregate +Input [3]: [l_partkey#X, l_suppkey#X, l_quantity#X] +Keys [2]: [l_partkey#X, l_suppkey#X] +Functions [1]: [partial_sum(l_quantity#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [4]: [l_partkey#X, l_suppkey#X, sum#X, isEmpty#X] + +(109) HashAggregate +Input [4]: [l_partkey#X, l_suppkey#X, sum#X, isEmpty#X] +Keys [2]: [l_partkey#X, l_suppkey#X] +Functions [1]: [sum(l_quantity#X)] +Aggregate Attributes [1]: [sum(l_quantity#X)#X] +Results [3]: [CheckOverflow((0.50 * promote_precision(sum(l_quantity#X)#X)), DecimalType(24,3), true) AS (0.5 * sum(l_quantity))#X, l_partkey#X, l_suppkey#X] + +(110) Filter +Input [3]: [(0.5 * sum(l_quantity))#X, l_partkey#X, l_suppkey#X] +Condition : isnotnull((0.5 * sum(l_quantity))#X) + +(111) Exchange +Input [3]: [(0.5 * sum(l_quantity))#X, l_partkey#X, l_suppkey#X] +Arguments: hashpartitioning(l_partkey#X, l_suppkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(112) ShuffledHashJoin +Left keys [2]: [ps_partkey#X, ps_suppkey#X] +Right keys [2]: [l_partkey#X, l_suppkey#X] +Join condition: (cast(cast(ps_availqty#X as decimal(10,0)) as decimal(24,3)) > (0.5 * sum(l_quantity))#X) + +(113) Project +Output [1]: [ps_suppkey#X] +Input [6]: [ps_partkey#X, ps_suppkey#X, ps_availqty#X, (0.5 * sum(l_quantity))#X, l_partkey#X, l_suppkey#X] + +(114) Exchange +Input [1]: [ps_suppkey#X] +Arguments: hashpartitioning(ps_suppkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(115) ShuffledHashJoin +Left keys [1]: [s_suppkey#X] +Right keys [1]: [ps_suppkey#X] +Join condition: None + +(116) Project +Output [3]: [s_name#X, s_address#X, s_nationkey#X] +Input [4]: [s_suppkey#X, s_name#X, s_address#X, s_nationkey#X] + +(117) Exchange +Input [3]: [s_name#X, s_address#X, s_nationkey#X] +Arguments: hashpartitioning(s_nationkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(118) Scan parquet +Output [2]: [n_nationkey#X, n_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_name), EqualTo(n_name,CANADA), IsNotNull(n_nationkey)] +ReadSchema: struct + +(119) Filter +Input [2]: [n_nationkey#X, n_name#X] +Condition : ((isnotnull(n_name#X) AND (n_name#X = CANADA)) AND isnotnull(n_nationkey#X)) + +(120) Project +Output [1]: [n_nationkey#X] +Input [2]: [n_nationkey#X, n_name#X] + +(121) Exchange +Input [1]: [n_nationkey#X] +Arguments: hashpartitioning(n_nationkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(122) ShuffledHashJoin +Left keys [1]: [s_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: None + +(123) Project +Output [2]: [s_name#X, s_address#X] +Input [4]: [s_name#X, s_address#X, s_nationkey#X, n_nationkey#X] + +(124) Exchange +Input [2]: [s_name#X, s_address#X] +Arguments: rangepartitioning(s_name#X ASC NULLS FIRST, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(125) Sort +Input [2]: [s_name#X, s_address#X] +Arguments: [s_name#X ASC NULLS FIRST], true, 0 + +(126) AdaptiveSparkPlan +Output [2]: [s_name#X, s_address#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/21.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/21.txt new file mode 100644 index 000000000000..17fad29860df --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/21.txt @@ -0,0 +1,623 @@ +== Physical Plan == +AdaptiveSparkPlan (119) ++- == Final Plan == + VeloxColumnarToRowExec (82) + +- TakeOrderedAndProjectExecTransformer (81) + +- ^ RegularHashAggregateExecTransformer (79) + +- ^ InputIteratorTransformer (78) + +- ^ InputAdapter (77) + +- ^ ShuffleQueryStage (76) + +- ColumnarExchange (75) + +- ^ ProjectExecTransformer (73) + +- ^ FlushableHashAggregateExecTransformer (72) + +- ^ ProjectExecTransformer (71) + +- ^ ShuffledHashJoinExecTransformer Inner (70) + :- ^ InputIteratorTransformer (61) + : +- ^ InputAdapter (60) + : +- ^ ShuffleQueryStage (59) + : +- ColumnarExchange (58) + : +- ^ ProjectExecTransformer (56) + : +- ^ ShuffledHashJoinExecTransformer Inner (55) + : :- ^ InputIteratorTransformer (46) + : : +- ^ InputAdapter (45) + : : +- ^ ShuffleQueryStage (44) + : : +- ColumnarExchange (43) + : : +- ^ ProjectExecTransformer (41) + : : +- ^ ShuffledHashJoinExecTransformer Inner (40) + : : :- ^ InputIteratorTransformer (8) + : : : +- ^ InputAdapter (7) + : : : +- ^ ShuffleQueryStage (6) + : : : +- ColumnarExchange (5) + : : : +- ^ ProjectExecTransformer (3) + : : : +- ^ FilterExecTransformer (2) + : : : +- ^ Scan parquet (1) + : : +- ^ InputIteratorTransformer (39) + : : +- ^ InputAdapter (38) + : : +- ^ ShuffleQueryStage (37) + : : +- ColumnarExchange (36) + : : +- ^ ProjectExecTransformer (34) + : : +- ^ ShuffledHashJoinExecTransformer LeftAnti (33) + : : :- ^ ShuffledHashJoinExecTransformer LeftSemi (24) + : : : :- ^ InputIteratorTransformer (16) + : : : : +- ^ InputAdapter (15) + : : : : +- ^ ShuffleQueryStage (14) + : : : : +- ColumnarExchange (13) + : : : : +- ^ ProjectExecTransformer (11) + : : : : +- ^ FilterExecTransformer (10) + : : : : +- ^ Scan parquet (9) + : : : +- ^ InputIteratorTransformer (23) + : : : +- ^ InputAdapter (22) + : : : +- ^ ShuffleQueryStage (21) + : : : +- ColumnarExchange (20) + : : : +- ^ ProjectExecTransformer (18) + : : : +- ^ Scan parquet (17) + : : +- ^ InputIteratorTransformer (32) + : : +- ^ InputAdapter (31) + : : +- ^ ShuffleQueryStage (30) + : : +- ColumnarExchange (29) + : : +- ^ ProjectExecTransformer (27) + : : +- ^ FilterExecTransformer (26) + : : +- ^ Scan parquet (25) + : +- ^ InputIteratorTransformer (54) + : +- ^ InputAdapter (53) + : +- ^ ShuffleQueryStage (52) + : +- ColumnarExchange (51) + : +- ^ ProjectExecTransformer (49) + : +- ^ FilterExecTransformer (48) + : +- ^ Scan parquet (47) + +- ^ InputIteratorTransformer (69) + +- ^ InputAdapter (68) + +- ^ ShuffleQueryStage (67) + +- ColumnarExchange (66) + +- ^ ProjectExecTransformer (64) + +- ^ FilterExecTransformer (63) + +- ^ Scan parquet (62) ++- == Initial Plan == + TakeOrderedAndProject (118) + +- HashAggregate (117) + +- Exchange (116) + +- HashAggregate (115) + +- Project (114) + +- ShuffledHashJoin Inner BuildRight (113) + :- Exchange (108) + : +- Project (107) + : +- ShuffledHashJoin Inner BuildRight (106) + : :- Exchange (101) + : : +- Project (100) + : : +- ShuffledHashJoin Inner BuildLeft (99) + : : :- Exchange (85) + : : : +- Filter (84) + : : : +- Scan parquet (83) + : : +- Exchange (98) + : : +- ShuffledHashJoin LeftAnti BuildRight (97) + : : :- ShuffledHashJoin LeftSemi BuildRight (92) + : : : :- Exchange (89) + : : : : +- Project (88) + : : : : +- Filter (87) + : : : : +- Scan parquet (86) + : : : +- Exchange (91) + : : : +- Scan parquet (90) + : : +- Exchange (96) + : : +- Project (95) + : : +- Filter (94) + : : +- Scan parquet (93) + : +- Exchange (105) + : +- Project (104) + : +- Filter (103) + : +- Scan parquet (102) + +- Exchange (112) + +- Project (111) + +- Filter (110) + +- Scan parquet (109) + + +(1) Scan parquet +Output [3]: [s_suppkey#X, s_name#X, s_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(s_suppkey), IsNotNull(s_nationkey)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [3]: [s_suppkey#X, s_name#X, s_nationkey#X] +Arguments: (isnotnull(s_suppkey#X) AND isnotnull(s_nationkey#X)) + +(3) ProjectExecTransformer +Output [4]: [hash(s_suppkey#X, 42) AS hash_partition_key#X, s_suppkey#X, s_name#X, s_nationkey#X] +Input [3]: [s_suppkey#X, s_name#X, s_nationkey#X] + +(4) WholeStageCodegenTransformer (X) +Input [4]: [hash_partition_key#X, s_suppkey#X, s_name#X, s_nationkey#X] +Arguments: false + +(5) ColumnarExchange +Input [4]: [hash_partition_key#X, s_suppkey#X, s_name#X, s_nationkey#X] +Arguments: hashpartitioning(s_suppkey#X, 1), ENSURE_REQUIREMENTS, [s_suppkey#X, s_name#X, s_nationkey#X], [plan_id=X], [id=#X] + +(6) ShuffleQueryStage +Output [3]: [s_suppkey#X, s_name#X, s_nationkey#X] +Arguments: X + +(7) InputAdapter +Input [3]: [s_suppkey#X, s_name#X, s_nationkey#X] + +(8) InputIteratorTransformer +Input [3]: [s_suppkey#X, s_name#X, s_nationkey#X] + +(9) Scan parquet +Output [4]: [l_orderkey#X, l_suppkey#X, l_commitdate#X, l_receiptdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_receiptdate), IsNotNull(l_commitdate), IsNotNull(l_suppkey), IsNotNull(l_orderkey)] +ReadSchema: struct + +(10) FilterExecTransformer +Input [4]: [l_orderkey#X, l_suppkey#X, l_commitdate#X, l_receiptdate#X] +Arguments: ((((isnotnull(l_receiptdate#X) AND isnotnull(l_commitdate#X)) AND (l_receiptdate#X > l_commitdate#X)) AND isnotnull(l_suppkey#X)) AND isnotnull(l_orderkey#X)) + +(11) ProjectExecTransformer +Output [3]: [hash(l_orderkey#X, 42) AS hash_partition_key#X, l_orderkey#X, l_suppkey#X] +Input [4]: [l_orderkey#X, l_suppkey#X, l_commitdate#X, l_receiptdate#X] + +(12) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, l_orderkey#X, l_suppkey#X] +Arguments: false + +(13) ColumnarExchange +Input [3]: [hash_partition_key#X, l_orderkey#X, l_suppkey#X] +Arguments: hashpartitioning(l_orderkey#X, 1), ENSURE_REQUIREMENTS, [l_orderkey#X, l_suppkey#X], [plan_id=X], [id=#X] + +(14) ShuffleQueryStage +Output [2]: [l_orderkey#X, l_suppkey#X] +Arguments: X + +(15) InputAdapter +Input [2]: [l_orderkey#X, l_suppkey#X] + +(16) InputIteratorTransformer +Input [2]: [l_orderkey#X, l_suppkey#X] + +(17) Scan parquet +Output [2]: [l_orderkey#X, l_suppkey#X] +Batched: true +Location: InMemoryFileIndex [*] +ReadSchema: struct + +(18) ProjectExecTransformer +Output [3]: [hash(l_orderkey#X, 42) AS hash_partition_key#X, l_orderkey#X, l_suppkey#X] +Input [2]: [l_orderkey#X, l_suppkey#X] + +(19) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, l_orderkey#X, l_suppkey#X] +Arguments: false + +(20) ColumnarExchange +Input [3]: [hash_partition_key#X, l_orderkey#X, l_suppkey#X] +Arguments: hashpartitioning(l_orderkey#X, 1), ENSURE_REQUIREMENTS, [l_orderkey#X, l_suppkey#X], [plan_id=X], [id=#X] + +(21) ShuffleQueryStage +Output [2]: [l_orderkey#X, l_suppkey#X] +Arguments: X + +(22) InputAdapter +Input [2]: [l_orderkey#X, l_suppkey#X] + +(23) InputIteratorTransformer +Input [2]: [l_orderkey#X, l_suppkey#X] + +(24) ShuffledHashJoinExecTransformer +Left keys [1]: [l_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: NOT (l_suppkey#X = l_suppkey#X) + +(25) Scan parquet +Output [4]: [l_orderkey#X, l_suppkey#X, l_commitdate#X, l_receiptdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_receiptdate), IsNotNull(l_commitdate)] +ReadSchema: struct + +(26) FilterExecTransformer +Input [4]: [l_orderkey#X, l_suppkey#X, l_commitdate#X, l_receiptdate#X] +Arguments: ((isnotnull(l_receiptdate#X) AND isnotnull(l_commitdate#X)) AND (l_receiptdate#X > l_commitdate#X)) + +(27) ProjectExecTransformer +Output [3]: [hash(l_orderkey#X, 42) AS hash_partition_key#X, l_orderkey#X, l_suppkey#X] +Input [4]: [l_orderkey#X, l_suppkey#X, l_commitdate#X, l_receiptdate#X] + +(28) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, l_orderkey#X, l_suppkey#X] +Arguments: false + +(29) ColumnarExchange +Input [3]: [hash_partition_key#X, l_orderkey#X, l_suppkey#X] +Arguments: hashpartitioning(l_orderkey#X, 1), ENSURE_REQUIREMENTS, [l_orderkey#X, l_suppkey#X], [plan_id=X], [id=#X] + +(30) ShuffleQueryStage +Output [2]: [l_orderkey#X, l_suppkey#X] +Arguments: X + +(31) InputAdapter +Input [2]: [l_orderkey#X, l_suppkey#X] + +(32) InputIteratorTransformer +Input [2]: [l_orderkey#X, l_suppkey#X] + +(33) ShuffledHashJoinExecTransformer +Left keys [1]: [l_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: NOT (l_suppkey#X = l_suppkey#X) + +(34) ProjectExecTransformer +Output [3]: [hash(l_suppkey#X, 42) AS hash_partition_key#X, l_orderkey#X, l_suppkey#X] +Input [2]: [l_orderkey#X, l_suppkey#X] + +(35) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, l_orderkey#X, l_suppkey#X] +Arguments: false + +(36) ColumnarExchange +Input [3]: [hash_partition_key#X, l_orderkey#X, l_suppkey#X] +Arguments: hashpartitioning(l_suppkey#X, 1), ENSURE_REQUIREMENTS, [l_orderkey#X, l_suppkey#X], [plan_id=X], [id=#X] + +(37) ShuffleQueryStage +Output [2]: [l_orderkey#X, l_suppkey#X] +Arguments: X + +(38) InputAdapter +Input [2]: [l_orderkey#X, l_suppkey#X] + +(39) InputIteratorTransformer +Input [2]: [l_orderkey#X, l_suppkey#X] + +(40) ShuffledHashJoinExecTransformer +Left keys [1]: [s_suppkey#X] +Right keys [1]: [l_suppkey#X] +Join condition: None + +(41) ProjectExecTransformer +Output [4]: [hash(l_orderkey#X, 42) AS hash_partition_key#X, s_name#X, s_nationkey#X, l_orderkey#X] +Input [5]: [s_suppkey#X, s_name#X, s_nationkey#X, l_orderkey#X, l_suppkey#X] + +(42) WholeStageCodegenTransformer (X) +Input [4]: [hash_partition_key#X, s_name#X, s_nationkey#X, l_orderkey#X] +Arguments: false + +(43) ColumnarExchange +Input [4]: [hash_partition_key#X, s_name#X, s_nationkey#X, l_orderkey#X] +Arguments: hashpartitioning(l_orderkey#X, 1), ENSURE_REQUIREMENTS, [s_name#X, s_nationkey#X, l_orderkey#X], [plan_id=X], [id=#X] + +(44) ShuffleQueryStage +Output [3]: [s_name#X, s_nationkey#X, l_orderkey#X] +Arguments: X + +(45) InputAdapter +Input [3]: [s_name#X, s_nationkey#X, l_orderkey#X] + +(46) InputIteratorTransformer +Input [3]: [s_name#X, s_nationkey#X, l_orderkey#X] + +(47) Scan parquet +Output [2]: [o_orderkey#X, o_orderstatus#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_orderstatus), EqualTo(o_orderstatus,F), IsNotNull(o_orderkey)] +ReadSchema: struct + +(48) FilterExecTransformer +Input [2]: [o_orderkey#X, o_orderstatus#X] +Arguments: ((isnotnull(o_orderstatus#X) AND (o_orderstatus#X = F)) AND isnotnull(o_orderkey#X)) + +(49) ProjectExecTransformer +Output [2]: [hash(o_orderkey#X, 42) AS hash_partition_key#X, o_orderkey#X] +Input [2]: [o_orderkey#X, o_orderstatus#X] + +(50) WholeStageCodegenTransformer (X) +Input [2]: [hash_partition_key#X, o_orderkey#X] +Arguments: false + +(51) ColumnarExchange +Input [2]: [hash_partition_key#X, o_orderkey#X] +Arguments: hashpartitioning(o_orderkey#X, 1), ENSURE_REQUIREMENTS, [o_orderkey#X], [plan_id=X], [id=#X] + +(52) ShuffleQueryStage +Output [1]: [o_orderkey#X] +Arguments: X + +(53) InputAdapter +Input [1]: [o_orderkey#X] + +(54) InputIteratorTransformer +Input [1]: [o_orderkey#X] + +(55) ShuffledHashJoinExecTransformer +Left keys [1]: [l_orderkey#X] +Right keys [1]: [o_orderkey#X] +Join condition: None + +(56) ProjectExecTransformer +Output [3]: [hash(s_nationkey#X, 42) AS hash_partition_key#X, s_name#X, s_nationkey#X] +Input [4]: [s_name#X, s_nationkey#X, l_orderkey#X, o_orderkey#X] + +(57) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, s_name#X, s_nationkey#X] +Arguments: false + +(58) ColumnarExchange +Input [3]: [hash_partition_key#X, s_name#X, s_nationkey#X] +Arguments: hashpartitioning(s_nationkey#X, 1), ENSURE_REQUIREMENTS, [s_name#X, s_nationkey#X], [plan_id=X], [id=#X] + +(59) ShuffleQueryStage +Output [2]: [s_name#X, s_nationkey#X] +Arguments: X + +(60) InputAdapter +Input [2]: [s_name#X, s_nationkey#X] + +(61) InputIteratorTransformer +Input [2]: [s_name#X, s_nationkey#X] + +(62) Scan parquet +Output [2]: [n_nationkey#X, n_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_name), EqualTo(n_name,SAUDI ARABIA), IsNotNull(n_nationkey)] +ReadSchema: struct + +(63) FilterExecTransformer +Input [2]: [n_nationkey#X, n_name#X] +Arguments: ((isnotnull(n_name#X) AND (n_name#X = SAUDI ARABIA)) AND isnotnull(n_nationkey#X)) + +(64) ProjectExecTransformer +Output [2]: [hash(n_nationkey#X, 42) AS hash_partition_key#X, n_nationkey#X] +Input [2]: [n_nationkey#X, n_name#X] + +(65) WholeStageCodegenTransformer (X) +Input [2]: [hash_partition_key#X, n_nationkey#X] +Arguments: false + +(66) ColumnarExchange +Input [2]: [hash_partition_key#X, n_nationkey#X] +Arguments: hashpartitioning(n_nationkey#X, 1), ENSURE_REQUIREMENTS, [n_nationkey#X], [plan_id=X], [id=#X] + +(67) ShuffleQueryStage +Output [1]: [n_nationkey#X] +Arguments: X + +(68) InputAdapter +Input [1]: [n_nationkey#X] + +(69) InputIteratorTransformer +Input [1]: [n_nationkey#X] + +(70) ShuffledHashJoinExecTransformer +Left keys [1]: [s_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: None + +(71) ProjectExecTransformer +Output [1]: [s_name#X] +Input [3]: [s_name#X, s_nationkey#X, n_nationkey#X] + +(72) FlushableHashAggregateExecTransformer +Input [1]: [s_name#X] +Keys [1]: [s_name#X] +Functions [1]: [partial_count(1)] +Aggregate Attributes [1]: [count#X] +Results [2]: [s_name#X, count#X] + +(73) ProjectExecTransformer +Output [3]: [hash(s_name#X, 42) AS hash_partition_key#X, s_name#X, count#X] +Input [2]: [s_name#X, count#X] + +(74) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, s_name#X, count#X] +Arguments: false + +(75) ColumnarExchange +Input [3]: [hash_partition_key#X, s_name#X, count#X] +Arguments: hashpartitioning(s_name#X, 1), ENSURE_REQUIREMENTS, [s_name#X, count#X], [plan_id=X], [id=#X] + +(76) ShuffleQueryStage +Output [2]: [s_name#X, count#X] +Arguments: X + +(77) InputAdapter +Input [2]: [s_name#X, count#X] + +(78) InputIteratorTransformer +Input [2]: [s_name#X, count#X] + +(79) RegularHashAggregateExecTransformer +Input [2]: [s_name#X, count#X] +Keys [1]: [s_name#X] +Functions [1]: [count(1)] +Aggregate Attributes [1]: [count(1)#X] +Results [2]: [s_name#X, count(1)#X AS numwait#X] + +(80) WholeStageCodegenTransformer (X) +Input [2]: [s_name#X, numwait#X] +Arguments: false + +(81) TakeOrderedAndProjectExecTransformer +Input [2]: [s_name#X, numwait#X] +Arguments: X, [numwait#X DESC NULLS LAST, s_name#X ASC NULLS FIRST], [s_name#X, numwait#X], 0 + +(82) VeloxColumnarToRowExec +Input [2]: [s_name#X, numwait#X] + +(83) Scan parquet +Output [3]: [s_suppkey#X, s_name#X, s_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(s_suppkey), IsNotNull(s_nationkey)] +ReadSchema: struct + +(84) Filter +Input [3]: [s_suppkey#X, s_name#X, s_nationkey#X] +Condition : (isnotnull(s_suppkey#X) AND isnotnull(s_nationkey#X)) + +(85) Exchange +Input [3]: [s_suppkey#X, s_name#X, s_nationkey#X] +Arguments: hashpartitioning(s_suppkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(86) Scan parquet +Output [4]: [l_orderkey#X, l_suppkey#X, l_commitdate#X, l_receiptdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_receiptdate), IsNotNull(l_commitdate), IsNotNull(l_suppkey), IsNotNull(l_orderkey)] +ReadSchema: struct + +(87) Filter +Input [4]: [l_orderkey#X, l_suppkey#X, l_commitdate#X, l_receiptdate#X] +Condition : ((((isnotnull(l_receiptdate#X) AND isnotnull(l_commitdate#X)) AND (l_receiptdate#X > l_commitdate#X)) AND isnotnull(l_suppkey#X)) AND isnotnull(l_orderkey#X)) + +(88) Project +Output [2]: [l_orderkey#X, l_suppkey#X] +Input [4]: [l_orderkey#X, l_suppkey#X, l_commitdate#X, l_receiptdate#X] + +(89) Exchange +Input [2]: [l_orderkey#X, l_suppkey#X] +Arguments: hashpartitioning(l_orderkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(90) Scan parquet +Output [2]: [l_orderkey#X, l_suppkey#X] +Batched: true +Location: InMemoryFileIndex [*] +ReadSchema: struct + +(91) Exchange +Input [2]: [l_orderkey#X, l_suppkey#X] +Arguments: hashpartitioning(l_orderkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(92) ShuffledHashJoin +Left keys [1]: [l_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: NOT (l_suppkey#X = l_suppkey#X) + +(93) Scan parquet +Output [4]: [l_orderkey#X, l_suppkey#X, l_commitdate#X, l_receiptdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_receiptdate), IsNotNull(l_commitdate)] +ReadSchema: struct + +(94) Filter +Input [4]: [l_orderkey#X, l_suppkey#X, l_commitdate#X, l_receiptdate#X] +Condition : ((isnotnull(l_receiptdate#X) AND isnotnull(l_commitdate#X)) AND (l_receiptdate#X > l_commitdate#X)) + +(95) Project +Output [2]: [l_orderkey#X, l_suppkey#X] +Input [4]: [l_orderkey#X, l_suppkey#X, l_commitdate#X, l_receiptdate#X] + +(96) Exchange +Input [2]: [l_orderkey#X, l_suppkey#X] +Arguments: hashpartitioning(l_orderkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(97) ShuffledHashJoin +Left keys [1]: [l_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: NOT (l_suppkey#X = l_suppkey#X) + +(98) Exchange +Input [2]: [l_orderkey#X, l_suppkey#X] +Arguments: hashpartitioning(l_suppkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(99) ShuffledHashJoin +Left keys [1]: [s_suppkey#X] +Right keys [1]: [l_suppkey#X] +Join condition: None + +(100) Project +Output [3]: [s_name#X, s_nationkey#X, l_orderkey#X] +Input [5]: [s_suppkey#X, s_name#X, s_nationkey#X, l_orderkey#X, l_suppkey#X] + +(101) Exchange +Input [3]: [s_name#X, s_nationkey#X, l_orderkey#X] +Arguments: hashpartitioning(l_orderkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(102) Scan parquet +Output [2]: [o_orderkey#X, o_orderstatus#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_orderstatus), EqualTo(o_orderstatus,F), IsNotNull(o_orderkey)] +ReadSchema: struct + +(103) Filter +Input [2]: [o_orderkey#X, o_orderstatus#X] +Condition : ((isnotnull(o_orderstatus#X) AND (o_orderstatus#X = F)) AND isnotnull(o_orderkey#X)) + +(104) Project +Output [1]: [o_orderkey#X] +Input [2]: [o_orderkey#X, o_orderstatus#X] + +(105) Exchange +Input [1]: [o_orderkey#X] +Arguments: hashpartitioning(o_orderkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(106) ShuffledHashJoin +Left keys [1]: [l_orderkey#X] +Right keys [1]: [o_orderkey#X] +Join condition: None + +(107) Project +Output [2]: [s_name#X, s_nationkey#X] +Input [4]: [s_name#X, s_nationkey#X, l_orderkey#X, o_orderkey#X] + +(108) Exchange +Input [2]: [s_name#X, s_nationkey#X] +Arguments: hashpartitioning(s_nationkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(109) Scan parquet +Output [2]: [n_nationkey#X, n_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_name), EqualTo(n_name,SAUDI ARABIA), IsNotNull(n_nationkey)] +ReadSchema: struct + +(110) Filter +Input [2]: [n_nationkey#X, n_name#X] +Condition : ((isnotnull(n_name#X) AND (n_name#X = SAUDI ARABIA)) AND isnotnull(n_nationkey#X)) + +(111) Project +Output [1]: [n_nationkey#X] +Input [2]: [n_nationkey#X, n_name#X] + +(112) Exchange +Input [1]: [n_nationkey#X] +Arguments: hashpartitioning(n_nationkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(113) ShuffledHashJoin +Left keys [1]: [s_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: None + +(114) Project +Output [1]: [s_name#X] +Input [3]: [s_name#X, s_nationkey#X, n_nationkey#X] + +(115) HashAggregate +Input [1]: [s_name#X] +Keys [1]: [s_name#X] +Functions [1]: [partial_count(1)] +Aggregate Attributes [1]: [count#X] +Results [2]: [s_name#X, count#X] + +(116) Exchange +Input [2]: [s_name#X, count#X] +Arguments: hashpartitioning(s_name#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(117) HashAggregate +Input [2]: [s_name#X, count#X] +Keys [1]: [s_name#X] +Functions [1]: [count(1)] +Aggregate Attributes [1]: [count(1)#X] +Results [2]: [s_name#X, count(1)#X AS numwait#X] + +(118) TakeOrderedAndProject +Input [2]: [s_name#X, numwait#X] +Arguments: X, [numwait#X DESC NULLS LAST, s_name#X ASC NULLS FIRST], [s_name#X, numwait#X] + +(119) AdaptiveSparkPlan +Output [2]: [s_name#X, numwait#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/22.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/22.txt new file mode 100644 index 000000000000..918335dff38b --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/22.txt @@ -0,0 +1,244 @@ +== Physical Plan == +AdaptiveSparkPlan (46) ++- == Final Plan == + VeloxColumnarToRowExec (33) + +- ^ SortExecTransformer (31) + +- ^ InputIteratorTransformer (30) + +- ^ InputAdapter (29) + +- ^ ShuffleQueryStage (28) + +- ColumnarExchange (27) + +- ^ RegularHashAggregateExecTransformer (25) + +- ^ InputIteratorTransformer (24) + +- ^ InputAdapter (23) + +- ^ ShuffleQueryStage (22) + +- ColumnarExchange (21) + +- ^ ProjectExecTransformer (19) + +- ^ FlushableHashAggregateExecTransformer (18) + +- ^ ProjectExecTransformer (17) + +- ^ ShuffledHashJoinExecTransformer LeftAnti (16) + :- ^ InputIteratorTransformer (8) + : +- ^ InputAdapter (7) + : +- ^ ShuffleQueryStage (6) + : +- ColumnarExchange (5) + : +- ^ ProjectExecTransformer (3) + : +- ^ FilterExecTransformer (2) + : +- ^ Scan parquet (1) + +- ^ InputIteratorTransformer (15) + +- ^ InputAdapter (14) + +- ^ ShuffleQueryStage (13) + +- ColumnarExchange (12) + +- ^ ProjectExecTransformer (10) + +- ^ Scan parquet (9) ++- == Initial Plan == + Sort (45) + +- Exchange (44) + +- HashAggregate (43) + +- Exchange (42) + +- HashAggregate (41) + +- Project (40) + +- ShuffledHashJoin LeftAnti BuildRight (39) + :- Exchange (36) + : +- Filter (35) + : +- Scan parquet (34) + +- Exchange (38) + +- Scan parquet (37) + + +(1) Scan parquet +Output [3]: [c_custkey#X, c_phone#X, c_acctbal#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(c_acctbal)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [3]: [c_custkey#X, c_phone#X, c_acctbal#X] +Arguments: ((isnotnull(c_acctbal#X) AND substring(c_phone#X, 1, 2) IN (13,31,23,29,30,18,17)) AND (cast(c_acctbal#X as decimal(16,6)) > Subquery subquery#X, [id=#X])) + +(3) ProjectExecTransformer +Output [4]: [hash(c_custkey#X, 42) AS hash_partition_key#X, c_custkey#X, c_phone#X, c_acctbal#X] +Input [3]: [c_custkey#X, c_phone#X, c_acctbal#X] + +(4) WholeStageCodegenTransformer (X) +Input [4]: [hash_partition_key#X, c_custkey#X, c_phone#X, c_acctbal#X] +Arguments: false + +(5) ColumnarExchange +Input [4]: [hash_partition_key#X, c_custkey#X, c_phone#X, c_acctbal#X] +Arguments: hashpartitioning(c_custkey#X, 1), ENSURE_REQUIREMENTS, [c_custkey#X, c_phone#X, c_acctbal#X], [plan_id=X], [id=#X] + +(6) ShuffleQueryStage +Output [3]: [c_custkey#X, c_phone#X, c_acctbal#X] +Arguments: X + +(7) InputAdapter +Input [3]: [c_custkey#X, c_phone#X, c_acctbal#X] + +(8) InputIteratorTransformer +Input [3]: [c_custkey#X, c_phone#X, c_acctbal#X] + +(9) Scan parquet +Output [1]: [o_custkey#X] +Batched: true +Location: InMemoryFileIndex [*] +ReadSchema: struct + +(10) ProjectExecTransformer +Output [2]: [hash(o_custkey#X, 42) AS hash_partition_key#X, o_custkey#X] +Input [1]: [o_custkey#X] + +(11) WholeStageCodegenTransformer (X) +Input [2]: [hash_partition_key#X, o_custkey#X] +Arguments: false + +(12) ColumnarExchange +Input [2]: [hash_partition_key#X, o_custkey#X] +Arguments: hashpartitioning(o_custkey#X, 1), ENSURE_REQUIREMENTS, [o_custkey#X], [plan_id=X], [id=#X] + +(13) ShuffleQueryStage +Output [1]: [o_custkey#X] +Arguments: X + +(14) InputAdapter +Input [1]: [o_custkey#X] + +(15) InputIteratorTransformer +Input [1]: [o_custkey#X] + +(16) ShuffledHashJoinExecTransformer +Left keys [1]: [c_custkey#X] +Right keys [1]: [o_custkey#X] +Join condition: None + +(17) ProjectExecTransformer +Output [2]: [substring(c_phone#X, 1, 2) AS cntrycode#X, c_acctbal#X] +Input [3]: [c_custkey#X, c_phone#X, c_acctbal#X] + +(18) FlushableHashAggregateExecTransformer +Input [2]: [cntrycode#X, c_acctbal#X] +Keys [1]: [cntrycode#X] +Functions [2]: [partial_count(1), partial_sum(c_acctbal#X)] +Aggregate Attributes [3]: [count#X, sum#X, isEmpty#X] +Results [4]: [cntrycode#X, count#X, sum#X, isEmpty#X] + +(19) ProjectExecTransformer +Output [5]: [hash(cntrycode#X, 42) AS hash_partition_key#X, cntrycode#X, count#X, sum#X, isEmpty#X] +Input [4]: [cntrycode#X, count#X, sum#X, isEmpty#X] + +(20) WholeStageCodegenTransformer (X) +Input [5]: [hash_partition_key#X, cntrycode#X, count#X, sum#X, isEmpty#X] +Arguments: false + +(21) ColumnarExchange +Input [5]: [hash_partition_key#X, cntrycode#X, count#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(cntrycode#X, 1), ENSURE_REQUIREMENTS, [cntrycode#X, count#X, sum#X, isEmpty#X], [plan_id=X], [id=#X] + +(22) ShuffleQueryStage +Output [4]: [cntrycode#X, count#X, sum#X, isEmpty#X] +Arguments: X + +(23) InputAdapter +Input [4]: [cntrycode#X, count#X, sum#X, isEmpty#X] + +(24) InputIteratorTransformer +Input [4]: [cntrycode#X, count#X, sum#X, isEmpty#X] + +(25) RegularHashAggregateExecTransformer +Input [4]: [cntrycode#X, count#X, sum#X, isEmpty#X] +Keys [1]: [cntrycode#X] +Functions [2]: [count(1), sum(c_acctbal#X)] +Aggregate Attributes [2]: [count(1)#X, sum(c_acctbal#X)#X] +Results [3]: [cntrycode#X, count(1)#X AS numcust#X, sum(c_acctbal#X)#X AS totacctbal#X] + +(26) WholeStageCodegenTransformer (X) +Input [3]: [cntrycode#X, numcust#X, totacctbal#X] +Arguments: false + +(27) ColumnarExchange +Input [3]: [cntrycode#X, numcust#X, totacctbal#X] +Arguments: rangepartitioning(cntrycode#X ASC NULLS FIRST, 1), ENSURE_REQUIREMENTS, [plan_id=X], [id=#X] + +(28) ShuffleQueryStage +Output [3]: [cntrycode#X, numcust#X, totacctbal#X] +Arguments: X + +(29) InputAdapter +Input [3]: [cntrycode#X, numcust#X, totacctbal#X] + +(30) InputIteratorTransformer +Input [3]: [cntrycode#X, numcust#X, totacctbal#X] + +(31) SortExecTransformer +Input [3]: [cntrycode#X, numcust#X, totacctbal#X] +Arguments: [cntrycode#X ASC NULLS FIRST], true, 0 + +(32) WholeStageCodegenTransformer (X) +Input [3]: [cntrycode#X, numcust#X, totacctbal#X] +Arguments: false + +(33) VeloxColumnarToRowExec +Input [3]: [cntrycode#X, numcust#X, totacctbal#X] + +(34) Scan parquet +Output [3]: [c_custkey#X, c_phone#X, c_acctbal#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(c_acctbal)] +ReadSchema: struct + +(35) Filter +Input [3]: [c_custkey#X, c_phone#X, c_acctbal#X] +Condition : ((isnotnull(c_acctbal#X) AND substring(c_phone#X, 1, 2) IN (13,31,23,29,30,18,17)) AND (cast(c_acctbal#X as decimal(16,6)) > Subquery subquery#X, [id=#X])) + +(36) Exchange +Input [3]: [c_custkey#X, c_phone#X, c_acctbal#X] +Arguments: hashpartitioning(c_custkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(37) Scan parquet +Output [1]: [o_custkey#X] +Batched: true +Location: InMemoryFileIndex [*] +ReadSchema: struct + +(38) Exchange +Input [1]: [o_custkey#X] +Arguments: hashpartitioning(o_custkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(39) ShuffledHashJoin +Left keys [1]: [c_custkey#X] +Right keys [1]: [o_custkey#X] +Join condition: None + +(40) Project +Output [2]: [substring(c_phone#X, 1, 2) AS cntrycode#X, c_acctbal#X] +Input [3]: [c_custkey#X, c_phone#X, c_acctbal#X] + +(41) HashAggregate +Input [2]: [cntrycode#X, c_acctbal#X] +Keys [1]: [cntrycode#X] +Functions [2]: [partial_count(1), partial_sum(c_acctbal#X)] +Aggregate Attributes [3]: [count#X, sum#X, isEmpty#X] +Results [4]: [cntrycode#X, count#X, sum#X, isEmpty#X] + +(42) Exchange +Input [4]: [cntrycode#X, count#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(cntrycode#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(43) HashAggregate +Input [4]: [cntrycode#X, count#X, sum#X, isEmpty#X] +Keys [1]: [cntrycode#X] +Functions [2]: [count(1), sum(c_acctbal#X)] +Aggregate Attributes [2]: [count(1)#X, sum(c_acctbal#X)#X] +Results [3]: [cntrycode#X, count(1)#X AS numcust#X, sum(c_acctbal#X)#X AS totacctbal#X] + +(44) Exchange +Input [3]: [cntrycode#X, numcust#X, totacctbal#X] +Arguments: rangepartitioning(cntrycode#X ASC NULLS FIRST, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(45) Sort +Input [3]: [cntrycode#X, numcust#X, totacctbal#X] +Arguments: [cntrycode#X ASC NULLS FIRST], true, 0 + +(46) AdaptiveSparkPlan +Output [3]: [cntrycode#X, numcust#X, totacctbal#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/3.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/3.txt new file mode 100644 index 000000000000..27f81d9d2637 --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/3.txt @@ -0,0 +1,319 @@ +== Physical Plan == +AdaptiveSparkPlan (59) ++- == Final Plan == + VeloxColumnarToRowExec (39) + +- TakeOrderedAndProjectExecTransformer (38) + +- ^ ProjectExecTransformer (36) + +- ^ RegularHashAggregateExecTransformer (35) + +- ^ RegularHashAggregateExecTransformer (34) + +- ^ ProjectExecTransformer (33) + +- ^ ShuffledHashJoinExecTransformer Inner (32) + :- ^ InputIteratorTransformer (23) + : +- ^ InputAdapter (22) + : +- ^ ShuffleQueryStage (21) + : +- ColumnarExchange (20) + : +- ^ ProjectExecTransformer (18) + : +- ^ ShuffledHashJoinExecTransformer Inner (17) + : :- ^ InputIteratorTransformer (8) + : : +- ^ InputAdapter (7) + : : +- ^ ShuffleQueryStage (6) + : : +- ColumnarExchange (5) + : : +- ^ ProjectExecTransformer (3) + : : +- ^ FilterExecTransformer (2) + : : +- ^ Scan parquet (1) + : +- ^ InputIteratorTransformer (16) + : +- ^ InputAdapter (15) + : +- ^ ShuffleQueryStage (14) + : +- ColumnarExchange (13) + : +- ^ ProjectExecTransformer (11) + : +- ^ FilterExecTransformer (10) + : +- ^ Scan parquet (9) + +- ^ InputIteratorTransformer (31) + +- ^ InputAdapter (30) + +- ^ ShuffleQueryStage (29) + +- ColumnarExchange (28) + +- ^ ProjectExecTransformer (26) + +- ^ FilterExecTransformer (25) + +- ^ Scan parquet (24) ++- == Initial Plan == + TakeOrderedAndProject (58) + +- HashAggregate (57) + +- HashAggregate (56) + +- Project (55) + +- ShuffledHashJoin Inner BuildRight (54) + :- Exchange (49) + : +- Project (48) + : +- ShuffledHashJoin Inner BuildLeft (47) + : :- Exchange (43) + : : +- Project (42) + : : +- Filter (41) + : : +- Scan parquet (40) + : +- Exchange (46) + : +- Filter (45) + : +- Scan parquet (44) + +- Exchange (53) + +- Project (52) + +- Filter (51) + +- Scan parquet (50) + + +(1) Scan parquet +Output [2]: [c_custkey#X, c_mktsegment#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(c_mktsegment), EqualTo(c_mktsegment,BUILDING), IsNotNull(c_custkey)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [2]: [c_custkey#X, c_mktsegment#X] +Arguments: ((isnotnull(c_mktsegment#X) AND (c_mktsegment#X = BUILDING)) AND isnotnull(c_custkey#X)) + +(3) ProjectExecTransformer +Output [2]: [hash(c_custkey#X, 42) AS hash_partition_key#X, c_custkey#X] +Input [2]: [c_custkey#X, c_mktsegment#X] + +(4) WholeStageCodegenTransformer (X) +Input [2]: [hash_partition_key#X, c_custkey#X] +Arguments: false + +(5) ColumnarExchange +Input [2]: [hash_partition_key#X, c_custkey#X] +Arguments: hashpartitioning(c_custkey#X, 1), ENSURE_REQUIREMENTS, [c_custkey#X], [plan_id=X], [id=#X] + +(6) ShuffleQueryStage +Output [1]: [c_custkey#X] +Arguments: X + +(7) InputAdapter +Input [1]: [c_custkey#X] + +(8) InputIteratorTransformer +Input [1]: [c_custkey#X] + +(9) Scan parquet +Output [4]: [o_orderkey#X, o_custkey#X, o_orderdate#X, o_shippriority#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_orderdate), LessThan(o_orderdate,1995-03-15), IsNotNull(o_custkey), IsNotNull(o_orderkey)] +ReadSchema: struct + +(10) FilterExecTransformer +Input [4]: [o_orderkey#X, o_custkey#X, o_orderdate#X, o_shippriority#X] +Arguments: (((isnotnull(o_orderdate#X) AND (o_orderdate#X < 1995-03-15)) AND isnotnull(o_custkey#X)) AND isnotnull(o_orderkey#X)) + +(11) ProjectExecTransformer +Output [5]: [hash(o_custkey#X, 42) AS hash_partition_key#X, o_orderkey#X, o_custkey#X, o_orderdate#X, o_shippriority#X] +Input [4]: [o_orderkey#X, o_custkey#X, o_orderdate#X, o_shippriority#X] + +(12) WholeStageCodegenTransformer (X) +Input [5]: [hash_partition_key#X, o_orderkey#X, o_custkey#X, o_orderdate#X, o_shippriority#X] +Arguments: false + +(13) ColumnarExchange +Input [5]: [hash_partition_key#X, o_orderkey#X, o_custkey#X, o_orderdate#X, o_shippriority#X] +Arguments: hashpartitioning(o_custkey#X, 1), ENSURE_REQUIREMENTS, [o_orderkey#X, o_custkey#X, o_orderdate#X, o_shippriority#X], [plan_id=X], [id=#X] + +(14) ShuffleQueryStage +Output [4]: [o_orderkey#X, o_custkey#X, o_orderdate#X, o_shippriority#X] +Arguments: X + +(15) InputAdapter +Input [4]: [o_orderkey#X, o_custkey#X, o_orderdate#X, o_shippriority#X] + +(16) InputIteratorTransformer +Input [4]: [o_orderkey#X, o_custkey#X, o_orderdate#X, o_shippriority#X] + +(17) ShuffledHashJoinExecTransformer +Left keys [1]: [c_custkey#X] +Right keys [1]: [o_custkey#X] +Join condition: None + +(18) ProjectExecTransformer +Output [4]: [hash(o_orderkey#X, 42) AS hash_partition_key#X, o_orderkey#X, o_orderdate#X, o_shippriority#X] +Input [5]: [c_custkey#X, o_orderkey#X, o_custkey#X, o_orderdate#X, o_shippriority#X] + +(19) WholeStageCodegenTransformer (X) +Input [4]: [hash_partition_key#X, o_orderkey#X, o_orderdate#X, o_shippriority#X] +Arguments: false + +(20) ColumnarExchange +Input [4]: [hash_partition_key#X, o_orderkey#X, o_orderdate#X, o_shippriority#X] +Arguments: hashpartitioning(o_orderkey#X, 1), ENSURE_REQUIREMENTS, [o_orderkey#X, o_orderdate#X, o_shippriority#X], [plan_id=X], [id=#X] + +(21) ShuffleQueryStage +Output [3]: [o_orderkey#X, o_orderdate#X, o_shippriority#X] +Arguments: X + +(22) InputAdapter +Input [3]: [o_orderkey#X, o_orderdate#X, o_shippriority#X] + +(23) InputIteratorTransformer +Input [3]: [o_orderkey#X, o_orderdate#X, o_shippriority#X] + +(24) Scan parquet +Output [4]: [l_orderkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_shipdate), GreaterThan(l_shipdate,1995-03-15), IsNotNull(l_orderkey)] +ReadSchema: struct + +(25) FilterExecTransformer +Input [4]: [l_orderkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Arguments: ((isnotnull(l_shipdate#X) AND (l_shipdate#X > 1995-03-15)) AND isnotnull(l_orderkey#X)) + +(26) ProjectExecTransformer +Output [4]: [hash(l_orderkey#X, 42) AS hash_partition_key#X, l_orderkey#X, l_extendedprice#X, l_discount#X] +Input [4]: [l_orderkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] + +(27) WholeStageCodegenTransformer (X) +Input [4]: [hash_partition_key#X, l_orderkey#X, l_extendedprice#X, l_discount#X] +Arguments: false + +(28) ColumnarExchange +Input [4]: [hash_partition_key#X, l_orderkey#X, l_extendedprice#X, l_discount#X] +Arguments: hashpartitioning(l_orderkey#X, 1), ENSURE_REQUIREMENTS, [l_orderkey#X, l_extendedprice#X, l_discount#X], [plan_id=X], [id=#X] + +(29) ShuffleQueryStage +Output [3]: [l_orderkey#X, l_extendedprice#X, l_discount#X] +Arguments: X + +(30) InputAdapter +Input [3]: [l_orderkey#X, l_extendedprice#X, l_discount#X] + +(31) InputIteratorTransformer +Input [3]: [l_orderkey#X, l_extendedprice#X, l_discount#X] + +(32) ShuffledHashJoinExecTransformer +Left keys [1]: [o_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: None + +(33) ProjectExecTransformer +Output [6]: [o_orderdate#X, o_shippriority#X, l_orderkey#X, l_extendedprice#X, l_discount#X, CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) AS _pre_110#X] +Input [6]: [o_orderkey#X, o_orderdate#X, o_shippriority#X, l_orderkey#X, l_extendedprice#X, l_discount#X] + +(34) RegularHashAggregateExecTransformer +Input [6]: [o_orderdate#X, o_shippriority#X, l_orderkey#X, l_extendedprice#X, l_discount#X, _pre_110#X] +Keys [3]: [l_orderkey#X, o_orderdate#X, o_shippriority#X] +Functions [1]: [partial_sum(_pre_110#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [5]: [l_orderkey#X, o_orderdate#X, o_shippriority#X, sum#X, isEmpty#X] + +(35) RegularHashAggregateExecTransformer +Input [5]: [l_orderkey#X, o_orderdate#X, o_shippriority#X, sum#X, isEmpty#X] +Keys [3]: [l_orderkey#X, o_orderdate#X, o_shippriority#X] +Functions [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))] +Aggregate Attributes [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X] +Results [4]: [l_orderkey#X, o_orderdate#X, o_shippriority#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X] + +(36) ProjectExecTransformer +Output [4]: [l_orderkey#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X AS revenue#X, o_orderdate#X, o_shippriority#X] +Input [4]: [l_orderkey#X, o_orderdate#X, o_shippriority#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X] + +(37) WholeStageCodegenTransformer (X) +Input [4]: [l_orderkey#X, revenue#X, o_orderdate#X, o_shippriority#X] +Arguments: false + +(38) TakeOrderedAndProjectExecTransformer +Input [4]: [l_orderkey#X, revenue#X, o_orderdate#X, o_shippriority#X] +Arguments: X, [revenue#X DESC NULLS LAST, o_orderdate#X ASC NULLS FIRST], [l_orderkey#X, revenue#X, o_orderdate#X, o_shippriority#X], 0 + +(39) VeloxColumnarToRowExec +Input [4]: [l_orderkey#X, revenue#X, o_orderdate#X, o_shippriority#X] + +(40) Scan parquet +Output [2]: [c_custkey#X, c_mktsegment#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(c_mktsegment), EqualTo(c_mktsegment,BUILDING), IsNotNull(c_custkey)] +ReadSchema: struct + +(41) Filter +Input [2]: [c_custkey#X, c_mktsegment#X] +Condition : ((isnotnull(c_mktsegment#X) AND (c_mktsegment#X = BUILDING)) AND isnotnull(c_custkey#X)) + +(42) Project +Output [1]: [c_custkey#X] +Input [2]: [c_custkey#X, c_mktsegment#X] + +(43) Exchange +Input [1]: [c_custkey#X] +Arguments: hashpartitioning(c_custkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(44) Scan parquet +Output [4]: [o_orderkey#X, o_custkey#X, o_orderdate#X, o_shippriority#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_orderdate), LessThan(o_orderdate,1995-03-15), IsNotNull(o_custkey), IsNotNull(o_orderkey)] +ReadSchema: struct + +(45) Filter +Input [4]: [o_orderkey#X, o_custkey#X, o_orderdate#X, o_shippriority#X] +Condition : (((isnotnull(o_orderdate#X) AND (o_orderdate#X < 1995-03-15)) AND isnotnull(o_custkey#X)) AND isnotnull(o_orderkey#X)) + +(46) Exchange +Input [4]: [o_orderkey#X, o_custkey#X, o_orderdate#X, o_shippriority#X] +Arguments: hashpartitioning(o_custkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(47) ShuffledHashJoin +Left keys [1]: [c_custkey#X] +Right keys [1]: [o_custkey#X] +Join condition: None + +(48) Project +Output [3]: [o_orderkey#X, o_orderdate#X, o_shippriority#X] +Input [5]: [c_custkey#X, o_orderkey#X, o_custkey#X, o_orderdate#X, o_shippriority#X] + +(49) Exchange +Input [3]: [o_orderkey#X, o_orderdate#X, o_shippriority#X] +Arguments: hashpartitioning(o_orderkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(50) Scan parquet +Output [4]: [l_orderkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_shipdate), GreaterThan(l_shipdate,1995-03-15), IsNotNull(l_orderkey)] +ReadSchema: struct + +(51) Filter +Input [4]: [l_orderkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Condition : ((isnotnull(l_shipdate#X) AND (l_shipdate#X > 1995-03-15)) AND isnotnull(l_orderkey#X)) + +(52) Project +Output [3]: [l_orderkey#X, l_extendedprice#X, l_discount#X] +Input [4]: [l_orderkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] + +(53) Exchange +Input [3]: [l_orderkey#X, l_extendedprice#X, l_discount#X] +Arguments: hashpartitioning(l_orderkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(54) ShuffledHashJoin +Left keys [1]: [o_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: None + +(55) Project +Output [5]: [o_orderdate#X, o_shippriority#X, l_orderkey#X, l_extendedprice#X, l_discount#X] +Input [6]: [o_orderkey#X, o_orderdate#X, o_shippriority#X, l_orderkey#X, l_extendedprice#X, l_discount#X] + +(56) HashAggregate +Input [5]: [o_orderdate#X, o_shippriority#X, l_orderkey#X, l_extendedprice#X, l_discount#X] +Keys [3]: [l_orderkey#X, o_orderdate#X, o_shippriority#X] +Functions [1]: [partial_sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [5]: [l_orderkey#X, o_orderdate#X, o_shippriority#X, sum#X, isEmpty#X] + +(57) HashAggregate +Input [5]: [l_orderkey#X, o_orderdate#X, o_shippriority#X, sum#X, isEmpty#X] +Keys [3]: [l_orderkey#X, o_orderdate#X, o_shippriority#X] +Functions [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))] +Aggregate Attributes [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X] +Results [4]: [l_orderkey#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X AS revenue#X, o_orderdate#X, o_shippriority#X] + +(58) TakeOrderedAndProject +Input [4]: [l_orderkey#X, revenue#X, o_orderdate#X, o_shippriority#X] +Arguments: X, [revenue#X DESC NULLS LAST, o_orderdate#X ASC NULLS FIRST], [l_orderkey#X, revenue#X, o_orderdate#X, o_shippriority#X] + +(59) AdaptiveSparkPlan +Output [4]: [l_orderkey#X, revenue#X, o_orderdate#X, o_shippriority#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/4.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/4.txt new file mode 100644 index 000000000000..74fca4208dd5 --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/4.txt @@ -0,0 +1,266 @@ +== Physical Plan == +AdaptiveSparkPlan (50) ++- == Final Plan == + VeloxColumnarToRowExec (34) + +- ^ SortExecTransformer (32) + +- ^ InputIteratorTransformer (31) + +- ^ InputAdapter (30) + +- ^ ShuffleQueryStage (29) + +- ColumnarExchange (28) + +- ^ RegularHashAggregateExecTransformer (26) + +- ^ InputIteratorTransformer (25) + +- ^ InputAdapter (24) + +- ^ ShuffleQueryStage (23) + +- ColumnarExchange (22) + +- ^ ProjectExecTransformer (20) + +- ^ FlushableHashAggregateExecTransformer (19) + +- ^ ProjectExecTransformer (18) + +- ^ ShuffledHashJoinExecTransformer LeftSemi (17) + :- ^ InputIteratorTransformer (8) + : +- ^ InputAdapter (7) + : +- ^ ShuffleQueryStage (6) + : +- ColumnarExchange (5) + : +- ^ ProjectExecTransformer (3) + : +- ^ FilterExecTransformer (2) + : +- ^ Scan parquet (1) + +- ^ InputIteratorTransformer (16) + +- ^ InputAdapter (15) + +- ^ ShuffleQueryStage (14) + +- ColumnarExchange (13) + +- ^ ProjectExecTransformer (11) + +- ^ FilterExecTransformer (10) + +- ^ Scan parquet (9) ++- == Initial Plan == + Sort (49) + +- Exchange (48) + +- HashAggregate (47) + +- Exchange (46) + +- HashAggregate (45) + +- Project (44) + +- ShuffledHashJoin LeftSemi BuildRight (43) + :- Exchange (38) + : +- Project (37) + : +- Filter (36) + : +- Scan parquet (35) + +- Exchange (42) + +- Project (41) + +- Filter (40) + +- Scan parquet (39) + + +(1) Scan parquet +Output [3]: [o_orderkey#X, o_orderdate#X, o_orderpriority#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_orderdate), GreaterThanOrEqual(o_orderdate,1993-07-01), LessThan(o_orderdate,1993-10-01)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [3]: [o_orderkey#X, o_orderdate#X, o_orderpriority#X] +Arguments: ((isnotnull(o_orderdate#X) AND (o_orderdate#X >= 1993-07-01)) AND (o_orderdate#X < 1993-10-01)) + +(3) ProjectExecTransformer +Output [3]: [hash(o_orderkey#X, 42) AS hash_partition_key#X, o_orderkey#X, o_orderpriority#X] +Input [3]: [o_orderkey#X, o_orderdate#X, o_orderpriority#X] + +(4) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, o_orderkey#X, o_orderpriority#X] +Arguments: false + +(5) ColumnarExchange +Input [3]: [hash_partition_key#X, o_orderkey#X, o_orderpriority#X] +Arguments: hashpartitioning(o_orderkey#X, 1), ENSURE_REQUIREMENTS, [o_orderkey#X, o_orderpriority#X], [plan_id=X], [id=#X] + +(6) ShuffleQueryStage +Output [2]: [o_orderkey#X, o_orderpriority#X] +Arguments: X + +(7) InputAdapter +Input [2]: [o_orderkey#X, o_orderpriority#X] + +(8) InputIteratorTransformer +Input [2]: [o_orderkey#X, o_orderpriority#X] + +(9) Scan parquet +Output [3]: [l_orderkey#X, l_commitdate#X, l_receiptdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_commitdate), IsNotNull(l_receiptdate)] +ReadSchema: struct + +(10) FilterExecTransformer +Input [3]: [l_orderkey#X, l_commitdate#X, l_receiptdate#X] +Arguments: ((isnotnull(l_commitdate#X) AND isnotnull(l_receiptdate#X)) AND (l_commitdate#X < l_receiptdate#X)) + +(11) ProjectExecTransformer +Output [2]: [hash(l_orderkey#X, 42) AS hash_partition_key#X, l_orderkey#X] +Input [3]: [l_orderkey#X, l_commitdate#X, l_receiptdate#X] + +(12) WholeStageCodegenTransformer (X) +Input [2]: [hash_partition_key#X, l_orderkey#X] +Arguments: false + +(13) ColumnarExchange +Input [2]: [hash_partition_key#X, l_orderkey#X] +Arguments: hashpartitioning(l_orderkey#X, 1), ENSURE_REQUIREMENTS, [l_orderkey#X], [plan_id=X], [id=#X] + +(14) ShuffleQueryStage +Output [1]: [l_orderkey#X] +Arguments: X + +(15) InputAdapter +Input [1]: [l_orderkey#X] + +(16) InputIteratorTransformer +Input [1]: [l_orderkey#X] + +(17) ShuffledHashJoinExecTransformer +Left keys [1]: [o_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: None + +(18) ProjectExecTransformer +Output [1]: [o_orderpriority#X] +Input [2]: [o_orderkey#X, o_orderpriority#X] + +(19) FlushableHashAggregateExecTransformer +Input [1]: [o_orderpriority#X] +Keys [1]: [o_orderpriority#X] +Functions [1]: [partial_count(1)] +Aggregate Attributes [1]: [count#X] +Results [2]: [o_orderpriority#X, count#X] + +(20) ProjectExecTransformer +Output [3]: [hash(o_orderpriority#X, 42) AS hash_partition_key#X, o_orderpriority#X, count#X] +Input [2]: [o_orderpriority#X, count#X] + +(21) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, o_orderpriority#X, count#X] +Arguments: false + +(22) ColumnarExchange +Input [3]: [hash_partition_key#X, o_orderpriority#X, count#X] +Arguments: hashpartitioning(o_orderpriority#X, 1), ENSURE_REQUIREMENTS, [o_orderpriority#X, count#X], [plan_id=X], [id=#X] + +(23) ShuffleQueryStage +Output [2]: [o_orderpriority#X, count#X] +Arguments: X + +(24) InputAdapter +Input [2]: [o_orderpriority#X, count#X] + +(25) InputIteratorTransformer +Input [2]: [o_orderpriority#X, count#X] + +(26) RegularHashAggregateExecTransformer +Input [2]: [o_orderpriority#X, count#X] +Keys [1]: [o_orderpriority#X] +Functions [1]: [count(1)] +Aggregate Attributes [1]: [count(1)#X] +Results [2]: [o_orderpriority#X, count(1)#X AS order_count#X] + +(27) WholeStageCodegenTransformer (X) +Input [2]: [o_orderpriority#X, order_count#X] +Arguments: false + +(28) ColumnarExchange +Input [2]: [o_orderpriority#X, order_count#X] +Arguments: rangepartitioning(o_orderpriority#X ASC NULLS FIRST, 1), ENSURE_REQUIREMENTS, [plan_id=X], [id=#X] + +(29) ShuffleQueryStage +Output [2]: [o_orderpriority#X, order_count#X] +Arguments: X + +(30) InputAdapter +Input [2]: [o_orderpriority#X, order_count#X] + +(31) InputIteratorTransformer +Input [2]: [o_orderpriority#X, order_count#X] + +(32) SortExecTransformer +Input [2]: [o_orderpriority#X, order_count#X] +Arguments: [o_orderpriority#X ASC NULLS FIRST], true, 0 + +(33) WholeStageCodegenTransformer (X) +Input [2]: [o_orderpriority#X, order_count#X] +Arguments: false + +(34) VeloxColumnarToRowExec +Input [2]: [o_orderpriority#X, order_count#X] + +(35) Scan parquet +Output [3]: [o_orderkey#X, o_orderdate#X, o_orderpriority#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_orderdate), GreaterThanOrEqual(o_orderdate,1993-07-01), LessThan(o_orderdate,1993-10-01)] +ReadSchema: struct + +(36) Filter +Input [3]: [o_orderkey#X, o_orderdate#X, o_orderpriority#X] +Condition : ((isnotnull(o_orderdate#X) AND (o_orderdate#X >= 1993-07-01)) AND (o_orderdate#X < 1993-10-01)) + +(37) Project +Output [2]: [o_orderkey#X, o_orderpriority#X] +Input [3]: [o_orderkey#X, o_orderdate#X, o_orderpriority#X] + +(38) Exchange +Input [2]: [o_orderkey#X, o_orderpriority#X] +Arguments: hashpartitioning(o_orderkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(39) Scan parquet +Output [3]: [l_orderkey#X, l_commitdate#X, l_receiptdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_commitdate), IsNotNull(l_receiptdate)] +ReadSchema: struct + +(40) Filter +Input [3]: [l_orderkey#X, l_commitdate#X, l_receiptdate#X] +Condition : ((isnotnull(l_commitdate#X) AND isnotnull(l_receiptdate#X)) AND (l_commitdate#X < l_receiptdate#X)) + +(41) Project +Output [1]: [l_orderkey#X] +Input [3]: [l_orderkey#X, l_commitdate#X, l_receiptdate#X] + +(42) Exchange +Input [1]: [l_orderkey#X] +Arguments: hashpartitioning(l_orderkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(43) ShuffledHashJoin +Left keys [1]: [o_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: None + +(44) Project +Output [1]: [o_orderpriority#X] +Input [2]: [o_orderkey#X, o_orderpriority#X] + +(45) HashAggregate +Input [1]: [o_orderpriority#X] +Keys [1]: [o_orderpriority#X] +Functions [1]: [partial_count(1)] +Aggregate Attributes [1]: [count#X] +Results [2]: [o_orderpriority#X, count#X] + +(46) Exchange +Input [2]: [o_orderpriority#X, count#X] +Arguments: hashpartitioning(o_orderpriority#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(47) HashAggregate +Input [2]: [o_orderpriority#X, count#X] +Keys [1]: [o_orderpriority#X] +Functions [1]: [count(1)] +Aggregate Attributes [1]: [count(1)#X] +Results [2]: [o_orderpriority#X, count(1)#X AS order_count#X] + +(48) Exchange +Input [2]: [o_orderpriority#X, order_count#X] +Arguments: rangepartitioning(o_orderpriority#X ASC NULLS FIRST, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(49) Sort +Input [2]: [o_orderpriority#X, order_count#X] +Arguments: [o_orderpriority#X ASC NULLS FIRST], true, 0 + +(50) AdaptiveSparkPlan +Output [2]: [o_orderpriority#X, order_count#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/5.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/5.txt new file mode 100644 index 000000000000..c1d9308e6132 --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/5.txt @@ -0,0 +1,694 @@ +== Physical Plan == +AdaptiveSparkPlan (134) ++- == Final Plan == + VeloxColumnarToRowExec (94) + +- ^ SortExecTransformer (92) + +- ^ InputIteratorTransformer (91) + +- ^ InputAdapter (90) + +- ^ ShuffleQueryStage (89) + +- ColumnarExchange (88) + +- ^ RegularHashAggregateExecTransformer (86) + +- ^ InputIteratorTransformer (85) + +- ^ InputAdapter (84) + +- ^ ShuffleQueryStage (83) + +- ColumnarExchange (82) + +- ^ ProjectExecTransformer (80) + +- ^ FlushableHashAggregateExecTransformer (79) + +- ^ ProjectExecTransformer (78) + +- ^ ShuffledHashJoinExecTransformer Inner (77) + :- ^ InputIteratorTransformer (68) + : +- ^ InputAdapter (67) + : +- ^ ShuffleQueryStage (66) + : +- ColumnarExchange (65) + : +- ^ ProjectExecTransformer (63) + : +- ^ ShuffledHashJoinExecTransformer Inner (62) + : :- ^ InputIteratorTransformer (53) + : : +- ^ InputAdapter (52) + : : +- ^ ShuffleQueryStage (51) + : : +- ColumnarExchange (50) + : : +- ^ ProjectExecTransformer (48) + : : +- ^ ShuffledHashJoinExecTransformer Inner (47) + : : :- ^ InputIteratorTransformer (38) + : : : +- ^ InputAdapter (37) + : : : +- ^ ShuffleQueryStage (36) + : : : +- ColumnarExchange (35) + : : : +- ^ ProjectExecTransformer (33) + : : : +- ^ ShuffledHashJoinExecTransformer Inner (32) + : : : :- ^ InputIteratorTransformer (23) + : : : : +- ^ InputAdapter (22) + : : : : +- ^ ShuffleQueryStage (21) + : : : : +- ColumnarExchange (20) + : : : : +- ^ ProjectExecTransformer (18) + : : : : +- ^ ShuffledHashJoinExecTransformer Inner (17) + : : : : :- ^ InputIteratorTransformer (8) + : : : : : +- ^ InputAdapter (7) + : : : : : +- ^ ShuffleQueryStage (6) + : : : : : +- ColumnarExchange (5) + : : : : : +- ^ ProjectExecTransformer (3) + : : : : : +- ^ FilterExecTransformer (2) + : : : : : +- ^ Scan parquet (1) + : : : : +- ^ InputIteratorTransformer (16) + : : : : +- ^ InputAdapter (15) + : : : : +- ^ ShuffleQueryStage (14) + : : : : +- ColumnarExchange (13) + : : : : +- ^ ProjectExecTransformer (11) + : : : : +- ^ FilterExecTransformer (10) + : : : : +- ^ Scan parquet (9) + : : : +- ^ InputIteratorTransformer (31) + : : : +- ^ InputAdapter (30) + : : : +- ^ ShuffleQueryStage (29) + : : : +- ColumnarExchange (28) + : : : +- ^ ProjectExecTransformer (26) + : : : +- ^ FilterExecTransformer (25) + : : : +- ^ Scan parquet (24) + : : +- ^ InputIteratorTransformer (46) + : : +- ^ InputAdapter (45) + : : +- ^ ShuffleQueryStage (44) + : : +- ColumnarExchange (43) + : : +- ^ ProjectExecTransformer (41) + : : +- ^ FilterExecTransformer (40) + : : +- ^ Scan parquet (39) + : +- ^ InputIteratorTransformer (61) + : +- ^ InputAdapter (60) + : +- ^ ShuffleQueryStage (59) + : +- ColumnarExchange (58) + : +- ^ ProjectExecTransformer (56) + : +- ^ FilterExecTransformer (55) + : +- ^ Scan parquet (54) + +- ^ InputIteratorTransformer (76) + +- ^ InputAdapter (75) + +- ^ ShuffleQueryStage (74) + +- ColumnarExchange (73) + +- ^ ProjectExecTransformer (71) + +- ^ FilterExecTransformer (70) + +- ^ Scan parquet (69) ++- == Initial Plan == + Sort (133) + +- Exchange (132) + +- HashAggregate (131) + +- Exchange (130) + +- HashAggregate (129) + +- Project (128) + +- ShuffledHashJoin Inner BuildRight (127) + :- Exchange (122) + : +- Project (121) + : +- ShuffledHashJoin Inner BuildRight (120) + : :- Exchange (116) + : : +- Project (115) + : : +- ShuffledHashJoin Inner BuildRight (114) + : : :- Exchange (110) + : : : +- Project (109) + : : : +- ShuffledHashJoin Inner BuildRight (108) + : : : :- Exchange (104) + : : : : +- Project (103) + : : : : +- ShuffledHashJoin Inner BuildLeft (102) + : : : : :- Exchange (97) + : : : : : +- Filter (96) + : : : : : +- Scan parquet (95) + : : : : +- Exchange (101) + : : : : +- Project (100) + : : : : +- Filter (99) + : : : : +- Scan parquet (98) + : : : +- Exchange (107) + : : : +- Filter (106) + : : : +- Scan parquet (105) + : : +- Exchange (113) + : : +- Filter (112) + : : +- Scan parquet (111) + : +- Exchange (119) + : +- Filter (118) + : +- Scan parquet (117) + +- Exchange (126) + +- Project (125) + +- Filter (124) + +- Scan parquet (123) + + +(1) Scan parquet +Output [2]: [c_custkey#X, c_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(c_custkey), IsNotNull(c_nationkey)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [2]: [c_custkey#X, c_nationkey#X] +Arguments: (isnotnull(c_custkey#X) AND isnotnull(c_nationkey#X)) + +(3) ProjectExecTransformer +Output [3]: [hash(c_custkey#X, 42) AS hash_partition_key#X, c_custkey#X, c_nationkey#X] +Input [2]: [c_custkey#X, c_nationkey#X] + +(4) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, c_custkey#X, c_nationkey#X] +Arguments: false + +(5) ColumnarExchange +Input [3]: [hash_partition_key#X, c_custkey#X, c_nationkey#X] +Arguments: hashpartitioning(c_custkey#X, 1), ENSURE_REQUIREMENTS, [c_custkey#X, c_nationkey#X], [plan_id=X], [id=#X] + +(6) ShuffleQueryStage +Output [2]: [c_custkey#X, c_nationkey#X] +Arguments: X + +(7) InputAdapter +Input [2]: [c_custkey#X, c_nationkey#X] + +(8) InputIteratorTransformer +Input [2]: [c_custkey#X, c_nationkey#X] + +(9) Scan parquet +Output [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_orderdate), GreaterThanOrEqual(o_orderdate,1994-01-01), LessThan(o_orderdate,1995-01-01), IsNotNull(o_custkey), IsNotNull(o_orderkey)] +ReadSchema: struct + +(10) FilterExecTransformer +Input [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] +Arguments: ((((isnotnull(o_orderdate#X) AND (o_orderdate#X >= 1994-01-01)) AND (o_orderdate#X < 1995-01-01)) AND isnotnull(o_custkey#X)) AND isnotnull(o_orderkey#X)) + +(11) ProjectExecTransformer +Output [3]: [hash(o_custkey#X, 42) AS hash_partition_key#X, o_orderkey#X, o_custkey#X] +Input [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] + +(12) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, o_orderkey#X, o_custkey#X] +Arguments: false + +(13) ColumnarExchange +Input [3]: [hash_partition_key#X, o_orderkey#X, o_custkey#X] +Arguments: hashpartitioning(o_custkey#X, 1), ENSURE_REQUIREMENTS, [o_orderkey#X, o_custkey#X], [plan_id=X], [id=#X] + +(14) ShuffleQueryStage +Output [2]: [o_orderkey#X, o_custkey#X] +Arguments: X + +(15) InputAdapter +Input [2]: [o_orderkey#X, o_custkey#X] + +(16) InputIteratorTransformer +Input [2]: [o_orderkey#X, o_custkey#X] + +(17) ShuffledHashJoinExecTransformer +Left keys [1]: [c_custkey#X] +Right keys [1]: [o_custkey#X] +Join condition: None + +(18) ProjectExecTransformer +Output [3]: [hash(o_orderkey#X, 42) AS hash_partition_key#X, c_nationkey#X, o_orderkey#X] +Input [4]: [c_custkey#X, c_nationkey#X, o_orderkey#X, o_custkey#X] + +(19) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, c_nationkey#X, o_orderkey#X] +Arguments: false + +(20) ColumnarExchange +Input [3]: [hash_partition_key#X, c_nationkey#X, o_orderkey#X] +Arguments: hashpartitioning(o_orderkey#X, 1), ENSURE_REQUIREMENTS, [c_nationkey#X, o_orderkey#X], [plan_id=X], [id=#X] + +(21) ShuffleQueryStage +Output [2]: [c_nationkey#X, o_orderkey#X] +Arguments: X + +(22) InputAdapter +Input [2]: [c_nationkey#X, o_orderkey#X] + +(23) InputIteratorTransformer +Input [2]: [c_nationkey#X, o_orderkey#X] + +(24) Scan parquet +Output [4]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_orderkey), IsNotNull(l_suppkey)] +ReadSchema: struct + +(25) FilterExecTransformer +Input [4]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Arguments: (isnotnull(l_orderkey#X) AND isnotnull(l_suppkey#X)) + +(26) ProjectExecTransformer +Output [5]: [hash(l_orderkey#X, 42) AS hash_partition_key#X, l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Input [4]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] + +(27) WholeStageCodegenTransformer (X) +Input [5]: [hash_partition_key#X, l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Arguments: false + +(28) ColumnarExchange +Input [5]: [hash_partition_key#X, l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Arguments: hashpartitioning(l_orderkey#X, 1), ENSURE_REQUIREMENTS, [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X], [plan_id=X], [id=#X] + +(29) ShuffleQueryStage +Output [4]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Arguments: X + +(30) InputAdapter +Input [4]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] + +(31) InputIteratorTransformer +Input [4]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] + +(32) ShuffledHashJoinExecTransformer +Left keys [1]: [o_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: None + +(33) ProjectExecTransformer +Output [5]: [hash(l_suppkey#X, c_nationkey#X, 42) AS hash_partition_key#X, c_nationkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Input [6]: [c_nationkey#X, o_orderkey#X, l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] + +(34) WholeStageCodegenTransformer (X) +Input [5]: [hash_partition_key#X, c_nationkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Arguments: false + +(35) ColumnarExchange +Input [5]: [hash_partition_key#X, c_nationkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Arguments: hashpartitioning(l_suppkey#X, c_nationkey#X, 1), ENSURE_REQUIREMENTS, [c_nationkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X], [plan_id=X], [id=#X] + +(36) ShuffleQueryStage +Output [4]: [c_nationkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Arguments: X + +(37) InputAdapter +Input [4]: [c_nationkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] + +(38) InputIteratorTransformer +Input [4]: [c_nationkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] + +(39) Scan parquet +Output [2]: [s_suppkey#X, s_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(s_suppkey), IsNotNull(s_nationkey)] +ReadSchema: struct + +(40) FilterExecTransformer +Input [2]: [s_suppkey#X, s_nationkey#X] +Arguments: (isnotnull(s_suppkey#X) AND isnotnull(s_nationkey#X)) + +(41) ProjectExecTransformer +Output [3]: [hash(s_suppkey#X, s_nationkey#X, 42) AS hash_partition_key#X, s_suppkey#X, s_nationkey#X] +Input [2]: [s_suppkey#X, s_nationkey#X] + +(42) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, s_suppkey#X, s_nationkey#X] +Arguments: false + +(43) ColumnarExchange +Input [3]: [hash_partition_key#X, s_suppkey#X, s_nationkey#X] +Arguments: hashpartitioning(s_suppkey#X, s_nationkey#X, 1), ENSURE_REQUIREMENTS, [s_suppkey#X, s_nationkey#X], [plan_id=X], [id=#X] + +(44) ShuffleQueryStage +Output [2]: [s_suppkey#X, s_nationkey#X] +Arguments: X + +(45) InputAdapter +Input [2]: [s_suppkey#X, s_nationkey#X] + +(46) InputIteratorTransformer +Input [2]: [s_suppkey#X, s_nationkey#X] + +(47) ShuffledHashJoinExecTransformer +Left keys [2]: [l_suppkey#X, c_nationkey#X] +Right keys [2]: [s_suppkey#X, s_nationkey#X] +Join condition: None + +(48) ProjectExecTransformer +Output [4]: [hash(s_nationkey#X, 42) AS hash_partition_key#X, l_extendedprice#X, l_discount#X, s_nationkey#X] +Input [6]: [c_nationkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X, s_suppkey#X, s_nationkey#X] + +(49) WholeStageCodegenTransformer (X) +Input [4]: [hash_partition_key#X, l_extendedprice#X, l_discount#X, s_nationkey#X] +Arguments: false + +(50) ColumnarExchange +Input [4]: [hash_partition_key#X, l_extendedprice#X, l_discount#X, s_nationkey#X] +Arguments: hashpartitioning(s_nationkey#X, 1), ENSURE_REQUIREMENTS, [l_extendedprice#X, l_discount#X, s_nationkey#X], [plan_id=X], [id=#X] + +(51) ShuffleQueryStage +Output [3]: [l_extendedprice#X, l_discount#X, s_nationkey#X] +Arguments: X + +(52) InputAdapter +Input [3]: [l_extendedprice#X, l_discount#X, s_nationkey#X] + +(53) InputIteratorTransformer +Input [3]: [l_extendedprice#X, l_discount#X, s_nationkey#X] + +(54) Scan parquet +Output [3]: [n_nationkey#X, n_name#X, n_regionkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_nationkey), IsNotNull(n_regionkey)] +ReadSchema: struct + +(55) FilterExecTransformer +Input [3]: [n_nationkey#X, n_name#X, n_regionkey#X] +Arguments: (isnotnull(n_nationkey#X) AND isnotnull(n_regionkey#X)) + +(56) ProjectExecTransformer +Output [4]: [hash(n_nationkey#X, 42) AS hash_partition_key#X, n_nationkey#X, n_name#X, n_regionkey#X] +Input [3]: [n_nationkey#X, n_name#X, n_regionkey#X] + +(57) WholeStageCodegenTransformer (X) +Input [4]: [hash_partition_key#X, n_nationkey#X, n_name#X, n_regionkey#X] +Arguments: false + +(58) ColumnarExchange +Input [4]: [hash_partition_key#X, n_nationkey#X, n_name#X, n_regionkey#X] +Arguments: hashpartitioning(n_nationkey#X, 1), ENSURE_REQUIREMENTS, [n_nationkey#X, n_name#X, n_regionkey#X], [plan_id=X], [id=#X] + +(59) ShuffleQueryStage +Output [3]: [n_nationkey#X, n_name#X, n_regionkey#X] +Arguments: X + +(60) InputAdapter +Input [3]: [n_nationkey#X, n_name#X, n_regionkey#X] + +(61) InputIteratorTransformer +Input [3]: [n_nationkey#X, n_name#X, n_regionkey#X] + +(62) ShuffledHashJoinExecTransformer +Left keys [1]: [s_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: None + +(63) ProjectExecTransformer +Output [5]: [hash(n_regionkey#X, 42) AS hash_partition_key#X, l_extendedprice#X, l_discount#X, n_name#X, n_regionkey#X] +Input [6]: [l_extendedprice#X, l_discount#X, s_nationkey#X, n_nationkey#X, n_name#X, n_regionkey#X] + +(64) WholeStageCodegenTransformer (X) +Input [5]: [hash_partition_key#X, l_extendedprice#X, l_discount#X, n_name#X, n_regionkey#X] +Arguments: false + +(65) ColumnarExchange +Input [5]: [hash_partition_key#X, l_extendedprice#X, l_discount#X, n_name#X, n_regionkey#X] +Arguments: hashpartitioning(n_regionkey#X, 1), ENSURE_REQUIREMENTS, [l_extendedprice#X, l_discount#X, n_name#X, n_regionkey#X], [plan_id=X], [id=#X] + +(66) ShuffleQueryStage +Output [4]: [l_extendedprice#X, l_discount#X, n_name#X, n_regionkey#X] +Arguments: X + +(67) InputAdapter +Input [4]: [l_extendedprice#X, l_discount#X, n_name#X, n_regionkey#X] + +(68) InputIteratorTransformer +Input [4]: [l_extendedprice#X, l_discount#X, n_name#X, n_regionkey#X] + +(69) Scan parquet +Output [2]: [r_regionkey#X, r_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(r_name), EqualTo(r_name,ASIA), IsNotNull(r_regionkey)] +ReadSchema: struct + +(70) FilterExecTransformer +Input [2]: [r_regionkey#X, r_name#X] +Arguments: ((isnotnull(r_name#X) AND (r_name#X = ASIA)) AND isnotnull(r_regionkey#X)) + +(71) ProjectExecTransformer +Output [2]: [hash(r_regionkey#X, 42) AS hash_partition_key#X, r_regionkey#X] +Input [2]: [r_regionkey#X, r_name#X] + +(72) WholeStageCodegenTransformer (X) +Input [2]: [hash_partition_key#X, r_regionkey#X] +Arguments: false + +(73) ColumnarExchange +Input [2]: [hash_partition_key#X, r_regionkey#X] +Arguments: hashpartitioning(r_regionkey#X, 1), ENSURE_REQUIREMENTS, [r_regionkey#X], [plan_id=X], [id=#X] + +(74) ShuffleQueryStage +Output [1]: [r_regionkey#X] +Arguments: X + +(75) InputAdapter +Input [1]: [r_regionkey#X] + +(76) InputIteratorTransformer +Input [1]: [r_regionkey#X] + +(77) ShuffledHashJoinExecTransformer +Left keys [1]: [n_regionkey#X] +Right keys [1]: [r_regionkey#X] +Join condition: None + +(78) ProjectExecTransformer +Output [4]: [l_extendedprice#X, l_discount#X, n_name#X, CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) AS _pre_111#X] +Input [5]: [l_extendedprice#X, l_discount#X, n_name#X, n_regionkey#X, r_regionkey#X] + +(79) FlushableHashAggregateExecTransformer +Input [4]: [l_extendedprice#X, l_discount#X, n_name#X, _pre_111#X] +Keys [1]: [n_name#X] +Functions [1]: [partial_sum(_pre_111#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [3]: [n_name#X, sum#X, isEmpty#X] + +(80) ProjectExecTransformer +Output [4]: [hash(n_name#X, 42) AS hash_partition_key#X, n_name#X, sum#X, isEmpty#X] +Input [3]: [n_name#X, sum#X, isEmpty#X] + +(81) WholeStageCodegenTransformer (X) +Input [4]: [hash_partition_key#X, n_name#X, sum#X, isEmpty#X] +Arguments: false + +(82) ColumnarExchange +Input [4]: [hash_partition_key#X, n_name#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(n_name#X, 1), ENSURE_REQUIREMENTS, [n_name#X, sum#X, isEmpty#X], [plan_id=X], [id=#X] + +(83) ShuffleQueryStage +Output [3]: [n_name#X, sum#X, isEmpty#X] +Arguments: X + +(84) InputAdapter +Input [3]: [n_name#X, sum#X, isEmpty#X] + +(85) InputIteratorTransformer +Input [3]: [n_name#X, sum#X, isEmpty#X] + +(86) RegularHashAggregateExecTransformer +Input [3]: [n_name#X, sum#X, isEmpty#X] +Keys [1]: [n_name#X] +Functions [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))] +Aggregate Attributes [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X] +Results [2]: [n_name#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X AS revenue#X] + +(87) WholeStageCodegenTransformer (X) +Input [2]: [n_name#X, revenue#X] +Arguments: false + +(88) ColumnarExchange +Input [2]: [n_name#X, revenue#X] +Arguments: rangepartitioning(revenue#X DESC NULLS LAST, 1), ENSURE_REQUIREMENTS, [plan_id=X], [id=#X] + +(89) ShuffleQueryStage +Output [2]: [n_name#X, revenue#X] +Arguments: X + +(90) InputAdapter +Input [2]: [n_name#X, revenue#X] + +(91) InputIteratorTransformer +Input [2]: [n_name#X, revenue#X] + +(92) SortExecTransformer +Input [2]: [n_name#X, revenue#X] +Arguments: [revenue#X DESC NULLS LAST], true, 0 + +(93) WholeStageCodegenTransformer (X) +Input [2]: [n_name#X, revenue#X] +Arguments: false + +(94) VeloxColumnarToRowExec +Input [2]: [n_name#X, revenue#X] + +(95) Scan parquet +Output [2]: [c_custkey#X, c_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(c_custkey), IsNotNull(c_nationkey)] +ReadSchema: struct + +(96) Filter +Input [2]: [c_custkey#X, c_nationkey#X] +Condition : (isnotnull(c_custkey#X) AND isnotnull(c_nationkey#X)) + +(97) Exchange +Input [2]: [c_custkey#X, c_nationkey#X] +Arguments: hashpartitioning(c_custkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(98) Scan parquet +Output [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_orderdate), GreaterThanOrEqual(o_orderdate,1994-01-01), LessThan(o_orderdate,1995-01-01), IsNotNull(o_custkey), IsNotNull(o_orderkey)] +ReadSchema: struct + +(99) Filter +Input [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] +Condition : ((((isnotnull(o_orderdate#X) AND (o_orderdate#X >= 1994-01-01)) AND (o_orderdate#X < 1995-01-01)) AND isnotnull(o_custkey#X)) AND isnotnull(o_orderkey#X)) + +(100) Project +Output [2]: [o_orderkey#X, o_custkey#X] +Input [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] + +(101) Exchange +Input [2]: [o_orderkey#X, o_custkey#X] +Arguments: hashpartitioning(o_custkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(102) ShuffledHashJoin +Left keys [1]: [c_custkey#X] +Right keys [1]: [o_custkey#X] +Join condition: None + +(103) Project +Output [2]: [c_nationkey#X, o_orderkey#X] +Input [4]: [c_custkey#X, c_nationkey#X, o_orderkey#X, o_custkey#X] + +(104) Exchange +Input [2]: [c_nationkey#X, o_orderkey#X] +Arguments: hashpartitioning(o_orderkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(105) Scan parquet +Output [4]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_orderkey), IsNotNull(l_suppkey)] +ReadSchema: struct + +(106) Filter +Input [4]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Condition : (isnotnull(l_orderkey#X) AND isnotnull(l_suppkey#X)) + +(107) Exchange +Input [4]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Arguments: hashpartitioning(l_orderkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(108) ShuffledHashJoin +Left keys [1]: [o_orderkey#X] +Right keys [1]: [l_orderkey#X] +Join condition: None + +(109) Project +Output [4]: [c_nationkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Input [6]: [c_nationkey#X, o_orderkey#X, l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] + +(110) Exchange +Input [4]: [c_nationkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Arguments: hashpartitioning(l_suppkey#X, c_nationkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(111) Scan parquet +Output [2]: [s_suppkey#X, s_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(s_suppkey), IsNotNull(s_nationkey)] +ReadSchema: struct + +(112) Filter +Input [2]: [s_suppkey#X, s_nationkey#X] +Condition : (isnotnull(s_suppkey#X) AND isnotnull(s_nationkey#X)) + +(113) Exchange +Input [2]: [s_suppkey#X, s_nationkey#X] +Arguments: hashpartitioning(s_suppkey#X, s_nationkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(114) ShuffledHashJoin +Left keys [2]: [l_suppkey#X, c_nationkey#X] +Right keys [2]: [s_suppkey#X, s_nationkey#X] +Join condition: None + +(115) Project +Output [3]: [l_extendedprice#X, l_discount#X, s_nationkey#X] +Input [6]: [c_nationkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X, s_suppkey#X, s_nationkey#X] + +(116) Exchange +Input [3]: [l_extendedprice#X, l_discount#X, s_nationkey#X] +Arguments: hashpartitioning(s_nationkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(117) Scan parquet +Output [3]: [n_nationkey#X, n_name#X, n_regionkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_nationkey), IsNotNull(n_regionkey)] +ReadSchema: struct + +(118) Filter +Input [3]: [n_nationkey#X, n_name#X, n_regionkey#X] +Condition : (isnotnull(n_nationkey#X) AND isnotnull(n_regionkey#X)) + +(119) Exchange +Input [3]: [n_nationkey#X, n_name#X, n_regionkey#X] +Arguments: hashpartitioning(n_nationkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(120) ShuffledHashJoin +Left keys [1]: [s_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: None + +(121) Project +Output [4]: [l_extendedprice#X, l_discount#X, n_name#X, n_regionkey#X] +Input [6]: [l_extendedprice#X, l_discount#X, s_nationkey#X, n_nationkey#X, n_name#X, n_regionkey#X] + +(122) Exchange +Input [4]: [l_extendedprice#X, l_discount#X, n_name#X, n_regionkey#X] +Arguments: hashpartitioning(n_regionkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(123) Scan parquet +Output [2]: [r_regionkey#X, r_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(r_name), EqualTo(r_name,ASIA), IsNotNull(r_regionkey)] +ReadSchema: struct + +(124) Filter +Input [2]: [r_regionkey#X, r_name#X] +Condition : ((isnotnull(r_name#X) AND (r_name#X = ASIA)) AND isnotnull(r_regionkey#X)) + +(125) Project +Output [1]: [r_regionkey#X] +Input [2]: [r_regionkey#X, r_name#X] + +(126) Exchange +Input [1]: [r_regionkey#X] +Arguments: hashpartitioning(r_regionkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(127) ShuffledHashJoin +Left keys [1]: [n_regionkey#X] +Right keys [1]: [r_regionkey#X] +Join condition: None + +(128) Project +Output [3]: [l_extendedprice#X, l_discount#X, n_name#X] +Input [5]: [l_extendedprice#X, l_discount#X, n_name#X, n_regionkey#X, r_regionkey#X] + +(129) HashAggregate +Input [3]: [l_extendedprice#X, l_discount#X, n_name#X] +Keys [1]: [n_name#X] +Functions [1]: [partial_sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [3]: [n_name#X, sum#X, isEmpty#X] + +(130) Exchange +Input [3]: [n_name#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(n_name#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(131) HashAggregate +Input [3]: [n_name#X, sum#X, isEmpty#X] +Keys [1]: [n_name#X] +Functions [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))] +Aggregate Attributes [1]: [sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X] +Results [2]: [n_name#X, sum(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true))#X AS revenue#X] + +(132) Exchange +Input [2]: [n_name#X, revenue#X] +Arguments: rangepartitioning(revenue#X DESC NULLS LAST, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(133) Sort +Input [2]: [n_name#X, revenue#X] +Arguments: [revenue#X DESC NULLS LAST], true, 0 + +(134) AdaptiveSparkPlan +Output [2]: [n_name#X, revenue#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/6.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/6.txt new file mode 100644 index 000000000000..ad916942a2df --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/6.txt @@ -0,0 +1,112 @@ +== Physical Plan == +AdaptiveSparkPlan (19) ++- == Final Plan == + VeloxColumnarToRowExec (12) + +- ^ RegularHashAggregateExecTransformer (10) + +- ^ InputIteratorTransformer (9) + +- ^ InputAdapter (8) + +- ^ ShuffleQueryStage (7) + +- ColumnarExchange (6) + +- ^ FlushableHashAggregateExecTransformer (4) + +- ^ ProjectExecTransformer (3) + +- ^ FilterExecTransformer (2) + +- ^ Scan parquet (1) ++- == Initial Plan == + HashAggregate (18) + +- Exchange (17) + +- HashAggregate (16) + +- Project (15) + +- Filter (14) + +- Scan parquet (13) + + +(1) Scan parquet +Output [4]: [l_quantity#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_shipdate), IsNotNull(l_discount), IsNotNull(l_quantity), GreaterThanOrEqual(l_shipdate,1994-01-01), LessThan(l_shipdate,1995-01-01), GreaterThanOrEqual(l_discount,0.05), LessThanOrEqual(l_discount,0.07), LessThan(l_quantity,24.00)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [4]: [l_quantity#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Arguments: (((((((isnotnull(l_shipdate#X) AND isnotnull(l_discount#X)) AND isnotnull(l_quantity#X)) AND (l_shipdate#X >= 1994-01-01)) AND (l_shipdate#X < 1995-01-01)) AND (l_discount#X >= 0.05)) AND (l_discount#X <= 0.07)) AND (l_quantity#X < 24.00)) + +(3) ProjectExecTransformer +Output [3]: [l_extendedprice#X, l_discount#X, CheckOverflow((promote_precision(l_extendedprice#X) * promote_precision(l_discount#X)), DecimalType(25,4), true) AS _pre_112#X] +Input [4]: [l_quantity#X, l_extendedprice#X, l_discount#X, l_shipdate#X] + +(4) FlushableHashAggregateExecTransformer +Input [3]: [l_extendedprice#X, l_discount#X, _pre_112#X] +Keys: [] +Functions [1]: [partial_sum(_pre_112#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [2]: [sum#X, isEmpty#X] + +(5) WholeStageCodegenTransformer (X) +Input [2]: [sum#X, isEmpty#X] +Arguments: false + +(6) ColumnarExchange +Input [2]: [sum#X, isEmpty#X] +Arguments: SinglePartition, ENSURE_REQUIREMENTS, [plan_id=X], [id=#X] + +(7) ShuffleQueryStage +Output [2]: [sum#X, isEmpty#X] +Arguments: X + +(8) InputAdapter +Input [2]: [sum#X, isEmpty#X] + +(9) InputIteratorTransformer +Input [2]: [sum#X, isEmpty#X] + +(10) RegularHashAggregateExecTransformer +Input [2]: [sum#X, isEmpty#X] +Keys: [] +Functions [1]: [sum(CheckOverflow((promote_precision(l_extendedprice#X) * promote_precision(l_discount#X)), DecimalType(25,4), true))] +Aggregate Attributes [1]: [sum(CheckOverflow((promote_precision(l_extendedprice#X) * promote_precision(l_discount#X)), DecimalType(25,4), true))#X] +Results [1]: [sum(CheckOverflow((promote_precision(l_extendedprice#X) * promote_precision(l_discount#X)), DecimalType(25,4), true))#X AS revenue#X] + +(11) WholeStageCodegenTransformer (X) +Input [1]: [revenue#X] +Arguments: false + +(12) VeloxColumnarToRowExec +Input [1]: [revenue#X] + +(13) Scan parquet +Output [4]: [l_quantity#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_shipdate), IsNotNull(l_discount), IsNotNull(l_quantity), GreaterThanOrEqual(l_shipdate,1994-01-01), LessThan(l_shipdate,1995-01-01), GreaterThanOrEqual(l_discount,0.05), LessThanOrEqual(l_discount,0.07), LessThan(l_quantity,24.00)] +ReadSchema: struct + +(14) Filter +Input [4]: [l_quantity#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Condition : (((((((isnotnull(l_shipdate#X) AND isnotnull(l_discount#X)) AND isnotnull(l_quantity#X)) AND (l_shipdate#X >= 1994-01-01)) AND (l_shipdate#X < 1995-01-01)) AND (l_discount#X >= 0.05)) AND (l_discount#X <= 0.07)) AND (l_quantity#X < 24.00)) + +(15) Project +Output [2]: [l_extendedprice#X, l_discount#X] +Input [4]: [l_quantity#X, l_extendedprice#X, l_discount#X, l_shipdate#X] + +(16) HashAggregate +Input [2]: [l_extendedprice#X, l_discount#X] +Keys: [] +Functions [1]: [partial_sum(CheckOverflow((promote_precision(l_extendedprice#X) * promote_precision(l_discount#X)), DecimalType(25,4), true))] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [2]: [sum#X, isEmpty#X] + +(17) Exchange +Input [2]: [sum#X, isEmpty#X] +Arguments: SinglePartition, ENSURE_REQUIREMENTS, [plan_id=X] + +(18) HashAggregate +Input [2]: [sum#X, isEmpty#X] +Keys: [] +Functions [1]: [sum(CheckOverflow((promote_precision(l_extendedprice#X) * promote_precision(l_discount#X)), DecimalType(25,4), true))] +Aggregate Attributes [1]: [sum(CheckOverflow((promote_precision(l_extendedprice#X) * promote_precision(l_discount#X)), DecimalType(25,4), true))#X] +Results [1]: [sum(CheckOverflow((promote_precision(l_extendedprice#X) * promote_precision(l_discount#X)), DecimalType(25,4), true))#X AS revenue#X] + +(19) AdaptiveSparkPlan +Output [1]: [revenue#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/7.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/7.txt new file mode 100644 index 000000000000..9cf916718039 --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/7.txt @@ -0,0 +1,661 @@ +== Physical Plan == +AdaptiveSparkPlan (128) ++- == Final Plan == + VeloxColumnarToRowExec (90) + +- ^ SortExecTransformer (88) + +- ^ InputIteratorTransformer (87) + +- ^ InputAdapter (86) + +- ^ ShuffleQueryStage (85) + +- ColumnarExchange (84) + +- ^ RegularHashAggregateExecTransformer (82) + +- ^ InputIteratorTransformer (81) + +- ^ InputAdapter (80) + +- ^ ShuffleQueryStage (79) + +- ColumnarExchange (78) + +- ^ ProjectExecTransformer (76) + +- ^ FlushableHashAggregateExecTransformer (75) + +- ^ ProjectExecTransformer (74) + +- ^ ShuffledHashJoinExecTransformer Inner (73) + :- ^ InputIteratorTransformer (68) + : +- ^ InputAdapter (67) + : +- ^ ShuffleQueryStage (66) + : +- ColumnarExchange (65) + : +- ^ ProjectExecTransformer (63) + : +- ^ ShuffledHashJoinExecTransformer Inner (62) + : :- ^ InputIteratorTransformer (53) + : : +- ^ InputAdapter (52) + : : +- ^ ShuffleQueryStage (51) + : : +- ColumnarExchange (50) + : : +- ^ ProjectExecTransformer (48) + : : +- ^ ShuffledHashJoinExecTransformer Inner (47) + : : :- ^ InputIteratorTransformer (38) + : : : +- ^ InputAdapter (37) + : : : +- ^ ShuffleQueryStage (36) + : : : +- ColumnarExchange (35) + : : : +- ^ ProjectExecTransformer (33) + : : : +- ^ ShuffledHashJoinExecTransformer Inner (32) + : : : :- ^ InputIteratorTransformer (23) + : : : : +- ^ InputAdapter (22) + : : : : +- ^ ShuffleQueryStage (21) + : : : : +- ColumnarExchange (20) + : : : : +- ^ ProjectExecTransformer (18) + : : : : +- ^ ShuffledHashJoinExecTransformer Inner (17) + : : : : :- ^ InputIteratorTransformer (8) + : : : : : +- ^ InputAdapter (7) + : : : : : +- ^ ShuffleQueryStage (6) + : : : : : +- ColumnarExchange (5) + : : : : : +- ^ ProjectExecTransformer (3) + : : : : : +- ^ FilterExecTransformer (2) + : : : : : +- ^ Scan parquet (1) + : : : : +- ^ InputIteratorTransformer (16) + : : : : +- ^ InputAdapter (15) + : : : : +- ^ ShuffleQueryStage (14) + : : : : +- ColumnarExchange (13) + : : : : +- ^ ProjectExecTransformer (11) + : : : : +- ^ FilterExecTransformer (10) + : : : : +- ^ Scan parquet (9) + : : : +- ^ InputIteratorTransformer (31) + : : : +- ^ InputAdapter (30) + : : : +- ^ ShuffleQueryStage (29) + : : : +- ColumnarExchange (28) + : : : +- ^ ProjectExecTransformer (26) + : : : +- ^ FilterExecTransformer (25) + : : : +- ^ Scan parquet (24) + : : +- ^ InputIteratorTransformer (46) + : : +- ^ InputAdapter (45) + : : +- ^ ShuffleQueryStage (44) + : : +- ColumnarExchange (43) + : : +- ^ ProjectExecTransformer (41) + : : +- ^ FilterExecTransformer (40) + : : +- ^ Scan parquet (39) + : +- ^ InputIteratorTransformer (61) + : +- ^ InputAdapter (60) + : +- ^ ShuffleQueryStage (59) + : +- ColumnarExchange (58) + : +- ^ ProjectExecTransformer (56) + : +- ^ FilterExecTransformer (55) + : +- ^ Scan parquet (54) + +- ^ InputIteratorTransformer (72) + +- ^ InputAdapter (71) + +- ^ ShuffleQueryStage (70) + +- ReusedExchange (69) ++- == Initial Plan == + Sort (127) + +- Exchange (126) + +- HashAggregate (125) + +- Exchange (124) + +- HashAggregate (123) + +- Project (122) + +- ShuffledHashJoin Inner BuildRight (121) + :- Exchange (117) + : +- Project (116) + : +- ShuffledHashJoin Inner BuildRight (115) + : :- Exchange (111) + : : +- Project (110) + : : +- ShuffledHashJoin Inner BuildRight (109) + : : :- Exchange (105) + : : : +- Project (104) + : : : +- ShuffledHashJoin Inner BuildRight (103) + : : : :- Exchange (99) + : : : : +- Project (98) + : : : : +- ShuffledHashJoin Inner BuildLeft (97) + : : : : :- Exchange (93) + : : : : : +- Filter (92) + : : : : : +- Scan parquet (91) + : : : : +- Exchange (96) + : : : : +- Filter (95) + : : : : +- Scan parquet (94) + : : : +- Exchange (102) + : : : +- Filter (101) + : : : +- Scan parquet (100) + : : +- Exchange (108) + : : +- Filter (107) + : : +- Scan parquet (106) + : +- Exchange (114) + : +- Filter (113) + : +- Scan parquet (112) + +- Exchange (120) + +- Filter (119) + +- Scan parquet (118) + + +(1) Scan parquet +Output [2]: [s_suppkey#X, s_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(s_suppkey), IsNotNull(s_nationkey)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [2]: [s_suppkey#X, s_nationkey#X] +Arguments: (isnotnull(s_suppkey#X) AND isnotnull(s_nationkey#X)) + +(3) ProjectExecTransformer +Output [3]: [hash(s_suppkey#X, 42) AS hash_partition_key#X, s_suppkey#X, s_nationkey#X] +Input [2]: [s_suppkey#X, s_nationkey#X] + +(4) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, s_suppkey#X, s_nationkey#X] +Arguments: false + +(5) ColumnarExchange +Input [3]: [hash_partition_key#X, s_suppkey#X, s_nationkey#X] +Arguments: hashpartitioning(s_suppkey#X, 1), ENSURE_REQUIREMENTS, [s_suppkey#X, s_nationkey#X], [plan_id=X], [id=#X] + +(6) ShuffleQueryStage +Output [2]: [s_suppkey#X, s_nationkey#X] +Arguments: X + +(7) InputAdapter +Input [2]: [s_suppkey#X, s_nationkey#X] + +(8) InputIteratorTransformer +Input [2]: [s_suppkey#X, s_nationkey#X] + +(9) Scan parquet +Output [5]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_shipdate), GreaterThanOrEqual(l_shipdate,1995-01-01), LessThanOrEqual(l_shipdate,1996-12-31), IsNotNull(l_suppkey), IsNotNull(l_orderkey)] +ReadSchema: struct + +(10) FilterExecTransformer +Input [5]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Arguments: ((((isnotnull(l_shipdate#X) AND (l_shipdate#X >= 1995-01-01)) AND (l_shipdate#X <= 1996-12-31)) AND isnotnull(l_suppkey#X)) AND isnotnull(l_orderkey#X)) + +(11) ProjectExecTransformer +Output [6]: [hash(l_suppkey#X, 42) AS hash_partition_key#X, l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Input [5]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] + +(12) WholeStageCodegenTransformer (X) +Input [6]: [hash_partition_key#X, l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Arguments: false + +(13) ColumnarExchange +Input [6]: [hash_partition_key#X, l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Arguments: hashpartitioning(l_suppkey#X, 1), ENSURE_REQUIREMENTS, [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X], [plan_id=X], [id=#X] + +(14) ShuffleQueryStage +Output [5]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Arguments: X + +(15) InputAdapter +Input [5]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] + +(16) InputIteratorTransformer +Input [5]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] + +(17) ShuffledHashJoinExecTransformer +Left keys [1]: [s_suppkey#X] +Right keys [1]: [l_suppkey#X] +Join condition: None + +(18) ProjectExecTransformer +Output [6]: [hash(l_orderkey#X, 42) AS hash_partition_key#X, s_nationkey#X, l_orderkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Input [7]: [s_suppkey#X, s_nationkey#X, l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] + +(19) WholeStageCodegenTransformer (X) +Input [6]: [hash_partition_key#X, s_nationkey#X, l_orderkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Arguments: false + +(20) ColumnarExchange +Input [6]: [hash_partition_key#X, s_nationkey#X, l_orderkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Arguments: hashpartitioning(l_orderkey#X, 1), ENSURE_REQUIREMENTS, [s_nationkey#X, l_orderkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X], [plan_id=X], [id=#X] + +(21) ShuffleQueryStage +Output [5]: [s_nationkey#X, l_orderkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Arguments: X + +(22) InputAdapter +Input [5]: [s_nationkey#X, l_orderkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] + +(23) InputIteratorTransformer +Input [5]: [s_nationkey#X, l_orderkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] + +(24) Scan parquet +Output [2]: [o_orderkey#X, o_custkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_orderkey), IsNotNull(o_custkey)] +ReadSchema: struct + +(25) FilterExecTransformer +Input [2]: [o_orderkey#X, o_custkey#X] +Arguments: (isnotnull(o_orderkey#X) AND isnotnull(o_custkey#X)) + +(26) ProjectExecTransformer +Output [3]: [hash(o_orderkey#X, 42) AS hash_partition_key#X, o_orderkey#X, o_custkey#X] +Input [2]: [o_orderkey#X, o_custkey#X] + +(27) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, o_orderkey#X, o_custkey#X] +Arguments: false + +(28) ColumnarExchange +Input [3]: [hash_partition_key#X, o_orderkey#X, o_custkey#X] +Arguments: hashpartitioning(o_orderkey#X, 1), ENSURE_REQUIREMENTS, [o_orderkey#X, o_custkey#X], [plan_id=X], [id=#X] + +(29) ShuffleQueryStage +Output [2]: [o_orderkey#X, o_custkey#X] +Arguments: X + +(30) InputAdapter +Input [2]: [o_orderkey#X, o_custkey#X] + +(31) InputIteratorTransformer +Input [2]: [o_orderkey#X, o_custkey#X] + +(32) ShuffledHashJoinExecTransformer +Left keys [1]: [l_orderkey#X] +Right keys [1]: [o_orderkey#X] +Join condition: None + +(33) ProjectExecTransformer +Output [6]: [hash(o_custkey#X, 42) AS hash_partition_key#X, s_nationkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X, o_custkey#X] +Input [7]: [s_nationkey#X, l_orderkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X, o_orderkey#X, o_custkey#X] + +(34) WholeStageCodegenTransformer (X) +Input [6]: [hash_partition_key#X, s_nationkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X, o_custkey#X] +Arguments: false + +(35) ColumnarExchange +Input [6]: [hash_partition_key#X, s_nationkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X, o_custkey#X] +Arguments: hashpartitioning(o_custkey#X, 1), ENSURE_REQUIREMENTS, [s_nationkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X, o_custkey#X], [plan_id=X], [id=#X] + +(36) ShuffleQueryStage +Output [5]: [s_nationkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X, o_custkey#X] +Arguments: X + +(37) InputAdapter +Input [5]: [s_nationkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X, o_custkey#X] + +(38) InputIteratorTransformer +Input [5]: [s_nationkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X, o_custkey#X] + +(39) Scan parquet +Output [2]: [c_custkey#X, c_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(c_custkey), IsNotNull(c_nationkey)] +ReadSchema: struct + +(40) FilterExecTransformer +Input [2]: [c_custkey#X, c_nationkey#X] +Arguments: (isnotnull(c_custkey#X) AND isnotnull(c_nationkey#X)) + +(41) ProjectExecTransformer +Output [3]: [hash(c_custkey#X, 42) AS hash_partition_key#X, c_custkey#X, c_nationkey#X] +Input [2]: [c_custkey#X, c_nationkey#X] + +(42) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, c_custkey#X, c_nationkey#X] +Arguments: false + +(43) ColumnarExchange +Input [3]: [hash_partition_key#X, c_custkey#X, c_nationkey#X] +Arguments: hashpartitioning(c_custkey#X, 1), ENSURE_REQUIREMENTS, [c_custkey#X, c_nationkey#X], [plan_id=X], [id=#X] + +(44) ShuffleQueryStage +Output [2]: [c_custkey#X, c_nationkey#X] +Arguments: X + +(45) InputAdapter +Input [2]: [c_custkey#X, c_nationkey#X] + +(46) InputIteratorTransformer +Input [2]: [c_custkey#X, c_nationkey#X] + +(47) ShuffledHashJoinExecTransformer +Left keys [1]: [o_custkey#X] +Right keys [1]: [c_custkey#X] +Join condition: None + +(48) ProjectExecTransformer +Output [6]: [hash(s_nationkey#X, 42) AS hash_partition_key#X, s_nationkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X, c_nationkey#X] +Input [7]: [s_nationkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X, o_custkey#X, c_custkey#X, c_nationkey#X] + +(49) WholeStageCodegenTransformer (X) +Input [6]: [hash_partition_key#X, s_nationkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X, c_nationkey#X] +Arguments: false + +(50) ColumnarExchange +Input [6]: [hash_partition_key#X, s_nationkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X, c_nationkey#X] +Arguments: hashpartitioning(s_nationkey#X, 1), ENSURE_REQUIREMENTS, [s_nationkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X, c_nationkey#X], [plan_id=X], [id=#X] + +(51) ShuffleQueryStage +Output [5]: [s_nationkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X, c_nationkey#X] +Arguments: X + +(52) InputAdapter +Input [5]: [s_nationkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X, c_nationkey#X] + +(53) InputIteratorTransformer +Input [5]: [s_nationkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X, c_nationkey#X] + +(54) Scan parquet +Output [2]: [n_nationkey#X, n_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_nationkey), Or(EqualTo(n_name,FRANCE),EqualTo(n_name,GERMANY))] +ReadSchema: struct + +(55) FilterExecTransformer +Input [2]: [n_nationkey#X, n_name#X] +Arguments: (isnotnull(n_nationkey#X) AND ((n_name#X = FRANCE) OR (n_name#X = GERMANY))) + +(56) ProjectExecTransformer +Output [3]: [hash(n_nationkey#X, 42) AS hash_partition_key#X, n_nationkey#X, n_name#X] +Input [2]: [n_nationkey#X, n_name#X] + +(57) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, n_nationkey#X, n_name#X] +Arguments: false + +(58) ColumnarExchange +Input [3]: [hash_partition_key#X, n_nationkey#X, n_name#X] +Arguments: hashpartitioning(n_nationkey#X, 1), ENSURE_REQUIREMENTS, [n_nationkey#X, n_name#X], [plan_id=X], [id=#X] + +(59) ShuffleQueryStage +Output [2]: [n_nationkey#X, n_name#X] +Arguments: X + +(60) InputAdapter +Input [2]: [n_nationkey#X, n_name#X] + +(61) InputIteratorTransformer +Input [2]: [n_nationkey#X, n_name#X] + +(62) ShuffledHashJoinExecTransformer +Left keys [1]: [s_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: None + +(63) ProjectExecTransformer +Output [6]: [hash(c_nationkey#X, 42) AS hash_partition_key#X, l_extendedprice#X, l_discount#X, l_shipdate#X, c_nationkey#X, n_name#X] +Input [7]: [s_nationkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X, c_nationkey#X, n_nationkey#X, n_name#X] + +(64) WholeStageCodegenTransformer (X) +Input [6]: [hash_partition_key#X, l_extendedprice#X, l_discount#X, l_shipdate#X, c_nationkey#X, n_name#X] +Arguments: false + +(65) ColumnarExchange +Input [6]: [hash_partition_key#X, l_extendedprice#X, l_discount#X, l_shipdate#X, c_nationkey#X, n_name#X] +Arguments: hashpartitioning(c_nationkey#X, 1), ENSURE_REQUIREMENTS, [l_extendedprice#X, l_discount#X, l_shipdate#X, c_nationkey#X, n_name#X], [plan_id=X], [id=#X] + +(66) ShuffleQueryStage +Output [5]: [l_extendedprice#X, l_discount#X, l_shipdate#X, c_nationkey#X, n_name#X] +Arguments: X + +(67) InputAdapter +Input [5]: [l_extendedprice#X, l_discount#X, l_shipdate#X, c_nationkey#X, n_name#X] + +(68) InputIteratorTransformer +Input [5]: [l_extendedprice#X, l_discount#X, l_shipdate#X, c_nationkey#X, n_name#X] + +(69) ReusedExchange [Reuses operator id: 58] +Output [2]: [n_nationkey#X, n_name#X] + +(70) ShuffleQueryStage +Output [2]: [n_nationkey#X, n_name#X] +Arguments: X + +(71) InputAdapter +Input [2]: [n_nationkey#X, n_name#X] + +(72) InputIteratorTransformer +Input [2]: [n_nationkey#X, n_name#X] + +(73) ShuffledHashJoinExecTransformer +Left keys [1]: [c_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: (((n_name#X = FRANCE) AND (n_name#X = GERMANY)) OR ((n_name#X = GERMANY) AND (n_name#X = FRANCE))) + +(74) ProjectExecTransformer +Output [4]: [n_name#X AS supp_nation#X, n_name#X AS cust_nation#X, year(l_shipdate#X) AS l_year#X, CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) AS volume#X] +Input [7]: [l_extendedprice#X, l_discount#X, l_shipdate#X, c_nationkey#X, n_name#X, n_nationkey#X, n_name#X] + +(75) FlushableHashAggregateExecTransformer +Input [4]: [supp_nation#X, cust_nation#X, l_year#X, volume#X] +Keys [3]: [supp_nation#X, cust_nation#X, l_year#X] +Functions [1]: [partial_sum(volume#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [5]: [supp_nation#X, cust_nation#X, l_year#X, sum#X, isEmpty#X] + +(76) ProjectExecTransformer +Output [6]: [hash(supp_nation#X, cust_nation#X, l_year#X, 42) AS hash_partition_key#X, supp_nation#X, cust_nation#X, l_year#X, sum#X, isEmpty#X] +Input [5]: [supp_nation#X, cust_nation#X, l_year#X, sum#X, isEmpty#X] + +(77) WholeStageCodegenTransformer (X) +Input [6]: [hash_partition_key#X, supp_nation#X, cust_nation#X, l_year#X, sum#X, isEmpty#X] +Arguments: false + +(78) ColumnarExchange +Input [6]: [hash_partition_key#X, supp_nation#X, cust_nation#X, l_year#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(supp_nation#X, cust_nation#X, l_year#X, 1), ENSURE_REQUIREMENTS, [supp_nation#X, cust_nation#X, l_year#X, sum#X, isEmpty#X], [plan_id=X], [id=#X] + +(79) ShuffleQueryStage +Output [5]: [supp_nation#X, cust_nation#X, l_year#X, sum#X, isEmpty#X] +Arguments: X + +(80) InputAdapter +Input [5]: [supp_nation#X, cust_nation#X, l_year#X, sum#X, isEmpty#X] + +(81) InputIteratorTransformer +Input [5]: [supp_nation#X, cust_nation#X, l_year#X, sum#X, isEmpty#X] + +(82) RegularHashAggregateExecTransformer +Input [5]: [supp_nation#X, cust_nation#X, l_year#X, sum#X, isEmpty#X] +Keys [3]: [supp_nation#X, cust_nation#X, l_year#X] +Functions [1]: [sum(volume#X)] +Aggregate Attributes [1]: [sum(volume#X)#X] +Results [4]: [supp_nation#X, cust_nation#X, l_year#X, sum(volume#X)#X AS revenue#X] + +(83) WholeStageCodegenTransformer (X) +Input [4]: [supp_nation#X, cust_nation#X, l_year#X, revenue#X] +Arguments: false + +(84) ColumnarExchange +Input [4]: [supp_nation#X, cust_nation#X, l_year#X, revenue#X] +Arguments: rangepartitioning(supp_nation#X ASC NULLS FIRST, cust_nation#X ASC NULLS FIRST, l_year#X ASC NULLS FIRST, 1), ENSURE_REQUIREMENTS, [plan_id=X], [id=#X] + +(85) ShuffleQueryStage +Output [4]: [supp_nation#X, cust_nation#X, l_year#X, revenue#X] +Arguments: X + +(86) InputAdapter +Input [4]: [supp_nation#X, cust_nation#X, l_year#X, revenue#X] + +(87) InputIteratorTransformer +Input [4]: [supp_nation#X, cust_nation#X, l_year#X, revenue#X] + +(88) SortExecTransformer +Input [4]: [supp_nation#X, cust_nation#X, l_year#X, revenue#X] +Arguments: [supp_nation#X ASC NULLS FIRST, cust_nation#X ASC NULLS FIRST, l_year#X ASC NULLS FIRST], true, 0 + +(89) WholeStageCodegenTransformer (X) +Input [4]: [supp_nation#X, cust_nation#X, l_year#X, revenue#X] +Arguments: false + +(90) VeloxColumnarToRowExec +Input [4]: [supp_nation#X, cust_nation#X, l_year#X, revenue#X] + +(91) Scan parquet +Output [2]: [s_suppkey#X, s_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(s_suppkey), IsNotNull(s_nationkey)] +ReadSchema: struct + +(92) Filter +Input [2]: [s_suppkey#X, s_nationkey#X] +Condition : (isnotnull(s_suppkey#X) AND isnotnull(s_nationkey#X)) + +(93) Exchange +Input [2]: [s_suppkey#X, s_nationkey#X] +Arguments: hashpartitioning(s_suppkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(94) Scan parquet +Output [5]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_shipdate), GreaterThanOrEqual(l_shipdate,1995-01-01), LessThanOrEqual(l_shipdate,1996-12-31), IsNotNull(l_suppkey), IsNotNull(l_orderkey)] +ReadSchema: struct + +(95) Filter +Input [5]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Condition : ((((isnotnull(l_shipdate#X) AND (l_shipdate#X >= 1995-01-01)) AND (l_shipdate#X <= 1996-12-31)) AND isnotnull(l_suppkey#X)) AND isnotnull(l_orderkey#X)) + +(96) Exchange +Input [5]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Arguments: hashpartitioning(l_suppkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(97) ShuffledHashJoin +Left keys [1]: [s_suppkey#X] +Right keys [1]: [l_suppkey#X] +Join condition: None + +(98) Project +Output [5]: [s_nationkey#X, l_orderkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Input [7]: [s_suppkey#X, s_nationkey#X, l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] + +(99) Exchange +Input [5]: [s_nationkey#X, l_orderkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X] +Arguments: hashpartitioning(l_orderkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(100) Scan parquet +Output [2]: [o_orderkey#X, o_custkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_orderkey), IsNotNull(o_custkey)] +ReadSchema: struct + +(101) Filter +Input [2]: [o_orderkey#X, o_custkey#X] +Condition : (isnotnull(o_orderkey#X) AND isnotnull(o_custkey#X)) + +(102) Exchange +Input [2]: [o_orderkey#X, o_custkey#X] +Arguments: hashpartitioning(o_orderkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(103) ShuffledHashJoin +Left keys [1]: [l_orderkey#X] +Right keys [1]: [o_orderkey#X] +Join condition: None + +(104) Project +Output [5]: [s_nationkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X, o_custkey#X] +Input [7]: [s_nationkey#X, l_orderkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X, o_orderkey#X, o_custkey#X] + +(105) Exchange +Input [5]: [s_nationkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X, o_custkey#X] +Arguments: hashpartitioning(o_custkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(106) Scan parquet +Output [2]: [c_custkey#X, c_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(c_custkey), IsNotNull(c_nationkey)] +ReadSchema: struct + +(107) Filter +Input [2]: [c_custkey#X, c_nationkey#X] +Condition : (isnotnull(c_custkey#X) AND isnotnull(c_nationkey#X)) + +(108) Exchange +Input [2]: [c_custkey#X, c_nationkey#X] +Arguments: hashpartitioning(c_custkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(109) ShuffledHashJoin +Left keys [1]: [o_custkey#X] +Right keys [1]: [c_custkey#X] +Join condition: None + +(110) Project +Output [5]: [s_nationkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X, c_nationkey#X] +Input [7]: [s_nationkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X, o_custkey#X, c_custkey#X, c_nationkey#X] + +(111) Exchange +Input [5]: [s_nationkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X, c_nationkey#X] +Arguments: hashpartitioning(s_nationkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(112) Scan parquet +Output [2]: [n_nationkey#X, n_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_nationkey), Or(EqualTo(n_name,FRANCE),EqualTo(n_name,GERMANY))] +ReadSchema: struct + +(113) Filter +Input [2]: [n_nationkey#X, n_name#X] +Condition : (isnotnull(n_nationkey#X) AND ((n_name#X = FRANCE) OR (n_name#X = GERMANY))) + +(114) Exchange +Input [2]: [n_nationkey#X, n_name#X] +Arguments: hashpartitioning(n_nationkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(115) ShuffledHashJoin +Left keys [1]: [s_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: None + +(116) Project +Output [5]: [l_extendedprice#X, l_discount#X, l_shipdate#X, c_nationkey#X, n_name#X] +Input [7]: [s_nationkey#X, l_extendedprice#X, l_discount#X, l_shipdate#X, c_nationkey#X, n_nationkey#X, n_name#X] + +(117) Exchange +Input [5]: [l_extendedprice#X, l_discount#X, l_shipdate#X, c_nationkey#X, n_name#X] +Arguments: hashpartitioning(c_nationkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(118) Scan parquet +Output [2]: [n_nationkey#X, n_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_nationkey), Or(EqualTo(n_name,GERMANY),EqualTo(n_name,FRANCE))] +ReadSchema: struct + +(119) Filter +Input [2]: [n_nationkey#X, n_name#X] +Condition : (isnotnull(n_nationkey#X) AND ((n_name#X = GERMANY) OR (n_name#X = FRANCE))) + +(120) Exchange +Input [2]: [n_nationkey#X, n_name#X] +Arguments: hashpartitioning(n_nationkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(121) ShuffledHashJoin +Left keys [1]: [c_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: (((n_name#X = FRANCE) AND (n_name#X = GERMANY)) OR ((n_name#X = GERMANY) AND (n_name#X = FRANCE))) + +(122) Project +Output [4]: [n_name#X AS supp_nation#X, n_name#X AS cust_nation#X, year(l_shipdate#X) AS l_year#X, CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) AS volume#X] +Input [7]: [l_extendedprice#X, l_discount#X, l_shipdate#X, c_nationkey#X, n_name#X, n_nationkey#X, n_name#X] + +(123) HashAggregate +Input [4]: [supp_nation#X, cust_nation#X, l_year#X, volume#X] +Keys [3]: [supp_nation#X, cust_nation#X, l_year#X] +Functions [1]: [partial_sum(volume#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [5]: [supp_nation#X, cust_nation#X, l_year#X, sum#X, isEmpty#X] + +(124) Exchange +Input [5]: [supp_nation#X, cust_nation#X, l_year#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(supp_nation#X, cust_nation#X, l_year#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(125) HashAggregate +Input [5]: [supp_nation#X, cust_nation#X, l_year#X, sum#X, isEmpty#X] +Keys [3]: [supp_nation#X, cust_nation#X, l_year#X] +Functions [1]: [sum(volume#X)] +Aggregate Attributes [1]: [sum(volume#X)#X] +Results [4]: [supp_nation#X, cust_nation#X, l_year#X, sum(volume#X)#X AS revenue#X] + +(126) Exchange +Input [4]: [supp_nation#X, cust_nation#X, l_year#X, revenue#X] +Arguments: rangepartitioning(supp_nation#X ASC NULLS FIRST, cust_nation#X ASC NULLS FIRST, l_year#X ASC NULLS FIRST, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(127) Sort +Input [4]: [supp_nation#X, cust_nation#X, l_year#X, revenue#X] +Arguments: [supp_nation#X ASC NULLS FIRST, cust_nation#X ASC NULLS FIRST, l_year#X ASC NULLS FIRST], true, 0 + +(128) AdaptiveSparkPlan +Output [4]: [supp_nation#X, cust_nation#X, l_year#X, revenue#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/8.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/8.txt new file mode 100644 index 000000000000..db2cd0bd9fdc --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/8.txt @@ -0,0 +1,913 @@ +== Physical Plan == +AdaptiveSparkPlan (177) ++- == Final Plan == + VeloxColumnarToRowExec (125) + +- ^ SortExecTransformer (123) + +- ^ InputIteratorTransformer (122) + +- ^ InputAdapter (121) + +- ^ ShuffleQueryStage (120) + +- ColumnarExchange (119) + +- ^ ProjectExecTransformer (117) + +- ^ RegularHashAggregateExecTransformer (116) + +- ^ InputIteratorTransformer (115) + +- ^ InputAdapter (114) + +- ^ ShuffleQueryStage (113) + +- ColumnarExchange (112) + +- ^ ProjectExecTransformer (110) + +- ^ FlushableHashAggregateExecTransformer (109) + +- ^ ProjectExecTransformer (108) + +- ^ ShuffledHashJoinExecTransformer Inner (107) + :- ^ InputIteratorTransformer (98) + : +- ^ InputAdapter (97) + : +- ^ ShuffleQueryStage (96) + : +- ColumnarExchange (95) + : +- ^ ProjectExecTransformer (93) + : +- ^ ShuffledHashJoinExecTransformer Inner (92) + : :- ^ InputIteratorTransformer (83) + : : +- ^ InputAdapter (82) + : : +- ^ ShuffleQueryStage (81) + : : +- ColumnarExchange (80) + : : +- ^ ProjectExecTransformer (78) + : : +- ^ ShuffledHashJoinExecTransformer Inner (77) + : : :- ^ InputIteratorTransformer (68) + : : : +- ^ InputAdapter (67) + : : : +- ^ ShuffleQueryStage (66) + : : : +- ColumnarExchange (65) + : : : +- ^ ProjectExecTransformer (63) + : : : +- ^ ShuffledHashJoinExecTransformer Inner (62) + : : : :- ^ InputIteratorTransformer (53) + : : : : +- ^ InputAdapter (52) + : : : : +- ^ ShuffleQueryStage (51) + : : : : +- ColumnarExchange (50) + : : : : +- ^ ProjectExecTransformer (48) + : : : : +- ^ ShuffledHashJoinExecTransformer Inner (47) + : : : : :- ^ InputIteratorTransformer (38) + : : : : : +- ^ InputAdapter (37) + : : : : : +- ^ ShuffleQueryStage (36) + : : : : : +- ColumnarExchange (35) + : : : : : +- ^ ProjectExecTransformer (33) + : : : : : +- ^ ShuffledHashJoinExecTransformer Inner (32) + : : : : : :- ^ InputIteratorTransformer (23) + : : : : : : +- ^ InputAdapter (22) + : : : : : : +- ^ ShuffleQueryStage (21) + : : : : : : +- ColumnarExchange (20) + : : : : : : +- ^ ProjectExecTransformer (18) + : : : : : : +- ^ ShuffledHashJoinExecTransformer Inner (17) + : : : : : : :- ^ InputIteratorTransformer (8) + : : : : : : : +- ^ InputAdapter (7) + : : : : : : : +- ^ ShuffleQueryStage (6) + : : : : : : : +- ColumnarExchange (5) + : : : : : : : +- ^ ProjectExecTransformer (3) + : : : : : : : +- ^ FilterExecTransformer (2) + : : : : : : : +- ^ Scan parquet (1) + : : : : : : +- ^ InputIteratorTransformer (16) + : : : : : : +- ^ InputAdapter (15) + : : : : : : +- ^ ShuffleQueryStage (14) + : : : : : : +- ColumnarExchange (13) + : : : : : : +- ^ ProjectExecTransformer (11) + : : : : : : +- ^ FilterExecTransformer (10) + : : : : : : +- ^ Scan parquet (9) + : : : : : +- ^ InputIteratorTransformer (31) + : : : : : +- ^ InputAdapter (30) + : : : : : +- ^ ShuffleQueryStage (29) + : : : : : +- ColumnarExchange (28) + : : : : : +- ^ ProjectExecTransformer (26) + : : : : : +- ^ FilterExecTransformer (25) + : : : : : +- ^ Scan parquet (24) + : : : : +- ^ InputIteratorTransformer (46) + : : : : +- ^ InputAdapter (45) + : : : : +- ^ ShuffleQueryStage (44) + : : : : +- ColumnarExchange (43) + : : : : +- ^ ProjectExecTransformer (41) + : : : : +- ^ FilterExecTransformer (40) + : : : : +- ^ Scan parquet (39) + : : : +- ^ InputIteratorTransformer (61) + : : : +- ^ InputAdapter (60) + : : : +- ^ ShuffleQueryStage (59) + : : : +- ColumnarExchange (58) + : : : +- ^ ProjectExecTransformer (56) + : : : +- ^ FilterExecTransformer (55) + : : : +- ^ Scan parquet (54) + : : +- ^ InputIteratorTransformer (76) + : : +- ^ InputAdapter (75) + : : +- ^ ShuffleQueryStage (74) + : : +- ColumnarExchange (73) + : : +- ^ ProjectExecTransformer (71) + : : +- ^ FilterExecTransformer (70) + : : +- ^ Scan parquet (69) + : +- ^ InputIteratorTransformer (91) + : +- ^ InputAdapter (90) + : +- ^ ShuffleQueryStage (89) + : +- ColumnarExchange (88) + : +- ^ ProjectExecTransformer (86) + : +- ^ FilterExecTransformer (85) + : +- ^ Scan parquet (84) + +- ^ InputIteratorTransformer (106) + +- ^ InputAdapter (105) + +- ^ ShuffleQueryStage (104) + +- ColumnarExchange (103) + +- ^ ProjectExecTransformer (101) + +- ^ FilterExecTransformer (100) + +- ^ Scan parquet (99) ++- == Initial Plan == + Sort (176) + +- Exchange (175) + +- HashAggregate (174) + +- Exchange (173) + +- HashAggregate (172) + +- Project (171) + +- ShuffledHashJoin Inner BuildRight (170) + :- Exchange (165) + : +- Project (164) + : +- ShuffledHashJoin Inner BuildRight (163) + : :- Exchange (159) + : : +- Project (158) + : : +- ShuffledHashJoin Inner BuildRight (157) + : : :- Exchange (153) + : : : +- Project (152) + : : : +- ShuffledHashJoin Inner BuildRight (151) + : : : :- Exchange (147) + : : : : +- Project (146) + : : : : +- ShuffledHashJoin Inner BuildRight (145) + : : : : :- Exchange (141) + : : : : : +- Project (140) + : : : : : +- ShuffledHashJoin Inner BuildRight (139) + : : : : : :- Exchange (135) + : : : : : : +- Project (134) + : : : : : : +- ShuffledHashJoin Inner BuildLeft (133) + : : : : : : :- Exchange (129) + : : : : : : : +- Project (128) + : : : : : : : +- Filter (127) + : : : : : : : +- Scan parquet (126) + : : : : : : +- Exchange (132) + : : : : : : +- Filter (131) + : : : : : : +- Scan parquet (130) + : : : : : +- Exchange (138) + : : : : : +- Filter (137) + : : : : : +- Scan parquet (136) + : : : : +- Exchange (144) + : : : : +- Filter (143) + : : : : +- Scan parquet (142) + : : : +- Exchange (150) + : : : +- Filter (149) + : : : +- Scan parquet (148) + : : +- Exchange (156) + : : +- Filter (155) + : : +- Scan parquet (154) + : +- Exchange (162) + : +- Filter (161) + : +- Scan parquet (160) + +- Exchange (169) + +- Project (168) + +- Filter (167) + +- Scan parquet (166) + + +(1) Scan parquet +Output [2]: [p_partkey#X, p_type#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(p_type), EqualTo(p_type,ECONOMY ANODIZED STEEL), IsNotNull(p_partkey)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [2]: [p_partkey#X, p_type#X] +Arguments: ((isnotnull(p_type#X) AND (p_type#X = ECONOMY ANODIZED STEEL)) AND isnotnull(p_partkey#X)) + +(3) ProjectExecTransformer +Output [2]: [hash(p_partkey#X, 42) AS hash_partition_key#X, p_partkey#X] +Input [2]: [p_partkey#X, p_type#X] + +(4) WholeStageCodegenTransformer (X) +Input [2]: [hash_partition_key#X, p_partkey#X] +Arguments: false + +(5) ColumnarExchange +Input [2]: [hash_partition_key#X, p_partkey#X] +Arguments: hashpartitioning(p_partkey#X, 1), ENSURE_REQUIREMENTS, [p_partkey#X], [plan_id=X], [id=#X] + +(6) ShuffleQueryStage +Output [1]: [p_partkey#X] +Arguments: X + +(7) InputAdapter +Input [1]: [p_partkey#X] + +(8) InputIteratorTransformer +Input [1]: [p_partkey#X] + +(9) Scan parquet +Output [5]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_partkey), IsNotNull(l_suppkey), IsNotNull(l_orderkey)] +ReadSchema: struct + +(10) FilterExecTransformer +Input [5]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Arguments: ((isnotnull(l_partkey#X) AND isnotnull(l_suppkey#X)) AND isnotnull(l_orderkey#X)) + +(11) ProjectExecTransformer +Output [6]: [hash(l_partkey#X, 42) AS hash_partition_key#X, l_orderkey#X, l_partkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Input [5]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] + +(12) WholeStageCodegenTransformer (X) +Input [6]: [hash_partition_key#X, l_orderkey#X, l_partkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Arguments: false + +(13) ColumnarExchange +Input [6]: [hash_partition_key#X, l_orderkey#X, l_partkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Arguments: hashpartitioning(l_partkey#X, 1), ENSURE_REQUIREMENTS, [l_orderkey#X, l_partkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X], [plan_id=X], [id=#X] + +(14) ShuffleQueryStage +Output [5]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Arguments: X + +(15) InputAdapter +Input [5]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] + +(16) InputIteratorTransformer +Input [5]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] + +(17) ShuffledHashJoinExecTransformer +Left keys [1]: [p_partkey#X] +Right keys [1]: [l_partkey#X] +Join condition: None + +(18) ProjectExecTransformer +Output [5]: [hash(l_suppkey#X, 42) AS hash_partition_key#X, l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Input [6]: [p_partkey#X, l_orderkey#X, l_partkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] + +(19) WholeStageCodegenTransformer (X) +Input [5]: [hash_partition_key#X, l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Arguments: false + +(20) ColumnarExchange +Input [5]: [hash_partition_key#X, l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Arguments: hashpartitioning(l_suppkey#X, 1), ENSURE_REQUIREMENTS, [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X], [plan_id=X], [id=#X] + +(21) ShuffleQueryStage +Output [4]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Arguments: X + +(22) InputAdapter +Input [4]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] + +(23) InputIteratorTransformer +Input [4]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] + +(24) Scan parquet +Output [2]: [s_suppkey#X, s_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(s_suppkey), IsNotNull(s_nationkey)] +ReadSchema: struct + +(25) FilterExecTransformer +Input [2]: [s_suppkey#X, s_nationkey#X] +Arguments: (isnotnull(s_suppkey#X) AND isnotnull(s_nationkey#X)) + +(26) ProjectExecTransformer +Output [3]: [hash(s_suppkey#X, 42) AS hash_partition_key#X, s_suppkey#X, s_nationkey#X] +Input [2]: [s_suppkey#X, s_nationkey#X] + +(27) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, s_suppkey#X, s_nationkey#X] +Arguments: false + +(28) ColumnarExchange +Input [3]: [hash_partition_key#X, s_suppkey#X, s_nationkey#X] +Arguments: hashpartitioning(s_suppkey#X, 1), ENSURE_REQUIREMENTS, [s_suppkey#X, s_nationkey#X], [plan_id=X], [id=#X] + +(29) ShuffleQueryStage +Output [2]: [s_suppkey#X, s_nationkey#X] +Arguments: X + +(30) InputAdapter +Input [2]: [s_suppkey#X, s_nationkey#X] + +(31) InputIteratorTransformer +Input [2]: [s_suppkey#X, s_nationkey#X] + +(32) ShuffledHashJoinExecTransformer +Left keys [1]: [l_suppkey#X] +Right keys [1]: [s_suppkey#X] +Join condition: None + +(33) ProjectExecTransformer +Output [5]: [hash(l_orderkey#X, 42) AS hash_partition_key#X, l_orderkey#X, l_extendedprice#X, l_discount#X, s_nationkey#X] +Input [6]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X, s_suppkey#X, s_nationkey#X] + +(34) WholeStageCodegenTransformer (X) +Input [5]: [hash_partition_key#X, l_orderkey#X, l_extendedprice#X, l_discount#X, s_nationkey#X] +Arguments: false + +(35) ColumnarExchange +Input [5]: [hash_partition_key#X, l_orderkey#X, l_extendedprice#X, l_discount#X, s_nationkey#X] +Arguments: hashpartitioning(l_orderkey#X, 1), ENSURE_REQUIREMENTS, [l_orderkey#X, l_extendedprice#X, l_discount#X, s_nationkey#X], [plan_id=X], [id=#X] + +(36) ShuffleQueryStage +Output [4]: [l_orderkey#X, l_extendedprice#X, l_discount#X, s_nationkey#X] +Arguments: X + +(37) InputAdapter +Input [4]: [l_orderkey#X, l_extendedprice#X, l_discount#X, s_nationkey#X] + +(38) InputIteratorTransformer +Input [4]: [l_orderkey#X, l_extendedprice#X, l_discount#X, s_nationkey#X] + +(39) Scan parquet +Output [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_orderdate), GreaterThanOrEqual(o_orderdate,1995-01-01), LessThanOrEqual(o_orderdate,1996-12-31), IsNotNull(o_orderkey), IsNotNull(o_custkey)] +ReadSchema: struct + +(40) FilterExecTransformer +Input [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] +Arguments: ((((isnotnull(o_orderdate#X) AND (o_orderdate#X >= 1995-01-01)) AND (o_orderdate#X <= 1996-12-31)) AND isnotnull(o_orderkey#X)) AND isnotnull(o_custkey#X)) + +(41) ProjectExecTransformer +Output [4]: [hash(o_orderkey#X, 42) AS hash_partition_key#X, o_orderkey#X, o_custkey#X, o_orderdate#X] +Input [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] + +(42) WholeStageCodegenTransformer (X) +Input [4]: [hash_partition_key#X, o_orderkey#X, o_custkey#X, o_orderdate#X] +Arguments: false + +(43) ColumnarExchange +Input [4]: [hash_partition_key#X, o_orderkey#X, o_custkey#X, o_orderdate#X] +Arguments: hashpartitioning(o_orderkey#X, 1), ENSURE_REQUIREMENTS, [o_orderkey#X, o_custkey#X, o_orderdate#X], [plan_id=X], [id=#X] + +(44) ShuffleQueryStage +Output [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] +Arguments: X + +(45) InputAdapter +Input [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] + +(46) InputIteratorTransformer +Input [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] + +(47) ShuffledHashJoinExecTransformer +Left keys [1]: [l_orderkey#X] +Right keys [1]: [o_orderkey#X] +Join condition: None + +(48) ProjectExecTransformer +Output [6]: [hash(o_custkey#X, 42) AS hash_partition_key#X, l_extendedprice#X, l_discount#X, s_nationkey#X, o_custkey#X, o_orderdate#X] +Input [7]: [l_orderkey#X, l_extendedprice#X, l_discount#X, s_nationkey#X, o_orderkey#X, o_custkey#X, o_orderdate#X] + +(49) WholeStageCodegenTransformer (X) +Input [6]: [hash_partition_key#X, l_extendedprice#X, l_discount#X, s_nationkey#X, o_custkey#X, o_orderdate#X] +Arguments: false + +(50) ColumnarExchange +Input [6]: [hash_partition_key#X, l_extendedprice#X, l_discount#X, s_nationkey#X, o_custkey#X, o_orderdate#X] +Arguments: hashpartitioning(o_custkey#X, 1), ENSURE_REQUIREMENTS, [l_extendedprice#X, l_discount#X, s_nationkey#X, o_custkey#X, o_orderdate#X], [plan_id=X], [id=#X] + +(51) ShuffleQueryStage +Output [5]: [l_extendedprice#X, l_discount#X, s_nationkey#X, o_custkey#X, o_orderdate#X] +Arguments: X + +(52) InputAdapter +Input [5]: [l_extendedprice#X, l_discount#X, s_nationkey#X, o_custkey#X, o_orderdate#X] + +(53) InputIteratorTransformer +Input [5]: [l_extendedprice#X, l_discount#X, s_nationkey#X, o_custkey#X, o_orderdate#X] + +(54) Scan parquet +Output [2]: [c_custkey#X, c_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(c_custkey), IsNotNull(c_nationkey)] +ReadSchema: struct + +(55) FilterExecTransformer +Input [2]: [c_custkey#X, c_nationkey#X] +Arguments: (isnotnull(c_custkey#X) AND isnotnull(c_nationkey#X)) + +(56) ProjectExecTransformer +Output [3]: [hash(c_custkey#X, 42) AS hash_partition_key#X, c_custkey#X, c_nationkey#X] +Input [2]: [c_custkey#X, c_nationkey#X] + +(57) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, c_custkey#X, c_nationkey#X] +Arguments: false + +(58) ColumnarExchange +Input [3]: [hash_partition_key#X, c_custkey#X, c_nationkey#X] +Arguments: hashpartitioning(c_custkey#X, 1), ENSURE_REQUIREMENTS, [c_custkey#X, c_nationkey#X], [plan_id=X], [id=#X] + +(59) ShuffleQueryStage +Output [2]: [c_custkey#X, c_nationkey#X] +Arguments: X + +(60) InputAdapter +Input [2]: [c_custkey#X, c_nationkey#X] + +(61) InputIteratorTransformer +Input [2]: [c_custkey#X, c_nationkey#X] + +(62) ShuffledHashJoinExecTransformer +Left keys [1]: [o_custkey#X] +Right keys [1]: [c_custkey#X] +Join condition: None + +(63) ProjectExecTransformer +Output [6]: [hash(c_nationkey#X, 42) AS hash_partition_key#X, l_extendedprice#X, l_discount#X, s_nationkey#X, o_orderdate#X, c_nationkey#X] +Input [7]: [l_extendedprice#X, l_discount#X, s_nationkey#X, o_custkey#X, o_orderdate#X, c_custkey#X, c_nationkey#X] + +(64) WholeStageCodegenTransformer (X) +Input [6]: [hash_partition_key#X, l_extendedprice#X, l_discount#X, s_nationkey#X, o_orderdate#X, c_nationkey#X] +Arguments: false + +(65) ColumnarExchange +Input [6]: [hash_partition_key#X, l_extendedprice#X, l_discount#X, s_nationkey#X, o_orderdate#X, c_nationkey#X] +Arguments: hashpartitioning(c_nationkey#X, 1), ENSURE_REQUIREMENTS, [l_extendedprice#X, l_discount#X, s_nationkey#X, o_orderdate#X, c_nationkey#X], [plan_id=X], [id=#X] + +(66) ShuffleQueryStage +Output [5]: [l_extendedprice#X, l_discount#X, s_nationkey#X, o_orderdate#X, c_nationkey#X] +Arguments: X + +(67) InputAdapter +Input [5]: [l_extendedprice#X, l_discount#X, s_nationkey#X, o_orderdate#X, c_nationkey#X] + +(68) InputIteratorTransformer +Input [5]: [l_extendedprice#X, l_discount#X, s_nationkey#X, o_orderdate#X, c_nationkey#X] + +(69) Scan parquet +Output [2]: [n_nationkey#X, n_regionkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_nationkey), IsNotNull(n_regionkey)] +ReadSchema: struct + +(70) FilterExecTransformer +Input [2]: [n_nationkey#X, n_regionkey#X] +Arguments: (isnotnull(n_nationkey#X) AND isnotnull(n_regionkey#X)) + +(71) ProjectExecTransformer +Output [3]: [hash(n_nationkey#X, 42) AS hash_partition_key#X, n_nationkey#X, n_regionkey#X] +Input [2]: [n_nationkey#X, n_regionkey#X] + +(72) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, n_nationkey#X, n_regionkey#X] +Arguments: false + +(73) ColumnarExchange +Input [3]: [hash_partition_key#X, n_nationkey#X, n_regionkey#X] +Arguments: hashpartitioning(n_nationkey#X, 1), ENSURE_REQUIREMENTS, [n_nationkey#X, n_regionkey#X], [plan_id=X], [id=#X] + +(74) ShuffleQueryStage +Output [2]: [n_nationkey#X, n_regionkey#X] +Arguments: X + +(75) InputAdapter +Input [2]: [n_nationkey#X, n_regionkey#X] + +(76) InputIteratorTransformer +Input [2]: [n_nationkey#X, n_regionkey#X] + +(77) ShuffledHashJoinExecTransformer +Left keys [1]: [c_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: None + +(78) ProjectExecTransformer +Output [6]: [hash(s_nationkey#X, 42) AS hash_partition_key#X, l_extendedprice#X, l_discount#X, s_nationkey#X, o_orderdate#X, n_regionkey#X] +Input [7]: [l_extendedprice#X, l_discount#X, s_nationkey#X, o_orderdate#X, c_nationkey#X, n_nationkey#X, n_regionkey#X] + +(79) WholeStageCodegenTransformer (X) +Input [6]: [hash_partition_key#X, l_extendedprice#X, l_discount#X, s_nationkey#X, o_orderdate#X, n_regionkey#X] +Arguments: false + +(80) ColumnarExchange +Input [6]: [hash_partition_key#X, l_extendedprice#X, l_discount#X, s_nationkey#X, o_orderdate#X, n_regionkey#X] +Arguments: hashpartitioning(s_nationkey#X, 1), ENSURE_REQUIREMENTS, [l_extendedprice#X, l_discount#X, s_nationkey#X, o_orderdate#X, n_regionkey#X], [plan_id=X], [id=#X] + +(81) ShuffleQueryStage +Output [5]: [l_extendedprice#X, l_discount#X, s_nationkey#X, o_orderdate#X, n_regionkey#X] +Arguments: X + +(82) InputAdapter +Input [5]: [l_extendedprice#X, l_discount#X, s_nationkey#X, o_orderdate#X, n_regionkey#X] + +(83) InputIteratorTransformer +Input [5]: [l_extendedprice#X, l_discount#X, s_nationkey#X, o_orderdate#X, n_regionkey#X] + +(84) Scan parquet +Output [2]: [n_nationkey#X, n_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_nationkey)] +ReadSchema: struct + +(85) FilterExecTransformer +Input [2]: [n_nationkey#X, n_name#X] +Arguments: isnotnull(n_nationkey#X) + +(86) ProjectExecTransformer +Output [3]: [hash(n_nationkey#X, 42) AS hash_partition_key#X, n_nationkey#X, n_name#X] +Input [2]: [n_nationkey#X, n_name#X] + +(87) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, n_nationkey#X, n_name#X] +Arguments: false + +(88) ColumnarExchange +Input [3]: [hash_partition_key#X, n_nationkey#X, n_name#X] +Arguments: hashpartitioning(n_nationkey#X, 1), ENSURE_REQUIREMENTS, [n_nationkey#X, n_name#X], [plan_id=X], [id=#X] + +(89) ShuffleQueryStage +Output [2]: [n_nationkey#X, n_name#X] +Arguments: X + +(90) InputAdapter +Input [2]: [n_nationkey#X, n_name#X] + +(91) InputIteratorTransformer +Input [2]: [n_nationkey#X, n_name#X] + +(92) ShuffledHashJoinExecTransformer +Left keys [1]: [s_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: None + +(93) ProjectExecTransformer +Output [6]: [hash(n_regionkey#X, 42) AS hash_partition_key#X, l_extendedprice#X, l_discount#X, o_orderdate#X, n_regionkey#X, n_name#X] +Input [7]: [l_extendedprice#X, l_discount#X, s_nationkey#X, o_orderdate#X, n_regionkey#X, n_nationkey#X, n_name#X] + +(94) WholeStageCodegenTransformer (X) +Input [6]: [hash_partition_key#X, l_extendedprice#X, l_discount#X, o_orderdate#X, n_regionkey#X, n_name#X] +Arguments: false + +(95) ColumnarExchange +Input [6]: [hash_partition_key#X, l_extendedprice#X, l_discount#X, o_orderdate#X, n_regionkey#X, n_name#X] +Arguments: hashpartitioning(n_regionkey#X, 1), ENSURE_REQUIREMENTS, [l_extendedprice#X, l_discount#X, o_orderdate#X, n_regionkey#X, n_name#X], [plan_id=X], [id=#X] + +(96) ShuffleQueryStage +Output [5]: [l_extendedprice#X, l_discount#X, o_orderdate#X, n_regionkey#X, n_name#X] +Arguments: X + +(97) InputAdapter +Input [5]: [l_extendedprice#X, l_discount#X, o_orderdate#X, n_regionkey#X, n_name#X] + +(98) InputIteratorTransformer +Input [5]: [l_extendedprice#X, l_discount#X, o_orderdate#X, n_regionkey#X, n_name#X] + +(99) Scan parquet +Output [2]: [r_regionkey#X, r_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(r_name), EqualTo(r_name,AMERICA), IsNotNull(r_regionkey)] +ReadSchema: struct + +(100) FilterExecTransformer +Input [2]: [r_regionkey#X, r_name#X] +Arguments: ((isnotnull(r_name#X) AND (r_name#X = AMERICA)) AND isnotnull(r_regionkey#X)) + +(101) ProjectExecTransformer +Output [2]: [hash(r_regionkey#X, 42) AS hash_partition_key#X, r_regionkey#X] +Input [2]: [r_regionkey#X, r_name#X] + +(102) WholeStageCodegenTransformer (X) +Input [2]: [hash_partition_key#X, r_regionkey#X] +Arguments: false + +(103) ColumnarExchange +Input [2]: [hash_partition_key#X, r_regionkey#X] +Arguments: hashpartitioning(r_regionkey#X, 1), ENSURE_REQUIREMENTS, [r_regionkey#X], [plan_id=X], [id=#X] + +(104) ShuffleQueryStage +Output [1]: [r_regionkey#X] +Arguments: X + +(105) InputAdapter +Input [1]: [r_regionkey#X] + +(106) InputIteratorTransformer +Input [1]: [r_regionkey#X] + +(107) ShuffledHashJoinExecTransformer +Left keys [1]: [n_regionkey#X] +Right keys [1]: [r_regionkey#X] +Join condition: None + +(108) ProjectExecTransformer +Output [4]: [year(o_orderdate#X) AS o_year#X, CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) AS volume#X, n_name#X AS nation#X, CASE WHEN (n_name#X = BRAZIL) THEN CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) ELSE 0.0000 END AS _pre_113#X] +Input [6]: [l_extendedprice#X, l_discount#X, o_orderdate#X, n_regionkey#X, n_name#X, r_regionkey#X] + +(109) FlushableHashAggregateExecTransformer +Input [4]: [o_year#X, volume#X, nation#X, _pre_113#X] +Keys [1]: [o_year#X] +Functions [2]: [partial_sum(_pre_113#X), partial_sum(volume#X)] +Aggregate Attributes [4]: [sum#X, isEmpty#X, sum#X, isEmpty#X] +Results [5]: [o_year#X, sum#X, isEmpty#X, sum#X, isEmpty#X] + +(110) ProjectExecTransformer +Output [6]: [hash(o_year#X, 42) AS hash_partition_key#X, o_year#X, sum#X, isEmpty#X, sum#X, isEmpty#X] +Input [5]: [o_year#X, sum#X, isEmpty#X, sum#X, isEmpty#X] + +(111) WholeStageCodegenTransformer (X) +Input [6]: [hash_partition_key#X, o_year#X, sum#X, isEmpty#X, sum#X, isEmpty#X] +Arguments: false + +(112) ColumnarExchange +Input [6]: [hash_partition_key#X, o_year#X, sum#X, isEmpty#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(o_year#X, 1), ENSURE_REQUIREMENTS, [o_year#X, sum#X, isEmpty#X, sum#X, isEmpty#X], [plan_id=X], [id=#X] + +(113) ShuffleQueryStage +Output [5]: [o_year#X, sum#X, isEmpty#X, sum#X, isEmpty#X] +Arguments: X + +(114) InputAdapter +Input [5]: [o_year#X, sum#X, isEmpty#X, sum#X, isEmpty#X] + +(115) InputIteratorTransformer +Input [5]: [o_year#X, sum#X, isEmpty#X, sum#X, isEmpty#X] + +(116) RegularHashAggregateExecTransformer +Input [5]: [o_year#X, sum#X, isEmpty#X, sum#X, isEmpty#X] +Keys [1]: [o_year#X] +Functions [2]: [sum(CASE WHEN (nation#X = BRAZIL) THEN volume#X ELSE 0.0000 END), sum(volume#X)] +Aggregate Attributes [2]: [sum(CASE WHEN (nation#X = BRAZIL) THEN volume#X ELSE 0.0000 END)#X, sum(volume#X)#X] +Results [3]: [o_year#X, sum(CASE WHEN (nation#X = BRAZIL) THEN volume#X ELSE 0.0000 END)#X, sum(volume#X)#X] + +(117) ProjectExecTransformer +Output [2]: [o_year#X, CheckOverflow((promote_precision(sum(CASE WHEN (nation#X = BRAZIL) THEN volume#X ELSE 0.0000 END)#X) / promote_precision(sum(volume#X)#X)), DecimalType(38,6), true) AS mkt_share#X] +Input [3]: [o_year#X, sum(CASE WHEN (nation#X = BRAZIL) THEN volume#X ELSE 0.0000 END)#X, sum(volume#X)#X] + +(118) WholeStageCodegenTransformer (X) +Input [2]: [o_year#X, mkt_share#X] +Arguments: false + +(119) ColumnarExchange +Input [2]: [o_year#X, mkt_share#X] +Arguments: rangepartitioning(o_year#X ASC NULLS FIRST, 1), ENSURE_REQUIREMENTS, [plan_id=X], [id=#X] + +(120) ShuffleQueryStage +Output [2]: [o_year#X, mkt_share#X] +Arguments: X + +(121) InputAdapter +Input [2]: [o_year#X, mkt_share#X] + +(122) InputIteratorTransformer +Input [2]: [o_year#X, mkt_share#X] + +(123) SortExecTransformer +Input [2]: [o_year#X, mkt_share#X] +Arguments: [o_year#X ASC NULLS FIRST], true, 0 + +(124) WholeStageCodegenTransformer (X) +Input [2]: [o_year#X, mkt_share#X] +Arguments: false + +(125) VeloxColumnarToRowExec +Input [2]: [o_year#X, mkt_share#X] + +(126) Scan parquet +Output [2]: [p_partkey#X, p_type#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(p_type), EqualTo(p_type,ECONOMY ANODIZED STEEL), IsNotNull(p_partkey)] +ReadSchema: struct + +(127) Filter +Input [2]: [p_partkey#X, p_type#X] +Condition : ((isnotnull(p_type#X) AND (p_type#X = ECONOMY ANODIZED STEEL)) AND isnotnull(p_partkey#X)) + +(128) Project +Output [1]: [p_partkey#X] +Input [2]: [p_partkey#X, p_type#X] + +(129) Exchange +Input [1]: [p_partkey#X] +Arguments: hashpartitioning(p_partkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(130) Scan parquet +Output [5]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_partkey), IsNotNull(l_suppkey), IsNotNull(l_orderkey)] +ReadSchema: struct + +(131) Filter +Input [5]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Condition : ((isnotnull(l_partkey#X) AND isnotnull(l_suppkey#X)) AND isnotnull(l_orderkey#X)) + +(132) Exchange +Input [5]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Arguments: hashpartitioning(l_partkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(133) ShuffledHashJoin +Left keys [1]: [p_partkey#X] +Right keys [1]: [l_partkey#X] +Join condition: None + +(134) Project +Output [4]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Input [6]: [p_partkey#X, l_orderkey#X, l_partkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] + +(135) Exchange +Input [4]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X] +Arguments: hashpartitioning(l_suppkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(136) Scan parquet +Output [2]: [s_suppkey#X, s_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(s_suppkey), IsNotNull(s_nationkey)] +ReadSchema: struct + +(137) Filter +Input [2]: [s_suppkey#X, s_nationkey#X] +Condition : (isnotnull(s_suppkey#X) AND isnotnull(s_nationkey#X)) + +(138) Exchange +Input [2]: [s_suppkey#X, s_nationkey#X] +Arguments: hashpartitioning(s_suppkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(139) ShuffledHashJoin +Left keys [1]: [l_suppkey#X] +Right keys [1]: [s_suppkey#X] +Join condition: None + +(140) Project +Output [4]: [l_orderkey#X, l_extendedprice#X, l_discount#X, s_nationkey#X] +Input [6]: [l_orderkey#X, l_suppkey#X, l_extendedprice#X, l_discount#X, s_suppkey#X, s_nationkey#X] + +(141) Exchange +Input [4]: [l_orderkey#X, l_extendedprice#X, l_discount#X, s_nationkey#X] +Arguments: hashpartitioning(l_orderkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(142) Scan parquet +Output [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_orderdate), GreaterThanOrEqual(o_orderdate,1995-01-01), LessThanOrEqual(o_orderdate,1996-12-31), IsNotNull(o_orderkey), IsNotNull(o_custkey)] +ReadSchema: struct + +(143) Filter +Input [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] +Condition : ((((isnotnull(o_orderdate#X) AND (o_orderdate#X >= 1995-01-01)) AND (o_orderdate#X <= 1996-12-31)) AND isnotnull(o_orderkey#X)) AND isnotnull(o_custkey#X)) + +(144) Exchange +Input [3]: [o_orderkey#X, o_custkey#X, o_orderdate#X] +Arguments: hashpartitioning(o_orderkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(145) ShuffledHashJoin +Left keys [1]: [l_orderkey#X] +Right keys [1]: [o_orderkey#X] +Join condition: None + +(146) Project +Output [5]: [l_extendedprice#X, l_discount#X, s_nationkey#X, o_custkey#X, o_orderdate#X] +Input [7]: [l_orderkey#X, l_extendedprice#X, l_discount#X, s_nationkey#X, o_orderkey#X, o_custkey#X, o_orderdate#X] + +(147) Exchange +Input [5]: [l_extendedprice#X, l_discount#X, s_nationkey#X, o_custkey#X, o_orderdate#X] +Arguments: hashpartitioning(o_custkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(148) Scan parquet +Output [2]: [c_custkey#X, c_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(c_custkey), IsNotNull(c_nationkey)] +ReadSchema: struct + +(149) Filter +Input [2]: [c_custkey#X, c_nationkey#X] +Condition : (isnotnull(c_custkey#X) AND isnotnull(c_nationkey#X)) + +(150) Exchange +Input [2]: [c_custkey#X, c_nationkey#X] +Arguments: hashpartitioning(c_custkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(151) ShuffledHashJoin +Left keys [1]: [o_custkey#X] +Right keys [1]: [c_custkey#X] +Join condition: None + +(152) Project +Output [5]: [l_extendedprice#X, l_discount#X, s_nationkey#X, o_orderdate#X, c_nationkey#X] +Input [7]: [l_extendedprice#X, l_discount#X, s_nationkey#X, o_custkey#X, o_orderdate#X, c_custkey#X, c_nationkey#X] + +(153) Exchange +Input [5]: [l_extendedprice#X, l_discount#X, s_nationkey#X, o_orderdate#X, c_nationkey#X] +Arguments: hashpartitioning(c_nationkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(154) Scan parquet +Output [2]: [n_nationkey#X, n_regionkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_nationkey), IsNotNull(n_regionkey)] +ReadSchema: struct + +(155) Filter +Input [2]: [n_nationkey#X, n_regionkey#X] +Condition : (isnotnull(n_nationkey#X) AND isnotnull(n_regionkey#X)) + +(156) Exchange +Input [2]: [n_nationkey#X, n_regionkey#X] +Arguments: hashpartitioning(n_nationkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(157) ShuffledHashJoin +Left keys [1]: [c_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: None + +(158) Project +Output [5]: [l_extendedprice#X, l_discount#X, s_nationkey#X, o_orderdate#X, n_regionkey#X] +Input [7]: [l_extendedprice#X, l_discount#X, s_nationkey#X, o_orderdate#X, c_nationkey#X, n_nationkey#X, n_regionkey#X] + +(159) Exchange +Input [5]: [l_extendedprice#X, l_discount#X, s_nationkey#X, o_orderdate#X, n_regionkey#X] +Arguments: hashpartitioning(s_nationkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(160) Scan parquet +Output [2]: [n_nationkey#X, n_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_nationkey)] +ReadSchema: struct + +(161) Filter +Input [2]: [n_nationkey#X, n_name#X] +Condition : isnotnull(n_nationkey#X) + +(162) Exchange +Input [2]: [n_nationkey#X, n_name#X] +Arguments: hashpartitioning(n_nationkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(163) ShuffledHashJoin +Left keys [1]: [s_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: None + +(164) Project +Output [5]: [l_extendedprice#X, l_discount#X, o_orderdate#X, n_regionkey#X, n_name#X] +Input [7]: [l_extendedprice#X, l_discount#X, s_nationkey#X, o_orderdate#X, n_regionkey#X, n_nationkey#X, n_name#X] + +(165) Exchange +Input [5]: [l_extendedprice#X, l_discount#X, o_orderdate#X, n_regionkey#X, n_name#X] +Arguments: hashpartitioning(n_regionkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(166) Scan parquet +Output [2]: [r_regionkey#X, r_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(r_name), EqualTo(r_name,AMERICA), IsNotNull(r_regionkey)] +ReadSchema: struct + +(167) Filter +Input [2]: [r_regionkey#X, r_name#X] +Condition : ((isnotnull(r_name#X) AND (r_name#X = AMERICA)) AND isnotnull(r_regionkey#X)) + +(168) Project +Output [1]: [r_regionkey#X] +Input [2]: [r_regionkey#X, r_name#X] + +(169) Exchange +Input [1]: [r_regionkey#X] +Arguments: hashpartitioning(r_regionkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(170) ShuffledHashJoin +Left keys [1]: [n_regionkey#X] +Right keys [1]: [r_regionkey#X] +Join condition: None + +(171) Project +Output [3]: [year(o_orderdate#X) AS o_year#X, CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) AS volume#X, n_name#X AS nation#X] +Input [6]: [l_extendedprice#X, l_discount#X, o_orderdate#X, n_regionkey#X, n_name#X, r_regionkey#X] + +(172) HashAggregate +Input [3]: [o_year#X, volume#X, nation#X] +Keys [1]: [o_year#X] +Functions [2]: [partial_sum(CASE WHEN (nation#X = BRAZIL) THEN volume#X ELSE 0.0000 END), partial_sum(volume#X)] +Aggregate Attributes [4]: [sum#X, isEmpty#X, sum#X, isEmpty#X] +Results [5]: [o_year#X, sum#X, isEmpty#X, sum#X, isEmpty#X] + +(173) Exchange +Input [5]: [o_year#X, sum#X, isEmpty#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(o_year#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(174) HashAggregate +Input [5]: [o_year#X, sum#X, isEmpty#X, sum#X, isEmpty#X] +Keys [1]: [o_year#X] +Functions [2]: [sum(CASE WHEN (nation#X = BRAZIL) THEN volume#X ELSE 0.0000 END), sum(volume#X)] +Aggregate Attributes [2]: [sum(CASE WHEN (nation#X = BRAZIL) THEN volume#X ELSE 0.0000 END)#X, sum(volume#X)#X] +Results [2]: [o_year#X, CheckOverflow((promote_precision(sum(CASE WHEN (nation#X = BRAZIL) THEN volume#X ELSE 0.0000 END)#X) / promote_precision(sum(volume#X)#X)), DecimalType(38,6), true) AS mkt_share#X] + +(175) Exchange +Input [2]: [o_year#X, mkt_share#X] +Arguments: rangepartitioning(o_year#X ASC NULLS FIRST, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(176) Sort +Input [2]: [o_year#X, mkt_share#X] +Arguments: [o_year#X ASC NULLS FIRST], true, 0 + +(177) AdaptiveSparkPlan +Output [2]: [o_year#X, mkt_share#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/9.txt b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/9.txt new file mode 100644 index 000000000000..a811b042b603 --- /dev/null +++ b/backends-velox/src/test/resources/tpch-approved-plan/v1/spark322/9.txt @@ -0,0 +1,689 @@ +== Physical Plan == +AdaptiveSparkPlan (133) ++- == Final Plan == + VeloxColumnarToRowExec (94) + +- ^ SortExecTransformer (92) + +- ^ InputIteratorTransformer (91) + +- ^ InputAdapter (90) + +- ^ ShuffleQueryStage (89) + +- ColumnarExchange (88) + +- ^ RegularHashAggregateExecTransformer (86) + +- ^ InputIteratorTransformer (85) + +- ^ InputAdapter (84) + +- ^ ShuffleQueryStage (83) + +- ColumnarExchange (82) + +- ^ ProjectExecTransformer (80) + +- ^ FlushableHashAggregateExecTransformer (79) + +- ^ ProjectExecTransformer (78) + +- ^ ShuffledHashJoinExecTransformer Inner (77) + :- ^ InputIteratorTransformer (68) + : +- ^ InputAdapter (67) + : +- ^ ShuffleQueryStage (66) + : +- ColumnarExchange (65) + : +- ^ ProjectExecTransformer (63) + : +- ^ ShuffledHashJoinExecTransformer Inner (62) + : :- ^ InputIteratorTransformer (53) + : : +- ^ InputAdapter (52) + : : +- ^ ShuffleQueryStage (51) + : : +- ColumnarExchange (50) + : : +- ^ ProjectExecTransformer (48) + : : +- ^ ShuffledHashJoinExecTransformer Inner (47) + : : :- ^ InputIteratorTransformer (38) + : : : +- ^ InputAdapter (37) + : : : +- ^ ShuffleQueryStage (36) + : : : +- ColumnarExchange (35) + : : : +- ^ ProjectExecTransformer (33) + : : : +- ^ ShuffledHashJoinExecTransformer Inner (32) + : : : :- ^ InputIteratorTransformer (23) + : : : : +- ^ InputAdapter (22) + : : : : +- ^ ShuffleQueryStage (21) + : : : : +- ColumnarExchange (20) + : : : : +- ^ ProjectExecTransformer (18) + : : : : +- ^ ShuffledHashJoinExecTransformer Inner (17) + : : : : :- ^ InputIteratorTransformer (8) + : : : : : +- ^ InputAdapter (7) + : : : : : +- ^ ShuffleQueryStage (6) + : : : : : +- ColumnarExchange (5) + : : : : : +- ^ ProjectExecTransformer (3) + : : : : : +- ^ FilterExecTransformer (2) + : : : : : +- ^ Scan parquet (1) + : : : : +- ^ InputIteratorTransformer (16) + : : : : +- ^ InputAdapter (15) + : : : : +- ^ ShuffleQueryStage (14) + : : : : +- ColumnarExchange (13) + : : : : +- ^ ProjectExecTransformer (11) + : : : : +- ^ FilterExecTransformer (10) + : : : : +- ^ Scan parquet (9) + : : : +- ^ InputIteratorTransformer (31) + : : : +- ^ InputAdapter (30) + : : : +- ^ ShuffleQueryStage (29) + : : : +- ColumnarExchange (28) + : : : +- ^ ProjectExecTransformer (26) + : : : +- ^ FilterExecTransformer (25) + : : : +- ^ Scan parquet (24) + : : +- ^ InputIteratorTransformer (46) + : : +- ^ InputAdapter (45) + : : +- ^ ShuffleQueryStage (44) + : : +- ColumnarExchange (43) + : : +- ^ ProjectExecTransformer (41) + : : +- ^ FilterExecTransformer (40) + : : +- ^ Scan parquet (39) + : +- ^ InputIteratorTransformer (61) + : +- ^ InputAdapter (60) + : +- ^ ShuffleQueryStage (59) + : +- ColumnarExchange (58) + : +- ^ ProjectExecTransformer (56) + : +- ^ FilterExecTransformer (55) + : +- ^ Scan parquet (54) + +- ^ InputIteratorTransformer (76) + +- ^ InputAdapter (75) + +- ^ ShuffleQueryStage (74) + +- ColumnarExchange (73) + +- ^ ProjectExecTransformer (71) + +- ^ FilterExecTransformer (70) + +- ^ Scan parquet (69) ++- == Initial Plan == + Sort (132) + +- Exchange (131) + +- HashAggregate (130) + +- Exchange (129) + +- HashAggregate (128) + +- Project (127) + +- ShuffledHashJoin Inner BuildRight (126) + :- Exchange (122) + : +- Project (121) + : +- ShuffledHashJoin Inner BuildRight (120) + : :- Exchange (116) + : : +- Project (115) + : : +- ShuffledHashJoin Inner BuildRight (114) + : : :- Exchange (110) + : : : +- Project (109) + : : : +- ShuffledHashJoin Inner BuildRight (108) + : : : :- Exchange (104) + : : : : +- Project (103) + : : : : +- ShuffledHashJoin Inner BuildLeft (102) + : : : : :- Exchange (98) + : : : : : +- Project (97) + : : : : : +- Filter (96) + : : : : : +- Scan parquet (95) + : : : : +- Exchange (101) + : : : : +- Filter (100) + : : : : +- Scan parquet (99) + : : : +- Exchange (107) + : : : +- Filter (106) + : : : +- Scan parquet (105) + : : +- Exchange (113) + : : +- Filter (112) + : : +- Scan parquet (111) + : +- Exchange (119) + : +- Filter (118) + : +- Scan parquet (117) + +- Exchange (125) + +- Filter (124) + +- Scan parquet (123) + + +(1) Scan parquet +Output [2]: [p_partkey#X, p_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(p_name), StringContains(p_name,green), IsNotNull(p_partkey)] +ReadSchema: struct + +(2) FilterExecTransformer +Input [2]: [p_partkey#X, p_name#X] +Arguments: ((isnotnull(p_name#X) AND Contains(p_name#X, green)) AND isnotnull(p_partkey#X)) + +(3) ProjectExecTransformer +Output [2]: [hash(p_partkey#X, 42) AS hash_partition_key#X, p_partkey#X] +Input [2]: [p_partkey#X, p_name#X] + +(4) WholeStageCodegenTransformer (X) +Input [2]: [hash_partition_key#X, p_partkey#X] +Arguments: false + +(5) ColumnarExchange +Input [2]: [hash_partition_key#X, p_partkey#X] +Arguments: hashpartitioning(p_partkey#X, 1), ENSURE_REQUIREMENTS, [p_partkey#X], [plan_id=X], [id=#X] + +(6) ShuffleQueryStage +Output [1]: [p_partkey#X] +Arguments: X + +(7) InputAdapter +Input [1]: [p_partkey#X] + +(8) InputIteratorTransformer +Input [1]: [p_partkey#X] + +(9) Scan parquet +Output [6]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_partkey), IsNotNull(l_suppkey), IsNotNull(l_orderkey)] +ReadSchema: struct + +(10) FilterExecTransformer +Input [6]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] +Arguments: ((isnotnull(l_partkey#X) AND isnotnull(l_suppkey#X)) AND isnotnull(l_orderkey#X)) + +(11) ProjectExecTransformer +Output [7]: [hash(l_partkey#X, 42) AS hash_partition_key#X, l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] +Input [6]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] + +(12) WholeStageCodegenTransformer (X) +Input [7]: [hash_partition_key#X, l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] +Arguments: false + +(13) ColumnarExchange +Input [7]: [hash_partition_key#X, l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] +Arguments: hashpartitioning(l_partkey#X, 1), ENSURE_REQUIREMENTS, [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X], [plan_id=X], [id=#X] + +(14) ShuffleQueryStage +Output [6]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] +Arguments: X + +(15) InputAdapter +Input [6]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] + +(16) InputIteratorTransformer +Input [6]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] + +(17) ShuffledHashJoinExecTransformer +Left keys [1]: [p_partkey#X] +Right keys [1]: [l_partkey#X] +Join condition: None + +(18) ProjectExecTransformer +Output [7]: [hash(l_suppkey#X, 42) AS hash_partition_key#X, l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] +Input [7]: [p_partkey#X, l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] + +(19) WholeStageCodegenTransformer (X) +Input [7]: [hash_partition_key#X, l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] +Arguments: false + +(20) ColumnarExchange +Input [7]: [hash_partition_key#X, l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] +Arguments: hashpartitioning(l_suppkey#X, 1), ENSURE_REQUIREMENTS, [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X], [plan_id=X], [id=#X] + +(21) ShuffleQueryStage +Output [6]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] +Arguments: X + +(22) InputAdapter +Input [6]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] + +(23) InputIteratorTransformer +Input [6]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] + +(24) Scan parquet +Output [2]: [s_suppkey#X, s_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(s_suppkey), IsNotNull(s_nationkey)] +ReadSchema: struct + +(25) FilterExecTransformer +Input [2]: [s_suppkey#X, s_nationkey#X] +Arguments: (isnotnull(s_suppkey#X) AND isnotnull(s_nationkey#X)) + +(26) ProjectExecTransformer +Output [3]: [hash(s_suppkey#X, 42) AS hash_partition_key#X, s_suppkey#X, s_nationkey#X] +Input [2]: [s_suppkey#X, s_nationkey#X] + +(27) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, s_suppkey#X, s_nationkey#X] +Arguments: false + +(28) ColumnarExchange +Input [3]: [hash_partition_key#X, s_suppkey#X, s_nationkey#X] +Arguments: hashpartitioning(s_suppkey#X, 1), ENSURE_REQUIREMENTS, [s_suppkey#X, s_nationkey#X], [plan_id=X], [id=#X] + +(29) ShuffleQueryStage +Output [2]: [s_suppkey#X, s_nationkey#X] +Arguments: X + +(30) InputAdapter +Input [2]: [s_suppkey#X, s_nationkey#X] + +(31) InputIteratorTransformer +Input [2]: [s_suppkey#X, s_nationkey#X] + +(32) ShuffledHashJoinExecTransformer +Left keys [1]: [l_suppkey#X] +Right keys [1]: [s_suppkey#X] +Join condition: None + +(33) ProjectExecTransformer +Output [8]: [hash(l_suppkey#X, l_partkey#X, 42) AS hash_partition_key#X, l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X] +Input [8]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_suppkey#X, s_nationkey#X] + +(34) WholeStageCodegenTransformer (X) +Input [8]: [hash_partition_key#X, l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X] +Arguments: false + +(35) ColumnarExchange +Input [8]: [hash_partition_key#X, l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X] +Arguments: hashpartitioning(l_suppkey#X, l_partkey#X, 1), ENSURE_REQUIREMENTS, [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X], [plan_id=X], [id=#X] + +(36) ShuffleQueryStage +Output [7]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X] +Arguments: X + +(37) InputAdapter +Input [7]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X] + +(38) InputIteratorTransformer +Input [7]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X] + +(39) Scan parquet +Output [3]: [ps_partkey#X, ps_suppkey#X, ps_supplycost#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(ps_suppkey), IsNotNull(ps_partkey)] +ReadSchema: struct + +(40) FilterExecTransformer +Input [3]: [ps_partkey#X, ps_suppkey#X, ps_supplycost#X] +Arguments: (isnotnull(ps_suppkey#X) AND isnotnull(ps_partkey#X)) + +(41) ProjectExecTransformer +Output [4]: [hash(ps_suppkey#X, ps_partkey#X, 42) AS hash_partition_key#X, ps_partkey#X, ps_suppkey#X, ps_supplycost#X] +Input [3]: [ps_partkey#X, ps_suppkey#X, ps_supplycost#X] + +(42) WholeStageCodegenTransformer (X) +Input [4]: [hash_partition_key#X, ps_partkey#X, ps_suppkey#X, ps_supplycost#X] +Arguments: false + +(43) ColumnarExchange +Input [4]: [hash_partition_key#X, ps_partkey#X, ps_suppkey#X, ps_supplycost#X] +Arguments: hashpartitioning(ps_suppkey#X, ps_partkey#X, 1), ENSURE_REQUIREMENTS, [ps_partkey#X, ps_suppkey#X, ps_supplycost#X], [plan_id=X], [id=#X] + +(44) ShuffleQueryStage +Output [3]: [ps_partkey#X, ps_suppkey#X, ps_supplycost#X] +Arguments: X + +(45) InputAdapter +Input [3]: [ps_partkey#X, ps_suppkey#X, ps_supplycost#X] + +(46) InputIteratorTransformer +Input [3]: [ps_partkey#X, ps_suppkey#X, ps_supplycost#X] + +(47) ShuffledHashJoinExecTransformer +Left keys [2]: [l_suppkey#X, l_partkey#X] +Right keys [2]: [ps_suppkey#X, ps_partkey#X] +Join condition: None + +(48) ProjectExecTransformer +Output [7]: [hash(l_orderkey#X, 42) AS hash_partition_key#X, l_orderkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X, ps_supplycost#X] +Input [10]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X, ps_partkey#X, ps_suppkey#X, ps_supplycost#X] + +(49) WholeStageCodegenTransformer (X) +Input [7]: [hash_partition_key#X, l_orderkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X, ps_supplycost#X] +Arguments: false + +(50) ColumnarExchange +Input [7]: [hash_partition_key#X, l_orderkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X, ps_supplycost#X] +Arguments: hashpartitioning(l_orderkey#X, 1), ENSURE_REQUIREMENTS, [l_orderkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X, ps_supplycost#X], [plan_id=X], [id=#X] + +(51) ShuffleQueryStage +Output [6]: [l_orderkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X, ps_supplycost#X] +Arguments: X + +(52) InputAdapter +Input [6]: [l_orderkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X, ps_supplycost#X] + +(53) InputIteratorTransformer +Input [6]: [l_orderkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X, ps_supplycost#X] + +(54) Scan parquet +Output [2]: [o_orderkey#X, o_orderdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_orderkey)] +ReadSchema: struct + +(55) FilterExecTransformer +Input [2]: [o_orderkey#X, o_orderdate#X] +Arguments: isnotnull(o_orderkey#X) + +(56) ProjectExecTransformer +Output [3]: [hash(o_orderkey#X, 42) AS hash_partition_key#X, o_orderkey#X, o_orderdate#X] +Input [2]: [o_orderkey#X, o_orderdate#X] + +(57) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, o_orderkey#X, o_orderdate#X] +Arguments: false + +(58) ColumnarExchange +Input [3]: [hash_partition_key#X, o_orderkey#X, o_orderdate#X] +Arguments: hashpartitioning(o_orderkey#X, 1), ENSURE_REQUIREMENTS, [o_orderkey#X, o_orderdate#X], [plan_id=X], [id=#X] + +(59) ShuffleQueryStage +Output [2]: [o_orderkey#X, o_orderdate#X] +Arguments: X + +(60) InputAdapter +Input [2]: [o_orderkey#X, o_orderdate#X] + +(61) InputIteratorTransformer +Input [2]: [o_orderkey#X, o_orderdate#X] + +(62) ShuffledHashJoinExecTransformer +Left keys [1]: [l_orderkey#X] +Right keys [1]: [o_orderkey#X] +Join condition: None + +(63) ProjectExecTransformer +Output [7]: [hash(s_nationkey#X, 42) AS hash_partition_key#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X, ps_supplycost#X, o_orderdate#X] +Input [8]: [l_orderkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X, ps_supplycost#X, o_orderkey#X, o_orderdate#X] + +(64) WholeStageCodegenTransformer (X) +Input [7]: [hash_partition_key#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X, ps_supplycost#X, o_orderdate#X] +Arguments: false + +(65) ColumnarExchange +Input [7]: [hash_partition_key#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X, ps_supplycost#X, o_orderdate#X] +Arguments: hashpartitioning(s_nationkey#X, 1), ENSURE_REQUIREMENTS, [l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X, ps_supplycost#X, o_orderdate#X], [plan_id=X], [id=#X] + +(66) ShuffleQueryStage +Output [6]: [l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X, ps_supplycost#X, o_orderdate#X] +Arguments: X + +(67) InputAdapter +Input [6]: [l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X, ps_supplycost#X, o_orderdate#X] + +(68) InputIteratorTransformer +Input [6]: [l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X, ps_supplycost#X, o_orderdate#X] + +(69) Scan parquet +Output [2]: [n_nationkey#X, n_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_nationkey)] +ReadSchema: struct + +(70) FilterExecTransformer +Input [2]: [n_nationkey#X, n_name#X] +Arguments: isnotnull(n_nationkey#X) + +(71) ProjectExecTransformer +Output [3]: [hash(n_nationkey#X, 42) AS hash_partition_key#X, n_nationkey#X, n_name#X] +Input [2]: [n_nationkey#X, n_name#X] + +(72) WholeStageCodegenTransformer (X) +Input [3]: [hash_partition_key#X, n_nationkey#X, n_name#X] +Arguments: false + +(73) ColumnarExchange +Input [3]: [hash_partition_key#X, n_nationkey#X, n_name#X] +Arguments: hashpartitioning(n_nationkey#X, 1), ENSURE_REQUIREMENTS, [n_nationkey#X, n_name#X], [plan_id=X], [id=#X] + +(74) ShuffleQueryStage +Output [2]: [n_nationkey#X, n_name#X] +Arguments: X + +(75) InputAdapter +Input [2]: [n_nationkey#X, n_name#X] + +(76) InputIteratorTransformer +Input [2]: [n_nationkey#X, n_name#X] + +(77) ShuffledHashJoinExecTransformer +Left keys [1]: [s_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: None + +(78) ProjectExecTransformer +Output [3]: [n_name#X AS nation#X, year(o_orderdate#X) AS o_year#X, CheckOverflow((promote_precision(cast(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) as decimal(27,4))) - promote_precision(cast(CheckOverflow((promote_precision(ps_supplycost#X) * promote_precision(l_quantity#X)), DecimalType(25,4), true) as decimal(27,4)))), DecimalType(27,4), true) AS amount#X] +Input [8]: [l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X, ps_supplycost#X, o_orderdate#X, n_nationkey#X, n_name#X] + +(79) FlushableHashAggregateExecTransformer +Input [3]: [nation#X, o_year#X, amount#X] +Keys [2]: [nation#X, o_year#X] +Functions [1]: [partial_sum(amount#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [4]: [nation#X, o_year#X, sum#X, isEmpty#X] + +(80) ProjectExecTransformer +Output [5]: [hash(nation#X, o_year#X, 42) AS hash_partition_key#X, nation#X, o_year#X, sum#X, isEmpty#X] +Input [4]: [nation#X, o_year#X, sum#X, isEmpty#X] + +(81) WholeStageCodegenTransformer (X) +Input [5]: [hash_partition_key#X, nation#X, o_year#X, sum#X, isEmpty#X] +Arguments: false + +(82) ColumnarExchange +Input [5]: [hash_partition_key#X, nation#X, o_year#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(nation#X, o_year#X, 1), ENSURE_REQUIREMENTS, [nation#X, o_year#X, sum#X, isEmpty#X], [plan_id=X], [id=#X] + +(83) ShuffleQueryStage +Output [4]: [nation#X, o_year#X, sum#X, isEmpty#X] +Arguments: X + +(84) InputAdapter +Input [4]: [nation#X, o_year#X, sum#X, isEmpty#X] + +(85) InputIteratorTransformer +Input [4]: [nation#X, o_year#X, sum#X, isEmpty#X] + +(86) RegularHashAggregateExecTransformer +Input [4]: [nation#X, o_year#X, sum#X, isEmpty#X] +Keys [2]: [nation#X, o_year#X] +Functions [1]: [sum(amount#X)] +Aggregate Attributes [1]: [sum(amount#X)#X] +Results [3]: [nation#X, o_year#X, sum(amount#X)#X AS sum_profit#X] + +(87) WholeStageCodegenTransformer (X) +Input [3]: [nation#X, o_year#X, sum_profit#X] +Arguments: false + +(88) ColumnarExchange +Input [3]: [nation#X, o_year#X, sum_profit#X] +Arguments: rangepartitioning(nation#X ASC NULLS FIRST, o_year#X DESC NULLS LAST, 1), ENSURE_REQUIREMENTS, [plan_id=X], [id=#X] + +(89) ShuffleQueryStage +Output [3]: [nation#X, o_year#X, sum_profit#X] +Arguments: X + +(90) InputAdapter +Input [3]: [nation#X, o_year#X, sum_profit#X] + +(91) InputIteratorTransformer +Input [3]: [nation#X, o_year#X, sum_profit#X] + +(92) SortExecTransformer +Input [3]: [nation#X, o_year#X, sum_profit#X] +Arguments: [nation#X ASC NULLS FIRST, o_year#X DESC NULLS LAST], true, 0 + +(93) WholeStageCodegenTransformer (X) +Input [3]: [nation#X, o_year#X, sum_profit#X] +Arguments: false + +(94) VeloxColumnarToRowExec +Input [3]: [nation#X, o_year#X, sum_profit#X] + +(95) Scan parquet +Output [2]: [p_partkey#X, p_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(p_name), StringContains(p_name,green), IsNotNull(p_partkey)] +ReadSchema: struct + +(96) Filter +Input [2]: [p_partkey#X, p_name#X] +Condition : ((isnotnull(p_name#X) AND Contains(p_name#X, green)) AND isnotnull(p_partkey#X)) + +(97) Project +Output [1]: [p_partkey#X] +Input [2]: [p_partkey#X, p_name#X] + +(98) Exchange +Input [1]: [p_partkey#X] +Arguments: hashpartitioning(p_partkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(99) Scan parquet +Output [6]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(l_partkey), IsNotNull(l_suppkey), IsNotNull(l_orderkey)] +ReadSchema: struct + +(100) Filter +Input [6]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] +Condition : ((isnotnull(l_partkey#X) AND isnotnull(l_suppkey#X)) AND isnotnull(l_orderkey#X)) + +(101) Exchange +Input [6]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] +Arguments: hashpartitioning(l_partkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(102) ShuffledHashJoin +Left keys [1]: [p_partkey#X] +Right keys [1]: [l_partkey#X] +Join condition: None + +(103) Project +Output [6]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] +Input [7]: [p_partkey#X, l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] + +(104) Exchange +Input [6]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X] +Arguments: hashpartitioning(l_suppkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(105) Scan parquet +Output [2]: [s_suppkey#X, s_nationkey#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(s_suppkey), IsNotNull(s_nationkey)] +ReadSchema: struct + +(106) Filter +Input [2]: [s_suppkey#X, s_nationkey#X] +Condition : (isnotnull(s_suppkey#X) AND isnotnull(s_nationkey#X)) + +(107) Exchange +Input [2]: [s_suppkey#X, s_nationkey#X] +Arguments: hashpartitioning(s_suppkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(108) ShuffledHashJoin +Left keys [1]: [l_suppkey#X] +Right keys [1]: [s_suppkey#X] +Join condition: None + +(109) Project +Output [7]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X] +Input [8]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_suppkey#X, s_nationkey#X] + +(110) Exchange +Input [7]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X] +Arguments: hashpartitioning(l_suppkey#X, l_partkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(111) Scan parquet +Output [3]: [ps_partkey#X, ps_suppkey#X, ps_supplycost#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(ps_suppkey), IsNotNull(ps_partkey)] +ReadSchema: struct + +(112) Filter +Input [3]: [ps_partkey#X, ps_suppkey#X, ps_supplycost#X] +Condition : (isnotnull(ps_suppkey#X) AND isnotnull(ps_partkey#X)) + +(113) Exchange +Input [3]: [ps_partkey#X, ps_suppkey#X, ps_supplycost#X] +Arguments: hashpartitioning(ps_suppkey#X, ps_partkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(114) ShuffledHashJoin +Left keys [2]: [l_suppkey#X, l_partkey#X] +Right keys [2]: [ps_suppkey#X, ps_partkey#X] +Join condition: None + +(115) Project +Output [6]: [l_orderkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X, ps_supplycost#X] +Input [10]: [l_orderkey#X, l_partkey#X, l_suppkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X, ps_partkey#X, ps_suppkey#X, ps_supplycost#X] + +(116) Exchange +Input [6]: [l_orderkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X, ps_supplycost#X] +Arguments: hashpartitioning(l_orderkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(117) Scan parquet +Output [2]: [o_orderkey#X, o_orderdate#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(o_orderkey)] +ReadSchema: struct + +(118) Filter +Input [2]: [o_orderkey#X, o_orderdate#X] +Condition : isnotnull(o_orderkey#X) + +(119) Exchange +Input [2]: [o_orderkey#X, o_orderdate#X] +Arguments: hashpartitioning(o_orderkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(120) ShuffledHashJoin +Left keys [1]: [l_orderkey#X] +Right keys [1]: [o_orderkey#X] +Join condition: None + +(121) Project +Output [6]: [l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X, ps_supplycost#X, o_orderdate#X] +Input [8]: [l_orderkey#X, l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X, ps_supplycost#X, o_orderkey#X, o_orderdate#X] + +(122) Exchange +Input [6]: [l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X, ps_supplycost#X, o_orderdate#X] +Arguments: hashpartitioning(s_nationkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(123) Scan parquet +Output [2]: [n_nationkey#X, n_name#X] +Batched: true +Location: InMemoryFileIndex [*] +PushedFilters: [IsNotNull(n_nationkey)] +ReadSchema: struct + +(124) Filter +Input [2]: [n_nationkey#X, n_name#X] +Condition : isnotnull(n_nationkey#X) + +(125) Exchange +Input [2]: [n_nationkey#X, n_name#X] +Arguments: hashpartitioning(n_nationkey#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(126) ShuffledHashJoin +Left keys [1]: [s_nationkey#X] +Right keys [1]: [n_nationkey#X] +Join condition: None + +(127) Project +Output [3]: [n_name#X AS nation#X, year(o_orderdate#X) AS o_year#X, CheckOverflow((promote_precision(cast(CheckOverflow((promote_precision(cast(l_extendedprice#X as decimal(13,2))) * promote_precision(CheckOverflow((1.00 - promote_precision(cast(l_discount#X as decimal(13,2)))), DecimalType(13,2), true))), DecimalType(26,4), true) as decimal(27,4))) - promote_precision(cast(CheckOverflow((promote_precision(ps_supplycost#X) * promote_precision(l_quantity#X)), DecimalType(25,4), true) as decimal(27,4)))), DecimalType(27,4), true) AS amount#X] +Input [8]: [l_quantity#X, l_extendedprice#X, l_discount#X, s_nationkey#X, ps_supplycost#X, o_orderdate#X, n_nationkey#X, n_name#X] + +(128) HashAggregate +Input [3]: [nation#X, o_year#X, amount#X] +Keys [2]: [nation#X, o_year#X] +Functions [1]: [partial_sum(amount#X)] +Aggregate Attributes [2]: [sum#X, isEmpty#X] +Results [4]: [nation#X, o_year#X, sum#X, isEmpty#X] + +(129) Exchange +Input [4]: [nation#X, o_year#X, sum#X, isEmpty#X] +Arguments: hashpartitioning(nation#X, o_year#X, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(130) HashAggregate +Input [4]: [nation#X, o_year#X, sum#X, isEmpty#X] +Keys [2]: [nation#X, o_year#X] +Functions [1]: [sum(amount#X)] +Aggregate Attributes [1]: [sum(amount#X)#X] +Results [3]: [nation#X, o_year#X, sum(amount#X)#X AS sum_profit#X] + +(131) Exchange +Input [3]: [nation#X, o_year#X, sum_profit#X] +Arguments: rangepartitioning(nation#X ASC NULLS FIRST, o_year#X DESC NULLS LAST, 1), ENSURE_REQUIREMENTS, [plan_id=X] + +(132) Sort +Input [3]: [nation#X, o_year#X, sum_profit#X] +Arguments: [nation#X ASC NULLS FIRST, o_year#X DESC NULLS LAST], true, 0 + +(133) AdaptiveSparkPlan +Output [3]: [nation#X, o_year#X, sum_profit#X] +Arguments: isFinalPlan=true \ No newline at end of file diff --git a/backends-velox/src/test/scala/io/glutenproject/execution/VeloxTPCHSuite.scala b/backends-velox/src/test/scala/io/glutenproject/execution/VeloxTPCHSuite.scala index 721cff99b81b..5c84e292d697 100644 --- a/backends-velox/src/test/scala/io/glutenproject/execution/VeloxTPCHSuite.scala +++ b/backends-velox/src/test/scala/io/glutenproject/execution/VeloxTPCHSuite.scala @@ -17,9 +17,13 @@ package io.glutenproject.execution import org.apache.spark.SparkConf -import org.apache.spark.sql.{Row, TestUtils} +import org.apache.spark.sql.{DataFrame, Row, TestUtils} +import org.apache.spark.sql.execution.FormattedMode + +import org.apache.commons.io.FileUtils import java.io.File +import java.nio.charset.StandardCharsets abstract class VeloxTPCHTableSupport extends VeloxWholeStageTransformerSuite { protected val rootPath: String = getClass.getResource("/").getPath @@ -42,6 +46,8 @@ abstract class VeloxTPCHTableSupport extends VeloxWholeStageTransformerSuite { .set("spark.memory.offHeap.size", "2g") .set("spark.unsafe.exceptionOnMemoryLeak", "true") .set("spark.sql.autoBroadcastJoinThreshold", "-1") + // TODO Should enable this after fix the issue of native plan detail occasional disappearance + // .set("spark.gluten.sql.injectNativePlanStringToExplain", "true") } override def beforeAll(): Unit = { @@ -51,135 +57,186 @@ abstract class VeloxTPCHTableSupport extends VeloxWholeStageTransformerSuite { } abstract class VeloxTPCHSuite extends VeloxTPCHTableSupport { + private lazy val formatSparkVersion: String = spark.version.replace(".", "") + + private def formatMaterializedPlan(plan: String): String = { + plan + .replaceAll("#[0-9]*L*", "#X") + .replaceAll("plan_id=[0-9]*", "plan_id=X") + .replaceAll("Statistics[(A-Za-z0-9=. ,+)]*", "Statistics(X)") + .replaceAll("WholeStageCodegenTransformer[0-9 ()]*", "WholeStageCodegenTransformer (X)") + .replaceAll("\\[file:[.\\-/a-zA-z0-9= ,_%]*]", "[*]") + // for unexpected blank + .replaceAll("Scan parquet ", "Scan parquet") + // Spark QueryStageExec will take it's id as argument, replace it with X + .replaceAll("Arguments: [0-9]+", "Arguments: X") + .trim + } + + private def getGoldenFile(path: String): String = { + FileUtils.readFileToString(new File(path), StandardCharsets.UTF_8).trim + } + + def subType(): String = "" + def shouldCheckGoldenFiles(): Boolean = { + Seq("v1", "v1-bhj").contains(subType()) && (formatSparkVersion match { + case "322" => true + case "331" => false + case "342" => false + case _ => false + }) + } + + private def checkGoldenFile(df: DataFrame, id: Int): Unit = { + // skip checking golden file for non-ready subtype and spark version + if (!shouldCheckGoldenFiles) { + return + } + val file = s"tpch-approved-plan/${subType()}/spark$formatSparkVersion/$id.txt" + val actual = formatMaterializedPlan(df.queryExecution.explainString(FormattedMode)) + val path = s"$rootPath$file" + // due to assert throw too much info + // let's check and print diff manually + if (!getGoldenFile(path).equals(actual)) { + val actualFile = new File(FileUtils.getTempDirectory, file) + new File(actualFile.getParent).mkdirs() + FileUtils.writeStringToFile(actualFile, actual, StandardCharsets.UTF_8) + org.scalatest.Assertions.fail( + s"Mismatch for query $id\n" + + s"Actual Plan path: ${actualFile.getAbsolutePath}\n" + + s"Golden Plan path: $path") + } + } + test("TPC-H q1") { runTPCHQuery(1, veloxTPCHQueries, queriesResults, compareResult = false, noFallBack = false) { - _ => + checkGoldenFile(_, 1) } } test("TPC-H q2") { runTPCHQuery(2, veloxTPCHQueries, queriesResults, compareResult = false, noFallBack = false) { - _ => + _ => // due to tpc-h q2 will generate multiple plans, skip checking golden file for now } } test("TPC-H q3") { runTPCHQuery(3, veloxTPCHQueries, queriesResults, compareResult = false, noFallBack = false) { - _ => + checkGoldenFile(_, 3) } } test("TPC-H q4") { runTPCHQuery(4, veloxTPCHQueries, queriesResults, compareResult = false, noFallBack = false) { - _ => + checkGoldenFile(_, 4) } } test("TPC-H q5") { runTPCHQuery(5, veloxTPCHQueries, queriesResults, compareResult = false, noFallBack = false) { - _ => + checkGoldenFile(_, 5) } } test("TPC-H q6") { runTPCHQuery(6, veloxTPCHQueries, queriesResults, compareResult = false, noFallBack = false) { - _ => + checkGoldenFile(_, 6) } } test("TPC-H q7") { runTPCHQuery(7, veloxTPCHQueries, queriesResults, compareResult = false, noFallBack = false) { - _ => + checkGoldenFile(_, 7) } } test("TPC-H q8") { runTPCHQuery(8, veloxTPCHQueries, queriesResults, compareResult = false, noFallBack = false) { - _ => + checkGoldenFile(_, 8) } } test("TPC-H q9") { runTPCHQuery(9, veloxTPCHQueries, queriesResults, compareResult = false, noFallBack = false) { - _ => + checkGoldenFile(_, 9) } } test("TPC-H q10") { runTPCHQuery(10, veloxTPCHQueries, queriesResults, compareResult = false, noFallBack = false) { - _ => + checkGoldenFile(_, 10) } } test("TPC-H q11") { runTPCHQuery(11, veloxTPCHQueries, queriesResults, compareResult = false, noFallBack = false) { - _ => + checkGoldenFile(_, 11) } } test("TPC-H q12") { runTPCHQuery(12, veloxTPCHQueries, queriesResults, compareResult = false, noFallBack = false) { - _ => + checkGoldenFile(_, 12) } } test("TPC-H q13") { runTPCHQuery(13, veloxTPCHQueries, queriesResults, compareResult = false, noFallBack = false) { - _ => + checkGoldenFile(_, 13) } } test("TPC-H q14") { runTPCHQuery(14, veloxTPCHQueries, queriesResults, compareResult = false, noFallBack = false) { - _ => + checkGoldenFile(_, 14) } } test("TPC-H q15") { runTPCHQuery(15, veloxTPCHQueries, queriesResults, compareResult = false, noFallBack = false) { - _ => + checkGoldenFile(_, 15) } } test("TPC-H q16") { runTPCHQuery(16, veloxTPCHQueries, queriesResults, compareResult = false, noFallBack = false) { - _ => + checkGoldenFile(_, 16) } } test("TPC-H q17") { runTPCHQuery(17, veloxTPCHQueries, queriesResults, compareResult = false, noFallBack = false) { - _ => + checkGoldenFile(_, 17) } } test("TPC-H q18") { runTPCHQuery(18, veloxTPCHQueries, queriesResults, compareResult = false, noFallBack = false) { - _ => + checkGoldenFile(_, 18) } } test("TPC-H q19") { runTPCHQuery(19, veloxTPCHQueries, queriesResults, compareResult = false, noFallBack = false) { - _ => + checkGoldenFile(_, 19) } } test("TPC-H q20") { runTPCHQuery(20, veloxTPCHQueries, queriesResults, compareResult = false, noFallBack = false) { - _ => + checkGoldenFile(_, 20) } } test("TPC-H q21") { runTPCHQuery(21, veloxTPCHQueries, queriesResults, compareResult = false, noFallBack = false) { - _ => + checkGoldenFile(_, 21) } } test("TPC-H q22") { runTPCHQuery(22, veloxTPCHQueries, queriesResults, compareResult = false, noFallBack = false) { - _ => + checkGoldenFile(_, 22) } } @@ -213,6 +270,8 @@ class VeloxTPCHDistinctSpill extends VeloxTPCHTableSupport { } class VeloxTPCHV1Suite extends VeloxTPCHSuite { + override def subType(): String = "v1" + override protected def sparkConf: SparkConf = { super.sparkConf .set("spark.sql.sources.useV1SourceList", "parquet") @@ -221,6 +280,8 @@ class VeloxTPCHV1Suite extends VeloxTPCHSuite { } class VeloxTPCHV1BhjSuite extends VeloxTPCHSuite { + override def subType(): String = "v1-bhj" + override protected def sparkConf: SparkConf = { super.sparkConf .set("spark.sql.sources.useV1SourceList", "parquet") @@ -229,6 +290,8 @@ class VeloxTPCHV1BhjSuite extends VeloxTPCHSuite { } class VeloxTPCHV2Suite extends VeloxTPCHSuite { + override def subType(): String = "v2" + override protected def sparkConf: SparkConf = { super.sparkConf .set("spark.sql.sources.useV1SourceList", "") @@ -237,6 +300,8 @@ class VeloxTPCHV2Suite extends VeloxTPCHSuite { } class VeloxTPCHV2BhjSuite extends VeloxTPCHSuite { + override def subType(): String = "v2-bhj" + override protected def sparkConf: SparkConf = { super.sparkConf .set("spark.sql.sources.useV1SourceList", "") @@ -245,6 +310,7 @@ class VeloxTPCHV2BhjSuite extends VeloxTPCHSuite { } class VeloxPartitionedTableTPCHSuite extends VeloxTPCHSuite { + override def subType(): String = "partitioned" override protected def sparkConf: SparkConf = { super.sparkConf.set("spark.memory.offHeap.size", "4g") @@ -275,6 +341,8 @@ class VeloxPartitionedTableTPCHSuite extends VeloxTPCHSuite { } class VeloxTPCHV1GlutenBhjVanillaBeSuite extends VeloxTPCHSuite { + override def subType(): String = "gluten-bhj-vanilla-be" + override protected def sparkConf: SparkConf = { super.sparkConf .set("spark.sql.sources.useV1SourceList", "parquet") @@ -285,6 +353,8 @@ class VeloxTPCHV1GlutenBhjVanillaBeSuite extends VeloxTPCHSuite { } class VeloxTPCHV1VanillaBhjGlutenBeSuite extends VeloxTPCHSuite { + override def subType(): String = "vanilla-bhj-gluten-be" + override protected def sparkConf: SparkConf = { super.sparkConf .set("spark.sql.sources.useV1SourceList", "parquet") diff --git a/docs/developers/NewToGluten.md b/docs/developers/NewToGluten.md index d27718dc5e7f..2cf67dcf625c 100644 --- a/docs/developers/NewToGluten.md +++ b/docs/developers/NewToGluten.md @@ -374,3 +374,22 @@ spark-shell --name run_gluten \ --jars https://github.com/oap-project/gluten/releases/download/v1.0.0/gluten-velox-bundle-spark3.2_2.12-ubuntu_20.04_x86_64-1.0.0.jar \ --conf spark.shuffle.manager=org.apache.spark.shuffle.sort.ColumnarShuffleManager ``` + +# Check Gluten Approved Spark Plan + +To make sure we don't accidentally modify the Gluten and Spark Plan build logic. +We introduce new logic in `VeloxTPCHSuite` to check whether the plan has been changed or not, +and this will be triggered when running the unit test. + +As a result, developers may encounter unit test fail in Github CI or locally, with the following error message: +```log +- TPC-H q5 *** FAILED *** + Mismatch for query 5 + Actual Plan path: /tmp/tpch-approved-plan/v2-bhj/spark322/5.txt + Golden Plan path: /opt/gluten/backends-velox/target/scala-2.12/test-classes/tpch-approved-plan/v2-bhj/spark322/5.txt (VeloxTPCHSuite.scala:101) +``` +For developers to update the golden plan, you can find the actual plan in Github CI Artifacts or in local `/tmp/` directory. + +![](../image/gluten_golden_file_upload.png) + +Developers can simply copy the actual plan to the golden plan path, and then re-run the unit test to make sure the plan is stabled. diff --git a/docs/image/gluten_golden_file_upload.png b/docs/image/gluten_golden_file_upload.png new file mode 100644 index 0000000000000000000000000000000000000000..3c0e884a6629586433c48abd3cb502642b7bf635 GIT binary patch literal 28636435 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

    w?k#^wX+~4GB=ZewbkPs7-UZrX^ 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

    ~vK-C2jA|i~}64Q(xQPI}LM_x#t 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%0D)1qM3eoadDxKmYhZa0R#|0 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 a*ZE)l;|c$H>