diff --git a/presto-benchto-benchmarks/src/test/resources/sql/presto/tpcds/q05.plan.txt b/presto-benchto-benchmarks/src/test/resources/sql/presto/tpcds/q05.plan.txt index 9577f71abc72..3d2e86f7b3c1 100644 --- a/presto-benchto-benchmarks/src/test/resources/sql/presto/tpcds/q05.plan.txt +++ b/presto-benchto-benchmarks/src/test/resources/sql/presto/tpcds/q05.plan.txt @@ -1,57 +1,56 @@ -local exchange (GATHER, SINGLE, []) - remote exchange (GATHER, SINGLE, []) - final aggregation over (channel$gid, groupid, id$gid) - local exchange (REPARTITION, HASH, ["channel$gid", "groupid", "id$gid"]) - remote exchange (REPARTITION, HASH, ["channel$gid", "groupid", "id$gid"]) - partial aggregation over (channel$gid, groupid, id$gid) - local exchange (REPARTITION, ROUND_ROBIN, []) - final aggregation over (s_store_id) - local exchange (GATHER, SINGLE, []) - remote exchange (REPARTITION, HASH, ["s_store_id"]) - partial aggregation over (s_store_id) +remote exchange (GATHER, SINGLE, []) + final aggregation over (channel$gid, groupid, id$gid) + local exchange (REPARTITION, HASH, ["channel$gid", "groupid", "id$gid"]) + remote exchange (REPARTITION, HASH, ["channel$gid", "groupid", "id$gid"]) + partial aggregation over (channel$gid, groupid, id$gid) + local exchange (REPARTITION, ROUND_ROBIN, []) + final aggregation over (s_store_id) + local exchange (GATHER, SINGLE, []) + remote exchange (REPARTITION, HASH, ["s_store_id"]) + partial aggregation over (s_store_id) + join (INNER, REPLICATED): join (INNER, REPLICATED): - join (INNER, REPLICATED): - remote exchange (REPARTITION, ROUND_ROBIN, []) - scan store_sales - scan store_returns - local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - scan date_dim + remote exchange (REPARTITION, ROUND_ROBIN, []) + scan store_sales + scan store_returns local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) - scan store - final aggregation over (cp_catalog_page_id) - local exchange (GATHER, SINGLE, []) - remote exchange (REPARTITION, HASH, ["cp_catalog_page_id"]) - partial aggregation over (cp_catalog_page_id) + scan date_dim + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + scan store + final aggregation over (cp_catalog_page_id) + local exchange (GATHER, SINGLE, []) + remote exchange (REPARTITION, HASH, ["cp_catalog_page_id"]) + partial aggregation over (cp_catalog_page_id) + join (INNER, REPLICATED): join (INNER, REPLICATED): - join (INNER, REPLICATED): - remote exchange (REPARTITION, ROUND_ROBIN, []) - scan catalog_sales - scan catalog_returns - local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - scan date_dim + remote exchange (REPARTITION, ROUND_ROBIN, []) + scan catalog_sales + scan catalog_returns local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) - scan catalog_page - final aggregation over (web_site_id) - local exchange (GATHER, SINGLE, []) - remote exchange (REPARTITION, HASH, ["web_site_id"]) - partial aggregation over (web_site_id) + scan date_dim + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + scan catalog_page + final aggregation over (web_site_id) + local exchange (GATHER, SINGLE, []) + remote exchange (REPARTITION, HASH, ["web_site_id"]) + partial aggregation over (web_site_id) + join (INNER, REPLICATED): join (INNER, REPLICATED): - join (INNER, REPLICATED): - remote exchange (REPARTITION, ROUND_ROBIN, []) - scan web_sales - join (RIGHT, PARTITIONED): - remote exchange (REPARTITION, HASH, ["ws_item_sk_216", "ws_order_number_230"]) - scan web_sales - local exchange (GATHER, SINGLE, []) - remote exchange (REPARTITION, HASH, ["wr_item_sk", "wr_order_number"]) - scan web_returns - local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - scan date_dim + remote exchange (REPARTITION, ROUND_ROBIN, []) + scan web_sales + join (RIGHT, PARTITIONED): + remote exchange (REPARTITION, HASH, ["ws_item_sk_216", "ws_order_number_230"]) + scan web_sales + local exchange (GATHER, SINGLE, []) + remote exchange (REPARTITION, HASH, ["wr_item_sk", "wr_order_number"]) + scan web_returns local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) - scan web_site + scan date_dim + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + scan web_site diff --git a/presto-benchto-benchmarks/src/test/resources/sql/presto/tpcds/q14_1.plan.txt b/presto-benchto-benchmarks/src/test/resources/sql/presto/tpcds/q14_1.plan.txt index ec4c1ac8a901..f49defc441a0 100644 --- a/presto-benchto-benchmarks/src/test/resources/sql/presto/tpcds/q14_1.plan.txt +++ b/presto-benchto-benchmarks/src/test/resources/sql/presto/tpcds/q14_1.plan.txt @@ -1,244 +1,243 @@ -local exchange (GATHER, SINGLE, []) - remote exchange (GATHER, SINGLE, []) - final aggregation over (channel$gid, groupid, i_brand_id$gid_1742, i_category_id$gid_1744, i_class_id$gid_1743) - local exchange (REPARTITION, HASH, ["channel$gid", "groupid", "i_brand_id$gid_1742", "i_category_id$gid_1744", "i_class_id$gid_1743"]) - remote exchange (REPARTITION, HASH, ["channel$gid", "groupid", "i_brand_id$gid_1742", "i_category_id$gid_1744", "i_class_id$gid_1743"]) - partial aggregation over (channel$gid, groupid, i_brand_id$gid_1742, i_category_id$gid_1744, i_class_id$gid_1743) - local exchange (REPARTITION, ROUND_ROBIN, []) - cross join: - final aggregation over (i_brand_id, i_category_id, i_class_id) - local exchange (GATHER, SINGLE, []) - remote exchange (REPARTITION, HASH, ["i_brand_id", "i_category_id", "i_class_id"]) - partial aggregation over (i_brand_id, i_category_id, i_class_id) - semijoin (PARTITIONED): - remote exchange (REPARTITION, HASH, ["ss_item_sk"]) +remote exchange (GATHER, SINGLE, []) + final aggregation over (channel$gid, groupid, i_brand_id$gid_1742, i_category_id$gid_1744, i_class_id$gid_1743) + local exchange (REPARTITION, HASH, ["channel$gid", "groupid", "i_brand_id$gid_1742", "i_category_id$gid_1744", "i_class_id$gid_1743"]) + remote exchange (REPARTITION, HASH, ["channel$gid", "groupid", "i_brand_id$gid_1742", "i_category_id$gid_1744", "i_class_id$gid_1743"]) + partial aggregation over (channel$gid, groupid, i_brand_id$gid_1742, i_category_id$gid_1744, i_class_id$gid_1743) + local exchange (REPARTITION, ROUND_ROBIN, []) + cross join: + final aggregation over (i_brand_id, i_category_id, i_class_id) + local exchange (GATHER, SINGLE, []) + remote exchange (REPARTITION, HASH, ["i_brand_id", "i_category_id", "i_class_id"]) + partial aggregation over (i_brand_id, i_category_id, i_class_id) + semijoin (PARTITIONED): + remote exchange (REPARTITION, HASH, ["ss_item_sk"]) + join (INNER, REPLICATED): join (INNER, REPLICATED): - join (INNER, REPLICATED): - scan store_sales - local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - scan date_dim + scan store_sales local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) - scan item - local exchange (GATHER, SINGLE, []) - remote exchange (REPARTITION, HASH, ["i_item_sk_1"]) - join (INNER, PARTITIONED): - remote exchange (REPARTITION, HASH, ["i_brand_id_8", "i_category_id_12", "i_class_id_10"]) - scan item - final aggregation over (expr_216, expr_217, expr_218) - local exchange (GATHER, SINGLE, []) - remote exchange (REPARTITION, HASH, ["i_brand_id_53", "i_category_id_57", "i_class_id_55"]) - partial aggregation over (i_brand_id_53, i_category_id_57, i_class_id_55) + scan date_dim + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + scan item + local exchange (GATHER, SINGLE, []) + remote exchange (REPARTITION, HASH, ["i_item_sk_1"]) + join (INNER, PARTITIONED): + remote exchange (REPARTITION, HASH, ["i_brand_id_8", "i_category_id_12", "i_class_id_10"]) + scan item + final aggregation over (expr_216, expr_217, expr_218) + local exchange (GATHER, SINGLE, []) + remote exchange (REPARTITION, HASH, ["i_brand_id_53", "i_category_id_57", "i_class_id_55"]) + partial aggregation over (i_brand_id_53, i_category_id_57, i_class_id_55) + join (INNER, REPLICATED): join (INNER, REPLICATED): - join (INNER, REPLICATED): - scan store_sales - local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - scan date_dim + scan store_sales local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) - scan item - remote exchange (REPARTITION, HASH, ["i_brand_id_108", "i_category_id_112", "i_class_id_110"]) - partial aggregation over (i_brand_id_108, i_category_id_112, i_class_id_110) + scan date_dim + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + scan item + remote exchange (REPARTITION, HASH, ["i_brand_id_108", "i_category_id_112", "i_class_id_110"]) + partial aggregation over (i_brand_id_108, i_category_id_112, i_class_id_110) + join (INNER, REPLICATED): join (INNER, REPLICATED): - join (INNER, REPLICATED): - scan catalog_sales - local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - scan date_dim + scan catalog_sales local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) - scan item - remote exchange (REPARTITION, HASH, ["i_brand_id_167", "i_category_id_171", "i_class_id_169"]) - partial aggregation over (i_brand_id_167, i_category_id_171, i_class_id_169) + scan date_dim + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + scan item + remote exchange (REPARTITION, HASH, ["i_brand_id_167", "i_category_id_171", "i_class_id_169"]) + partial aggregation over (i_brand_id_167, i_category_id_171, i_class_id_169) + join (INNER, REPLICATED): join (INNER, REPLICATED): - join (INNER, REPLICATED): - scan web_sales - local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - scan date_dim + scan web_sales local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) - scan item + scan date_dim + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + scan item + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + final aggregation over () + local exchange (GATHER, SINGLE, []) + remote exchange (GATHER, SINGLE, []) + partial aggregation over () + join (INNER, REPLICATED): + scan store_sales + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + scan date_dim + partial aggregation over () + join (INNER, REPLICATED): + scan catalog_sales + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + scan date_dim + partial aggregation over () + join (INNER, REPLICATED): + scan web_sales + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + scan date_dim + cross join: + final aggregation over (i_brand_id_508, i_category_id_512, i_class_id_510) local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - final aggregation over () - local exchange (GATHER, SINGLE, []) - remote exchange (GATHER, SINGLE, []) - partial aggregation over () - join (INNER, REPLICATED): - scan store_sales - local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - scan date_dim - partial aggregation over () + remote exchange (REPARTITION, HASH, ["i_brand_id_508", "i_category_id_512", "i_class_id_510"]) + partial aggregation over (i_brand_id_508, i_category_id_512, i_class_id_510) + semijoin (PARTITIONED): + remote exchange (REPARTITION, HASH, ["cs_item_sk_482"]) + join (INNER, REPLICATED): join (INNER, REPLICATED): scan catalog_sales local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) scan date_dim - partial aggregation over () - join (INNER, REPLICATED): - scan web_sales - local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - scan date_dim - cross join: - final aggregation over (i_brand_id_508, i_category_id_512, i_class_id_510) - local exchange (GATHER, SINGLE, []) - remote exchange (REPARTITION, HASH, ["i_brand_id_508", "i_category_id_512", "i_class_id_510"]) - partial aggregation over (i_brand_id_508, i_category_id_512, i_class_id_510) - semijoin (PARTITIONED): - remote exchange (REPARTITION, HASH, ["cs_item_sk_482"]) - join (INNER, REPLICATED): - join (INNER, REPLICATED): - scan catalog_sales + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + scan item + local exchange (GATHER, SINGLE, []) + remote exchange (REPARTITION, HASH, ["i_item_sk_552"]) + join (INNER, PARTITIONED): + remote exchange (REPARTITION, HASH, ["i_brand_id_559", "i_category_id_563", "i_class_id_561"]) + scan item + final aggregation over (expr_836, expr_837, expr_838) local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - scan date_dim - local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - scan item - local exchange (GATHER, SINGLE, []) - remote exchange (REPARTITION, HASH, ["i_item_sk_552"]) - join (INNER, PARTITIONED): - remote exchange (REPARTITION, HASH, ["i_brand_id_559", "i_category_id_563", "i_class_id_561"]) - scan item - final aggregation over (expr_836, expr_837, expr_838) - local exchange (GATHER, SINGLE, []) - remote exchange (REPARTITION, HASH, ["i_brand_id_604", "i_category_id_608", "i_class_id_606"]) - partial aggregation over (i_brand_id_604, i_category_id_608, i_class_id_606) + remote exchange (REPARTITION, HASH, ["i_brand_id_604", "i_category_id_608", "i_class_id_606"]) + partial aggregation over (i_brand_id_604, i_category_id_608, i_class_id_606) + join (INNER, REPLICATED): join (INNER, REPLICATED): - join (INNER, REPLICATED): - scan store_sales - local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - scan date_dim + scan store_sales local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) - scan item - remote exchange (REPARTITION, HASH, ["i_brand_id_694", "i_category_id_698", "i_class_id_696"]) - partial aggregation over (i_brand_id_694, i_category_id_698, i_class_id_696) + scan date_dim + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + scan item + remote exchange (REPARTITION, HASH, ["i_brand_id_694", "i_category_id_698", "i_class_id_696"]) + partial aggregation over (i_brand_id_694, i_category_id_698, i_class_id_696) + join (INNER, REPLICATED): join (INNER, REPLICATED): - join (INNER, REPLICATED): - scan catalog_sales - local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - scan date_dim + scan catalog_sales local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) - scan item - remote exchange (REPARTITION, HASH, ["i_brand_id_787", "i_category_id_791", "i_class_id_789"]) - partial aggregation over (i_brand_id_787, i_category_id_791, i_class_id_789) + scan date_dim + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + scan item + remote exchange (REPARTITION, HASH, ["i_brand_id_787", "i_category_id_791", "i_class_id_789"]) + partial aggregation over (i_brand_id_787, i_category_id_791, i_class_id_789) + join (INNER, REPLICATED): join (INNER, REPLICATED): - join (INNER, REPLICATED): - scan web_sales - local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - scan date_dim + scan web_sales local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) - scan item + scan date_dim + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + scan item + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + final aggregation over () + local exchange (GATHER, SINGLE, []) + remote exchange (GATHER, SINGLE, []) + partial aggregation over () + join (INNER, REPLICATED): + scan store_sales + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + scan date_dim + partial aggregation over () + join (INNER, REPLICATED): + scan catalog_sales + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + scan date_dim + partial aggregation over () + join (INNER, REPLICATED): + scan web_sales + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + scan date_dim + cross join: + final aggregation over (i_brand_id_1135, i_category_id_1139, i_class_id_1137) local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - final aggregation over () - local exchange (GATHER, SINGLE, []) - remote exchange (GATHER, SINGLE, []) - partial aggregation over () - join (INNER, REPLICATED): - scan store_sales - local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - scan date_dim - partial aggregation over () - join (INNER, REPLICATED): - scan catalog_sales - local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - scan date_dim - partial aggregation over () + remote exchange (REPARTITION, HASH, ["i_brand_id_1135", "i_category_id_1139", "i_class_id_1137"]) + partial aggregation over (i_brand_id_1135, i_category_id_1139, i_class_id_1137) + semijoin (PARTITIONED): + remote exchange (REPARTITION, HASH, ["ws_item_sk_1097"]) + join (INNER, REPLICATED): join (INNER, REPLICATED): scan web_sales local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) scan date_dim - cross join: - final aggregation over (i_brand_id_1135, i_category_id_1139, i_class_id_1137) - local exchange (GATHER, SINGLE, []) - remote exchange (REPARTITION, HASH, ["i_brand_id_1135", "i_category_id_1139", "i_class_id_1137"]) - partial aggregation over (i_brand_id_1135, i_category_id_1139, i_class_id_1137) - semijoin (PARTITIONED): - remote exchange (REPARTITION, HASH, ["ws_item_sk_1097"]) - join (INNER, REPLICATED): - join (INNER, REPLICATED): - scan web_sales + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + scan item + local exchange (GATHER, SINGLE, []) + remote exchange (REPARTITION, HASH, ["i_item_sk_1179"]) + join (INNER, PARTITIONED): + remote exchange (REPARTITION, HASH, ["i_brand_id_1186", "i_category_id_1190", "i_class_id_1188"]) + scan item + final aggregation over (expr_1463, expr_1464, expr_1465) local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - scan date_dim - local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - scan item - local exchange (GATHER, SINGLE, []) - remote exchange (REPARTITION, HASH, ["i_item_sk_1179"]) - join (INNER, PARTITIONED): - remote exchange (REPARTITION, HASH, ["i_brand_id_1186", "i_category_id_1190", "i_class_id_1188"]) - scan item - final aggregation over (expr_1463, expr_1464, expr_1465) - local exchange (GATHER, SINGLE, []) - remote exchange (REPARTITION, HASH, ["i_brand_id_1231", "i_category_id_1235", "i_class_id_1233"]) - partial aggregation over (i_brand_id_1231, i_category_id_1235, i_class_id_1233) + remote exchange (REPARTITION, HASH, ["i_brand_id_1231", "i_category_id_1235", "i_class_id_1233"]) + partial aggregation over (i_brand_id_1231, i_category_id_1235, i_class_id_1233) + join (INNER, REPLICATED): join (INNER, REPLICATED): - join (INNER, REPLICATED): - scan store_sales - local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - scan date_dim + scan store_sales local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) - scan item - remote exchange (REPARTITION, HASH, ["i_brand_id_1321", "i_category_id_1325", "i_class_id_1323"]) - partial aggregation over (i_brand_id_1321, i_category_id_1325, i_class_id_1323) + scan date_dim + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + scan item + remote exchange (REPARTITION, HASH, ["i_brand_id_1321", "i_category_id_1325", "i_class_id_1323"]) + partial aggregation over (i_brand_id_1321, i_category_id_1325, i_class_id_1323) + join (INNER, REPLICATED): join (INNER, REPLICATED): - join (INNER, REPLICATED): - scan catalog_sales - local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - scan date_dim + scan catalog_sales local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) - scan item - remote exchange (REPARTITION, HASH, ["i_brand_id_1414", "i_category_id_1418", "i_class_id_1416"]) - partial aggregation over (i_brand_id_1414, i_category_id_1418, i_class_id_1416) + scan date_dim + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + scan item + remote exchange (REPARTITION, HASH, ["i_brand_id_1414", "i_category_id_1418", "i_class_id_1416"]) + partial aggregation over (i_brand_id_1414, i_category_id_1418, i_class_id_1416) + join (INNER, REPLICATED): join (INNER, REPLICATED): - join (INNER, REPLICATED): - scan web_sales - local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - scan date_dim + scan web_sales local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) - scan item - local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - final aggregation over () - local exchange (GATHER, SINGLE, []) - remote exchange (GATHER, SINGLE, []) - partial aggregation over () - join (INNER, REPLICATED): - scan store_sales - local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - scan date_dim - partial aggregation over () - join (INNER, REPLICATED): - scan catalog_sales - local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - scan date_dim - partial aggregation over () - join (INNER, REPLICATED): - scan web_sales - local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - scan date_dim + scan date_dim + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + scan item + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + final aggregation over () + local exchange (GATHER, SINGLE, []) + remote exchange (GATHER, SINGLE, []) + partial aggregation over () + join (INNER, REPLICATED): + scan store_sales + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + scan date_dim + partial aggregation over () + join (INNER, REPLICATED): + scan catalog_sales + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + scan date_dim + partial aggregation over () + join (INNER, REPLICATED): + scan web_sales + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + scan date_dim diff --git a/presto-benchto-benchmarks/src/test/resources/sql/presto/tpcds/q18.plan.txt b/presto-benchto-benchmarks/src/test/resources/sql/presto/tpcds/q18.plan.txt index 1af346266b2c..c09a7374f0ea 100644 --- a/presto-benchto-benchmarks/src/test/resources/sql/presto/tpcds/q18.plan.txt +++ b/presto-benchto-benchmarks/src/test/resources/sql/presto/tpcds/q18.plan.txt @@ -1,35 +1,34 @@ -local exchange (GATHER, SINGLE, []) - remote exchange (GATHER, SINGLE, []) - final aggregation over (ca_country$gid, ca_county$gid, ca_state$gid, groupid, i_item_id$gid) - local exchange (REPARTITION, HASH, ["ca_country$gid", "ca_county$gid", "ca_state$gid", "groupid", "i_item_id$gid"]) - remote exchange (REPARTITION, HASH, ["ca_country$gid", "ca_county$gid", "ca_state$gid", "groupid", "i_item_id$gid"]) - partial aggregation over (ca_country$gid, ca_county$gid, ca_state$gid, groupid, i_item_id$gid) - local exchange (REPARTITION, HASH, ["ca_country", "i_item_id"]) - remote exchange (REPARTITION, HASH, ["ca_country", "i_item_id"]) +remote exchange (GATHER, SINGLE, []) + final aggregation over (ca_country$gid, ca_county$gid, ca_state$gid, groupid, i_item_id$gid) + local exchange (REPARTITION, HASH, ["ca_country$gid", "ca_county$gid", "ca_state$gid", "groupid", "i_item_id$gid"]) + remote exchange (REPARTITION, HASH, ["ca_country$gid", "ca_county$gid", "ca_state$gid", "groupid", "i_item_id$gid"]) + partial aggregation over (ca_country$gid, ca_county$gid, ca_state$gid, groupid, i_item_id$gid) + local exchange (REPARTITION, HASH, ["ca_country", "i_item_id"]) + remote exchange (REPARTITION, HASH, ["ca_country", "i_item_id"]) + join (INNER, REPLICATED): join (INNER, REPLICATED): join (INNER, REPLICATED): join (INNER, REPLICATED): - join (INNER, REPLICATED): - scan catalog_sales - local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - scan customer_demographics + scan catalog_sales local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) - join (INNER, PARTITIONED): - remote exchange (REPARTITION, HASH, ["c_current_cdemo_sk"]) - join (INNER, PARTITIONED): - remote exchange (REPARTITION, HASH, ["c_current_addr_sk"]) - scan customer - local exchange (GATHER, SINGLE, []) - remote exchange (REPARTITION, HASH, ["ca_address_sk"]) - scan customer_address - local exchange (GATHER, SINGLE, []) - remote exchange (REPARTITION, HASH, ["cd_demo_sk_0"]) - scan customer_demographics + scan customer_demographics local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) - scan date_dim + join (INNER, PARTITIONED): + remote exchange (REPARTITION, HASH, ["c_current_cdemo_sk"]) + join (INNER, PARTITIONED): + remote exchange (REPARTITION, HASH, ["c_current_addr_sk"]) + scan customer + local exchange (GATHER, SINGLE, []) + remote exchange (REPARTITION, HASH, ["ca_address_sk"]) + scan customer_address + local exchange (GATHER, SINGLE, []) + remote exchange (REPARTITION, HASH, ["cd_demo_sk_0"]) + scan customer_demographics local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) - scan item + scan date_dim + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + scan item diff --git a/presto-benchto-benchmarks/src/test/resources/sql/presto/tpcds/q22.plan.txt b/presto-benchto-benchmarks/src/test/resources/sql/presto/tpcds/q22.plan.txt index 2fd28d3f31ed..5bf9d1c23b92 100644 --- a/presto-benchto-benchmarks/src/test/resources/sql/presto/tpcds/q22.plan.txt +++ b/presto-benchto-benchmarks/src/test/resources/sql/presto/tpcds/q22.plan.txt @@ -1,17 +1,16 @@ -local exchange (GATHER, SINGLE, []) - remote exchange (GATHER, SINGLE, []) - final aggregation over (groupid, i_brand$gid, i_category$gid, i_class$gid, i_product_name$gid) - local exchange (REPARTITION, HASH, ["groupid", "i_brand$gid", "i_category$gid", "i_class$gid", "i_product_name$gid"]) - remote exchange (REPARTITION, HASH, ["groupid", "i_brand$gid", "i_category$gid", "i_class$gid", "i_product_name$gid"]) - partial aggregation over (groupid, i_brand$gid, i_category$gid, i_class$gid, i_product_name$gid) - local exchange (REPARTITION, HASH, ["i_brand", "i_product_name"]) - remote exchange (REPARTITION, HASH, ["i_brand", "i_product_name"]) +remote exchange (GATHER, SINGLE, []) + final aggregation over (groupid, i_brand$gid, i_category$gid, i_class$gid, i_product_name$gid) + local exchange (REPARTITION, HASH, ["groupid", "i_brand$gid", "i_category$gid", "i_class$gid", "i_product_name$gid"]) + remote exchange (REPARTITION, HASH, ["groupid", "i_brand$gid", "i_category$gid", "i_class$gid", "i_product_name$gid"]) + partial aggregation over (groupid, i_brand$gid, i_category$gid, i_class$gid, i_product_name$gid) + local exchange (REPARTITION, HASH, ["i_brand", "i_product_name"]) + remote exchange (REPARTITION, HASH, ["i_brand", "i_product_name"]) + join (INNER, REPLICATED): join (INNER, REPLICATED): - join (INNER, REPLICATED): - scan inventory - local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - scan date_dim + scan inventory local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) - scan item + scan date_dim + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + scan item diff --git a/presto-benchto-benchmarks/src/test/resources/sql/presto/tpcds/q27.plan.txt b/presto-benchto-benchmarks/src/test/resources/sql/presto/tpcds/q27.plan.txt index ed0e2e73e9f3..a4a4f197044a 100644 --- a/presto-benchto-benchmarks/src/test/resources/sql/presto/tpcds/q27.plan.txt +++ b/presto-benchto-benchmarks/src/test/resources/sql/presto/tpcds/q27.plan.txt @@ -1,24 +1,23 @@ -local exchange (GATHER, SINGLE, []) - remote exchange (GATHER, SINGLE, []) - final aggregation over (groupid, i_item_id$gid, s_state$gid) - local exchange (REPARTITION, HASH, ["groupid", "i_item_id$gid", "s_state$gid"]) - remote exchange (REPARTITION, HASH, ["groupid", "i_item_id$gid", "s_state$gid"]) - partial aggregation over (groupid, i_item_id$gid, s_state$gid) - join (INNER, PARTITIONED): - remote exchange (REPARTITION, HASH, ["ss_item_sk"]) +remote exchange (GATHER, SINGLE, []) + final aggregation over (groupid, i_item_id$gid, s_state$gid) + local exchange (REPARTITION, HASH, ["groupid", "i_item_id$gid", "s_state$gid"]) + remote exchange (REPARTITION, HASH, ["groupid", "i_item_id$gid", "s_state$gid"]) + partial aggregation over (groupid, i_item_id$gid, s_state$gid) + join (INNER, PARTITIONED): + remote exchange (REPARTITION, HASH, ["ss_item_sk"]) + join (INNER, REPLICATED): join (INNER, REPLICATED): join (INNER, REPLICATED): - join (INNER, REPLICATED): - scan store_sales - local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - scan customer_demographics + scan store_sales local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) - scan store + scan customer_demographics local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) - scan date_dim - local exchange (GATHER, SINGLE, []) - remote exchange (REPARTITION, HASH, ["i_item_sk"]) - scan item + scan store + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + scan date_dim + local exchange (GATHER, SINGLE, []) + remote exchange (REPARTITION, HASH, ["i_item_sk"]) + scan item diff --git a/presto-benchto-benchmarks/src/test/resources/sql/presto/tpcds/q77.plan.txt b/presto-benchto-benchmarks/src/test/resources/sql/presto/tpcds/q77.plan.txt index 32474cf29af0..9fa45d156a4a 100644 --- a/presto-benchto-benchmarks/src/test/resources/sql/presto/tpcds/q77.plan.txt +++ b/presto-benchto-benchmarks/src/test/resources/sql/presto/tpcds/q77.plan.txt @@ -1,82 +1,81 @@ -local exchange (GATHER, SINGLE, []) - remote exchange (GATHER, SINGLE, []) - final aggregation over (channel$gid, groupid, id$gid) - local exchange (REPARTITION, HASH, ["channel$gid", "groupid", "id$gid"]) - remote exchange (REPARTITION, HASH, ["channel$gid", "groupid", "id$gid"]) - partial aggregation over (channel$gid, groupid, id$gid) - local exchange (REPARTITION, ROUND_ROBIN, []) - join (LEFT, PARTITIONED): - final aggregation over (s_store_sk) - local exchange (GATHER, SINGLE, []) - remote exchange (REPARTITION, HASH, ["s_store_sk"]) - partial aggregation over (s_store_sk) - join (INNER, REPLICATED): - join (INNER, REPLICATED): - scan store_sales - local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - scan date_dim - local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - scan store - final aggregation over (s_store_sk_46) - local exchange (GATHER, SINGLE, []) - remote exchange (REPARTITION, HASH, ["s_store_sk_46"]) - partial aggregation over (s_store_sk_46) +remote exchange (GATHER, SINGLE, []) + final aggregation over (channel$gid, groupid, id$gid) + local exchange (REPARTITION, HASH, ["channel$gid", "groupid", "id$gid"]) + remote exchange (REPARTITION, HASH, ["channel$gid", "groupid", "id$gid"]) + partial aggregation over (channel$gid, groupid, id$gid) + local exchange (REPARTITION, ROUND_ROBIN, []) + join (LEFT, PARTITIONED): + final aggregation over (s_store_sk) + local exchange (GATHER, SINGLE, []) + remote exchange (REPARTITION, HASH, ["s_store_sk"]) + partial aggregation over (s_store_sk) + join (INNER, REPLICATED): join (INNER, REPLICATED): - join (INNER, REPLICATED): - scan store_returns - local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - scan date_dim + scan store_sales local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) - scan store - cross join: - final aggregation over (cs_call_center_sk) - local exchange (GATHER, SINGLE, []) - remote exchange (REPARTITION, HASH, ["cs_call_center_sk"]) - partial aggregation over (cs_call_center_sk) + scan date_dim + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + scan store + final aggregation over (s_store_sk_46) + local exchange (GATHER, SINGLE, []) + remote exchange (REPARTITION, HASH, ["s_store_sk_46"]) + partial aggregation over (s_store_sk_46) + join (INNER, REPLICATED): join (INNER, REPLICATED): - scan catalog_sales + scan store_returns local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) scan date_dim + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + scan store + cross join: + final aggregation over (cs_call_center_sk) local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - final aggregation over (cr_call_center_sk) - local exchange (GATHER, SINGLE, []) - remote exchange (REPARTITION, HASH, ["cr_call_center_sk"]) - partial aggregation over (cr_call_center_sk) - join (INNER, REPLICATED): - scan catalog_returns - local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - scan date_dim - join (LEFT, PARTITIONED): - final aggregation over (wp_web_page_sk) - local exchange (GATHER, SINGLE, []) - remote exchange (REPARTITION, HASH, ["wp_web_page_sk"]) - partial aggregation over (wp_web_page_sk) - join (INNER, REPLICATED): + remote exchange (REPARTITION, HASH, ["cs_call_center_sk"]) + partial aggregation over (cs_call_center_sk) + join (INNER, REPLICATED): + scan catalog_sales + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + scan date_dim + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + final aggregation over (cr_call_center_sk) + local exchange (GATHER, SINGLE, []) + remote exchange (REPARTITION, HASH, ["cr_call_center_sk"]) + partial aggregation over (cr_call_center_sk) join (INNER, REPLICATED): - scan web_sales + scan catalog_returns local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) scan date_dim + join (LEFT, PARTITIONED): + final aggregation over (wp_web_page_sk) + local exchange (GATHER, SINGLE, []) + remote exchange (REPARTITION, HASH, ["wp_web_page_sk"]) + partial aggregation over (wp_web_page_sk) + join (INNER, REPLICATED): + join (INNER, REPLICATED): + scan web_sales local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) - scan web_page - final aggregation over (wp_web_page_sk_298) - local exchange (GATHER, SINGLE, []) - remote exchange (REPARTITION, HASH, ["wp_web_page_sk_298"]) - partial aggregation over (wp_web_page_sk_298) + scan date_dim + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + scan web_page + final aggregation over (wp_web_page_sk_298) + local exchange (GATHER, SINGLE, []) + remote exchange (REPARTITION, HASH, ["wp_web_page_sk_298"]) + partial aggregation over (wp_web_page_sk_298) + join (INNER, REPLICATED): join (INNER, REPLICATED): - join (INNER, REPLICATED): - scan web_returns - local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - scan date_dim + scan web_returns local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) - scan web_page + scan date_dim + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + scan web_page diff --git a/presto-benchto-benchmarks/src/test/resources/sql/presto/tpcds/q80.plan.txt b/presto-benchto-benchmarks/src/test/resources/sql/presto/tpcds/q80.plan.txt index 9fbd54c9adae..f28b8928dbec 100644 --- a/presto-benchto-benchmarks/src/test/resources/sql/presto/tpcds/q80.plan.txt +++ b/presto-benchto-benchmarks/src/test/resources/sql/presto/tpcds/q80.plan.txt @@ -1,82 +1,81 @@ -local exchange (GATHER, SINGLE, []) - remote exchange (GATHER, SINGLE, []) - final aggregation over (channel$gid, groupid, id$gid) - local exchange (REPARTITION, HASH, ["channel$gid", "groupid", "id$gid"]) - remote exchange (REPARTITION, HASH, ["channel$gid", "groupid", "id$gid"]) - partial aggregation over (channel$gid, groupid, id$gid) - local exchange (REPARTITION, ROUND_ROBIN, []) - final aggregation over (s_store_id) - local exchange (GATHER, SINGLE, []) - remote exchange (REPARTITION, HASH, ["s_store_id"]) - partial aggregation over (s_store_id) +remote exchange (GATHER, SINGLE, []) + final aggregation over (channel$gid, groupid, id$gid) + local exchange (REPARTITION, HASH, ["channel$gid", "groupid", "id$gid"]) + remote exchange (REPARTITION, HASH, ["channel$gid", "groupid", "id$gid"]) + partial aggregation over (channel$gid, groupid, id$gid) + local exchange (REPARTITION, ROUND_ROBIN, []) + final aggregation over (s_store_id) + local exchange (GATHER, SINGLE, []) + remote exchange (REPARTITION, HASH, ["s_store_id"]) + partial aggregation over (s_store_id) + join (INNER, REPLICATED): join (INNER, REPLICATED): join (INNER, REPLICATED): join (INNER, REPLICATED): - join (INNER, REPLICATED): - join (LEFT, REPLICATED): - scan store_sales - local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - scan store_returns + join (LEFT, REPLICATED): + scan store_sales local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) - scan date_dim + scan store_returns local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) - scan item + scan date_dim local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) - scan promotion + scan item local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) - scan store - final aggregation over (cp_catalog_page_id) - local exchange (GATHER, SINGLE, []) - remote exchange (REPARTITION, HASH, ["cp_catalog_page_id"]) - partial aggregation over (cp_catalog_page_id) + scan promotion + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + scan store + final aggregation over (cp_catalog_page_id) + local exchange (GATHER, SINGLE, []) + remote exchange (REPARTITION, HASH, ["cp_catalog_page_id"]) + partial aggregation over (cp_catalog_page_id) + join (INNER, REPLICATED): join (INNER, REPLICATED): join (INNER, REPLICATED): join (INNER, REPLICATED): - join (INNER, REPLICATED): - join (LEFT, REPLICATED): - scan catalog_sales - local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - scan catalog_returns + join (LEFT, REPLICATED): + scan catalog_sales local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) - scan date_dim + scan catalog_returns local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) - scan item + scan date_dim local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) - scan promotion + scan item local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) - scan catalog_page - final aggregation over (web_site_id) - local exchange (GATHER, SINGLE, []) - remote exchange (REPARTITION, HASH, ["web_site_id"]) - partial aggregation over (web_site_id) + scan promotion + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + scan catalog_page + final aggregation over (web_site_id) + local exchange (GATHER, SINGLE, []) + remote exchange (REPARTITION, HASH, ["web_site_id"]) + partial aggregation over (web_site_id) + join (INNER, REPLICATED): join (INNER, REPLICATED): join (INNER, REPLICATED): join (INNER, REPLICATED): - join (INNER, REPLICATED): - join (LEFT, REPLICATED): - scan web_sales - local exchange (GATHER, SINGLE, []) - remote exchange (REPLICATE, BROADCAST, []) - scan web_returns + join (LEFT, REPLICATED): + scan web_sales local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) - scan date_dim + scan web_returns local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) - scan item + scan date_dim local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) - scan promotion + scan item local exchange (GATHER, SINGLE, []) remote exchange (REPLICATE, BROADCAST, []) - scan web_site + scan promotion + local exchange (GATHER, SINGLE, []) + remote exchange (REPLICATE, BROADCAST, []) + scan web_site diff --git a/presto-main/src/main/java/io/prestosql/sql/planner/PlanOptimizers.java b/presto-main/src/main/java/io/prestosql/sql/planner/PlanOptimizers.java index 34ff9932dd57..f3deb18547c5 100644 --- a/presto-main/src/main/java/io/prestosql/sql/planner/PlanOptimizers.java +++ b/presto-main/src/main/java/io/prestosql/sql/planner/PlanOptimizers.java @@ -41,9 +41,7 @@ import io.prestosql.sql.planner.iterative.rule.DetermineJoinDistributionType; import io.prestosql.sql.planner.iterative.rule.DetermineSemiJoinDistributionType; import io.prestosql.sql.planner.iterative.rule.EliminateCrossJoins; -import io.prestosql.sql.planner.iterative.rule.EvaluateZeroLimit; import io.prestosql.sql.planner.iterative.rule.EvaluateZeroSample; -import io.prestosql.sql.planner.iterative.rule.EvaluateZeroTopN; import io.prestosql.sql.planner.iterative.rule.ExtractSpatialJoins; import io.prestosql.sql.planner.iterative.rule.GatherAndMergeWindows; import io.prestosql.sql.planner.iterative.rule.ImplementBernoulliSampleAsFilter; @@ -101,7 +99,11 @@ import io.prestosql.sql.planner.iterative.rule.RemoveAggregationInSemiJoin; import io.prestosql.sql.planner.iterative.rule.RemoveEmptyDelete; import io.prestosql.sql.planner.iterative.rule.RemoveFullSample; +import io.prestosql.sql.planner.iterative.rule.RemoveRedundantDistinctLimit; import io.prestosql.sql.planner.iterative.rule.RemoveRedundantIdentityProjections; +import io.prestosql.sql.planner.iterative.rule.RemoveRedundantLimit; +import io.prestosql.sql.planner.iterative.rule.RemoveRedundantSort; +import io.prestosql.sql.planner.iterative.rule.RemoveRedundantTopN; import io.prestosql.sql.planner.iterative.rule.RemoveTrivialFilters; import io.prestosql.sql.planner.iterative.rule.RemoveUnreferencedScalarApplyNodes; import io.prestosql.sql.planner.iterative.rule.RemoveUnreferencedScalarLateralNodes; @@ -293,8 +295,6 @@ public PlanOptimizers( .addAll(ImmutableSet.of( new RemoveRedundantIdentityProjections(), new RemoveFullSample(), - new EvaluateZeroLimit(), - new EvaluateZeroTopN(), new EvaluateZeroSample(), new PushOffsetThroughProject(), new PushLimitThroughOffset(), @@ -309,6 +309,10 @@ public PlanOptimizers( new PushLimitIntoTableScan(metadata), new PushPredicateIntoTableScan(metadata, typeAnalyzer), new RemoveTrivialFilters(), + new RemoveRedundantLimit(), + new RemoveRedundantSort(), + new RemoveRedundantTopN(), + new RemoveRedundantDistinctLimit(), new ImplementFilteredAggregations(), new SingleDistinctAggregationToGroupBy(), new MultipleDistinctAggregationToMarkDistinct(), diff --git a/presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/RemoveRedundantDistinctLimit.java b/presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/RemoveRedundantDistinctLimit.java new file mode 100644 index 000000000000..f274281661fd --- /dev/null +++ b/presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/RemoveRedundantDistinctLimit.java @@ -0,0 +1,73 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.prestosql.sql.planner.iterative.rule; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import io.prestosql.matching.Captures; +import io.prestosql.matching.Pattern; +import io.prestosql.sql.planner.iterative.Rule; +import io.prestosql.sql.planner.plan.AggregationNode; +import io.prestosql.sql.planner.plan.DistinctLimitNode; +import io.prestosql.sql.planner.plan.ValuesNode; + +import java.util.Optional; + +import static com.google.common.base.Preconditions.checkArgument; +import static io.prestosql.sql.planner.optimizations.QueryCardinalityUtil.isAtMost; +import static io.prestosql.sql.planner.optimizations.QueryCardinalityUtil.isScalar; +import static io.prestosql.sql.planner.plan.AggregationNode.Step.SINGLE; +import static io.prestosql.sql.planner.plan.AggregationNode.singleGroupingSet; +import static io.prestosql.sql.planner.plan.Patterns.distinctLimit; + +/** + * Replace DistinctLimit node + * 1. With a empty ValuesNode when count is 0 + * 2. With a Distinct node when the subplan is guaranteed to produce fewer rows than count + * 3. With its source when the subplan produces only one row + */ +public class RemoveRedundantDistinctLimit + implements Rule +{ + private static final Pattern PATTERN = distinctLimit(); + + @Override + public Pattern getPattern() + { + return PATTERN; + } + + @Override + public Result apply(DistinctLimitNode node, Captures captures, Context context) + { + checkArgument(!node.getHashSymbol().isPresent(), "HashSymbol should be empty"); + if (node.getLimit() == 0) { + return Result.ofPlanNode(new ValuesNode(node.getId(), node.getOutputSymbols(), ImmutableList.of())); + } + if (isScalar(node.getSource(), context.getLookup())) { + return Result.ofPlanNode(node.getSource()); + } + else if (isAtMost(node.getSource(), context.getLookup(), node.getLimit())) { + return Result.ofPlanNode(new AggregationNode(node.getId(), + node.getSource(), + ImmutableMap.of(), + singleGroupingSet(node.getDistinctSymbols()), + ImmutableList.of(), + SINGLE, + node.getHashSymbol(), + Optional.empty())); + } + return Result.empty(); + } +} diff --git a/presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/EvaluateZeroLimit.java b/presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/RemoveRedundantLimit.java similarity index 63% rename from presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/EvaluateZeroLimit.java rename to presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/RemoveRedundantLimit.java index 48a7810d28cf..94067ed1da68 100644 --- a/presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/EvaluateZeroLimit.java +++ b/presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/RemoveRedundantLimit.java @@ -20,14 +20,17 @@ import io.prestosql.sql.planner.plan.LimitNode; import io.prestosql.sql.planner.plan.ValuesNode; -import static io.prestosql.sql.planner.plan.Patterns.Limit.count; +import static io.prestosql.sql.planner.optimizations.QueryCardinalityUtil.isAtMost; import static io.prestosql.sql.planner.plan.Patterns.limit; -public class EvaluateZeroLimit +/** + * Remove Limit node when the subplan is guaranteed to produce fewer rows than the limit and + * replace the plan with empty values if the limit count is 0. + */ +public class RemoveRedundantLimit implements Rule { - private static final Pattern PATTERN = limit() - .with(count().equalTo(0L)); + private static final Pattern PATTERN = limit(); @Override public Pattern getPattern() @@ -38,6 +41,12 @@ public Pattern getPattern() @Override public Result apply(LimitNode limit, Captures captures, Context context) { - return Result.ofPlanNode(new ValuesNode(limit.getId(), limit.getOutputSymbols(), ImmutableList.of())); + if (limit.getCount() == 0) { + return Result.ofPlanNode(new ValuesNode(limit.getId(), limit.getOutputSymbols(), ImmutableList.of())); + } + if (isAtMost(limit.getSource(), context.getLookup(), limit.getCount())) { + return Result.ofPlanNode(limit.getSource()); + } + return Result.empty(); } } diff --git a/presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/EvaluateZeroTopN.java b/presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/RemoveRedundantSort.java similarity index 52% rename from presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/EvaluateZeroTopN.java rename to presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/RemoveRedundantSort.java index f1bd204be2cb..2593f124d80f 100644 --- a/presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/EvaluateZeroTopN.java +++ b/presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/RemoveRedundantSort.java @@ -17,27 +17,33 @@ import io.prestosql.matching.Captures; import io.prestosql.matching.Pattern; import io.prestosql.sql.planner.iterative.Rule; -import io.prestosql.sql.planner.plan.TopNNode; +import io.prestosql.sql.planner.plan.SortNode; import io.prestosql.sql.planner.plan.ValuesNode; -import static io.prestosql.sql.planner.plan.Patterns.TopN.count; -import static io.prestosql.sql.planner.plan.Patterns.topN; +import static io.prestosql.sql.planner.optimizations.QueryCardinalityUtil.isAtMost; +import static io.prestosql.sql.planner.optimizations.QueryCardinalityUtil.isScalar; +import static io.prestosql.sql.planner.plan.Patterns.sort; -public class EvaluateZeroTopN - implements Rule +public class RemoveRedundantSort + implements Rule { - private static final Pattern PATTERN = topN() - .with(count().equalTo(0L)); + private static final Pattern PATTERN = sort(); @Override - public Pattern getPattern() + public Pattern getPattern() { return PATTERN; } @Override - public Result apply(TopNNode topN, Captures captures, Context context) + public Result apply(SortNode node, Captures captures, Context context) { - return Result.ofPlanNode(new ValuesNode(topN.getId(), topN.getOutputSymbols(), ImmutableList.of())); + if (isAtMost(node.getSource(), context.getLookup(), 0)) { + return Result.ofPlanNode(new ValuesNode(node.getId(), node.getOutputSymbols(), ImmutableList.of())); + } + if (isScalar(node.getSource(), context.getLookup())) { + return Result.ofPlanNode(node.getSource()); + } + return Result.empty(); } } diff --git a/presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/RemoveRedundantTopN.java b/presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/RemoveRedundantTopN.java new file mode 100644 index 000000000000..b4b40eae769d --- /dev/null +++ b/presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/RemoveRedundantTopN.java @@ -0,0 +1,59 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.prestosql.sql.planner.iterative.rule; + +import com.google.common.collect.ImmutableList; +import io.prestosql.matching.Captures; +import io.prestosql.matching.Pattern; +import io.prestosql.sql.planner.iterative.Rule; +import io.prestosql.sql.planner.plan.SortNode; +import io.prestosql.sql.planner.plan.TopNNode; +import io.prestosql.sql.planner.plan.ValuesNode; + +import static io.prestosql.sql.planner.optimizations.QueryCardinalityUtil.isAtMost; +import static io.prestosql.sql.planner.optimizations.QueryCardinalityUtil.isScalar; +import static io.prestosql.sql.planner.plan.Patterns.topN; + +/** + * Replace TopN node + * 1. With a Sort node when the subplan is guaranteed to produce fewer rows than N + * 2. With its source when the subplan produces only one row + * 3. With a empty ValuesNode when N is 0 + */ +public class RemoveRedundantTopN + implements Rule +{ + private static final Pattern PATTERN = topN(); + + @Override + public Pattern getPattern() + { + return PATTERN; + } + + @Override + public Result apply(TopNNode node, Captures captures, Context context) + { + if (node.getCount() == 0) { + return Result.ofPlanNode(new ValuesNode(node.getId(), node.getOutputSymbols(), ImmutableList.of())); + } + if (isScalar(node.getSource(), context.getLookup())) { + return Result.ofPlanNode(node.getSource()); + } + if (isAtMost(node.getSource(), context.getLookup(), node.getCount())) { + return Result.ofPlanNode(new SortNode(context.getIdAllocator().getNextId(), node.getSource(), node.getOrderingScheme())); + } + return Result.empty(); + } +} diff --git a/presto-main/src/main/java/io/prestosql/sql/planner/optimizations/QueryCardinalityUtil.java b/presto-main/src/main/java/io/prestosql/sql/planner/optimizations/QueryCardinalityUtil.java index 4b631047f03f..46e4634463c8 100644 --- a/presto-main/src/main/java/io/prestosql/sql/planner/optimizations/QueryCardinalityUtil.java +++ b/presto-main/src/main/java/io/prestosql/sql/planner/optimizations/QueryCardinalityUtil.java @@ -60,7 +60,7 @@ public static boolean isAtMostScalar(PlanNode node, Lookup lookup) return isAtMost(node, lookup, 1L); } - private static boolean isAtMost(PlanNode node, Lookup lookup, long maxCardinality) + public static boolean isAtMost(PlanNode node, Lookup lookup, long maxCardinality) { return Range.closed(0L, maxCardinality).encloses(extractCardinality(node, lookup)); } diff --git a/presto-main/src/main/java/io/prestosql/sql/planner/plan/Patterns.java b/presto-main/src/main/java/io/prestosql/sql/planner/plan/Patterns.java index c4a873300458..0db0a5883ca5 100644 --- a/presto-main/src/main/java/io/prestosql/sql/planner/plan/Patterns.java +++ b/presto-main/src/main/java/io/prestosql/sql/planner/plan/Patterns.java @@ -167,6 +167,11 @@ public static Pattern rowNumber() return typeOf(RowNumberNode.class); } + public static Pattern distinctLimit() + { + return typeOf(DistinctLimitNode.class); + } + public static Property source() { return optionalProperty( diff --git a/presto-main/src/test/java/io/prestosql/sql/planner/TestLogicalPlanner.java b/presto-main/src/test/java/io/prestosql/sql/planner/TestLogicalPlanner.java index 8c770f1654a8..585c0f80ff0c 100644 --- a/presto-main/src/test/java/io/prestosql/sql/planner/TestLogicalPlanner.java +++ b/presto-main/src/test/java/io/prestosql/sql/planner/TestLogicalPlanner.java @@ -33,8 +33,11 @@ import io.prestosql.sql.planner.plan.IndexJoinNode; import io.prestosql.sql.planner.plan.JoinNode; import io.prestosql.sql.planner.plan.LateralJoinNode; +import io.prestosql.sql.planner.plan.LimitNode; import io.prestosql.sql.planner.plan.PlanNode; +import io.prestosql.sql.planner.plan.ProjectNode; import io.prestosql.sql.planner.plan.SemiJoinNode; +import io.prestosql.sql.planner.plan.SortNode; import io.prestosql.sql.planner.plan.StatisticsWriterNode; import io.prestosql.sql.planner.plan.TableScanNode; import io.prestosql.sql.planner.plan.TopNNode; @@ -57,6 +60,7 @@ import static io.prestosql.spi.StandardErrorCode.SUBQUERY_MULTIPLE_ROWS; import static io.prestosql.spi.predicate.Domain.singleValue; import static io.prestosql.spi.type.VarcharType.createVarcharType; +import static io.prestosql.sql.planner.LogicalPlanner.Stage.OPTIMIZED; import static io.prestosql.sql.planner.assertions.PlanMatchPattern.aggregation; import static io.prestosql.sql.planner.assertions.PlanMatchPattern.any; import static io.prestosql.sql.planner.assertions.PlanMatchPattern.anyNot; @@ -443,7 +447,7 @@ private void assertPlanContainsNoApplyOrAnyJoin(String sql) private void assertPlanDoesNotContain(String sql, Class... classes) { assertFalse( - searchFrom(plan(sql, LogicalPlanner.Stage.OPTIMIZED).getRoot()) + searchFrom(plan(sql, OPTIMIZED).getRoot()) .where(isInstanceOfAny(classes)) .matches(), "Unexpected node for query: " + sql); @@ -454,7 +458,7 @@ public void testCorrelatedSubqueries() { assertPlan( "SELECT orderkey FROM orders WHERE 3 = (SELECT orderkey)", - LogicalPlanner.Stage.OPTIMIZED, + OPTIMIZED, any( filter( "X = BIGINT '3'", @@ -612,7 +616,7 @@ public void testDoubleNestedCorrelatedSubqueries() assertPlan( "SELECT orderkey FROM orders o " + "WHERE 3 IN (SELECT o.custkey FROM lineitem l WHERE (SELECT l.orderkey = o.orderkey))", - LogicalPlanner.Stage.OPTIMIZED, + OPTIMIZED, anyTree( filter("OUTER_FILTER", apply(ImmutableList.of("C", "O"), @@ -943,4 +947,106 @@ public void testOffset() tableScan("nation", ImmutableMap.of("NAME", "name"))))) .withAlias("row_num", new RowNumberSymbolMatcher()))))); } + + public void testRedundantLimitNodeRemoval() + { + String query = "SELECT count(*) FROM orders LIMIT 10"; + assertFalse( + searchFrom(plan(query, OPTIMIZED).getRoot()) + .where(LimitNode.class::isInstance) + .matches(), + format("Unexpected limit node for query: '%s'", query)); + + query = "SELECT orderkey, count(*) FROM orders GROUP BY orderkey LIMIT 10"; + assertPlan( + query, + output( + limit(10, + anyTree( + tableScan("orders"))))); + + query = "SELECT * FROM (VALUES 1,2,3,4,5,6) AS t1 LIMIT 10"; + assertPlan( + query, + output( + values(ImmutableList.of("t1")))); + } + + @Test + public void testRemoveSingleRowSort() + { + String query = "SELECT count(*) FROM orders ORDER BY 1"; + assertFalse( + searchFrom(plan(query, LogicalPlanner.Stage.OPTIMIZED).getRoot()) + .where(isInstanceOfAny(SortNode.class)) + .matches(), + format("Unexpected sort node for query: '%s'", query)); + + query = "SELECT orderkey, count(*) FROM orders GROUP BY orderkey ORDER BY 1"; + assertPlan( + query, + anyTree( + node(SortNode.class, + anyTree( + tableScan("orders"))))); + } + + public void testRedundantTopNNodeRemoval() + { + String query = "SELECT count(*) FROM orders ORDER BY 1 LIMIT 10"; + assertFalse( + searchFrom(plan(query, LogicalPlanner.Stage.OPTIMIZED).getRoot()) + .where(isInstanceOfAny(TopNNode.class, SortNode.class)) + .matches(), + format("Unexpected TopN node for query: '%s'", query)); + + query = "SELECT orderkey, count(*) FROM orders GROUP BY orderkey ORDER BY 1 LIMIT 10"; + assertPlan( + query, + output( + node(TopNNode.class, + anyTree( + tableScan("orders"))))); + + query = "SELECT orderkey, count(*) FROM orders GROUP BY orderkey ORDER BY 1 LIMIT 0"; + assertPlan( + query, + output( + node(ValuesNode.class))); + + query = "SELECT * FROM (VALUES 1,2,3,4,5,6) AS t1 ORDER BY 1 LIMIT 10"; + assertPlan( + query, + output( + node(SortNode.class, + values(ImmutableList.of("t1"))))); + } + + @Test + public void testRedundantDistinctLimitNodeRemoval() + { + String query = "SELECT distinct(c) FROM (SELECT count(*) as c FROM orders) LIMIT 10"; + assertFalse( + searchFrom(plan(query, LogicalPlanner.Stage.OPTIMIZED).getRoot()) + .where(isInstanceOfAny(DistinctLimitNode.class)) + .matches(), + format("Unexpected DistinctLimit node for query: '%s'", query)); + + query = "SELECT distinct(c) FROM (SELECT count(*) as c FROM orders GROUP BY orderkey) LIMIT 10"; + assertPlan( + query, + output( + node(DistinctLimitNode.class, + anyTree( + tableScan("orders"))))); + + query = "SELECT distinct(id) FROM (VALUES 1, 2, 3, 4, 5, 6) as t1 (id) LIMIT 10"; + assertPlan( + query, + output( + node(ProjectNode.class, + node(AggregationNode.class, + node(ProjectNode.class, + values(ImmutableList.of("t1"))))))); + } } diff --git a/presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestEvaluateZeroTopN.java b/presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestEvaluateZeroTopN.java deleted file mode 100644 index 307a4af7d842..000000000000 --- a/presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestEvaluateZeroTopN.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.prestosql.sql.planner.iterative.rule; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import io.prestosql.sql.planner.iterative.rule.test.BaseRuleTest; -import org.testng.annotations.Test; - -import static io.prestosql.sql.planner.assertions.PlanMatchPattern.values; -import static io.prestosql.sql.planner.iterative.rule.test.PlanBuilder.expression; -import static io.prestosql.sql.planner.iterative.rule.test.PlanBuilder.expressions; - -public class TestEvaluateZeroTopN - extends BaseRuleTest -{ - @Test - public void testDoesNotFire() - { - tester().assertThat(new EvaluateZeroTopN()) - .on(p -> - p.topN( - 1, - ImmutableList.of(p.symbol("a")), - p.values(p.symbol("a")))) - .doesNotFire(); - } - - @Test - public void test() - { - tester().assertThat(new EvaluateZeroTopN()) - .on(p -> - p.topN( - 0, - ImmutableList.of(p.symbol("a")), - p.filter( - expression("b > 5"), - p.values( - ImmutableList.of(p.symbol("a"), p.symbol("b")), - ImmutableList.of( - expressions("1", "10"), - expressions("2", "11")))))) - // TODO: verify contents - .matches(values(ImmutableMap.of())); - } -} diff --git a/presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestRemoveRedundantDistinctLimit.java b/presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestRemoveRedundantDistinctLimit.java new file mode 100644 index 000000000000..10ea7fb7814f --- /dev/null +++ b/presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestRemoveRedundantDistinctLimit.java @@ -0,0 +1,68 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.prestosql.sql.planner.iterative.rule; + +import com.google.common.collect.ImmutableList; +import io.prestosql.sql.planner.iterative.rule.test.BaseRuleTest; +import io.prestosql.sql.planner.plan.AggregationNode; +import io.prestosql.sql.planner.plan.ValuesNode; +import org.testng.annotations.Test; + +import static io.prestosql.sql.planner.assertions.PlanMatchPattern.node; + +public class TestRemoveRedundantDistinctLimit + extends BaseRuleTest +{ + @Test + public void test() + { + tester().assertThat(new RemoveRedundantDistinctLimit()) + .on(p -> + p.distinctLimit( + 10, + ImmutableList.of(p.symbol("c")), + p.values(1, p.symbol("c")))) + .matches(node(ValuesNode.class)); + + tester().assertThat(new RemoveRedundantDistinctLimit()) + .on(p -> + p.distinctLimit( + 10, + ImmutableList.of(p.symbol("c")), + p.values(6, p.symbol("c")))) + .matches( + node(AggregationNode.class, + node(ValuesNode.class))); + + tester().assertThat(new RemoveRedundantDistinctLimit()) + .on(p -> + p.distinctLimit( + 0, + ImmutableList.of(p.symbol("c")), + p.values(1, p.symbol("c")))) + .matches(node(ValuesNode.class)); + } + + @Test + public void doesNotFire() + { + tester().assertThat(new RemoveRedundantDistinctLimit()) + .on(p -> + p.distinctLimit( + 10, + ImmutableList.of(p.symbol("c")), + p.values(100, p.symbol("c")))) + .doesNotFire(); + } +} diff --git a/presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestEvaluateZeroLimit.java b/presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestRemoveRedundantLimit.java similarity index 56% rename from presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestEvaluateZeroLimit.java rename to presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestRemoveRedundantLimit.java index 1aa158652c6b..56eff6a8639f 100644 --- a/presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestEvaluateZeroLimit.java +++ b/presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestRemoveRedundantLimit.java @@ -16,30 +16,39 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import io.prestosql.sql.planner.iterative.rule.test.BaseRuleTest; +import io.prestosql.sql.planner.plan.AggregationNode; +import io.prestosql.sql.planner.plan.ValuesNode; import org.testng.annotations.Test; +import static io.prestosql.spi.type.BigintType.BIGINT; +import static io.prestosql.sql.planner.assertions.PlanMatchPattern.node; import static io.prestosql.sql.planner.assertions.PlanMatchPattern.values; import static io.prestosql.sql.planner.iterative.rule.test.PlanBuilder.expression; import static io.prestosql.sql.planner.iterative.rule.test.PlanBuilder.expressions; -public class TestEvaluateZeroLimit +public class TestRemoveRedundantLimit extends BaseRuleTest { @Test - public void testDoesNotFire() + public void test() { - tester().assertThat(new EvaluateZeroLimit()) + tester().assertThat(new RemoveRedundantLimit()) .on(p -> p.limit( - 1, - p.values(p.symbol("a")))) - .doesNotFire(); + 10, + p.aggregation(builder -> builder + .addAggregation(p.symbol("c"), expression("count(foo)"), ImmutableList.of(BIGINT)) + .globalGrouping() + .source(p.values(p.symbol("foo")))))) + .matches( + node(AggregationNode.class, + node(ValuesNode.class))); } @Test - public void test() + public void testForZeroLimit() { - tester().assertThat(new EvaluateZeroLimit()) + tester().assertThat(new RemoveRedundantLimit()) .on(p -> p.limit( 0, @@ -53,4 +62,18 @@ public void test() // TODO: verify contents .matches(values(ImmutableMap.of())); } + + @Test + public void doesNotFire() + { + tester().assertThat(new RemoveRedundantLimit()) + .on(p -> + p.limit( + 10, + p.aggregation(builder -> builder + .addAggregation(p.symbol("c"), expression("count(foo)"), ImmutableList.of(BIGINT)) + .singleGroupingSet(p.symbol("foo")) + .source(p.values(p.symbol("foo")))))) + .doesNotFire(); + } } diff --git a/presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestRemoveRedundantSort.java b/presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestRemoveRedundantSort.java new file mode 100644 index 000000000000..01149581f72c --- /dev/null +++ b/presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestRemoveRedundantSort.java @@ -0,0 +1,69 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.prestosql.sql.planner.iterative.rule; + +import com.google.common.collect.ImmutableList; +import io.prestosql.sql.planner.iterative.rule.test.BaseRuleTest; +import io.prestosql.sql.planner.plan.AggregationNode; +import io.prestosql.sql.planner.plan.ValuesNode; +import org.testng.annotations.Test; + +import static io.prestosql.spi.type.BigintType.BIGINT; +import static io.prestosql.sql.planner.assertions.PlanMatchPattern.node; +import static io.prestosql.sql.planner.iterative.rule.test.PlanBuilder.expression; + +public class TestRemoveRedundantSort + extends BaseRuleTest +{ + @Test + public void test() + { + tester().assertThat(new RemoveRedundantSort()) + .on(p -> + p.sort( + ImmutableList.of(p.symbol("c")), + p.aggregation(builder -> builder + .addAggregation(p.symbol("c"), expression("count(foo)"), ImmutableList.of(BIGINT)) + .globalGrouping() + .source(p.values(p.symbol("foo")))))) + .matches( + node(AggregationNode.class, + node(ValuesNode.class))); + } + + @Test + public void testForZeroCardinality() + { + tester().assertThat(new RemoveRedundantSort()) + .on(p -> + p.sort( + ImmutableList.of(p.symbol("c")), + p.values(p.symbol("foo")))) + .matches(node(ValuesNode.class)); + } + + @Test + public void doesNotFire() + { + tester().assertThat(new RemoveRedundantSort()) + .on(p -> + p.sort( + ImmutableList.of(p.symbol("c")), + p.aggregation(builder -> builder + .addAggregation(p.symbol("c"), expression("count(foo)"), ImmutableList.of(BIGINT)) + .singleGroupingSet(p.symbol("foo")) + .source(p.values(p.symbol("foo")))))) + .doesNotFire(); + } +} diff --git a/presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestRemoveRedundantTopN.java b/presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestRemoveRedundantTopN.java new file mode 100644 index 000000000000..8c065348e9c5 --- /dev/null +++ b/presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestRemoveRedundantTopN.java @@ -0,0 +1,102 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.prestosql.sql.planner.iterative.rule; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import io.prestosql.sql.planner.iterative.rule.test.BaseRuleTest; +import io.prestosql.sql.planner.plan.AggregationNode; +import io.prestosql.sql.planner.plan.FilterNode; +import io.prestosql.sql.planner.plan.SortNode; +import io.prestosql.sql.planner.plan.ValuesNode; +import org.testng.annotations.Test; + +import static io.prestosql.spi.type.BigintType.BIGINT; +import static io.prestosql.sql.planner.assertions.PlanMatchPattern.node; +import static io.prestosql.sql.planner.assertions.PlanMatchPattern.values; +import static io.prestosql.sql.planner.iterative.rule.test.PlanBuilder.expression; +import static io.prestosql.sql.planner.iterative.rule.test.PlanBuilder.expressions; + +public class TestRemoveRedundantTopN + extends BaseRuleTest +{ + @Test + public void test() + { + tester().assertThat(new RemoveRedundantTopN()) + .on(p -> + p.topN( + 10, + ImmutableList.of(p.symbol("c")), + p.aggregation(builder -> builder + .addAggregation(p.symbol("c"), expression("count(foo)"), ImmutableList.of(BIGINT)) + .globalGrouping() + .source(p.values(p.symbol("foo")))))) + .matches( + node(AggregationNode.class, + node(ValuesNode.class))); + + tester().assertThat(new RemoveRedundantTopN()) + .on(p -> + p.topN( + 10, + ImmutableList.of(p.symbol("a")), + p.filter( + expression("b > 5"), + p.values( + ImmutableList.of(p.symbol("a"), p.symbol("b")), + ImmutableList.of( + expressions("1", "10"), + expressions("2", "11")))))) + // TODO: verify contents + .matches( + node(SortNode.class, + node(FilterNode.class, + node(ValuesNode.class)))); + } + + @Test + public void testZeroTopN() + { + tester().assertThat(new RemoveRedundantTopN()) + .on(p -> + p.topN( + 0, + ImmutableList.of(p.symbol("a")), + p.filter( + expression("b > 5"), + p.values( + ImmutableList.of(p.symbol("a"), p.symbol("b")), + ImmutableList.of( + expressions("1", "10"), + expressions("2", "11")))))) + // TODO: verify contents + .matches(values(ImmutableMap.of())); + } + + @Test + public void doesNotFire() + { + tester().assertThat(new RemoveRedundantTopN()) + .on(p -> + p.topN( + 10, + ImmutableList.of(p.symbol("c")), + p.aggregation(builder -> builder + .addAggregation(p.symbol("c"), expression("count(foo)"), ImmutableList.of(BIGINT)) + .singleGroupingSet(p.symbol("foo")) + .source(p.values(p.symbol("foo")))))) + .doesNotFire(); + } +} diff --git a/presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/test/PlanBuilder.java b/presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/test/PlanBuilder.java index 531a6bd37254..dbd53b367b62 100644 --- a/presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/test/PlanBuilder.java +++ b/presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/test/PlanBuilder.java @@ -48,6 +48,7 @@ import io.prestosql.sql.planner.plan.AssignUniqueId; import io.prestosql.sql.planner.plan.Assignments; import io.prestosql.sql.planner.plan.DeleteNode; +import io.prestosql.sql.planner.plan.DistinctLimitNode; import io.prestosql.sql.planner.plan.EnforceSingleRowNode; import io.prestosql.sql.planner.plan.ExchangeNode; import io.prestosql.sql.planner.plan.FilterNode; @@ -269,6 +270,17 @@ public AggregationNode aggregation(Consumer aggregationBuild return aggregationBuilder.build(); } + public DistinctLimitNode distinctLimit(long count, List distinctSymbols, PlanNode source) + { + return new DistinctLimitNode( + idAllocator.getNextId(), + source, + count, + false, + distinctSymbols, + Optional.empty()); + } + public class AggregationBuilder { private PlanNode source; diff --git a/presto-main/src/test/java/io/prestosql/sql/query/TestSubqueries.java b/presto-main/src/test/java/io/prestosql/sql/query/TestSubqueries.java index 98303a9f7dd5..42f3cb638934 100644 --- a/presto-main/src/test/java/io/prestosql/sql/query/TestSubqueries.java +++ b/presto-main/src/test/java/io/prestosql/sql/query/TestSubqueries.java @@ -65,11 +65,11 @@ public void teardown() public void testCorrelatedExistsSubqueriesWithOrPredicateAndNull() { assertExistsRewrittenToAggregationAboveJoin( - "SELECT EXISTS(SELECT 1 FROM (VALUES null, 10) t(x) WHERE y > x OR y + 10 > x) FROM (values (11)) t2(y)", + "SELECT EXISTS(SELECT 1 FROM (VALUES null, 10) t(x) WHERE y > x OR y + 10 > x) FROM (VALUES (11)) t2(y)", "VALUES true", false); assertExistsRewrittenToAggregationAboveJoin( - "SELECT EXISTS(SELECT 1 FROM (VALUES null) t(x) WHERE y > x OR y + 10 > x) FROM (values (11)) t2(y)", + "SELECT EXISTS(SELECT 1 FROM (VALUES null) t(x) WHERE y > x OR y + 10 > x) FROM (VALUES (11)) t2(y)", "VALUES false", false); } @@ -77,13 +77,13 @@ public void testCorrelatedExistsSubqueriesWithOrPredicateAndNull() @Test public void testUnsupportedSubqueriesWithCoercions() { - // coercion from subquery symbol type to correlation type + // coercion FROM subquery symbol type to correlation type assertions.assertFails( - "select (select count(*) from (values 1) t(a) where t.a=t2.b limit 1) from (values 1.0) t2(b)", + "SELECT (SELECT count(*) FROM (VALUES 1) t(a) WHERE t.a=t2.b GROUP BY t.a LIMIT 1) FROM (VALUES 1.0) t2(b)", UNSUPPORTED_CORRELATED_SUBQUERY_ERROR_MSG); // coercion from t.a (null) to integer assertions.assertFails( - "select EXISTS(select 1 from (values (null, null)) t(a, b) where t.a=t2.b GROUP BY t.b) from (values 1, 2) t2(b)", + "SELECT EXISTS(SELECT 1 FROM (VALUES (null, null)) t(a, b) WHERE t.a=t2.b GROUP BY t.b) FROM (VALUES 1, 2) t2(b)", UNSUPPORTED_CORRELATED_SUBQUERY_ERROR_MSG); } @@ -91,29 +91,31 @@ public void testUnsupportedSubqueriesWithCoercions() public void testCorrelatedSubqueriesWithLimit() { assertions.assertQuery( - "select (select t.a from (values 1, 2) t(a) where t.a=t2.b limit 1) from (values 1) t2(b)", + "SELECT (SELECT t.a FROM (VALUES 1, 2) t(a) WHERE t.a=t2.b LIMIT 1) FROM (VALUES 1) t2(b)", "VALUES 1"); - // cannot enforce limit 2 on correlated subquery + assertions.assertQuery( + "SELECT (SELECT t.a FROM (VALUES 1, 2) t(a) WHERE t.a=t2.b LIMIT 2) FROM (VALUES 1) t2(b)", + "VALUES 1"); + // cannot enforce LIMIT on correlated subquery assertions.assertFails( - "select (select t.a from (values 1, 2) t(a) where t.a=t2.b limit 2) from (values 1) t2(b)", + "SELECT (SELECT t.a FROM (VALUES 1, 2, 3) t(a) WHERE t.a=t2.b LIMIT 2) from (VALUES 1) t2(b)", UNSUPPORTED_CORRELATED_SUBQUERY_ERROR_MSG); assertions.assertQuery( - "select (select sum(t.a) from (values 1, 2) t(a) where t.a=t2.b group by t.a limit 2) from (values 1) t2(b)", + "SELECT (SELECT sum(t.a) FROM (VALUES 1, 2) t(a) WHERE t.a=t2.b group by t.a LIMIT 2) FROM (VALUES 1) t2(b)", "VALUES BIGINT '1'"); assertions.assertQuery( - "select (select count(*) from (select t.a from (values 1, 1, null, 3) t(a) limit 1) t where t.a=t2.b) from (values 1, 2) t2(b)", + "SELECT (SELECT count(*) FROM (SELECT t.a FROM (VALUES 1, 1, null, 3) t(a) LIMIT 1) t WHERE t.a=t2.b) FROM (VALUES 1, 2) t2(b)", "VALUES BIGINT '1', BIGINT '0'"); assertExistsRewrittenToAggregationBelowJoin( - "select EXISTS(select 1 from (values 1, 1, 3) t(a) where t.a=t2.b limit 1) from (values 1, 2) t2(b)", + "SELECT EXISTS(SELECT 1 FROM (VALUES 1, 1, 3) t(a) WHERE t.a=t2.b LIMIT 1) FROM (VALUES 1, 2) t2(b)", "VALUES true, false", false); - // TransformCorrelatedScalarAggregationToJoin does not fire since limit is above aggregation node - assertions.assertFails( - "select (select count(*) from (values 1, 1, 3) t(a) where t.a=t2.b limit 1) from (values 1) t2(b)", - UNSUPPORTED_CORRELATED_SUBQUERY_ERROR_MSG); + assertions.assertQuery( + "SELECT (SELECT count(*) FROM (VALUES 1, 1, 3) t(a) WHERE t.a=t2.b LIMIT 1) FROM (VALUES 1) t2(b)", + "VALUES BIGINT '2'"); assertExistsRewrittenToAggregationBelowJoin( - "SELECT EXISTS(SELECT 1 FROM (values ('x', 1)) u(x, cid) WHERE x = 'x' AND t.cid = cid LIMIT 1) " + - "FROM (values 1) t(cid)", + "SELECT EXISTS(SELECT 1 FROM (VALUES ('x', 1)) u(x, cid) WHERE x = 'x' AND t.cid = cid LIMIT 1) " + + "FROM (VALUES 1) t(cid)", "VALUES true", false); } @@ -123,45 +125,45 @@ public void testCorrelatedSubqueriesWithGroupBy() { // t.a is not a "constant" column, group by does not guarantee single row per correlated subquery assertions.assertFails( - "select (select count(*) from (values 1, 2, 3, null) t(a) where t.a 1) from (values 1, 2) t2(b)", + "SELECT (SELECT count(*) FROM (VALUES 1, 1, 2, 3, null) t(a) WHERE t.a 1) FROM (VALUES 1, 2) t2(b)", "VALUES null, BIGINT '2'"); assertExistsRewrittenToAggregationBelowJoin( - "select EXISTS(select 1 from (values 1, 1, 3) t(a) where t.a=t2.b GROUP BY t.a) from (values 1, 2) t2(b)", + "SELECT EXISTS(SELECT 1 FROM (VALUES 1, 1, 3) t(a) WHERE t.a=t2.b GROUP BY t.a) FROM (VALUES 1, 2) t2(b)", "VALUES true, false", false); assertExistsRewrittenToAggregationBelowJoin( - "select EXISTS(select 1 from (values (1, 2), (1, 2), (null, null), (3, 3)) t(a, b) where t.a=t2.b GROUP BY t.a, t.b) from (values 1, 2) t2(b)", + "SELECT EXISTS(SELECT 1 FROM (VALUES (1, 2), (1, 2), (null, null), (3, 3)) t(a, b) WHERE t.a=t2.b GROUP BY t.a, t.b) FROM (VALUES 1, 2) t2(b)", "VALUES true, false", true); assertExistsRewrittenToAggregationAboveJoin( - "select EXISTS(select 1 from (values (1, 2), (1, 2), (null, null), (3, 3)) t(a, b) where t.a 1) from (values 1, 2) t2(b)", + "SELECT EXISTS(SELECT * FROM (VALUES 1, 1, 2, 3) t(a) WHERE t.a=t2.b GROUP BY t.a HAVING count(*) > 1) FROM (VALUES 1, 2) t2(b)", "VALUES true, false", false); assertions.assertQuery( - "select EXISTS(select * from (select t.a from (values (1, 1), (1, 1), (1, 2), (1, 2), (3, 3)) t(a, b) where t.b=t2.b GROUP BY t.a HAVING count(*) > 1) t where t.a=t2.b)" + - " from (values 1, 2) t2(b)", + "SELECT EXISTS(SELECT * FROM (SELECT t.a FROM (VALUES (1, 1), (1, 1), (1, 2), (1, 2), (3, 3)) t(a, b) WHERE t.b=t2.b GROUP BY t.a HAVING count(*) > 1) t WHERE t.a=t2.b)" + + " FROM (VALUES 1, 2) t2(b)", "VALUES true, false"); assertExistsRewrittenToAggregationBelowJoin( - "select EXISTS(select * from (values 1, 1, 2, 3) t(a) where t.a=t2.b GROUP BY (t.a) HAVING count(*) > 1) from (values 1, 2) t2(b)", + "SELECT EXISTS(SELECT * FROM (VALUES 1, 1, 2, 3) t(a) WHERE t.a=t2.b GROUP BY (t.a) HAVING count(*) > 1) FROM (VALUES 1, 2) t2(b)", "VALUES true, false", false); } @@ -170,14 +172,14 @@ public void testCorrelatedSubqueriesWithGroupBy() public void testCorrelatedLateralWithGroupBy() { assertions.assertQuery( - "select * from (values 1, 2) t2(b), LATERAL (select t.a from (values 1, 1, 3) t(a) where t.a=t2.b GROUP BY t.a)", + "SELECT * FROM (VALUES 1, 2) t2(b), LATERAL (SELECT t.a FROM (VALUES 1, 1, 3) t(a) WHERE t.a=t2.b GROUP BY t.a)", "VALUES (1, 1)"); assertions.assertQuery( - "select * from (values 1, 2) t2(b), LATERAL (select count(*) from (values 1, 1, 2, 3) t(a) where t.a=t2.b GROUP BY t.a HAVING count(*) > 1)", + "SELECT * FROM (VALUES 1, 2) t2(b), LATERAL (SELECT count(*) FROM (VALUES 1, 1, 2, 3) t(a) WHERE t.a=t2.b GROUP BY t.a HAVING count(*) > 1)", "VALUES (1, BIGINT '2')"); // correlated subqueries with grouping sets are not supported assertions.assertFails( - "select * from (values 1, 2) t2(b), LATERAL (select t.a, t.b, count(*) from (values (1, 1), (1, 2), (2, 2), (3, 3)) t(a, b) where t.a=t2.b GROUP BY GROUPING SETS ((t.a, t.b), (t.a)))", + "SELECT * FROM (VALUES 1, 2) t2(b), LATERAL (SELECT t.a, t.b, count(*) FROM (VALUES (1, 1), (1, 2), (2, 2), (3, 3)) t(a, b) WHERE t.a=t2.b GROUP BY GROUPING SETS ((t.a, t.b), (t.a)))", UNSUPPORTED_CORRELATED_SUBQUERY_ERROR_MSG); } diff --git a/presto-tests/src/main/java/io/prestosql/tests/AbstractTestQueries.java b/presto-tests/src/main/java/io/prestosql/tests/AbstractTestQueries.java index f3e9468fd5f2..212069618828 100644 --- a/presto-tests/src/main/java/io/prestosql/tests/AbstractTestQueries.java +++ b/presto-tests/src/main/java/io/prestosql/tests/AbstractTestQueries.java @@ -3360,9 +3360,12 @@ public void testCorrelatedScalarSubqueries() // two level of nesting assertQuery("SELECT * FROM nation n WHERE 2 = (SELECT (SELECT 2 * n.nationkey))"); + // redundant LIMIT in subquery + assertQuery("SELECT (SELECT count(*) FROM (VALUES (7,1)) t(orderkey, value) WHERE orderkey = corr_key LIMIT 1) FROM (values 7) t(corr_key)"); + // explicit LIMIT in subquery assertQueryFails( - "SELECT (SELECT count(*) FROM (VALUES (7,1)) t(orderkey, value) WHERE orderkey = corr_key LIMIT 1) FROM (values 7) t(corr_key)", + "SELECT (SELECT count(*) FROM (VALUES (7,1)) t(orderkey, value) WHERE orderkey = corr_key GROUP BY value LIMIT 1) FROM (values 7) t(corr_key)", "line 1:9: Given correlated subquery is not supported"); }