PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
initsplan.c File Reference
Include dependency graph for initsplan.c:

Go to the source code of this file.

Data Structures

struct  PostponedQual
 

Typedefs

typedef struct PostponedQual PostponedQual
 

Functions

static void extract_lateral_references (PlannerInfo *root, RelOptInfo *brel, Index rtindex)
 
static Listdeconstruct_recurse (PlannerInfo *root, Node *jtnode, bool below_outer_join, Relids *qualscope, Relids *inner_join_rels, List **postponed_qual_list)
 
static void process_security_barrier_quals (PlannerInfo *root, int rti, Relids qualscope, bool below_outer_join)
 
static SpecialJoinInfomake_outerjoininfo (PlannerInfo *root, Relids left_rels, Relids right_rels, Relids inner_join_rels, JoinType jointype, List *clause)
 
static void compute_semijoin_info (SpecialJoinInfo *sjinfo, List *clause)
 
static void distribute_qual_to_rels (PlannerInfo *root, Node *clause, bool is_deduced, bool below_outer_join, JoinType jointype, Index security_level, Relids qualscope, Relids ojscope, Relids outerjoin_nonnullable, Relids deduced_nullable_relids, List **postponed_qual_list)
 
static bool check_outerjoin_delay (PlannerInfo *root, Relids *relids_p, Relids *nullable_relids_p, bool is_pushed_down)
 
static bool check_equivalence_delay (PlannerInfo *root, RestrictInfo *restrictinfo)
 
static bool check_redundant_nullability_qual (PlannerInfo *root, Node *clause)
 
static void check_mergejoinable (RestrictInfo *restrictinfo)
 
static void check_hashjoinable (RestrictInfo *restrictinfo)
 
void add_base_rels_to_query (PlannerInfo *root, Node *jtnode)
 
void build_base_rel_tlists (PlannerInfo *root, List *final_tlist)
 
void add_vars_to_targetlist (PlannerInfo *root, List *vars, Relids where_needed, bool create_new_ph)
 
void find_lateral_references (PlannerInfo *root)
 
void create_lateral_join_info (PlannerInfo *root)
 
Listdeconstruct_jointree (PlannerInfo *root)
 
void distribute_restrictinfo_to_rels (PlannerInfo *root, RestrictInfo *restrictinfo)
 
void process_implied_equality (PlannerInfo *root, Oid opno, Oid collation, Expr *item1, Expr *item2, Relids qualscope, Relids nullable_relids, Index security_level, bool below_outer_join, bool both_const)
 
RestrictInfobuild_implied_join_equality (Oid opno, Oid collation, Expr *item1, Expr *item2, Relids qualscope, Relids nullable_relids, Index security_level)
 
void match_foreign_keys_to_quals (PlannerInfo *root)
 

Variables

int from_collapse_limit
 
int join_collapse_limit
 

Typedef Documentation

Function Documentation

void add_base_rels_to_query ( PlannerInfo root,
Node jtnode 
)

Definition at line 105 of file initsplan.c.

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

Referenced by add_base_rels_to_query(), and query_planner().

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

Definition at line 198 of file initsplan.c.

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

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

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

Definition at line 151 of file initsplan.c.

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

Referenced by query_planner().

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

Definition at line 2372 of file initsplan.c.

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

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

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

Definition at line 2150 of file initsplan.c.

References bms_copy(), check_outerjoin_delay(), PlannerInfo::join_info_list, RestrictInfo::left_relids, NIL, and RestrictInfo::right_relids.

Referenced by distribute_qual_to_rels().

2152 {
2153  Relids relids;
2154  Relids nullable_relids;
2155 
2156  /* fast path if no special joins */
2157  if (root->join_info_list == NIL)
2158  return true;
2159 
2160  /* must copy restrictinfo's relids to avoid changing it */
2161  relids = bms_copy(restrictinfo->left_relids);
2162  /* check left side does not need delay */
2163  if (check_outerjoin_delay(root, &relids, &nullable_relids, true))
2164  return false;
2165 
2166  /* and similarly for the right side */
2167  relids = bms_copy(restrictinfo->right_relids);
2168  if (check_outerjoin_delay(root, &relids, &nullable_relids, true))
2169  return false;
2170 
2171  return true;
2172 }
#define NIL
Definition: pg_list.h:69
static bool check_outerjoin_delay(PlannerInfo *root, Relids *relids_p, Relids *nullable_relids_p, bool is_pushed_down)
Definition: initsplan.c:2066
Bitmapset * bms_copy(const Bitmapset *a)
Definition: bitmapset.c:111
List * join_info_list
Definition: relation.h:250
Relids left_relids
Definition: relation.h:1774
Relids right_relids
Definition: relation.h:1775
static void check_hashjoinable ( RestrictInfo restrictinfo)
static

Definition at line 2636 of file initsplan.c.

References generate_unaccent_rules::args, RestrictInfo::clause, contain_volatile_functions(), exprType(), RestrictInfo::hashjoinoperator, is_opclause, linitial, list_length(), op_hashjoinable(), and RestrictInfo::pseudoconstant.

Referenced by build_implied_join_equality(), and distribute_restrictinfo_to_rels().

2637 {
2638  Expr *clause = restrictinfo->clause;
2639  Oid opno;
2640  Node *leftarg;
2641 
2642  if (restrictinfo->pseudoconstant)
2643  return;
2644  if (!is_opclause(clause))
2645  return;
2646  if (list_length(((OpExpr *) clause)->args) != 2)
2647  return;
2648 
2649  opno = ((OpExpr *) clause)->opno;
2650  leftarg = linitial(((OpExpr *) clause)->args);
2651 
2652  if (op_hashjoinable(opno, exprType(leftarg)) &&
2653  !contain_volatile_functions((Node *) clause))
2654  restrictinfo->hashjoinoperator = opno;
2655 }
bool pseudoconstant
Definition: relation.h:1755
Definition: nodes.h:509
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:957
unsigned int Oid
Definition: postgres_ext.h:31
bool op_hashjoinable(Oid opno, Oid inputtype)
Definition: lsyscache.c:1246
#define linitial(l)
Definition: pg_list.h:111
#define is_opclause(clause)
Definition: clauses.h:20
Expr * clause
Definition: relation.h:1747
Oid hashjoinoperator
Definition: relation.h:1805
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
static int list_length(const List *l)
Definition: pg_list.h:89
static void check_mergejoinable ( RestrictInfo restrictinfo)
static

Definition at line 2599 of file initsplan.c.

References generate_unaccent_rules::args, RestrictInfo::clause, contain_volatile_functions(), exprType(), get_mergejoin_opfamilies(), is_opclause, linitial, list_length(), RestrictInfo::mergeopfamilies, op_mergejoinable(), and RestrictInfo::pseudoconstant.

Referenced by build_implied_join_equality(), and distribute_qual_to_rels().

2600 {
2601  Expr *clause = restrictinfo->clause;
2602  Oid opno;
2603  Node *leftarg;
2604 
2605  if (restrictinfo->pseudoconstant)
2606  return;
2607  if (!is_opclause(clause))
2608  return;
2609  if (list_length(((OpExpr *) clause)->args) != 2)
2610  return;
2611 
2612  opno = ((OpExpr *) clause)->opno;
2613  leftarg = linitial(((OpExpr *) clause)->args);
2614 
2615  if (op_mergejoinable(opno, exprType(leftarg)) &&
2616  !contain_volatile_functions((Node *) clause))
2617  restrictinfo->mergeopfamilies = get_mergejoin_opfamilies(opno);
2618 
2619  /*
2620  * Note: op_mergejoinable is just a hint; if we fail to find the operator
2621  * in any btree opfamilies, mergeopfamilies remains NIL and so the clause
2622  * is not treated as mergejoinable.
2623  */
2624 }
List * get_mergejoin_opfamilies(Oid opno)
Definition: lsyscache.c:363
bool pseudoconstant
Definition: relation.h:1755
Definition: nodes.h:509
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:957
bool op_mergejoinable(Oid opno, Oid inputtype)
Definition: lsyscache.c:1195
unsigned int Oid
Definition: postgres_ext.h:31
List * mergeopfamilies
Definition: relation.h:1792
#define linitial(l)
Definition: pg_list.h:111
#define is_opclause(clause)
Definition: clauses.h:20
Expr * clause
Definition: relation.h:1747
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
static int list_length(const List *l)
Definition: pg_list.h:89
static bool check_outerjoin_delay ( PlannerInfo root,
Relids relids_p,
Relids nullable_relids_p,
bool  is_pushed_down 
)
static

Definition at line 2066 of file initsplan.c.

References bms_add_members(), bms_copy(), bms_free(), bms_int_members(), bms_is_subset(), bms_overlap(), SpecialJoinInfo::delay_upper_joins, JOIN_FULL, PlannerInfo::join_info_list, SpecialJoinInfo::jointype, lfirst, SpecialJoinInfo::min_lefthand, SpecialJoinInfo::min_righthand, and NIL.

Referenced by check_equivalence_delay(), and distribute_qual_to_rels().

