* core.c
* Routines copied from PostgreSQL core distribution.
*
-
* The main purpose of this files is having access to static functions in core.
* Another purpose is tweaking functions behavior by replacing part of them by
* macro definitions. See at the end of pg_hint_plan.c for details. Anyway,
*
* src/backend/optimizer/path/allpaths.c
*
- * static functions:
- * set_plain_rel_pathlist()
- * set_append_rel_pathlist()
- * add_paths_to_append_rel()
- * generate_mergeappend_paths()
- * get_cheapest_parameterized_child_path()
- * accumulate_append_subpath()
- *
* public functions:
* standard_join_search(): This funcion is not static. The reason for
* including this function is make_rels_by_clause_joins. In order to
* change the behavior of make_join_rel, which is called under this
* function.
*
+ * static functions:
+ * set_plain_rel_pathlist()
+ * create_plain_partial_paths()
+ * set_append_rel_pathlist()
+ * add_paths_to_append_rel()
+ * generate_mergeappend_paths()
+ * get_cheapest_parameterized_child_path()
+ *
* src/backend/optimizer/path/joinrels.c
*
* public functions:
* make_rels_by_clauseless_joins()
* join_is_legal()
* has_join_restriction()
- * is_dummy_rel()
* mark_dummy_rel()
* restriction_is_constant_false()
*
- *
- * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*-------------------------------------------------------------------------
*/
+static void populate_joinrel_with_paths(PlannerInfo *root, RelOptInfo *rel1,
+ RelOptInfo *rel2, RelOptInfo *joinrel,
+ SpecialJoinInfo *sjinfo, List *restrictlist);
/*
* set_plain_rel_pathlist
/*
+ * 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"
*/
add_paths_to_append_rel(root, rel, live_childrels);
}
+
/*
* add_paths_to_append_rel
* Generate paths for given "append" relation given the set of non-dummy
build_partitioned_rels = true;
break;
default:
- elog(ERROR, "unexpcted rtekind: %d", (int) rte->rtekind);
+ elog(ERROR, "unexpected rtekind: %d", (int) rte->rtekind);
}
/*
/*
* Consider an append of partial unordered, unparameterized partial paths.
*/
- if (partial_subpaths_valid)
+ if (partial_subpaths_valid && partial_subpaths != NIL)
{
AppendPath *appendpath;
ListCell *lc;
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
{
SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(l);
+ /* ignore full joins --- their ordering is predetermined */
+ if (sjinfo->jointype == JOIN_FULL)
+ continue;
+
if (bms_overlap(sjinfo->min_lefthand, join_plus_rhs) &&
!bms_is_subset(sjinfo->min_righthand, join_plus_rhs))
{
sjinfo->min_righthand);
more = true;
}
- /* full joins constrain both sides symmetrically */
- if (sjinfo->jointype == JOIN_FULL &&
- bms_overlap(sjinfo->min_righthand, join_plus_rhs) &&
- !bms_is_subset(sjinfo->min_lefthand, join_plus_rhs))
- {
- join_plus_rhs = bms_add_members(join_plus_rhs,
- sjinfo->min_lefthand);
- more = true;
- }
}
} while (more);
if (bms_overlap(join_plus_rhs, join_lateral_rels))
/*
- * is_dummy_rel --- has relation been proven empty?
- */
-static bool
-is_dummy_rel(RelOptInfo *rel)
-{
- return IS_DUMMY_REL(rel);
-}
-
-
-/*
* Mark a relation as proven empty.
*
* During GEQO planning, this can get invoked more than once on the same
rel->partial_pathlist = NIL;
/* Set up the dummy path */
- add_path(rel, (Path *) create_append_path(rel, NIL, NULL, 0, NIL));
+ add_path(rel, (Path *) create_append_path(rel, NIL,
+ rel->lateral_relids,
+ 0, NIL));
/* Set or update cheapest_total_path and related fields */
set_cheapest(rel);
/*
- * 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))