From 50d7f3af03d8961d251508888e76df9f57a1266b Mon Sep 17 00:00:00 2001 From: Masahiro Ikeda Date: Tue, 22 Aug 2023 17:26:19 +0900 Subject: [PATCH] [Poc] Fix handling of joinrelids #139 find_join_hint() calculates the join level using joinrelids which is a bitmapset of relations within the join with the assumption that the relids has only base relations. But, relids became to have outer-join relids with PostgreSQL commit (2489d76c). So, the calculation logic became wrong and crash on some condition. The commit fixes the logic to calculate joinrelids to consider only base relations. This patch is for PoC. I think we need to think the following. * Is the test enough and stable? * Don't we need to change OuterInnerJoinCreate() and transform_join_hints which call find_join_hint()? --- expected/pg_hint_plan.out | 16 ++++++++++++++++ pg_hint_plan.c | 2 ++ sql/pg_hint_plan.sql | 5 +++++ 3 files changed, 23 insertions(+) diff --git a/expected/pg_hint_plan.out b/expected/pg_hint_plan.out index 8ef19f85..37b80a9c 100644 --- a/expected/pg_hint_plan.out +++ b/expected/pg_hint_plan.out @@ -9131,6 +9131,22 @@ set max_parallel_workers_per_gather to DEFAULT; -> Seq Scan on t3 (cost=xxx..xxx rows=100 width=xxx) \! rm results/pg_hint_plan.tmpout +-- query with join RTE +/*+Leading(ft_1 ft_2 t1)*/ +SELECT relname, seq_scan > 0 as seq_scan, idx_scan > 0 as idx_scan +FROM pg_stat_user_tables WHERE schemaname = 'public' AND relname = 't1'; +LOG: pg_hint_plan: +used hint: +not used hint: +Leading(ft_1 ft_2 t1) +duplication hint: +error hint: + + relname | seq_scan | idx_scan +---------+----------+---------- + t1 | f | f +(1 row) + -- hint error level set client_min_messages to 'DEBUG1'; /*+ SeqScan( */ SELECT 1; diff --git a/pg_hint_plan.c b/pg_hint_plan.c index 2d4421fa..adbc67aa 100644 --- a/pg_hint_plan.c +++ b/pg_hint_plan.c @@ -4530,6 +4530,7 @@ make_join_rel_wrapper(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2) int save_nestlevel; joinrelids = bms_union(rel1->relids, rel2->relids); + joinrelids = bms_intersect(joinrelids, root->all_baserels); join_hint = find_join_hint(joinrelids); memoize_hint = find_memoize_hint(joinrelids); bms_free(joinrelids); @@ -4597,6 +4598,7 @@ add_paths_to_joinrel_wrapper(PlannerInfo *root, int save_nestlevel; joinrelids = bms_union(outerrel->relids, innerrel->relids); + joinrelids = bms_intersect(joinrelids, root->all_baserels); join_hint = find_join_hint(joinrelids); memoize_hint = find_memoize_hint(joinrelids); bms_free(joinrelids); diff --git a/sql/pg_hint_plan.sql b/sql/pg_hint_plan.sql index 5e12ecce..507c21cd 100644 --- a/sql/pg_hint_plan.sql +++ b/sql/pg_hint_plan.sql @@ -1159,6 +1159,11 @@ set max_parallel_workers_per_gather to DEFAULT; \! sql/maskout.sh results/pg_hint_plan.tmpout \! rm results/pg_hint_plan.tmpout +-- query with join RTE +/*+Leading(ft_1 ft_2 t1)*/ +SELECT relname, seq_scan > 0 as seq_scan, idx_scan > 0 as idx_scan +FROM pg_stat_user_tables WHERE schemaname = 'public' AND relname = 't1'; + -- hint error level set client_min_messages to 'DEBUG1'; /*+ SeqScan( */ SELECT 1;