Skip to content

Commit fa9d209

Browse files
committed
attempt to fix broken 'FOR UPDATE' feature (working prototype stage)
1 parent 487ec8e commit fa9d209

File tree

5 files changed

+348
-77
lines changed

5 files changed

+348
-77
lines changed

src/hooks.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,7 @@ pathman_planner_hook(Query *parse, int cursorOptions, ParamListInfo boundParams)
377377
{
378378
case CMD_SELECT:
379379
disable_inheritance(parse);
380+
rowmark_add_tableoids(parse); /* add attributes for rowmarks */
380381
break;
381382

382383
case CMD_UPDATE:
@@ -410,6 +411,16 @@ pathman_planner_hook(Query *parse, int cursorOptions, ParamListInfo boundParams)
410411
else
411412
result = standard_planner(parse, cursorOptions, boundParams);
412413

414+
if (pg_pathman_enable)
415+
{
416+
ListCell *lc;
417+
418+
/* Give rowmark-related attributes correct names */
419+
postprocess_lock_rows(result->rtable, result->planTree);
420+
foreach (lc, result->subplans)
421+
postprocess_lock_rows(result->rtable, (Plan *) lfirst(lc));
422+
}
423+
413424
return result;
414425
}
415426

src/partition_filter.c

Lines changed: 33 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ init_partition_filter_static_data(void)
4242

4343
Plan *
4444
make_partition_filter(Plan *subplan, Oid partitioned_table,
45-
OnConflictAction conflict_action)
45+
OnConflictAction conflict_action)
4646
{
4747
CustomScan *cscan = makeNode(CustomScan);
4848

@@ -327,78 +327,44 @@ pfilter_build_tlist(List *tlist)
327327
}
328328

329329
/*
330-
* Add PartitionFilter nodes to the plan tree
330+
* Add partition filters to ModifyTable node's children
331+
*
332+
* 'context' should point to the PlannedStmt->rtable
331333
*/
332-
void
333-
add_partition_filters(List *rtable, Plan *plan)
334+
static void
335+
partition_filter_visitor(Plan *plan, void *context)
334336
{
335-
ListCell *l;
337+
List *rtable = (List *) context;
338+
ModifyTable *modify_table = (ModifyTable *) plan;
339+
ListCell *lc1,
340+
*lc2;
341+
342+
Assert(rtable && IsA(rtable, List));
336343

337-
if (plan == NULL || !pg_pathman_enable_partition_filter)
344+
/* Skip if not ModifyTable with 'INSERT' command */
345+
if (!IsA(modify_table, ModifyTable) || modify_table->operation != CMD_INSERT)
338346
return;
339347

340-
/* Plan-type-specific fixes*/
341-
switch (nodeTag(plan))
348+
forboth (lc1, modify_table->plans, lc2, modify_table->resultRelations)
342349
{
343-
case T_SubqueryScan:
344-
add_partition_filters(rtable, ((SubqueryScan *) plan)->subplan);
345-
break;
346-
347-
case T_CustomScan:
348-
foreach(l, ((CustomScan *) plan)->custom_plans)
349-
add_partition_filters(rtable, (Plan *) lfirst(l));
350-
break;
351-
352-
/*
353-
* Add proxy PartitionFilter nodes
354-
* to subplans of ModifyTable node
355-
*/
356-
case T_ModifyTable:
357-
{
358-
ModifyTable *modify_table = ((ModifyTable *) plan);
359-
ListCell *lc1,
360-
*lc2;
361-
362-
if (modify_table->operation != CMD_INSERT)
363-
break;
364-
365-
forboth (lc1, modify_table->plans, lc2, modify_table->resultRelations)
366-
{
367-
Index rindex = lfirst_int(lc2);
368-
Oid relid = getrelid(rindex, rtable);
369-
PartRelationInfo *prel = get_pathman_relation_info(relid, NULL);
370-
371-
add_partition_filters(rtable, (Plan *) lfirst(lc1));
372-
373-
if (prel)
374-
lfirst(lc1) = make_partition_filter((Plan *) lfirst(lc1),
375-
relid,
376-
modify_table->onConflictAction);
377-
}
378-
}
379-
break;
380-
381-
/* Since they look alike */
382-
case T_MergeAppend:
383-
case T_Append:
384-
foreach(l, ((Append *) plan)->appendplans)
385-
add_partition_filters(rtable, (Plan *) lfirst(l));
386-
break;
387-
388-
case T_BitmapAnd:
389-
foreach(l, ((BitmapAnd *) plan)->bitmapplans)
390-
add_partition_filters(rtable, (Plan *) lfirst(l));
391-
break;
392-
393-
case T_BitmapOr:
394-
foreach(l, ((BitmapOr *) plan)->bitmapplans)
395-
add_partition_filters(rtable, (Plan *) lfirst(l));
396-
break;
397-
398-
default:
399-
break;
350+
Index rindex = lfirst_int(lc2);
351+
Oid relid = getrelid(rindex, rtable);
352+
PartRelationInfo *prel = get_pathman_relation_info(relid, NULL);
353+
354+
/* Check that table is partitioned */
355+
if (prel)
356+
lfirst(lc1) = make_partition_filter((Plan *) lfirst(lc1),
357+
relid,
358+
modify_table->onConflictAction);
400359
}
360+
}
401361

