Skip to content

Commit 0568e7a

Browse files
committed
Cosmetic improvements for code related to partitionwise join.
Move have_partkey_equi_join and match_expr_to_partition_keys to relnode.c, since they're used only there. Refactor build_joinrel_partition_info to split out the code that fills the joinrel's partition key lists; this doesn't have any non-cosmetic impact, but it seems like a useful separation of concerns. Improve assorted nearby comments. Amit Langote, with a little further editorialization by me Discussion: https://postgr.es/m/CA+HiwqG2WVUGmLJqtR0tPFhniO=H=9qQ+Z3L_ZC+Y3-EVQHFGg@mail.gmail.com
1 parent 21dc488 commit 0568e7a

File tree

5 files changed

+283
-234
lines changed

5 files changed

+283
-234
lines changed

src/backend/optimizer/path/joinrels.c

Lines changed: 0 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
#include "optimizer/pathnode.h"
2121
#include "optimizer/paths.h"
2222
#include "partitioning/partbounds.h"
23-
#include "utils/lsyscache.h"
2423
#include "utils/memutils.h"
2524

2625

@@ -46,8 +45,6 @@ static void try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1,
4645
static SpecialJoinInfo *build_child_join_sjinfo(PlannerInfo *root,
4746
SpecialJoinInfo *parent_sjinfo,
4847
Relids left_relids, Relids right_relids);
49-
static int match_expr_to_partition_keys(Expr *expr, RelOptInfo *rel,
50-
bool strict_op);
5148

5249

5350
/*
@@ -1573,168 +1570,3 @@ build_child_join_sjinfo(PlannerInfo *root, SpecialJoinInfo *parent_sjinfo,
15731570

15741571
return sjinfo;
15751572
}
1576-
1577-
/*
1578-
* Returns true if there exists an equi-join condition for each pair of
1579-
* partition keys from given relations being joined.
1580-
*/
1581-
bool
1582-
have_partkey_equi_join(RelOptInfo *joinrel,
1583-
RelOptInfo *rel1, RelOptInfo *rel2,
1584-
JoinType jointype, List *restrictlist)
1585-
{
1586-
PartitionScheme part_scheme = rel1->part_scheme;
1587-
ListCell *lc;
1588-
int cnt_pks;
1589-
bool pk_has_clause[PARTITION_MAX_KEYS];
1590-
bool strict_op;
1591-
1592-
/*
1593-
* This function should be called when the joining relations have same
1594-
* partitioning scheme.
1595-
*/
1596-
Assert(rel1->part_scheme == rel2->part_scheme);
1597-
Assert(part_scheme);
1598-
1599-
memset(pk_has_clause, 0, sizeof(pk_has_clause));
1600-
foreach(lc, restrictlist)
1601-
{
1602-
RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
1603-
OpExpr *opexpr;
1604-
Expr *expr1;
1605-
Expr *expr2;
1606-
int ipk1;
1607-
int ipk2;
1608-
1609-
/* If processing an outer join, only use its own join clauses. */
1610-
if (IS_OUTER_JOIN(jointype) &&
1611-
RINFO_IS_PUSHED_DOWN(rinfo, joinrel->relids))
1612-
continue;
1613-
1614-
/* Skip clauses which can not be used for a join. */
1615-
if (!rinfo->can_join)
1616-
continue;
1617-
1618-
/* Skip clauses which are not equality conditions. */
1619-
if (!rinfo->mergeopfamilies && !OidIsValid(rinfo->hashjoinoperator))
1620-
continue;
1621-
1622-
opexpr = castNode(OpExpr, rinfo->clause);
1623-
1624-
/*
1625-
* The equi-join between partition keys is strict if equi-join between
1626-
* at least one partition key is using a strict operator. See
1627-
* explanation about outer join reordering identity 3 in
1628-
* optimizer/README
1629-
*/
1630-
strict_op = op_strict(opexpr->opno);
1631-
1632-
/* Match the operands to the relation. */
1633-
if (bms_is_subset(rinfo->left_relids, rel1->relids) &&
1634-
bms_is_subset(rinfo->right_relids, rel2->relids))
1635-
{
1636-
expr1 = linitial(opexpr->args);
1637-
expr2 = lsecond(opexpr->args);
1638-
}
1639-
else if (bms_is_subset(rinfo->left_relids, rel2->relids) &&
1640-
bms_is_subset(rinfo->right_relids, rel1->relids))
1641-
{
1642-
expr1 = lsecond(opexpr->args);
1643-
expr2 = linitial(opexpr->args);
1644-
}
1645-
else
1646-
continue;
1647-
1648-
/*
1649-
* Only clauses referencing the partition keys are useful for
1650-
* partitionwise join.
1651-
*/
1652-
ipk1 = match_expr_to_partition_keys(expr1, rel1, strict_op);
1653-
if (ipk1 < 0)
1654-
continue;
1655-
ipk2 = match_expr_to_partition_keys(expr2, rel2, strict_op);
1656-
if (ipk2 < 0)
1657-
continue;
1658-
1659-
/*
1660-
* If the clause refers to keys at different ordinal positions, it can
1661-
* not be used for partitionwise join.
1662-
*/
1663-
if (ipk1 != ipk2)
1664-
continue;
1665-
1666-
/*
1667-
* The clause allows partitionwise join if only it uses the same
1668-
* operator family as that specified by the partition key.
1669-
*/
1670-
if (rel1->part_scheme->strategy == PARTITION_STRATEGY_HASH)
1671-
{
1672-
if (!op_in_opfamily(rinfo->hashjoinoperator,
1673-
part_scheme->partopfamily[ipk1]))
1674-
continue;
1675-
}
1676-
else if (!list_member_oid(rinfo->mergeopfamilies,
1677-
part_scheme->partopfamily[ipk1]))
1678-
continue;
1679-
1680-
/* Mark the partition key as having an equi-join clause. */
1681-
pk_has_clause[ipk1] = true;
1682-
}
1683-
1684-
/* Check whether every partition key has an equi-join condition. */
1685-
for (cnt_pks = 0; cnt_pks < part_scheme->partnatts; cnt_pks++)
1686-
{
1687-
if (!pk_has_clause[cnt_pks])
1688-
return false;
1689-
}
1690-
1691-
return true;
1692-
}
1693-
1694-
/*
1695-
* Find the partition key from the given relation matching the given
1696-
* expression. If found, return the index of the partition key, else return -1.
1697-
*/
1698-
static int
1699-
match_expr_to_partition_keys(Expr *expr, RelOptInfo *rel, bool strict_op)
1700-
{
1701-
int cnt;
1702-
1703-
/* This function should be called only for partitioned relations. */
1704-
Assert(rel->part_scheme);
1705-
1706-
/* Remove any relabel decorations. */
1707-
while (IsA(expr, RelabelType))
1708-
expr = (Expr *) (castNode(RelabelType, expr))->arg;
1709-
1710-
for (cnt = 0; cnt < rel->part_scheme->partnatts; cnt++)
1711-
{
1712-
ListCell *lc;
1713-
1714-
Assert(rel->partexprs);
1715-
foreach(lc, rel->partexprs[cnt])
1716-
{
1717-
if (equal(lfirst(lc), expr))
1718-
return cnt;
1719-
}
1720-
1721-
if (!strict_op)
1722-
continue;
1723-
1724-
/*
1725-
* If it's a strict equi-join a NULL partition key on one side will
1726-
* not join a NULL partition key on the other side. So, rows with NULL
1727-
* partition key from a partition on one side can not join with those
1728-
* from a non-matching partition on the other side. So, search the
1729-
* nullable partition keys as well.
1730-
*/
1731-
Assert(rel->nullable_partexprs);
1732-
foreach(lc, rel->nullable_partexprs[cnt])
1733-
{
1734-
if (equal(lfirst(lc), expr))
1735-
return cnt;
1736-
}
1737-
}
1738-
1739-
return -1;
1740-
}

