PostgreSQL Source Code git master
Loading...
Searching...
No Matches
planner.h File Reference
#include "nodes/pathnodes.h"
#include "nodes/plannodes.h"
Include dependency graph for planner.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Typedefs

typedef struct ExplainState ExplainState
 
typedef PlannedStmt *(* planner_hook_type) (Query *parse, const char *query_string, int cursorOptions, ParamListInfo boundParams, ExplainState *es)
 
typedef void(* planner_setup_hook_type) (PlannerGlobal *glob, Query *parse, const char *query_string, int cursorOptions, double *tuple_fraction, ExplainState *es)
 
typedef void(* planner_shutdown_hook_type) (PlannerGlobal *glob, Query *parse, const char *query_string, PlannedStmt *pstmt)
 
typedef void(* create_upper_paths_hook_type) (PlannerInfo *root, UpperRelationKind stage, RelOptInfo *input_rel, RelOptInfo *output_rel, void *extra)
 

Functions

PlannedStmtstandard_planner (Query *parse, const char *query_string, int cursorOptions, ParamListInfo boundParams, ExplainState *es)
 
PlannerInfosubquery_planner (PlannerGlobal *glob, Query *parse, char *plan_name, PlannerInfo *parent_root, PlannerInfo *alternative_root, bool hasRecursion, double tuple_fraction, SetOperationStmt *setops)
 
RowMarkType select_rowmark_type (RangeTblEntry *rte, LockClauseStrength strength)
 
bool limit_needed (Query *parse)
 
void mark_partial_aggref (Aggref *agg, AggSplit aggsplit)
 
Pathget_cheapest_fractional_path (RelOptInfo *rel, double tuple_fraction)
 
Exprpreprocess_phv_expression (PlannerInfo *root, Expr *expr)
 
RelOptInfocreate_unique_paths (PlannerInfo *root, RelOptInfo *rel, SpecialJoinInfo *sjinfo)
 
charchoose_plan_name (PlannerGlobal *glob, const char *name, bool always_number)
 

Variables

PGDLLIMPORT planner_hook_type planner_hook
 
PGDLLIMPORT planner_setup_hook_type planner_setup_hook
 
PGDLLIMPORT planner_shutdown_hook_type planner_shutdown_hook
 
PGDLLIMPORT create_upper_paths_hook_type create_upper_paths_hook
 

Typedef Documentation

◆ create_upper_paths_hook_type

typedef void(* create_upper_paths_hook_type) (PlannerInfo *root, UpperRelationKind stage, RelOptInfo *input_rel, RelOptInfo *output_rel, void *extra)

Definition at line 50 of file planner.h.

◆ ExplainState

Definition at line 25 of file planner.h.

◆ planner_hook_type

typedef PlannedStmt *(* planner_hook_type) (Query *parse, const char *query_string, int cursorOptions, ParamListInfo boundParams, ExplainState *es)

Definition at line 28 of file planner.h.

◆ planner_setup_hook_type

typedef void(* planner_setup_hook_type) (PlannerGlobal *glob, Query *parse, const char *query_string, int cursorOptions, double *tuple_fraction, ExplainState *es)

Definition at line 36 of file planner.h.

◆ planner_shutdown_hook_type

typedef void(* planner_shutdown_hook_type) (PlannerGlobal *glob, Query *parse, const char *query_string, PlannedStmt *pstmt)

Definition at line 44 of file planner.h.

Function Documentation

◆ choose_plan_name()

char * choose_plan_name ( PlannerGlobal glob,
const char name,
bool  always_number 
)
extern

Definition at line 9215 of file planner.c.

9216{
9217 unsigned n;
9218
9219 /*
9220 * If a numeric suffix is not required, then search the list of
9221 * previously-assigned names for a match. If none is found, then we can
9222 * use the provided name without modification.
9223 */
9224 if (!always_number)
9225 {
9226 bool found = false;
9227
9228 foreach_ptr(char, subplan_name, glob->subplanNames)
9229 {
9230 if (strcmp(subplan_name, name) == 0)
9231 {
9232 found = true;
9233 break;
9234 }
9235 }
9236
9237 if (!found)
9238 {
9239 /* pstrdup here is just to avoid cast-away-const */
9240 char *chosen_name = pstrdup(name);
9241
9242 glob->subplanNames = lappend(glob->subplanNames, chosen_name);
9243 return chosen_name;
9244 }
9245 }
9246
9247 /*
9248 * If a numeric suffix is required or if the un-suffixed name is already
9249 * in use, then loop until we find a positive integer that produces a
9250 * novel name.
9251 */
9252 for (n = 1; true; ++n)
9253 {
9254 char *proposed_name = psprintf("%s_%u", name, n);
9255 bool found = false;
9256
9257 foreach_ptr(char, subplan_name, glob->subplanNames)
9258 {
9260 {
9261 found = true;
9262 break;
9263 }
9264 }
9265
9266 if (!found)
9267 {
9268 glob->subplanNames = lappend(glob->subplanNames, proposed_name);
9269 return proposed_name;
9270 }
9271
9273 }
9274}
List * lappend(List *list, void *datum)
Definition list.c:339
char * pstrdup(const char *in)
Definition mcxt.c:1910
void pfree(void *pointer)
Definition mcxt.c:1619
#define foreach_ptr(type, var, lst)
Definition pg_list.h:501
static int fb(int x)
char * psprintf(const char *fmt,...)
Definition psprintf.c:43
const char * name

References fb(), foreach_ptr, lappend(), name, pfree(), psprintf(), and pstrdup().

Referenced by build_minmax_path(), make_subplan(), recurse_set_operations(), set_subquery_pathlist(), and SS_process_ctes().

◆ create_unique_paths()

RelOptInfo * create_unique_paths ( PlannerInfo root,
RelOptInfo rel,
SpecialJoinInfo sjinfo 
)
extern

Definition at line 8663 of file planner.c.