2070 {
2071  Relids relids;
2072  Relids nullable_relids;
2073  bool outerjoin_delayed;
2074  bool found_some;
2075 
2076  /* fast path if no special joins */
2077  if (root->join_info_list == NIL)
2078  {
2079  *nullable_relids_p = NULL;
2080  return false;
2081  }
2082 
2083  /* must copy relids because we need the original value at the end */
2084  relids = bms_copy(*relids_p);
2085  nullable_relids = NULL;
2086  outerjoin_delayed = false;
2087  do
2088  {
2089  ListCell *l;
2090 
2091  found_some = false;
2092  foreach(l, root->join_info_list)
2093  {
2094  SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(l);
2095 
2096  /* do we reference any nullable rels of this OJ? */
2097  if (bms_overlap(relids, sjinfo->min_righthand) ||
2098  (sjinfo->jointype == JOIN_FULL &&
2099  bms_overlap(relids, sjinfo->min_lefthand)))
2100  {
2101  /* yes; have we included all its rels in relids? */
2102  if (!bms_is_subset(sjinfo->min_lefthand, relids) ||
2103  !bms_is_subset(sjinfo->min_righthand, relids))
2104  {
2105  /* no, so add them in */
2106  relids = bms_add_members(relids, sjinfo->min_lefthand);
2107  relids = bms_add_members(relids, sjinfo->min_righthand);
2108  outerjoin_delayed = true;
2109  /* we'll need another iteration */
2110  found_some = true;
2111  }
2112  /* track all the nullable rels of relevant OJs */
2113  nullable_relids = bms_add_members(nullable_relids,
2114  sjinfo->min_righthand);
2115  if (sjinfo->jointype == JOIN_FULL)
2116  nullable_relids = bms_add_members(nullable_relids,
2117  sjinfo->min_lefthand);
2118  /* set delay_upper_joins if needed */
2119  if (is_pushed_down && sjinfo->jointype != JOIN_FULL &&
2120  bms_overlap(relids, sjinfo->min_lefthand))
2121  sjinfo->delay_upper_joins = true;
2122  }
2123  }
2124  } while (found_some);
2125 
2126  /* identify just the actually-referenced nullable rels */
2127  nullable_relids = bms_int_members(nullable_relids, *relids_p);
2128 
2129  /* replace *relids_p, and return nullable_relids */
2130  bms_free(*relids_p);
2131  *relids_p = relids;
2132  *nullable_relids_p = nullable_relids;
2133  return outerjoin_delayed;
2134 }
#define NIL
Definition: pg_list.h:69
Bitmapset * bms_copy(const Bitmapset *a)
Definition: bitmapset.c:111
List * join_info_list
Definition: relation.h:250
Relids min_righthand
Definition: relation.h:1920
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:308
bool delay_upper_joins
Definition: relation.h:1925
void bms_free(Bitmapset *a)
Definition: bitmapset.c:201
#define lfirst(lc)
Definition: pg_list.h:106
JoinType jointype
Definition: relation.h:1923
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:443
Bitmapset * bms_int_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:791
Relids min_lefthand
Definition: relation.h:1919
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:755
static bool check_redundant_nullability_qual ( PlannerInfo root,
Node clause 
)
static

Definition at line 2185 of file initsplan.c.

References bms_is_member(), find_forced_null_var(), JOIN_ANTI, PlannerInfo::join_info_list, SpecialJoinInfo::jointype, lfirst, SpecialJoinInfo::syn_righthand, and Var::varno.

Referenced by distribute_qual_to_rels().

2186 {
2187  Var *forced_null_var;
2188  Index forced_null_rel;
2189  ListCell *lc;
2190 
2191  /* Check for IS NULL, and identify the Var forced to NULL */
2192  forced_null_var = find_forced_null_var(clause);
2193  if (forced_null_var == NULL)
2194  return false;
2195  forced_null_rel = forced_null_var->varno;
2196 
2197  /*
2198  * If the Var comes from the nullable side of a lower antijoin, the IS
2199  * NULL condition is necessarily true.
2200  */
2201  foreach(lc, root->join_info_list)
2202  {
2203  SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(lc);
2204 
2205  if (sjinfo->jointype == JOIN_ANTI &&
2206  bms_is_member(forced_null_rel, sjinfo->syn_righthand))
2207  return true;
2208  }
2209 
2210  return false;
2211 }
List * join_info_list
Definition: relation.h:250
Definition: primnodes.h:163
Relids syn_righthand
Definition: relation.h:1922
Index varno
Definition: primnodes.h:166
unsigned int Index
Definition: c.h:359
#define lfirst(lc)
Definition: pg_list.h:106
JoinType jointype
Definition: relation.h:1923
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:420
Var * find_forced_null_var(Node *node)
Definition: clauses.c:2086
static void compute_semijoin_info ( SpecialJoinInfo sjinfo,
List clause 
)
static

Definition at line 1422 of file initsplan.c.

References OpExpr::args, bms_is_empty(), bms_is_subset(), bms_overlap(), bms_union(), contain_volatile_functions(), copyObject, enable_hashagg, exprType(), get_commutator(), get_mergejoin_opfamilies(), IsA, JOIN_SEMI, SpecialJoinInfo::jointype, lappend(), lappend_oid(), lfirst, linitial, list_length(), lsecond, NIL, OidIsValid, op_hashjoinable(), op_mergejoinable(), OpExpr::opno, pull_varnos(), SpecialJoinInfo::semi_can_btree, SpecialJoinInfo::semi_can_hash, SpecialJoinInfo::semi_operators, SpecialJoinInfo::semi_rhs_exprs, and SpecialJoinInfo::syn_righthand.

Referenced by make_outerjoininfo().

1423 {
1424  List *semi_operators;
1425  List *semi_rhs_exprs;
1426  bool all_btree;
1427  bool all_hash;
1428  ListCell *lc;
1429 
1430  /* Initialize semijoin-related fields in case we can't unique-ify */
1431  sjinfo->semi_can_btree = false;
1432  sjinfo->semi_can_hash = false;
1433  sjinfo->semi_operators = NIL;
1434  sjinfo->semi_rhs_exprs = NIL;
1435 
1436  /* Nothing more to do if it's not a semijoin */
1437  if (sjinfo->jointype != JOIN_SEMI)
1438  return;
1439 
1440  /*
1441  * Look to see whether the semijoin's join quals consist of AND'ed
1442  * equality operators, with (only) RHS variables on only one side of each
1443  * one. If so, we can figure out how to enforce uniqueness for the RHS.
1444  *
1445  * Note that the input clause list is the list of quals that are
1446  * *syntactically* associated with the semijoin, which in practice means
1447  * the synthesized comparison list for an IN or the WHERE of an EXISTS.
1448  * Particularly in the latter case, it might contain clauses that aren't
1449  * *semantically* associated with the join, but refer to just one side or
1450  * the other. We can ignore such clauses here, as they will just drop
1451  * down to be processed within one side or the other. (It is okay to
1452  * consider only the syntactically-associated clauses here because for a
1453  * semijoin, no higher-level quals could refer to the RHS, and so there
1454  * can be no other quals that are semantically associated with this join.
1455  * We do things this way because it is useful to have the set of potential
1456  * unique-ification expressions before we can extract the list of quals
1457  * that are actually semantically associated with the particular join.)
1458  *
1459  * Note that the semi_operators list consists of the joinqual operators
1460  * themselves (but commuted if needed to put the RHS value on the right).
1461  * These could be cross-type operators, in which case the operator
1462  * actually needed for uniqueness is a related single-type operator. We
1463  * assume here that that operator will be available from the btree or hash
1464  * opclass when the time comes ... if not, create_unique_plan() will fail.
1465  */
1466  semi_operators = NIL;
1467  semi_rhs_exprs = NIL;
1468  all_btree = true;
1469  all_hash = enable_hashagg; /* don't consider hash if not enabled */
1470  foreach(lc, clause)
1471  {
1472  OpExpr *op = (OpExpr *) lfirst(lc);
1473  Oid opno;
1474  Node *left_expr;
1475  Node *right_expr;
1476  Relids left_varnos;
1477  Relids right_varnos;
1478  Relids all_varnos;
1479  Oid opinputtype;
1480 
1481  /* Is it a binary opclause? */
1482  if (!IsA(op, OpExpr) ||
1483  list_length(op->args) != 2)
1484  {
1485  /* No, but does it reference both sides? */
1486  all_varnos = pull_varnos((Node *) op);
1487  if (!bms_overlap(all_varnos, sjinfo->syn_righthand) ||
1488  bms_is_subset(all_varnos, sjinfo->syn_righthand))
1489  {
1490  /*
1491  * Clause refers to only one rel, so ignore it --- unless it
1492  * contains volatile functions, in which case we'd better
1493  * punt.
1494  */
1495  if (contain_volatile_functions((Node *) op))
1496  return;
1497  continue;
1498  }
1499  /* Non-operator clause referencing both sides, must punt */
1500  return;
1501  }
1502 
1503  /* Extract data from binary opclause */
1504  opno = op->opno;
1505  left_expr = linitial(op->args);
1506  right_expr = lsecond(op->args);
1507  left_varnos = pull_varnos(left_expr);
1508  right_varnos = pull_varnos(right_expr);
1509  all_varnos = bms_union(left_varnos, right_varnos);
1510  opinputtype = exprType(left_expr);
1511 
1512  /* Does it reference both sides? */
1513  if (!bms_overlap(all_varnos, sjinfo->syn_righthand) ||
1514  bms_is_subset(all_varnos, sjinfo->syn_righthand))
1515  {
1516  /*
1517  * Clause refers to only one rel, so ignore it --- unless it
1518  * contains volatile functions, in which case we'd better punt.
1519  */
1520  if (contain_volatile_functions((Node *) op))
1521  return;
1522  continue;
1523  }
1524 
1525  /* check rel membership of arguments */
1526  if (!bms_is_empty(right_varnos) &&
1527  bms_is_subset(right_varnos, sjinfo->syn_righthand) &&
1528  !bms_overlap(left_varnos, sjinfo->syn_righthand))
1529  {
1530  /* typical case, right_expr is RHS variable */
1531  }
1532  else if (!bms_is_empty(left_varnos) &&
1533  bms_is_subset(left_varnos, sjinfo->syn_righthand) &&
1534  !bms_overlap(right_varnos, sjinfo->syn_righthand))
1535  {
1536  /* flipped case, left_expr is RHS variable */
1537  opno = get_commutator(opno);
1538  if (!OidIsValid(opno))
1539  return;
1540  right_expr = left_expr;
1541  }
1542  else
1543  {
1544  /* mixed membership of args, punt */
1545  return;
1546  }
1547 
1548  /* all operators must be btree equality or hash equality */
1549  if (all_btree)
1550  {
1551  /* oprcanmerge is considered a hint... */
1552  if (!op_mergejoinable(opno, opinputtype) ||
1553  get_mergejoin_opfamilies(opno) == NIL)
1554  all_btree = false;
1555  }
1556  if (all_hash)
1557  {
1558  /* ... but oprcanhash had better be correct */
1559  if (!op_hashjoinable(opno, opinputtype))
1560  all_hash = false;
1561  }
1562  if (!(all_btree || all_hash))
1563  return;
1564 
1565  /* so far so good, keep building lists */
1566  semi_operators = lappend_oid(semi_operators, opno);
1567  semi_rhs_exprs = lappend(semi_rhs_exprs, copyObject(right_expr));
1568  }
1569 
1570  /* Punt if we didn't find at least one column to unique-ify */
1571  if (semi_rhs_exprs == NIL)
1572  return;
1573 
1574  /*
1575  * The expressions we'd need to unique-ify mustn't be volatile.
1576  */
1577  if (contain_volatile_functions((Node *) semi_rhs_exprs))
1578  return;
1579 
1580  /*
1581  * If we get here, we can unique-ify the semijoin's RHS using at least one
1582  * of sorting and hashing. Save the information about how to do that.
1583  */
1584  sjinfo->semi_can_btree = all_btree;
1585  sjinfo->semi_can_hash = all_hash;
1586  sjinfo->semi_operators = semi_operators;
1587  sjinfo->semi_rhs_exprs = semi_rhs_exprs;
1588 }
#define NIL
Definition: pg_list.h:69
bool semi_can_btree
Definition: relation.h:1927
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
Oid get_commutator(Oid opno)
Definition: lsyscache.c:1313
List * get_mergejoin_opfamilies(Oid opno)
Definition: lsyscache.c:363
Definition: nodes.h:509
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:957
bool op_mergejoinable(Oid opno, Oid inputtype)
Definition: lsyscache.c:1195
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
#define OidIsValid(objectId)
Definition: c.h:532
#define lsecond(l)
Definition: pg_list.h:116
Relids syn_righthand
Definition: relation.h:1922
bool op_hashjoinable(Oid opno, Oid inputtype)
Definition: lsyscache.c:1246
#define linitial(l)
Definition: pg_list.h:111
List * semi_rhs_exprs
Definition: relation.h:1930
bool semi_can_hash
Definition: relation.h:1928
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:308
Relids pull_varnos(Node *node)
Definition: var.c:95
List * lappend(List *list, void *datum)
Definition: list.c:128
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:663
#define lfirst(lc)
Definition: pg_list.h:106
JoinType jointype
Definition: relation.h:1923
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:218
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
static int list_length(const List *l)
Definition: pg_list.h:89
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:443
bool enable_hashagg
Definition: costsize.c:124
List * semi_operators
Definition: relation.h:1929
Oid opno
Definition: primnodes.h:496
#define copyObject(obj)
Definition: nodes.h:622
List * args
Definition: primnodes.h:502
Definition: pg_list.h:45
void create_lateral_join_info ( PlannerInfo root)

