PostgreSQL Source Code git master
Loading...
Searching...
No Matches
pgpa_walker.h File Reference
#include "pgpa_ast.h"
#include "pgpa_join.h"
#include "pgpa_scan.h"
Include dependency graph for pgpa_walker.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  pgpa_query_feature
 
struct  pgpa_plan_walker_context
 

Macros

#define NUM_PGPA_QF_TYPES   ((int) PGPAQF_SEMIJOIN_UNIQUE + 1)
 

Typedefs

typedef enum pgpa_qf_type pgpa_qf_type
 
typedef struct pgpa_query_feature pgpa_query_feature
 
typedef struct pgpa_plan_walker_context pgpa_plan_walker_context
 

Enumerations

enum  pgpa_qf_type { PGPAQF_GATHER , PGPAQF_GATHER_MERGE , PGPAQF_SEMIJOIN_NON_UNIQUE , PGPAQF_SEMIJOIN_UNIQUE }
 

Functions

void pgpa_plan_walker (pgpa_plan_walker_context *walker, PlannedStmt *pstmt, List *proots)
 
void pgpa_add_future_feature (pgpa_plan_walker_context *walker, pgpa_qf_type type, Plan *plan)
 
ElidedNodepgpa_last_elided_node (PlannedStmt *pstmt, Plan *plan)
 
Bitmapsetpgpa_relids (Plan *plan)
 
Index pgpa_scanrelid (Plan *plan)
 
bool pgpa_is_scan_level_materialize (Plan *plan)
 
Bitmapsetpgpa_filter_out_join_relids (Bitmapset *relids, List *rtable)
 
bool pgpa_walker_would_advise (pgpa_plan_walker_context *walker, pgpa_identifier *rt_identifiers, pgpa_advice_tag_type tag, pgpa_advice_target *target)
 

Macro Definition Documentation

◆ NUM_PGPA_QF_TYPES

#define NUM_PGPA_QF_TYPES   ((int) PGPAQF_SEMIJOIN_UNIQUE + 1)

Definition at line 52 of file pgpa_walker.h.

Typedef Documentation

◆ pgpa_plan_walker_context

◆ pgpa_qf_type

◆ pgpa_query_feature

Enumeration Type Documentation

◆ pgpa_qf_type

Enumerator
PGPAQF_GATHER 
PGPAQF_GATHER_MERGE 
PGPAQF_SEMIJOIN_NON_UNIQUE 
PGPAQF_SEMIJOIN_UNIQUE 

Definition at line 43 of file pgpa_walker.h.

