PostgreSQL Source Code  git master
relnode.c File Reference
#include "postgres.h"
#include <limits.h>
#include "miscadmin.h"
#include "optimizer/clauses.h"
#include "optimizer/cost.h"
#include "optimizer/pathnode.h"
#include "optimizer/paths.h"
#include "optimizer/placeholder.h"
#include "optimizer/plancat.h"
#include "optimizer/prep.h"
#include "optimizer/restrictinfo.h"
#include "optimizer/tlist.h"
#include "partitioning/partbounds.h"
#include "utils/hsearch.h"
Include dependency graph for relnode.c:

Go to the source code of this file.

Data Structures

struct  JoinHashEntry
 

Typedefs

typedef struct JoinHashEntry JoinHashEntry
 

Functions

static void build_joinrel_tlist (PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *input_rel)
 
static Listbuild_joinrel_restrictlist (PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel)
 
static void build_joinrel_joinlist (RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel)
 
static Listsubbuild_joinrel_restrictlist (RelOptInfo *joinrel, List *joininfo_list, List *new_restrictlist)
 
static Listsubbuild_joinrel_joinlist (RelOptInfo *joinrel, List *joininfo_list, List *new_joininfo)
 
static void set_foreign_rel_properties (RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel)
 
static void add_join_rel (PlannerInfo *root, RelOptInfo *joinrel)
 
static void build_joinrel_partition_info (RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, List *restrictlist, JoinType jointype)
 
void setup_simple_rel_arrays (PlannerInfo *root)
 
RelOptInfobuild_simple_rel (PlannerInfo *root, int relid, RelOptInfo *parent)
 
RelOptInfofind_base_rel (PlannerInfo *root, int relid)
 
static void build_join_rel_hash (PlannerInfo *root)
 
RelOptInfofind_join_rel (PlannerInfo *root, Relids relids)
 
RelOptInfobuild_join_rel (PlannerInfo *root, Relids joinrelids, RelOptInfo *outer_rel, RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo, List **restrictlist_ptr)
 
RelOptInfobuild_child_join_rel (PlannerInfo *root, RelOptInfo *outer_rel, RelOptInfo *inner_rel, RelOptInfo *parent_joinrel, List *restrictlist, SpecialJoinInfo *sjinfo, JoinType jointype)
 
Relids min_join_parameterization (PlannerInfo *root, Relids joinrelids, RelOptInfo *outer_rel, RelOptInfo *inner_rel)
 
RelOptInfobuild_empty_join_rel (PlannerInfo *root)
 
RelOptInfofetch_upper_rel (PlannerInfo *root, UpperRelationKind kind, Relids relids)
 
AppendRelInfofind_childrel_appendrelinfo (PlannerInfo *root, RelOptInfo *rel)
 
Relids find_childrel_parents (PlannerInfo *root, RelOptInfo *rel)
 
ParamPathInfoget_baserel_parampathinfo (PlannerInfo *root, RelOptInfo *baserel, Relids required_outer)
 
ParamPathInfoget_joinrel_parampathinfo (PlannerInfo *root, RelOptInfo *joinrel, Path *outer_path, Path *inner_path, SpecialJoinInfo *sjinfo, Relids required_outer, List **restrict_clauses)
 
ParamPathInfoget_appendrel_parampathinfo (RelOptInfo *appendrel, Relids required_outer)
 
ParamPathInfofind_param_path_info (RelOptInfo *rel, Relids required_outer)
 

Typedef Documentation

◆ JoinHashEntry

Function Documentation

◆ add_join_rel()

static void add_join_rel ( PlannerInfo root,
RelOptInfo joinrel 
)
static

Definition at line 445 of file relnode.c.

References Assert, HASH_ENTER, hash_search(), JoinHashEntry::join_rel, PlannerInfo::join_rel_hash, PlannerInfo::join_rel_list, lappend(), and RelOptInfo::relids.

Referenced by build_child_join_rel(), and build_join_rel().

446 {
447  /* GEQO requires us to append the new joinrel to the end of the list! */
448  root->join_rel_list = lappend(root->join_rel_list, joinrel);
449 
450  /* store it into the auxiliary hashtable if there is one. */
451  if (root->join_rel_hash)
452  {
453  JoinHashEntry *hentry;
454  bool found;
455 
456  hentry = (JoinHashEntry *) hash_search(root->join_rel_hash,
457  &(joinrel->relids),
458  HASH_ENTER,
459  &found);
460  Assert(!found);
461  hentry->join_rel = joinrel;
462  }
463 }
List * join_rel_list
Definition: relation.h:218
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
RelOptInfo * join_rel
Definition: relnode.c:36
Relids relids
Definition: relation.h:600
List * lappend(List *list, void *datum)
Definition: list.c:128
#define Assert(condition)
Definition: c.h:699
struct HTAB * join_rel_hash
Definition: relation.h:219

◆ build_child_join_rel()

RelOptInfo* build_child_join_rel ( PlannerInfo root,
RelOptInfo outer_rel,
RelOptInfo inner_rel,
RelOptInfo parent_joinrel,
List restrictlist,
SpecialJoinInfo sjinfo,
JoinType  jointype 
)

Definition at line 686 of file relnode.c.

References add_join_rel(), add_placeholders_to_child_joinrel(), adjust_appendrel_attrs(), RelOptInfo::allvisfrac, Assert, RelOptInfo::attr_needed, RelOptInfo::attr_widths, RelOptInfo::baserestrictcost, RelOptInfo::baserestrictinfo, bms_copy(), bms_free(), bms_union(), RelOptInfo::boundinfo, build_joinrel_partition_info(), build_joinrel_tlist(), RelOptInfo::cheapest_parameterized_paths, RelOptInfo::cheapest_startup_path, RelOptInfo::cheapest_total_path, RelOptInfo::cheapest_unique_path, RelOptInfo::consider_parallel, RelOptInfo::consider_param_startup, RelOptInfo::consider_startup, create_empty_pathtarget(), RelOptInfo::direct_lateral_relids, RelOptInfo::fdw_private, RelOptInfo::fdwroutine, find_appinfos_by_relids(), find_join_rel(), RelOptInfo::has_eclass_joins, RelOptInfo::indexlist, InvalidOid, IS_OTHER_REL, RelOptInfo::joininfo, RelOptInfo::lateral_referencers, RelOptInfo::lateral_relids, RelOptInfo::lateral_vars, makeNode, RelOptInfo::max_attr, RelOptInfo::min_attr, NIL, RelOptInfo::nparts, RelOptInfo::nullable_partexprs, RelOptInfo::pages, RelOptInfo::part_rels, RelOptInfo::part_scheme, RelOptInfo::partexprs, RelOptInfo::partial_pathlist, RelOptInfo::partition_qual, RelOptInfo::partitioned_child_rels, RelOptInfo::pathlist, QualCost::per_tuple, pfree(), RelOptInfo::ppilist, RelOptInfo::relid, RelOptInfo::relids, RELOPT_OTHER_JOINREL, RelOptInfo::reloptkind, RelOptInfo::reltarget, RelOptInfo::rows, RTE_JOIN, RelOptInfo::rtekind, RelOptInfo::serverid, set_foreign_rel_properties(), set_joinrel_size_estimates(), QualCost::startup, RelOptInfo::subplan_params, RelOptInfo::subroot, RelOptInfo::top_parent_relids, PlannerInfo::tuple_fraction, RelOptInfo::tuples, RelOptInfo::userid, and RelOptInfo::useridiscurrent.

Referenced by try_partitionwise_join().

690 {
691  RelOptInfo *joinrel = makeNode(RelOptInfo);
692  AppendRelInfo **appinfos;
693  int nappinfos;
694 
695  /* Only joins between "other" relations land here. */
696  Assert(IS_OTHER_REL(outer_rel) && IS_OTHER_REL(inner_rel));
697 
698  joinrel->reloptkind = RELOPT_OTHER_JOINREL;
699  joinrel->relids = bms_union(outer_rel->relids, inner_rel->relids);
700  joinrel->rows = 0;
701  /* cheap startup cost is interesting iff not all tuples to be retrieved */
702  joinrel->consider_startup = (root->tuple_fraction > 0);
703  joinrel->consider_param_startup = false;
704  joinrel->consider_parallel = false;
705  joinrel->reltarget = create_empty_pathtarget();
706  joinrel->pathlist = NIL;
707  joinrel->ppilist = NIL;
708  joinrel->partial_pathlist = NIL;
709  joinrel->cheapest_startup_path = NULL;
710  joinrel->cheapest_total_path = NULL;
711  joinrel->cheapest_unique_path = NULL;
713  joinrel->direct_lateral_relids = NULL;
714  joinrel->lateral_relids = NULL;
715  joinrel->relid = 0; /* indicates not a baserel */
716  joinrel->rtekind = RTE_JOIN;
717  joinrel->min_attr = 0;
718  joinrel->max_attr = 0;
719  joinrel->attr_needed = NULL;
720  joinrel->attr_widths = NULL;
721  joinrel->lateral_vars = NIL;
722  joinrel->lateral_referencers = NULL;
723  joinrel->indexlist = NIL;
724  joinrel->pages = 0;
725  joinrel->tuples = 0;
726  joinrel->allvisfrac = 0;
727  joinrel->subroot = NULL;
728  joinrel->subplan_params = NIL;
729  joinrel->serverid = InvalidOid;
730  joinrel->userid = InvalidOid;
731  joinrel->useridiscurrent = false;
732  joinrel->fdwroutine = NULL;
733  joinrel->fdw_private = NULL;
734  joinrel->baserestrictinfo = NIL;
735  joinrel->baserestrictcost.startup = 0;
736  joinrel->baserestrictcost.per_tuple = 0;
737  joinrel->joininfo = NIL;
738  joinrel->has_eclass_joins = false;
739  joinrel->top_parent_relids = NULL;
740  joinrel->part_scheme = NULL;
741  joinrel->nparts = 0;
742  joinrel->boundinfo = NULL;
743  joinrel->partition_qual = NIL;
744  joinrel->part_rels = NULL;
745  joinrel->partexprs = NULL;
746  joinrel->nullable_partexprs = NULL;
747  joinrel->partitioned_child_rels = NIL;
748 
749  joinrel->top_parent_relids = bms_union(outer_rel->top_parent_relids,
750  inner_rel->top_parent_relids);
751 
752  /* Compute information relevant to foreign relations. */
753  set_foreign_rel_properties(joinrel, outer_rel, inner_rel);
754 
755  /* Build targetlist */
756  build_joinrel_tlist(root, joinrel, outer_rel);
757  build_joinrel_tlist(root, joinrel, inner_rel);
758  /* Add placeholder variables. */
759  add_placeholders_to_child_joinrel(root, joinrel, parent_joinrel);
760 
761  /* Construct joininfo list. */
762  appinfos = find_appinfos_by_relids(root, joinrel->relids, &nappinfos);
763  joinrel->joininfo = (List *) adjust_appendrel_attrs(root,
764  (Node *) parent_joinrel->joininfo,
765  nappinfos,
766  appinfos);
767  pfree(appinfos);
768 
769  /*
770  * Lateral relids referred in child join will be same as that referred in
771  * the parent relation. Throw any partial result computed while building
772  * the targetlist.
773  */
775  bms_free(joinrel->lateral_relids);
776  joinrel->direct_lateral_relids = (Relids) bms_copy(parent_joinrel->direct_lateral_relids);
777  joinrel->lateral_relids = (Relids) bms_copy(parent_joinrel->lateral_relids);
778 
779  /*
780  * If the parent joinrel has pending equivalence classes, so does the
781  * child.
782  */
783  joinrel->has_eclass_joins = parent_joinrel->has_eclass_joins;
784 
785  /* Is the join between partitions itself partitioned? */
786  build_joinrel_partition_info(joinrel, outer_rel, inner_rel, restrictlist,
787  jointype);
788 
789  /* Child joinrel is parallel safe if parent is parallel safe. */
790  joinrel->consider_parallel = parent_joinrel->consider_parallel;
791 
792 
793  /* Set estimates of the child-joinrel's size. */
794  set_joinrel_size_estimates(root, joinrel, outer_rel, inner_rel,
795  sjinfo, restrictlist);
796 
797  /* We build the join only once. */
798  Assert(!find_join_rel(root, joinrel->relids));
799 
800  /* Add the relation to the PlannerInfo. */
801  add_join_rel(root, joinrel);
802 
803  return joinrel;
804 }
bool has_eclass_joins
Definition: relation.h:666
struct Path * cheapest_unique_path
Definition: relation.h:619
PathTarget * create_empty_pathtarget(void)
Definition: tlist.c:653
#define NIL
Definition: pg_list.h:69
Bitmapset * bms_copy(const Bitmapset *a)
Definition: bitmapset.c:133
RelOptKind reloptkind
Definition: relation.h:597
Relids * attr_needed
Definition: relation.h:633
RelOptInfo * find_join_rel(PlannerInfo *root, Relids relids)
Definition: relnode.c:344
void set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo, List *restrictlist)
Definition: costsize.c:4374
struct Path * cheapest_startup_path
Definition: relation.h:617
Oid userid
Definition: relation.h:648
double tuples
Definition: relation.h:640
List * baserestrictinfo
Definition: relation.h:660
bool consider_param_startup
Definition: relation.h:607
Definition: nodes.h:517
List * partial_pathlist
Definition: relation.h:616
#define IS_OTHER_REL(rel)
Definition: relation.h:588
List * cheapest_parameterized_paths
Definition: relation.h:620
bool useridiscurrent
Definition: relation.h:649
List ** nullable_partexprs
Definition: relation.h:679
Cost startup
Definition: relation.h:46
double allvisfrac
Definition: relation.h:641
PlannerInfo * subroot
Definition: relation.h:642
bool consider_startup
Definition: relation.h:606
Relids lateral_relids
Definition: relation.h:625
Cost per_tuple
Definition: relation.h:47
static void set_foreign_rel_properties(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel)
Definition: relnode.c:407
double tuple_fraction
Definition: relation.h:295
void pfree(void *pointer)
Definition: mcxt.c:1031
List ** partexprs
Definition: relation.h:678
static void build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *input_rel)
Definition: relnode.c:858
struct Path * cheapest_total_path
Definition: relation.h:618
List * joininfo
Definition: relation.h:664
struct FdwRoutine * fdwroutine
Definition: relation.h:651
int nparts
Definition: relation.h:673
Relids relids
Definition: relation.h:600
List * ppilist
Definition: relation.h:615
Index relid
Definition: relation.h:628
Bitmapset * Relids
Definition: relation.h:29
Relids lateral_referencers
Definition: relation.h:636
Node * adjust_appendrel_attrs(PlannerInfo *root, Node *node, int nappinfos, AppendRelInfo **appinfos)
Definition: prepunion.c:2046
Oid serverid
Definition: relation.h:647
Relids direct_lateral_relids
Definition: relation.h:624
struct PartitionBoundInfoData * boundinfo
Definition: relation.h:674
AppendRelInfo ** find_appinfos_by_relids(PlannerInfo *root, Relids relids, int *nappinfos)
Definition: prepunion.c:2617
RTEKind rtekind
Definition: relation.h:630
List * indexlist
Definition: relation.h:637
double rows
Definition: relation.h:603
#define InvalidOid
Definition: postgres_ext.h:36
void * fdw_private
Definition: relation.h:652
void bms_free(Bitmapset *a)
Definition: bitmapset.c:267
#define makeNode(_type_)
Definition: nodes.h:565
BlockNumber pages
Definition: relation.h:639
#define Assert(condition)
Definition: c.h:699
List * lateral_vars
Definition: relation.h:635
void add_placeholders_to_child_joinrel(PlannerInfo *root, RelOptInfo *childrel, RelOptInfo *parentrel)
Definition: placeholder.c:474
struct RelOptInfo ** part_rels
Definition: relation.h:676
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:284
bool consider_parallel
Definition: relation.h:608
List * partitioned_child_rels
Definition: relation.h:680
AttrNumber max_attr
Definition: relation.h:632
static void build_joinrel_partition_info(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, List *restrictlist, JoinType jointype)
Definition: relnode.c:1604
PartitionScheme part_scheme
Definition: relation.h:672
List * pathlist
Definition: relation.h:614
List * partition_qual
Definition: relation.h:675
int32 * attr_widths
Definition: relation.h:634
Definition: pg_list.h:45
struct PathTarget * reltarget
Definition: relation.h:611
QualCost baserestrictcost
Definition: relation.h:661
static void add_join_rel(PlannerInfo *root, RelOptInfo *joinrel)
Definition: relnode.c:445
List * subplan_params
Definition: relation.h:643
Relids top_parent_relids
Definition: relation.h:669
AttrNumber min_attr
Definition: relation.h:631

