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

Go to the source code of this file.

Typedefs

typedef void(* set_rel_pathlist_hook_type) (PlannerInfo *root, RelOptInfo *rel, Index rti, RangeTblEntry *rte)
 
typedef void(* set_join_pathlist_hook_type) (PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, JoinPathExtraData *extra)
 
typedef RelOptInfo *(* join_search_hook_type) (PlannerInfo *root, int levels_needed, List *initial_rels)
 
typedef bool(* ec_matches_callback_type) (PlannerInfo *root, RelOptInfo *rel, EquivalenceClass *ec, EquivalenceMember *em, void *arg)
 

Enumerations

enum  PathKeysComparison { PATHKEYS_EQUAL , PATHKEYS_BETTER1 , PATHKEYS_BETTER2 , PATHKEYS_DIFFERENT }
 

Functions

RelOptInfomake_one_rel (PlannerInfo *root, List *joinlist)
 
RelOptInfostandard_join_search (PlannerInfo *root, int levels_needed, List *initial_rels)
 
void generate_gather_paths (PlannerInfo *root, RelOptInfo *rel, bool override_rows)
 
void generate_useful_gather_paths (PlannerInfo *root, RelOptInfo *rel, bool override_rows)
 
int compute_parallel_worker (RelOptInfo *rel, double heap_pages, double index_pages, int max_workers)
 
void create_partial_bitmap_paths (PlannerInfo *root, RelOptInfo *rel, Path *bitmapqual)
 
void generate_partitionwise_join_paths (PlannerInfo *root, RelOptInfo *rel)
 
void create_index_paths (PlannerInfo *root, RelOptInfo *rel)
 
bool relation_has_unique_index_for (PlannerInfo *root, RelOptInfo *rel, List *restrictlist, List *exprlist, List *oprlist)
 
bool relation_has_unique_index_ext (PlannerInfo *root, RelOptInfo *rel, List *restrictlist, List *exprlist, List *oprlist, List **extra_clauses)
 
bool indexcol_is_bool_constant_for_query (PlannerInfo *root, IndexOptInfo *index, int indexcol)
 
bool match_index_to_operand (Node *operand, int indexcol, IndexOptInfo *index)
 
void check_index_predicates (PlannerInfo *root, RelOptInfo *rel)
 
void create_tidscan_paths (PlannerInfo *root, RelOptInfo *rel)
 
void add_paths_to_joinrel (PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, SpecialJoinInfo *sjinfo, List *restrictlist)
 
void join_search_one_level (PlannerInfo *root, int level)
 
RelOptInfomake_join_rel (PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2)
 
Relids add_outer_joins_to_relids (PlannerInfo *root, Relids input_relids, SpecialJoinInfo *sjinfo, List **pushed_down_joins)
 
bool have_join_order_restriction (PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2)
 
bool have_dangerous_phv (PlannerInfo *root, Relids outer_relids, Relids inner_params)
 
void mark_dummy_rel (RelOptInfo *rel)
 
bool process_equivalence (PlannerInfo *root, RestrictInfo **p_restrictinfo, JoinDomain *jdomain)
 
Exprcanonicalize_ec_expression (Expr *expr, Oid req_type, Oid req_collation)
 
void reconsider_outer_join_clauses (PlannerInfo *root)
 
EquivalenceClassget_eclass_for_sort_expr (PlannerInfo *root, Expr *expr, List *opfamilies, Oid opcintype, Oid collation, Index sortref, Relids rel, bool create_it)
 
EquivalenceMemberfind_ec_member_matching_expr (EquivalenceClass *ec, Expr *expr, Relids relids)
 
EquivalenceMemberfind_computable_ec_member (PlannerInfo *root, EquivalenceClass *ec, List *exprs, Relids relids, bool require_parallel_safe)
 
bool relation_can_be_sorted_early (PlannerInfo *root, RelOptInfo *rel, EquivalenceClass *ec, bool require_parallel_safe)
 
void generate_base_implied_equalities (PlannerInfo *root)
 
Listgenerate_join_implied_equalities (PlannerInfo *root, Relids join_relids, Relids outer_relids, RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo)
 
Listgenerate_join_implied_equalities_for_ecs (PlannerInfo *root, List *eclasses, Relids join_relids, Relids outer_relids, RelOptInfo *inner_rel)
 
bool exprs_known_equal (PlannerInfo *root, Node *item1, Node *item2)
 
EquivalenceClassmatch_eclasses_to_foreign_key_col (PlannerInfo *root, ForeignKeyOptInfo *fkinfo, int colno)
 
RestrictInfofind_derived_clause_for_ec_member (EquivalenceClass *ec, EquivalenceMember *em)
 
void add_child_rel_equivalences (PlannerInfo *root, AppendRelInfo *appinfo, RelOptInfo *parent_rel, RelOptInfo *child_rel)
 
void add_child_join_rel_equivalences (PlannerInfo *root, int nappinfos, AppendRelInfo **appinfos, RelOptInfo *parent_joinrel, RelOptInfo *child_joinrel)
 
Listgenerate_implied_equalities_for_column (PlannerInfo *root, RelOptInfo *rel, ec_matches_callback_type callback, void *callback_arg, Relids prohibited_rels)
 
bool have_relevant_eclass_joinclause (PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2)
 
bool has_relevant_eclass_joinclause (PlannerInfo *root, RelOptInfo *rel1)
 
bool eclass_useful_for_merging (PlannerInfo *root, EquivalenceClass *eclass, RelOptInfo *rel)
 
bool is_redundant_derived_clause (RestrictInfo *rinfo, List *clauselist)
 
bool is_redundant_with_indexclauses (RestrictInfo *rinfo, List *indexclauses)
 
PathKeysComparison compare_pathkeys (List *keys1, List *keys2)
 
bool pathkeys_contained_in (List *keys1, List *keys2)
 
bool pathkeys_count_contained_in (List *keys1, List *keys2, int *n_common)
 
Listget_useful_group_keys_orderings (PlannerInfo *root, Path *path)
 
Pathget_cheapest_path_for_pathkeys (List *paths, List *pathkeys, Relids required_outer, CostSelector cost_criterion, bool require_parallel_safe)
 
Pathget_cheapest_fractional_path_for_pathkeys (List *paths, List *pathkeys, Relids required_outer, double fraction)
 
Pathget_cheapest_parallel_safe_total_inner (List *paths)
 
Listbuild_index_pathkeys (PlannerInfo *root, IndexOptInfo *index, ScanDirection scandir)
 
Listbuild_partition_pathkeys (PlannerInfo *root, RelOptInfo *partrel, ScanDirection scandir, bool *partialkeys)
 
Listbuild_expression_pathkey (PlannerInfo *root, Expr *expr, Oid opno, Relids rel, bool create_it)
 
Listconvert_subquery_pathkeys (PlannerInfo *root, RelOptInfo *rel, List *subquery_pathkeys, List *subquery_tlist)
 
Listbuild_join_pathkeys (PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype, List *outer_pathkeys)
 
Listmake_pathkeys_for_sortclauses (PlannerInfo *root, List *sortclauses, List *tlist)
 
Listmake_pathkeys_for_sortclauses_extended (PlannerInfo *root, List **sortclauses, List *tlist, bool remove_redundant, bool *sortable)
 
void initialize_mergeclause_eclasses (PlannerInfo *root, RestrictInfo *restrictinfo)
 
void update_mergeclause_eclasses (PlannerInfo *root, RestrictInfo *restrictinfo)
 
Listfind_mergeclauses_for_outer_pathkeys (PlannerInfo *root, List *pathkeys, List *restrictinfos)
 
Listselect_outer_pathkeys_for_merge (PlannerInfo *root, List *mergeclauses, RelOptInfo *joinrel)
 
Listmake_inner_pathkeys_for_merge (PlannerInfo *root, List *mergeclauses, List *outer_pathkeys)
 
Listtrim_mergeclauses_for_inner_pathkeys (PlannerInfo *root, List *mergeclauses, List *pathkeys)
 
Listtruncate_useless_pathkeys (PlannerInfo *root, RelOptInfo *rel, List *pathkeys)
 
bool has_useful_pathkeys (PlannerInfo *root, RelOptInfo *rel)
 
Listappend_pathkeys (List *target, List *source)
 
PathKeymake_canonical_pathkey (PlannerInfo *root, EquivalenceClass *eclass, Oid opfamily, int strategy, bool nulls_first)
 
void add_paths_to_append_rel (PlannerInfo *root, RelOptInfo *rel, List *live_childrels)
 

Variables

PGDLLIMPORT bool enable_geqo
 
PGDLLIMPORT int geqo_threshold
 
PGDLLIMPORT int min_parallel_table_scan_size
 
PGDLLIMPORT int min_parallel_index_scan_size
 
PGDLLIMPORT bool enable_group_by_reordering
 
PGDLLIMPORT set_rel_pathlist_hook_type set_rel_pathlist_hook
 
PGDLLIMPORT set_join_pathlist_hook_type set_join_pathlist_hook
 
PGDLLIMPORT join_search_hook_type join_search_hook
 

Typedef Documentation

◆ ec_matches_callback_type

typedef bool(* ec_matches_callback_type) (PlannerInfo *root, RelOptInfo *rel, EquivalenceClass *ec, EquivalenceMember *em, void *arg)

Definition at line 120 of file paths.h.

◆ join_search_hook_type

typedef RelOptInfo*(* join_search_hook_type) (PlannerInfo *root, int levels_needed, List *initial_rels)

Definition at line 46 of file paths.h.

◆ set_join_pathlist_hook_type

typedef void(* set_join_pathlist_hook_type) (PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, JoinPathExtraData *extra)

Definition at line 37 of file paths.h.

◆ set_rel_pathlist_hook_type

typedef void(* set_rel_pathlist_hook_type) (PlannerInfo *root, RelOptInfo *rel, Index rti, RangeTblEntry *rte)

Definition at line 30 of file paths.h.

Enumeration Type Documentation

◆ PathKeysComparison

Enumerator
PATHKEYS_EQUAL 
PATHKEYS_BETTER1 
PATHKEYS_BETTER2 
PATHKEYS_DIFFERENT 

Definition at line 197 of file paths.h.

198 {
199  PATHKEYS_EQUAL, /* pathkeys are identical */
200  PATHKEYS_BETTER1, /* pathkey 1 is a superset of pathkey 2 */
201  PATHKEYS_BETTER2, /* vice versa */
202  PATHKEYS_DIFFERENT, /* neither pathkey includes the other */
PathKeysComparison
Definition: paths.h:198
@ PATHKEYS_BETTER2
Definition: paths.h:201
@ PATHKEYS_BETTER1
Definition: paths.h:200
@ PATHKEYS_DIFFERENT
Definition: paths.h:202
@ PATHKEYS_EQUAL
Definition: paths.h:199

Function Documentation

◆ add_child_join_rel_equivalences()

void add_child_join_rel_equivalences ( PlannerInfo root,
int  nappinfos,
AppendRelInfo **  appinfos,
RelOptInfo parent_joinrel,
RelOptInfo child_joinrel 
)

Definition at line 2754 of file equivclass.c.

2758 {
2759  Relids top_parent_relids = child_joinrel->top_parent_relids;
2760  Relids child_relids = child_joinrel->relids;
2761  Bitmapset *matching_ecs;
2762  MemoryContext oldcontext;
2763  int i;
2764 
2765  Assert(IS_JOIN_REL(child_joinrel) && IS_JOIN_REL(parent_joinrel));
2766 
2767  /* We need consider only ECs that mention the parent joinrel */
2768  matching_ecs = get_eclass_indexes_for_relids(root, top_parent_relids);
2769 
2770  /*
2771  * If we're being called during GEQO join planning, we still have to
2772  * create any new EC members in the main planner context, to avoid having
2773  * a corrupt EC data structure after the GEQO context is reset. This is
2774  * problematic since we'll leak memory across repeated GEQO cycles. For
2775  * now, though, bloat is better than crash. If it becomes a real issue
2776  * we'll have to do something to avoid generating duplicate EC members.
2777  */
2778  oldcontext = MemoryContextSwitchTo(root->planner_cxt);
2779 
2780  i = -1;
2781  while ((i = bms_next_member(matching_ecs, i)) >= 0)
2782  {
2783  EquivalenceClass *cur_ec = (EquivalenceClass *) list_nth(root->eq_classes, i);
2784  int num_members;
2785 
2786  /*
2787  * If this EC contains a volatile expression, then generating child
2788  * EMs would be downright dangerous, so skip it. We rely on a
2789  * volatile EC having only one EM.
2790  */
2791  if (cur_ec->ec_has_volatile)
2792  continue;
2793 
2794  /* Sanity check on get_eclass_indexes_for_relids result */
2795  Assert(bms_overlap(top_parent_relids, cur_ec->ec_relids));
2796 
2797  /*
2798  * We don't use foreach() here because there's no point in scanning
2799  * newly-added child members, so we can stop after the last
2800  * pre-existing EC member.
2801  */
2802  num_members = list_length(cur_ec->ec_members);
2803  for (int pos = 0; pos < num_members; pos++)
2804  {
2805  EquivalenceMember *cur_em = (EquivalenceMember *) list_nth(cur_ec->ec_members, pos);
2806 
2807  if (cur_em->em_is_const)
2808  continue; /* ignore consts here */
2809 
2810  /*
2811  * We consider only original EC members here, not
2812  * already-transformed child members.
2813  */
2814  if (cur_em->em_is_child)
2815  continue; /* ignore children here */
2816 
2817  /*
2818  * We may ignore expressions that reference a single baserel,
2819  * because add_child_rel_equivalences should have handled them.
2820  */
2821  if (bms_membership(cur_em->em_relids) != BMS_MULTIPLE)
2822  continue;
2823 
2824  /* Does this member reference child's topmost parent rel? */
2825  if (bms_overlap(cur_em->em_relids, top_parent_relids))
2826  {
2827  /* Yes, generate transformed child version */
2828  Expr *child_expr;
2829  Relids new_relids;
2830 
2831  if (parent_joinrel->reloptkind == RELOPT_JOINREL)
2832  {
2833  /* Simple single-level transformation */
2834  child_expr = (Expr *)
2836  (Node *) cur_em->em_expr,
2837  nappinfos, appinfos);
2838  }
2839  else
2840  {
2841  /* Must do multi-level transformation */
2842  Assert(parent_joinrel->reloptkind == RELOPT_OTHER_JOINREL);
2843  child_expr = (Expr *)
2845  (Node *) cur_em->em_expr,
2846  child_joinrel,
2847  child_joinrel->top_parent);
2848  }
2849 
2850  /*
2851  * Transform em_relids to match. Note we do *not* do
2852  * pull_varnos(child_expr) here, as for example the
2853  * transformation might have substituted a constant, but we
2854  * don't want the child member to be marked as constant.
2855  */
2856  new_relids = bms_difference(cur_em->em_relids,
2857  top_parent_relids);
2858  new_relids = bms_add_members(new_relids, child_relids);
2859 
2860  (void) add_eq_member(cur_ec, child_expr, new_relids,
2861  cur_em->em_jdomain,
2862  cur_em, cur_em->em_datatype);
2863  }
2864  }
2865  }
2866 
2867  MemoryContextSwitchTo(oldcontext);
2868 }
Node * adjust_appendrel_attrs(PlannerInfo *root, Node *node, int nappinfos, AppendRelInfo **appinfos)
Definition: appendinfo.c:196
Node * adjust_appendrel_attrs_multilevel(PlannerInfo *root, Node *node, RelOptInfo *childrel, RelOptInfo *parentrel)
Definition: appendinfo.c:521
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1306
Bitmapset * bms_difference(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:346
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:917
BMS_Membership bms_membership(const Bitmapset *a)
Definition: bitmapset.c:781
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:582
@ BMS_MULTIPLE
Definition: bitmapset.h:73
static EquivalenceMember * add_eq_member(EquivalenceClass *ec, Expr *expr, Relids relids, JoinDomain *jdomain, EquivalenceMember *parent, Oid datatype)
Definition: equivclass.c:517
static Bitmapset * get_eclass_indexes_for_relids(PlannerInfo *root, Relids relids)
Definition: equivclass.c:3268
int i
Definition: isn.c:73
Assert(fmt[strlen(fmt) - 1] !='\n')
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
#define IS_JOIN_REL(rel)
Definition: pathnodes.h:829
@ RELOPT_JOINREL
Definition: pathnodes.h:813
@ RELOPT_OTHER_JOINREL
Definition: pathnodes.h:815
static int list_length(const List *l)
Definition: pg_list.h:152
static void * list_nth(const List *list, int n)
Definition: pg_list.h:299
JoinDomain * em_jdomain
Definition: pathnodes.h:1426
Definition: nodes.h:129
List * eq_classes
Definition: pathnodes.h:311
Relids relids
Definition: pathnodes.h:856
Relids top_parent_relids
Definition: pathnodes.h:990
RelOptKind reloptkind
Definition: pathnodes.h:850

References add_eq_member(), adjust_appendrel_attrs(), adjust_appendrel_attrs_multilevel(), Assert(), bms_add_members(), bms_difference(), bms_membership(), BMS_MULTIPLE, bms_next_member(), bms_overlap(), EquivalenceClass::ec_has_volatile, EquivalenceClass::ec_members, EquivalenceClass::ec_relids, EquivalenceMember::em_datatype, EquivalenceMember::em_expr, EquivalenceMember::em_is_child, EquivalenceMember::em_is_const, EquivalenceMember::em_jdomain, EquivalenceMember::em_relids, PlannerInfo::eq_classes, get_eclass_indexes_for_relids(), i, IS_JOIN_REL, list_length(), list_nth(), MemoryContextSwitchTo(), RelOptInfo::relids, RELOPT_JOINREL, RELOPT_OTHER_JOINREL, RelOptInfo::reloptkind, and RelOptInfo::top_parent_relids.

Referenced by build_child_join_rel().

◆ add_child_rel_equivalences()

void add_child_rel_equivalences ( PlannerInfo root,
AppendRelInfo appinfo,
RelOptInfo parent_rel,
RelOptInfo child_rel 
)

Definition at line 2632 of file equivclass.c.

2636 {
2637  Relids top_parent_relids = child_rel->top_parent_relids;
2638  Relids child_relids = child_rel->relids;
2639  int i;
2640 
2641  /*
2642  * EC merging should be complete already, so we can use the parent rel's
2643  * eclass_indexes to avoid searching all of root->eq_classes.
2644  */
2645  Assert(root->ec_merging_done);
2646  Assert(IS_SIMPLE_REL(parent_rel));
2647 
2648  i = -1;
2649  while ((i = bms_next_member(parent_rel->eclass_indexes, i)) >= 0)
2650  {
2651  EquivalenceClass *cur_ec = (EquivalenceClass *) list_nth(root->eq_classes, i);
2652  int num_members;
2653 
2654  /*
2655  * If this EC contains a volatile expression, then generating child
2656  * EMs would be downright dangerous, so skip it. We rely on a
2657  * volatile EC having only one EM.
2658  */
2659  if (cur_ec->ec_has_volatile)
2660  continue;
2661 
2662  /* Sanity check eclass_indexes only contain ECs for parent_rel */
2663  Assert(bms_is_subset(top_parent_relids, cur_ec->ec_relids));
2664 
2665  /*
2666  * We don't use foreach() here because there's no point in scanning
2667  * newly-added child members, so we can stop after the last
2668  * pre-existing EC member.
2669  */
2670  num_members = list_length(cur_ec->ec_members);
2671  for (int pos = 0; pos < num_members; pos++)
2672  {
2673  EquivalenceMember *cur_em = (EquivalenceMember *) list_nth(cur_ec->ec_members, pos);
2674 
2675  if (cur_em->em_is_const)
2676  continue; /* ignore consts here */
2677 
2678  /*
2679  * We consider only original EC members here, not
2680  * already-transformed child members. Otherwise, if some original
2681  * member expression references more than one appendrel, we'd get
2682  * an O(N^2) explosion of useless derived expressions for
2683  * combinations of children. (But add_child_join_rel_equivalences
2684  * may add targeted combinations for partitionwise-join purposes.)
2685  */
2686  if (cur_em->em_is_child)
2687  continue; /* ignore children here */
2688 
2689  /*
2690  * Consider only members that reference and can be computed at
2691  * child's topmost parent rel. In particular we want to exclude
2692  * parent-rel Vars that have nonempty varnullingrels. Translating
2693  * those might fail, if the transformed expression wouldn't be a
2694  * simple Var; and in any case it wouldn't produce a member that
2695  * has any use in creating plans for the child rel.
2696  */
2697  if (bms_is_subset(cur_em->em_relids, top_parent_relids) &&
2698  !bms_is_empty(cur_em->em_relids))
2699  {
2700  /* OK, generate transformed child version */
2701  Expr *child_expr;
2702  Relids new_relids;
2703 
2704  if (parent_rel->reloptkind == RELOPT_BASEREL)
2705  {
2706  /* Simple single-level transformation */
2707  child_expr = (Expr *)
2709  (Node *) cur_em->em_expr,
2710  1, &appinfo);
2711  }
2712  else
2713  {
2714  /* Must do multi-level transformation */
2715  child_expr = (Expr *)
2717  (Node *) cur_em->em_expr,
2718  child_rel,
2719  child_rel->top_parent);
2720  }
2721 
2722  /*
2723  * Transform em_relids to match. Note we do *not* do
2724  * pull_varnos(child_expr) here, as for example the
2725  * transformation might have substituted a constant, but we
2726  * don't want the child member to be marked as constant.
2727  */
2728  new_relids = bms_difference(cur_em->em_relids,
2729  top_parent_relids);
2730  new_relids = bms_add_members(new_relids, child_relids);
2731 
2732  (void) add_eq_member(cur_ec, child_expr, new_relids,
2733  cur_em->em_jdomain,
2734  cur_em, cur_em->em_datatype);
2735 
2736  /* Record this EC index for the child rel */
2737  child_rel->eclass_indexes = bms_add_member(child_rel->eclass_indexes, i);
2738  }
2739  }
2740  }
2741 }
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:412
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:815
#define bms_is_empty(a)
Definition: bitmapset.h:118
#define IS_SIMPLE_REL(rel)
Definition: pathnodes.h:824
@ RELOPT_BASEREL
Definition: pathnodes.h:812
bool ec_merging_done
Definition: pathnodes.h:314
Bitmapset * eclass_indexes
Definition: pathnodes.h:933

References add_eq_member(), adjust_appendrel_attrs(), adjust_appendrel_attrs_multilevel(), Assert(), bms_add_member(), bms_add_members(), bms_difference(), bms_is_empty, bms_is_subset(), bms_next_member(), EquivalenceClass::ec_has_volatile, EquivalenceClass::ec_members, PlannerInfo::ec_merging_done, EquivalenceClass::ec_relids, RelOptInfo::eclass_indexes, EquivalenceMember::em_datatype, EquivalenceMember::em_expr, EquivalenceMember::em_is_child, EquivalenceMember::em_is_const, EquivalenceMember::em_jdomain, EquivalenceMember::em_relids, PlannerInfo::eq_classes, i, IS_SIMPLE_REL, list_length(), list_nth(), RelOptInfo::relids, RELOPT_BASEREL, RelOptInfo::reloptkind, and RelOptInfo::top_parent_relids.

Referenced by set_append_rel_size().

◆ add_outer_joins_to_relids()

Relids add_outer_joins_to_relids ( PlannerInfo root,
Relids  input_relids,
SpecialJoinInfo sjinfo,
List **  pushed_down_joins 
)

Definition at line 783 of file joinrels.c.

786 {
787  /* Nothing to do if this isn't an outer join with an assigned relid. */
788  if (sjinfo == NULL || sjinfo->ojrelid == 0)
789  return input_relids;
790 
791  /*
792  * If it's not a left join, we have no rules that would permit executing
793  * it in non-syntactic order, so just form the syntactic relid set. (This
794  * is just a quick-exit test; we'd come to the same conclusion anyway,
795  * since its commute_below_l and commute_above_l sets must be empty.)
796  */
797  if (sjinfo->jointype != JOIN_LEFT)
798  return bms_add_member(input_relids, sjinfo->ojrelid);
799 
800  /*
801  * We cannot add the OJ relid if this join has been pushed into the RHS of
802  * a syntactically-lower left join per OJ identity 3. (If it has, then we
803  * cannot claim that its outputs represent the final state of its RHS.)
804  * There will not be any other OJs that can be added either, so we're
805  * done.
806  */
807  if (!bms_is_subset(sjinfo->commute_below_l, input_relids))
808  return input_relids;
809 
810  /* OK to add OJ's own relid */
811  input_relids = bms_add_member(input_relids, sjinfo->ojrelid);
812 
813  /*
814  * Contrariwise, if we are now forming the final result of such a commuted
815  * pair of OJs, it's time to add the relid(s) of the pushed-down join(s).
816  * We can skip this if this join was never a candidate to be pushed up.
817  */
818  if (sjinfo->commute_above_l)
819  {
820  Relids commute_above_rels = bms_copy(sjinfo->commute_above_l);
821  ListCell *lc;
822 
823  /*
824  * The current join could complete the nulling of more than one
825  * pushed-down join, so we have to examine all the SpecialJoinInfos.
826  * Because join_info_list was built in bottom-up order, it's
827  * sufficient to traverse it once: an ojrelid we add in one loop
828  * iteration would not have affected decisions of earlier iterations.
829  */
830  foreach(lc, root->join_info_list)
831  {
832  SpecialJoinInfo *othersj = (SpecialJoinInfo *) lfirst(lc);
833 
834  if (othersj == sjinfo ||
835  othersj->ojrelid == 0 || othersj->jointype != JOIN_LEFT)
836  continue; /* definitely not interesting */
837 
838  if (!bms_is_member(othersj->ojrelid, commute_above_rels))
839  continue;
840 
841  /* Add it if not already present but conditions now satisfied */
842  if (!bms_is_member(othersj->ojrelid, input_relids) &&
843  bms_is_subset(othersj->min_lefthand, input_relids) &&
844  bms_is_subset(othersj->min_righthand, input_relids) &&
845  bms_is_subset(othersj->commute_below_l, input_relids))
846  {
847  input_relids = bms_add_member(input_relids, othersj->ojrelid);
848  /* report such pushed down outer joins, if asked */
849  if (pushed_down_joins != NULL)
850  *pushed_down_joins = lappend(*pushed_down_joins, othersj);
851 
852  /*
853  * We must also check any joins that othersj potentially
854  * commutes with. They likewise must appear later in
855  * join_info_list than othersj itself, so we can visit them
856  * later in this loop.
857  */
858  commute_above_rels = bms_add_members(commute_above_rels,
859  othersj->commute_above_l);
860  }
861  }
862  }
863 
864  return input_relids;
865 }
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:510
Bitmapset * bms_copy(const Bitmapset *a)
Definition: bitmapset.c:122
List * lappend(List *list, void *datum)
Definition: list.c:339
@ JOIN_LEFT
Definition: nodes.h:284
#define lfirst(lc)
Definition: pg_list.h:172
List * join_info_list
Definition: pathnodes.h:337
Relids min_righthand
Definition: pathnodes.h:2869
Relids commute_above_l
Definition: pathnodes.h:2874
JoinType jointype
Definition: pathnodes.h:2872
Relids commute_below_l
Definition: pathnodes.h:2876
Relids min_lefthand
Definition: pathnodes.h:2868

References bms_add_member(), bms_add_members(), bms_copy(), bms_is_member(), bms_is_subset(), SpecialJoinInfo::commute_above_l, SpecialJoinInfo::commute_below_l, PlannerInfo::join_info_list, JOIN_LEFT, SpecialJoinInfo::jointype, lappend(), lfirst, SpecialJoinInfo::min_lefthand, SpecialJoinInfo::min_righthand, and SpecialJoinInfo::ojrelid.

Referenced by generate_join_implied_equalities(), and make_join_rel().

◆ add_paths_to_append_rel()

void add_paths_to_append_rel ( PlannerInfo root,
RelOptInfo rel,
List live_childrels 
)

Definition at line 1302 of file allpaths.c.

