PostgreSQL Source Code git master
Loading...
Searching...
No Matches
initsplan.c File Reference
Include dependency graph for initsplan.c:

Go to the source code of this file.

Data Structures

struct  JoinTreeItem
 

Typedefs

typedef struct JoinTreeItem JoinTreeItem
 

Functions

static bool is_partial_agg_memory_risky (PlannerInfo *root)
 
static void create_agg_clause_infos (PlannerInfo *root)
 
static void create_grouping_expr_infos (PlannerInfo *root)
 
static EquivalenceClassget_eclass_for_sortgroupclause (PlannerInfo *root, SortGroupClause *sgc, Expr *expr)
 
static void extract_lateral_references (PlannerInfo *root, RelOptInfo *brel, Index rtindex)
 
static Listdeconstruct_recurse (PlannerInfo *root, Node *jtnode, JoinDomain *parent_domain, JoinTreeItem *parent_jtitem, List **item_list)
 
static void deconstruct_distribute (PlannerInfo *root, JoinTreeItem *jtitem)
 
static void process_security_barrier_quals (PlannerInfo *root, int rti, JoinTreeItem *jtitem)
 
static void mark_rels_nulled_by_join (PlannerInfo *root, Index ojrelid, Relids lower_rels)
 
static SpecialJoinInfomake_outerjoininfo (PlannerInfo *root, Relids left_rels, Relids right_rels, Relids inner_join_rels, JoinType jointype, Index ojrelid, List *clause)
 
static void compute_semijoin_info (PlannerInfo *root, SpecialJoinInfo *sjinfo, List *clause)
 
static void deconstruct_distribute_oj_quals (PlannerInfo *root, List *jtitems, JoinTreeItem *jtitem)
 
static void distribute_quals_to_rels (PlannerInfo *root, List *clauses, JoinTreeItem *jtitem, SpecialJoinInfo *sjinfo, Index security_level, Relids qualscope, Relids ojscope, Relids outerjoin_nonnullable, Relids incompatible_relids, bool allow_equivalence, bool has_clone, bool is_clone, List **postponed_oj_qual_list)
 
static void distribute_qual_to_rels (PlannerInfo *root, Node *clause, JoinTreeItem *jtitem, SpecialJoinInfo *sjinfo, Index security_level, Relids qualscope, Relids ojscope, Relids outerjoin_nonnullable, Relids incompatible_relids, bool allow_equivalence, bool has_clone, bool is_clone, List **postponed_oj_qual_list)
 
static bool check_redundant_nullability_qual (PlannerInfo *root, Node *clause)
 
static Relids get_join_domain_min_rels (PlannerInfo *root, Relids domain_relids)
 
static void check_mergejoinable (RestrictInfo *restrictinfo)
 
static void check_hashjoinable (RestrictInfo *restrictinfo)
 
static void check_memoizable (RestrictInfo *restrictinfo)
 
void add_base_rels_to_query (PlannerInfo *root, Node *jtnode)
 
void add_other_rels_to_query (PlannerInfo *root)
 
void build_base_rel_tlists (PlannerInfo *root, List *final_tlist)
 
void add_vars_to_targetlist (PlannerInfo *root, List *vars, Relids where_needed)
 
void add_vars_to_attr_needed (PlannerInfo *root, List *vars, Relids where_needed)
 
void remove_useless_groupby_columns (PlannerInfo *root)
 
void setup_eager_aggregation (PlannerInfo *root)
 
void find_lateral_references (PlannerInfo *root)
 
void rebuild_lateral_attr_needed (PlannerInfo *root)
 
void create_lateral_join_info (PlannerInfo *root)
 
Listdeconstruct_jointree (PlannerInfo *root)
 
static void add_base_clause_to_rel (PlannerInfo *root, Index relid, RestrictInfo *restrictinfo)
 
bool restriction_is_always_true (PlannerInfo *root, RestrictInfo *restrictinfo)
 
bool restriction_is_always_false (PlannerInfo *root, RestrictInfo *restrictinfo)
 
void distribute_restrictinfo_to_rels (PlannerInfo *root, RestrictInfo *restrictinfo)
 
RestrictInfoprocess_implied_equality (PlannerInfo *root, Oid opno, Oid collation, Expr *item1, Expr *item2, Relids qualscope, Index security_level, bool both_const)
 
RestrictInfobuild_implied_join_equality (PlannerInfo *root, Oid opno, Oid collation, Expr *item1, Expr *item2, Relids qualscope, Index security_level)
 
void rebuild_joinclause_attr_needed (PlannerInfo *root)
 
void match_foreign_keys_to_quals (PlannerInfo *root)
 

Variables

int from_collapse_limit
 
int join_collapse_limit
 

Typedef Documentation

◆ JoinTreeItem

Function Documentation

◆ add_base_clause_to_rel()

static void add_base_clause_to_rel ( PlannerInfo root,
Index  relid,
RestrictInfo restrictinfo 
)
static

Definition at line 3367 of file initsplan.c.

3369{
3370 RelOptInfo *rel = find_base_rel(root, relid);
3371 RangeTblEntry *rte = root->simple_rte_array[relid];
3372
3373 Assert(bms_membership(restrictinfo->required_relids) == BMS_SINGLETON);
3374
3375 /*
3376 * For inheritance parent tables, we must always record the RestrictInfo
3377 * in baserestrictinfo as is. If we were to transform or skip adding it,
3378 * then the original wouldn't be available in apply_child_basequals. Since
3379 * there are two RangeTblEntries for inheritance parents, one with
3380 * inh==true and the other with inh==false, we're still able to apply this
3381 * optimization to the inh==false one. The inh==true one is what
3382 * apply_child_basequals() sees, whereas the inh==false one is what's used
3383 * for the scan node in the final plan.
3384 *
3385 * We make an exception to this for partitioned tables. For these, we
3386 * always apply the constant-TRUE and constant-FALSE transformations. A
3387 * qual which is either of these for a partitioned table must also be that
3388 * for all of its child partitions.
3389 */
3390 if (!rte->inh || rte->relkind == RELKIND_PARTITIONED_TABLE)
3391 {
3392 /* Don't add the clause if it is always true */
3394 return;
3395
3396 /*
3397 * Substitute the origin qual with constant-FALSE if it is provably
3398 * always false.
3399 *
3400 * Note that we need to keep the same rinfo_serial, since it is in
3401 * practice the same condition. We also need to reset the
3402 * last_rinfo_serial counter, which is essential to ensure that the
3403 * RestrictInfos for the "same" qual condition get identical serial
3404 * numbers (see deconstruct_distribute_oj_quals).
3405 */
3407 {
3408 int save_rinfo_serial = restrictinfo->rinfo_serial;
3409 int save_last_rinfo_serial = root->last_rinfo_serial;
3410
3412 (Expr *) makeBoolConst(false, false),
3413 restrictinfo->is_pushed_down,
3414 restrictinfo->has_clone,
3415 restrictinfo->is_clone,
3416 restrictinfo->pseudoconstant,
3417 0, /* security_level */
3418 restrictinfo->required_relids,
3419 restrictinfo->incompatible_relids,
3420 restrictinfo->outer_relids);
3421 restrictinfo->rinfo_serial = save_rinfo_serial;
3422 root->last_rinfo_serial = save_last_rinfo_serial;
3423 }
3424 }
3425
3426 /* Add clause to rel's restriction list */
3428
3429 /* Update security level info */
3431 restrictinfo->security_level);
3432}
BMS_Membership bms_membership(const Bitmapset *a)
Definition bitmapset.c:765
@ BMS_SINGLETON
Definition bitmapset.h:72
#define Min(x, y)
Definition c.h:1091
#define Assert(condition)
Definition c.h:943
bool restriction_is_always_true(PlannerInfo *root, RestrictInfo *restrictinfo)
Definition initsplan.c:3442
bool restriction_is_always_false(PlannerInfo *root, RestrictInfo *restrictinfo)
Definition initsplan.c:3507
List * lappend(List *list, void *datum)
Definition list.c:339
Node * makeBoolConst(bool value, bool isnull)
Definition makefuncs.c:408
static int fb(int x)
tree ctl root
Definition radixtree.h:1857
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition relnode.c:544
RestrictInfo * make_restrictinfo(PlannerInfo *root, Expr *clause, bool is_pushed_down, bool has_clone, bool is_clone, bool pseudoconstant, Index security_level, Relids required_relids, Relids incompatible_relids, Relids outer_relids)
List * baserestrictinfo
Definition pathnodes.h:1142
Index baserestrict_min_security
Definition pathnodes.h:1146

References Assert, RelOptInfo::baserestrict_min_security, RelOptInfo::baserestrictinfo, bms_membership(), BMS_SINGLETON, fb(), find_base_rel(), lappend(), make_restrictinfo(), makeBoolConst(), Min, restriction_is_always_false(), restriction_is_always_true(), and root.

Referenced by distribute_restrictinfo_to_rels().

◆ add_base_rels_to_query()

void add_base_rels_to_query ( PlannerInfo root,
Node jtnode 
)

Definition at line 166 of file initsplan.c.

167{
168 if (jtnode == NULL)
169 return;
170 if (IsA(jtnode, RangeTblRef))
171 {
172 int varno = ((RangeTblRef *) jtnode)->rtindex;
173
174 (void) build_simple_rel(root, varno, NULL);
175 }
176 else if (IsA(jtnode, FromExpr))
177 {
178 FromExpr *f = (FromExpr *) jtnode;
179 ListCell *l;
180
181 foreach(l, f->fromlist)
183 }
184 else if (IsA(jtnode, JoinExpr))
185 {
186 JoinExpr *j = (JoinExpr *) jtnode;
187
190 }
191 else
192 elog(ERROR, "unrecognized node type: %d",
193 (int) nodeTag(jtnode));
194}
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
void add_base_rels_to_query(PlannerInfo *root, Node *jtnode)
Definition initsplan.c:166
int j
Definition isn.c:78
#define IsA(nodeptr, _type_)
Definition nodes.h:164
#define nodeTag(nodeptr)
Definition nodes.h:139
#define lfirst(lc)
Definition pg_list.h:172
RelOptInfo * build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
Definition relnode.c:212
List * fromlist
Definition primnodes.h:2384

References add_base_rels_to_query(), build_simple_rel(), elog, ERROR, fb(), FromExpr::fromlist, IsA, j, JoinTreeItem::jtnode, lfirst, nodeTag, and root.

Referenced by add_base_rels_to_query(), and query_planner().

◆ add_other_rels_to_query()

void add_other_rels_to_query ( PlannerInfo root)

Definition at line 204 of file initsplan.c.

205{
206 int rti;
207
208 for (rti = 1; rti < root->simple_rel_array_size; rti++)
209 {
210 RelOptInfo *rel = root->simple_rel_array[rti];
211 RangeTblEntry *rte = root->simple_rte_array[rti];
212
213 /* there may be empty slots corresponding to non-baserel RTEs */
214 if (rel == NULL)
215 continue;
216
217 /* Ignore any "otherrels" that were already added. */
218 if (rel->reloptkind != RELOPT_BASEREL)
219 continue;
220
221 /* If it's marked as inheritable, look for children. */
222 if (rte->inh)
224 }
225}
void expand_inherited_rtentry(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte, Index rti)
Definition inherit.c:88
@ RELOPT_BASEREL
Definition pathnodes.h:977
RelOptKind reloptkind
Definition pathnodes.h:1015

References expand_inherited_rtentry(), fb(), RELOPT_BASEREL, RelOptInfo::reloptkind, and root.

Referenced by query_planner().

◆ add_vars_to_attr_needed()

void add_vars_to_attr_needed ( PlannerInfo root,
List vars,
Relids  where_needed 
)

Definition at line 361 of file initsplan.c.

