* src/backend/optimizer/path/allpaths.c
*
* static functions:
- * set_plain_rel_pathlist()
+ * set_plain_rel_pathlist()
+ * create_plain_partial_paths()
* set_append_rel_pathlist()
* add_paths_to_append_rel()
* generate_mergeappend_paths()
/*
+ * create_plain_partial_paths
+ * Build partial access paths for parallel scan of a plain relation
+ */
+static void
+create_plain_partial_paths(PlannerInfo *root, RelOptInfo *rel)
+{
+ int parallel_workers;
+
+ parallel_workers = compute_parallel_worker(rel, rel->pages, -1);
+
+ /* If any limit was set to zero, the user doesn't want a parallel scan. */
+ if (parallel_workers <= 0)
+ return;
+
+ /* Add an unordered partial path based on a parallel sequential scan. */
+ add_partial_path(rel, create_seqscan_path(root, rel, NULL, parallel_workers));
+}
+
+
+/*
* set_append_rel_pathlist
* Build access paths for an "append relation"
*/
ListCell *l;
List *partitioned_rels = NIL;
RangeTblEntry *rte;
+ bool build_partitioned_rels = false;
+ /*
+ * A plain relation will already have a PartitionedChildRelInfo if it is
+ * partitioned. For a subquery RTE, no PartitionedChildRelInfo exists; we
+ * collect all partitioned_rels associated with any child. (This assumes
+ * that we don't need to look through multiple levels of subquery RTEs; if
+ * we ever do, we could create a PartitionedChildRelInfo with the
+ * accumulated list of partitioned_rels which would then be found when
+ * populated our parent rel with paths. For the present, that appears to
+ * be unnecessary.)
+ */
rte = planner_rt_fetch(rel->relid, root);
- if (rte->relkind == RELKIND_PARTITIONED_TABLE)
+ switch (rte->rtekind)
{
- partitioned_rels = get_partitioned_child_rels(root, rel->relid);
- /* The root partitioned table is included as a child rel */
- Assert(list_length(partitioned_rels) >= 1);
+ case RTE_RELATION:
+ if (rte->relkind == RELKIND_PARTITIONED_TABLE)
+ {
+ partitioned_rels =
+ get_partitioned_child_rels(root, rel->relid);
+ Assert(list_length(partitioned_rels) >= 1);
+ }
+ break;
+ case RTE_SUBQUERY:
+ build_partitioned_rels = true;
+ break;
+ default:
+ elog(ERROR, "unexpected rtekind: %d", (int) rte->rtekind);
}
/*
ListCell *lcp;
/*
+ * If we need to build partitioned_rels, accumulate the partitioned
+ * rels for this child.
+ */
+ if (build_partitioned_rels)
+ {
+ List *cprels;
+
+ cprels = get_partitioned_child_rels(root, childrel->relid);
+ partitioned_rels = list_concat(partitioned_rels,
+ list_copy(cprels));
+ }
+
+ /*
* If child has an unparameterized cheapest-total path, add that to
* the unparameterized Append path we are constructing for the parent.
* If not, there's no workable unparameterized path.
return rel;
}
-/*
- * create_plain_partial_paths
- * Build partial access paths for parallel scan of a plain relation
- */
-static void
-create_plain_partial_paths(PlannerInfo *root, RelOptInfo *rel)
-{
- int parallel_workers;
-
- parallel_workers = compute_parallel_worker(rel, rel->pages, -1);
-
- /* If any limit was set to zero, the user doesn't want a parallel scan. */
- if (parallel_workers <= 0)
- return;
-
- /* Add an unordered partial path based on a parallel sequential scan. */
- add_partial_path(rel, create_seqscan_path(root, rel, NULL, parallel_workers));
-}
-
/*
* join_search_one_level
/*
- * restriction_is_constant_false --- is a restrictlist just FALSE?
+ * restriction_is_constant_false --- is a restrictlist just false?
*
- * In cases where a qual is provably constant FALSE, eval_const_expressions
+ * In cases where a qual is provably constant false, eval_const_expressions
* will generally have thrown away anything that's ANDed with it. In outer
* join situations this will leave us computing cartesian products only to
* decide there's no match for an outer row, which is pretty stupid. So,
* we need to detect the case.
*
- * If only_pushed_down is TRUE, then consider only pushed-down quals.
+ * If only_pushed_down is true, then consider only quals that are pushed-down
+ * from the point of view of the joinrel.
*/
static bool
-restriction_is_constant_false(List *restrictlist, bool only_pushed_down)
+restriction_is_constant_false(List *restrictlist,
+ RelOptInfo *joinrel,
+ bool only_pushed_down)
{
ListCell *lc;
{
RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
- if (only_pushed_down && !rinfo->is_pushed_down)
+ if (only_pushed_down && !RINFO_IS_PUSHED_DOWN(rinfo, joinrel->relids))
continue;
if (rinfo->clause && IsA(rinfo->clause, Const))
}
return false;
}
-