PostgreSQL Source Code  git master
planmain.h File Reference
#include "nodes/plannodes.h"
#include "nodes/relation.h"
Include dependency graph for planmain.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define DEFAULT_CURSOR_TUPLE_FRACTION   0.1
 

Typedefs

typedef void(* query_pathkeys_callback) (PlannerInfo *root, void *extra)
 

Enumerations

enum  ForceParallelMode { FORCE_PARALLEL_OFF, FORCE_PARALLEL_ON, FORCE_PARALLEL_REGRESS }
 

Functions

RelOptInfoquery_planner (PlannerInfo *root, List *tlist, query_pathkeys_callback qp_callback, void *qp_extra)
 
void preprocess_minmax_aggregates (PlannerInfo *root, List *tlist)
 
Plancreate_plan (PlannerInfo *root, Path *best_path)
 
ForeignScanmake_foreignscan (List *qptlist, List *qpqual, Index scanrelid, List *fdw_exprs, List *fdw_private, List *fdw_scan_tlist, List *fdw_recheck_quals, Plan *outer_plan)
 
Planmaterialize_finished_plan (Plan *subplan)
 
bool is_projection_capable_path (Path *path)
 
bool is_projection_capable_plan (Plan *plan)
 
Sortmake_sort_from_sortclauses (List *sortcls, Plan *lefttree)
 
Aggmake_agg (List *tlist, List *qual, AggStrategy aggstrategy, AggSplit aggsplit, int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators, List *groupingSets, List *chain, double dNumGroups, Plan *lefttree)
 
Limitmake_limit (Plan *lefttree, Node *limitOffset, Node *limitCount)
 
void add_base_rels_to_query (PlannerInfo *root, Node *jtnode)
 
void build_base_rel_tlists (PlannerInfo *root, List *final_tlist)
 
void add_vars_to_targetlist (PlannerInfo *root, List *vars, Relids where_needed, bool create_new_ph)
 
void find_lateral_references (PlannerInfo *root)
 
void create_lateral_join_info (PlannerInfo *root)
 
Listdeconstruct_jointree (PlannerInfo *root)
 
void distribute_restrictinfo_to_rels (PlannerInfo *root, RestrictInfo *restrictinfo)
 
void process_implied_equality (PlannerInfo *root, Oid opno, Oid collation, Expr *item1, Expr *item2, Relids qualscope, Relids nullable_relids, Index security_level, bool below_outer_join, bool both_const)
 
RestrictInfobuild_implied_join_equality (Oid opno, Oid collation, Expr *item1, Expr *item2, Relids qualscope, Relids nullable_relids, Index security_level)
 
void match_foreign_keys_to_quals (PlannerInfo *root)
 
Listremove_useless_joins (PlannerInfo *root, List *joinlist)
 
void reduce_unique_semijoins (PlannerInfo *root)
 
bool query_supports_distinctness (Query *query)
 
bool query_is_distinct_for (Query *query, List *colnos, List *opids)
 
bool innerrel_is_unique (PlannerInfo *root, Relids outerrelids, RelOptInfo *innerrel, JoinType jointype, List *restrictlist, bool force_cache)
 
Planset_plan_references (PlannerInfo *root, Plan *plan)
 
void record_plan_function_dependency (PlannerInfo *root, Oid funcid)
 
void extract_query_dependencies (Node *query, List **relationOids, List **invalItems, bool *hasRowSecurity)
 

Variables

double cursor_tuple_fraction
 
int force_parallel_mode
 
bool parallel_leader_participation
 
int from_collapse_limit
 
int join_collapse_limit
 

Macro Definition Documentation

◆ DEFAULT_CURSOR_TUPLE_FRACTION

#define DEFAULT_CURSOR_TUPLE_FRACTION   0.1

Definition at line 29 of file planmain.h.

Typedef Documentation

◆ query_pathkeys_callback

typedef void(* query_pathkeys_callback) (PlannerInfo *root, void *extra)

Definition at line 35 of file planmain.h.

Enumeration Type Documentation

◆ ForceParallelMode

Enumerator
FORCE_PARALLEL_OFF 
FORCE_PARALLEL_ON 
FORCE_PARALLEL_REGRESS 

Definition at line 21 of file planmain.h.

Function Documentation

◆ add_base_rels_to_query()

void add_base_rels_to_query ( PlannerInfo root,
Node jtnode 
)

Definition at line 105 of file initsplan.c.

References add_base_rels_to_query(), build_simple_rel(), elog, ERROR, FromExpr::fromlist, IsA, JoinExpr::larg, lfirst, nodeTag, and JoinExpr::rarg.

Referenced by add_base_rels_to_query(), and query_planner().

106 {
107  if (jtnode == NULL)
108  return;
109  if (IsA(jtnode, RangeTblRef))
110  {
111  int varno = ((RangeTblRef *) jtnode)->rtindex;
112 
113  (void) build_simple_rel(root, varno, NULL);
114  }
115  else if (IsA(jtnode, FromExpr))
116  {
117  FromExpr *f = (FromExpr *) jtnode;
118  ListCell *l;
119 
120  foreach(l, f->fromlist)
121  add_base_rels_to_query(root, lfirst(l));
122  }
123  else if (IsA(jtnode, JoinExpr))
124  {
125  JoinExpr *j = (JoinExpr *) jtnode;
126 
127  add_base_rels_to_query(root, j->larg);
128  add_base_rels_to_query(root, j->rarg);
129  }
130  else
131  elog(ERROR, "unrecognized node type: %d",
132  (int) nodeTag(jtnode));
133 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:563
void add_base_rels_to_query(PlannerInfo *root, Node *jtnode)
Definition: initsplan.c:105
List * fromlist
Definition: primnodes.h:1478
Node * larg
Definition: primnodes.h:1458
#define ERROR
Definition: elog.h:43
RelOptInfo * build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
Definition: relnode.c:96
Node * rarg
Definition: primnodes.h:1459
#define lfirst(lc)
Definition: pg_list.h:106
#define nodeTag(nodeptr)
Definition: nodes.h:517
#define elog
Definition: elog.h:219

◆ add_vars_to_targetlist()

void add_vars_to_targetlist ( PlannerInfo root,
List vars,
Relids  where_needed,
bool  create_new_ph 
)

Definition at line 198 of file initsplan.c.

References Assert, RelOptInfo::attr_needed, bms_add_members(), bms_is_empty(), bms_is_subset(), copyObject, elog, ERROR, PathTarget::exprs, find_base_rel(), find_placeholder_info(), IsA, lappend(), lfirst, RelOptInfo::min_attr, nodeTag, PlaceHolderInfo::ph_needed, RelOptInfo::relids, RelOptInfo::reltarget, Var::varattno, and Var::varno.

Referenced by build_base_rel_tlists(), distribute_qual_to_rels(), extract_lateral_references(), fix_placeholder_input_needed_levels(), and generate_base_implied_equalities_no_const().

200 {
201  ListCell *temp;
202 
203  Assert(!bms_is_empty(where_needed));
204 
205  foreach(temp, vars)
206  {
207  Node *node = (Node *) lfirst(temp);
208 
209  if (IsA(node, Var))
210  {
211  Var *var = (Var *) node;
212  RelOptInfo *rel = find_base_rel(root, var->varno);
213  int attno = var->varattno;
214 
215  if (bms_is_subset(where_needed, rel->relids))
216  continue;
217  Assert(attno >= rel->min_attr && attno <= rel->max_attr);
218  attno -= rel->min_attr;
219  if (rel->attr_needed[attno] == NULL)
220  {
221  /* Variable not yet requested, so add to rel's targetlist */
222  /* XXX is copyObject necessary here? */
223  rel->reltarget->exprs = lappend(rel->reltarget->exprs,
224  copyObject(var));
225  /* reltarget cost and width will be computed later */
226  }
227  rel->attr_needed[attno] = bms_add_members(rel->attr_needed[attno],
228  where_needed);
229  }
230  else if (IsA(node, PlaceHolderVar))
231  {
232  PlaceHolderVar *phv = (PlaceHolderVar *) node;
233  PlaceHolderInfo *phinfo = find_placeholder_info(root, phv,
234  create_new_ph);
235 
236  phinfo->ph_needed = bms_add_members(phinfo->ph_needed,
237  where_needed);
238  }
239  else
240  elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
241  }
242 }
Relids ph_needed
Definition: relation.h:2162
#define IsA(nodeptr, _type_)
Definition: nodes.h:563
Relids * attr_needed
Definition: relation.h:618
Definition: nodes.h:512
AttrNumber varattno
Definition: primnodes.h:168
Definition: primnodes.h:163
#define ERROR
Definition: elog.h:43
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:308
PlaceHolderInfo * find_placeholder_info(PlannerInfo *root, PlaceHolderVar *phv, bool create_new_ph)
Definition: placeholder.c:70
Relids relids
Definition: relation.h:585
List * lappend(List *list, void *datum)
Definition: list.c:128
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:663
Index varno
Definition: primnodes.h:166
List * exprs
Definition: relation.h:972
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
#define nodeTag(nodeptr)
Definition: nodes.h:517
#define elog
Definition: elog.h:219
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition: relnode.c:277
#define copyObject(obj)
Definition: nodes.h:625
struct PathTarget * reltarget
Definition: relation.h:596
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:755
AttrNumber min_attr
Definition: relation.h:616

◆ build_base_rel_tlists()

void build_base_rel_tlists ( PlannerInfo root,
List final_tlist 
)

Definition at line 151 of file initsplan.c.

References add_vars_to_targetlist(), bms_make_singleton(), Query::havingQual, list_free(), NIL, PlannerInfo::parse, pull_var_clause(), PVC_INCLUDE_PLACEHOLDERS, PVC_RECURSE_AGGREGATES, and PVC_RECURSE_WINDOWFUNCS.

Referenced by query_planner().

152 {
153  List *tlist_vars = pull_var_clause((Node *) final_tlist,
157 
158  if (tlist_vars != NIL)
159  {
160  add_vars_to_targetlist(root, tlist_vars, bms_make_singleton(0), true);
161  list_free(tlist_vars);
162  }
163 
164  /*
165  * If there's a HAVING clause, we'll need the Vars it uses, too. Note
166  * that HAVING can contain Aggrefs but not WindowFuncs.
167  */
168  if (root->parse->havingQual)
169  {
170  List *having_vars = pull_var_clause(root->parse->havingQual,
173 
174  if (having_vars != NIL)
175  {
176  add_vars_to_targetlist(root, having_vars,
177  bms_make_singleton(0), true);
178  list_free(having_vars);
179  }
180  }
181 }
#define NIL
Definition: pg_list.h:69
Query * parse
Definition: relation.h:155
#define PVC_RECURSE_AGGREGATES
Definition: var.h:21
Definition: nodes.h:512
List * pull_var_clause(Node *node, int flags)
Definition: var.c:535
void add_vars_to_targetlist(PlannerInfo *root, List *vars, Relids where_needed, bool create_new_ph)
Definition: initsplan.c:198
#define PVC_INCLUDE_PLACEHOLDERS
Definition: var.h:24
Bitmapset * bms_make_singleton(int x)
Definition: bitmapset.c:179
#define PVC_RECURSE_WINDOWFUNCS
Definition: var.h:23
void list_free(List *list)
Definition: list.c:1133
Node * havingQual
Definition: parsenodes.h:150
Definition: pg_list.h:45

◆ build_implied_join_equality()

RestrictInfo* build_implied_join_equality ( Oid  opno,
Oid  collation,
Expr item1,
Expr item2,
Relids  qualscope,
Relids  nullable_relids,
Index  security_level 
)

Definition at line 2376 of file initsplan.c.

References BOOLOID, check_hashjoinable(), check_mergejoinable(), copyObject, InvalidOid, make_opclause(), and make_restrictinfo().

Referenced by create_join_clause(), reconsider_full_join_clause(), and reconsider_outer_join_clause().

2383 {
2384  RestrictInfo *restrictinfo;
2385  Expr *clause;
2386 
2387  /*
2388  * Build the new clause. Copy to ensure it shares no substructure with
2389  * original (this is necessary in case there are subselects in there...)
2390  */
2391  clause = make_opclause(opno,
2392  BOOLOID, /* opresulttype */
2393  false, /* opretset */
2394  copyObject(item1),
2395  copyObject(item2),
2396  InvalidOid,
2397  collation);
2398 
2399  /*
2400  * Build the RestrictInfo node itself.
2401  */
2402  restrictinfo = make_restrictinfo(clause,
2403  true, /* is_pushed_down */
2404  false, /* outerjoin_delayed */
2405  false, /* pseudoconstant */
2406  security_level, /* security_level */
2407  qualscope, /* required_relids */
2408  NULL, /* outer_relids */
2409  nullable_relids); /* nullable_relids */
2410 
2411  /* Set mergejoinability/hashjoinability flags */
2412  check_mergejoinable(restrictinfo);
2413  check_hashjoinable(restrictinfo);
2414 
2415  return restrictinfo;
2416 }
RestrictInfo * make_restrictinfo(Expr *clause, bool is_pushed_down, bool outerjoin_delayed, bool pseudoconstant, Index security_level, Relids required_relids, Relids outer_relids, Relids nullable_relids)
Definition: restrictinfo.c:57
Expr * make_opclause(Oid opno, Oid opresulttype, bool opretset, Expr *leftop, Expr *rightop, Oid opcollid, Oid inputcollid)
Definition: clauses.c:172
#define InvalidOid
Definition: postgres_ext.h:36
static void check_mergejoinable(RestrictInfo *restrictinfo)
Definition: initsplan.c:2603
#define BOOLOID
Definition: pg_type.h:288
static void check_hashjoinable(RestrictInfo *restrictinfo)
Definition: initsplan.c:2640
#define copyObject(obj)
Definition: nodes.h:625

◆ create_lateral_join_info()

void create_lateral_join_info ( PlannerInfo root)

Definition at line 418 of file initsplan.c.

References PlannerInfo::append_rel_list, Assert, bms_add_member(), bms_add_members(), bms_copy(), bms_get_singleton_member(), bms_is_empty(), bms_is_member(), bms_next_member(), AppendRelInfo::child_relid, RelOptInfo::direct_lateral_relids, find_base_rel(), find_placeholder_info(), PlannerInfo::hasLateralRTEs, RangeTblEntry::inh, IS_SIMPLE_REL, IsA, RelOptInfo::lateral_referencers, RelOptInfo::lateral_relids, RelOptInfo::lateral_vars, lfirst, AppendRelInfo::parent_relid, PlaceHolderInfo::ph_eval_at, PlaceHolderInfo::ph_lateral, PlannerInfo::placeholder_list, RelOptInfo::relid, RangeTblEntry::relkind, RELKIND_PARTITIONED_TABLE, RELOPT_BASEREL, RELOPT_OTHER_MEMBER_REL, RelOptInfo::reloptkind, RTE_RELATION, RangeTblEntry::rtekind, PlannerInfo::simple_rel_array, PlannerInfo::simple_rel_array_size, PlannerInfo::simple_rte_array, and Var::varno.

Referenced by query_planner().

419 {
420  bool found_laterals = false;
421  Index rti;
422  ListCell *lc;
423 
424  /* We need do nothing if the query contains no LATERAL RTEs */
425  if (!root->hasLateralRTEs)
426  return;
427 
428  /*
429  * Examine all baserels (the rel array has been set up by now).
430  */
431  for (rti = 1; rti < root->simple_rel_array_size; rti++)
432  {
433  RelOptInfo *brel = root->simple_rel_array[rti];
434  Relids lateral_relids;
435 
436  /* there may be empty slots corresponding to non-baserel RTEs */
437  if (brel == NULL)
438  continue;
439 
440  Assert(brel->relid == rti); /* sanity check on array */
441 
442  /* ignore RTEs that are "other rels" */
443  if (brel->reloptkind != RELOPT_BASEREL)
444  continue;
445 
446  lateral_relids = NULL;
447 
448  /* consider each laterally-referenced Var or PHV */
449  foreach(lc, brel->lateral_vars)
450  {
451  Node *node = (Node *) lfirst(lc);
452 
453  if (IsA(node, Var))
454  {
455  Var *var = (Var *) node;
456 
457  found_laterals = true;
458  lateral_relids = bms_add_member(lateral_relids,
459  var->varno);
460  }
461  else if (IsA(node, PlaceHolderVar))
462  {
463  PlaceHolderVar *phv = (PlaceHolderVar *) node;
464  PlaceHolderInfo *phinfo = find_placeholder_info(root, phv,
465  false);
466 
467  found_laterals = true;
468  lateral_relids = bms_add_members(lateral_relids,
469  phinfo->ph_eval_at);
470  }
471  else
472  Assert(false);
473  }
474 
475  /* We now have all the simple lateral refs from this rel */
476  brel->direct_lateral_relids = lateral_relids;
477  brel->lateral_relids = bms_copy(lateral_relids);
478  }
479 
480  /*
481  * Now check for lateral references within PlaceHolderVars, and mark their
482  * eval_at rels as having lateral references to the source rels.
483  *
484  * For a PHV that is due to be evaluated at a baserel, mark its source(s)
485  * as direct lateral dependencies of the baserel (adding onto the ones
486  * recorded above). If it's due to be evaluated at a join, mark its
487  * source(s) as indirect lateral dependencies of each baserel in the join,
488  * ie put them into lateral_relids but not direct_lateral_relids. This is
489  * appropriate because we can't put any such baserel on the outside of a
490  * join to one of the PHV's lateral dependencies, but on the other hand we
491  * also can't yet join it directly to the dependency.
492  */
493  foreach(lc, root->placeholder_list)
494  {
495  PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(lc);
496  Relids eval_at = phinfo->ph_eval_at;
497  int varno;
498 
499  if (phinfo->ph_lateral == NULL)
500  continue; /* PHV is uninteresting if no lateral refs */
501 
502  found_laterals = true;
503 
504  if (bms_get_singleton_member(eval_at, &varno))
505  {
506  /* Evaluation site is a baserel */
507  RelOptInfo *brel = find_base_rel(root, varno);
508 
509  brel->direct_lateral_relids =
511  phinfo->ph_lateral);
512  brel->lateral_relids =
514  phinfo->ph_lateral);
515  }
516  else
517  {
518  /* Evaluation site is a join */
519  varno = -1;
520  while ((varno = bms_next_member(eval_at, varno)) >= 0)
521  {
522  RelOptInfo *brel = find_base_rel(root, varno);
523 
525  phinfo->ph_lateral);
526  }
527  }
528  }
529 
530  /*
531  * If we found no actual lateral references, we're done; but reset the
532  * hasLateralRTEs flag to avoid useless work later.
533  */
534  if (!found_laterals)
535  {
536  root->hasLateralRTEs = false;
537  return;
538  }
539 
540  /*
541  * Calculate the transitive closure of the lateral_relids sets, so that
542  * they describe both direct and indirect lateral references. If relation
543  * X references Y laterally, and Y references Z laterally, then we will
544  * have to scan X on the inside of a nestloop with Z, so for all intents
545  * and purposes X is laterally dependent on Z too.
546  *
547  * This code is essentially Warshall's algorithm for transitive closure.
548  * The outer loop considers each baserel, and propagates its lateral
549  * dependencies to those baserels that have a lateral dependency on it.
550  */
551  for (rti = 1; rti < root->simple_rel_array_size; rti++)
552  {
553  RelOptInfo *brel = root->simple_rel_array[rti];
554  Relids outer_lateral_relids;
555  Index rti2;
556 
557  if (brel == NULL || brel->reloptkind != RELOPT_BASEREL)
558  continue;
559 
560  /* need not consider baserel further if it has no lateral refs */
561  outer_lateral_relids = brel->lateral_relids;
562  if (outer_lateral_relids == NULL)
563  continue;
564 
565  /* else scan all baserels */
566  for (rti2 = 1; rti2 < root->simple_rel_array_size; rti2++)
567  {
568  RelOptInfo *brel2 = root->simple_rel_array[rti2];
569 
570  if (brel2 == NULL || brel2->reloptkind != RELOPT_BASEREL)
571  continue;
572 
573  /* if brel2 has lateral ref to brel, propagate brel's refs */
574  if (bms_is_member(rti, brel2->lateral_relids))
576  outer_lateral_relids);
577  }
578  }
579 
580  /*
581  * Now that we've identified all lateral references, mark each baserel
582  * with the set of relids of rels that reference it laterally (possibly
583  * indirectly) --- that is, the inverse mapping of lateral_relids.
584  */
585  for (rti = 1; rti < root->simple_rel_array_size; rti++)
586  {
587  RelOptInfo *brel = root->simple_rel_array[rti];
588  Relids lateral_relids;
589  int rti2;
590 
591  if (brel == NULL || brel->reloptkind != RELOPT_BASEREL)
592  continue;
593 
594  /* Nothing to do at rels with no lateral refs */
595  lateral_relids = brel->lateral_relids;
596  if (lateral_relids == NULL)
597  continue;
598 
599  /*
600  * We should not have broken the invariant that lateral_relids is
601  * exactly NULL if empty.
602  */
603  Assert(!bms_is_empty(lateral_relids));
604 
605  /* Also, no rel should have a lateral dependency on itself */
606  Assert(!bms_is_member(rti, lateral_relids));
607 
608  /* Mark this rel's referencees */
609  rti2 = -1;
610  while ((rti2 = bms_next_member(lateral_relids, rti2)) >= 0)
611  {
612  RelOptInfo *brel2 = root->simple_rel_array[rti2];
613 
614  Assert(brel2 != NULL && brel2->reloptkind == RELOPT_BASEREL);
615  brel2->lateral_referencers =
616  bms_add_member(brel2->lateral_referencers, rti);
617  }
618  }
619 
620  /*
621  * Lastly, propagate lateral_relids and lateral_referencers from appendrel
622  * parent rels to their child rels. We intentionally give each child rel
623  * the same minimum parameterization, even though it's quite possible that
624  * some don't reference all the lateral rels. This is because any append
625  * path for the parent will have to have the same parameterization for
626  * every child anyway, and there's no value in forcing extra
627  * reparameterize_path() calls. Similarly, a lateral reference to the
628  * parent prevents use of otherwise-movable join rels for each child.
629  */
630  for (rti = 1; rti < root->simple_rel_array_size; rti++)
631  {
632  RelOptInfo *brel = root->simple_rel_array[rti];
633  RangeTblEntry *brte = root->simple_rte_array[rti];
634 
635  /*
636  * Skip empty slots. Also skip non-simple relations i.e. dead
637  * relations.
638  */
639  if (brel == NULL || !IS_SIMPLE_REL(brel))
640  continue;
641 
642  /*
643  * In the case of table inheritance, the parent RTE is directly linked
644  * to every child table via an AppendRelInfo. In the case of table
645  * partitioning, the inheritance hierarchy is expanded one level at a
646  * time rather than flattened. Therefore, an other member rel that is
647  * a partitioned table may have children of its own, and must
648  * therefore be marked with the appropriate lateral info so that those
649  * children eventually get marked also.
650  */
651  Assert(brte);
652  if (brel->reloptkind == RELOPT_OTHER_MEMBER_REL &&
653  (brte->rtekind != RTE_RELATION ||
655  continue;
656 
657  if (brte->inh)
658  {
659  foreach(lc, root->append_rel_list)
660  {
661  AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(lc);
662  RelOptInfo *childrel;
663 
664  if (appinfo->parent_relid != rti)
665  continue;
666  childrel = root->simple_rel_array[appinfo->child_relid];
668  Assert(childrel->direct_lateral_relids == NULL);
670  Assert(childrel->lateral_relids == NULL);
671  childrel->lateral_relids = brel->lateral_relids;
672  Assert(childrel->lateral_referencers == NULL);
673  childrel->lateral_referencers = brel->lateral_referencers;
674  }
675  }
676  }
677 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:563
Bitmapset * bms_copy(const Bitmapset *a)
Definition: bitmapset.c:111
Relids ph_eval_at
Definition: relation.h:2160
RelOptKind reloptkind
Definition: relation.h:582
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1009
Definition: nodes.h:512
bool bms_get_singleton_member(const Bitmapset *a, int *member)
Definition: bitmapset.c:569
Definition: primnodes.h:163
#define IS_SIMPLE_REL(rel)
Definition: relation.h:561
struct RelOptInfo ** simple_rel_array
Definition: relation.h:179
Relids lateral_relids
Definition: relation.h:610
bool hasLateralRTEs
Definition: relation.h:303
PlaceHolderInfo * find_placeholder_info(PlannerInfo *root, PlaceHolderVar *phv, bool create_new_ph)
Definition: placeholder.c:70
int simple_rel_array_size
Definition: relation.h:180
Index relid
Definition: relation.h:613
RangeTblEntry ** simple_rte_array
Definition: relation.h:188
Relids lateral_referencers
Definition: relation.h:621
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:663
Index varno
Definition: primnodes.h:166
Relids direct_lateral_relids
Definition: relation.h:609
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
List * append_rel_list
Definition: relation.h:252
Relids ph_lateral
Definition: relation.h:2161
unsigned int Index
Definition: c.h:413
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
List * lateral_vars
Definition: relation.h:620
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:698
RTEKind rtekind
Definition: parsenodes.h:951
List * placeholder_list
Definition: relation.h:258
Index child_relid
Definition: relation.h:2072
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition: relnode.c:277
Index parent_relid
Definition: relation.h:2071
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:420
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:755

◆ create_plan()

Plan* create_plan ( PlannerInfo root,
Path best_path 
)

Definition at line 305 of file createplan.c.

References apply_tlist_labeling(), Assert, CP_EXACT_TLIST, create_plan_recurse(), PlannerInfo::curOuterParams, PlannerInfo::curOuterRels, elog, ERROR, IsA, NIL, PlannerInfo::plan_params, PlannerInfo::processed_tlist, SS_attach_initplans(), and Plan::targetlist.

Referenced by create_minmaxagg_plan(), create_subqueryscan_plan(), make_subplan(), SS_process_ctes(), and standard_planner().

306 {
307  Plan *plan;
308 
309  /* plan_params should not be in use in current query level */
310  Assert(root->plan_params == NIL);
311 
312  /* Initialize this module's private workspace in PlannerInfo */
313  root->curOuterRels = NULL;
314  root->curOuterParams = NIL;
315 
316  /* Recursively process the path tree, demanding the correct tlist result */
317  plan = create_plan_recurse(root, best_path, CP_EXACT_TLIST);
318 
319  /*
320  * Make sure the topmost plan node's targetlist exposes the original
321  * column names and other decorative info. Targetlists generated within
322  * the planner don't bother with that stuff, but we must have it on the
323  * top-level tlist seen at execution time. However, ModifyTable plan
324  * nodes don't have a tlist matching the querytree targetlist.
325  */
326  if (!IsA(plan, ModifyTable))
328 
329  /*
330  * Attach any initPlans created in this query level to the topmost plan
331  * node. (In principle the initplans could go in any plan node at or
332  * above where they're referenced, but there seems no reason to put them
333  * any lower than the topmost node for the query level. Also, see
334  * comments for SS_finalize_plan before you try to change this.)
335  */
336  SS_attach_initplans(root, plan);
337 
338  /* Check we successfully assigned all NestLoopParams to plan nodes */
339  if (root->curOuterParams != NIL)
340  elog(ERROR, "failed to assign all NestLoopParams to plan nodes");
341 
342  /*
343  * Reset plan_params to ensure param IDs used for nestloop params are not
344  * re-used later
345  */
346  root->plan_params = NIL;
347 
348  return plan;
349 }
#define NIL
Definition: pg_list.h:69
void apply_tlist_labeling(List *dest_tlist, List *src_tlist)
Definition: tlist.c:321
#define IsA(nodeptr, _type_)
Definition: nodes.h:563
List * plan_params
Definition: relation.h:169
Relids curOuterRels
Definition: relation.h:315
static Plan * create_plan_recurse(PlannerInfo *root, Path *best_path, int flags)
Definition: createplan.c:356
#define ERROR
Definition: elog.h:43
List * curOuterParams
Definition: relation.h:316
#define Assert(condition)
Definition: c.h:670
void SS_attach_initplans(PlannerInfo *root, Plan *plan)
Definition: subselect.c:2220
List * targetlist
Definition: plannodes.h:144
#define elog
Definition: elog.h:219
List * processed_tlist
Definition: relation.h:284
#define CP_EXACT_TLIST
Definition: createplan.c:66

◆ deconstruct_jointree()

List* deconstruct_jointree ( PlannerInfo root)

Definition at line 713 of file initsplan.c.

References Assert, deconstruct_recurse(), IsA, Query::jointree, NIL, PlannerInfo::nullable_baserels, and PlannerInfo::parse.

Referenced by query_planner().

714 {
715  List *result;
716  Relids qualscope;
717  Relids inner_join_rels;
718  List *postponed_qual_list = NIL;
719 
720  /* Start recursion at top of jointree */
721  Assert(root->parse->jointree != NULL &&
722  IsA(root->parse->jointree, FromExpr));
723 
724  /* this is filled as we scan the jointree */
725  root->nullable_baserels = NULL;
726 
727  result = deconstruct_recurse(root, (Node *) root->parse->jointree, false,
728  &qualscope, &inner_join_rels,
729  &postponed_qual_list);
730 
731  /* Shouldn't be any leftover quals */
732  Assert(postponed_qual_list == NIL);
733 
734  return result;
735 }
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:563
Query * parse
Definition: relation.h:155
FromExpr * jointree
Definition: parsenodes.h:136
Definition: nodes.h:512
#define Assert(condition)
Definition: c.h:670
static List * deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, Relids *qualscope, Relids *inner_join_rels, List **postponed_qual_list)
Definition: initsplan.c:759
Relids nullable_baserels
Definition: relation.h:204
Definition: pg_list.h:45

◆ distribute_restrictinfo_to_rels()

void distribute_restrictinfo_to_rels ( PlannerInfo root,
RestrictInfo restrictinfo 
)

Definition at line 2227 of file initsplan.c.

References add_join_clause_to_rels(), RelOptInfo::baserestrict_min_security, RelOptInfo::baserestrictinfo, bms_membership(), BMS_MULTIPLE, BMS_SINGLETON, bms_singleton_member(), check_hashjoinable(), elog, ERROR, find_base_rel(), lappend(), Min, PostponedQual::relids, RestrictInfo::required_relids, and RestrictInfo::security_level.

Referenced by distribute_qual_to_rels(), generate_base_implied_equalities_broken(), generate_base_implied_equalities_const(), reconsider_outer_join_clauses(), and remove_rel_from_query().

2229 {
2230  Relids relids = restrictinfo->required_relids;
2231  RelOptInfo *rel;
2232 
2233  switch (bms_membership(relids))
2234  {
2235  case BMS_SINGLETON:
2236 
2237  /*
2238  * There is only one relation participating in the clause, so it
2239  * is a restriction clause for that relation.
2240  */
2241  rel = find_base_rel(root, bms_singleton_member(relids));
2242 
2243  /* Add clause to rel's restriction list */
2245  restrictinfo);
2246  /* Update security level info */
2248  restrictinfo->security_level);
2249  break;
2250  case BMS_MULTIPLE:
2251 
2252  /*
2253  * The clause is a join clause, since there is more than one rel
2254  * in its relid set.
2255  */
2256 
2257  /*
2258  * Check for hashjoinable operators. (We don't bother setting the
2259  * hashjoin info except in true join clauses.)
2260  */
2261  check_hashjoinable(restrictinfo);
2262 
2263  /*
2264  * Add clause to the join lists of all the relevant relations.
2265  */
2266  add_join_clause_to_rels(root, restrictinfo, relids);
2267  break;
2268  default:
2269 
2270  /*
2271  * clause references no rels, and therefore we have no place to
2272  * attach it. Shouldn't get here if callers are working properly.
2273  */
2274  elog(ERROR, "cannot cope with variable-free clause");
2275  break;
2276  }
2277 }
Index security_level
Definition: relation.h:1853
Relids required_relids
Definition: relation.h:1859
List * baserestrictinfo
Definition: relation.h:645
#define Min(x, y)
Definition: c.h:802
Index baserestrict_min_security
Definition: relation.h:647
#define ERROR
Definition: elog.h:43
List * lappend(List *list, void *datum)
Definition: list.c:128
BMS_Membership bms_membership(const Bitmapset *a)
Definition: bitmapset.c:634
int bms_singleton_member(const Bitmapset *a)
Definition: bitmapset.c:526
void add_join_clause_to_rels(PlannerInfo *root, RestrictInfo *restrictinfo, Relids join_relids)
Definition: joininfo.c:95
static void check_hashjoinable(RestrictInfo *restrictinfo)
Definition: initsplan.c:2640
#define elog
Definition: elog.h:219
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition: relnode.c:277