1304 {
1305  List *subpaths = NIL;
1306  bool subpaths_valid = true;
1307  List *startup_subpaths = NIL;
1308  bool startup_subpaths_valid = true;
1309  List *partial_subpaths = NIL;
1310  List *pa_partial_subpaths = NIL;
1311  List *pa_nonpartial_subpaths = NIL;
1312  bool partial_subpaths_valid = true;
1313  bool pa_subpaths_valid;
1314  List *all_child_pathkeys = NIL;
1315  List *all_child_outers = NIL;
1316  ListCell *l;
1317  double partial_rows = -1;
1318 
1319  /* If appropriate, consider parallel append */
1320  pa_subpaths_valid = enable_parallel_append && rel->consider_parallel;
1321 
1322  /*
1323  * For every non-dummy child, remember the cheapest path. Also, identify
1324  * all pathkeys (orderings) and parameterizations (required_outer sets)
1325  * available for the non-dummy member relations.
1326  */
1327  foreach(l, live_childrels)
1328  {
1329  RelOptInfo *childrel = lfirst(l);
1330  ListCell *lcp;
1331  Path *cheapest_partial_path = NULL;
1332 
1333  /*
1334  * If child has an unparameterized cheapest-total path, add that to
1335  * the unparameterized Append path we are constructing for the parent.
1336  * If not, there's no workable unparameterized path.
1337  *
1338  * With partitionwise aggregates, the child rel's pathlist may be
1339  * empty, so don't assume that a path exists here.
1340  */
1341  if (childrel->pathlist != NIL &&
1342  childrel->cheapest_total_path->param_info == NULL)
1344  &subpaths, NULL);
1345  else
1346  subpaths_valid = false;
1347 
1348  /*
1349  * When the planner is considering cheap startup plans, we'll also
1350  * collect all the cheapest_startup_paths (if set) and build an
1351  * AppendPath containing those as subpaths.
1352  */
1353  if (rel->consider_startup && childrel->cheapest_startup_path != NULL)
1354  {
1355  /* cheapest_startup_path must not be a parameterized path. */
1356  Assert(childrel->cheapest_startup_path->param_info == NULL);
1358  &startup_subpaths,
1359  NULL);
1360  }
1361  else
1362  startup_subpaths_valid = false;
1363 
1364 
1365  /* Same idea, but for a partial plan. */
1366  if (childrel->partial_pathlist != NIL)
1367  {
1368  cheapest_partial_path = linitial(childrel->partial_pathlist);
1369  accumulate_append_subpath(cheapest_partial_path,
1370  &partial_subpaths, NULL);
1371  }
1372  else
1373  partial_subpaths_valid = false;
1374 
1375  /*
1376  * Same idea, but for a parallel append mixing partial and non-partial
1377  * paths.
1378  */
1379  if (pa_subpaths_valid)
1380  {
1381  Path *nppath = NULL;
1382 
1383  nppath =
1385 
1386  if (cheapest_partial_path == NULL && nppath == NULL)
1387  {
1388  /* Neither a partial nor a parallel-safe path? Forget it. */
1389  pa_subpaths_valid = false;
1390  }
1391  else if (nppath == NULL ||
1392  (cheapest_partial_path != NULL &&
1393  cheapest_partial_path->total_cost < nppath->total_cost))
1394  {
1395  /* Partial path is cheaper or the only option. */
1396  Assert(cheapest_partial_path != NULL);
1397  accumulate_append_subpath(cheapest_partial_path,
1398  &pa_partial_subpaths,
1399  &pa_nonpartial_subpaths);
1400  }
1401  else
1402  {
1403  /*
1404  * Either we've got only a non-partial path, or we think that
1405  * a single backend can execute the best non-partial path
1406  * faster than all the parallel backends working together can
1407  * execute the best partial path.
1408  *
1409  * It might make sense to be more aggressive here. Even if
1410  * the best non-partial path is more expensive than the best
1411  * partial path, it could still be better to choose the
1412  * non-partial path if there are several such paths that can
1413  * be given to different workers. For now, we don't try to
1414  * figure that out.
1415  */
1417  &pa_nonpartial_subpaths,
1418  NULL);
1419  }
1420  }
1421 
1422  /*
1423  * Collect lists of all the available path orderings and
1424  * parameterizations for all the children. We use these as a
1425  * heuristic to indicate which sort orderings and parameterizations we
1426  * should build Append and MergeAppend paths for.
1427  */
1428  foreach(lcp, childrel->pathlist)
1429  {
1430  Path *childpath = (Path *) lfirst(lcp);
1431  List *childkeys = childpath->pathkeys;
1432  Relids childouter = PATH_REQ_OUTER(childpath);
1433 
1434  /* Unsorted paths don't contribute to pathkey list */
1435  if (childkeys != NIL)
1436  {
1437  ListCell *lpk;
1438  bool found = false;
1439 
1440  /* Have we already seen this ordering? */
1441  foreach(lpk, all_child_pathkeys)
1442  {
1443  List *existing_pathkeys = (List *) lfirst(lpk);
1444 
1445  if (compare_pathkeys(existing_pathkeys,
1446  childkeys) == PATHKEYS_EQUAL)
1447  {
1448  found = true;
1449  break;
1450  }
1451  }
1452  if (!found)
1453  {
1454  /* No, so add it to all_child_pathkeys */
1455  all_child_pathkeys = lappend(all_child_pathkeys,
1456  childkeys);
1457  }
1458  }
1459 
1460  /* Unparameterized paths don't contribute to param-set list */
1461  if (childouter)
1462  {
1463  ListCell *lco;
1464  bool found = false;
1465 
1466  /* Have we already seen this param set? */
1467  foreach(lco, all_child_outers)
1468  {
1469  Relids existing_outers = (Relids) lfirst(lco);
1470 
1471  if (bms_equal(existing_outers, childouter))
1472  {
1473  found = true;
1474  break;
1475  }
1476  }
1477  if (!found)
1478  {
1479  /* No, so add it to all_child_outers */
1480  all_child_outers = lappend(all_child_outers,
1481  childouter);
1482  }
1483  }
1484  }
1485  }
1486 
1487  /*
1488  * If we found unparameterized paths for all children, build an unordered,
1489  * unparameterized Append path for the rel. (Note: this is correct even
1490  * if we have zero or one live subpath due to constraint exclusion.)
1491  */
1492  if (subpaths_valid)
1493  add_path(rel, (Path *) create_append_path(root, rel, subpaths, NIL,
1494  NIL, NULL, 0, false,
1495  -1));
1496 
1497  /* build an AppendPath for the cheap startup paths, if valid */
1498  if (startup_subpaths_valid)
1499  add_path(rel, (Path *) create_append_path(root, rel, startup_subpaths,
1500  NIL, NIL, NULL, 0, false, -1));
1501 
1502  /*
1503  * Consider an append of unordered, unparameterized partial paths. Make
1504  * it parallel-aware if possible.
1505  */
1506  if (partial_subpaths_valid && partial_subpaths != NIL)
1507  {
1508  AppendPath *appendpath;
1509  ListCell *lc;
1510  int parallel_workers = 0;
1511 
1512  /* Find the highest number of workers requested for any subpath. */
1513  foreach(lc, partial_subpaths)
1514  {
1515  Path *path = lfirst(lc);
1516 
1517  parallel_workers = Max(parallel_workers, path->parallel_workers);
1518  }
1519  Assert(parallel_workers > 0);
1520 
1521  /*
1522  * If the use of parallel append is permitted, always request at least
1523  * log2(# of children) workers. We assume it can be useful to have
1524  * extra workers in this case because they will be spread out across
1525  * the children. The precise formula is just a guess, but we don't
1526  * want to end up with a radically different answer for a table with N
1527  * partitions vs. an unpartitioned table with the same data, so the
1528  * use of some kind of log-scaling here seems to make some sense.
1529  */
1531  {
1532  parallel_workers = Max(parallel_workers,
1533  pg_leftmost_one_pos32(list_length(live_childrels)) + 1);
1534  parallel_workers = Min(parallel_workers,
1536  }
1537  Assert(parallel_workers > 0);
1538 
1539  /* Generate a partial append path. */
1540  appendpath = create_append_path(root, rel, NIL, partial_subpaths,
1541  NIL, NULL, parallel_workers,
1543  -1);
1544 
1545  /*
1546  * Make sure any subsequent partial paths use the same row count
1547  * estimate.
1548  */
1549  partial_rows = appendpath->path.rows;
1550 
1551  /* Add the path. */
1552  add_partial_path(rel, (Path *) appendpath);
1553  }
1554 
1555  /*
1556  * Consider a parallel-aware append using a mix of partial and non-partial
1557  * paths. (This only makes sense if there's at least one child which has
1558  * a non-partial path that is substantially cheaper than any partial path;
1559  * otherwise, we should use the append path added in the previous step.)
1560  */
1561  if (pa_subpaths_valid && pa_nonpartial_subpaths != NIL)
1562  {
1563  AppendPath *appendpath;
1564  ListCell *lc;
1565  int parallel_workers = 0;
1566 
1567  /*
1568  * Find the highest number of workers requested for any partial
1569  * subpath.
1570  */
1571  foreach(lc, pa_partial_subpaths)
1572  {
1573  Path *path = lfirst(lc);
1574 
1575  parallel_workers = Max(parallel_workers, path->parallel_workers);
1576  }
1577 
1578  /*
1579  * Same formula here as above. It's even more important in this
1580  * instance because the non-partial paths won't contribute anything to
1581  * the planned number of parallel workers.
1582  */
1583  parallel_workers = Max(parallel_workers,
1584  pg_leftmost_one_pos32(list_length(live_childrels)) + 1);
1585  parallel_workers = Min(parallel_workers,
1587  Assert(parallel_workers > 0);
1588 
1589  appendpath = create_append_path(root, rel, pa_nonpartial_subpaths,
1590  pa_partial_subpaths,
1591  NIL, NULL, parallel_workers, true,
1592  partial_rows);
1593  add_partial_path(rel, (Path *) appendpath);
1594  }
1595 
1596  /*
1597  * Also build unparameterized ordered append paths based on the collected
1598  * list of child pathkeys.
1599  */
1600  if (subpaths_valid)
1601  generate_orderedappend_paths(root, rel, live_childrels,
1602  all_child_pathkeys);
1603 
1604  /*
1605  * Build Append paths for each parameterization seen among the child rels.
1606  * (This may look pretty expensive, but in most cases of practical
1607  * interest, the child rels will expose mostly the same parameterizations,
1608  * so that not that many cases actually get considered here.)
1609  *
1610  * The Append node itself cannot enforce quals, so all qual checking must
1611  * be done in the child paths. This means that to have a parameterized
1612  * Append path, we must have the exact same parameterization for each
1613  * child path; otherwise some children might be failing to check the
1614  * moved-down quals. To make them match up, we can try to increase the
1615  * parameterization of lesser-parameterized paths.
1616  */
1617  foreach(l, all_child_outers)
1618  {
1619  Relids required_outer = (Relids) lfirst(l);
1620  ListCell *lcr;
1621 
1622  /* Select the child paths for an Append with this parameterization */
1623  subpaths = NIL;
1624  subpaths_valid = true;
1625  foreach(lcr, live_childrels)
1626  {
1627  RelOptInfo *childrel = (RelOptInfo *) lfirst(lcr);
1628  Path *subpath;
1629 
1630  if (childrel->pathlist == NIL)
1631  {
1632  /* failed to make a suitable path for this child */
1633  subpaths_valid = false;
1634  break;
1635  }
1636 
1638  childrel,
1639  required_outer);
1640  if (subpath == NULL)
1641  {
1642  /* failed to make a suitable path for this child */
1643  subpaths_valid = false;
1644  break;
1645  }
1646  accumulate_append_subpath(subpath, &subpaths, NULL);
1647  }
1648 
1649  if (subpaths_valid)
1650  add_path(rel, (Path *)
1651  create_append_path(root, rel, subpaths, NIL,
1652  NIL, required_outer, 0, false,
1653  -1));
1654  }
1655 
1656  /*
1657  * When there is only a single child relation, the Append path can inherit
1658  * any ordering available for the child rel's path, so that it's useful to
1659  * consider ordered partial paths. Above we only considered the cheapest
1660  * partial path for each child, but let's also make paths using any
1661  * partial paths that have pathkeys.
1662  */
1663  if (list_length(live_childrels) == 1)
1664  {
1665  RelOptInfo *childrel = (RelOptInfo *) linitial(live_childrels);
1666 
1667  /* skip the cheapest partial path, since we already used that above */
1668  for_each_from(l, childrel->partial_pathlist, 1)
1669  {
1670  Path *path = (Path *) lfirst(l);
1671  AppendPath *appendpath;
1672 
1673  /* skip paths with no pathkeys. */
1674  if (path->pathkeys == NIL)
1675  continue;
1676 
1677  appendpath = create_append_path(root, rel, NIL, list_make1(path),
1678  NIL, NULL,
1679  path->parallel_workers, true,
1680  partial_rows);
1681  add_partial_path(rel, (Path *) appendpath);
1682  }
1683  }
1684 }
static Path * get_cheapest_parameterized_child_path(PlannerInfo *root, RelOptInfo *rel, Relids required_outer)
Definition: allpaths.c:1999
static void generate_orderedappend_paths(PlannerInfo *root, RelOptInfo *rel, List *live_childrels, List *all_child_pathkeys)
Definition: allpaths.c:1714
static void accumulate_append_subpath(Path *path, List **subpaths, List **special_subpaths)
Definition: allpaths.c:2087
bool bms_equal(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:142
#define Min(x, y)
Definition: c.h:991
#define Max(x, y)
Definition: c.h:985
int max_parallel_workers_per_gather
Definition: costsize.c:132
bool enable_parallel_append
Definition: costsize.c:150
Datum subpath(PG_FUNCTION_ARGS)
Definition: ltree_op.c:241
Path * get_cheapest_parallel_safe_total_inner(List *paths)
Definition: pathkeys.c:714
PathKeysComparison compare_pathkeys(List *keys1, List *keys2)
Definition: pathkeys.c:302
AppendPath * create_append_path(PlannerInfo *root, RelOptInfo *rel, List *subpaths, List *partial_subpaths, List *pathkeys, Relids required_outer, int parallel_workers, bool parallel_aware, double rows)
Definition: pathnode.c:1242
void add_partial_path(RelOptInfo *parent_rel, Path *new_path)
Definition: pathnode.c:745
void add_path(RelOptInfo *parent_rel, Path *new_path)
Definition: pathnode.c:418
#define PATH_REQ_OUTER(path)
Definition: pathnodes.h:1649
Bitmapset * Relids
Definition: pathnodes.h:30
static int pg_leftmost_one_pos32(uint32 word)
Definition: pg_bitutils.h:41
#define NIL
Definition: pg_list.h:68
#define list_make1(x1)
Definition: pg_list.h:212
#define for_each_from(cell, lst, N)
Definition: pg_list.h:414
#define linitial(l)
Definition: pg_list.h:178
Definition: pg_list.h:54
List * pathkeys
Definition: pathnodes.h:1645
Cardinality rows
Definition: pathnodes.h:1640
int parallel_workers
Definition: pathnodes.h:1637
Cost total_cost
Definition: pathnodes.h:1642
bool consider_parallel
Definition: pathnodes.h:872
List * pathlist
Definition: pathnodes.h:883
struct Path * cheapest_startup_path
Definition: pathnodes.h:886
struct Path * cheapest_total_path
Definition: pathnodes.h:887
bool consider_startup
Definition: pathnodes.h:868
List * partial_pathlist
Definition: pathnodes.h:885

References accumulate_append_subpath(), add_partial_path(), add_path(), Assert(), bms_equal(), RelOptInfo::cheapest_startup_path, RelOptInfo::cheapest_total_path, compare_pathkeys(), RelOptInfo::consider_parallel, RelOptInfo::consider_startup, create_append_path(), enable_parallel_append, for_each_from, generate_orderedappend_paths(), get_cheapest_parallel_safe_total_inner(), get_cheapest_parameterized_child_path(), lappend(), lfirst, linitial, list_length(), list_make1, Max, max_parallel_workers_per_gather, Min, NIL, Path::parallel_workers, RelOptInfo::partial_pathlist, AppendPath::path, PATH_REQ_OUTER, Path::pathkeys, PATHKEYS_EQUAL, RelOptInfo::pathlist, pg_leftmost_one_pos32(), Path::rows, subpath(), and Path::total_cost.

Referenced by apply_scanjoin_target_to_paths(), create_partitionwise_grouping_paths(), generate_partitionwise_join_paths(), and set_append_rel_pathlist().

◆ add_paths_to_joinrel()

void add_paths_to_joinrel ( PlannerInfo root,
RelOptInfo joinrel,
RelOptInfo outerrel,
RelOptInfo innerrel,
JoinType  jointype,
SpecialJoinInfo sjinfo,
List restrictlist 
)

Definition at line 123 of file joinpath.c.

130 {
131  JoinPathExtraData extra;
132  bool mergejoin_allowed = true;
133  ListCell *lc;
134  Relids joinrelids;
135 
136  /*
137  * PlannerInfo doesn't contain the SpecialJoinInfos created for joins
138  * between child relations, even if there is a SpecialJoinInfo node for
139  * the join between the topmost parents. So, while calculating Relids set
140  * representing the restriction, consider relids of topmost parent of
141  * partitions.
142  */
143  if (joinrel->reloptkind == RELOPT_OTHER_JOINREL)
144  joinrelids = joinrel->top_parent_relids;
145  else
146  joinrelids = joinrel->relids;
147 
148  extra.restrictlist = restrictlist;
149  extra.mergeclause_list = NIL;
150  extra.sjinfo = sjinfo;
151  extra.param_source_rels = NULL;
152 
153  /*
154  * See if the inner relation is provably unique for this outer rel.
155  *
156  * We have some special cases: for JOIN_SEMI and JOIN_ANTI, it doesn't
157  * matter since the executor can make the equivalent optimization anyway;
158  * we need not expend planner cycles on proofs. For JOIN_UNIQUE_INNER, we
159  * must be considering a semijoin whose inner side is not provably unique
160  * (else reduce_unique_semijoins would've simplified it), so there's no
161  * point in calling innerrel_is_unique. However, if the LHS covers all of
162  * the semijoin's min_lefthand, then it's appropriate to set inner_unique
163  * because the path produced by create_unique_path will be unique relative
164  * to the LHS. (If we have an LHS that's only part of the min_lefthand,
165  * that is *not* true.) For JOIN_UNIQUE_OUTER, pass JOIN_INNER to avoid
166  * letting that value escape this module.
167  */
168  switch (jointype)
169  {
170  case JOIN_SEMI:
171  case JOIN_ANTI:
172 
173  /*
174  * XXX it may be worth proving this to allow a Memoize to be
175  * considered for Nested Loop Semi/Anti Joins.
176  */
177  extra.inner_unique = false; /* well, unproven */
178  break;
179  case JOIN_UNIQUE_INNER:
180  extra.inner_unique = bms_is_subset(sjinfo->min_lefthand,
181  outerrel->relids);
182  break;
183  case JOIN_UNIQUE_OUTER:
184  extra.inner_unique = innerrel_is_unique(root,
185  joinrel->relids,
186  outerrel->relids,
187  innerrel,
188  JOIN_INNER,
189  restrictlist,
190  false);
191  break;
192  default:
193  extra.inner_unique = innerrel_is_unique(root,
194  joinrel->relids,
195  outerrel->relids,
196  innerrel,
197  jointype,
198  restrictlist,
199  false);
200  break;
201  }
202 
203  /*
204  * Find potential mergejoin clauses. We can skip this if we are not
205  * interested in doing a mergejoin. However, mergejoin may be our only
206  * way of implementing a full outer join, so override enable_mergejoin if
207  * it's a full join.
208  */
209  if (enable_mergejoin || jointype == JOIN_FULL)
211  joinrel,
212  outerrel,
213  innerrel,
214  restrictlist,
215  jointype,
216  &mergejoin_allowed);
217 
218  /*
219  * If it's SEMI, ANTI, or inner_unique join, compute correction factors
220  * for cost estimation. These will be the same for all paths.
221  */
222  if (jointype == JOIN_SEMI || jointype == JOIN_ANTI || extra.inner_unique)
223  compute_semi_anti_join_factors(root, joinrel, outerrel, innerrel,
224  jointype, sjinfo, restrictlist,
225  &extra.semifactors);
226 
227  /*
228  * Decide whether it's sensible to generate parameterized paths for this
229  * joinrel, and if so, which relations such paths should require. There
230  * is usually no need to create a parameterized result path unless there
231  * is a join order restriction that prevents joining one of our input rels
232  * directly to the parameter source rel instead of joining to the other
233  * input rel. (But see allow_star_schema_join().) This restriction
234  * reduces the number of parameterized paths we have to deal with at
235  * higher join levels, without compromising the quality of the resulting
236  * plan. We express the restriction as a Relids set that must overlap the
237  * parameterization of any proposed join path. Note: param_source_rels
238  * should contain only baserels, not OJ relids, so starting from
239  * all_baserels not all_query_rels is correct.
240  */
241  foreach(lc, root->join_info_list)
242  {
243  SpecialJoinInfo *sjinfo2 = (SpecialJoinInfo *) lfirst(lc);
244 
245  /*
246  * SJ is relevant to this join if we have some part of its RHS
247  * (possibly not all of it), and haven't yet joined to its LHS. (This
248  * test is pretty simplistic, but should be sufficient considering the
249  * join has already been proven legal.) If the SJ is relevant, it
250  * presents constraints for joining to anything not in its RHS.
251  */
252  if (bms_overlap(joinrelids, sjinfo2->min_righthand) &&
253  !bms_overlap(joinrelids, sjinfo2->min_lefthand))
256  sjinfo2->min_righthand));
257 
258  /* full joins constrain both sides symmetrically */
259  if (sjinfo2->jointype == JOIN_FULL &&
260  bms_overlap(joinrelids, sjinfo2->min_lefthand) &&
261  !bms_overlap(joinrelids, sjinfo2->min_righthand))
264  sjinfo2->min_lefthand));
265  }
266 
267  /*
268  * However, when a LATERAL subquery is involved, there will simply not be
269  * any paths for the joinrel that aren't parameterized by whatever the
270  * subquery is parameterized by, unless its parameterization is resolved
271  * within the joinrel. So we might as well allow additional dependencies
272  * on whatever residual lateral dependencies the joinrel will have.
273  */
275  joinrel->lateral_relids);
276 
277  /*
278  * 1. Consider mergejoin paths where both relations must be explicitly
279  * sorted. Skip this if we can't mergejoin.
280  */
281  if (mergejoin_allowed)
282  sort_inner_and_outer(root, joinrel, outerrel, innerrel,
283  jointype, &extra);
284 
285  /*
286  * 2. Consider paths where the outer relation need not be explicitly
287  * sorted. This includes both nestloops and mergejoins where the outer
288  * path is already ordered. Again, skip this if we can't mergejoin.
289  * (That's okay because we know that nestloop can't handle
290  * right/right-anti/full joins at all, so it wouldn't work in the
291  * prohibited cases either.)
292  */
293  if (mergejoin_allowed)
294  match_unsorted_outer(root, joinrel, outerrel, innerrel,
295  jointype, &extra);
296 
297 #ifdef NOT_USED
298 
299  /*
300  * 3. Consider paths where the inner relation need not be explicitly
301  * sorted. This includes mergejoins only (nestloops were already built in
302  * match_unsorted_outer).
303  *
304  * Diked out as redundant 2/13/2000 -- tgl. There isn't any really
305  * significant difference between the inner and outer side of a mergejoin,
306  * so match_unsorted_inner creates no paths that aren't equivalent to
307  * those made by match_unsorted_outer when add_paths_to_joinrel() is
308  * invoked with the two rels given in the other order.
309  */
310  if (mergejoin_allowed)
311  match_unsorted_inner(root, joinrel, outerrel, innerrel,
312  jointype, &extra);
313 #endif
314 
315  /*
316  * 4. Consider paths where both outer and inner relations must be hashed
317  * before being joined. As above, disregard enable_hashjoin for full
318  * joins, because there may be no other alternative.
319  */
320  if (enable_hashjoin || jointype == JOIN_FULL)
321  hash_inner_and_outer(root, joinrel, outerrel, innerrel,
322  jointype, &extra);
323 
324  /*
325  * 5. If inner and outer relations are foreign tables (or joins) belonging
326  * to the same server and assigned to the same user to check access
327  * permissions as, give the FDW a chance to push down joins.
328  */
329  if (joinrel->fdwroutine &&
330  joinrel->fdwroutine->GetForeignJoinPaths)
331  joinrel->fdwroutine->GetForeignJoinPaths(root, joinrel,
332  outerrel, innerrel,
333  jointype, &extra);
334 
335  /*
336  * 6. Finally, give extensions a chance to manipulate the path list. They
337  * could add new paths (such as CustomPaths) by calling add_path(), or
338  * add_partial_path() if parallel aware. They could also delete or modify
339  * paths added by the core code.
340  */
342  set_join_pathlist_hook(root, joinrel, outerrel, innerrel,
343  jointype, &extra);
344 }
bool innerrel_is_unique(PlannerInfo *root, Relids joinrelids, Relids outerrelids, RelOptInfo *innerrel, JoinType jointype, List *restrictlist, bool force_cache)
Bitmapset * bms_join(Bitmapset *a, Bitmapset *b)
Definition: bitmapset.c:1230
void compute_semi_anti_join_factors(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, SpecialJoinInfo *sjinfo, List *restrictlist, SemiAntiJoinFactors *semifactors)
Definition: costsize.c:5003
bool enable_hashjoin
Definition: costsize.c:146
bool enable_mergejoin
Definition: costsize.c:145
static List * select_mergejoin_clauses(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, List *restrictlist, JoinType jointype, bool *mergejoin_allowed)
Definition: joinpath.c:2358
static void sort_inner_and_outer(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, JoinPathExtraData *extra)
Definition: joinpath.c:1277
set_join_pathlist_hook_type set_join_pathlist_hook
Definition: joinpath.c:30
static void hash_inner_and_outer(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, JoinPathExtraData *extra)
Definition: joinpath.c:2104
static void match_unsorted_outer(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, JoinPathExtraData *extra)
Definition: joinpath.c:1728
@ JOIN_SEMI
Definition: nodes.h:297
@ JOIN_FULL
Definition: nodes.h:285
@ JOIN_INNER
Definition: nodes.h:283
@ JOIN_UNIQUE_OUTER
Definition: nodes.h:305
@ JOIN_UNIQUE_INNER
Definition: nodes.h:306
@ JOIN_ANTI
Definition: nodes.h:298
List * mergeclause_list
Definition: pathnodes.h:3205
Relids param_source_rels
Definition: pathnodes.h:3209
SemiAntiJoinFactors semifactors
Definition: pathnodes.h:3208
SpecialJoinInfo * sjinfo
Definition: pathnodes.h:3207
Relids all_baserels
Definition: pathnodes.h:252
Relids lateral_relids
Definition: pathnodes.h:898

References PlannerInfo::all_baserels, bms_add_members(), bms_difference(), bms_is_subset(), bms_join(), bms_overlap(), compute_semi_anti_join_factors(), enable_hashjoin, enable_mergejoin, hash_inner_and_outer(), JoinPathExtraData::inner_unique, innerrel_is_unique(), JOIN_ANTI, JOIN_FULL, PlannerInfo::join_info_list, JOIN_INNER, JOIN_SEMI, JOIN_UNIQUE_INNER, JOIN_UNIQUE_OUTER, SpecialJoinInfo::jointype, RelOptInfo::lateral_relids, lfirst, match_unsorted_outer(), JoinPathExtraData::mergeclause_list, SpecialJoinInfo::min_lefthand, SpecialJoinInfo::min_righthand, NIL, JoinPathExtraData::param_source_rels, RelOptInfo::relids, RELOPT_OTHER_JOINREL, RelOptInfo::reloptkind, JoinPathExtraData::restrictlist, select_mergejoin_clauses(), JoinPathExtraData::semifactors, set_join_pathlist_hook, JoinPathExtraData::sjinfo, sort_inner_and_outer(), and RelOptInfo::top_parent_relids.

Referenced by populate_joinrel_with_paths().

◆ append_pathkeys()

List* append_pathkeys ( List target,
List source 
)

Definition at line 106 of file pathkeys.c.

107 {
108  ListCell *lc;
109 
110  Assert(target != NIL);
111 
112  foreach(lc, source)
113  {
114  PathKey *pk = lfirst_node(PathKey, lc);
115 
116  if (!pathkey_is_redundant(pk, target))
117  target = lappend(target, pk);
118  }
119  return target;
120 }
static bool pathkey_is_redundant(PathKey *new_pathkey, List *pathkeys)
Definition: pathkeys.c:158
#define lfirst_node(type, lc)
Definition: pg_list.h:176
static rewind_source * source
Definition: pg_rewind.c:89

References Assert(), lappend(), lfirst_node, NIL, pathkey_is_redundant(), and source.

Referenced by adjust_group_pathkeys_for_groupagg(), and make_pathkeys_for_window().

◆ build_expression_pathkey()

List* build_expression_pathkey ( PlannerInfo root,
Expr expr,
Oid  opno,
Relids  rel,
bool  create_it 
)

Definition at line 1015 of file pathkeys.c.

1020 {
1021  List *pathkeys;
1022  Oid opfamily,
1023  opcintype;
1024  int16 strategy;
1025  PathKey *cpathkey;
1026 
1027  /* Find the operator in pg_amop --- failure shouldn't happen */
1028  if (!get_ordering_op_properties(opno,
1029  &opfamily, &opcintype, &strategy))
1030  elog(ERROR, "operator %u is not a valid ordering operator",
1031  opno);
1032 
1033  cpathkey = make_pathkey_from_sortinfo(root,
1034  expr,
1035  opfamily,
1036  opcintype,
1037  exprCollation((Node *) expr),
1038  (strategy == BTGreaterStrategyNumber),
1039  (strategy == BTGreaterStrategyNumber),
1040  0,
1041  rel,
1042  create_it);
1043 
1044  if (cpathkey)
1045  pathkeys = list_make1(cpathkey);
1046  else
1047  pathkeys = NIL;
1048 
1049  return pathkeys;
1050 }
signed short int16
Definition: c.h:480
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
bool get_ordering_op_properties(Oid opno, Oid *opfamily, Oid *opcintype, int16 *strategy)
Definition: lsyscache.c:207
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:788
static PathKey * make_pathkey_from_sortinfo(PlannerInfo *root, Expr *expr, Oid opfamily, Oid opcintype, Oid collation, bool reverse_sort, bool nulls_first, Index sortref, Relids rel, bool create_it)
Definition: pathkeys.c:197
unsigned int Oid
Definition: postgres_ext.h:31
#define BTGreaterStrategyNumber
Definition: stratnum.h:33

References BTGreaterStrategyNumber, elog, ERROR, exprCollation(), get_ordering_op_properties(), list_make1, make_pathkey_from_sortinfo(), and NIL.

Referenced by set_function_pathlist().

◆ build_index_pathkeys()

List* build_index_pathkeys ( PlannerInfo root,
IndexOptInfo index,
ScanDirection  scandir 
)

Definition at line 755 of file pathkeys.c.

758 {
759  List *retval = NIL;
760  ListCell *lc;
761  int i;
762 
763  if (index->sortopfamily == NULL)
764  return NIL; /* non-orderable index */
765 
766  i = 0;
767  foreach(lc, index->indextlist)
768  {
769  TargetEntry *indextle = (TargetEntry *) lfirst(lc);
770  Expr *indexkey;
771  bool reverse_sort;
772  bool nulls_first;
773  PathKey *cpathkey;
774 
775  /*
776  * INCLUDE columns are stored in index unordered, so they don't
777  * support ordered index scan.
778  */
779  if (i >= index->nkeycolumns)
780  break;
781 
782  /* We assume we don't need to make a copy of the tlist item */
783  indexkey = indextle->expr;
784 
785  if (ScanDirectionIsBackward(scandir))
786  {
787  reverse_sort = !index->reverse_sort[i];
788  nulls_first = !index->nulls_first[i];
789  }
790  else
791  {
792  reverse_sort = index->reverse_sort[i];
793  nulls_first = index->nulls_first[i];
794  }
795 
796  /*
797  * OK, try to make a canonical pathkey for this sort key.
798  */
799  cpathkey = make_pathkey_from_sortinfo(root,
800  indexkey,
801  index->sortopfamily[i],
802  index->opcintype[i],
803  index->indexcollations[i],
804  reverse_sort,
805  nulls_first,
806  0,
807  index->rel->relids,
808  false);
809 
810  if (cpathkey)
811  {
812  /*
813  * We found the sort key in an EquivalenceClass, so it's relevant
814  * for this query. Add it to list, unless it's redundant.
815  */
816  if (!pathkey_is_redundant(cpathkey, retval))
817  retval = lappend(retval, cpathkey);
818  }
819  else
820  {
821  /*
822  * Boolean index keys might be redundant even if they do not
823  * appear in an EquivalenceClass, because of our special treatment
824  * of boolean equality conditions --- see the comment for
825  * indexcol_is_bool_constant_for_query(). If that applies, we can
826  * continue to examine lower-order index columns. Otherwise, the
827  * sort key is not an interesting sort order for this query, so we
828  * should stop considering index columns; any lower-order sort
829  * keys won't be useful either.
830  */
832  break;
833  }
834 
835  i++;
836  }
837 
838  return retval;
839 }
bool indexcol_is_bool_constant_for_query(PlannerInfo *root, IndexOptInfo *index, int indexcol)
Definition: indxpath.c:3707
#define ScanDirectionIsBackward(direction)
Definition: sdir.h:50
Expr * expr
Definition: primnodes.h:1943
Definition: type.h:95

References TargetEntry::expr, i, indexcol_is_bool_constant_for_query(), lappend(), lfirst, make_pathkey_from_sortinfo(), NIL, pathkey_is_redundant(), and ScanDirectionIsBackward.

Referenced by build_index_paths().

◆ build_join_pathkeys()

List* build_join_pathkeys ( PlannerInfo root,
RelOptInfo joinrel,
JoinType  jointype,
List outer_pathkeys 
)

Definition at line 1309 of file pathkeys.c.

1313 {
1314  if (jointype == JOIN_FULL ||
1315  jointype == JOIN_RIGHT ||
1316  jointype == JOIN_RIGHT_ANTI)
1317  return NIL;
1318 
1319  /*
1320  * This used to be quite a complex bit of code, but now that all pathkey
1321  * sublists start out life canonicalized, we don't have to do a darn thing
1322  * here!
1323  *
1324  * We do, however, need to truncate the pathkeys list, since it may
1325  * contain pathkeys that were useful for forming this joinrel but are
1326  * uninteresting to higher levels.
1327  */
1328  return truncate_useless_pathkeys(root, joinrel, outer_pathkeys);
1329 }
@ JOIN_RIGHT
Definition: nodes.h:286
@ JOIN_RIGHT_ANTI
Definition: nodes.h:299
List * truncate_useless_pathkeys(PlannerInfo *root, RelOptInfo *rel, List *pathkeys)
Definition: pathkeys.c:2199

References JOIN_FULL, JOIN_RIGHT, JOIN_RIGHT_ANTI, NIL, and truncate_useless_pathkeys().

Referenced by consider_parallel_mergejoin(), consider_parallel_nestloop(), match_unsorted_outer(), and sort_inner_and_outer().

◆ build_partition_pathkeys()

List* build_partition_pathkeys ( PlannerInfo root,
RelOptInfo partrel,
ScanDirection  scandir,
bool partialkeys 
)

Definition at line 934 of file pathkeys.c.

