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,
4645static 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- }
0 commit comments