◆ build_empty_join_rel()

RelOptInfo* build_empty_join_rel ( PlannerInfo root)

Definition at line 1111 of file relnode.c.

References Assert, create_empty_pathtarget(), PlannerInfo::join_rel_list, lappend(), makeNode, NIL, RelOptInfo::relids, RELOPT_JOINREL, RelOptInfo::reloptkind, RelOptInfo::reltarget, RelOptInfo::rows, RTE_JOIN, and RelOptInfo::rtekind.

Referenced by query_planner().

1112 {
1113  RelOptInfo *joinrel;
1114 
1115  /* The dummy join relation should be the only one ... */
1116  Assert(root->join_rel_list == NIL);
1117 
1118  joinrel = makeNode(RelOptInfo);
1119  joinrel->reloptkind = RELOPT_JOINREL;
1120  joinrel->relids = NULL; /* empty set */
1121  joinrel->rows = 1; /* we produce one row for such cases */
1122  joinrel->rtekind = RTE_JOIN;
1123  joinrel->reltarget = create_empty_pathtarget();
1124 
1125  root->join_rel_list = lappend(root->join_rel_list, joinrel);
1126 
1127  return joinrel;
1128 }
PathTarget * create_empty_pathtarget(void)
Definition: tlist.c:653
#define NIL
Definition: pg_list.h:69
RelOptKind reloptkind
Definition: relation.h:597
List * join_rel_list
Definition: relation.h:218
Relids relids
Definition: relation.h:600
List * lappend(List *list, void *datum)
Definition: list.c:128
RTEKind rtekind
Definition: relation.h:630
double rows
Definition: relation.h:603
#define makeNode(_type_)
Definition: nodes.h:565
#define Assert(condition)
Definition: c.h:699
struct PathTarget * reltarget
Definition: relation.h:611

◆ build_join_rel()

RelOptInfo* build_join_rel ( PlannerInfo root,
Relids  joinrelids,
RelOptInfo outer_rel,
RelOptInfo inner_rel,
SpecialJoinInfo sjinfo,
List **  restrictlist_ptr 
)

Definition at line 482 of file relnode.c.

References add_join_rel(), add_placeholders_to_joinrel(), RelOptInfo::allvisfrac, Assert, RelOptInfo::attr_needed, RelOptInfo::attr_widths, RelOptInfo::baserestrict_min_security, RelOptInfo::baserestrictcost, RelOptInfo::baserestrictinfo, bms_copy(), bms_del_members(), bms_is_empty(), bms_num_members(), bms_union(), RelOptInfo::boundinfo, build_joinrel_joinlist(), build_joinrel_partition_info(), build_joinrel_restrictlist(), build_joinrel_tlist(), RelOptInfo::cheapest_parameterized_paths, RelOptInfo::cheapest_startup_path, RelOptInfo::cheapest_total_path, RelOptInfo::cheapest_unique_path, RelOptInfo::consider_parallel, RelOptInfo::consider_param_startup, RelOptInfo::consider_startup, create_empty_pathtarget(), RelOptInfo::direct_lateral_relids, PathTarget::exprs, RelOptInfo::fdw_private, RelOptInfo::fdwroutine, find_join_rel(), RelOptInfo::has_eclass_joins, has_relevant_eclass_joinclause(), RelOptInfo::indexlist, InvalidOid, IS_OTHER_REL, is_parallel_safe(), PlannerInfo::join_cur_level, PlannerInfo::join_rel_level, RelOptInfo::joininfo, SpecialJoinInfo::jointype, lappend(), RelOptInfo::lateral_referencers, RelOptInfo::lateral_relids, RelOptInfo::lateral_vars, makeNode, RelOptInfo::max_attr, RelOptInfo::min_attr, min_join_parameterization(), NIL, RelOptInfo::non_unique_for_rels, RelOptInfo::nparts, RelOptInfo::nullable_partexprs, RelOptInfo::pages, RelOptInfo::part_rels, RelOptInfo::part_scheme, RelOptInfo::partexprs, RelOptInfo::partial_pathlist, RelOptInfo::partition_qual, RelOptInfo::partitioned_child_rels, RelOptInfo::pathlist, QualCost::per_tuple, RelOptInfo::ppilist, RelOptInfo::rel_parallel_workers, RelOptInfo::relid, RelOptInfo::relids, RELOPT_JOINREL, RelOptInfo::reloptkind, RelOptInfo::reltarget, RelOptInfo::rows, RTE_JOIN, RelOptInfo::rtekind, RelOptInfo::serverid, set_foreign_rel_properties(), set_joinrel_size_estimates(), QualCost::startup, RelOptInfo::statlist, RelOptInfo::subplan_params, RelOptInfo::subroot, RelOptInfo::top_parent_relids, PlannerInfo::tuple_fraction, RelOptInfo::tuples, RelOptInfo::unique_for_rels, RelOptInfo::userid, and RelOptInfo::useridiscurrent.

Referenced by make_join_rel().

488 {
489  RelOptInfo *joinrel;
490  List *restrictlist;
491 
492  /* This function should be used only for join between parents. */
493  Assert(!IS_OTHER_REL(outer_rel) && !IS_OTHER_REL(inner_rel));
494 
495  /*
496  * See if we already have a joinrel for this set of base rels.
497  */
498  joinrel = find_join_rel(root, joinrelids);
499 
500  if (joinrel)
501  {
502  /*
503  * Yes, so we only need to figure the restrictlist for this particular
504  * pair of component relations.
505  */
506  if (restrictlist_ptr)
507  *restrictlist_ptr = build_joinrel_restrictlist(root,
508  joinrel,
509  outer_rel,
510  inner_rel);
511  return joinrel;
512  }
513 
514  /*
515  * Nope, so make one.
516  */
517  joinrel = makeNode(RelOptInfo);
518  joinrel->reloptkind = RELOPT_JOINREL;
519  joinrel->relids = bms_copy(joinrelids);
520  joinrel->rows = 0;
521  /* cheap startup cost is interesting iff not all tuples to be retrieved */
522  joinrel->consider_startup = (root->tuple_fraction > 0);
523  joinrel->consider_param_startup = false;
524  joinrel->consider_parallel = false;
525  joinrel->reltarget = create_empty_pathtarget();
526  joinrel->pathlist = NIL;
527  joinrel->ppilist = NIL;
528  joinrel->partial_pathlist = NIL;
529  joinrel->cheapest_startup_path = NULL;
530  joinrel->cheapest_total_path = NULL;
531  joinrel->cheapest_unique_path = NULL;
533  /* init direct_lateral_relids from children; we'll finish it up below */
534  joinrel->direct_lateral_relids =
535  bms_union(outer_rel->direct_lateral_relids,
536  inner_rel->direct_lateral_relids);
537  joinrel->lateral_relids = min_join_parameterization(root, joinrel->relids,
538  outer_rel, inner_rel);
539  joinrel->relid = 0; /* indicates not a baserel */
540  joinrel->rtekind = RTE_JOIN;
541  joinrel->min_attr = 0;
542  joinrel->max_attr = 0;
543  joinrel->attr_needed = NULL;
544  joinrel->attr_widths = NULL;
545  joinrel->lateral_vars = NIL;
546  joinrel->lateral_referencers = NULL;
547  joinrel->indexlist = NIL;
548  joinrel->statlist = NIL;
549  joinrel->pages = 0;
550  joinrel->tuples = 0;
551  joinrel->allvisfrac = 0;
552  joinrel->subroot = NULL;
553  joinrel->subplan_params = NIL;
554  joinrel->rel_parallel_workers = -1;
555  joinrel->serverid = InvalidOid;
556  joinrel->userid = InvalidOid;
557  joinrel->useridiscurrent = false;
558  joinrel->fdwroutine = NULL;
559  joinrel->fdw_private = NULL;
560  joinrel->unique_for_rels = NIL;
561  joinrel->non_unique_for_rels = NIL;
562  joinrel->baserestrictinfo = NIL;
563  joinrel->baserestrictcost.startup = 0;
564  joinrel->baserestrictcost.per_tuple = 0;
565  joinrel->baserestrict_min_security = UINT_MAX;
566  joinrel->joininfo = NIL;
567  joinrel->has_eclass_joins = false;
568  joinrel->top_parent_relids = NULL;
569  joinrel->part_scheme = NULL;
570  joinrel->nparts = 0;
571  joinrel->boundinfo = NULL;
572  joinrel->partition_qual = NIL;
573  joinrel->part_rels = NULL;
574  joinrel->partexprs = NULL;
575  joinrel->nullable_partexprs = NULL;
576  joinrel->partitioned_child_rels = NIL;
577 
578  /* Compute information relevant to the foreign relations. */
579  set_foreign_rel_properties(joinrel, outer_rel, inner_rel);
580 
581  /*
582  * Create a new tlist containing just the vars that need to be output from
583  * this join (ie, are needed for higher joinclauses or final output).
584  *
585  * NOTE: the tlist order for a join rel will depend on which pair of outer
586  * and inner rels we first try to build it from. But the contents should
587  * be the same regardless.
588  */
589  build_joinrel_tlist(root, joinrel, outer_rel);
590  build_joinrel_tlist(root, joinrel, inner_rel);
591  add_placeholders_to_joinrel(root, joinrel, outer_rel, inner_rel);
592 
593  /*
594  * add_placeholders_to_joinrel also took care of adding the ph_lateral
595  * sets of any PlaceHolderVars computed here to direct_lateral_relids, so
596  * now we can finish computing that. This is much like the computation of
597  * the transitively-closed lateral_relids in min_join_parameterization,
598  * except that here we *do* have to consider the added PHVs.
599  */
600  joinrel->direct_lateral_relids =
601  bms_del_members(joinrel->direct_lateral_relids, joinrel->relids);
602  if (bms_is_empty(joinrel->direct_lateral_relids))
603  joinrel->direct_lateral_relids = NULL;
604 
605  /*
606  * Construct restrict and join clause lists for the new joinrel. (The
607  * caller might or might not need the restrictlist, but I need it anyway
608  * for set_joinrel_size_estimates().)
609  */
610  restrictlist = build_joinrel_restrictlist(root, joinrel,
611  outer_rel, inner_rel);
612  if (restrictlist_ptr)
613  *restrictlist_ptr = restrictlist;
614  build_joinrel_joinlist(joinrel, outer_rel, inner_rel);
615 
616  /*
617  * This is also the right place to check whether the joinrel has any
618  * pending EquivalenceClass joins.
619  */
620  joinrel->has_eclass_joins = has_relevant_eclass_joinclause(root, joinrel);
621 
622  /* Store the partition information. */
623  build_joinrel_partition_info(joinrel, outer_rel, inner_rel, restrictlist,
624  sjinfo->jointype);
625 
626  /*
627  * Set estimates of the joinrel's size.
628  */
629  set_joinrel_size_estimates(root, joinrel, outer_rel, inner_rel,
630  sjinfo, restrictlist);
631 
632  /*
633  * Set the consider_parallel flag if this joinrel could potentially be
634  * scanned within a parallel worker. If this flag is false for either
635  * inner_rel or outer_rel, then it must be false for the joinrel also.
636  * Even if both are true, there might be parallel-restricted expressions
637  * in the targetlist or quals.
638  *
639  * Note that if there are more than two rels in this relation, they could
640  * be divided between inner_rel and outer_rel in any arbitrary way. We
641  * assume this doesn't matter, because we should hit all the same baserels
642  * and joinclauses while building up to this joinrel no matter which we
643  * take; therefore, we should make the same decision here however we get
644  * here.
645  */
646  if (inner_rel->consider_parallel && outer_rel->consider_parallel &&
647  is_parallel_safe(root, (Node *) restrictlist) &&
648  is_parallel_safe(root, (Node *) joinrel->reltarget->exprs))
649  joinrel->consider_parallel = true;
650 
651  /* Add the joinrel to the PlannerInfo. */
652  add_join_rel(root, joinrel);
653 
654  /*
655  * Also, if dynamic-programming join search is active, add the new joinrel
656  * to the appropriate sublist. Note: you might think the Assert on number
657  * of members should be for equality, but some of the level 1 rels might
658  * have been joinrels already, so we can only assert <=.
659  */
660  if (root->join_rel_level)
661  {
662  Assert(root->join_cur_level > 0);
663  Assert(root->join_cur_level <= bms_num_members(joinrel->relids));
664  root->join_rel_level[root->join_cur_level] =
665  lappend(root->join_rel_level[root->join_cur_level], joinrel);
666  }
667 
668  return joinrel;
669 }
bool has_eclass_joins
Definition: relation.h:666
struct Path * cheapest_unique_path
Definition: relation.h:619
PathTarget * create_empty_pathtarget(void)
Definition: tlist.c:653
#define NIL
Definition: pg_list.h:69
int join_cur_level
Definition: relation.h:229
List * unique_for_rels
Definition: relation.h:655
List * statlist
Definition: relation.h:638
Bitmapset * bms_copy(const Bitmapset *a)
Definition: bitmapset.c:133
RelOptKind reloptkind
Definition: relation.h:597
Relids * attr_needed
Definition: relation.h:633
RelOptInfo * find_join_rel(PlannerInfo *root, Relids relids)
Definition: relnode.c:344
void set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo, List *restrictlist)
Definition: costsize.c:4374
struct Path * cheapest_startup_path
Definition: relation.h:617
Oid userid
Definition: relation.h:648
double tuples
Definition: relation.h:640
List * baserestrictinfo
Definition: relation.h:660
bool consider_param_startup
Definition: relation.h:607
Definition: nodes.h:517
List * partial_pathlist
Definition: relation.h:616
#define IS_OTHER_REL(rel)
Definition: relation.h:588
List * cheapest_parameterized_paths
Definition: relation.h:620
Index baserestrict_min_security
Definition: relation.h:662
bool useridiscurrent
Definition: relation.h:649
List ** nullable_partexprs
Definition: relation.h:679
void add_placeholders_to_joinrel(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel)
Definition: placeholder.c:412
Cost startup
Definition: relation.h:46
double allvisfrac
Definition: relation.h:641
PlannerInfo * subroot
Definition: relation.h:642
bool consider_startup
Definition: relation.h:606
bool is_parallel_safe(PlannerInfo *root, Node *node)
Definition: clauses.c:1088
Relids lateral_relids
Definition: relation.h:625
Cost per_tuple
Definition: relation.h:47
static void set_foreign_rel_properties(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel)
Definition: relnode.c:407
double tuple_fraction
Definition: relation.h:295
List ** partexprs
Definition: relation.h:678
static void build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *input_rel)
Definition: relnode.c:858
Relids min_join_parameterization(PlannerInfo *root, Relids joinrelids, RelOptInfo *outer_rel, RelOptInfo *inner_rel)
Definition: relnode.c:815
int bms_num_members(const Bitmapset *a)
Definition: bitmapset.c:671
struct Path * cheapest_total_path
Definition: relation.h:618
static List * build_joinrel_restrictlist(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel)
Definition: relnode.c:981
List * joininfo
Definition: relation.h:664
struct FdwRoutine * fdwroutine
Definition: relation.h:651
int nparts
Definition: relation.h:673
Relids relids
Definition: relation.h:600
bool has_relevant_eclass_joinclause(PlannerInfo *root, RelOptInfo *rel1)
Definition: equivclass.c:2397
List * non_unique_for_rels
Definition: relation.h:657
List * ppilist
Definition: relation.h:615
Index relid
Definition: relation.h:628
List * lappend(List *list, void *datum)
Definition: list.c:128
Relids lateral_referencers
Definition: relation.h:636
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:729
Oid serverid
Definition: relation.h:647
List * exprs
Definition: relation.h:996
Relids direct_lateral_relids
Definition: relation.h:624
int rel_parallel_workers
Definition: relation.h:644
struct PartitionBoundInfoData * boundinfo
Definition: relation.h:674
RTEKind rtekind
Definition: relation.h:630
List * indexlist
Definition: relation.h:637
double rows
Definition: relation.h:603
#define InvalidOid
Definition: postgres_ext.h:36
void * fdw_private
Definition: relation.h:652
#define makeNode(_type_)
Definition: nodes.h:565
BlockNumber pages
Definition: relation.h:639
#define Assert(condition)
Definition: c.h:699
List ** join_rel_level
Definition: relation.h:228
List * lateral_vars
Definition: relation.h:635
JoinType jointype
Definition: relation.h:2058
struct RelOptInfo ** part_rels
Definition: relation.h:676
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:284
bool consider_parallel
Definition: relation.h:608
Bitmapset * bms_del_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:955
List * partitioned_child_rels
Definition: relation.h:680
AttrNumber max_attr
Definition: relation.h:632
static void build_joinrel_partition_info(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, List *restrictlist, JoinType jointype)
Definition: relnode.c:1604
PartitionScheme part_scheme
Definition: relation.h:672
List * pathlist
Definition: relation.h:614
List * partition_qual
Definition: relation.h:675
int32 * attr_widths
Definition: relation.h:634
Definition: pg_list.h:45
struct PathTarget * reltarget
Definition: relation.h:611
QualCost baserestrictcost
Definition: relation.h:661
static void add_join_rel(PlannerInfo *root, RelOptInfo *joinrel)
Definition: relnode.c:445
List * subplan_params
Definition: relation.h:643
static void build_joinrel_joinlist(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel)
Definition: relnode.c:1011
Relids top_parent_relids
Definition: relation.h:669
AttrNumber min_attr
Definition: relation.h:631

◆ build_join_rel_hash()

static void build_join_rel_hash ( PlannerInfo root)
static

Definition at line 302 of file relnode.c.

References Assert, bitmap_hash(), bitmap_match(), CurrentMemoryContext, HASHCTL::entrysize, HASHCTL::hash, HASH_COMPARE, HASH_CONTEXT, hash_create(), HASH_ELEM, HASH_ENTER, HASH_FUNCTION, hash_search(), HASHCTL::hcxt, JoinHashEntry::join_rel, PlannerInfo::join_rel_hash, PlannerInfo::join_rel_list, HASHCTL::keysize, lfirst, HASHCTL::match, MemSet, and RelOptInfo::relids.

Referenced by find_join_rel().

