Skip to content

Commit c0e3513

Browse files
committed
WIP more fixes in EPQ handling
1 parent d1255a5 commit c0e3513

6 files changed

+83
-88
lines changed

src/hooks.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -987,8 +987,9 @@ pathman_executor_hook(QueryDesc *queryDesc,
987987
{
988988
CustomScanState *pr_state = (CustomScanState *) mt_state->mt_plans[i];
989989

990-
/* Check if this is a PartitionRouter node */
991-
if (IsPartitionRouterState(pr_state))
990+
/* Check if this is a PartitionFilter + PartitionRouter combo */
991+
if (IsPartitionFilterState(pr_state) &&
992+
IsPartitionRouterState(linitial(pr_state->custom_ps)))
992993
{
993994
ResultRelInfo *rri = &mt_state->resultRelInfo[i];
994995

src/include/partition_filter.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,6 @@ typedef struct
108108
ResultPartsStorage result_parts; /* partition ResultRelInfo cache */
109109
CmdType command_type;
110110

111-
bool warning_triggered; /* warning message counter */
112-
113-
TupleTableSlot *subplan_slot; /* slot that was returned from subplan */
114111
TupleTableSlot *tup_convert_slot; /* slot for rebuilt tuples */
115112
} PartitionFilterState;
116113

@@ -170,6 +167,8 @@ PartRelationInfo * refresh_result_parts_storage(ResultPartsStorage *parts_storag
170167

171168
TupleConversionMap * build_part_tuple_map(Relation parent_rel, Relation child_rel);
172169

170+
List * pfilter_build_tlist(Plan *subplan);
171+
173172

174173
/* Find suitable partition using 'value' */
175174
Oid * find_partitions_for_value(Datum value, Oid value_type,
@@ -183,8 +182,8 @@ Plan * make_partition_filter(Plan *subplan,
183182
Oid parent_relid,
184183
Index parent_rti,
185184
OnConflictAction conflict_action,
186-
List *returning_list,
187-
CmdType command_type);
185+
CmdType command_type,
186+
List *returning_list);
188187

189188

190189
Node * partition_filter_create_scan_state(CustomScan *node);

src/include/partition_router.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,13 @@ typedef struct PartitionRouterState
3131
CustomScanState css;
3232

3333
Oid partitioned_table;
34-
JunkFilter *junkfilter;
34+
Plan *subplan; /* proxy variable to store subplan */
35+
JunkFilter *junkfilter; /* 'ctid' extraction facility */
36+
3537
EPQState epqstate;
3638
int epqparam;
37-
Plan *subplan; /* proxy variable to store subplan */
39+
40+
ResultRelInfo *current_rri;
3841
} PartitionRouterState;
3942

4043

src/partition_filter.c

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "partition_filter.h"
1717
#include "utils.h"
1818

19+
#include "access/htup_details.h"
1920
#include "catalog/pg_class.h"
2021
#include "catalog/pg_type.h"
2122
#include "foreign/fdwapi.h"
@@ -87,8 +88,6 @@ static Node *fix_returning_list_mutator(Node *node, void *state);
8788
static Index append_rte_to_estate(EState *estate, RangeTblEntry *rte);
8889
static int append_rri_to_estate(EState *estate, ResultRelInfo *rri);
8990

90-
static List *pfilter_build_tlist(Plan *subplan);
91-
9291
static void pf_memcxt_callback(void *arg);
9392
static estate_mod_data * fetch_estate_mod_data(EState *estate);
9493

@@ -633,8 +632,8 @@ make_partition_filter(Plan *subplan,
633632
Oid parent_relid,
634633
Index parent_rti,
635634
OnConflictAction conflict_action,
636-
List *returning_list,
637-
CmdType command_type)
635+
CmdType command_type,
636+
List *returning_list)
638637
{
639638
CustomScan *cscan = makeNode(CustomScan);
640639

@@ -723,9 +722,6 @@ partition_filter_begin(CustomScanState *node, EState *estate, int eflags)
723722
state->on_conflict_action != ONCONFLICT_NONE,
724723
RPS_RRI_CB(prepare_rri_for_insert, state),
725724
RPS_RRI_CB(NULL, NULL));
726-
727-
/* No warnings yet */
728-
state->warning_triggered = false;
729725
}
730726

