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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy