PostgreSQL Source Code  git master
restrictinfo.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * restrictinfo.c
4  * RestrictInfo node manipulation routines.
5  *
6  * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/backend/optimizer/util/restrictinfo.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16 
17 #include "nodes/makefuncs.h"
18 #include "nodes/nodeFuncs.h"
19 #include "optimizer/clauses.h"
20 #include "optimizer/optimizer.h"
21 #include "optimizer/restrictinfo.h"
22 
23 
25  Expr *clause,
26  Expr *orclause,
27  bool is_pushed_down,
28  bool outerjoin_delayed,
29  bool pseudoconstant,
30  Index security_level,
31  Relids required_relids,
32  Relids outer_relids,
33  Relids nullable_relids);
35  Expr *clause,
36  bool is_pushed_down,
37  bool outerjoin_delayed,
38  bool pseudoconstant,
39  Index security_level,
40  Relids required_relids,
41  Relids outer_relids,
42  Relids nullable_relids);
43 
44 
45 /*
46  * make_restrictinfo
47  *
48  * Build a RestrictInfo node containing the given subexpression.
49  *
50  * The is_pushed_down, outerjoin_delayed, and pseudoconstant flags for the
51  * RestrictInfo must be supplied by the caller, as well as the correct values
52  * for security_level, outer_relids, and nullable_relids.
53  * required_relids can be NULL, in which case it defaults to the actual clause
54  * contents (i.e., clause_relids).
55  *
56  * We initialize fields that depend only on the given subexpression, leaving
57  * others that depend on context (or may never be needed at all) to be filled
58  * later.
59  */
62  Expr *clause,
63  bool is_pushed_down,
64  bool outerjoin_delayed,
65  bool pseudoconstant,
66  Index security_level,
67  Relids required_relids,
68  Relids outer_relids,
69  Relids nullable_relids)
70 {
71  /*
72  * If it's an OR clause, build a modified copy with RestrictInfos inserted
73  * above each subclause of the top-level AND/OR structure.
74  */
75  if (is_orclause(clause))
76  return (RestrictInfo *) make_sub_restrictinfos(root,
77  clause,
78  is_pushed_down,
79  outerjoin_delayed,
80  pseudoconstant,
81  security_level,
82  required_relids,
83  outer_relids,
84  nullable_relids);
85 
86  /* Shouldn't be an AND clause, else AND/OR flattening messed up */
87  Assert(!is_andclause(clause));
88 
89  return make_restrictinfo_internal(root,
90  clause,
91  NULL,
92  is_pushed_down,
93  outerjoin_delayed,
94  pseudoconstant,
95  security_level,
96  required_relids,
97  outer_relids,
98  nullable_relids);
99 }
100 
101 /*
102  * make_restrictinfo_internal
103  *
104  * Common code for the main entry points and the recursive cases.
105  */
106 static RestrictInfo *
108  Expr *clause,
109  Expr *orclause,
110  bool is_pushed_down,
111  bool outerjoin_delayed,
112  bool pseudoconstant,
113  Index security_level,
114  Relids required_relids,
115  Relids outer_relids,
116  Relids nullable_relids)
117 {
118  RestrictInfo *restrictinfo = makeNode(RestrictInfo);
119 
120  restrictinfo->clause = clause;
121  restrictinfo->orclause = orclause;
122  restrictinfo->is_pushed_down = is_pushed_down;
123  restrictinfo->outerjoin_delayed = outerjoin_delayed;
124  restrictinfo->pseudoconstant = pseudoconstant;
125  restrictinfo->can_join = false; /* may get set below */
126  restrictinfo->security_level = security_level;
127  restrictinfo->outer_relids = outer_relids;
128  restrictinfo->nullable_relids = nullable_relids;
129 
130  /*
131  * If it's potentially delayable by lower-level security quals, figure out
132  * whether it's leakproof. We can skip testing this for level-zero quals,
133  * since they would never get delayed on security grounds anyway.
134  */
135  if (security_level > 0)
136  restrictinfo->leakproof = !contain_leaked_vars((Node *) clause);
137  else
138  restrictinfo->leakproof = false; /* really, "don't know" */
139 
140  /*
141  * Mark volatility as unknown. The contain_volatile_functions function
142  * will determine if there are any volatile functions when called for the
143  * first time with this RestrictInfo.
144  */
145  restrictinfo->has_volatile = VOLATILITY_UNKNOWN;
146 
147  /*
148  * If it's a binary opclause, set up left/right relids info. In any case
149  * set up the total clause relids info.
150  */
151  if (is_opclause(clause) && list_length(((OpExpr *) clause)->args) == 2)
152  {
153  restrictinfo->left_relids = pull_varnos(root, get_leftop(clause));
154  restrictinfo->right_relids = pull_varnos(root, get_rightop(clause));
155 
156  restrictinfo->clause_relids = bms_union(restrictinfo->left_relids,
157  restrictinfo->right_relids);
158 
159  /*
160  * Does it look like a normal join clause, i.e., a binary operator
161  * relating expressions that come from distinct relations? If so we
162  * might be able to use it in a join algorithm. Note that this is a
163  * purely syntactic test that is made regardless of context.
164  */
165  if (!bms_is_empty(restrictinfo->left_relids) &&
166  !bms_is_empty(restrictinfo->right_relids) &&
167  !bms_overlap(restrictinfo->left_relids,
168  restrictinfo->right_relids))
169  {
170  restrictinfo->can_join = true;
171  /* pseudoconstant should certainly not be true */
172  Assert(!restrictinfo->pseudoconstant);
173  }
174  }
175  else
176  {
177  /* Not a binary opclause, so mark left/right relid sets as empty */
178  restrictinfo->left_relids = NULL;
179  restrictinfo->right_relids = NULL;
180  /* and get the total relid set the hard way */
181  restrictinfo->clause_relids = pull_varnos(root, (Node *) clause);
182  }
183 
184  /* required_relids defaults to clause_relids */
185  if (required_relids != NULL)
186  restrictinfo->required_relids = required_relids;
187  else
188  restrictinfo->required_relids = restrictinfo->clause_relids;
189 
190  /*
191  * Fill in all the cacheable fields with "not yet set" markers. None of
192  * these will be computed until/unless needed. Note in particular that we
193  * don't mark a binary opclause as mergejoinable or hashjoinable here;
194  * that happens only if it appears in the right context (top level of a
195  * joinclause list).
196  */
197  restrictinfo->parent_ec = NULL;
198 
199  restrictinfo->eval_cost.startup = -1;
200  restrictinfo->norm_selec = -1;
201  restrictinfo->outer_selec = -1;
202 
203  restrictinfo->mergeopfamilies = NIL;
204 
205  restrictinfo->left_ec = NULL;
206  restrictinfo->right_ec = NULL;
207  restrictinfo->left_em = NULL;
208  restrictinfo->right_em = NULL;
209  restrictinfo->scansel_cache = NIL;
210 
211  restrictinfo->outer_is_left = false;
212 
213  restrictinfo->hashjoinoperator = InvalidOid;
214 
215  restrictinfo->left_bucketsize = -1;
216  restrictinfo->right_bucketsize = -1;
217  restrictinfo->left_mcvfreq = -1;
218  restrictinfo->right_mcvfreq = -1;
219 
220  restrictinfo->left_hasheqoperator = InvalidOid;
221  restrictinfo->right_hasheqoperator = InvalidOid;
222 
223  return restrictinfo;
224 }
225 
226 /*
227  * Recursively insert sub-RestrictInfo nodes into a boolean expression.
228  *
229  * We put RestrictInfos above simple (non-AND/OR) clauses and above
230  * sub-OR clauses, but not above sub-AND clauses, because there's no need.
231  * This may seem odd but it is closely related to the fact that we use
232  * implicit-AND lists at top level of RestrictInfo lists. Only ORs and
233  * simple clauses are valid RestrictInfos.
234  *
235  * The same is_pushed_down, outerjoin_delayed, and pseudoconstant flag
236  * values can be applied to all RestrictInfo nodes in the result. Likewise
237  * for security_level, outer_relids, and nullable_relids.
238  *
239  * The given required_relids are attached to our top-level output,
240  * but any OR-clause constituents are allowed to default to just the
241  * contained rels.
242  */
243 static Expr *
245  Expr *clause,
246  bool is_pushed_down,
247  bool outerjoin_delayed,
248  bool pseudoconstant,
249  Index security_level,
250  Relids required_relids,
251  Relids outer_relids,
252  Relids nullable_relids)
253 {
254  if (is_orclause(clause))
255  {
256  List *orlist = NIL;
257  ListCell *temp;
258 
259  foreach(temp, ((BoolExpr *) clause)->args)
260  orlist = lappend(orlist,
262  lfirst(temp),
263  is_pushed_down,
264  outerjoin_delayed,
265  pseudoconstant,
266  security_level,
267  NULL,
268  outer_relids,
269  nullable_relids));
270  return (Expr *) make_restrictinfo_internal(root,
271  clause,
272  make_orclause(orlist),
273  is_pushed_down,
274  outerjoin_delayed,
275  pseudoconstant,
276  security_level,
277  required_relids,
278  outer_relids,
279  nullable_relids);
280  }
281  else if (is_andclause(clause))
282  {
283  List *andlist = NIL;
284  ListCell *temp;
285 
286  foreach(temp, ((BoolExpr *) clause)->args)
287  andlist = lappend(andlist,
289  lfirst(temp),
290  is_pushed_down,
291  outerjoin_delayed,
292  pseudoconstant,
293  security_level,
294  required_relids,
295  outer_relids,
296  nullable_relids));
297  return make_andclause(andlist);
298  }
299  else
300  return (Expr *) make_restrictinfo_internal(root,
301  clause,
302  NULL,
303  is_pushed_down,
304  outerjoin_delayed,
305  pseudoconstant,
306  security_level,
307  required_relids,
308  outer_relids,
309  nullable_relids);
310 }
311 
312 /*
313  * commute_restrictinfo
314  *
315  * Given a RestrictInfo containing a binary opclause, produce a RestrictInfo
316  * representing the commutation of that clause. The caller must pass the
317  * OID of the commutator operator (which it's presumably looked up, else
318  * it would not know this is valid).
319  *
320  * Beware that the result shares sub-structure with the given RestrictInfo.
321  * That's okay for the intended usage with derived index quals, but might
322  * be hazardous if the source is subject to change. Also notice that we
323  * assume without checking that the commutator op is a member of the same
324  * btree and hash opclasses as the original op.
325  */
326 RestrictInfo *
328 {
329  RestrictInfo *result;
330  OpExpr *newclause;
331  OpExpr *clause = castNode(OpExpr, rinfo->clause);
332 
333  Assert(list_length(clause->args) == 2);
334 
335  /* flat-copy all the fields of clause ... */
336  newclause = makeNode(OpExpr);
337  memcpy(newclause, clause, sizeof(OpExpr));
338 
339  /* ... and adjust those we need to change to commute it */
340  newclause->opno = comm_op;
341  newclause->opfuncid = InvalidOid;
342  newclause->args = list_make2(lsecond(clause->args),
343  linitial(clause->args));
344 
345  /* likewise, flat-copy all the fields of rinfo ... */
346  result = makeNode(RestrictInfo);
347  memcpy(result, rinfo, sizeof(RestrictInfo));
348 
349  /*
350  * ... and adjust those we need to change. Note in particular that we can
351  * preserve any cached selectivity or cost estimates, since those ought to
352  * be the same for the new clause. Likewise we can keep the source's
353  * parent_ec.
354  */
355  result->clause = (Expr *) newclause;
356  result->left_relids = rinfo->right_relids;
357  result->right_relids = rinfo->left_relids;
358  Assert(result->orclause == NULL);
359  result->left_ec = rinfo->right_ec;
360  result->right_ec = rinfo->left_ec;
361  result->left_em = rinfo->right_em;
362  result->right_em = rinfo->left_em;
363  result->scansel_cache = NIL; /* not worth updating this */
364  if (rinfo->hashjoinoperator == clause->opno)
365  result->hashjoinoperator = comm_op;
366  else
367  result->hashjoinoperator = InvalidOid;
368  result->left_bucketsize = rinfo->right_bucketsize;
369  result->right_bucketsize = rinfo->left_bucketsize;
370  result->left_mcvfreq = rinfo->right_mcvfreq;
371  result->right_mcvfreq = rinfo->left_mcvfreq;
374 
375  return result;
376 }
377 
378 /*
379  * restriction_is_or_clause
380  *
381  * Returns t iff the restrictinfo node contains an 'or' clause.
382  */
383 bool
385 {
386  if (restrictinfo->orclause != NULL)
387  return true;
388  else
389  return false;
390 }
391 
392 /*
393  * restriction_is_securely_promotable
394  *
395  * Returns true if it's okay to evaluate this clause "early", that is before
396  * other restriction clauses attached to the specified relation.
397  */
398 bool
400  RelOptInfo *rel)
401 {
402  /*
403  * It's okay if there are no baserestrictinfo clauses for the rel that
404  * would need to go before this one, *or* if this one is leakproof.
405  */
406  if (restrictinfo->security_level <= rel->baserestrict_min_security ||
407  restrictinfo->leakproof)
408  return true;
409  else
410  return false;
411 }
412 
413 /*
414  * get_actual_clauses
415  *
416  * Returns a list containing the bare clauses from 'restrictinfo_list'.
417  *
418  * This is only to be used in cases where none of the RestrictInfos can
419  * be pseudoconstant clauses (for instance, it's OK on indexqual lists).
420  */
421 List *
422 get_actual_clauses(List *restrictinfo_list)
423 {
424  List *result = NIL;
425  ListCell *l;
426 
427  foreach(l, restrictinfo_list)
428  {
430 
431  Assert(!rinfo->pseudoconstant);
432 
433  result = lappend(result, rinfo->clause);
434  }
435  return result;
436 }
437 
438 /*
439  * extract_actual_clauses
440  *
441  * Extract bare clauses from 'restrictinfo_list', returning either the
442  * regular ones or the pseudoconstant ones per 'pseudoconstant'.
443  */
444 List *
445 extract_actual_clauses(List *restrictinfo_list,
446  bool pseudoconstant)
447 {
448  List *result = NIL;
449  ListCell *l;
450 
451  foreach(l, restrictinfo_list)
452  {
454 
455  if (rinfo->pseudoconstant == pseudoconstant)
456  result = lappend(result, rinfo->clause);
457  }
458  return result;
459 }
460 
461 /*
462  * extract_actual_join_clauses
463  *
464  * Extract bare clauses from 'restrictinfo_list', separating those that
465  * semantically match the join level from those that were pushed down.
466  * Pseudoconstant clauses are excluded from the results.
467  *
468  * This is only used at outer joins, since for plain joins we don't care
469  * about pushed-down-ness.
470  */
471 void
473  Relids joinrelids,
474  List **joinquals,
475  List **otherquals)
476 {
477  ListCell *l;
478 
479  *joinquals = NIL;
480  *otherquals = NIL;
481 
482  foreach(l, restrictinfo_list)
483  {
485 
486  if (RINFO_IS_PUSHED_DOWN(rinfo, joinrelids))
487  {
488  if (!rinfo->pseudoconstant)
489  *otherquals = lappend(*otherquals, rinfo->clause);
490  }
491  else
492  {
493  /* joinquals shouldn't have been marked pseudoconstant */
494  Assert(!rinfo->pseudoconstant);
495  *joinquals = lappend(*joinquals, rinfo->clause);
496  }
497  }
498 }
499 
500 
501 /*
502  * join_clause_is_movable_to
503  * Test whether a join clause is a safe candidate for parameterization
504  * of a scan on the specified base relation.
505  *
506  * A movable join clause is one that can safely be evaluated at a rel below
507  * its normal semantic level (ie, its required_relids), if the values of
508  * variables that it would need from other rels are provided.
509  *
510  * We insist that the clause actually reference the target relation; this
511  * prevents undesirable movement of degenerate join clauses, and ensures
512  * that there is a unique place that a clause can be moved down to.
513  *
514  * We cannot move an outer-join clause into the non-nullable side of its
515  * outer join, as that would change the results (rows would be suppressed
516  * rather than being null-extended).
517  *
518  * Also there must not be an outer join below the clause that would null the
519  * Vars coming from the target relation. Otherwise the clause might give
520  * results different from what it would give at its normal semantic level.
521  *
522  * Also, the join clause must not use any relations that have LATERAL
523  * references to the target relation, since we could not put such rels on
524  * the outer side of a nestloop with the target relation.
525  */
526 bool
528 {
529  /* Clause must physically reference target rel */
530  if (!bms_is_member(baserel->relid, rinfo->clause_relids))
531  return false;
532 
533  /* Cannot move an outer-join clause into the join's outer side */
534  if (bms_is_member(baserel->relid, rinfo->outer_relids))
535  return false;
536 
537  /* Target rel must not be nullable below the clause */
538  if (bms_is_member(baserel->relid, rinfo->nullable_relids))
539  return false;
540 
541  /* Clause must not use any rels with LATERAL references to this rel */
542  if (bms_overlap(baserel->lateral_referencers, rinfo->clause_relids))
543  return false;
544 
545  return true;
546 }
547 
548 /*
549  * join_clause_is_movable_into
550  * Test whether a join clause is movable and can be evaluated within
551  * the current join context.
552  *
553  * currentrelids: the relids of the proposed evaluation location
554  * current_and_outer: the union of currentrelids and the required_outer
555  * relids (parameterization's outer relations)
556  *
557  * The API would be a bit clearer if we passed the current relids and the
558  * outer relids separately and did bms_union internally; but since most
559  * callers need to apply this function to multiple clauses, we make the
560  * caller perform the union.
561  *
562  * Obviously, the clause must only refer to Vars available from the current
563  * relation plus the outer rels. We also check that it does reference at
564  * least one current Var, ensuring that the clause will be pushed down to
565  * a unique place in a parameterized join tree. And we check that we're
566  * not pushing the clause into its outer-join outer side, nor down into
567  * a lower outer join's inner side.
568  *
569  * The check about pushing a clause down into a lower outer join's inner side
570  * is only approximate; it sometimes returns "false" when actually it would
571  * be safe to use the clause here because we're still above the outer join
572  * in question. This is okay as long as the answers at different join levels
573  * are consistent: it just means we might sometimes fail to push a clause as
574  * far down as it could safely be pushed. It's unclear whether it would be
575  * worthwhile to do this more precisely. (But if it's ever fixed to be
576  * exactly accurate, there's an Assert in get_joinrel_parampathinfo() that
577  * should be re-enabled.)
578  *
579  * There's no check here equivalent to join_clause_is_movable_to's test on
580  * lateral_referencers. We assume the caller wouldn't be inquiring unless
581  * it'd verified that the proposed outer rels don't have lateral references
582  * to the current rel(s). (If we are considering join paths with the outer
583  * rels on the outside and the current rels on the inside, then this should
584  * have been checked at the outset of such consideration; see join_is_legal
585  * and the path parameterization checks in joinpath.c.) On the other hand,
586  * in join_clause_is_movable_to we are asking whether the clause could be
587  * moved for some valid set of outer rels, so we don't have the benefit of
588  * relying on prior checks for lateral-reference validity.
589  *
590  * Note: if this returns true, it means that the clause could be moved to
591  * this join relation, but that doesn't mean that this is the lowest join
592  * it could be moved to. Caller may need to make additional calls to verify
593  * that this doesn't succeed on either of the inputs of a proposed join.
594  *
595  * Note: get_joinrel_parampathinfo depends on the fact that if
596  * current_and_outer is NULL, this function will always return false
597  * (since one or the other of the first two tests must fail).
598  */
599 bool
601  Relids currentrelids,
602  Relids current_and_outer)
603 {
604  /* Clause must be evaluable given available context */
605  if (!bms_is_subset(rinfo->clause_relids, current_and_outer))
606  return false;
607 
608  /* Clause must physically reference at least one target rel */
609  if (!bms_overlap(currentrelids, rinfo->clause_relids))
610  return false;
611 
612  /* Cannot move an outer-join clause into the join's outer side */
613  if (bms_overlap(currentrelids, rinfo->outer_relids))
614  return false;
615 
616  /*
617  * Target rel(s) must not be nullable below the clause. This is
618  * approximate, in the safe direction, because the current join might be
619  * above the join where the nulling would happen, in which case the clause
620  * would work correctly here. But we don't have enough info to be sure.
621  */
622  if (bms_overlap(currentrelids, rinfo->nullable_relids))
623  return false;
624 
625  return true;
626 }
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:315
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:427
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:225
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:703
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:494
unsigned int Index
Definition: c.h:549
bool contain_leaked_vars(Node *clause)
Definition: clauses.c:1150
Assert(fmt[strlen(fmt) - 1] !='\n')
List * lappend(List *list, void *datum)
Definition: list.c:336
Expr * make_andclause(List *andclauses)
Definition: makefuncs.c:636
Expr * make_orclause(List *orclauses)
Definition: makefuncs.c:652
static bool is_andclause(const void *clause)
Definition: nodeFuncs.h:95
static bool is_orclause(const void *clause)
Definition: nodeFuncs.h:104
static bool is_opclause(const void *clause)
Definition: nodeFuncs.h:64
static Node * get_rightop(const void *clause)
Definition: nodeFuncs.h:83
static Node * get_leftop(const void *clause)
Definition: nodeFuncs.h:71
#define makeNode(_type_)
Definition: nodes.h:586
#define castNode(_type_, nodeptr)
Definition: nodes.h:607
#define RINFO_IS_PUSHED_DOWN(rinfo, joinrelids)
Definition: pathnodes.h:2142
@ VOLATILITY_UNKNOWN
Definition: pathnodes.h:1079
#define lfirst(lc)
Definition: pg_list.h:169
#define lfirst_node(type, lc)
Definition: pg_list.h:172
static int list_length(const List *l)
Definition: pg_list.h:149
#define NIL
Definition: pg_list.h:65
#define linitial(l)
Definition: pg_list.h:174
#define lsecond(l)
Definition: pg_list.h:179
#define list_make2(x1, x2)
Definition: pg_list.h:208
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
List * get_actual_clauses(List *restrictinfo_list)
Definition: restrictinfo.c:422
bool restriction_is_or_clause(RestrictInfo *restrictinfo)
Definition: restrictinfo.c:384
void extract_actual_join_clauses(List *restrictinfo_list, Relids joinrelids, List **joinquals, List **otherquals)
Definition: restrictinfo.c:472
RestrictInfo * commute_restrictinfo(RestrictInfo *rinfo, Oid comm_op)
Definition: restrictinfo.c:327
static RestrictInfo * make_restrictinfo_internal(PlannerInfo *root, Expr *clause, Expr *orclause, bool is_pushed_down, bool outerjoin_delayed, bool pseudoconstant, Index security_level, Relids required_relids, Relids outer_relids, Relids nullable_relids)
Definition: restrictinfo.c:107
bool restriction_is_securely_promotable(RestrictInfo *restrictinfo, RelOptInfo *rel)
Definition: restrictinfo.c:399
RestrictInfo * make_restrictinfo(PlannerInfo *root, 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:61
bool join_clause_is_movable_into(RestrictInfo *rinfo, Relids currentrelids, Relids current_and_outer)
Definition: restrictinfo.c:600
List * extract_actual_clauses(List *restrictinfo_list, bool pseudoconstant)
Definition: restrictinfo.c:445
bool join_clause_is_movable_to(RestrictInfo *rinfo, RelOptInfo *baserel)
Definition: restrictinfo.c:527
static Expr * make_sub_restrictinfos(PlannerInfo *root, 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:244
Definition: pg_list.h:51
Definition: nodes.h:539
Oid opno
Definition: primnodes.h:542
List * args
Definition: primnodes.h:548
Oid opfuncid
Definition: primnodes.h:543
Cost startup
Definition: pathnodes.h:45
Index relid
Definition: pathnodes.h:709
Relids lateral_referencers
Definition: pathnodes.h:717
Index baserestrict_min_security
Definition: pathnodes.h:747
Selectivity left_mcvfreq
Definition: pathnodes.h:2124
bool is_pushed_down
Definition: pathnodes.h:2060
Selectivity outer_selec
Definition: pathnodes.h:2102
Index security_level
Definition: pathnodes.h:2073
EquivalenceClass * left_ec
Definition: pathnodes.h:2109
bool leakproof
Definition: pathnodes.h:2068
bool outer_is_left
Definition: pathnodes.h:2116
bool pseudoconstant
Definition: pathnodes.h:2066
QualCost eval_cost
Definition: pathnodes.h:2098
Relids required_relids
Definition: pathnodes.h:2079
Selectivity right_bucketsize
Definition: pathnodes.h:2123
VolatileFunctionStatus has_volatile
Definition: pathnodes.h:2070
Oid right_hasheqoperator
Definition: pathnodes.h:2129
Relids clause_relids
Definition: pathnodes.h:2076
Relids right_relids
Definition: pathnodes.h:2089
Oid left_hasheqoperator
Definition: pathnodes.h:2128
Relids nullable_relids
Definition: pathnodes.h:2085
Selectivity left_bucketsize
Definition: pathnodes.h:2122
Relids outer_relids
Definition: pathnodes.h:2082
Relids left_relids
Definition: pathnodes.h:2088
List * scansel_cache
Definition: pathnodes.h:2113
EquivalenceMember * left_em
Definition: pathnodes.h:2111
Expr * clause
Definition: pathnodes.h:2058
EquivalenceClass * parent_ec
Definition: pathnodes.h:2095
EquivalenceClass * right_ec
Definition: pathnodes.h:2110
Expr * orclause
Definition: pathnodes.h:2092
Selectivity norm_selec
Definition: pathnodes.h:2099
bool outerjoin_delayed
Definition: pathnodes.h:2062
EquivalenceMember * right_em
Definition: pathnodes.h:2112
Oid hashjoinoperator
Definition: pathnodes.h:2119
List * mergeopfamilies
Definition: pathnodes.h:2106
Selectivity right_mcvfreq
Definition: pathnodes.h:2125
Relids pull_varnos(PlannerInfo *root, Node *node)
Definition: var.c:97