303 {
304  HTAB *hashtab;
305  HASHCTL hash_ctl;
306  ListCell *l;
307 
308  /* Create the hash table */
309  MemSet(&hash_ctl, 0, sizeof(hash_ctl));
310  hash_ctl.keysize = sizeof(Relids);
311  hash_ctl.entrysize = sizeof(JoinHashEntry);
312  hash_ctl.hash = bitmap_hash;
313  hash_ctl.match = bitmap_match;
314  hash_ctl.hcxt = CurrentMemoryContext;
315  hashtab = hash_create("JoinRelHashTable",
316  256L,
317  &hash_ctl,
319 
320  /* Insert all the already-existing joinrels */
321  foreach(l, root->join_rel_list)
322  {
323  RelOptInfo *rel = (RelOptInfo *) lfirst(l);
324  JoinHashEntry *hentry;
325  bool found;
326 
327  hentry = (JoinHashEntry *) hash_search(hashtab,
328  &(rel->relids),
329  HASH_ENTER,
330  &found);
331  Assert(!found);
332  hentry->join_rel = rel;
333  }
334 
335  root->join_rel_hash = hashtab;
336 }
#define HASH_CONTEXT
Definition: hsearch.h:93
#define HASH_ELEM
Definition: hsearch.h:87
MemoryContext hcxt
Definition: hsearch.h:78
Size entrysize
Definition: hsearch.h:73
#define MemSet(start, val, len)
Definition: c.h:908
List * join_rel_list
Definition: relation.h:218
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
Definition: dynahash.c:208
struct JoinHashEntry JoinHashEntry
uint32 bitmap_hash(const void *key, Size keysize)
Definition: hashfn.c:76
RelOptInfo * join_rel
Definition: relnode.c:36
Relids relids
Definition: relation.h:600
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
int bitmap_match(const void *key1, const void *key2, Size keysize)
Definition: hashfn.c:86
Bitmapset * Relids
Definition: relation.h:29
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:316
Size keysize
Definition: hsearch.h:72
HashCompareFunc match
Definition: hsearch.h:75
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106
#define HASH_COMPARE
Definition: hsearch.h:90
struct HTAB * join_rel_hash
Definition: relation.h:219
HashValueFunc hash
Definition: hsearch.h:74
#define HASH_FUNCTION
Definition: hsearch.h:89

◆ build_joinrel_joinlist()

static void build_joinrel_joinlist ( RelOptInfo joinrel,
RelOptInfo outer_rel,
RelOptInfo inner_rel 
)
static

Definition at line 1011 of file relnode.c.

References RelOptInfo::joininfo, NIL, and subbuild_joinrel_joinlist().

Referenced by build_join_rel().

1014 {
1015  List *result;
1016 
1017  /*
1018  * Collect all the clauses that syntactically belong above this level,
1019  * eliminating any duplicates (important since we will see many of the
1020  * same clauses arriving from both input relations).
1021  */
1022  result = subbuild_joinrel_joinlist(joinrel, outer_rel->joininfo, NIL);
1023  result = subbuild_joinrel_joinlist(joinrel, inner_rel->joininfo, result);
1024 
1025  joinrel->joininfo = result;
1026 }
#define NIL
Definition: pg_list.h:69
List * joininfo
Definition: relation.h:664
static List * subbuild_joinrel_joinlist(RelOptInfo *joinrel, List *joininfo_list, List *new_joininfo)
Definition: relnode.c:1063
Definition: pg_list.h:45

◆ build_joinrel_partition_info()

static void build_joinrel_partition_info ( RelOptInfo joinrel,
RelOptInfo outer_rel,
RelOptInfo inner_rel,
List restrictlist,
JoinType  jointype 
)
static

Definition at line 1604 of file relnode.c.

References Assert, RelOptInfo::boundinfo, elog, enable_partitionwise_join, ERROR, have_partkey_equi_join(), IS_PARTITIONED_REL, JOIN_ANTI, JOIN_FULL, JOIN_INNER, JOIN_LEFT, JOIN_SEMI, list_concat(), list_copy(), NIL, RelOptInfo::nparts, RelOptInfo::nullable_partexprs, palloc0(), RelOptInfo::part_rels, RelOptInfo::part_scheme, RelOptInfo::partexprs, partition_bounds_equal(), PartitionSchemeData::partnatts, PartitionSchemeData::parttypbyval, PartitionSchemeData::parttyplen, and REL_HAS_ALL_PART_PROPS.

Referenced by build_child_join_rel(), and build_join_rel().

1607 {
1608  int partnatts;
1609  int cnt;
1610  PartitionScheme part_scheme;
1611 
1612  /* Nothing to do if partitionwise join technique is disabled. */
1614  {
1615  Assert(!IS_PARTITIONED_REL(joinrel));
1616  return;
1617  }
1618 
1619  /*
1620  * We can only consider this join as an input to further partitionwise
1621  * joins if (a) the input relations are partitioned, (b) the partition
1622  * schemes match, and (c) we can identify an equi-join between the
1623  * partition keys. Note that if it were possible for
1624  * have_partkey_equi_join to return different answers for the same joinrel
1625  * depending on which join ordering we try first, this logic would break.
1626  * That shouldn't happen, though, because of the way the query planner
1627  * deduces implied equalities and reorders the joins. Please see
1628  * optimizer/README for details.
1629  */
1630  if (!IS_PARTITIONED_REL(outer_rel) || !IS_PARTITIONED_REL(inner_rel) ||
1631  outer_rel->part_scheme != inner_rel->part_scheme ||
1632  !have_partkey_equi_join(joinrel, outer_rel, inner_rel,
1633  jointype, restrictlist))
1634  {
1635  Assert(!IS_PARTITIONED_REL(joinrel));
1636  return;
1637  }
1638 
1639  part_scheme = outer_rel->part_scheme;
1640 
1641  Assert(REL_HAS_ALL_PART_PROPS(outer_rel) &&
1642  REL_HAS_ALL_PART_PROPS(inner_rel));
1643 
1644  /*
1645  * For now, our partition matching algorithm can match partitions only
1646  * when the partition bounds of the joining relations are exactly same.
1647  * So, bail out otherwise.
1648  */
1649  if (outer_rel->nparts != inner_rel->nparts ||
1650  !partition_bounds_equal(part_scheme->partnatts,
1651  part_scheme->parttyplen,
1652  part_scheme->parttypbyval,
1653  outer_rel->boundinfo, inner_rel->boundinfo))
1654  {
1655  Assert(!IS_PARTITIONED_REL(joinrel));
1656  return;
1657  }
1658 
1659  /*
1660  * This function will be called only once for each joinrel, hence it
1661  * should not have partition scheme, partition bounds, partition key
1662  * expressions and array for storing child relations set.
1663  */
1664  Assert(!joinrel->part_scheme && !joinrel->partexprs &&
1665  !joinrel->nullable_partexprs && !joinrel->part_rels &&
1666  !joinrel->boundinfo);
1667 
1668  /*
1669  * Join relation is partitioned using the same partitioning scheme as the
1670  * joining relations and has same bounds.
1671  */
1672  joinrel->part_scheme = part_scheme;
1673  joinrel->boundinfo = outer_rel->boundinfo;
1674  partnatts = joinrel->part_scheme->partnatts;
1675  joinrel->partexprs = (List **) palloc0(sizeof(List *) * partnatts);
1676  joinrel->nullable_partexprs =
1677  (List **) palloc0(sizeof(List *) * partnatts);
1678  joinrel->nparts = outer_rel->nparts;
1679  joinrel->part_rels =
1680  (RelOptInfo **) palloc0(sizeof(RelOptInfo *) * joinrel->nparts);
1681 
1682 
1683  /*
1684  * Construct partition keys for the join.
1685  *
1686  * An INNER join between two partitioned relations can be regarded as
1687  * partitioned by either key expression. For example, A INNER JOIN B ON
1688  * A.a = B.b can be regarded as partitioned on A.a or on B.b; they are
1689  * equivalent.
1690  *
1691  * For a SEMI or ANTI join, the result can only be regarded as being
1692  * partitioned in the same manner as the outer side, since the inner
1693  * columns are not retained.
1694  *
1695  * An OUTER join like (A LEFT JOIN B ON A.a = B.b) may produce rows with
1696  * B.b NULL. These rows may not fit the partitioning conditions imposed on
1697  * B.b. Hence, strictly speaking, the join is not partitioned by B.b and
1698  * thus partition keys of an OUTER join should include partition key
1699  * expressions from the OUTER side only. However, because all
1700  * commonly-used comparison operators are strict, the presence of nulls on
1701  * the outer side doesn't cause any problem; they can't match anything at
1702  * future join levels anyway. Therefore, we track two sets of
1703  * expressions: those that authentically partition the relation
1704  * (partexprs) and those that partition the relation with the exception
1705  * that extra nulls may be present (nullable_partexprs). When the
1706  * comparison operator is strict, the latter is just as good as the
1707  * former.
1708  */
1709  for (cnt = 0; cnt < partnatts; cnt++)
1710  {
1711  List *outer_expr;
1712  List *outer_null_expr;
1713  List *inner_expr;
1714  List *inner_null_expr;
1715  List *partexpr = NIL;
1716  List *nullable_partexpr = NIL;
1717 
1718  outer_expr = list_copy(outer_rel->partexprs[cnt]);
1719  outer_null_expr = list_copy(outer_rel->nullable_partexprs[cnt]);
1720  inner_expr = list_copy(inner_rel->partexprs[cnt]);
1721  inner_null_expr = list_copy(inner_rel->nullable_partexprs[cnt]);
1722 
1723  switch (jointype)
1724  {
1725  case JOIN_INNER:
1726  partexpr = list_concat(outer_expr, inner_expr);
1727  nullable_partexpr = list_concat(outer_null_expr,
1728  inner_null_expr);
1729  break;
1730 
1731  case JOIN_SEMI:
1732  case JOIN_ANTI:
1733  partexpr = outer_expr;
1734  nullable_partexpr = outer_null_expr;
1735  break;
1736 
1737  case JOIN_LEFT:
1738  partexpr = outer_expr;
1739  nullable_partexpr = list_concat(inner_expr,
1740  outer_null_expr);
1741  nullable_partexpr = list_concat(nullable_partexpr,
1742  inner_null_expr);
1743  break;
1744 
1745  case JOIN_FULL:
1746  nullable_partexpr = list_concat(outer_expr,
1747  inner_expr);
1748  nullable_partexpr = list_concat(nullable_partexpr,
1749  outer_null_expr);
1750  nullable_partexpr = list_concat(nullable_partexpr,
1751  inner_null_expr);
1752  break;
1753 
1754  default:
1755  elog(ERROR, "unrecognized join type: %d", (int) jointype);
1756 
1757  }
1758 
1759  joinrel->partexprs[cnt] = partexpr;
1760  joinrel->nullable_partexprs[cnt] = nullable_partexpr;
1761  }
1762 }
#define NIL
Definition: pg_list.h:69
#define IS_PARTITIONED_REL(rel)
Definition: relation.h:694
List * list_copy(const List *oldlist)
Definition: list.c:1160
List * list_concat(List *list1, List *list2)
Definition: list.c:321
List ** nullable_partexprs
Definition: relation.h:679
List ** partexprs
Definition: relation.h:678
#define ERROR
Definition: elog.h:43
int16 * parttyplen
Definition: relation.h:359
int nparts
Definition: relation.h:673
#define REL_HAS_ALL_PART_PROPS(rel)
Definition: relation.h:702
void * palloc0(Size size)
Definition: mcxt.c:955
struct PartitionBoundInfoData * boundinfo
Definition: relation.h:674
#define Assert(condition)
Definition: c.h:699
struct RelOptInfo ** part_rels
Definition: relation.h:676
bool enable_partitionwise_join
Definition: costsize.c:137
bool have_partkey_equi_join(RelOptInfo *joinrel, RelOptInfo *rel1, RelOptInfo *rel2, JoinType jointype, List *restrictlist)
Definition: joinrels.c:1418
bool partition_bounds_equal(int partnatts, int16 *parttyplen, bool *parttypbyval, PartitionBoundInfo b1, PartitionBoundInfo b2)
Definition: partbounds.c:104
PartitionScheme part_scheme
Definition: relation.h:672
#define elog
Definition: elog.h:219
Definition: pg_list.h:45

◆ build_joinrel_restrictlist()

static List * build_joinrel_restrictlist ( PlannerInfo root,
RelOptInfo joinrel,
RelOptInfo outer_rel,
RelOptInfo inner_rel 
)
static

Definition at line 981 of file relnode.c.

References generate_join_implied_equalities(), RelOptInfo::joininfo, list_concat(), NIL, RelOptInfo::relids, and subbuild_joinrel_restrictlist().

Referenced by build_join_rel().

985 {
986  List *result;
987 
988  /*
989  * Collect all the clauses that syntactically belong at this level,
990  * eliminating any duplicates (important since we will see many of the
991  * same clauses arriving from both input relations).
992  */
993  result = subbuild_joinrel_restrictlist(joinrel, outer_rel->joininfo, NIL);
994  result = subbuild_joinrel_restrictlist(joinrel, inner_rel->joininfo, result);
995 
996  /*
997  * Add on any clauses derived from EquivalenceClasses. These cannot be
998  * redundant with the clauses in the joininfo lists, so don't bother
999  * checking.
1000  */
1001  result = list_concat(result,
1003  joinrel->relids,
1004  outer_rel->relids,
1005  inner_rel));
1006 
1007  return result;
1008 }
#define NIL
Definition: pg_list.h:69
static List * subbuild_joinrel_restrictlist(RelOptInfo *joinrel, List *joininfo_list, List *new_restrictlist)
Definition: relnode.c:1029
List * list_concat(List *list1, List *list2)
Definition: list.c:321
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:664
Relids relids
Definition: relation.h:600
Definition: pg_list.h:45

◆ build_joinrel_tlist()

static void build_joinrel_tlist ( PlannerInfo root,
RelOptInfo joinrel,
RelOptInfo input_rel 
)
static

Definition at line 858 of file relnode.c.

References ConvertRowtypeExpr::arg, Assert, RelOptInfo::attr_needed, RelOptInfo::attr_widths, bms_nonempty_difference(), elog, ERROR, PathTarget::exprs, find_base_rel(), IsA, lappend(), lfirst, RelOptInfo::min_attr, nodeTag, RelOptInfo::relids, RelOptInfo::reltarget, RelOptInfo::top_parent_relids, Var::varattno, Var::varno, and PathTarget::width.

Referenced by build_child_join_rel(), and build_join_rel().