44{
49 /* update NUM_PGPA_QF_TYPES if you add anything here */
pgpa_qf_type
Definition pgpa_walker.h:44
@ PGPAQF_GATHER
Definition pgpa_walker.h:45
@ PGPAQF_GATHER_MERGE
Definition pgpa_walker.h:46
@ PGPAQF_SEMIJOIN_UNIQUE
Definition pgpa_walker.h:48
@ PGPAQF_SEMIJOIN_NON_UNIQUE
Definition pgpa_walker.h:47

Function Documentation

◆ pgpa_add_future_feature()

void pgpa_add_future_feature ( pgpa_plan_walker_context walker,
pgpa_qf_type  type,
Plan plan 
)
extern

Definition at line 534 of file pgpa_walker.c.

536{
538
539 walker->future_query_features =
540 lappend(walker->future_query_features, qf);
541}
List * lappend(List *list, void *datum)
Definition list.c:339
#define plan(x)
Definition pg_regress.c:164
static pgpa_query_feature * pgpa_add_feature(pgpa_plan_walker_context *walker, pgpa_qf_type type, Plan *plan)
static int fb(int x)
const char * type

References fb(), lappend(), pgpa_add_feature(), plan, and type.

Referenced by pgpa_decompose_join().

◆ pgpa_filter_out_join_relids()

Bitmapset * pgpa_filter_out_join_relids ( Bitmapset relids,
List rtable 
)
extern

Definition at line 645 of file pgpa_walker.c.

646{
647 int rti = -1;
649
650 while ((rti = bms_next_member(relids, rti)) >= 0)
651 {
652 RangeTblEntry *rte = rt_fetch(rti, rtable);
653
654 if (rte->rtekind != RTE_JOIN)
656 }
657
658 return result;
659}
int bms_next_member(const Bitmapset *a, int prevbit)
Definition bitmapset.c:1290
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition bitmapset.c:799
uint32 result
@ RTE_JOIN
#define rt_fetch(rangetable_index, rangetable)
Definition parsetree.h:31

References bms_add_member(), bms_next_member(), fb(), result, rt_fetch, and RTE_JOIN.

Referenced by pgpa_build_scan(), pgpa_join_path_setup(), pgpa_qf_add_plan_rtis(), and pgpa_walk_recursively().

◆ pgpa_is_scan_level_materialize()

bool pgpa_is_scan_level_materialize ( Plan plan)
extern

Definition at line 625 of file pgpa_walker.c.

626{
627 Plan *child;
630
631 if (!IsA(plan, Material))
632 return false;
633 child = plan->lefttree;
634 if (child == NULL || !IsA(child, SampleScan))
635 return false;
636 sscan = (SampleScan *) child;
637 tsm = GetTsmRoutine(sscan->tablesample->tsmhandler);
638 return !tsm->repeatable_across_scans;
639}
#define IsA(nodeptr, _type_)
Definition nodes.h:164
struct Plan * lefttree
Definition plannodes.h:239
TsmRoutine * GetTsmRoutine(Oid tsmhandler)
Definition tablesample.c:27

References fb(), GetTsmRoutine(), IsA, Plan::lefttree, and plan.

Referenced by pgpa_build_scan(), and pgpa_decompose_join().

◆ pgpa_last_elided_node()

ElidedNode * pgpa_last_elided_node ( PlannedStmt pstmt,
Plan plan 
)
extern

Definition at line 550 of file pgpa_walker.c.

551{
552 ElidedNode *elided_node = NULL;
553
555 {
556 if (n->plan_node_id == plan->plan_node_id)
557 elided_node = n;
558 }
559
560 return elided_node;
561}
#define foreach_node(type, var, lst)
Definition pg_list.h:528
List * elidedNodes
Definition plannodes.h:156

References PlannedStmt::elidedNodes, fb(), foreach_node, and plan.

Referenced by pgpa_decompose_join(), and pgpa_descend_node().

◆ pgpa_plan_walker()

void pgpa_plan_walker ( pgpa_plan_walker_context walker,
PlannedStmt pstmt,
List proots 
)
extern

Definition at line 77 of file pgpa_walker.c.

79{
80 ListCell *lc;
85
86 /* Initialization. */
88 walker->pstmt = pstmt;
89
90 /* Walk the main plan tree. */
91 pgpa_walk_recursively(walker, pstmt->planTree, false, NULL, NIL, false);
92
93 /* Main plan tree walk won't reach subplans, so walk those. */
94 foreach(lc, pstmt->subplans)
95 {
96 Plan *plan = lfirst(lc);
97
98 if (plan != NULL)
99 pgpa_walk_recursively(walker, plan, false, NULL, NIL, false);
100 }
101
102 /* Adjust RTIs from sj_unique_rels for the flattened range table. */
104 {
105 /* If there are no sj_unique_rels for this proot, we can skip it. */
106 if (proot->sj_unique_rels == NIL)
107 continue;
108
109 /* If this is a subplan, find the range table offset. */
110 if (!proot->has_rtoffset)
111 elog(ERROR, "no rtoffset for plan %s", proot->plan_name);
112
113 /* Offset each relid set by the proot's rtoffset. */
114 foreach_node(Bitmapset, relids, proot->sj_unique_rels)
115 {
116 int rtindex = -1;
118
119 while ((rtindex = bms_next_member(relids, rtindex)) >= 0)
121 rtindex + proot->rtoffset);
122
124 }
125 }
126
127 /*
128 * Remove any non-unique semijoin query features for which making the rel
129 * unique wasn't considered.
130 */
132 walker->query_features[PGPAQF_SEMIJOIN_NON_UNIQUE])
133 {
134 if (list_member(sj_unique_rtis, qf->relids))
136 }
138
139 /*
140 * If we find any cases where analysis of the Plan tree shows that the
141 * semijoin was made unique but this possibility was never observed to be
142 * considered during planning, then we have a bug somewhere.
143 */
145 walker->query_features[PGPAQF_SEMIJOIN_UNIQUE])
146 {
147 if (!list_member(sj_unique_rtis, qf->relids))
148 {
150
152 outBitmapset(&buf, qf->relids);
153 elog(ERROR,
154 "unique semijoin found for relids %s but not observed during planning",
155 buf.data);
156 }
157 }
158
159 /*
160 * It's possible for a Gather or Gather Merge query feature to find no
161 * RTIs when partitionwise aggregation is in use. We shouldn't emit
162 * something like GATHER_MERGE(()), so instead emit nothing. This means
163 * that we won't advise either GATHER or GATHER_MERGE or NO_GATHER in such
164 * cases, which might be something we want to improve in the future.
165 *
166 * (Should the Partial Aggregates in such a case be created in an
167 * UPPERREL_GROUP_AGG with a non-empty relid set? Right now that doesn't
168 * happen, but it seems like it would make life easier for us if it did.)
169 */
170 for (int t = 0; t < NUM_PGPA_QF_TYPES; ++t)
171 {
172 List *query_features = NIL;
173
174 foreach_ptr(pgpa_query_feature, qf, walker->query_features[t])
175 {
176 if (qf->relids != NULL)
177 query_features = lappend(query_features, qf);
178 else
180 }
181
182 walker->query_features[t] = query_features;
183 }
184
185 /* Classify alternative subplans. */
188
189 /*
190 * Figure out which of the discarded alternatives have a non-discarded
191 * alternative. Those are the ones for which we want to emit DO_NOT_SCAN
192 * advice. (If every alternative was discarded, then there's no point.)
193 */
195 {
196 bool some_alternative_chosen = false;
197
199 {
200 if (strings_equal_or_both_null(discarded_proot->alternative_plan_name,
201 chosen_proot->alternative_plan_name))
202 {
204 break;
205 }
206 }
207
209 {
210 for (int rti = 1; rti <= discarded_proot->rid_array_size; rti++)
211 {
212 pgpa_identifier *rid = &discarded_proot->rid_array[rti - 1];
213
214 if (rid->alias_name != NULL)
215 walker->do_not_scan_identifiers =
216 lappend(walker->do_not_scan_identifiers, rid);
217 }
218 }
219 }
220}
#define Assert(condition)
Definition c.h:943
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
bool list_member(const List *list, const void *datum)
Definition list.c:661
void outBitmapset(StringInfo str, const Bitmapset *bms)
Definition outfuncs.c:331
#define lfirst(lc)
Definition pg_list.h:172
#define NIL
Definition pg_list.h:68
#define foreach_ptr(type, var, lst)
Definition pg_list.h:501
static char buf[DEFAULT_XLOG_SEG_SIZE]
static bool strings_equal_or_both_null(const char *a, const char *b)
static void pgpa_classify_alternative_subplans(pgpa_plan_walker_context *walker, List *proots, List **chosen_proots, List **discarded_proots)
static void pgpa_walk_recursively(pgpa_plan_walker_context *walker, Plan *plan, bool within_join_problem, pgpa_join_unroller *join_unroller, List *active_query_features, bool beneath_any_gather)
#define NUM_PGPA_QF_TYPES
Definition pgpa_walker.h:52
void initStringInfo(StringInfo str)
Definition stringinfo.c:97
Definition pg_list.h:54
struct Plan * planTree
Definition plannodes.h:99
List * subplans
Definition plannodes.h:129
const char * alias_name