8664{
8665 RelOptInfo *unique_rel;
8667 List *groupClause = NIL;
8668 MemoryContext oldcontext;
8669
8670 /* Caller made a mistake if SpecialJoinInfo is the wrong one */
8671 Assert(sjinfo->jointype == JOIN_SEMI);
8672 Assert(bms_equal(rel->relids, sjinfo->syn_righthand));
8673
8674 /* If result already cached, return it */
8675 if (rel->unique_rel)
8676 return rel->unique_rel;
8677
8678 /* If it's not possible to unique-ify, return NULL */
8679 if (!(sjinfo->semi_can_btree || sjinfo->semi_can_hash))
8680 return NULL;
8681
8682 /*
8683 * Punt if this is a child relation and we failed to build a unique-ified
8684 * relation for its parent. This can happen if all the RHS columns were
8685 * found to be equated to constants when unique-ifying the parent table,
8686 * leaving no columns to unique-ify.
8687 */
8688 if (IS_OTHER_REL(rel) && rel->top_parent->unique_rel == NULL)
8689 return NULL;
8690
8691 /*
8692 * When called during GEQO join planning, we are in a short-lived memory
8693 * context. We must make sure that the unique rel and any subsidiary data
8694 * structures created for a baserel survive the GEQO cycle, else the
8695 * baserel is trashed for future GEQO cycles. On the other hand, when we
8696 * are creating those for a joinrel during GEQO, we don't want them to
8697 * clutter the main planning context. Upshot is that the best solution is
8698 * to explicitly allocate memory in the same context the given RelOptInfo
8699 * is in.
8700 */
8702
8703 unique_rel = makeNode(RelOptInfo);
8704 memcpy(unique_rel, rel, sizeof(RelOptInfo));
8705
8706 /*
8707 * clear path info
8708 */
8709 unique_rel->pathlist = NIL;
8710 unique_rel->ppilist = NIL;
8711 unique_rel->partial_pathlist = NIL;
8712 unique_rel->cheapest_startup_path = NULL;
8713 unique_rel->cheapest_total_path = NULL;
8714 unique_rel->cheapest_parameterized_paths = NIL;
8715
8716 /*
8717 * Build the target list for the unique rel. We also build the pathkeys
8718 * that represent the ordering requirements for the sort-based
8719 * implementation, and the list of SortGroupClause nodes that represent
8720 * the columns to be grouped on for the hash-based implementation.
8721 *
8722 * For a child rel, we can construct these fields from those of its
8723 * parent.
8724 */
8725 if (IS_OTHER_REL(rel))
8726 {
8729
8730 parent_unique_target = rel->top_parent->unique_rel->reltarget;
8731
8733
8734 /* Translate the target expressions */
8735 child_unique_target->exprs = (List *)
8737 (Node *) parent_unique_target->exprs,
8738 rel,
8739 rel->top_parent);
8740
8741 unique_rel->reltarget = child_unique_target;
8742
8743 sortPathkeys = rel->top_parent->unique_pathkeys;
8744 groupClause = rel->top_parent->unique_groupclause;
8745 }
8746 else
8747 {
8748 List *newtlist;
8749 int nextresno;
8750 List *sortList = NIL;
8751 ListCell *lc1;
8752 ListCell *lc2;
8753
8754 /*
8755 * The values we are supposed to unique-ify may be expressions in the
8756 * variables of the input rel's targetlist. We have to add any such
8757 * expressions to the unique rel's targetlist.
8758 *
8759 * To complicate matters, some of the values to be unique-ified may be
8760 * known redundant by the EquivalenceClass machinery (e.g., because
8761 * they have been equated to constants). There is no need to compare
8762 * such values during unique-ification, and indeed we had better not
8763 * try because the Vars involved may not have propagated as high as
8764 * the semijoin's level. We use make_pathkeys_for_sortclauses to
8765 * detect such cases, which is a tad inefficient but it doesn't seem
8766 * worth building specialized infrastructure for this.
8767 */
8770
8771 forboth(lc1, sjinfo->semi_rhs_exprs, lc2, sjinfo->semi_operators)
8772 {
8773 Expr *uniqexpr = lfirst(lc1);
8775 Oid sortop;
8777 bool made_tle = false;
8778
8780 if (!tle)
8781 {
8783 nextresno,
8784 NULL,
8785 false);
8787 nextresno++;
8788 made_tle = true;
8789 }
8790
8791 /*
8792 * Try to build an ORDER BY list to sort the input compatibly. We
8793 * do this for each sortable clause even when the clauses are not
8794 * all sortable, so that we can detect clauses that are redundant
8795 * according to the pathkey machinery.
8796 */
8798 if (OidIsValid(sortop))
8799 {
8800 Oid eqop;
8802
8803 /*
8804 * The Unique node will need equality operators. Normally
8805 * these are the same as the IN clause operators, but if those
8806 * are cross-type operators then the equality operators are
8807 * the ones for the IN clause operators' RHS datatype.
8808 */
8809 eqop = get_equality_op_for_ordering_op(sortop, NULL);
8810 if (!OidIsValid(eqop)) /* shouldn't happen */
8811 elog(ERROR, "could not find equality operator for ordering operator %u",
8812 sortop);
8813
8815 sortcl->tleSortGroupRef = assignSortGroupRef(tle, newtlist);
8816 sortcl->eqop = eqop;
8817 sortcl->sortop = sortop;
8818 sortcl->reverse_sort = false;
8819 sortcl->nulls_first = false;
8820 sortcl->hashable = false; /* no need to make this accurate */
8822
8823 /*
8824 * At each step, convert the SortGroupClause list to pathkey
8825 * form. If the just-added SortGroupClause is redundant, the
8826 * result will be shorter than the SortGroupClause list.
8827 */
8829 newtlist);
8831 {
8832 /* Drop the redundant SortGroupClause */
8835 /* Undo tlist addition, if we made one */
8836 if (made_tle)
8837 {
8839 nextresno--;
8840 }
8841 /* We need not consider this clause for hashing, either */
8842 continue;
8843 }
8844 }
8845 else if (sjinfo->semi_can_btree) /* shouldn't happen */
8846 elog(ERROR, "could not find ordering operator for equality operator %u",
8847 in_oper);
8848
8849 if (sjinfo->semi_can_hash)
8850 {
8851 /* Create a GROUP BY list for the Agg node to use */
8852 Oid eq_oper;
8854
8855 /*
8856 * Get the hashable equality operators for the Agg node to
8857 * use. Normally these are the same as the IN clause
8858 * operators, but if those are cross-type operators then the
8859 * equality operators are the ones for the IN clause
8860 * operators' RHS datatype.
8861 */
8863 elog(ERROR, "could not find compatible hash operator for operator %u",
8864 in_oper);
8865
8867 groupcl->tleSortGroupRef = assignSortGroupRef(tle, newtlist);
8868 groupcl->eqop = eq_oper;
8869 groupcl->sortop = sortop;
8870 groupcl->reverse_sort = false;
8871 groupcl->nulls_first = false;
8872 groupcl->hashable = true;
8873 groupClause = lappend(groupClause, groupcl);
8874 }
8875 }
8876
8877 /*
8878 * Done building the sortPathkeys and groupClause. But the
8879 * sortPathkeys are bogus if not all the clauses were sortable.
8880 */
8881 if (!sjinfo->semi_can_btree)
8882 sortPathkeys = NIL;
8883
8884 /*
8885 * It can happen that all the RHS columns are equated to constants.
8886 * We'd have to do something special to unique-ify in that case, and
8887 * it's such an unlikely-in-the-real-world case that it's not worth
8888 * the effort. So just punt if we found no columns to unique-ify.
8889 */
8890 if (sortPathkeys == NIL && groupClause == NIL)
8891 {
8892 MemoryContextSwitchTo(oldcontext);
8893 return NULL;
8894 }
8895
8896 /* Convert the required targetlist back to PathTarget form */
8897 unique_rel->reltarget = create_pathtarget(root, newtlist);
8898 }
8899
8900 /* build unique paths based on input rel's pathlist */
8901 create_final_unique_paths(root, rel, sortPathkeys, groupClause,
8902 sjinfo, unique_rel);
8903
8904 /* build unique paths based on input rel's partial_pathlist */
8906 sjinfo, unique_rel);
8907
8908 /* Now choose the best path(s) */
8909 set_cheapest(unique_rel);
8910
8911 /*
8912 * There shouldn't be any partial paths for the unique relation;
8913 * otherwise, we won't be able to properly guarantee uniqueness.
8914 */
8915 Assert(unique_rel->partial_pathlist == NIL);
8916
8917 /* Cache the result */
8918 rel->unique_rel = unique_rel;
8920 rel->unique_groupclause = groupClause;
8921
8922 MemoryContextSwitchTo(oldcontext);
8923
8924 return unique_rel;
8925}
Node * adjust_appendrel_attrs_multilevel(PlannerInfo *root, Node *node, RelOptInfo *childrel, RelOptInfo *parentrel)
Definition appendinfo.c:597
bool bms_equal(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:143
#define Assert(condition)
Definition c.h:1002
#define OidIsValid(objectId)
Definition c.h:917
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
List * list_delete_last(List *list)
Definition list.c:957
bool get_compatible_hash_operators(Oid opno, Oid *lhs_opno, Oid *rhs_opno)
Definition lsyscache.c:483
Oid get_equality_op_for_ordering_op(Oid opno, bool *reverse)
Definition lsyscache.c:326
Oid get_ordering_op_for_equality_op(Oid opno, bool use_lhs_type)
Definition lsyscache.c:364
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition makefuncs.c:289
MemoryContext GetMemoryChunkContext(void *pointer)
Definition mcxt.c:759
#define makeNode(_type_)
Definition nodes.h:159
@ JOIN_SEMI
Definition nodes.h:315
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:138
Index assignSortGroupRef(TargetEntry *tle, List *tlist)
List * make_pathkeys_for_sortclauses(PlannerInfo *root, List *sortclauses, List *tlist)
Definition pathkeys.c:1336
void set_cheapest(RelOptInfo *parent_rel)
Definition pathnode.c:268
#define IS_OTHER_REL(rel)
Definition pathnodes.h:1004
#define lfirst(lc)
Definition pg_list.h:172
static int list_length(const List *l)
Definition pg_list.h:152
#define NIL
Definition pg_list.h:68
#define forboth(cell1, list1, cell2, list2)
Definition pg_list.h:550
#define lfirst_oid(lc)
Definition pg_list.h:174
static void create_final_unique_paths(PlannerInfo *root, RelOptInfo *input_rel, List *sortPathkeys, List *groupClause, SpecialJoinInfo *sjinfo, RelOptInfo *unique_rel)
Definition planner.c:8932
static void create_partial_unique_paths(PlannerInfo *root, RelOptInfo *input_rel, List *sortPathkeys, List *groupClause, SpecialJoinInfo *sjinfo, RelOptInfo *unique_rel)
Definition planner.c:9057
unsigned int Oid
tree ctl root
Definition radixtree.h:1857
Definition pg_list.h:54
Definition nodes.h:133
List * ppilist
Definition pathnodes.h:1051
Relids relids
Definition pathnodes.h:1021
struct PathTarget * reltarget
Definition pathnodes.h:1045
List * unique_pathkeys
Definition pathnodes.h:1134
List * cheapest_parameterized_paths
Definition pathnodes.h:1055
List * pathlist
Definition pathnodes.h:1050
struct Path * cheapest_startup_path
Definition pathnodes.h:1053
struct Path * cheapest_total_path
Definition pathnodes.h:1054
List * unique_groupclause
Definition pathnodes.h:1136
List * partial_pathlist
Definition pathnodes.h:1052
struct RelOptInfo * unique_rel
Definition pathnodes.h:1132
List * semi_rhs_exprs
Definition pathnodes.h:3241
JoinType jointype
Definition pathnodes.h:3230
Relids syn_righthand
Definition pathnodes.h:3229
List * semi_operators
Definition pathnodes.h:3240
TargetEntry * tlist_member(Expr *node, List *targetlist)
Definition tlist.c:88
List * make_tlist_from_pathtarget(PathTarget *target)
Definition tlist.c:633
PathTarget * copy_pathtarget(PathTarget *src)
Definition tlist.c:666
#define create_pathtarget(root, tlist)
Definition tlist.h:58

References adjust_appendrel_attrs_multilevel(), Assert, assignSortGroupRef(), bms_equal(), RelOptInfo::cheapest_parameterized_paths, RelOptInfo::cheapest_startup_path, RelOptInfo::cheapest_total_path, copy_pathtarget(), create_final_unique_paths(), create_partial_unique_paths(), create_pathtarget, elog, ERROR, fb(), forboth, get_compatible_hash_operators(), get_equality_op_for_ordering_op(), get_ordering_op_for_equality_op(), GetMemoryChunkContext(), IS_OTHER_REL, JOIN_SEMI, SpecialJoinInfo::jointype, lappend(), lfirst, lfirst_oid, list_delete_last(), list_length(), make_pathkeys_for_sortclauses(), make_tlist_from_pathtarget(), makeNode, makeTargetEntry(), memcpy(), MemoryContextSwitchTo(), NIL, OidIsValid, RelOptInfo::partial_pathlist, RelOptInfo::pathlist, RelOptInfo::ppilist, RelOptInfo::relids, RelOptInfo::reltarget, root, SpecialJoinInfo::semi_can_btree, SpecialJoinInfo::semi_can_hash, SpecialJoinInfo::semi_operators, SpecialJoinInfo::semi_rhs_exprs, set_cheapest(), SpecialJoinInfo::syn_righthand, tlist_member(), RelOptInfo::unique_groupclause, RelOptInfo::unique_pathkeys, and RelOptInfo::unique_rel.

Referenced by join_is_legal(), and populate_joinrel_with_paths().

◆ get_cheapest_fractional_path()

Path * get_cheapest_fractional_path ( RelOptInfo rel,
double  tuple_fraction 
)
extern

Definition at line 6848 of file planner.c.

6849{
6851 ListCell *l;
6852
6853 /* If all tuples will be retrieved, just return the cheapest-total path */
6854 if (tuple_fraction <= 0.0)
6855 return best_path;
6856
6857 /* Convert absolute # of tuples to a fraction; no need to clamp to 0..1 */
6858 if (tuple_fraction >= 1.0 && best_path->rows > 0)
6859 tuple_fraction /= best_path->rows;
6860
6861 foreach(l, rel->pathlist)
6862 {
6863 Path *path = (Path *) lfirst(l);
6864
6865 if (path->param_info)
6866 continue;
6867
6868 if (path == rel->cheapest_total_path ||
6869 compare_fractional_path_costs(best_path, path, tuple_fraction) <= 0)
6870 continue;
6871
6872 best_path = path;
6873 }
6874
6875 return best_path;
6876}
int compare_fractional_path_costs(Path *path1, Path *path2, double fraction)
Definition pathnode.c:123

References RelOptInfo::cheapest_total_path, compare_fractional_path_costs(), fb(), lfirst, and RelOptInfo::pathlist.

Referenced by add_paths_to_append_rel(), make_subplan(), and standard_planner().

◆ limit_needed()

bool limit_needed ( Query parse)
extern

Definition at line 3032 of file planner.c.

3033{
3034 Node *node;
3035
3036 node = parse->limitCount;
3037 if (node)
3038 {
3039 if (IsA(node, Const))
3040 {
3041 /* NULL indicates LIMIT ALL, ie, no limit */
3042 if (!((Const *) node)->constisnull)
3043 return true; /* LIMIT with a constant value */
3044 }
3045 else
3046 return true; /* non-constant LIMIT */
3047 }
3048
3049 node = parse->limitOffset;
3050 if (node)
3051 {
3052 if (IsA(node, Const))
3053 {
3054 /* Treat NULL as no offset; the executor would too */
3055 if (!((Const *) node)->constisnull)
3056 {
3057 int64 offset = DatumGetInt64(((Const *) node)->constvalue);
3058
3059 if (offset != 0)
3060 return true; /* OFFSET with a nonzero value */
3061 }
3062 }
3063 else
3064 return true; /* non-constant OFFSET */
3065 }
3066
3067 return false; /* don't need a Limit plan node */
3068}
int64_t int64
Definition c.h:680
void parse(int)
Definition parse.c:49
#define IsA(nodeptr, _type_)
Definition nodes.h:162
static int64 DatumGetInt64(Datum X)
Definition postgres.h:416

References DatumGetInt64(), fb(), IsA, and parse().

Referenced by grouping_planner(), and set_rel_consider_parallel().

◆ mark_partial_aggref()

void mark_partial_aggref ( Aggref agg,
AggSplit  aggsplit 
)
extern

Definition at line 6009 of file planner.c.

6010{
6011 /* aggtranstype should be computed by this point */
6012 Assert(OidIsValid(agg->aggtranstype));
6013 /* ... but aggsplit should still be as the parser left it */
6014 Assert(agg->aggsplit == AGGSPLIT_SIMPLE);
6015
6016 /* Mark the Aggref with the intended partial-aggregation mode */
6017 agg->aggsplit = aggsplit;
6018
6019 /*
6020 * Adjust result type if needed. Normally, a partial aggregate returns
6021 * the aggregate's transition type; but if that's INTERNAL and we're
6022 * serializing, it returns BYTEA instead.
6023 */
6024 if (DO_AGGSPLIT_SKIPFINAL(aggsplit))
6025 {
6026 if (agg->aggtranstype == INTERNALOID && DO_AGGSPLIT_SERIALIZE(aggsplit))
6027 agg->aggtype = BYTEAOID;
6028 else
6029 agg->aggtype = agg->aggtranstype;
6030 }
6031}
#define DO_AGGSPLIT_SKIPFINAL(as)
Definition nodes.h:394
#define DO_AGGSPLIT_SERIALIZE(as)
Definition nodes.h:395
@ AGGSPLIT_SIMPLE
Definition nodes.h:385

References AGGSPLIT_SIMPLE, Assert, DO_AGGSPLIT_SERIALIZE, DO_AGGSPLIT_SKIPFINAL, fb(), and OidIsValid.

Referenced by convert_combining_aggrefs(), create_rel_agg_info(), and make_partial_grouping_target().

◆ preprocess_phv_expression()

Expr * preprocess_phv_expression ( PlannerInfo root,
Expr expr 
)
extern

Definition at line 1671 of file planner.c.

1672{
1673 return (Expr *) preprocess_expression(root, (Node *) expr, EXPRKIND_PHV);
1674}
#define EXPRKIND_PHV
Definition planner.c:95
static Node * preprocess_expression(PlannerInfo *root, Node *expr, int kind)
Definition planner.c:1429

References EXPRKIND_PHV, preprocess_expression(), and root.

Referenced by extract_lateral_references().

◆ select_rowmark_type()

RowMarkType select_rowmark_type ( RangeTblEntry rte,
LockClauseStrength  strength 
)
extern

Definition at line 2781 of file planner.c.

2782{
2783 if (rte->rtekind != RTE_RELATION)
2784 {
2785 /* If it's not a table at all, use ROW_MARK_COPY */
2786 return ROW_MARK_COPY;
2787 }
2788 else if (rte->relkind == RELKIND_FOREIGN_TABLE)
2789 {
2790 /* Let the FDW select the rowmark type, if it wants to */
2791 FdwRoutine *fdwroutine = GetFdwRoutineByRelId(rte->relid);
2792
2793 if (fdwroutine->GetForeignRowMarkType != NULL)
2794 return fdwroutine->GetForeignRowMarkType(rte, strength);
2795 /* Otherwise, use ROW_MARK_COPY by default */
2796 return ROW_MARK_COPY;
2797 }
2798 else
2799 {
2800 /* Regular table, apply the appropriate lock type */
2801 switch (strength)
2802 {
2803 case LCS_NONE:
2804
2805 /*
2806 * We don't need a tuple lock, only the ability to re-fetch
2807 * the row.
2808 */
2809 return ROW_MARK_REFERENCE;
2810 break;
2811 case LCS_FORKEYSHARE:
2812 return ROW_MARK_KEYSHARE;
2813 break;
2814 case LCS_FORSHARE:
2815 return ROW_MARK_SHARE;
2816 break;
2817 case LCS_FORNOKEYUPDATE:
2819 break;
2820 case LCS_FORUPDATE:
2821 return ROW_MARK_EXCLUSIVE;
2822 break;
2823 }
2824 elog(ERROR, "unrecognized LockClauseStrength %d", (int) strength);
2825 return ROW_MARK_EXCLUSIVE; /* keep compiler quiet */
2826 }
2827}
FdwRoutine * GetFdwRoutineByRelId(Oid relid)
Definition foreign.c:451
@ LCS_FORUPDATE
Definition lockoptions.h:28
@ LCS_NONE
Definition lockoptions.h:23
@ LCS_FORSHARE
Definition lockoptions.h:26
@ LCS_FORKEYSHARE
Definition lockoptions.h:25
@ LCS_FORNOKEYUPDATE
Definition lockoptions.h:27
@ RTE_RELATION
@ ROW_MARK_COPY
Definition plannodes.h:1564
@ ROW_MARK_REFERENCE
Definition plannodes.h:1563
@ ROW_MARK_SHARE
Definition plannodes.h:1561
@ ROW_MARK_EXCLUSIVE
Definition plannodes.h:1559
@ ROW_MARK_NOKEYEXCLUSIVE
Definition plannodes.h:1560
@ ROW_MARK_KEYSHARE
Definition plannodes.h:1562
GetForeignRowMarkType_function GetForeignRowMarkType
Definition fdwapi.h:251

References elog, ERROR, fb(), GetFdwRoutineByRelId(), FdwRoutine::GetForeignRowMarkType, LCS_FORKEYSHARE, LCS_FORNOKEYUPDATE, LCS_FORSHARE, LCS_FORUPDATE, LCS_NONE, ROW_MARK_COPY, ROW_MARK_EXCLUSIVE, ROW_MARK_KEYSHARE, ROW_MARK_NOKEYEXCLUSIVE, ROW_MARK_REFERENCE, ROW_MARK_SHARE, and RTE_RELATION.

Referenced by expand_single_inheritance_child(), and preprocess_rowmarks().

◆ standard_planner()

PlannedStmt * standard_planner ( Query parse,
const char query_string,
int  cursorOptions,
ParamListInfo  boundParams,
ExplainState es 
)
extern

Definition at line 346 of file planner.c.

348{
350 PlannerGlobal *glob;
351 double tuple_fraction;
355 Plan *top_plan;
356 ListCell *lp,
357 *lr,
358 *lc;
359
360 /*
361 * Set up global state for this planner invocation. This data is needed
362 * across all levels of sub-Query that might exist in the given command,
363 * so we keep it in a separate struct that's linked to by each per-Query
364 * PlannerInfo.
365 */
366 glob = makeNode(PlannerGlobal);
367
368 glob->boundParams = boundParams;
369 glob->subplans = NIL;
370 glob->subpaths = NIL;
371 glob->subroots = NIL;
372 glob->rewindPlanIDs = NULL;
373 glob->finalrtable = NIL;
374 glob->allRelids = NULL;
375 glob->prunableRelids = NULL;
376 glob->finalrteperminfos = NIL;
377 glob->finalrowmarks = NIL;
378 glob->resultRelations = NIL;
379 glob->appendRelations = NIL;
380 glob->partPruneInfos = NIL;
381 glob->relationOids = NIL;
382 glob->invalItems = NIL;
383 glob->paramExecTypes = NIL;
384 glob->lastPHId = 0;
385 glob->lastRowMarkId = 0;
386 glob->lastPlanNodeId = 0;
387 glob->transientPlan = false;
388 glob->dependsOnRole = false;
389 glob->partition_directory = NULL;
390 glob->rel_notnullatts_hash = NULL;
391
392 /*
393 * Assess whether it's feasible to use parallel mode for this query. We
394 * can't do this in a standalone backend, or if the command will try to
395 * modify any data, or if this is a cursor operation, or if GUCs are set
396 * to values that don't permit parallelism, or if parallel-unsafe
397 * functions are present in the query tree.
398 *
399 * (Note that we do allow CREATE TABLE AS, SELECT INTO, and CREATE
400 * MATERIALIZED VIEW to use parallel plans, but this is safe only because
401 * the command is writing into a completely new table which workers won't
402 * be able to see. If the workers could see the table, the fact that
403 * group locking would cause them to ignore the leader's heavyweight GIN
404 * page locks would make this unsafe. We'll have to fix that somehow if
405 * we want to allow parallel inserts in general; updates and deletes have
406 * additional problems especially around combo CIDs.)
407 *
408 * For now, we don't try to use parallel mode if we're running inside a
409 * parallel worker. We might eventually be able to relax this
410 * restriction, but for now it seems best not to have parallel workers
411 * trying to create their own parallel workers.
412 */
413 if ((cursorOptions & CURSOR_OPT_PARALLEL_OK) != 0 &&
415 parse->commandType == CMD_SELECT &&
416 !parse->hasModifyingCTE &&
419 {
420 /* all the cheap tests pass, so scan the query tree */
423 }
424 else
425 {
426 /* skip the query tree scan, just assume it's unsafe */
428 glob->parallelModeOK = false;
429 }
430
431 /*
432 * glob->parallelModeNeeded is normally set to false here and changed to
433 * true during plan creation if a Gather or Gather Merge plan is actually
434 * created (cf. create_gather_plan, create_gather_merge_plan).
435 *
436 * However, if debug_parallel_query = on or debug_parallel_query =
437 * regress, then we impose parallel mode whenever it's safe to do so, even
438 * if the final plan doesn't use parallelism. It's not safe to do so if
439 * the query contains anything parallel-unsafe; parallelModeOK will be
440 * false in that case. Note that parallelModeOK can't change after this
441 * point. Otherwise, everything in the query is either parallel-safe or
442 * parallel-restricted, and in either case it should be OK to impose
443 * parallel-mode restrictions. If that ends up breaking something, then
444 * either some function the user included in the query is incorrectly
445 * labeled as parallel-safe or parallel-restricted when in reality it's
446 * parallel-unsafe, or else the query planner itself has a bug.
447 */
448 glob->parallelModeNeeded = glob->parallelModeOK &&
450
451 /* Determine what fraction of the plan is likely to be scanned */
452 if (cursorOptions & CURSOR_OPT_FAST_PLAN)
453 {
454 /*
455 * We have no real idea how many tuples the user will ultimately FETCH
456 * from a cursor, but it is often the case that he doesn't want 'em
457 * all, or would prefer a fast-start plan anyway so that he can
458 * process some of the tuples sooner. Use a GUC parameter to decide
459 * what fraction to optimize for.
460 */
461 tuple_fraction = cursor_tuple_fraction;
462
463 /*
464 * We document cursor_tuple_fraction as simply being a fraction, which
465 * means the edge cases 0 and 1 have to be treated specially here. We
466 * convert 1 to 0 ("all the tuples") and 0 to a very small fraction.
467 */
468 if (tuple_fraction >= 1.0)
469 tuple_fraction = 0.0;
470 else if (tuple_fraction <= 0.0)
471 tuple_fraction = 1e-10;
472 }
473 else
474 {
475 /* Default assumption is we need all the tuples */
476 tuple_fraction = 0.0;
477 }
478
479 /*
480 * Compute the initial path generation strategy mask.
481 *
482 * Some strategies, such as PGS_FOREIGNJOIN, have no corresponding enable_*
483 * GUC, and so the corresponding bits are always set in the default
484 * strategy mask.
485 *
486 * It may seem surprising that enable_indexscan sets both PGS_INDEXSCAN
487 * and PGS_INDEXONLYSCAN. However, the historical behavior of this GUC
488 * corresponds to this exactly: enable_indexscan=off disables both
489 * index-scan and index-only scan paths, whereas enable_indexonlyscan=off
490 * converts the index-only scan paths that we would have considered into
491 * index scan paths.
492 */
495 if (enable_tidscan)
497 if (enable_seqscan)
506 {
508 if (enable_material)
510 }
511 if (enable_nestloop)
512 {
514 if (enable_material)
516 if (enable_memoize)
518 }
519 if (enable_hashjoin)
525
526 /* Allow plugins to take control after we've initialized "glob" */
528 (*planner_setup_hook) (glob, parse, query_string, cursorOptions,
529 &tuple_fraction, es);
530
531 /* primary planning entry point (may recurse for subqueries) */
532 root = subquery_planner(glob, parse, NULL, NULL, NULL, false,
533 tuple_fraction, NULL);
534
535 /* Select best Path and turn it into a Plan */
538
540
541 /*
542 * If creating a plan for a scrollable cursor, make sure it can run
543 * backwards on demand. Add a Material node at the top at need.
544 */
545 if (cursorOptions & CURSOR_OPT_SCROLL)
546 {
549 }
550
551 /*
552 * Optionally add a Gather node for testing purposes, provided this is
553 * actually a safe thing to do.
554 *
555 * We can add Gather even when top_plan has parallel-safe initPlans, but
556 * then we have to move the initPlans to the Gather node because of
557 * SS_finalize_plan's limitations. That would cause cosmetic breakage of
558 * regression tests when debug_parallel_query = regress, because initPlans
559 * that would normally appear on the top_plan move to the Gather, causing
560 * them to disappear from EXPLAIN output. That doesn't seem worth kluging
561 * EXPLAIN to hide, so skip it when debug_parallel_query = regress.
562 */
564 top_plan->parallel_safe &&
565 (top_plan->initPlan == NIL ||
567 {
570 bool unsafe_initplans;
571
572 gather->plan.targetlist = top_plan->targetlist;
573 gather->plan.qual = NIL;
574 gather->plan.lefttree = top_plan;
575 gather->plan.righttree = NULL;
576 gather->num_workers = 1;
577 gather->single_copy = true;
579
580 /* Transfer any initPlans to the new top node */
581 gather->plan.initPlan = top_plan->initPlan;
582 top_plan->initPlan = NIL;
583
584 /*
585 * Since this Gather has no parallel-aware descendants to signal to,
586 * we don't need a rescan Param.
587 */
588 gather->rescan_param = -1;
589
590 /*
591 * Ideally we'd use cost_gather here, but setting up dummy path data
592 * to satisfy it doesn't seem much cleaner than knowing what it does.
593 */
594 gather->plan.startup_cost = top_plan->startup_cost +
596 gather->plan.total_cost = top_plan->total_cost +
598 gather->plan.plan_rows = top_plan->plan_rows;
599 gather->plan.plan_width = top_plan->plan_width;
600 gather->plan.parallel_aware = false;
601 gather->plan.parallel_safe = false;
602
603 /*
604 * Delete the initplans' cost from top_plan. We needn't add it to the
605 * Gather node, since the above coding already included it there.
606 */
607 SS_compute_initplan_cost(gather->plan.initPlan,
609 top_plan->startup_cost -= initplan_cost;
610 top_plan->total_cost -= initplan_cost;
611
612 /* use parallel mode for parallel plans. */
613 root->glob->parallelModeNeeded = true;
614
615 top_plan = &gather->plan;
616 }
617
618 /*
619 * If any Params were generated, run through the plan tree and compute
620 * each plan node's extParam/allParam sets. Ideally we'd merge this into
621 * set_plan_references' tree traversal, but for now it has to be separate
622 * because we need to visit subplans before not after main plan.
623 */
624 if (glob->paramExecTypes != NIL)
625 {
626 Assert(list_length(glob->subplans) == list_length(glob->subroots));
627 forboth(lp, glob->subplans, lr, glob->subroots)
628 {
629 Plan *subplan = (Plan *) lfirst(lp);
631
632 SS_finalize_plan(subroot, subplan);
633 }
635 }
636
637 /* final cleanup of the plan */
638 Assert(glob->finalrtable == NIL);
639 Assert(glob->finalrteperminfos == NIL);
640 Assert(glob->finalrowmarks == NIL);
641 Assert(glob->resultRelations == NIL);
642 Assert(glob->appendRelations == NIL);
644 /* ... and the subplans (both regular subplans and initplans) */
645 Assert(list_length(glob->subplans) == list_length(glob->subroots));
646 forboth(lp, glob->subplans, lr, glob->subroots)
647 {
648 Plan *subplan = (Plan *) lfirst(lp);
650
651 lfirst(lp) = set_plan_references(subroot, subplan);
652 }
653
654 /* build the PlannedStmt result */
656
657 result->commandType = parse->commandType;
658 result->queryId = parse->queryId;
659 result->planOrigin = PLAN_STMT_STANDARD;
660 result->hasReturning = (parse->returningList != NIL);
661 result->hasModifyingCTE = parse->hasModifyingCTE;
662 result->canSetTag = parse->canSetTag;
663 result->transientPlan = glob->transientPlan;
664 result->dependsOnRole = glob->dependsOnRole;
665 result->parallelModeNeeded = glob->parallelModeNeeded;
666 result->planTree = top_plan;
667 result->partPruneInfos = glob->partPruneInfos;
668 result->rtable = glob->finalrtable;
669 result->unprunableRelids = bms_difference(glob->allRelids,
670 glob->prunableRelids);
671 result->permInfos = glob->finalrteperminfos;
672 result->subrtinfos = glob->subrtinfos;
673 result->appendRelations = glob->appendRelations;
674 result->subplans = glob->subplans;
675 result->rewindPlanIDs = glob->rewindPlanIDs;
676 result->rowMarks = glob->finalrowmarks;
677
678 /*
679 * Compute resultRelationRelids and rowMarkRelids from resultRelations and
680 * rowMarks. These can be used for cheap membership checks.
681 */
682 foreach(lc, glob->resultRelations)
683 result->resultRelationRelids = bms_add_member(result->resultRelationRelids,
684 lfirst_int(lc));
685 foreach(lc, glob->finalrowmarks)
686 result->rowMarkRelids = bms_add_member(result->rowMarkRelids,
687 ((PlanRowMark *) lfirst(lc))->rti);
688
689 result->relationOids = glob->relationOids;
690 result->invalItems = glob->invalItems;
691 result->paramExecTypes = glob->paramExecTypes;
692 /* utilityStmt should be null, but we might as well copy it */
693 result->utilityStmt = parse->utilityStmt;
694 result->elidedNodes = glob->elidedNodes;
695 result->stmt_location = parse->stmt_location;
696 result->stmt_len = parse->stmt_len;
697
698 result->jitFlags = PGJIT_NONE;
699 if (jit_enabled && jit_above_cost >= 0 &&
700 top_plan->total_cost > jit_above_cost)
701 {
702 result->jitFlags |= PGJIT_PERFORM;
703
704 /*
705 * Decide how much effort should be put into generating better code.
706 */
707 if (jit_optimize_above_cost >= 0 &&
708 top_plan->total_cost > jit_optimize_above_cost)
709 result->jitFlags |= PGJIT_OPT3;
710 if (jit_inline_above_cost >= 0 &&
711 top_plan->total_cost > jit_inline_above_cost)
712 result->jitFlags |= PGJIT_INLINE;
713
714 /*
715 * Decide which operations should be JITed.
716 */
717 if (jit_expressions)
718 result->jitFlags |= PGJIT_EXPR;
720 result->jitFlags |= PGJIT_DEFORM;
721 }
722
723 /* Allow plugins to take control before we discard "glob" */
725 (*planner_shutdown_hook) (glob, parse, query_string, result);
726
727 if (glob->partition_directory != NULL)
728 DestroyPartitionDirectory(glob->partition_directory);
729
730 return result;
731}
Bitmapset * bms_difference(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:347
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition bitmapset.c:934
uint32 result
char max_parallel_hazard(Query *parse)
Definition clauses.c:763
bool enable_seqscan
Definition costsize.c:146
int max_parallel_workers_per_gather
Definition costsize.c:144
bool enable_memoize
Definition costsize.c:157
double parallel_setup_cost
Definition costsize.c:137
bool enable_gathermerge
Definition costsize.c:160
double parallel_tuple_cost
Definition costsize.c:136
bool enable_indexonlyscan
Definition costsize.c:148
bool enable_tidscan
Definition costsize.c:150
bool enable_material
Definition costsize.c:156
bool enable_hashjoin
Definition costsize.c:159
bool enable_mergejoin
Definition costsize.c:158
bool enable_partitionwise_join
Definition costsize.c:161
bool enable_nestloop
Definition costsize.c:155
bool enable_bitmapscan
Definition costsize.c:149
bool enable_indexscan
Definition costsize.c:147
Plan * materialize_finished_plan(Plan *subplan)
Plan * create_plan(PlannerInfo *root, Path *best_path)
Definition createplan.c:345
bool ExecSupportsBackwardScan(Plan *node)
Definition execAmi.c:512
bool IsUnderPostmaster
Definition globals.c:122
#define IsParallelWorker()
Definition parallel.h:62
double jit_optimize_above_cost
Definition jit.c:42
bool jit_enabled
Definition jit.c:33
bool jit_expressions
Definition jit.c:37
bool jit_tuple_deforming
Definition jit.c:39
double jit_above_cost
Definition jit.c:40
double jit_inline_above_cost
Definition jit.c:41
#define PGJIT_OPT3
Definition jit.h:21
#define PGJIT_NONE
Definition jit.h:19
#define PGJIT_EXPR
Definition jit.h:23
#define PGJIT_DEFORM
Definition jit.h:24
#define PGJIT_INLINE
Definition jit.h:22
#define PGJIT_PERFORM
Definition jit.h:20
double Cost
Definition nodes.h:259
@ CMD_SELECT
Definition nodes.h:273
@ DEBUG_PARALLEL_REGRESS
Definition optimizer.h:98
@ DEBUG_PARALLEL_OFF
Definition optimizer.h:96
#define CURSOR_OPT_SCROLL
#define CURSOR_OPT_FAST_PLAN
#define CURSOR_OPT_PARALLEL_OK
void DestroyPartitionDirectory(PartitionDirectory pdir)
Definition partdesc.c:484
#define PGS_NESTLOOP_MEMOIZE
Definition pathnodes.h:76
#define PGS_TIDSCAN
Definition pathnodes.h:70
#define PGS_FOREIGNJOIN
Definition pathnodes.h:71
#define PGS_APPEND
Definition pathnodes.h:78
#define PGS_MERGE_APPEND
Definition pathnodes.h:79
#define PGS_SEQSCAN
Definition pathnodes.h:66
#define PGS_CONSIDER_INDEXONLY
Definition pathnodes.h:82
#define PGS_NESTLOOP_MATERIALIZE
Definition pathnodes.h:75
#define PGS_MERGEJOIN_PLAIN
Definition pathnodes.h:72
#define PGS_MERGEJOIN_MATERIALIZE
Definition pathnodes.h:73
#define PGS_HASHJOIN
Definition pathnodes.h:77
#define PGS_CONSIDER_NONPARTIAL
Definition pathnodes.h:84
#define PGS_BITMAPSCAN
Definition pathnodes.h:69
#define PGS_GATHER
Definition pathnodes.h:80
#define PGS_CONSIDER_PARTITIONWISE
Definition pathnodes.h:83
#define PGS_GATHER_MERGE
Definition pathnodes.h:81
@ UPPERREL_FINAL
Definition pathnodes.h:152
#define PGS_INDEXONLYSCAN
Definition pathnodes.h:68
#define PGS_INDEXSCAN
Definition pathnodes.h:67
#define PGS_NESTLOOP_PLAIN
Definition pathnodes.h:74
#define lfirst_node(type, lc)
Definition pg_list.h:176
#define lfirst_int(lc)
Definition pg_list.h:173
PlannerInfo * subquery_planner(PlannerGlobal *glob, Query *parse, char *plan_name, PlannerInfo *parent_root, PlannerInfo *alternative_root, bool hasRecursion, double tuple_fraction, SetOperationStmt *setops)
Definition planner.c:770
double cursor_tuple_fraction
Definition planner.c:68
planner_shutdown_hook_type planner_shutdown_hook
Definition planner.c:80
Path * get_cheapest_fractional_path(RelOptInfo *rel, double tuple_fraction)
Definition planner.c:6848
planner_setup_hook_type planner_setup_hook
Definition planner.c:77
int debug_parallel_query
Definition planner.c:69
@ PLAN_STMT_STANDARD
Definition plannodes.h:39
e
RelOptInfo * fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
Definition relnode.c:1617
Plan * set_plan_references(PlannerInfo *root, Plan *plan)
Definition setrefs.c:288
Bitmapset * prunableRelids
Definition pathnodes.h:206
char maxParallelHazard
Definition pathnodes.h:260
List * subplans
Definition pathnodes.h:178
bool dependsOnRole
Definition pathnodes.h:251
Bitmapset * allRelids
Definition pathnodes.h:199
List * appendRelations
Definition pathnodes.h:221
List * finalrowmarks
Definition pathnodes.h:215
List * invalItems
Definition pathnodes.h:230
List * relationOids
Definition pathnodes.h:227
List * paramExecTypes
Definition pathnodes.h:233
bool parallelModeOK
Definition pathnodes.h:254
bool transientPlan
Definition pathnodes.h:248
Bitmapset * rewindPlanIDs
Definition pathnodes.h:190
List * finalrteperminfos
Definition pathnodes.h:209
List * subpaths
Definition pathnodes.h:181
Index lastRowMarkId
Definition pathnodes.h:242
List * resultRelations
Definition pathnodes.h:218
List * partPruneInfos
Definition pathnodes.h:224
List * finalrtable
Definition pathnodes.h:193
uint64 default_pgs_mask
Definition pathnodes.h:263
bool parallelModeNeeded
Definition pathnodes.h:257
void SS_finalize_plan(PlannerInfo *root, Plan *plan)
Definition subselect.c:2551
void SS_compute_initplan_cost(List *init_plans, Cost *initplan_cost_p, bool *unsafe_initplans_p)
Definition subselect.c:2495

References PlannerGlobal::allRelids, PlannerGlobal::appendRelations, Assert, bms_add_member(), bms_difference(), CMD_SELECT, create_plan(), CURSOR_OPT_FAST_PLAN, CURSOR_OPT_PARALLEL_OK, CURSOR_OPT_SCROLL, cursor_tuple_fraction, DEBUG_PARALLEL_OFF, debug_parallel_query, DEBUG_PARALLEL_REGRESS, PlannerGlobal::default_pgs_mask, PlannerGlobal::dependsOnRole, DestroyPartitionDirectory(), PlannerGlobal::elidedNodes, enable_bitmapscan, enable_gathermerge, enable_hashjoin, enable_indexonlyscan, enable_indexscan, enable_material, enable_memoize, enable_mergejoin, enable_nestloop, enable_partitionwise_join, enable_seqscan, enable_tidscan, ExecSupportsBackwardScan(), fb(), fetch_upper_rel(), PlannerGlobal::finalrowmarks, PlannerGlobal::finalrtable, PlannerGlobal::finalrteperminfos, forboth, get_cheapest_fractional_path(), PlannerGlobal::invalItems, IsParallelWorker, IsUnderPostmaster, jit_above_cost, jit_enabled, jit_expressions, jit_inline_above_cost, jit_optimize_above_cost, jit_tuple_deforming, PlannerGlobal::lastPHId, PlannerGlobal::lastPlanNodeId, PlannerGlobal::lastRowMarkId, lfirst, lfirst_int, lfirst_node, list_length(), makeNode, materialize_finished_plan(), max_parallel_hazard(), max_parallel_workers_per_gather, PlannerGlobal::maxParallelHazard, NIL, parallel_setup_cost, parallel_tuple_cost, PlannerGlobal::parallelModeNeeded, PlannerGlobal::parallelModeOK, PlannerGlobal::paramExecTypes, parse(), PlannerGlobal::partPruneInfos, PGJIT_DEFORM, PGJIT_EXPR, PGJIT_INLINE, PGJIT_NONE, PGJIT_OPT3, PGJIT_PERFORM, PGS_APPEND, PGS_BITMAPSCAN, PGS_CONSIDER_INDEXONLY, PGS_CONSIDER_NONPARTIAL, PGS_CONSIDER_PARTITIONWISE, PGS_FOREIGNJOIN, PGS_GATHER, PGS_GATHER_MERGE, PGS_HASHJOIN, PGS_INDEXONLYSCAN, PGS_INDEXSCAN, PGS_MERGE_APPEND, PGS_MERGEJOIN_MATERIALIZE, PGS_MERGEJOIN_PLAIN, PGS_NESTLOOP_MATERIALIZE, PGS_NESTLOOP_MEMOIZE, PGS_NESTLOOP_PLAIN, PGS_SEQSCAN, PGS_TIDSCAN, PLAN_STMT_STANDARD, planner_setup_hook, planner_shutdown_hook, PlannerGlobal::prunableRelids, PlannerGlobal::relationOids, result, PlannerGlobal::resultRelations, PlannerGlobal::rewindPlanIDs, root, set_plan_references(), SS_compute_initplan_cost(), SS_finalize_plan(), PlannerGlobal::subpaths, PlannerGlobal::subplans, subquery_planner(), PlannerGlobal::subrtinfos, PlannerGlobal::transientPlan, and UPPERREL_FINAL.

Referenced by delay_execution_planner(), pgss_planner(), and planner().

◆ subquery_planner()

PlannerInfo * subquery_planner ( PlannerGlobal glob,
Query parse,
char plan_name,
PlannerInfo parent_root,
PlannerInfo alternative_root,
bool  hasRecursion,
double  tuple_fraction,
SetOperationStmt setops 
)
extern

Definition at line 770 of file planner.c.

774{
779 int havingIdx;
780 bool hasOuterJoins;
781 bool hasResultRTEs;
783 ListCell *l;
784
785 /* Create a PlannerInfo data structure for this subquery */
787 root->parse = parse;
788 root->glob = glob;
789 root->query_level = parent_root ? parent_root->query_level + 1 : 1;
790 root->plan_name = plan_name;
791 if (alternative_root != NULL)
792 root->alternative_plan_name = alternative_root->plan_name;
793 else
794 root->alternative_plan_name = plan_name;
795 root->parent_root = parent_root;
796 root->plan_params = NIL;
797 root->outer_params = NULL;
798 root->planner_cxt = CurrentMemoryContext;
799 root->init_plans = NIL;
800 root->cte_plan_ids = NIL;
801 root->multiexpr_params = NIL;
802 root->join_domains = NIL;
803 root->eq_classes = NIL;
804 root->ec_merging_done = false;
805 root->last_rinfo_serial = 0;
806 root->all_result_relids =
807 parse->resultRelation ? bms_make_singleton(parse->resultRelation) : NULL;
808 root->leaf_result_relids = NULL; /* we'll find out leaf-ness later */
809 root->append_rel_list = NIL;
810 root->row_identity_vars = NIL;
811 root->rowMarks = NIL;
812 memset(root->upper_rels, 0, sizeof(root->upper_rels));
813 memset(root->upper_targets, 0, sizeof(root->upper_targets));
814 root->processed_groupClause = NIL;
815 root->processed_distinctClause = NIL;
816 root->processed_tlist = NIL;
817 root->update_colnos = NIL;
818 root->grouping_map = NULL;
819 root->minmax_aggs = NIL;
820 root->qual_security_level = 0;
821 root->hasPseudoConstantQuals = false;
822 root->hasAlternativeSubPlans = false;
823 root->placeholdersFrozen = false;
824 root->hasRecursion = hasRecursion;
825 root->assumeReplanning = false;
826 if (hasRecursion)
827 root->wt_param_id = assign_special_exec_param(root);
828 else
829 root->wt_param_id = -1;
830 root->non_recursive_path = NULL;
831
832 /*
833 * Create the top-level join domain. This won't have valid contents until
834 * deconstruct_jointree fills it in, but the node needs to exist before
835 * that so we can build EquivalenceClasses referencing it.
836 */
837 root->join_domains = list_make1(makeNode(JoinDomain));
838
839 /*
840 * If there is a WITH list, process each WITH query and either convert it
841 * to RTE_SUBQUERY RTE(s) or build an initplan SubPlan structure for it.
842 */
843 if (parse->cteList)
845
846 /*
847 * If it's a MERGE command, transform the joinlist as appropriate.
848 */
850
851 /*
852 * Reject FOR PORTION OF on a generated column. We can't write to a
853 * virtual generated column, and a stored generated column should be
854 * written by its own expression.
855 *
856 * We do this in the planner rather than parse analysis so that updatable
857 * views have been rewritten; otherwise they would mask which columns are
858 * generated. We need to check before preprocess_relation_rtes(), so that
859 * for virtual generated columns we still have the rangeVar. After that
860 * it is replaced by the column's expression.
861 *
862 * XXX: We plan to implement PERIODs as stored generated columns, so later
863 * we will loosen this restriction if the column belongs to a PERIOD.
864 */
865 if (parse->forPortionOf)
866 {
867 ForPortionOfExpr *forPortionOf = parse->forPortionOf;
868 RangeTblEntry *rte = rt_fetch(parse->resultRelation, parse->rtable);
869
870 if (get_attgenerated(rte->relid, forPortionOf->rangeVar->varattno))
873 errmsg("cannot use generated column \"%s\" in FOR PORTION OF",
874 forPortionOf->range_name)));
875 }
876
877 /*
878 * Scan the rangetable for relation RTEs and retrieve the necessary
879 * catalog information for each relation. Using this information, clear
880 * the inh flag for any relation that has no children, collect not-null
881 * attribute numbers for any relation that has column not-null
882 * constraints, and expand virtual generated columns for any relation that
883 * contains them. Note that this step does not descend into sublinks and
884 * subqueries; if we pull up any sublinks or subqueries below, their
885 * relation RTEs are processed just before pulling them up.
886 */
888
889 /*
890 * If the FROM clause is empty, replace it with a dummy RTE_RESULT RTE, so
891 * that we don't need so many special cases to deal with that situation.
892 */
894
895 /*
896 * Look for ANY and EXISTS SubLinks in WHERE and JOIN/ON clauses, and try
897 * to transform them into joins. Note that this step does not descend
898 * into subqueries; if we pull up any subqueries below, their SubLinks are
899 * processed just before pulling them up.
900 */
901 if (parse->hasSubLinks)
903
904 /*
905 * Scan the rangetable for function RTEs, do const-simplification on them,
906 * and then inline them if possible (producing subqueries that might get
907 * pulled up next). Recursion issues here are handled in the same way as
908 * for SubLinks.
909 */
911
912 /*
913 * Check to see if any subqueries in the jointree can be merged into this
914 * query.
915 */
917
918 /*
919 * If this is a simple UNION ALL query, flatten it into an appendrel. We
920 * do this now because it requires applying pull_up_subqueries to the leaf
921 * queries of the UNION ALL, which weren't touched above because they
922 * weren't referenced by the jointree (they will be after we do this).
923 */
924 if (parse->setOperations)
926
927 /*
928 * Survey the rangetable to see what kinds of entries are present. We can
929 * skip some later processing if relevant SQL features are not used; for
930 * example if there are no JOIN RTEs we can avoid the expense of doing
931 * flatten_join_alias_vars(). This must be done after we have finished
932 * adding rangetable entries, of course. (Note: actually, processing of
933 * inherited or partitioned rels can cause RTEs for their child tables to
934 * get added later; but those must all be RTE_RELATION entries, so they
935 * don't invalidate the conclusions drawn here.)
936 */
937 root->hasJoinRTEs = false;
938 root->hasLateralRTEs = false;
939 root->group_rtindex = 0;
940 hasOuterJoins = false;
941 hasResultRTEs = false;
942 foreach(l, parse->rtable)
943 {
945
946 switch (rte->rtekind)
947 {
948 case RTE_JOIN:
949 root->hasJoinRTEs = true;
950 if (IS_OUTER_JOIN(rte->jointype))
951 hasOuterJoins = true;
952 break;
953 case RTE_RESULT:
954 hasResultRTEs = true;
955 break;
956 case RTE_GROUP:
957 Assert(parse->hasGroupRTE);
958 root->group_rtindex = list_cell_number(parse->rtable, l) + 1;
959 break;
960 default:
961 /* No work here for other RTE types */
962 break;
963 }
964
965 if (rte->lateral)
966 root->hasLateralRTEs = true;
967
968 /*
969 * We can also determine the maximum security level required for any
970 * securityQuals now. Addition of inheritance-child RTEs won't affect
971 * this, because child tables don't have their own securityQuals; see
972 * expand_single_inheritance_child().
973 */
974 if (rte->securityQuals)
975 root->qual_security_level = Max(root->qual_security_level,
976 list_length(rte->securityQuals));
977 }
978
979 /*
980 * If we have now verified that the query target relation is
981 * non-inheriting, mark it as a leaf target.
982 */
983 if (parse->resultRelation)
984 {
985 RangeTblEntry *rte = rt_fetch(parse->resultRelation, parse->rtable);
986
987 if (!rte->inh)
988 root->leaf_result_relids =
989 bms_make_singleton(parse->resultRelation);
990 }
991
992 /*
993 * This would be a convenient time to check access permissions for all
994 * relations mentioned in the query, since it would be better to fail now,
995 * before doing any detailed planning. However, for historical reasons,
996 * we leave this to be done at executor startup.
997 *
998 * Note, however, that we do need to check access permissions for any view
999 * relations mentioned in the query, in order to prevent information being
1000 * leaked by selectivity estimation functions, which only check view owner
1001 * permissions on underlying tables (see all_rows_selectable() and its
1002 * callers). This is a little ugly, because it means that access
1003 * permissions for views will be checked twice, which is another reason
1004 * why it would be better to do all the ACL checks here.
1005 */
1006 foreach(l, parse->rtable)
1007 {
1009
1010 if (rte->perminfoindex != 0 &&
1011 rte->relkind == RELKIND_VIEW)
1012 {
1014 bool result;
1015
1016 perminfo = getRTEPermissionInfo(parse->rteperminfos, rte);
1018 if (!result)
1020 get_rel_name(perminfo->relid));
1021 }
1022 }
1023
1024 /*
1025 * Preprocess RowMark information. We need to do this after subquery
1026 * pullup, so that all base relations are present.
1027 */
1029
1030 /*
1031 * Set hasHavingQual to remember if HAVING clause is present. Needed
1032 * because preprocess_expression will reduce a constant-true condition to
1033 * an empty qual list ... but "HAVING TRUE" is not a semantic no-op.
1034 */
1035 root->hasHavingQual = (parse->havingQual != NULL);
1036
1037 /*
1038 * Do expression preprocessing on targetlist and quals, as well as other
1039 * random expressions in the querytree. Note that we do not need to
1040 * handle sort/group expressions explicitly, because they are actually
1041 * part of the targetlist.
1042 */
1043 parse->targetList = (List *)
1044 preprocess_expression(root, (Node *) parse->targetList,
1046
1048 foreach(l, parse->withCheckOptions)
1049 {
1051
1052 wco->qual = preprocess_expression(root, wco->qual,
1054 if (wco->qual != NULL)
1056 }
1057 parse->withCheckOptions = newWithCheckOptions;
1058
1059 parse->returningList = (List *)
1060 preprocess_expression(root, (Node *) parse->returningList,
1062
1063 preprocess_qual_conditions(root, (Node *) parse->jointree);
1064
1065 parse->havingQual = preprocess_expression(root, parse->havingQual,
1067
1068 foreach(l, parse->windowClause)
1069 {
1071
1072 /* partitionClause/orderClause are sort/group expressions */
1077 }
1078
1079 parse->limitOffset = preprocess_expression(root, parse->limitOffset,
1081 parse->limitCount = preprocess_expression(root, parse->limitCount,
1083
1084 if (parse->onConflict)
1085 {
1086 parse->onConflict->arbiterElems = (List *)
1088 (Node *) parse->onConflict->arbiterElems,
1090 parse->onConflict->arbiterWhere =
1092 parse->onConflict->arbiterWhere,
1094 parse->onConflict->onConflictSet = (List *)
1096 (Node *) parse->onConflict->onConflictSet,
1098 parse->onConflict->onConflictWhere =
1100 parse->onConflict->onConflictWhere,
1102 /* exclRelTlist contains only Vars, so no preprocessing needed */
1103 }
1104
1105 if (parse->forPortionOf)
1106 {
1107 parse->forPortionOf->targetRange =
1109 parse->forPortionOf->targetRange,
1111 if (contain_volatile_functions(parse->forPortionOf->targetRange))
1112 ereport(ERROR,
1114 errmsg("FOR PORTION OF bounds cannot contain volatile functions")));
1115 }
1116
1117 foreach(l, parse->mergeActionList)
1118 {
1120
1121 action->targetList = (List *)
1123 (Node *) action->targetList,
1125 action->qual =
1127 (Node *) action->qual,
1129 }
1130
1131 parse->mergeJoinCondition =
1132 preprocess_expression(root, parse->mergeJoinCondition, EXPRKIND_QUAL);
1133
1134 root->append_rel_list = (List *)
1135 preprocess_expression(root, (Node *) root->append_rel_list,
1137
1138 /* Also need to preprocess expressions within RTEs */
1139 foreach(l, parse->rtable)
1140 {
1142 int kind;
1143 ListCell *lcsq;
1144
1145 if (rte->rtekind == RTE_RELATION)
1146 {
1147 if (rte->tablesample)
1148 rte->tablesample = (TableSampleClause *)
1150 (Node *) rte->tablesample,
1152 }
1153 else if (rte->rtekind == RTE_SUBQUERY)
1154 {
1155 /*
1156 * We don't want to do all preprocessing yet on the subquery's
1157 * expressions, since that will happen when we plan it. But if it
1158 * contains any join aliases of our level, those have to get
1159 * expanded now, because planning of the subquery won't do it.
1160 * That's only possible if the subquery is LATERAL.
1161 */
1162 if (rte->lateral && root->hasJoinRTEs)
1163 rte->subquery = (Query *)
1165 (Node *) rte->subquery);
1166 }
1167 else if (rte->rtekind == RTE_FUNCTION)
1168 {
1169 /* Preprocess the function expression(s) fully */
1170 kind = rte->lateral ? EXPRKIND_RTFUNC_LATERAL : EXPRKIND_RTFUNC;
1171 rte->functions = (List *)
1172 preprocess_expression(root, (Node *) rte->functions, kind);
1173 }
1174 else if (rte->rtekind == RTE_TABLEFUNC)
1175 {
1176 /* Preprocess the function expression(s) fully */
1178 rte->tablefunc = (TableFunc *)
1179 preprocess_expression(root, (Node *) rte->tablefunc, kind);
1180 }
1181 else if (rte->rtekind == RTE_VALUES)
1182 {
1183 /* Preprocess the values lists fully */
1184 kind = rte->lateral ? EXPRKIND_VALUES_LATERAL : EXPRKIND_VALUES;
1185 rte->values_lists = (List *)
1186 preprocess_expression(root, (Node *) rte->values_lists, kind);
1187 }
1188 else if (rte->rtekind == RTE_GROUP)
1189 {
1190 /* Preprocess the groupexprs list fully */
1191 rte->groupexprs = (List *)
1192 preprocess_expression(root, (Node *) rte->groupexprs,
1194 }
1195
1196 /*
1197 * Process each element of the securityQuals list as if it were a
1198 * separate qual expression (as indeed it is). We need to do it this
1199 * way to get proper canonicalization of AND/OR structure. Note that
1200 * this converts each element into an implicit-AND sublist.
1201 */
1202 foreach(lcsq, rte->securityQuals)
1203 {
1205 (Node *) lfirst(lcsq),
1207 }
1208 }
1209
1210 /*
1211 * Now that we are done preprocessing expressions, and in particular done
1212 * flattening join alias variables, get rid of the joinaliasvars lists.
1213 * They no longer match what expressions in the rest of the tree look
1214 * like, because we have not preprocessed expressions in those lists (and
1215 * do not want to; for example, expanding a SubLink there would result in
1216 * a useless unreferenced subplan). Leaving them in place simply creates
1217 * a hazard for later scans of the tree. We could try to prevent that by
1218 * using QTW_IGNORE_JOINALIASES in every tree scan done after this point,
1219 * but that doesn't sound very reliable.
1220 */
1221 if (root->hasJoinRTEs)
1222 {
1223 foreach(l, parse->rtable)
1224 {
1226
1227 rte->joinaliasvars = NIL;
1228 }
1229 }
1230
1231 /*
1232 * Before we flatten GROUP Vars, identify HAVING clauses whose equality
1233 * semantics disagree with the GROUP BY's. See find_having_conflicts.
1234 */
1235 if (parse->hasGroupRTE)
1237 root->group_rtindex);
1238 else
1240
1241 /*
1242 * Replace any Vars in the subquery's targetlist and havingQual that
1243 * reference GROUP outputs with the underlying grouping expressions.
1244 *
1245 * Note that we need to perform this replacement after we've preprocessed
1246 * the grouping expressions. This is to ensure that there is only one
1247 * instance of SubPlan for each SubLink contained within the grouping
1248 * expressions.
1249 */
1250 if (parse->hasGroupRTE)
1251 {
1252 parse->targetList = (List *)
1253 flatten_group_exprs(root, root->parse, (Node *) parse->targetList);
1254 parse->havingQual =
1255 flatten_group_exprs(root, root->parse, parse->havingQual);
1256 }
1257
1258 /* Constant-folding might have removed all set-returning functions */
1259 if (parse->hasTargetSRFs)
1260 parse->hasTargetSRFs = expression_returns_set((Node *) parse->targetList);
1261
1262 /*
1263 * If we have grouping sets, expand the groupingSets tree of this query to
1264 * a flat list of grouping sets. We need to do this before optimizing
1265 * HAVING, since we can't easily tell if there's an empty grouping set
1266 * until we have this representation.
1267 */
1268 if (parse->groupingSets)
1269 {
1270 parse->groupingSets =
1271 expand_grouping_sets(parse->groupingSets, parse->groupDistinct, -1);
1272 }
1273
1274 /*
1275 * In some cases we may want to transfer a HAVING clause into WHERE. We
1276 * cannot do so if the HAVING clause contains aggregates (obviously) or
1277 * volatile functions (since a HAVING clause is supposed to be executed
1278 * only once per group). We also can't do this if there are any grouping
1279 * sets and the clause references any columns that are nullable by the
1280 * grouping sets; the nulled values of those columns are not available
1281 * before the grouping step. (The test on groupClause might seem wrong,
1282 * but it's okay: it's just an optimization to avoid running pull_varnos
1283 * when there cannot be any Vars in the HAVING clause.)
1284 *
1285 * We also cannot do this for HAVING clauses that conflict with GROUP BY
1286 * on collation or operator family. Both kinds of conflict are detected
1287 * before flatten_group_exprs (see find_having_conflicts above) and
1288 * recorded in the havingPushdownConflicts bitmapset. The bitmapset
1289 * indexes remain valid here because flatten_group_exprs uses
1290 * expression_tree_mutator, which preserves the list length and ordering
1291 * of havingQual.
1292 *
1293 * Also, it may be that the clause is so expensive to execute that we're
1294 * better off doing it only once per group, despite the loss of
1295 * selectivity. This is hard to estimate short of doing the entire
1296 * planning process twice, so we use a heuristic: clauses containing
1297 * subplans are left in HAVING. Otherwise, we move or copy the HAVING
1298 * clause into WHERE, in hopes of eliminating tuples before aggregation
1299 * instead of after.
1300 *
1301 * If the query has no empty grouping set then we can simply move such a
1302 * clause into WHERE; any group that fails the clause will not be in the
1303 * output because none of its tuples will reach the grouping or
1304 * aggregation stage. Otherwise we have to keep the clause in HAVING to
1305 * ensure that we don't emit a bogus aggregated row. But then the HAVING
1306 * clause must be degenerate (variable-free), so we can copy it into WHERE
1307 * so that query_planner() can use it in a gating Result node. (This could
1308 * be done better, but it seems not worth optimizing.)
1309 *
1310 * Note that a HAVING clause may contain expressions that are not fully
1311 * preprocessed. This can happen if these expressions are part of
1312 * grouping items. In such cases, they are replaced with GROUP Vars in
1313 * the parser and then replaced back after we're done with expression
1314 * preprocessing on havingQual. This is not an issue if the clause
1315 * remains in HAVING, because these expressions will be matched to lower
1316 * target items in setrefs.c. However, if the clause is moved or copied
1317 * into WHERE, we need to ensure that these expressions are fully
1318 * preprocessed.
1319 *
1320 * Note that both havingQual and parse->jointree->quals are in
1321 * implicitly-ANDed-list form at this point, even though they are declared
1322 * as Node *.
1323 */
1324 newHaving = NIL;
1325 havingIdx = 0;
1326 foreach(l, (List *) parse->havingQual)
1327 {
1328 Node *havingclause = (Node *) lfirst(l);
1329
1334 (parse->groupClause && parse->groupingSets &&
1335 bms_is_member(root->group_rtindex, pull_varnos(root, havingclause))))
1336 {
1337 /* keep it in HAVING */
1339 }
1340 else if (parse->groupClause &&
1341 (parse->groupingSets == NIL ||
1342 (List *) linitial(parse->groupingSets) != NIL))
1343 {
1344 /* There is GROUP BY, but no empty grouping set */
1346
1347 /* Preprocess the HAVING clause fully */
1350 /* ... and move it to WHERE */
1351 parse->jointree->quals = (Node *)
1352 list_concat((List *) parse->jointree->quals,
1353 (List *) whereclause);
1354 }
1355 else
1356 {
1357 /* There is an empty grouping set (perhaps implicitly) */
1359
1360 /* Preprocess the HAVING clause fully */
1363 /* ... and put a copy in WHERE */
1364 parse->jointree->quals = (Node *)
1365 list_concat((List *) parse->jointree->quals,
1366 (List *) whereclause);
1367 /* ... and also keep it in HAVING */
1369 }
1370
1371 havingIdx++;
1372 }
1373 parse->havingQual = (Node *) newHaving;
1374
1375 /*
1376 * If we have any outer joins, try to reduce them to plain inner joins.
1377 * This step is most easily done after we've done expression
1378 * preprocessing.
1379 */
1380 if (hasOuterJoins)
1382
1383 /*
1384 * If we have any RTE_RESULT relations, see if they can be deleted from
1385 * the jointree. We also rely on this processing to flatten single-child
1386 * FromExprs underneath outer joins. This step is most effectively done
1387 * after we've done expression preprocessing and outer join reduction.
1388 */
1391
1392 /*
1393 * Do the main planning.
1394 */
1395 grouping_planner(root, tuple_fraction, setops);
1396
1397 /*
1398 * Capture the set of outer-level param IDs we have access to, for use in
1399 * extParam/allParam calculations later.
1400 */
1402
1403 /*
1404 * If any initPlans were created in this query level, adjust the surviving
1405 * Paths' costs and parallel-safety flags to account for them. The
1406 * initPlans won't actually get attached to the plan tree till
1407 * create_plan() runs, but we must include their effects now.
1408 */
1411
1412 /*
1413 * Make sure we've identified the cheapest Path for the final rel. (By
1414 * doing this here not in grouping_planner, we include initPlan costs in
1415 * the decision, though it's unlikely that will change anything.)
1416 */
1418
1419 return root;
1420}
@ ACLCHECK_NO_PRIV
Definition acl.h:185
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition aclchk.c:2672
Bitmapset * bms_make_singleton(int x)
Definition bitmapset.c:217
bool bms_is_member(int x, const Bitmapset *a)
Definition bitmapset.c:645
#define Max(x, y)
Definition c.h:1144
bool contain_agg_clause(Node *clause)
Definition clauses.c:210
bool contain_subplans(Node *clause)
Definition clauses.c:359
bool contain_volatile_functions(Node *clause)
Definition clauses.c:567
int errcode(int sqlerrcode)
Definition elog.c:875
#define ereport(elevel,...)
Definition elog.h:152
bool ExecCheckOneRelPerms(RTEPermissionInfo *perminfo)
Definition execMain.c:657
List * list_concat(List *list1, const List *list2)
Definition list.c:561
char * get_rel_name(Oid relid)
Definition lsyscache.c:2242
char get_attgenerated(Oid relid, AttrNumber attnum)
Definition lsyscache.c:1114
MemoryContext CurrentMemoryContext
Definition mcxt.c:161
bool expression_returns_set(Node *clause)
Definition nodeFuncs.c:768
#define copyObject(obj)
Definition nodes.h:230
#define IS_OUTER_JOIN(jointype)
Definition nodes.h:346
static char * errmsg
int assign_special_exec_param(PlannerInfo *root)
List * expand_grouping_sets(List *groupingSets, bool groupDistinct, int limit)
Definition parse_agg.c:2019
RTEPermissionInfo * getRTEPermissionInfo(List *rteperminfos, RangeTblEntry *rte)
@ RTE_JOIN
@ RTE_VALUES
@ RTE_SUBQUERY
@ RTE_RESULT
@ RTE_FUNCTION
@ RTE_TABLEFUNC
@ RTE_GROUP
@ OBJECT_VIEW
#define rt_fetch(rangetable_index, rangetable)
Definition parsetree.h:31
#define list_make1(x1)
Definition pg_list.h:244
#define linitial(l)
Definition pg_list.h:178
static int list_cell_number(const List *l, const ListCell *c)
Definition pg_list.h:365
#define EXPRKIND_TABLEFUNC_LATERAL
Definition planner.c:99
#define EXPRKIND_TARGET
Definition planner.c:88
#define EXPRKIND_APPINFO
Definition planner.c:94
static void preprocess_rowmarks(PlannerInfo *root)
Definition planner.c:2669
#define EXPRKIND_TABLESAMPLE
Definition planner.c:96
#define EXPRKIND_GROUPEXPR
Definition planner.c:100
static Bitmapset * find_having_conflicts(Query *parse, Index group_rtindex)
Definition planner.c:1587
static void preprocess_qual_conditions(PlannerInfo *root, Node *jtnode)
Definition planner.c:1531
#define EXPRKIND_RTFUNC_LATERAL
Definition planner.c:90
#define EXPRKIND_VALUES_LATERAL
Definition planner.c:92
#define EXPRKIND_LIMIT
Definition planner.c:93
#define EXPRKIND_VALUES
Definition planner.c:91
#define EXPRKIND_QUAL
Definition planner.c:87
static void grouping_planner(PlannerInfo *root, double tuple_fraction, SetOperationStmt *setops)
Definition planner.c:1704
#define EXPRKIND_TABLEFUNC
Definition planner.c:98
#define EXPRKIND_RTFUNC
Definition planner.c:89
#define EXPRKIND_ARBITER_ELEM
Definition planner.c:97
void preprocess_function_rtes(PlannerInfo *root)
void flatten_simple_union_all(PlannerInfo *root)
void transform_MERGE_to_join(Query *parse)
void remove_useless_result_rtes(PlannerInfo *root)
void pull_up_sublinks(PlannerInfo *root)
void replace_empty_jointree(Query *parse)
void pull_up_subqueries(PlannerInfo *root)
Query * preprocess_relation_rtes(PlannerInfo *root)
void reduce_outer_joins(PlannerInfo *root)
AttrNumber varattno
Definition primnodes.h:275
Node * startOffset
Node * endOffset
void SS_process_ctes(PlannerInfo *root)
Definition subselect.c:886
void SS_identify_outer_params(PlannerInfo *root)
Definition subselect.c:2367
void SS_charge_for_initplans(PlannerInfo *root, RelOptInfo *final_rel)
Definition subselect.c:2431
Node * flatten_group_exprs(PlannerInfo *root, Query *query, Node *node)
Definition var.c:999
Relids pull_varnos(PlannerInfo *root, Node *node)
Definition var.c:114
Node * flatten_join_alias_vars(PlannerInfo *root, Query *query, Node *node)
Definition var.c:781

References aclcheck_error(), ACLCHECK_NO_PRIV, Assert, assign_special_exec_param(), bms_is_member(), bms_make_singleton(), contain_agg_clause(), contain_subplans(), contain_volatile_functions(), copyObject, CurrentMemoryContext, WindowClause::endOffset, ereport, errcode(), errmsg, ERROR, ExecCheckOneRelPerms(), expand_grouping_sets(), expression_returns_set(), EXPRKIND_APPINFO, EXPRKIND_ARBITER_ELEM, EXPRKIND_GROUPEXPR, EXPRKIND_LIMIT, EXPRKIND_QUAL, EXPRKIND_RTFUNC, EXPRKIND_RTFUNC_LATERAL, EXPRKIND_TABLEFUNC, EXPRKIND_TABLEFUNC_LATERAL, EXPRKIND_TABLESAMPLE, EXPRKIND_TARGET, EXPRKIND_VALUES, EXPRKIND_VALUES_LATERAL, fb(), fetch_upper_rel(), find_having_conflicts(), flatten_group_exprs(), flatten_join_alias_vars(), flatten_simple_union_all(), get_attgenerated(), get_rel_name(), getRTEPermissionInfo(), grouping_planner(), IS_OUTER_JOIN, lappend(), lfirst, lfirst_node, linitial, list_cell_number(), list_concat(), list_length(), list_make1, makeNode, Max, NIL, OBJECT_VIEW, parse(), preprocess_expression(), preprocess_function_rtes(), preprocess_qual_conditions(), preprocess_relation_rtes(), preprocess_rowmarks(), pull_up_sublinks(), pull_up_subqueries(), pull_varnos(), ForPortionOfExpr::range_name, ForPortionOfExpr::rangeVar, reduce_outer_joins(), remove_useless_result_rtes(), replace_empty_jointree(), result, root, rt_fetch, RTE_FUNCTION, RTE_GROUP, RTE_JOIN, RTE_RELATION, RTE_RESULT, RTE_SUBQUERY, RTE_TABLEFUNC, RTE_VALUES, set_cheapest(), SS_charge_for_initplans(), SS_identify_outer_params(), SS_process_ctes(), WindowClause::startOffset, transform_MERGE_to_join(), UPPERREL_FINAL, and Var::varattno.

Referenced by make_subplan(), recurse_set_operations(), set_subquery_pathlist(), SS_process_ctes(), and standard_planner().

Variable Documentation

◆ create_upper_paths_hook

◆ planner_hook

PGDLLIMPORT planner_hook_type planner_hook
extern

Definition at line 74 of file planner.c.

Referenced by _PG_init(), and planner().

◆ planner_setup_hook

PGDLLIMPORT planner_setup_hook_type planner_setup_hook
extern

Definition at line 77 of file planner.c.

Referenced by pgpa_planner_install_hooks(), and standard_planner().

◆ planner_shutdown_hook

PGDLLIMPORT planner_shutdown_hook_type planner_shutdown_hook
extern

Definition at line 80 of file planner.c.

Referenced by pgpa_planner_install_hooks(), and standard_planner().