Definition at line 418 of file initsplan.c.

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

Referenced by query_planner().

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

Definition at line 710 of file initsplan.c.

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

Referenced by query_planner().

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

Definition at line 756 of file initsplan.c.

References Assert, bms_add_members(), bms_is_subset(), bms_make_singleton(), bms_union(), distribute_qual_to_rels(), elog, ERROR, from_collapse_limit, FromExpr::fromlist, IsA, JOIN_ANTI, join_collapse_limit, JOIN_FULL, PlannerInfo::join_info_list, JOIN_INNER, JOIN_LEFT, JOIN_SEMI, JoinExpr::jointype, lappend(), JoinExpr::larg, lfirst, linitial, list_concat(), list_length(), list_make1, list_make2, make_outerjoininfo(), SpecialJoinInfo::min_lefthand, SpecialJoinInfo::min_righthand, NIL, nodeTag, PlannerInfo::nullable_baserels, process_security_barrier_quals(), PostponedQual::qual, PlannerInfo::qual_security_level, JoinExpr::quals, FromExpr::quals, JoinExpr::rarg, PostponedQual::relids, remaining, and update_placeholder_eval_levels().

Referenced by deconstruct_jointree().

759 {
760  List *joinlist;
761 
762  if (jtnode == NULL)
763  {
764  *qualscope = NULL;
765  *inner_join_rels = NULL;
766  return NIL;
767  }
768  if (IsA(jtnode, RangeTblRef))
769  {
770  int varno = ((RangeTblRef *) jtnode)->rtindex;
771 
772  /* qualscope is just the one RTE */
773  *qualscope = bms_make_singleton(varno);
774  /* Deal with any securityQuals attached to the RTE */
775  if (root->qual_security_level > 0)
777  varno,
778  *qualscope,
779  below_outer_join);
780  /* A single baserel does not create an inner join */
781  *inner_join_rels = NULL;
782  joinlist = list_make1(jtnode);
783  }
784  else if (IsA(jtnode, FromExpr))
785  {
786  FromExpr *f = (FromExpr *) jtnode;
787  List *child_postponed_quals = NIL;
788  int remaining;
789  ListCell *l;
790 
791  /*
792  * First, recurse to handle child joins. We collapse subproblems into
793  * a single joinlist whenever the resulting joinlist wouldn't exceed
794  * from_collapse_limit members. Also, always collapse one-element
795  * subproblems, since that won't lengthen the joinlist anyway.
796  */
797  *qualscope = NULL;
798  *inner_join_rels = NULL;
799  joinlist = NIL;
800  remaining = list_length(f->fromlist);
801  foreach(l, f->fromlist)
802  {
803  Relids sub_qualscope;
804  List *sub_joinlist;
805  int sub_members;
806 
807  sub_joinlist = deconstruct_recurse(root, lfirst(l),
808  below_outer_join,
809  &sub_qualscope,
810  inner_join_rels,
811  &child_postponed_quals);
812  *qualscope = bms_add_members(*qualscope, sub_qualscope);
813  sub_members = list_length(sub_joinlist);
814  remaining--;
815  if (sub_members <= 1 ||
816  list_length(joinlist) + sub_members + remaining <= from_collapse_limit)
817  joinlist = list_concat(joinlist, sub_joinlist);
818  else
819  joinlist = lappend(joinlist, sub_joinlist);
820  }
821 
822  /*
823  * A FROM with more than one list element is an inner join subsuming
824  * all below it, so we should report inner_join_rels = qualscope. If
825  * there was exactly one element, we should (and already did) report
826  * whatever its inner_join_rels were. If there were no elements (is
827  * that possible?) the initialization before the loop fixed it.
828  */
829  if (list_length(f->fromlist) > 1)
830  *inner_join_rels = *qualscope;
831 
832  /*
833  * Try to process any quals postponed by children. If they need
834  * further postponement, add them to my output postponed_qual_list.
835  */
836  foreach(l, child_postponed_quals)
837  {
838  PostponedQual *pq = (PostponedQual *) lfirst(l);
839 
840  if (bms_is_subset(pq->relids, *qualscope))
841  distribute_qual_to_rels(root, pq->qual,
842  false, below_outer_join, JOIN_INNER,
843  root->qual_security_level,
844  *qualscope, NULL, NULL, NULL,
845  NULL);
846  else
847  *postponed_qual_list = lappend(*postponed_qual_list, pq);
848  }
849 
850  /*
851  * Now process the top-level quals.
852  */
853  foreach(l, (List *) f->quals)
854  {
855  Node *qual = (Node *) lfirst(l);
856 
857  distribute_qual_to_rels(root, qual,
858  false, below_outer_join, JOIN_INNER,
859  root->qual_security_level,
860  *qualscope, NULL, NULL, NULL,
861  postponed_qual_list);
862  }
863  }
864  else if (IsA(jtnode, JoinExpr))
865  {
866  JoinExpr *j = (JoinExpr *) jtnode;
867  List *child_postponed_quals = NIL;
868  Relids leftids,
869  rightids,
870  left_inners,
871  right_inners,
872  nonnullable_rels,
873  nullable_rels,
874  ojscope;
875  List *leftjoinlist,
876  *rightjoinlist;
877  List *my_quals;
878  SpecialJoinInfo *sjinfo;
879  ListCell *l;
880 
881  /*
882  * Order of operations here is subtle and critical. First we recurse
883  * to handle sub-JOINs. Their join quals will be placed without
884  * regard for whether this level is an outer join, which is correct.
885  * Then we place our own join quals, which are restricted by lower
886  * outer joins in any case, and are forced to this level if this is an
887  * outer join and they mention the outer side. Finally, if this is an
888  * outer join, we create a join_info_list entry for the join. This
889  * will prevent quals above us in the join tree that use those rels
890  * from being pushed down below this level. (It's okay for upper
891  * quals to be pushed down to the outer side, however.)
892  */
893  switch (j->jointype)
894  {
895  case JOIN_INNER:
896  leftjoinlist = deconstruct_recurse(root, j->larg,
897  below_outer_join,
898  &leftids, &left_inners,
899  &child_postponed_quals);
900  rightjoinlist = deconstruct_recurse(root, j->rarg,
901  below_outer_join,
902  &rightids, &right_inners,
903  &child_postponed_quals);
904  *qualscope = bms_union(leftids, rightids);
905  *inner_join_rels = *qualscope;
906  /* Inner join adds no restrictions for quals */
907  nonnullable_rels = NULL;
908  /* and it doesn't force anything to null, either */
909  nullable_rels = NULL;
910  break;
911  case JOIN_LEFT:
912  case JOIN_ANTI:
913  leftjoinlist = deconstruct_recurse(root, j->larg,
914  below_outer_join,
915  &leftids, &left_inners,
916  &child_postponed_quals);
917  rightjoinlist = deconstruct_recurse(root, j->rarg,
918  true,
919  &rightids, &right_inners,
920  &child_postponed_quals);
921  *qualscope = bms_union(leftids, rightids);
922  *inner_join_rels = bms_union(left_inners, right_inners);
923  nonnullable_rels = leftids;
924  nullable_rels = rightids;
925  break;
926  case JOIN_SEMI:
927  leftjoinlist = deconstruct_recurse(root, j->larg,
928  below_outer_join,
929  &leftids, &left_inners,
930  &child_postponed_quals);
931  rightjoinlist = deconstruct_recurse(root, j->rarg,
932  below_outer_join,
933  &rightids, &right_inners,
934  &child_postponed_quals);
935  *qualscope = bms_union(leftids, rightids);
936  *inner_join_rels = bms_union(left_inners, right_inners);
937  /* Semi join adds no restrictions for quals */
938  nonnullable_rels = NULL;
939 
940  /*
941  * Theoretically, a semijoin would null the RHS; but since the
942  * RHS can't be accessed above the join, this is immaterial
943  * and we needn't account for it.
944  */
945  nullable_rels = NULL;
946  break;
947  case JOIN_FULL:
948  leftjoinlist = deconstruct_recurse(root, j->larg,
949  true,
950  &leftids, &left_inners,
951  &child_postponed_quals);
952  rightjoinlist = deconstruct_recurse(root, j->rarg,
953  true,
954  &rightids, &right_inners,
955  &child_postponed_quals);
956  *qualscope = bms_union(leftids, rightids);
957  *inner_join_rels = bms_union(left_inners, right_inners);
958  /* each side is both outer and inner */
959  nonnullable_rels = *qualscope;
960  nullable_rels = *qualscope;
961  break;
962  default:
963  /* JOIN_RIGHT was eliminated during reduce_outer_joins() */
964  elog(ERROR, "unrecognized join type: %d",
965  (int) j->jointype);
966  nonnullable_rels = NULL; /* keep compiler quiet */
967  nullable_rels = NULL;
968  leftjoinlist = rightjoinlist = NIL;
969  break;
970  }
971 
972  /* Report all rels that will be nulled anywhere in the jointree */
974  nullable_rels);
975 
976  /*
977  * Try to process any quals postponed by children. If they need
978  * further postponement, add them to my output postponed_qual_list.
979  * Quals that can be processed now must be included in my_quals, so
980  * that they'll be handled properly in make_outerjoininfo.
981  */
982  my_quals = NIL;
983  foreach(l, child_postponed_quals)
984  {
985  PostponedQual *pq = (PostponedQual *) lfirst(l);
986 
987  if (bms_is_subset(pq->relids, *qualscope))
988  my_quals = lappend(my_quals, pq->qual);
989  else
990  {
991  /*
992  * We should not be postponing any quals past an outer join.
993  * If this Assert fires, pull_up_subqueries() messed up.
994  */
995  Assert(j->jointype == JOIN_INNER);
996  *postponed_qual_list = lappend(*postponed_qual_list, pq);
997  }
998  }
999  /* list_concat is nondestructive of its second argument */
1000  my_quals = list_concat(my_quals, (List *) j->quals);
1001 
1002  /*
1003  * For an OJ, form the SpecialJoinInfo now, because we need the OJ's
1004  * semantic scope (ojscope) to pass to distribute_qual_to_rels. But
1005  * we mustn't add it to join_info_list just yet, because we don't want
1006  * distribute_qual_to_rels to think it is an outer join below us.
1007  *
1008  * Semijoins are a bit of a hybrid: we build a SpecialJoinInfo, but we
1009  * want ojscope = NULL for distribute_qual_to_rels.
1010  */
1011  if (j->jointype != JOIN_INNER)
1012  {
1013  sjinfo = make_outerjoininfo(root,
1014  leftids, rightids,
1015  *inner_join_rels,
1016  j->jointype,
1017  my_quals);
1018  if (j->jointype == JOIN_SEMI)
1019  ojscope = NULL;
1020  else
1021  ojscope = bms_union(sjinfo->min_lefthand,
1022  sjinfo->min_righthand);
1023  }
1024  else
1025  {
1026  sjinfo = NULL;
1027  ojscope = NULL;
1028  }
1029 
1030  /* Process the JOIN's qual clauses */
1031  foreach(l, my_quals)
1032  {
1033  Node *qual = (Node *) lfirst(l);
1034 
1035  distribute_qual_to_rels(root, qual,
1036  false, below_outer_join, j->jointype,
1037  root->qual_security_level,
1038  *qualscope,
1039  ojscope, nonnullable_rels, NULL,
1040  postponed_qual_list);
1041  }
1042 
1043  /* Now we can add the SpecialJoinInfo to join_info_list */
1044  if (sjinfo)
1045  {
1046  root->join_info_list = lappend(root->join_info_list, sjinfo);
1047  /* Each time we do that, recheck placeholder eval levels */
1048  update_placeholder_eval_levels(root, sjinfo);
1049  }
1050 
1051  /*
1052  * Finally, compute the output joinlist. We fold subproblems together
1053  * except at a FULL JOIN or where join_collapse_limit would be
1054  * exceeded.
1055  */
1056  if (j->jointype == JOIN_FULL)
1057  {
1058  /* force the join order exactly at this node */
1059  joinlist = list_make1(list_make2(leftjoinlist, rightjoinlist));
1060  }
1061  else if (list_length(leftjoinlist) + list_length(rightjoinlist) <=
1063  {
1064  /* OK to combine subproblems */
1065  joinlist = list_concat(leftjoinlist, rightjoinlist);
1066  }
1067  else
1068  {
1069  /* can't combine, but needn't force join order above here */
1070  Node *leftpart,
1071  *rightpart;
1072 
1073  /* avoid creating useless 1-element sublists */
1074  if (list_length(leftjoinlist) == 1)
1075  leftpart = (Node *) linitial(leftjoinlist);
1076  else
1077  leftpart = (Node *) leftjoinlist;
1078  if (list_length(rightjoinlist) == 1)
1079  rightpart = (Node *) linitial(rightjoinlist);
1080  else
1081  rightpart = (Node *) rightjoinlist;
1082  joinlist = list_make2(leftpart, rightpart);
1083  }
1084  }
1085  else
1086  {
1087  elog(ERROR, "unrecognized node type: %d",
1088  (int) nodeTag(jtnode));
1089  joinlist = NIL; /* keep compiler quiet */
1090  }
1091  return joinlist;
1092 }
int remaining
Definition: informix.c:692
#define list_make2(x1, x2)
Definition: pg_list.h:140
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
List * join_info_list
Definition: relation.h:250
Relids min_righthand
Definition: relation.h:1920
static void process_security_barrier_quals(PlannerInfo *root, int rti, Relids qualscope, bool below_outer_join)
Definition: initsplan.c:1108
static void distribute_qual_to_rels(PlannerInfo *root, Node *clause, bool is_deduced, bool below_outer_join, JoinType jointype, Index security_level, Relids qualscope, Relids ojscope, Relids outerjoin_nonnullable, Relids deduced_nullable_relids, List **postponed_qual_list)
Definition: initsplan.c:1639
Definition: nodes.h:509
List * list_concat(List *list1, List *list2)
Definition: list.c:321
List * fromlist
Definition: primnodes.h:1471
Node * quals
Definition: primnodes.h:1472
Node * qual
Definition: initsplan.c:44
Node * larg
Definition: primnodes.h:1451
#define list_make1(x1)
Definition: pg_list.h:139
#define linitial(l)
Definition: pg_list.h:111
#define ERROR
Definition: elog.h:43
static SpecialJoinInfo * make_outerjoininfo(PlannerInfo *root, Relids left_rels, Relids right_rels, Relids inner_join_rels, JoinType jointype, List *clause)
Definition: initsplan.c:1174
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:308
Bitmapset * bms_make_singleton(int x)
Definition: bitmapset.c:179
List * lappend(List *list, void *datum)
Definition: list.c:128
int from_collapse_limit
Definition: initsplan.c:37
Node * quals
Definition: primnodes.h:1454
Node * rarg
Definition: primnodes.h:1452
JoinType jointype
Definition: primnodes.h:1449
#define Assert(condition)
Definition: c.h:664
#define lfirst(lc)
Definition: pg_list.h:106
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:218
static int list_length(const List *l)
Definition: pg_list.h:89
static List * deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, Relids *qualscope, Relids *inner_join_rels, List **postponed_qual_list)
Definition: initsplan.c:756
int join_collapse_limit
Definition: initsplan.c:38
Index qual_security_level
Definition: relation.h:294
#define nodeTag(nodeptr)
Definition: nodes.h:514
void update_placeholder_eval_levels(PlannerInfo *root, SpecialJoinInfo *new_sjinfo)
Definition: placeholder.c:265
Relids nullable_baserels
Definition: relation.h:204
Relids relids
Definition: initsplan.c:45
#define elog
Definition: elog.h:219
Definition: pg_list.h:45
Relids min_lefthand
Definition: relation.h:1919
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:755
static void distribute_qual_to_rels ( PlannerInfo root,
Node clause,
bool  is_deduced,
bool  below_outer_join,
JoinType  jointype,
Index  security_level,
Relids  qualscope,
Relids  ojscope,
Relids  outerjoin_nonnullable,
Relids  deduced_nullable_relids,
List **  postponed_qual_list 
)
static