731727
TupleTableSlot *
@@ -739,16 +735,12 @@ partition_filter_exec(CustomScanState *node)
739735
TupleTableSlot *slot;
740736

741737
slot = ExecProcNode(child_ps);
742-
state->subplan_slot = slot;
743-
744-
if (state->tup_convert_slot)
745-
ExecClearTuple(state->tup_convert_slot);
746738

747739
if (!TupIsNull(slot))
748740
{
749741
MemoryContext old_mcxt;
750742
ResultRelInfoHolder *rri_holder;
751-
ResultRelInfo *resultRelInfo;
743+
ResultRelInfo *rri;
752744

753745
/* Switch to per-tuple context */
754746
old_mcxt = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
@@ -760,30 +752,28 @@ partition_filter_exec(CustomScanState *node)
760752
MemoryContextSwitchTo(old_mcxt);
761753
ResetExprContext(econtext);
762754

763-
resultRelInfo = rri_holder->result_rel_info;
755+
rri = rri_holder->result_rel_info;
764756

765757
/* Magic: replace parent's ResultRelInfo with ours */
766-
estate->es_result_relation_info = resultRelInfo;
758+
estate->es_result_relation_info = rri;
767759

768760
/* If there's a transform map, rebuild the tuple */
769761
if (rri_holder->tuple_map)
770762
{
771763
HeapTuple htup_old,
772764
htup_new;
773-
Relation child_rel = resultRelInfo->ri_RelationDesc;
765+
Relation child_rel = rri->ri_RelationDesc;
774766

775767
htup_old = ExecMaterializeSlot(slot);
776768
htup_new = do_convert_tuple(htup_old, rri_holder->tuple_map);
769+
ExecClearTuple(slot);
777770

778771
/* Allocate new slot if needed */
779772
if (!state->tup_convert_slot)
780773
state->tup_convert_slot = MakeTupleTableSlotCompat();
781774

782775
ExecSetSlotDescriptor(state->tup_convert_slot, RelationGetDescr(child_rel));
783-
ExecStoreTuple(htup_new, state->tup_convert_slot, InvalidBuffer, true);
784-
785-
/* Now replace the original slot */
786-
slot = state->tup_convert_slot;
776+
slot = ExecStoreTuple(htup_new, state->tup_convert_slot, InvalidBuffer, true);
787777
}
788778

789779
return slot;
@@ -826,7 +816,7 @@ partition_filter_explain(CustomScanState *node, List *ancestors, ExplainState *e
826816
/*
827817
* Build partition filter's target list pointing to subplan tuple's elements.
828818
*/
829-
static List *
819+
List *
830820
pfilter_build_tlist(Plan *subplan)
831821
{
832822
List *result_tlist = NIL;

src/partition_router.c

Lines changed: 42 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,10 @@ bool pg_pathman_enable_partition_router = true;
2828
CustomScanMethods partition_router_plan_methods;
2929
CustomExecMethods partition_router_exec_methods;
3030

31-
static bool ExecDeleteInternal(ItemPointer tupleid,
32-
EPQState *epqstate,
33-
EState *estate);
31+
static TupleTableSlot *ExecDeleteInternal(TupleTableSlot *slot,
32+
ItemPointer tupleid,
33+
EPQState *epqstate,
34+
EState *estate);
3435

3536
void
3637
init_partition_router_static_data(void)
@@ -70,15 +71,6 @@ make_partition_router(Plan *subplan,
7071

7172
{
7273
CustomScan *cscan = makeNode(CustomScan);
73-
Plan *pfilter;
74-
75-
/* Create child PartitionFilter node */
76-
pfilter = make_partition_filter(subplan,
77-
parent_relid,
78-
parent_rti,
79-
ONCONFLICT_NONE,
80-
returning_list,
81-
CMD_UPDATE);
8274

8375
/* Copy costs etc */
8476
cscan->scan.plan.startup_cost = subplan->startup_cost;
@@ -88,14 +80,14 @@ make_partition_router(Plan *subplan,
8880

8981
/* Setup methods, child plan and param number for EPQ */
9082
cscan->methods = &partition_router_plan_methods;
91-
cscan->custom_plans = list_make1(pfilter);
83+
cscan->custom_plans = list_make1(subplan);
9284
cscan->custom_private = list_make1(makeInteger(epq_param));
9385

9486
/* No physical relation will be scanned */
9587
cscan->scan.scanrelid = 0;
9688

9789
/* Build an appropriate target list */
98-
cscan->scan.plan.targetlist = pfilter->targetlist;
90+
cscan->scan.plan.targetlist = pfilter_build_tlist(subplan);
9991

10092
/* FIXME: should we use the same tlist? */
10193
cscan->custom_scan_tlist = subplan->targetlist;
@@ -126,6 +118,9 @@ partition_router_begin(CustomScanState *node, EState *estate, int eflags)
126118
{
127119
PartitionRouterState *state = (PartitionRouterState *) node;
128120

121+
/* Remember current relation we're going to delete from */
122+
state->current_rri = estate->es_result_relation_info;
123+
129124
EvalPlanQualInit(&state->epqstate, estate,
130125
state->subplan, NIL,
131126
state->epqparam);
@@ -148,26 +143,18 @@ partition_router_exec(CustomScanState *node)
148143

149144
if (!TupIsNull(slot))
150145
{
151-
ResultRelInfo *new_rri, /* new tuple owner */
152-
*old_rri; /* previous tuple owner */
153-
PartitionFilterState *child_state;
154-
char relkind;
155-
ItemPointerData ctid;
146+
ResultRelInfo *current_rri = state->current_rri;
147+
char relkind;
148+
ItemPointerData ctid;
156149

157150
ItemPointerSetInvalid(&ctid);
158151

159-
child_state = (PartitionFilterState *) child_ps;
160-
Assert(child_state->command_type == CMD_UPDATE);
161-
162-
old_rri = child_state->result_parts.base_rri;
163-
new_rri = estate->es_result_relation_info;
164-
165152
/* Build new junkfilter if we have to */
166153
if (state->junkfilter == NULL)
167154
{
168155
state->junkfilter =
169156
ExecInitJunkFilter(state->subplan->targetlist,
170-
old_rri->ri_RelationDesc->rd_att->tdhasoid,
157+
current_rri->ri_RelationDesc->rd_att->tdhasoid,
171158
ExecInitExtraTupleSlotCompat(estate));
172159

173160
state->junkfilter->jf_junkAttNo =
@@ -177,13 +164,14 @@ partition_router_exec(CustomScanState *node)
177164
elog(ERROR, "could not find junk ctid column");
178165
}
179166

180-
relkind = old_rri->ri_RelationDesc->rd_rel->relkind;
167+
/* Additional checks based on 'relkind' */
168+
relkind = current_rri->ri_RelationDesc->rd_rel->relkind;
181169
if (relkind == RELKIND_RELATION)
182170
{
183171
Datum ctid_datum;
184172
bool ctid_isnull;
185173

186-
ctid_datum = ExecGetJunkAttribute(child_state->subplan_slot,
174+
ctid_datum = ExecGetJunkAttribute(slot,
187175
state->junkfilter->jf_junkAttNo,
188176
&ctid_isnull);
189177

@@ -199,30 +187,26 @@ partition_router_exec(CustomScanState *node)
199187
else
200188
elog(ERROR, UPDATE_NODE_NAME " cannot handle relkind %u", relkind);
201189

202-
/*
203-
* Clean from junk attributes before INSERT,
204-
* but only if slot wasn't transformed in PartitionFilter.
205-
*/
206-
if (TupIsNull(child_state->tup_convert_slot))
207-
slot = ExecFilterJunk(state->junkfilter, slot);
190+
elog(INFO, "deleting (%d, %d) from table: %s",
191+
ItemPointerGetBlockNumber(&ctid),
192+
ItemPointerGetOffsetNumber(&ctid),
193+
get_rel_name(RelationGetRelid(current_rri->ri_RelationDesc)));
208194

209-
/* Magic: replace current ResultRelInfo with parent's one (DELETE) */
210-
estate->es_result_relation_info = old_rri;
195+
/* Magic: replace parent's ResultRelInfo with ours */
196+
estate->es_result_relation_info = current_rri;
211197

212198
/* Delete tuple from old partition */
213199
Assert(ItemPointerIsValid(&ctid));
214-
EvalPlanQualSetSlot(&state->epqstate, child_state->subplan_slot);
215-
if (!ExecDeleteInternal(&ctid, &state->epqstate, estate))
200+
slot = ExecDeleteInternal(slot, &ctid, &state->epqstate, estate);
201+
202+
if (TupIsNull(slot))
216203
{
217204
elog(INFO, "oops, deleted, taking next tuple!");
218205
goto take_next_tuple;
219206
}
220207

221-
/* Magic: replace parent's ResultRelInfo with child's one (INSERT) */
222-
estate->es_result_relation_info = new_rri;
223-
224208
/* Tuple will be inserted by ModifyTable */
225-
return slot;
209+
return ExecFilterJunk(state->junkfilter, slot);
226210
}
227211

228212
return NULL;
@@ -231,7 +215,10 @@ partition_router_exec(CustomScanState *node)
231215
void
232216
partition_router_end(CustomScanState *node)
233217
{
218+
PartitionRouterState *state = (PartitionRouterState *) node;
219+
234220
Assert(list_length(node->custom_ps) == 1);
221+
EvalPlanQualEnd(&state->epqstate);
235222
ExecEndNode((PlanState *) linitial(node->custom_ps));
236223
}
237224

@@ -256,8 +243,9 @@ partition_router_explain(CustomScanState *node, List *ancestors, ExplainState *e
256243
* ----------------------------------------------------------------
257244
*/
258245

259-
static bool
260-
ExecDeleteInternal(ItemPointer tupleid,
246+
static TupleTableSlot *
247+
ExecDeleteInternal(TupleTableSlot *slot,
248+
ItemPointer tupleid,
261249
EPQState *epqstate,
262250
EState *estate)
263251
{
@@ -284,13 +272,15 @@ ExecDeleteInternal(ItemPointer tupleid,
284272
rri->ri_TrigDesc->trig_delete_before_row)
285273
{
286274
if (!ExecBRDeleteTriggers(estate, epqstate, rri, tupleid, NULL))
287-
return false;
275+
return NULL;
288276
}
289277

290278
if (tupleid != NULL)
291279
{
292-
/* delete the tuple */
280+
EvalPlanQualSetSlot(epqstate, slot);
281+
293282
ldelete:
283+
/* delete the tuple */
294284
result = heap_delete_compat(rel, tupleid,
295285
estate->es_output_cid,
296286
estate->es_crosscheck_snapshot,
@@ -305,8 +295,8 @@ ExecDeleteInternal(ItemPointer tupleid,
305295
errmsg("tuple to be updated was already modified by an operation triggered by the current command"),
306296
errhint("Consider using an AFTER trigger instead of a BEFORE trigger to propagate changes to other rows.")));
307297

308-
/* Else, already deleted by self; nothing to do */
309-
return false;
298+
/* Already deleted by self; nothing to do */
299+
return NULL;
310300

311301
case HeapTupleMayBeUpdated:
312302
break;
@@ -333,12 +323,13 @@ ExecDeleteInternal(ItemPointer tupleid,
333323
{
334324
Assert(tupleid != NULL);
335325
*tupleid = hufd.ctid;
326+
slot = epqslot;
336327
goto ldelete;
337328
}
338329
}
339330

340-
/* tuple already deleted; nothing to do */
341-
return false;
331+
/* Tuple already deleted; nothing to do */
332+
return NULL;
342333

343334
default:
344335
elog(ERROR, "unrecognized heap_delete status: %u", result);
@@ -350,5 +341,5 @@ ExecDeleteInternal(ItemPointer tupleid,
350341
/* AFTER ROW DELETE triggers */
351342
ExecARDeleteTriggersCompat(estate, rri, tupleid, NULL, NULL);
352343

353-
return true;
344+
return slot;
354345
}

0 commit comments

Comments
 (0)