Skip to content

Commit 0a3c84a

Browse files
committed
multilevel partitioning
1 parent 083e6a1 commit 0a3c84a

File tree

5 files changed

+117
-37
lines changed

5 files changed

+117
-37
lines changed

src/include/partition_filter.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ typedef struct
4040
Oid partid; /* partition's relid */
4141
ResultRelInfo *result_rel_info; /* cached ResultRelInfo */
4242
TupleConversionMap *tuple_map; /* tuple conversion map (parent => child) */
43+
bool has_subpartitions;
44+
ExprState *expr_state; /* if has_subpartitions true */
4345
} ResultRelInfoHolder;
4446

4547

@@ -133,11 +135,15 @@ Oid * find_partitions_for_value(Datum value, Oid value_type,
133135
const PartRelationInfo *prel,
134136
int *nparts);
135137

136-
ResultRelInfoHolder * select_partition_for_insert(Datum value, Oid value_type,
137-
const PartRelationInfo *prel,
138-
ResultPartsStorage *parts_storage,
139-
EState *estate);
140-
138+
// ResultRelInfoHolder * select_partition_for_insert(Datum value, Oid value_type,
139+
// const PartRelationInfo *prel,
140+
// ResultPartsStorage *parts_storage,
141+
// EState *estate);
142+
ResultRelInfoHolder *
143+
select_partition_for_insert(ExprContext *econtext, ExprState *expr_state,
144+
const PartRelationInfo *prel,
145+
ResultPartsStorage *parts_storage,
146+
EState *estate);
141147

142148
Plan * make_partition_filter(Plan *subplan,
143149
Oid parent_relid,

src/partition_filter.c

Lines changed: 75 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,11 @@ scan_result_parts_storage(Oid partid, ResultPartsStorage *parts_storage)
319319
/* Generate tuple transformation map and some other stuff */
320320
rri_holder->tuple_map = build_part_tuple_map(parent_rel, child_rel);
321321

322+
/* Are there subpartitions? */
323+
rri_holder->has_subpartitions =
324+
(get_pathman_relation_info(partid) != NULL);
325+
rri_holder->expr_state = NULL;
326+
322327
/* Call on_new_rri_holder_callback() if needed */
323328
if (parts_storage->on_new_rri_holder_callback)
324329
parts_storage->on_new_rri_holder_callback(parts_storage->estate,
@@ -412,7 +417,7 @@ find_partitions_for_value(Datum value, Oid value_type,
412417
* Smart wrapper for scan_result_parts_storage().
413418
*/
414419
ResultRelInfoHolder *
415-
select_partition_for_insert(Datum value, Oid value_type,
420+
select_partition_for_insert(ExprContext *econtext, ExprState *expr_state,
416421
const PartRelationInfo *prel,
417422
ResultPartsStorage *parts_storage,
418423
EState *estate)
@@ -422,9 +427,23 @@ select_partition_for_insert(Datum value, Oid value_type,
422427
Oid selected_partid = InvalidOid;
423428
Oid *parts;
424429
int nparts;
430+
TupleTableSlot *tmp_slot;
431+
// const PartRelationInfo *subprel;
432+
bool isnull;
433+
ExprDoneCond itemIsDone;
434+
Datum value;
435+
436+
/* Execute expression */
437+
value = ExecEvalExpr(expr_state, econtext, &isnull, &itemIsDone);
438+
439+
if (isnull)
440+
elog(ERROR, ERR_PART_ATTR_NULL);
441+
442+
if (itemIsDone != ExprSingleResult)
443+
elog(ERROR, ERR_PART_ATTR_MULTIPLE_RESULTS);
425444

426445
/* Search for matching partitions */
427-
parts = find_partitions_for_value(value, value_type, prel, &nparts);
446+
parts = find_partitions_for_value(value, prel->atttype, prel, &nparts);
428447

429448
if (nparts > 1)
430449
elog(ERROR, ERR_PART_ATTR_MULTIPLE);
@@ -438,9 +457,57 @@ select_partition_for_insert(Datum value, Oid value_type,
438457
}
439458
else selected_partid = parts[0];
440459

460+
// subprel = get_pathman_relation_info(state->partitioned_table))
441461
/* Replace parent table with a suitable partition */
442462
old_mcxt = MemoryContextSwitchTo(estate->es_query_cxt);
443463
rri_holder = scan_result_parts_storage(selected_partid, parts_storage);
464+
465+
/* If partition has subpartitions */
466+
if (rri_holder->has_subpartitions)
467+
{
468+
const PartRelationInfo *subprel;
469+
470+
/* Fetch PartRelationInfo for this partitioned relation */
471+
subprel = get_pathman_relation_info(selected_partid);
472+
Assert(subprel != NULL);
473+
474+
/* Build an expression state if not yet */
475+
if (!rri_holder->expr_state)
476+
{
477+
MemoryContext tmp_mcxt;
478+
Node *expr;
479+
Index varno = 1;
480+
ListCell *lc;
481+
482+
/* Change varno in Vars according to range table */
483+
expr = copyObject(subprel->expr);
484+
foreach(lc, estate->es_range_table)
485+
{
486+
RangeTblEntry *entry = lfirst(lc);
487+
if (entry->relid == selected_partid)
488+
{
489+
if (varno > 1)
490+
ChangeVarNodes(expr, 1, varno, 0);
491+
break;
492+
}
493+
varno += 1;
494+
}
495+
496+
/* Prepare state for expression execution */
497+
tmp_mcxt = MemoryContextSwitchTo(estate->es_query_cxt);
498+
rri_holder->expr_state = ExecInitExpr((Expr *) expr, NULL);
499+
MemoryContextSwitchTo(tmp_mcxt);
500+
}
501+
502+
Assert(rri_holder->expr_state != NULL);
503+
504+
/* Dive in */
505+
rri_holder = select_partition_for_insert(econtext, rri_holder->expr_state,
506+
subprel,
507+
parts_storage,
508+
estate);
509+
}
510+
444511
MemoryContextSwitchTo(old_mcxt);
445512

446513
/* Could not find suitable partition */
@@ -598,9 +665,9 @@ partition_filter_exec(CustomScanState *node)
598665
MemoryContext old_mcxt;
599666
const PartRelationInfo *prel;
600667
ResultRelInfoHolder *rri_holder;
601-
bool isnull;
602-
Datum value;
603-
ExprDoneCond itemIsDone;
668+
// bool isnull;
669+
// Datum value;
670+
// ExprDoneCond itemIsDone;
604671
TupleTableSlot *tmp_slot;
605672

606673
/* Fetch PartRelationInfo for this partitioned relation */
@@ -618,22 +685,15 @@ partition_filter_exec(CustomScanState *node)
618685
/* Switch to per-tuple context */
619686
old_mcxt = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
620687

621-
/* Execute expression */
622688
tmp_slot = econtext->ecxt_scantuple;
623689
econtext->ecxt_scantuple = slot;
624-
value = ExecEvalExpr(state->expr_state, econtext, &isnull, &itemIsDone);
625-
econtext->ecxt_scantuple = tmp_slot;
626-
627-
if (isnull)
628-
elog(ERROR, ERR_PART_ATTR_NULL);
629-
630-
if (itemIsDone != ExprSingleResult)
631-
elog(ERROR, ERR_PART_ATTR_MULTIPLE_RESULTS);
632690

633691
/* Search for a matching partition */
634-
rri_holder = select_partition_for_insert(value, prel->atttype, prel,
692+
rri_holder = select_partition_for_insert(econtext, state->expr_state, prel,
635693
&state->result_parts, estate);
636694

695+
econtext->ecxt_scantuple = tmp_slot;
696+
637697
/* Switch back and clean up per-tuple context */
638698
MemoryContextSwitchTo(old_mcxt);
639699
ResetExprContext(econtext);

src/pg_pathman.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,9 @@ append_child_relation(PlannerInfo *root, Relation parent_relation,
249249
child_rte = copyObject(parent_rte);
250250
child_rte->relid = child_oid;
251251
child_rte->relkind = child_relation->rd_rel->relkind;
252-
child_rte->inh = false; /* relation has no children */
252+
// child_rte->inh = false; /* relation has no children */
253+
child_rte->inh = (child_oid != parent_rte->relid) ?
254+
child_relation->rd_rel->relhassubclass : false;
253255
child_rte->requiredPerms = 0; /* perform all checks on parent */
254256

255257
/* Add 'child_rte' to rtable and 'root->simple_rte_array' */
@@ -391,6 +393,17 @@ append_child_relation(PlannerInfo *root, Relation parent_relation,
391393
parent_rowmark->isParent = true;
392394
}
393395

396+
/*
397+
* TODO: new!!!
398+
*/
399+
if (child_rte->inh)
400+
{
401+
pathman_rel_pathlist_hook(root,
402+
child_rel,
403+
childRTindex,
404+
child_rte);
405+
}
406+
394407
return childRTindex;
395408
}
396409

@@ -1659,7 +1672,8 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, Index rti,
16591672

16601673
set_foreign_pathlist(root, childrel, childRTE);
16611674
}
1662-
else
1675+
/* TODO: temporary!!! */
1676+
else if(!childRTE->inh || childrel->pathlist == NIL)
16631677
{
16641678
/* childrel->rows should be >= 1 */
16651679
set_plain_rel_size(root, childrel, childRTE);

src/pl_funcs.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -612,9 +612,9 @@ is_tuple_convertible(PG_FUNCTION_ARGS)
612612
void *map; /* we don't actually need it */
613613

614614
/* Try to build a conversion map */
615-
map = convert_tuples_by_name_map(RelationGetDescr(rel1),
616-
RelationGetDescr(rel2),
617-
ERR_PART_DESC_CONVERT);
615+
map = convert_tuples_by_name(RelationGetDescr(rel1),
616+
RelationGetDescr(rel2),
617+
ERR_PART_DESC_CONVERT);
618618
/* Now free map */
619619
pfree(map);
620620
}

src/utility_stmt_hooking.c

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -597,11 +597,11 @@ PathmanCopyFrom(CopyState cstate, Relation parent_rel,
597597
{
598598
TupleTableSlot *slot,
599599
*tmp_slot;
600-
ExprDoneCond itemIsDone;
601-
bool skip_tuple,
602-
isnull;
600+
// ExprDoneCond itemIsDone;
601+
bool skip_tuple;
602+
// isnull;
603603
Oid tuple_oid = InvalidOid;
604-
Datum value;
604+
// Datum value;
605605

606606
const PartRelationInfo *prel;
607607
ResultRelInfoHolder *rri_holder;
@@ -641,19 +641,19 @@ PathmanCopyFrom(CopyState cstate, Relation parent_rel,
641641
/* Execute expression */
642642
tmp_slot = econtext->ecxt_scantuple;
643643
econtext->ecxt_scantuple = slot;
644-
value = ExecEvalExpr(expr_state, econtext, &isnull, &itemIsDone);
645-
econtext->ecxt_scantuple = tmp_slot;
644+
// value = ExecEvalExpr(expr_state, econtext, &isnull, &itemIsDone);
646645

647-
if (isnull)
648-
elog(ERROR, ERR_PART_ATTR_NULL);
646+
// if (isnull)
647+
// elog(ERROR, ERR_PART_ATTR_NULL);
649648

650-
if (itemIsDone != ExprSingleResult)
651-
elog(ERROR, ERR_PART_ATTR_MULTIPLE_RESULTS);
649+
// if (itemIsDone != ExprSingleResult)
650+
// elog(ERROR, ERR_PART_ATTR_MULTIPLE_RESULTS);
652651

653652
/* Search for a matching partition */
654-
rri_holder = select_partition_for_insert(value,
655-
prel->atttype, prel,
653+
// rri_holder = select_partition_for_insert(value,
654+
rri_holder = select_partition_for_insert(econtext, expr_state, prel,
656655
&parts_storage, estate);
656+
econtext->ecxt_scantuple = tmp_slot;
657657
child_result_rel = rri_holder->result_rel_info;
658658
estate->es_result_relation_info = child_result_rel;
659659

0 commit comments

Comments
 (0)