References pgpa_identifier::alias_name, Assert, bms_add_member(), bms_next_member(), buf, elog, ERROR, fb(), foreach_node, foreach_ptr, initStringInfo(), lappend(), lfirst, list_member(), NIL, NUM_PGPA_QF_TYPES, outBitmapset(), pgpa_classify_alternative_subplans(), pgpa_walk_recursively(), PGPAQF_GATHER, PGPAQF_GATHER_MERGE, PGPAQF_SEMIJOIN_NON_UNIQUE, PGPAQF_SEMIJOIN_UNIQUE, plan, PlannedStmt::planTree, strings_equal_or_both_null(), and PlannedStmt::subplans.

Referenced by pgpa_planner_shutdown().

◆ pgpa_relids()

Bitmapset * pgpa_relids ( Plan plan)
extern

Definition at line 567 of file pgpa_walker.c.

568{
569 if (IsA(plan, Result))
570 return ((Result *) plan)->relids;
571 else if (IsA(plan, ForeignScan))
572 return ((ForeignScan *) plan)->fs_relids;
573 else if (IsA(plan, Append))
574 return ((Append *) plan)->apprelids;
575 else if (IsA(plan, MergeAppend))
576 return ((MergeAppend *) plan)->apprelids;
577
578 return NULL;
579}