◆ extract_query_dependencies()

void extract_query_dependencies ( Node query,
List **  relationOids,
List **  invalItems,
bool hasRowSecurity 
)

Definition at line 2596 of file setrefs.c.

References PlannerGlobal::dependsOnRole, extract_query_dependencies_walker(), PlannerInfo::glob, PlannerGlobal::invalItems, MemSet, NIL, PlannerGlobal::relationOids, T_PlannerGlobal, T_PlannerInfo, PlannerGlobal::type, and PlannerInfo::type.

Referenced by CompleteCachedPlan(), and RevalidateCachedQuery().

2600 {
2601  PlannerGlobal glob;
2602  PlannerInfo root;
2603 
2604  /* Make up dummy planner state so we can use this module's machinery */
2605  MemSet(&glob, 0, sizeof(glob));
2606  glob.type = T_PlannerGlobal;
2607  glob.relationOids = NIL;
2608  glob.invalItems = NIL;
2609  /* Hack: we use glob.dependsOnRole to collect hasRowSecurity flags */
2610  glob.dependsOnRole = false;
2611 
2612  MemSet(&root, 0, sizeof(root));
2613  root.type = T_PlannerInfo;
2614  root.glob = &glob;
2615 
2616  (void) extract_query_dependencies_walker(query, &root);
2617 
2618  *relationOids = glob.relationOids;
2619  *invalItems = glob.invalItems;
2620  *hasRowSecurity = glob.dependsOnRole;
2621 }
#define NIL
Definition: pg_list.h:69
#define MemSet(start, val, len)
Definition: c.h:853
bool dependsOnRole
Definition: relation.h:127
PlannerGlobal * glob
Definition: relation.h:157
List * invalItems
Definition: relation.h:115
NodeTag type
Definition: relation.h:153
static bool extract_query_dependencies_walker(Node *node, PlannerInfo *context)
Definition: setrefs.c:2624
NodeTag type
Definition: relation.h:94
List * relationOids
Definition: relation.h:113

◆ find_lateral_references()

void find_lateral_references ( PlannerInfo root)

Definition at line 272 of file initsplan.c.

References Assert, extract_lateral_references(), PlannerInfo::hasLateralRTEs, RelOptInfo::relid, RELOPT_BASEREL, RelOptInfo::reloptkind, PlannerInfo::simple_rel_array, and PlannerInfo::simple_rel_array_size.

Referenced by query_planner().

273 {
274  Index rti;
275 
276  /* We need do nothing if the query contains no LATERAL RTEs */
277  if (!root->hasLateralRTEs)
278  return;
279 
280  /*
281  * Examine all baserels (the rel array has been set up by now).
282  */
283  for (rti = 1; rti < root->simple_rel_array_size; rti++)
284  {
285  RelOptInfo *brel = root->simple_rel_array[rti];
286 
287  /* there may be empty slots corresponding to non-baserel RTEs */
288  if (brel == NULL)
289  continue;
290 
291  Assert(brel->relid == rti); /* sanity check on array */
292 
293  /*
294  * This bit is less obvious than it might look. We ignore appendrel
295  * otherrels and consider only their parent baserels. In a case where
296  * a LATERAL-containing UNION ALL subquery was pulled up, it is the
297  * otherrel that is actually going to be in the plan. However, we
298  * want to mark all its lateral references as needed by the parent,
299  * because it is the parent's relid that will be used for join
300  * planning purposes. And the parent's RTE will contain all the
301  * lateral references we need to know, since the pulled-up member is
302  * nothing but a copy of parts of the original RTE's subquery. We
303  * could visit the parent's children instead and transform their
304  * references back to the parent's relid, but it would be much more
305  * complicated for no real gain. (Important here is that the child
306  * members have not yet received any processing beyond being pulled
307  * up.) Similarly, in appendrels created by inheritance expansion,
308  * it's sufficient to look at the parent relation.
309  */
310 
311  /* ignore RTEs that are "other rels" */
312  if (brel->reloptkind != RELOPT_BASEREL)
313  continue;
314 
315  extract_lateral_references(root, brel, rti);
316  }
317 }
RelOptKind reloptkind
Definition: relation.h:582
struct RelOptInfo ** simple_rel_array
Definition: relation.h:179
bool hasLateralRTEs
Definition: relation.h:303
int simple_rel_array_size
Definition: relation.h:180
Index relid
Definition: relation.h:613
unsigned int Index
Definition: c.h:413
#define Assert(condition)
Definition: c.h:670
static void extract_lateral_references(PlannerInfo *root, RelOptInfo *brel, Index rtindex)
Definition: initsplan.c:320

◆ innerrel_is_unique()

bool innerrel_is_unique ( PlannerInfo root,
Relids  outerrelids,
RelOptInfo innerrel,
JoinType  jointype,
List restrictlist,
bool  force_cache 
)

Definition at line 970 of file analyzejoins.c.

References bms_copy(), bms_is_subset(), is_innerrel_unique_for(), PlannerInfo::join_search_private, lappend(), lfirst, MemoryContextSwitchTo(), NIL, RelOptInfo::non_unique_for_rels, PlannerInfo::planner_cxt, rel_supports_distinctness(), and RelOptInfo::unique_for_rels.

Referenced by add_paths_to_joinrel(), and reduce_unique_semijoins().

976 {
977  MemoryContext old_context;
978  ListCell *lc;
979 
980  /* Certainly can't prove uniqueness when there are no joinclauses */
981  if (restrictlist == NIL)
982  return false;
983 
984  /*
985  * Make a quick check to eliminate cases in which we will surely be unable
986  * to prove uniqueness of the innerrel.
987  */
988  if (!rel_supports_distinctness(root, innerrel))
989  return false;
990 
991  /*
992  * Query the cache to see if we've managed to prove that innerrel is
993  * unique for any subset of this outerrel. We don't need an exact match,
994  * as extra outerrels can't make the innerrel any less unique (or more
995  * formally, the restrictlist for a join to a superset outerrel must be a
996  * superset of the conditions we successfully used before).
997  */
998  foreach(lc, innerrel->unique_for_rels)
999  {
1000  Relids unique_for_rels = (Relids) lfirst(lc);
1001 
1002  if (bms_is_subset(unique_for_rels, outerrelids))
1003  return true; /* Success! */
1004  }
1005 
1006  /*
1007  * Conversely, we may have already determined that this outerrel, or some
1008  * superset thereof, cannot prove this innerrel to be unique.
1009  */
1010  foreach(lc, innerrel->non_unique_for_rels)
1011  {
1012  Relids unique_for_rels = (Relids) lfirst(lc);
1013 
1014  if (bms_is_subset(outerrelids, unique_for_rels))
1015  return false;
1016  }
1017 
1018  /* No cached information, so try to make the proof. */
1019  if (is_innerrel_unique_for(root, outerrelids, innerrel,
1020  jointype, restrictlist))
1021  {
1022  /*
1023  * Cache the positive result for future probes, being sure to keep it
1024  * in the planner_cxt even if we are working in GEQO.
1025  *
1026  * Note: one might consider trying to isolate the minimal subset of
1027  * the outerrels that proved the innerrel unique. But it's not worth
1028  * the trouble, because the planner builds up joinrels incrementally
1029  * and so we'll see the minimally sufficient outerrels before any
1030  * supersets of them anyway.
1031  */
1032  old_context = MemoryContextSwitchTo(root->planner_cxt);
1033  innerrel->unique_for_rels = lappend(innerrel->unique_for_rels,
1034  bms_copy(outerrelids));
1035  MemoryContextSwitchTo(old_context);
1036 
1037  return true; /* Success! */
1038  }
1039  else
1040  {
1041  /*
1042  * None of the join conditions for outerrel proved innerrel unique, so
1043  * we can safely reject this outerrel or any subset of it in future
1044  * checks.
1045  *
1046  * However, in normal planning mode, caching this knowledge is totally
1047  * pointless; it won't be queried again, because we build up joinrels
1048  * from smaller to larger. It is useful in GEQO mode, where the
1049  * knowledge can be carried across successive planning attempts; and
1050  * it's likely to be useful when using join-search plugins, too. Hence
1051  * cache when join_search_private is non-NULL. (Yeah, that's a hack,
1052  * but it seems reasonable.)
1053  *
1054  * Also, allow callers to override that heuristic and force caching;
1055  * that's useful for reduce_unique_semijoins, which calls here before
1056  * the normal join search starts.
1057  */
1058  if (force_cache || root->join_search_private)
1059  {
1060  old_context = MemoryContextSwitchTo(root->planner_cxt);
1061  innerrel->non_unique_for_rels =
1062  lappend(innerrel->non_unique_for_rels,
1063  bms_copy(outerrelids));
1064  MemoryContextSwitchTo(old_context);
1065  }
1066 
1067  return false;
1068  }
1069 }
#define NIL
Definition: pg_list.h:69
List * unique_for_rels
Definition: relation.h:640
Bitmapset * bms_copy(const Bitmapset *a)
Definition: bitmapset.c:111
void * join_search_private
Definition: relation.h:319
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:308
List * non_unique_for_rels
Definition: relation.h:642
Bitmapset * Relids
Definition: relation.h:28
List * lappend(List *list, void *datum)
Definition: list.c:128
#define lfirst(lc)
Definition: pg_list.h:106
static bool is_innerrel_unique_for(PlannerInfo *root, Relids outerrelids, RelOptInfo *innerrel, JoinType jointype, List *restrictlist)
MemoryContext planner_cxt
Definition: relation.h:290
static bool rel_supports_distinctness(PlannerInfo *root, RelOptInfo *rel)
Definition: analyzejoins.c:592