Definition at line 1639 of file initsplan.c.

References add_vars_to_targetlist(), Assert, bms_copy(), bms_is_empty(), bms_is_subset(), bms_membership(), BMS_MULTIPLE, bms_overlap(), RestrictInfo::can_join, check_equivalence_delay(), check_mergejoinable(), check_outerjoin_delay(), check_redundant_nullability_qual(), contain_volatile_functions(), distribute_restrictinfo_to_rels(), elog, ERROR, PlannerInfo::full_join_clauses, get_relids_in_jointree(), PlannerInfo::hasLateralRTEs, PlannerInfo::hasPseudoConstantQuals, initialize_mergeclause_eclasses(), JOIN_FULL, JOIN_INNER, Query::jointree, lappend(), PlannerInfo::left_join_clauses, RestrictInfo::left_relids, list_free(), make_restrictinfo(), RestrictInfo::mergeopfamilies, palloc(), PlannerInfo::parse, process_equivalence(), pull_var_clause(), pull_varnos(), PVC_INCLUDE_PLACEHOLDERS, PVC_RECURSE_AGGREGATES, PVC_RECURSE_WINDOWFUNCS, PostponedQual::qual, PostponedQual::relids, PlannerInfo::right_join_clauses, and RestrictInfo::right_relids.

Referenced by deconstruct_recurse(), process_implied_equality(), and process_security_barrier_quals().

