* representation of partition bounds.
*/
bool
-partition_bounds_equal(PartitionKey key,
+partition_bounds_equal(int partnatts, int16 *parttyplen, bool *parttypbyval,
PartitionBoundInfo b1, PartitionBoundInfo b2)
{
int i;
{
int j;
- for (j = 0; j < key->partnatts; j++)
+ for (j = 0; j < partnatts; j++)
{
/* For range partitions, the bounds might not be finite. */
if (b1->kind != NULL)
* context. datumIsEqual() should be simple enough to be safe.
*/
if (!datumIsEqual(b1->datums[i][j], b2->datums[i][j],
- key->parttypbyval[j],
- key->parttyplen[j]))
+ parttypbyval[j], parttyplen[j]))
return false;
}
}
/* There are ndatums+1 indexes in case of range partitions */
- if (key->strategy == PARTITION_STRATEGY_RANGE &&
+ if (b1->strategy == PARTITION_STRATEGY_RANGE &&
b1->indexes[i] != b2->indexes[i])
return false;
*/
static inline bool
allow_star_schema_join(PlannerInfo *root,
- Path *outer_path,
- Path *inner_path)
+ Relids outerrelids,
+ Relids inner_paramrels)
{
- Relids innerparams = PATH_REQ_OUTER(inner_path);
- Relids outerrelids = outer_path->parent->relids;
-
/*
* It's a star-schema case if the outer rel provides some but not all of
* the inner rel's parameterization.
*/
- return (bms_overlap(innerparams, outerrelids) &&
- bms_nonempty_difference(innerparams, outerrelids));
+ return (bms_overlap(inner_paramrels, outerrelids) &&
+ bms_nonempty_difference(inner_paramrels, outerrelids));
}
/*
{
Relids required_outer;
JoinCostWorkspace workspace;
+ RelOptInfo *innerrel = inner_path->parent;
+ RelOptInfo *outerrel = outer_path->parent;
+ Relids innerrelids = innerrel->relids;
+ Relids outerrelids = outerrel->relids;
+ Relids inner_paramrels = PATH_REQ_OUTER(inner_path);
+ Relids outer_paramrels = PATH_REQ_OUTER(outer_path);
/*
* Check to see if proposed path is still parameterized, and reject if the
* doesn't like the look of it, which could only happen if the nestloop is
* still parameterized.
*/
- required_outer = calc_nestloop_required_outer(outer_path,
- inner_path);
+ required_outer = calc_nestloop_required_outer(outerrelids, outer_paramrels,
+ innerrelids, inner_paramrels);
if (required_outer &&
((!bms_overlap(required_outer, extra->param_source_rels) &&
- !allow_star_schema_join(root, outer_path, inner_path)) ||
- have_dangerous_phv(root,
- outer_path->parent->relids,
- PATH_REQ_OUTER(inner_path))))
+ !allow_star_schema_join(root, outerrelids, inner_paramrels)) ||
+ have_dangerous_phv(root, outerrelids, inner_paramrels)))
{
/* Waste no memory when we reject a path here */
bms_free(required_outer);
* Note: result must not share storage with either input
*/
Relids
-calc_nestloop_required_outer(Path *outer_path, Path *inner_path)
+calc_nestloop_required_outer(Relids outerrelids,
+ Relids outer_paramrels,
+ Relids innerrelids,
+ Relids inner_paramrels)
{
- Relids outer_paramrels = PATH_REQ_OUTER(outer_path);
- Relids inner_paramrels = PATH_REQ_OUTER(inner_path);
Relids required_outer;
/* inner_path can require rels from outer path, but not vice versa */
- Assert(!bms_overlap(outer_paramrels, inner_path->parent->relids));
+ Assert(!bms_overlap(outer_paramrels, innerrelids));
/* easy case if inner path is not parameterized */
if (!inner_paramrels)
return bms_copy(outer_paramrels);
required_outer = bms_union(outer_paramrels, inner_paramrels);
/* ... and remove any mention of now-satisfied outer rels */
required_outer = bms_del_members(required_outer,
- outer_path->parent->relids);
+ outerrelids);
/* maintain invariant that required_outer is exactly NULL if empty */
if (bms_is_empty(required_outer))
{
Assert(!bms_overlap(baserel->relids, required_outer));
/* If we already have a PPI for this parameterization, just return it */
- foreach(lc, baserel->ppilist)
- {
- ppi = (ParamPathInfo *) lfirst(lc);
- if (bms_equal(ppi->ppi_req_outer, required_outer))
- return ppi;
- }
+ if ((ppi = find_param_path_info(baserel, required_outer)))
+ return ppi;
/*
* Identify all joinclauses that are movable to this base rel given this
*restrict_clauses = list_concat(pclauses, *restrict_clauses);
/* If we already have a PPI for this parameterization, just return it */
- foreach(lc, joinrel->ppilist)
- {
- ppi = (ParamPathInfo *) lfirst(lc);
- if (bms_equal(ppi->ppi_req_outer, required_outer))
- return ppi;
- }
+ if ((ppi = find_param_path_info(joinrel, required_outer)))
+ return ppi;
/* Estimate the number of rows returned by the parameterized join */
rows = get_parameterized_joinrel_size(root, joinrel,
get_appendrel_parampathinfo(RelOptInfo *appendrel, Relids required_outer)
{
ParamPathInfo *ppi;
- ListCell *lc;
/* Unparameterized paths have no ParamPathInfo */
if (bms_is_empty(required_outer))
Assert(!bms_overlap(appendrel->relids, required_outer));
/* If we already have a PPI for this parameterization, just return it */
- foreach(lc, appendrel->ppilist)
- {
- ppi = (ParamPathInfo *) lfirst(lc);
- if (bms_equal(ppi->ppi_req_outer, required_outer))
- return ppi;
- }
+ if ((ppi = find_param_path_info(appendrel, required_outer)))
+ return ppi;
/* Else build the ParamPathInfo */
ppi = makeNode(ParamPathInfo);
return ppi;
}
+
+/*
+ * Returns a ParamPathInfo for the parameterization given by required_outer, if
+ * already available in the given rel. Returns NULL otherwise.
+ */
+ParamPathInfo *
+find_param_path_info(RelOptInfo *rel, Relids required_outer)
+{
+ ListCell *lc;
+
+ foreach(lc, rel->ppilist)
+ {
+ ParamPathInfo *ppi = (ParamPathInfo *) lfirst(lc);
+
+ if (bms_equal(ppi->ppi_req_outer, required_outer))
+ return ppi;
+ }
+
+ return NULL;
+}
if (partdesc2->boundinfo == NULL)
return false;
- if (!partition_bounds_equal(key, partdesc1->boundinfo,
+ if (!partition_bounds_equal(key->partnatts, key->parttyplen,
+ key->parttypbyval,
+ partdesc1->boundinfo,
partdesc2->boundinfo))
return false;
}
typedef struct PartitionDispatchData *PartitionDispatch;
extern void RelationBuildPartitionDesc(Relation relation);
-extern bool partition_bounds_equal(PartitionKey key,
- PartitionBoundInfo p1, PartitionBoundInfo p2);
+extern bool partition_bounds_equal(int partnatts, int16 *parttyplen,
+ bool *parttypbyval, PartitionBoundInfo b1,
+ PartitionBoundInfo b2);
extern void check_new_partition_bound(char *relname, Relation parent,
PartitionBoundSpec *spec);
Path *fdw_outerpath,
List *fdw_private);
-extern Relids calc_nestloop_required_outer(Path *outer_path, Path *inner_path);
+extern Relids calc_nestloop_required_outer(Relids outerrelids,
+ Relids outer_paramrels,
+ Relids innerrelids,
+ Relids inner_paramrels);
extern Relids calc_non_nestloop_required_outer(Path *outer_path, Path *inner_path);
extern NestPath *create_nestloop_path(PlannerInfo *root,
List **restrict_clauses);
extern ParamPathInfo *get_appendrel_parampathinfo(RelOptInfo *appendrel,
Relids required_outer);
+extern ParamPathInfo *find_param_path_info(RelOptInfo *rel,
+ Relids required_outer);
#endif /* PATHNODE_H */