402-
add_partition_filters(rtable, plan->lefttree);
403-
add_partition_filters(rtable, plan->righttree);
362+
/*
363+
* Add PartitionFilter nodes to the plan tree
364+
*/
365+
void
366+
add_partition_filters(List *rtable, Plan *plan)
367+
{
368+
if (pg_pathman_enable_partition_filter)
369+
plan_tree_walker(plan, partition_filter_visitor, rtable);
404370
}

src/pg_pathman.c

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "optimizer/paths.h"
2222
#include "optimizer/pathnode.h"
2323
#include "optimizer/planner.h"
24+
#include "optimizer/prep.h"
2425
#include "optimizer/restrictinfo.h"
2526
#include "optimizer/cost.h"
2627
#include "parser/analyze.h"
@@ -33,6 +34,7 @@
3334
#include "utils/selfuncs.h"
3435
#include "access/heapam.h"
3536
#include "access/nbtree.h"
37+
#include "access/sysattr.h"
3638
#include "storage/ipc.h"
3739
#include "catalog/pg_type.h"
3840
#include "foreign/fdwapi.h"
@@ -207,7 +209,7 @@ disable_inheritance(Query *parse)
207209

208210
foreach(lc, parse->rtable)
209211
{
210-
rte = (RangeTblEntry*) lfirst(lc);
212+
rte = (RangeTblEntry *) lfirst(lc);
211213
switch(rte->rtekind)
212214
{
213215
case RTE_RELATION:
@@ -380,13 +382,17 @@ int
380382
append_child_relation(PlannerInfo *root, RelOptInfo *rel, Index rti,
381383
RangeTblEntry *rte, int index, Oid childOid, List *wrappers)
382384
{
383-
RangeTblEntry *childrte;
384-
RelOptInfo *childrel;
385-
Index childRTindex;
386-
AppendRelInfo *appinfo;
387-
Node *node;
388-
ListCell *lc, *lc2;
389-
Relation newrelation;
385+
RangeTblEntry *childrte;
386+
RelOptInfo *childrel;
387+
Index childRTindex;
388+
AppendRelInfo *appinfo;
389+
Node *node;
390+
ListCell *lc,
391+
*lc2;
392+
Relation newrelation;
393+
PlanRowMark *parent_rowmark;
394+
PlanRowMark *child_rowmark;
395+
AttrNumber i;
390396

391397
newrelation = heap_open(childOid, NoLock);
392398

@@ -418,8 +424,18 @@ append_child_relation(PlannerInfo *root, RelOptInfo *rel, Index rti,
418424
childrel->reltargetlist = lappend(childrel->reltargetlist, new_target);
419425
}
420426

421-
/* Copy attr_needed (used in build_joinrel_tlist() function) */
422-
childrel->attr_needed = rel->attr_needed;
427+
/* Copy attr_needed & attr_widths */
428+
childrel->attr_needed = (Relids *)
429+
palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(Relids));
430+
childrel->attr_widths = (int32 *)
431+
palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(int32));
432+
433+
for (i = 0; i < rel->max_attr - rel->min_attr + 1; i++)
434+
childrel->attr_needed[i] = bms_copy(rel->attr_needed[i]);
435+
436+
memcpy(childrel->attr_widths, rel->attr_widths,
437+
(rel->max_attr - rel->min_attr + 1) * sizeof(int32));
438+
423439

424440
/* Copy restrictions */
425441
childrel->baserestrictinfo = NIL;
@@ -502,6 +518,32 @@ append_child_relation(PlannerInfo *root, RelOptInfo *rel, Index rti,
502518

503519
heap_close(newrelation, NoLock);
504520

521+
522+
/* Create rowmarks required for child rels */
523+
parent_rowmark = get_plan_rowmark(root->rowMarks, rti);
524+
if (parent_rowmark)
525+
{
526+
child_rowmark = makeNode(PlanRowMark);
527+
528+
child_rowmark->rti = childRTindex;
529+
child_rowmark->prti = rti;
530+
child_rowmark->rowmarkId = parent_rowmark->rowmarkId;
531+
/* Reselect rowmark type, because relkind might not match parent */
532+
child_rowmark->markType = select_rowmark_type(childrte,
533+
parent_rowmark->strength);
534+
child_rowmark->allMarkTypes = (1 << child_rowmark->markType);
535+
child_rowmark->strength = parent_rowmark->strength;
536+
child_rowmark->waitPolicy = parent_rowmark->waitPolicy;
537+
child_rowmark->isParent = false;
538+
539+
/* Include child's rowmark type in parent's allMarkTypes */
540+
parent_rowmark->allMarkTypes |= child_rowmark->allMarkTypes;
541+
542+
root->rowMarks = lappend(root->rowMarks, child_rowmark);
543+
544+
parent_rowmark->isParent = true;
545+
}
546+
505547
return childRTindex;
506548
}
507549

0 commit comments

Comments
 (0)