936 {
937  List *retval = NIL;
938  PartitionScheme partscheme = partrel->part_scheme;
939  int i;
940 
941  Assert(partscheme != NULL);
942  Assert(partitions_are_ordered(partrel->boundinfo, partrel->live_parts));
943  /* For now, we can only cope with baserels */
944  Assert(IS_SIMPLE_REL(partrel));
945 
946  for (i = 0; i < partscheme->partnatts; i++)
947  {
948  PathKey *cpathkey;
949  Expr *keyCol = (Expr *) linitial(partrel->partexprs[i]);
950 
951  /*
952  * Try to make a canonical pathkey for this partkey.
953  *
954  * We assume the PartitionDesc lists any NULL partition last, so we
955  * treat the scan like a NULLS LAST index: we have nulls_first for
956  * backwards scan only.
957  */
958  cpathkey = make_pathkey_from_sortinfo(root,
959  keyCol,
960  partscheme->partopfamily[i],
961  partscheme->partopcintype[i],
962  partscheme->partcollation[i],
963  ScanDirectionIsBackward(scandir),
964  ScanDirectionIsBackward(scandir),
965  0,
966  partrel->relids,
967  false);
968 
969 
970  if (cpathkey)
971  {
972  /*
973  * We found the sort key in an EquivalenceClass, so it's relevant
974  * for this query. Add it to list, unless it's redundant.
975  */
976  if (!pathkey_is_redundant(cpathkey, retval))
977  retval = lappend(retval, cpathkey);
978  }
979  else
980  {
981  /*
982  * Boolean partition keys might be redundant even if they do not
983  * appear in an EquivalenceClass, because of our special treatment
984  * of boolean equality conditions --- see the comment for
985  * partkey_is_bool_constant_for_query(). If that applies, we can
986  * continue to examine lower-order partition keys. Otherwise, the
987  * sort key is not an interesting sort order for this query, so we
988  * should stop considering partition columns; any lower-order sort
989  * keys won't be useful either.
990  */
991  if (!partkey_is_bool_constant_for_query(partrel, i))
992  {
993  *partialkeys = true;
994  return retval;
995  }
996  }
997  }
998 
999  *partialkeys = false;
1000  return retval;
1001 }
bool partitions_are_ordered(PartitionBoundInfo boundinfo, Bitmapset *live_parts)
Definition: partbounds.c:2852
static bool partkey_is_bool_constant_for_query(RelOptInfo *partrel, int partkeycol)
Definition: pathkeys.c:859
Bitmapset * live_parts
Definition: pathnodes.h:1020

References Assert(), i, IS_SIMPLE_REL, lappend(), linitial, RelOptInfo::live_parts, make_pathkey_from_sortinfo(), NIL, PartitionSchemeData::partcollation, partitions_are_ordered(), partkey_is_bool_constant_for_query(), PartitionSchemeData::partnatts, PartitionSchemeData::partopcintype, PartitionSchemeData::partopfamily, pathkey_is_redundant(), RelOptInfo::relids, and ScanDirectionIsBackward.

Referenced by generate_orderedappend_paths().

◆ canonicalize_ec_expression()

Expr* canonicalize_ec_expression ( Expr expr,
Oid  req_type,
Oid  req_collation 
)

Definition at line 472 of file equivclass.c.

473 {
474  Oid expr_type = exprType((Node *) expr);
475 
476  /*
477  * For a polymorphic-input-type opclass, just keep the same exposed type.
478  * RECORD opclasses work like polymorphic-type ones for this purpose.
479  */
480  if (IsPolymorphicType(req_type) || req_type == RECORDOID)
481  req_type = expr_type;
482 
483  /*
484  * No work if the expression exposes the right type/collation already.
485  */
486  if (expr_type != req_type ||
487  exprCollation((Node *) expr) != req_collation)
488  {
489  /*
490  * If we have to change the type of the expression, set typmod to -1,
491  * since the new type may not have the same typmod interpretation.
492  * When we only have to change collation, preserve the exposed typmod.
493  */
494  int32 req_typmod;
495 
496  if (expr_type != req_type)
497  req_typmod = -1;
498  else
499  req_typmod = exprTypmod((Node *) expr);
500 
501  /*
502  * Use applyRelabelType so that we preserve const-flatness. This is
503  * important since eval_const_expressions has already been applied.
504  */
505  expr = (Expr *) applyRelabelType((Node *) expr,
506  req_type, req_typmod, req_collation,
507  COERCE_IMPLICIT_CAST, -1, false);
508  }
509 
510  return expr;
511 }
signed int int32
Definition: c.h:481
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:284
Node * applyRelabelType(Node *arg, Oid rtype, int32 rtypmod, Oid rcollid, CoercionForm rformat, int rlocation, bool overwrite_ok)
Definition: nodeFuncs.c:603
@ COERCE_IMPLICIT_CAST
Definition: primnodes.h:692

References applyRelabelType(), COERCE_IMPLICIT_CAST, exprCollation(), exprType(), and exprTypmod().

Referenced by convert_subquery_pathkeys(), get_eclass_for_sort_expr(), and process_equivalence().

◆ check_index_predicates()

void check_index_predicates ( PlannerInfo root,
RelOptInfo rel 
)

Definition at line 3298 of file indxpath.c.

3299 {
3300  List *clauselist;
3301  bool have_partial;
3302  bool is_target_rel;
3303  Relids otherrels;
3304  ListCell *lc;
3305 
3306  /* Indexes are available only on base or "other" member relations. */
3307  Assert(IS_SIMPLE_REL(rel));
3308 
3309  /*
3310  * Initialize the indrestrictinfo lists to be identical to
3311  * baserestrictinfo, and check whether there are any partial indexes. If
3312  * not, this is all we need to do.
3313  */
3314  have_partial = false;
3315  foreach(lc, rel->indexlist)
3316  {
3318 
3319  index->indrestrictinfo = rel->baserestrictinfo;
3320  if (index->indpred)
3321  have_partial = true;
3322  }
3323  if (!have_partial)
3324  return;
3325 
3326  /*
3327  * Construct a list of clauses that we can assume true for the purpose of
3328  * proving the index(es) usable. Restriction clauses for the rel are
3329  * always usable, and so are any join clauses that are "movable to" this
3330  * rel. Also, we can consider any EC-derivable join clauses (which must
3331  * be "movable to" this rel, by definition).
3332  */
3333  clauselist = list_copy(rel->baserestrictinfo);
3334 
3335  /* Scan the rel's join clauses */
3336  foreach(lc, rel->joininfo)
3337  {
3338  RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
3339 
3340  /* Check if clause can be moved to this rel */
3341  if (!join_clause_is_movable_to(rinfo, rel))
3342  continue;
3343 
3344  clauselist = lappend(clauselist, rinfo);
3345  }
3346 
3347  /*
3348  * Add on any equivalence-derivable join clauses. Computing the correct
3349  * relid sets for generate_join_implied_equalities is slightly tricky
3350  * because the rel could be a child rel rather than a true baserel, and in
3351  * that case we must subtract its parents' relid(s) from all_query_rels.
3352  * Additionally, we mustn't consider clauses that are only computable
3353  * after outer joins that can null the rel.
3354  */
3355  if (rel->reloptkind == RELOPT_OTHER_MEMBER_REL)
3356  otherrels = bms_difference(root->all_query_rels,
3357  find_childrel_parents(root, rel));
3358  else
3359  otherrels = bms_difference(root->all_query_rels, rel->relids);
3360  otherrels = bms_del_members(otherrels, rel->nulling_relids);
3361 
3362  if (!bms_is_empty(otherrels))
3363  clauselist =
3364  list_concat(clauselist,
3366  bms_union(rel->relids,
3367  otherrels),
3368  otherrels,
3369  rel,
3370  NULL));
3371 
3372  /*
3373  * Normally we remove quals that are implied by a partial index's
3374  * predicate from indrestrictinfo, indicating that they need not be
3375  * checked explicitly by an indexscan plan using this index. However, if
3376  * the rel is a target relation of UPDATE/DELETE/MERGE/SELECT FOR UPDATE,
3377  * we cannot remove such quals from the plan, because they need to be in
3378  * the plan so that they will be properly rechecked by EvalPlanQual
3379  * testing. Some day we might want to remove such quals from the main
3380  * plan anyway and pass them through to EvalPlanQual via a side channel;
3381  * but for now, we just don't remove implied quals at all for target
3382  * relations.
3383  */
3384  is_target_rel = (bms_is_member(rel->relid, root->all_result_relids) ||
3385  get_plan_rowmark(root->rowMarks, rel->relid) != NULL);
3386 
3387  /*
3388  * Now try to prove each index predicate true, and compute the
3389  * indrestrictinfo lists for partial indexes. Note that we compute the
3390  * indrestrictinfo list even for non-predOK indexes; this might seem
3391  * wasteful, but we may be able to use such indexes in OR clauses, cf
3392  * generate_bitmap_or_paths().
3393  */
3394  foreach(lc, rel->indexlist)
3395  {
3397  ListCell *lcr;
3398 
3399  if (index->indpred == NIL)
3400  continue; /* ignore non-partial indexes here */
3401 
3402  if (!index->predOK) /* don't repeat work if already proven OK */
3403  index->predOK = predicate_implied_by(index->indpred, clauselist,
3404  false);
3405 
3406  /* If rel is an update target, leave indrestrictinfo as set above */
3407  if (is_target_rel)
3408  continue;
3409 
3410  /* Else compute indrestrictinfo as the non-implied quals */
3411  index->indrestrictinfo = NIL;
3412  foreach(lcr, rel->baserestrictinfo)
3413  {
3414  RestrictInfo *rinfo = (RestrictInfo *) lfirst(lcr);
3415 
3416  /* predicate_implied_by() assumes first arg is immutable */
3417  if (contain_mutable_functions((Node *) rinfo->clause) ||
3419  index->indpred, false))
3420  index->indrestrictinfo = lappend(index->indrestrictinfo, rinfo);
3421  }
3422  }
3423 }
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:251
Bitmapset * bms_del_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:1161
bool contain_mutable_functions(Node *clause)
Definition: clauses.c:369
List * generate_join_implied_equalities(PlannerInfo *root, Relids join_relids, Relids outer_relids, RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo)
Definition: equivclass.c:1392
List * list_copy(const List *oldlist)
Definition: list.c:1573
List * list_concat(List *list1, const List *list2)
Definition: list.c:561
@ RELOPT_OTHER_MEMBER_REL
Definition: pathnodes.h:814
bool predicate_implied_by(List *predicate_list, List *clause_list, bool weak)
Definition: predtest.c:152
PlanRowMark * get_plan_rowmark(List *rowmarks, Index rtindex)
Definition: preptlist.c:485
Relids find_childrel_parents(PlannerInfo *root, RelOptInfo *rel)
Definition: relnode.c:1514
bool join_clause_is_movable_to(RestrictInfo *rinfo, RelOptInfo *baserel)
Definition: restrictinfo.c:584
Relids all_query_rels
Definition: pathnodes.h:266
List * rowMarks
Definition: pathnodes.h:368
Relids all_result_relids
Definition: pathnodes.h:351
List * baserestrictinfo
Definition: pathnodes.h:966
List * joininfo
Definition: pathnodes.h:972
Index relid
Definition: pathnodes.h:903
List * indexlist
Definition: pathnodes.h:925
Relids nulling_relids
Definition: pathnodes.h:919
Expr * clause
Definition: pathnodes.h:2541

References PlannerInfo::all_query_rels, PlannerInfo::all_result_relids, Assert(), RelOptInfo::baserestrictinfo, bms_del_members(), bms_difference(), bms_is_empty, bms_is_member(), bms_union(), RestrictInfo::clause, contain_mutable_functions(), find_childrel_parents(), generate_join_implied_equalities(), get_plan_rowmark(), RelOptInfo::indexlist, IS_SIMPLE_REL, join_clause_is_movable_to(), RelOptInfo::joininfo, lappend(), lfirst, list_concat(), list_copy(), list_make1, NIL, RelOptInfo::nulling_relids, predicate_implied_by(), RelOptInfo::relid, RelOptInfo::relids, RELOPT_OTHER_MEMBER_REL, RelOptInfo::reloptkind, and PlannerInfo::rowMarks.

Referenced by set_plain_rel_size(), and set_tablesample_rel_size().

◆ compare_pathkeys()

PathKeysComparison compare_pathkeys ( List keys1,
List keys2 
)

Definition at line 302 of file pathkeys.c.

303 {
304  ListCell *key1,
305  *key2;
306 
307  /*
308  * Fall out quickly if we are passed two identical lists. This mostly
309  * catches the case where both are NIL, but that's common enough to
310  * warrant the test.
311  */
312  if (keys1 == keys2)
313  return PATHKEYS_EQUAL;
314 
315  forboth(key1, keys1, key2, keys2)
316  {
317  PathKey *pathkey1 = (PathKey *) lfirst(key1);
318  PathKey *pathkey2 = (PathKey *) lfirst(key2);
319 
320  if (pathkey1 != pathkey2)
321  return PATHKEYS_DIFFERENT; /* no need to keep looking */
322  }
323 
324  /*
325  * If we reached the end of only one list, the other is longer and
326  * therefore not a subset.
327  */
328  if (key1 != NULL)
329  return PATHKEYS_BETTER1; /* key1 is longer */
330  if (key2 != NULL)
331  return PATHKEYS_BETTER2; /* key2 is longer */
332  return PATHKEYS_EQUAL;
333 }
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:518

References forboth, lfirst, PATHKEYS_BETTER1, PATHKEYS_BETTER2, PATHKEYS_DIFFERENT, and PATHKEYS_EQUAL.

Referenced by add_partial_path(), add_partial_path_precheck(), add_path(), add_path_precheck(), add_paths_to_append_rel(), adjust_group_pathkeys_for_groupagg(), pathkeys_are_duplicate(), pathkeys_contained_in(), and set_cheapest().

◆ compute_parallel_worker()

int compute_parallel_worker ( RelOptInfo rel,
double  heap_pages,
double  index_pages,
int  max_workers 
)

Definition at line 4210 of file allpaths.c.

4212 {
4213  int parallel_workers = 0;
4214 
4215  /*
4216  * If the user has set the parallel_workers reloption, use that; otherwise
4217  * select a default number of workers.
4218  */
4219  if (rel->rel_parallel_workers != -1)
4220  parallel_workers = rel->rel_parallel_workers;
4221  else
4222  {
4223  /*
4224  * If the number of pages being scanned is insufficient to justify a
4225  * parallel scan, just return zero ... unless it's an inheritance
4226  * child. In that case, we want to generate a parallel path here
4227  * anyway. It might not be worthwhile just for this relation, but
4228  * when combined with all of its inheritance siblings it may well pay
4229  * off.
4230  */
4231  if (rel->reloptkind == RELOPT_BASEREL &&
4232  ((heap_pages >= 0 && heap_pages < min_parallel_table_scan_size) ||
4233  (index_pages >= 0 && index_pages < min_parallel_index_scan_size)))
4234  return 0;
4235 
4236  if (heap_pages >= 0)
4237  {
4238  int heap_parallel_threshold;
4239  int heap_parallel_workers = 1;
4240 
4241  /*
4242  * Select the number of workers based on the log of the size of
4243  * the relation. This probably needs to be a good deal more
4244  * sophisticated, but we need something here for now. Note that
4245  * the upper limit of the min_parallel_table_scan_size GUC is
4246  * chosen to prevent overflow here.
4247  */
4248  heap_parallel_threshold = Max(min_parallel_table_scan_size, 1);
4249  while (heap_pages >= (BlockNumber) (heap_parallel_threshold * 3))
4250  {
4251  heap_parallel_workers++;
4252  heap_parallel_threshold *= 3;
4253  if (heap_parallel_threshold > INT_MAX / 3)
4254  break; /* avoid overflow */
4255  }
4256 
4257  parallel_workers = heap_parallel_workers;
4258  }
4259 
4260  if (index_pages >= 0)
4261  {
4262  int index_parallel_workers = 1;
4263  int index_parallel_threshold;
4264 
4265  /* same calculation as for heap_pages above */
4266  index_parallel_threshold = Max(min_parallel_index_scan_size, 1);
4267  while (index_pages >= (BlockNumber) (index_parallel_threshold * 3))
4268  {
4269  index_parallel_workers++;
4270  index_parallel_threshold *= 3;
4271  if (index_parallel_threshold > INT_MAX / 3)
4272  break; /* avoid overflow */
4273  }
4274 
4275  if (parallel_workers > 0)
4276  parallel_workers = Min(parallel_workers, index_parallel_workers);
4277  else
4278  parallel_workers = index_parallel_workers;
4279  }
4280  }
4281 
4282  /* In no case use more than caller supplied maximum number of workers */
4283  parallel_workers = Min(parallel_workers, max_workers);
4284 
4285  return parallel_workers;
4286 }
int min_parallel_index_scan_size
Definition: allpaths.c:82
int min_parallel_table_scan_size
Definition: allpaths.c:81
uint32 BlockNumber
Definition: block.h:31
int rel_parallel_workers
Definition: pathnodes.h:937

References Max, Min, min_parallel_index_scan_size, min_parallel_table_scan_size, RelOptInfo::rel_parallel_workers, RELOPT_BASEREL, and RelOptInfo::reloptkind.

Referenced by cost_index(), create_partial_bitmap_paths(), create_plain_partial_paths(), and plan_create_index_workers().

◆ convert_subquery_pathkeys()

List* convert_subquery_pathkeys ( PlannerInfo root,
RelOptInfo rel,
List subquery_pathkeys,
List subquery_tlist 
)

Definition at line 1069 of file pathkeys.c.

1072 {
1073  List *retval = NIL;
1074  int retvallen = 0;
1075  int outer_query_keys = list_length(root->query_pathkeys);
1076  ListCell *i;
1077 
1078  foreach(i, subquery_pathkeys)
1079  {
1080  PathKey *sub_pathkey = (PathKey *) lfirst(i);
1081  EquivalenceClass *sub_eclass = sub_pathkey->pk_eclass;
1082  PathKey *best_pathkey = NULL;
1083 
1084  if (sub_eclass->ec_has_volatile)
1085  {
1086  /*
1087  * If the sub_pathkey's EquivalenceClass is volatile, then it must
1088  * have come from an ORDER BY clause, and we have to match it to
1089  * that same targetlist entry.
1090  */
1091  TargetEntry *tle;
1092  Var *outer_var;
1093 
1094  if (sub_eclass->ec_sortref == 0) /* can't happen */
1095  elog(ERROR, "volatile EquivalenceClass has no sortref");
1096  tle = get_sortgroupref_tle(sub_eclass->ec_sortref, subquery_tlist);
1097  Assert(tle);
1098  /* Is TLE actually available to the outer query? */
1099  outer_var = find_var_for_subquery_tle(rel, tle);
1100  if (outer_var)
1101  {
1102  /* We can represent this sub_pathkey */
1103  EquivalenceMember *sub_member;
1104  EquivalenceClass *outer_ec;
1105 
1106  Assert(list_length(sub_eclass->ec_members) == 1);
1107  sub_member = (EquivalenceMember *) linitial(sub_eclass->ec_members);
1108 
1109  /*
1110  * Note: it might look funny to be setting sortref = 0 for a
1111  * reference to a volatile sub_eclass. However, the
1112  * expression is *not* volatile in the outer query: it's just
1113  * a Var referencing whatever the subquery emitted. (IOW, the
1114  * outer query isn't going to re-execute the volatile
1115  * expression itself.) So this is okay.
1116  */
1117  outer_ec =
1119  (Expr *) outer_var,
1120  sub_eclass->ec_opfamilies,
1121  sub_member->em_datatype,
1122  sub_eclass->ec_collation,
1123  0,
1124  rel->relids,
1125  false);
1126 
1127  /*
1128  * If we don't find a matching EC, sub-pathkey isn't
1129  * interesting to the outer query
1130  */
1131  if (outer_ec)
1132  best_pathkey =
1134  outer_ec,
1135  sub_pathkey->pk_opfamily,
1136  sub_pathkey->pk_strategy,
1137  sub_pathkey->pk_nulls_first);
1138  }
1139  }
1140  else
1141  {
1142  /*
1143  * Otherwise, the sub_pathkey's EquivalenceClass could contain
1144  * multiple elements (representing knowledge that multiple items
1145  * are effectively equal). Each element might match none, one, or
1146  * more of the output columns that are visible to the outer query.
1147  * This means we may have multiple possible representations of the
1148  * sub_pathkey in the context of the outer query. Ideally we
1149  * would generate them all and put them all into an EC of the
1150  * outer query, thereby propagating equality knowledge up to the
1151  * outer query. Right now we cannot do so, because the outer
1152  * query's EquivalenceClasses are already frozen when this is
1153  * called. Instead we prefer the one that has the highest "score"
1154  * (number of EC peers, plus one if it matches the outer
1155  * query_pathkeys). This is the most likely to be useful in the
1156  * outer query.
1157  */
1158  int best_score = -1;
1159  ListCell *j;
1160 
1161  foreach(j, sub_eclass->ec_members)
1162  {
1163  EquivalenceMember *sub_member = (EquivalenceMember *) lfirst(j);
1164  Expr *sub_expr = sub_member->em_expr;
1165  Oid sub_expr_type = sub_member->em_datatype;
1166  Oid sub_expr_coll = sub_eclass->ec_collation;
1167  ListCell *k;
1168 
1169  if (sub_member->em_is_child)
1170  continue; /* ignore children here */
1171 
1172  foreach(k, subquery_tlist)
1173  {
1174  TargetEntry *tle = (TargetEntry *) lfirst(k);
1175  Var *outer_var;
1176  Expr *tle_expr;
1177  EquivalenceClass *outer_ec;
1178  PathKey *outer_pk;
1179  int score;
1180 
1181  /* Is TLE actually available to the outer query? */
1182  outer_var = find_var_for_subquery_tle(rel, tle);
1183  if (!outer_var)
1184  continue;
1185 
1186  /*
1187  * The targetlist entry is considered to match if it
1188  * matches after sort-key canonicalization. That is
1189  * needed since the sub_expr has been through the same
1190  * process.
1191  */
1192  tle_expr = canonicalize_ec_expression(tle->expr,
1193  sub_expr_type,
1194  sub_expr_coll);
1195  if (!equal(tle_expr, sub_expr))
1196  continue;
1197 
1198  /* See if we have a matching EC for the TLE */
1199  outer_ec = get_eclass_for_sort_expr(root,
1200  (Expr *) outer_var,
1201  sub_eclass->ec_opfamilies,
1202  sub_expr_type,
1203  sub_expr_coll,
1204  0,
1205  rel->relids,
1206  false);
1207 
1208  /*
1209  * If we don't find a matching EC, this sub-pathkey isn't
1210  * interesting to the outer query
1211  */
1212  if (!outer_ec)
1213  continue;
1214 
1215  outer_pk = make_canonical_pathkey(root,
1216  outer_ec,
1217  sub_pathkey->pk_opfamily,
1218  sub_pathkey->pk_strategy,
1219  sub_pathkey->pk_nulls_first);
1220  /* score = # of equivalence peers */
1221  score = list_length(outer_ec->ec_members) - 1;
1222  /* +1 if it matches the proper query_pathkeys item */
1223  if (retvallen < outer_query_keys &&
1224  list_nth(root->query_pathkeys, retvallen) == outer_pk)
1225  score++;
1226  if (score > best_score)
1227  {
1228  best_pathkey = outer_pk;
1229  best_score = score;
1230  }
1231  }
1232  }
1233  }
1234 
1235  /*
1236  * If we couldn't find a representation of this sub_pathkey, we're
1237  * done (we can't use the ones to its right, either).
1238  */
1239  if (!best_pathkey)
1240  break;
1241 
1242  /*
1243  * Eliminate redundant ordering info; could happen if outer query
1244  * equivalences subquery keys...
1245  */
1246  if (!pathkey_is_redundant(best_pathkey, retval))
1247  {
1248  retval = lappend(retval, best_pathkey);
1249  retvallen++;
1250  }
1251  }
1252 
1253  return retval;
1254 }
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:223
Expr * canonicalize_ec_expression(Expr *expr, Oid req_type, Oid req_collation)
Definition: equivclass.c:472
EquivalenceClass * get_eclass_for_sort_expr(PlannerInfo *root, Expr *expr, List *opfamilies, Oid opcintype, Oid collation, Index sortref, Relids rel, bool create_it)
Definition: equivclass.c:587
int j
Definition: isn.c:74
static Var * find_var_for_subquery_tle(RelOptInfo *rel, TargetEntry *tle)
Definition: pathkeys.c:1266
PathKey * make_canonical_pathkey(PlannerInfo *root, EquivalenceClass *eclass, Oid opfamily, int strategy, bool nulls_first)
Definition: pathkeys.c:55
List * ec_opfamilies
Definition: pathnodes.h:1370
bool pk_nulls_first
Definition: pathnodes.h:1458
int pk_strategy
Definition: pathnodes.h:1457
Oid pk_opfamily
Definition: pathnodes.h:1456
List * query_pathkeys
Definition: pathnodes.h:382
Definition: primnodes.h:234
TargetEntry * get_sortgroupref_tle(Index sortref, List *targetList)
Definition: tlist.c:345

References Assert(), canonicalize_ec_expression(), EquivalenceClass::ec_collation, EquivalenceClass::ec_has_volatile, EquivalenceClass::ec_members, EquivalenceClass::ec_opfamilies, EquivalenceClass::ec_sortref, elog, EquivalenceMember::em_datatype, EquivalenceMember::em_expr, EquivalenceMember::em_is_child, equal(), ERROR, TargetEntry::expr, find_var_for_subquery_tle(), get_eclass_for_sort_expr(), get_sortgroupref_tle(), i, j, lappend(), lfirst, linitial, list_length(), list_nth(), make_canonical_pathkey(), NIL, pathkey_is_redundant(), PathKey::pk_nulls_first, PathKey::pk_opfamily, PathKey::pk_strategy, PlannerInfo::query_pathkeys, and RelOptInfo::relids.

Referenced by set_subquery_pathlist().

◆ create_index_paths()

void create_index_paths ( PlannerInfo root,
RelOptInfo rel 
)

Definition at line 235 of file indxpath.c.

236 {
237  List *indexpaths;
238  List *bitindexpaths;
239  List *bitjoinpaths;
240  List *joinorclauses;
241  IndexClauseSet rclauseset;
242  IndexClauseSet jclauseset;
243  IndexClauseSet eclauseset;
244  ListCell *lc;
245 
246  /* Skip the whole mess if no indexes */
247  if (rel->indexlist == NIL)
248  return;
249 
250  /* Bitmap paths are collected and then dealt with at the end */
251  bitindexpaths = bitjoinpaths = joinorclauses = NIL;
252 
253  /* Examine each index in turn */
254  foreach(lc, rel->indexlist)
255  {
257 
258  /* Protect limited-size array in IndexClauseSets */
259  Assert(index->nkeycolumns <= INDEX_MAX_KEYS);
260 
261  /*
262  * Ignore partial indexes that do not match the query.
263  * (generate_bitmap_or_paths() might be able to do something with
264  * them, but that's of no concern here.)
265  */
266  if (index->indpred != NIL && !index->predOK)
267  continue;
268 
269  /*
270  * Identify the restriction clauses that can match the index.
271  */
272  MemSet(&rclauseset, 0, sizeof(rclauseset));
273  match_restriction_clauses_to_index(root, index, &rclauseset);
274 
275  /*
276  * Build index paths from the restriction clauses. These will be
277  * non-parameterized paths. Plain paths go directly to add_path(),
278  * bitmap paths are added to bitindexpaths to be handled below.
279  */
280  get_index_paths(root, rel, index, &rclauseset,
281  &bitindexpaths);
282 
283  /*
284  * Identify the join clauses that can match the index. For the moment
285  * we keep them separate from the restriction clauses. Note that this
286  * step finds only "loose" join clauses that have not been merged into
287  * EquivalenceClasses. Also, collect join OR clauses for later.
288  */
289  MemSet(&jclauseset, 0, sizeof(jclauseset));
291  &jclauseset, &joinorclauses);
292 
293  /*
294  * Look for EquivalenceClasses that can generate joinclauses matching
295  * the index.
296  */
297  MemSet(&eclauseset, 0, sizeof(eclauseset));
299  &eclauseset);
300 
301  /*
302  * If we found any plain or eclass join clauses, build parameterized
303  * index paths using them.
304  */
305  if (jclauseset.nonempty || eclauseset.nonempty)
307  &rclauseset,
308  &jclauseset,
309  &eclauseset,
310  &bitjoinpaths);
311  }
312 
313  /*
314  * Generate BitmapOrPaths for any suitable OR-clauses present in the
315  * restriction list. Add these to bitindexpaths.
316  */
317  indexpaths = generate_bitmap_or_paths(root, rel,
318  rel->baserestrictinfo, NIL);
319  bitindexpaths = list_concat(bitindexpaths, indexpaths);
320 
321  /*
322  * Likewise, generate BitmapOrPaths for any suitable OR-clauses present in
323  * the joinclause list. Add these to bitjoinpaths.
324  */
325  indexpaths = generate_bitmap_or_paths(root, rel,
326  joinorclauses, rel->baserestrictinfo);
327  bitjoinpaths = list_concat(bitjoinpaths, indexpaths);
328 
329  /*
330  * If we found anything usable, generate a BitmapHeapPath for the most
331  * promising combination of restriction bitmap index paths. Note there
332  * will be only one such path no matter how many indexes exist. This
333  * should be sufficient since there's basically only one figure of merit
334  * (total cost) for such a path.
335  */
336  if (bitindexpaths != NIL)
337  {
338  Path *bitmapqual;
339  BitmapHeapPath *bpath;
340 
341  bitmapqual = choose_bitmap_and(root, rel, bitindexpaths);
342  bpath = create_bitmap_heap_path(root, rel, bitmapqual,
343  rel->lateral_relids, 1.0, 0);
344  add_path(rel, (Path *) bpath);
345 
346  /* create a partial bitmap heap path */
347  if (rel->consider_parallel && rel->lateral_relids == NULL)
348  create_partial_bitmap_paths(root, rel, bitmapqual);
349  }
350 
351  /*
352  * Likewise, if we found anything usable, generate BitmapHeapPaths for the
353  * most promising combinations of join bitmap index paths. Our strategy
354  * is to generate one such path for each distinct parameterization seen
355  * among the available bitmap index paths. This may look pretty
356  * expensive, but usually there won't be very many distinct
357  * parameterizations. (This logic is quite similar to that in
358  * consider_index_join_clauses, but we're working with whole paths not
359  * individual clauses.)
360  */
361  if (bitjoinpaths != NIL)
362  {
363  List *all_path_outers;
364 
365  /* Identify each distinct parameterization seen in bitjoinpaths */
366  all_path_outers = NIL;
367  foreach(lc, bitjoinpaths)
368  {
369  Path *path = (Path *) lfirst(lc);
370  Relids required_outer = PATH_REQ_OUTER(path);
371 
372  all_path_outers = list_append_unique(all_path_outers,
373  required_outer);
374  }
375 
376  /* Now, for each distinct parameterization set ... */
377  foreach(lc, all_path_outers)
378  {
379  Relids max_outers = (Relids) lfirst(lc);
380  List *this_path_set;
381  Path *bitmapqual;
382  Relids required_outer;
383  double loop_count;
384  BitmapHeapPath *bpath;
385  ListCell *lcp;
386 
387  /* Identify all the bitmap join paths needing no more than that */
388  this_path_set = NIL;
389  foreach(lcp, bitjoinpaths)
390  {
391  Path *path = (Path *) lfirst(lcp);
392 
393  if (bms_is_subset(PATH_REQ_OUTER(path), max_outers))
394  this_path_set = lappend(this_path_set, path);
395  }
396 
397  /*
398  * Add in restriction bitmap paths, since they can be used
399  * together with any join paths.
400  */
401  this_path_set = list_concat(this_path_set, bitindexpaths);
402 
403  /* Select best AND combination for this parameterization */
404  bitmapqual = choose_bitmap_and(root, rel, this_path_set);
405 
406  /* And push that path into the mix */
407  required_outer = PATH_REQ_OUTER(bitmapqual);
408  loop_count = get_loop_count(root, rel->relid, required_outer);
409  bpath = create_bitmap_heap_path(root, rel, bitmapqual,
410  required_outer, loop_count, 0);
411  add_path(rel, (Path *) bpath);
412  }
413  }
414 }
void create_partial_bitmap_paths(PlannerInfo *root, RelOptInfo *rel, Path *bitmapqual)
Definition: allpaths.c:4174
#define MemSet(start, val, len)
Definition: c.h:1007
static Path * choose_bitmap_and(PlannerInfo *root, RelOptInfo *rel, List *paths)
Definition: indxpath.c:1341
static void match_join_clauses_to_index(PlannerInfo *root, RelOptInfo *rel, IndexOptInfo *index, IndexClauseSet *clauseset, List **joinorclauses)
Definition: indxpath.c:2037
static void match_eclass_clauses_to_index(PlannerInfo *root, IndexOptInfo *index, IndexClauseSet *clauseset)
Definition: indxpath.c:2067
static void get_index_paths(PlannerInfo *root, RelOptInfo *rel, IndexOptInfo *index, IndexClauseSet *clauses, List **bitindexpaths)
Definition: indxpath.c:713
static double get_loop_count(PlannerInfo *root, Index cur_relid, Relids outer_relids)
Definition: indxpath.c:1883
static void consider_index_join_clauses(PlannerInfo *root, RelOptInfo *rel, IndexOptInfo *index, IndexClauseSet *rclauseset, IndexClauseSet *jclauseset, IndexClauseSet *eclauseset, List **bitindexpaths)
Definition: indxpath.c:432
static void match_restriction_clauses_to_index(PlannerInfo *root, IndexOptInfo *index, IndexClauseSet *clauseset)
Definition: indxpath.c:2022
static List * generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel, List *clauses, List *other_clauses)
Definition: indxpath.c:1234
List * list_append_unique(List *list, void *datum)
Definition: list.c:1343
BitmapHeapPath * create_bitmap_heap_path(PlannerInfo *root, RelOptInfo *rel, Path *bitmapqual, Relids required_outer, double loop_count, int parallel_degree)
Definition: pathnode.c:1040
#define INDEX_MAX_KEYS
bool nonempty
Definition: indxpath.c:54

