1/*-------------------------------------------------------------------------
4 * Relation-node lookup/construction routines
6 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/backend/optimizer/util/relnode.c
13 *-------------------------------------------------------------------------
47 List *pushed_down_joins,
61 List *new_restrictlist);
89 * setup_simple_rel_arrays
90 * Prepare the arrays we use for quickly accessing base relations
100 /* Arrays are accessed using RT indexes (1..N) */
102 root->simple_rel_array_size = size;
105 * simple_rel_array is initialized to all NULLs, since no RelOptInfos
106 * exist yet. It'll be filled by later calls to build_simple_rel().
111 /* simple_rte_array is an array equivalent of the rtable list */
115 foreach(lc,
root->parse->rtable)
119 root->simple_rte_array[rti++] = rte;
122 /* append_rel_array is not needed if there are no AppendRelInfos */
123 if (
root->append_rel_list ==
NIL)
125 root->append_rel_array = NULL;
133 * append_rel_array is filled with any already-existing AppendRelInfos,
134 * which currently could only come from UNION ALL flattening. We might
135 * add more later during inheritance expansion, but it's the
136 * responsibility of the expansion code to update the array properly.
138 foreach(lc,
root->append_rel_list)
144 Assert(child_relid < size);
146 if (
root->append_rel_array[child_relid])
147 elog(
ERROR,
"child relation already exists");
149 root->append_rel_array[child_relid] = appinfo;
154 * expand_planner_arrays
155 * Expand the PlannerInfo's per-RTE arrays by add_size members
156 * and initialize the newly added entries to NULLs
158 * Note: this causes the append_rel_array to become allocated even if
159 * it was not before. This is okay for current uses, because we only call
160 * this when adding child relations, which always have AppendRelInfos.
171 root->simple_rel_array =
174 root->simple_rte_array =
177 if (
root->append_rel_array)
178 root->append_rel_array =
181 root->append_rel_array =
184 root->simple_rel_array_size = new_size;
189 * Construct a new RelOptInfo for a base relation or 'other' relation.
197 /* Rel should not exist already */
198 Assert(relid > 0 && relid < root->simple_rel_array_size);
199 if (
root->simple_rel_array[relid] != NULL)
200 elog(
ERROR,
"rel %d already exists", relid);
202 /* Fetch RTE for relation */
203 rte =
root->simple_rte_array[relid];
210 /* cheap startup cost is interesting iff not all tuples to be retrieved */
223 /* min_attr, max_attr, attr_needed, attr_widths are set below */
244 * For any RELATION rte, we need a userid with which to check
245 * permission access. Baserels simply use their own
246 * RTEPermissionInfo's checkAsUser.
248 * For otherrels normally there's no RTEPermissionInfo, so we use the
249 * parent's, which normally has one. The exceptional case is that the
250 * parent is a subquery, in which case the otherrel will have its own.
267 rel->fdwroutine = NULL;
268 rel->fdw_private = NULL;
281 rel->part_scheme = NULL;
283 rel->boundinfo = NULL;
286 rel->part_rels = NULL;
289 rel->partexprs = NULL;
290 rel->nullable_partexprs = NULL;
293 * Pass assorted information down the inheritance hierarchy.
297 /* We keep back-links to immediate parent and topmost parent. */
298 rel->parent = parent;
299 rel->top_parent = parent->top_parent ? parent->top_parent : parent;
303 * A child rel is below the same outer joins as its parent. (We
304 * presume this info was already calculated for the parent.)
309 * Also propagate lateral-reference information from appendrel parent
310 * rels to their child rels. We intentionally give each child rel the
311 * same minimum parameterization, even though it's quite possible that
312 * some don't reference all the lateral rels. This is because any
313 * append path for the parent will have to have the same
314 * parameterization for every child anyway, and there's no value in
315 * forcing extra reparameterize_path() calls. Similarly, a lateral
316 * reference to the parent prevents use of otherwise-movable join rels
319 * It's possible for child rels to have their own children, in which
320 * case the topmost parent's lateral info propagates all the way down.
329 rel->top_parent = NULL;
337 /* Check type of rtable entry */
341 /* Table --- retrieve statistics from the system catalogs */
352 * Subquery, function, tablefunc, values list, CTE, or ENR --- set
353 * up attr range and arrays
355 * Note: 0 is included in range to support whole-row Vars
359 rel->attr_needed = (
Relids *)
361 rel->attr_widths = (
int32 *)
365 /* RTE_RESULT has no columns, nor could it have whole-row Var */
368 rel->attr_needed = NULL;
369 rel->attr_widths = NULL;
378 * We must apply the partially filled in RelOptInfo before calling
379 * apply_child_basequals due to some transformations within that function
380 * which require the RelOptInfo to be available in the simple_rel_array.
382 root->simple_rel_array[relid] = rel;
385 * Apply the parent's quals to the child, with appropriate substitution of
386 * variables. If the resulting clause is constant-FALSE or NULL after
387 * applying transformations, apply_child_basequals returns false to
388 * indicate that scanning this relation won't yield any rows. In this
389 * case, we mark the child as dummy right away. (We must do this
390 * immediately so that pruning works correctly when recursing in
391 * expand_partitioned_rtentry.)
401 * Restriction clause reduced to constant FALSE or NULL. Mark as
402 * dummy so we won't scan this relation.
413 * Find a base or otherrel relation entry, which must already exist.
420 /* use an unsigned comparison to prevent negative array element access */
423 rel =
root->simple_rel_array[relid];
428 elog(
ERROR,
"no relation entry for relid %d", relid);
430 return NULL;
/* keep compiler quiet */
434 * find_base_rel_noerr
435 * Find a base or otherrel relation entry, returning NULL if there's none
440 /* use an unsigned comparison to prevent negative array element access */
442 return root->simple_rel_array[relid];
447 * find_base_rel_ignore_join
448 * Find a base or otherrel relation entry, which must already exist.
450 * Unlike find_base_rel, if relid references an outer join then this
451 * will return NULL rather than raising an error. This is convenient
452 * for callers that must deal with relid sets including both base and
458 /* use an unsigned comparison to prevent negative array element access */
464 rel =
root->simple_rel_array[relid];
469 * We could just return NULL here, but for debugging purposes it seems
470 * best to actually verify that the relid is an outer join and not
473 rte =
root->simple_rte_array[relid];
478 elog(
ERROR,
"no relation entry for relid %d", relid);
480 return NULL;
/* keep compiler quiet */
484 * build_join_rel_hash
485 * Construct the auxiliary hash table for join relations.
494 /* Create the hash table */
505 /* Insert all the already-existing joinrels */
506 foreach(l,
root->join_rel_list)
520 root->join_rel_hash = hashtab;
525 * Returns relation entry corresponding to 'relids' (a set of RT indexes),
526 * or NULL if none exists. This is for join relations.
532 * Switch to using hash lookup when list grows "too long". The threshold
533 * is arbitrary and is known only here.
539 * Use either hashtable lookup or linear search, as appropriate.
541 * Note: the seemingly redundant hashkey variable is used to avoid taking
542 * the address of relids; unless the compiler is exceedingly smart, doing
543 * so would force relids out of a register and thus probably slow down the
546 if (
root->join_rel_hash)
562 foreach(l,
root->join_rel_list)
575 * set_foreign_rel_properties
576 * Set up foreign-join fields if outer and inner relation are foreign
577 * tables (or joins) belonging to the same server and assigned to the same
578 * user to check access permissions as.
580 * In addition to an exact match of userid, we allow the case where one side
581 * has zero userid (implying current user) and the other side has explicit
582 * userid that happens to equal the current user; but in that case, pushdown of
583 * the join is only valid for the current user. The useridiscurrent field
584 * records whether we had to make such an assumption for this join or any
587 * Otherwise these fields are left invalid, so GetForeignJoinPaths will not be
588 * called for the join relation.
602 joinrel->fdwroutine = outer_rel->fdwroutine;
610 joinrel->fdwroutine = outer_rel->fdwroutine;
618 joinrel->fdwroutine = outer_rel->fdwroutine;
625 * Add given join relation to the list of join relations in the given
626 * PlannerInfo. Also add it to the auxiliary hashtable if there is one.
631 /* GEQO requires us to append the new joinrel to the end of the list! */
634 /* store it into the auxiliary hashtable if there is one. */
635 if (
root->join_rel_hash)
651 * Returns relation entry corresponding to the union of two given rels,
652 * creating a new relation entry if none already exists.
654 * 'joinrelids' is the Relids set that uniquely identifies the join
655 * 'outer_rel' and 'inner_rel' are relation nodes for the relations to be
657 * 'sjinfo': join context info
658 * 'pushed_down_joins': any pushed-down outer joins that are now completed
659 * 'restrictlist_ptr': result variable. If not NULL, *restrictlist_ptr
660 * receives the list of RestrictInfo nodes that apply to this
661 * particular pair of joinable relations.
663 * restrictlist_ptr makes the routine's API a little grotty, but it saves
664 * duplicated calculation of the restrictlist...
672 List *pushed_down_joins,
673 List **restrictlist_ptr)
678 /* This function should be used only for join between parents. */
682 * See if we already have a joinrel for this set of base rels.
689 * Yes, so we only need to figure the restrictlist for this particular
690 * pair of component relations.
692 if (restrictlist_ptr)
708 /* cheap startup cost is interesting iff not all tuples to be retrieved */
719 /* init direct_lateral_relids from children; we'll finish it up below */
724 outer_rel, inner_rel);
725 joinrel->
relid = 0;
/* indicates not a baserel */
729 joinrel->attr_needed = NULL;
730 joinrel->attr_widths = NULL;
748 joinrel->fdwroutine = NULL;
749 joinrel->fdw_private = NULL;
762 joinrel->parent = NULL;
763 joinrel->top_parent = NULL;
765 joinrel->part_scheme = NULL;
767 joinrel->boundinfo = NULL;
770 joinrel->part_rels = NULL;
773 joinrel->partexprs = NULL;
774 joinrel->nullable_partexprs = NULL;
776 /* Compute information relevant to the foreign relations. */
780 * Fill the joinrel's tlist with just the Vars and PHVs that need to be
781 * output from this join (ie, are needed for higher joinclauses or final
784 * NOTE: the tlist order for a join rel will depend on which pair of outer
785 * and inner rels we first try to build it from. But the contents should
786 * be the same regardless.
795 * add_placeholders_to_joinrel also took care of adding the ph_lateral
796 * sets of any PlaceHolderVars computed here to direct_lateral_relids, so
797 * now we can finish computing that. This is much like the computation of
798 * the transitively-closed lateral_relids in min_join_parameterization,
799 * except that here we *do* have to consider the added PHVs.
805 * Construct restrict and join clause lists for the new joinrel. (The
806 * caller might or might not need the restrictlist, but I need it anyway
807 * for set_joinrel_size_estimates().)
810 outer_rel, inner_rel,
812 if (restrictlist_ptr)
813 *restrictlist_ptr = restrictlist;
817 * This is also the right place to check whether the joinrel has any
818 * pending EquivalenceClass joins.
822 /* Store the partition information. */
827 * Set estimates of the joinrel's size.
830 sjinfo, restrictlist);
833 * Set the consider_parallel flag if this joinrel could potentially be
834 * scanned within a parallel worker. If this flag is false for either
835 * inner_rel or outer_rel, then it must be false for the joinrel also.
836 * Even if both are true, there might be parallel-restricted expressions
837 * in the targetlist or quals.
839 * Note that if there are more than two rels in this relation, they could
840 * be divided between inner_rel and outer_rel in any arbitrary way. We
841 * assume this doesn't matter, because we should hit all the same baserels
842 * and joinclauses while building up to this joinrel no matter which we
843 * take; therefore, we should make the same decision here however we get
851 /* Add the joinrel to the PlannerInfo. */
855 * Also, if dynamic-programming join search is active, add the new joinrel
856 * to the appropriate sublist. Note: you might think the Assert on number
857 * of members should be for equality, but some of the level 1 rels might
858 * have been joinrels already, so we can only assert <=.
860 if (
root->join_rel_level)
864 root->join_rel_level[
root->join_cur_level] =
872 * build_child_join_rel
873 * Builds RelOptInfo representing join between given two child relations.
875 * 'outer_rel' and 'inner_rel' are the RelOptInfos of child relations being
877 * 'parent_joinrel' is the RelOptInfo representing the join between parent
878 * relations. Some of the members of new RelOptInfo are produced by
879 * translating corresponding members of this RelOptInfo
880 * 'restrictlist': list of RestrictInfo nodes that apply to this particular
881 * pair of joinable relations
882 * 'sjinfo': child join's join-type details
883 * 'nappinfos' and 'appinfos': AppendRelInfo array for child relids
893 /* Only joins between "other" relations land here. */
896 /* The parent joinrel should have consider_partitionwise_join set. */
901 nappinfos, appinfos);
903 /* cheap startup cost is interesting iff not all tuples to be retrieved */
916 joinrel->
relid = 0;
/* indicates not a baserel */
920 joinrel->attr_needed = NULL;
921 joinrel->attr_widths = NULL;
937 joinrel->fdwroutine = NULL;
938 joinrel->fdw_private = NULL;
948 joinrel->parent = parent_joinrel;
949 joinrel->top_parent = parent_joinrel->top_parent ? parent_joinrel->top_parent : parent_joinrel;
951 joinrel->part_scheme = NULL;
953 joinrel->boundinfo = NULL;
956 joinrel->part_rels = NULL;
959 joinrel->partexprs = NULL;
960 joinrel->nullable_partexprs = NULL;
962 /* Compute information relevant to foreign relations. */
965 /* Set up reltarget struct */
967 nappinfos, appinfos);
969 /* Construct joininfo list. */
976 * Lateral relids referred in child join will be same as that referred in
977 * the parent relation.
983 * If the parent joinrel has pending equivalence classes, so does the
988 /* Is the join between partitions itself partitioned? */
992 /* Child joinrel is parallel safe if parent is parallel safe. */
995 /* Set estimates of the child-joinrel's size. */
997 sjinfo, restrictlist);
999 /* We build the join only once. */
1002 /* Add the relation to the PlannerInfo. */
1006 * We might need EquivalenceClass members corresponding to the child join,
1007 * so that we can represent sort pathkeys for it. As with children of
1008 * baserels, we shouldn't need this unless there are relevant eclass joins
1009 * (implying that a merge join might be possible) or pathkeys to sort by.
1013 nappinfos, appinfos,
1014 parent_joinrel, joinrel);
1020 * min_join_parameterization
1022 * Determine the minimum possible parameterization of a joinrel, that is, the
1023 * set of other rels it contains LATERAL references to. We save this value in
1024 * the join's RelOptInfo. This function is split out of build_join_rel()
1025 * because join_is_legal() needs the value to check a prospective join.
1036 * Basically we just need the union of the inputs' lateral_relids, less
1037 * whatever is already in the join.
1039 * It's not immediately obvious that this is a valid way to compute the
1040 * result, because it might seem that we're ignoring possible lateral refs
1041 * of PlaceHolderVars that are due to be computed at the join but not in
1042 * either input. However, because create_lateral_join_info() already
1043 * charged all such PHV refs to each member baserel of the join, they'll
1044 * be accounted for already in the inputs' lateral_relids. Likewise, we
1045 * do not need to worry about doing transitive closure here, because that
1046 * was already accounted for in the original baserel lateral_relids.
1054 * build_joinrel_tlist
1055 * Builds a join relation's target list from an input relation.
1056 * (This is invoked twice to handle the two input relations.)
1058 * The join's targetlist includes all Vars of its member relations that
1059 * will still be needed above the join. This subroutine adds all such
1060 * Vars from the specified input rel's tlist to the join rel's tlist.
1061 * Likewise for any PlaceHolderVars emitted by the input rel.
1063 * We also compute the expected width of the join's output, making use
1064 * of data that was cached at the baserel level by set_rel_width().
1066 * Pass can_null as true if the join is an outer join that can null Vars
1067 * from this input relation. If so, we will (normally) add the join's relid
1068 * to the nulling bitmaps of Vars and PHVs bubbled up from the input.
1070 * When forming an outer join's target list, special handling is needed in
1071 * case the outer join was commuted with another one per outer join identity 3
1072 * (see optimizer/README). We must take steps to ensure that the output Vars
1073 * have the same nulling bitmaps that they would if the two joins had been
1074 * done in syntactic order; else they won't match Vars appearing higher in
1075 * the query tree. An exception to the match-the-syntactic-order rule is
1076 * that when an outer join is pushed down into another one's RHS per identity
1077 * 3, we can't mark its Vars as nulled until the now-upper outer join is also
1078 * completed. So we need to do three things:
1080 * First, we add the outer join's relid to the nulling bitmap only if the
1081 * outer join has been completely performed and the Var or PHV actually
1082 * comes from within the syntactically nullable side(s) of the outer join.
1083 * This takes care of the possibility that we have transformed
1084 * (A leftjoin B on (Pab)) leftjoin C on (Pbc)
1086 * A leftjoin (B leftjoin C on (Pbc)) on (Pab)
1087 * Here the pushed-down B/C join cannot mark C columns as nulled yet,
1088 * while the now-upper A/B join must not mark C columns as nulled by itself.
1090 * Second, perform the same operation for each SpecialJoinInfo listed in
1091 * pushed_down_joins (which, in this example, would be the B/C join when
1092 * we are at the now-upper A/B join). This allows the now-upper join to
1093 * complete the marking of "C" Vars that now have fully valid values.
1095 * Third, any relid in sjinfo->commute_above_r that is already part of
1096 * the joinrel is added to the nulling bitmaps of nullable Vars and PHVs.
1097 * This takes care of the reverse case where we implement
1098 * A leftjoin (B leftjoin C on (Pbc)) on (Pab)
1100 * (A leftjoin B on (Pab)) leftjoin C on (Pbc)
1101 * The C columns emitted by the B/C join need to be shown as nulled by both
1102 * the B/C and A/B joins, even though they've not physically traversed the
1109 List *pushed_down_joins,
1122 * For a PlaceHolderVar, we have to look up the PlaceHolderInfo.
1129 /* Is it still needed above this joinrel? */
1133 * Yup, add it to the output. If this join potentially nulls
1134 * this input, we have to update the PHV's phnullingrels,
1135 * which means making a copy.
1140 /* See comments above to understand this logic */
1148 foreach(lc, pushed_down_joins)
1165 /* Bubbling up the precomputed result has cost zero */
1172 * Otherwise, anything in a baserel or joinrel targetlist ought to be
1173 * a Var. (More general cases can only appear in appendrel child
1174 * rels, which will never be seen here.)
1177 elog(
ERROR,
"unexpected node type in rel targetlist: %d",
1182 /* UPDATE/DELETE/MERGE row identity vars are always needed */
1186 /* Update reltarget width estimate from RowIdentityVarInfo */
1194 /* Get the Var's original base rel */
1197 /* Is it still needed above this joinrel? */
1200 continue;
/* nope, skip it */
1202 /* Update reltarget width estimate from baserel's attr_widths */
1203 tuple_width += baserel->attr_widths[ndx];
1207 * Add the Var to the output. If this join potentially nulls this
1208 * input, we have to update the Var's varnullingrels, which means
1209 * making a copy. But note that we don't ever add nullingrel bits to
1210 * row identity Vars (cf. comments in setrefs.c).
1215 /* See comments above to understand this logic */
1223 foreach(lc, pushed_down_joins)
1232 var->varnullingrels =
1241 /* Vars have cost zero, so no need to adjust reltarget->cost */
1248 * build_joinrel_restrictlist
1249 * build_joinrel_joinlist
1250 * These routines build lists of restriction and join clauses for a
1251 * join relation from the joininfo lists of the relations it joins.
1253 * These routines are separate because the restriction list must be
1254 * built afresh for each pair of input sub-relations we consider, whereas
1255 * the join list need only be computed once for any join RelOptInfo.
1256 * The join list is fully determined by the set of rels making up the
1257 * joinrel, so we should get the same results (up to ordering) from any
1258 * candidate pair of sub-relations. But the restriction list is whatever
1259 * is not handled in the sub-relations, so it depends on which
1260 * sub-relations are considered.
1262 * If a join clause from an input relation refers to base+OJ rels still not
1263 * present in the joinrel, then it is still a join clause for the joinrel;
1264 * we put it into the joininfo list for the joinrel. Otherwise,
1265 * the clause is now a restrict clause for the joined relation, and we
1266 * return it to the caller of build_joinrel_restrictlist() to be stored in
1267 * join paths made from this pair of sub-relations. (It will not need to
1268 * be considered further up the join tree.)
1270 * In many cases we will find the same RestrictInfos in both input
1271 * relations' joinlists, so be careful to eliminate duplicates.
1272 * Pointer equality should be a sufficient test for dups, since all
1273 * the various joinlist entries ultimately refer to RestrictInfos
1274 * pushed into them by distribute_restrictinfo_to_rels().
1276 * 'joinrel' is a join relation node
1277 * 'outer_rel' and 'inner_rel' are a pair of relations that can be joined
1279 * 'sjinfo': join context info
1281 * build_joinrel_restrictlist() returns a list of relevant restrictinfos,
1282 * whereas build_joinrel_joinlist() stores its results in the joinrel's
1283 * joininfo list. One or the other must accept each given clause!
1285 * NB: Formerly, we made deep(!) copies of each input RestrictInfo to pass
1286 * up to the join relation. I believe this is no longer necessary, because
1287 * RestrictInfo nodes are no longer context-dependent. Instead, just include
1288 * the original nodes in the lists made for the join relation.
1298 Relids both_input_relids;
1303 * Collect all the clauses that syntactically belong at this level,
1304 * eliminating any duplicates (important since we will see many of the
1305 * same clauses arriving from both input relations).
1308 both_input_relids,
NIL);
1310 both_input_relids, result);
1313 * Add on any clauses derived from EquivalenceClasses. These cannot be
1314 * redundant with the clauses in the joininfo lists, so don't bother
1335 * Collect all the clauses that syntactically belong above this level,
1336 * eliminating any duplicates (important since we will see many of the
1337 * same clauses arriving from both input relations).
1349 Relids both_input_relids,
1350 List *new_restrictlist)
1361 * This clause should become a restriction clause for the joinrel,
1362 * since it refers to no outside rels. However, if it's a clone
1363 * clause then it might be too late to evaluate it, so we have to
1364 * check. (If it is too late, just ignore the clause, taking it
1365 * on faith that another clone was or will be selected.) Clone
1366 * clauses should always be outer-join clauses, so we compare
1367 * against both_input_relids.
1380 * For non-clone clauses, we just Assert it's OK. These might
1381 * be either join or filter clauses; if it's a join clause
1382 * then it should not refer to the current join's output.
1383 * (There is little point in checking incompatible_relids,
1384 * because it'll be NULL.)
1388 both_input_relids));
1392 * OK, so add it to the list, being careful to eliminate
1393 * duplicates. (Since RestrictInfo nodes in different joinlists
1394 * will have been multiply-linked rather than copied, pointer
1395 * equality should be a sufficient test.)
1402 * This clause is still a join clause at this level, so we ignore
1403 * it in this routine.
1408 return new_restrictlist;
1413 List *joininfo_list,
1418 /* Expected to be called only for join between parent relations. */
1421 foreach(l, joininfo_list)
1428 * This clause becomes a restriction clause for the joinrel, since
1429 * it refers to no outside rels. So we can ignore it in this
1436 * This clause is still a join clause at this level, so add it to
1437 * the new joininfo list, being careful to eliminate duplicates.
1438 * (Since RestrictInfo nodes in different joinlists will have been
1439 * multiply-linked rather than copied, pointer equality should be
1440 * a sufficient test.)
1446 return new_joininfo;
1452 * Build a RelOptInfo describing some post-scan/join query processing,
1453 * or return a pre-existing one if somebody already built it.
1455 * An "upper" relation is identified by an UpperRelationKind and a Relids set.
1456 * The meaning of the Relids set is not specified here, and very likely will
1457 * vary for different relation kinds.
1459 * Most of the fields in an upper-level RelOptInfo are not used and are not
1460 * set here (though makeNode should ensure they're zeroes). We basically only
1461 * care about fields that are of interest to add_path() and set_cheapest().
1470 * For the moment, our indexing data structure is just a List for each
1471 * relation kind. If we ever get so many of one kind that this stops
1472 * working well, we can improve it. No code outside this function should
1473 * assume anything about how to find a particular upperrel.
1476 /* If we already made this upperrel for the query, return it */
1477 foreach(lc,
root->upper_rels[kind])
1489 /* cheap startup cost is interesting iff not all tuples to be retrieved */
1506 * find_childrel_parents
1507 * Compute the set of parent relids of an appendrel child rel.
1509 * Since appendrels can be nested, a child could have multiple levels of
1510 * appendrel ancestors. This function computes a Relids set of all the
1511 * parent relation IDs.
1528 /* traverse up to the parent rel, loop if it's also a child rel */
1539 * get_baserel_parampathinfo
1540 * Get the ParamPathInfo for a parameterized path for a base relation,
1541 * constructing one if we don't have one already.
1543 * This centralizes estimating the rowcounts for parameterized paths.
1544 * We need to cache those to be sure we use the same rowcount for all paths
1545 * of the same parameterization for a given rel. This is also a convenient
1546 * place to determine which movable join clauses the parameterized path will
1547 * be responsible for evaluating.
1561 /* If rel has LATERAL refs, every path for it should account for them */
1564 /* Unparameterized paths have no ParamPathInfo */
1570 /* If we already have a PPI for this parameterization, just return it */
1575 * Identify all joinclauses that are movable to this base rel given this
1587 pclauses =
lappend(pclauses, rinfo);
1591 * Add in joinclauses generated by EquivalenceClasses, too. (These
1592 * necessarily satisfy join_clause_is_movable_into; but in assert-enabled
1593 * builds, let's verify that.)
1600#ifdef USE_ASSERT_CHECKING
1601 foreach(lc, eqclauses)
1612 /* Compute set of serial numbers of the enforced clauses */
1614 foreach(lc, pclauses)
1621 /* Estimate the number of rows returned by the parameterized scan */
1624 /* And now we can build the ParamPathInfo */
1636 * get_joinrel_parampathinfo
1637 * Get the ParamPathInfo for a parameterized path for a join relation,
1638 * constructing one if we don't have one already.
1640 * This centralizes estimating the rowcounts for parameterized paths.
1641 * We need to cache those to be sure we use the same rowcount for all paths
1642 * of the same parameterization for a given rel. This is also a convenient
1643 * place to determine which movable join clauses the parameterized path will
1644 * be responsible for evaluating.
1646 * outer_path and inner_path are a pair of input paths that can be used to
1647 * construct the join, and restrict_clauses is the list of regular join
1648 * clauses (including clauses derived from EquivalenceClasses) that must be
1649 * applied at the join node when using these inputs.
1651 * Unlike the situation for base rels, the set of movable join clauses to be
1652 * enforced at a join varies with the selected pair of input paths, so we
1653 * must calculate that and pass it back, even if we already have a matching
1654 * ParamPathInfo. We handle this by adding any clauses moved down to this
1655 * join to *restrict_clauses, which is an in/out parameter. (The addition
1656 * is done in such a way as to not modify the passed-in List structure.)
1658 * Note: when considering a nestloop join, the caller must have removed from
1659 * restrict_clauses any movable clauses that are themselves scheduled to be
1660 * pushed into the right-hand path. We do not do that here since it's
1661 * unnecessary for other join types.
1669 List **restrict_clauses)
1681 /* If rel has LATERAL refs, every path for it should account for them */
1684 /* Unparameterized paths have no ParamPathInfo or extra join clauses */
1691 * Identify all joinclauses that are movable to this join rel given this
1692 * parameterization. These are the clauses that are movable into this
1693 * join, but not movable into either input path. Treat an unparameterized
1694 * input path as not accepting parameterized clauses (because it won't,
1695 * per the shortcut exit above), even though the joinclause movement rules
1696 * might allow the same clauses to be moved into a parameterized path for
1700 if (outer_path->param_info)
1701 outer_and_req =
bms_union(outer_path->parent->relids,
1704 outer_and_req = NULL;
/* outer path does not accept parameters */
1705 if (inner_path->param_info)
1706 inner_and_req =
bms_union(inner_path->parent->relids,
1709 inner_and_req = NULL;
/* inner path does not accept parameters */
1720 outer_path->parent->relids,
1723 inner_path->parent->relids,
1725 pclauses =
lappend(pclauses, rinfo);
1728 /* Consider joinclauses generated by EquivalenceClasses, too */
1734 /* We only want ones that aren't movable to lower levels */
1736 foreach(lc, eclauses)
1744 outer_path->parent->relids,
1746 continue;
/* drop if movable into LHS */
1748 inner_path->parent->relids,
1751 /* drop if movable into RHS, but remember EC for use below */
1752 Assert(rinfo->left_ec == rinfo->right_ec);
1753 dropped_ecs =
lappend(dropped_ecs, rinfo->left_ec);
1756 pclauses =
lappend(pclauses, rinfo);
1760 * EquivalenceClasses are harder to deal with than we could wish, because
1761 * of the fact that a given EC can generate different clauses depending on
1762 * context. Suppose we have an EC {X.X, Y.Y, Z.Z} where X and Y are the
1763 * LHS and RHS of the current join and Z is in required_outer, and further
1764 * suppose that the inner_path is parameterized by both X and Z. The code
1765 * above will have produced either Z.Z = X.X or Z.Z = Y.Y from that EC,
1766 * and in the latter case will have discarded it as being movable into the
1767 * RHS. However, the EC machinery might have produced either Y.Y = X.X or
1768 * Y.Y = Z.Z as the EC enforcement clause within the inner_path; it will
1769 * not have produced both, and we can't readily tell from here which one
1770 * it did pick. If we add no clause to this join, we'll end up with
1771 * insufficient enforcement of the EC; either Z.Z or X.X will fail to be
1772 * constrained to be equal to the other members of the EC. (When we come
1773 * to join Z to this X/Y path, we will certainly drop whichever EC clause
1774 * is generated at that join, so this omission won't get fixed later.)
1776 * To handle this, for each EC we discarded such a clause from, try to
1777 * generate a clause connecting the required_outer rels to the join's LHS
1778 * ("Z.Z = X.X" in the terms of the above example). If successful, and if
1779 * the clause can't be moved to the LHS, add it to the current join's
1780 * restriction clauses. (If an EC cannot generate such a clause then it
1781 * has nothing that needs to be enforced here, while if the clause can be
1782 * moved into the LHS then it should have been enforced within that path.)
1784 * Note that we don't need similar processing for ECs whose clause was
1785 * considered to be movable into the LHS, because the LHS can't refer to
1786 * the RHS so there is no comparable ambiguity about what it might
1787 * actually be enforcing internally.
1791 Relids real_outer_and_req;
1793 real_outer_and_req =
bms_union(outer_path->parent->relids,
1800 outer_path->parent);
1801 foreach(lc, eclauses)
1806 outer_path->parent->relids,
1807 real_outer_and_req));
1809 outer_path->parent->relids,
1811 pclauses =
lappend(pclauses, rinfo);
1816 * Now, attach the identified moved-down clauses to the caller's
1817 * restrict_clauses list. By using list_concat in this order, we leave
1818 * the original list structure of restrict_clauses undamaged.
1820 *restrict_clauses =
list_concat(pclauses, *restrict_clauses);
1822 /* If we already have a PPI for this parameterization, just return it */
1826 /* Estimate the number of rows returned by the parameterized join */
1834 * And now we can build the ParamPathInfo. No point in saving the
1835 * input-pair-dependent clause list, though.
1837 * Note: in GEQO mode, we'll be called in a temporary memory context, but
1838 * the joinrel structure is there too, so no problem.
1851 * get_appendrel_parampathinfo
1852 * Get the ParamPathInfo for a parameterized path for an append relation.
1854 * For an append relation, the rowcount estimate will just be the sum of
1855 * the estimates for its children. However, we still need a ParamPathInfo
1856 * to flag the fact that the path requires parameters. So this just creates
1857 * a suitable struct with zero ppi_rows (and no ppi_clauses either, since
1858 * the Append node isn't responsible for checking quals).
1865 /* If rel has LATERAL refs, every path for it should account for them */
1868 /* Unparameterized paths have no ParamPathInfo */
1874 /* If we already have a PPI for this parameterization, just return it */
1878 /* Else build the ParamPathInfo */
1890 * Returns a ParamPathInfo for the parameterization given by required_outer, if
1891 * already available in the given rel. Returns NULL otherwise.
1910 * get_param_path_clause_serials
1911 * Given a parameterized Path, return the set of pushed-down clauses
1912 * (identified by rinfo_serial numbers) enforced within the Path.
1917 if (path->param_info == NULL)
1918 return NULL;
/* not parameterized */
1921 * We don't currently support parameterized MergeAppend paths, as
1922 * explained in the comments for generate_orderedappend_paths.
1931 * For a join path, combine clauses enforced within either input path
1932 * with those enforced as joinrestrictinfo in this path. Note that
1933 * joinrestrictinfo may include some non-pushed-down clauses, but for
1934 * current purposes it's okay if we include those in the result. (To
1935 * be more careful, we could check for clause_relids overlapping the
1936 * path parameterization, but it's not worth the cycles for now.)
1958 * For an appendrel, take the intersection of the sets of clauses
1959 * enforced in each input path.
1982 * Otherwise, it's a baserel path and we can use the
1983 * previously-computed set of serial numbers.
1985 return path->param_info->ppi_serials;
1990 * build_joinrel_partition_info
1991 * Checks if the two relations being joined can use partitionwise join
1992 * and if yes, initialize partitioning information of the resulting
1993 * partitioned join relation.
2003 /* Nothing to do if partitionwise join technique is disabled. */
2011 * We can only consider this join as an input to further partitionwise
2012 * joins if (a) the input relations are partitioned and have
2013 * consider_partitionwise_join=true, (b) the partition schemes match, and
2014 * (c) we can identify an equi-join between the partition keys. Note that
2015 * if it were possible for have_partkey_equi_join to return different
2016 * answers for the same joinrel depending on which join ordering we try
2017 * first, this logic would break. That shouldn't happen, though, because
2018 * of the way the query planner deduces implied equalities and reorders
2019 * the joins. Please see optimizer/README for details.
2021 if (outer_rel->part_scheme == NULL || inner_rel->part_scheme == NULL ||
2024 outer_rel->part_scheme != inner_rel->part_scheme ||
2032 part_scheme = outer_rel->part_scheme;
2035 * This function will be called only once for each joinrel, hence it
2036 * should not have partitioning fields filled yet.
2038 Assert(!joinrel->part_scheme && !joinrel->partexprs &&
2039 !joinrel->nullable_partexprs && !joinrel->part_rels &&
2040 !joinrel->boundinfo);
2043 * If the join relation is partitioned, it uses the same partitioning
2044 * scheme as the joining relations.
2046 * Note: we calculate the partition bounds, number of partitions, and
2047 * child-join relations of the join relation in try_partitionwise_join().
2049 joinrel->part_scheme = part_scheme;
2054 * Set the consider_partitionwise_join flag.
2062 * have_partkey_equi_join
2064 * Returns true if there exist equi-join conditions involving pairs
2065 * of matching partition keys of the relations being joined for all
2079 * This function must only be called when the joined relations have same
2080 * partitioning scheme.
2082 Assert(rel1->part_scheme == rel2->part_scheme);
2085 /* We use a bool array to track which partkey columns are known equal */
2086 memset(pk_known_equal, 0,
sizeof(pk_known_equal));
2087 /* ... as well as a count of how many are known equal */
2090 /* First, look through the join's restriction clauses */
2091 foreach(lc, restrictlist)
2101 /* If processing an outer join, only use its own join clauses. */
2106 /* Skip clauses which can not be used for a join. */
2107 if (!rinfo->can_join)
2110 /* Skip clauses which are not equality conditions. */
2111 if (!rinfo->mergeopfamilies && !
OidIsValid(rinfo->hashjoinoperator))
2114 /* Should be OK to assume it's an OpExpr. */
2117 /* Match the operands to the relation. */
2134 * Now we need to know whether the join operator is strict; see
2135 * comments in pathnodes.h.
2140 * Vars appearing in the relation's partition keys will not have any
2141 * varnullingrels, but those in expr1 and expr2 will if we're above
2142 * outer joins that could null the respective rels. It's okay to
2143 * match anyway, if the join operator is strict.
2149 root->outer_join_rels,
2153 root->outer_join_rels,
2158 * Only clauses referencing the partition keys are useful for
2159 * partitionwise join.
2169 * If the clause refers to keys at different ordinal positions, it can
2170 * not be used for partitionwise join.
2175 /* Ignore clause if we already proved these keys equal. */
2176 if (pk_known_equal[ipk1])
2179 /* Reject if the partition key collation differs from the clause's. */
2180 if (rel1->part_scheme->partcollation[ipk1] != opexpr->inputcollid)
2184 * The clause allows partitionwise join only if it uses the same
2185 * operator family as that specified by the partition key.
2198 /* Mark the partition key as having an equi-join clause. */
2199 pk_known_equal[ipk1] =
true;
2201 /* We can stop examining clauses once we prove all keys equal. */
2202 if (++num_equal_pks == part_scheme->
partnatts)
2207 * Also check to see if any keys are known equal by equivclass.c. In most
2208 * cases there would have been a join restriction clause generated from
2209 * any EC that had such knowledge, but there might be no such clause, or
2210 * it might happen to constrain other members of the ECs than the ones we
2213 for (
int ipk = 0; ipk < part_scheme->
partnatts; ipk++)
2217 /* Ignore if we already proved these keys equal. */
2218 if (pk_known_equal[ipk])
2222 * We need a btree opfamily to ask equivclass.c about. If the
2223 * partopfamily is a hash opfamily, look up its equality operator, and
2224 * select some btree opfamily that that operator is part of. (Any
2225 * such opfamily should be good enough, since equivclass.c will track
2226 * multiple opfamilies as appropriate.)
2231 List *eq_opfamilies;
2238 break;
/* we're not going to succeed */
2240 if (eq_opfamilies ==
NIL)
2241 break;
/* we're not going to succeed */
2248 * We consider only non-nullable partition keys here; nullable ones
2249 * would not be treated as part of the same equivalence classes as
2250 * non-nullable ones.
2252 foreach(lc, rel1->partexprs[ipk])
2256 Oid partcoll1 = rel1->part_scheme->partcollation[ipk];
2259 foreach(lc2, rel2->partexprs[ipk])
2266 * Ensure that the collation of the expression matches
2267 * that of the partition key. Checking just one collation
2268 * (partcoll1 and exprcoll1) suffices because partcoll1
2269 * and partcoll2, as well as exprcoll1 and exprcoll2,
2270 * should be identical. This holds because both rel1 and
2271 * rel2 use the same PartitionScheme and expr1 and expr2
2274 if (partcoll1 == exprcoll1)
2277 rel2->part_scheme->partcollation[ipk];
2281 Assert(partcoll2 == exprcoll2);
2282 pk_known_equal[ipk] =
true;
2287 if (pk_known_equal[ipk])
2291 if (pk_known_equal[ipk])
2293 /* We can stop examining keys once we prove all keys equal. */
2294 if (++num_equal_pks == part_scheme->
partnatts)
2298 break;
/* no chance to succeed, give up */
2305 * match_expr_to_partition_keys
2307 * Tries to match an expression to one of the nullable or non-nullable
2308 * partition keys of "rel". Returns the matched key's ordinal position,
2309 * or -1 if the expression could not be matched to any of the keys.
2311 * strict_op must be true if the expression will be compared with the
2312 * partition key using a strict operator. This allows us to consider
2313 * nullable as well as nonnullable partition keys.
2320 /* This function should be called only for partitioned relations. */
2321 Assert(rel->part_scheme);
2323 Assert(rel->nullable_partexprs);
2325 /* Remove any relabel decorations. */
2329 for (cnt = 0; cnt < rel->part_scheme->partnatts; cnt++)
2333 /* We can always match to the non-nullable partition keys. */
2334 foreach(lc, rel->partexprs[cnt])
2344 * If it's a strict join operator then a NULL partition key on one
2345 * side will not join to any partition key on the other side, and in
2346 * particular such a row can't join to a row from a different
2347 * partition on the other side. So, it's okay to search the nullable
2348 * partition keys as well.
2350 foreach(lc, rel->nullable_partexprs[cnt])
2361 * set_joinrel_partition_key_exprs
2362 * Initialize partition key expressions for a partitioned joinrel.
2373 joinrel->nullable_partexprs =
2377 * The joinrel's partition expressions are the same as those of the input
2378 * rels, but we must properly classify them as nullable or not in the
2379 * joinrel's output. (Also, we add some more partition expressions if
2380 * it's a FULL JOIN.)
2382 for (
int cnt = 0; cnt < partnatts; cnt++)
2384 /* mark these const to enforce that we copy them properly */
2385 const List *outer_expr = outer_rel->partexprs[cnt];
2386 const List *outer_null_expr = outer_rel->nullable_partexprs[cnt];
2387 const List *inner_expr = inner_rel->partexprs[cnt];
2388 const List *inner_null_expr = inner_rel->nullable_partexprs[cnt];
2390 List *nullable_partexpr =
NIL;
2396 * A join relation resulting from an INNER join may be
2397 * regarded as partitioned by either of the inner and outer
2398 * relation keys. For example, A INNER JOIN B ON A.a = B.b
2399 * can be regarded as partitioned on either A.a or B.b. So we
2400 * add both keys to the joinrel's partexpr lists. However,
2401 * anything that was already nullable still has to be treated
2411 * A join relation resulting from a SEMI or ANTI join may be
2412 * regarded as partitioned by the outer relation keys. The
2413 * inner relation's keys are no longer interesting; since they
2414 * aren't visible in the join output, nothing could join to
2420 nullable_partexpr =
list_copy(outer_null_expr);
2424 * A join relation resulting from a LEFT OUTER JOIN likewise
2425 * may be regarded as partitioned on the (non-nullable) outer
2426 * relation keys. The inner (nullable) relation keys are okay
2427 * as partition keys for further joins as long as they involve
2428 * strict join operators.
2434 nullable_partexpr =
list_concat(nullable_partexpr,
2439 * For FULL OUTER JOINs, both relations are nullable, so the
2440 * resulting join relation may be regarded as partitioned on
2441 * either of inner and outer relation keys, but only for joins
2442 * that involve strict join operators.
2447 nullable_partexpr =
list_concat(nullable_partexpr,
2449 nullable_partexpr =
list_concat(nullable_partexpr,
2453 * Also add CoalesceExprs corresponding to each possible
2454 * full-join output variable (that is, left side coalesced to
2455 * right side), so that we can match equijoin expressions
2456 * using those variables. We really only need these for
2457 * columns merged by JOIN USING, and only with the pairs of
2458 * input items that correspond to the data structures that
2459 * parse analysis would build for such variables. But it's
2460 * hard to tell which those are, so just make all the pairs.
2461 * Extra items in the nullable_partexprs list won't cause big
2462 * problems. (It's possible that such items will get matched
2463 * to user-written COALESCEs, but it should still be valid to
2464 * partition on those, since they're going to be either the
2465 * partition column or NULL; it's the same argument as for
2466 * partitionwise nesting of any outer join.) We assume no
2467 * type coercions are needed to make the coalesce expressions,
2468 * since columns of different types won't have gotten
2469 * classified as the same PartitionScheme. Note that we
2470 * intentionally leave out the varnullingrels decoration that
2471 * would ordinarily appear on the Vars inside these
2472 * CoalesceExprs, because have_partkey_equi_join will strip
2473 * varnullingrels from the expressions it will compare to the
2490 nullable_partexpr =
lappend(nullable_partexpr,
c);
2496 elog(
ERROR,
"unrecognized join type: %d", (
int) jointype);
2499 joinrel->partexprs[cnt] = partexpr;
2500 joinrel->nullable_partexprs[cnt] = nullable_partexpr;
2505 * build_child_join_reltarget
2506 * Set up a child-join relation's reltarget from a parent-join relation.
2515 /* Build the targetlist */
2519 nappinfos, appinfos);
2521 /* Set the cost and width fields */
Node * adjust_appendrel_attrs(PlannerInfo *root, Node *node, int nappinfos, AppendRelInfo **appinfos)
Relids adjust_child_relids(Relids relids, int nappinfos, AppendRelInfo **appinfos)
Bitmapset * bms_make_singleton(int x)
Bitmapset * bms_int_members(Bitmapset *a, const Bitmapset *b)
Bitmapset * bms_intersect(const Bitmapset *a, const Bitmapset *b)
uint32 bitmap_hash(const void *key, Size keysize)
bool bms_equal(const Bitmapset *a, const Bitmapset *b)
Bitmapset * bms_del_members(Bitmapset *a, const Bitmapset *b)
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
int bms_num_members(const Bitmapset *a)
bool bms_is_member(int x, const Bitmapset *a)
Bitmapset * bms_add_member(Bitmapset *a, int x)
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
int bitmap_match(const void *key1, const void *key2, Size keysize)
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Bitmapset * bms_join(Bitmapset *a, Bitmapset *b)
bool bms_nonempty_difference(const Bitmapset *a, const Bitmapset *b)
Bitmapset * bms_copy(const Bitmapset *a)
#define PG_USED_FOR_ASSERTS_ONLY
#define OidIsValid(objectId)
bool is_parallel_safe(PlannerInfo *root, Node *node)
double get_parameterized_baserel_size(PlannerInfo *root, RelOptInfo *rel, List *param_clauses)
double get_parameterized_joinrel_size(PlannerInfo *root, RelOptInfo *rel, Path *outer_path, Path *inner_path, SpecialJoinInfo *sjinfo, List *restrict_clauses)
void set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo, List *restrictlist)
bool enable_partitionwise_join
int32 clamp_width_est(int64 tuple_width)
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
HTAB * hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)
bool equal(const void *a, const void *b)
bool exprs_known_equal(PlannerInfo *root, Node *item1, Node *item2, Oid opfamily)
List * generate_join_implied_equalities_for_ecs(PlannerInfo *root, List *eclasses, Relids join_relids, Relids outer_relids, RelOptInfo *inner_rel)
void add_child_join_rel_equivalences(PlannerInfo *root, int nappinfos, AppendRelInfo **appinfos, RelOptInfo *parent_joinrel, RelOptInfo *child_joinrel)
List * generate_join_implied_equalities(PlannerInfo *root, Relids join_relids, Relids outer_relids, RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo)
bool has_relevant_eclass_joinclause(PlannerInfo *root, RelOptInfo *rel1)
#define palloc0_array(type, count)
Assert(PointerIsAligned(start, uint64))
bool apply_child_basequals(PlannerInfo *root, RelOptInfo *parentrel, RelOptInfo *childrel, RangeTblEntry *childRTE, AppendRelInfo *appinfo)
void mark_dummy_rel(RelOptInfo *rel)
List * lappend(List *list, void *datum)
List * list_concat(List *list1, const List *list2)
List * list_concat_copy(const List *list1, const List *list2)
List * list_copy(const List *oldlist)
bool list_member_oid(const List *list, Oid datum)
List * list_append_unique_ptr(List *list, void *datum)
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
List * get_mergejoin_opfamilies(Oid opno)
bool op_in_opfamily(Oid opno, Oid opfamily)
Datum subpath(PG_FUNCTION_ARGS)
void * palloc0(Size size)
MemoryContext CurrentMemoryContext
Oid exprType(const Node *expr)
Oid exprCollation(const Node *expr)
#define IsA(nodeptr, _type_)
#define IS_OUTER_JOIN(jointype)
#define castNode(_type_, nodeptr)
#define repalloc0_array(pointer, type, oldcount, count)
RTEPermissionInfo * getRTEPermissionInfo(List *rteperminfos, RangeTblEntry *rte)
@ PARTITION_STRATEGY_HASH
bool has_useful_pathkeys(PlannerInfo *root, RelOptInfo *rel)
#define RINFO_IS_PUSHED_DOWN(rinfo, joinrelids)
#define IS_PARTITIONED_REL(rel)
#define PATH_REQ_OUTER(path)
@ RELOPT_OTHER_MEMBER_REL
#define IS_OTHER_REL(rel)
#define PARTITION_MAX_KEYS
#define lfirst_node(type, lc)
static int list_length(const List *l)
static void * list_nth(const List *list, int n)
static ListCell * list_head(const List *l)
#define list_make2(x1, x2)
PlaceHolderInfo * find_placeholder_info(PlannerInfo *root, PlaceHolderVar *phv)
void add_placeholders_to_joinrel(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo)
void get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, RelOptInfo *rel)
static void build_joinrel_partition_info(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo, List *restrictlist)
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
void setup_simple_rel_arrays(PlannerInfo *root)
static void set_joinrel_partition_key_exprs(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, JoinType jointype)
ParamPathInfo * get_appendrel_parampathinfo(RelOptInfo *appendrel, Relids required_outer)
static void build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *input_rel, SpecialJoinInfo *sjinfo, List *pushed_down_joins, bool can_null)
RelOptInfo * build_child_join_rel(PlannerInfo *root, RelOptInfo *outer_rel, RelOptInfo *inner_rel, RelOptInfo *parent_joinrel, List *restrictlist, SpecialJoinInfo *sjinfo, int nappinfos, AppendRelInfo **appinfos)
static bool have_partkey_equi_join(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *rel1, RelOptInfo *rel2, JoinType jointype, List *restrictlist)
RelOptInfo * find_base_rel_noerr(PlannerInfo *root, int relid)
Relids min_join_parameterization(PlannerInfo *root, Relids joinrelids, RelOptInfo *outer_rel, RelOptInfo *inner_rel)
RelOptInfo * find_join_rel(PlannerInfo *root, Relids relids)
static void build_join_rel_hash(PlannerInfo *root)
ParamPathInfo * get_joinrel_parampathinfo(PlannerInfo *root, RelOptInfo *joinrel, Path *outer_path, Path *inner_path, SpecialJoinInfo *sjinfo, Relids required_outer, List **restrict_clauses)
Relids find_childrel_parents(PlannerInfo *root, RelOptInfo *rel)
void expand_planner_arrays(PlannerInfo *root, int add_size)
ParamPathInfo * get_baserel_parampathinfo(PlannerInfo *root, RelOptInfo *baserel, Relids required_outer)
RelOptInfo * fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
RelOptInfo * build_join_rel(PlannerInfo *root, Relids joinrelids, RelOptInfo *outer_rel, RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo, List *pushed_down_joins, List **restrictlist_ptr)
static void build_child_join_reltarget(PlannerInfo *root, RelOptInfo *parentrel, RelOptInfo *childrel, int nappinfos, AppendRelInfo **appinfos)
RelOptInfo * build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
static List * build_joinrel_restrictlist(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo)
static int match_expr_to_partition_keys(Expr *expr, RelOptInfo *rel, bool strict_op)
ParamPathInfo * find_param_path_info(RelOptInfo *rel, Relids required_outer)
static void set_foreign_rel_properties(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel)
struct JoinHashEntry JoinHashEntry
static void build_joinrel_joinlist(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel)
Bitmapset * get_param_path_clause_serials(Path *path)
static void add_join_rel(PlannerInfo *root, RelOptInfo *joinrel)
RelOptInfo * find_base_rel_ignore_join(PlannerInfo *root, int relid)
static List * subbuild_joinrel_joinlist(RelOptInfo *joinrel, List *joininfo_list, List *new_joininfo)
static List * subbuild_joinrel_restrictlist(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *input_rel, Relids both_input_relids, List *new_restrictlist)
bool join_clause_is_movable_into(RestrictInfo *rinfo, Relids currentrelids, Relids current_and_outer)
Node * remove_nulling_relids(Node *node, const Bitmapset *removable_relids, const Bitmapset *except_relids)
Size add_size(Size s1, Size s2)
#define HTEqualStrategyNumber
bool consider_param_startup
Bitmapset * notnullattnums
struct PathTarget * reltarget
List * cheapest_parameterized_paths
Relids lateral_referencers
struct Path * cheapest_startup_path
QualCost baserestrictcost
struct Path * cheapest_total_path
List * unique_groupclause
List * non_unique_for_rels
Bitmapset * eclass_indexes
Relids direct_lateral_relids
bool consider_partitionwise_join
Index baserestrict_min_security
struct RelOptInfo * unique_rel
Relids incompatible_relids
PathTarget * create_empty_pathtarget(void)