363{
364 ListCell *temp;
365
367
368 foreach(temp, vars)
369 {
370 Node *node = (Node *) lfirst(temp);
371
372 if (IsA(node, Var))
373 {
374 Var *var = (Var *) node;
375 RelOptInfo *rel = find_base_rel(root, var->varno);
376 int attno = var->varattno;
377
379 continue;
380 Assert(attno >= rel->min_attr && attno <= rel->max_attr);
381 attno -= rel->min_attr;
382 rel->attr_needed[attno] = bms_add_members(rel->attr_needed[attno],
384 }
385 else if (IsA(node, PlaceHolderVar))
386 {
389
390 phinfo->ph_needed = bms_add_members(phinfo->ph_needed,
392 }
393 else
394 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
395 }
396}
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:412
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:901
#define bms_is_empty(a)
Definition bitmapset.h:118
PlaceHolderInfo * find_placeholder_info(PlannerInfo *root, PlaceHolderVar *phv)
Definition placeholder.c:85
Definition nodes.h:135
Relids relids
Definition pathnodes.h:1021
AttrNumber min_attr
Definition pathnodes.h:1075
AttrNumber varattno
Definition primnodes.h:275
int varno
Definition primnodes.h:270

References Assert, bms_add_members(), bms_is_empty, bms_is_subset(), elog, ERROR, fb(), find_base_rel(), find_placeholder_info(), IsA, lfirst, RelOptInfo::min_attr, nodeTag, RelOptInfo::relids, root, Var::varattno, and Var::varno.

Referenced by rebuild_eclass_attr_needed(), rebuild_joinclause_attr_needed(), rebuild_lateral_attr_needed(), and rebuild_placeholder_attr_needed().

◆ add_vars_to_targetlist()

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

Definition at line 290 of file initsplan.c.

292{
293 ListCell *temp;
294
296
297 foreach(temp, vars)
298 {
299 Node *node = (Node *) lfirst(temp);
300
301 if (IsA(node, Var))
302 {
303 Var *var = (Var *) node;
304 RelOptInfo *rel = find_base_rel(root, var->varno);
305 int attno = var->varattno;
306
308 continue;
309 Assert(attno >= rel->min_attr && attno <= rel->max_attr);
310 attno -= rel->min_attr;
311 if (rel->attr_needed[attno] == NULL)
312 {
313 /*
314 * Variable not yet requested, so add to rel's targetlist.
315 *
316 * The value available at the rel's scan level has not been
317 * nulled by any outer join, so drop its varnullingrels.
318 * (We'll put those back as we climb up the join tree.)
319 */
320 var = copyObject(var);
321 var->varnullingrels = NULL;
322 rel->reltarget->exprs = lappend(rel->reltarget->exprs, var);
323 /* reltarget cost and width will be computed later */
324 }
325 rel->attr_needed[attno] = bms_add_members(rel->attr_needed[attno],
327 }
328 else if (IsA(node, PlaceHolderVar))
329 {
332
333 phinfo->ph_needed = bms_add_members(phinfo->ph_needed,
335 }
336 else
337 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
338 }
339}
#define copyObject(obj)
Definition nodes.h:232
List * exprs
Definition pathnodes.h:1878
struct PathTarget * reltarget
Definition pathnodes.h:1045

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

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

◆ build_base_rel_tlists()

void build_base_rel_tlists ( PlannerInfo root,
List final_tlist 
)

Definition at line 243 of file initsplan.c.

244{
245 List *tlist_vars = pull_var_clause((Node *) final_tlist,
249
250 if (tlist_vars != NIL)
251 {
253 list_free(tlist_vars);
254 }
255
256 /*
257 * If there's a HAVING clause, we'll need the Vars it uses, too. Note
258 * that HAVING can contain Aggrefs but not WindowFuncs.
259 */
260 if (root->parse->havingQual)
261 {
262 List *having_vars = pull_var_clause(root->parse->havingQual,
265
266 if (having_vars != NIL)
267 {
271 }
272 }
273}
Bitmapset * bms_make_singleton(int x)
Definition bitmapset.c:216
void add_vars_to_targetlist(PlannerInfo *root, List *vars, Relids where_needed)
Definition initsplan.c:290
void list_free(List *list)
Definition list.c:1546
#define PVC_RECURSE_AGGREGATES
Definition optimizer.h:198
#define PVC_RECURSE_WINDOWFUNCS
Definition optimizer.h:200
#define PVC_INCLUDE_PLACEHOLDERS
Definition optimizer.h:201
#define NIL
Definition pg_list.h:68
Definition pg_list.h:54
List * pull_var_clause(Node *node, int flags)
Definition var.c:653

References add_vars_to_targetlist(), bms_make_singleton(), fb(), list_free(), NIL, pull_var_clause(), PVC_INCLUDE_PLACEHOLDERS, PVC_RECURSE_AGGREGATES, PVC_RECURSE_WINDOWFUNCS, and root.

Referenced by distribute_row_identity_vars(), and query_planner().

◆ build_implied_join_equality()

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

Definition at line 3807 of file initsplan.c.

3814{
3816 Expr *clause;
3817
3818 /*
3819 * Build the new clause. Copy to ensure it shares no substructure with
3820 * original (this is necessary in case there are subselects in there...)
3821 */
3822 clause = make_opclause(opno,
3823 BOOLOID, /* opresulttype */
3824 false, /* opretset */
3827 InvalidOid,
3828 collation);
3829
3830 /*
3831 * Build the RestrictInfo node itself.
3832 */
3834 clause,
3835 true, /* is_pushed_down */
3836 false, /* !has_clone */
3837 false, /* !is_clone */
3838 false, /* pseudoconstant */
3839 security_level, /* security_level */
3840 qualscope, /* required_relids */
3841 NULL, /* incompatible_relids */
3842 NULL); /* outer_relids */
3843
3844 /* Set mergejoinability/hashjoinability flags */
3848
3849 return restrictinfo;
3850}
static void check_hashjoinable(RestrictInfo *restrictinfo)
Definition initsplan.c:4184
static void check_mergejoinable(RestrictInfo *restrictinfo)
Definition initsplan.c:4147
static void check_memoizable(RestrictInfo *restrictinfo)
Definition initsplan.c:4212
Expr * make_opclause(Oid opno, Oid opresulttype, bool opretset, Expr *leftop, Expr *rightop, Oid opcollid, Oid inputcollid)
Definition makefuncs.c:701
#define InvalidOid

References check_hashjoinable(), check_memoizable(), check_mergejoinable(), copyObject, fb(), InvalidOid, make_opclause(), make_restrictinfo(), JoinTreeItem::qualscope, and root.

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

◆ check_hashjoinable()

static void check_hashjoinable ( RestrictInfo restrictinfo)
static

Definition at line 4184 of file initsplan.c.

4185{
4186 Expr *clause = restrictinfo->clause;
4187 Oid opno;
4188 Node *leftarg;
4189
4190 if (restrictinfo->pseudoconstant)
4191 return;
4192 if (!is_opclause(clause))
4193 return;
4194 if (list_length(((OpExpr *) clause)->args) != 2)
4195 return;
4196
4197 opno = ((OpExpr *) clause)->opno;
4198 leftarg = linitial(((OpExpr *) clause)->args);
4199
4200 if (op_hashjoinable(opno, exprType(leftarg)) &&
4202 restrictinfo->hashjoinoperator = opno;
4203}
bool contain_volatile_functions(Node *clause)
Definition clauses.c:549
bool op_hashjoinable(Oid opno, Oid inputtype)
Definition lsyscache.c:1657
Oid exprType(const Node *expr)
Definition nodeFuncs.c:42
static bool is_opclause(const void *clause)
Definition nodeFuncs.h:76
static int list_length(const List *l)
Definition pg_list.h:152
#define linitial(l)
Definition pg_list.h:178
unsigned int Oid

References contain_volatile_functions(), exprType(), fb(), is_opclause(), linitial, list_length(), and op_hashjoinable().

Referenced by build_implied_join_equality(), and distribute_restrictinfo_to_rels().

◆ check_memoizable()

static void check_memoizable ( RestrictInfo restrictinfo)
static

Definition at line 4212 of file initsplan.c.

4213{
4214 TypeCacheEntry *typentry;
4215 Expr *clause = restrictinfo->clause;
4216 Oid lefttype;
4217 Oid righttype;
4218
4219 if (restrictinfo->pseudoconstant)
4220 return;
4221 if (!is_opclause(clause))
4222 return;
4223 if (list_length(((OpExpr *) clause)->args) != 2)
4224 return;
4225
4226 lefttype = exprType(linitial(((OpExpr *) clause)->args));
4227
4228 typentry = lookup_type_cache(lefttype, TYPECACHE_HASH_PROC |
4230
4231 if (OidIsValid(typentry->hash_proc) && OidIsValid(typentry->eq_opr))
4232 restrictinfo->left_hasheqoperator = typentry->eq_opr;
4233
4234 righttype = exprType(lsecond(((OpExpr *) clause)->args));
4235
4236 /*
4237 * Lookup the right type, unless it's the same as the left type, in which
4238 * case typentry is already pointing to the required TypeCacheEntry.
4239 */
4240 if (lefttype != righttype)
4241 typentry = lookup_type_cache(righttype, TYPECACHE_HASH_PROC |
4243
4244 if (OidIsValid(typentry->hash_proc) && OidIsValid(typentry->eq_opr))
4245 restrictinfo->right_hasheqoperator = typentry->eq_opr;
4246}
#define OidIsValid(objectId)
Definition c.h:858
#define lsecond(l)
Definition pg_list.h:183
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition typcache.c:389
#define TYPECACHE_EQ_OPR
Definition typcache.h:138
#define TYPECACHE_HASH_PROC
Definition typcache.h:142

References TypeCacheEntry::eq_opr, exprType(), fb(), TypeCacheEntry::hash_proc, is_opclause(), linitial, list_length(), lookup_type_cache(), lsecond, OidIsValid, TYPECACHE_EQ_OPR, and TYPECACHE_HASH_PROC.

Referenced by build_implied_join_equality(), and distribute_restrictinfo_to_rels().

◆ check_mergejoinable()

static void check_mergejoinable ( RestrictInfo restrictinfo)
static

Definition at line 4147 of file initsplan.c.

4148{
4149 Expr *clause = restrictinfo->clause;
4150 Oid opno;
4151 Node *leftarg;
4152
4153 if (restrictinfo->pseudoconstant)
4154 return;
4155 if (!is_opclause(clause))
4156 return;
4157 if (list_length(((OpExpr *) clause)->args) != 2)
4158 return;
4159
4160 opno = ((OpExpr *) clause)->opno;
4161 leftarg = linitial(((OpExpr *) clause)->args);
4162
4163 if (op_mergejoinable(opno, exprType(leftarg)) &&
4165 restrictinfo->mergeopfamilies = get_mergejoin_opfamilies(opno);
4166
4167 /*
4168 * Note: op_mergejoinable is just a hint; if we fail to find the operator
4169 * in any btree opfamilies, mergeopfamilies remains NIL and so the clause
4170 * is not treated as mergejoinable.
4171 */
4172}
bool op_mergejoinable(Oid opno, Oid inputtype)
Definition lsyscache.c:1606
List * get_mergejoin_opfamilies(Oid opno)
Definition lsyscache.c:430

References contain_volatile_functions(), exprType(), fb(), get_mergejoin_opfamilies(), is_opclause(), linitial, list_length(), and op_mergejoinable().

Referenced by build_implied_join_equality(), distribute_qual_to_rels(), and process_implied_equality().

◆ check_redundant_nullability_qual()

static bool check_redundant_nullability_qual ( PlannerInfo root,
Node clause 
)
static

Definition at line 3322 of file initsplan.c.

3323{
3325 ListCell *lc;
3326
3327 /* Check for IS NULL, and identify the Var forced to NULL */
3329 if (forced_null_var == NULL)
3330 return false;
3331
3332 /*
3333 * If the Var comes from the nullable side of a lower antijoin, the IS
3334 * NULL condition is necessarily true. If it's not nulled by anything,
3335 * there is no point in searching the join_info_list. Otherwise, we need
3336 * to find out whether the nulling rel is an antijoin.
3337 */
3338 if (forced_null_var->varnullingrels == NULL)
3339 return false;
3340
3341 foreach(lc, root->join_info_list)
3342 {
3344
3345 /*
3346 * This test will not succeed if sjinfo->ojrelid is zero, which is
3347 * possible for an antijoin that was converted from a semijoin; but in
3348 * such a case the Var couldn't have come from its nullable side.
3349 */
3350 if (sjinfo->jointype == JOIN_ANTI && sjinfo->ojrelid != 0 &&
3351 bms_is_member(sjinfo->ojrelid, forced_null_var->varnullingrels))
3352 return true;
3353 }
3354
3355 return false;
3356}
bool bms_is_member(int x, const Bitmapset *a)
Definition bitmapset.c:510
Var * find_forced_null_var(Node *node)
Definition clauses.c:1995
@ JOIN_ANTI
Definition nodes.h:318
JoinType jointype
Definition pathnodes.h:3230

References bms_is_member(), fb(), find_forced_null_var(), JOIN_ANTI, SpecialJoinInfo::jointype, lfirst, SpecialJoinInfo::ojrelid, root, and JoinTreeItem::sjinfo.

Referenced by distribute_qual_to_rels().

◆ compute_semijoin_info()

static void compute_semijoin_info ( PlannerInfo root,
SpecialJoinInfo sjinfo,
List clause 
)
static

Definition at line 2435 of file initsplan.c.

2436{
2437 List *semi_operators;
2438 List *semi_rhs_exprs;
2439 bool all_btree;
2440 bool all_hash;
2441 ListCell *lc;
2442
2443 /* Initialize semijoin-related fields in case we can't unique-ify */
2444 sjinfo->semi_can_btree = false;
2445 sjinfo->semi_can_hash = false;
2446 sjinfo->semi_operators = NIL;
2447 sjinfo->semi_rhs_exprs = NIL;
2448
2449 /* Nothing more to do if it's not a semijoin */
2450 if (sjinfo->jointype != JOIN_SEMI)
2451 return;
2452
2453 /*
2454 * Look to see whether the semijoin's join quals consist of AND'ed
2455 * equality operators, with (only) RHS variables on only one side of each
2456 * one. If so, we can figure out how to enforce uniqueness for the RHS.
2457 *
2458 * Note that the input clause list is the list of quals that are
2459 * *syntactically* associated with the semijoin, which in practice means
2460 * the synthesized comparison list for an IN or the WHERE of an EXISTS.
2461 * Particularly in the latter case, it might contain clauses that aren't
2462 * *semantically* associated with the join, but refer to just one side or
2463 * the other. We can ignore such clauses here, as they will just drop
2464 * down to be processed within one side or the other. (It is okay to
2465 * consider only the syntactically-associated clauses here because for a
2466 * semijoin, no higher-level quals could refer to the RHS, and so there
2467 * can be no other quals that are semantically associated with this join.
2468 * We do things this way because it is useful to have the set of potential
2469 * unique-ification expressions before we can extract the list of quals
2470 * that are actually semantically associated with the particular join.)
2471 *
2472 * Note that the semi_operators list consists of the joinqual operators
2473 * themselves (but commuted if needed to put the RHS value on the right).
2474 * These could be cross-type operators, in which case the operator
2475 * actually needed for uniqueness is a related single-type operator. We
2476 * assume here that that operator will be available from the btree or hash
2477 * opclass when the time comes ... if not, create_unique_plan() will fail.
2478 */
2479 semi_operators = NIL;
2480 semi_rhs_exprs = NIL;
2481 all_btree = true;
2482 all_hash = enable_hashagg; /* don't consider hash if not enabled */
2483 foreach(lc, clause)
2484 {
2485 OpExpr *op = (OpExpr *) lfirst(lc);
2486 Oid opno;
2487 Node *left_expr;
2493
2494 /* Is it a binary opclause? */
2495 if (!IsA(op, OpExpr) ||
2496 list_length(op->args) != 2)
2497 {
2498 /* No, but does it reference both sides? */
2499 all_varnos = pull_varnos(root, (Node *) op);
2500 if (!bms_overlap(all_varnos, sjinfo->syn_righthand) ||
2502 {
2503 /*
2504 * Clause refers to only one rel, so ignore it --- unless it
2505 * contains volatile functions, in which case we'd better
2506 * punt.
2507 */
2508 if (contain_volatile_functions((Node *) op))
2509 return;
2510 continue;
2511 }
2512 /* Non-operator clause referencing both sides, must punt */
2513 return;
2514 }
2515
2516 /* Extract data from binary opclause */
2517 opno = op->opno;
2518 left_expr = linitial(op->args);
2519 right_expr = lsecond(op->args);
2524
2525 /* Does it reference both sides? */
2526 if (!bms_overlap(all_varnos, sjinfo->syn_righthand) ||
2528 {
2529 /*
2530 * Clause refers to only one rel, so ignore it --- unless it
2531 * contains volatile functions, in which case we'd better punt.
2532 */
2533 if (contain_volatile_functions((Node *) op))
2534 return;
2535 continue;
2536 }
2537
2538 /* check rel membership of arguments */
2539 if (!bms_is_empty(right_varnos) &&
2542 {
2543 /* typical case, right_expr is RHS variable */
2544 }
2545 else if (!bms_is_empty(left_varnos) &&
2548 {
2549 /* flipped case, left_expr is RHS variable */
2550 opno = get_commutator(opno);
2551 if (!OidIsValid(opno))
2552 return;
2554 }
2555 else
2556 {
2557 /* mixed membership of args, punt */
2558 return;
2559 }
2560
2561 /* all operators must be btree equality or hash equality */
2562 if (all_btree)
2563 {
2564 /* oprcanmerge is considered a hint... */
2565 if (!op_mergejoinable(opno, opinputtype) ||
2567 all_btree = false;
2568 }
2569 if (all_hash)
2570 {
2571 /* ... but oprcanhash had better be correct */
2572 if (!op_hashjoinable(opno, opinputtype))
2573 all_hash = false;
2574 }
2575 if (!(all_btree || all_hash))
2576 return;
2577
2578 /* so far so good, keep building lists */
2579 semi_operators = lappend_oid(semi_operators, opno);
2580 semi_rhs_exprs = lappend(semi_rhs_exprs, copyObject(right_expr));
2581 }
2582
2583 /* Punt if we didn't find at least one column to unique-ify */
2584 if (semi_rhs_exprs == NIL)
2585 return;
2586
2587 /*
2588 * The expressions we'd need to unique-ify mustn't be volatile.
2589 */
2590 if (contain_volatile_functions((Node *) semi_rhs_exprs))
2591 return;
2592
2593 /*
2594 * If we get here, we can unique-ify the semijoin's RHS using at least one
2595 * of sorting and hashing. Save the information about how to do that.
2596 */
2597 sjinfo->semi_can_btree = all_btree;
2598 sjinfo->semi_can_hash = all_hash;
2599 sjinfo->semi_operators = semi_operators;
2600 sjinfo->semi_rhs_exprs = semi_rhs_exprs;
2601}
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:251
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:575
bool enable_hashagg
Definition costsize.c:153
List * lappend_oid(List *list, Oid datum)
Definition list.c:375
Oid get_commutator(Oid opno)
Definition lsyscache.c:1729
@ JOIN_SEMI
Definition nodes.h:317
Oid opno
Definition primnodes.h:851
List * args
Definition primnodes.h:869
List * semi_rhs_exprs
Definition pathnodes.h:3241
Relids syn_righthand
Definition pathnodes.h:3229
List * semi_operators
Definition pathnodes.h:3240
Relids pull_varnos(PlannerInfo *root, Node *node)
Definition var.c:114

References OpExpr::args, bms_is_empty, bms_is_subset(), bms_overlap(), bms_union(), contain_volatile_functions(), copyObject, enable_hashagg, exprType(), fb(), 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(), root, SpecialJoinInfo::semi_can_btree, SpecialJoinInfo::semi_can_hash, SpecialJoinInfo::semi_operators, SpecialJoinInfo::semi_rhs_exprs, JoinTreeItem::sjinfo, and SpecialJoinInfo::syn_righthand.

Referenced by make_outerjoininfo().

◆ create_agg_clause_infos()

static void create_agg_clause_infos ( PlannerInfo root)
static

Definition at line 751 of file initsplan.c.

752{
754 List *agg_clause_list = NIL;
755 List *tlist_vars = NIL;
757 bool eager_agg_applicable = true;
758 ListCell *lc;
759
760 Assert(root->agg_clause_list == NIL);
761 Assert(root->tlist_vars == NIL);
762
763 tlist_exprs = pull_var_clause((Node *) root->processed_tlist,
767
768 /*
769 * Aggregates within the HAVING clause need to be processed in the same
770 * way as those in the targetlist. Note that HAVING can contain Aggrefs
771 * but not WindowFuncs.
772 */
773 if (root->parse->havingQual != NULL)
774 {
776
777 having_exprs = pull_var_clause((Node *) root->parse->havingQual,
780 if (having_exprs != NIL)
781 {
784 }
785 }
786
787 foreach(lc, tlist_exprs)
788 {
789 Expr *expr = (Expr *) lfirst(lc);
790 Aggref *aggref;
791 Relids agg_eval_at;
793
794 /* For now we don't try to support GROUPING() expressions */
795 if (IsA(expr, GroupingFunc))
796 {
797 eager_agg_applicable = false;
798 break;
799 }
800
801 /* Collect plain Vars for future reference */
802 if (IsA(expr, Var))
803 {
804 tlist_vars = list_append_unique(tlist_vars, expr);
805 continue;
806 }
807
808 aggref = castNode(Aggref, expr);
809
810 Assert(aggref->aggorder == NIL);
811 Assert(aggref->aggdistinct == NIL);
812
813 /*
814 * We cannot push down aggregates that contain volatile functions.
815 * Doing so would change the number of times the function is
816 * evaluated.
817 */
818 if (contain_volatile_functions((Node *) aggref))
819 {
820 eager_agg_applicable = false;
821 break;
822 }
823
824 /*
825 * If there are any securityQuals, do not try to apply eager
826 * aggregation if any non-leakproof aggregate functions are present.
827 * This is overly strict, but for now...
828 */
829 if (root->qual_security_level > 0 &&
830 !get_func_leakproof(aggref->aggfnoid))
831 {
832 eager_agg_applicable = false;
833 break;
834 }
835
836 agg_eval_at = pull_varnos(root, (Node *) aggref);
837
838 /*
839 * If all base relations in the query are referenced by aggregate
840 * functions, then eager aggregation is not applicable.
841 */
843 if (bms_is_subset(root->all_baserels, aggregate_relids))
844 {
845 eager_agg_applicable = false;
846 break;
847 }
848
849 /* OK, create the AggClauseInfo node */
851 ac_info->aggref = aggref;
852 ac_info->agg_eval_at = agg_eval_at;
853
854 /* ... and add it to the list */
855 agg_clause_list = list_append_unique(agg_clause_list, ac_info);
856 }
857
859
861 {
862 root->agg_clause_list = agg_clause_list;
863 root->tlist_vars = tlist_vars;
864 }
865 else
866 {
867 list_free_deep(agg_clause_list);
868 list_free(tlist_vars);
869 }
870}
List * list_append_unique(List *list, void *datum)
Definition list.c:1343
List * list_concat(List *list1, const List *list2)
Definition list.c:561
void list_free_deep(List *list)
Definition list.c:1560
bool get_func_leakproof(Oid funcid)
Definition lsyscache.c:2057
#define makeNode(_type_)
Definition nodes.h:161
#define castNode(_type_, nodeptr)
Definition nodes.h:182
#define PVC_RECURSE_PLACEHOLDERS
Definition optimizer.h:202
#define PVC_INCLUDE_AGGREGATES
Definition optimizer.h:197
List * aggdistinct
Definition primnodes.h:494
List * aggorder
Definition primnodes.h:491

References Aggref::aggdistinct, Aggref::aggfnoid, Aggref::aggorder, Assert, bms_add_members(), bms_is_subset(), castNode, contain_volatile_functions(), fb(), get_func_leakproof(), IsA, lfirst, list_append_unique(), list_concat(), list_free(), list_free_deep(), makeNode, NIL, pull_var_clause(), pull_varnos(), PVC_INCLUDE_AGGREGATES, PVC_RECURSE_PLACEHOLDERS, PVC_RECURSE_WINDOWFUNCS, and root.

Referenced by setup_eager_aggregation().

◆ create_grouping_expr_infos()

static void create_grouping_expr_infos ( PlannerInfo root)
static

Definition at line 880 of file initsplan.c.

881{
882 List *exprs = NIL;
884 List *ecs = NIL;
885 ListCell *lc,
886 *lc1,
887 *lc2,
888 *lc3;
889
890 Assert(root->group_expr_list == NIL);
891
892 foreach(lc, root->processed_groupClause)
893 {
895 TargetEntry *tle = get_sortgroupclause_tle(sgc, root->processed_tlist);
898
899 Assert(tle->ressortgroupref > 0);
900
901 /*
902 * For now we only support plain Vars as grouping expressions.
903 */
904 if (!IsA(tle->expr, Var))
905 return;
906
907 /*
908 * Eager aggregation is only possible if equality implies image
909 * equality for each grouping key. Otherwise, placing keys with
910 * different byte images into the same group may result in the loss of
911 * information that could be necessary to evaluate upper qual clauses.
912 *
913 * For instance, the NUMERIC data type is not supported, as values
914 * that are considered equal by the equality operator (e.g., 0 and
915 * 0.0) can have different scales.
916 */
919 if (!OidIsValid(tce->btree_opf) ||
920 !OidIsValid(tce->btree_opintype))
921 return;
922
924 tce->btree_opintype,
925 tce->btree_opintype,
927
928 /*
929 * If there is no BTEQUALIMAGE_PROC, eager aggregation is assumed to
930 * be unsafe. Otherwise, we call the procedure to check. We must be
931 * careful to pass the expression's actual collation, rather than the
932 * data type's default collation, to ensure that non-deterministic
933 * collations are correctly handled.
934 */
937 exprCollation((Node *) tle->expr),
938 ObjectIdGetDatum(tce->btree_opintype))))
939 return;
940
941 exprs = lappend(exprs, tle->expr);
942 sortgrouprefs = lappend_int(sortgrouprefs, tle->ressortgroupref);
944 }
945
946 /*
947 * Construct a GroupingExprInfo for each expression.
948 */
949 forthree(lc1, exprs, lc2, sortgrouprefs, lc3, ecs)
950 {
951 Expr *expr = (Expr *) lfirst(lc1);
952 int sortgroupref = lfirst_int(lc2);
955
957 ge_info->expr = (Expr *) copyObject(expr);
958 ge_info->sortgroupref = sortgroupref;
959 ge_info->ec = ec;
960
961 root->group_expr_list = lappend(root->group_expr_list, ge_info);
962 }
963}
Datum OidFunctionCall1Coll(Oid functionId, Oid collation, Datum arg1)
Definition fmgr.c:1413
static EquivalenceClass * get_eclass_for_sortgroupclause(PlannerInfo *root, SortGroupClause *sgc, Expr *expr)
Definition initsplan.c:971
List * lappend_int(List *list, int datum)
Definition list.c:357
Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
Definition lsyscache.c:915
#define BTEQUALIMAGE_PROC
Definition nbtree.h:720
Oid exprCollation(const Node *expr)
Definition nodeFuncs.c:826
#define lfirst_node(type, lc)
Definition pg_list.h:176
#define lfirst_int(lc)
Definition pg_list.h:173
#define forthree(cell1, list1, cell2, list2, cell3, list3)
Definition pg_list.h:595
static bool DatumGetBool(Datum X)
Definition postgres.h:100
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
TargetEntry * get_sortgroupclause_tle(SortGroupClause *sgClause, List *targetList)
Definition tlist.c:376
#define TYPECACHE_BTREE_OPFAMILY
Definition typcache.h:147

References Assert, BTEQUALIMAGE_PROC, copyObject, DatumGetBool(), exprCollation(), exprType(), fb(), forthree, get_eclass_for_sortgroupclause(), get_opfamily_proc(), get_sortgroupclause_tle(), IsA, lappend(), lappend_int(), lfirst, lfirst_int, lfirst_node, lookup_type_cache(), makeNode, NIL, ObjectIdGetDatum(), OidFunctionCall1Coll(), OidIsValid, root, and TYPECACHE_BTREE_OPFAMILY.

Referenced by setup_eager_aggregation().

◆ create_lateral_join_info()

void create_lateral_join_info ( PlannerInfo root)

Definition at line 1232 of file initsplan.c.

1233{
1234 bool found_laterals = false;
1235 Index rti;
1236 ListCell *lc;
1237
1238 /* We need do nothing if the query contains no LATERAL RTEs */
1239 if (!root->hasLateralRTEs)
1240 return;
1241
1242 /* We'll need to have the ph_eval_at values for PlaceHolderVars */
1243 Assert(root->placeholdersFrozen);
1244
1245 /*
1246 * Examine all baserels (the rel array has been set up by now).
1247 */
1248 for (rti = 1; rti < root->simple_rel_array_size; rti++)
1249 {
1250 RelOptInfo *brel = root->simple_rel_array[rti];
1251 Relids lateral_relids;
1252
1253 /* there may be empty slots corresponding to non-baserel RTEs */
1254 if (brel == NULL)
1255 continue;
1256
1257 Assert(brel->relid == rti); /* sanity check on array */
1258
1259 /* ignore RTEs that are "other rels" */
1260 if (brel->reloptkind != RELOPT_BASEREL)
1261 continue;
1262
1263 lateral_relids = NULL;
1264
1265 /* consider each laterally-referenced Var or PHV */
1266 foreach(lc, brel->lateral_vars)
1267 {
1268 Node *node = (Node *) lfirst(lc);
1269
1270 if (IsA(node, Var))
1271 {
1272 Var *var = (Var *) node;
1273
1274 found_laterals = true;
1275 lateral_relids = bms_add_member(lateral_relids,
1276 var->varno);
1277 }
1278 else if (IsA(node, PlaceHolderVar))
1279 {
1280 PlaceHolderVar *phv = (PlaceHolderVar *) node;
1282
1283 found_laterals = true;
1284 lateral_relids = bms_add_members(lateral_relids,
1285 phinfo->ph_eval_at);
1286 }
1287 else
1288 Assert(false);
1289 }
1290
1291 /* We now have all the simple lateral refs from this rel */
1292 brel->direct_lateral_relids = lateral_relids;
1293 brel->lateral_relids = bms_copy(lateral_relids);
1294 }
1295
1296 /*
1297 * Now check for lateral references within PlaceHolderVars, and mark their
1298 * eval_at rels as having lateral references to the source rels.
1299 *
1300 * For a PHV that is due to be evaluated at a baserel, mark its source(s)
1301 * as direct lateral dependencies of the baserel (adding onto the ones
1302 * recorded above). If it's due to be evaluated at a join, mark its
1303 * source(s) as indirect lateral dependencies of each baserel in the join,
1304 * ie put them into lateral_relids but not direct_lateral_relids. This is
1305 * appropriate because we can't put any such baserel on the outside of a
1306 * join to one of the PHV's lateral dependencies, but on the other hand we
1307 * also can't yet join it directly to the dependency.
1308 */
1309 foreach(lc, root->placeholder_list)
1310 {
1312 Relids eval_at = phinfo->ph_eval_at;
1314 int varno;
1315
1316 if (phinfo->ph_lateral == NULL)
1317 continue; /* PHV is uninteresting if no lateral refs */
1318
1319 found_laterals = true;
1320
1321 /*
1322 * Include only baserels not outer joins in the evaluation sites'
1323 * lateral relids. This avoids problems when outer join order gets
1324 * rearranged, and it should still ensure that the lateral values are
1325 * available when needed.
1326 */
1327 lateral_refs = bms_intersect(phinfo->ph_lateral, root->all_baserels);
1329
1330 if (bms_get_singleton_member(eval_at, &varno))
1331 {
1332 /* Evaluation site is a baserel */
1333 RelOptInfo *brel = find_base_rel(root, varno);
1334
1335 brel->direct_lateral_relids =
1336 bms_add_members(brel->direct_lateral_relids,
1337 lateral_refs);
1338 brel->lateral_relids =
1339 bms_add_members(brel->lateral_relids,
1340 lateral_refs);
1341 }
1342 else
1343 {
1344 /* Evaluation site is a join */
1345 varno = -1;
1346 while ((varno = bms_next_member(eval_at, varno)) >= 0)
1347 {
1349
1350 if (brel == NULL)
1351 continue; /* ignore outer joins in eval_at */
1352 brel->lateral_relids = bms_add_members(brel->lateral_relids,
1353 lateral_refs);
1354 }
1355 }
1356 }
1357
1358 /*
1359 * If we found no actual lateral references, we're done; but reset the
1360 * hasLateralRTEs flag to avoid useless work later.
1361 */
1362 if (!found_laterals)
1363 {
1364 root->hasLateralRTEs = false;
1365 return;
1366 }
1367
1368 /*
1369 * Calculate the transitive closure of the lateral_relids sets, so that
1370 * they describe both direct and indirect lateral references. If relation
1371 * X references Y laterally, and Y references Z laterally, then we will
1372 * have to scan X on the inside of a nestloop with Z, so for all intents
1373 * and purposes X is laterally dependent on Z too.
1374 *
1375 * This code is essentially Warshall's algorithm for transitive closure.
1376 * The outer loop considers each baserel, and propagates its lateral
1377 * dependencies to those baserels that have a lateral dependency on it.
1378 */
1379 for (rti = 1; rti < root->simple_rel_array_size; rti++)
1380 {
1381 RelOptInfo *brel = root->simple_rel_array[rti];
1383 Index rti2;
1384
1385 if (brel == NULL || brel->reloptkind != RELOPT_BASEREL)
1386 continue;
1387
1388 /* need not consider baserel further if it has no lateral refs */
1389 outer_lateral_relids = brel->lateral_relids;
1391 continue;
1392
1393 /* else scan all baserels */
1394 for (rti2 = 1; rti2 < root->simple_rel_array_size; rti2++)
1395 {
1396 RelOptInfo *brel2 = root->simple_rel_array[rti2];
1397
1398 if (brel2 == NULL || brel2->reloptkind != RELOPT_BASEREL)
1399 continue;
1400
1401 /* if brel2 has lateral ref to brel, propagate brel's refs */
1402 if (bms_is_member(rti, brel2->lateral_relids))
1403 brel2->lateral_relids = bms_add_members(brel2->lateral_relids,
1405 }
1406 }
1407
1408 /*
1409 * Now that we've identified all lateral references, mark each baserel
1410 * with the set of relids of rels that reference it laterally (possibly
1411 * indirectly) --- that is, the inverse mapping of lateral_relids.
1412 */
1413 for (rti = 1; rti < root->simple_rel_array_size; rti++)
1414 {
1415 RelOptInfo *brel = root->simple_rel_array[rti];
1416 Relids lateral_relids;
1417 int rti2;
1418
1419 if (brel == NULL || brel->reloptkind != RELOPT_BASEREL)
1420 continue;
1421
1422 /* Nothing to do at rels with no lateral refs */
1423 lateral_relids = brel->lateral_relids;
1424 if (bms_is_empty(lateral_relids))
1425 continue;
1426
1427 /* No rel should have a lateral dependency on itself */
1428 Assert(!bms_is_member(rti, lateral_relids));
1429
1430 /* Mark this rel's referencees */
1431 rti2 = -1;
1432 while ((rti2 = bms_next_member(lateral_relids, rti2)) >= 0)
1433 {
1434 RelOptInfo *brel2 = root->simple_rel_array[rti2];
1435
1436 if (brel2 == NULL)
1437 continue; /* must be an OJ */
1438
1439 Assert(brel2->reloptkind == RELOPT_BASEREL);
1440 brel2->lateral_referencers =
1441 bms_add_member(brel2->lateral_referencers, rti);
1442 }
1443 }
1444}
Bitmapset * bms_intersect(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:292
int bms_next_member(const Bitmapset *a, int prevbit)
Definition bitmapset.c:1290
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition bitmapset.c:799
bool bms_get_singleton_member(const Bitmapset *a, int *member)
Definition bitmapset.c:708
Bitmapset * bms_copy(const Bitmapset *a)
Definition bitmapset.c:122
unsigned int Index
Definition c.h:698
RelOptInfo * find_base_rel_ignore_join(PlannerInfo *root, int relid)
Definition relnode.c:584
Relids lateral_relids
Definition pathnodes.h:1064

References Assert, bms_add_member(), bms_add_members(), bms_copy(), bms_get_singleton_member(), bms_intersect(), bms_is_empty, bms_is_member(), bms_next_member(), fb(), find_base_rel(), find_base_rel_ignore_join(), find_placeholder_info(), IsA, RelOptInfo::lateral_relids, lfirst, RELOPT_BASEREL, root, and Var::varno.

Referenced by query_planner().

◆ deconstruct_distribute()

static void deconstruct_distribute ( PlannerInfo root,
JoinTreeItem jtitem 
)
static

Definition at line 1851 of file initsplan.c.

1852{
1853 Node *jtnode = jtitem->jtnode;
1854
1855 if (IsA(jtnode, RangeTblRef))
1856 {
1857 int varno = ((RangeTblRef *) jtnode)->rtindex;
1858
1859 /* Deal with any securityQuals attached to the RTE */
1860 if (root->qual_security_level > 0)
1862 varno,
1863 jtitem);
1864 }
1865 else if (IsA(jtnode, FromExpr))
1866 {
1867 FromExpr *f = (FromExpr *) jtnode;
1868
1869 /*
1870 * Process any lateral-referencing quals that were postponed to this
1871 * level by children.
1872 */
1873 distribute_quals_to_rels(root, jtitem->lateral_clauses,
1874 jtitem,
1875 NULL,
1876 root->qual_security_level,
1877 jtitem->qualscope,
1878 NULL, NULL, NULL,
1879 true, false, false,
1880 NULL);
1881
1882 /*
1883 * Now process the top-level quals.
1884 */
1886 jtitem,
1887 NULL,
1888 root->qual_security_level,
1889 jtitem->qualscope,
1890 NULL, NULL, NULL,
1891 true, false, false,
1892 NULL);
1893 }
1894 else if (IsA(jtnode, JoinExpr))
1895 {
1896 JoinExpr *j = (JoinExpr *) jtnode;
1898 List *my_quals;
1899 SpecialJoinInfo *sjinfo;
1901
1902 /*
1903 * Include lateral-referencing quals postponed from children in
1904 * my_quals, so that they'll be handled properly in
1905 * make_outerjoininfo. (This is destructive to
1906 * jtitem->lateral_clauses, but we won't use that again.)
1907 */
1908 my_quals = list_concat(jtitem->lateral_clauses,
1909 (List *) j->quals);
1910
1911 /*
1912 * For an OJ, form the SpecialJoinInfo now, so that we can pass it to
1913 * distribute_qual_to_rels. We must compute its ojscope too.
1914 *
1915 * Semijoins are a bit of a hybrid: we build a SpecialJoinInfo, but we
1916 * want ojscope = NULL for distribute_qual_to_rels.
1917 */
1918 if (j->jointype != JOIN_INNER)
1919 {
1920 sjinfo = make_outerjoininfo(root,
1921 jtitem->left_rels,
1922 jtitem->right_rels,
1923 jtitem->inner_join_rels,
1924 j->jointype,
1925 j->rtindex,
1926 my_quals);
1927 jtitem->sjinfo = sjinfo;
1928 if (j->jointype == JOIN_SEMI)
1929 ojscope = NULL;
1930 else
1931 ojscope = bms_union(sjinfo->min_lefthand,
1932 sjinfo->min_righthand);
1933 }
1934 else
1935 {
1936 sjinfo = NULL;
1937 ojscope = NULL;
1938 }
1939
1940 /*
1941 * If it's a left join with a join clause that is strict for the LHS,
1942 * then we need to postpone handling of any non-degenerate join
1943 * clauses, in case the join is able to commute with another left join
1944 * per identity 3. (Degenerate clauses need not be postponed, since
1945 * they will drop down below this join anyway.)
1946 */
1947 if (j->jointype == JOIN_LEFT && sjinfo->lhs_strict)
1948 {
1949 postponed_oj_qual_list = &jtitem->oj_joinclauses;
1950
1951 /*
1952 * Add back any commutable lower OJ relids that were removed from
1953 * min_lefthand or min_righthand, else the ojscope cross-check in
1954 * distribute_qual_to_rels will complain. Since we are postponing
1955 * processing of non-degenerate clauses, this addition doesn't
1956 * affect anything except that cross-check. Real clause
1957 * positioning decisions will be made later, when we revisit the
1958 * postponed clauses.
1959 */
1962 }
1963 else
1965
1966 /* Process the JOIN's qual clauses */
1968 jtitem,
1969 sjinfo,
1970 root->qual_security_level,
1971 jtitem->qualscope,
1972 ojscope, jtitem->nonnullable_rels,
1973 NULL, /* incompatible_relids */
1974 true, /* allow_equivalence */
1975 false, false, /* not clones */
1977
1978 /* And add the SpecialJoinInfo to join_info_list */
1979 if (sjinfo)
1980 root->join_info_list = lappend(root->join_info_list, sjinfo);
1981 }
1982 else
1983 {
1984 elog(ERROR, "unrecognized node type: %d",
1985 (int) nodeTag(jtnode));
1986 }
1987}
static void distribute_quals_to_rels(PlannerInfo *root, List *clauses, JoinTreeItem *jtitem, SpecialJoinInfo *sjinfo, Index security_level, Relids qualscope, Relids ojscope, Relids outerjoin_nonnullable, Relids incompatible_relids, bool allow_equivalence, bool has_clone, bool is_clone, List **postponed_oj_qual_list)
Definition initsplan.c:2854
static SpecialJoinInfo * make_outerjoininfo(PlannerInfo *root, Relids left_rels, Relids right_rels, Relids inner_join_rels, JoinType jointype, Index ojrelid, List *clause)
Definition initsplan.c:2095
static void process_security_barrier_quals(PlannerInfo *root, int rti, JoinTreeItem *jtitem)
Definition initsplan.c:2003
@ JOIN_INNER
Definition nodes.h:303
@ JOIN_LEFT
Definition nodes.h:304
Node * quals
Definition primnodes.h:2385
Relids min_righthand
Definition pathnodes.h:3227
Relids commute_below_l
Definition pathnodes.h:3234
Relids min_lefthand
Definition pathnodes.h:3226
Relids commute_below_r
Definition pathnodes.h:3235

References bms_add_members(), bms_union(), SpecialJoinInfo::commute_below_l, SpecialJoinInfo::commute_below_r, distribute_quals_to_rels(), elog, ERROR, fb(), IsA, j, JOIN_INNER, JOIN_LEFT, JOIN_SEMI, JoinTreeItem::jtnode, lappend(), SpecialJoinInfo::lhs_strict, list_concat(), make_outerjoininfo(), SpecialJoinInfo::min_lefthand, SpecialJoinInfo::min_righthand, nodeTag, process_security_barrier_quals(), FromExpr::quals, root, and JoinTreeItem::sjinfo.

Referenced by deconstruct_jointree().

◆ deconstruct_distribute_oj_quals()

static void deconstruct_distribute_oj_quals ( PlannerInfo root,
List jtitems,
JoinTreeItem jtitem 
)
static

Definition at line 2613 of file initsplan.c.

2616{
2617 SpecialJoinInfo *sjinfo = jtitem->sjinfo;
2618 Relids qualscope,
2619 ojscope,
2620 nonnullable_rels;
2621
2622 /* Recompute syntactic and semantic scopes of this left join */
2623 qualscope = bms_union(sjinfo->syn_lefthand, sjinfo->syn_righthand);
2624 qualscope = bms_add_member(qualscope, sjinfo->ojrelid);
2625 ojscope = bms_union(sjinfo->min_lefthand, sjinfo->min_righthand);
2626 nonnullable_rels = sjinfo->syn_lefthand;
2627
2628 /*
2629 * If this join can commute with any other ones per outer-join identity 3,
2630 * and it is the one providing the join clause with flexible semantics,
2631 * then we have to generate variants of the join clause with different
2632 * nullingrels labeling. Otherwise, just push out the postponed clause
2633 * as-is.
2634 */
2635 Assert(sjinfo->lhs_strict); /* else we shouldn't be here */
2636 if (sjinfo->commute_above_r || sjinfo->commute_below_l)
2637 {
2642 List *quals;
2644 ListCell *lc;
2645
2646 /* Identify the outer joins this one commutes with */
2647 joins_above = sjinfo->commute_above_r;
2648 joins_below = sjinfo->commute_below_l;
2649
2650 /*
2651 * Generate qual variants with different sets of nullingrels bits.
2652 *
2653 * We only need bit-sets that correspond to the successively less
2654 * deeply syntactically-nested subsets of this join and its
2655 * commutators. That's true first because obviously only those forms
2656 * of the Vars and PHVs could appear elsewhere in the query, and
2657 * second because the outer join identities do not provide a way to
2658 * re-order such joins in a way that would require different marking.
2659 * (That is, while the current join may commute with several others,
2660 * none of those others can commute with each other.) To visit the
2661 * interesting joins in syntactic nesting order, we rely on the
2662 * jtitems list to be ordered that way.
2663 *
2664 * We first strip out all the nullingrels bits corresponding to
2665 * commuting joins below this one, and then successively put them back
2666 * as we crawl up the join stack.
2667 */
2668 quals = jtitem->oj_joinclauses;
2670 quals = (List *) remove_nulling_relids((Node *) quals,
2672 NULL);
2673
2674 /*
2675 * We'll need to mark the lower versions of the quals as not safe to
2676 * apply above not-yet-processed joins of the stack. This prevents
2677 * possibly applying a cloned qual at the wrong join level.
2678 */
2681 sjinfo->ojrelid);
2682
2683 /*
2684 * Each time we produce RestrictInfo(s) from these quals, reset the
2685 * last_rinfo_serial counter, so that the RestrictInfos for the "same"
2686 * qual condition get identical serial numbers. (This relies on the
2687 * fact that we're not changing the qual list in any way that'd affect
2688 * the number of RestrictInfos built from it.) This'll allow us to
2689 * detect duplicative qual usage later.
2690 */
2691 save_last_rinfo_serial = root->last_rinfo_serial;
2692
2694 foreach(lc, jtitems)
2695 {
2698 bool below_sjinfo = false;
2699 bool above_sjinfo = false;
2702 bool allow_equivalence,
2703 has_clone,
2704 is_clone;
2705
2706 if (othersj == NULL)
2707 continue; /* not an outer-join item, ignore */
2708
2709 if (bms_is_member(othersj->ojrelid, joins_below))
2710 {
2711 /* othersj commutes with sjinfo from below left */
2712 below_sjinfo = true;
2713 }
2714 else if (othersj == sjinfo)
2715 {
2716 /* found our join in syntactic order */
2718 }
2719 else if (bms_is_member(othersj->ojrelid, joins_above))
2720 {
2721 /* othersj commutes with sjinfo from above */
2722 above_sjinfo = true;
2723 }
2724 else
2725 {
2726 /* othersj is not relevant, ignore */
2727 continue;
2728 }
2729
2730 /* Reset serial counter for this version of the quals */
2731 root->last_rinfo_serial = save_last_rinfo_serial;
2732
2733 /*
2734 * When we are looking at joins above sjinfo, we are envisioning
2735 * pushing sjinfo to above othersj, so add othersj's nulling bit
2736 * before distributing the quals. We should add it to Vars coming
2737 * from the current join's LHS: we want to transform the second
2738 * form of OJ identity 3 to the first form, in which Vars of
2739 * relation B will appear nulled by the syntactically-upper OJ
2740 * within the Pbc clause, but those of relation C will not. (In
2741 * the notation used by optimizer/README, we're converting a qual
2742 * of the form Pbc to Pb*c.) Of course, we must also remove that
2743 * bit from the incompatible_joins value, else we'll make a qual
2744 * that can't be placed anywhere.
2745 */
2746 if (above_sjinfo)
2747 {
2748 quals = (List *)
2749 add_nulling_relids((Node *) quals,
2750 sjinfo->syn_lefthand,
2751 bms_make_singleton(othersj->ojrelid));
2753 othersj->ojrelid);
2754 }
2755
2756 /* Compute qualscope and ojscope for this join level */
2759 if (above_sjinfo)
2760 {
2761 /* othersj is not yet in joins_so_far, but we need it */
2763 othersj->ojrelid);
2765 othersj->ojrelid);
2766 /* sjinfo is in joins_so_far, and we don't want it */
2768 sjinfo->ojrelid);
2769 }
2770
2771 /*
2772 * We generate EquivalenceClasses only from the first form of the
2773 * quals, with the fewest nullingrels bits set. An EC made from
2774 * this version of the quals can be useful below the outer-join
2775 * nest, whereas versions with some nullingrels bits set would not
2776 * be. We cannot generate ECs from more than one version, or
2777 * we'll make nonsensical conclusions that Vars with nullingrels
2778 * bits set are equal to their versions without. Fortunately,
2779 * such ECs wouldn't be very useful anyway, because they'd equate
2780 * values not observable outside the join nest. (See
2781 * optimizer/README.)
2782 *
2783 * The first form of the quals is also the only one marked as
2784 * has_clone rather than is_clone.
2785 */
2787 has_clone = allow_equivalence;
2788 is_clone = !has_clone;
2789
2792 sjinfo,
2793 root->qual_security_level,
2795 this_ojscope, nonnullable_rels,
2798 has_clone,
2799 is_clone,
2800 NULL); /* no more postponement */
2801
2802 /*
2803 * Adjust qual nulling bits for next level up, if needed. We
2804 * don't want to put sjinfo's own bit in at all, and if we're
2805 * above sjinfo then we did it already. Here, we should mark all
2806 * Vars coming from the lower join's RHS. (Again, we are
2807 * converting a qual of the form Pbc to Pb*c, but now we are
2808 * putting back bits that were there in the parser output and were
2809 * temporarily stripped above.) Update incompatible_joins too.
2810 */
2811 if (below_sjinfo)
2812 {
2813 quals = (List *)
2814 add_nulling_relids((Node *) quals,
2815 othersj->syn_righthand,
2816 bms_make_singleton(othersj->ojrelid));
2818 othersj->ojrelid);
2819 }
2820
2821 /* ... and track joins processed so far */
2823 }
2824 }
2825 else
2826 {
2827 /* No commutation possible, just process the postponed clauses */
2828 distribute_quals_to_rels(root, jtitem->oj_joinclauses,
2829 jtitem,
2830 sjinfo,
2831 root->qual_security_level,
2832 qualscope,
2833 ojscope, nonnullable_rels,
2834 NULL, /* incompatible_relids */
2835 true, /* allow_equivalence */
2836 false, false, /* not clones */
2837 NULL); /* no more postponement */
2838 }
2839}
bool bms_equal(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:142
Bitmapset * bms_del_member(Bitmapset *a, int x)
Definition bitmapset.c:852
Node * add_nulling_relids(Node *node, const Bitmapset *target_relids, const Bitmapset *added_relids)
Node * remove_nulling_relids(Node *node, const Bitmapset *removable_relids, const Bitmapset *except_relids)
Relids commute_above_r
Definition pathnodes.h:3233
Relids syn_lefthand
Definition pathnodes.h:3228

References add_nulling_relids(), Assert, bms_add_member(), bms_copy(), bms_del_member(), bms_equal(), bms_is_empty, bms_is_member(), bms_make_singleton(), bms_union(), SpecialJoinInfo::commute_above_r, SpecialJoinInfo::commute_below_l, distribute_quals_to_rels(), fb(), lfirst, SpecialJoinInfo::lhs_strict, SpecialJoinInfo::min_lefthand, SpecialJoinInfo::min_righthand, JoinTreeItem::nonnullable_rels, SpecialJoinInfo::ojrelid, JoinTreeItem::qualscope, remove_nulling_relids(), root, JoinTreeItem::sjinfo, SpecialJoinInfo::syn_lefthand, and SpecialJoinInfo::syn_righthand.

Referenced by deconstruct_jointree().

◆ deconstruct_jointree()

List * deconstruct_jointree ( PlannerInfo root)

Definition at line 1471 of file initsplan.c.

1472{
1473 List *result;
1475 List *item_list = NIL;
1476 ListCell *lc;
1477
1478 /*
1479 * After this point, no more PlaceHolderInfos may be made, because
1480 * make_outerjoininfo requires all active placeholders to be present in
1481 * root->placeholder_list while we crawl up the join tree.
1482 */
1483 root->placeholdersFrozen = true;
1484
1485 /* Fetch the already-created top-level join domain for the query */
1486 top_jdomain = linitial_node(JoinDomain, root->join_domains);
1487 top_jdomain->jd_relids = NULL; /* filled during deconstruct_recurse */
1488
1489 /* Start recursion at top of jointree */
1490 Assert(root->parse->jointree != NULL &&
1491 IsA(root->parse->jointree, FromExpr));
1492
1493 /* These are filled as we scan the jointree */
1494 root->all_baserels = NULL;
1495 root->outer_join_rels = NULL;
1496
1497 /* Perform the initial scan of the jointree */
1498 result = deconstruct_recurse(root, (Node *) root->parse->jointree,
1500 &item_list);
1501
1502 /* Now we can form the value of all_query_rels, too */
1503 root->all_query_rels = bms_union(root->all_baserels, root->outer_join_rels);
1504
1505 /* ... which should match what we computed for the top join domain */
1506 Assert(bms_equal(root->all_query_rels, top_jdomain->jd_relids));
1507
1508 /* Now scan all the jointree nodes again, and distribute quals */
1509 foreach(lc, item_list)
1510 {
1512
1514 }
1515
1516 /*
1517 * If there were any special joins then we may have some postponed LEFT
1518 * JOIN clauses to deal with.
1519 */
1520 if (root->join_info_list)
1521 {
1522 foreach(lc, item_list)
1523 {
1525
1526 if (jtitem->oj_joinclauses != NIL)
1528 }
1529 }
1530
1531 /* Don't need the JoinTreeItems any more */
1533
1534 return result;
1535}
uint32 result
static List * deconstruct_recurse(PlannerInfo *root, Node *jtnode, JoinDomain *parent_domain, JoinTreeItem *parent_jtitem, List **item_list)
Definition initsplan.c:1553
static void deconstruct_distribute_oj_quals(PlannerInfo *root, List *jtitems, JoinTreeItem *jtitem)
Definition initsplan.c:2613
static void deconstruct_distribute(PlannerInfo *root, JoinTreeItem *jtitem)
Definition initsplan.c:1851
#define linitial_node(type, l)
Definition pg_list.h:181

References Assert, bms_equal(), bms_union(), deconstruct_distribute(), deconstruct_distribute_oj_quals(), deconstruct_recurse(), fb(), IsA, lfirst, linitial_node, list_free_deep(), NIL, result, and root.

Referenced by query_planner().

◆ deconstruct_recurse()

static List * deconstruct_recurse ( PlannerInfo root,
Node jtnode,
JoinDomain parent_domain,
JoinTreeItem parent_jtitem,
List **  item_list 
)
static

Definition at line 1553 of file initsplan.c.

1557{
1558 List *joinlist;
1560
1561 Assert(jtnode != NULL);
1562
1563 /* Make the new JoinTreeItem, but don't add it to item_list yet */
1565 jtitem->jtnode = jtnode;
1566 jtitem->jti_parent = parent_jtitem;
1567
1568 if (IsA(jtnode, RangeTblRef))
1569 {
1570 int varno = ((RangeTblRef *) jtnode)->rtindex;
1571
1572 /* Fill all_baserels as we encounter baserel jointree nodes */
1573 root->all_baserels = bms_add_member(root->all_baserels, varno);
1574 /* This node belongs to parent_domain */
1575 jtitem->jdomain = parent_domain;
1576 parent_domain->jd_relids = bms_add_member(parent_domain->jd_relids,
1577 varno);
1578 /* qualscope is just the one RTE */
1579 jtitem->qualscope = bms_make_singleton(varno);
1580 /* A single baserel does not create an inner join */
1581 jtitem->inner_join_rels = NULL;
1582 joinlist = list_make1(jtnode);
1583 }
1584 else if (IsA(jtnode, FromExpr))
1585 {
1586 FromExpr *f = (FromExpr *) jtnode;
1587 int remaining;
1588 ListCell *l;
1589
1590 /* This node belongs to parent_domain, as do its children */
1591 jtitem->jdomain = parent_domain;
1592
1593 /*
1594 * Recurse to handle child nodes, and compute output joinlist. We
1595 * collapse subproblems into a single joinlist whenever the resulting
1596 * joinlist wouldn't exceed from_collapse_limit members. Also, always
1597 * collapse one-element subproblems, since that won't lengthen the
1598 * joinlist anyway.
1599 */
1600 jtitem->qualscope = NULL;
1601 jtitem->inner_join_rels = NULL;
1602 joinlist = NIL;
1604 foreach(l, f->fromlist)
1605 {
1608 int sub_members;
1609
1612 jtitem,
1613 item_list);
1615 jtitem->qualscope = bms_add_members(jtitem->qualscope,
1616 sub_item->qualscope);
1617 jtitem->inner_join_rels = sub_item->inner_join_rels;
1619 remaining--;
1620 if (sub_members <= 1 ||
1623 else
1625 }
1626
1627 /*
1628 * A FROM with more than one list element is an inner join subsuming
1629 * all below it, so we should report inner_join_rels = qualscope. If
1630 * there was exactly one element, we should (and already did) report
1631 * whatever its inner_join_rels were. If there were no elements (is
1632 * that still possible?) the initialization before the loop fixed it.
1633 */
1634 if (list_length(f->fromlist) > 1)
1635 jtitem->inner_join_rels = jtitem->qualscope;
1636 }
1637 else if (IsA(jtnode, JoinExpr))
1638 {
1639 JoinExpr *j = (JoinExpr *) jtnode;
1641 *fj_domain;
1643 *right_item;
1646
1647 switch (j->jointype)
1648 {
1649 case JOIN_INNER:
1650 /* This node belongs to parent_domain, as do its children */
1651 jtitem->jdomain = parent_domain;
1652 /* Recurse */
1655 jtitem,
1656 item_list);
1660 jtitem,
1661 item_list);
1663 /* Compute qualscope etc */
1664 jtitem->qualscope = bms_union(left_item->qualscope,
1665 right_item->qualscope);
1666 jtitem->inner_join_rels = jtitem->qualscope;
1667 jtitem->left_rels = left_item->qualscope;
1668 jtitem->right_rels = right_item->qualscope;
1669 /* Inner join adds no restrictions for quals */
1670 jtitem->nonnullable_rels = NULL;
1671 break;
1672 case JOIN_LEFT:
1673 case JOIN_ANTI:
1674 /* Make new join domain for my quals and the RHS */
1676 child_domain->jd_relids = NULL; /* filled by recursion */
1677 root->join_domains = lappend(root->join_domains, child_domain);
1678 jtitem->jdomain = child_domain;
1679 /* Recurse */
1682 jtitem,
1683 item_list);
1687 jtitem,
1688 item_list);
1690 /* Compute join domain contents, qualscope etc */
1691 parent_domain->jd_relids =
1692 bms_add_members(parent_domain->jd_relids,
1693 child_domain->jd_relids);
1694 jtitem->qualscope = bms_union(left_item->qualscope,
1695 right_item->qualscope);
1696 /* caution: ANTI join derived from SEMI will lack rtindex */
1697 if (j->rtindex != 0)
1698 {
1699 parent_domain->jd_relids =
1700 bms_add_member(parent_domain->jd_relids,
1701 j->rtindex);
1702 jtitem->qualscope = bms_add_member(jtitem->qualscope,
1703 j->rtindex);
1704 root->outer_join_rels = bms_add_member(root->outer_join_rels,
1705 j->rtindex);
1707 right_item->qualscope);
1708 }
1709 jtitem->inner_join_rels = bms_union(left_item->inner_join_rels,
1710 right_item->inner_join_rels);
1711 jtitem->left_rels = left_item->qualscope;
1712 jtitem->right_rels = right_item->qualscope;
1713 jtitem->nonnullable_rels = left_item->qualscope;
1714 break;
1715 case JOIN_SEMI:
1716 /* This node belongs to parent_domain, as do its children */
1717 jtitem->jdomain = parent_domain;
1718 /* Recurse */
1721 jtitem,
1722 item_list);
1726 jtitem,
1727 item_list);
1729 /* Compute qualscope etc */
1730 jtitem->qualscope = bms_union(left_item->qualscope,
1731 right_item->qualscope);
1732 /* SEMI join never has rtindex, so don't add to anything */
1733 Assert(j->rtindex == 0);
1734 jtitem->inner_join_rels = bms_union(left_item->inner_join_rels,
1735 right_item->inner_join_rels);
1736 jtitem->left_rels = left_item->qualscope;
1737 jtitem->right_rels = right_item->qualscope;
1738 /* Semi join adds no restrictions for quals */
1739 jtitem->nonnullable_rels = NULL;
1740 break;
1741 case JOIN_FULL:
1742 /* The FULL JOIN's quals need their very own domain */
1744 root->join_domains = lappend(root->join_domains, fj_domain);
1745 jtitem->jdomain = fj_domain;
1746 /* Recurse, giving each side its own join domain */
1748 child_domain->jd_relids = NULL; /* filled by recursion */
1749 root->join_domains = lappend(root->join_domains, child_domain);
1752 jtitem,
1753 item_list);
1755 fj_domain->jd_relids = bms_copy(child_domain->jd_relids);
1757 child_domain->jd_relids = NULL; /* filled by recursion */
1758 root->join_domains = lappend(root->join_domains, child_domain);
1761 jtitem,
1762 item_list);
1764 /* Compute qualscope etc */
1765 fj_domain->jd_relids = bms_add_members(fj_domain->jd_relids,
1766 child_domain->jd_relids);
1767 parent_domain->jd_relids = bms_add_members(parent_domain->jd_relids,
1768 fj_domain->jd_relids);
1769 jtitem->qualscope = bms_union(left_item->qualscope,
1770 right_item->qualscope);
1771 Assert(j->rtindex != 0);
1772 parent_domain->jd_relids = bms_add_member(parent_domain->jd_relids,
1773 j->rtindex);
1774 jtitem->qualscope = bms_add_member(jtitem->qualscope,
1775 j->rtindex);
1776 root->outer_join_rels = bms_add_member(root->outer_join_rels,
1777 j->rtindex);
1779 left_item->qualscope);
1781 right_item->qualscope);
1782 jtitem->inner_join_rels = bms_union(left_item->inner_join_rels,
1783 right_item->inner_join_rels);
1784 jtitem->left_rels = left_item->qualscope;
1785 jtitem->right_rels = right_item->qualscope;
1786 /* each side is both outer and inner */
1787 jtitem->nonnullable_rels = jtitem->qualscope;
1788 break;
1789 default:
1790 /* JOIN_RIGHT was eliminated during reduce_outer_joins() */
1791 elog(ERROR, "unrecognized join type: %d",
1792 (int) j->jointype);
1793 leftjoinlist = rightjoinlist = NIL; /* keep compiler quiet */
1794 break;
1795 }
1796
1797 /*
1798 * Compute the output joinlist. We fold subproblems together except
1799 * at a FULL JOIN or where join_collapse_limit would be exceeded.
1800 */
1801 if (j->jointype == JOIN_FULL)
1802 {
1803 /* force the join order exactly at this node */
1805 }
1808 {
1809 /* OK to combine subproblems */
1811 }
1812 else
1813 {
1814 /* can't combine, but needn't force join order above here */
1815 Node *leftpart,
1816 *rightpart;
1817
1818 /* avoid creating useless 1-element sublists */
1819 if (list_length(leftjoinlist) == 1)
1821 else
1823 if (list_length(rightjoinlist) == 1)
1825 else
1828 }
1829 }
1830 else
1831 {
1832 elog(ERROR, "unrecognized node type: %d",
1833 (int) nodeTag(jtnode));
1834 joinlist = NIL; /* keep compiler quiet */
1835 }
1836
1837 /* Finally, we can add the new JoinTreeItem to item_list */
1839
1840 return joinlist;
1841}
#define palloc0_object(type)
Definition fe_memutils.h:75
int remaining
Definition informix.c:692
int join_collapse_limit
Definition initsplan.c:42
int from_collapse_limit
Definition initsplan.c:41
static void mark_rels_nulled_by_join(PlannerInfo *root, Index ojrelid, Relids lower_rels)
Definition initsplan.c:2053
@ JOIN_FULL
Definition nodes.h:305
#define llast(l)
Definition pg_list.h:198
#define list_make1(x1)
Definition pg_list.h:244
#define list_make2(x1, x2)
Definition pg_list.h:246