◆ is_projection_capable_path()

bool is_projection_capable_path ( Path path)

Definition at line 6573 of file createplan.c.

References IS_DUMMY_PATH, Path::pathtype, T_Append, T_Hash, T_Limit, T_LockRows, T_Material, T_MergeAppend, T_ModifyTable, T_ProjectSet, T_RecursiveUnion, T_SetOp, T_Sort, and T_Unique.

Referenced by apply_projection_to_path(), create_projection_path(), and create_projection_plan().

6574 {
6575  /* Most plan types can project, so just list the ones that can't */
6576  switch (path->pathtype)
6577  {
6578  case T_Hash:
6579  case T_Material:
6580  case T_Sort:
6581  case T_Unique:
6582  case T_SetOp:
6583  case T_LockRows:
6584  case T_Limit:
6585  case T_ModifyTable:
6586  case T_MergeAppend:
6587  case T_RecursiveUnion:
6588  return false;
6589  case T_Append:
6590 
6591  /*
6592  * Append can't project, but if it's being used to represent a
6593  * dummy path, claim that it can project. This prevents us from
6594  * converting a rel from dummy to non-dummy status by applying a
6595  * projection to its dummy path.
6596  */
6597  return IS_DUMMY_PATH(path);
6598  case T_ProjectSet:
6599 
6600  /*
6601  * Although ProjectSet certainly projects, say "no" because we
6602  * don't want the planner to randomly replace its tlist with
6603  * something else; the SRFs have to stay at top level. This might
6604  * get relaxed later.
6605  */
6606  return false;
6607  default:
6608  break;
6609  }
6610  return true;
6611 }
Definition: nodes.h:79
Definition: nodes.h:48
Definition: nodes.h:75
#define IS_DUMMY_PATH(p)
Definition: relation.h:1277
NodeTag pathtype
Definition: relation.h:1040
Definition: nodes.h:82
Definition: nodes.h:83
Definition: nodes.h:85

◆ is_projection_capable_plan()

bool is_projection_capable_plan ( Plan plan)

Definition at line 6618 of file createplan.c.

References nodeTag, T_Append, T_Hash, T_Limit, T_LockRows, T_Material, T_MergeAppend, T_ModifyTable, T_ProjectSet, T_RecursiveUnion, T_SetOp, T_Sort, and T_Unique.

Referenced by create_unique_plan(), and prepare_sort_from_pathkeys().

6619 {
6620  /* Most plan types can project, so just list the ones that can't */
6621  switch (nodeTag(plan))
6622  {
6623  case T_Hash:
6624  case T_Material:
6625  case T_Sort:
6626  case T_Unique:
6627  case T_SetOp:
6628  case T_LockRows:
6629  case T_Limit:
6630  case T_ModifyTable:
6631  case T_Append:
6632  case T_MergeAppend:
6633  case T_RecursiveUnion:
6634  return false;
6635  case T_ProjectSet:
6636 
6637  /*
6638  * Although ProjectSet certainly projects, say "no" because we
6639  * don't want the planner to randomly replace its tlist with
6640  * something else; the SRFs have to stay at top level. This might
6641  * get relaxed later.
6642  */
6643  return false;
6644  default:
6645  break;
6646  }
6647  return true;
6648 }
Definition: nodes.h:79
Definition: nodes.h:48
Definition: nodes.h:75
Definition: nodes.h:82
#define nodeTag(nodeptr)
Definition: nodes.h:517
Definition: nodes.h:83
Definition: nodes.h:85

◆ make_agg()

Agg* make_agg ( List tlist,
List qual,
AggStrategy  aggstrategy,
AggSplit  aggsplit,
int  numGroupCols,
AttrNumber grpColIdx,
Oid grpOperators,
List groupingSets,
List chain,
double  dNumGroups,
Plan lefttree 
)

Definition at line 6031 of file createplan.c.

References Agg::aggParams, Agg::aggsplit, Agg::aggstrategy, Agg::chain, Agg::groupingSets, Agg::grpColIdx, Agg::grpOperators, Plan::lefttree, makeNode, Min, Agg::numCols, Agg::numGroups, Agg::plan, Plan::qual, Plan::righttree, and Plan::targetlist.

Referenced by create_agg_plan(), create_groupingsets_plan(), and create_unique_plan().

6036 {
6037  Agg *node = makeNode(Agg);
6038  Plan *plan = &node->plan;
6039  long numGroups;
6040 
6041  /* Reduce to long, but 'ware overflow! */
6042  numGroups = (long) Min(dNumGroups, (double) LONG_MAX);
6043 
6044  node->aggstrategy = aggstrategy;
6045  node->aggsplit = aggsplit;
6046  node->numCols = numGroupCols;
6047  node->grpColIdx = grpColIdx;
6048  node->grpOperators = grpOperators;
6049  node->numGroups = numGroups;
6050  node->aggParams = NULL; /* SS_finalize_plan() will fill this */
6051  node->groupingSets = groupingSets;
6052  node->chain = chain;
6053 
6054  plan->qual = qual;
6055  plan->targetlist = tlist;
6056  plan->lefttree = lefttree;
6057  plan->righttree = NULL;
6058 
6059  return node;
6060 }
int numCols
Definition: plannodes.h:786
List * qual
Definition: plannodes.h:145
AttrNumber * grpColIdx
Definition: plannodes.h:787
#define Min(x, y)
Definition: c.h:802
struct Plan * righttree
Definition: plannodes.h:147
AggStrategy aggstrategy
Definition: plannodes.h:784
Bitmapset * aggParams
Definition: plannodes.h:790
Plan plan
Definition: plannodes.h:783
List * groupingSets
Definition: plannodes.h:792
#define makeNode(_type_)
Definition: nodes.h:560
AggSplit aggsplit
Definition: plannodes.h:785
long numGroups
Definition: plannodes.h:789
struct Plan * lefttree
Definition: plannodes.h:146
List * targetlist
Definition: plannodes.h:144
Oid * grpOperators
Definition: plannodes.h:788
List * chain
Definition: plannodes.h:793
Definition: plannodes.h:781

◆ make_foreignscan()

ForeignScan* make_foreignscan ( List qptlist,
List qpqual,
Index  scanrelid,
List fdw_exprs,
List fdw_private,
List fdw_scan_tlist,
List fdw_recheck_quals,
Plan outer_plan 
)

Definition at line 5265 of file createplan.c.

References CMD_SELECT, ForeignScan::fdw_exprs, ForeignScan::fdw_private, ForeignScan::fdw_recheck_quals, ForeignScan::fdw_scan_tlist, ForeignScan::fs_relids, ForeignScan::fs_server, ForeignScan::fsSystemCol, InvalidOid, Plan::lefttree, makeNode, ForeignScan::operation, Scan::plan, Plan::qual, Plan::righttree, ForeignScan::scan, Scan::scanrelid, and Plan::targetlist.

Referenced by fileGetForeignPlan(), and postgresGetForeignPlan().

5273 {
5274  ForeignScan *node = makeNode(ForeignScan);
5275  Plan *plan = &node->scan.plan;
5276 
5277  /* cost will be filled in by create_foreignscan_plan */
5278  plan->targetlist = qptlist;
5279  plan->qual = qpqual;
5280  plan->lefttree = outer_plan;
5281  plan->righttree = NULL;
5282  node->scan.scanrelid = scanrelid;
5283  node->operation = CMD_SELECT;
5284  /* fs_server will be filled in by create_foreignscan_plan */
5285  node->fs_server = InvalidOid;
5286  node->fdw_exprs = fdw_exprs;
5287  node->fdw_private = fdw_private;
5288  node->fdw_scan_tlist = fdw_scan_tlist;
5289  node->fdw_recheck_quals = fdw_recheck_quals;
5290  /* fs_relids will be filled in by create_foreignscan_plan */
5291  node->fs_relids = NULL;
5292  /* fsSystemCol will be filled in by create_foreignscan_plan */
5293  node->fsSystemCol = false;
5294 
5295  return node;
5296 }
List * qual
Definition: plannodes.h:145
Plan plan
Definition: plannodes.h:329
Index scanrelid
Definition: plannodes.h:330
Oid fs_server
Definition: plannodes.h:600
List * fdw_exprs
Definition: plannodes.h:601
List * fdw_private
Definition: plannodes.h:602
List * fdw_scan_tlist
Definition: plannodes.h:603
CmdType operation
Definition: plannodes.h:599
struct Plan * righttree
Definition: plannodes.h:147
List * fdw_recheck_quals
Definition: plannodes.h:604
#define InvalidOid
Definition: postgres_ext.h:36
#define makeNode(_type_)
Definition: nodes.h:560
struct Plan * lefttree
Definition: plannodes.h:146
List * targetlist
Definition: plannodes.h:144
bool fsSystemCol
Definition: plannodes.h:606
Bitmapset * fs_relids
Definition: plannodes.h:605

◆ make_limit()

Limit* make_limit ( Plan lefttree,
Node limitOffset,
Node limitCount 
)

Definition at line 6371 of file createplan.c.

References Plan::lefttree, Limit::limitCount, Limit::limitOffset, makeNode, NIL, Limit::plan, Plan::qual, Plan::righttree, and Plan::targetlist.

Referenced by create_limit_plan(), and create_minmaxagg_plan().

6372 {
6373  Limit *node = makeNode(Limit);
6374  Plan *plan = &node->plan;
6375 
6376  plan->targetlist = lefttree->targetlist;
6377  plan->qual = NIL;
6378  plan->lefttree = lefttree;
6379  plan->righttree = NULL;
6380 
6381  node->limitOffset = limitOffset;
6382  node->limitCount = limitCount;
6383 
6384  return node;
6385 }
#define NIL
Definition: pg_list.h:69
List * qual
Definition: plannodes.h:145
Plan plan
Definition: plannodes.h:928
Node * limitOffset
Definition: plannodes.h:929
struct Plan * righttree
Definition: plannodes.h:147
Node * limitCount
Definition: plannodes.h:930
#define makeNode(_type_)
Definition: nodes.h:560
struct Plan * lefttree
Definition: plannodes.h:146
List * targetlist
Definition: plannodes.h:144

◆ make_sort_from_sortclauses()

Sort* make_sort_from_sortclauses ( List sortcls,
Plan lefttree 
)

Definition at line 5885 of file createplan.c.

References TargetEntry::expr, exprCollation(), get_sortgroupclause_tle(), lfirst, list_length(), make_sort(), SortGroupClause::nulls_first, palloc(), TargetEntry::resno, SortGroupClause::sortop, and Plan::targetlist.

Referenced by create_unique_plan().

5886 {
5887  List *sub_tlist = lefttree->targetlist;
5888  ListCell *l;
5889  int numsortkeys;
5890  AttrNumber *sortColIdx;
5891  Oid *sortOperators;
5892  Oid *collations;
5893  bool *nullsFirst;
5894 
5895  /* Convert list-ish representation to arrays wanted by executor */
5896  numsortkeys = list_length(sortcls);
5897  sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber));
5898  sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid));
5899  collations = (Oid *) palloc(numsortkeys * sizeof(Oid));
5900  nullsFirst = (bool *) palloc(numsortkeys * sizeof(bool));
5901 
5902  numsortkeys = 0;
5903  foreach(l, sortcls)
5904  {
5905  SortGroupClause *sortcl = (SortGroupClause *) lfirst(l);
5906  TargetEntry *tle = get_sortgroupclause_tle(sortcl, sub_tlist);
5907 
5908  sortColIdx[numsortkeys] = tle->resno;
5909  sortOperators[numsortkeys] = sortcl->sortop;
5910  collations[numsortkeys] = exprCollation((Node *) tle->expr);
5911  nullsFirst[numsortkeys] = sortcl->nulls_first;
5912  numsortkeys++;
5913  }
5914 
5915  return make_sort(lefttree, numsortkeys,
5916  sortColIdx, sortOperators,
5917  collations, nullsFirst);
5918 }
TargetEntry * get_sortgroupclause_tle(SortGroupClause *sgClause, List *targetList)
Definition: tlist.c:370
Definition: nodes.h:512
unsigned int Oid
Definition: postgres_ext.h:31
AttrNumber resno
Definition: primnodes.h:1376
static Sort * make_sort(Plan *lefttree, int numCols, AttrNumber *sortColIdx, Oid *sortOperators, Oid *collations, bool *nullsFirst)
Definition: createplan.c:5511
#define lfirst(lc)
Definition: pg_list.h:106
Expr * expr
Definition: primnodes.h:1375
static int list_length(const List *l)
Definition: pg_list.h:89
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:720
List * targetlist
Definition: plannodes.h:144
void * palloc(Size size)
Definition: mcxt.c:848
Definition: pg_list.h:45
int16 AttrNumber
Definition: attnum.h:21

◆ match_foreign_keys_to_quals()

void match_foreign_keys_to_quals ( PlannerInfo root)

Definition at line 2434 of file initsplan.c.