860 {
861  Relids relids;
862  ListCell *vars;
863 
864  /* attrs_needed refers to parent relids and not those of a child. */
865  if (joinrel->top_parent_relids)
866  relids = joinrel->top_parent_relids;
867  else
868  relids = joinrel->relids;
869 
870  foreach(vars, input_rel->reltarget->exprs)
871  {
872  Var *var = (Var *) lfirst(vars);
873  RelOptInfo *baserel;
874  int ndx;
875 
876  /*
877  * Ignore PlaceHolderVars in the input tlists; we'll make our own
878  * decisions about whether to copy them.
879  */
880  if (IsA(var, PlaceHolderVar))
881  continue;
882 
883  /*
884  * Otherwise, anything in a baserel or joinrel targetlist ought to be
885  * a Var. Children of a partitioned table may have ConvertRowtypeExpr
886  * translating whole-row Var of a child to that of the parent.
887  * Children of an inherited table or subquery child rels can not
888  * directly participate in a join, so other kinds of nodes here.
889  */
890  if (IsA(var, Var))
891  {
892  baserel = find_base_rel(root, var->varno);
893  ndx = var->varattno - baserel->min_attr;
894  }
895  else if (IsA(var, ConvertRowtypeExpr))
896  {
897  ConvertRowtypeExpr *child_expr = (ConvertRowtypeExpr *) var;
898  Var *childvar = (Var *) child_expr->arg;
899 
900  /*
901  * Child's whole-row references are converted to look like those
902  * of parent using ConvertRowtypeExpr. There can be as many
903  * ConvertRowtypeExpr decorations as the depth of partition tree.
904  * The argument to the deepest ConvertRowtypeExpr is expected to
905  * be a whole-row reference of the child.
906  */
907  while (IsA(childvar, ConvertRowtypeExpr))
908  {
909  child_expr = (ConvertRowtypeExpr *) childvar;
910  childvar = (Var *) child_expr->arg;
911  }
912  Assert(IsA(childvar, Var) &&childvar->varattno == 0);
913 
914  baserel = find_base_rel(root, childvar->varno);
915  ndx = 0 - baserel->min_attr;
916  }
917  else
918  elog(ERROR, "unexpected node type in rel targetlist: %d",
919  (int) nodeTag(var));
920 
921 
922  /* Is the target expression still needed above this joinrel? */
923  if (bms_nonempty_difference(baserel->attr_needed[ndx], relids))
924  {
925  /* Yup, add it to the output */
926  joinrel->reltarget->exprs = lappend(joinrel->reltarget->exprs, var);
927 
928  /*
929  * Vars have cost zero, so no need to adjust reltarget->cost. Even
930  * if it's a ConvertRowtypeExpr, it will be computed only for the
931  * base relation, costing nothing for a join.
932  */
933  joinrel->reltarget->width += baserel->attr_widths[ndx];
934  }
935  }
936 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
Relids * attr_needed
Definition: relation.h:633
AttrNumber varattno
Definition: primnodes.h:169
Definition: primnodes.h:164
#define ERROR
Definition: elog.h:43
Relids relids
Definition: relation.h:600
List * lappend(List *list, void *datum)
Definition: list.c:128
Index varno
Definition: primnodes.h:167
List * exprs
Definition: relation.h:996
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106
#define nodeTag(nodeptr)
Definition: nodes.h:522
int width
Definition: relation.h:999
#define elog
Definition: elog.h:219
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition: relnode.c:279
int32 * attr_widths
Definition: relation.h:634
Definition: regcomp.c:224
struct PathTarget * reltarget
Definition: relation.h:611
Relids top_parent_relids
Definition: relation.h:669
bool bms_nonempty_difference(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:560
AttrNumber min_attr
Definition: relation.h:631

◆ build_simple_rel()

RelOptInfo* build_simple_rel ( PlannerInfo root,
int  relid,
RelOptInfo parent 
)

Definition at line 96 of file relnode.c.

References RelOptInfo::allvisfrac, PlannerInfo::append_rel_list, Assert, RelOptInfo::attr_needed, RelOptInfo::attr_widths, RelOptInfo::baserestrict_min_security, RelOptInfo::baserestrictcost, RelOptInfo::baserestrictinfo, bms_copy(), bms_make_singleton(), RelOptInfo::boundinfo, build_simple_rel(), RelOptInfo::cheapest_parameterized_paths, RelOptInfo::cheapest_startup_path, RelOptInfo::cheapest_total_path, RelOptInfo::cheapest_unique_path, RangeTblEntry::checkAsUser, AppendRelInfo::child_relid, Alias::colnames, RelOptInfo::consider_parallel, RelOptInfo::consider_param_startup, RelOptInfo::consider_startup, create_empty_pathtarget(), RelOptInfo::direct_lateral_relids, elog, RangeTblEntry::eref, ERROR, RelOptInfo::fdw_private, RelOptInfo::fdwroutine, get_relation_info(), RelOptInfo::has_eclass_joins, RelOptInfo::indexlist, RangeTblEntry::inh, InvalidOid, RelOptInfo::joininfo, RelOptInfo::lateral_referencers, RelOptInfo::lateral_relids, RelOptInfo::lateral_vars, lfirst, list_length(), makeNode, Max, RelOptInfo::max_attr, RelOptInfo::min_attr, NIL, RelOptInfo::non_unique_for_rels, RelOptInfo::nparts, RelOptInfo::nullable_partexprs, RelOptInfo::pages, palloc(), palloc0(), AppendRelInfo::parent_relid, RelOptInfo::part_rels, RelOptInfo::part_scheme, RelOptInfo::partexprs, RelOptInfo::partial_pathlist, RelOptInfo::partition_qual, RelOptInfo::partitioned_child_rels, RelOptInfo::pathlist, QualCost::per_tuple, RelOptInfo::ppilist, PlannerInfo::qual_security_level, RelOptInfo::rel_parallel_workers, RelOptInfo::relid, RangeTblEntry::relid, RelOptInfo::relids, RELOPT_BASEREL, RELOPT_OTHER_MEMBER_REL, RelOptInfo::reloptkind, RelOptInfo::reltarget, RelOptInfo::rows, RTE_CTE, RTE_FUNCTION, RTE_NAMEDTUPLESTORE, RTE_RELATION, RTE_SUBQUERY, RTE_TABLEFUNC, RTE_VALUES, RelOptInfo::rtekind, RangeTblEntry::rtekind, RangeTblEntry::securityQuals, RelOptInfo::serverid, PlannerInfo::simple_rel_array, PlannerInfo::simple_rte_array, QualCost::startup, RelOptInfo::statlist, RelOptInfo::subplan_params, RelOptInfo::subroot, RelOptInfo::top_parent_relids, PlannerInfo::tuple_fraction, RelOptInfo::tuples, RelOptInfo::unique_for_rels, RelOptInfo::userid, and RelOptInfo::useridiscurrent.

Referenced by add_base_rels_to_query(), build_simple_rel(), plan_cluster_use_sort(), plan_create_index_workers(), and recurse_set_operations().

97 {
98  RelOptInfo *rel;
99  RangeTblEntry *rte;
100 
101  /* Rel should not exist already */
102  Assert(relid > 0 && relid < root->simple_rel_array_size);
103  if (root->simple_rel_array[relid] != NULL)
104  elog(ERROR, "rel %d already exists", relid);
105 
106  /* Fetch RTE for relation */
107  rte = root->simple_rte_array[relid];
108  Assert(rte != NULL);
109 
110  rel = makeNode(RelOptInfo);
112  rel->relids = bms_make_singleton(relid);
113  rel->rows = 0;
114  /* cheap startup cost is interesting iff not all tuples to be retrieved */
115  rel->consider_startup = (root->tuple_fraction > 0);
116  rel->consider_param_startup = false; /* might get changed later */
117  rel->consider_parallel = false; /* might get changed later */
119  rel->pathlist = NIL;
120  rel->ppilist = NIL;
121  rel->partial_pathlist = NIL;
122  rel->cheapest_startup_path = NULL;
123  rel->cheapest_total_path = NULL;
124  rel->cheapest_unique_path = NULL;
126  rel->direct_lateral_relids = NULL;
127  rel->lateral_relids = NULL;
128  rel->relid = relid;
129  rel->rtekind = rte->rtekind;
130  /* min_attr, max_attr, attr_needed, attr_widths are set below */
131  rel->lateral_vars = NIL;
132  rel->lateral_referencers = NULL;
133  rel->indexlist = NIL;
134  rel->statlist = NIL;
135  rel->pages = 0;
136  rel->tuples = 0;
137  rel->allvisfrac = 0;
138  rel->subroot = NULL;
139  rel->subplan_params = NIL;
140  rel->rel_parallel_workers = -1; /* set up in get_relation_info */
141  rel->serverid = InvalidOid;
142  rel->userid = rte->checkAsUser;
143  rel->useridiscurrent = false;
144  rel->fdwroutine = NULL;
145  rel->fdw_private = NULL;
146  rel->unique_for_rels = NIL;
147  rel->non_unique_for_rels = NIL;
148  rel->baserestrictinfo = NIL;
149  rel->baserestrictcost.startup = 0;
150  rel->baserestrictcost.per_tuple = 0;
151  rel->baserestrict_min_security = UINT_MAX;
152  rel->joininfo = NIL;
153  rel->has_eclass_joins = false;
154  rel->part_scheme = NULL;
155  rel->nparts = 0;
156  rel->boundinfo = NULL;
157  rel->partition_qual = NIL;
158  rel->part_rels = NULL;
159  rel->partexprs = NULL;
160  rel->nullable_partexprs = NULL;
162 
163  /*
164  * Pass top parent's relids down the inheritance hierarchy. If the parent
165  * has top_parent_relids set, it's a direct or an indirect child of the
166  * top parent indicated by top_parent_relids. By extension this child is
167  * also an indirect child of that parent.
168  */
169  if (parent)
170  {
171  if (parent->top_parent_relids)
172  rel->top_parent_relids = parent->top_parent_relids;
173  else
174  rel->top_parent_relids = bms_copy(parent->relids);
175  }
176  else
177  rel->top_parent_relids = NULL;
178 
179  /* Check type of rtable entry */
180  switch (rte->rtekind)
181  {
182  case RTE_RELATION:
183  /* Table --- retrieve statistics from the system catalogs */
184  get_relation_info(root, rte->relid, rte->inh, rel);
185  break;
186  case RTE_SUBQUERY:
187  case RTE_FUNCTION:
188  case RTE_TABLEFUNC:
189  case RTE_VALUES:
190  case RTE_CTE:
191  case RTE_NAMEDTUPLESTORE:
192 
193  /*
194  * Subquery, function, tablefunc, values list, CTE, or ENR --- set
195  * up attr range and arrays
196  *
197  * Note: 0 is included in range to support whole-row Vars
198  */
199  rel->min_attr = 0;
200  rel->max_attr = list_length(rte->eref->colnames);
201  rel->attr_needed = (Relids *)
202  palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(Relids));
203  rel->attr_widths = (int32 *)
204  palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(int32));
205  break;
206  default:
207  elog(ERROR, "unrecognized RTE kind: %d",
208  (int) rte->rtekind);
209  break;
210  }
211 
212  /* Save the finished struct in the query's simple_rel_array */
213  root->simple_rel_array[relid] = rel;
214 
215  /*
216  * This is a convenient spot at which to note whether rels participating
217  * in the query have any securityQuals attached. If so, increase
218  * root->qual_security_level to ensure it's larger than the maximum
219  * security level needed for securityQuals.
220  */
221  if (rte->securityQuals)
223  list_length(rte->securityQuals));
224 
225  /*
226  * If this rel is an appendrel parent, recurse to build "other rel"
227  * RelOptInfos for its children. They are "other rels" because they are
228  * not in the main join tree, but we will need RelOptInfos to plan access
229  * to them.
230  */
231  if (rte->inh)
232  {
233  ListCell *l;
234  int nparts = rel->nparts;
235  int cnt_parts = 0;
236 
237  if (nparts > 0)
238  rel->part_rels = (RelOptInfo **)
239  palloc(sizeof(RelOptInfo *) * nparts);
240 
241  foreach(l, root->append_rel_list)
242  {
243  AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(l);
244  RelOptInfo *childrel;
245 
246  /* append_rel_list contains all append rels; ignore others */
247  if (appinfo->parent_relid != relid)
248  continue;
249 
250  childrel = build_simple_rel(root, appinfo->child_relid,
251  rel);
252 
253  /* Nothing more to do for an unpartitioned table. */
254  if (!rel->part_scheme)
255  continue;
256 
257  /*
258  * The order of partition OIDs in append_rel_list is the same as
259  * the order in the PartitionDesc, so the order of part_rels will
260  * also match the PartitionDesc. See expand_partitioned_rtentry.
261  */
262  Assert(cnt_parts < nparts);
263  rel->part_rels[cnt_parts] = childrel;
264  cnt_parts++;
265  }
266 
267  /* We should have seen all the child partitions. */
268  Assert(cnt_parts == nparts);
269  }
270 
271  return rel;
272 }
bool has_eclass_joins
Definition: relation.h:666
struct Path * cheapest_unique_path
Definition: relation.h:619
PathTarget * create_empty_pathtarget(void)
Definition: tlist.c:653
#define NIL
Definition: pg_list.h:69
List * unique_for_rels
Definition: relation.h:655
List * statlist
Definition: relation.h:638
Bitmapset * bms_copy(const Bitmapset *a)
Definition: bitmapset.c:133
RelOptKind reloptkind
Definition: relation.h:597
Relids * attr_needed
Definition: relation.h:633
List * colnames
Definition: primnodes.h:44
struct Path * cheapest_startup_path
Definition: relation.h:617
Oid userid
Definition: relation.h:648
List * securityQuals
Definition: parsenodes.h:1075
double tuples
Definition: relation.h:640
List * baserestrictinfo
Definition: relation.h:660
bool consider_param_startup
Definition: relation.h:607
List * partial_pathlist
Definition: relation.h:616
List * cheapest_parameterized_paths
Definition: relation.h:620
Index baserestrict_min_security
Definition: relation.h:662
bool useridiscurrent
Definition: relation.h:649
List ** nullable_partexprs
Definition: relation.h:679
Cost startup
Definition: relation.h:46
double allvisfrac
Definition: relation.h:641
signed int int32
Definition: c.h:313
struct RelOptInfo ** simple_rel_array
Definition: relation.h:182
PlannerInfo * subroot
Definition: relation.h:642
bool consider_startup
Definition: relation.h:606
Relids lateral_relids
Definition: relation.h:625
Cost per_tuple
Definition: relation.h:47
double tuple_fraction
Definition: relation.h:295
List ** partexprs
Definition: relation.h:678
#define ERROR
Definition: elog.h:43
struct Path * cheapest_total_path
Definition: relation.h:618
Bitmapset * bms_make_singleton(int x)
Definition: bitmapset.c:245
List * joininfo
Definition: relation.h:664
struct FdwRoutine * fdwroutine
Definition: relation.h:651
int nparts
Definition: relation.h:673
Relids relids
Definition: relation.h:600
RelOptInfo * build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
Definition: relnode.c:96
List * non_unique_for_rels
Definition: relation.h:657
List * ppilist
Definition: relation.h:615
Index relid
Definition: relation.h:628
Bitmapset * Relids
Definition: relation.h:29
RangeTblEntry ** simple_rte_array
Definition: relation.h:191
Relids lateral_referencers
Definition: relation.h:636
Oid serverid
Definition: relation.h:647
Relids direct_lateral_relids
Definition: relation.h:624
void * palloc0(Size size)
Definition: mcxt.c:955
int rel_parallel_workers
Definition: relation.h:644
List * append_rel_list
Definition: relation.h:255
struct PartitionBoundInfoData * boundinfo
Definition: relation.h:674
RTEKind rtekind
Definition: relation.h:630
List * indexlist
Definition: relation.h:637
double rows
Definition: relation.h:603
#define InvalidOid
Definition: postgres_ext.h:36
void * fdw_private
Definition: relation.h:652
#define Max(x, y)
Definition: c.h:851
#define makeNode(_type_)
Definition: nodes.h:565
BlockNumber pages
Definition: relation.h:639
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106
List * lateral_vars
Definition: relation.h:635
struct RelOptInfo ** part_rels
Definition: relation.h:676
static int list_length(const List *l)
Definition: pg_list.h:89
Index qual_security_level
Definition: relation.h:298
bool consider_parallel
Definition: relation.h:608
RTEKind rtekind
Definition: parsenodes.h:962
List * partitioned_child_rels
Definition: relation.h:680
AttrNumber max_attr
Definition: relation.h:632
void * palloc(Size size)
Definition: mcxt.c:924
PartitionScheme part_scheme
Definition: relation.h:672
List * pathlist
Definition: relation.h:614
#define elog
Definition: elog.h:219
Index child_relid
Definition: relation.h:2113
Alias * eref
Definition: parsenodes.h:1066
List * partition_qual
Definition: relation.h:675
Index parent_relid
Definition: relation.h:2112
int32 * attr_widths
Definition: relation.h:634
struct PathTarget * reltarget
Definition: relation.h:611
QualCost baserestrictcost
Definition: relation.h:661
List * subplan_params
Definition: relation.h:643
void get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, RelOptInfo *rel)
Definition: plancat.c:108
Relids top_parent_relids
Definition: relation.h:669
AttrNumber min_attr
Definition: relation.h:631