References add_path(), Assert(), RelOptInfo::baserestrictinfo, bms_is_subset(), choose_bitmap_and(), consider_index_join_clauses(), RelOptInfo::consider_parallel, create_bitmap_heap_path(), create_partial_bitmap_paths(), generate_bitmap_or_paths(), get_index_paths(), get_loop_count(), INDEX_MAX_KEYS, RelOptInfo::indexlist, lappend(), RelOptInfo::lateral_relids, lfirst, list_append_unique(), list_concat(), match_eclass_clauses_to_index(), match_join_clauses_to_index(), match_restriction_clauses_to_index(), MemSet, NIL, IndexClauseSet::nonempty, PATH_REQ_OUTER, and RelOptInfo::relid.

Referenced by set_plain_rel_pathlist().

◆ create_partial_bitmap_paths()

void create_partial_bitmap_paths ( PlannerInfo root,
RelOptInfo rel,
Path bitmapqual 
)

Definition at line 4174 of file allpaths.c.

4176 {
4177  int parallel_workers;
4178  double pages_fetched;
4179 
4180  /* Compute heap pages for bitmap heap scan */
4181  pages_fetched = compute_bitmap_pages(root, rel, bitmapqual, 1.0,
4182  NULL, NULL);
4183 
4184  parallel_workers = compute_parallel_worker(rel, pages_fetched, -1,
4186 
4187  if (parallel_workers <= 0)
4188  return;
4189 
4190  add_partial_path(rel, (Path *) create_bitmap_heap_path(root, rel,
4191  bitmapqual, rel->lateral_relids, 1.0, parallel_workers));
4192 }
int compute_parallel_worker(RelOptInfo *rel, double heap_pages, double index_pages, int max_workers)
Definition: allpaths.c:4210
double compute_bitmap_pages(PlannerInfo *root, RelOptInfo *baserel, Path *bitmapqual, double loop_count, Cost *cost_p, double *tuples_p)
Definition: costsize.c:6433

References add_partial_path(), compute_bitmap_pages(), compute_parallel_worker(), create_bitmap_heap_path(), RelOptInfo::lateral_relids, and max_parallel_workers_per_gather.

Referenced by create_index_paths().

◆ create_tidscan_paths()

void create_tidscan_paths ( PlannerInfo root,
RelOptInfo rel 
)

Definition at line 459 of file tidpath.c.

460 {
461  List *tidquals;
462  List *tidrangequals;
463 
464  /*
465  * If any suitable quals exist in the rel's baserestrict list, generate a
466  * plain (unparameterized) TidPath with them.
467  */
468  tidquals = TidQualFromRestrictInfoList(root, rel->baserestrictinfo, rel);
469 
470  if (tidquals != NIL)
471  {
472  /*
473  * This path uses no join clauses, but it could still have required
474  * parameterization due to LATERAL refs in its tlist.
475  */
476  Relids required_outer = rel->lateral_relids;
477 
478  add_path(rel, (Path *) create_tidscan_path(root, rel, tidquals,
479  required_outer));
480  }
481 
482  /*
483  * If there are range quals in the baserestrict list, generate a
484  * TidRangePath.
485  */
487  rel);
488 
489  if (tidrangequals != NIL)
490  {
491  /*
492  * This path uses no join clauses, but it could still have required
493  * parameterization due to LATERAL refs in its tlist.
494  */
495  Relids required_outer = rel->lateral_relids;
496 
497  add_path(rel, (Path *) create_tidrangescan_path(root, rel,
498  tidrangequals,
499  required_outer));
500  }
501 
502  /*
503  * Try to generate parameterized TidPaths using equality clauses extracted
504  * from EquivalenceClasses. (This is important since simple "t1.ctid =
505  * t2.ctid" clauses will turn into ECs.)
506  */
507  if (rel->has_eclass_joins)
508  {
509  List *clauses;
510 
511  /* Generate clauses, skipping any that join to lateral_referencers */
513  rel,
515  NULL,
516  rel->lateral_referencers);
517 
518  /* Generate a path for each usable join clause */
519  BuildParameterizedTidPaths(root, rel, clauses);
520  }
521 
522  /*
523  * Also consider parameterized TidPaths using "loose" join quals. Quals
524  * of the form "t1.ctid = t2.ctid" would turn into these if they are outer
525  * join quals, for example.
526  */
527  BuildParameterizedTidPaths(root, rel, rel->joininfo);
528 }
List * generate_implied_equalities_for_column(PlannerInfo *root, RelOptInfo *rel, ec_matches_callback_type callback, void *callback_arg, Relids prohibited_rels)
Definition: equivclass.c:2895
TidPath * create_tidscan_path(PlannerInfo *root, RelOptInfo *rel, List *tidquals, Relids required_outer)
Definition: pathnode.c:1177
TidRangePath * create_tidrangescan_path(PlannerInfo *root, RelOptInfo *rel, List *tidrangequals, Relids required_outer)
Definition: pathnode.c:1206
Relids lateral_referencers
Definition: pathnodes.h:923
bool has_eclass_joins
Definition: pathnodes.h:974
static void BuildParameterizedTidPaths(PlannerInfo *root, RelOptInfo *rel, List *clauses)
Definition: tidpath.c:387
static List * TidQualFromRestrictInfoList(PlannerInfo *root, List *rlist, RelOptInfo *rel)
Definition: tidpath.c:276
static List * TidRangeQualFromRestrictInfoList(List *rlist, RelOptInfo *rel)
Definition: tidpath.c:359
static bool ec_member_matches_ctid(PlannerInfo *root, RelOptInfo *rel, EquivalenceClass *ec, EquivalenceMember *em, void *arg)
Definition: tidpath.c:442

References add_path(), RelOptInfo::baserestrictinfo, BuildParameterizedTidPaths(), create_tidrangescan_path(), create_tidscan_path(), ec_member_matches_ctid(), generate_implied_equalities_for_column(), RelOptInfo::has_eclass_joins, RelOptInfo::joininfo, RelOptInfo::lateral_referencers, RelOptInfo::lateral_relids, NIL, TidQualFromRestrictInfoList(), and TidRangeQualFromRestrictInfoList().

Referenced by set_plain_rel_pathlist().

◆ eclass_useful_for_merging()

bool eclass_useful_for_merging ( PlannerInfo root,
EquivalenceClass eclass,
RelOptInfo rel 
)

Definition at line 3147 of file equivclass.c.

3150 {
3151  Relids relids;
3152  ListCell *lc;
3153 
3154  Assert(!eclass->ec_merged);
3155 
3156  /*
3157  * Won't generate joinclauses if const or single-member (the latter test
3158  * covers the volatile case too)
3159  */
3160  if (eclass->ec_has_const || list_length(eclass->ec_members) <= 1)
3161  return false;
3162 
3163  /*
3164  * Note we don't test ec_broken; if we did, we'd need a separate code path
3165  * to look through ec_sources. Checking the members anyway is OK as a
3166  * possibly-overoptimistic heuristic.
3167  */
3168 
3169  /* If specified rel is a child, we must consider the topmost parent rel */
3170  if (IS_OTHER_REL(rel))
3171  {
3173  relids = rel->top_parent_relids;
3174  }
3175  else
3176  relids = rel->relids;
3177 
3178  /* If rel already includes all members of eclass, no point in searching */
3179  if (bms_is_subset(eclass->ec_relids, relids))
3180  return false;
3181 
3182  /* To join, we need a member not in the given rel */
3183  foreach(lc, eclass->ec_members)
3184  {
3185  EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc);
3186 
3187  if (cur_em->em_is_child)
3188  continue; /* ignore children here */
3189 
3190  if (!bms_overlap(cur_em->em_relids, relids))
3191  return true;
3192  }
3193 
3194  return false;
3195 }
#define IS_OTHER_REL(rel)
Definition: pathnodes.h:839
static struct cvec * eclass(struct vars *v, chr c, int cases)
Definition: regc_locale.c:500

References Assert(), bms_is_empty, bms_is_subset(), bms_overlap(), eclass(), EquivalenceMember::em_is_child, EquivalenceMember::em_relids, IS_OTHER_REL, lfirst, list_length(), RelOptInfo::relids, and RelOptInfo::top_parent_relids.

Referenced by get_useful_ecs_for_relation(), and pathkeys_useful_for_merging().

◆ exprs_known_equal()

bool exprs_known_equal ( PlannerInfo root,
Node item1,
Node item2 
)

Definition at line 2450 of file equivclass.c.

2451 {
2452  ListCell *lc1;
2453 
2454  foreach(lc1, root->eq_classes)
2455  {
2456  EquivalenceClass *ec = (EquivalenceClass *) lfirst(lc1);
2457  bool item1member = false;
2458  bool item2member = false;
2459  ListCell *lc2;
2460 
2461  /* Never match to a volatile EC */
2462  if (ec->ec_has_volatile)
2463  continue;
2464 
2465  foreach(lc2, ec->ec_members)
2466  {
2468 
2469  if (em->em_is_child)
2470  continue; /* ignore children here */
2471  if (equal(item1, em->em_expr))
2472  item1member = true;
2473  else if (equal(item2, em->em_expr))
2474  item2member = true;
2475  /* Exit as soon as equality is proven */
2476  if (item1member && item2member)
2477  return true;
2478  }
2479  }
2480  return false;
2481 }

References EquivalenceClass::ec_has_volatile, EquivalenceClass::ec_members, EquivalenceMember::em_expr, EquivalenceMember::em_is_child, PlannerInfo::eq_classes, equal(), and lfirst.

Referenced by add_unique_group_var().

◆ find_computable_ec_member()

EquivalenceMember* find_computable_ec_member ( PlannerInfo root,
EquivalenceClass ec,
List exprs,
Relids  relids,
bool  require_parallel_safe 
)

Definition at line 836 of file equivclass.c.

841 {
842  ListCell *lc;
843 
844  foreach(lc, ec->ec_members)
845  {
847  List *exprvars;
848  ListCell *lc2;
849 
850  /*
851  * We shouldn't be trying to sort by an equivalence class that
852  * contains a constant, so no need to consider such cases any further.
853  */
854  if (em->em_is_const)
855  continue;
856 
857  /*
858  * Ignore child members unless they belong to the requested rel.
859  */
860  if (em->em_is_child &&
861  !bms_is_subset(em->em_relids, relids))
862  continue;
863 
864  /*
865  * Match if all Vars and quasi-Vars are available in "exprs".
866  */
867  exprvars = pull_var_clause((Node *) em->em_expr,
871  foreach(lc2, exprvars)
872  {
873  if (!is_exprlist_member(lfirst(lc2), exprs))
874  break;
875  }
876  list_free(exprvars);
877  if (lc2)
878  continue; /* we hit a non-available Var */
879 
880  /*
881  * If requested, reject expressions that are not parallel-safe. We
882  * check this last because it's a rather expensive test.
883  */
884  if (require_parallel_safe &&
885  !is_parallel_safe(root, (Node *) em->em_expr))
886  continue;
887 
888  return em; /* found usable expression */
889  }
890 
891  return NULL;
892 }
bool is_parallel_safe(PlannerInfo *root, Node *node)
Definition: clauses.c:733
static bool is_exprlist_member(Expr *node, List *exprs)
Definition: equivclass.c:902
void list_free(List *list)
Definition: list.c:1546
#define PVC_INCLUDE_WINDOWFUNCS
Definition: optimizer.h:188
#define PVC_INCLUDE_PLACEHOLDERS
Definition: optimizer.h:190
#define PVC_INCLUDE_AGGREGATES
Definition: optimizer.h:186
List * pull_var_clause(Node *node, int flags)
Definition: var.c:607

References bms_is_subset(), EquivalenceClass::ec_members, EquivalenceMember::em_expr, EquivalenceMember::em_is_child, EquivalenceMember::em_is_const, EquivalenceMember::em_relids, is_exprlist_member(), is_parallel_safe(), lfirst, list_free(), pull_var_clause(), PVC_INCLUDE_AGGREGATES, PVC_INCLUDE_PLACEHOLDERS, and PVC_INCLUDE_WINDOWFUNCS.

Referenced by prepare_sort_from_pathkeys(), and relation_can_be_sorted_early().

◆ find_derived_clause_for_ec_member()

RestrictInfo* find_derived_clause_for_ec_member ( EquivalenceClass ec,
EquivalenceMember em 
)

Definition at line 2592 of file equivclass.c.

2594 {
2595  ListCell *lc;
2596 
2597  Assert(ec->ec_has_const);
2598  Assert(!em->em_is_const);
2599  foreach(lc, ec->ec_derives)
2600  {
2601  RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
2602 
2603  /*
2604  * generate_base_implied_equalities_const will have put non-const
2605  * members on the left side of derived clauses.
2606  */
2607  if (rinfo->left_em == em)
2608  return rinfo;
2609  }
2610  return NULL;
2611 }

References Assert(), EquivalenceClass::ec_derives, EquivalenceClass::ec_has_const, EquivalenceMember::em_is_const, and lfirst.

Referenced by get_foreign_key_join_selectivity().

◆ find_ec_member_matching_expr()

EquivalenceMember* find_ec_member_matching_expr ( EquivalenceClass ec,
Expr expr,
Relids  relids 
)

Definition at line 771 of file equivclass.c.

774 {
775  ListCell *lc;
776 
777  /* We ignore binary-compatible relabeling on both ends */
778  while (expr && IsA(expr, RelabelType))
779  expr = ((RelabelType *) expr)->arg;
780 
781  foreach(lc, ec->ec_members)
782  {
784  Expr *emexpr;
785 
786  /*
787  * We shouldn't be trying to sort by an equivalence class that
788  * contains a constant, so no need to consider such cases any further.
789  */
790  if (em->em_is_const)
791  continue;
792 
793  /*
794  * Ignore child members unless they belong to the requested rel.
795  */
796  if (em->em_is_child &&
797  !bms_is_subset(em->em_relids, relids))
798  continue;
799 
800  /*
801  * Match if same expression (after stripping relabel).
802  */
803  emexpr = em->em_expr;
804  while (emexpr && IsA(emexpr, RelabelType))
805  emexpr = ((RelabelType *) emexpr)->arg;
806 
807  if (equal(emexpr, expr))
808  return em;
809  }
810 
811  return NULL;
812 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
void * arg

References arg, bms_is_subset(), EquivalenceClass::ec_members, EquivalenceMember::em_expr, EquivalenceMember::em_is_child, EquivalenceMember::em_is_const, EquivalenceMember::em_relids, equal(), IsA, and lfirst.

Referenced by make_unique_from_pathkeys(), prepare_sort_from_pathkeys(), and relation_can_be_sorted_early().

◆ find_mergeclauses_for_outer_pathkeys()

List* find_mergeclauses_for_outer_pathkeys ( PlannerInfo root,
List pathkeys,
List restrictinfos 
)

Definition at line 1527 of file pathkeys.c.

1530 {
1531  List *mergeclauses = NIL;
1532  ListCell *i;
1533 
1534  /* make sure we have eclasses cached in the clauses */
1535  foreach(i, restrictinfos)
1536  {
1537  RestrictInfo *rinfo = (RestrictInfo *) lfirst(i);
1538 
1539  update_mergeclause_eclasses(root, rinfo);
1540  }
1541 
1542  foreach(i, pathkeys)
1543  {
1544  PathKey *pathkey = (PathKey *) lfirst(i);
1545  EquivalenceClass *pathkey_ec = pathkey->pk_eclass;
1546  List *matched_restrictinfos = NIL;
1547  ListCell *j;
1548 
1549  /*----------
1550  * A mergejoin clause matches a pathkey if it has the same EC.
1551  * If there are multiple matching clauses, take them all. In plain
1552  * inner-join scenarios we expect only one match, because
1553  * equivalence-class processing will have removed any redundant
1554  * mergeclauses. However, in outer-join scenarios there might be
1555  * multiple matches. An example is
1556  *
1557  * select * from a full join b
1558  * on a.v1 = b.v1 and a.v2 = b.v2 and a.v1 = b.v2;
1559  *
1560  * Given the pathkeys ({a.v1}, {a.v2}) it is okay to return all three
1561  * clauses (in the order a.v1=b.v1, a.v1=b.v2, a.v2=b.v2) and indeed
1562  * we *must* do so or we will be unable to form a valid plan.
1563  *
1564  * We expect that the given pathkeys list is canonical, which means
1565  * no two members have the same EC, so it's not possible for this
1566  * code to enter the same mergeclause into the result list twice.
1567  *
1568  * It's possible that multiple matching clauses might have different
1569  * ECs on the other side, in which case the order we put them into our
1570  * result makes a difference in the pathkeys required for the inner
1571  * input rel. However this routine hasn't got any info about which
1572  * order would be best, so we don't worry about that.
1573  *
1574  * It's also possible that the selected mergejoin clauses produce
1575  * a noncanonical ordering of pathkeys for the inner side, ie, we
1576  * might select clauses that reference b.v1, b.v2, b.v1 in that
1577  * order. This is not harmful in itself, though it suggests that
1578  * the clauses are partially redundant. Since the alternative is
1579  * to omit mergejoin clauses and thereby possibly fail to generate a
1580  * plan altogether, we live with it. make_inner_pathkeys_for_merge()
1581  * has to delete duplicates when it constructs the inner pathkeys
1582  * list, and we also have to deal with such cases specially in
1583  * create_mergejoin_plan().
1584  *----------
1585  */
1586  foreach(j, restrictinfos)
1587  {
1588  RestrictInfo *rinfo = (RestrictInfo *) lfirst(j);
1589  EquivalenceClass *clause_ec;
1590 
1591  clause_ec = rinfo->outer_is_left ?
1592  rinfo->left_ec : rinfo->right_ec;
1593  if (clause_ec == pathkey_ec)
1594  matched_restrictinfos = lappend(matched_restrictinfos, rinfo);
1595  }
1596 
1597  /*
1598  * If we didn't find a mergeclause, we're done --- any additional
1599  * sort-key positions in the pathkeys are useless. (But we can still
1600  * mergejoin if we found at least one mergeclause.)
1601  */
1602  if (matched_restrictinfos == NIL)
1603  break;
1604 
1605  /*
1606  * If we did find usable mergeclause(s) for this sort-key position,
1607  * add them to result list.
1608  */
1609  mergeclauses = list_concat(mergeclauses, matched_restrictinfos);
1610  }
1611 
1612  return mergeclauses;
1613 }
void update_mergeclause_eclasses(PlannerInfo *root, RestrictInfo *restrictinfo)
Definition: pathkeys.c:1493

References i, j, lappend(), lfirst, list_concat(), NIL, and update_mergeclause_eclasses().

Referenced by generate_mergejoin_paths(), and sort_inner_and_outer().

◆ generate_base_implied_equalities()

void generate_base_implied_equalities ( PlannerInfo root)

Definition at line 1044 of file equivclass.c.

1045 {
1046  int ec_index;
1047  ListCell *lc;
1048 
1049  /*
1050  * At this point, we're done absorbing knowledge of equivalences in the
1051  * query, so no further EC merging should happen, and ECs remaining in the
1052  * eq_classes list can be considered canonical. (But note that it's still
1053  * possible for new single-member ECs to be added through
1054  * get_eclass_for_sort_expr().)
1055  */
1056  root->ec_merging_done = true;
1057 
1058  ec_index = 0;
1059  foreach(lc, root->eq_classes)
1060  {
1062  bool can_generate_joinclause = false;
1063  int i;
1064 
1065  Assert(ec->ec_merged == NULL); /* else shouldn't be in list */
1066  Assert(!ec->ec_broken); /* not yet anyway... */
1067 
1068  /*
1069  * Generate implied equalities that are restriction clauses.
1070  * Single-member ECs won't generate any deductions, either here or at
1071  * the join level.
1072  */
1073  if (list_length(ec->ec_members) > 1)
1074  {
1075  if (ec->ec_has_const)
1077  else
1079 
1080  /* Recover if we failed to generate required derived clauses */
1081  if (ec->ec_broken)
1083 
1084  /* Detect whether this EC might generate join clauses */
1085  can_generate_joinclause =
1087  }
1088 
1089  /*
1090  * Mark the base rels cited in each eclass (which should all exist by
1091  * now) with the eq_classes indexes of all eclasses mentioning them.
1092  * This will let us avoid searching in subsequent lookups. While
1093  * we're at it, we can mark base rels that have pending eclass joins;
1094  * this is a cheap version of has_relevant_eclass_joinclause().
1095  */
1096  i = -1;
1097  while ((i = bms_next_member(ec->ec_relids, i)) > 0)
1098  {
1099  RelOptInfo *rel = root->simple_rel_array[i];
1100 
1101  if (rel == NULL) /* must be an outer join */
1102  {
1104  continue;
1105  }
1106 
1107  Assert(rel->reloptkind == RELOPT_BASEREL);
1108 
1110  ec_index);
1111 
1112  if (can_generate_joinclause)
1113  rel->has_eclass_joins = true;
1114  }
1115 
1116  ec_index++;
1117  }
1118 }
static void generate_base_implied_equalities_broken(PlannerInfo *root, EquivalenceClass *ec)
Definition: equivclass.c:1329
static void generate_base_implied_equalities_no_const(PlannerInfo *root, EquivalenceClass *ec)
Definition: equivclass.c:1219
static void generate_base_implied_equalities_const(PlannerInfo *root, EquivalenceClass *ec)
Definition: equivclass.c:1124
struct EquivalenceClass * ec_merged
Definition: pathnodes.h:1383
Relids outer_join_rels
Definition: pathnodes.h:258

References Assert(), bms_add_member(), bms_is_member(), bms_membership(), BMS_MULTIPLE, bms_next_member(), EquivalenceClass::ec_broken, EquivalenceClass::ec_has_const, EquivalenceClass::ec_members, EquivalenceClass::ec_merged, PlannerInfo::ec_merging_done, EquivalenceClass::ec_relids, RelOptInfo::eclass_indexes, PlannerInfo::eq_classes, generate_base_implied_equalities_broken(), generate_base_implied_equalities_const(), generate_base_implied_equalities_no_const(), RelOptInfo::has_eclass_joins, i, lfirst, list_length(), PlannerInfo::outer_join_rels, RELOPT_BASEREL, and RelOptInfo::reloptkind.

Referenced by query_planner().

◆ generate_gather_paths()

void generate_gather_paths ( PlannerInfo root,
RelOptInfo rel,
bool  override_rows 
)

Definition at line 3059 of file allpaths.c.

3060 {
3061  Path *cheapest_partial_path;
3062  Path *simple_gather_path;
3063  ListCell *lc;
3064  double rows;
3065  double *rowsp = NULL;
3066 
3067  /* If there are no partial paths, there's nothing to do here. */
3068  if (rel->partial_pathlist == NIL)
3069  return;
3070 
3071  /* Should we override the rel's rowcount estimate? */
3072  if (override_rows)
3073  rowsp = &rows;
3074 
3075  /*
3076  * The output of Gather is always unsorted, so there's only one partial
3077  * path of interest: the cheapest one. That will be the one at the front
3078  * of partial_pathlist because of the way add_partial_path works.
3079  */
3080  cheapest_partial_path = linitial(rel->partial_pathlist);
3081  rows =
3082  cheapest_partial_path->rows * cheapest_partial_path->parallel_workers;
3083  simple_gather_path = (Path *)
3084  create_gather_path(root, rel, cheapest_partial_path, rel->reltarget,
3085  NULL, rowsp);
3086  add_path(rel, simple_gather_path);
3087 
3088  /*
3089  * For each useful ordering, we can consider an order-preserving Gather
3090  * Merge.
3091  */
3092  foreach(lc, rel->partial_pathlist)
3093  {
3094  Path *subpath = (Path *) lfirst(lc);
3095  GatherMergePath *path;
3096 
3097  if (subpath->pathkeys == NIL)
3098  continue;
3099 
3100  rows = subpath->rows * subpath->parallel_workers;
3101  path = create_gather_merge_path(root, rel, subpath, rel->reltarget,
3102  subpath->pathkeys, NULL, rowsp);
3103  add_path(rel, &path->path);
3104  }
3105 }
GatherMergePath * create_gather_merge_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, PathTarget *target, List *pathkeys, Relids required_outer, double *rows)
Definition: pathnode.c:1878
GatherPath * create_gather_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, PathTarget *target, Relids required_outer, double *rows)
Definition: pathnode.c:1969
struct PathTarget * reltarget
Definition: pathnodes.h:878

References add_path(), create_gather_merge_path(), create_gather_path(), lfirst, linitial, NIL, Path::parallel_workers, RelOptInfo::partial_pathlist, GatherMergePath::path, RelOptInfo::reltarget, Path::rows, and subpath().

Referenced by generate_useful_gather_paths().

◆ generate_implied_equalities_for_column()

List* generate_implied_equalities_for_column ( PlannerInfo root,
RelOptInfo rel,
ec_matches_callback_type  callback,
void *  callback_arg,
Relids  prohibited_rels 
)

Definition at line 2895 of file equivclass.c.

2900 {
2901  List *result = NIL;
2902  bool is_child_rel = (rel->reloptkind == RELOPT_OTHER_MEMBER_REL);
2903  Relids parent_relids;
2904  int i;
2905 
2906  /* Should be OK to rely on eclass_indexes */
2907  Assert(root->ec_merging_done);
2908 
2909  /* Indexes are available only on base or "other" member relations. */
2910  Assert(IS_SIMPLE_REL(rel));
2911 
2912  /* If it's a child rel, we'll need to know what its parent(s) are */
2913  if (is_child_rel)
2914  parent_relids = find_childrel_parents(root, rel);
2915  else
2916  parent_relids = NULL; /* not used, but keep compiler quiet */
2917 
2918  i = -1;
2919  while ((i = bms_next_member(rel->eclass_indexes, i)) >= 0)
2920  {
2921  EquivalenceClass *cur_ec = (EquivalenceClass *) list_nth(root->eq_classes, i);
2922  EquivalenceMember *cur_em;
2923  ListCell *lc2;
2924 
2925  /* Sanity check eclass_indexes only contain ECs for rel */
2926  Assert(is_child_rel || bms_is_subset(rel->relids, cur_ec->ec_relids));
2927 
2928  /*
2929  * Won't generate joinclauses if const or single-member (the latter
2930  * test covers the volatile case too)
2931  */
2932  if (cur_ec->ec_has_const || list_length(cur_ec->ec_members) <= 1)
2933  continue;
2934 
2935  /*
2936  * Scan members, looking for a match to the target column. Note that
2937  * child EC members are considered, but only when they belong to the
2938  * target relation. (Unlike regular members, the same expression
2939  * could be a child member of more than one EC. Therefore, it's
2940  * potentially order-dependent which EC a child relation's target
2941  * column gets matched to. This is annoying but it only happens in
2942  * corner cases, so for now we live with just reporting the first
2943  * match. See also get_eclass_for_sort_expr.)
2944  */
2945  cur_em = NULL;
2946  foreach(lc2, cur_ec->ec_members)
2947  {
2948  cur_em = (EquivalenceMember *) lfirst(lc2);
2949  if (bms_equal(cur_em->em_relids, rel->relids) &&
2950  callback(root, rel, cur_ec, cur_em, callback_arg))
2951  break;
2952  cur_em = NULL;
2953  }
2954 
2955  if (!cur_em)
2956  continue;
2957 
2958  /*
2959  * Found our match. Scan the other EC members and attempt to generate
2960  * joinclauses.
2961  */
2962  foreach(lc2, cur_ec->ec_members)
2963  {
2964  EquivalenceMember *other_em = (EquivalenceMember *) lfirst(lc2);
2965  Oid eq_op;
2966  RestrictInfo *rinfo;
2967 
2968  if (other_em->em_is_child)
2969  continue; /* ignore children here */
2970 
2971  /* Make sure it'll be a join to a different rel */
2972  if (other_em == cur_em ||
2973  bms_overlap(other_em->em_relids, rel->relids))
2974  continue;
2975 
2976  /* Forget it if caller doesn't want joins to this rel */
2977  if (bms_overlap(other_em->em_relids, prohibited_rels))
2978  continue;
2979 
2980  /*
2981  * Also, if this is a child rel, avoid generating a useless join
2982  * to its parent rel(s).
2983  */
2984  if (is_child_rel &&
2985  bms_overlap(parent_relids, other_em->em_relids))
2986  continue;
2987 
2988  eq_op = select_equality_operator(cur_ec,
2989  cur_em->em_datatype,
2990  other_em->em_datatype);
2991  if (!OidIsValid(eq_op))
2992  continue;
2993 
2994  /* set parent_ec to mark as redundant with other joinclauses */
2995  rinfo = create_join_clause(root, cur_ec, eq_op,
2996  cur_em, other_em,
2997  cur_ec);
2998 
2999  result = lappend(result, rinfo);
3000  }
3001 
3002  /*
3003  * If somehow we failed to create any join clauses, we might as well
3004  * keep scanning the ECs for another match. But if we did make any,
3005  * we're done, because we don't want to return non-redundant clauses.
3006  */
3007  if (result)
3008  break;
3009  }
3010 
3011  return result;
3012 }
#define OidIsValid(objectId)
Definition: c.h:762
static RestrictInfo * create_join_clause(PlannerInfo *root, EquivalenceClass *ec, Oid opno, EquivalenceMember *leftem, EquivalenceMember *rightem, EquivalenceClass *parent_ec)
Definition: equivclass.c:1824
static Oid select_equality_operator(EquivalenceClass *ec, Oid lefttype, Oid righttype)
Definition: equivclass.c:1788
static void callback(struct sockaddr *addr, struct sockaddr *mask, void *unused)
Definition: test_ifaddrs.c:46

References Assert(), bms_equal(), bms_is_subset(), bms_next_member(), bms_overlap(), callback(), create_join_clause(), EquivalenceClass::ec_has_const, EquivalenceClass::ec_members, PlannerInfo::ec_merging_done, EquivalenceClass::ec_relids, RelOptInfo::eclass_indexes, EquivalenceMember::em_datatype, EquivalenceMember::em_is_child, EquivalenceMember::em_relids, PlannerInfo::eq_classes, find_childrel_parents(), i, IS_SIMPLE_REL, lappend(), lfirst, list_length(), list_nth(), NIL, OidIsValid, RelOptInfo::relids, RELOPT_OTHER_MEMBER_REL, RelOptInfo::reloptkind, and select_equality_operator().

Referenced by create_tidscan_paths(), match_eclass_clauses_to_index(), and postgresGetForeignPaths().

◆ generate_join_implied_equalities()

List* generate_join_implied_equalities ( PlannerInfo root,
Relids  join_relids,
Relids  outer_relids,
RelOptInfo inner_rel,
SpecialJoinInfo sjinfo 
)

Definition at line 1392 of file equivclass.c.

