Skip to content

Commit cb7658e

Browse files
committed
fix parameterization (instead of stupid bms_make_singleton(outerrel->relid))
1 parent 632e864 commit cb7658e

File tree

1 file changed

+54
-18
lines changed

1 file changed

+54
-18
lines changed

src/hooks.c

Lines changed: 54 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
* definitions of rel_pathlist and join_pathlist hooks
55
*
66
* Copyright (c) 2016, Postgres Professional
7+
* Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
8+
* Portions Copyright (c) 1994, Regents of the University of California
79
*
810
* ------------------------------------------------------------------------
911
*/
@@ -38,6 +40,23 @@
3840
((path)->param_info && bms_overlap(PATH_REQ_OUTER(path), (rel)->relids))
3941

4042

43+
static inline bool
44+
allow_star_schema_join(PlannerInfo *root,
45+
Path *outer_path,
46+
Path *inner_path)
47+
{
48+
Relids innerparams = PATH_REQ_OUTER(inner_path);
49+
Relids outerrelids = outer_path->parent->relids;
50+
51+
/*
52+
* It's a star-schema case if the outer rel provides some but not all of
53+
* the inner rel's parameterization.
54+
*/
55+
return (bms_overlap(innerparams, outerrelids) &&
56+
bms_nonempty_difference(innerparams, outerrelids));
57+
}
58+
59+
4160
set_join_pathlist_hook_type set_join_pathlist_next = NULL;
4261
set_rel_pathlist_hook_type set_rel_pathlist_hook_next = NULL;
4362
planner_hook_type planner_hook_next = NULL;
@@ -59,8 +78,7 @@ pathman_join_pathlist_hook(PlannerInfo *root,
5978
JoinType saved_jointype = jointype;
6079
RangeTblEntry *inner_rte = root->simple_rte_array[innerrel->relid];
6180
const PartRelationInfo *inner_prel;
62-
List *pathkeys = NIL,
63-
*joinclauses,
81+
List *joinclauses,
6482
*otherclauses;
6583
ListCell *lc;
6684
WalkerContext context;
@@ -124,7 +142,8 @@ pathman_join_pathlist_hook(PlannerInfo *root,
124142
*inner;
125143
NestPath *nest_path; /* NestLoop we're creating */
126144
ParamPathInfo *ppi; /* parameterization info */
127-
Relids inner_required; /* required paremeterization relids */
145+
Relids required_nestloop,
146+
required_inner;
128147
List *filtered_joinclauses = NIL,
129148
*saved_ppi_list;
130149
ListCell *rinfo_lc;
@@ -151,16 +170,17 @@ pathman_join_pathlist_hook(PlannerInfo *root,
151170
if (saved_jointype == JOIN_UNIQUE_INNER)
152171
return;
153172

154-
/* Make innerrel path depend on outerrel's column */
155-
inner_required = bms_union(PATH_REQ_OUTER((Path *) cur_inner_path),
156-
bms_make_singleton(outerrel->relid));
173+
174+
/* Make inner path depend on outerrel's columns */
175+
required_inner = bms_union(PATH_REQ_OUTER((Path *) cur_inner_path),
176+
outerrel->relids);
157177

158178
/* Preserve existing ppis built by get_appendrel_parampathinfo() */
159179
saved_ppi_list = innerrel->ppilist;
160180

161181
/* Get the ParamPathInfo for a parameterized path */
162182
innerrel->ppilist = NIL;
163-
ppi = get_baserel_parampathinfo(root, innerrel, inner_required);
183+
ppi = get_baserel_parampathinfo(root, innerrel, required_inner);
164184
innerrel->ppilist = saved_ppi_list;
165185

166186
/* Skip ppi->ppi_clauses don't reference partition attribute */
@@ -173,17 +193,34 @@ pathman_join_pathlist_hook(PlannerInfo *root,
173193
if (!inner)
174194
return; /* could not build it, retreat! */
175195

196+
197+
required_nestloop = calc_nestloop_required_outer(outer, inner);
198+
199+
/*
200+
* Check to see if proposed path is still parameterized, and reject if the
201+
* parameterization wouldn't be sensible --- unless allow_star_schema_join
202+
* says to allow it anyway. Also, we must reject if have_dangerous_phv
203+
* doesn't like the look of it, which could only happen if the nestloop is
204+
* still parameterized.
205+
*/
206+
if (required_nestloop &&
207+
((!bms_overlap(required_nestloop, extra->param_source_rels) &&
208+
!allow_star_schema_join(root, outer, inner)) ||
209+
have_dangerous_phv(root, outer->parent->relids, required_inner)))
210+
return;
211+
212+
176213
initial_cost_nestloop(root, &workspace, jointype,
177214
outer, inner, /* built paths */
178215
extra->sjinfo, &extra->semifactors);
179216

180-
pathkeys = build_join_pathkeys(root, joinrel, jointype, outer->pathkeys);
181-
182217
nest_path = create_nestloop_path(root, joinrel, jointype, &workspace,
183218
extra->sjinfo, &extra->semifactors,
184219
outer, inner, extra->restrictlist,
185-
pathkeys,
186-
calc_nestloop_required_outer(outer, inner));
220+
build_join_pathkeys(root, joinrel,
221+
jointype,
222+
outer->pathkeys),
223+
required_nestloop);
187224

188225
/* Discard all clauses that are to be evaluated by 'inner' */
189226
foreach (rinfo_lc, extra->restrictlist)
@@ -196,16 +233,15 @@ pathman_join_pathlist_hook(PlannerInfo *root,
196233
}
197234

198235
/*
199-
* Override 'rows' value produced by standard estimator.
236+
* NOTE: Override 'rows' value produced by standard estimator.
200237
* Currently we use get_parameterized_joinrel_size() since
201238
* it works just fine, but this might change some day.
202239
*/
203-
nest_path->path.rows = get_parameterized_joinrel_size_compat(root,
204-
joinrel,
205-
outer,
206-
inner,
207-
extra->sjinfo,
208-
filtered_joinclauses);
240+
nest_path->path.rows =
241+
get_parameterized_joinrel_size_compat(root, joinrel,
242+
outer, inner,
243+
extra->sjinfo,
244+
filtered_joinclauses);
209245

210246
/* Finally we can add the new NestLoop path */
211247
add_path(joinrel, (Path *) nest_path);

0 commit comments

Comments
 (0)