◆ fetch_upper_rel()

RelOptInfo* fetch_upper_rel ( PlannerInfo root,
UpperRelationKind  kind,
Relids  relids 
)

Definition at line 1145 of file relnode.c.

References bms_copy(), bms_equal(), RelOptInfo::cheapest_parameterized_paths, RelOptInfo::cheapest_startup_path, RelOptInfo::cheapest_total_path, RelOptInfo::cheapest_unique_path, RelOptInfo::consider_parallel, RelOptInfo::consider_param_startup, RelOptInfo::consider_startup, create_empty_pathtarget(), lappend(), lfirst, makeNode, NIL, RelOptInfo::pathlist, RelOptInfo::relids, RELOPT_UPPER_REL, RelOptInfo::reloptkind, RelOptInfo::reltarget, PlannerInfo::tuple_fraction, and PlannerInfo::upper_rels.

Referenced by add_rtes_to_flat_rtable(), create_distinct_paths(), create_ordered_paths(), create_partial_grouping_paths(), create_window_paths(), generate_nonunion_paths(), generate_recursion_path(), generate_union_paths(), grouping_planner(), inheritance_planner(), make_grouping_rel(), make_subplan(), make_union_unique(), preprocess_minmax_aggregates(), recurse_set_operations(), set_subquery_pathlist(), set_subquery_size_estimates(), SS_process_ctes(), standard_planner(), and subquery_planner().