1397 {
1398  List *result = NIL;
1399  Relids inner_relids = inner_rel->relids;
1400  Relids nominal_inner_relids;
1401  Relids nominal_join_relids;
1402  Bitmapset *matching_ecs;
1403  int i;
1404 
1405  /* If inner rel is a child, extra setup work is needed */
1406  if (IS_OTHER_REL(inner_rel))
1407  {
1408  Assert(!bms_is_empty(inner_rel->top_parent_relids));
1409 
1410  /* Fetch relid set for the topmost parent rel */
1411  nominal_inner_relids = inner_rel->top_parent_relids;
1412  /* ECs will be marked with the parent's relid, not the child's */
1413  nominal_join_relids = bms_union(outer_relids, nominal_inner_relids);
1414  nominal_join_relids = add_outer_joins_to_relids(root,
1415  nominal_join_relids,
1416  sjinfo,
1417  NULL);
1418  }
1419  else
1420  {
1421  nominal_inner_relids = inner_relids;
1422  nominal_join_relids = join_relids;
1423  }
1424 
1425  /*
1426  * Examine all potentially-relevant eclasses.
1427  *
1428  * If we are considering an outer join, we must include "join" clauses
1429  * that mention either input rel plus the outer join's relid; these
1430  * represent post-join filter clauses that have to be applied at this
1431  * join. We don't have infrastructure that would let us identify such
1432  * eclasses cheaply, so just fall back to considering all eclasses
1433  * mentioning anything in nominal_join_relids.
1434  *
1435  * At inner joins, we can be smarter: only consider eclasses mentioning
1436  * both input rels.
1437  */
1438  if (sjinfo && sjinfo->ojrelid != 0)
1439  matching_ecs = get_eclass_indexes_for_relids(root, nominal_join_relids);
1440  else
1441  matching_ecs = get_common_eclass_indexes(root, nominal_inner_relids,
1442  outer_relids);
1443 
1444  i = -1;
1445  while ((i = bms_next_member(matching_ecs, i)) >= 0)
1446  {
1448  List *sublist = NIL;
1449 
1450  /* ECs containing consts do not need any further enforcement */
1451  if (ec->ec_has_const)
1452  continue;
1453 
1454  /* Single-member ECs won't generate any deductions */
1455  if (list_length(ec->ec_members) <= 1)
1456  continue;
1457 
1458  /* Sanity check that this eclass overlaps the join */
1459  Assert(bms_overlap(ec->ec_relids, nominal_join_relids));
1460 
1461  if (!ec->ec_broken)
1463  ec,
1464  join_relids,
1465  outer_relids,
1466  inner_relids);
1467 
1468  /* Recover if we failed to generate required derived clauses */
1469  if (ec->ec_broken)
1471  ec,
1472  nominal_join_relids,
1473  outer_relids,
1474  nominal_inner_relids,
1475  inner_rel);
1476 
1477  result = list_concat(result, sublist);
1478  }
1479 
1480  return result;
1481 }
static List * generate_join_implied_equalities_normal(PlannerInfo *root, EquivalenceClass *ec, Relids join_relids, Relids outer_relids, Relids inner_relids)
Definition: equivclass.c:1563
static Bitmapset * get_common_eclass_indexes(PlannerInfo *root, Relids relids1, Relids relids2)
Definition: equivclass.c:3298
static List * generate_join_implied_equalities_broken(PlannerInfo *root, EquivalenceClass *ec, Relids nominal_join_relids, Relids outer_relids, Relids nominal_inner_relids, RelOptInfo *inner_rel)
Definition: equivclass.c:1739
Relids add_outer_joins_to_relids(PlannerInfo *root, Relids input_relids, SpecialJoinInfo *sjinfo, List **pushed_down_joins)
Definition: joinrels.c:783

References add_outer_joins_to_relids(), Assert(), bms_is_empty, bms_next_member(), bms_overlap(), bms_union(), EquivalenceClass::ec_broken, EquivalenceClass::ec_has_const, EquivalenceClass::ec_members, EquivalenceClass::ec_relids, PlannerInfo::eq_classes, generate_join_implied_equalities_broken(), generate_join_implied_equalities_normal(), get_common_eclass_indexes(), get_eclass_indexes_for_relids(), i, IS_OTHER_REL, list_concat(), list_length(), list_nth(), NIL, SpecialJoinInfo::ojrelid, RelOptInfo::relids, and RelOptInfo::top_parent_relids.

Referenced by build_joinrel_restrictlist(), check_index_predicates(), get_baserel_parampathinfo(), get_joinrel_parampathinfo(), reduce_unique_semijoins(), and remove_self_joins_one_group().

◆ generate_join_implied_equalities_for_ecs()

List* generate_join_implied_equalities_for_ecs ( PlannerInfo root,
List eclasses,
Relids  join_relids,
Relids  outer_relids,
RelOptInfo inner_rel 
)

Definition at line 1492 of file equivclass.c.

1497 {
1498  List *result = NIL;
1499  Relids inner_relids = inner_rel->relids;
1500  Relids nominal_inner_relids;
1501  Relids nominal_join_relids;
1502  ListCell *lc;
1503 
1504  /* If inner rel is a child, extra setup work is needed */
1505  if (IS_OTHER_REL(inner_rel))
1506  {
1507  Assert(!bms_is_empty(inner_rel->top_parent_relids));
1508 
1509  /* Fetch relid set for the topmost parent rel */
1510  nominal_inner_relids = inner_rel->top_parent_relids;
1511  /* ECs will be marked with the parent's relid, not the child's */
1512  nominal_join_relids = bms_union(outer_relids, nominal_inner_relids);
1513  }
1514  else
1515  {
1516  nominal_inner_relids = inner_relids;
1517  nominal_join_relids = join_relids;
1518  }
1519 
1520  foreach(lc, eclasses)
1521  {
1523  List *sublist = NIL;
1524 
1525  /* ECs containing consts do not need any further enforcement */
1526  if (ec->ec_has_const)
1527  continue;
1528 
1529  /* Single-member ECs won't generate any deductions */
1530  if (list_length(ec->ec_members) <= 1)
1531  continue;
1532 
1533  /* We can quickly ignore any that don't overlap the join, too */
1534  if (!bms_overlap(ec->ec_relids, nominal_join_relids))
1535  continue;
1536 
1537  if (!ec->ec_broken)
1539  ec,
1540  join_relids,
1541  outer_relids,
1542  inner_relids);
1543 
1544  /* Recover if we failed to generate required derived clauses */
1545  if (ec->ec_broken)
1547  ec,
1548  nominal_join_relids,
1549  outer_relids,
1550  nominal_inner_relids,
1551  inner_rel);
1552 
1553  result = list_concat(result, sublist);
1554  }
1555 
1556  return result;
1557 }

References Assert(), bms_is_empty, bms_overlap(), bms_union(), EquivalenceClass::ec_broken, EquivalenceClass::ec_has_const, EquivalenceClass::ec_members, EquivalenceClass::ec_relids, generate_join_implied_equalities_broken(), generate_join_implied_equalities_normal(), IS_OTHER_REL, lfirst, list_concat(), list_length(), NIL, RelOptInfo::relids, and RelOptInfo::top_parent_relids.

Referenced by get_joinrel_parampathinfo().

◆ generate_partitionwise_join_paths()

void generate_partitionwise_join_paths ( PlannerInfo root,
RelOptInfo rel 
)

Definition at line 4298 of file allpaths.c.

4299 {
4300  List *live_children = NIL;
4301  int cnt_parts;
4302  int num_parts;
4303  RelOptInfo **part_rels;
4304 
4305  /* Handle only join relations here. */
4306  if (!IS_JOIN_REL(rel))
4307  return;
4308 
4309  /* We've nothing to do if the relation is not partitioned. */
4310  if (!IS_PARTITIONED_REL(rel))
4311  return;
4312 
4313  /* The relation should have consider_partitionwise_join set. */
4315 
4316  /* Guard against stack overflow due to overly deep partition hierarchy. */
4318 
4319  num_parts = rel->nparts;
4320  part_rels = rel->part_rels;
4321 
4322  /* Collect non-dummy child-joins. */
4323  for (cnt_parts = 0; cnt_parts < num_parts; cnt_parts++)
4324  {
4325  RelOptInfo *child_rel = part_rels[cnt_parts];
4326 
4327  /* If it's been pruned entirely, it's certainly dummy. */
4328  if (child_rel == NULL)
4329  continue;
4330 
4331  /* Make partitionwise join paths for this partitioned child-join. */
4332  generate_partitionwise_join_paths(root, child_rel);
4333 
4334  /* If we failed to make any path for this child, we must give up. */
4335  if (child_rel->pathlist == NIL)
4336  {
4337  /*
4338  * Mark the parent joinrel as unpartitioned so that later
4339  * functions treat it correctly.
4340  */
4341  rel->nparts = 0;
4342  return;
4343  }
4344 
4345  /* Else, identify the cheapest path for it. */
4346  set_cheapest(child_rel);
4347 
4348  /* Dummy children need not be scanned, so ignore those. */
4349  if (IS_DUMMY_REL(child_rel))
4350  continue;
4351 
4352 #ifdef OPTIMIZER_DEBUG
4353  pprint(child_rel);
4354 #endif
4355 
4356  live_children = lappend(live_children, child_rel);
4357  }
4358 
4359  /* If all child-joins are dummy, parent join is also dummy. */
4360  if (!live_children)
4361  {
4362  mark_dummy_rel(rel);
4363  return;
4364  }
4365 
4366  /* Build additional paths for this rel from child-join paths. */
4367  add_paths_to_append_rel(root, rel, live_children);
4368  list_free(live_children);
4369 }
void generate_partitionwise_join_paths(PlannerInfo *root, RelOptInfo *rel)
Definition: allpaths.c:4298
void add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel, List *live_childrels)
Definition: allpaths.c:1302
void pprint(const void *obj)
Definition: print.c:54
void mark_dummy_rel(RelOptInfo *rel)
Definition: joinrels.c:1363
void set_cheapest(RelOptInfo *parent_rel)
Definition: pathnode.c:240
#define IS_DUMMY_REL(r)
Definition: pathnodes.h:1926
#define IS_PARTITIONED_REL(rel)
Definition: pathnodes.h:1043
void check_stack_depth(void)
Definition: postgres.c:3531
bool consider_partitionwise_join
Definition: pathnodes.h:980

References add_paths_to_append_rel(), Assert(), check_stack_depth(), RelOptInfo::consider_partitionwise_join, IS_DUMMY_REL, IS_JOIN_REL, IS_PARTITIONED_REL, lappend(), list_free(), mark_dummy_rel(), NIL, RelOptInfo::nparts, RelOptInfo::pathlist, pprint(), and set_cheapest().

Referenced by merge_clump(), and standard_join_search().

◆ generate_useful_gather_paths()

void generate_useful_gather_paths ( PlannerInfo root,
RelOptInfo rel,
bool  override_rows 
)

Definition at line 3197 of file allpaths.c.

3198 {
3199  ListCell *lc;
3200  double rows;
3201  double *rowsp = NULL;
3202  List *useful_pathkeys_list = NIL;
3203  Path *cheapest_partial_path = NULL;
3204 
3205  /* If there are no partial paths, there's nothing to do here. */
3206  if (rel->partial_pathlist == NIL)
3207  return;
3208 
3209  /* Should we override the rel's rowcount estimate? */
3210  if (override_rows)
3211  rowsp = &rows;
3212 
3213  /* generate the regular gather (merge) paths */
3214  generate_gather_paths(root, rel, override_rows);
3215 
3216  /* consider incremental sort for interesting orderings */
3217  useful_pathkeys_list = get_useful_pathkeys_for_relation(root, rel, true);
3218 
3219  /* used for explicit (full) sort paths */
3220  cheapest_partial_path = linitial(rel->partial_pathlist);
3221 
3222  /*
3223  * Consider sorted paths for each interesting ordering. We generate both
3224  * incremental and full sort.
3225  */
3226  foreach(lc, useful_pathkeys_list)
3227  {
3228  List *useful_pathkeys = lfirst(lc);
3229  ListCell *lc2;
3230  bool is_sorted;
3231  int presorted_keys;
3232 
3233  foreach(lc2, rel->partial_pathlist)
3234  {
3235  Path *subpath = (Path *) lfirst(lc2);
3236  GatherMergePath *path;
3237 
3238  is_sorted = pathkeys_count_contained_in(useful_pathkeys,
3239  subpath->pathkeys,
3240  &presorted_keys);
3241 
3242  /*
3243  * We don't need to consider the case where a subpath is already
3244  * fully sorted because generate_gather_paths already creates a
3245  * gather merge path for every subpath that has pathkeys present.
3246  *
3247  * But since the subpath is already sorted, we know we don't need
3248  * to consider adding a sort (full or incremental) on top of it,
3249  * so we can continue here.
3250  */
3251  if (is_sorted)
3252  continue;
3253 
3254  /*
3255  * Try at least sorting the cheapest path and also try
3256  * incrementally sorting any path which is partially sorted
3257  * already (no need to deal with paths which have presorted keys
3258  * when incremental sort is disabled unless it's the cheapest
3259  * input path).
3260  */
3261  if (subpath != cheapest_partial_path &&
3262  (presorted_keys == 0 || !enable_incremental_sort))
3263  continue;
3264 
3265  /*
3266  * Consider regular sort for any path that's not presorted or if
3267  * incremental sort is disabled. We've no need to consider both
3268  * sort and incremental sort on the same path. We assume that
3269  * incremental sort is always faster when there are presorted
3270  * keys.
3271  *
3272  * This is not redundant with the gather paths created in
3273  * generate_gather_paths, because that doesn't generate ordered
3274  * output. Here we add an explicit sort to match the useful
3275  * ordering.
3276  */
3277  if (presorted_keys == 0 || !enable_incremental_sort)
3278  {
3279  subpath = (Path *) create_sort_path(root,
3280  rel,
3281  subpath,
3282  useful_pathkeys,
3283  -1.0);
3284  rows = subpath->rows * subpath->parallel_workers;
3285  }
3286  else
3288  rel,
3289  subpath,
3290  useful_pathkeys,
3291  presorted_keys,
3292  -1);
3293  path = create_gather_merge_path(root, rel,
3294  subpath,
3295  rel->reltarget,
3296  subpath->pathkeys,
3297  NULL,
3298  rowsp);
3299 
3300  add_path(rel, &path->path);
3301  }
3302  }
3303 }
void generate_gather_paths(PlannerInfo *root, RelOptInfo *rel, bool override_rows)
Definition: allpaths.c:3059
static List * get_useful_pathkeys_for_relation(PlannerInfo *root, RelOptInfo *rel, bool require_parallel_safe)
Definition: allpaths.c:3129
bool enable_incremental_sort
Definition: costsize.c:140
bool pathkeys_count_contained_in(List *keys1, List *keys2, int *n_common)
Definition: pathkeys.c:573
SortPath * create_sort_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, List *pathkeys, double limit_tuples)
Definition: pathnode.c:2986
IncrementalSortPath * create_incremental_sort_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, List *pathkeys, int presorted_keys, double limit_tuples)
Definition: pathnode.c:2937

References add_path(), create_gather_merge_path(), create_incremental_sort_path(), create_sort_path(), enable_incremental_sort, generate_gather_paths(), get_useful_pathkeys_for_relation(), lfirst, linitial, NIL, RelOptInfo::partial_pathlist, GatherMergePath::path, pathkeys_count_contained_in(), RelOptInfo::reltarget, and subpath().

Referenced by apply_scanjoin_target_to_paths(), create_partial_distinct_paths(), gather_grouping_paths(), merge_clump(), set_rel_pathlist(), and standard_join_search().

◆ get_cheapest_fractional_path_for_pathkeys()

Path* get_cheapest_fractional_path_for_pathkeys ( List paths,
List pathkeys,
Relids  required_outer,
double  fraction 
)

Definition at line 681 of file pathkeys.c.

685 {
686  Path *matched_path = NULL;
687  ListCell *l;
688 
689  foreach(l, paths)
690  {
691  Path *path = (Path *) lfirst(l);
692 
693  /*
694  * Since cost comparison is a lot cheaper than pathkey comparison, do
695  * that first. (XXX is that still true?)
696  */
697  if (matched_path != NULL &&
698  compare_fractional_path_costs(matched_path, path, fraction) <= 0)
699  continue;
700 
701  if (pathkeys_contained_in(pathkeys, path->pathkeys) &&
702  bms_is_subset(PATH_REQ_OUTER(path), required_outer))
703  matched_path = path;
704  }
705  return matched_path;
706 }
bool pathkeys_contained_in(List *keys1, List *keys2)
Definition: pathkeys.c:341
int compare_fractional_path_costs(Path *path1, Path *path2, double fraction)
Definition: pathnode.c:113

References bms_is_subset(), compare_fractional_path_costs(), lfirst, PATH_REQ_OUTER, Path::pathkeys, and pathkeys_contained_in().

Referenced by build_minmax_path(), and generate_orderedappend_paths().

◆ get_cheapest_parallel_safe_total_inner()

Path* get_cheapest_parallel_safe_total_inner ( List paths)

Definition at line 714 of file pathkeys.c.

715 {
716  ListCell *l;
717 
718  foreach(l, paths)
719  {
720  Path *innerpath = (Path *) lfirst(l);
721 
722  if (innerpath->parallel_safe &&
723  bms_is_empty(PATH_REQ_OUTER(innerpath)))
724  return innerpath;
725  }
726 
727  return NULL;
728 }
bool parallel_safe
Definition: pathnodes.h:1635

References bms_is_empty, lfirst, Path::parallel_safe, and PATH_REQ_OUTER.

Referenced by add_paths_to_append_rel(), hash_inner_and_outer(), match_unsorted_outer(), and sort_inner_and_outer().

◆ get_cheapest_path_for_pathkeys()

Path* get_cheapest_path_for_pathkeys ( List paths,
List pathkeys,
Relids  required_outer,
CostSelector  cost_criterion,
bool  require_parallel_safe 
)

Definition at line 635 of file pathkeys.c.

639 {
640  Path *matched_path = NULL;
641  ListCell *l;
642 
643  foreach(l, paths)
644  {
645  Path *path = (Path *) lfirst(l);
646 
647  /* If required, reject paths that are not parallel-safe */
648  if (require_parallel_safe && !path->parallel_safe)
649  continue;
650 
651  /*
652  * Since cost comparison is a lot cheaper than pathkey comparison, do
653  * that first. (XXX is that still true?)
654  */
655  if (matched_path != NULL &&
656  compare_path_costs(matched_path, path, cost_criterion) <= 0)
657  continue;
658 
659  if (pathkeys_contained_in(pathkeys, path->pathkeys) &&
660  bms_is_subset(PATH_REQ_OUTER(path), required_outer))
661  matched_path = path;
662  }
663  return matched_path;
664 }
int compare_path_costs(Path *path1, Path *path2, CostSelector criterion)
Definition: pathnode.c:67

References bms_is_subset(), compare_path_costs(), lfirst, Path::parallel_safe, PATH_REQ_OUTER, Path::pathkeys, and pathkeys_contained_in().

Referenced by generate_mergejoin_paths(), generate_orderedappend_paths(), and get_cheapest_parameterized_child_path().

◆ get_eclass_for_sort_expr()

EquivalenceClass* get_eclass_for_sort_expr ( PlannerInfo root,
Expr expr,
List opfamilies,
Oid  opcintype,
Oid  collation,
Index  sortref,
Relids  rel,
bool  create_it 
)

Definition at line 587 of file equivclass.c.

595 {
596  JoinDomain *jdomain;
597  Relids expr_relids;
598  EquivalenceClass *newec;
599  EquivalenceMember *newem;
600  ListCell *lc1;
601  MemoryContext oldcontext;
602 
603  /*
604  * Ensure the expression exposes the correct type and collation.
605  */
606  expr = canonicalize_ec_expression(expr, opcintype, collation);
607 
608  /*
609  * Since SortGroupClause nodes are top-level expressions (GROUP BY, ORDER
610  * BY, etc), they can be presumed to belong to the top JoinDomain.
611  */
612  jdomain = linitial_node(JoinDomain, root->join_domains);
613 
614  /*
615  * Scan through the existing EquivalenceClasses for a match
616  */
617  foreach(lc1, root->eq_classes)
618  {
619  EquivalenceClass *cur_ec = (EquivalenceClass *) lfirst(lc1);
620  ListCell *lc2;
621 
622  /*
623  * Never match to a volatile EC, except when we are looking at another
624  * reference to the same volatile SortGroupClause.
625  */
626  if (cur_ec->ec_has_volatile &&
627  (sortref == 0 || sortref != cur_ec->ec_sortref))
628  continue;
629 
630  if (collation != cur_ec->ec_collation)
631  continue;
632  if (!equal(opfamilies, cur_ec->ec_opfamilies))
633  continue;
634 
635  foreach(lc2, cur_ec->ec_members)
636  {
637  EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc2);
638 
639  /*
640  * Ignore child members unless they match the request.
641  */
642  if (cur_em->em_is_child &&
643  !bms_equal(cur_em->em_relids, rel))
644  continue;
645 
646  /*
647  * Match constants only within the same JoinDomain (see
648  * optimizer/README).
649  */
650  if (cur_em->em_is_const && cur_em->em_jdomain != jdomain)
651  continue;
652 
653  if (opcintype == cur_em->em_datatype &&
654  equal(expr, cur_em->em_expr))
655  {
656  /*
657  * Match!
658  *
659  * Copy the sortref if it wasn't set yet. That may happen if
660  * the ec was constructed from a WHERE clause, i.e. it doesn't
661  * have a target reference at all.
662  */
663  if (cur_ec->ec_sortref == 0 && sortref > 0)
664  cur_ec->ec_sortref = sortref;
665  return cur_ec;
666  }
667  }
668  }
669 
670  /* No match; does caller want a NULL result? */
671  if (!create_it)
672  return NULL;
673 
674  /*
675  * OK, build a new single-member EC
676  *
677  * Here, we must be sure that we construct the EC in the right context.
678  */
679  oldcontext = MemoryContextSwitchTo(root->planner_cxt);
680 
681  newec = makeNode(EquivalenceClass);
682  newec->ec_opfamilies = list_copy(opfamilies);
683  newec->ec_collation = collation;
684  newec->ec_members = NIL;
685  newec->ec_sources = NIL;
686  newec->ec_derives = NIL;
687  newec->ec_relids = NULL;
688  newec->ec_has_const = false;
690  newec->ec_broken = false;
691  newec->ec_sortref = sortref;
692  newec->ec_min_security = UINT_MAX;
693  newec->ec_max_security = 0;
694  newec->ec_merged = NULL;
695 
696  if (newec->ec_has_volatile && sortref == 0) /* should not happen */
697  elog(ERROR, "volatile EquivalenceClass has no sortref");
698 
699  /*
700  * Get the precise set of relids appearing in the expression.
701  */
702  expr_relids = pull_varnos(root, (Node *) expr);
703 
704  newem = add_eq_member(newec, copyObject(expr), expr_relids,
705  jdomain, NULL, opcintype);
706 
707  /*
708  * add_eq_member doesn't check for volatile functions, set-returning
709  * functions, aggregates, or window functions, but such could appear in
710  * sort expressions; so we have to check whether its const-marking was
711  * correct.
712  */
713  if (newec->ec_has_const)
714  {
715  if (newec->ec_has_volatile ||
716  expression_returns_set((Node *) expr) ||
717  contain_agg_clause((Node *) expr) ||
718  contain_window_function((Node *) expr))
719  {
720  newec->ec_has_const = false;
721  newem->em_is_const = false;
722  }
723  }
724 
725  root->eq_classes = lappend(root->eq_classes, newec);
726 
727  /*
728  * If EC merging is already complete, we have to mop up by adding the new
729  * EC to the eclass_indexes of the relation(s) mentioned in it.
730  */
731  if (root->ec_merging_done)
732  {
733  int ec_index = list_length(root->eq_classes) - 1;
734  int i = -1;
735 
736  while ((i = bms_next_member(newec->ec_relids, i)) > 0)
737  {
738  RelOptInfo *rel = root->simple_rel_array[i];
739 
740  if (rel == NULL) /* must be an outer join */
741  {
743  continue;
744  }
745 
747 
749  ec_index);
750  }
751  }
752 
753  MemoryContextSwitchTo(oldcontext);
754 
755  return newec;
756 }
bool contain_agg_clause(Node *clause)
Definition: clauses.c:176
bool contain_window_function(Node *clause)
Definition: clauses.c:213
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:518
bool expression_returns_set(Node *clause)
Definition: nodeFuncs.c:730
#define copyObject(obj)
Definition: nodes.h:223
#define makeNode(_type_)
Definition: nodes.h:155
#define linitial_node(type, l)
Definition: pg_list.h:181
Index ec_min_security
Definition: pathnodes.h:1381
Index ec_max_security
Definition: pathnodes.h:1382
List * join_domains
Definition: pathnodes.h:308
Relids pull_varnos(PlannerInfo *root, Node *node)
Definition: var.c:108

References add_eq_member(), Assert(), bms_add_member(), bms_equal(), bms_is_member(), bms_next_member(), canonicalize_ec_expression(), contain_agg_clause(), contain_volatile_functions(), contain_window_function(), copyObject, EquivalenceClass::ec_broken, EquivalenceClass::ec_collation, EquivalenceClass::ec_derives, EquivalenceClass::ec_has_const, EquivalenceClass::ec_has_volatile, EquivalenceClass::ec_max_security, EquivalenceClass::ec_members, EquivalenceClass::ec_merged, PlannerInfo::ec_merging_done, EquivalenceClass::ec_min_security, EquivalenceClass::ec_opfamilies, EquivalenceClass::ec_relids, EquivalenceClass::ec_sortref, EquivalenceClass::ec_sources, RelOptInfo::eclass_indexes, elog, EquivalenceMember::em_datatype, EquivalenceMember::em_expr, EquivalenceMember::em_is_child, EquivalenceMember::em_is_const, EquivalenceMember::em_jdomain, EquivalenceMember::em_relids, PlannerInfo::eq_classes, equal(), ERROR, expression_returns_set(), i, PlannerInfo::join_domains, lappend(), lfirst, linitial_node, list_copy(), list_length(), makeNode, MemoryContextSwitchTo(), NIL, PlannerInfo::outer_join_rels, pull_varnos(), RELOPT_BASEREL, and RelOptInfo::reloptkind.

Referenced by convert_subquery_pathkeys(), initialize_mergeclause_eclasses(), and make_pathkey_from_sortinfo().

◆ get_useful_group_keys_orderings()

List* get_useful_group_keys_orderings ( PlannerInfo root,
Path path 
)

Definition at line 485 of file pathkeys.c.