References fb(), IsA, and plan.

Referenced by pgpa_build_scan(), and pgpa_qf_add_plan_rtis().

◆ pgpa_scanrelid()

Index pgpa_scanrelid ( Plan plan)
extern

Definition at line 587 of file pgpa_walker.c.

588{
589 switch (nodeTag(plan))
590 {
591 case T_SeqScan:
592 case T_SampleScan:
593 case T_BitmapHeapScan:
594 case T_TidScan:
595 case T_TidRangeScan:
596 case T_SubqueryScan:
597 case T_FunctionScan:
598 case T_TableFuncScan:
599 case T_ValuesScan:
600 case T_CteScan:
602 case T_WorkTableScan:
603 case T_ForeignScan:
604 case T_CustomScan:
605 case T_IndexScan:
606 case T_IndexOnlyScan:
607 return ((Scan *) plan)->scanrelid;
608 default:
609 return 0;
610 }
611}
#define nodeTag(nodeptr)
Definition nodes.h:139

References fb(), nodeTag, and plan.

Referenced by pgpa_build_scan(), and pgpa_qf_add_plan_rtis().

◆ pgpa_walker_would_advise()

bool pgpa_walker_would_advise ( pgpa_plan_walker_context walker,
pgpa_identifier rt_identifiers,
pgpa_advice_tag_type  tag,
pgpa_advice_target target 
)
extern

Definition at line 732 of file pgpa_walker.c.