References OpExpr::args, RestrictInfo::clause, ForeignKeyOptInfo::con_relid, ForeignKeyOptInfo::confkey, ForeignKeyOptInfo::conkey, ForeignKeyOptInfo::conpfeqop, ForeignKeyOptInfo::eclass, PlannerInfo::fkey_list, get_commutator(), get_leftop(), get_rightop(), InvalidOid, IsA, RelOptInfo::joininfo, lappend(), lfirst, list_length(), match_eclasses_to_foreign_key_col(), NIL, ForeignKeyOptInfo::nkeys, ForeignKeyOptInfo::nmatched_ec, ForeignKeyOptInfo::nmatched_rcols, ForeignKeyOptInfo::nmatched_ri, OidIsValid, OpExpr::opno, RestrictInfo::outerjoin_delayed, ForeignKeyOptInfo::ref_relid, RELOPT_BASEREL, RelOptInfo::reloptkind, ForeignKeyOptInfo::rinfos, PlannerInfo::simple_rel_array, and PlannerInfo::simple_rel_array_size.

Referenced by query_planner().

2435 {
2436  List *newlist = NIL;
2437  ListCell *lc;
2438 
2439  foreach(lc, root->fkey_list)
2440  {
2441  ForeignKeyOptInfo *fkinfo = (ForeignKeyOptInfo *) lfirst(lc);
2442  RelOptInfo *con_rel;
2443  RelOptInfo *ref_rel;
2444  int colno;
2445 
2446  /*
2447  * Either relid might identify a rel that is in the query's rtable but
2448  * isn't referenced by the jointree so won't have a RelOptInfo. Hence
2449  * don't use find_base_rel() here. We can ignore such FKs.
2450  */
2451  if (fkinfo->con_relid >= root->simple_rel_array_size ||
2452  fkinfo->ref_relid >= root->simple_rel_array_size)
2453  continue; /* just paranoia */
2454  con_rel = root->simple_rel_array[fkinfo->con_relid];
2455  if (con_rel == NULL)
2456  continue;
2457  ref_rel = root->simple_rel_array[fkinfo->ref_relid];
2458  if (ref_rel == NULL)
2459  continue;
2460 
2461  /*
2462  * Ignore FK unless both rels are baserels. This gets rid of FKs that
2463  * link to inheritance child rels (otherrels) and those that link to
2464  * rels removed by join removal (dead rels).
2465  */
2466  if (con_rel->reloptkind != RELOPT_BASEREL ||
2467  ref_rel->reloptkind != RELOPT_BASEREL)
2468  continue;
2469 
2470  /*
2471  * Scan the columns and try to match them to eclasses and quals.
2472  *
2473  * Note: for simple inner joins, any match should be in an eclass.
2474  * "Loose" quals that syntactically match an FK equality must have
2475  * been rejected for EC status because they are outer-join quals or
2476  * similar. We can still consider them to match the FK if they are
2477  * not outerjoin_delayed.
2478  */
2479  for (colno = 0; colno < fkinfo->nkeys; colno++)
2480  {
2481  AttrNumber con_attno,
2482  ref_attno;
2483  Oid fpeqop;
2484  ListCell *lc2;
2485 
2486  fkinfo->eclass[colno] = match_eclasses_to_foreign_key_col(root,
2487  fkinfo,
2488  colno);
2489  /* Don't bother looking for loose quals if we got an EC match */
2490  if (fkinfo->eclass[colno] != NULL)
2491  {
2492  fkinfo->nmatched_ec++;
2493  continue;
2494  }
2495 
2496  /*
2497  * Scan joininfo list for relevant clauses. Either rel's joininfo
2498  * list would do equally well; we use con_rel's.
2499  */
2500  con_attno = fkinfo->conkey[colno];
2501  ref_attno = fkinfo->confkey[colno];
2502  fpeqop = InvalidOid; /* we'll look this up only if needed */
2503 
2504  foreach(lc2, con_rel->joininfo)
2505  {
2506  RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc2);
2507  OpExpr *clause = (OpExpr *) rinfo->clause;
2508  Var *leftvar;
2509  Var *rightvar;
2510 
2511  /* Ignore outerjoin-delayed clauses */
2512  if (rinfo->outerjoin_delayed)
2513  continue;
2514 
2515  /* Only binary OpExprs are useful for consideration */
2516  if (!IsA(clause, OpExpr) ||
2517  list_length(clause->args) != 2)
2518  continue;
2519  leftvar = (Var *) get_leftop((Expr *) clause);
2520  rightvar = (Var *) get_rightop((Expr *) clause);
2521 
2522  /* Operands must be Vars, possibly with RelabelType */
2523  while (leftvar && IsA(leftvar, RelabelType))
2524  leftvar = (Var *) ((RelabelType *) leftvar)->arg;
2525  if (!(leftvar && IsA(leftvar, Var)))
2526  continue;
2527  while (rightvar && IsA(rightvar, RelabelType))
2528  rightvar = (Var *) ((RelabelType *) rightvar)->arg;
2529  if (!(rightvar && IsA(rightvar, Var)))
2530  continue;
2531 
2532  /* Now try to match the vars to the current foreign key cols */
2533  if (fkinfo->ref_relid == leftvar->varno &&
2534  ref_attno == leftvar->varattno &&
2535  fkinfo->con_relid == rightvar->varno &&
2536  con_attno == rightvar->varattno)
2537  {
2538  /* Vars match, but is it the right operator? */
2539  if (clause->opno == fkinfo->conpfeqop[colno])
2540  {
2541  fkinfo->rinfos[colno] = lappend(fkinfo->rinfos[colno],
2542  rinfo);
2543  fkinfo->nmatched_ri++;
2544  }
2545  }
2546  else if (fkinfo->ref_relid == rightvar->varno &&
2547  ref_attno == rightvar->varattno &&
2548  fkinfo->con_relid == leftvar->varno &&
2549  con_attno == leftvar->varattno)
2550  {
2551  /*
2552  * Reverse match, must check commutator operator. Look it
2553  * up if we didn't already. (In the worst case we might
2554  * do multiple lookups here, but that would require an FK
2555  * equality operator without commutator, which is
2556  * unlikely.)
2557  */
2558  if (!OidIsValid(fpeqop))
2559  fpeqop = get_commutator(fkinfo->conpfeqop[colno]);
2560  if (clause->opno == fpeqop)
2561  {
2562  fkinfo->rinfos[colno] = lappend(fkinfo->rinfos[colno],
2563  rinfo);
2564  fkinfo->nmatched_ri++;
2565  }
2566  }
2567  }
2568  /* If we found any matching loose quals, count col as matched */
2569  if (fkinfo->rinfos[colno])
2570  fkinfo->nmatched_rcols++;
2571  }
2572 
2573  /*
2574  * Currently, we drop multicolumn FKs that aren't fully matched to the
2575  * query. Later we might figure out how to derive some sort of
2576  * estimate from them, in which case this test should be weakened to
2577  * "if ((fkinfo->nmatched_ec + fkinfo->nmatched_rcols) > 0)".
2578  */
2579  if ((fkinfo->nmatched_ec + fkinfo->nmatched_rcols) == fkinfo->nkeys)
2580  newlist = lappend(newlist, fkinfo);
2581  }
2582  /* Replace fkey_list, thereby discarding any useless entries */
2583  root->fkey_list = newlist;
2584 }
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:563
Oid get_commutator(Oid opno)
Definition: lsyscache.c:1313
RelOptKind reloptkind
Definition: relation.h:582
unsigned int Oid
Definition: postgres_ext.h:31
Definition: primnodes.h:163
List * fkey_list
Definition: relation.h:260
#define OidIsValid(objectId)
Definition: c.h:576
struct RelOptInfo ** simple_rel_array
Definition: relation.h:179
Node * get_leftop(const Expr *clause)
Definition: clauses.c:199
Oid conpfeqop[INDEX_MAX_KEYS]
Definition: relation.h:787
bool outerjoin_delayed
Definition: relation.h:1845
List * joininfo
Definition: relation.h:649
int simple_rel_array_size
Definition: relation.h:180
List * lappend(List *list, void *datum)
Definition: list.c:128
Expr * clause
Definition: relation.h:1841
struct EquivalenceClass * eclass[INDEX_MAX_KEYS]
Definition: relation.h:794
AttrNumber conkey[INDEX_MAX_KEYS]
Definition: relation.h:785
EquivalenceClass * match_eclasses_to_foreign_key_col(PlannerInfo *root, ForeignKeyOptInfo *fkinfo, int colno)
Definition: equivclass.c:2030
#define InvalidOid
Definition: postgres_ext.h:36
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89
Node * get_rightop(const Expr *clause)
Definition: clauses.c:216
Oid opno
Definition: primnodes.h:496
List * args
Definition: primnodes.h:502
Definition: pg_list.h:45
AttrNumber confkey[INDEX_MAX_KEYS]
Definition: relation.h:786
int16 AttrNumber
Definition: attnum.h:21
List * rinfos[INDEX_MAX_KEYS]
Definition: relation.h:796

◆ materialize_finished_plan()

Plan* materialize_finished_plan ( Plan subplan)

Definition at line 5997 of file createplan.c.

References cost_material(), Plan::initPlan, make_material(), NIL, Plan::parallel_aware, Plan::parallel_safe, Plan::plan_rows, Plan::plan_width, Plan::startup_cost, Path::startup_cost, Plan::total_cost, and Path::total_cost.

Referenced by build_subplan(), and standard_planner().

5998 {
5999  Plan *matplan;
6000  Path matpath; /* dummy for result of cost_material */
6001 
6002  matplan = (Plan *) make_material(subplan);
6003 
6004  /*
6005  * XXX horrid kluge: if there are any initPlans attached to the subplan,
6006  * move them up to the Material node, which is now effectively the top
6007  * plan node in its query level. This prevents failure in
6008  * SS_finalize_plan(), which see for comments. We don't bother adjusting
6009  * the subplan's cost estimate for this.
6010  */
6011  matplan->initPlan = subplan->initPlan;
6012  subplan->initPlan = NIL;
6013 
6014  /* Set cost data */
6015  cost_material(&matpath,
6016  subplan->startup_cost,
6017  subplan->total_cost,
6018  subplan->plan_rows,
6019  subplan->plan_width);
6020  matplan->startup_cost = matpath.startup_cost;
6021  matplan->total_cost = matpath.total_cost;
6022  matplan->plan_rows = subplan->plan_rows;
6023  matplan->plan_width = subplan->plan_width;
6024  matplan->parallel_aware = false;
6025  matplan->parallel_safe = subplan->parallel_safe;
6026 
6027  return matplan;
6028 }
#define NIL
Definition: pg_list.h:69
double plan_rows
Definition: plannodes.h:131
static Material * make_material(Plan *lefttree)
Definition: createplan.c:5975
Cost startup_cost
Definition: relation.h:1053
Cost startup_cost
Definition: plannodes.h:125
bool parallel_aware
Definition: plannodes.h:137
Cost total_cost
Definition: relation.h:1054
void cost_material(Path *path, Cost input_startup_cost, Cost input_total_cost, double tuples, int width)
Definition: costsize.c:1984
int plan_width
Definition: plannodes.h:132
List * initPlan
Definition: plannodes.h:148
Cost total_cost
Definition: plannodes.h:126
bool parallel_safe
Definition: plannodes.h:138

◆ preprocess_minmax_aggregates()

void preprocess_minmax_aggregates ( PlannerInfo root,
List tlist 
)

Definition at line 75 of file planagg.c.

References add_path(), MinMaxAggInfo::aggsortop, Assert, build_minmax_path(), create_minmaxagg_path(), create_pathtarget, Query::cteList, elog, ERROR, exprCollation(), exprType(), fetch_upper_rel(), find_minmax_aggs_walker(), FromExpr::fromlist, get_equality_op_for_ordering_op(), Query::groupClause, Query::groupingSets, Query::hasAggs, Query::hasWindowFuncs, Query::havingQual, RangeTblEntry::inh, IsA, Query::jointree, lfirst, linitial, list_length(), PlannerInfo::minmax_aggs, NIL, OidIsValid, MinMaxAggInfo::param, parse(), PlannerInfo::parse, planner_rt_fetch, Query::rowMarks, RTE_RELATION, RTE_SUBQUERY, RangeTblEntry::rtekind, RangeTblRef::rtindex, Query::setOperations, SS_make_initplan_output_param(), MinMaxAggInfo::target, and UPPERREL_GROUP_AGG.

Referenced by grouping_planner().

