Skip to content

Commit e139f19

Browse files
committed
Assorted preparatory refactoring for partition-wise join.
Instead of duplicating the logic to search for a matching ParamPathInfo in multiple places, factor it out into a separate function. Pass only the relevant bits of the PartitionKey to partition_bounds_equal instead of the whole thing, because partition-wise join will want to call this without having a PartitionKey available. Adjust allow_star_schema_join and calc_nestloop_required_outer to take relevant Relids rather than the entire Path, because partition-wise join will want to call it with the top-parent relids to determine whether a child join is allowable. Ashutosh Bapat. Review and testing of the larger patch set of which this is a part by Amit Langote, Rajkumar Raghuwanshi, Rafia Sabih, Thomas Munro, Dilip Kumar, and me. Discussion: http://postgr.es/m/CA+TgmobQK80vtXjAsPZWWXd7c8u13G86gmuLupN+uUJjA+i4nA@mail.gmail.com
1 parent 00418c6 commit e139f19

File tree

7 files changed

+62
-46
lines changed

7 files changed

+62
-46
lines changed

src/backend/catalog/partition.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -583,7 +583,7 @@ RelationBuildPartitionDesc(Relation rel)
583583
* representation of partition bounds.
584584
*/
585585
bool
586-
partition_bounds_equal(PartitionKey key,
586+
partition_bounds_equal(int partnatts, int16 *parttyplen, bool *parttypbyval,
587587
PartitionBoundInfo b1, PartitionBoundInfo b2)
588588
{
589589
int i;
@@ -601,7 +601,7 @@ partition_bounds_equal(PartitionKey key,
601601
{
602602
int j;
603603

604-
for (j = 0; j < key->partnatts; j++)
604+
for (j = 0; j < partnatts; j++)
605605
{
606606
/* For range partitions, the bounds might not be finite. */
607607
if (b1->kind != NULL)
@@ -627,8 +627,7 @@ partition_bounds_equal(PartitionKey key,
627627
* context. datumIsEqual() should be simple enough to be safe.
628628
*/
629629
if (!datumIsEqual(b1->datums[i][j], b2->datums[i][j],
630-
key->parttypbyval[j],
631-
key->parttyplen[j]))
630+
parttypbyval[j], parttyplen[j]))
632631
return false;
633632
}
634633

@@ -637,7 +636,7 @@ partition_bounds_equal(PartitionKey key,
637636
}
638637

639638
/* There are ndatums+1 indexes in case of range partitions */
640-
if (key->strategy == PARTITION_STRATEGY_RANGE &&
639+
if (b1->strategy == PARTITION_STRATEGY_RANGE &&
641640
b1->indexes[i] != b2->indexes[i])
642641
return false;
643642

src/backend/optimizer/path/joinpath.c

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -318,18 +318,15 @@ add_paths_to_joinrel(PlannerInfo *root,
318318
*/
319319
static inline bool
320320
allow_star_schema_join(PlannerInfo *root,
321-
Path *outer_path,
322-
Path *inner_path)
321+
Relids outerrelids,
322+
Relids inner_paramrels)
323323
{
324-
Relids innerparams = PATH_REQ_OUTER(inner_path);
325-
Relids outerrelids = outer_path->parent->relids;
326-
327324
/*
328325
* It's a star-schema case if the outer rel provides some but not all of
329326
* the inner rel's parameterization.
330327
*/
331-
return (bms_overlap(innerparams, outerrelids) &&
332-
bms_nonempty_difference(innerparams, outerrelids));
328+
return (bms_overlap(inner_paramrels, outerrelids) &&
329+
bms_nonempty_difference(inner_paramrels, outerrelids));
333330
}
334331

335332
/*
@@ -348,6 +345,12 @@ try_nestloop_path(PlannerInfo *root,
348345
{
349346
Relids required_outer;
350347
JoinCostWorkspace workspace;
348+
RelOptInfo *innerrel = inner_path->parent;
349+
RelOptInfo *outerrel = outer_path->parent;
350+
Relids innerrelids = innerrel->relids;
351+
Relids outerrelids = outerrel->relids;
352+
Relids inner_paramrels = PATH_REQ_OUTER(inner_path);
353+
Relids outer_paramrels = PATH_REQ_OUTER(outer_path);
351354

352355
/*
353356
* Check to see if proposed path is still parameterized, and reject if the
@@ -356,14 +359,12 @@ try_nestloop_path(PlannerInfo *root,
356359
* doesn't like the look of it, which could only happen if the nestloop is
357360
* still parameterized.
358361
*/
359-
required_outer = calc_nestloop_required_outer(outer_path,
360-
inner_path);
362+
required_outer = calc_nestloop_required_outer(outerrelids, outer_paramrels,
363+
innerrelids, inner_paramrels);
361364
if (required_outer &&
362365
((!bms_overlap(required_outer, extra->param_source_rels) &&
363-
!allow_star_schema_join(root, outer_path, inner_path)) ||
364-
have_dangerous_phv(root,
365-
outer_path->parent->relids,
366-
PATH_REQ_OUTER(inner_path))))
366+
!allow_star_schema_join(root, outerrelids, inner_paramrels)) ||
367+
have_dangerous_phv(root, outerrelids, inner_paramrels)))
367368
{
368369
/* Waste no memory when we reject a path here */
369370
bms_free(required_outer);

src/backend/optimizer/util/pathnode.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1993,22 +1993,23 @@ create_foreignscan_path(PlannerInfo *root, RelOptInfo *rel,
19931993
* Note: result must not share storage with either input
19941994
*/
19951995
Relids
1996-
calc_nestloop_required_outer(Path *outer_path, Path *inner_path)
1996+
calc_nestloop_required_outer(Relids outerrelids,
1997+
Relids outer_paramrels,
1998+
Relids innerrelids,
1999+
Relids inner_paramrels)
19972000
{
1998-
Relids outer_paramrels = PATH_REQ_OUTER(outer_path);
1999-
Relids inner_paramrels = PATH_REQ_OUTER(inner_path);
20002001
Relids required_outer;
20012002

20022003
/* inner_path can require rels from outer path, but not vice versa */
2003-
Assert(!bms_overlap(outer_paramrels, inner_path->parent->relids));
2004+
Assert(!bms_overlap(outer_paramrels, innerrelids));
20042005
/* easy case if inner path is not parameterized */
20052006
if (!inner_paramrels)
20062007
return bms_copy(outer_paramrels);
20072008
/* else, form the union ... */
20082009
required_outer = bms_union(outer_paramrels, inner_paramrels);
20092010
/* ... and remove any mention of now-satisfied outer rels */
20102011
required_outer = bms_del_members(required_outer,
2011-
outer_path->parent->relids);
2012+
outerrelids);
20122013
/* maintain invariant that required_outer is exactly NULL if empty */
20132014
if (bms_is_empty(required_outer))
20142015
{

src/backend/optimizer/util/relnode.c

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1048,12 +1048,8 @@ get_baserel_parampathinfo(PlannerInfo *root, RelOptInfo *baserel,
10481048
Assert(!bms_overlap(baserel->relids, required_outer));
10491049

10501050
/* If we already have a PPI for this parameterization, just return it */
1051-
foreach(lc, baserel->ppilist)
1052-
{
1053-
ppi = (ParamPathInfo *) lfirst(lc);
1054-
if (bms_equal(ppi->ppi_req_outer, required_outer))
1055-
return ppi;
1056-
}
1051+
if ((ppi = find_param_path_info(baserel, required_outer)))
1052+
return ppi;
10571053

10581054
/*
10591055
* Identify all joinclauses that are movable to this base rel given this
@@ -1290,12 +1286,8 @@ get_joinrel_parampathinfo(PlannerInfo *root, RelOptInfo *joinrel,
12901286
*restrict_clauses = list_concat(pclauses, *restrict_clauses);
12911287

12921288
/* If we already have a PPI for this parameterization, just return it */
1293-
foreach(lc, joinrel->ppilist)
1294-
{
1295-
ppi = (ParamPathInfo *) lfirst(lc);
1296-
if (bms_equal(ppi->ppi_req_outer, required_outer))
1297-
return ppi;
1298-
}
1289+
if ((ppi = find_param_path_info(joinrel, required_outer)))
1290+
return ppi;
12991291

13001292
/* Estimate the number of rows returned by the parameterized join */
13011293
rows = get_parameterized_joinrel_size(root, joinrel,
@@ -1334,7 +1326,6 @@ ParamPathInfo *
13341326
get_appendrel_parampathinfo(RelOptInfo *appendrel, Relids required_outer)
13351327
{
13361328
ParamPathInfo *ppi;
1337-
ListCell *lc;
13381329

13391330
/* Unparameterized paths have no ParamPathInfo */
13401331
if (bms_is_empty(required_outer))
@@ -1343,12 +1334,8 @@ get_appendrel_parampathinfo(RelOptInfo *appendrel, Relids required_outer)
13431334
Assert(!bms_overlap(appendrel->relids, required_outer));
13441335

13451336
/* If we already have a PPI for this parameterization, just return it */
1346-
foreach(lc, appendrel->ppilist)
1347-
{
1348-
ppi = (ParamPathInfo *) lfirst(lc);
1349-
if (bms_equal(ppi->ppi_req_outer, required_outer))
1350-
return ppi;
1351-
}
1337+
if ((ppi = find_param_path_info(appendrel, required_outer)))
1338+
return ppi;
13521339

13531340
/* Else build the ParamPathInfo */
13541341
ppi = makeNode(ParamPathInfo);
@@ -1359,3 +1346,23 @@ get_appendrel_parampathinfo(RelOptInfo *appendrel, Relids required_outer)
13591346

13601347
return ppi;
13611348
}
1349+
1350+
/*
1351+
* Returns a ParamPathInfo for the parameterization given by required_outer, if
1352+
* already available in the given rel. Returns NULL otherwise.
1353+
*/
1354+
ParamPathInfo *
1355+
find_param_path_info(RelOptInfo *rel, Relids required_outer)
1356+
{
1357+
ListCell *lc;
1358+
1359+
foreach(lc, rel->ppilist)
1360+
{
1361+
ParamPathInfo *ppi = (ParamPathInfo *) lfirst(lc);
1362+
1363+
if (bms_equal(ppi->ppi_req_outer, required_outer))
1364+
return ppi;
1365+
}
1366+
1367+
return NULL;
1368+
}

src/backend/utils/cache/relcache.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1208,7 +1208,9 @@ equalPartitionDescs(PartitionKey key, PartitionDesc partdesc1,
12081208
if (partdesc2->boundinfo == NULL)
12091209
return false;
12101210

1211-
if (!partition_bounds_equal(key, partdesc1->boundinfo,
1211+
if (!partition_bounds_equal(key->partnatts, key->parttyplen,
1212+
key->parttypbyval,
1213+
partdesc1->boundinfo,
12121214
partdesc2->boundinfo))
12131215
return false;
12141216
}

src/include/catalog/partition.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,9 @@ typedef struct PartitionDispatchData
7171
typedef struct PartitionDispatchData *PartitionDispatch;
7272

7373
extern void RelationBuildPartitionDesc(Relation relation);
74-
extern bool partition_bounds_equal(PartitionKey key,
75-
PartitionBoundInfo p1, PartitionBoundInfo p2);
74+
extern bool partition_bounds_equal(int partnatts, int16 *parttyplen,
75+
bool *parttypbyval, PartitionBoundInfo b1,
76+
PartitionBoundInfo b2);
7677

7778
extern void check_new_partition_bound(char *relname, Relation parent,
7879
PartitionBoundSpec *spec);

src/include/optimizer/pathnode.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,10 @@ extern ForeignPath *create_foreignscan_path(PlannerInfo *root, RelOptInfo *rel,
112112
Path *fdw_outerpath,
113113
List *fdw_private);
114114

115-
extern Relids calc_nestloop_required_outer(Path *outer_path, Path *inner_path);
115+
extern Relids calc_nestloop_required_outer(Relids outerrelids,
116+
Relids outer_paramrels,
117+
Relids innerrelids,
118+
Relids inner_paramrels);
116119
extern Relids calc_non_nestloop_required_outer(Path *outer_path, Path *inner_path);
117120

118121
extern NestPath *create_nestloop_path(PlannerInfo *root,
@@ -285,5 +288,7 @@ extern ParamPathInfo *get_joinrel_parampathinfo(PlannerInfo *root,
285288
List **restrict_clauses);
286289
extern ParamPathInfo *get_appendrel_parampathinfo(RelOptInfo *appendrel,
287290
Relids required_outer);
291+
extern ParamPathInfo *find_param_path_info(RelOptInfo *rel,
292+
Relids required_outer);
288293

289294
#endif /* PATHNODE_H */

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy