Skip to content

Commit d630bf0

Browse files
committedOct 11, 2016
Merge branch 'rel_1_1_beta' of https://github.com/postgrespro/pg_pathman into rel_1_1_beta
2 parents 45552a7 + a333ac3 commit d630bf0

File tree

3 files changed

+172
-66
lines changed

3 files changed

+172
-66
lines changed
 

‎src/hooks.c

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ pathman_join_pathlist_hook(PlannerInfo *root,
4343
JoinPathExtraData *extra)
4444
{
4545
JoinCostWorkspace workspace;
46+
JoinType saved_jointype = jointype;
4647
RangeTblEntry *inner_rte = root->simple_rte_array[innerrel->relid];
4748
const PartRelationInfo *inner_prel;
4849
List *pathkeys = NIL,
@@ -118,6 +119,12 @@ pathman_join_pathlist_hook(PlannerInfo *root,
118119

119120
/* Select cheapest path for outerrel */
120121
outer = outerrel->cheapest_total_path;
122+
if (saved_jointype == JOIN_UNIQUE_OUTER)
123+
{
124+
outer = (Path *) create_unique_path(root, outerrel,
125+
outer, extra->sjinfo);
126+
Assert(outer);
127+
}
121128

122129
/* Make innerrel path depend on outerrel's column */
123130
inner_required = bms_union(PATH_REQ_OUTER((Path *) cur_inner_path),
@@ -133,6 +140,8 @@ pathman_join_pathlist_hook(PlannerInfo *root,
133140
continue;
134141

135142
inner = create_runtimeappend_path(root, cur_inner_path, ppi, paramsel);
143+
if (saved_jointype == JOIN_UNIQUE_INNER)
144+
return; /* No way to do this with a parameterized inner path */
136145

137146
initial_cost_nestloop(root, &workspace, jointype,
138147
outer, inner, /* built paths */
@@ -204,7 +213,7 @@ pathman_rel_pathlist_hook(PlannerInfo *root,
204213
Oid *children;
205214
List *ranges,
206215
*wrappers,
207-
*rel_partattr_clauses = NIL;
216+
*rel_part_clauses = NIL;
208217
PathKey *pathkeyAsc = NULL,
209218
*pathkeyDesc = NULL;
210219
double paramsel = 1.0;
@@ -310,8 +319,7 @@ pathman_rel_pathlist_hook(PlannerInfo *root,
310319
IndexRange irange = lfirst_irange(lc);
311320

312321
for (i = irange.ir_lower; i <= irange.ir_upper; i++)
313-
append_child_relation(root, rel, rti, rte, i, children[i],
314-
wrappers);
322+
append_child_relation(root, rel, rti, rte, i, children[i], wrappers);
315323
}
316324

317325
/* Clear old path list */
@@ -327,19 +335,26 @@ pathman_rel_pathlist_hook(PlannerInfo *root,
327335
return;
328336

329337
/* Check that rel's RestrictInfo contains partitioned column */
330-
rel_partattr_clauses = get_partitioned_attr_clauses(rel->baserestrictinfo,
331-
prel, rel->relid);
338+
rel_part_clauses = get_partitioned_attr_clauses(rel->baserestrictinfo,
339+
prel, rel->relid);
332340

333341
/* Runtime[Merge]Append is pointless if there are no params in clauses */
334-
if (!clause_contains_params((Node *) rel_partattr_clauses))
342+
if (!clause_contains_params((Node *) rel_part_clauses))
335343
return;
336344

337345
foreach (lc, rel->pathlist)
338346
{
339347
AppendPath *cur_path = (AppendPath *) lfirst(lc);
340348
Relids inner_required = PATH_REQ_OUTER((Path *) cur_path);
341-
ParamPathInfo *ppi = get_baserel_parampathinfo(root, rel, inner_required);
342349
Path *inner_path = NULL;
350+
ParamPathInfo *ppi;
351+
List *ppi_part_clauses = NIL;
352+
353+
/* Fetch ParamPathInfo & try to extract part-related clauses */
354+
ppi = get_baserel_parampathinfo(root, rel, inner_required);
355+
if (ppi && ppi->ppi_clauses)
356+
ppi_part_clauses = get_partitioned_attr_clauses(ppi->ppi_clauses,
357+
prel, rel->relid);
343358

344359
/* Skip if rel contains some join-related stuff or path type mismatched */
345360
if (!(IsA(cur_path, AppendPath) || IsA(cur_path, MergeAppendPath)) ||
@@ -352,9 +367,7 @@ pathman_rel_pathlist_hook(PlannerInfo *root,
352367
* Skip if neither rel->baserestrictinfo nor
353368
* ppi->ppi_clauses reference partition attribute
354369
*/
355-
if (!(rel_partattr_clauses ||
356-
(ppi && get_partitioned_attr_clauses(ppi->ppi_clauses,
357-
prel, rel->relid))))
370+
if (!(rel_part_clauses || ppi_part_clauses))
358371
continue;
359372

360373
if (IsA(cur_path, AppendPath) && pg_pathman_enable_runtimeappend)

‎src/init.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -841,6 +841,7 @@ validate_range_constraint(const Expr *expr,
841841
const TypeCacheEntry *tce;
842842
const BoolExpr *boolexpr = (const BoolExpr *) expr;
843843
const OpExpr *opexpr;
844+
int strategy;
844845

845846
if (!expr)
846847
return false;
@@ -853,8 +854,9 @@ validate_range_constraint(const Expr *expr,
853854

854855
/* check that left operand is >= operator */
855856
opexpr = (OpExpr *) linitial(boolexpr->args);
856-
if (BTGreaterEqualStrategyNumber == get_op_opfamily_strategy(opexpr->opno,
857-
tce->btree_opf))
857+
strategy = get_op_opfamily_strategy(opexpr->opno, tce->btree_opf);
858+
859+
if (strategy == BTGreaterEqualStrategyNumber)
858860
{
859861
if (!read_opexpr_const(opexpr, prel, min))
860862
return false;
@@ -864,8 +866,9 @@ validate_range_constraint(const Expr *expr,
864866

865867
/* check that right operand is < operator */
866868
opexpr = (OpExpr *) lsecond(boolexpr->args);
867-
if (BTLessStrategyNumber == get_op_opfamily_strategy(opexpr->opno,
868-
tce->btree_opf))
869+
strategy = get_op_opfamily_strategy(opexpr->opno, tce->btree_opf);
870+
871+
if (strategy == BTLessStrategyNumber)
869872
{
870873
if (!read_opexpr_const(opexpr, prel, max))
871874
return false;

‎src/pg_pathman.c

Lines changed: 142 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -625,39 +625,35 @@ wrapper_make_expression(WrapperNode *wrap, int index, bool *alwaysTrue)
625625
WrapperNode *
626626
walk_expr_tree(Expr *expr, WalkerContext *context)
627627
{
628-
BoolExpr *boolexpr;
629-
OpExpr *opexpr;
630-
ScalarArrayOpExpr *arrexpr;
631-
WrapperNode *result;
628+
WrapperNode *result;
632629

633-
switch (expr->type)
630+
switch (nodeTag(expr))
634631
{
635632
/* Useful for INSERT optimization */
636633
case T_Const:
637634
return handle_const((Const *) expr, context);
638635

639636
/* AND, OR, NOT expressions */
640637
case T_BoolExpr:
641-
boolexpr = (BoolExpr *) expr;
642-
return handle_boolexpr(boolexpr, context);
638+
return handle_boolexpr((BoolExpr *) expr, context);
643639

644640
/* =, !=, <, > etc. */
645641
case T_OpExpr:
646-
opexpr = (OpExpr *) expr;
647-
return handle_opexpr(opexpr, context);
642+
return handle_opexpr((OpExpr *) expr, context);
648643

649644
/* IN expression */
650645
case T_ScalarArrayOpExpr:
651-
arrexpr = (ScalarArrayOpExpr *) expr;
652-
return handle_arrexpr(arrexpr, context);
646+
return handle_arrexpr((ScalarArrayOpExpr *) expr, context);
653647

654648
default:
655649
result = (WrapperNode *) palloc(sizeof(WrapperNode));
656650
result->orig = (const Node *) expr;
657651
result->args = NIL;
652+
result->paramsel = 1.0;
653+
658654
result->rangeset = list_make1_irange(
659655
make_irange(0, PrelLastChild(context->prel), true));
660-
result->paramsel = 1.0;
656+
661657
return result;
662658
}
663659
}
@@ -1175,15 +1171,29 @@ handle_binary_opexpr(WalkerContext *context, WrapperNode *result,
11751171
((Var *) varnode)->vartype :
11761172
((RelabelType *) varnode)->resulttype;
11771173

1174+
/* Exit if Constant is NULL */
1175+
if (c->constisnull)
1176+
{
1177+
result->rangeset = NIL;
1178+
result->paramsel = 1.0;
1179+
return;
1180+
}
1181+
11781182
tce = lookup_type_cache(vartype, TYPECACHE_BTREE_OPFAMILY);
11791183
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+
11801189
fill_type_cmp_fmgr_info(&cmp_func,
11811190
getBaseType(c->consttype),
11821191
getBaseType(prel->atttype));
11831192

11841193
switch (prel->parttype)
11851194
{
11861195
case PT_HASH:
1196+
/* If strategy is "=", select one partiton */
11871197
if (strategy == BTEqualStrategyNumber)
11881198
{
11891199
Datum value = OidFunctionCall1(prel->hash_proc, c->constvalue);
@@ -1195,7 +1205,8 @@ handle_binary_opexpr(WalkerContext *context, WrapperNode *result,
11951205

11961206
return; /* exit on equal */
11971207
}
1198-
break; /* continue to function's end */
1208+
/* Else go to end */
1209+
else goto binary_opexpr_return;
11991210

12001211
case PT_RANGE:
12011212
{
@@ -1205,14 +1216,17 @@ handle_binary_opexpr(WalkerContext *context, WrapperNode *result,
12051216
PrelChildrenCount(context->prel),
12061217
strategy,
12071218
result);
1219+
12081220
result->paramsel = estimate_paramsel_using_prel(prel, strategy);
1209-
return;
1221+
1222+
return; /* done, now exit */
12101223
}
12111224

12121225
default:
12131226
elog(ERROR, "Unknown partitioning type %u", prel->parttype);
12141227
}
12151228

1229+
binary_opexpr_return:
12161230
result->rangeset = list_make1_irange(make_irange(0, PrelLastChild(prel), true));
12171231
result->paramsel = 1.0;
12181232
}
@@ -1224,7 +1238,7 @@ static void
12241238
handle_binary_opexpr_param(const PartRelationInfo *prel,
12251239
WrapperNode *result, const Node *varnode)
12261240
{
1227-
const OpExpr *expr = (const OpExpr *)result->orig;
1241+
const OpExpr *expr = (const OpExpr *) result->orig;
12281242
TypeCacheEntry *tce;
12291243
int strategy;
12301244
Oid vartype;
@@ -1332,7 +1346,7 @@ static WrapperNode *
13321346
handle_const(const Const *c, WalkerContext *context)
13331347
{
13341348
const PartRelationInfo *prel = context->prel;
1335-
WrapperNode *result = (WrapperNode *) palloc(sizeof(WrapperNode));
1349+
WrapperNode *result = (WrapperNode *) palloc0(sizeof(WrapperNode));
13361350
int strategy = BTEqualStrategyNumber;
13371351

13381352
result->orig = (const Node *) c;
@@ -1341,11 +1355,9 @@ handle_const(const Const *c, WalkerContext *context)
13411355
* Had to add this check for queries like:
13421356
* select * from test.hash_rel where txt = NULL;
13431357
*/
1344-
if (!context->for_insert)
1358+
if (!context->for_insert || c->constisnull)
13451359
{
1346-
result->rangeset = list_make1_irange(make_irange(0,
1347-
PrelLastChild(prel),
1348-
true));
1360+
result->rangeset = NIL;
13491361
result->paramsel = 1.0;
13501362

13511363
return result;
@@ -1366,12 +1378,14 @@ handle_const(const Const *c, WalkerContext *context)
13661378

13671379
case PT_RANGE:
13681380
{
1369-
TypeCacheEntry *tce;
1381+
FmgrInfo cmp_finfo;
13701382

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));
13721386

13731387
select_range_partitions(c->constvalue,
1374-
&tce->cmp_proc_finfo,
1388+
&cmp_finfo,
13751389
PrelGetRangesArray(context->prel),
13761390
PrelChildrenCount(context->prel),
13771391
strategy,
@@ -1395,11 +1409,11 @@ handle_const(const Const *c, WalkerContext *context)
13951409
static WrapperNode *
13961410
handle_opexpr(const OpExpr *expr, WalkerContext *context)
13971411
{
1398-
WrapperNode *result = (WrapperNode *)palloc(sizeof(WrapperNode));
1412+
WrapperNode *result = (WrapperNode *) palloc0(sizeof(WrapperNode));
13991413
Node *var, *param;
14001414
const PartRelationInfo *prel = context->prel;
14011415

1402-
result->orig = (const Node *)expr;
1416+
result->orig = (const Node *) expr;
14031417
result->args = NIL;
14041418

14051419
if (list_length(expr->args) == 2)
@@ -1481,7 +1495,7 @@ pull_var_param(const WalkerContext *ctx,
14811495
static WrapperNode *
14821496
handle_boolexpr(const BoolExpr *expr, WalkerContext *context)
14831497
{
1484-
WrapperNode *result = (WrapperNode *)palloc(sizeof(WrapperNode));
1498+
WrapperNode *result = (WrapperNode *) palloc0(sizeof(WrapperNode));
14851499
ListCell *lc;
14861500
const PartRelationInfo *prel = context->prel;
14871501

@@ -1500,17 +1514,22 @@ handle_boolexpr(const BoolExpr *expr, WalkerContext *context)
15001514
{
15011515
WrapperNode *arg;
15021516

1503-
arg = walk_expr_tree((Expr *)lfirst(lc), context);
1517+
arg = walk_expr_tree((Expr *) lfirst(lc), context);
15041518
result->args = lappend(result->args, arg);
1519+
15051520
switch (expr->boolop)
15061521
{
15071522
case OR_EXPR:
1508-
result->rangeset = irange_list_union(result->rangeset, arg->rangeset);
1523+
result->rangeset = irange_list_union(result->rangeset,
1524+
arg->rangeset);
15091525
break;
1526+
15101527
case AND_EXPR:
1511-
result->rangeset = irange_list_intersect(result->rangeset, arg->rangeset);
1528+
result->rangeset = irange_list_intersect(result->rangeset,
1529+
arg->rangeset);
15121530
result->paramsel *= arg->paramsel;
15131531
break;
1532+
15141533
default:
15151534
result->rangeset = list_make1_irange(make_irange(0,
15161535
PrelLastChild(prel),
@@ -1542,15 +1561,15 @@ handle_boolexpr(const BoolExpr *expr, WalkerContext *context)
15421561
static WrapperNode *
15431562
handle_arrexpr(const ScalarArrayOpExpr *expr, WalkerContext *context)
15441563
{
1545-
WrapperNode *result = (WrapperNode *)palloc(sizeof(WrapperNode));
1564+
WrapperNode *result = (WrapperNode *) palloc(sizeof(WrapperNode));
15461565
Node *varnode = (Node *) linitial(expr->args);
15471566
Var *var;
15481567
Node *arraynode = (Node *) lsecond(expr->args);
15491568
const PartRelationInfo *prel = context->prel;
15501569

1551-
result->orig = (const Node *)expr;
1570+
result->orig = (const Node *) expr;
15521571
result->args = NIL;
1553-
result->paramsel = 1.0;
1572+
result->paramsel = 0.0;
15541573

15551574
Assert(varnode != NULL);
15561575

@@ -1560,8 +1579,13 @@ handle_arrexpr(const ScalarArrayOpExpr *expr, WalkerContext *context)
15601579
var = !IsA(varnode, RelabelType) ?
15611580
(Var *) varnode :
15621581
(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+
{
15641587
goto handle_arrexpr_return;
1588+
}
15651589
}
15661590
else
15671591
goto handle_arrexpr_return;
@@ -1570,38 +1594,103 @@ handle_arrexpr(const ScalarArrayOpExpr *expr, WalkerContext *context)
15701594
!((Const *) arraynode)->constisnull)
15711595
{
15721596
ArrayType *arrayval;
1573-
int16 elmlen;
1574-
bool elmbyval;
1575-
char elmalign;
1597+
int16 elemlen;
1598+
bool elembyval;
1599+
char elemalign;
15761600
int num_elems;
15771601
Datum *elem_values;
15781602
bool *elem_nulls;
1579-
int i;
1603+
int strategy = BTEqualStrategyNumber;
15801604

15811605
/* Extract values from array */
15821606
arrayval = DatumGetArrayTypeP(((Const *) arraynode)->constvalue);
15831607
get_typlenbyvalalign(ARR_ELEMTYPE(arrayval),
1584-
&elmlen, &elmbyval, &elmalign);
1608+
&elemlen, &elembyval, &elemalign);
15851609
deconstruct_array(arrayval,
15861610
ARR_ELEMTYPE(arrayval),
1587-
elmlen, elmbyval, elmalign,
1611+
elemlen, elembyval, elemalign,
15881612
&elem_values, &elem_nulls, &num_elems);
15891613

15901614
result->rangeset = NIL;
15911615

1592-
/* Construct OIDs list */
1593-
for (i = 0; i < num_elems; i++)
1616+
switch (prel->parttype)
15941617
{
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);
16051694
}
16061695

16071696
/* Free resources */
@@ -1616,11 +1705,12 @@ handle_arrexpr(const ScalarArrayOpExpr *expr, WalkerContext *context)
16161705

16171706
handle_arrexpr_return:
16181707
result->rangeset = list_make1_irange(make_irange(0, PrelLastChild(prel), true));
1708+
result->paramsel = 1.0;
16191709
return result;
16201710
}
16211711

16221712
/*
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
16241714
* modifications. Couldn't use original because of 'static' modifier.
16251715
*/
16261716

0 commit comments

Comments
 (0)
Please sign in to comment.