References Assert, bms_add_member(), bms_add_members(), bms_copy(), bms_make_singleton(), bms_union(), deconstruct_recurse(), elog, ERROR, fb(), from_collapse_limit, FromExpr::fromlist, IsA, j, JOIN_ANTI, join_collapse_limit, JOIN_FULL, JOIN_INNER, JOIN_LEFT, JOIN_SEMI, JoinTreeItem::jtnode, lappend(), lfirst, linitial, list_concat(), list_length(), list_make1, list_make2, llast, makeNode, mark_rels_nulled_by_join(), NIL, nodeTag, palloc0_object, remaining, and root.

Referenced by deconstruct_jointree(), and deconstruct_recurse().

◆ distribute_qual_to_rels()

static void distribute_qual_to_rels ( PlannerInfo root,
Node clause,
JoinTreeItem jtitem,
SpecialJoinInfo sjinfo,
Index  security_level,
Relids  qualscope,
Relids  ojscope,
Relids  outerjoin_nonnullable,
Relids  incompatible_relids,
bool  allow_equivalence,
bool  has_clone,
bool  is_clone,
List **  postponed_oj_qual_list 
)
static

Definition at line 2932 of file initsplan.c.

2944{
2945 Relids relids;
2946 bool is_pushed_down;
2947 bool pseudoconstant = false;
2948 bool maybe_equivalence;
2949 bool maybe_outer_join;
2951
2952 /*
2953 * Retrieve all relids mentioned within the clause.
2954 */
2955 relids = pull_varnos(root, clause);
2956
2957 /*
2958 * In ordinary SQL, a WHERE or JOIN/ON clause can't reference any rels
2959 * that aren't within its syntactic scope; however, if we pulled up a
2960 * LATERAL subquery then we might find such references in quals that have
2961 * been pulled up. We need to treat such quals as belonging to the join
2962 * level that includes every rel they reference. Although we could make
2963 * pull_up_subqueries() place such quals correctly to begin with, it's
2964 * easier to handle it here. When we find a clause that contains Vars
2965 * outside its syntactic scope, locate the nearest parent join level that
2966 * includes all the required rels and add the clause to that level's
2967 * lateral_clauses list. We'll process it when we reach that join level.
2968 */
2969 if (!bms_is_subset(relids, qualscope))
2970 {
2972
2973 Assert(root->hasLateralRTEs); /* shouldn't happen otherwise */
2974 Assert(sjinfo == NULL); /* mustn't postpone past outer join */
2975 for (pitem = jtitem->jti_parent; pitem; pitem = pitem->jti_parent)
2976 {
2977 if (bms_is_subset(relids, pitem->qualscope))
2978 {
2979 pitem->lateral_clauses = lappend(pitem->lateral_clauses,
2980 clause);
2981 return;
2982 }
2983
2984 /*
2985 * We should not be postponing any quals past an outer join. If
2986 * this Assert fires, pull_up_subqueries() messed up.
2987 */
2988 Assert(pitem->sjinfo == NULL);
2989 }
2990 elog(ERROR, "failed to postpone qual containing lateral reference");
2991 }
2992
2993 /*
2994 * If it's an outer-join clause, also check that relids is a subset of
2995 * ojscope. (This should not fail if the syntactic scope check passed.)
2996 */
2997 if (ojscope && !bms_is_subset(relids, ojscope))
2998 elog(ERROR, "JOIN qualification cannot refer to other relations");
2999
3000 /*
3001 * If the clause is variable-free, our normal heuristic for pushing it
3002 * down to just the mentioned rels doesn't work, because there are none.
3003 *
3004 * If the clause is an outer-join clause, we must force it to the OJ's
3005 * semantic level to preserve semantics.
3006 *
3007 * Otherwise, when the clause contains volatile functions, we force it to
3008 * be evaluated at its original syntactic level. This preserves the
3009 * expected semantics.
3010 *
3011 * When the clause contains no volatile functions either, it is actually a
3012 * pseudoconstant clause that will not change value during any one
3013 * execution of the plan, and hence can be used as a one-time qual in a
3014 * gating Result plan node. We put such a clause into the regular
3015 * RestrictInfo lists for the moment, but eventually createplan.c will
3016 * pull it out and make a gating Result node immediately above whatever
3017 * plan node the pseudoconstant clause is assigned to. It's usually best
3018 * to put a gating node as high in the plan tree as possible.
3019 */
3020 if (bms_is_empty(relids))
3021 {
3022 if (ojscope)
3023 {
3024 /* clause is attached to outer join, eval it there */
3025 relids = bms_copy(ojscope);
3026 /* mustn't use as gating qual, so don't mark pseudoconstant */
3027 }
3028 else if (contain_volatile_functions(clause))
3029 {
3030 /* eval at original syntactic level */
3031 relids = bms_copy(qualscope);
3032 /* again, can't mark pseudoconstant */
3033 }
3034 else
3035 {
3036 /*
3037 * If we are in the top-level join domain, we can push the qual to
3038 * the top of the plan tree. Otherwise, be conservative and eval
3039 * it at original syntactic level. (Ideally we'd push it to the
3040 * top of the current join domain in all cases, but that causes
3041 * problems if we later rearrange outer-join evaluation order.
3042 * Pseudoconstant quals below the top level are a pretty odd case,
3043 * so it's not clear that it's worth working hard on.)
3044 */
3045 if (jtitem->jdomain == (JoinDomain *) linitial(root->join_domains))
3046 relids = bms_copy(jtitem->jdomain->jd_relids);
3047 else
3048 relids = bms_copy(qualscope);
3049 /* mark as gating qual */
3050 pseudoconstant = true;
3051 /* tell createplan.c to check for gating quals */
3052 root->hasPseudoConstantQuals = true;
3053 }
3054 }
3055
3056 /*----------
3057 * Check to see if clause application must be delayed by outer-join
3058 * considerations.
3059 *
3060 * A word about is_pushed_down: we mark the qual as "pushed down" if
3061 * it is (potentially) applicable at a level different from its original
3062 * syntactic level. This flag is used to distinguish OUTER JOIN ON quals
3063 * from other quals pushed down to the same joinrel. The rules are:
3064 * WHERE quals and INNER JOIN quals: is_pushed_down = true.
3065 * Non-degenerate OUTER JOIN quals: is_pushed_down = false.
3066 * Degenerate OUTER JOIN quals: is_pushed_down = true.
3067 * A "degenerate" OUTER JOIN qual is one that doesn't mention the
3068 * non-nullable side, and hence can be pushed down into the nullable side
3069 * without changing the join result. It is correct to treat it as a
3070 * regular filter condition at the level where it is evaluated.
3071 *
3072 * Note: it is not immediately obvious that a simple boolean is enough
3073 * for this: if for some reason we were to attach a degenerate qual to
3074 * its original join level, it would need to be treated as an outer join
3075 * qual there. However, this cannot happen, because all the rels the
3076 * clause mentions must be in the outer join's min_righthand, therefore
3077 * the join it needs must be formed before the outer join; and we always
3078 * attach quals to the lowest level where they can be evaluated. But
3079 * if we were ever to re-introduce a mechanism for delaying evaluation
3080 * of "expensive" quals, this area would need work.
3081 *
3082 * Note: generally, use of is_pushed_down has to go through the macro
3083 * RINFO_IS_PUSHED_DOWN, because that flag alone is not always sufficient
3084 * to tell whether a clause must be treated as pushed-down in context.
3085 * This seems like another reason why it should perhaps be rethought.
3086 *----------
3087 */
3089 {
3090 /*
3091 * The qual is attached to an outer join and mentions (some of the)
3092 * rels on the nonnullable side, so it's not degenerate. If the
3093 * caller wants to postpone handling such clauses, just add it to
3094 * postponed_oj_qual_list and return. (The work we've done up to here
3095 * will have to be redone later, but there's not much of it.)
3096 */
3098 {
3100 return;
3101 }
3102
3103 /*
3104 * We can't use such a clause to deduce equivalence (the left and
3105 * right sides might be unequal above the join because one of them has
3106 * gone to NULL) ... but we might be able to use it for more limited
3107 * deductions, if it is mergejoinable. So consider adding it to the
3108 * lists of set-aside outer-join clauses.
3109 */
3110 is_pushed_down = false;
3111 maybe_equivalence = false;
3112 maybe_outer_join = true;
3113
3114 /*
3115 * Now force the qual to be evaluated exactly at the level of joining
3116 * corresponding to the outer join. We cannot let it get pushed down
3117 * into the nonnullable side, since then we'd produce no output rows,
3118 * rather than the intended single null-extended row, for any
3119 * nonnullable-side rows failing the qual.
3120 */
3121 Assert(ojscope);
3122 relids = ojscope;
3124 }
3125 else
3126 {
3127 /*
3128 * Normal qual clause or degenerate outer-join clause. Either way, we
3129 * can mark it as pushed-down.
3130 */
3131 is_pushed_down = true;
3132
3133 /*
3134 * It's possible that this is an IS NULL clause that's redundant with
3135 * a lower antijoin; if so we can just discard it. We need not test
3136 * in any of the other cases, because this will only be possible for
3137 * pushed-down clauses.
3138 */
3140 return;
3141
3142 /* Feed qual to the equivalence machinery, if allowed by caller */
3144
3145 /*
3146 * Since it doesn't mention the LHS, it's certainly not useful as a
3147 * set-aside OJ clause, even if it's in an OJ.
3148 */
3149 maybe_outer_join = false;
3150 }
3151
3152 /*
3153 * Build the RestrictInfo node itself.
3154 */
3156 (Expr *) clause,
3157 is_pushed_down,
3158 has_clone,
3159 is_clone,
3161 security_level,
3162 relids,
3163 incompatible_relids,
3165
3166 /*
3167 * If it's a join clause, add vars used in the clause to targetlists of
3168 * their relations, so that they will be emitted by the plan nodes that
3169 * scan those relations (else they won't be available at the join node!).
3170 *
3171 * Normally we mark the vars as needed at the join identified by "relids".
3172 * However, if this is a clone clause then ignore the outer-join relids in
3173 * that set. Otherwise, vars appearing in a cloned clause would end up
3174 * marked as having to propagate to the highest one of the commuting
3175 * joins, which would often be an overestimate. For such clauses, correct
3176 * var propagation is ensured by making ojscope include input rels from
3177 * both sides of the join.
3178 *
3179 * See also rebuild_joinclause_attr_needed, which has to partially repeat
3180 * this work after removal of an outer join.
3181 *
3182 * Note: if the clause gets absorbed into an EquivalenceClass then this
3183 * may be unnecessary, but for now we have to do it to cover the case
3184 * where the EC becomes ec_broken and we end up reinserting the original
3185 * clauses into the plan.
3186 */
3187 if (bms_membership(relids) == BMS_MULTIPLE)
3188 {
3189 List *vars = pull_var_clause(clause,
3194
3195 if (is_clone)
3196 where_needed = bms_intersect(relids, root->all_baserels);
3197 else
3198 where_needed = relids;
3200 list_free(vars);
3201 }
3202
3203 /*
3204 * We check "mergejoinability" of every clause, not only join clauses,
3205 * because we want to know about equivalences between vars of the same
3206 * relation, or between vars and consts.
3207 */
3209
3210 /*
3211 * If it is a true equivalence clause, send it to the EquivalenceClass
3212 * machinery. We do *not* attach it directly to any restriction or join
3213 * lists. The EC code will propagate it to the appropriate places later.
3214 *
3215 * If the clause has a mergejoinable operator, yet isn't an equivalence
3216 * because it is an outer-join clause, the EC code may still be able to do
3217 * something with it. We add it to appropriate lists for further
3218 * consideration later. Specifically:
3219 *
3220 * If it is a left or right outer-join qualification that relates the two
3221 * sides of the outer join (no funny business like leftvar1 = leftvar2 +
3222 * rightvar), we add it to root->left_join_clauses or
3223 * root->right_join_clauses according to which side the nonnullable
3224 * variable appears on.
3225 *
3226 * If it is a full outer-join qualification, we add it to
3227 * root->full_join_clauses. (Ideally we'd discard cases that aren't
3228 * leftvar = rightvar, as we do for left/right joins, but this routine
3229 * doesn't have the info needed to do that; and the current usage of the
3230 * full_join_clauses list doesn't require that, so it's not currently
3231 * worth complicating this routine's API to make it possible.)
3232 *
3233 * If none of the above hold, pass it off to
3234 * distribute_restrictinfo_to_rels().
3235 *
3236 * In all cases, it's important to initialize the left_ec and right_ec
3237 * fields of a mergejoinable clause, so that all possibly mergejoinable
3238 * expressions have representations in EquivalenceClasses. If
3239 * process_equivalence is successful, it will take care of that;
3240 * otherwise, we have to call initialize_mergeclause_eclasses to do it.
3241 */
3242 if (restrictinfo->mergeopfamilies)
3243 {
3245 {
3247 return;
3248 /* EC rejected it, so set left_ec/right_ec the hard way ... */
3249 if (restrictinfo->mergeopfamilies) /* EC might have changed this */
3251 /* ... and fall through to distribute_restrictinfo_to_rels */
3252 }
3253 else if (maybe_outer_join && restrictinfo->can_join)
3254 {
3255 /* we need to set up left_ec/right_ec the hard way */
3257 /* now see if it should go to any outer-join lists */
3258 Assert(sjinfo != NULL);
3259 if (bms_is_subset(restrictinfo->left_relids,
3261 !bms_overlap(restrictinfo->right_relids,
3263 {
3264 /* we have outervar = innervar */
3266
3267 ojcinfo->rinfo = restrictinfo;
3268 ojcinfo->sjinfo = sjinfo;
3269 root->left_join_clauses = lappend(root->left_join_clauses,
3270 ojcinfo);
3271 return;
3272 }
3273 if (bms_is_subset(restrictinfo->right_relids,
3275 !bms_overlap(restrictinfo->left_relids,
3277 {
3278 /* we have innervar = outervar */
3280
3281 ojcinfo->rinfo = restrictinfo;
3282 ojcinfo->sjinfo = sjinfo;
3283 root->right_join_clauses = lappend(root->right_join_clauses,
3284 ojcinfo);
3285 return;
3286 }
3287 if (sjinfo->jointype == JOIN_FULL)
3288 {
3289 /* FULL JOIN (above tests cannot match in this case) */
3291
3292 ojcinfo->rinfo = restrictinfo;
3293 ojcinfo->sjinfo = sjinfo;
3294 root->full_join_clauses = lappend(root->full_join_clauses,
3295 ojcinfo);
3296 return;
3297 }
3298 /* nope, so fall through to distribute_restrictinfo_to_rels */
3299 }
3300 else
3301 {
3302 /* we still need to set up left_ec/right_ec */
3304 }
3305 }
3306
3307 /* No EC special case applies, so push it into the clause lists */
3309}
@ BMS_MULTIPLE
Definition bitmapset.h:73
bool process_equivalence(PlannerInfo *root, RestrictInfo **p_restrictinfo, JoinDomain *jdomain)
Definition equivclass.c:179
void distribute_restrictinfo_to_rels(PlannerInfo *root, RestrictInfo *restrictinfo)
Definition initsplan.c:3578
static bool check_redundant_nullability_qual(PlannerInfo *root, Node *clause)
Definition initsplan.c:3322
void initialize_mergeclause_eclasses(PlannerInfo *root, RestrictInfo *restrictinfo)
Definition pathkeys.c:1463

References add_vars_to_targetlist(), Assert, bms_copy(), bms_intersect(), bms_is_empty, bms_is_subset(), bms_membership(), BMS_MULTIPLE, bms_overlap(), check_mergejoinable(), check_redundant_nullability_qual(), contain_volatile_functions(), distribute_restrictinfo_to_rels(), elog, ERROR, fb(), initialize_mergeclause_eclasses(), JOIN_FULL, SpecialJoinInfo::jointype, lappend(), linitial, list_free(), make_restrictinfo(), makeNode, process_equivalence(), pull_var_clause(), pull_varnos(), PVC_INCLUDE_PLACEHOLDERS, PVC_RECURSE_AGGREGATES, PVC_RECURSE_WINDOWFUNCS, JoinTreeItem::qualscope, root, and JoinTreeItem::sjinfo.

Referenced by distribute_quals_to_rels().

◆ distribute_quals_to_rels()

static void distribute_quals_to_rels ( PlannerInfo root,
List clauses,
JoinTreeItem jtitem,
SpecialJoinInfo sjinfo,
Index  security_level,
Relids  qualscope,
Relids  ojscope,
Relids  outerjoin_nonnullable,
Relids  incompatible_relids,
bool  allow_equivalence,
bool  has_clone,
bool  is_clone,
List **  postponed_oj_qual_list 
)
static

Definition at line 2854 of file initsplan.c.

2866{
2867 ListCell *lc;
2868
2869 foreach(lc, clauses)
2870 {
2871 Node *clause = (Node *) lfirst(lc);
2872
2874 jtitem,
2875 sjinfo,
2876 security_level,
2877 qualscope,
2878 ojscope,
2880 incompatible_relids,
2882 has_clone,
2883 is_clone,
2885 }
2886}
static void distribute_qual_to_rels(PlannerInfo *root, Node *clause, JoinTreeItem *jtitem, SpecialJoinInfo *sjinfo, Index security_level, Relids qualscope, Relids ojscope, Relids outerjoin_nonnullable, Relids incompatible_relids, bool allow_equivalence, bool has_clone, bool is_clone, List **postponed_oj_qual_list)
Definition initsplan.c:2932

References distribute_qual_to_rels(), fb(), lfirst, JoinTreeItem::qualscope, root, and JoinTreeItem::sjinfo.

Referenced by deconstruct_distribute(), deconstruct_distribute_oj_quals(), and process_security_barrier_quals().

◆ distribute_restrictinfo_to_rels()

void distribute_restrictinfo_to_rels ( PlannerInfo root,
RestrictInfo restrictinfo 
)

Definition at line 3578 of file initsplan.c.

3580{
3581 Relids relids = restrictinfo->required_relids;
3582
3583 if (!bms_is_empty(relids))
3584 {
3585 int relid;
3586
3587 if (bms_get_singleton_member(relids, &relid))
3588 {
3589 /*
3590 * There is only one relation participating in the clause, so it
3591 * is a restriction clause for that relation.
3592 */
3594 }
3595 else
3596 {
3597 /*
3598 * The clause is a join clause, since there is more than one rel
3599 * in its relid set.
3600 */
3601
3602 /*
3603 * Check for hashjoinable operators. (We don't bother setting the
3604 * hashjoin info except in true join clauses.)
3605 */
3607
3608 /*
3609 * Likewise, check if the clause is suitable to be used with a
3610 * Memoize node to cache inner tuples during a parameterized
3611 * nested loop.
3612 */
3614
3615 /*
3616 * Add clause to the join lists of all the relevant relations.
3617 */
3619 }
3620 }
3621 else
3622 {
3623 /*
3624 * clause references no rels, and therefore we have no place to attach
3625 * it. Shouldn't get here if callers are working properly.
3626 */
3627 elog(ERROR, "cannot cope with variable-free clause");
3628 }
3629}
static void add_base_clause_to_rel(PlannerInfo *root, Index relid, RestrictInfo *restrictinfo)
Definition initsplan.c:3367
void add_join_clause_to_rels(PlannerInfo *root, RestrictInfo *restrictinfo, Relids join_relids)
Definition joininfo.c:98

References add_base_clause_to_rel(), add_join_clause_to_rels(), bms_get_singleton_member(), bms_is_empty, check_hashjoinable(), check_memoizable(), elog, ERROR, fb(), and root.

Referenced by add_non_redundant_clauses(), distribute_qual_to_rels(), generate_base_implied_equalities_broken(), generate_base_implied_equalities_const(), process_implied_equality(), reconsider_outer_join_clauses(), and remove_leftjoinrel_from_query().

◆ extract_lateral_references()

static void extract_lateral_references ( PlannerInfo root,
RelOptInfo brel,
Index  rtindex 
)
static

Definition at line 1093 of file initsplan.c.

1094{
1095 RangeTblEntry *rte = root->simple_rte_array[rtindex];
1096 List *vars;
1097 List *newvars;
1099 ListCell *lc;
1100
1101 /* No cross-references are possible if it's not LATERAL */
1102 if (!rte->lateral)
1103 return;
1104
1105 /* Fetch the appropriate variables */
1106 if (rte->rtekind == RTE_RELATION)
1107 vars = pull_vars_of_level((Node *) rte->tablesample, 0);
1108 else if (rte->rtekind == RTE_SUBQUERY)
1109 vars = pull_vars_of_level((Node *) rte->subquery, 1);
1110 else if (rte->rtekind == RTE_FUNCTION)
1111 vars = pull_vars_of_level((Node *) rte->functions, 0);
1112 else if (rte->rtekind == RTE_TABLEFUNC)
1113 vars = pull_vars_of_level((Node *) rte->tablefunc, 0);
1114 else if (rte->rtekind == RTE_VALUES)
1115 vars = pull_vars_of_level((Node *) rte->values_lists, 0);
1116 else
1117 {
1118 Assert(false);
1119 return; /* keep compiler quiet */
1120 }
1121
1122 if (vars == NIL)
1123 return; /* nothing to do */
1124
1125 /* Copy each Var (or PlaceHolderVar) and adjust it to match our level */
1126 newvars = NIL;
1127 foreach(lc, vars)
1128 {
1129 Node *node = (Node *) lfirst(lc);
1130
1131 node = copyObject(node);
1132 if (IsA(node, Var))
1133 {
1134 Var *var = (Var *) node;
1135
1136 /* Adjustment is easy since it's just one node */
1137 var->varlevelsup = 0;
1138 }
1139 else if (IsA(node, PlaceHolderVar))
1140 {
1141 PlaceHolderVar *phv = (PlaceHolderVar *) node;
1142 int levelsup = phv->phlevelsup;
1143
1144 /* Have to work harder to adjust the contained expression too */
1145 if (levelsup != 0)
1146 IncrementVarSublevelsUp(node, -levelsup, 0);
1147
1148 /*
1149 * If we pulled the PHV out of a subquery RTE, its expression
1150 * needs to be preprocessed. subquery_planner() already did this
1151 * for level-zero PHVs in function and values RTEs, though.
1152 */
1153 if (levelsup > 0)
1154 phv->phexpr = preprocess_phv_expression(root, phv->phexpr);
1155 }
1156 else
1157 Assert(false);
1158 newvars = lappend(newvars, node);
1159 }
1160
1161 list_free(vars);
1162
1163 /*
1164 * We mark the Vars as being "needed" at the LATERAL RTE. This is a bit
1165 * of a cheat: a more formal approach would be to mark each one as needed
1166 * at the join of the LATERAL RTE with its source RTE. But it will work,
1167 * and it's much less tedious than computing a separate where_needed for
1168 * each Var.
1169 */
1171
1172 /*
1173 * Push Vars into their source relations' targetlists, and PHVs into
1174 * root->placeholder_list.
1175 */
1177
1178 /*
1179 * Remember the lateral references for rebuild_lateral_attr_needed and
1180 * create_lateral_join_info.
1181 */
1182 brel->lateral_vars = newvars;
1183}
@ RTE_VALUES
@ RTE_SUBQUERY
@ RTE_FUNCTION
@ RTE_TABLEFUNC
@ RTE_RELATION
Expr * preprocess_phv_expression(PlannerInfo *root, Expr *expr)
Definition planner.c:1500
void IncrementVarSublevelsUp(Node *node, int delta_sublevels_up, int min_sublevels_up)
Index varlevelsup
Definition primnodes.h:295
List * pull_vars_of_level(Node *node, int levelsup)
Definition var.c:339

References add_vars_to_targetlist(), Assert, bms_make_singleton(), copyObject, fb(), IncrementVarSublevelsUp(), IsA, lappend(), lfirst, list_free(), NIL, preprocess_phv_expression(), pull_vars_of_level(), root, RTE_FUNCTION, RTE_RELATION, RTE_SUBQUERY, RTE_TABLEFUNC, RTE_VALUES, and Var::varlevelsup.

Referenced by find_lateral_references().

◆ find_lateral_references()

void find_lateral_references ( PlannerInfo root)

Definition at line 1045 of file initsplan.c.

1046{
1047 Index rti;
1048
1049 /* We need do nothing if the query contains no LATERAL RTEs */
1050 if (!root->hasLateralRTEs)
1051 return;
1052
1053 /*
1054 * Examine all baserels (the rel array has been set up by now).
1055 */
1056 for (rti = 1; rti < root->simple_rel_array_size; rti++)
1057 {
1058 RelOptInfo *brel = root->simple_rel_array[rti];
1059
1060 /* there may be empty slots corresponding to non-baserel RTEs */
1061 if (brel == NULL)
1062 continue;
1063
1064 Assert(brel->relid == rti); /* sanity check on array */
1065
1066 /*
1067 * This bit is less obvious than it might look. We ignore appendrel
1068 * otherrels and consider only their parent baserels. In a case where
1069 * a LATERAL-containing UNION ALL subquery was pulled up, it is the
1070 * otherrel that is actually going to be in the plan. However, we
1071 * want to mark all its lateral references as needed by the parent,
1072 * because it is the parent's relid that will be used for join
1073 * planning purposes. And the parent's RTE will contain all the
1074 * lateral references we need to know, since the pulled-up member is
1075 * nothing but a copy of parts of the original RTE's subquery. We
1076 * could visit the parent's children instead and transform their
1077 * references back to the parent's relid, but it would be much more
1078 * complicated for no real gain. (Important here is that the child
1079 * members have not yet received any processing beyond being pulled
1080 * up.) Similarly, in appendrels created by inheritance expansion,
1081 * it's sufficient to look at the parent relation.
1082 */
1083
1084 /* ignore RTEs that are "other rels" */
1085 if (brel->reloptkind != RELOPT_BASEREL)
1086 continue;
1087
1089 }
1090}
static void extract_lateral_references(PlannerInfo *root, RelOptInfo *brel, Index rtindex)
Definition initsplan.c:1093

References Assert, extract_lateral_references(), fb(), RELOPT_BASEREL, and root.

Referenced by query_planner().

◆ get_eclass_for_sortgroupclause()

static EquivalenceClass * get_eclass_for_sortgroupclause ( PlannerInfo root,
SortGroupClause sgc,
Expr expr 
)
static

Definition at line 971 of file initsplan.c.

973{
974 Oid opfamily,
975 opcintype,
976 collation;
977 CompareType cmptype;
980
981 /* Punt if the group clause is not sortable */
982 if (!OidIsValid(sgc->sortop))
983 return NULL;
984
985 /* Find the operator in pg_amop --- failure shouldn't happen */
986 if (!get_ordering_op_properties(sgc->sortop,
987 &opfamily, &opcintype, &cmptype))
988 elog(ERROR, "operator %u is not a valid ordering operator",
989 sgc->sortop);
990
991 /* Because SortGroupClause doesn't carry collation, consult the expr */
992 collation = exprCollation((Node *) expr);
993
994 /*
995 * EquivalenceClasses need to contain opfamily lists based on the family
996 * membership of mergejoinable equality operators, which could belong to
997 * more than one opfamily. So we have to look up the opfamily's equality
998 * operator and get its membership.
999 */
1001 opcintype,
1002 opcintype,
1003 COMPARE_EQ);
1004 if (!OidIsValid(equality_op)) /* shouldn't happen */
1005 elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
1006 COMPARE_EQ, opcintype, opcintype, opfamily);
1008 if (!opfamilies) /* certainly should find some */
1009 elog(ERROR, "could not find opfamilies for equality operator %u",
1010 equality_op);
1011
1012 /* Now find a matching EquivalenceClass */
1013 return get_eclass_for_sort_expr(root, expr, opfamilies, opcintype,
1014 collation, sgc->tleSortGroupRef,
1015 NULL, false);
1016}
CompareType
Definition cmptype.h:32
@ COMPARE_EQ
Definition cmptype.h:36
EquivalenceClass * get_eclass_for_sort_expr(PlannerInfo *root, Expr *expr, List *opfamilies, Oid opcintype, Oid collation, Index sortref, Relids rel, bool create_it)
Definition equivclass.c:736
bool get_ordering_op_properties(Oid opno, Oid *opfamily, Oid *opcintype, CompareType *cmptype)
Definition lsyscache.c:261
Oid get_opfamily_member_for_cmptype(Oid opfamily, Oid lefttype, Oid righttype, CompareType cmptype)
Definition lsyscache.c:199

References COMPARE_EQ, elog, ERROR, exprCollation(), fb(), get_eclass_for_sort_expr(), get_mergejoin_opfamilies(), get_opfamily_member_for_cmptype(), get_ordering_op_properties(), OidIsValid, and root.

Referenced by create_grouping_expr_infos().

◆ get_join_domain_min_rels()

static Relids get_join_domain_min_rels ( PlannerInfo root,
Relids  domain_relids 
)
static

Definition at line 3876 of file initsplan.c.

3877{
3879 ListCell *lc;
3880
3881 /* Top-level join domain? */
3882 if (bms_equal(result, root->all_query_rels))
3883 return result;
3884
3885 /* Nope, look for lower outer joins that could potentially commute out */
3886 foreach(lc, root->join_info_list)
3887 {
3889
3890 if (sjinfo->jointype == JOIN_LEFT &&
3891 bms_is_member(sjinfo->ojrelid, result))
3892 {
3893 result = bms_del_member(result, sjinfo->ojrelid);
3895 }
3896 }
3897 return result;
3898}
Bitmapset * bms_del_members(Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:1145

References bms_copy(), bms_del_member(), bms_del_members(), bms_equal(), bms_is_member(), fb(), JOIN_LEFT, SpecialJoinInfo::jointype, lfirst, SpecialJoinInfo::ojrelid, result, root, JoinTreeItem::sjinfo, and SpecialJoinInfo::syn_righthand.

Referenced by process_implied_equality().

◆ is_partial_agg_memory_risky()

static bool is_partial_agg_memory_risky ( PlannerInfo root)
static

Definition at line 730 of file initsplan.c.

731{
732 ListCell *lc;
733
734 foreach(lc, root->aggtransinfos)
735 {
737
738 if (transinfo->aggtransspace < 0)
739 return true;
740 }
741
742 return false;
743}

References fb(), lfirst_node, and root.

Referenced by setup_eager_aggregation().

◆ make_outerjoininfo()

static SpecialJoinInfo * make_outerjoininfo ( PlannerInfo root,
Relids  left_rels,
Relids  right_rels,
Relids  inner_join_rels,
JoinType  jointype,
Index  ojrelid,
List clause 
)
static

Definition at line 2095 of file initsplan.c.

2100{
2104 Relids min_lefthand;
2105 Relids min_righthand;
2106 Relids commute_below_l;
2107 Relids commute_below_r;
2108 ListCell *l;
2109
2110 /*
2111 * We should not see RIGHT JOIN here because left/right were switched
2112 * earlier
2113 */
2114 Assert(jointype != JOIN_INNER);
2115 Assert(jointype != JOIN_RIGHT);
2116
2117 /*
2118 * Presently the executor cannot support FOR [KEY] UPDATE/SHARE marking of
2119 * rels appearing on the nullable side of an outer join. (It's somewhat
2120 * unclear what that would mean, anyway: what should we mark when a result
2121 * row is generated from no element of the nullable relation?) So,
2122 * complain if any nullable rel is FOR [KEY] UPDATE/SHARE.
2123 *
2124 * You might be wondering why this test isn't made far upstream in the
2125 * parser. It's because the parser hasn't got enough info --- consider
2126 * FOR UPDATE applied to a view. Only after rewriting and flattening do
2127 * we know whether the view contains an outer join.
2128 *
2129 * We use the original RowMarkClause list here; the PlanRowMark list would
2130 * list everything.
2131 */
2132 foreach(l, root->parse->rowMarks)
2133 {
2134 RowMarkClause *rc = (RowMarkClause *) lfirst(l);
2135
2136 if (bms_is_member(rc->rti, right_rels) ||
2137 (jointype == JOIN_FULL && bms_is_member(rc->rti, left_rels)))
2138 ereport(ERROR,
2140 /*------
2141 translator: %s is a SQL row locking clause such as FOR UPDATE */
2142 errmsg("%s cannot be applied to the nullable side of an outer join",
2143 LCS_asString(rc->strength))));
2144 }
2145
2146 sjinfo->syn_lefthand = left_rels;
2147 sjinfo->syn_righthand = right_rels;
2148 sjinfo->jointype = jointype;
2149 sjinfo->ojrelid = ojrelid;
2150 /* these fields may get added to later: */
2151 sjinfo->commute_above_l = NULL;
2152 sjinfo->commute_above_r = NULL;
2153 sjinfo->commute_below_l = NULL;
2154 sjinfo->commute_below_r = NULL;
2155
2156 compute_semijoin_info(root, sjinfo, clause);
2157
2158 /* If it's a full join, no need to be very smart */
2159 if (jointype == JOIN_FULL)
2160 {
2161 sjinfo->min_lefthand = bms_copy(left_rels);
2162 sjinfo->min_righthand = bms_copy(right_rels);
2163 sjinfo->lhs_strict = false; /* don't care about this */
2164 return sjinfo;
2165 }
2166
2167 /*
2168 * Retrieve all relids mentioned within the join clause.
2169 */
2170 clause_relids = pull_varnos(root, (Node *) clause);
2171
2172 /*
2173 * For which relids is the clause strict, ie, it cannot succeed if the
2174 * rel's columns are all NULL?
2175 */
2177
2178 /* Remember whether the clause is strict for any LHS relations */
2179 sjinfo->lhs_strict = bms_overlap(strict_relids, left_rels);
2180
2181 /*
2182 * Required LHS always includes the LHS rels mentioned in the clause. We
2183 * may have to add more rels based on lower outer joins; see below.
2184 */
2185 min_lefthand = bms_intersect(clause_relids, left_rels);
2186
2187 /*
2188 * Similarly for required RHS. But here, we must also include any lower
2189 * inner joins, to ensure we don't try to commute with any of them.
2190 */
2191 min_righthand = bms_int_members(bms_union(clause_relids, inner_join_rels),
2192 right_rels);
2193
2194 /*
2195 * Now check previous outer joins for ordering restrictions.
2196 *
2197 * commute_below_l and commute_below_r accumulate the relids of lower
2198 * outer joins that we think this one can commute with. These decisions
2199 * are just tentative within this loop, since we might find an
2200 * intermediate outer join that prevents commutation. Surviving relids
2201 * will get merged into the SpecialJoinInfo structs afterwards.
2202 */
2203 commute_below_l = commute_below_r = NULL;
2204 foreach(l, root->join_info_list)
2205 {
2207 bool have_unsafe_phvs;
2208
2209 /*
2210 * A full join is an optimization barrier: we can't associate into or
2211 * out of it. Hence, if it overlaps either LHS or RHS of the current
2212 * rel, expand that side's min relset to cover the whole full join.
2213 */
2214 if (otherinfo->jointype == JOIN_FULL)
2215 {
2216 Assert(otherinfo->ojrelid != 0);
2217 if (bms_overlap(left_rels, otherinfo->syn_lefthand) ||
2218 bms_overlap(left_rels, otherinfo->syn_righthand))
2219 {
2220 min_lefthand = bms_add_members(min_lefthand,
2221 otherinfo->syn_lefthand);
2222 min_lefthand = bms_add_members(min_lefthand,
2223 otherinfo->syn_righthand);
2224 min_lefthand = bms_add_member(min_lefthand,
2225 otherinfo->ojrelid);
2226 }
2227 if (bms_overlap(right_rels, otherinfo->syn_lefthand) ||
2228 bms_overlap(right_rels, otherinfo->syn_righthand))
2229 {
2230 min_righthand = bms_add_members(min_righthand,
2231 otherinfo->syn_lefthand);
2232 min_righthand = bms_add_members(min_righthand,
2233 otherinfo->syn_righthand);
2234 min_righthand = bms_add_member(min_righthand,
2235 otherinfo->ojrelid);
2236 }
2237 /* Needn't do anything else with the full join */
2238 continue;
2239 }
2240
2241 /*
2242 * If our join condition contains any PlaceHolderVars that need to be
2243 * evaluated above the lower OJ, then we can't commute with it.
2244 */
2245 if (otherinfo->ojrelid != 0)
2248 (Node *) clause,
2249 otherinfo->ojrelid);
2250 else
2251 have_unsafe_phvs = false;
2252
2253 /*
2254 * For a lower OJ in our LHS, if our join condition uses the lower
2255 * join's RHS and is not strict for that rel, we must preserve the
2256 * ordering of the two OJs, so add lower OJ's full syntactic relset to
2257 * min_lefthand. (We must use its full syntactic relset, not just its
2258 * min_lefthand + min_righthand. This is because there might be other
2259 * OJs below this one that this one can commute with, but we cannot
2260 * commute with them if we don't with this one.) Also, if we have
2261 * unsafe PHVs or the current join is a semijoin or antijoin, we must
2262 * preserve ordering regardless of strictness.
2263 *
2264 * Note: I believe we have to insist on being strict for at least one
2265 * rel in the lower OJ's min_righthand, not its whole syn_righthand.
2266 *
2267 * When we don't need to preserve ordering, check to see if outer join
2268 * identity 3 applies, and if so, remove the lower OJ's ojrelid from
2269 * our min_lefthand so that commutation is allowed.
2270 */
2271 if (bms_overlap(left_rels, otherinfo->syn_righthand))
2272 {
2273 if (bms_overlap(clause_relids, otherinfo->syn_righthand) &&
2275 jointype == JOIN_SEMI || jointype == JOIN_ANTI ||
2276 !bms_overlap(strict_relids, otherinfo->min_righthand)))
2277 {
2278 /* Preserve ordering */
2279 min_lefthand = bms_add_members(min_lefthand,
2280 otherinfo->syn_lefthand);
2281 min_lefthand = bms_add_members(min_lefthand,
2282 otherinfo->syn_righthand);
2283 if (otherinfo->ojrelid != 0)
2284 min_lefthand = bms_add_member(min_lefthand,
2285 otherinfo->ojrelid);
2286 }
2287 else if (jointype == JOIN_LEFT &&
2288 otherinfo->jointype == JOIN_LEFT &&
2289 bms_overlap(strict_relids, otherinfo->min_righthand) &&
2290 !bms_overlap(clause_relids, otherinfo->syn_lefthand))
2291 {
2292 /* Identity 3 applies, so remove the ordering restriction */
2293 min_lefthand = bms_del_member(min_lefthand, otherinfo->ojrelid);
2294 /* Record the (still tentative) commutability relationship */
2295 commute_below_l =
2296 bms_add_member(commute_below_l, otherinfo->ojrelid);
2297 }
2298 }
2299
2300 /*
2301 * For a lower OJ in our RHS, if our join condition does not use the
2302 * lower join's RHS and the lower OJ's join condition is strict, we
2303 * can interchange the ordering of the two OJs; otherwise we must add
2304 * the lower OJ's full syntactic relset to min_righthand.
2305 *
2306 * Also, if our join condition does not use the lower join's LHS
2307 * either, force the ordering to be preserved. Otherwise we can end
2308 * up with SpecialJoinInfos with identical min_righthands, which can
2309 * confuse join_is_legal (see discussion in backend/optimizer/README).
2310 *
2311 * Also, we must preserve ordering anyway if we have unsafe PHVs, or
2312 * if either this join or the lower OJ is a semijoin or antijoin.
2313 *
2314 * When we don't need to preserve ordering, check to see if outer join
2315 * identity 3 applies, and if so, remove the lower OJ's ojrelid from
2316 * our min_righthand so that commutation is allowed.
2317 */
2318 if (bms_overlap(right_rels, otherinfo->syn_righthand))
2319 {
2320 if (bms_overlap(clause_relids, otherinfo->syn_righthand) ||
2321 !bms_overlap(clause_relids, otherinfo->min_lefthand) ||
2323 jointype == JOIN_SEMI ||
2324 jointype == JOIN_ANTI ||
2325 otherinfo->jointype == JOIN_SEMI ||
2326 otherinfo->jointype == JOIN_ANTI ||
2327 !otherinfo->lhs_strict)
2328 {
2329 /* Preserve ordering */
2330 min_righthand = bms_add_members(min_righthand,
2331 otherinfo->syn_lefthand);
2332 min_righthand = bms_add_members(min_righthand,
2333 otherinfo->syn_righthand);
2334 if (otherinfo->ojrelid != 0)
2335 min_righthand = bms_add_member(min_righthand,
2336 otherinfo->ojrelid);
2337 }
2338 else if (jointype == JOIN_LEFT &&
2339 otherinfo->jointype == JOIN_LEFT &&
2340 otherinfo->lhs_strict)
2341 {
2342 /* Identity 3 applies, so remove the ordering restriction */
2343 min_righthand = bms_del_member(min_righthand,
2344 otherinfo->ojrelid);
2345 /* Record the (still tentative) commutability relationship */
2346 commute_below_r =
2347 bms_add_member(commute_below_r, otherinfo->ojrelid);
2348 }
2349 }
2350 }
2351
2352 /*
2353 * Examine PlaceHolderVars. If a PHV is supposed to be evaluated within
2354 * this join's nullable side, then ensure that min_righthand contains the
2355 * full eval_at set of the PHV. This ensures that the PHV actually can be
2356 * evaluated within the RHS. Note that this works only because we should
2357 * already have determined the final eval_at level for any PHV
2358 * syntactically within this join.
2359 */
2360 foreach(l, root->placeholder_list)
2361 {
2363 Relids ph_syn_level = phinfo->ph_var->phrels;
2364
2365 /* Ignore placeholder if it didn't syntactically come from RHS */
2366 if (!bms_is_subset(ph_syn_level, right_rels))
2367 continue;
2368
2369 /* Else, prevent join from being formed before we eval the PHV */
2370 min_righthand = bms_add_members(min_righthand, phinfo->ph_eval_at);
2371 }
2372
2373 /*
2374 * If we found nothing to put in min_lefthand, punt and make it the full
2375 * LHS, to avoid having an empty min_lefthand which will confuse later
2376 * processing. (We don't try to be smart about such cases, just correct.)
2377 * Likewise for min_righthand.
2378 */
2379 if (bms_is_empty(min_lefthand))
2380 min_lefthand = bms_copy(left_rels);
2381 if (bms_is_empty(min_righthand))
2382 min_righthand = bms_copy(right_rels);
2383
2384 /* Now they'd better be nonempty */
2385 Assert(!bms_is_empty(min_lefthand));
2386 Assert(!bms_is_empty(min_righthand));
2387 /* Shouldn't overlap either */
2388 Assert(!bms_overlap(min_lefthand, min_righthand));
2389
2390 sjinfo->min_lefthand = min_lefthand;
2391 sjinfo->min_righthand = min_righthand;
2392
2393 /*
2394 * Now that we've identified the correct min_lefthand and min_righthand,
2395 * any commute_below_l or commute_below_r relids that have not gotten
2396 * added back into those sets (due to intervening outer joins) are indeed
2397 * commutable with this one.
2398 *
2399 * First, delete any subsequently-added-back relids (this is easier than
2400 * maintaining commute_below_l/r precisely through all the above).
2401 */
2402 commute_below_l = bms_del_members(commute_below_l, min_lefthand);
2403 commute_below_r = bms_del_members(commute_below_r, min_righthand);
2404
2405 /* Anything left? */
2406 if (commute_below_l || commute_below_r)
2407 {
2408 /* Yup, so we must update the derived data in the SpecialJoinInfos */
2409 sjinfo->commute_below_l = commute_below_l;
2410 sjinfo->commute_below_r = commute_below_r;
2411 foreach(l, root->join_info_list)
2412 {
2414
2415 if (bms_is_member(otherinfo->ojrelid, commute_below_l))
2417 bms_add_member(otherinfo->commute_above_l, ojrelid);
2418 else if (bms_is_member(otherinfo->ojrelid, commute_below_r))
2419 otherinfo->commute_above_r =
2420 bms_add_member(otherinfo->commute_above_r, ojrelid);
2421 }
2422 }
2423
2424 return sjinfo;
2425}
Bitmapset * bms_int_members(Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:1093
Relids find_nonnullable_rels(Node *clause)
Definition clauses.c:1474
int errcode(int sqlerrcode)
Definition elog.c:874
#define ereport(elevel,...)
Definition elog.h:152
static void compute_semijoin_info(PlannerInfo *root, SpecialJoinInfo *sjinfo, List *clause)
Definition initsplan.c:2435
@ JOIN_RIGHT
Definition nodes.h:306
static char * errmsg
const char * LCS_asString(LockClauseStrength strength)
Definition analyze.c:3704
bool contain_placeholder_references_to(PlannerInfo *root, Node *clause, int relid)
LockClauseStrength strength
Relids commute_above_l
Definition pathnodes.h:3232

References Assert, bms_add_member(), bms_add_members(), bms_copy(), bms_del_member(), bms_del_members(), bms_int_members(), bms_intersect(), bms_is_empty, bms_is_member(), bms_is_subset(), bms_overlap(), bms_union(), SpecialJoinInfo::commute_above_l, SpecialJoinInfo::commute_above_r, SpecialJoinInfo::commute_below_l, SpecialJoinInfo::commute_below_r, compute_semijoin_info(), contain_placeholder_references_to(), ereport, errcode(), errmsg, ERROR, fb(), find_nonnullable_rels(), JoinTreeItem::inner_join_rels, JOIN_ANTI, JOIN_FULL, JOIN_INNER, JOIN_LEFT, JOIN_RIGHT, JOIN_SEMI, SpecialJoinInfo::jointype, LCS_asString(), JoinTreeItem::left_rels, lfirst, SpecialJoinInfo::lhs_strict, makeNode, SpecialJoinInfo::min_lefthand, SpecialJoinInfo::min_righthand, SpecialJoinInfo::ojrelid, pull_varnos(), JoinTreeItem::right_rels, root, RowMarkClause::rti, JoinTreeItem::sjinfo, RowMarkClause::strength, SpecialJoinInfo::syn_lefthand, and SpecialJoinInfo::syn_righthand.

Referenced by deconstruct_distribute().

◆ mark_rels_nulled_by_join()

static void mark_rels_nulled_by_join ( PlannerInfo root,
Index  ojrelid,
Relids  lower_rels 
)
static

Definition at line 2053 of file initsplan.c.

2055{
2056 int relid = -1;
2057
2058 while ((relid = bms_next_member(lower_rels, relid)) > 0)
2059 {
2060 RelOptInfo *rel = root->simple_rel_array[relid];
2061
2062 /* ignore the RTE_GROUP RTE */
2063 if (relid == root->group_rtindex)
2064 continue;
2065
2066 if (rel == NULL) /* must be an outer join */
2067 {
2068 Assert(bms_is_member(relid, root->outer_join_rels));
2069 continue;
2070 }
2071 rel->nulling_relids = bms_add_member(rel->nulling_relids, ojrelid);
2072 }
2073}
Relids nulling_relids
Definition pathnodes.h:1085

References Assert, bms_add_member(), bms_is_member(), bms_next_member(), fb(), RelOptInfo::nulling_relids, and root.

Referenced by deconstruct_recurse().

◆ match_foreign_keys_to_quals()

void match_foreign_keys_to_quals ( PlannerInfo root)

Definition at line 3982 of file initsplan.c.

3983{
3984 List *newlist = NIL;
3985 ListCell *lc;
3986
3987 foreach(lc, root->fkey_list)
3988 {
3992 int colno;
3993
3994 /*
3995 * Either relid might identify a rel that is in the query's rtable but
3996 * isn't referenced by the jointree, or has been removed by join
3997 * removal, so that it won't have a RelOptInfo. Hence don't use
3998 * find_base_rel() here. We can ignore such FKs.
3999 */
4000 if (fkinfo->con_relid >= root->simple_rel_array_size ||
4001 fkinfo->ref_relid >= root->simple_rel_array_size)
4002 continue; /* just paranoia */
4003 con_rel = root->simple_rel_array[fkinfo->con_relid];
4004 if (con_rel == NULL)
4005 continue;
4006 ref_rel = root->simple_rel_array[fkinfo->ref_relid];
4007 if (ref_rel == NULL)
4008 continue;
4009
4010 /*
4011 * Ignore FK unless both rels are baserels. This gets rid of FKs that
4012 * link to inheritance child rels (otherrels).
4013 */
4014 if (con_rel->reloptkind != RELOPT_BASEREL ||
4015 ref_rel->reloptkind != RELOPT_BASEREL)
4016 continue;
4017
4018 /*
4019 * Scan the columns and try to match them to eclasses and quals.
4020 *
4021 * Note: for simple inner joins, any match should be in an eclass.
4022 * "Loose" quals that syntactically match an FK equality must have
4023 * been rejected for EC status because they are outer-join quals or
4024 * similar. We can still consider them to match the FK.
4025 */
4026 for (colno = 0; colno < fkinfo->nkeys; colno++)
4027 {
4028 EquivalenceClass *ec;
4030 ref_attno;
4031 Oid fpeqop;
4032 ListCell *lc2;
4033
4035 /* Don't bother looking for loose quals if we got an EC match */
4036 if (ec != NULL)
4037 {
4038 fkinfo->nmatched_ec++;
4039 if (ec->ec_has_const)
4040 fkinfo->nconst_ec++;
4041 continue;
4042 }
4043
4044 /*
4045 * Scan joininfo list for relevant clauses. Either rel's joininfo
4046 * list would do equally well; we use con_rel's.
4047 */
4048 con_attno = fkinfo->conkey[colno];
4049 ref_attno = fkinfo->confkey[colno];
4050 fpeqop = InvalidOid; /* we'll look this up only if needed */
4051
4052 foreach(lc2, con_rel->joininfo)
4053 {
4054 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc2);
4055 OpExpr *clause = (OpExpr *) rinfo->clause;
4056 Var *leftvar;
4057 Var *rightvar;
4058
4059 /* Only binary OpExprs are useful for consideration */
4060 if (!IsA(clause, OpExpr) ||
4061 list_length(clause->args) != 2)
4062 continue;
4063 leftvar = (Var *) get_leftop((Expr *) clause);
4064 rightvar = (Var *) get_rightop((Expr *) clause);
4065
4066 /* Operands must be Vars, possibly with RelabelType */
4067 while (leftvar && IsA(leftvar, RelabelType))
4068 leftvar = (Var *) ((RelabelType *) leftvar)->arg;
4069 if (!(leftvar && IsA(leftvar, Var)))
4070 continue;
4071 while (rightvar && IsA(rightvar, RelabelType))
4072 rightvar = (Var *) ((RelabelType *) rightvar)->arg;
4073 if (!(rightvar && IsA(rightvar, Var)))
4074 continue;
4075
4076 /* Now try to match the vars to the current foreign key cols */
4077 if (fkinfo->ref_relid == leftvar->varno &&
4078 ref_attno == leftvar->varattno &&
4079 fkinfo->con_relid == rightvar->varno &&
4080 con_attno == rightvar->varattno)
4081 {
4082 /* Vars match, but is it the right operator? */
4083 if (clause->opno == fkinfo->conpfeqop[colno])
4084 {
4085 fkinfo->rinfos[colno] = lappend(fkinfo->rinfos[colno],
4086 rinfo);
4087 fkinfo->nmatched_ri++;
4088 }
4089 }
4090 else if (fkinfo->ref_relid == rightvar->varno &&
4091 ref_attno == rightvar->varattno &&
4092 fkinfo->con_relid == leftvar->varno &&
4093 con_attno == leftvar->varattno)
4094 {
4095 /*
4096 * Reverse match, must check commutator operator. Look it
4097 * up if we didn't already. (In the worst case we might
4098 * do multiple lookups here, but that would require an FK
4099 * equality operator without commutator, which is
4100 * unlikely.)
4101 */
4102 if (!OidIsValid(fpeqop))
4103 fpeqop = get_commutator(fkinfo->conpfeqop[colno]);
4104 if (clause->opno == fpeqop)
4105 {
4106 fkinfo->rinfos[colno] = lappend(fkinfo->rinfos[colno],
4107 rinfo);
4108 fkinfo->nmatched_ri++;
4109 }
4110 }
4111 }
4112 /* If we found any matching loose quals, count col as matched */
4113 if (fkinfo->rinfos[colno])
4114 fkinfo->nmatched_rcols++;
4115 }
4116
4117 /*
4118 * Currently, we drop multicolumn FKs that aren't fully matched to the
4119 * query. Later we might figure out how to derive some sort of
4120 * estimate from them, in which case this test should be weakened to
4121 * "if ((fkinfo->nmatched_ec + fkinfo->nmatched_rcols) > 0)".
4122 */
4123 if ((fkinfo->nmatched_ec + fkinfo->nmatched_rcols) == fkinfo->nkeys)
4125 }
4126 /* Replace fkey_list, thereby discarding any useless entries */
4127 root->fkey_list = newlist;
4128}
int16 AttrNumber
Definition attnum.h:21
EquivalenceClass * match_eclasses_to_foreign_key_col(PlannerInfo *root, ForeignKeyOptInfo *fkinfo, int colno)
static Node * get_rightop(const void *clause)
Definition nodeFuncs.h:95
static Node * get_leftop(const void *clause)
Definition nodeFuncs.h:83
Expr * clause
Definition pathnodes.h:2901

References OpExpr::args, RestrictInfo::clause, EquivalenceClass::ec_has_const, fb(), get_commutator(), get_leftop(), get_rightop(), InvalidOid, IsA, lappend(), lfirst, list_length(), match_eclasses_to_foreign_key_col(), NIL, OidIsValid, OpExpr::opno, RELOPT_BASEREL, and root.

Referenced by query_planner().

◆ process_implied_equality()

RestrictInfo * process_implied_equality ( PlannerInfo root,
Oid  opno,
Oid  collation,
Expr item1,
Expr item2,
Relids  qualscope,
Index  security_level,
bool  both_const 
)

Definition at line 3663 of file initsplan.c.

3671{
3673 Node *clause;
3674 Relids relids;
3675 bool pseudoconstant = false;
3676
3677 /*
3678 * Build the new clause. Copy to ensure it shares no substructure with
3679 * original (this is necessary in case there are subselects in there...)
3680 */
3681 clause = (Node *) make_opclause(opno,
3682 BOOLOID, /* opresulttype */
3683 false, /* opretset */
3686 InvalidOid,
3687 collation);
3688
3689 /* If both constant, try to reduce to a boolean constant. */
3690 if (both_const)
3691 {
3692 clause = eval_const_expressions(root, clause);
3693
3694 /* If we produced const TRUE, just drop the clause */
3695 if (clause && IsA(clause, Const))
3696 {
3697 Const *cclause = (Const *) clause;
3698
3699 Assert(cclause->consttype == BOOLOID);
3700 if (!cclause->constisnull && DatumGetBool(cclause->constvalue))
3701 return NULL;
3702 }
3703 }
3704
3705 /*
3706 * The rest of this is a very cut-down version of distribute_qual_to_rels.
3707 * We can skip most of the work therein, but there are a couple of special
3708 * cases we still have to handle.
3709 *
3710 * Retrieve all relids mentioned within the possibly-simplified clause.
3711 */
3712 relids = pull_varnos(root, clause);
3713 Assert(bms_is_subset(relids, qualscope));
3714
3715 /*
3716 * If the clause is variable-free, our normal heuristic for pushing it
3717 * down to just the mentioned rels doesn't work, because there are none.
3718 * Apply it as a gating qual at the appropriate level (see comments for
3719 * get_join_domain_min_rels).
3720 */
3721 if (bms_is_empty(relids))
3722 {
3723 /* eval at join domain's safe level */
3724 relids = get_join_domain_min_rels(root, qualscope);
3725 /* mark as gating qual */
3726 pseudoconstant = true;
3727 /* tell createplan.c to check for gating quals */
3728 root->hasPseudoConstantQuals = true;
3729 }
3730
3731 /*
3732 * Build the RestrictInfo node itself.
3733 */
3735 (Expr *) clause,
3736 true, /* is_pushed_down */
3737 false, /* !has_clone */
3738 false, /* !is_clone */
3740 security_level,
3741 relids,
3742 NULL, /* incompatible_relids */
3743 NULL); /* outer_relids */
3744
3745 /*
3746 * If it's a join clause, add vars used in the clause to targetlists of
3747 * their relations, so that they will be emitted by the plan nodes that
3748 * scan those relations (else they won't be available at the join node!).
3749 *
3750 * Typically, we'd have already done this when the component expressions
3751 * were first seen by distribute_qual_to_rels; but it is possible that
3752 * some of the Vars could have missed having that done because they only
3753 * appeared in single-relation clauses originally. So do it here for
3754 * safety.
3755 *
3756 * See also rebuild_joinclause_attr_needed, which has to partially repeat
3757 * this work after removal of an outer join. (Since we will put this
3758 * clause into the joininfo lists, that function needn't do any extra work
3759 * to find it.)
3760 */
3761 if (bms_membership(relids) == BMS_MULTIPLE)
3762 {
3763 List *vars = pull_var_clause(clause,
3767
3769 list_free(vars);
3770 }
3771
3772 /*
3773 * Check mergejoinability. This will usually succeed, since the op came
3774 * from an EquivalenceClass; but we could have reduced the original clause
3775 * to a constant.
3776 */
3778
3779 /*
3780 * Note we don't do initialize_mergeclause_eclasses(); the caller can
3781 * handle that much more cheaply than we can. It's okay to call
3782 * distribute_restrictinfo_to_rels() before that happens.
3783 */
3784
3785 /*
3786 * Push the new clause into all the appropriate restrictinfo lists.
3787 */
3789
3790 return restrictinfo;
3791}
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition clauses.c:2498
static Relids get_join_domain_min_rels(PlannerInfo *root, Relids domain_relids)
Definition initsplan.c:3876

References add_vars_to_targetlist(), Assert, bms_is_empty, bms_is_subset(), bms_membership(), BMS_MULTIPLE, check_mergejoinable(), copyObject, DatumGetBool(), distribute_restrictinfo_to_rels(), eval_const_expressions(), fb(), get_join_domain_min_rels(), InvalidOid, IsA, list_free(), make_opclause(), make_restrictinfo(), pull_var_clause(), pull_varnos(), PVC_INCLUDE_PLACEHOLDERS, PVC_RECURSE_AGGREGATES, PVC_RECURSE_WINDOWFUNCS, JoinTreeItem::qualscope, and root.

Referenced by generate_base_implied_equalities_const(), and generate_base_implied_equalities_no_const().

◆ process_security_barrier_quals()

static void process_security_barrier_quals ( PlannerInfo root,
int  rti,
JoinTreeItem jtitem 
)
static

Definition at line 2003 of file initsplan.c.

2005{
2006 RangeTblEntry *rte = root->simple_rte_array[rti];
2007 Index security_level = 0;
2008 ListCell *lc;
2009
2010 /*
2011 * Each element of the securityQuals list has been preprocessed into an
2012 * implicitly-ANDed list of clauses. All the clauses in a given sublist
2013 * should get the same security level, but successive sublists get higher
2014 * levels.
2015 */
2016 foreach(lc, rte->securityQuals)
2017 {
2018 List *qualset = (List *) lfirst(lc);
2019
2020 /*
2021 * We cheat to the extent of passing ojscope = qualscope rather than
2022 * its more logical value of NULL. The only effect this has is to
2023 * force a Var-free qual to be evaluated at the rel rather than being
2024 * pushed up to top of tree, which we don't want.
2025 */
2027 jtitem,
2028 NULL,
2029 security_level,
2030 jtitem->qualscope,
2031 jtitem->qualscope,
2032 NULL,
2033 NULL,
2034 true,
2035 false, false, /* not clones */
2036 NULL);
2037 security_level++;
2038 }
2039
2040 /* Assert that qual_security_level is higher than anything we just used */
2041 Assert(security_level <= root->qual_security_level);
2042}

References Assert, distribute_quals_to_rels(), fb(), lfirst, and root.

Referenced by deconstruct_distribute().

◆ rebuild_joinclause_attr_needed()

void rebuild_joinclause_attr_needed ( PlannerInfo root)

Definition at line 3910 of file initsplan.c.

3911{
3912 /*
3913 * We must examine all join clauses, but there's no value in processing
3914 * any join clause more than once. So it's slightly annoying that we have
3915 * to find them via the per-base-relation joininfo lists. Avoid duplicate
3916 * processing by tracking the rinfo_serial numbers of join clauses we've
3917 * already seen. (This doesn't work for is_clone clauses, so we must
3918 * waste effort on them.)
3919 */
3921 Index rti;
3922
3923 /* Scan all baserels for join clauses */
3924 for (rti = 1; rti < root->simple_rel_array_size; rti++)
3925 {
3926 RelOptInfo *brel = root->simple_rel_array[rti];
3927 ListCell *lc;
3928
3929 if (brel == NULL)
3930 continue;
3931 if (brel->reloptkind != RELOPT_BASEREL)
3932 continue;
3933
3934 foreach(lc, brel->joininfo)
3935 {
3936 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
3937 Relids relids = rinfo->required_relids;
3938
3939 if (!rinfo->is_clone) /* else serial number is not unique */
3940 {
3942 continue; /* saw it already */
3944 rinfo->rinfo_serial);
3945 }
3946
3947 if (bms_membership(relids) == BMS_MULTIPLE)
3948 {
3949 List *vars = pull_var_clause((Node *) rinfo->clause,
3954
3955 if (rinfo->is_clone)
3956 where_needed = bms_intersect(relids, root->all_baserels);
3957 else
3958 where_needed = relids;
3960 list_free(vars);
3961 }
3962 }
3963 }
3964}
void add_vars_to_attr_needed(PlannerInfo *root, List *vars, Relids where_needed)
Definition initsplan.c:361
Relids required_relids
Definition pathnodes.h:2932

References add_vars_to_attr_needed(), bms_add_member(), bms_intersect(), bms_is_member(), bms_membership(), BMS_MULTIPLE, RestrictInfo::clause, fb(), RestrictInfo::is_clone, lfirst, list_free(), pull_var_clause(), PVC_INCLUDE_PLACEHOLDERS, PVC_RECURSE_AGGREGATES, PVC_RECURSE_WINDOWFUNCS, RELOPT_BASEREL, RestrictInfo::required_relids, RestrictInfo::rinfo_serial, and root.

Referenced by remove_leftjoinrel_from_query(), and remove_self_join_rel().

◆ rebuild_lateral_attr_needed()

void rebuild_lateral_attr_needed ( PlannerInfo root)

Definition at line 1194 of file initsplan.c.

1195{
1196 Index rti;
1197
1198 /* We need do nothing if the query contains no LATERAL RTEs */
1199 if (!root->hasLateralRTEs)
1200 return;
1201
1202 /* Examine the same baserels that find_lateral_references did */
1203 for (rti = 1; rti < root->simple_rel_array_size; rti++)
1204 {
1205 RelOptInfo *brel = root->simple_rel_array[rti];
1207
1208 if (brel == NULL)
1209 continue;
1210 if (brel->reloptkind != RELOPT_BASEREL)
1211 continue;
1212
1213 /*
1214 * We don't need to repeat all of extract_lateral_references, since it
1215 * kindly saved the extracted Vars/PHVs in lateral_vars.
1216 */
1217 if (brel->lateral_vars == NIL)
1218 continue;
1219
1221
1223 }
1224}

References add_vars_to_attr_needed(), bms_make_singleton(), fb(), NIL, RELOPT_BASEREL, and root.

Referenced by remove_leftjoinrel_from_query(), and remove_self_join_rel().

◆ remove_useless_groupby_columns()

void remove_useless_groupby_columns ( PlannerInfo root)

Definition at line 420 of file initsplan.c.

421{
422 Query *parse = root->parse;
425 bool tryremove = false;
426 ListCell *lc;
427 int relid;
428
429 /* No chance to do anything if there are less than two GROUP BY items */
430 if (list_length(root->processed_groupClause) < 2)
431 return;
432
433 /* Don't fiddle with the GROUP BY clause if the query has grouping sets */
434 if (parse->groupingSets)
435 return;
436
437 /*
438 * Scan the GROUP BY clause to find GROUP BY items that are simple Vars.
439 * Fill groupbyattnos[k] with a bitmapset of the column attnos of RTE k
440 * that are GROUP BY items.
441 */
443 foreach(lc, root->processed_groupClause)
444 {
447 Var *var = (Var *) tle->expr;
448
449 /*
450 * Ignore non-Vars and Vars from other query levels.
451 *
452 * XXX in principle, stable expressions containing Vars could also be
453 * removed, if all the Vars are functionally dependent on other GROUP
454 * BY items. But it's not clear that such cases occur often enough to
455 * be worth troubling over.
456 */
457 if (!IsA(var, Var) ||
458 var->varlevelsup > 0)
459 continue;
460
461 /* OK, remember we have this Var */
462 relid = var->varno;
463 Assert(relid <= list_length(parse->rtable));
464
465 /*
466 * If this isn't the first column for this relation then we now have
467 * multiple columns. That means there might be some that can be
468 * removed.
469 */
472 var->varattno - FirstLowInvalidHeapAttributeNumber);
473 }
474
475 /*
476 * No Vars or didn't find multiple Vars for any relation in the GROUP BY?
477 * If so, nothing can be removed, so don't waste more effort trying.
478 */
479 if (!tryremove)
480 return;
481
482 /*
483 * Consider each relation and see if it is possible to remove some of its
484 * Vars from GROUP BY. For simplicity and speed, we do the actual removal
485 * in a separate pass. Here, we just fill surplusvars[k] with a bitmapset
486 * of the column attnos of RTE k that are removable GROUP BY items.
487 */
488 surplusvars = NULL; /* don't allocate array unless required */
489 relid = 0;
490 foreach(lc, parse->rtable)
491 {
493 RelOptInfo *rel;
497
498 relid++;
499
500 /* Only plain relations could have primary-key constraints */
501 if (rte->rtekind != RTE_RELATION)
502 continue;
503
504 /*
505 * We must skip inheritance parent tables as some of the child rels
506 * may cause duplicate rows. This cannot happen with partitioned
507 * tables, however.
508 */
509 if (rte->inh && rte->relkind != RELKIND_PARTITIONED_TABLE)
510 continue;
511
512 /* Nothing to do unless this rel has multiple Vars in GROUP BY */
513 relattnos = groupbyattnos[relid];
515 continue;
516
517 rel = root->simple_rel_array[relid];
518
519 /*
520 * Now check each index for this relation to see if there are any with
521 * columns which are a proper subset of the grouping columns for this
522 * relation.
523 */
525 {
527 bool nulls_check_ok;
528
529 /*
530 * Skip any non-unique and deferrable indexes. Predicate indexes
531 * have not been checked yet, so we must skip those too as the
532 * predOK check that's done later might fail.
533 */
534 if (!index->unique || !index->immediate || index->indpred != NIL)
535 continue;
536
537 /* For simplicity, we currently don't support expression indexes */
538 if (index->indexprs != NIL)
539 continue;
540
542 nulls_check_ok = true;
543 for (int i = 0; i < index->nkeycolumns; i++)
544 {
545 /*
546 * We must insist that the index columns are all defined NOT
547 * NULL otherwise duplicate NULLs could exist. However, we
548 * can relax this check when the index is defined with NULLS
549 * NOT DISTINCT as there can only be 1 NULL row, therefore
550 * functional dependency on the unique columns is maintained,
551 * despite the NULL.
552 */
553 if (!index->nullsnotdistinct &&
554 !bms_is_member(index->indexkeys[i],
555 rel->notnullattnums))
556 {
557 nulls_check_ok = false;
558 break;
559 }
560
561 ind_attnos =
563 index->indexkeys[i] -
565 }
566
567 if (!nulls_check_ok)
568 continue;
569
570 /*
571 * Skip any indexes where the indexed columns aren't a proper
572 * subset of the GROUP BY.
573 */
575 continue;
576
577 /*
578 * Record the attribute numbers from the index with the fewest
579 * columns. This allows the largest number of columns to be
580 * removed from the GROUP BY clause. In the future, we may wish
581 * to consider using the narrowest set of columns and looking at
582 * pg_statistic.stawidth as it might be better to use an index
583 * with, say two INT4s, rather than, say, one long varlena column.
584 */
585 if (index->nkeycolumns < best_nkeycolumns)
586 {
588 best_nkeycolumns = index->nkeycolumns;
589 }
590 }
591
592 /* Did we find a suitable index? */
594 {
595 /*
596 * To easily remember whether we've found anything to do, we don't
597 * allocate the surplusvars[] array until we find something.
598 */
599 if (surplusvars == NULL)
601
602 /* Remember the attnos of the removable columns */
604 }
605 }
606
607 /*
608 * If we found any surplus Vars, build a new GROUP BY clause without them.
609 * (Note: this may leave some TLEs with unreferenced ressortgroupref
610 * markings, but that's harmless.)
611 */
612 if (surplusvars != NULL)
613 {
615
616 foreach(lc, root->processed_groupClause)
617 {
620 Var *var = (Var *) tle->expr;
621
622 /*
623 * New list must include non-Vars, outer Vars, and anything not
624 * marked as surplus.
625 */
626 if (!IsA(var, Var) ||
627 var->varlevelsup > 0 ||
629 surplusvars[var->varno]))
631 }
632
633 root->processed_groupClause = new_groupby;
634 }
635}
Bitmapset * bms_difference(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:346
BMS_Comparison bms_subset_compare(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:445
@ BMS_SUBSET1
Definition bitmapset.h:63
#define PG_INT32_MAX
Definition c.h:673
int32_t int32
Definition c.h:620
#define palloc0_array(type, count)
Definition fe_memutils.h:77
void parse(int)
Definition parse.c:49
int i
Definition isn.c:77
#define foreach_node(type, var, lst)
Definition pg_list.h:528
Bitmapset * notnullattnums
Definition pathnodes.h:1083
List * indexlist
Definition pathnodes.h:1091
Definition type.h:96
#define FirstLowInvalidHeapAttributeNumber
Definition sysattr.h:27

References Assert, bms_add_member(), bms_difference(), bms_is_empty, bms_is_member(), bms_membership(), BMS_MULTIPLE, BMS_SUBSET1, bms_subset_compare(), fb(), FirstLowInvalidHeapAttributeNumber, foreach_node, get_sortgroupclause_tle(), i, RelOptInfo::indexlist, IsA, lappend(), lfirst_node, list_length(), NIL, RelOptInfo::notnullattnums, palloc0_array, parse(), PG_INT32_MAX, root, RTE_RELATION, Var::varattno, Var::varlevelsup, and Var::varno.

Referenced by query_planner().

◆ restriction_is_always_false()

bool restriction_is_always_false ( PlannerInfo root,
RestrictInfo restrictinfo 
)

Definition at line 3507 of file initsplan.c.

3509{
3510 /*
3511 * For a clone clause, we don't have a reliable way to determine if the
3512 * input expression of a NullTest is non-nullable: nullingrel bits in
3513 * clone clauses may not reflect reality, so we dare not draw conclusions
3514 * from clones about whether Vars are guaranteed not-null.
3515 */
3516 if (restrictinfo->has_clone || restrictinfo->is_clone)
3517 return false;
3518
3519 /* Check for NullTest qual */
3520 if (IsA(restrictinfo->clause, NullTest))
3521 {
3522 NullTest *nulltest = (NullTest *) restrictinfo->clause;
3523
3524 /* is this NullTest an IS_NULL qual? */
3525 if (nulltest->nulltesttype != IS_NULL)
3526 return false;
3527
3528 /*
3529 * Empty rows can appear NULL in some contexts and NOT NULL in others,
3530 * so avoid this optimization for row expressions.
3531 */
3532 if (nulltest->argisrow)
3533 return false;
3534
3536 }
3537
3538 /* If it's an OR, check its sub-clauses */
3540 {
3541 ListCell *lc;
3542
3543 Assert(is_orclause(restrictinfo->orclause));
3544
3545 /*
3546 * Currently, when processing OR expressions, we only return true when
3547 * all of the OR branches are always false. This could perhaps be
3548 * expanded to remove OR branches that are provably false. This may
3549 * be a useful thing to do as it could result in the OR being left
3550 * with a single arg. That's useful as it would allow the OR
3551 * condition to be replaced with its single argument which may allow
3552 * use of an index for faster filtering on the remaining condition.
3553 */
3554 foreach(lc, ((BoolExpr *) restrictinfo->orclause)->args)
3555 {
3556 Node *orarg = (Node *) lfirst(lc);
3557
3558 if (!IsA(orarg, RestrictInfo) ||
3560 return false;
3561 }
3562 return true;
3563 }
3564
3565 return false;
3566}
bool expr_is_nonnullable(PlannerInfo *root, Expr *expr, NotNullSource source)
Definition clauses.c:4757
static bool is_orclause(const void *clause)
Definition nodeFuncs.h:116
@ NOTNULL_SOURCE_RELOPT
Definition optimizer.h:136
@ IS_NULL
Definition primnodes.h:1980
bool restriction_is_or_clause(RestrictInfo *restrictinfo)

References Assert, expr_is_nonnullable(), fb(), IS_NULL, is_orclause(), IsA, lfirst, NOTNULL_SOURCE_RELOPT, restriction_is_always_false(), restriction_is_or_clause(), and root.

Referenced by add_base_clause_to_rel(), add_join_clause_to_rels(), and restriction_is_always_false().

◆ restriction_is_always_true()

bool restriction_is_always_true ( PlannerInfo root,
RestrictInfo restrictinfo 
)

Definition at line 3442 of file initsplan.c.

3444{
3445 /*
3446 * For a clone clause, we don't have a reliable way to determine if the
3447 * input expression of a NullTest is non-nullable: nullingrel bits in
3448 * clone clauses may not reflect reality, so we dare not draw conclusions
3449 * from clones about whether Vars are guaranteed not-null.
3450 */
3451 if (restrictinfo->has_clone || restrictinfo->is_clone)
3452 return false;
3453
3454 /* Check for NullTest qual */
3455 if (IsA(restrictinfo->clause, NullTest))
3456 {
3457 NullTest *nulltest = (NullTest *) restrictinfo->clause;
3458
3459 /* is this NullTest an IS_NOT_NULL qual? */
3460 if (nulltest->nulltesttype != IS_NOT_NULL)
3461 return false;
3462
3463 /*
3464 * Empty rows can appear NULL in some contexts and NOT NULL in others,
3465 * so avoid this optimization for row expressions.
3466 */
3467 if (nulltest->argisrow)
3468 return false;
3469
3471 }
3472
3473 /* If it's an OR, check its sub-clauses */
3475 {
3476 ListCell *lc;
3477
3478 Assert(is_orclause(restrictinfo->orclause));
3479
3480 /*
3481 * if any of the given OR branches is provably always true then the
3482 * entire condition is true.
3483 */
3484 foreach(lc, ((BoolExpr *) restrictinfo->orclause)->args)
3485 {
3486 Node *orarg = (Node *) lfirst(lc);
3487
3488 if (!IsA(orarg, RestrictInfo))
3489 continue;
3490
3492 return true;
3493 }
3494 }
3495
3496 return false;
3497}
@ IS_NOT_NULL
Definition primnodes.h:1980

References Assert, expr_is_nonnullable(), fb(), IS_NOT_NULL, is_orclause(), IsA, lfirst, NOTNULL_SOURCE_RELOPT, restriction_is_always_true(), restriction_is_or_clause(), and root.

Referenced by add_base_clause_to_rel(), add_join_clause_to_rels(), and restriction_is_always_true().

◆ setup_eager_aggregation()

void setup_eager_aggregation ( PlannerInfo root)

Definition at line 643 of file initsplan.c.

644{
645 /*
646 * Don't apply eager aggregation if disabled by user.
647 */
649 return;
650
651 /*
652 * Don't apply eager aggregation if there are no available GROUP BY
653 * clauses.
654 */
655 if (!root->processed_groupClause)
656 return;
657
658 /*
659 * For now we don't try to support grouping sets.
660 */
661 if (root->parse->groupingSets)
662 return;
663
664 /*
665 * For now we don't try to support DISTINCT or ORDER BY aggregates.
666 */
667 if (root->numOrderedAggs > 0)
668 return;
669
670 /*
671 * If there are any aggregates that do not support partial mode, or any
672 * partial aggregates that are non-serializable, do not apply eager
673 * aggregation.
674 */
675 if (root->hasNonPartialAggs || root->hasNonSerialAggs)
676 return;
677
678 /*
679 * We don't try to apply eager aggregation if there are set-returning
680 * functions in targetlist.
681 */
682 if (root->parse->hasTargetSRFs)
683 return;
684
685 /*
686 * Eager aggregation only makes sense if there are multiple base rels in
687 * the query.
688 */
689 if (bms_membership(root->all_baserels) != BMS_MULTIPLE)
690 return;
691
692 /*
693 * Don't apply eager aggregation if any aggregate poses a risk of
694 * excessive memory usage during partial aggregation.
695 */
697 return;
698
699 /*
700 * Collect aggregate expressions and plain Vars that appear in the
701 * targetlist and havingQual.
702 */
704
705 /*
706 * If there are no suitable aggregate expressions, we cannot apply eager
707 * aggregation.
708 */
709 if (root->agg_clause_list == NIL)
710 return;
711
712 /*
713 * Collect grouping expressions that appear in grouping clauses.
714 */
716}
bool enable_eager_aggregate
Definition allpaths.c:82
static void create_grouping_expr_infos(PlannerInfo *root)
Definition initsplan.c:880
static bool is_partial_agg_memory_risky(PlannerInfo *root)
Definition initsplan.c:730
static void create_agg_clause_infos(PlannerInfo *root)
Definition initsplan.c:751

References bms_membership(), BMS_MULTIPLE, create_agg_clause_infos(), create_grouping_expr_infos(), enable_eager_aggregate, is_partial_agg_memory_risky(), NIL, and root.

Referenced by query_planner().

Variable Documentation

◆ from_collapse_limit

int from_collapse_limit

Definition at line 41 of file initsplan.c.

Referenced by deconstruct_recurse().

◆ join_collapse_limit

int join_collapse_limit

Definition at line 42 of file initsplan.c.

Referenced by deconstruct_recurse().