486 {
487  Query *parse = root->parse;
488  List *infos = NIL;
489  PathKeyInfo *info;
490 
491  List *pathkeys = root->group_pathkeys;
492  List *clauses = root->processed_groupClause;
493 
494  /* always return at least the original pathkeys/clauses */
495  info = makeNode(PathKeyInfo);
496  info->pathkeys = pathkeys;
497  info->clauses = clauses;
498  infos = lappend(infos, info);
499 
500  /*
501  * Should we try generating alternative orderings of the group keys? If
502  * not, we produce only the order specified in the query, i.e. the
503  * optimization is effectively disabled.
504  */
506  return infos;
507 
508  /*
509  * Grouping sets have own and more complex logic to decide the ordering.
510  */
511  if (parse->groupingSets)
512  return infos;
513 
514  /*
515  * If the path is sorted in some way, try reordering the group keys to
516  * match the path as much of the ordering as possible. Then thanks to
517  * incremental sort we would get this sort as cheap as possible.
518  */
519  if (path->pathkeys &&
521  {
522  int n;
523 
524  n = group_keys_reorder_by_pathkeys(path->pathkeys, &pathkeys, &clauses,
525  root->num_groupby_pathkeys);
526 
527  if (n > 0 &&
529  !pathkeys_are_duplicate(infos, pathkeys))
530  {
531  info = makeNode(PathKeyInfo);
532  info->pathkeys = pathkeys;
533  info->clauses = clauses;
534 
535  infos = lappend(infos, info);
536  }
537  }
538 
539  /*
540  * Try reordering pathkeys to minimize the sort cost (this time consider
541  * the ORDER BY clause).
542  */
543  if (root->sort_pathkeys &&
545  {
546  int n;
547 
548  n = group_keys_reorder_by_pathkeys(root->sort_pathkeys, &pathkeys,
549  &clauses,
550  root->num_groupby_pathkeys);
551 
552  if (n > 0 &&
554  !pathkeys_are_duplicate(infos, pathkeys))
555  {
556  info = makeNode(PathKeyInfo);
557  info->pathkeys = pathkeys;
558  info->clauses = clauses;
559 
560  infos = lappend(infos, info);
561  }
562  }
563 
564  return infos;
565 }
static int group_keys_reorder_by_pathkeys(List *pathkeys, List **group_pathkeys, List **group_clauses, int num_groupby_pathkeys)
Definition: pathkeys.c:368
bool enable_group_by_reordering
Definition: pathkeys.c:31
static bool pathkeys_are_duplicate(List *infos, List *pathkeys)
Definition: pathkeys.c:456
static struct subre * parse(struct vars *v, int stopper, int type, struct state *init, struct state *final)
Definition: regcomp.c:715
List * pathkeys
Definition: pathnodes.h:1467
List * clauses
Definition: pathnodes.h:1468
int num_groupby_pathkeys
Definition: pathnodes.h:392
List * sort_pathkeys
Definition: pathnodes.h:399
List * group_pathkeys
Definition: pathnodes.h:385
List * processed_groupClause
Definition: pathnodes.h:430
Query * parse
Definition: pathnodes.h:199

References PathKeyInfo::clauses, enable_group_by_reordering, enable_incremental_sort, group_keys_reorder_by_pathkeys(), PlannerInfo::group_pathkeys, lappend(), list_length(), makeNode, NIL, PlannerInfo::num_groupby_pathkeys, parse(), PlannerInfo::parse, PathKeyInfo::pathkeys, Path::pathkeys, pathkeys_are_duplicate(), pathkeys_contained_in(), PlannerInfo::processed_groupClause, and PlannerInfo::sort_pathkeys.

Referenced by add_paths_to_grouping_rel(), and create_partial_grouping_paths().

◆ has_relevant_eclass_joinclause()

bool has_relevant_eclass_joinclause ( PlannerInfo root,
RelOptInfo rel1 
)

Definition at line 3103 of file equivclass.c.

3104 {
3105  Bitmapset *matched_ecs;
3106  int i;
3107 
3108  /* Examine only eclasses mentioning rel1 */
3109  matched_ecs = get_eclass_indexes_for_relids(root, rel1->relids);
3110 
3111  i = -1;
3112  while ((i = bms_next_member(matched_ecs, i)) >= 0)
3113  {
3115  i);
3116 
3117  /*
3118  * Won't generate joinclauses if single-member (this test covers the
3119  * volatile case too)
3120  */
3121  if (list_length(ec->ec_members) <= 1)
3122  continue;
3123 
3124  /*
3125  * Per the comment in have_relevant_eclass_joinclause, it's sufficient
3126  * to find an EC that mentions both this rel and some other rel.
3127  */
3128  if (!bms_is_subset(ec->ec_relids, rel1->relids))
3129  return true;
3130  }
3131 
3132  return false;
3133 }

References bms_is_subset(), bms_next_member(), EquivalenceClass::ec_members, EquivalenceClass::ec_relids, PlannerInfo::eq_classes, get_eclass_indexes_for_relids(), i, list_length(), list_nth(), and RelOptInfo::relids.

Referenced by build_join_rel().

◆ has_useful_pathkeys()

bool has_useful_pathkeys ( PlannerInfo root,
RelOptInfo rel 
)

Definition at line 2242 of file pathkeys.c.

2243 {
2244  if (rel->joininfo != NIL || rel->has_eclass_joins)
2245  return true; /* might be able to use pathkeys for merging */
2246  if (root->group_pathkeys != NIL)
2247  return true; /* might be able to use pathkeys for grouping */
2248  if (root->query_pathkeys != NIL)
2249  return true; /* might be able to use them for ordering */
2250  return false; /* definitely useless */
2251 }

References PlannerInfo::group_pathkeys, RelOptInfo::has_eclass_joins, RelOptInfo::joininfo, NIL, and PlannerInfo::query_pathkeys.

Referenced by build_child_join_rel(), build_index_paths(), and set_append_rel_size().

◆ have_dangerous_phv()

bool have_dangerous_phv ( PlannerInfo root,
Relids  outer_relids,
Relids  inner_params 
)

Definition at line 1286 of file joinrels.c.

1288 {
1289  ListCell *lc;
1290 
1291  foreach(lc, root->placeholder_list)
1292  {
1293  PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(lc);
1294 
1295  if (!bms_is_subset(phinfo->ph_eval_at, inner_params))
1296  continue; /* ignore, could not be a nestloop param */
1297  if (!bms_overlap(phinfo->ph_eval_at, outer_relids))
1298  continue; /* ignore, not relevant to this join */
1299  if (bms_is_subset(phinfo->ph_eval_at, outer_relids))
1300  continue; /* safe, it can be eval'd within outerrel */
1301  /* Otherwise, it's potentially unsafe, so reject the join */
1302  return true;
1303  }
1304 
1305  /* OK to perform the join */
1306  return false;
1307 }
Relids ph_eval_at
Definition: pathnodes.h:3062
List * placeholder_list
Definition: pathnodes.h:371

References bms_is_subset(), bms_overlap(), lfirst, PlaceHolderInfo::ph_eval_at, and PlannerInfo::placeholder_list.

Referenced by join_is_legal(), and try_nestloop_path().

◆ have_join_order_restriction()

bool have_join_order_restriction ( PlannerInfo root,
RelOptInfo rel1,
RelOptInfo rel2 
)

Definition at line 1053 of file joinrels.c.

1055 {
1056  bool result = false;
1057  ListCell *l;
1058 
1059  /*
1060  * If either side has a direct lateral reference to the other, attempt the
1061  * join regardless of outer-join considerations.
1062  */
1063  if (bms_overlap(rel1->relids, rel2->direct_lateral_relids) ||
1065  return true;
1066 
1067  /*
1068  * Likewise, if both rels are needed to compute some PlaceHolderVar,
1069  * attempt the join regardless of outer-join considerations. (This is not
1070  * very desirable, because a PHV with a large eval_at set will cause a lot
1071  * of probably-useless joins to be considered, but failing to do this can
1072  * cause us to fail to construct a plan at all.)
1073  */
1074  foreach(l, root->placeholder_list)
1075  {
1076  PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(l);
1077 
1078  if (bms_is_subset(rel1->relids, phinfo->ph_eval_at) &&
1079  bms_is_subset(rel2->relids, phinfo->ph_eval_at))
1080  return true;
1081  }
1082 
1083  /*
1084  * It's possible that the rels correspond to the left and right sides of a
1085  * degenerate outer join, that is, one with no joinclause mentioning the
1086  * non-nullable side; in which case we should force the join to occur.
1087  *
1088  * Also, the two rels could represent a clauseless join that has to be
1089  * completed to build up the LHS or RHS of an outer join.
1090  */
1091  foreach(l, root->join_info_list)
1092  {
1093  SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(l);
1094 
1095  /* ignore full joins --- other mechanisms handle them */
1096  if (sjinfo->jointype == JOIN_FULL)
1097  continue;
1098 
1099  /* Can we perform the SJ with these rels? */
1100  if (bms_is_subset(sjinfo->min_lefthand, rel1->relids) &&
1101  bms_is_subset(sjinfo->min_righthand, rel2->relids))
1102  {
1103  result = true;
1104  break;
1105  }
1106  if (bms_is_subset(sjinfo->min_lefthand, rel2->relids) &&
1107  bms_is_subset(sjinfo->min_righthand, rel1->relids))
1108  {
1109  result = true;
1110  break;
1111  }
1112 
1113  /*
1114  * Might we need to join these rels to complete the RHS? We have to
1115  * use "overlap" tests since either rel might include a lower SJ that
1116  * has been proven to commute with this one.
1117  */
1118  if (bms_overlap(sjinfo->min_righthand, rel1->relids) &&
1119  bms_overlap(sjinfo->min_righthand, rel2->relids))
1120  {
1121  result = true;
1122  break;
1123  }
1124 
1125  /* Likewise for the LHS. */
1126  if (bms_overlap(sjinfo->min_lefthand, rel1->relids) &&
1127  bms_overlap(sjinfo->min_lefthand, rel2->relids))
1128  {
1129  result = true;
1130  break;
1131  }
1132  }
1133 
1134  /*
1135  * We do not force the join to occur if either input rel can legally be
1136  * joined to anything else using joinclauses. This essentially means that
1137  * clauseless bushy joins are put off as long as possible. The reason is
1138  * that when there is a join order restriction high up in the join tree
1139  * (that is, with many rels inside the LHS or RHS), we would otherwise
1140  * expend lots of effort considering very stupid join combinations within
1141  * its LHS or RHS.
1142  */
1143  if (result)
1144  {
1145  if (has_legal_joinclause(root, rel1) ||
1146  has_legal_joinclause(root, rel2))
1147  result = false;
1148  }
1149 
1150  return result;
1151 }
static bool has_legal_joinclause(PlannerInfo *root, RelOptInfo *rel)
Definition: joinrels.c:1222
Relids direct_lateral_relids
Definition: pathnodes.h:896

References bms_is_subset(), bms_overlap(), RelOptInfo::direct_lateral_relids, has_legal_joinclause(), JOIN_FULL, PlannerInfo::join_info_list, SpecialJoinInfo::jointype, lfirst, SpecialJoinInfo::min_lefthand, SpecialJoinInfo::min_righthand, PlaceHolderInfo::ph_eval_at, PlannerInfo::placeholder_list, and RelOptInfo::relids.

Referenced by desirable_join(), join_search_one_level(), and make_rels_by_clause_joins().

◆ have_relevant_eclass_joinclause()

bool have_relevant_eclass_joinclause ( PlannerInfo root,
RelOptInfo rel1,
RelOptInfo rel2 
)

Definition at line 3027 of file equivclass.c.

3029 {
3030  Bitmapset *matching_ecs;
3031  int i;
3032 
3033  /*
3034  * Examine only eclasses mentioning both rel1 and rel2.
3035  *
3036  * Note that we do not consider the possibility of an eclass generating
3037  * "join" clauses that mention just one of the rels plus an outer join
3038  * that could be formed from them. Although such clauses must be
3039  * correctly enforced when we form the outer join, they don't seem like
3040  * sufficient reason to prioritize this join over other ones. The join
3041  * ordering rules will force the join to be made when necessary.
3042  */
3043  matching_ecs = get_common_eclass_indexes(root, rel1->relids,
3044  rel2->relids);
3045 
3046  i = -1;
3047  while ((i = bms_next_member(matching_ecs, i)) >= 0)
3048  {
3050  i);
3051 
3052  /*
3053  * Sanity check that get_common_eclass_indexes gave only ECs
3054  * containing both rels.
3055  */
3056  Assert(bms_overlap(rel1->relids, ec->ec_relids));
3057  Assert(bms_overlap(rel2->relids, ec->ec_relids));
3058 
3059  /*
3060  * Won't generate joinclauses if single-member (this test covers the
3061  * volatile case too)
3062  */
3063  if (list_length(ec->ec_members) <= 1)
3064  continue;
3065 
3066  /*
3067  * We do not need to examine the individual members of the EC, because
3068  * all that we care about is whether each rel overlaps the relids of
3069  * at least one member, and get_common_eclass_indexes() and the single
3070  * member check above are sufficient to prove that. (As with
3071  * have_relevant_joinclause(), it is not necessary that the EC be able
3072  * to form a joinclause relating exactly the two given rels, only that
3073  * it be able to form a joinclause mentioning both, and this will
3074  * surely be true if both of them overlap ec_relids.)
3075  *
3076  * Note we don't test ec_broken; if we did, we'd need a separate code
3077  * path to look through ec_sources. Checking the membership anyway is
3078  * OK as a possibly-overoptimistic heuristic.
3079  *
3080  * We don't test ec_has_const either, even though a const eclass won't
3081  * generate real join clauses. This is because if we had "WHERE a.x =
3082  * b.y and a.x = 42", it is worth considering a join between a and b,
3083  * since the join result is likely to be small even though it'll end
3084  * up being an unqualified nestloop.
3085  */
3086 
3087  return true;
3088  }
3089 
3090  return false;
3091 }

References Assert(), bms_next_member(), bms_overlap(), EquivalenceClass::ec_members, EquivalenceClass::ec_relids, PlannerInfo::eq_classes, get_common_eclass_indexes(), i, list_length(), list_nth(), and RelOptInfo::relids.

Referenced by have_relevant_joinclause().

◆ indexcol_is_bool_constant_for_query()

bool indexcol_is_bool_constant_for_query ( PlannerInfo root,
IndexOptInfo index,
int  indexcol 
)

Definition at line 3707 of file indxpath.c.

3710 {
3711  ListCell *lc;
3712 
3713  /* If the index isn't boolean, we can't possibly get a match */
3714  if (!IsBooleanOpfamily(index->opfamily[indexcol]))
3715  return false;
3716 
3717  /* Check each restriction clause for the index's rel */
3718  foreach(lc, index->rel->baserestrictinfo)
3719  {
3720  RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
3721 
3722  /*
3723  * As in match_clause_to_indexcol, never match pseudoconstants to
3724  * indexes. (It might be semantically okay to do so here, but the
3725  * odds of getting a match are negligible, so don't waste the cycles.)
3726  */
3727  if (rinfo->pseudoconstant)
3728  continue;
3729 
3730  /* See if we can match the clause's expression to the index column */
3731  if (match_boolean_index_clause(root, rinfo, indexcol, index))
3732  return true;
3733  }
3734 
3735  return false;
3736 }
static bool IsBooleanOpfamily(Oid opfamily)
Definition: indxpath.c:2334
static IndexClause * match_boolean_index_clause(PlannerInfo *root, RestrictInfo *rinfo, int indexcol, IndexOptInfo *index)
Definition: indxpath.c:2359

References IsBooleanOpfamily(), lfirst, and match_boolean_index_clause().

Referenced by build_index_pathkeys().

◆ initialize_mergeclause_eclasses()

void initialize_mergeclause_eclasses ( PlannerInfo root,
RestrictInfo restrictinfo 
)

Definition at line 1446 of file pathkeys.c.

1447 {
1448  Expr *clause = restrictinfo->clause;
1449  Oid lefttype,
1450  righttype;
1451 
1452  /* Should be a mergeclause ... */
1453  Assert(restrictinfo->mergeopfamilies != NIL);
1454  /* ... with links not yet set */
1455  Assert(restrictinfo->left_ec == NULL);
1456  Assert(restrictinfo->right_ec == NULL);
1457 
1458  /* Need the declared input types of the operator */
1459  op_input_types(((OpExpr *) clause)->opno, &lefttype, &righttype);
1460 
1461  /* Find or create a matching EquivalenceClass for each side */
1462  restrictinfo->left_ec =
1464  (Expr *) get_leftop(clause),
1465  restrictinfo->mergeopfamilies,
1466  lefttype,
1467  ((OpExpr *) clause)->inputcollid,
1468  0,
1469  NULL,
1470  true);
1471  restrictinfo->right_ec =
1473  (Expr *) get_rightop(clause),
1474  restrictinfo->mergeopfamilies,
1475  righttype,
1476  ((OpExpr *) clause)->inputcollid,
1477  0,
1478  NULL,
1479  true);
1480 }
void op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
Definition: lsyscache.c:1336
static Node * get_rightop(const void *clause)
Definition: nodeFuncs.h:93
static Node * get_leftop(const void *clause)
Definition: nodeFuncs.h:81

References Assert(), RestrictInfo::clause, get_eclass_for_sort_expr(), get_leftop(), get_rightop(), NIL, and op_input_types().

Referenced by distribute_qual_to_rels().

◆ is_redundant_derived_clause()

bool is_redundant_derived_clause ( RestrictInfo rinfo,
List clauselist 
)

Definition at line 3205 of file equivclass.c.

3206 {
3207  EquivalenceClass *parent_ec = rinfo->parent_ec;
3208  ListCell *lc;
3209 
3210  /* Fail if it's not a potentially-redundant clause from some EC */
3211  if (parent_ec == NULL)
3212  return false;
3213 
3214  foreach(lc, clauselist)
3215  {
3216  RestrictInfo *otherrinfo = (RestrictInfo *) lfirst(lc);
3217 
3218  if (otherrinfo->parent_ec == parent_ec)
3219  return true;
3220  }
3221 
3222  return false;
3223 }

References lfirst.

Referenced by create_tidscan_plan().

◆ is_redundant_with_indexclauses()

bool is_redundant_with_indexclauses ( RestrictInfo rinfo,
List indexclauses 
)

Definition at line 3232 of file equivclass.c.

3233 {
3234  EquivalenceClass *parent_ec = rinfo->parent_ec;
3235  ListCell *lc;
3236 
3237  foreach(lc, indexclauses)
3238  {
3239  IndexClause *iclause = lfirst_node(IndexClause, lc);
3240  RestrictInfo *otherrinfo = iclause->rinfo;
3241 
3242  /* If indexclause is lossy, it won't enforce the condition exactly */
3243  if (iclause->lossy)
3244  continue;
3245 
3246  /* Match if it's same clause (pointer equality should be enough) */
3247  if (rinfo == otherrinfo)
3248  return true;
3249  /* Match if derived from same EC */
3250  if (parent_ec && otherrinfo->parent_ec == parent_ec)
3251  return true;
3252 
3253  /*
3254  * No need to look at the derived clauses in iclause->indexquals; they
3255  * couldn't match if the parent clause didn't.
3256  */
3257  }
3258 
3259  return false;
3260 }
struct RestrictInfo * rinfo
Definition: pathnodes.h:1738

References lfirst_node, IndexClause::lossy, and IndexClause::rinfo.

Referenced by create_indexscan_plan(), extract_nonindex_conditions(), and has_indexed_join_quals().

◆ join_search_one_level()

void join_search_one_level ( PlannerInfo root,
int  level 
)

Definition at line 71 of file joinrels.c.

72 {
73  List **joinrels = root->join_rel_level;
74  ListCell *r;
75  int k;
76 
77  Assert(joinrels[level] == NIL);
78 
79  /* Set join_cur_level so that new joinrels are added to proper list */
80  root->join_cur_level = level;
81 
82  /*
83  * First, consider left-sided and right-sided plans, in which rels of
84  * exactly level-1 member relations are joined against initial relations.
85  * We prefer to join using join clauses, but if we find a rel of level-1
86  * members that has no join clauses, we will generate Cartesian-product
87  * joins against all initial rels not already contained in it.
88  */
89  foreach(r, joinrels[level - 1])
90  {
91  RelOptInfo *old_rel = (RelOptInfo *) lfirst(r);
92 
93  if (old_rel->joininfo != NIL || old_rel->has_eclass_joins ||
94  has_join_restriction(root, old_rel))
95  {
96  int first_rel;
97 
98  /*
99  * There are join clauses or join order restrictions relevant to
100  * this rel, so consider joins between this rel and (only) those
101  * initial rels it is linked to by a clause or restriction.
102  *
103  * At level 2 this condition is symmetric, so there is no need to
104  * look at initial rels before this one in the list; we already
105  * considered such joins when we were at the earlier rel. (The
106  * mirror-image joins are handled automatically by make_join_rel.)
107  * In later passes (level > 2), we join rels of the previous level
108  * to each initial rel they don't already include but have a join
109  * clause or restriction with.
110  */
111  if (level == 2) /* consider remaining initial rels */
112  first_rel = foreach_current_index(r) + 1;
113  else
114  first_rel = 0;
115 
116  make_rels_by_clause_joins(root, old_rel, joinrels[1], first_rel);
117  }
118  else
119  {
120  /*
121  * Oops, we have a relation that is not joined to any other
122  * relation, either directly or by join-order restrictions.
123  * Cartesian product time.
124  *
125  * We consider a cartesian product with each not-already-included
126  * initial rel, whether it has other join clauses or not. At
127  * level 2, if there are two or more clauseless initial rels, we
128  * will redundantly consider joining them in both directions; but
129  * such cases aren't common enough to justify adding complexity to
130  * avoid the duplicated effort.
131  */
133  old_rel,
134  joinrels[1]);
135  }
136  }
137 
138  /*
139  * Now, consider "bushy plans" in which relations of k initial rels are
140  * joined to relations of level-k initial rels, for 2 <= k <= level-2.
141  *
142  * We only consider bushy-plan joins for pairs of rels where there is a
143  * suitable join clause (or join order restriction), in order to avoid
144  * unreasonable growth of planning time.
145  */
146  for (k = 2;; k++)
147  {
148  int other_level = level - k;
149 
150  /*
151  * Since make_join_rel(x, y) handles both x,y and y,x cases, we only
152  * need to go as far as the halfway point.
153  */
154  if (k > other_level)
155  break;
156 
157  foreach(r, joinrels[k])
158  {
159  RelOptInfo *old_rel = (RelOptInfo *) lfirst(r);
160  int first_rel;
161  ListCell *r2;
162 
163  /*
164  * We can ignore relations without join clauses here, unless they
165  * participate in join-order restrictions --- then we might have
166  * to force a bushy join plan.
167  */
168  if (old_rel->joininfo == NIL && !old_rel->has_eclass_joins &&
169  !has_join_restriction(root, old_rel))
170  continue;
171 
172  if (k == other_level) /* only consider remaining rels */
173  first_rel = foreach_current_index(r) + 1;
174  else
175  first_rel = 0;
176 
177  for_each_from(r2, joinrels[other_level], first_rel)
178  {
179  RelOptInfo *new_rel = (RelOptInfo *) lfirst(r2);
180 
181  if (!bms_overlap(old_rel->relids, new_rel->relids))
182  {
183  /*
184  * OK, we can build a rel of the right level from this
185  * pair of rels. Do so if there is at least one relevant
186  * join clause or join order restriction.
187  */
188  if (have_relevant_joinclause(root, old_rel, new_rel) ||
189  have_join_order_restriction(root, old_rel, new_rel))
190  {
191  (void) make_join_rel(root, old_rel, new_rel);
192  }
193  }
194  }
195  }
196  }
197 
198  /*----------
199  * Last-ditch effort: if we failed to find any usable joins so far, force
200  * a set of cartesian-product joins to be generated. This handles the
201  * special case where all the available rels have join clauses but we
202  * cannot use any of those clauses yet. This can only happen when we are
203  * considering a join sub-problem (a sub-joinlist) and all the rels in the
204  * sub-problem have only join clauses with rels outside the sub-problem.
205  * An example is
206  *
207  * SELECT ... FROM a INNER JOIN b ON TRUE, c, d, ...
208  * WHERE a.w = c.x and b.y = d.z;
209  *
210  * If the "a INNER JOIN b" sub-problem does not get flattened into the
211  * upper level, we must be willing to make a cartesian join of a and b;
212  * but the code above will not have done so, because it thought that both
213  * a and b have joinclauses. We consider only left-sided and right-sided
214  * cartesian joins in this case (no bushy).
215  *----------
216  */
217  if (joinrels[level] == NIL)
218  {
219  /*
220  * This loop is just like the first one, except we always call
221  * make_rels_by_clauseless_joins().
222  */
223  foreach(r, joinrels[level - 1])
224  {
225  RelOptInfo *old_rel = (RelOptInfo *) lfirst(r);
226 
228  old_rel,
229  joinrels[1]);
230  }
231 
232  /*----------
233  * When special joins are involved, there may be no legal way
234  * to make an N-way join for some values of N. For example consider
235  *
236  * SELECT ... FROM t1 WHERE
237  * x IN (SELECT ... FROM t2,t3 WHERE ...) AND
238  * y IN (SELECT ... FROM t4,t5 WHERE ...)
239  *
240  * We will flatten this query to a 5-way join problem, but there are
241  * no 4-way joins that join_is_legal() will consider legal. We have
242  * to accept failure at level 4 and go on to discover a workable
243  * bushy plan at level 5.
244  *
245  * However, if there are no special joins and no lateral references
246  * then join_is_legal() should never fail, and so the following sanity
247  * check is useful.
248  *----------
249  */
250  if (joinrels[level] == NIL &&
251  root->join_info_list == NIL &&
252  !root->hasLateralRTEs)
253  elog(ERROR, "failed to build any %d-way joins", level);
254  }
255 }
bool have_relevant_joinclause(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2)
Definition: joininfo.c:39
static void make_rels_by_clauseless_joins(PlannerInfo *root, RelOptInfo *old_rel, List *other_rels)
Definition: joinrels.c:312
RelOptInfo * make_join_rel(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2)
Definition: joinrels.c:670
bool have_join_order_restriction(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2)
Definition: joinrels.c:1053
static bool has_join_restriction(PlannerInfo *root, RelOptInfo *rel)
Definition: joinrels.c:1166
static void make_rels_by_clause_joins(PlannerInfo *root, RelOptInfo *old_rel, List *other_rels, int first_rel_idx)
Definition: joinrels.c:278
#define foreach_current_index(var_or_cell)
Definition: pg_list.h:403
bool hasLateralRTEs
Definition: pathnodes.h:491
int join_cur_level
Definition: pathnodes.h:293

References Assert(), bms_overlap(), elog, ERROR, for_each_from, foreach_current_index, RelOptInfo::has_eclass_joins, has_join_restriction(), PlannerInfo::hasLateralRTEs, have_join_order_restriction(), have_relevant_joinclause(), PlannerInfo::join_cur_level, PlannerInfo::join_info_list, RelOptInfo::joininfo, lfirst, make_join_rel(), make_rels_by_clause_joins(), make_rels_by_clauseless_joins(), NIL, and RelOptInfo::relids.

Referenced by standard_join_search().

◆ make_canonical_pathkey()

PathKey* make_canonical_pathkey ( PlannerInfo root,
EquivalenceClass eclass,
Oid  opfamily,
int  strategy,
bool  nulls_first 
)

Definition at line 55 of file pathkeys.c.

58 {
59  PathKey *pk;
60  ListCell *lc;
61  MemoryContext oldcontext;
62 
63  /* Can't make canonical pathkeys if the set of ECs might still change */
64  if (!root->ec_merging_done)
65  elog(ERROR, "too soon to build canonical pathkeys");
66 
67  /* The passed eclass might be non-canonical, so chase up to the top */
68  while (eclass->ec_merged)
69  eclass = eclass->ec_merged;
70 
71  foreach(lc, root->canon_pathkeys)
72  {
73  pk = (PathKey *) lfirst(lc);
74  if (eclass == pk->pk_eclass &&
75  opfamily == pk->pk_opfamily &&
76  strategy == pk->pk_strategy &&
77  nulls_first == pk->pk_nulls_first)
78  return pk;
79  }
80 
81  /*
82  * Be sure canonical pathkeys are allocated in the main planning context.
83  * Not an issue in normal planning, but it is for GEQO.
84  */
85  oldcontext = MemoryContextSwitchTo(root->planner_cxt);
86 
87  pk = makeNode(PathKey);
88  pk->pk_eclass = eclass;
89  pk->pk_opfamily = opfamily;
90  pk->pk_strategy = strategy;
91  pk->pk_nulls_first = nulls_first;
92 
93  root->canon_pathkeys = lappend(root->canon_pathkeys, pk);
94 
95  MemoryContextSwitchTo(oldcontext);
96 
97  return pk;
98 }
List * canon_pathkeys
Definition: pathnodes.h:317

References PlannerInfo::canon_pathkeys, PlannerInfo::ec_merging_done, eclass(), elog, ERROR, lappend(), lfirst, makeNode, MemoryContextSwitchTo(), PathKey::pk_nulls_first, PathKey::pk_opfamily, and PathKey::pk_strategy.

Referenced by convert_subquery_pathkeys(), get_useful_pathkeys_for_relation(), make_inner_pathkeys_for_merge(), make_pathkey_from_sortinfo(), and select_outer_pathkeys_for_merge().

◆ make_inner_pathkeys_for_merge()

List* make_inner_pathkeys_for_merge ( PlannerInfo root,
List mergeclauses,
List outer_pathkeys 
)

Definition at line 1838 of file pathkeys.c.

1841 {
1842  List *pathkeys = NIL;
1843  EquivalenceClass *lastoeclass;
1844  PathKey *opathkey;
1845  ListCell *lc;
1846  ListCell *lop;
1847 
1848  lastoeclass = NULL;
1849  opathkey = NULL;
1850  lop = list_head(outer_pathkeys);
1851 
1852  foreach(lc, mergeclauses)
1853  {
1854  RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1855  EquivalenceClass *oeclass;
1856  EquivalenceClass *ieclass;
1857  PathKey *pathkey;
1858 
1859  update_mergeclause_eclasses(root, rinfo);
1860 
1861  if (rinfo->outer_is_left)
1862  {
1863  oeclass = rinfo->left_ec;
1864  ieclass = rinfo->right_ec;
1865  }
1866  else
1867  {
1868  oeclass = rinfo->right_ec;
1869  ieclass = rinfo->left_ec;
1870  }
1871 
1872  /* outer eclass should match current or next pathkeys */
1873  /* we check this carefully for debugging reasons */
1874  if (oeclass != lastoeclass)
1875  {
1876  if (!lop)
1877  elog(ERROR, "too few pathkeys for mergeclauses");
1878  opathkey = (PathKey *) lfirst(lop);
1879  lop = lnext(outer_pathkeys, lop);
1880  lastoeclass = opathkey->pk_eclass;
1881  if (oeclass != lastoeclass)
1882  elog(ERROR, "outer pathkeys do not match mergeclause");
1883  }
1884 
1885  /*
1886  * Often, we'll have same EC on both sides, in which case the outer
1887  * pathkey is also canonical for the inner side, and we can skip a
1888  * useless search.
1889  */
1890  if (ieclass == oeclass)
1891  pathkey = opathkey;
1892  else
1893  pathkey = make_canonical_pathkey(root,
1894  ieclass,
1895  opathkey->pk_opfamily,
1896  opathkey->pk_strategy,
1897  opathkey->pk_nulls_first);
1898 
1899  /*
1900  * Don't generate redundant pathkeys (which can happen if multiple
1901  * mergeclauses refer to the same EC). Because we do this, the output
1902  * pathkey list isn't necessarily ordered like the mergeclauses, which
1903  * complicates life for create_mergejoin_plan(). But if we didn't,
1904  * we'd have a noncanonical sort key list, which would be bad; for one
1905  * reason, it certainly wouldn't match any available sort order for
1906  * the input relation.
1907  */
1908  if (!pathkey_is_redundant(pathkey, pathkeys))
1909  pathkeys = lappend(pathkeys, pathkey);
1910  }
1911 
1912  return pathkeys;
1913 }
static ListCell * list_head(const List *l)
Definition: pg_list.h:128
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:343

References elog, ERROR, lappend(), lfirst, list_head(), lnext(), make_canonical_pathkey(), NIL, pathkey_is_redundant(), PathKey::pk_nulls_first, PathKey::pk_opfamily, PathKey::pk_strategy, and update_mergeclause_eclasses().

Referenced by generate_mergejoin_paths(), and sort_inner_and_outer().

◆ make_join_rel()

RelOptInfo* make_join_rel ( PlannerInfo root,
RelOptInfo rel1,
RelOptInfo rel2 
)

Definition at line 670 of file joinrels.c.

671 {
672  Relids joinrelids;
673  SpecialJoinInfo *sjinfo;
674  bool reversed;
675  List *pushed_down_joins = NIL;
676  SpecialJoinInfo sjinfo_data;
677  RelOptInfo *joinrel;
678  List *restrictlist;
679 
680  /* We should never try to join two overlapping sets of rels. */
681  Assert(!bms_overlap(rel1->relids, rel2->relids));
682 
683  /* Construct Relids set that identifies the joinrel (without OJ as yet). */
684  joinrelids = bms_union(rel1->relids, rel2->relids);
685 
686  /* Check validity and determine join type. */
687  if (!join_is_legal(root, rel1, rel2, joinrelids,
688  &sjinfo, &reversed))
689  {
690  /* invalid join path */
691  bms_free(joinrelids);
692  return NULL;
693  }
694 
695  /*
696  * Add outer join relid(s) to form the canonical relids. Any added outer
697  * joins besides sjinfo itself are appended to pushed_down_joins.
698  */
699  joinrelids = add_outer_joins_to_relids(root, joinrelids, sjinfo,
700  &pushed_down_joins);
701 
702  /* Swap rels if needed to match the join info. */
703  if (reversed)
704  {
705  RelOptInfo *trel = rel1;
706 
707  rel1 = rel2;
708  rel2 = trel;
709  }
710 
711  /*
712  * If it's a plain inner join, then we won't have found anything in
713  * join_info_list. Make up a SpecialJoinInfo so that selectivity
714  * estimation functions will know what's being joined.
715  */
716  if (sjinfo == NULL)
717  {
718  sjinfo = &sjinfo_data;
719  sjinfo->type = T_SpecialJoinInfo;
720  sjinfo->min_lefthand = rel1->relids;
721  sjinfo->min_righthand = rel2->relids;
722  sjinfo->syn_lefthand = rel1->relids;
723  sjinfo->syn_righthand = rel2->relids;
724  sjinfo->jointype = JOIN_INNER;
725  sjinfo->ojrelid = 0;
726  sjinfo->commute_above_l = NULL;
727  sjinfo->commute_above_r = NULL;
728  sjinfo->commute_below_l = NULL;
729  sjinfo->commute_below_r = NULL;
730  /* we don't bother trying to make the remaining fields valid */
731  sjinfo->lhs_strict = false;
732  sjinfo->semi_can_btree = false;
733  sjinfo->semi_can_hash = false;
734  sjinfo->semi_operators = NIL;
735  sjinfo->semi_rhs_exprs = NIL;
736  }
737 
738  /*
739  * Find or build the join RelOptInfo, and compute the restrictlist that
740  * goes with this particular joining.
741  */
742  joinrel = build_join_rel(root, joinrelids, rel1, rel2,
743  sjinfo, pushed_down_joins,
744  &restrictlist);
745 
746  /*
747  * If we've already proven this join is empty, we needn't consider any
748  * more paths for it.
749  */
750  if (is_dummy_rel(joinrel))
751  {
752  bms_free(joinrelids);
753  return joinrel;
754  }
755 
756  /* Add paths to the join relation. */
757  populate_joinrel_with_paths(root, rel1, rel2, joinrel, sjinfo,
758  restrictlist);
759 
760  bms_free(joinrelids);
761 
762  return joinrel;
763 }
void bms_free(Bitmapset *a)
Definition: bitmapset.c:239
static void populate_joinrel_with_paths(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2, RelOptInfo *joinrel, SpecialJoinInfo *sjinfo, List *restrictlist)
Definition: joinrels.c:875
bool is_dummy_rel(RelOptInfo *rel)
Definition: joinrels.c:1314
static bool join_is_legal(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2, Relids joinrelids, SpecialJoinInfo **sjinfo_p, bool *reversed_p)
Definition: joinrels.c:348
RelOptInfo * build_join_rel(PlannerInfo *root, Relids joinrelids, RelOptInfo *outer_rel, RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo, List *pushed_down_joins, List **restrictlist_ptr)
Definition: relnode.c:658
Relids commute_above_r
Definition: pathnodes.h:2875
Relids syn_lefthand
Definition: pathnodes.h:2870
List * semi_rhs_exprs
Definition: pathnodes.h:2883
Relids syn_righthand
Definition: pathnodes.h:2871
Relids commute_below_r
Definition: pathnodes.h:2877
List * semi_operators
Definition: pathnodes.h:2882

References add_outer_joins_to_relids(), Assert(), bms_free(), bms_overlap(), bms_union(), build_join_rel(), SpecialJoinInfo::commute_above_l, SpecialJoinInfo::commute_above_r, SpecialJoinInfo::commute_below_l, SpecialJoinInfo::commute_below_r, is_dummy_rel(), JOIN_INNER, join_is_legal(), SpecialJoinInfo::jointype, SpecialJoinInfo::lhs_strict, SpecialJoinInfo::min_lefthand, SpecialJoinInfo::min_righthand, NIL, SpecialJoinInfo::ojrelid, populate_joinrel_with_paths(), RelOptInfo::relids, SpecialJoinInfo::semi_can_btree, SpecialJoinInfo::semi_can_hash, SpecialJoinInfo::semi_operators, SpecialJoinInfo::semi_rhs_exprs, SpecialJoinInfo::syn_lefthand, and SpecialJoinInfo::syn_righthand.