1649 {
1650  Relids relids;
1651  bool is_pushed_down;
1652  bool outerjoin_delayed;
1653  bool pseudoconstant = false;
1654  bool maybe_equivalence;
1655  bool maybe_outer_join;
1656  Relids nullable_relids;
1657  RestrictInfo *restrictinfo;
1658 
1659  /*
1660  * Retrieve all relids mentioned within the clause.
1661  */
1662  relids = pull_varnos(clause);
1663 
1664  /*
1665  * In ordinary SQL, a WHERE or JOIN/ON clause can't reference any rels
1666  * that aren't within its syntactic scope; however, if we pulled up a
1667  * LATERAL subquery then we might find such references in quals that have
1668  * been pulled up. We need to treat such quals as belonging to the join
1669  * level that includes every rel they reference. Although we could make
1670  * pull_up_subqueries() place such quals correctly to begin with, it's
1671  * easier to handle it here. When we find a clause that contains Vars
1672  * outside its syntactic scope, we add it to the postponed-quals list, and
1673  * process it once we've recursed back up to the appropriate join level.
1674  */
1675  if (!bms_is_subset(relids, qualscope))
1676  {
1677  PostponedQual *pq = (PostponedQual *) palloc(sizeof(PostponedQual));
1678 
1679  Assert(root->hasLateralRTEs); /* shouldn't happen otherwise */
1680  Assert(jointype == JOIN_INNER); /* mustn't postpone past outer join */
1681  Assert(!is_deduced); /* shouldn't be deduced, either */
1682  pq->qual = clause;
1683  pq->relids = relids;
1684  *postponed_qual_list = lappend(*postponed_qual_list, pq);
1685  return;
1686  }
1687 
1688  /*
1689  * If it's an outer-join clause, also check that relids is a subset of
1690  * ojscope. (This should not fail if the syntactic scope check passed.)
1691  */
1692  if (ojscope && !bms_is_subset(relids, ojscope))
1693  elog(ERROR, "JOIN qualification cannot refer to other relations");
1694 
1695  /*
1696  * If the clause is variable-free, our normal heuristic for pushing it
1697  * down to just the mentioned rels doesn't work, because there are none.
1698  *
1699  * If the clause is an outer-join clause, we must force it to the OJ's
1700  * semantic level to preserve semantics.
1701  *
1702  * Otherwise, when the clause contains volatile functions, we force it to
1703  * be evaluated at its original syntactic level. This preserves the
1704  * expected semantics.
1705  *
1706  * When the clause contains no volatile functions either, it is actually a
1707  * pseudoconstant clause that will not change value during any one
1708  * execution of the plan, and hence can be used as a one-time qual in a
1709  * gating Result plan node. We put such a clause into the regular
1710  * RestrictInfo lists for the moment, but eventually createplan.c will
1711  * pull it out and make a gating Result node immediately above whatever
1712  * plan node the pseudoconstant clause is assigned to. It's usually best
1713  * to put a gating node as high in the plan tree as possible. If we are
1714  * not below an outer join, we can actually push the pseudoconstant qual
1715  * all the way to the top of the tree. If we are below an outer join, we
1716  * leave the qual at its original syntactic level (we could push it up to
1717  * just below the outer join, but that seems more complex than it's
1718  * worth).
1719  */
1720  if (bms_is_empty(relids))
1721  {
1722  if (ojscope)
1723  {
1724  /* clause is attached to outer join, eval it there */
1725  relids = bms_copy(ojscope);
1726  /* mustn't use as gating qual, so don't mark pseudoconstant */
1727  }
1728  else
1729  {
1730  /* eval at original syntactic level */
1731  relids = bms_copy(qualscope);
1732  if (!contain_volatile_functions(clause))
1733  {
1734  /* mark as gating qual */
1735  pseudoconstant = true;
1736  /* tell createplan.c to check for gating quals */
1737  root->hasPseudoConstantQuals = true;
1738  /* if not below outer join, push it to top of tree */
1739  if (!below_outer_join)
1740  {
1741  relids =
1743  false);
1744  qualscope = bms_copy(relids);
1745  }
1746  }
1747  }
1748  }
1749 
1750  /*----------
1751  * Check to see if clause application must be delayed by outer-join
1752  * considerations.
1753  *
1754  * A word about is_pushed_down: we mark the qual as "pushed down" if
1755  * it is (potentially) applicable at a level different from its original
1756  * syntactic level. This flag is used to distinguish OUTER JOIN ON quals
1757  * from other quals pushed down to the same joinrel. The rules are:
1758  * WHERE quals and INNER JOIN quals: is_pushed_down = true.
1759  * Non-degenerate OUTER JOIN quals: is_pushed_down = false.
1760  * Degenerate OUTER JOIN quals: is_pushed_down = true.
1761  * A "degenerate" OUTER JOIN qual is one that doesn't mention the
1762  * non-nullable side, and hence can be pushed down into the nullable side
1763  * without changing the join result. It is correct to treat it as a
1764  * regular filter condition at the level where it is evaluated.
1765  *
1766  * Note: it is not immediately obvious that a simple boolean is enough
1767  * for this: if for some reason we were to attach a degenerate qual to
1768  * its original join level, it would need to be treated as an outer join
1769  * qual there. However, this cannot happen, because all the rels the
1770  * clause mentions must be in the outer join's min_righthand, therefore
1771  * the join it needs must be formed before the outer join; and we always
1772  * attach quals to the lowest level where they can be evaluated. But
1773  * if we were ever to re-introduce a mechanism for delaying evaluation
1774  * of "expensive" quals, this area would need work.
1775  *----------
1776  */
1777  if (is_deduced)
1778  {
1779  /*
1780  * If the qual came from implied-equality deduction, it should not be
1781  * outerjoin-delayed, else deducer blew it. But we can't check this
1782  * because the join_info_list may now contain OJs above where the qual
1783  * belongs. For the same reason, we must rely on caller to supply the
1784  * correct nullable_relids set.
1785  */
1786  Assert(!ojscope);
1787  is_pushed_down = true;
1788  outerjoin_delayed = false;
1789  nullable_relids = deduced_nullable_relids;
1790  /* Don't feed it back for more deductions */
1791  maybe_equivalence = false;
1792  maybe_outer_join = false;
1793  }
1794  else if (bms_overlap(relids, outerjoin_nonnullable))
1795  {
1796  /*
1797  * The qual is attached to an outer join and mentions (some of the)
1798  * rels on the nonnullable side, so it's not degenerate.
1799  *
1800  * We can't use such a clause to deduce equivalence (the left and
1801  * right sides might be unequal above the join because one of them has
1802  * gone to NULL) ... but we might be able to use it for more limited
1803  * deductions, if it is mergejoinable. So consider adding it to the
1804  * lists of set-aside outer-join clauses.
1805  */
1806  is_pushed_down = false;
1807  maybe_equivalence = false;
1808  maybe_outer_join = true;
1809 
1810  /* Check to see if must be delayed by lower outer join */
1811  outerjoin_delayed = check_outerjoin_delay(root,
1812  &relids,
1813  &nullable_relids,
1814  false);
1815 
1816  /*
1817  * Now force the qual to be evaluated exactly at the level of joining
1818  * corresponding to the outer join. We cannot let it get pushed down
1819  * into the nonnullable side, since then we'd produce no output rows,
1820  * rather than the intended single null-extended row, for any
1821  * nonnullable-side rows failing the qual.
1822  *
1823  * (Do this step after calling check_outerjoin_delay, because that
1824  * trashes relids.)
1825  */
1826  Assert(ojscope);
1827  relids = ojscope;
1828  Assert(!pseudoconstant);
1829  }
1830  else
1831  {
1832  /*
1833  * Normal qual clause or degenerate outer-join clause. Either way, we
1834  * can mark it as pushed-down.
1835  */
1836  is_pushed_down = true;
1837 
1838  /* Check to see if must be delayed by lower outer join */
1839  outerjoin_delayed = check_outerjoin_delay(root,
1840  &relids,
1841  &nullable_relids,
1842  true);
1843 
1844  if (outerjoin_delayed)
1845  {
1846  /* Should still be a subset of current scope ... */
1847  Assert(root->hasLateralRTEs || bms_is_subset(relids, qualscope));
1848  Assert(ojscope == NULL || bms_is_subset(relids, ojscope));
1849 
1850  /*
1851  * Because application of the qual will be delayed by outer join,
1852  * we mustn't assume its vars are equal everywhere.
1853  */
1854  maybe_equivalence = false;
1855 
1856  /*
1857  * It's possible that this is an IS NULL clause that's redundant
1858  * with a lower antijoin; if so we can just discard it. We need
1859  * not test in any of the other cases, because this will only be
1860  * possible for pushed-down, delayed clauses.
1861  */
1862  if (check_redundant_nullability_qual(root, clause))
1863  return;
1864  }
1865  else
1866  {
1867  /*
1868  * Qual is not delayed by any lower outer-join restriction, so we
1869  * can consider feeding it to the equivalence machinery. However,
1870  * if it's itself within an outer-join clause, treat it as though
1871  * it appeared below that outer join (note that we can only get
1872  * here when the clause references only nullable-side rels).
1873  */
1874  maybe_equivalence = true;
1875  if (outerjoin_nonnullable != NULL)
1876  below_outer_join = true;
1877  }
1878 
1879  /*
1880  * Since it doesn't mention the LHS, it's certainly not useful as a
1881  * set-aside OJ clause, even if it's in an OJ.
1882  */
1883  maybe_outer_join = false;
1884  }
1885 
1886  /*
1887  * Build the RestrictInfo node itself.
1888  */
1889  restrictinfo = make_restrictinfo((Expr *) clause,
1890  is_pushed_down,
1891  outerjoin_delayed,
1892  pseudoconstant,
1893  security_level,
1894  relids,
1895  outerjoin_nonnullable,
1896  nullable_relids);
1897 
1898  /*
1899  * If it's a join clause (either naturally, or because delayed by
1900  * outer-join rules), add vars used in the clause to targetlists of their
1901  * relations, so that they will be emitted by the plan nodes that scan
1902  * those relations (else they won't be available at the join node!).
1903  *
1904  * Note: if the clause gets absorbed into an EquivalenceClass then this
1905  * may be unnecessary, but for now we have to do it to cover the case
1906  * where the EC becomes ec_broken and we end up reinserting the original
1907  * clauses into the plan.
1908  */
1909  if (bms_membership(relids) == BMS_MULTIPLE)
1910  {
1911  List *vars = pull_var_clause(clause,
1915 
1916  add_vars_to_targetlist(root, vars, relids, false);
1917  list_free(vars);
1918  }
1919 
1920  /*
1921  * We check "mergejoinability" of every clause, not only join clauses,
1922  * because we want to know about equivalences between vars of the same
1923  * relation, or between vars and consts.
1924  */
1925  check_mergejoinable(restrictinfo);
1926 
1927  /*
1928  * If it is a true equivalence clause, send it to the EquivalenceClass
1929  * machinery. We do *not* attach it directly to any restriction or join
1930  * lists. The EC code will propagate it to the appropriate places later.
1931  *
1932  * If the clause has a mergejoinable operator and is not
1933  * outerjoin-delayed, yet isn't an equivalence because it is an outer-join
1934  * clause, the EC code may yet be able to do something with it. We add it
1935  * to appropriate lists for further consideration later. Specifically:
1936  *
1937  * If it is a left or right outer-join qualification that relates the two
1938  * sides of the outer join (no funny business like leftvar1 = leftvar2 +
1939  * rightvar), we add it to root->left_join_clauses or
1940  * root->right_join_clauses according to which side the nonnullable
1941  * variable appears on.
1942  *
1943  * If it is a full outer-join qualification, we add it to
1944  * root->full_join_clauses. (Ideally we'd discard cases that aren't
1945  * leftvar = rightvar, as we do for left/right joins, but this routine
1946  * doesn't have the info needed to do that; and the current usage of the
1947  * full_join_clauses list doesn't require that, so it's not currently
1948  * worth complicating this routine's API to make it possible.)
1949  *
1950  * If none of the above hold, pass it off to
1951  * distribute_restrictinfo_to_rels().
1952  *
1953  * In all cases, it's important to initialize the left_ec and right_ec
1954  * fields of a mergejoinable clause, so that all possibly mergejoinable
1955  * expressions have representations in EquivalenceClasses. If
1956  * process_equivalence is successful, it will take care of that;
1957  * otherwise, we have to call initialize_mergeclause_eclasses to do it.
1958  */
1959  if (restrictinfo->mergeopfamilies)
1960  {
1961  if (maybe_equivalence)
1962  {
1963  if (check_equivalence_delay(root, restrictinfo) &&
1964  process_equivalence(root, restrictinfo, below_outer_join))
1965  return;
1966  /* EC rejected it, so set left_ec/right_ec the hard way ... */
1967  initialize_mergeclause_eclasses(root, restrictinfo);
1968  /* ... and fall through to distribute_restrictinfo_to_rels */
1969  }
1970  else if (maybe_outer_join && restrictinfo->can_join)
1971  {
1972  /* we need to set up left_ec/right_ec the hard way */
1973  initialize_mergeclause_eclasses(root, restrictinfo);
1974  /* now see if it should go to any outer-join lists */
1975  if (bms_is_subset(restrictinfo->left_relids,
1976  outerjoin_nonnullable) &&
1977  !bms_overlap(restrictinfo->right_relids,
1978  outerjoin_nonnullable))
1979  {
1980  /* we have outervar = innervar */
1982  restrictinfo);
1983  return;
1984  }
1985  if (bms_is_subset(restrictinfo->right_relids,
1986  outerjoin_nonnullable) &&
1987  !bms_overlap(restrictinfo->left_relids,
1988  outerjoin_nonnullable))
1989  {
1990  /* we have innervar = outervar */
1992  restrictinfo);
1993  return;
1994  }
1995  if (jointype == JOIN_FULL)
1996  {
1997  /* FULL JOIN (above tests cannot match in this case) */
1999  restrictinfo);
2000  return;
2001  }
2002  /* nope, so fall through to distribute_restrictinfo_to_rels */
2003  }
2004  else
2005  {
2006  /* we still need to set up left_ec/right_ec */
2007  initialize_mergeclause_eclasses(root, restrictinfo);
2008  }
2009  }
2010 
2011  /* No EC special case applies, so push it into the clause lists */
2012  distribute_restrictinfo_to_rels(root, restrictinfo);
2013 }
static bool check_outerjoin_delay(PlannerInfo *root, Relids *relids_p, Relids *nullable_relids_p, bool is_pushed_down)
Definition: initsplan.c:2066
Query * parse
Definition: relation.h:155
Bitmapset * bms_copy(const Bitmapset *a)
Definition: bitmapset.c:111
#define PVC_RECURSE_AGGREGATES
Definition: var.h:21
void initialize_mergeclause_eclasses(PlannerInfo *root, RestrictInfo *restrictinfo)
Definition: pathkeys.c:919
RestrictInfo * make_restrictinfo(Expr *clause, bool is_pushed_down, bool outerjoin_delayed, bool pseudoconstant, Index security_level, Relids required_relids, Relids outer_relids, Relids nullable_relids)
Definition: restrictinfo.c:57
FromExpr * jointree
Definition: parsenodes.h:136
Definition: nodes.h:509
Relids left_relids
Definition: relation.h:1774
List * pull_var_clause(Node *node, int flags)
Definition: var.c:535
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:957
List * mergeopfamilies
Definition: relation.h:1792
Node * qual
Definition: initsplan.c:44
void add_vars_to_targetlist(PlannerInfo *root, List *vars, Relids where_needed, bool create_new_ph)
Definition: initsplan.c:198
#define PVC_INCLUDE_PLACEHOLDERS
Definition: var.h:24
void distribute_restrictinfo_to_rels(PlannerInfo *root, RestrictInfo *restrictinfo)
Definition: initsplan.c:2223
#define ERROR
Definition: elog.h:43
bool hasLateralRTEs
Definition: relation.h:300
bool can_join
Definition: relation.h:1753
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:308
Relids get_relids_in_jointree(Node *jtnode, bool include_joins)
List * left_join_clauses
Definition: relation.h:239
List * full_join_clauses
Definition: relation.h:247
#define PVC_RECURSE_WINDOWFUNCS
Definition: var.h:23
Relids pull_varnos(Node *node)
Definition: var.c:95
List * lappend(List *list, void *datum)
Definition: list.c:128
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:663
BMS_Membership bms_membership(const Bitmapset *a)
Definition: bitmapset.c:634
bool hasPseudoConstantQuals
Definition: relation.h:303
Relids right_relids
Definition: relation.h:1775
bool process_equivalence(PlannerInfo *root, RestrictInfo *restrictinfo, bool below_outer_join)
Definition: equivclass.c:107
static bool check_redundant_nullability_qual(PlannerInfo *root, Node *clause)
Definition: initsplan.c:2185
#define Assert(condition)
Definition: c.h:664
static bool check_equivalence_delay(PlannerInfo *root, RestrictInfo *restrictinfo)
Definition: initsplan.c:2150
static void check_mergejoinable(RestrictInfo *restrictinfo)
Definition: initsplan.c:2599
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:443
void * palloc(Size size)
Definition: mcxt.c:848
void list_free(List *list)
Definition: list.c:1133
Relids relids
Definition: initsplan.c:45
List * right_join_clauses
Definition: relation.h:243
#define elog
Definition: elog.h:219
Definition: regcomp.c:224
Definition: pg_list.h:45
void distribute_restrictinfo_to_rels ( PlannerInfo root,
RestrictInfo restrictinfo 
)

