@@ -946,13 +946,7 @@ gen_prune_step_op(GeneratePruningStepsContext *context,
946
946
* InvalidStrategy to signal get_matching_list_bounds to do the right
947
947
* thing.
948
948
*/
949
- if (op_is_ne )
950
- {
951
- Assert (opstrategy == BTEqualStrategyNumber );
952
- opstep -> opstrategy = InvalidStrategy ;
953
- }
954
- else
955
- opstep -> opstrategy = opstrategy ;
949
+ opstep -> opstrategy = op_is_ne ? InvalidStrategy : opstrategy ;
956
950
Assert (list_length (exprs ) == list_length (cmpfns ));
957
951
opstep -> exprs = exprs ;
958
952
opstep -> cmpfns = cmpfns ;
@@ -1426,10 +1420,12 @@ match_clause_to_partition_key(RelOptInfo *rel,
1426
1420
OpExpr * opclause = (OpExpr * ) clause ;
1427
1421
Expr * leftop ,
1428
1422
* rightop ;
1429
- Oid commutator = InvalidOid ,
1423
+ Oid op_lefttype ,
1424
+ op_righttype ,
1425
+ commutator = InvalidOid ,
1430
1426
negator = InvalidOid ;
1431
1427
Oid cmpfn ;
1432
- Oid exprtype ;
1428
+ int op_strategy ;
1433
1429
bool is_opne_listp = false;
1434
1430
PartClauseInfo * partclause ;
1435
1431
@@ -1483,58 +1479,80 @@ match_clause_to_partition_key(RelOptInfo *rel,
1483
1479
return PARTCLAUSE_UNSUPPORTED ;
1484
1480
1485
1481
/*
1486
- * Normally we only bother with operators that are listed as being
1487
- * part of the partitioning operator family. But we make an exception
1488
- * in one case -- operators named '<>' are not listed in any operator
1489
- * family whatsoever, in which case, we try to perform partition
1490
- * pruning with it only if list partitioning is in use.
1482
+ * Determine the input types of the operator we're considering.
1483
+ *
1484
+ * Normally we only care about operators that are listed as being part
1485
+ * of the partitioning operator family. But there is one exception:
1486
+ * the not-equals operators are not listed in any operator family
1487
+ * whatsoever, but their negators (equality) are. We can use one of
1488
+ * those if we find it, but only for list partitioning.
1491
1489
*/
1492
- if (! op_in_opfamily (opclause -> opno , partopfamily ))
1490
+ if (op_in_opfamily (opclause -> opno , partopfamily ))
1493
1491
{
1492
+ Oid oper ;
1493
+
1494
+ oper = OidIsValid (commutator ) ? commutator : opclause -> opno ;
1495
+ get_op_opfamily_properties (oper , partopfamily , false,
1496
+ & op_strategy , & op_lefttype ,
1497
+ & op_righttype );
1498
+ }
1499
+ else
1500
+ {
1501
+ /* Not good unless list partitioning */
1494
1502
if (part_scheme -> strategy != PARTITION_STRATEGY_LIST )
1495
1503
return PARTCLAUSE_UNSUPPORTED ;
1496
1504
1497
- /*
1498
- * To confirm if the operator is really '<>', check if its negator
1499
- * is a btree equality operator.
1500
- */
1505
+ /* See if the negator is equality */
1501
1506
negator = get_negator (opclause -> opno );
1502
1507
if (OidIsValid (negator ) && op_in_opfamily (negator , partopfamily ))
1503
1508
{
1504
- Oid lefttype ;
1505
- Oid righttype ;
1506
- int strategy ;
1507
-
1508
1509
get_op_opfamily_properties (negator , partopfamily , false,
1509
- & strategy , & lefttype , & righttype );
1510
-
1511
- if (strategy == BTEqualStrategyNumber )
1512
- is_opne_listp = true;
1510
+ & op_strategy , & op_lefttype ,
1511
+ & op_righttype );
1512
+ if (op_strategy == BTEqualStrategyNumber )
1513
+ is_opne_listp = true; /* bingo */
1513
1514
}
1514
1515
1515
1516
/* Operator isn't really what we were hoping it'd be. */
1516
1517
if (!is_opne_listp )
1517
1518
return PARTCLAUSE_UNSUPPORTED ;
1518
1519
}
1519
1520
1520
- /* Check if we're going to need a cross-type comparison function. */
1521
- exprtype = exprType ((Node * ) expr );
1522
- if (exprtype != part_scheme -> partopcintype [partkeyidx ])
1521
+ /*
1522
+ * Now find the procedure to use, based on the types. If the clause's
1523
+ * other argument is of the same type as the partitioning opclass's
1524
+ * declared input type, we can use the procedure cached in
1525
+ * PartitionKey. If not, search for a cross-type one in the same
1526
+ * opfamily; if one doesn't exist, give up on pruning for this clause.
1527
+ */
1528
+ if (op_righttype == part_scheme -> partopcintype [partkeyidx ])
1529
+ cmpfn = part_scheme -> partsupfunc [partkeyidx ].fn_oid ;
1530
+ else
1523
1531
{
1524
1532
switch (part_scheme -> strategy )
1525
1533
{
1534
+ /*
1535
+ * For range and list partitioning, we need the ordering
1536
+ * procedure with lefttype being the partition key's type, and
1537
+ * righttype the clause's operator's right type.
1538
+ */
1526
1539
case PARTITION_STRATEGY_LIST :
1527
1540
case PARTITION_STRATEGY_RANGE :
1528
1541
cmpfn =
1529
1542
get_opfamily_proc (part_scheme -> partopfamily [partkeyidx ],
1530
1543
part_scheme -> partopcintype [partkeyidx ],
1531
- exprtype , BTORDER_PROC );
1544
+ op_righttype , BTORDER_PROC );
1532
1545
break ;
1533
1546
1547
+ /*
1548
+ * For hash partitioning, we need the hashing procedure for
1549
+ * the clause's type.
1550
+ */
1534
1551
case PARTITION_STRATEGY_HASH :
1535
1552
cmpfn =
1536
1553
get_opfamily_proc (part_scheme -> partopfamily [partkeyidx ],
1537
- exprtype , exprtype , HASHEXTENDED_PROC );
1554
+ op_righttype , op_righttype ,
1555
+ HASHEXTENDED_PROC );
1538
1556
break ;
1539
1557
1540
1558
default :
@@ -1547,34 +1565,26 @@ match_clause_to_partition_key(RelOptInfo *rel,
1547
1565
if (!OidIsValid (cmpfn ))
1548
1566
return PARTCLAUSE_UNSUPPORTED ;
1549
1567
}
1550
- else
1551
- cmpfn = part_scheme -> partsupfunc [partkeyidx ].fn_oid ;
1552
1568
1569
+ /*
1570
+ * Build the clause, passing the negator or commutator if applicable.
1571
+ */
1553
1572
partclause = (PartClauseInfo * ) palloc (sizeof (PartClauseInfo ));
1554
1573
partclause -> keyno = partkeyidx ;
1555
-
1556
- /* For <> operator clauses, pass on the negator. */
1557
- partclause -> op_is_ne = false;
1558
- partclause -> op_strategy = InvalidStrategy ;
1559
-
1560
1574
if (is_opne_listp )
1561
1575
{
1562
1576
Assert (OidIsValid (negator ));
1563
1577
partclause -> opno = negator ;
1564
1578
partclause -> op_is_ne = true;
1565
-
1566
- /*
1567
- * We already know the strategy in this case, so may as well set
1568
- * it rather than having to look it up later.
1569
- */
1570
- partclause -> op_strategy = BTEqualStrategyNumber ;
1579
+ partclause -> op_strategy = InvalidStrategy ;
1571
1580
}
1572
- /* And if commuted before matching, pass on the commutator */
1573
- else if (OidIsValid (commutator ))
1574
- partclause -> opno = commutator ;
1575
1581
else
1576
- partclause -> opno = opclause -> opno ;
1577
-
1582
+ {
1583
+ partclause -> opno = OidIsValid (commutator ) ?
1584
+ commutator : opclause -> opno ;
1585
+ partclause -> op_is_ne = false;
1586
+ partclause -> op_strategy = op_strategy ;
1587
+ }
1578
1588
partclause -> expr = expr ;
1579
1589
partclause -> cmpfn = cmpfn ;
1580
1590
0 commit comments