diff --git a/pkg/sql/exec_util.go b/pkg/sql/exec_util.go index 31333f9fd01c..984866dbb354 100644 --- a/pkg/sql/exec_util.go +++ b/pkg/sql/exec_util.go @@ -3336,6 +3336,10 @@ func (m *sessionDataMutator) SetUnconstrainedNonCoveringIndexScanEnabled(val boo m.data.UnconstrainedNonCoveringIndexScanEnabled = val } +func (m *sessionDataMutator) SetDisableHoistProjectionInJoinLimitation(val bool) { + m.data.DisableHoistProjectionInJoinLimitation = val +} + func (m *sessionDataMutator) SetTroubleshootingModeEnabled(val bool) { m.data.TroubleshootingMode = val } diff --git a/pkg/sql/logictest/testdata/logic_test/information_schema b/pkg/sql/logictest/testdata/logic_test/information_schema index 5719b33cdf30..9f873f6f8918 100644 --- a/pkg/sql/logictest/testdata/logic_test/information_schema +++ b/pkg/sql/logictest/testdata/logic_test/information_schema @@ -4690,6 +4690,7 @@ default_transaction_quality_of_service regular default_transaction_read_only off default_transaction_use_follower_reads off default_with_oids off +disable_hoist_projection_in_join_limitation off disable_partially_distributed_plans off disable_plan_gists off disallow_full_table_scans off diff --git a/pkg/sql/logictest/testdata/logic_test/pg_catalog b/pkg/sql/logictest/testdata/logic_test/pg_catalog index 5f643990f086..9daa3637c13b 100644 --- a/pkg/sql/logictest/testdata/logic_test/pg_catalog +++ b/pkg/sql/logictest/testdata/logic_test/pg_catalog @@ -4173,6 +4173,7 @@ default_transaction_quality_of_service regular NULL default_transaction_read_only off NULL NULL NULL string default_transaction_use_follower_reads off NULL NULL NULL string default_with_oids off NULL NULL NULL string +disable_hoist_projection_in_join_limitation off NULL NULL NULL string disable_partially_distributed_plans off NULL NULL NULL string disable_plan_gists off NULL NULL NULL string disallow_full_table_scans off NULL NULL NULL string @@ -4299,6 +4300,7 @@ default_transaction_quality_of_service regular NULL default_transaction_read_only off NULL user NULL off off default_transaction_use_follower_reads off NULL user NULL off off default_with_oids off NULL user NULL off off +disable_hoist_projection_in_join_limitation off NULL user NULL off off disable_partially_distributed_plans off NULL user NULL off off disable_plan_gists off NULL user NULL off off disallow_full_table_scans off NULL user NULL off off @@ -4421,6 +4423,7 @@ default_transaction_quality_of_service NULL NULL NULL default_transaction_read_only NULL NULL NULL NULL NULL default_transaction_use_follower_reads NULL NULL NULL NULL NULL default_with_oids NULL NULL NULL NULL NULL +disable_hoist_projection_in_join_limitation NULL NULL NULL NULL NULL disable_partially_distributed_plans NULL NULL NULL NULL NULL disable_plan_gists NULL NULL NULL NULL NULL disallow_full_table_scans NULL NULL NULL NULL NULL diff --git a/pkg/sql/logictest/testdata/logic_test/show_source b/pkg/sql/logictest/testdata/logic_test/show_source index 7c961d6d4f5b..6764f90d3f45 100644 --- a/pkg/sql/logictest/testdata/logic_test/show_source +++ b/pkg/sql/logictest/testdata/logic_test/show_source @@ -46,6 +46,7 @@ default_transaction_quality_of_service regular default_transaction_read_only off default_transaction_use_follower_reads off default_with_oids off +disable_hoist_projection_in_join_limitation off disable_partially_distributed_plans off disable_plan_gists off disallow_full_table_scans off diff --git a/pkg/sql/opt/memo/testdata/stats_quality/tpcc b/pkg/sql/opt/memo/testdata/stats_quality/tpcc index c522fec3dd32..9ad2e72d5658 100644 --- a/pkg/sql/opt/memo/testdata/stats_quality/tpcc +++ b/pkg/sql/opt/memo/testdata/stats_quality/tpcc @@ -15,7 +15,7 @@ import file=tpcc_stats_w10 # reflect on-line database activity as typically found in production # environments. # -------------------------------------------------- -stats-quality format=hide-qual database=tpcc stats-quality-prefix=new_order_01 ignore-tables=1 +stats-quality format=hide-qual database=tpcc set=save_tables_prefix=new_order_01 ignore-tables=1 SELECT w_tax FROM warehouse WHERE w_id = 1 ---- ---- @@ -46,7 +46,7 @@ column_names row_count_est row_count_err distinct_count_est distinct_count_e ---- ---- -stats-quality format=hide-qual database=tpcc stats-quality-prefix=new_order_02 ignore-tables=1 +stats-quality format=hide-qual database=tpcc set=save_tables_prefix=new_order_02 ignore-tables=1 SELECT c_discount, c_last, c_credit FROM customer WHERE c_w_id = 1 AND c_d_id = 1 AND c_id = 50 @@ -87,7 +87,7 @@ column_names row_count_est row_count_err distinct_count_est distinct_count_e ---- ---- -stats-quality format=hide-qual database=tpcc stats-quality-prefix=new_order_03 +stats-quality format=hide-qual database=tpcc set=save_tables_prefix=new_order_03 SELECT i_price, i_name, i_data FROM item WHERE i_id IN (125, 150, 175, 200, 25, 50, 75, 100, 225, 250, 275, 300) @@ -131,7 +131,7 @@ column_names row_count_est row_count_err distinct_count_est distinct_count_e ---- ---- -stats-quality format=hide-qual database=tpcc stats-quality-prefix=new_order_04 ignore-tables=1 +stats-quality format=hide-qual database=tpcc set=save_tables_prefix=new_order_04 ignore-tables=1 SELECT s_quantity, s_ytd, s_order_cnt, s_remote_cnt, s_data, s_dist_05 FROM stock WHERE (s_i_id, s_w_id) IN ((1000, 4), (900, 4), (1100, 4), (1500, 4), (1400, 4)) @@ -193,7 +193,7 @@ column_names row_count_est row_count_err distinct_count_est distinct_count # stringent response time requirements to satisfy on-line users. In addition, # this transaction includes non-primary key access to the CUSTOMER table. # -------------------------------------------------- -stats-quality format=hide-qual database=tpcc stats-quality-prefix=payment_01 ignore-tables=1 +stats-quality format=hide-qual database=tpcc set=save_tables_prefix=payment_01 ignore-tables=1 SELECT c_id FROM customer WHERE c_w_id = 1 AND c_d_id = 1 AND c_last = 'ANTIABLEABLE' @@ -248,7 +248,7 @@ column_names row_count_est row_count_err distinct_count_est distinct_count_e # users. In addition, this table includes non-primary key access to the # CUSTOMER table. # -------------------------------------------------- -stats-quality format=hide-qual database=tpcc stats-quality-prefix=order_status_01 ignore-tables=1 +stats-quality format=hide-qual database=tpcc set=save_tables_prefix=order_status_01 ignore-tables=1 SELECT c_balance, c_first, c_middle, c_last FROM customer WHERE c_w_id = 1 AND c_d_id = 1 AND c_id = 50 @@ -291,7 +291,7 @@ column_names row_count_est row_count_err distinct_count_est distinct_count_e ---- ---- -stats-quality format=hide-qual database=tpcc stats-quality-prefix=order_status_02 ignore-tables=(1,3) +stats-quality format=hide-qual database=tpcc set=save_tables_prefix=order_status_02 ignore-tables=(1,3) SELECT c_id, c_balance, c_first, c_middle FROM customer WHERE c_w_id = 2 AND c_d_id = 2 AND c_last = 'ANTIBARESE' @@ -358,7 +358,7 @@ column_names row_count_est row_count_err distinct_count_est distinct_count_e ---- ---- -stats-quality format=hide-qual database=tpcc stats-quality-prefix=order_status_03 ignore-tables=1 +stats-quality format=hide-qual database=tpcc set=save_tables_prefix=order_status_03 ignore-tables=1 SELECT o_id, o_entry_d, o_carrier_id FROM "order" WHERE o_w_id = 4 AND o_d_id = 3 AND o_c_id = 10 @@ -401,7 +401,7 @@ column_names row_count_est row_count_err distinct_count_est distinct_count ---- ---- -stats-quality format=hide-qual database=tpcc stats-quality-prefix=order_status_04 ignore-tables=1 +stats-quality format=hide-qual database=tpcc set=save_tables_prefix=order_status_04 ignore-tables=1 SELECT ol_i_id, ol_supply_w_id, ol_quantity, ol_amount, ol_delivery_d FROM order_line WHERE ol_w_id = 1 AND ol_d_id = 1 AND ol_o_id = 1000 @@ -463,7 +463,7 @@ column_names row_count_est row_count_err distinct_count_est distinct_cou # indicating transaction completion. The result of the deferred execution is # recorded into a result file. # -------------------------------------------------- -stats-quality format=hide-qual database=tpcc stats-quality-prefix=delivery_01 ignore-tables=1 +stats-quality format=hide-qual database=tpcc set=save_tables_prefix=delivery_01 ignore-tables=1 SELECT no_o_id FROM new_order WHERE no_w_id = 7 AND no_d_id = 6 @@ -500,7 +500,7 @@ column_names row_count_est row_count_err distinct_count_est distinct_count_e ---- ---- -stats-quality format=hide-qual database=tpcc stats-quality-prefix=delivery_02 +stats-quality format=hide-qual database=tpcc set=save_tables_prefix=delivery_02 SELECT sum(ol_amount) FROM order_line WHERE ol_w_id = 8 AND ol_d_id = 6 AND ol_o_id = 1000 @@ -559,7 +559,7 @@ column_names row_count_est row_count_err distinct_count_est distinct_count_e # heavy read-only database transaction with a low frequency of execution, a # relaxed response time requirement, and relaxed consistency requirements. # -------------------------------------------------- -stats-quality format=hide-qual database=tpcc stats-quality-prefix=stock_level_01 ignore-tables=1 +stats-quality format=hide-qual database=tpcc set=save_tables_prefix=stock_level_01 ignore-tables=1 SELECT d_next_o_id FROM district WHERE d_w_id = 4 AND d_id = 9 @@ -594,7 +594,7 @@ column_names row_count_est row_count_err distinct_count_est distinct_count_ ---- ---- -stats-quality format=hide-qual database=tpcc stats-quality-prefix=stock_level_02 +stats-quality format=hide-qual database=tpcc set=save_tables_prefix=stock_level_02 SELECT count(DISTINCT s_i_id) FROM order_line JOIN stock @@ -697,7 +697,7 @@ column_names row_count_est row_count_err distinct_count_est distinct_count_e # These queries run after TPCC in order to check database consistency. # They are not part of the benchmark itself. # -------------------------------------------------- -stats-quality format=hide-qual database=tpcc stats-quality-prefix=consistency_01 +stats-quality format=hide-qual database=tpcc set=save_tables_prefix=consistency_01 SELECT count(*) FROM warehouse FULL OUTER JOIN @@ -812,7 +812,7 @@ column_names row_count_est row_count_err distinct_count_est distinct_count_e ---- ---- -stats-quality format=hide-qual database=tpcc stats-quality-prefix=consistency_02 +stats-quality format=hide-qual database=tpcc set=save_tables_prefix=consistency_02 SELECT d_next_o_id FROM district ORDER BY d_w_id, d_id @@ -845,7 +845,7 @@ column_names row_count_est row_count_err distinct_count_est distinct_count_ ---- ---- -stats-quality format=hide-qual database=tpcc stats-quality-prefix=consistency_03 +stats-quality format=hide-qual database=tpcc set=save_tables_prefix=consistency_03 SELECT max(no_o_id) FROM new_order GROUP BY no_d_id, no_w_id @@ -900,7 +900,7 @@ column_names row_count_est row_count_err distinct_count_est distinct_count_e ---- ---- -stats-quality format=hide-qual database=tpcc stats-quality-prefix=consistency_04 +stats-quality format=hide-qual database=tpcc set=save_tables_prefix=consistency_04 SELECT max(o_id) FROM "order" GROUP BY o_d_id, o_w_id @@ -955,7 +955,7 @@ column_names row_count_est row_count_err distinct_count_est distinct_count_e ---- ---- -stats-quality format=hide-qual database=tpcc stats-quality-prefix=consistency_05 +stats-quality format=hide-qual database=tpcc set=save_tables_prefix=consistency_05 SELECT count(*) FROM ( @@ -1062,7 +1062,7 @@ column_names row_count_est row_count_err distinct_count_est distinct_count_e ---- ---- -stats-quality format=hide-qual database=tpcc stats-quality-prefix=consistency_06 +stats-quality format=hide-qual database=tpcc set=save_tables_prefix=consistency_06 SELECT sum(o_ol_cnt) FROM "order" GROUP BY o_w_id, o_d_id @@ -1116,7 +1116,7 @@ column_names row_count_est row_count_err distinct_count_est distinct_count_e ---- ---- -stats-quality format=hide-qual database=tpcc stats-quality-prefix=consistency_07 +stats-quality format=hide-qual database=tpcc set=save_tables_prefix=consistency_07 SELECT count(*) FROM order_line GROUP BY ol_w_id, ol_d_id @@ -1165,7 +1165,7 @@ column_names row_count_est row_count_err distinct_count_est distinct_count_e ---- ---- -stats-quality format=hide-qual database=tpcc stats-quality-prefix=consistency_08 +stats-quality format=hide-qual database=tpcc set=save_tables_prefix=consistency_08 (SELECT no_w_id, no_d_id, no_o_id FROM new_order) EXCEPT ALL (SELECT o_w_id, o_d_id, o_id FROM "order" WHERE o_carrier_id IS NULL) @@ -1280,7 +1280,7 @@ column_names row_count_est row_count_err distinct_count_est distinct_count ---- ---- -stats-quality format=hide-qual database=tpcc stats-quality-prefix=consistency_09 +stats-quality format=hide-qual database=tpcc set=save_tables_prefix=consistency_09 (SELECT o_w_id, o_d_id, o_id FROM "order" WHERE o_carrier_id IS NULL) EXCEPT ALL (SELECT no_w_id, no_d_id, no_o_id FROM new_order) @@ -1395,7 +1395,7 @@ column_names row_count_est row_count_err distinct_count_est distinct_count_e ---- ---- -stats-quality format=hide-qual database=tpcc stats-quality-prefix=consistency_10 +stats-quality format=hide-qual database=tpcc set=save_tables_prefix=consistency_10 ( SELECT o_w_id, o_d_id, o_id, o_ol_cnt FROM "order" @@ -1508,7 +1508,7 @@ column_names row_count_est row_count_err distinct_count_est distinct_count_e ---- ---- -stats-quality format=hide-qual database=tpcc stats-quality-prefix=consistency_11 +stats-quality format=hide-qual database=tpcc set=save_tables_prefix=consistency_11 ( SELECT ol_w_id, ol_d_id, ol_o_id, count(*) FROM order_line @@ -1621,7 +1621,7 @@ column_names row_count_est row_count_err distinct_count_est distinct_count_e ---- ---- -stats-quality database=tpcc stats-quality-prefix=consistency_12 +stats-quality database=tpcc set=save_tables_prefix=consistency_12 SELECT count(*) FROM ( diff --git a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q01 b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q01 index 20baaf61b1e4..8f124959aafe 100644 --- a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q01 +++ b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q01 @@ -17,7 +17,7 @@ import file=tpch_stats # LINESTATUS, and listed in ascending order of RETURNFLAG and LINESTATUS. A # count of the number of lineitems in each group is included. # -------------------------------------------------- -stats-quality database=tpch stats-quality-prefix=q1 +stats-quality database=tpch set=save_tables_prefix=q1 SELECT l_returnflag, l_linestatus, diff --git a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q02 b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q02 index 878a9f5690a2..34aaefcca64e 100644 --- a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q02 +++ b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q02 @@ -22,7 +22,7 @@ import file=tpch_stats # 1. Allow Select to be pushed below Ordinality used to add key column # 2. Add decorrelation rule for Ordinality/RowKey # -------------------------------------------------- -stats-quality database=tpch stats-quality-prefix=q2 +stats-quality database=tpch set=save_tables_prefix=q2 SELECT s_acctbal, s_name, diff --git a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q03 b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q03 index ef33e14c15b1..c81d77b23103 100644 --- a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q03 +++ b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q03 @@ -15,7 +15,7 @@ import file=tpch_stats # decreasing order of revenue. If more than 10 unshipped orders exist, only the # 10 orders with the largest revenue are listed. # -------------------------------------------------- -stats-quality database=tpch stats-quality-prefix=q3 +stats-quality database=tpch set=save_tables_prefix=q3 SELECT l_orderkey, sum(l_extendedprice * (1 - l_discount)) AS revenue, diff --git a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q04 b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q04 index 033bc7047e7d..bd16eb3c6427 100644 --- a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q04 +++ b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q04 @@ -15,7 +15,7 @@ import file=tpch_stats # committed date. The query lists the count of such orders for each order # priority sorted in ascending priority order. # -------------------------------------------------- -stats-quality database=tpch stats-quality-prefix=q4 +stats-quality database=tpch set=save_tables_prefix=q4 SELECT o_orderpriority, count(*) AS order_count diff --git a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q05 b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q05 index 4c8080c86f95..c0253301079c 100644 --- a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q05 +++ b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q05 @@ -18,7 +18,7 @@ import file=tpch_stats # all qualifying lineitems in a particular nation is defined as # sum(l_extendedprice * (1 - l_discount)). # -------------------------------------------------- -stats-quality database=tpch stats-quality-prefix=q5 +stats-quality database=tpch set=save_tables_prefix=q5 SELECT n_name, sum(l_extendedprice * (1 - l_discount)) AS revenue diff --git a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q06 b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q06 index 84ff69a4021c..53f82b75b4c2 100644 --- a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q06 +++ b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q06 @@ -19,7 +19,7 @@ import file=tpch_stats # increase is equal to the sum of [l_extendedprice * l_discount] for all # lineitems with discounts and quantities in the qualifying range. # -------------------------------------------------- -stats-quality database=tpch stats-quality-prefix=q6 +stats-quality database=tpch set=save_tables_prefix=q6 SELECT sum(l_extendedprice * l_discount) AS revenue FROM diff --git a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q07 b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q07 index 9c287bdabec7..5aadac10ecee 100644 --- a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q07 +++ b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q07 @@ -17,7 +17,7 @@ import file=tpch_stats # that took place in that year. The query orders the answer by Supplier nation, # Customer nation, and year (all ascending). # -------------------------------------------------- -stats-quality database=tpch stats-quality-prefix=q7 +stats-quality database=tpch set=save_tables_prefix=q7 SELECT supp_nation, cust_nation, diff --git a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q08 b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q08 index 4db72cef5a94..77cdd560427e 100644 --- a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q08 +++ b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q08 @@ -16,7 +16,7 @@ import file=tpch_stats # from the given nation. The query determines this for the years 1995 and 1996 # presented in this order. # -------------------------------------------------- -stats-quality database=tpch stats-quality-prefix=q8 +stats-quality database=tpch set=save_tables_prefix=q8 SELECT o_year, sum(CASE diff --git a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q09 b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q09 index 20ef0f923370..37a5a3e10270 100644 --- a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q09 +++ b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q09 @@ -20,7 +20,7 @@ import file=tpch_stats # nations in ascending alphabetical order and, for each nation, the year and # profit in descending order by year (most recent first). # -------------------------------------------------- -stats-quality database=tpch stats-quality-prefix=q9 +stats-quality database=tpch set=save_tables_prefix=q9 SELECT nation, o_year, diff --git a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q10 b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q10 index f75cc1f376e5..7d62fb950063 100644 --- a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q10 +++ b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q10 @@ -18,7 +18,7 @@ import file=tpch_stats # Revenue lost is defined as sum(l_extendedprice*(1-l_discount)) for all # qualifying lineitems. # -------------------------------------------------- -stats-quality database=tpch stats-quality-prefix=q10 +stats-quality database=tpch set=save_tables_prefix=q10 SELECT c_custkey, c_name, diff --git a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q11 b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q11 index 7d533b7832ea..2803bfc6e52a 100644 --- a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q11 +++ b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q11 @@ -14,7 +14,7 @@ import file=tpch_stats # available parts. The query displays the part number and the value of those # parts in descending order of value. # -------------------------------------------------- -stats-quality database=tpch stats-quality-prefix=q11 +stats-quality database=tpch set=save_tables_prefix=q11 SELECT ps_partkey, sum(ps_supplycost * ps_availqty::float) AS value diff --git a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q12 b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q12 index 5a7f5b86e977..47b71c4505e2 100644 --- a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q12 +++ b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q12 @@ -18,7 +18,7 @@ import file=tpch_stats # The late lineitems are partitioned into two groups, those with priority URGENT # or HIGH, and those with a priority other than URGENT or HIGH. # -------------------------------------------------- -stats-quality database=tpch stats-quality-prefix=q12 +stats-quality database=tpch set=save_tables_prefix=q12 SELECT l_shipmode, sum(CASE diff --git a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q13 b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q13 index bb08251a2b82..0df26ecd0e65 100644 --- a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q13 +++ b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q13 @@ -15,7 +15,7 @@ import file=tpch_stats # several special categories of orders. Special categories are identified in the # order comment column by looking for a particular pattern. # -------------------------------------------------- -stats-quality database=tpch stats-quality-prefix=q13 +stats-quality database=tpch set=save_tables_prefix=q13 SELECT c_count, count(*) AS custdist FROM ( diff --git a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q14 b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q14 index c273a8e7702a..c08c50af7cb7 100644 --- a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q14 +++ b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q14 @@ -15,7 +15,7 @@ import file=tpch_stats # shipped in that month and gives the percentage. Revenue is defined as # (l_extendedprice * (1-l_discount)). # -------------------------------------------------- -stats-quality database=tpch stats-quality-prefix=q14 +stats-quality database=tpch set=save_tables_prefix=q14 SELECT 100.00 * sum(CASE WHEN p_type LIKE 'PROMO%' diff --git a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q15 b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q15 index dde14d716e23..300610f61813 100644 --- a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q15 +++ b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q15 @@ -29,7 +29,7 @@ CREATE VIEW revenue0 (supplier_no, total_revenue) AS l_suppkey; ---- -stats-quality database=tpch stats-quality-prefix=q15 +stats-quality database=tpch set=save_tables_prefix=q15 SELECT s_suppkey, s_name, diff --git a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q16 b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q16 index a864c0329ccb..d82c83af1704 100644 --- a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q16 +++ b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q16 @@ -18,7 +18,7 @@ import file=tpch_stats # Business Bureau. Results must be presented in descending count and ascending # brand, type, and size. # -------------------------------------------------- -stats-quality database=tpch stats-quality-prefix=q16 +stats-quality database=tpch set=save_tables_prefix=q16 SELECT p_brand, p_type, diff --git a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q17 b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q17 index 2fd309ac23cc..9fd0d5597f81 100644 --- a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q17 +++ b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q17 @@ -20,7 +20,7 @@ import file=tpch_stats # TODO: # 1. Allow Select to be pushed below Ordinality used to add key column # -------------------------------------------------- -stats-quality database=tpch stats-quality-prefix=q17 +stats-quality database=tpch set=save_tables_prefix=q17 SELECT sum(l_extendedprice) / 7.0 AS avg_yearly FROM diff --git a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q18 b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q18 index 91faff3f150b..47f9c2801495 100644 --- a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q18 +++ b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q18 @@ -15,7 +15,7 @@ import file=tpch_stats # orders. The query lists the customer name, customer key, the order key, date # and total price and the quantity for the order. # -------------------------------------------------- -stats-quality database=tpch stats-quality-prefix=q18 +stats-quality database=tpch set=save_tables_prefix=q18 SELECT c_name, c_custkey, diff --git a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q19 b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q19 index 81eb9957b874..b3f6b29d1b1f 100644 --- a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q19 +++ b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q19 @@ -16,7 +16,7 @@ import file=tpch_stats # person. Parts are selected based on the combination of specific brands, a list # of containers, and a range of sizes. # -------------------------------------------------- -stats-quality database=tpch stats-quality-prefix=q19 +stats-quality database=tpch set=save_tables_prefix=q19 SELECT sum(l_extendedprice* (1 - l_discount)) AS revenue FROM diff --git a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q20 b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q20 index 807a5eec232c..8f6b6f87e551 100644 --- a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q20 +++ b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q20 @@ -18,7 +18,7 @@ import file=tpch_stats # TODO: # 1. Push 'forest%' prefix filter down into Scan # -------------------------------------------------- -stats-quality database=tpch stats-quality-prefix=q20 +stats-quality database=tpch set=save_tables_prefix=q20 SELECT s_name, s_address diff --git a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q21 b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q21 index 56930f3adbfa..95cd1eb7e6da 100644 --- a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q21 +++ b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q21 @@ -14,7 +14,7 @@ import file=tpch_stats # supplier order (with current status of 'F') where they were the only supplier # who failed to meet the committed delivery date. # -------------------------------------------------- -stats-quality database=tpch stats-quality-prefix=q21 +stats-quality database=tpch set=save_tables_prefix=q21 SELECT s_name, count(*) AS numwait diff --git a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q22 b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q22 index e1af99e17b8e..47b71a8fdb7b 100644 --- a/pkg/sql/opt/memo/testdata/stats_quality/tpch/q22 +++ b/pkg/sql/opt/memo/testdata/stats_quality/tpch/q22 @@ -15,7 +15,7 @@ import file=tpch_stats # “positive” account balance. It also reflects the magnitude of that balance. # Country code is defined as the first two characters of c_phone. # -------------------------------------------------- -stats-quality database=tpch stats-quality-prefix=q22 +stats-quality database=tpch set=save_tables_prefix=q22 SELECT cntrycode, count(*) AS numcust, diff --git a/pkg/sql/opt/norm/testdata/rules/ordering b/pkg/sql/opt/norm/testdata/rules/ordering index 2a602c4202d6..02112e815b80 100644 --- a/pkg/sql/opt/norm/testdata/rules/ordering +++ b/pkg/sql/opt/norm/testdata/rules/ordering @@ -246,7 +246,7 @@ project # -------------------------------------------------- # SimplifyWithBindingOrdering # -------------------------------------------------- -norm propagate-input-ordering expect=SimplifyWithBindingOrdering +norm set=propagate_input_ordering=true expect=SimplifyWithBindingOrdering WITH cte AS (SELECT a, b FROM abcde ORDER BY a, b, c) SELECT * FROM cte, xyz ---- @@ -277,7 +277,7 @@ with &1 (cte) │ └── fd: (10)-->(11,12) └── filters (true) -norm propagate-input-ordering expect=SimplifyWithBindingOrdering +norm set=propagate_input_ordering=true expect=SimplifyWithBindingOrdering WITH cte AS (SELECT d, 1 AS one, e FROM abcde ORDER BY d, one, e) SELECT * FROM cte ---- diff --git a/pkg/sql/opt/optbuilder/testdata/fk-checks-delete b/pkg/sql/opt/optbuilder/testdata/fk-checks-delete index dde80065ff05..324fa0c55a6c 100644 --- a/pkg/sql/opt/optbuilder/testdata/fk-checks-delete +++ b/pkg/sql/opt/optbuilder/testdata/fk-checks-delete @@ -140,7 +140,7 @@ delete doublechild └── p1:7 = 10 # Verify that the join hint is set. -build prefer-lookup-joins-for-fks +build set=prefer_lookup_joins_for_fks=true DELETE FROM parent WHERE p = 3 ---- delete parent diff --git a/pkg/sql/opt/optbuilder/testdata/fk-checks-insert b/pkg/sql/opt/optbuilder/testdata/fk-checks-insert index a6e0c5961e91..6abb42dc9f79 100644 --- a/pkg/sql/opt/optbuilder/testdata/fk-checks-insert +++ b/pkg/sql/opt/optbuilder/testdata/fk-checks-insert @@ -657,7 +657,7 @@ insert multi_ref_child └── (1, NULL, NULL, NULL) # Verify that the join hint is set. -build prefer-lookup-joins-for-fks +build set=prefer_lookup_joins_for_fks=true INSERT INTO child VALUES (100, 1), (200, 1) ---- insert child diff --git a/pkg/sql/opt/optbuilder/testdata/fk-checks-update b/pkg/sql/opt/optbuilder/testdata/fk-checks-update index 229d11bd385f..34248f2f540c 100644 --- a/pkg/sql/opt/optbuilder/testdata/fk-checks-update +++ b/pkg/sql/opt/optbuilder/testdata/fk-checks-update @@ -541,7 +541,7 @@ update fam └── d:19 = two.b:21 # Verify that the join hint is set. -build prefer-lookup-joins-for-fks +build set=prefer_lookup_joins_for_fks=true UPDATE child SET p = 4 ---- update child diff --git a/pkg/sql/opt/optbuilder/testdata/orderby b/pkg/sql/opt/optbuilder/testdata/orderby index bd394125cfbe..29216a9b64d2 100644 --- a/pkg/sql/opt/optbuilder/testdata/orderby +++ b/pkg/sql/opt/optbuilder/testdata/orderby @@ -1091,7 +1091,7 @@ sort # Try NULLS ordered last. # Next two plans should be the same. -build null-ordered-last +build set=null_ordered_last=true SELECT a, b FROM abcd ORDER BY b, c ---- sort @@ -1105,7 +1105,7 @@ sort ├── b:2 IS NULL [as=nulls_ordering_b:7] └── c:3 IS NULL [as=nulls_ordering_c:8] -build null-ordered-last +build set=null_ordered_last=true SELECT a, b FROM abcd ORDER BY b, c NULLS LAST ---- sort @@ -1120,7 +1120,7 @@ sort └── c:3 IS NULL [as=nulls_ordering_c:8] # Should be different from the plan above (1 null re-ordering). -build null-ordered-last +build set=null_ordered_last=true SELECT a, b FROM abcd ORDER BY b NULLS FIRST, c ---- sort @@ -1134,7 +1134,7 @@ sort └── c:3 IS NULL [as=nulls_ordering_c:7] # Should be different from the two plans above (2 null re-orderings). -build null-ordered-last +build set=null_ordered_last=true SELECT a, b FROM abcd ORDER BY b NULLS FIRST, c DESC NULLS LAST ---- sort @@ -1218,7 +1218,7 @@ sort # Try with NULL ordered last. # Next two plans should be the same. -build null-ordered-last +build set=null_ordered_last=true SELECT * FROM abcd ORDER BY b DESC ---- sort @@ -1231,7 +1231,7 @@ sort └── projections └── b:2 IS NULL [as=nulls_ordering_b:7] -build null-ordered-last +build set=null_ordered_last=true SELECT * FROM abcd ORDER BY b DESC NULLS FIRST ---- sort @@ -1245,7 +1245,7 @@ sort └── b:2 IS NULL [as=nulls_ordering_b:7] # Should be different from the plan above (1 null re-ordering). -build null-ordered-last +build set=null_ordered_last=true SELECT * FROM abcd ORDER BY b DESC NULLS LAST ---- sort diff --git a/pkg/sql/opt/optbuilder/testdata/propagate-input-ordering b/pkg/sql/opt/optbuilder/testdata/propagate-input-ordering index 47c75ef8db45..90b24db52639 100644 --- a/pkg/sql/opt/optbuilder/testdata/propagate-input-ordering +++ b/pkg/sql/opt/optbuilder/testdata/propagate-input-ordering @@ -8,7 +8,7 @@ exec-ddl CREATE TABLE xy (x int, y int); ---- -build propagate-input-ordering +build set=propagate_input_ordering=true SELECT * FROM (SELECT * FROM generate_series(1, 10) i ORDER BY i % 5 ASC, i ASC) ---- @@ -26,7 +26,7 @@ sort └── projections └── generate_series:1 % 5 [as=column2:2] -build propagate-input-ordering +build set=propagate_input_ordering=true WITH tmp AS (SELECT * FROM generate_series(1, 10) i ORDER BY i % 5 ASC, i ASC) SELECT * FROM tmp; ---- with &1 (tmp) @@ -51,7 +51,7 @@ with &1 (tmp) └── generate_series:1 => i:3 # The internal ordering column for i%5 should not be present in the output. -build propagate-input-ordering +build set=propagate_input_ordering=true SELECT foo FROM (SELECT i, i%2 FROM generate_series(1, 10) i ORDER BY i % 5 ASC, i ASC) AS foo ---- sort @@ -74,7 +74,7 @@ sort └── ((generate_series:1, "?column?":2) AS i, "?column?") [as=foo:4] # The internal ordering column for i%5 should not be present in the output. -build propagate-input-ordering +build set=propagate_input_ordering=true SELECT foo.* FROM (SELECT i, i%2 FROM generate_series(1, 10) i ORDER BY i % 5 ASC, i ASC) AS foo ---- sort @@ -93,7 +93,7 @@ sort └── generate_series:1 % 5 [as=column3:3] # The subquery ordering is propagated to the aggregation. -build propagate-input-ordering +build set=propagate_input_ordering=true SELECT array_agg(i) FROM (SELECT * FROM generate_series(1, 5) i ORDER BY i%2 DESC, i) ---- scalar-group-by @@ -117,7 +117,7 @@ scalar-group-by └── generate_series:1 # The input ordering is not propagated through joins. -build propagate-input-ordering +build set=propagate_input_ordering=true SELECT * FROM (SELECT * FROM generate_series(1, 2) x) tmp, (SELECT * FROM generate_series(8, 12) i ORDER BY i % 5 ASC, i ASC) tmp2; @@ -144,7 +144,7 @@ inner-join (cross) # Do not preserve the subquery ordering because the parent scope has its own # ordering. -build propagate-input-ordering +build set=propagate_input_ordering=true SELECT * FROM (SELECT * FROM generate_series(1, 10) i ORDER BY i % 5 ASC, i ASC) ORDER BY i DESC; @@ -166,7 +166,7 @@ sort └── generate_series:1 % 5 [as=column2:2] # CTEs get materialized in the desired order. -build propagate-input-ordering +build set=propagate_input_ordering=true WITH cte1 AS (SELECT b FROM ab ORDER BY a, b), cte2 AS (SELECT y FROM xy ORDER BY x, y) @@ -205,7 +205,7 @@ with &1 (cte1) └── mapping: └── xy.y:7 => y:12 -build propagate-input-ordering +build set=propagate_input_ordering=true WITH cte1 AS (SELECT b FROM ab), cte2 AS (SELECT DISTINCT ON (x) y FROM xy ORDER BY x, y) diff --git a/pkg/sql/opt/testutils/opttester/BUILD.bazel b/pkg/sql/opt/testutils/opttester/BUILD.bazel index 7996f157ae96..2e648149c730 100644 --- a/pkg/sql/opt/testutils/opttester/BUILD.bazel +++ b/pkg/sql/opt/testutils/opttester/BUILD.bazel @@ -22,6 +22,7 @@ go_library( "//pkg/roachpb", "//pkg/security/username", "//pkg/settings/cluster", + "//pkg/sql", "//pkg/sql/catalog/descpb", "//pkg/sql/catalog/schemaexpr", "//pkg/sql/opt", diff --git a/pkg/sql/opt/testutils/opttester/opt_tester.go b/pkg/sql/opt/testutils/opttester/opt_tester.go index e569b032b602..90b9e69fcc15 100644 --- a/pkg/sql/opt/testutils/opttester/opt_tester.go +++ b/pkg/sql/opt/testutils/opttester/opt_tester.go @@ -39,6 +39,7 @@ import ( "github.com/cockroachdb/cockroach/pkg/roachpb" "github.com/cockroachdb/cockroach/pkg/security/username" "github.com/cockroachdb/cockroach/pkg/settings/cluster" + "github.com/cockroachdb/cockroach/pkg/sql" "github.com/cockroachdb/cockroach/pkg/sql/catalog/descpb" "github.com/cockroachdb/cockroach/pkg/sql/catalog/schemaexpr" "github.com/cockroachdb/cockroach/pkg/sql/opt" @@ -135,6 +136,10 @@ type OptTester struct { // Flags are control knobs for tests. Note that specific testcases can // override these defaults. type Flags struct { + ctx context.Context + + evalCtx eval.Context + // ExprFormat controls the output detail of build / opt/ optsteps command // directives. ExprFormat memo.ExprFmtFlags @@ -180,21 +185,10 @@ type Flags struct { // the coster will be in the range [c - 0.5 * c, c + 0.5 * c). PerturbCost float64 - // JoinLimit is the default value for SessionData.ReorderJoinsLimit. - JoinLimit int - // PreferLookupJoinsForFK is the default value for // SessionData.PreferLookupJoinsForFKs. PreferLookupJoinsForFKs bool - // PropagateInputOrdering is the default value for - // SessionData.PropagateInputOrdering. - PropagateInputOrdering bool - - // NullOrderedLast is the default value for - // SessionData.NullOrderedLast. - NullOrderedLast bool - // Locality specifies the location of the planning node as a set of user- // defined key/value pairs, ordered from most inclusive to least inclusive. // If there are no tiers, then the node's location is not known. Examples: @@ -212,10 +206,6 @@ type Flags struct { // only used by the inject-stats commands. Table string - // SaveTablesPrefix specifies the prefix of the table to create or print - // for each subexpression in the query. - SaveTablesPrefix string - // IgnoreTables specifies the subset of stats tables which should not be // outputted by the stats-quality command. IgnoreTables util.FastIntSet @@ -258,13 +248,12 @@ type Flags struct { // QueryArgs are values for placeholders, used for assign-placeholders-*. QueryArgs []string - // UseMultiColStats is the value for SessionData.OptimizerUseMultiColStats. - // It defaults to true in New. - UseMultiColStats bool - // SkipRace indicates that a test should be skipped if the race detector is // enabled. SkipRace bool + + // ot is a reference to the OptTester owning Flags. + ot *OptTester } // New constructs a new instance of the OptTester for the given SQL statement. @@ -272,13 +261,16 @@ type Flags struct { func New(catalog cat.Catalog, sql string) *OptTester { ctx := context.Background() ot := &OptTester{ - Flags: Flags{JoinLimit: opt.DefaultJoinOrderLimit, UseMultiColStats: true}, catalog: catalog, sql: sql, ctx: ctx, semaCtx: tree.MakeSemaContext(), evalCtx: eval.MakeTestingEvalContext(cluster.MakeTestingClusterSettings()), } + ot.evalCtx.SessionData().ReorderJoinsLimit = opt.DefaultJoinOrderLimit + ot.evalCtx.SessionData().OptimizerUseMultiColStats = true + ot.Flags.ctx = ot.ctx + ot.Flags.evalCtx = ot.evalCtx ot.semaCtx.SearchPath = tree.EmptySearchPath ot.semaCtx.FunctionResolver = ot.catalog // To allow opttester tests to use now(), we hardcode a preset transaction @@ -508,16 +500,6 @@ func New(catalog cat.Catalog, sql string) *OptTester { // - import: the file path is relative to opttester/testfixtures; // - inject-stats: the file path is relative to the test file. // -// - join-limit: sets the value for SessionData.ReorderJoinsLimit, which -// indicates the number of joins at which the optimizer should stop -// attempting to reorder. -// -// - prefer-lookup-joins-for-fks: sets SessionData.PreferLookupJoinsForFKs to -// true, causing foreign key operations to prefer lookup joins. -// -// - null-ordered-last: sets SessionData.NullOrderedLast to true, which orders -// NULL values last in ascending order. -// // - cascade-levels: used to limit the depth of recursive cascades for // build-cascades. // @@ -538,13 +520,13 @@ func New(catalog cat.Catalog, sql string) *OptTester { // - memo-cycles: used with memo to search the memo for cycles and output a // path with a cycle if one is found. // -// - use-multi-col-stats: sets the value for -// SessionData.OptimizerUseMultiColStats which indicates whether or not -// multi-column statistics are used for cardinality estimation in the -// optimizer. This option requires a single boolean argument. -// // - skip-race: skips the test if the race detector is enabled. // +// - set: sets the session setting for the given SQL statement, for example: +// build set=prefer_lookup_joins_for_fks=true +// DELETE FROM parent WHERE p = 3 +// ---- +// func (ot *OptTester) RunCommand(tb testing.TB, d *datadriven.TestData) string { // Allow testcases to override the flags. for _, a := range d.CmdArgs { @@ -562,15 +544,8 @@ func (ot *OptTester) RunCommand(tb testing.TB, d *datadriven.TestData) string { ot.semaCtx.Placeholders = tree.PlaceholderInfo{} - ot.evalCtx.SessionData().ReorderJoinsLimit = int64(ot.Flags.JoinLimit) - ot.evalCtx.SessionData().PreferLookupJoinsForFKs = ot.Flags.PreferLookupJoinsForFKs - ot.evalCtx.SessionData().PropagateInputOrdering = ot.Flags.PropagateInputOrdering - ot.evalCtx.SessionData().NullOrderedLast = ot.Flags.NullOrderedLast - ot.evalCtx.SessionData().OptimizerUseMultiColStats = ot.Flags.UseMultiColStats - ot.evalCtx.TestingKnobs.OptimizerCostPerturbation = ot.Flags.PerturbCost ot.evalCtx.Locality = ot.Flags.Locality - ot.evalCtx.SessionData().SaveTablesPrefix = ot.Flags.SaveTablesPrefix ot.evalCtx.Placeholders = nil switch d.Cmd { @@ -897,6 +872,18 @@ func ruleNamesToRuleSet(args []string) (RuleSet, error) { // See OptTester.RunCommand for supported flags. func (f *Flags) Set(arg datadriven.CmdArg) error { switch arg.Key { + case "set": + for _, val := range arg.Vals { + s := strings.Split(val, "=") + if len(s) != 2 { + return errors.Errorf("Expected both session variable name and value for set flag") + } + err := sql.SetSessionVariable(f.ctx, f.evalCtx, s[0], s[1]) + if err != nil { + return err + } + } + case "format": if len(arg.Vals) == 0 { return fmt.Errorf("format flag requires value(s)") @@ -937,28 +924,6 @@ func (f *Flags) Set(arg datadriven.CmdArg) error { f.DisableRules.Add(int(r)) } - case "join-limit": - if len(arg.Vals) != 1 { - return fmt.Errorf("join-limit requires a single argument") - } - limit, err := strconv.ParseInt(arg.Vals[0], 10, 64) - if err != nil { - return errors.Wrap(err, "join-limit") - } - f.JoinLimit = int(limit) - - case "prefer-lookup-joins-for-fks": - if len(arg.Vals) > 0 { - return fmt.Errorf("unknown vals for prefer-lookup-joins-for-fks") - } - f.PreferLookupJoinsForFKs = true - - case "null-ordered-last": - if len(arg.Vals) > 0 { - return fmt.Errorf("unknown vals for null-ordered-last") - } - f.NullOrderedLast = true - case "rule": if len(arg.Vals) != 1 { return fmt.Errorf("rule requires one argument") @@ -1030,12 +995,6 @@ func (f *Flags) Set(arg datadriven.CmdArg) error { } f.Table = arg.Vals[0] - case "stats-quality-prefix": - if len(arg.Vals) != 1 { - return fmt.Errorf("stats-quality-prefix requires one argument") - } - f.SaveTablesPrefix = arg.Vals[0] - case "ignore-tables": var tables util.FastIntSet addTables := func(val string) error { @@ -1120,19 +1079,6 @@ func (f *Flags) Set(arg datadriven.CmdArg) error { case "query-args": f.QueryArgs = arg.Vals - case "propagate-input-ordering": - f.PropagateInputOrdering = true - - case "use-multi-col-stats": - if len(arg.Vals) != 1 { - return fmt.Errorf("use-multi-col-stats requires a single argument") - } - b, err := strconv.ParseBool(arg.Vals[0]) - if err != nil { - return errors.Wrap(err, "use-multi-col-stats") - } - f.UseMultiColStats = b - case "memo-cycles": f.MemoFormat = xform.FmtCycle @@ -1907,7 +1853,7 @@ func (ot *OptTester) StatsQuality(tb testing.TB, d *datadriven.TestData) (string // tree. Keep track of the name of each table so that stats can be outputted // later. var names []string - nameGen := memo.NewExprNameGenerator(ot.Flags.SaveTablesPrefix) + nameGen := memo.NewExprNameGenerator(ot.evalCtx.SessionData().SaveTablesPrefix) var traverse func(e opt.Expr) error traverse = func(e opt.Expr) error { if r, ok := e.(memo.RelExpr); ok { @@ -2003,7 +1949,7 @@ func (ot *OptTester) saveActualTables() error { } if _, err := c.ExecContext(ctx, - fmt.Sprintf("SET save_tables_prefix = '%s'", ot.Flags.SaveTablesPrefix), + fmt.Sprintf("SET save_tables_prefix = '%s'", ot.evalCtx.SessionData().SaveTablesPrefix), ); err != nil { return err } diff --git a/pkg/sql/opt/testutils/opttester/testdata/explore-trace b/pkg/sql/opt/testutils/opttester/testdata/explore-trace index d44a8ef4be10..7497be623f23 100644 --- a/pkg/sql/opt/testutils/opttester/testdata/explore-trace +++ b/pkg/sql/opt/testutils/opttester/testdata/explore-trace @@ -125,7 +125,7 @@ CREATE TABLE grandchild ( ---- # Regression test for 36225. -exploretrace join-limit=3 rule=ReorderJoins skip-no-op format=hide-all +exploretrace set=reorder_joins_limit=3 rule=ReorderJoins skip-no-op format=hide-all SELECT * FROM grandchild JOIN child USING (pid, cid) diff --git a/pkg/sql/opt/testutils/opttester/testdata/use-multi-col-stats b/pkg/sql/opt/testutils/opttester/testdata/use-multi-col-stats index 4f9c79b52bc8..2a2c68b5a38a 100644 --- a/pkg/sql/opt/testutils/opttester/testdata/use-multi-col-stats +++ b/pkg/sql/opt/testutils/opttester/testdata/use-multi-col-stats @@ -21,7 +21,7 @@ CREATE TABLE rides ( inject-stats file=inject-stats.json table=rides ---- -opt format=show-stats use-multi-col-stats=true +opt format=show-stats set=optimizer_use_multicol_stats=true SELECT * FROM rides WHERE city = 'rome' and id = '17198184-b24f-4aa8-9933-64a72ff6665f' ---- scan rides @@ -32,7 +32,7 @@ scan rides ├── key: () └── fd: ()-->(1-10) -opt format=show-stats use-multi-col-stats=false +opt format=show-stats set=optimizer_use_multicol_stats=false SELECT * FROM rides WHERE city = 'rome' and id = '17198184-b24f-4aa8-9933-64a72ff6665f' ---- scan rides diff --git a/pkg/sql/opt/xform/join_funcs.go b/pkg/sql/opt/xform/join_funcs.go index 92790099449d..70b057988347 100644 --- a/pkg/sql/opt/xform/join_funcs.go +++ b/pkg/sql/opt/xform/join_funcs.go @@ -1679,9 +1679,15 @@ func (c *CustomFuncs) getfilteredCanonicalScan( return scanExpr, filters, true } -// IsCanonicalScanOrSelect returns true if `relation` is a canonical scan or a -// select from a canonical scan. -func (c *CustomFuncs) IsCanonicalScanOrSelect(relation memo.RelExpr) (ok bool) { +// CanHoistProjectInput returns true if a projection of an expression on +// `relation` is allowed to be hoisted above a parent Join. The preconditions +// for this are if `relation` is a canonical scan or a select from a canonical +// scan, or the disable_hoist_projection_in_join_limitation session flag is +// true. +func (c *CustomFuncs) CanHoistProjectInput(relation memo.RelExpr) (ok bool) { + if c.e.evalCtx.SessionData().DisableHoistProjectionInJoinLimitation { + return true + } _, _, ok = c.getfilteredCanonicalScan(relation) return ok } diff --git a/pkg/sql/opt/xform/rules/join.opt b/pkg/sql/opt/xform/rules/join.opt index 9ba682b60116..4d1d174ac676 100644 --- a/pkg/sql/opt/xform/rules/join.opt +++ b/pkg/sql/opt/xform/rules/join.opt @@ -444,7 +444,7 @@ (InnerJoin $left:* $proj:(Project - $right:* & (IsCanonicalScanOrSelect $right) + $right:* & (CanHoistProjectInput $right) $projections:* & ^(HasVolatileProjection $projections) $passthrough:* ) @@ -486,7 +486,7 @@ (LeftJoin $left:* (Project - $right:* & (IsCanonicalScanOrSelect $right) + $right:* & (CanHoistProjectInput $right) $projections:* & ^(HasVolatileProjection $projections) $passthrough:* ) diff --git a/pkg/sql/opt/xform/testdata/coster/join b/pkg/sql/opt/xform/testdata/coster/join index b2764a16d3bb..3bb3a3200990 100644 --- a/pkg/sql/opt/xform/testdata/coster/join +++ b/pkg/sql/opt/xform/testdata/coster/join @@ -811,7 +811,7 @@ insert c └── filters (true) # The cost should be much smaller with this hint. -opt prefer-lookup-joins-for-fks +opt set=prefer_lookup_joins_for_fks=true INSERT INTO c VALUES (1,1), (2,2) ---- insert c diff --git a/pkg/sql/opt/xform/testdata/rules/join b/pkg/sql/opt/xform/testdata/rules/join index 595f4b8c1460..4298e30ba478 100644 --- a/pkg/sql/opt/xform/testdata/rules/join +++ b/pkg/sql/opt/xform/testdata/rules/join @@ -330,7 +330,7 @@ memo (optimized, ~28KB, required=[presentation: a:1,b:2,c:3,s:7,t:8,u:9,x:12,y:1 # Joins that exceed reorder_joins_limit are not reordered apart from # commutation. -memo join-limit=1 +memo set=reorder_joins_limit=1 SELECT * FROM stu, abc, xyz, pqr WHERE u = a AND a = x AND x = p @@ -1375,7 +1375,7 @@ memo (optimized, ~12KB, required=[presentation: a:1,b:2,c:3,x:7,y:8,z:9]) └── G8: (variable x) # Verify that setting the join limit to 1 allows only commutation. -exploretrace rule=ReorderJoins format=hide-all join-limit=1 +exploretrace rule=ReorderJoins format=hide-all set=reorder_joins_limit=1 SELECT * FROM abc INNER JOIN stu ON s = a INNER JOIN xyz ON s = x @@ -9950,7 +9950,7 @@ memo (optimized, ~21KB, required=[presentation: ?column?:7]) ├── G15: (tuple G16) └── G16: (scalar-list) -opt join-limit=3 +opt set=reorder_joins_limit=3 SELECT false FROM @@ -9991,7 +9991,7 @@ with &1 ├── key: () └── fd: ()-->(30) -opt join-limit=3 +opt set=reorder_joins_limit=3 SELECT 1 FROM ((VALUES (1), (1)) JOIN ((VALUES (1), (1), (1)) JOIN (VALUES (1), (1), (1), (1)) ON true) ON true) UNION ALL SELECT 1 FROM ((VALUES (1), (1)) JOIN (VALUES (1), (1), (1)) ON true) JOIN (VALUES (1), (1), (1), (1)) ON true @@ -10230,8 +10230,32 @@ inner-join (merge) │ └── columns: m:1 n:2 └── filters (true) +# The rule should be allowed to fire when the projection is from a join if the +# session flag disable_hoist_projection_in_join_limitation is true. +opt expect=HoistProjectFromInnerJoin set=disable_hoist_projection_in_join_limitation=true +SELECT * FROM (SELECT a, a+b FROM (SELECT tab1.* from abcd tab1, abcd tab2)) JOIN small ON a=m; +---- +project + ├── columns: a:1!null "?column?":13 m:14!null n:15 + ├── immutable + ├── fd: (1)==(14), (14)==(1) + ├── inner-join (cross) + │ ├── columns: tab1.a:1!null tab1.b:2 m:14!null n:15 + │ ├── fd: (1)==(14), (14)==(1) + │ ├── scan abcd@abcd_a_b_idx [as=tab2] + │ ├── inner-join (lookup abcd@abcd_a_b_idx [as=tab1]) + │ │ ├── columns: tab1.a:1!null tab1.b:2 m:14!null n:15 + │ │ ├── key columns: [14] = [1] + │ │ ├── fd: (1)==(14), (14)==(1) + │ │ ├── scan small + │ │ │ └── columns: m:14 n:15 + │ │ └── filters (true) + │ └── filters (true) + └── projections + └── tab1.a:1 + tab1.b:2 [as="?column?":13, outer=(1,2), immutable] + # The rule should not fire when the projection is from a join. -opt expect-not=HoistProjectFromInnerJoin +opt expect-not=HoistProjectFromInnerJoin set=disable_hoist_projection_in_join_limitation=false SELECT * FROM (SELECT a, a+b FROM (SELECT tab1.* from abcd tab1, abcd tab2)) JOIN small ON a=m ---- inner-join (hash) @@ -11570,7 +11594,7 @@ semi-join (lookup abc_part@c_idx) # NOTE: A locality optimized lookup join is possible here after the join has # been reordered (because d is a lax key), so we prevent reordering to test this # case and ensure the expect-not holds. -opt locality=(region=east) expect-not=GenerateLocalityOptimizedLookupJoin join-limit=0 +opt locality=(region=east) expect-not=GenerateLocalityOptimizedLookupJoin set=reorder_joins_limit=0 SELECT * FROM def_part WHERE EXISTS (SELECT * FROM abc_part WHERE f = c AND e % a = 0) AND d = 10 ---- semi-join (lookup abc_part@c_idx) @@ -11614,7 +11638,7 @@ semi-join (lookup abc_part@c_idx) # NOTE: A locality optimized lookup join is possible here after the join has # been reordered (because d is a lax key), so we prevent reordering to test this # case and ensure the expect-not holds. -opt locality=(region=east) expect-not=GenerateLocalityOptimizedLookupJoin join-limit=0 +opt locality=(region=east) expect-not=GenerateLocalityOptimizedLookupJoin set=reorder_joins_limit=0 SELECT * FROM def_part INNER JOIN abc_part ON f = c WHERE d = 10 ---- project @@ -11722,7 +11746,7 @@ anti-join (lookup abc_part) # NOTE: A locality optimized lookup join is possible here after the join has # been reordered, so we prevent reordering to test this case and ensure the # expect-not holds. -opt locality=(region=east) expect-not=GenerateLocalityOptimizedLookupJoin join-limit=0 +opt locality=(region=east) expect-not=GenerateLocalityOptimizedLookupJoin set=reorder_joins_limit=0 SELECT * FROM def_part INNER JOIN abc_part ON f = v WHERE d = 1 ---- inner-join (lookup abc_part) diff --git a/pkg/sql/opt/xform/testdata/rules/join_order b/pkg/sql/opt/xform/testdata/rules/join_order index b234826807c8..d72927dcc547 100644 --- a/pkg/sql/opt/xform/testdata/rules/join_order +++ b/pkg/sql/opt/xform/testdata/rules/join_order @@ -28,7 +28,7 @@ CREATE TABLE abc ( ) ---- -opt join-limit=2 expect=ReorderJoins +opt set=reorder_joins_limit=2 expect=ReorderJoins SELECT * FROM abc, bx, cy WHERE a = 1 AND abc.b = bx.b AND abc.c = cy.c ---- inner-join (lookup cy) @@ -54,7 +54,7 @@ inner-join (lookup cy) │ └── filters (true) └── filters (true) -opt join-limit=2 expect=ReorderJoins +opt set=reorder_joins_limit=2 expect=ReorderJoins SELECT * FROM bx, abc, cy WHERE a = 1 AND abc.b = bx.b AND abc.c = cy.c ---- inner-join (lookup bx) @@ -80,7 +80,7 @@ inner-join (lookup bx) │ └── filters (true) └── filters (true) -opt join-limit=2 expect=ReorderJoins +opt set=reorder_joins_limit=2 expect=ReorderJoins SELECT * FROM bx, cy, abc WHERE a = 1 AND abc.b = bx.b AND abc.c = cy.c ---- inner-join (lookup bx) @@ -107,7 +107,7 @@ inner-join (lookup bx) └── filters (true) # Reorder subtrees of size 2. -exploretrace join-limit=2 rule=ReorderJoins format=hide-all +exploretrace set=reorder_joins_limit=2 rule=ReorderJoins format=hide-all SELECT * FROM bx, cy, dz, abc WHERE a = 1 AND abc.b = bx.b AND abc.c = cy.c AND cy.c = dz.d @@ -309,7 +309,7 @@ New expression 3 of 3: ---- # No joins should be reordered besides commutation. -memo join-limit=0 expect-not=ReorderJoins +memo set=reorder_joins_limit=0 expect-not=ReorderJoins SELECT * FROM bx, cy, abc WHERE a = 1 AND abc.b = bx.b AND abc.c = cy.c ---- memo (optimized, ~22KB, required=[presentation: b:1,x:2,c:5,y:6,a:9,b:10,c:11,d:12]) @@ -357,7 +357,7 @@ memo (optimized, ~22KB, required=[presentation: b:1,x:2,c:5,y:6,a:9,b:10,c:11,d: ├── G18: (variable a) └── G19: (const 1) -memo join-limit=2 +memo set=reorder_joins_limit=2 SELECT * FROM bx, cy, abc WHERE a = 1 AND abc.b = bx.b AND abc.c = cy.c ---- memo (optimized, ~33KB, required=[presentation: b:1,x:2,c:5,y:6,a:9,b:10,c:11,d:12]) @@ -409,7 +409,7 @@ memo (optimized, ~33KB, required=[presentation: b:1,x:2,c:5,y:6,a:9,b:10,c:11,d: ├── G19: (variable a) └── G20: (const 1) -opt join-limit=3 expect=ReorderJoins +opt set=reorder_joins_limit=3 expect=ReorderJoins SELECT * FROM bx, cy, dz, abc WHERE a = 1 ---- inner-join (cross) @@ -447,7 +447,7 @@ inner-join (cross) │ └── fd: (1)-->(2) └── filters (true) -opt join-limit=2 format=show-all +opt set=reorder_joins_limit=2 format=show-all SELECT * FROM abc, bx, cy, dz WHERE a = 1 ---- inner-join (cross) @@ -518,7 +518,7 @@ inner-join (cross) # Note the difference in memo size for with and without reorder-joins, for only four tables. # TODO(justin): Find a way to reduce this. -memo join-limit=0 +memo set=reorder_joins_limit=0 SELECT * FROM bx, cy, dz, abc WHERE x = y AND y = z AND z = a ---- memo (optimized, ~29KB, required=[presentation: b:1,x:2,c:5,y:6,d:9,z:10,a:13,b:14,c:15,d:16]) @@ -584,7 +584,7 @@ memo (optimized, ~29KB, required=[presentation: b:1,x:2,c:5,y:6,d:9,z:10,a:13,b: # are connected, which allows every join order to be added to the memo. # TODO(drewk): implement branch pruning and/or a max operator limit for the # memo. -memo join-limit=3 +memo set=reorder_joins_limit=3 SELECT * FROM bx, cy, dz, abc WHERE x = y AND y = z AND z = a ---- memo (optimized, ~62KB, required=[presentation: b:1,x:2,c:5,y:6,d:9,z:10,a:13,b:14,c:15,d:16]) @@ -752,7 +752,7 @@ exec-ddl CREATE TABLE a (id INT8 PRIMARY KEY) ---- -opt join-limit=3 +opt set=reorder_joins_limit=3 SELECT 1 FROM @@ -1965,7 +1965,7 @@ full-join (hash) └── y = z # Iteratively reorder subtrees of up to size 2. -reorderjoins join-limit=2 format=hide-all +reorderjoins set=reorder_joins_limit=2 format=hide-all SELECT * FROM abc AS a1 INNER JOIN abc AS a2 ON a1.a = a2.a LEFT JOIN abc AS a3 ON a2.b = a3.b diff --git a/pkg/sql/sessiondatapb/local_only_session_data.proto b/pkg/sql/sessiondatapb/local_only_session_data.proto index f4c9a3677a35..452f6a8ded52 100644 --- a/pkg/sql/sessiondatapb/local_only_session_data.proto +++ b/pkg/sql/sessiondatapb/local_only_session_data.proto @@ -278,6 +278,9 @@ message LocalOnlySessionData { bool optimizer_use_not_visible_indexes = 74; // CopyFastPathEnabled controls whether the optimized copy mode is enabled. bool copy_fast_path_enabled = 75; + // disable_hoist_projection_in_join_limitation disables the restrictions + // placed on projection hoisting during query planning in the optimizer. + bool disable_hoist_projection_in_join_limitation = 76; /////////////////////////////////////////////////////////////////////////// // WARNING: consider whether a session parameter you're adding needs to // diff --git a/pkg/sql/vars.go b/pkg/sql/vars.go index 7050ebf5bd13..ae62efc35b19 100644 --- a/pkg/sql/vars.go +++ b/pkg/sql/vars.go @@ -2034,7 +2034,6 @@ var varGen = map[string]sessionVar{ }, GlobalDefault: globalFalse, }, - // CockroachDB extension. `show_primary_key_constraint_on_not_visible_columns`: { GetStringVal: makePostgresBoolGetStringValFn(`show_primary_key_constraint_on_not_visible_columns`), @@ -2159,6 +2158,23 @@ var varGen = map[string]sessionVar{ return formatBoolAsPostgresSetting(copyFastPathDefault) }, }, + + // CockroachDB extension. + `disable_hoist_projection_in_join_limitation`: { + GetStringVal: makePostgresBoolGetStringValFn(`disable_hoist_projection_in_join_limitation`), + Set: func(_ context.Context, m sessionDataMutator, s string) error { + b, err := paramparse.ParseBoolVar("disable_hoist_projection_in_join_limitation", s) + if err != nil { + return err + } + m.SetDisableHoistProjectionInJoinLimitation(b) + return nil + }, + Get: func(evalCtx *extendedEvalContext, _ *kv.Txn) (string, error) { + return formatBoolAsPostgresSetting(evalCtx.SessionData().DisableHoistProjectionInJoinLimitation), nil + }, + GlobalDefault: globalFalse, + }, } // We want test coverage for this on and off so make it metamorphic. @@ -2211,6 +2227,34 @@ func init() { }() } +// SetSessionVariable sets a new value for session setting `varName` in the +// session settings owned by `evalCtx`, returning an error if not successful. +// This function should only be used for testing. For general-purpose code, +// please use SessionAccessor.SetSessionVar instead. +func SetSessionVariable( + ctx context.Context, evalCtx eval.Context, varName, varValue string, +) (err error) { + err = CheckSessionVariableValueValid(ctx, evalCtx.Settings, varName, varValue) + if err != nil { + return err + } + sdMutatorBase := sessionDataMutatorBase{ + defaults: make(map[string]string), + settings: evalCtx.Settings, + } + sdMutator := sessionDataMutator{ + data: evalCtx.SessionData(), + sessionDataMutatorBase: sdMutatorBase, + sessionDataMutatorCallbacks: sessionDataMutatorCallbacks{}, + } + _, sVar, err := getSessionVar(varName, false) + if err != nil { + return err + } + + return sVar.Set(ctx, sdMutator, varValue) +} + // makePostgresBoolGetStringValFn returns a function that evaluates and returns // a string representation of the first argument value. func makePostgresBoolGetStringValFn(varName string) getStringValFn {