Definition at line 2223 of file initsplan.c.

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

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

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

Definition at line 320 of file initsplan.c.

References add_vars_to_targetlist(), Assert, bms_make_singleton(), copyObject, RangeTblEntry::functions, IncrementVarSublevelsUp(), IsA, lappend(), RangeTblEntry::lateral, RelOptInfo::lateral_vars, lfirst, list_free(), NIL, PlaceHolderVar::phexpr, PlaceHolderVar::phlevelsup, preprocess_phv_expression(), pull_vars_of_level(), RTE_FUNCTION, RTE_RELATION, RTE_SUBQUERY, RTE_TABLEFUNC, RTE_VALUES, RangeTblEntry::rtekind, PlannerInfo::simple_rte_array, RangeTblEntry::subquery, RangeTblEntry::tablefunc, RangeTblEntry::tablesample, RangeTblEntry::values_lists, and Var::varlevelsup.

Referenced by find_lateral_references().

321 {
322  RangeTblEntry *rte = root->simple_rte_array[rtindex];
323  List *vars;
324  List *newvars;
325  Relids where_needed;
326  ListCell *lc;
327 
328  /* No cross-references are possible if it's not LATERAL */
329  if (!rte->lateral)
330  return;
331 
332  /* Fetch the appropriate variables */
333  if (rte->rtekind == RTE_RELATION)
334  vars = pull_vars_of_level((Node *) rte->tablesample, 0);
335  else if (rte->rtekind == RTE_SUBQUERY)
336  vars = pull_vars_of_level((Node *) rte->subquery, 1);
337  else if (rte->rtekind == RTE_FUNCTION)
338  vars = pull_vars_of_level((Node *) rte->functions, 0);
339  else if (rte->rtekind == RTE_TABLEFUNC)
340  vars = pull_vars_of_level((Node *) rte->tablefunc, 0);
341  else if (rte->rtekind == RTE_VALUES)
342  vars = pull_vars_of_level((Node *) rte->values_lists, 0);
343  else
344  {
345  Assert(false);
346  return; /* keep compiler quiet */
347  }
348 
349  if (vars == NIL)
350  return; /* nothing to do */
351 
352  /* Copy each Var (or PlaceHolderVar) and adjust it to match our level */
353  newvars = NIL;
354  foreach(lc, vars)
355  {
356  Node *node = (Node *) lfirst(lc);
357 
358  node = copyObject(node);
359  if (IsA(node, Var))
360  {
361  Var *var = (Var *) node;
362 
363  /* Adjustment is easy since it's just one node */
364  var->varlevelsup = 0;
365  }
366  else if (IsA(node, PlaceHolderVar))
367  {
368  PlaceHolderVar *phv = (PlaceHolderVar *) node;
369  int levelsup = phv->phlevelsup;
370 
371  /* Have to work harder to adjust the contained expression too */
372  if (levelsup != 0)
373  IncrementVarSublevelsUp(node, -levelsup, 0);
374 
375  /*
376  * If we pulled the PHV out of a subquery RTE, its expression
377  * needs to be preprocessed. subquery_planner() already did this
378  * for level-zero PHVs in function and values RTEs, though.
379  */
380  if (levelsup > 0)
381  phv->phexpr = preprocess_phv_expression(root, phv->phexpr);
382  }
383  else
384  Assert(false);
385  newvars = lappend(newvars, node);
386  }
387 
388  list_free(vars);
389 
390  /*
391  * We mark the Vars as being "needed" at the LATERAL RTE. This is a bit
392  * of a cheat: a more formal approach would be to mark each one as needed
393  * at the join of the LATERAL RTE with its source RTE. But it will work,
394  * and it's much less tedious than computing a separate where_needed for
395  * each Var.
396  */
397  where_needed = bms_make_singleton(rtindex);
398 
399  /*
400  * Push Vars into their source relations' targetlists, and PHVs into
401  * root->placeholder_list.
402  */
403  add_vars_to_targetlist(root, newvars, where_needed, true);
404 
405  /* Remember the lateral references for create_lateral_join_info */
406  brel->lateral_vars = newvars;
407 }
List * pull_vars_of_level(Node *node, int levelsup)
Definition: var.c:263
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
Expr * preprocess_phv_expression(PlannerInfo *root, Expr *expr)
Definition: planner.c:1013
Index varlevelsup
Definition: primnodes.h:173
void IncrementVarSublevelsUp(Node *node, int delta_sublevels_up, int min_sublevels_up)
Definition: rewriteManip.c:773
Definition: nodes.h:509
Definition: primnodes.h:163
List * values_lists
Definition: parsenodes.h:1010
void add_vars_to_targetlist(PlannerInfo *root, List *vars, Relids where_needed, bool create_new_ph)
Definition: initsplan.c:198
Expr * phexpr
Definition: relation.h:1852
TableFunc * tablefunc
Definition: parsenodes.h:1005
Bitmapset * bms_make_singleton(int x)
Definition: bitmapset.c:179
List * lappend(List *list, void *datum)
Definition: list.c:128
RangeTblEntry ** simple_rte_array
Definition: relation.h:188
#define Assert(condition)
Definition: c.h:664
#define lfirst(lc)
Definition: pg_list.h:106
List * functions
Definition: parsenodes.h:999
List * lateral_vars
Definition: relation.h:560
RTEKind rtekind
Definition: parsenodes.h:945
Query * subquery
Definition: parsenodes.h:968
Index phlevelsup
Definition: relation.h:1855
void list_free(List *list)
Definition: list.c:1133
#define copyObject(obj)
Definition: nodes.h:622
Definition: regcomp.c:224
Definition: pg_list.h:45
struct TableSampleClause * tablesample
Definition: parsenodes.h:963
void find_lateral_references ( PlannerInfo root)

