@@ -625,39 +625,35 @@ wrapper_make_expression(WrapperNode *wrap, int index, bool *alwaysTrue)
625
625
WrapperNode *
626
626
walk_expr_tree (Expr * expr , WalkerContext * context )
627
627
{
628
- BoolExpr * boolexpr ;
629
- OpExpr * opexpr ;
630
- ScalarArrayOpExpr * arrexpr ;
631
- WrapperNode * result ;
628
+ WrapperNode * result ;
632
629
633
- switch (expr -> type )
630
+ switch (nodeTag ( expr ) )
634
631
{
635
632
/* Useful for INSERT optimization */
636
633
case T_Const :
637
634
return handle_const ((Const * ) expr , context );
638
635
639
636
/* AND, OR, NOT expressions */
640
637
case T_BoolExpr :
641
- boolexpr = (BoolExpr * ) expr ;
642
- return handle_boolexpr (boolexpr , context );
638
+ return handle_boolexpr ((BoolExpr * ) expr , context );
643
639
644
640
/* =, !=, <, > etc. */
645
641
case T_OpExpr :
646
- opexpr = (OpExpr * ) expr ;
647
- return handle_opexpr (opexpr , context );
642
+ return handle_opexpr ((OpExpr * ) expr , context );
648
643
649
644
/* IN expression */
650
645
case T_ScalarArrayOpExpr :
651
- arrexpr = (ScalarArrayOpExpr * ) expr ;
652
- return handle_arrexpr (arrexpr , context );
646
+ return handle_arrexpr ((ScalarArrayOpExpr * ) expr , context );
653
647
654
648
default :
655
649
result = (WrapperNode * ) palloc (sizeof (WrapperNode ));
656
650
result -> orig = (const Node * ) expr ;
657
651
result -> args = NIL ;
652
+ result -> paramsel = 1.0 ;
653
+
658
654
result -> rangeset = list_make1_irange (
659
655
make_irange (0 , PrelLastChild (context -> prel ), true));
660
- result -> paramsel = 1.0 ;
656
+
661
657
return result ;
662
658
}
663
659
}
@@ -1175,15 +1171,29 @@ handle_binary_opexpr(WalkerContext *context, WrapperNode *result,
1175
1171
((Var * ) varnode )-> vartype :
1176
1172
((RelabelType * ) varnode )-> resulttype ;
1177
1173
1174
+ /* Exit if Constant is NULL */
1175
+ if (c -> constisnull )
1176
+ {
1177
+ result -> rangeset = NIL ;
1178
+ result -> paramsel = 1.0 ;
1179
+ return ;
1180
+ }
1181
+
1178
1182
tce = lookup_type_cache (vartype , TYPECACHE_BTREE_OPFAMILY );
1179
1183
strategy = get_op_opfamily_strategy (expr -> opno , tce -> btree_opf );
1184
+
1185
+ /* There's no strategy for this operator, go to end */
1186
+ if (strategy == 0 )
1187
+ goto binary_opexpr_return ;
1188
+
1180
1189
fill_type_cmp_fmgr_info (& cmp_func ,
1181
1190
getBaseType (c -> consttype ),
1182
1191
getBaseType (prel -> atttype ));
1183
1192
1184
1193
switch (prel -> parttype )
1185
1194
{
1186
1195
case PT_HASH :
1196
+ /* If strategy is "=", select one partiton */
1187
1197
if (strategy == BTEqualStrategyNumber )
1188
1198
{
1189
1199
Datum value = OidFunctionCall1 (prel -> hash_proc , c -> constvalue );
@@ -1195,7 +1205,8 @@ handle_binary_opexpr(WalkerContext *context, WrapperNode *result,
1195
1205
1196
1206
return ; /* exit on equal */
1197
1207
}
1198
- break ; /* continue to function's end */
1208
+ /* Else go to end */
1209
+ else goto binary_opexpr_return ;
1199
1210
1200
1211
case PT_RANGE :
1201
1212
{
@@ -1205,14 +1216,17 @@ handle_binary_opexpr(WalkerContext *context, WrapperNode *result,
1205
1216
PrelChildrenCount (context -> prel ),
1206
1217
strategy ,
1207
1218
result );
1219
+
1208
1220
result -> paramsel = estimate_paramsel_using_prel (prel , strategy );
1209
- return ;
1221
+
1222
+ return ; /* done, now exit */
1210
1223
}
1211
1224
1212
1225
default :
1213
1226
elog (ERROR , "Unknown partitioning type %u" , prel -> parttype );
1214
1227
}
1215
1228
1229
+ binary_opexpr_return :
1216
1230
result -> rangeset = list_make1_irange (make_irange (0 , PrelLastChild (prel ), true));
1217
1231
result -> paramsel = 1.0 ;
1218
1232
}
@@ -1224,7 +1238,7 @@ static void
1224
1238
handle_binary_opexpr_param (const PartRelationInfo * prel ,
1225
1239
WrapperNode * result , const Node * varnode )
1226
1240
{
1227
- const OpExpr * expr = (const OpExpr * )result -> orig ;
1241
+ const OpExpr * expr = (const OpExpr * ) result -> orig ;
1228
1242
TypeCacheEntry * tce ;
1229
1243
int strategy ;
1230
1244
Oid vartype ;
@@ -1332,7 +1346,7 @@ static WrapperNode *
1332
1346
handle_const (const Const * c , WalkerContext * context )
1333
1347
{
1334
1348
const PartRelationInfo * prel = context -> prel ;
1335
- WrapperNode * result = (WrapperNode * ) palloc (sizeof (WrapperNode ));
1349
+ WrapperNode * result = (WrapperNode * ) palloc0 (sizeof (WrapperNode ));
1336
1350
int strategy = BTEqualStrategyNumber ;
1337
1351
1338
1352
result -> orig = (const Node * ) c ;
@@ -1341,11 +1355,9 @@ handle_const(const Const *c, WalkerContext *context)
1341
1355
* Had to add this check for queries like:
1342
1356
* select * from test.hash_rel where txt = NULL;
1343
1357
*/
1344
- if (!context -> for_insert )
1358
+ if (!context -> for_insert || c -> constisnull )
1345
1359
{
1346
- result -> rangeset = list_make1_irange (make_irange (0 ,
1347
- PrelLastChild (prel ),
1348
- true));
1360
+ result -> rangeset = NIL ;
1349
1361
result -> paramsel = 1.0 ;
1350
1362
1351
1363
return result ;
@@ -1366,12 +1378,14 @@ handle_const(const Const *c, WalkerContext *context)
1366
1378
1367
1379
case PT_RANGE :
1368
1380
{
1369
- TypeCacheEntry * tce ;
1381
+ FmgrInfo cmp_finfo ;
1370
1382
1371
- tce = lookup_type_cache (c -> consttype , TYPECACHE_CMP_PROC_FINFO );
1383
+ fill_type_cmp_fmgr_info (& cmp_finfo ,
1384
+ getBaseType (c -> consttype ),
1385
+ getBaseType (prel -> atttype ));
1372
1386
1373
1387
select_range_partitions (c -> constvalue ,
1374
- & tce -> cmp_proc_finfo ,
1388
+ & cmp_finfo ,
1375
1389
PrelGetRangesArray (context -> prel ),
1376
1390
PrelChildrenCount (context -> prel ),
1377
1391
strategy ,
@@ -1395,11 +1409,11 @@ handle_const(const Const *c, WalkerContext *context)
1395
1409
static WrapperNode *
1396
1410
handle_opexpr (const OpExpr * expr , WalkerContext * context )
1397
1411
{
1398
- WrapperNode * result = (WrapperNode * )palloc (sizeof (WrapperNode ));
1412
+ WrapperNode * result = (WrapperNode * ) palloc0 (sizeof (WrapperNode ));
1399
1413
Node * var , * param ;
1400
1414
const PartRelationInfo * prel = context -> prel ;
1401
1415
1402
- result -> orig = (const Node * )expr ;
1416
+ result -> orig = (const Node * ) expr ;
1403
1417
result -> args = NIL ;
1404
1418
1405
1419
if (list_length (expr -> args ) == 2 )
@@ -1481,7 +1495,7 @@ pull_var_param(const WalkerContext *ctx,
1481
1495
static WrapperNode *
1482
1496
handle_boolexpr (const BoolExpr * expr , WalkerContext * context )
1483
1497
{
1484
- WrapperNode * result = (WrapperNode * )palloc (sizeof (WrapperNode ));
1498
+ WrapperNode * result = (WrapperNode * ) palloc0 (sizeof (WrapperNode ));
1485
1499
ListCell * lc ;
1486
1500
const PartRelationInfo * prel = context -> prel ;
1487
1501
@@ -1500,17 +1514,22 @@ handle_boolexpr(const BoolExpr *expr, WalkerContext *context)
1500
1514
{
1501
1515
WrapperNode * arg ;
1502
1516
1503
- arg = walk_expr_tree ((Expr * )lfirst (lc ), context );
1517
+ arg = walk_expr_tree ((Expr * ) lfirst (lc ), context );
1504
1518
result -> args = lappend (result -> args , arg );
1519
+
1505
1520
switch (expr -> boolop )
1506
1521
{
1507
1522
case OR_EXPR :
1508
- result -> rangeset = irange_list_union (result -> rangeset , arg -> rangeset );
1523
+ result -> rangeset = irange_list_union (result -> rangeset ,
1524
+ arg -> rangeset );
1509
1525
break ;
1526
+
1510
1527
case AND_EXPR :
1511
- result -> rangeset = irange_list_intersect (result -> rangeset , arg -> rangeset );
1528
+ result -> rangeset = irange_list_intersect (result -> rangeset ,
1529
+ arg -> rangeset );
1512
1530
result -> paramsel *= arg -> paramsel ;
1513
1531
break ;
1532
+
1514
1533
default :
1515
1534
result -> rangeset = list_make1_irange (make_irange (0 ,
1516
1535
PrelLastChild (prel ),
@@ -1542,15 +1561,15 @@ handle_boolexpr(const BoolExpr *expr, WalkerContext *context)
1542
1561
static WrapperNode *
1543
1562
handle_arrexpr (const ScalarArrayOpExpr * expr , WalkerContext * context )
1544
1563
{
1545
- WrapperNode * result = (WrapperNode * )palloc (sizeof (WrapperNode ));
1564
+ WrapperNode * result = (WrapperNode * ) palloc (sizeof (WrapperNode ));
1546
1565
Node * varnode = (Node * ) linitial (expr -> args );
1547
1566
Var * var ;
1548
1567
Node * arraynode = (Node * ) lsecond (expr -> args );
1549
1568
const PartRelationInfo * prel = context -> prel ;
1550
1569
1551
- result -> orig = (const Node * )expr ;
1570
+ result -> orig = (const Node * ) expr ;
1552
1571
result -> args = NIL ;
1553
- result -> paramsel = 1 .0 ;
1572
+ result -> paramsel = 0 .0 ;
1554
1573
1555
1574
Assert (varnode != NULL );
1556
1575
@@ -1560,8 +1579,13 @@ handle_arrexpr(const ScalarArrayOpExpr *expr, WalkerContext *context)
1560
1579
var = !IsA (varnode , RelabelType ) ?
1561
1580
(Var * ) varnode :
1562
1581
(Var * ) ((RelabelType * ) varnode )-> arg ;
1563
- if (var -> varoattno != prel -> attnum )
1582
+
1583
+ /* Skip if base types or attribute numbers do not match */
1584
+ if (getBaseType (var -> vartype ) != getBaseType (prel -> atttype ) ||
1585
+ var -> varoattno != prel -> attnum )
1586
+ {
1564
1587
goto handle_arrexpr_return ;
1588
+ }
1565
1589
}
1566
1590
else
1567
1591
goto handle_arrexpr_return ;
@@ -1570,38 +1594,103 @@ handle_arrexpr(const ScalarArrayOpExpr *expr, WalkerContext *context)
1570
1594
!((Const * ) arraynode )-> constisnull )
1571
1595
{
1572
1596
ArrayType * arrayval ;
1573
- int16 elmlen ;
1574
- bool elmbyval ;
1575
- char elmalign ;
1597
+ int16 elemlen ;
1598
+ bool elembyval ;
1599
+ char elemalign ;
1576
1600
int num_elems ;
1577
1601
Datum * elem_values ;
1578
1602
bool * elem_nulls ;
1579
- int i ;
1603
+ int strategy = BTEqualStrategyNumber ;
1580
1604
1581
1605
/* Extract values from array */
1582
1606
arrayval = DatumGetArrayTypeP (((Const * ) arraynode )-> constvalue );
1583
1607
get_typlenbyvalalign (ARR_ELEMTYPE (arrayval ),
1584
- & elmlen , & elmbyval , & elmalign );
1608
+ & elemlen , & elembyval , & elemalign );
1585
1609
deconstruct_array (arrayval ,
1586
1610
ARR_ELEMTYPE (arrayval ),
1587
- elmlen , elmbyval , elmalign ,
1611
+ elemlen , elembyval , elemalign ,
1588
1612
& elem_values , & elem_nulls , & num_elems );
1589
1613
1590
1614
result -> rangeset = NIL ;
1591
1615
1592
- /* Construct OIDs list */
1593
- for (i = 0 ; i < num_elems ; i ++ )
1616
+ switch (prel -> parttype )
1594
1617
{
1595
- Datum value ;
1596
- uint32 idx ;
1597
-
1598
- /* Invoke base hash function for value type */
1599
- value = OidFunctionCall1 (prel -> hash_proc , elem_values [i ]);
1600
- idx = hash_to_part_index (DatumGetInt32 (value ), PrelChildrenCount (prel ));
1601
- result -> rangeset = irange_list_union (result -> rangeset ,
1602
- list_make1_irange (make_irange (idx ,
1603
- idx ,
1604
- true)));
1618
+ case PT_HASH :
1619
+ {
1620
+ List * ranges = NIL ;
1621
+ int i ;
1622
+
1623
+ /* Construct OIDs list */
1624
+ for (i = 0 ; i < num_elems ; i ++ )
1625
+ {
1626
+ Datum value ;
1627
+ uint32 idx ;
1628
+ List * irange ;
1629
+ double cur_paramsel ;
1630
+
1631
+ if (!elem_nulls [i ])
1632
+ {
1633
+ /* Invoke base hash function for value type */
1634
+ value = OidFunctionCall1 (prel -> hash_proc , elem_values [i ]);
1635
+ idx = hash_to_part_index (DatumGetUInt32 (value ),
1636
+ PrelChildrenCount (prel ));
1637
+
1638
+ irange = list_make1_irange (make_irange (idx , idx , true));
1639
+ }
1640
+ /* No children if Const is NULL */
1641
+ else irange = NIL ;
1642
+
1643
+ ranges = irange_list_union (ranges , irange );
1644
+
1645
+ cur_paramsel = estimate_paramsel_using_prel (prel , strategy );
1646
+ result -> paramsel = Max (result -> paramsel , cur_paramsel );
1647
+ }
1648
+
1649
+ result -> rangeset = ranges ;
1650
+ }
1651
+ break ;
1652
+
1653
+ case PT_RANGE :
1654
+ {
1655
+ WalkerContext * nested_wcxt ;
1656
+ List * ranges = NIL ;
1657
+ int i ;
1658
+
1659
+ nested_wcxt = palloc (sizeof (WalkerContext ));
1660
+ memcpy ((void * ) nested_wcxt ,
1661
+ (const void * ) context ,
1662
+ sizeof (WalkerContext ));
1663
+
1664
+ /* Overload variable to allow search by Const */
1665
+ nested_wcxt -> for_insert = true;
1666
+
1667
+ /* Construct OIDs list */
1668
+ for (i = 0 ; i < num_elems ; i ++ )
1669
+ {
1670
+ WrapperNode * wrap ;
1671
+ Const * c = makeConst (ARR_ELEMTYPE (arrayval ),
1672
+ -1 , InvalidOid ,
1673
+ datumGetSize (elem_values [i ],
1674
+ elembyval ,
1675
+ elemlen ),
1676
+ elem_values [i ],
1677
+ elem_nulls [i ],
1678
+ elembyval );
1679
+
1680
+ wrap = walk_expr_tree ((Expr * ) c , nested_wcxt );
1681
+ ranges = irange_list_union (ranges , wrap -> rangeset );
1682
+
1683
+ pfree (c );
1684
+
1685
+ result -> paramsel = Max (result -> paramsel , wrap -> paramsel );
1686
+ }
1687
+
1688
+ result -> rangeset = ranges ;
1689
+ }
1690
+ break ;
1691
+
1692
+ default :
1693
+ elog (ERROR , "Unknown partitioning type %u" , prel -> parttype );
1605
1694
}
1606
1695
1607
1696
/* Free resources */
@@ -1616,11 +1705,12 @@ handle_arrexpr(const ScalarArrayOpExpr *expr, WalkerContext *context)
1616
1705
1617
1706
handle_arrexpr_return :
1618
1707
result -> rangeset = list_make1_irange (make_irange (0 , PrelLastChild (prel ), true));
1708
+ result -> paramsel = 1.0 ;
1619
1709
return result ;
1620
1710
}
1621
1711
1622
1712
/*
1623
- * Theres are functions below copied from allpaths.c with (or without) some
1713
+ * These functions below are copied from allpaths.c with (or without) some
1624
1714
* modifications. Couldn't use original because of 'static' modifier.
1625
1715
*/
1626
1716
0 commit comments