PostgreSQL Source Code git master
Loading...
Searching...
No Matches
pgpa_walker.h
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * pgpa_walker.h
4 * Main entrypoints for analyzing a plan to generate an advice string
5 *
6 * Copyright (c) 2016-2026, PostgreSQL Global Development Group
7 *
8 * contrib/pg_plan_advice/pgpa_walker.h
9 *
10 *-------------------------------------------------------------------------
11 */
12#ifndef PGPA_WALKER_H
13#define PGPA_WALKER_H
14
15#include "pgpa_ast.h"
16#include "pgpa_join.h"
17#include "pgpa_scan.h"
18
19/*
20 * When generating advice, we should emit either SEMIJOIN_UNIQUE advice or
21 * SEMIJOIN_NON_UNIQUE advice for each semijoin depending on whether we chose
22 * to implement it as a semijoin or whether we instead chose to make the
23 * nullable side unique and then perform an inner join. When the make-unique
24 * strategy is not chosen, it's not easy to tell from the final plan tree
25 * whether it was considered. That's awkward, because we don't want to emit
26 * useless SEMIJOIN_NON_UNIQUE advice when there was no decision to be made.
27 *
28 * To avoid that, during planning, we create a pgpa_sj_unique_rel for each
29 * relation that we considered making unique for purposes of semijoin planning.
30 */
36
37/*
38 * We use the term "query feature" to refer to plan nodes that are interesting
39 * in the following way: to generate advice, we'll need to know the set of
40 * same-subquery, non-join RTIs occurring at or below that plan node, without
41 * admixture of parent and child RTIs.
42 *
43 * For example, Gather nodes, designated by PGPAQF_GATHER, and Gather Merge
44 * nodes, designated by PGPAQF_GATHER_MERGE, are query features, because we'll
45 * want to admit some kind of advice that describes the portion of the plan
46 * tree that appears beneath those nodes.
47 *
48 * Each semijoin can be implemented either by directly performing a semijoin,
49 * or by making one side unique and then performing a normal join. Either way,
50 * we use a query feature to notice what decision was made, so that we can
51 * describe it by enumerating the RTIs on that side of the join.
52 *
53 * To elaborate on the "no admixture of parent and child RTIs" rule, in all of
54 * these cases, if the entirety of an inheritance hierarchy appears beneath
55 * the query feature, we only want to name the parent table. But it's also
56 * possible to have cases where we must name child tables. This is particularly
57 * likely to happen when partitionwise join is in use, but could happen for
58 * Gather or Gather Merge even without that, if one of those appears below
59 * an Append or MergeAppend node for a single table.
60 */
61typedef enum pgpa_qf_type
62{
67 /* update NUM_PGPA_QF_TYPES if you add anything here */
69
70#define NUM_PGPA_QF_TYPES ((int) PGPAQF_SEMIJOIN_UNIQUE + 1)
71
72/*
73 * For each query feature, we keep track of the feature type and the set of
74 * relids that we found underneath the relevant plan node. See the comments
75 * on pgpa_qf_type, above, for additional details.
76 */
83
84/*
85 * Context object for plan tree walk.
86 *
87 * pstmt is the PlannedStmt we're studying.
88 *
89 * scans is an array of lists of pgpa_scan objects. The array is indexed by
90 * the scan's pgpa_scan_strategy.
91 *
92 * no_gather_scans is the set of scan RTIs that do not appear beneath any
93 * Gather or Gather Merge node.
94 *
95 * toplevel_unrolled_joins is a list of all pgpa_unrolled_join objects that
96 * are not a child of some other pgpa_unrolled_join.
97 *
98 * join_strategy is an array of lists of Bitmapset objects. Each Bitmapset
99 * is the set of relids that appears on the inner side of some join (excluding
100 * RTIs from partition children and subqueries). The array is indexed by
101 * pgpa_join_strategy.
102 *
103 * query_features is an array lists of pgpa_query_feature objects, indexed
104 * by pgpa_qf_type.
105 *
106 * future_query_features is only used during the plan tree walk and should
107 * be empty when the tree walk concludes. It is a list of pgpa_query_feature
108 * objects for Plan nodes that the plan tree walk has not yet encountered;
109 * when encountered, they will be moved to the list of active query features
110 * that is propagated via the call stack.
111 */
122
124 PlannedStmt *pstmt,
125 List *sj_unique_rels);
126
129 Plan *plan);
130
134extern Bitmapset *pgpa_filter_out_join_relids(Bitmapset *relids, List *rtable);
135
139 pgpa_advice_target *target);
140
141#endif
unsigned int Index
Definition c.h:682
#define plan(x)
Definition pg_regress.c:161
pgpa_advice_tag_type
Definition pgpa_ast.h:81
#define NUM_PGPA_JOIN_STRATEGY
Definition pgpa_join.h:38
#define NUM_PGPA_SCAN_STRATEGY
Definition pgpa_scan.h:68
Bitmapset * pgpa_filter_out_join_relids(Bitmapset *relids, List *rtable)
pgpa_qf_type
Definition pgpa_walker.h:62
@ PGPAQF_GATHER
Definition pgpa_walker.h:63
@ PGPAQF_GATHER_MERGE
Definition pgpa_walker.h:64
@ PGPAQF_SEMIJOIN_UNIQUE
Definition pgpa_walker.h:66
@ PGPAQF_SEMIJOIN_NON_UNIQUE
Definition pgpa_walker.h:65
Bitmapset * pgpa_relids(Plan *plan)
ElidedNode * pgpa_last_elided_node(PlannedStmt *pstmt, Plan *plan)
bool pgpa_walker_would_advise(pgpa_plan_walker_context *walker, pgpa_identifier *rt_identifiers, pgpa_advice_tag_type tag, pgpa_advice_target *target)
void pgpa_plan_walker(pgpa_plan_walker_context *walker, PlannedStmt *pstmt, List *sj_unique_rels)
Definition pgpa_walker.c:71
#define NUM_PGPA_QF_TYPES
Definition pgpa_walker.h:70
void pgpa_add_future_feature(pgpa_plan_walker_context *walker, pgpa_qf_type type, Plan *plan)
Index pgpa_scanrelid(Plan *plan)
static int fb(int x)
Definition pg_list.h:54
List * scans[NUM_PGPA_SCAN_STRATEGY]
List * query_features[NUM_PGPA_QF_TYPES]
List * join_strategies[NUM_PGPA_JOIN_STRATEGY]
pgpa_qf_type type
Definition pgpa_walker.h:79
Bitmapset * relids
Definition pgpa_walker.h:81
Bitmapset * relids
Definition pgpa_walker.h:34
const char * type