736{
737 Index rtable_length = list_length(walker->pstmt->rtable);
738 Bitmapset *relids = NULL;
739
740 if (tag == PGPA_TAG_JOIN_ORDER)
741 {
742 foreach_ptr(pgpa_unrolled_join, ujoin, walker->toplevel_unrolled_joins)
743 {
745 rt_identifiers, target, true))
746 return true;
747 }
748
749 return false;
750 }
751
752 /*
753 * DO_NOT_SCAN advice targets rels that may not be in the flat range table
754 * (e.g. MinMaxAgg losers), so pgpa_compute_rti_from_identifier won't work
755 * here. Instead, check directly against the do_not_scan_identifiers list.
756 */
757 if (tag == PGPA_TAG_DO_NOT_SCAN)
758 {
759 if (target->ttype != PGPA_TARGET_IDENTIFIER)
760 return false;
761 foreach_ptr(pgpa_identifier, rid, walker->do_not_scan_identifiers)
762 {
763 if (strcmp(rid->alias_name, target->rid.alias_name) == 0 &&
764 rid->occurrence == target->rid.occurrence &&
765 strings_equal_or_both_null(rid->partnsp,
766 target->rid.partnsp) &&
767 strings_equal_or_both_null(rid->partrel,
768 target->rid.partrel) &&
769 strings_equal_or_both_null(rid->plan_name,
770 target->rid.plan_name))
771 return true;
772 }
773 return false;
774 }
775
776 if (target->ttype == PGPA_TARGET_IDENTIFIER)
777 {
778 Index rti;
779
781 &target->rid);
782 if (rti == 0)
783 return false;
784 relids = bms_make_singleton(rti);
785 }
786 else
787 {
790 {
791 Index rti;
792
796 &child_target->rid);
797 if (rti == 0)
798 return false;
799 relids = bms_add_member(relids, rti);
800 }
801 }
802
803 switch (tag)
804 {
806 /* should have been handled above */
808 break;
810 /* should have been handled above */
812 break;
816 relids) != NULL;
820 relids) != NULL;
822 {
823 pgpa_scan *scan;
824
826 relids);
827 if (scan == NULL)
828 return false;
829
831 }
833 {
834 pgpa_scan *scan;
835
837 relids);
838 if (scan == NULL)
839 return false;
840
842 }
846 relids) != NULL;
850 relids) != NULL;
854 relids) != NULL;
855 case PGPA_TAG_GATHER:
858 relids);
862 relids);
866 relids);
870 relids);
874 relids);
878 relids);
882 relids);
886 relids);
890 relids);
894 relids);
897 }
898
899 /* should not get here */
900 return false;
901}
Bitmapset * bms_make_singleton(int x)
Definition bitmapset.c:216
#define pg_unreachable()
Definition c.h:367
unsigned int Index
Definition c.h:698
static int list_length(const List *l)
Definition pg_list.h:152
@ PGPA_TAG_INDEX_SCAN
Definition pgpa_ast.h:89
@ PGPA_TAG_NESTED_LOOP_MATERIALIZE
Definition pgpa_ast.h:93
@ PGPA_TAG_MERGE_JOIN_PLAIN
Definition pgpa_ast.h:92
@ PGPA_TAG_GATHER_MERGE
Definition pgpa_ast.h:86
@ PGPA_TAG_GATHER
Definition pgpa_ast.h:85
@ PGPA_TAG_NESTED_LOOP_MEMOIZE
Definition pgpa_ast.h:94
@ PGPA_TAG_SEMIJOIN_NON_UNIQUE
Definition pgpa_ast.h:98
@ PGPA_TAG_BITMAP_HEAP_SCAN
Definition pgpa_ast.h:82
@ PGPA_TAG_PARTITIONWISE
Definition pgpa_ast.h:97
@ PGPA_TAG_NO_GATHER
Definition pgpa_ast.h:96
@ PGPA_TAG_INDEX_ONLY_SCAN
Definition pgpa_ast.h:88
@ PGPA_TAG_SEQ_SCAN
Definition pgpa_ast.h:100
@ PGPA_TAG_HASH_JOIN
Definition pgpa_ast.h:87
@ PGPA_TAG_SEMIJOIN_UNIQUE
Definition pgpa_ast.h:99
@ PGPA_TAG_DO_NOT_SCAN
Definition pgpa_ast.h:83
@ PGPA_TAG_JOIN_ORDER
Definition pgpa_ast.h:90
@ PGPA_TAG_TID_SCAN
Definition pgpa_ast.h:101
@ PGPA_TAG_FOREIGN_JOIN
Definition pgpa_ast.h:84
@ PGPA_TAG_NESTED_LOOP_PLAIN
Definition pgpa_ast.h:95
@ PGPA_TAG_MERGE_JOIN_MATERIALIZE
Definition pgpa_ast.h:91
@ PGPA_TARGET_IDENTIFIER
Definition pgpa_ast.h:27
@ PGPA_TARGET_ORDERED_LIST
Definition pgpa_ast.h:28
Index pgpa_compute_rti_from_identifier(int rtable_length, pgpa_identifier *rt_identifiers, pgpa_identifier *rid)
@ JSTRAT_MERGE_JOIN_PLAIN
Definition pgpa_join.h:29
@ JSTRAT_NESTED_LOOP_MATERIALIZE
Definition pgpa_join.h:32
@ JSTRAT_NESTED_LOOP_MEMOIZE
Definition pgpa_join.h:33
@ JSTRAT_HASH_JOIN
Definition pgpa_join.h:34
@ JSTRAT_NESTED_LOOP_PLAIN
Definition pgpa_join.h:31
@ JSTRAT_MERGE_JOIN_MATERIALIZE
Definition pgpa_join.h:30
@ PGPA_SCAN_SEQ
Definition pgpa_scan.h:58
@ PGPA_SCAN_INDEX
Definition pgpa_scan.h:61
@ PGPA_SCAN_INDEX_ONLY
Definition pgpa_scan.h:62
@ PGPA_SCAN_BITMAP_HEAP
Definition pgpa_scan.h:59
@ PGPA_SCAN_FOREIGN
Definition pgpa_scan.h:60
@ PGPA_SCAN_TID
Definition pgpa_scan.h:64
@ PGPA_SCAN_PARTITIONWISE
Definition pgpa_scan.h:63
static bool pgpa_walker_contains_feature(pgpa_plan_walker_context *walker, pgpa_qf_type type, Bitmapset *relids)
static pgpa_scan * pgpa_walker_find_scan(pgpa_plan_walker_context *walker, pgpa_scan_strategy strategy, Bitmapset *relids)
static bool pgpa_walker_contains_no_gather(pgpa_plan_walker_context *walker, Bitmapset *relids)
static bool pgpa_walker_contains_join(pgpa_plan_walker_context *walker, pgpa_join_strategy strategy, Bitmapset *relids)
static bool pgpa_walker_index_target_matches_plan(pgpa_index_target *itarget, Plan *plan)
static bool pgpa_walker_join_order_matches(pgpa_unrolled_join *ujoin, Index rtable_length, pgpa_identifier *rt_identifiers, pgpa_advice_target *target, bool toplevel)
pgpa_identifier rid
Definition pgpa_ast.h:58
pgpa_target_type ttype
Definition pgpa_ast.h:49
pgpa_index_target * itarget
Definition pgpa_ast.h:64
const char * partnsp
const char * partrel
const char * plan_name
Plan * plan
Definition pgpa_scan.h:75