Definition at line 272 of file initsplan.c.

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

Referenced by query_planner().

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

Definition at line 1174 of file initsplan.c.

References Assert, bms_add_members(), bms_copy(), bms_int_members(), bms_intersect(), bms_is_empty(), bms_is_member(), bms_is_subset(), bms_overlap(), bms_union(), compute_semijoin_info(), SpecialJoinInfo::delay_upper_joins, ereport, errcode(), errmsg(), ERROR, find_nonnullable_rels(), JOIN_ANTI, JOIN_FULL, PlannerInfo::join_info_list, JOIN_INNER, JOIN_RIGHT, JOIN_SEMI, SpecialJoinInfo::jointype, LCS_asString(), lfirst, SpecialJoinInfo::lhs_strict, makeNode, SpecialJoinInfo::min_lefthand, SpecialJoinInfo::min_righthand, PlannerInfo::parse, PlaceHolderInfo::ph_eval_at, PlaceHolderInfo::ph_var, PlaceHolderVar::phrels, PlannerInfo::placeholder_list, pull_varnos(), Query::rowMarks, RowMarkClause::rti, RowMarkClause::strength, SpecialJoinInfo::syn_lefthand, and SpecialJoinInfo::syn_righthand.

Referenced by deconstruct_recurse().

1178 {
1180  Relids clause_relids;
1181  Relids strict_relids;
1182  Relids min_lefthand;
1183  Relids min_righthand;
1184  ListCell *l;
1185 
1186  /*
1187  * We should not see RIGHT JOIN here because left/right were switched
1188  * earlier
1189  */
1190  Assert(jointype != JOIN_INNER);
1191  Assert(jointype != JOIN_RIGHT);
1192 
1193  /*
1194  * Presently the executor cannot support FOR [KEY] UPDATE/SHARE marking of
1195  * rels appearing on the nullable side of an outer join. (It's somewhat
1196  * unclear what that would mean, anyway: what should we mark when a result
1197  * row is generated from no element of the nullable relation?) So,
1198  * complain if any nullable rel is FOR [KEY] UPDATE/SHARE.
1199  *
1200  * You might be wondering why this test isn't made far upstream in the
1201  * parser. It's because the parser hasn't got enough info --- consider
1202  * FOR UPDATE applied to a view. Only after rewriting and flattening do
1203  * we know whether the view contains an outer join.
1204  *
1205  * We use the original RowMarkClause list here; the PlanRowMark list would
1206  * list everything.
1207  */
1208  foreach(l, root->parse->rowMarks)
1209  {
1210  RowMarkClause *rc = (RowMarkClause *) lfirst(l);
1211 
1212  if (bms_is_member(rc->rti, right_rels) ||
1213  (jointype == JOIN_FULL && bms_is_member(rc->rti, left_rels)))
1214  ereport(ERROR,
1215  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1216  /*------
1217  translator: %s is a SQL row locking clause such as FOR UPDATE */
1218  errmsg("%s cannot be applied to the nullable side of an outer join",
1219  LCS_asString(rc->strength))));
1220  }
1221 
1222  sjinfo->syn_lefthand = left_rels;
1223  sjinfo->syn_righthand = right_rels;
1224  sjinfo->jointype = jointype;
1225  /* this always starts out false */
1226  sjinfo->delay_upper_joins = false;
1227 
1228  compute_semijoin_info(sjinfo, clause);
1229 
1230  /* If it's a full join, no need to be very smart */
1231  if (jointype == JOIN_FULL)
1232  {
1233  sjinfo->min_lefthand = bms_copy(left_rels);
1234  sjinfo->min_righthand = bms_copy(right_rels);
1235  sjinfo->lhs_strict = false; /* don't care about this */
1236  return sjinfo;
1237  }
1238 
1239  /*
1240  * Retrieve all relids mentioned within the join clause.
1241  */
1242  clause_relids = pull_varnos((Node *) clause);
1243 
1244  /*
1245  * For which relids is the clause strict, ie, it cannot succeed if the
1246  * rel's columns are all NULL?
1247  */
1248  strict_relids = find_nonnullable_rels((Node *) clause);
1249 
1250  /* Remember whether the clause is strict for any LHS relations */
1251  sjinfo->lhs_strict = bms_overlap(strict_relids, left_rels);
1252 
1253  /*
1254  * Required LHS always includes the LHS rels mentioned in the clause. We
1255  * may have to add more rels based on lower outer joins; see below.
1256  */
1257  min_lefthand = bms_intersect(clause_relids, left_rels);
1258 
1259  /*
1260  * Similarly for required RHS. But here, we must also include any lower
1261  * inner joins, to ensure we don't try to commute with any of them.
1262  */
1263  min_righthand = bms_int_members(bms_union(clause_relids, inner_join_rels),
1264  right_rels);
1265 
1266  /*
1267  * Now check previous outer joins for ordering restrictions.
1268  */
1269  foreach(l, root->join_info_list)
1270  {
1271  SpecialJoinInfo *otherinfo = (SpecialJoinInfo *) lfirst(l);
1272 
1273  /*
1274  * A full join is an optimization barrier: we can't associate into or
1275  * out of it. Hence, if it overlaps either LHS or RHS of the current
1276  * rel, expand that side's min relset to cover the whole full join.
1277  */
1278  if (otherinfo->jointype == JOIN_FULL)
1279  {
1280  if (bms_overlap(left_rels, otherinfo->syn_lefthand) ||
1281  bms_overlap(left_rels, otherinfo->syn_righthand))
1282  {
1283  min_lefthand = bms_add_members(min_lefthand,
1284  otherinfo->syn_lefthand);
1285  min_lefthand = bms_add_members(min_lefthand,
1286  otherinfo->syn_righthand);
1287  }
1288  if (bms_overlap(right_rels, otherinfo->syn_lefthand) ||
1289  bms_overlap(right_rels, otherinfo->syn_righthand))
1290  {
1291  min_righthand = bms_add_members(min_righthand,
1292  otherinfo->syn_lefthand);
1293  min_righthand = bms_add_members(min_righthand,
1294  otherinfo->syn_righthand);
1295  }
1296  /* Needn't do anything else with the full join */
1297  continue;
1298  }
1299 
1300  /*
1301  * For a lower OJ in our LHS, if our join condition uses the lower
1302  * join's RHS and is not strict for that rel, we must preserve the
1303  * ordering of the two OJs, so add lower OJ's full syntactic relset to
1304  * min_lefthand. (We must use its full syntactic relset, not just its
1305  * min_lefthand + min_righthand. This is because there might be other
1306  * OJs below this one that this one can commute with, but we cannot
1307  * commute with them if we don't with this one.) Also, if the current
1308  * join is a semijoin or antijoin, we must preserve ordering
1309  * regardless of strictness.
1310  *
1311  * Note: I believe we have to insist on being strict for at least one
1312  * rel in the lower OJ's min_righthand, not its whole syn_righthand.
1313  */
1314  if (bms_overlap(left_rels, otherinfo->syn_righthand))
1315  {
1316  if (bms_overlap(clause_relids, otherinfo->syn_righthand) &&
1317  (jointype == JOIN_SEMI || jointype == JOIN_ANTI ||
1318  !bms_overlap(strict_relids, otherinfo->min_righthand)))
1319  {
1320  min_lefthand = bms_add_members(min_lefthand,
1321  otherinfo->syn_lefthand);
1322  min_lefthand = bms_add_members(min_lefthand,
1323  otherinfo->syn_righthand);
1324  }
1325  }
1326 
1327  /*
1328  * For a lower OJ in our RHS, if our join condition does not use the
1329  * lower join's RHS and the lower OJ's join condition is strict, we
1330  * can interchange the ordering of the two OJs; otherwise we must add
1331  * the lower OJ's full syntactic relset to min_righthand.
1332  *
1333  * Also, if our join condition does not use the lower join's LHS
1334  * either, force the ordering to be preserved. Otherwise we can end
1335  * up with SpecialJoinInfos with identical min_righthands, which can
1336  * confuse join_is_legal (see discussion in backend/optimizer/README).
1337  *
1338  * Also, we must preserve ordering anyway if either the current join
1339  * or the lower OJ is either a semijoin or an antijoin.
1340  *
1341  * Here, we have to consider that "our join condition" includes any
1342  * clauses that syntactically appeared above the lower OJ and below
1343  * ours; those are equivalent to degenerate clauses in our OJ and must
1344  * be treated as such. Such clauses obviously can't reference our
1345  * LHS, and they must be non-strict for the lower OJ's RHS (else
1346  * reduce_outer_joins would have reduced the lower OJ to a plain
1347  * join). Hence the other ways in which we handle clauses within our
1348  * join condition are not affected by them. The net effect is
1349  * therefore sufficiently represented by the delay_upper_joins flag
1350  * saved for us by check_outerjoin_delay.
1351  */
1352  if (bms_overlap(right_rels, otherinfo->syn_righthand))
1353  {
1354  if (bms_overlap(clause_relids, otherinfo->syn_righthand) ||
1355  !bms_overlap(clause_relids, otherinfo->min_lefthand) ||
1356  jointype == JOIN_SEMI ||
1357  jointype == JOIN_ANTI ||
1358  otherinfo->jointype == JOIN_SEMI ||
1359  otherinfo->jointype == JOIN_ANTI ||
1360  !otherinfo->lhs_strict || otherinfo->delay_upper_joins)
1361  {
1362  min_righthand = bms_add_members(min_righthand,
1363  otherinfo->syn_lefthand);
1364  min_righthand = bms_add_members(min_righthand,
1365  otherinfo->syn_righthand);
1366  }
1367  }
1368  }
1369 
1370  /*
1371  * Examine PlaceHolderVars. If a PHV is supposed to be evaluated within
1372  * this join's nullable side, then ensure that min_righthand contains the
1373  * full eval_at set of the PHV. This ensures that the PHV actually can be
1374  * evaluated within the RHS. Note that this works only because we should
1375  * already have determined the final eval_at level for any PHV
1376  * syntactically within this join.
1377  */
1378  foreach(l, root->placeholder_list)
1379  {
1380  PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(l);
1381  Relids ph_syn_level = phinfo->ph_var->phrels;
1382 
1383  /* Ignore placeholder if it didn't syntactically come from RHS */
1384  if (!bms_is_subset(ph_syn_level, right_rels))
1385  continue;
1386 
1387  /* Else, prevent join from being formed before we eval the PHV */
1388  min_righthand = bms_add_members(min_righthand, phinfo->ph_eval_at);
1389  }
1390 
1391  /*
1392  * If we found nothing to put in min_lefthand, punt and make it the full
1393  * LHS, to avoid having an empty min_lefthand which will confuse later
1394  * processing. (We don't try to be smart about such cases, just correct.)
1395  * Likewise for min_righthand.
1396  */
1397  if (bms_is_empty(min_lefthand))
1398  min_lefthand = bms_copy(left_rels);
1399  if (bms_is_empty(min_righthand))
1400  min_righthand = bms_copy(right_rels);
1401 
1402  /* Now they'd better be nonempty */
1403  Assert(!bms_is_empty(min_lefthand));
1404  Assert(!bms_is_empty(min_righthand));
1405  /* Shouldn't overlap either */
1406  Assert(!bms_overlap(min_lefthand, min_righthand));
1407 
1408  sjinfo->min_lefthand = min_lefthand;
1409  sjinfo->min_righthand = min_righthand;
1410 
1411  return sjinfo;
1412 }
Query * parse
Definition: relation.h:155
const char * LCS_asString(LockClauseStrength strength)
Definition: analyze.c:2581
Bitmapset * bms_copy(const Bitmapset *a)
Definition: bitmapset.c:111
Relids ph_eval_at
Definition: relation.h:2066
PlaceHolderVar * ph_var
Definition: relation.h:2065
List * join_info_list
Definition: relation.h:250
Relids min_righthand
Definition: relation.h:1920
Definition: nodes.h:509
int errcode(int sqlerrcode)
Definition: elog.c:575
List * rowMarks
Definition: parsenodes.h:161
Relids syn_lefthand
Definition: relation.h:1921
LockClauseStrength strength
Definition: parsenodes.h:1308
Relids syn_righthand
Definition: relation.h:1922
Relids phrels
Definition: relation.h:1853
#define ERROR
Definition: elog.h:43
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:308
Relids find_nonnullable_rels(Node *clause)
Definition: clauses.c:1626
#define ereport(elevel, rest)
Definition: elog.h:122
Relids pull_varnos(Node *node)
Definition: var.c:95
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:663
bool delay_upper_joins
Definition: relation.h:1925
Bitmapset * bms_intersect(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:252
#define makeNode(_type_)
Definition: nodes.h:557
#define Assert(condition)
Definition: c.h:664
#define lfirst(lc)
Definition: pg_list.h:106
JoinType jointype
Definition: relation.h:1923
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:218
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:443
int errmsg(const char *fmt,...)
Definition: elog.c:797
List * placeholder_list
Definition: relation.h:258
Bitmapset * bms_int_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:791
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:420
Relids min_lefthand
Definition: relation.h:1919
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:755
static void compute_semijoin_info(SpecialJoinInfo *sjinfo, List *clause)
Definition: initsplan.c:1422
void match_foreign_keys_to_quals ( PlannerInfo root)

Definition at line 2430 of file initsplan.c.

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

Referenced by query_planner().

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

Definition at line 2307 of file initsplan.c.

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

Referenced by generate_base_implied_equalities_const(), and generate_base_implied_equalities_no_const().

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

Definition at line 1108 of file initsplan.c.

References Assert, distribute_qual_to_rels(), JOIN_INNER, lfirst, RangeTblEntry::securityQuals, and PlannerInfo::simple_rte_array.

Referenced by deconstruct_recurse().

1111 {
1112  RangeTblEntry *rte = root->simple_rte_array[rti];
1113  Index security_level = 0;
1114  ListCell *lc;
1115 
1116  /*
1117  * Each element of the securityQuals list has been preprocessed into an
1118  * implicitly-ANDed list of clauses. All the clauses in a given sublist
1119  * should get the same security level, but successive sublists get higher
1120  * levels.
1121  */
1122  foreach(lc, rte->securityQuals)
1123  {
1124  List *qualset = (List *) lfirst(lc);
1125  ListCell *lc2;
1126 
1127  foreach(lc2, qualset)
1128  {
1129  Node *qual = (Node *) lfirst(lc2);
1130 
1131  /*
1132  * We cheat to the extent of passing ojscope = qualscope rather
1133  * than its more logical value of NULL. The only effect this has
1134  * is to force a Var-free qual to be evaluated at the rel rather
1135  * than being pushed up to top of tree, which we don't want.
1136  */
1137  distribute_qual_to_rels(root, qual,
1138  false,
1139  below_outer_join,
1140  JOIN_INNER,
1141  security_level,
1142  qualscope,
1143  qualscope,
1144  NULL,
1145  NULL,
1146  NULL);
1147  }
1148  security_level++;
1149  }
1150 
1151  /* Assert that qual_security_level is higher than anything we just used */
1152  Assert(security_level <= root->qual_security_level);
1153 }
static void distribute_qual_to_rels(PlannerInfo *root, Node *clause, bool is_deduced, bool below_outer_join, JoinType jointype, Index security_level, Relids qualscope, Relids ojscope, Relids outerjoin_nonnullable, Relids deduced_nullable_relids, List **postponed_qual_list)
Definition: initsplan.c:1639
List * securityQuals
Definition: parsenodes.h:1058
Definition: nodes.h:509
RangeTblEntry ** simple_rte_array
Definition: relation.h:188
unsigned int Index
Definition: c.h:359
#define Assert(condition)
Definition: c.h:664
#define lfirst(lc)
Definition: pg_list.h:106
Definition: pg_list.h:45

Variable Documentation

int from_collapse_limit

Definition at line 37 of file initsplan.c.

Referenced by deconstruct_recurse().

int join_collapse_limit

Definition at line 38 of file initsplan.c.

Referenced by deconstruct_recurse().