76 {
77  Query *parse = root->parse;
78  FromExpr *jtnode;
79  RangeTblRef *rtr;
80  RangeTblEntry *rte;
81  List *aggs_list;
82  RelOptInfo *grouped_rel;
83  ListCell *lc;
84 
85  /* minmax_aggs list should be empty at this point */
86  Assert(root->minmax_aggs == NIL);
87 
88  /* Nothing to do if query has no aggregates */
89  if (!parse->hasAggs)
90  return;
91 
92  Assert(!parse->setOperations); /* shouldn't get here if a setop */
93  Assert(parse->rowMarks == NIL); /* nor if FOR UPDATE */
94 
95  /*
96  * Reject unoptimizable cases.
97  *
98  * We don't handle GROUP BY or windowing, because our current
99  * implementations of grouping require looking at all the rows anyway, and
100  * so there's not much point in optimizing MIN/MAX.
101  */
102  if (parse->groupClause || list_length(parse->groupingSets) > 1 ||
103  parse->hasWindowFuncs)
104  return;
105 
106  /*
107  * Reject if query contains any CTEs; there's no way to build an indexscan
108  * on one so we couldn't succeed here. (If the CTEs are unreferenced,
109  * that's not true, but it doesn't seem worth expending cycles to check.)
110  */
111  if (parse->cteList)
112  return;
113 
114  /*
115  * We also restrict the query to reference exactly one table, since join
116  * conditions can't be handled reasonably. (We could perhaps handle a
117  * query containing cartesian-product joins, but it hardly seems worth the
118  * trouble.) However, the single table could be buried in several levels
119  * of FromExpr due to subqueries. Note the "single" table could be an
120  * inheritance parent, too, including the case of a UNION ALL subquery
121  * that's been flattened to an appendrel.
122  */
123  jtnode = parse->jointree;
124  while (IsA(jtnode, FromExpr))
125  {
126  if (list_length(jtnode->fromlist) != 1)
127  return;
128  jtnode = linitial(jtnode->fromlist);
129  }
130  if (!IsA(jtnode, RangeTblRef))
131  return;
132  rtr = (RangeTblRef *) jtnode;
133  rte = planner_rt_fetch(rtr->rtindex, root);
134  if (rte->rtekind == RTE_RELATION)
135  /* ordinary relation, ok */ ;
136  else if (rte->rtekind == RTE_SUBQUERY && rte->inh)
137  /* flattened UNION ALL subquery, ok */ ;
138  else
139  return;
140 
141  /*
142  * Scan the tlist and HAVING qual to find all the aggregates and verify
143  * all are MIN/MAX aggregates. Stop as soon as we find one that isn't.
144  */
145  aggs_list = NIL;
146  if (find_minmax_aggs_walker((Node *) tlist, &aggs_list))
147  return;
148  if (find_minmax_aggs_walker(parse->havingQual, &aggs_list))
149  return;
150 
151  /*
152  * OK, there is at least the possibility of performing the optimization.
153  * Build an access path for each aggregate. If any of the aggregates
154  * prove to be non-indexable, give up; there is no point in optimizing
155  * just some of them.
156  */
157  foreach(lc, aggs_list)
158  {
159  MinMaxAggInfo *mminfo = (MinMaxAggInfo *) lfirst(lc);
160  Oid eqop;
161  bool reverse;
162 
163  /*
164  * We'll need the equality operator that goes with the aggregate's
165  * ordering operator.
166  */
167  eqop = get_equality_op_for_ordering_op(mminfo->aggsortop, &reverse);
168  if (!OidIsValid(eqop)) /* shouldn't happen */
169  elog(ERROR, "could not find equality operator for ordering operator %u",
170  mminfo->aggsortop);
171 
172  /*
173  * We can use either an ordering that gives NULLS FIRST or one that
174  * gives NULLS LAST; furthermore there's unlikely to be much
175  * performance difference between them, so it doesn't seem worth
176  * costing out both ways if we get a hit on the first one. NULLS
177  * FIRST is more likely to be available if the operator is a
178  * reverse-sort operator, so try that first if reverse.
179  */
180  if (build_minmax_path(root, mminfo, eqop, mminfo->aggsortop, reverse))
181  continue;
182  if (build_minmax_path(root, mminfo, eqop, mminfo->aggsortop, !reverse))
183  continue;
184 
185  /* No indexable path for this aggregate, so fail */
186  return;
187  }
188 
189  /*
190  * OK, we can do the query this way. Prepare to create a MinMaxAggPath
191  * node.
192  *
193  * First, create an output Param node for each agg. (If we end up not
194  * using the MinMaxAggPath, we'll waste a PARAM_EXEC slot for each agg,
195  * which is not worth worrying about. We can't wait till create_plan time
196  * to decide whether to make the Param, unfortunately.)
197  */
198  foreach(lc, aggs_list)
199  {
200  MinMaxAggInfo *mminfo = (MinMaxAggInfo *) lfirst(lc);
201 
202  mminfo->param =
204  exprType((Node *) mminfo->target),
205  -1,
206  exprCollation((Node *) mminfo->target));
207  }
208 
209  /*
210  * Create a MinMaxAggPath node with the appropriate estimated costs and
211  * other needed data, and add it to the UPPERREL_GROUP_AGG upperrel, where
212  * it will compete against the standard aggregate implementation. (It
213  * will likely always win, but we need not assume that here.)
214  *
215  * Note: grouping_planner won't have created this upperrel yet, but it's
216  * fine for us to create it first. We will not have inserted the correct
217  * consider_parallel value in it, but MinMaxAggPath paths are currently
218  * never parallel-safe anyway, so that doesn't matter. Likewise, it
219  * doesn't matter that we haven't filled FDW-related fields in the rel.
220  */
221  grouped_rel = fetch_upper_rel(root, UPPERREL_GROUP_AGG, NULL);
222  add_path(grouped_rel, (Path *)
223  create_minmaxagg_path(root, grouped_rel,
224  create_pathtarget(root, tlist),
225  aggs_list,
226  (List *) parse->havingQual));
227 }
#define NIL
Definition: pg_list.h:69
static bool find_minmax_aggs_walker(Node *node, List **context)
Definition: planagg.c:247
MinMaxAggPath * create_minmaxagg_path(PlannerInfo *root, RelOptInfo *rel, PathTarget *target, List *mmaggregates, List *quals)
Definition: pathnode.c:2976
#define IsA(nodeptr, _type_)
Definition: nodes.h:563
Query * parse
Definition: relation.h:155
void add_path(RelOptInfo *parent_rel, Path *new_path)
Definition: pathnode.c:422
FromExpr * jointree
Definition: parsenodes.h:136
bool hasAggs
Definition: parsenodes.h:123
Oid get_equality_op_for_ordering_op(Oid opno, bool *reverse)
Definition: lsyscache.c:264
Param * param
Definition: relation.h:2181
List * groupingSets
Definition: parsenodes.h:148
Definition: nodes.h:512
List * minmax_aggs
Definition: relation.h:288
List * fromlist
Definition: primnodes.h:1478
unsigned int Oid
Definition: postgres_ext.h:31
List * rowMarks
Definition: parsenodes.h:161
#define OidIsValid(objectId)
Definition: c.h:576
#define linitial(l)
Definition: pg_list.h:111
#define planner_rt_fetch(rti, root)
Definition: relation.h:328
#define ERROR
Definition: elog.h:43
RelOptInfo * fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
Definition: relnode.c:1137
#define create_pathtarget(root, tlist)
Definition: tlist.h:69
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
Expr * target
Definition: relation.h:2177
bool hasWindowFuncs
Definition: parsenodes.h:124
Param * SS_make_initplan_output_param(PlannerInfo *root, Oid resulttype, int32 resulttypmod, Oid resultcollation)
Definition: subselect.c:2969
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
static int list_length(const List *l)
Definition: pg_list.h:89
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:720
static bool build_minmax_path(PlannerInfo *root, MinMaxAggInfo *mminfo, Oid eqop, Oid sortop, bool nulls_first)
Definition: planagg.c:342
RTEKind rtekind
Definition: parsenodes.h:951
List * cteList
Definition: parsenodes.h:133
Node * setOperations
Definition: parsenodes.h:163
List * groupClause
Definition: parsenodes.h:146
#define elog
Definition: elog.h:219
Node * havingQual
Definition: parsenodes.h:150
Definition: pg_list.h:45
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:649

◆ process_implied_equality()

void process_implied_equality ( PlannerInfo root,
Oid  opno,
Oid  collation,
Expr item1,
Expr item2,
Relids  qualscope,
Relids  nullable_relids,
Index  security_level,
bool  below_outer_join,
bool  both_const 
)

Definition at line 2311 of file initsplan.c.

References Assert, BOOLOID, Const::constisnull, Const::consttype, Const::constvalue, copyObject, DatumGetBool, distribute_qual_to_rels(), eval_const_expressions(), InvalidOid, IsA, JOIN_INNER, and make_opclause().

Referenced by generate_base_implied_equalities_const(), and generate_base_implied_equalities_no_const().

2321 {
2322  Expr *clause;
2323 
2324  /*
2325  * Build the new clause. Copy to ensure it shares no substructure with
2326  * original (this is necessary in case there are subselects in there...)
2327  */
2328  clause = make_opclause(opno,
2329  BOOLOID, /* opresulttype */
2330  false, /* opretset */
2331  copyObject(item1),
2332  copyObject(item2),
2333  InvalidOid,
2334  collation);
2335 
2336  /* If both constant, try to reduce to a boolean constant. */
2337  if (both_const)
2338  {
2339  clause = (Expr *) eval_const_expressions(root, (Node *) clause);
2340 
2341  /* If we produced const TRUE, just drop the clause */
2342  if (clause && IsA(clause, Const))
2343  {
2344  Const *cclause = (Const *) clause;
2345 
2346  Assert(cclause->consttype == BOOLOID);
2347  if (!cclause->constisnull && DatumGetBool(cclause->constvalue))
2348  return;
2349  }
2350  }
2351 
2352  /*
2353  * Push the new clause into all the appropriate restrictinfo lists.
2354  */
2355  distribute_qual_to_rels(root, (Node *) clause,
2356  true, below_outer_join, JOIN_INNER,
2357  security_level,
2358  qualscope, NULL, NULL, nullable_relids,
2359  NULL);
2360 }
Datum constvalue
Definition: primnodes.h:196
#define IsA(nodeptr, _type_)
Definition: nodes.h:563
static void distribute_qual_to_rels(PlannerInfo *root, Node *clause, bool is_deduced, bool below_outer_join, JoinType jointype, Index security_level, Relids qualscope, Relids ojscope, Relids outerjoin_nonnullable, Relids deduced_nullable_relids, List **postponed_qual_list)
Definition: initsplan.c:1642
Definition: nodes.h:512
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2459
Expr * make_opclause(Oid opno, Oid opresulttype, bool opretset, Expr *leftop, Expr *rightop, Oid opcollid, Oid inputcollid)
Definition: clauses.c:172
Oid consttype
Definition: primnodes.h:192
#define DatumGetBool(X)
Definition: postgres.h:399
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:670
#define BOOLOID
Definition: pg_type.h:288
#define copyObject(obj)
Definition: nodes.h:625
bool constisnull
Definition: primnodes.h:197

◆ query_is_distinct_for()

bool query_is_distinct_for ( Query query,
List colnos,
List opids 
)

Definition at line 782 of file analyzejoins.c.

References SetOperationStmt::all, Assert, castNode, distinct_col_search(), Query::distinctClause, SortGroupClause::eqop, equality_ops_are_compatible(), get_sortgroupclause_tle(), Query::groupClause, SetOperationStmt::groupClauses, GROUPING_SET_EMPTY, Query::groupingSets, Query::hasAggs, Query::hasTargetSRFs, Query::havingQual, lfirst, linitial, list_head(), list_length(), lnext, OidIsValid, SetOperationStmt::op, TargetEntry::resjunk, TargetEntry::resno, SETOP_NONE, Query::setOperations, and Query::targetList.

Referenced by create_unique_path(), and rel_is_distinct_for().

783 {
784  ListCell *l;
785  Oid opid;
786 
787  Assert(list_length(colnos) == list_length(opids));
788 
789  /*
790  * DISTINCT (including DISTINCT ON) guarantees uniqueness if all the
791  * columns in the DISTINCT clause appear in colnos and operator semantics
792  * match. This is true even if there are SRFs in the DISTINCT columns or
793  * elsewhere in the tlist.
794  */
795  if (query->distinctClause)
796  {
797  foreach(l, query->distinctClause)
798  {
799  SortGroupClause *sgc = (SortGroupClause *) lfirst(l);
801  query->targetList);
802 
803  opid = distinct_col_search(tle->resno, colnos, opids);
804  if (!OidIsValid(opid) ||
805  !equality_ops_are_compatible(opid, sgc->eqop))
806  break; /* exit early if no match */
807  }
808  if (l == NULL) /* had matches for all? */
809  return true;
810  }
811 
812  /*
813  * Otherwise, a set-returning function in the query's targetlist can
814  * result in returning duplicate rows, despite any grouping that might
815  * occur before tlist evaluation. (If all tlist SRFs are within GROUP BY
816  * columns, it would be safe because they'd be expanded before grouping.
817  * But it doesn't currently seem worth the effort to check for that.)
818  */
819  if (query->hasTargetSRFs)
820  return false;
821 
822  /*
823  * Similarly, GROUP BY without GROUPING SETS guarantees uniqueness if all
824  * the grouped columns appear in colnos and operator semantics match.
825  */
826  if (query->groupClause && !query->groupingSets)
827  {
828  foreach(l, query->groupClause)
829  {
830  SortGroupClause *sgc = (SortGroupClause *) lfirst(l);
832  query->targetList);
833 
834  opid = distinct_col_search(tle->resno, colnos, opids);
835  if (!OidIsValid(opid) ||
836  !equality_ops_are_compatible(opid, sgc->eqop))
837  break; /* exit early if no match */
838  }
839  if (l == NULL) /* had matches for all? */
840  return true;
841  }
842  else if (query->groupingSets)
843  {
844  /*
845  * If we have grouping sets with expressions, we probably don't have
846  * uniqueness and analysis would be hard. Punt.
847  */
848  if (query->groupClause)
849  return false;
850 
851  /*
852  * If we have no groupClause (therefore no grouping expressions), we
853  * might have one or many empty grouping sets. If there's just one,
854  * then we're returning only one row and are certainly unique. But
855  * otherwise, we know we're certainly not unique.
856  */
857  if (list_length(query->groupingSets) == 1 &&
858  ((GroupingSet *) linitial(query->groupingSets))->kind == GROUPING_SET_EMPTY)
859  return true;
860  else
861  return false;
862  }
863  else
864  {
865  /*
866  * If we have no GROUP BY, but do have aggregates or HAVING, then the
867  * result is at most one row so it's surely unique, for any operators.
868  */
869  if (query->hasAggs || query->havingQual)
870  return true;
871  }
872 
873  /*
874  * UNION, INTERSECT, EXCEPT guarantee uniqueness of the whole output row,
875  * except with ALL.
876  */
877  if (query->setOperations)
878  {
880 
881  Assert(topop->op != SETOP_NONE);
882 
883  if (!topop->all)
884  {
885  ListCell *lg;
886 
887  /* We're good if all the nonjunk output columns are in colnos */
888  lg = list_head(topop->groupClauses);
889  foreach(l, query->targetList)
890  {
891  TargetEntry *tle = (TargetEntry *) lfirst(l);
892  SortGroupClause *sgc;
893 
894  if (tle->resjunk)
895  continue; /* ignore resjunk columns */
896 
897  /* non-resjunk columns should have grouping clauses */
898  Assert(lg != NULL);
899  sgc = (SortGroupClause *) lfirst(lg);
900  lg = lnext(lg);
901 
902  opid = distinct_col_search(tle->resno, colnos, opids);
903  if (!OidIsValid(opid) ||
904  !equality_ops_are_compatible(opid, sgc->eqop))
905  break; /* exit early if no match */
906  }
907  if (l == NULL) /* had matches for all? */
908  return true;
909  }
910  }
911 
912  /*
913  * XXX Are there any other cases in which we can easily see the result
914  * must be distinct?
915  *
916  * If you do add more smarts to this function, be sure to update
917  * query_supports_distinctness() to match.
918  */
919 
920  return false;
921 }
TargetEntry * get_sortgroupclause_tle(SortGroupClause *sgClause, List *targetList)
Definition: tlist.c:370
#define castNode(_type_, nodeptr)
Definition: nodes.h:581
static Oid distinct_col_search(int colno, List *colnos, List *opids)
Definition: analyzejoins.c:931
bool hasAggs
Definition: parsenodes.h:123
List * groupingSets
Definition: parsenodes.h:148
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:576
List * targetList
Definition: parsenodes.h:138
bool resjunk
Definition: primnodes.h:1382
#define linitial(l)
Definition: pg_list.h:111
List * distinctClause
Definition: parsenodes.h:154
AttrNumber resno
Definition: primnodes.h:1376
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
#define lnext(lc)
Definition: pg_list.h:105
bool hasTargetSRFs
Definition: parsenodes.h:125
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
bool equality_ops_are_compatible(Oid opno1, Oid opno2)
Definition: lsyscache.c:695
static int list_length(const List *l)
Definition: pg_list.h:89
SetOperation op
Definition: parsenodes.h:1580
Node * setOperations
Definition: parsenodes.h:163
List * groupClause
Definition: parsenodes.h:146
Node * havingQual
Definition: parsenodes.h:150