References pgpa_identifier::alias_name, Assert, bms_add_member(), bms_make_singleton(), pgpa_advice_target::children, fb(), foreach_ptr, pgpa_advice_target::itarget, JSTRAT_HASH_JOIN, JSTRAT_MERGE_JOIN_MATERIALIZE, JSTRAT_MERGE_JOIN_PLAIN, JSTRAT_NESTED_LOOP_MATERIALIZE, JSTRAT_NESTED_LOOP_MEMOIZE, JSTRAT_NESTED_LOOP_PLAIN, list_length(), pgpa_identifier::occurrence, pgpa_identifier::partnsp, pgpa_identifier::partrel, pg_unreachable, pgpa_compute_rti_from_identifier(), PGPA_SCAN_BITMAP_HEAP, PGPA_SCAN_FOREIGN, PGPA_SCAN_INDEX, PGPA_SCAN_INDEX_ONLY, PGPA_SCAN_PARTITIONWISE, PGPA_SCAN_SEQ, PGPA_SCAN_TID, PGPA_TAG_BITMAP_HEAP_SCAN, PGPA_TAG_DO_NOT_SCAN, PGPA_TAG_FOREIGN_JOIN, PGPA_TAG_GATHER, PGPA_TAG_GATHER_MERGE, PGPA_TAG_HASH_JOIN, PGPA_TAG_INDEX_ONLY_SCAN, PGPA_TAG_INDEX_SCAN, PGPA_TAG_JOIN_ORDER, PGPA_TAG_MERGE_JOIN_MATERIALIZE, PGPA_TAG_MERGE_JOIN_PLAIN, PGPA_TAG_NESTED_LOOP_MATERIALIZE, PGPA_TAG_NESTED_LOOP_MEMOIZE, PGPA_TAG_NESTED_LOOP_PLAIN, PGPA_TAG_NO_GATHER, PGPA_TAG_PARTITIONWISE, PGPA_TAG_SEMIJOIN_NON_UNIQUE, PGPA_TAG_SEMIJOIN_UNIQUE, PGPA_TAG_SEQ_SCAN, PGPA_TAG_TID_SCAN, PGPA_TARGET_IDENTIFIER, PGPA_TARGET_ORDERED_LIST, pgpa_walker_contains_feature(), pgpa_walker_contains_join(), pgpa_walker_contains_no_gather(), pgpa_walker_find_scan(), pgpa_walker_index_target_matches_plan(), pgpa_walker_join_order_matches(), PGPAQF_GATHER, PGPAQF_GATHER_MERGE, PGPAQF_SEMIJOIN_NON_UNIQUE, PGPAQF_SEMIJOIN_UNIQUE, pgpa_scan::plan, pgpa_identifier::plan_name, pgpa_advice_target::rid, strings_equal_or_both_null(), and pgpa_advice_target::ttype.

Referenced by pgpa_planner_append_feedback().