1146 {
1147  RelOptInfo *upperrel;
1148  ListCell *lc;
1149 
1150  /*
1151  * For the moment, our indexing data structure is just a List for each
1152  * relation kind. If we ever get so many of one kind that this stops
1153  * working well, we can improve it. No code outside this function should
1154  * assume anything about how to find a particular upperrel.
1155  */
1156 
1157  /* If we already made this upperrel for the query, return it */
1158  foreach(lc, root->upper_rels[kind])
1159  {
1160  upperrel = (RelOptInfo *) lfirst(lc);
1161 
1162  if (bms_equal(upperrel->relids, relids))
1163  return upperrel;
1164  }
1165 
1166  upperrel = makeNode(RelOptInfo);
1167  upperrel->reloptkind = RELOPT_UPPER_REL;
1168  upperrel->relids = bms_copy(relids);
1169 
1170  /* cheap startup cost is interesting iff not all tuples to be retrieved */
1171  upperrel->consider_startup = (root->tuple_fraction > 0);
1172  upperrel->consider_param_startup = false;
1173  upperrel->consider_parallel = false; /* might get changed later */
1174  upperrel->reltarget = create_empty_pathtarget();
1175  upperrel->pathlist = NIL;
1176  upperrel->cheapest_startup_path = NULL;
1177  upperrel->cheapest_total_path = NULL;
1178  upperrel->cheapest_unique_path = NULL;
1179  upperrel->cheapest_parameterized_paths = NIL;
1180 
1181  root->upper_rels[kind] = lappend(root->upper_rels[kind], upperrel);
1182 
1183  return upperrel;
1184 }
struct Path * cheapest_unique_path
Definition: relation.h:619
PathTarget * create_empty_pathtarget(void)
Definition: tlist.c:653
#define NIL
Definition: pg_list.h:69
Bitmapset * bms_copy(const Bitmapset *a)
Definition: bitmapset.c:133
RelOptKind reloptkind
Definition: relation.h:597
struct Path * cheapest_startup_path
Definition: relation.h:617
bool consider_param_startup
Definition: relation.h:607
List * cheapest_parameterized_paths
Definition: relation.h:620
bool consider_startup
Definition: relation.h:606
double tuple_fraction
Definition: relation.h:295
struct Path * cheapest_total_path
Definition: relation.h:618
Relids relids
Definition: relation.h:600
List * lappend(List *list, void *datum)
Definition: list.c:128
#define makeNode(_type_)
Definition: nodes.h:565
#define lfirst(lc)
Definition: pg_list.h:106
bool consider_parallel
Definition: relation.h:608
List * pathlist
Definition: relation.h:614
struct PathTarget * reltarget
Definition: relation.h:611
bool bms_equal(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:153
List * upper_rels[UPPERREL_FINAL+1]
Definition: relation.h:276

◆ find_base_rel()

RelOptInfo* find_base_rel ( PlannerInfo root,
int  relid 
)

Definition at line 279 of file relnode.c.

References Assert, elog, ERROR, and PlannerInfo::simple_rel_array.

Referenced by add_join_clause_to_rels(), add_placeholders_to_base_rels(), add_vars_to_targetlist(), build_joinrel_tlist(), clause_selectivity(), create_lateral_join_info(), distribute_restrictinfo_to_rels(), examine_simple_variable(), examine_variable(), finalize_plan(), find_childrel_parents(), find_join_input_rel(), find_single_rel_for_clauses(), get_foreign_key_join_selectivity(), join_is_removable(), make_partition_pruneinfo(), make_rel_from_joinlist(), reduce_unique_semijoins(), remove_join_clause_from_rels(), remove_rel_from_query(), set_append_rel_size(), set_base_rel_consider_startup(), set_subquery_size_estimates(), and set_subqueryscan_references().

280 {
281  RelOptInfo *rel;
282 
283  Assert(relid > 0);
284 
285  if (relid < root->simple_rel_array_size)
286  {
287  rel = root->simple_rel_array[relid];
288  if (rel)
289  return rel;
290  }
291 
292  elog(ERROR, "no relation entry for relid %d", relid);
293 
294  return NULL; /* keep compiler quiet */
295 }
struct RelOptInfo ** simple_rel_array
Definition: relation.h:182
#define ERROR
Definition: elog.h:43
#define Assert(condition)
Definition: c.h:699
#define elog
Definition: elog.h:219

◆ find_childrel_appendrelinfo()

AppendRelInfo* find_childrel_appendrelinfo ( PlannerInfo root,
RelOptInfo rel 
)

Definition at line 1196 of file relnode.c.

References PlannerInfo::append_rel_list, Assert, AppendRelInfo::child_relid, elog, ERROR, lfirst, RelOptInfo::relid, RELOPT_OTHER_MEMBER_REL, and RelOptInfo::reloptkind.

Referenced by find_childrel_parents().

1197 {
1198  Index relid = rel->relid;
1199  ListCell *lc;
1200 
1201  /* Should only be called on child rels */
1203 
1204  foreach(lc, root->append_rel_list)
1205  {
1206  AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(lc);
1207 
1208  if (appinfo->child_relid == relid)
1209  return appinfo;
1210  }
1211  /* should have found the entry ... */
1212  elog(ERROR, "child rel %d not found in append_rel_list", relid);
1213  return NULL; /* not reached */
1214 }
RelOptKind reloptkind
Definition: relation.h:597
#define ERROR
Definition: elog.h:43
Index relid
Definition: relation.h:628
List * append_rel_list
Definition: relation.h:255
unsigned int Index
Definition: c.h:442
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106
#define elog
Definition: elog.h:219
Index child_relid
Definition: relation.h:2113

◆ find_childrel_parents()

Relids find_childrel_parents ( PlannerInfo root,
RelOptInfo rel 
)

Definition at line 1226 of file relnode.c.

References Assert, bms_add_member(), find_base_rel(), find_childrel_appendrelinfo(), AppendRelInfo::parent_relid, RELOPT_BASEREL, RELOPT_OTHER_MEMBER_REL, and RelOptInfo::reloptkind.

Referenced by check_index_predicates(), and generate_implied_equalities_for_column().

1227 {
1228  Relids result = NULL;
1229 
1231 
1232  do
1233  {
1234  AppendRelInfo *appinfo = find_childrel_appendrelinfo(root, rel);
1235  Index prelid = appinfo->parent_relid;
1236 
1237  result = bms_add_member(result, prelid);
1238 
1239  /* traverse up to the parent rel, loop if it's also a child rel */
1240  rel = find_base_rel(root, prelid);
1241  } while (rel->reloptkind == RELOPT_OTHER_MEMBER_REL);
1242 
1243  Assert(rel->reloptkind == RELOPT_BASEREL);
1244 
1245  return result;
1246 }
RelOptKind reloptkind
Definition: relation.h:597
AppendRelInfo * find_childrel_appendrelinfo(PlannerInfo *root, RelOptInfo *rel)
Definition: relnode.c:1196
unsigned int Index
Definition: c.h:442
#define Assert(condition)
Definition: c.h:699
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:764
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition: relnode.c:279
Index parent_relid
Definition: relation.h:2112

◆ find_join_rel()

RelOptInfo* find_join_rel ( PlannerInfo root,
Relids  relids 
)

Definition at line 344 of file relnode.c.

References bms_equal(), build_join_rel_hash(), HASH_FIND, hash_search(), JoinHashEntry::join_rel, PlannerInfo::join_rel_hash, PlannerInfo::join_rel_list, lfirst, list_length(), and RelOptInfo::relids.

Referenced by build_child_join_rel(), build_join_rel(), examine_variable(), find_join_input_rel(), and postgresPlanDirectModify().

345 {
346  /*
347  * Switch to using hash lookup when list grows "too long". The threshold
348  * is arbitrary and is known only here.
349  */
350  if (!root->join_rel_hash && list_length(root->join_rel_list) > 32)
351  build_join_rel_hash(root);
352 
353  /*
354  * Use either hashtable lookup or linear search, as appropriate.
355  *
356  * Note: the seemingly redundant hashkey variable is used to avoid taking
357  * the address of relids; unless the compiler is exceedingly smart, doing
358  * so would force relids out of a register and thus probably slow down the
359  * list-search case.
360  */
361  if (root->join_rel_hash)
362  {
363  Relids hashkey = relids;
364  JoinHashEntry *hentry;
365 
366  hentry = (JoinHashEntry *) hash_search(root->join_rel_hash,
367  &hashkey,
368  HASH_FIND,
369  NULL);
370  if (hentry)
371  return hentry->join_rel;
372  }
373  else
374  {
375  ListCell *l;
376 
377  foreach(l, root->join_rel_list)
378  {
379  RelOptInfo *rel = (RelOptInfo *) lfirst(l);
380 
381  if (bms_equal(rel->relids, relids))
382  return rel;
383  }
384  }
385 
386  return NULL;
387 }
List * join_rel_list
Definition: relation.h:218
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
RelOptInfo * join_rel
Definition: relnode.c:36
Relids relids
Definition: relation.h:600
static void build_join_rel_hash(PlannerInfo *root)
Definition: relnode.c:302
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89
struct HTAB * join_rel_hash
Definition: relation.h:219
bool bms_equal(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:153

◆ find_param_path_info()

ParamPathInfo* find_param_path_info ( RelOptInfo rel,
Relids  required_outer 
)

Definition at line 1581 of file relnode.c.

References bms_equal(), lfirst, ParamPathInfo::ppi_req_outer, and RelOptInfo::ppilist.

Referenced by get_appendrel_parampathinfo(), get_baserel_parampathinfo(), get_joinrel_parampathinfo(), and reparameterize_path_by_child().

1582 {
1583  ListCell *lc;
1584 
1585  foreach(lc, rel->ppilist)
1586  {
1587  ParamPathInfo *ppi = (ParamPathInfo *) lfirst(lc);
1588 
1589  if (bms_equal(ppi->ppi_req_outer, required_outer))
1590  return ppi;
1591  }
1592 
1593  return NULL;
1594 }
List * ppilist
Definition: relation.h:615
#define lfirst(lc)
Definition: pg_list.h:106
Relids ppi_req_outer
Definition: relation.h:1025
bool bms_equal(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:153

◆ get_appendrel_parampathinfo()

ParamPathInfo* get_appendrel_parampathinfo ( RelOptInfo appendrel,
Relids  required_outer 
)

Definition at line 1552 of file relnode.c.

References Assert, bms_is_empty(), bms_overlap(), find_param_path_info(), lappend(), makeNode, NIL, ParamPathInfo::ppi_clauses, ParamPathInfo::ppi_req_outer, ParamPathInfo::ppi_rows, RelOptInfo::ppilist, and RelOptInfo::relids.

Referenced by create_append_path(), and create_merge_append_path().

1553 {
1554  ParamPathInfo *ppi;
1555 
1556  /* Unparameterized paths have no ParamPathInfo */
1557  if (bms_is_empty(required_outer))
1558  return NULL;
1559 
1560  Assert(!bms_overlap(appendrel->relids, required_outer));
1561 
1562  /* If we already have a PPI for this parameterization, just return it */
1563  if ((ppi = find_param_path_info(appendrel, required_outer)))
1564  return ppi;
1565 
1566  /* Else build the ParamPathInfo */
1567  ppi = makeNode(ParamPathInfo);
1568  ppi->ppi_req_outer = required_outer;
1569  ppi->ppi_rows = 0;
1570  ppi->ppi_clauses = NIL;
1571  appendrel->ppilist = lappend(appendrel->ppilist, ppi);
1572 
1573  return ppi;
1574 }
#define NIL
Definition: pg_list.h:69
ParamPathInfo * find_param_path_info(RelOptInfo *rel, Relids required_outer)
Definition: relnode.c:1581
Relids relids
Definition: relation.h:600
List * ppilist
Definition: relation.h:615
List * lappend(List *list, void *datum)
Definition: list.c:128
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:729
#define makeNode(_type_)
Definition: nodes.h:565
#define Assert(condition)
Definition: c.h:699
List * ppi_clauses
Definition: relation.h:1027
double ppi_rows
Definition: relation.h:1026
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:509
Relids ppi_req_outer
Definition: relation.h:1025

◆ get_baserel_parampathinfo()

ParamPathInfo* get_baserel_parampathinfo ( PlannerInfo root,
RelOptInfo baserel,
Relids  required_outer 
)

Definition at line 1261 of file relnode.c.

References Assert, bms_is_empty(), bms_overlap(), bms_union(), find_param_path_info(), generate_join_implied_equalities(), get_parameterized_baserel_size(), join_clause_is_movable_into(), RelOptInfo::joininfo, lappend(), lfirst, list_concat(), makeNode, NIL, ParamPathInfo::ppi_clauses, ParamPathInfo::ppi_req_outer, ParamPathInfo::ppi_rows, RelOptInfo::ppilist, and RelOptInfo::relids.

Referenced by bitmap_and_cost_est(), bitmap_scan_cost_est(), create_append_path(), create_bitmap_heap_path(), create_ctescan_path(), create_foreignscan_path(), create_functionscan_path(), create_gather_merge_path(), create_gather_path(), create_index_path(), create_namedtuplestorescan_path(), create_samplescan_path(), create_seqscan_path(), create_subqueryscan_path(), create_tablefuncscan_path(), create_tidscan_path(), create_valuesscan_path(), create_worktablescan_path(), postgresGetForeignPaths(), and reparameterize_path().

1263 {
1264  ParamPathInfo *ppi;
1265  Relids joinrelids;
1266  List *pclauses;
1267  double rows;
1268  ListCell *lc;
1269 
1270  /* Unparameterized paths have no ParamPathInfo */
1271  if (bms_is_empty(required_outer))
1272  return NULL;
1273 
1274  Assert(!bms_overlap(baserel->relids, required_outer));
1275 
1276  /* If we already have a PPI for this parameterization, just return it */
1277  if ((ppi = find_param_path_info(baserel, required_outer)))
1278  return ppi;
1279 
1280  /*
1281  * Identify all joinclauses that are movable to this base rel given this
1282  * parameterization.
1283  */
1284  joinrelids = bms_union(baserel->relids, required_outer);
1285  pclauses = NIL;
1286  foreach(lc, baserel->joininfo)
1287  {
1288  RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1289 
1290  if (join_clause_is_movable_into(rinfo,
1291  baserel->relids,
1292  joinrelids))
1293  pclauses = lappend(pclauses, rinfo);
1294  }
1295 
1296  /*
1297  * Add in joinclauses generated by EquivalenceClasses, too. (These
1298  * necessarily satisfy join_clause_is_movable_into.)
1299  */
1300  pclauses = list_concat(pclauses,
1302  joinrelids,
1303  required_outer,
1304  baserel));
1305 
1306  /* Estimate the number of rows returned by the parameterized scan */
1307  rows = get_parameterized_baserel_size(root, baserel, pclauses);
1308 
1309  /* And now we can build the ParamPathInfo */
1310  ppi = makeNode(ParamPathInfo);
1311  ppi->ppi_req_outer = required_outer;
1312  ppi->ppi_rows = rows;
1313  ppi->ppi_clauses = pclauses;
1314  baserel->ppilist = lappend(baserel->ppilist, ppi);
1315 
1316  return ppi;
1317 }
#define NIL
Definition: pg_list.h:69
ParamPathInfo * find_param_path_info(RelOptInfo *rel, Relids required_outer)
Definition: relnode.c:1581
List * list_concat(List *list1, List *list2)
Definition: list.c:321
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:664
Relids relids
Definition: relation.h:600
bool join_clause_is_movable_into(RestrictInfo *rinfo, Relids currentrelids, Relids current_and_outer)
Definition: restrictinfo.c:511
List * ppilist
Definition: relation.h:615
List * lappend(List *list, void *datum)
Definition: list.c:128
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:729
double get_parameterized_baserel_size(PlannerInfo *root, RelOptInfo *rel, List *param_clauses)
Definition: costsize.c:4324
#define makeNode(_type_)
Definition: nodes.h:565
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106
List * ppi_clauses
Definition: relation.h:1027
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:284
double ppi_rows
Definition: relation.h:1026
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:509
Relids ppi_req_outer
Definition: relation.h:1025
Definition: pg_list.h:45

◆ get_joinrel_parampathinfo()

ParamPathInfo* get_joinrel_parampathinfo ( PlannerInfo root,
RelOptInfo joinrel,
Path outer_path,
Path inner_path,
SpecialJoinInfo sjinfo,
Relids  required_outer,
List **  restrict_clauses 
)

Definition at line 1348 of file relnode.c.

References Assert, bms_is_empty(), bms_overlap(), bms_union(), find_param_path_info(), generate_join_implied_equalities(), generate_join_implied_equalities_for_ecs(), get_parameterized_joinrel_size(), join_clause_is_movable_into(), RelOptInfo::joininfo, lappend(), RestrictInfo::left_ec, lfirst, list_concat(), makeNode, NIL, Path::param_info, Path::parent, PATH_REQ_OUTER, ParamPathInfo::ppi_clauses, ParamPathInfo::ppi_req_outer, ParamPathInfo::ppi_rows, RelOptInfo::ppilist, RelOptInfo::relids, and RestrictInfo::right_ec.

Referenced by create_hashjoin_path(), create_mergejoin_path(), and create_nestloop_path().

1354 {
1355  ParamPathInfo *ppi;
1356  Relids join_and_req;
1357  Relids outer_and_req;
1358  Relids inner_and_req;
1359  List *pclauses;
1360  List *eclauses;
1361  List *dropped_ecs;
1362  double rows;
1363  ListCell *lc;
1364 
1365  /* Unparameterized paths have no ParamPathInfo or extra join clauses */
1366  if (bms_is_empty(required_outer))
1367  return NULL;
1368 
1369  Assert(!bms_overlap(joinrel->relids, required_outer));
1370 
1371  /*
1372  * Identify all joinclauses that are movable to this join rel given this
1373  * parameterization. These are the clauses that are movable into this
1374  * join, but not movable into either input path. Treat an unparameterized
1375  * input path as not accepting parameterized clauses (because it won't,
1376  * per the shortcut exit above), even though the joinclause movement rules
1377  * might allow the same clauses to be moved into a parameterized path for
1378  * that rel.
1379  */
1380  join_and_req = bms_union(joinrel->relids, required_outer);
1381  if (outer_path->param_info)
1382  outer_and_req = bms_union(outer_path->parent->relids,
1383  PATH_REQ_OUTER(outer_path));
1384  else
1385  outer_and_req = NULL; /* outer path does not accept parameters */
1386  if (inner_path->param_info)
1387  inner_and_req = bms_union(inner_path->parent->relids,
1388  PATH_REQ_OUTER(inner_path));
1389  else
1390  inner_and_req = NULL; /* inner path does not accept parameters */
1391 
1392  pclauses = NIL;
1393  foreach(lc, joinrel->joininfo)
1394  {
1395  RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1396 
1397  if (join_clause_is_movable_into(rinfo,
1398  joinrel->relids,
1399  join_and_req) &&
1401  outer_path->parent->relids,
1402  outer_and_req) &&
1404  inner_path->parent->relids,
1405  inner_and_req))
1406  pclauses = lappend(pclauses, rinfo);
1407  }
1408 
1409  /* Consider joinclauses generated by EquivalenceClasses, too */
1410  eclauses = generate_join_implied_equalities(root,
1411  join_and_req,
1412  required_outer,
1413  joinrel);
1414  /* We only want ones that aren't movable to lower levels */
1415  dropped_ecs = NIL;
1416  foreach(lc, eclauses)
1417  {
1418  RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1419 
1420  /*
1421  * In principle, join_clause_is_movable_into() should accept anything
1422  * returned by generate_join_implied_equalities(); but because its
1423  * analysis is only approximate, sometimes it doesn't. So we
1424  * currently cannot use this Assert; instead just assume it's okay to
1425  * apply the joinclause at this level.
1426  */
1427 #ifdef NOT_USED
1429  joinrel->relids,
1430  join_and_req));
1431 #endif
1432  if (join_clause_is_movable_into(rinfo,
1433  outer_path->parent->relids,
1434  outer_and_req))
1435  continue; /* drop if movable into LHS */
1436  if (join_clause_is_movable_into(rinfo,
1437  inner_path->parent->relids,
1438  inner_and_req))
1439  {
1440  /* drop if movable into RHS, but remember EC for use below */
1441  Assert(rinfo->left_ec == rinfo->right_ec);
1442  dropped_ecs = lappend(dropped_ecs, rinfo->left_ec);
1443  continue;
1444  }
1445  pclauses = lappend(pclauses, rinfo);
1446  }
1447 
1448  /*
1449  * EquivalenceClasses are harder to deal with than we could wish, because
1450  * of the fact that a given EC can generate different clauses depending on
1451  * context. Suppose we have an EC {X.X, Y.Y, Z.Z} where X and Y are the
1452  * LHS and RHS of the current join and Z is in required_outer, and further
1453  * suppose that the inner_path is parameterized by both X and Z. The code
1454  * above will have produced either Z.Z = X.X or Z.Z = Y.Y from that EC,
1455  * and in the latter case will have discarded it as being movable into the
1456  * RHS. However, the EC machinery might have produced either Y.Y = X.X or
1457  * Y.Y = Z.Z as the EC enforcement clause within the inner_path; it will
1458  * not have produced both, and we can't readily tell from here which one
1459  * it did pick. If we add no clause to this join, we'll end up with
1460  * insufficient enforcement of the EC; either Z.Z or X.X will fail to be
1461  * constrained to be equal to the other members of the EC. (When we come
1462  * to join Z to this X/Y path, we will certainly drop whichever EC clause
1463  * is generated at that join, so this omission won't get fixed later.)
1464  *
1465  * To handle this, for each EC we discarded such a clause from, try to
1466  * generate a clause connecting the required_outer rels to the join's LHS
1467  * ("Z.Z = X.X" in the terms of the above example). If successful, and if
1468  * the clause can't be moved to the LHS, add it to the current join's
1469  * restriction clauses. (If an EC cannot generate such a clause then it
1470  * has nothing that needs to be enforced here, while if the clause can be
1471  * moved into the LHS then it should have been enforced within that path.)
1472  *
1473  * Note that we don't need similar processing for ECs whose clause was
1474  * considered to be movable into the LHS, because the LHS can't refer to
1475  * the RHS so there is no comparable ambiguity about what it might
1476  * actually be enforcing internally.
1477  */
1478  if (dropped_ecs)
1479  {
1480  Relids real_outer_and_req;
1481 
1482  real_outer_and_req = bms_union(outer_path->parent->relids,
1483  required_outer);
1484  eclauses =
1486  dropped_ecs,
1487  real_outer_and_req,
1488  required_outer,
1489  outer_path->parent);
1490  foreach(lc, eclauses)
1491  {
1492  RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1493 
1494  /* As above, can't quite assert this here */
1495 #ifdef NOT_USED
1497  outer_path->parent->relids,
1498  real_outer_and_req));
1499 #endif
1500  if (!join_clause_is_movable_into(rinfo,
1501  outer_path->parent->relids,
1502  outer_and_req))
1503  pclauses = lappend(pclauses, rinfo);
1504  }
1505  }
1506 
1507  /*
1508  * Now, attach the identified moved-down clauses to the caller's
1509  * restrict_clauses list. By using list_concat in this order, we leave
1510  * the original list structure of restrict_clauses undamaged.
1511  */
1512  *restrict_clauses = list_concat(pclauses, *restrict_clauses);
1513 
1514  /* If we already have a PPI for this parameterization, just return it */
1515  if ((ppi = find_param_path_info(joinrel, required_outer)))
1516  return ppi;
1517 
1518  /* Estimate the number of rows returned by the parameterized join */
1519  rows = get_parameterized_joinrel_size(root, joinrel,
1520  outer_path,
1521  inner_path,
1522  sjinfo,
1523  *restrict_clauses);
1524 
1525  /*
1526  * And now we can build the ParamPathInfo. No point in saving the
1527  * input-pair-dependent clause list, though.
1528  *
1529  * Note: in GEQO mode, we'll be called in a temporary memory context, but
1530  * the joinrel structure is there too, so no problem.
1531  */
1532  ppi = makeNode(ParamPathInfo);
1533  ppi->ppi_req_outer = required_outer;
1534  ppi->ppi_rows = rows;
1535  ppi->ppi_clauses = NIL;
1536  joinrel->ppilist = lappend(joinrel->ppilist, ppi);
1537 
1538  return ppi;
1539 }
#define NIL
Definition: pg_list.h:69
ParamPathInfo * find_param_path_info(RelOptInfo *rel, Relids required_outer)
Definition: relnode.c:1581
ParamPathInfo * param_info
Definition: relation.h:1069
List * list_concat(List *list1, List *list2)
Definition: list.c:321
EquivalenceClass * right_ec
Definition: relation.h:1917
List * generate_join_implied_equalities(PlannerInfo *root, Relids join_relids, Relids outer_relids, RelOptInfo *inner_rel)
Definition: equivclass.c:1071
RelOptInfo * parent
Definition: relation.h:1066
double get_parameterized_joinrel_size(PlannerInfo *root, RelOptInfo *rel, Path *outer_path, Path *inner_path, SpecialJoinInfo *sjinfo, List *restrict_clauses)
Definition: costsize.c:4406
List * joininfo
Definition: relation.h:664
Relids relids
Definition: relation.h:600
bool join_clause_is_movable_into(RestrictInfo *rinfo, Relids currentrelids, Relids current_and_outer)
Definition: restrictinfo.c:511
List * ppilist
Definition: relation.h:615
List * lappend(List *list, void *datum)
Definition: list.c:128
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:729
List * generate_join_implied_equalities_for_ecs(PlannerInfo *root, List *eclasses, Relids join_relids, Relids outer_relids, RelOptInfo *inner_rel)
Definition: equivclass.c:1088
#define makeNode(_type_)
Definition: nodes.h:565
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106
#define PATH_REQ_OUTER(path)
Definition: relation.h:1085
List * ppi_clauses
Definition: relation.h:1027
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:284
double ppi_rows
Definition: relation.h:1026
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:509
EquivalenceClass * left_ec
Definition: relation.h:1916
Relids ppi_req_outer
Definition: relation.h:1025
Definition: pg_list.h:45