◆ query_planner()

RelOptInfo* query_planner ( PlannerInfo root,
List tlist,
query_pathkeys_callback  qp_callback,
void *  qp_extra 
)

Definition at line 54 of file planmain.c.

References add_base_rels_to_query(), add_path(), add_placeholders_to_base_rels(), Assert, build_base_rel_tlists(), build_empty_join_rel(), PlannerInfo::canon_pathkeys, RelOptInfo::cheapest_total_path, RelOptInfo::consider_parallel, create_lateral_join_info(), create_result_path(), deconstruct_jointree(), elog, ERROR, extract_restriction_or_clauses(), find_lateral_references(), find_placeholders_in_jointree(), fix_placeholder_input_needed_levels(), PlannerInfo::fkey_list, FromExpr::fromlist, PlannerInfo::full_join_clauses, generate_base_implied_equalities(), PlannerInfo::glob, PlannerInfo::initial_rels, is_parallel_safe(), IS_SIMPLE_REL, PlannerInfo::join_cur_level, PlannerInfo::join_info_list, PlannerInfo::join_rel_hash, PlannerInfo::join_rel_level, PlannerInfo::join_rel_list, Query::jointree, PlannerInfo::left_join_clauses, make_one_rel(), match_foreign_keys_to_quals(), NIL, RelOptInfo::pages, PlannerGlobal::parallelModeOK, Path::param_info, parse(), PlannerInfo::parse, PlannerInfo::placeholder_list, FromExpr::quals, reconsider_outer_join_clauses(), reduce_unique_semijoins(), RelOptInfo::relid, RelOptInfo::reltarget, remove_useless_joins(), PlannerInfo::right_join_clauses, set_cheapest(), and setup_simple_rel_arrays().

Referenced by build_minmax_path(), and grouping_planner().

56 {
57  Query *parse = root->parse;
58  List *joinlist;
59  RelOptInfo *final_rel;
60  Index rti;
61  double total_pages;
62 
63  /*
64  * If the query has an empty join tree, then it's something easy like
65  * "SELECT 2+2;" or "INSERT ... VALUES()". Fall through quickly.
66  */
67  if (parse->jointree->fromlist == NIL)
68  {
69  /* We need a dummy joinrel to describe the empty set of baserels */
70  final_rel = build_empty_join_rel(root);
71 
72  /*
73  * If query allows parallelism in general, check whether the quals are
74  * parallel-restricted. (We need not check final_rel->reltarget
75  * because it's empty at this point. Anything parallel-restricted in
76  * the query tlist will be dealt with later.)
77  */
78  if (root->glob->parallelModeOK)
79  final_rel->consider_parallel =
80  is_parallel_safe(root, parse->jointree->quals);
81 
82  /* The only path for it is a trivial Result path */
83  add_path(final_rel, (Path *)
84  create_result_path(root, final_rel,
85  final_rel->reltarget,
86  (List *) parse->jointree->quals));
87 
88  /* Select cheapest path (pretty easy in this case...) */
89  set_cheapest(final_rel);
90 
91  /*
92  * We still are required to call qp_callback, in case it's something
93  * like "SELECT 2+2 ORDER BY 1".
94  */
95  root->canon_pathkeys = NIL;
96  (*qp_callback) (root, qp_extra);
97 
98  return final_rel;
99  }
100 
101  /*
102  * Init planner lists to empty.
103  *
104  * NOTE: append_rel_list was set up by subquery_planner, so do not touch
105  * here.
106  */
107  root->join_rel_list = NIL;
108  root->join_rel_hash = NULL;
109  root->join_rel_level = NULL;
110  root->join_cur_level = 0;
111  root->canon_pathkeys = NIL;
112  root->left_join_clauses = NIL;
113  root->right_join_clauses = NIL;
114  root->full_join_clauses = NIL;
115  root->join_info_list = NIL;
116  root->placeholder_list = NIL;
117  root->fkey_list = NIL;
118  root->initial_rels = NIL;
119 
120  /*
121  * Make a flattened version of the rangetable for faster access (this is
122  * OK because the rangetable won't change any more), and set up an empty
123  * array for indexing base relations.
124  */
126 
127  /*
128  * Construct RelOptInfo nodes for all base relations in query, and
129  * indirectly for all appendrel member relations ("other rels"). This
130  * will give us a RelOptInfo for every "simple" (non-join) rel involved in
131  * the query.
132  *
133  * Note: the reason we find the rels by searching the jointree and
134  * appendrel list, rather than just scanning the rangetable, is that the
135  * rangetable may contain RTEs for rels not actively part of the query,
136  * for example views. We don't want to make RelOptInfos for them.
137  */
138  add_base_rels_to_query(root, (Node *) parse->jointree);
139 
140  /*
141  * Examine the targetlist and join tree, adding entries to baserel
142  * targetlists for all referenced Vars, and generating PlaceHolderInfo
143  * entries for all referenced PlaceHolderVars. Restrict and join clauses
144  * are added to appropriate lists belonging to the mentioned relations. We
145  * also build EquivalenceClasses for provably equivalent expressions. The
146  * SpecialJoinInfo list is also built to hold information about join order
147  * restrictions. Finally, we form a target joinlist for make_one_rel() to
148  * work from.
149  */
150  build_base_rel_tlists(root, tlist);
151 
153 
155 
156  joinlist = deconstruct_jointree(root);
157 
158  /*
159  * Reconsider any postponed outer-join quals now that we have built up
160  * equivalence classes. (This could result in further additions or
161  * mergings of classes.)
162  */
164 
165  /*
166  * If we formed any equivalence classes, generate additional restriction
167  * clauses as appropriate. (Implied join clauses are formed on-the-fly
168  * later.)
169  */
171 
172  /*
173  * We have completed merging equivalence sets, so it's now possible to
174  * generate pathkeys in canonical form; so compute query_pathkeys and
175  * other pathkeys fields in PlannerInfo.
176  */
177  (*qp_callback) (root, qp_extra);
178 
179  /*
180  * Examine any "placeholder" expressions generated during subquery pullup.
181  * Make sure that the Vars they need are marked as needed at the relevant
182  * join level. This must be done before join removal because it might
183  * cause Vars or placeholders to be needed above a join when they weren't
184  * so marked before.
185  */
187 
188  /*
189  * Remove any useless outer joins. Ideally this would be done during
190  * jointree preprocessing, but the necessary information isn't available
191  * until we've built baserel data structures and classified qual clauses.
192  */
193  joinlist = remove_useless_joins(root, joinlist);
194 
195  /*
196  * Also, reduce any semijoins with unique inner rels to plain inner joins.
197  * Likewise, this can't be done until now for lack of needed info.
198  */
200 
201  /*
202  * Now distribute "placeholders" to base rels as needed. This has to be
203  * done after join removal because removal could change whether a
204  * placeholder is evaluable at a base rel.
205  */
207 
208  /*
209  * Construct the lateral reference sets now that we have finalized
210  * PlaceHolderVar eval levels.
211  */
213 
214  /*
215  * Match foreign keys to equivalence classes and join quals. This must be
216  * done after finalizing equivalence classes, and it's useful to wait till
217  * after join removal so that we can skip processing foreign keys
218  * involving removed relations.
219  */
221 
222  /*
223  * Look for join OR clauses that we can extract single-relation
224  * restriction OR clauses from.
225  */
227 
228  /*
229  * We should now have size estimates for every actual table involved in
230  * the query, and we also know which if any have been deleted from the
231  * query by join removal; so we can compute total_table_pages.
232  *
233  * Note that appendrels are not double-counted here, even though we don't
234  * bother to distinguish RelOptInfos for appendrel parents, because the
235  * parents will still have size zero.
236  *
237  * XXX if a table is self-joined, we will count it once per appearance,
238  * which perhaps is the wrong thing ... but that's not completely clear,
239  * and detecting self-joins here is difficult, so ignore it for now.
240  */
241  total_pages = 0;
242  for (rti = 1; rti < root->simple_rel_array_size; rti++)
243  {
244  RelOptInfo *brel = root->simple_rel_array[rti];
245 
246  if (brel == NULL)
247  continue;
248 
249  Assert(brel->relid == rti); /* sanity check on array */
250 
251  if (IS_SIMPLE_REL(brel))
252  total_pages += (double) brel->pages;
253  }
254  root->total_table_pages = total_pages;
255 
256  /*
257  * Ready to do the primary planning.
258  */
259  final_rel = make_one_rel(root, joinlist);
260 
261  /* Check that we got at least one usable path */
262  if (!final_rel || !final_rel->cheapest_total_path ||
263  final_rel->cheapest_total_path->param_info != NULL)
264  elog(ERROR, "failed to construct the join relation");
265 
266  return final_rel;
267 }
#define NIL
Definition: pg_list.h:69
int join_cur_level
Definition: relation.h:226
RelOptInfo * make_one_rel(PlannerInfo *root, List *joinlist)
Definition: allpaths.c:147
Query * parse
Definition: relation.h:155
void add_path(RelOptInfo *parent_rel, Path *new_path)
Definition: pathnode.c:422
void reduce_unique_semijoins(PlannerInfo *root)
Definition: analyzejoins.c:512
void add_base_rels_to_query(PlannerInfo *root, Node *jtnode)
Definition: initsplan.c:105
List * join_info_list
Definition: relation.h:250
FromExpr * jointree
Definition: parsenodes.h:136
void extract_restriction_or_clauses(PlannerInfo *root)
Definition: orclauses.c:73
List * deconstruct_jointree(PlannerInfo *root)
Definition: initsplan.c:713
ParamPathInfo * param_info
Definition: relation.h:1045
Definition: nodes.h:512
List * join_rel_list
Definition: relation.h:215
List * fromlist
Definition: primnodes.h:1478
List * fkey_list
Definition: relation.h:260
void add_placeholders_to_base_rels(PlannerInfo *root)
Definition: placeholder.c:380
Node * quals
Definition: primnodes.h:1479
#define IS_SIMPLE_REL(rel)
Definition: relation.h:561
bool is_parallel_safe(PlannerInfo *root, Node *node)
Definition: clauses.c:1087
#define ERROR
Definition: elog.h:43
bool parallelModeOK
Definition: relation.h:129
struct Path * cheapest_total_path
Definition: relation.h:603
PlannerGlobal * glob
Definition: relation.h:157
List * left_join_clauses
Definition: relation.h:239
List * full_join_clauses
Definition: relation.h:247
List * canon_pathkeys
Definition: relation.h:237
Index relid
Definition: relation.h:613
void fix_placeholder_input_needed_levels(PlannerInfo *root)
Definition: placeholder.c:351
void set_cheapest(RelOptInfo *parent_rel)
Definition: pathnode.c:244
void find_placeholders_in_jointree(PlannerInfo *root)
Definition: placeholder.c:145
void generate_base_implied_equalities(PlannerInfo *root)
Definition: equivclass.c:800
unsigned int Index
Definition: c.h:413
void reconsider_outer_join_clauses(PlannerInfo *root)
Definition: equivclass.c:1572
BlockNumber pages
Definition: relation.h:624
#define Assert(condition)
Definition: c.h:670
RelOptInfo * build_empty_join_rel(PlannerInfo *root)
Definition: relnode.c:1103
List ** join_rel_level
Definition: relation.h:225
void setup_simple_rel_arrays(PlannerInfo *root)
Definition: relnode.c:67
List * remove_useless_joins(PlannerInfo *root, List *joinlist)
Definition: analyzejoins.c:60
struct HTAB * join_rel_hash
Definition: relation.h:216
void build_base_rel_tlists(PlannerInfo *root, List *final_tlist)
Definition: initsplan.c:151
bool consider_parallel
Definition: relation.h:593
void match_foreign_keys_to_quals(PlannerInfo *root)
Definition: initsplan.c:2434
List * placeholder_list
Definition: relation.h:258
ResultPath * create_result_path(PlannerInfo *root, RelOptInfo *rel, PathTarget *target, List *resconstantqual)
Definition: pathnode.c:1409
List * initial_rels
Definition: relation.h:272
List * right_join_clauses
Definition: relation.h:243
#define elog
Definition: elog.h:219
Definition: pg_list.h:45
struct PathTarget * reltarget
Definition: relation.h:596
void create_lateral_join_info(PlannerInfo *root)
Definition: initsplan.c:418
void find_lateral_references(PlannerInfo *root)
Definition: initsplan.c:272
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:649

◆ query_supports_distinctness()

bool query_supports_distinctness ( Query query)

Definition at line 745 of file analyzejoins.c.

References Query::distinctClause, Query::groupClause, Query::groupingSets, Query::hasAggs, Query::hasTargetSRFs, Query::havingQual, NIL, and Query::setOperations.

Referenced by create_unique_path(), and rel_supports_distinctness().

746 {
747  /* SRFs break distinctness except with DISTINCT, see below */
748  if (query->hasTargetSRFs && query->distinctClause == NIL)
749  return false;
750 
751  /* check for features we can prove distinctness with */
752  if (query->distinctClause != NIL ||
753  query->groupClause != NIL ||
754  query->groupingSets != NIL ||
755  query->hasAggs ||
756  query->havingQual ||
757  query->setOperations)
758  return true;
759 
760  return false;
761 }
#define NIL
Definition: pg_list.h:69
bool hasAggs
Definition: parsenodes.h:123
List * groupingSets
Definition: parsenodes.h:148
List * distinctClause
Definition: parsenodes.h:154
bool hasTargetSRFs
Definition: parsenodes.h:125
Node * setOperations
Definition: parsenodes.h:163
List * groupClause
Definition: parsenodes.h:146
Node * havingQual
Definition: parsenodes.h:150

◆ record_plan_function_dependency()

void record_plan_function_dependency ( PlannerInfo root,
Oid  funcid 
)

Definition at line 2558 of file setrefs.c.

References PlanInvalItem::cacheId, FirstBootstrapObjectId, GetSysCacheHashValue1, PlannerInfo::glob, PlanInvalItem::hashValue, PlannerGlobal::invalItems, lappend(), makeNode, ObjectIdGetDatum, and PROCOID.

Referenced by fix_expr_common(), inline_function(), and inline_set_returning_function().

2559 {
2560  /*
2561  * For performance reasons, we don't bother to track built-in functions;
2562  * we just assume they'll never change (or at least not in ways that'd
2563  * invalidate plans using them). For this purpose we can consider a
2564  * built-in function to be one with OID less than FirstBootstrapObjectId.
2565  * Note that the OID generator guarantees never to generate such an OID
2566  * after startup, even at OID wraparound.
2567  */
2568  if (funcid >= (Oid) FirstBootstrapObjectId)
2569  {
2570  PlanInvalItem *inval_item = makeNode(PlanInvalItem);
2571 
2572  /*
2573  * It would work to use any syscache on pg_proc, but the easiest is
2574  * PROCOID since we already have the function's OID at hand. Note
2575  * that plancache.c knows we use PROCOID.
2576  */
2577  inval_item->cacheId = PROCOID;
2578  inval_item->hashValue = GetSysCacheHashValue1(PROCOID,
2579  ObjectIdGetDatum(funcid));
2580 
2581  root->glob->invalItems = lappend(root->glob->invalItems, inval_item);
2582  }
2583 }
#define GetSysCacheHashValue1(cacheId, key1)
Definition: syscache.h:200
unsigned int Oid
Definition: postgres_ext.h:31
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
PlannerGlobal * glob
Definition: relation.h:157
#define FirstBootstrapObjectId
Definition: transam.h:93
List * lappend(List *list, void *datum)
Definition: list.c:128
List * invalItems
Definition: relation.h:115
uint32 hashValue
Definition: plannodes.h:1042
#define makeNode(_type_)
Definition: nodes.h:560

◆ reduce_unique_semijoins()

void reduce_unique_semijoins ( PlannerInfo root)

Definition at line 512 of file analyzejoins.c.

References bms_get_singleton_member(), bms_union(), SpecialJoinInfo::delay_upper_joins, find_base_rel(), generate_join_implied_equalities(), innerrel_is_unique(), PlannerInfo::join_info_list, JOIN_SEMI, RelOptInfo::joininfo, SpecialJoinInfo::jointype, lfirst, list_concat(), list_delete_ptr(), list_head(), lnext, SpecialJoinInfo::min_lefthand, SpecialJoinInfo::min_righthand, next, and rel_supports_distinctness().

Referenced by query_planner().

513 {
514  ListCell *lc;
515  ListCell *next;
516 
517  /*
518  * Scan the join_info_list to find semijoins. We can't use foreach
519  * because we may delete the current cell.
520  */
521  for (lc = list_head(root->join_info_list); lc != NULL; lc = next)
522  {
523  SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(lc);
524  int innerrelid;
525  RelOptInfo *innerrel;
526  Relids joinrelids;
527  List *restrictlist;
528 
529  next = lnext(lc);
530 
531  /*
532  * Must be a non-delaying semijoin to a single baserel, else we aren't
533  * going to be able to do anything with it. (It's probably not
534  * possible for delay_upper_joins to be set on a semijoin, but we
535  * might as well check.)
536  */
537  if (sjinfo->jointype != JOIN_SEMI ||
538  sjinfo->delay_upper_joins)
539  continue;
540 
541  if (!bms_get_singleton_member(sjinfo->min_righthand, &innerrelid))
542  continue;
543 
544  innerrel = find_base_rel(root, innerrelid);
545 
546  /*
547  * Before we trouble to run generate_join_implied_equalities, make a
548  * quick check to eliminate cases in which we will surely be unable to
549  * prove uniqueness of the innerrel.
550  */
551  if (!rel_supports_distinctness(root, innerrel))
552  continue;
553 
554  /* Compute the relid set for the join we are considering */
555  joinrelids = bms_union(sjinfo->min_lefthand, sjinfo->min_righthand);
556 
557  /*
558  * Since we're only considering a single-rel RHS, any join clauses it
559  * has must be clauses linking it to the semijoin's min_lefthand. We
560  * can also consider EC-derived join clauses.
561  */
562  restrictlist =
564  joinrelids,
565  sjinfo->min_lefthand,
566  innerrel),
567  innerrel->joininfo);
568 
569  /* Test whether the innerrel is unique for those clauses. */
570  if (!innerrel_is_unique(root, sjinfo->min_lefthand, innerrel,
571  JOIN_SEMI, restrictlist, true))
572  continue;
573 
574  /* OK, remove the SpecialJoinInfo from the list. */
575  root->join_info_list = list_delete_ptr(root->join_info_list, sjinfo);
576  }
577 }
static int32 next
Definition: blutils.c:210
List * join_info_list
Definition: relation.h:250
Relids min_righthand
Definition: relation.h:2014
bool bms_get_singleton_member(const Bitmapset *a, int *member)
Definition: bitmapset.c:569
List * list_concat(List *list1, List *list2)
Definition: list.c:321
List * list_delete_ptr(List *list, void *datum)
Definition: list.c:590
List * generate_join_implied_equalities(PlannerInfo *root, Relids join_relids, Relids outer_relids, RelOptInfo *inner_rel)
Definition: equivclass.c:1071
List * joininfo
Definition: relation.h:649
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
#define lnext(lc)
Definition: pg_list.h:105
bool innerrel_is_unique(PlannerInfo *root, Relids outerrelids, RelOptInfo *innerrel, JoinType jointype, List *restrictlist, bool force_cache)
Definition: analyzejoins.c:970
bool delay_upper_joins
Definition: relation.h:2019
#define lfirst(lc)
Definition: pg_list.h:106
JoinType jointype
Definition: relation.h:2017
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:218
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition: relnode.c:277
static bool rel_supports_distinctness(PlannerInfo *root, RelOptInfo *rel)
Definition: analyzejoins.c:592
Definition: pg_list.h:45
Relids min_lefthand
Definition: relation.h:2013

◆ remove_useless_joins()

List* remove_useless_joins ( PlannerInfo root,
List joinlist 
)

Definition at line 60 of file analyzejoins.c.

References bms_singleton_member(), bms_union(), elog, ERROR, PlannerInfo::join_info_list, join_is_removable(), lfirst, list_delete_ptr(), SpecialJoinInfo::min_lefthand, SpecialJoinInfo::min_righthand, remove_rel_from_joinlist(), and remove_rel_from_query().

Referenced by query_planner().

61 {
62  ListCell *lc;
63 
64  /*
65  * We are only interested in relations that are left-joined to, so we can
66  * scan the join_info_list to find them easily.
67  */
68 restart:
69  foreach(lc, root->join_info_list)
70  {
71  SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(lc);
72  int innerrelid;
73  int nremoved;
74 
75  /* Skip if not removable */
76  if (!join_is_removable(root, sjinfo))
77  continue;
78 
79  /*
80  * Currently, join_is_removable can only succeed when the sjinfo's
81  * righthand is a single baserel. Remove that rel from the query and
82  * joinlist.
83  */
84  innerrelid = bms_singleton_member(sjinfo->min_righthand);
85 
86  remove_rel_from_query(root, innerrelid,
87  bms_union(sjinfo->min_lefthand,
88  sjinfo->min_righthand));
89 
90  /* We verify that exactly one reference gets removed from joinlist */
91  nremoved = 0;
92  joinlist = remove_rel_from_joinlist(joinlist, innerrelid, &nremoved);
93  if (nremoved != 1)
94  elog(ERROR, "failed to find relation %d in joinlist", innerrelid);
95 
96  /*
97  * We can delete this SpecialJoinInfo from the list too, since it's no
98  * longer of interest.
99  */
100  root->join_info_list = list_delete_ptr(root->join_info_list, sjinfo);
101 
102  /*
103  * Restart the scan. This is necessary to ensure we find all
104  * removable joins independently of ordering of the join_info_list
105  * (note that removal of attr_needed bits may make a join appear
106  * removable that did not before). Also, since we just deleted the
107  * current list cell, we'd have to have some kluge to continue the
108  * list scan anyway.
109  */
110  goto restart;
111  }
112 
113  return joinlist;
114 }
List * join_info_list
Definition: relation.h:250
Relids min_righthand
Definition: relation.h:2014
static void remove_rel_from_query(PlannerInfo *root, int relid, Relids joinrelids)
Definition: analyzejoins.c:313
List * list_delete_ptr(List *list, void *datum)
Definition: list.c:590
#define ERROR
Definition: elog.h:43
static bool join_is_removable(PlannerInfo *root, SpecialJoinInfo *sjinfo)
Definition: analyzejoins.c:159
int bms_singleton_member(const Bitmapset *a)
Definition: bitmapset.c:526
#define lfirst(lc)
Definition: pg_list.h:106
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:218
static List * remove_rel_from_joinlist(List *joinlist, int relid, int *nremoved)
Definition: analyzejoins.c:458
#define elog
Definition: elog.h:219
Relids min_lefthand
Definition: relation.h:2013

◆ set_plan_references()

Plan* set_plan_references ( PlannerInfo root,
Plan plan 
)

Definition at line 214 of file setrefs.c.

References add_rtes_to_flat_rtable(), PlannerGlobal::finalrowmarks, PlannerGlobal::finalrtable, PlannerInfo::glob, lappend(), lfirst_node, list_length(), palloc(), PlanRowMark::prti, PlannerInfo::rowMarks, PlanRowMark::rti, and set_plan_refs().

Referenced by set_subqueryscan_references(), and standard_planner().

215 {
216  PlannerGlobal *glob = root->glob;
217  int rtoffset = list_length(glob->finalrtable);
218  ListCell *lc;
219 
220  /*
221  * Add all the query's RTEs to the flattened rangetable. The live ones
222  * will have their rangetable indexes increased by rtoffset. (Additional
223  * RTEs, not referenced by the Plan tree, might get added after those.)
224  */
225  add_rtes_to_flat_rtable(root, false);
226 
227  /*
228  * Adjust RT indexes of PlanRowMarks and add to final rowmarks list
229  */
230  foreach(lc, root->rowMarks)
231  {
233  PlanRowMark *newrc;
234 
235  /* flat copy is enough since all fields are scalars */
236  newrc = (PlanRowMark *) palloc(sizeof(PlanRowMark));
237  memcpy(newrc, rc, sizeof(PlanRowMark));
238 
239  /* adjust indexes ... but *not* the rowmarkId */
240  newrc->rti += rtoffset;
241  newrc->prti += rtoffset;
242 
243  glob->finalrowmarks = lappend(glob->finalrowmarks, newrc);
244  }
245 
246  /* Now fix the Plan tree */
247  return set_plan_refs(root, plan, rtoffset);
248 }
List * rowMarks
Definition: relation.h:256
Index prti
Definition: plannodes.h:1019
static Plan * set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
Definition: setrefs.c:439
#define lfirst_node(type, lc)
Definition: pg_list.h:109
PlannerGlobal * glob
Definition: relation.h:157
List * lappend(List *list, void *datum)
Definition: list.c:128
static void add_rtes_to_flat_rtable(PlannerInfo *root, bool recursing)
Definition: setrefs.c:256
static int list_length(const List *l)
Definition: pg_list.h:89
List * finalrtable
Definition: relation.h:104
void * palloc(Size size)
Definition: mcxt.c:848
List * finalrowmarks
Definition: relation.h:106

Variable Documentation

◆ cursor_tuple_fraction

double cursor_tuple_fraction

Definition at line 62 of file planner.c.

Referenced by standard_planner().

◆ force_parallel_mode

int force_parallel_mode

Definition at line 63 of file planner.c.

Referenced by HandleParallelMessage(), and standard_planner().

◆ from_collapse_limit

int from_collapse_limit

Definition at line 37 of file initsplan.c.

Referenced by deconstruct_recurse().

◆ join_collapse_limit

int join_collapse_limit

Definition at line 38 of file initsplan.c.

Referenced by deconstruct_recurse().

◆ parallel_leader_participation

bool parallel_leader_participation

Definition at line 64 of file planner.c.

Referenced by ExecGather(), ExecGatherMerge(), ExecInitGather(), and get_parallel_divisor().