Referenced by join_search_one_level(), make_rels_by_clause_joins(), make_rels_by_clauseless_joins(), and merge_clump().

◆ make_one_rel()

RelOptInfo* make_one_rel ( PlannerInfo root,
List joinlist 
)

Definition at line 171 of file allpaths.c.

172 {
173  RelOptInfo *rel;
174  Index rti;
175  double total_pages;
176 
177  /* Mark base rels as to whether we care about fast-start plans */
179 
180  /*
181  * Compute size estimates and consider_parallel flags for each base rel.
182  */
183  set_base_rel_sizes(root);
184 
185  /*
186  * We should now have size estimates for every actual table involved in
187  * the query, and we also know which if any have been deleted from the
188  * query by join removal, pruned by partition pruning, or eliminated by
189  * constraint exclusion. So we can now compute total_table_pages.
190  *
191  * Note that appendrels are not double-counted here, even though we don't
192  * bother to distinguish RelOptInfos for appendrel parents, because the
193  * parents will have pages = 0.
194  *
195  * XXX if a table is self-joined, we will count it once per appearance,
196  * which perhaps is the wrong thing ... but that's not completely clear,
197  * and detecting self-joins here is difficult, so ignore it for now.
198  */
199  total_pages = 0;
200  for (rti = 1; rti < root->simple_rel_array_size; rti++)
201  {
202  RelOptInfo *brel = root->simple_rel_array[rti];
203 
204  /* there may be empty slots corresponding to non-baserel RTEs */
205  if (brel == NULL)
206  continue;
207 
208  Assert(brel->relid == rti); /* sanity check on array */
209 
210  if (IS_DUMMY_REL(brel))
211  continue;
212 
213  if (IS_SIMPLE_REL(brel))
214  total_pages += (double) brel->pages;
215  }
216  root->total_table_pages = total_pages;
217 
218  /*
219  * Generate access paths for each base rel.
220  */
222 
223  /*
224  * Generate access paths for the entire join tree.
225  */
226  rel = make_rel_from_joinlist(root, joinlist);
227 
228  /*
229  * The result should join all and only the query's base + outer-join rels.
230  */
231  Assert(bms_equal(rel->relids, root->all_query_rels));
232 
233  return rel;
234 }
static void set_base_rel_sizes(PlannerInfo *root)
Definition: allpaths.c:290
static void set_base_rel_consider_startup(PlannerInfo *root)
Definition: allpaths.c:247
static void set_base_rel_pathlists(PlannerInfo *root)
Definition: allpaths.c:333
static RelOptInfo * make_rel_from_joinlist(PlannerInfo *root, List *joinlist)
Definition: allpaths.c:3313
unsigned int Index
Definition: c.h:601
int simple_rel_array_size
Definition: pathnodes.h:229
Cardinality total_table_pages
Definition: pathnodes.h:475
BlockNumber pages
Definition: pathnodes.h:929

References PlannerInfo::all_query_rels, Assert(), bms_equal(), IS_DUMMY_REL, IS_SIMPLE_REL, make_rel_from_joinlist(), RelOptInfo::pages, RelOptInfo::relid, RelOptInfo::relids, set_base_rel_consider_startup(), set_base_rel_pathlists(), set_base_rel_sizes(), PlannerInfo::simple_rel_array_size, and PlannerInfo::total_table_pages.

Referenced by query_planner().

◆ make_pathkeys_for_sortclauses()

List* make_pathkeys_for_sortclauses ( PlannerInfo root,
List sortclauses,
List tlist 
)

Definition at line 1347 of file pathkeys.c.

1350 {
1351  List *result;
1352  bool sortable;
1353 
1355  &sortclauses,
1356  tlist,
1357  false,
1358  &sortable);
1359  /* It's caller error if not all clauses were sortable */
1360  Assert(sortable);
1361  return result;
1362 }
List * make_pathkeys_for_sortclauses_extended(PlannerInfo *root, List **sortclauses, List *tlist, bool remove_redundant, bool *sortable)
Definition: pathkeys.c:1384

References Assert(), and make_pathkeys_for_sortclauses_extended().

Referenced by adjust_group_pathkeys_for_groupagg(), generate_nonunion_paths(), grouping_planner(), make_pathkeys_for_window(), make_union_unique(), minmax_qp_callback(), and standard_qp_callback().

◆ make_pathkeys_for_sortclauses_extended()

List* make_pathkeys_for_sortclauses_extended ( PlannerInfo root,
List **  sortclauses,
List tlist,
bool  remove_redundant,
bool sortable 
)

Definition at line 1384 of file pathkeys.c.

1389 {
1390  List *pathkeys = NIL;
1391  ListCell *l;
1392 
1393  *sortable = true;
1394  foreach(l, *sortclauses)
1395  {
1396  SortGroupClause *sortcl = (SortGroupClause *) lfirst(l);
1397  Expr *sortkey;
1398  PathKey *pathkey;
1399 
1400  sortkey = (Expr *) get_sortgroupclause_expr(sortcl, tlist);
1401  if (!OidIsValid(sortcl->sortop))
1402  {
1403  *sortable = false;
1404  continue;
1405  }
1406  pathkey = make_pathkey_from_sortop(root,
1407  sortkey,
1408  sortcl->sortop,
1409  sortcl->nulls_first,
1410  sortcl->tleSortGroupRef,
1411  true);
1412 
1413  /* Canonical form eliminates redundant ordering keys */
1414  if (!pathkey_is_redundant(pathkey, pathkeys))
1415  pathkeys = lappend(pathkeys, pathkey);
1416  else if (remove_redundant)
1417  *sortclauses = foreach_delete_current(*sortclauses, l);
1418  }
1419  return pathkeys;
1420 }
static PathKey * make_pathkey_from_sortop(PlannerInfo *root, Expr *expr, Oid ordering_op, bool nulls_first, Index sortref, bool create_it)
Definition: pathkeys.c:255
#define foreach_delete_current(lst, var_or_cell)
Definition: pg_list.h:391
Index tleSortGroupRef
Definition: parsenodes.h:1397
Node * get_sortgroupclause_expr(SortGroupClause *sgClause, List *targetList)
Definition: tlist.c:379

References foreach_delete_current, get_sortgroupclause_expr(), lappend(), lfirst, make_pathkey_from_sortop(), NIL, SortGroupClause::nulls_first, OidIsValid, pathkey_is_redundant(), SortGroupClause::sortop, and SortGroupClause::tleSortGroupRef.

Referenced by make_pathkeys_for_sortclauses(), make_pathkeys_for_window(), and standard_qp_callback().

◆ mark_dummy_rel()

void mark_dummy_rel ( RelOptInfo rel)

Definition at line 1363 of file joinrels.c.

1364 {
1365  MemoryContext oldcontext;
1366 
1367  /* Already marked? */
1368  if (is_dummy_rel(rel))
1369  return;
1370 
1371  /* No, so choose correct context to make the dummy path in */
1372  oldcontext = MemoryContextSwitchTo(GetMemoryChunkContext(rel));
1373 
1374  /* Set dummy size estimate */
1375  rel->rows = 0;
1376 
1377  /* Evict any previously chosen paths */
1378  rel->pathlist = NIL;
1379  rel->partial_pathlist = NIL;
1380 
1381  /* Set up the dummy path */
1382  add_path(rel, (Path *) create_append_path(NULL, rel, NIL, NIL,
1383  NIL, rel->lateral_relids,
1384  0, false, -1));
1385 
1386  /* Set or update cheapest_total_path and related fields */
1387  set_cheapest(rel);
1388 
1389  MemoryContextSwitchTo(oldcontext);
1390 }
MemoryContext GetMemoryChunkContext(void *pointer)
Definition: mcxt.c:695
Cardinality rows
Definition: pathnodes.h:862

References add_path(), create_append_path(), GetMemoryChunkContext(), is_dummy_rel(), RelOptInfo::lateral_relids, MemoryContextSwitchTo(), NIL, RelOptInfo::partial_pathlist, RelOptInfo::pathlist, RelOptInfo::rows, and set_cheapest().

Referenced by build_simple_rel(), generate_partitionwise_join_paths(), and populate_joinrel_with_paths().

◆ match_eclasses_to_foreign_key_col()

EquivalenceClass* match_eclasses_to_foreign_key_col ( PlannerInfo root,
ForeignKeyOptInfo fkinfo,
int  colno 
)

Definition at line 2501 of file equivclass.c.

2504 {
2505  Index var1varno = fkinfo->con_relid;
2506  AttrNumber var1attno = fkinfo->conkey[colno];
2507  Index var2varno = fkinfo->ref_relid;
2508  AttrNumber var2attno = fkinfo->confkey[colno];
2509  Oid eqop = fkinfo->conpfeqop[colno];
2510  RelOptInfo *rel1 = root->simple_rel_array[var1varno];
2511  RelOptInfo *rel2 = root->simple_rel_array[var2varno];
2512  List *opfamilies = NIL; /* compute only if needed */
2513  Bitmapset *matching_ecs;
2514  int i;
2515 
2516  /* Consider only eclasses mentioning both relations */
2517  Assert(root->ec_merging_done);
2518  Assert(IS_SIMPLE_REL(rel1));
2519  Assert(IS_SIMPLE_REL(rel2));
2520  matching_ecs = bms_intersect(rel1->eclass_indexes,
2521  rel2->eclass_indexes);
2522 
2523  i = -1;
2524  while ((i = bms_next_member(matching_ecs, i)) >= 0)
2525  {
2527  i);
2528  EquivalenceMember *item1_em = NULL;
2529  EquivalenceMember *item2_em = NULL;
2530  ListCell *lc2;
2531 
2532  /* Never match to a volatile EC */
2533  if (ec->ec_has_volatile)
2534  continue;
2535  /* Note: it seems okay to match to "broken" eclasses here */
2536 
2537  foreach(lc2, ec->ec_members)
2538  {
2540  Var *var;
2541 
2542  if (em->em_is_child)
2543  continue; /* ignore children here */
2544 
2545  /* EM must be a Var, possibly with RelabelType */
2546  var = (Var *) em->em_expr;
2547  while (var && IsA(var, RelabelType))
2548  var = (Var *) ((RelabelType *) var)->arg;
2549  if (!(var && IsA(var, Var)))
2550  continue;
2551 
2552  /* Match? */
2553  if (var->varno == var1varno && var->varattno == var1attno)
2554  item1_em = em;
2555  else if (var->varno == var2varno && var->varattno == var2attno)
2556  item2_em = em;
2557 
2558  /* Have we found both PK and FK column in this EC? */
2559  if (item1_em && item2_em)
2560  {
2561  /*
2562  * Succeed if eqop matches EC's opfamilies. We could test
2563  * this before scanning the members, but it's probably cheaper
2564  * to test for member matches first.
2565  */
2566  if (opfamilies == NIL) /* compute if we didn't already */
2567  opfamilies = get_mergejoin_opfamilies(eqop);
2568  if (equal(opfamilies, ec->ec_opfamilies))
2569  {
2570  fkinfo->eclass[colno] = ec;
2571  fkinfo->fk_eclass_member[colno] = item2_em;
2572  return ec;
2573  }
2574  /* Otherwise, done with this EC, move on to the next */
2575  break;
2576  }
2577  }
2578  }
2579  return NULL;
2580 }
int16 AttrNumber
Definition: attnum.h:21
Bitmapset * bms_intersect(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:292
List * get_mergejoin_opfamilies(Oid opno)
Definition: lsyscache.c:366
while(p+4<=pend)
struct EquivalenceClass * eclass[INDEX_MAX_KEYS]
Definition: pathnodes.h:1237
struct EquivalenceMember * fk_eclass_member[INDEX_MAX_KEYS]
Definition: pathnodes.h:1239
AttrNumber varattno
Definition: primnodes.h:246
int varno
Definition: primnodes.h:241

References Assert(), bms_intersect(), bms_next_member(), ForeignKeyOptInfo::con_relid, EquivalenceClass::ec_has_volatile, EquivalenceClass::ec_members, PlannerInfo::ec_merging_done, EquivalenceClass::ec_opfamilies, ForeignKeyOptInfo::eclass, RelOptInfo::eclass_indexes, EquivalenceMember::em_expr, EquivalenceMember::em_is_child, PlannerInfo::eq_classes, equal(), ForeignKeyOptInfo::fk_eclass_member, get_mergejoin_opfamilies(), i, IS_SIMPLE_REL, IsA, lfirst, list_nth(), NIL, ForeignKeyOptInfo::ref_relid, Var::varattno, Var::varno, and while().

Referenced by match_foreign_keys_to_quals().

◆ match_index_to_operand()

bool match_index_to_operand ( Node operand,
int  indexcol,
IndexOptInfo index 
)

Definition at line 3758 of file indxpath.c.

3761 {
3762  int indkey;
3763 
3764  /*
3765  * Ignore any RelabelType node above the operand. This is needed to be
3766  * able to apply indexscanning in binary-compatible-operator cases. Note:
3767  * we can assume there is at most one RelabelType node;
3768  * eval_const_expressions() will have simplified if more than one.
3769  */
3770  if (operand && IsA(operand, RelabelType))
3771  operand = (Node *) ((RelabelType *) operand)->arg;
3772 
3773  indkey = index->indexkeys[indexcol];
3774  if (indkey != 0)
3775  {
3776  /*
3777  * Simple index column; operand must be a matching Var.
3778  */
3779  if (operand && IsA(operand, Var) &&
3780  index->rel->relid == ((Var *) operand)->varno &&
3781  indkey == ((Var *) operand)->varattno &&
3782  ((Var *) operand)->varnullingrels == NULL)
3783  return true;
3784  }
3785  else
3786  {
3787  /*
3788  * Index expression; find the correct expression. (This search could
3789  * be avoided, at the cost of complicating all the callers of this
3790  * routine; doesn't seem worth it.)
3791  */
3792  ListCell *indexpr_item;
3793  int i;
3794  Node *indexkey;
3795 
3796  indexpr_item = list_head(index->indexprs);
3797  for (i = 0; i < indexcol; i++)
3798  {
3799  if (index->indexkeys[i] == 0)
3800  {
3801  if (indexpr_item == NULL)
3802  elog(ERROR, "wrong number of index expressions");
3803  indexpr_item = lnext(index->indexprs, indexpr_item);
3804  }
3805  }
3806  if (indexpr_item == NULL)
3807  elog(ERROR, "wrong number of index expressions");
3808  indexkey = (Node *) lfirst(indexpr_item);
3809 
3810  /*
3811  * Does it match the operand? Again, strip any relabeling.
3812  */
3813  if (indexkey && IsA(indexkey, RelabelType))
3814  indexkey = (Node *) ((RelabelType *) indexkey)->arg;
3815 
3816  if (equal(indexkey, operand))
3817  return true;
3818  }
3819 
3820  return false;
3821 }

References arg, elog, equal(), ERROR, i, IsA, lfirst, list_head(), and lnext().

Referenced by ec_member_matches_indexcol(), expand_indexqual_rowcompare(), get_actual_variable_range(), match_boolean_index_clause(), match_clause_to_indexcol(), match_clause_to_ordering_op(), match_funcclause_to_indexcol(), match_opclause_to_indexcol(), match_rowcompare_to_indexcol(), match_saopclause_to_indexcol(), and relation_has_unique_index_ext().

◆ pathkeys_contained_in()

◆ pathkeys_count_contained_in()

bool pathkeys_count_contained_in ( List keys1,
List keys2,
int *  n_common 
)

Definition at line 573 of file pathkeys.c.

574 {
575  int n = 0;
576  ListCell *key1,
577  *key2;
578 
579  /*
580  * See if we can avoiding looping through both lists. This optimization
581  * gains us several percent in planning time in a worst-case test.
582  */
583  if (keys1 == keys2)
584  {
585  *n_common = list_length(keys1);
586  return true;
587  }
588  else if (keys1 == NIL)
589  {
590  *n_common = 0;
591  return true;
592  }
593  else if (keys2 == NIL)
594  {
595  *n_common = 0;
596  return false;
597  }
598 
599  /*
600  * If both lists are non-empty, iterate through both to find out how many
601  * items are shared.
602  */
603  forboth(key1, keys1, key2, keys2)
604  {
605  PathKey *pathkey1 = (PathKey *) lfirst(key1);
606  PathKey *pathkey2 = (PathKey *) lfirst(key2);
607 
608  if (pathkey1 != pathkey2)
609  {
610  *n_common = n;
611  return false;
612  }
613  n++;
614  }
615 
616  /* If we ended with a null value, then we've processed the whole list. */
617  *n_common = n;
618  return (key1 == NULL);
619 }

References forboth, lfirst, list_length(), and NIL.

Referenced by create_final_distinct_paths(), create_one_window_path(), create_ordered_paths(), create_partial_distinct_paths(), create_window_paths(), gather_grouping_paths(), generate_useful_gather_paths(), make_ordered_path(), and pathkeys_useful_for_ordering().

◆ process_equivalence()

bool process_equivalence ( PlannerInfo root,
RestrictInfo **  p_restrictinfo,
JoinDomain jdomain 
)

Definition at line 118 of file equivclass.c.

121 {
122  RestrictInfo *restrictinfo = *p_restrictinfo;
123  Expr *clause = restrictinfo->clause;
124  Oid opno,
125  collation,
126  item1_type,
127  item2_type;
128  Expr *item1;
129  Expr *item2;
130  Relids item1_relids,
131  item2_relids;
132  List *opfamilies;
133  EquivalenceClass *ec1,
134  *ec2;
135  EquivalenceMember *em1,
136  *em2;
137  ListCell *lc1;
138  int ec2_idx;
139 
140  /* Should not already be marked as having generated an eclass */
141  Assert(restrictinfo->left_ec == NULL);
142  Assert(restrictinfo->right_ec == NULL);
143 
144  /* Reject if it is potentially postponable by security considerations */
145  if (restrictinfo->security_level > 0 && !restrictinfo->leakproof)
146  return false;
147 
148  /* Extract info from given clause */
149  Assert(is_opclause(clause));
150  opno = ((OpExpr *) clause)->opno;
151  collation = ((OpExpr *) clause)->inputcollid;
152  item1 = (Expr *) get_leftop(clause);
153  item2 = (Expr *) get_rightop(clause);
154  item1_relids = restrictinfo->left_relids;
155  item2_relids = restrictinfo->right_relids;
156 
157  /*
158  * Ensure both input expressions expose the desired collation (their types
159  * should be OK already); see comments for canonicalize_ec_expression.
160  */
161  item1 = canonicalize_ec_expression(item1,
162  exprType((Node *) item1),
163  collation);
164  item2 = canonicalize_ec_expression(item2,
165  exprType((Node *) item2),
166  collation);
167 
168  /*
169  * Clauses of the form X=X cannot be translated into EquivalenceClasses.
170  * We'd either end up with a single-entry EC, losing the knowledge that
171  * the clause was present at all, or else make an EC with duplicate
172  * entries, causing other issues.
173  */
174  if (equal(item1, item2))
175  {
176  /*
177  * If the operator is strict, then the clause can be treated as just
178  * "X IS NOT NULL". (Since we know we are considering a top-level
179  * qual, we can ignore the difference between FALSE and NULL results.)
180  * It's worth making the conversion because we'll typically get a much
181  * better selectivity estimate than we would for X=X.
182  *
183  * If the operator is not strict, we can't be sure what it will do
184  * with NULLs, so don't attempt to optimize it.
185  */
186  set_opfuncid((OpExpr *) clause);
187  if (func_strict(((OpExpr *) clause)->opfuncid))
188  {
189  NullTest *ntest = makeNode(NullTest);
190 
191  ntest->arg = item1;
192  ntest->nulltesttype = IS_NOT_NULL;
193  ntest->argisrow = false; /* correct even if composite arg */
194  ntest->location = -1;
195 
196  *p_restrictinfo =
197  make_restrictinfo(root,
198  (Expr *) ntest,
199  restrictinfo->is_pushed_down,
200  restrictinfo->has_clone,
201  restrictinfo->is_clone,
202  restrictinfo->pseudoconstant,
203  restrictinfo->security_level,
204  NULL,
205  restrictinfo->incompatible_relids,
206  restrictinfo->outer_relids);
207  }
208  return false;
209  }
210 
211  /*
212  * We use the declared input types of the operator, not exprType() of the
213  * inputs, as the nominal datatypes for opfamily lookup. This presumes
214  * that btree operators are always registered with amoplefttype and
215  * amoprighttype equal to their declared input types. We will need this
216  * info anyway to build EquivalenceMember nodes, and by extracting it now
217  * we can use type comparisons to short-circuit some equal() tests.
218  */
219  op_input_types(opno, &item1_type, &item2_type);
220 
221  opfamilies = restrictinfo->mergeopfamilies;
222 
223  /*
224  * Sweep through the existing EquivalenceClasses looking for matches to
225  * item1 and item2. These are the possible outcomes:
226  *
227  * 1. We find both in the same EC. The equivalence is already known, so
228  * there's nothing to do.
229  *
230  * 2. We find both in different ECs. Merge the two ECs together.
231  *
232  * 3. We find just one. Add the other to its EC.
233  *
234  * 4. We find neither. Make a new, two-entry EC.
235  *
236  * Note: since all ECs are built through this process or the similar
237  * search in get_eclass_for_sort_expr(), it's impossible that we'd match
238  * an item in more than one existing nonvolatile EC. So it's okay to stop
239  * at the first match.
240  */
241  ec1 = ec2 = NULL;
242  em1 = em2 = NULL;
243  ec2_idx = -1;
244  foreach(lc1, root->eq_classes)
245  {
246  EquivalenceClass *cur_ec = (EquivalenceClass *) lfirst(lc1);
247  ListCell *lc2;
248 
249  /* Never match to a volatile EC */
250  if (cur_ec->ec_has_volatile)
251  continue;
252 
253  /*
254  * The collation has to match; check this first since it's cheaper
255  * than the opfamily comparison.
256  */
257  if (collation != cur_ec->ec_collation)
258  continue;
259 
260  /*
261  * A "match" requires matching sets of btree opfamilies. Use of
262  * equal() for this test has implications discussed in the comments
263  * for get_mergejoin_opfamilies().
264  */
265  if (!equal(opfamilies, cur_ec->ec_opfamilies))
266  continue;
267 
268  foreach(lc2, cur_ec->ec_members)
269  {
270  EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc2);
271 
272  Assert(!cur_em->em_is_child); /* no children yet */
273 
274  /*
275  * Match constants only within the same JoinDomain (see
276  * optimizer/README).
277  */
278  if (cur_em->em_is_const && cur_em->em_jdomain != jdomain)
279  continue;
280 
281  if (!ec1 &&
282  item1_type == cur_em->em_datatype &&
283  equal(item1, cur_em->em_expr))
284  {
285  ec1 = cur_ec;
286  em1 = cur_em;
287  if (ec2)
288  break;
289  }
290 
291  if (!ec2 &&
292  item2_type == cur_em->em_datatype &&
293  equal(item2, cur_em->em_expr))
294  {
295  ec2 = cur_ec;
296  ec2_idx = foreach_current_index(lc1);
297  em2 = cur_em;
298  if (ec1)
299  break;
300  }
301  }
302 
303  if (ec1 && ec2)
304  break;
305  }
306 
307  /* Sweep finished, what did we find? */
308 
309  if (ec1 && ec2)
310  {
311  /* If case 1, nothing to do, except add to sources */
312  if (ec1 == ec2)
313  {
314  ec1->ec_sources = lappend(ec1->ec_sources, restrictinfo);
315  ec1->ec_min_security = Min(ec1->ec_min_security,
316  restrictinfo->security_level);
317  ec1->ec_max_security = Max(ec1->ec_max_security,
318  restrictinfo->security_level);
319  /* mark the RI as associated with this eclass */
320  restrictinfo->left_ec = ec1;
321  restrictinfo->right_ec = ec1;
322  /* mark the RI as usable with this pair of EMs */
323  restrictinfo->left_em = em1;
324  restrictinfo->right_em = em2;
325  return true;
326  }
327 
328  /*
329  * Case 2: need to merge ec1 and ec2. This should never happen after
330  * the ECs have reached canonical state; otherwise, pathkeys could be
331  * rendered non-canonical by the merge, and relation eclass indexes
332  * would get broken by removal of an eq_classes list entry.
333  */
334  if (root->ec_merging_done)
335  elog(ERROR, "too late to merge equivalence classes");
336 
337  /*
338  * We add ec2's items to ec1, then set ec2's ec_merged link to point
339  * to ec1 and remove ec2 from the eq_classes list. We cannot simply
340  * delete ec2 because that could leave dangling pointers in existing
341  * PathKeys. We leave it behind with a link so that the merged EC can
342  * be found.
343  */
344  ec1->ec_members = list_concat(ec1->ec_members, ec2->ec_members);
345  ec1->ec_sources = list_concat(ec1->ec_sources, ec2->ec_sources);
346  ec1->ec_derives = list_concat(ec1->ec_derives, ec2->ec_derives);
347  ec1->ec_relids = bms_join(ec1->ec_relids, ec2->ec_relids);
348  ec1->ec_has_const |= ec2->ec_has_const;
349  /* can't need to set has_volatile */
350  ec1->ec_min_security = Min(ec1->ec_min_security,
351  ec2->ec_min_security);
352  ec1->ec_max_security = Max(ec1->ec_max_security,
353  ec2->ec_max_security);
354  ec2->ec_merged = ec1;
355  root->eq_classes = list_delete_nth_cell(root->eq_classes, ec2_idx);
356  /* just to avoid debugging confusion w/ dangling pointers: */
357  ec2->ec_members = NIL;
358  ec2->ec_sources = NIL;
359  ec2->ec_derives = NIL;
360  ec2->ec_relids = NULL;
361  ec1->ec_sources = lappend(ec1->ec_sources, restrictinfo);
362  ec1->ec_min_security = Min(ec1->ec_min_security,
363  restrictinfo->security_level);
364  ec1->ec_max_security = Max(ec1->ec_max_security,
365  restrictinfo->security_level);
366  /* mark the RI as associated with this eclass */
367  restrictinfo->left_ec = ec1;
368  restrictinfo->right_ec = ec1;
369  /* mark the RI as usable with this pair of EMs */
370  restrictinfo->left_em = em1;
371  restrictinfo->right_em = em2;
372  }
373  else if (ec1)
374  {
375  /* Case 3: add item2 to ec1 */
376  em2 = add_eq_member(ec1, item2, item2_relids,
377  jdomain, NULL, item2_type);
378  ec1->ec_sources = lappend(ec1->ec_sources, restrictinfo);
379  ec1->ec_min_security = Min(ec1->ec_min_security,
380  restrictinfo->security_level);
381  ec1->ec_max_security = Max(ec1->ec_max_security,
382  restrictinfo->security_level);
383  /* mark the RI as associated with this eclass */
384  restrictinfo->left_ec = ec1;
385  restrictinfo->right_ec = ec1;
386  /* mark the RI as usable with this pair of EMs */
387  restrictinfo->left_em = em1;
388  restrictinfo->right_em = em2;
389  }
390  else if (ec2)
391  {
392  /* Case 3: add item1 to ec2 */
393  em1 = add_eq_member(ec2, item1, item1_relids,
394  jdomain, NULL, item1_type);
395  ec2->ec_sources = lappend(ec2->ec_sources, restrictinfo);
396  ec2->ec_min_security = Min(ec2->ec_min_security,
397  restrictinfo->security_level);
398  ec2->ec_max_security = Max(ec2->ec_max_security,
399  restrictinfo->security_level);
400  /* mark the RI as associated with this eclass */
401  restrictinfo->left_ec = ec2;
402  restrictinfo->right_ec = ec2;
403  /* mark the RI as usable with this pair of EMs */
404  restrictinfo->left_em = em1;
405  restrictinfo->right_em = em2;
406  }
407  else
408  {
409  /* Case 4: make a new, two-entry EC */
411 
412  ec->ec_opfamilies = opfamilies;
413  ec->ec_collation = collation;
414  ec->ec_members = NIL;
415  ec->ec_sources = list_make1(restrictinfo);
416  ec->ec_derives = NIL;
417  ec->ec_relids = NULL;
418  ec->ec_has_const = false;
419  ec->ec_has_volatile = false;
420  ec->ec_broken = false;
421  ec->ec_sortref = 0;
422  ec->ec_min_security = restrictinfo->security_level;
423  ec->ec_max_security = restrictinfo->security_level;
424  ec->ec_merged = NULL;
425  em1 = add_eq_member(ec, item1, item1_relids,
426  jdomain, NULL, item1_type);
427  em2 = add_eq_member(ec, item2, item2_relids,
428  jdomain, NULL, item2_type);
429 
430  root->eq_classes = lappend(root->eq_classes, ec);
431 
432  /* mark the RI as associated with this eclass */
433  restrictinfo->left_ec = ec;
434  restrictinfo->right_ec = ec;
435  /* mark the RI as usable with this pair of EMs */
436  restrictinfo->left_em = em1;
437  restrictinfo->right_em = em2;
438  }
439 
440  return true;
441 }
List * list_delete_nth_cell(List *list, int n)
Definition: list.c:767
bool func_strict(Oid funcid)
Definition: lsyscache.c:1739
void set_opfuncid(OpExpr *opexpr)
Definition: nodeFuncs.c:1790
static bool is_opclause(const void *clause)
Definition: nodeFuncs.h:74
@ IS_NOT_NULL
Definition: primnodes.h:1715
RestrictInfo * make_restrictinfo(PlannerInfo *root, Expr *clause, bool is_pushed_down, bool has_clone, bool is_clone, bool pseudoconstant, Index security_level, Relids required_relids, Relids incompatible_relids, Relids outer_relids)
Definition: restrictinfo.c:63
NullTestType nulltesttype
Definition: primnodes.h:1722
int location
Definition: primnodes.h:1725
Expr * arg
Definition: primnodes.h:1721
bool is_pushed_down
Definition: pathnodes.h:2544
Index security_level
Definition: pathnodes.h:2563
Relids outer_relids
Definition: pathnodes.h:2578
Relids incompatible_relids
Definition: pathnodes.h:2575
bool has_clone
Definition: pathnodes.h:2553

References add_eq_member(), NullTest::arg, Assert(), bms_join(), canonicalize_ec_expression(), RestrictInfo::clause, EquivalenceClass::ec_broken, EquivalenceClass::ec_collation, EquivalenceClass::ec_derives, EquivalenceClass::ec_has_const, EquivalenceClass::ec_has_volatile, EquivalenceClass::ec_max_security, EquivalenceClass::ec_members, EquivalenceClass::ec_merged, PlannerInfo::ec_merging_done, EquivalenceClass::ec_min_security, EquivalenceClass::ec_opfamilies, EquivalenceClass::ec_relids, EquivalenceClass::ec_sortref, EquivalenceClass::ec_sources, elog, EquivalenceMember::em_datatype, EquivalenceMember::em_expr, EquivalenceMember::em_is_child, EquivalenceMember::em_is_const, EquivalenceMember::em_jdomain, PlannerInfo::eq_classes, equal(), ERROR, exprType(), foreach_current_index, func_strict(), get_leftop(), get_rightop(), RestrictInfo::has_clone, RestrictInfo::incompatible_relids, RestrictInfo::is_clone, IS_NOT_NULL, is_opclause(), RestrictInfo::is_pushed_down, lappend(), lfirst, list_concat(), list_delete_nth_cell(), list_make1, NullTest::location, make_restrictinfo(), makeNode, Max, Min, NIL, NullTest::nulltesttype, op_input_types(), RestrictInfo::outer_relids, RestrictInfo::security_level, and set_opfuncid().

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

◆ reconsider_outer_join_clauses()

void reconsider_outer_join_clauses ( PlannerInfo root)

Definition at line 1993 of file equivclass.c.