◆ min_join_parameterization()

Relids min_join_parameterization ( PlannerInfo root,
Relids  joinrelids,
RelOptInfo outer_rel,
RelOptInfo inner_rel 
)

Definition at line 815 of file relnode.c.

References bms_del_members(), bms_is_empty(), bms_union(), and RelOptInfo::lateral_relids.

Referenced by build_join_rel(), and join_is_legal().

819 {
820  Relids result;
821 
822  /*
823  * Basically we just need the union of the inputs' lateral_relids, less
824  * whatever is already in the join.
825  *
826  * It's not immediately obvious that this is a valid way to compute the
827  * result, because it might seem that we're ignoring possible lateral refs
828  * of PlaceHolderVars that are due to be computed at the join but not in
829  * either input. However, because create_lateral_join_info() already
830  * charged all such PHV refs to each member baserel of the join, they'll
831  * be accounted for already in the inputs' lateral_relids. Likewise, we
832  * do not need to worry about doing transitive closure here, because that
833  * was already accounted for in the original baserel lateral_relids.
834  */
835  result = bms_union(outer_rel->lateral_relids, inner_rel->lateral_relids);
836  result = bms_del_members(result, joinrelids);
837 
838  /* Maintain invariant that result is exactly NULL if empty */
839  if (bms_is_empty(result))
840  result = NULL;
841 
842  return result;
843 }
Relids lateral_relids
Definition: relation.h:625
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:729
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:284
Bitmapset * bms_del_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:955

◆ set_foreign_rel_properties()

static void set_foreign_rel_properties ( RelOptInfo joinrel,
RelOptInfo outer_rel,
RelOptInfo inner_rel 
)
static

Definition at line 407 of file relnode.c.

References RelOptInfo::fdwroutine, GetUserId(), OidIsValid, RelOptInfo::serverid, RelOptInfo::userid, and RelOptInfo::useridiscurrent.

Referenced by build_child_join_rel(), and build_join_rel().

409 {
410  if (OidIsValid(outer_rel->serverid) &&
411  inner_rel->serverid == outer_rel->serverid)
412  {
413  if (inner_rel->userid == outer_rel->userid)
414  {
415  joinrel->serverid = outer_rel->serverid;
416  joinrel->userid = outer_rel->userid;
417  joinrel->useridiscurrent = outer_rel->useridiscurrent || inner_rel->useridiscurrent;
418  joinrel->fdwroutine = outer_rel->fdwroutine;
419  }
420  else if (!OidIsValid(inner_rel->userid) &&
421  outer_rel->userid == GetUserId())
422  {
423  joinrel->serverid = outer_rel->serverid;
424  joinrel->userid = outer_rel->userid;
425  joinrel->useridiscurrent = true;
426  joinrel->fdwroutine = outer_rel->fdwroutine;
427  }
428  else if (!OidIsValid(outer_rel->userid) &&
429  inner_rel->userid == GetUserId())
430  {
431  joinrel->serverid = outer_rel->serverid;
432  joinrel->userid = inner_rel->userid;
433  joinrel->useridiscurrent = true;
434  joinrel->fdwroutine = outer_rel->fdwroutine;
435  }
436  }
437 }
Oid GetUserId(void)
Definition: miscinit.c:379
Oid userid
Definition: relation.h:648
bool useridiscurrent
Definition: relation.h:649
#define OidIsValid(objectId)
Definition: c.h:605
struct FdwRoutine * fdwroutine
Definition: relation.h:651
Oid serverid
Definition: relation.h:647

◆ setup_simple_rel_arrays()

void setup_simple_rel_arrays ( PlannerInfo root)

Definition at line 67 of file relnode.c.

References lfirst, list_length(), palloc0(), PlannerInfo::parse, Query::rtable, PlannerInfo::simple_rel_array, PlannerInfo::simple_rel_array_size, and PlannerInfo::simple_rte_array.

Referenced by plan_cluster_use_sort(), plan_create_index_workers(), plan_set_operations(), and query_planner().

68 {
69  Index rti;
70  ListCell *lc;
71 
72  /* Arrays are accessed using RT indexes (1..N) */
73  root->simple_rel_array_size = list_length(root->parse->rtable) + 1;
74 
75  /* simple_rel_array is initialized to all NULLs */
76  root->simple_rel_array = (RelOptInfo **)
77  palloc0(root->simple_rel_array_size * sizeof(RelOptInfo *));
78 
79  /* simple_rte_array is an array equivalent of the rtable list */
80  root->simple_rte_array = (RangeTblEntry **)
81  palloc0(root->simple_rel_array_size * sizeof(RangeTblEntry *));
82  rti = 1;
83  foreach(lc, root->parse->rtable)
84  {
85  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
86 
87  root->simple_rte_array[rti++] = rte;
88  }
89 }
Query * parse
Definition: relation.h:158
struct RelOptInfo ** simple_rel_array
Definition: relation.h:182
List * rtable
Definition: parsenodes.h:137
int simple_rel_array_size
Definition: relation.h:183
RangeTblEntry ** simple_rte_array
Definition: relation.h:191
void * palloc0(Size size)
Definition: mcxt.c:955
unsigned int Index
Definition: c.h:442
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89

◆ subbuild_joinrel_joinlist()

static List * subbuild_joinrel_joinlist ( RelOptInfo joinrel,
List joininfo_list,
List new_joininfo 
)
static

Definition at line 1063 of file relnode.c.

References Assert, bms_is_subset(), lfirst, list_append_unique_ptr(), RelOptInfo::relids, RELOPT_JOINREL, RelOptInfo::reloptkind, and RestrictInfo::required_relids.

Referenced by build_joinrel_joinlist().

1066 {
1067  ListCell *l;
1068 
1069  /* Expected to be called only for join between parent relations. */
1070  Assert(joinrel->reloptkind == RELOPT_JOINREL);
1071 
1072  foreach(l, joininfo_list)
1073  {
1074  RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
1075 
1076  if (bms_is_subset(rinfo->required_relids, joinrel->relids))
1077  {
1078  /*
1079  * This clause becomes a restriction clause for the joinrel, since
1080  * it refers to no outside rels. So we can ignore it in this
1081  * routine.
1082  */
1083  }
1084  else
1085  {
1086  /*
1087  * This clause is still a join clause at this level, so add it to
1088  * the new joininfo list, being careful to eliminate duplicates.
1089  * (Since RestrictInfo nodes in different joinlists will have been
1090  * multiply-linked rather than copied, pointer equality should be
1091  * a sufficient test.)
1092  */
1093  new_joininfo = list_append_unique_ptr(new_joininfo, rinfo);
1094  }
1095  }
1096 
1097  return new_joininfo;
1098 }
RelOptKind reloptkind
Definition: relation.h:597
Relids required_relids
Definition: relation.h:1886
List * list_append_unique_ptr(List *list, void *datum)
Definition: list.c:975
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:374
Relids relids
Definition: relation.h:600
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106

◆ subbuild_joinrel_restrictlist()

static List * subbuild_joinrel_restrictlist ( RelOptInfo joinrel,
List joininfo_list,
List new_restrictlist 
)
static

Definition at line 1029 of file relnode.c.

References bms_is_subset(), lfirst, list_append_unique_ptr(), RelOptInfo::relids, and RestrictInfo::required_relids.

Referenced by build_joinrel_restrictlist().

1032 {
1033  ListCell *l;
1034 
1035  foreach(l, joininfo_list)
1036  {
1037  RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
1038 
1039  if (bms_is_subset(rinfo->required_relids, joinrel->relids))
1040  {
1041  /*
1042  * This clause becomes a restriction clause for the joinrel, since
1043  * it refers to no outside rels. Add it to the list, being
1044  * careful to eliminate duplicates. (Since RestrictInfo nodes in
1045  * different joinlists will have been multiply-linked rather than
1046  * copied, pointer equality should be a sufficient test.)
1047  */
1048  new_restrictlist = list_append_unique_ptr(new_restrictlist, rinfo);
1049  }
1050  else
1051  {
1052  /*
1053  * This clause is still a join clause at this level, so we ignore
1054  * it in this routine.
1055  */
1056  }
1057  }
1058 
1059  return new_restrictlist;
1060 }
Relids required_relids
Definition: relation.h:1886
List * list_append_unique_ptr(List *list, void *datum)
Definition: list.c:975
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:374
Relids relids
Definition: relation.h:600
#define lfirst(lc)
Definition: pg_list.h:106