Skip to content

Commit c0e3513

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

File tree

6 files changed

+83
-88
lines changed

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