1994 {
1995  bool found;
1996  ListCell *cell;
1997 
1998  /* Outer loop repeats until we find no more deductions */
1999  do
2000  {
2001  found = false;
2002 
2003  /* Process the LEFT JOIN clauses */
2004  foreach(cell, root->left_join_clauses)
2005  {
2006  OuterJoinClauseInfo *ojcinfo = (OuterJoinClauseInfo *) lfirst(cell);
2007 
2008  if (reconsider_outer_join_clause(root, ojcinfo, true))
2009  {
2010  RestrictInfo *rinfo = ojcinfo->rinfo;
2011 
2012  found = true;
2013  /* remove it from the list */
2014  root->left_join_clauses =
2016  /* throw back a dummy replacement clause (see notes above) */
2017  rinfo = make_restrictinfo(root,
2018  (Expr *) makeBoolConst(true, false),
2019  rinfo->is_pushed_down,
2020  rinfo->has_clone,
2021  rinfo->is_clone,
2022  false, /* pseudoconstant */
2023  0, /* security_level */
2024  rinfo->required_relids,
2025  rinfo->incompatible_relids,
2026  rinfo->outer_relids);
2027  distribute_restrictinfo_to_rels(root, rinfo);
2028  }
2029  }
2030 
2031  /* Process the RIGHT JOIN clauses */
2032  foreach(cell, root->right_join_clauses)
2033  {
2034  OuterJoinClauseInfo *ojcinfo = (OuterJoinClauseInfo *) lfirst(cell);
2035 
2036  if (reconsider_outer_join_clause(root, ojcinfo, false))
2037  {
2038  RestrictInfo *rinfo = ojcinfo->rinfo;
2039 
2040  found = true;
2041  /* remove it from the list */
2042  root->right_join_clauses =
2044  /* throw back a dummy replacement clause (see notes above) */
2045  rinfo = make_restrictinfo(root,
2046  (Expr *) makeBoolConst(true, false),
2047  rinfo->is_pushed_down,
2048  rinfo->has_clone,
2049  rinfo->is_clone,
2050  false, /* pseudoconstant */
2051  0, /* security_level */
2052  rinfo->required_relids,
2053  rinfo->incompatible_relids,
2054  rinfo->outer_relids);
2055  distribute_restrictinfo_to_rels(root, rinfo);
2056  }
2057  }
2058 
2059  /* Process the FULL JOIN clauses */
2060  foreach(cell, root->full_join_clauses)
2061  {
2062  OuterJoinClauseInfo *ojcinfo = (OuterJoinClauseInfo *) lfirst(cell);
2063 
2064  if (reconsider_full_join_clause(root, ojcinfo))
2065  {
2066  RestrictInfo *rinfo = ojcinfo->rinfo;
2067 
2068  found = true;
2069  /* remove it from the list */
2070  root->full_join_clauses =
2072  /* throw back a dummy replacement clause (see notes above) */
2073  rinfo = make_restrictinfo(root,
2074  (Expr *) makeBoolConst(true, false),
2075  rinfo->is_pushed_down,
2076  rinfo->has_clone,
2077  rinfo->is_clone,
2078  false, /* pseudoconstant */
2079  0, /* security_level */
2080  rinfo->required_relids,
2081  rinfo->incompatible_relids,
2082  rinfo->outer_relids);
2083  distribute_restrictinfo_to_rels(root, rinfo);
2084  }
2085  }
2086  } while (found);
2087 
2088  /* Now, any remaining clauses have to be thrown back */
2089  foreach(cell, root->left_join_clauses)
2090  {
2091  OuterJoinClauseInfo *ojcinfo = (OuterJoinClauseInfo *) lfirst(cell);
2092 
2093  distribute_restrictinfo_to_rels(root, ojcinfo->rinfo);
2094  }
2095  foreach(cell, root->right_join_clauses)
2096  {
2097  OuterJoinClauseInfo *ojcinfo = (OuterJoinClauseInfo *) lfirst(cell);
2098 
2099  distribute_restrictinfo_to_rels(root, ojcinfo->rinfo);
2100  }
2101  foreach(cell, root->full_join_clauses)
2102  {
2103  OuterJoinClauseInfo *ojcinfo = (OuterJoinClauseInfo *) lfirst(cell);
2104 
2105  distribute_restrictinfo_to_rels(root, ojcinfo->rinfo);
2106  }
2107 }
static bool reconsider_outer_join_clause(PlannerInfo *root, OuterJoinClauseInfo *ojcinfo, bool outer_on_left)
Definition: equivclass.c:2115
static bool reconsider_full_join_clause(PlannerInfo *root, OuterJoinClauseInfo *ojcinfo)
Definition: equivclass.c:2238
void distribute_restrictinfo_to_rels(PlannerInfo *root, RestrictInfo *restrictinfo)
Definition: initsplan.c:2816
Node * makeBoolConst(bool value, bool isnull)
Definition: makefuncs.c:359
RestrictInfo * rinfo
Definition: pathnodes.h:2897
List * left_join_clauses
Definition: pathnodes.h:323
List * full_join_clauses
Definition: pathnodes.h:334
List * right_join_clauses
Definition: pathnodes.h:329
Relids required_relids
Definition: pathnodes.h:2572

References distribute_restrictinfo_to_rels(), foreach_delete_current, PlannerInfo::full_join_clauses, RestrictInfo::has_clone, RestrictInfo::incompatible_relids, RestrictInfo::is_clone, RestrictInfo::is_pushed_down, PlannerInfo::left_join_clauses, lfirst, make_restrictinfo(), makeBoolConst(), RestrictInfo::outer_relids, reconsider_full_join_clause(), reconsider_outer_join_clause(), RestrictInfo::required_relids, PlannerInfo::right_join_clauses, and OuterJoinClauseInfo::rinfo.

Referenced by query_planner().

◆ relation_can_be_sorted_early()

bool relation_can_be_sorted_early ( PlannerInfo root,
RelOptInfo rel,
EquivalenceClass ec,
bool  require_parallel_safe 
)

Definition at line 933 of file equivclass.c.

935 {
936  PathTarget *target = rel->reltarget;
937  EquivalenceMember *em;
938  ListCell *lc;
939 
940  /*
941  * Reject volatile ECs immediately; such sorts must always be postponed.
942  */
943  if (ec->ec_has_volatile)
944  return false;
945 
946  /*
947  * Try to find an EM directly matching some reltarget member.
948  */
949  foreach(lc, target->exprs)
950  {
951  Expr *targetexpr = (Expr *) lfirst(lc);
952 
953  em = find_ec_member_matching_expr(ec, targetexpr, rel->relids);
954  if (!em)
955  continue;
956 
957  /*
958  * Reject expressions involving set-returning functions, as those
959  * can't be computed early either. (Note: this test and the following
960  * one are effectively checking properties of targetexpr, so there's
961  * no point in asking whether some other EC member would be better.)
962  */
963  if (expression_returns_set((Node *) em->em_expr))
964  continue;
965 
966  /*
967  * If requested, reject expressions that are not parallel-safe. We
968  * check this last because it's a rather expensive test.
969  */
970  if (require_parallel_safe &&
971  !is_parallel_safe(root, (Node *) em->em_expr))
972  continue;
973 
974  return true;
975  }
976 
977  /*
978  * Try to find an expression computable from the reltarget.
979  */
980  em = find_computable_ec_member(root, ec, target->exprs, rel->relids,
981  require_parallel_safe);
982  if (!em)
983  return false;
984 
985  /*
986  * Reject expressions involving set-returning functions, as those can't be
987  * computed early either. (There's no point in looking for another EC
988  * member in this case; since SRFs can't appear in WHERE, they cannot
989  * belong to multi-member ECs.)
990  */
991  if (expression_returns_set((Node *) em->em_expr))
992  return false;
993 
994  return true;
995 }
EquivalenceMember * find_ec_member_matching_expr(EquivalenceClass *ec, Expr *expr, Relids relids)
Definition: equivclass.c:771
EquivalenceMember * find_computable_ec_member(PlannerInfo *root, EquivalenceClass *ec, List *exprs, Relids relids, bool require_parallel_safe)
Definition: equivclass.c:836
List * exprs
Definition: pathnodes.h:1513

References EquivalenceClass::ec_has_volatile, EquivalenceMember::em_expr, expression_returns_set(), PathTarget::exprs, find_computable_ec_member(), find_ec_member_matching_expr(), is_parallel_safe(), lfirst, RelOptInfo::relids, and RelOptInfo::reltarget.

Referenced by get_useful_pathkeys_for_relation().

◆ relation_has_unique_index_ext()

bool relation_has_unique_index_ext ( PlannerInfo root,
RelOptInfo rel,
List restrictlist,
List exprlist,
List oprlist,
List **  extra_clauses 
)

Definition at line 3509 of file indxpath.c.

3513 {
3514  ListCell *ic;
3515 
3516  Assert(list_length(exprlist) == list_length(oprlist));
3517 
3518  /* Short-circuit if no indexes... */
3519  if (rel->indexlist == NIL)
3520  return false;
3521 
3522  /*
3523  * Examine the rel's restriction clauses for usable var = const clauses
3524  * that we can add to the restrictlist.
3525  */
3526  foreach(ic, rel->baserestrictinfo)
3527  {
3528  RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(ic);
3529 
3530  /*
3531  * Note: can_join won't be set for a restriction clause, but
3532  * mergeopfamilies will be if it has a mergejoinable operator and
3533  * doesn't contain volatile functions.
3534  */
3535  if (restrictinfo->mergeopfamilies == NIL)
3536  continue; /* not mergejoinable */
3537 
3538  /*
3539  * The clause certainly doesn't refer to anything but the given rel.
3540  * If either side is pseudoconstant then we can use it.
3541  */
3542  if (bms_is_empty(restrictinfo->left_relids))
3543  {
3544  /* righthand side is inner */
3545  restrictinfo->outer_is_left = true;
3546  }
3547  else if (bms_is_empty(restrictinfo->right_relids))
3548  {
3549  /* lefthand side is inner */
3550  restrictinfo->outer_is_left = false;
3551  }
3552  else
3553  continue;
3554 
3555  /* OK, add to list */
3556  restrictlist = lappend(restrictlist, restrictinfo);
3557  }
3558 
3559  /* Short-circuit the easy case */
3560  if (restrictlist == NIL && exprlist == NIL)
3561  return false;
3562 
3563  /* Examine each index of the relation ... */
3564  foreach(ic, rel->indexlist)
3565  {
3566  IndexOptInfo *ind = (IndexOptInfo *) lfirst(ic);
3567  int c;
3568  List *exprs = NIL;
3569 
3570  /*
3571  * If the index is not unique, or not immediately enforced, or if it's
3572  * a partial index, it's useless here. We're unable to make use of
3573  * predOK partial unique indexes due to the fact that
3574  * check_index_predicates() also makes use of join predicates to
3575  * determine if the partial index is usable. Here we need proofs that
3576  * hold true before any joins are evaluated.
3577  */
3578  if (!ind->unique || !ind->immediate || ind->indpred != NIL)
3579  continue;
3580 
3581  /*
3582  * Try to find each index column in the lists of conditions. This is
3583  * O(N^2) or worse, but we expect all the lists to be short.
3584  */
3585  for (c = 0; c < ind->nkeycolumns; c++)
3586  {
3587  bool matched = false;
3588  ListCell *lc;
3589  ListCell *lc2;
3590 
3591  foreach(lc, restrictlist)
3592  {
3593  RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
3594  Node *rexpr;
3595 
3596  /*
3597  * The condition's equality operator must be a member of the
3598  * index opfamily, else it is not asserting the right kind of
3599  * equality behavior for this index. We check this first
3600  * since it's probably cheaper than match_index_to_operand().
3601  */
3602  if (!list_member_oid(rinfo->mergeopfamilies, ind->opfamily[c]))
3603  continue;
3604 
3605  /*
3606  * XXX at some point we may need to check collations here too.
3607  * For the moment we assume all collations reduce to the same
3608  * notion of equality.
3609  */
3610 
3611  /* OK, see if the condition operand matches the index key */
3612  if (rinfo->outer_is_left)
3613  rexpr = get_rightop(rinfo->clause);
3614  else
3615  rexpr = get_leftop(rinfo->clause);
3616 
3617  if (match_index_to_operand(rexpr, c, ind))
3618  {
3619  matched = true; /* column is unique */
3620 
3621  if (bms_membership(rinfo->clause_relids) == BMS_SINGLETON)
3622  {
3623  MemoryContext oldMemCtx =
3624  MemoryContextSwitchTo(root->planner_cxt);
3625 
3626  /*
3627  * Add filter clause into a list allowing caller to
3628  * know if uniqueness have made not only by join
3629  * clauses.
3630  */
3631  Assert(bms_is_empty(rinfo->left_relids) ||
3632  bms_is_empty(rinfo->right_relids));
3633  if (extra_clauses)
3634  exprs = lappend(exprs, rinfo);
3635  MemoryContextSwitchTo(oldMemCtx);
3636  }
3637 
3638  break;
3639  }
3640  }
3641 
3642  if (matched)
3643  continue;
3644 
3645  forboth(lc, exprlist, lc2, oprlist)
3646  {
3647  Node *expr = (Node *) lfirst(lc);
3648  Oid opr = lfirst_oid(lc2);
3649 
3650  /* See if the expression matches the index key */
3651  if (!match_index_to_operand(expr, c, ind))
3652  continue;
3653 
3654  /*
3655  * The equality operator must be a member of the index
3656  * opfamily, else it is not asserting the right kind of
3657  * equality behavior for this index. We assume the caller
3658  * determined it is an equality operator, so we don't need to
3659  * check any more tightly than this.
3660  */
3661  if (!op_in_opfamily(opr, ind->opfamily[c]))
3662  continue;
3663 
3664  /*
3665  * XXX at some point we may need to check collations here too.
3666  * For the moment we assume all collations reduce to the same
3667  * notion of equality.
3668  */
3669 
3670  matched = true; /* column is unique */
3671  break;
3672  }
3673 
3674  if (!matched)
3675  break; /* no match; this index doesn't help us */
3676  }
3677 
3678  /* Matched all key columns of this index? */
3679  if (c == ind->nkeycolumns)
3680  {
3681  if (extra_clauses)
3682  *extra_clauses = exprs;
3683  return true;
3684  }
3685  }
3686 
3687  return false;
3688 }
@ BMS_SINGLETON
Definition: bitmapset.h:72
bool match_index_to_operand(Node *operand, int indexcol, IndexOptInfo *index)
Definition: indxpath.c:3758
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:722
bool op_in_opfamily(Oid opno, Oid opfamily)
Definition: lsyscache.c:66
#define lfirst_oid(lc)
Definition: pg_list.h:174
char * c

References Assert(), RelOptInfo::baserestrictinfo, bms_is_empty, bms_membership(), BMS_SINGLETON, RestrictInfo::clause, forboth, get_leftop(), get_rightop(), RelOptInfo::indexlist, lappend(), lfirst, lfirst_oid, list_length(), list_member_oid(), match_index_to_operand(), MemoryContextSwitchTo(), NIL, and op_in_opfamily().

Referenced by rel_is_distinct_for(), and relation_has_unique_index_for().

◆ relation_has_unique_index_for()

bool relation_has_unique_index_for ( PlannerInfo root,
RelOptInfo rel,
List restrictlist,
List exprlist,
List oprlist 
)

Definition at line 3494 of file indxpath.c.

3497 {
3498  return relation_has_unique_index_ext(root, rel, restrictlist,
3499  exprlist, oprlist, NULL);
3500 }
bool relation_has_unique_index_ext(PlannerInfo *root, RelOptInfo *rel, List *restrictlist, List *exprlist, List *oprlist, List **extra_clauses)
Definition: indxpath.c:3509

References relation_has_unique_index_ext().

Referenced by create_unique_path().

◆ select_outer_pathkeys_for_merge()

List* select_outer_pathkeys_for_merge ( PlannerInfo root,
List mergeclauses,
RelOptInfo joinrel 
)

Definition at line 1642 of file pathkeys.c.

1645 {
1646  List *pathkeys = NIL;
1647  int nClauses = list_length(mergeclauses);
1648  EquivalenceClass **ecs;
1649  int *scores;
1650  int necs;
1651  ListCell *lc;
1652  int j;
1653 
1654  /* Might have no mergeclauses */
1655  if (nClauses == 0)
1656  return NIL;
1657 
1658  /*
1659  * Make arrays of the ECs used by the mergeclauses (dropping any
1660  * duplicates) and their "popularity" scores.
1661  */
1662  ecs = (EquivalenceClass **) palloc(nClauses * sizeof(EquivalenceClass *));
1663  scores = (int *) palloc(nClauses * sizeof(int));
1664  necs = 0;
1665 
1666  foreach(lc, mergeclauses)
1667  {
1668  RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
1669  EquivalenceClass *oeclass;
1670  int score;
1671  ListCell *lc2;
1672 
1673  /* get the outer eclass */
1674  update_mergeclause_eclasses(root, rinfo);
1675 
1676  if (rinfo->outer_is_left)
1677  oeclass = rinfo->left_ec;
1678  else
1679  oeclass = rinfo->right_ec;
1680 
1681  /* reject duplicates */
1682  for (j = 0; j < necs; j++)
1683  {
1684  if (ecs[j] == oeclass)
1685  break;
1686  }
1687  if (j < necs)
1688  continue;
1689 
1690  /* compute score */
1691  score = 0;
1692  foreach(lc2, oeclass->ec_members)
1693  {
1695 
1696  /* Potential future join partner? */
1697  if (!em->em_is_const && !em->em_is_child &&
1698  !bms_overlap(em->em_relids, joinrel->relids))
1699  score++;
1700  }
1701 
1702  ecs[necs] = oeclass;
1703  scores[necs] = score;
1704  necs++;
1705  }
1706 
1707  /*
1708  * Find out if we have all the ECs mentioned in query_pathkeys; if so we
1709  * can generate a sort order that's also useful for final output. If we
1710  * only have a prefix of the query_pathkeys, and that prefix is the entire
1711  * join condition, then it's useful to use the prefix as the pathkeys as
1712  * this increases the chances that an incremental sort will be able to be
1713  * used by the upper planner.
1714  */
1715  if (root->query_pathkeys)
1716  {
1717  int matches = 0;
1718 
1719  foreach(lc, root->query_pathkeys)
1720  {
1721  PathKey *query_pathkey = (PathKey *) lfirst(lc);
1722  EquivalenceClass *query_ec = query_pathkey->pk_eclass;
1723 
1724  for (j = 0; j < necs; j++)
1725  {
1726  if (ecs[j] == query_ec)
1727  break; /* found match */
1728  }
1729  if (j >= necs)
1730  break; /* didn't find match */
1731 
1732  matches++;
1733  }
1734  /* if we got to the end of the list, we have them all */
1735  if (lc == NULL)
1736  {
1737  /* copy query_pathkeys as starting point for our output */
1738  pathkeys = list_copy(root->query_pathkeys);
1739  /* mark their ECs as already-emitted */
1740  foreach(lc, root->query_pathkeys)
1741  {
1742  PathKey *query_pathkey = (PathKey *) lfirst(lc);
1743  EquivalenceClass *query_ec = query_pathkey->pk_eclass;
1744 
1745  for (j = 0; j < necs; j++)
1746  {
1747  if (ecs[j] == query_ec)
1748  {
1749  scores[j] = -1;
1750  break;
1751  }
1752  }
1753  }
1754  }
1755 
1756  /*
1757  * If we didn't match to all of the query_pathkeys, but did match to
1758  * all of the join clauses then we'll make use of these as partially
1759  * sorted input is better than nothing for the upper planner as it may
1760  * lead to incremental sorts instead of full sorts.
1761  */
1762  else if (matches == nClauses)
1763  {
1764  pathkeys = list_copy_head(root->query_pathkeys, matches);
1765 
1766  /* we have all of the join pathkeys, so nothing more to do */
1767  pfree(ecs);
1768  pfree(scores);
1769 
1770  return pathkeys;
1771  }
1772  }
1773 
1774  /*
1775  * Add remaining ECs to the list in popularity order, using a default sort
1776  * ordering. (We could use qsort() here, but the list length is usually
1777  * so small it's not worth it.)
1778  */
1779  for (;;)
1780  {
1781  int best_j;
1782  int best_score;
1783  EquivalenceClass *ec;
1784  PathKey *pathkey;
1785 
1786  best_j = 0;
1787  best_score = scores[0];
1788  for (j = 1; j < necs; j++)
1789  {
1790  if (scores[j] > best_score)
1791  {
1792  best_j = j;
1793  best_score = scores[j];
1794  }
1795  }
1796  if (best_score < 0)
1797  break; /* all done */
1798  ec = ecs[best_j];
1799  scores[best_j] = -1;
1800  pathkey = make_canonical_pathkey(root,
1801  ec,
1804  false);
1805  /* can't be redundant because no duplicate ECs */
1806  Assert(!pathkey_is_redundant(pathkey, pathkeys));
1807  pathkeys = lappend(pathkeys, pathkey);
1808  }
1809 
1810  pfree(ecs);
1811  pfree(scores);
1812 
1813  return pathkeys;
1814 }
List * list_copy_head(const List *oldlist, int len)
Definition: list.c:1593
void pfree(void *pointer)
Definition: mcxt.c:1508
void * palloc(Size size)
Definition: mcxt.c:1304
#define linitial_oid(l)
Definition: pg_list.h:180
#define BTLessStrategyNumber
Definition: stratnum.h:29

References Assert(), bms_overlap(), BTLessStrategyNumber, EquivalenceClass::ec_members, EquivalenceClass::ec_opfamilies, EquivalenceMember::em_is_child, EquivalenceMember::em_is_const, EquivalenceMember::em_relids, j, lappend(), lfirst, linitial_oid, list_copy(), list_copy_head(), list_length(), make_canonical_pathkey(), NIL, palloc(), pathkey_is_redundant(), pfree(), PlannerInfo::query_pathkeys, RelOptInfo::relids, and update_mergeclause_eclasses().

Referenced by sort_inner_and_outer().

◆ standard_join_search()

RelOptInfo* standard_join_search ( PlannerInfo root,
int  levels_needed,
List initial_rels 
)

Definition at line 3418 of file allpaths.c.

3419 {
3420  int lev;
3421  RelOptInfo *rel;
3422 
3423  /*
3424  * This function cannot be invoked recursively within any one planning
3425  * problem, so join_rel_level[] can't be in use already.
3426  */
3427  Assert(root->join_rel_level == NULL);
3428 
3429  /*
3430  * We employ a simple "dynamic programming" algorithm: we first find all
3431  * ways to build joins of two jointree items, then all ways to build joins
3432  * of three items (from two-item joins and single items), then four-item
3433  * joins, and so on until we have considered all ways to join all the
3434  * items into one rel.
3435  *
3436  * root->join_rel_level[j] is a list of all the j-item rels. Initially we
3437  * set root->join_rel_level[1] to represent all the single-jointree-item
3438  * relations.
3439  */
3440  root->join_rel_level = (List **) palloc0((levels_needed + 1) * sizeof(List *));
3441 
3442  root->join_rel_level[1] = initial_rels;
3443 
3444  for (lev = 2; lev <= levels_needed; lev++)
3445  {
3446  ListCell *lc;
3447 
3448  /*
3449  * Determine all possible pairs of relations to be joined at this
3450  * level, and build paths for making each one from every available
3451  * pair of lower-level relations.
3452  */
3453  join_search_one_level(root, lev);
3454 
3455  /*
3456  * Run generate_partitionwise_join_paths() and
3457  * generate_useful_gather_paths() for each just-processed joinrel. We
3458  * could not do this earlier because both regular and partial paths
3459  * can get added to a particular joinrel at multiple times within
3460  * join_search_one_level.
3461  *
3462  * After that, we're done creating paths for the joinrel, so run
3463  * set_cheapest().
3464  */
3465  foreach(lc, root->join_rel_level[lev])
3466  {
3467  rel = (RelOptInfo *) lfirst(lc);
3468 
3469  /* Create paths for partitionwise joins. */
3471 
3472  /*
3473  * Except for the topmost scan/join rel, consider gathering
3474  * partial paths. We'll do the same for the topmost scan/join rel
3475  * once we know the final targetlist (see grouping_planner's and
3476  * its call to apply_scanjoin_target_to_paths).
3477  */
3478  if (!bms_equal(rel->relids, root->all_query_rels))
3479  generate_useful_gather_paths(root, rel, false);
3480 
3481  /* Find and save the cheapest paths for this rel */
3482  set_cheapest(rel);
3483 
3484 #ifdef OPTIMIZER_DEBUG
3485  pprint(rel);
3486 #endif
3487  }
3488  }
3489 
3490  /*
3491  * We should have a single rel at the final level.
3492  */
3493  if (root->join_rel_level[levels_needed] == NIL)
3494  elog(ERROR, "failed to build any %d-way joins", levels_needed);
3495  Assert(list_length(root->join_rel_level[levels_needed]) == 1);
3496 
3497  rel = (RelOptInfo *) linitial(root->join_rel_level[levels_needed]);
3498 
3499  root->join_rel_level = NULL;
3500 
3501  return rel;
3502 }
void generate_useful_gather_paths(PlannerInfo *root, RelOptInfo *rel, bool override_rows)
Definition: allpaths.c:3197
void join_search_one_level(PlannerInfo *root, int level)
Definition: joinrels.c:71
void * palloc0(Size size)
Definition: mcxt.c:1334

References PlannerInfo::all_query_rels, Assert(), bms_equal(), elog, ERROR, generate_partitionwise_join_paths(), generate_useful_gather_paths(), join_search_one_level(), lfirst, linitial, list_length(), NIL, palloc0(), pprint(), RelOptInfo::relids, and set_cheapest().

Referenced by make_rel_from_joinlist().

◆ trim_mergeclauses_for_inner_pathkeys()

List* trim_mergeclauses_for_inner_pathkeys ( PlannerInfo root,
List mergeclauses,
List pathkeys 
)

Definition at line 1941 of file pathkeys.c.

1944 {
1945  List *new_mergeclauses = NIL;
1946  PathKey *pathkey;
1947  EquivalenceClass *pathkey_ec;
1948  bool matched_pathkey;
1949  ListCell *lip;
1950  ListCell *i;
1951 
1952  /* No pathkeys => no mergeclauses (though we don't expect this case) */
1953  if (pathkeys == NIL)
1954  return NIL;
1955  /* Initialize to consider first pathkey */
1956  lip = list_head(pathkeys);
1957  pathkey = (PathKey *) lfirst(lip);
1958  pathkey_ec = pathkey->pk_eclass;
1959  lip = lnext(pathkeys, lip);
1960  matched_pathkey = false;
1961 
1962  /* Scan mergeclauses to see how many we can use */
1963  foreach(i, mergeclauses)
1964  {
1965  RestrictInfo *rinfo = (RestrictInfo *) lfirst(i);
1966  EquivalenceClass *clause_ec;
1967 
1968  /* Assume we needn't do update_mergeclause_eclasses again here */
1969 
1970  /* Check clause's inner-rel EC against current pathkey */
1971  clause_ec = rinfo->outer_is_left ?
1972  rinfo->right_ec : rinfo->left_ec;
1973 
1974  /* If we don't have a match, attempt to advance to next pathkey */
1975  if (clause_ec != pathkey_ec)
1976  {
1977  /* If we had no clauses matching this inner pathkey, must stop */
1978  if (!matched_pathkey)
1979  break;
1980 
1981  /* Advance to next inner pathkey, if any */
1982  if (lip == NULL)
1983  break;
1984  pathkey = (PathKey *) lfirst(lip);
1985  pathkey_ec = pathkey->pk_eclass;
1986  lip = lnext(pathkeys, lip);
1987  matched_pathkey = false;
1988  }
1989 
1990  /* If mergeclause matches current inner pathkey, we can use it */
1991  if (clause_ec == pathkey_ec)
1992  {
1993  new_mergeclauses = lappend(new_mergeclauses, rinfo);
1994  matched_pathkey = true;
1995  }
1996  else
1997  {
1998  /* Else, no hope of adding any more mergeclauses */
1999  break;
2000  }
2001  }
2002 
2003  return new_mergeclauses;
2004 }

References i, lappend(), lfirst, list_head(), lnext(), and NIL.

Referenced by generate_mergejoin_paths().

◆ truncate_useless_pathkeys()

List* truncate_useless_pathkeys ( PlannerInfo root,
RelOptInfo rel,
List pathkeys 
)

Definition at line 2199 of file pathkeys.c.

2202 {
2203  int nuseful;
2204  int nuseful2;
2205 
2206  nuseful = pathkeys_useful_for_merging(root, rel, pathkeys);
2207  nuseful2 = pathkeys_useful_for_ordering(root, pathkeys);
2208  if (nuseful2 > nuseful)
2209  nuseful = nuseful2;
2210  nuseful2 = pathkeys_useful_for_grouping(root, pathkeys);
2211  if (nuseful2 > nuseful)
2212  nuseful = nuseful2;
2213 
2214  /*
2215  * Note: not safe to modify input list destructively, but we can avoid
2216  * copying the list if we're not actually going to change it
2217  */
2218  if (nuseful == 0)
2219  return NIL;
2220  else if (nuseful == list_length(pathkeys))
2221  return pathkeys;
2222  else
2223  return list_copy_head(pathkeys, nuseful);
2224 }
static int pathkeys_useful_for_ordering(PlannerInfo *root, List *pathkeys)
Definition: pathkeys.c:2140
static int pathkeys_useful_for_grouping(PlannerInfo *root, List *pathkeys)
Definition: pathkeys.c:2170
static int pathkeys_useful_for_merging(PlannerInfo *root, RelOptInfo *rel, List *pathkeys)
Definition: pathkeys.c:2036

References list_copy_head(), list_length(), NIL, pathkeys_useful_for_grouping(), pathkeys_useful_for_merging(), and pathkeys_useful_for_ordering().

Referenced by build_index_paths(), and build_join_pathkeys().

◆ update_mergeclause_eclasses()

void update_mergeclause_eclasses ( PlannerInfo root,
RestrictInfo restrictinfo 
)

Definition at line 1493 of file pathkeys.c.

1494 {
1495  /* Should be a merge clause ... */
1496  Assert(restrictinfo->mergeopfamilies != NIL);
1497  /* ... with pointers already set */
1498  Assert(restrictinfo->left_ec != NULL);
1499  Assert(restrictinfo->right_ec != NULL);
1500 
1501  /* Chase up to the top as needed */
1502  while (restrictinfo->left_ec->ec_merged)
1503  restrictinfo->left_ec = restrictinfo->left_ec->ec_merged;
1504  while (restrictinfo->right_ec->ec_merged)
1505  restrictinfo->right_ec = restrictinfo->right_ec->ec_merged;
1506 }

References Assert(), and NIL.

Referenced by find_mergeclauses_for_outer_pathkeys(), get_useful_ecs_for_relation(), make_inner_pathkeys_for_merge(), pathkeys_useful_for_merging(), select_mergejoin_clauses(), and select_outer_pathkeys_for_merge().

Variable Documentation

◆ enable_geqo

PGDLLIMPORT bool enable_geqo
extern

Definition at line 79 of file allpaths.c.

Referenced by make_rel_from_joinlist().

◆ enable_group_by_reordering

PGDLLIMPORT bool enable_group_by_reordering
extern

Definition at line 31 of file pathkeys.c.

Referenced by get_useful_group_keys_orderings().

◆ geqo_threshold

PGDLLIMPORT int geqo_threshold
extern

Definition at line 80 of file allpaths.c.

Referenced by make_rel_from_joinlist().

◆ join_search_hook

PGDLLIMPORT join_search_hook_type join_search_hook
extern

Definition at line 88 of file allpaths.c.

Referenced by make_rel_from_joinlist().

◆ min_parallel_index_scan_size

PGDLLIMPORT int min_parallel_index_scan_size
extern

Definition at line 82 of file allpaths.c.

Referenced by compute_parallel_worker(), and parallel_vacuum_compute_workers().

◆ min_parallel_table_scan_size

PGDLLIMPORT int min_parallel_table_scan_size
extern

Definition at line 81 of file allpaths.c.

Referenced by compute_parallel_worker().

◆ set_join_pathlist_hook

PGDLLIMPORT set_join_pathlist_hook_type set_join_pathlist_hook
extern

Definition at line 30 of file joinpath.c.

Referenced by add_paths_to_joinrel().

◆ set_rel_pathlist_hook

PGDLLIMPORT set_rel_pathlist_hook_type set_rel_pathlist_hook
extern

Definition at line 85 of file allpaths.c.

Referenced by set_rel_pathlist().