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 */
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+
4160set_join_pathlist_hook_type set_join_pathlist_next = NULL ;
4261set_rel_pathlist_hook_type set_rel_pathlist_hook_next = NULL ;
4362planner_hook_type planner_hook_next = NULL ;
@@ -59,8 +78,7 @@ pathman_join_pathlist_hook(PlannerInfo *root,
5978JoinType saved_jointype = jointype ;
6079RangeTblEntry * inner_rte = root -> simple_rte_array [innerrel -> relid ];
6180const PartRelationInfo * inner_prel ;
62- List * pathkeys = NIL ,
63- * joinclauses ,
81+ List * joinclauses ,
6482* otherclauses ;
6583ListCell * lc ;
6684WalkerContext context ;
@@ -124,7 +142,8 @@ pathman_join_pathlist_hook(PlannerInfo *root,
124142* inner ;
125143NestPath * nest_path ;/* NestLoop we're creating */
126144ParamPathInfo * ppi ;/* parameterization info */
127- Relids inner_required ;/* required paremeterization relids */
145+ Relids required_nestloop ,
146+ required_inner ;
128147List * filtered_joinclauses = NIL ,
129148* saved_ppi_list ;
130149ListCell * rinfo_lc ;
@@ -151,16 +170,17 @@ pathman_join_pathlist_hook(PlannerInfo *root,
151170if (saved_jointype == JOIN_UNIQUE_INNER )
152171return ;
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() */
159179saved_ppi_list = innerrel -> ppilist ;
160180
161181/* Get the ParamPathInfo for a parameterized path */
162182innerrel -> ppilist = NIL ;
163- ppi = get_baserel_parampathinfo (root ,innerrel ,inner_required );
183+ ppi = get_baserel_parampathinfo (root ,innerrel ,required_inner );
164184innerrel -> 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,
173193if (!inner )
174194return ;/* 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+
176213initial_cost_nestloop (root ,& workspace ,jointype ,
177214outer ,inner ,/* built paths */
178215extra -> sjinfo ,& extra -> semifactors );
179216
180- pathkeys = build_join_pathkeys (root ,joinrel ,jointype ,outer -> pathkeys );
181-
182217nest_path = create_nestloop_path (root ,joinrel ,jointype ,& workspace ,
183218extra -> sjinfo ,& extra -> semifactors ,
184219outer ,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' */
189226foreach (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 */
211247add_path (joinrel , (Path * )nest_path );