src/backend/optimizer/util/plancat.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2250,9 +2250,8 @@ find_partition_scheme(PlannerInfo *root, Relation relation)
22502250
/*
22512251
* set_baserel_partition_key_exprs
22522252
*
2253-
* Builds partition key expressions for the given base relation and sets them
2254-
* in given RelOptInfo. Any single column partition keys are converted to Var
2255-
* nodes. All Var nodes are restamped with the relid of given relation.
2253+
* Builds partition key expressions for the given base relation and fills
2254+
* rel->partexprs.
22562255
*/
22572256
static void
22582257
set_baserel_partition_key_exprs(Relation relation,
@@ -2300,16 +2299,17 @@ set_baserel_partition_key_exprs(Relation relation,
23002299
lc = lnext(partkey->partexprs, lc);
23012300
}
23022301

2302+
/* Base relations have a single expression per key. */
23032303
partexprs[cnt] = list_make1(partexpr);
23042304
}
23052305

23062306
rel->partexprs = partexprs;
23072307

23082308
/*
2309-
* A base relation can not have nullable partition key expressions. We
2310-
* still allocate array of empty expressions lists to keep partition key
2311-
* expression handling code simple. See build_joinrel_partition_info() and
2312-
* match_expr_to_partition_keys().
2309+
* A base relation does not have nullable partition key expressions, since
2310+
* no outer join is involved. We still allocate an array of empty
2311+
* expression lists to keep partition key expression handling code simple.
2312+
* See build_joinrel_partition_info() and match_expr_to_partition_keys().
23132313
*/
23142314
rel->nullable_partexprs = (List **) palloc0(sizeof(List *) * partnatts);
23152315
}

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