Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc4b841b

Browse files
committed
Fix interaction of triggers, partitioning, and EXPLAIN ANALYZE.
Add a new EState member es_leaf_result_relations, so that the triggercode knows about ResultRelInfos created by tuple routing. Also makesure ExplainPrintTriggers knows about partition-relatedResultRelInfos.Etsuro Fujita, reviewed by Amit LangoteDiscussion:http://postgr.es/m/57163e18-8e56-da83-337a-22f2c0008051@lab.ntt.co.jp
1 parenta20aac8 commitc4b841b

File tree

7 files changed

+115
-65
lines changed

7 files changed

+115
-65
lines changed

‎src/backend/commands/copy.c

Lines changed: 57 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1415,59 +1415,6 @@ BeginCopy(ParseState *pstate,
14151415
(errcode(ERRCODE_UNDEFINED_COLUMN),
14161416
errmsg("table \"%s\" does not have OIDs",
14171417
RelationGetRelationName(cstate->rel))));
1418-
1419-
/*
1420-
* If there are any triggers with transition tables on the named
1421-
* relation, we need to be prepared to capture transition tuples.
1422-
*/
1423-
cstate->transition_capture=MakeTransitionCaptureState(rel->trigdesc);
1424-
1425-
/* Initialize state for CopyFrom tuple routing. */
1426-
if (is_from&&rel->rd_rel->relkind==RELKIND_PARTITIONED_TABLE)
1427-
{
1428-
PartitionDispatch*partition_dispatch_info;
1429-
ResultRelInfo*partitions;
1430-
TupleConversionMap**partition_tupconv_maps;
1431-
TupleTableSlot*partition_tuple_slot;
1432-
intnum_parted,
1433-
num_partitions;
1434-
1435-
ExecSetupPartitionTupleRouting(rel,
1436-
1,
1437-
&partition_dispatch_info,
1438-
&partitions,
1439-
&partition_tupconv_maps,
1440-
&partition_tuple_slot,
1441-
&num_parted,&num_partitions);
1442-
cstate->partition_dispatch_info=partition_dispatch_info;
1443-
cstate->num_dispatch=num_parted;
1444-
cstate->partitions=partitions;
1445-
cstate->num_partitions=num_partitions;
1446-
cstate->partition_tupconv_maps=partition_tupconv_maps;
1447-
cstate->partition_tuple_slot=partition_tuple_slot;
1448-
1449-
/*
1450-
* If we are capturing transition tuples, they may need to be
1451-
* converted from partition format back to partitioned table
1452-
* format (this is only ever necessary if a BEFORE trigger
1453-
* modifies the tuple).
1454-
*/
1455-
if (cstate->transition_capture!=NULL)
1456-
{
1457-
inti;
1458-
1459-
cstate->transition_tupconv_maps= (TupleConversionMap**)
1460-
palloc0(sizeof(TupleConversionMap*)*
1461-
cstate->num_partitions);
1462-
for (i=0;i<cstate->num_partitions;++i)
1463-
{
1464-
cstate->transition_tupconv_maps[i]=
1465-
convert_tuples_by_name(RelationGetDescr(cstate->partitions[i].ri_RelationDesc),
1466-
RelationGetDescr(rel),
1467-
gettext_noop("could not convert row type"));
1468-
}
1469-
}
1470-
}
14711418
}
14721419
else
14731420
{
@@ -2482,6 +2429,63 @@ CopyFrom(CopyState cstate)
24822429
/* Triggers might need a slot as well */
24832430
estate->es_trig_tuple_slot=ExecInitExtraTupleSlot(estate);
24842431

2432+
/*
2433+
* If there are any triggers with transition tables on the named relation,
2434+
* we need to be prepared to capture transition tuples.
2435+
*/
2436+
cstate->transition_capture=
2437+
MakeTransitionCaptureState(cstate->rel->trigdesc);
2438+
2439+
/*
2440+
* If the named relation is a partitioned table, initialize state for
2441+
* CopyFrom tuple routing.
2442+
*/
2443+
if (cstate->rel->rd_rel->relkind==RELKIND_PARTITIONED_TABLE)
2444+
{
2445+
PartitionDispatch*partition_dispatch_info;
2446+
ResultRelInfo*partitions;
2447+
TupleConversionMap**partition_tupconv_maps;
2448+
TupleTableSlot*partition_tuple_slot;
2449+
intnum_parted,
2450+
num_partitions;
2451+
2452+
ExecSetupPartitionTupleRouting(cstate->rel,
2453+
1,
2454+
estate,
2455+
&partition_dispatch_info,
2456+
&partitions,
2457+
&partition_tupconv_maps,
2458+
&partition_tuple_slot,
2459+
&num_parted,&num_partitions);
2460+
cstate->partition_dispatch_info=partition_dispatch_info;
2461+
cstate->num_dispatch=num_parted;
2462+
cstate->partitions=partitions;
2463+
cstate->num_partitions=num_partitions;
2464+
cstate->partition_tupconv_maps=partition_tupconv_maps;
2465+
cstate->partition_tuple_slot=partition_tuple_slot;
2466+
2467+
/*
2468+
* If we are capturing transition tuples, they may need to be
2469+
* converted from partition format back to partitioned table format
2470+
* (this is only ever necessary if a BEFORE trigger modifies the
2471+
* tuple).
2472+
*/
2473+
if (cstate->transition_capture!=NULL)
2474+
{
2475+
inti;
2476+
2477+
cstate->transition_tupconv_maps= (TupleConversionMap**)
2478+
palloc0(sizeof(TupleConversionMap*)*cstate->num_partitions);
2479+
for (i=0;i<cstate->num_partitions;++i)
2480+
{
2481+
cstate->transition_tupconv_maps[i]=
2482+
convert_tuples_by_name(RelationGetDescr(cstate->partitions[i].ri_RelationDesc),
2483+
RelationGetDescr(cstate->rel),
2484+
gettext_noop("could not convert row type"));
2485+
}
2486+
}
2487+
}
2488+
24852489
/*
24862490
* It's more efficient to prepare a bunch of tuples for insertion, and
24872491
* insert them in one heap_multi_insert() call, than call heap_insert()

‎src/backend/commands/explain.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -656,17 +656,30 @@ ExplainPrintTriggers(ExplainState *es, QueryDesc *queryDesc)
656656
ResultRelInfo*rInfo;
657657
boolshow_relname;
658658
intnumrels=queryDesc->estate->es_num_result_relations;
659+
intnumrootrels=queryDesc->estate->es_num_root_result_relations;
660+
List*leafrels=queryDesc->estate->es_leaf_result_relations;
659661
List*targrels=queryDesc->estate->es_trig_target_relations;
660662
intnr;
661663
ListCell*l;
662664

663665
ExplainOpenGroup("Triggers","Triggers", false,es);
664666

665-
show_relname= (numrels>1||targrels!=NIL);
667+
show_relname= (numrels>1||numrootrels>0||
668+
leafrels!=NIL||targrels!=NIL);
666669
rInfo=queryDesc->estate->es_result_relations;
667670
for (nr=0;nr<numrels;rInfo++,nr++)
668671
report_triggers(rInfo,show_relname,es);
669672

673+
rInfo=queryDesc->estate->es_root_result_relations;
674+
for (nr=0;nr<numrootrels;rInfo++,nr++)
675+
report_triggers(rInfo,show_relname,es);
676+
677+
foreach(l,leafrels)
678+
{
679+
rInfo= (ResultRelInfo*)lfirst(l);
680+
report_triggers(rInfo,show_relname,es);
681+
}
682+
670683
foreach(l,targrels)
671684
{
672685
rInfo= (ResultRelInfo*)lfirst(l);

‎src/backend/executor/execMain.c

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1365,16 +1365,18 @@ InitResultRelInfo(ResultRelInfo *resultRelInfo,
13651365
*
13661366
* Get a ResultRelInfo for a trigger target relation. Most of the time,
13671367
* triggers are fired on one of the result relations of the query, and so
1368-
* we can just return a member of the es_result_relations array. (Note: in
1369-
* self-join situations there might be multiple members with the same OID;
1370-
* if so it doesn't matter which one we pick.) However, it is sometimes
1371-
* necessary to fire triggers on other relations; this happens mainly when an
1372-
* RI update trigger queues additional triggers on other relations, which will
1373-
* be processed in the context of the outer query. For efficiency's sake,
1374-
* we want to have a ResultRelInfo for those triggers too; that can avoid
1375-
* repeated re-opening of the relation. (It also provides a way for EXPLAIN
1376-
* ANALYZE to report the runtimes of such triggers.) So we make additional
1377-
* ResultRelInfo's as needed, and save them in es_trig_target_relations.
1368+
* we can just return a member of the es_result_relations array, the
1369+
* es_root_result_relations array (if any), or the es_leaf_result_relations
1370+
* list (if any). (Note: in self-join situations there might be multiple
1371+
* members with the same OID; if so it doesn't matter which one we pick.)
1372+
* However, it is sometimes necessary to fire triggers on other relations;
1373+
* this happens mainly when an RI update trigger queues additional triggers
1374+
* on other relations, which will be processed in the context of the outer
1375+
* query. For efficiency's sake, we want to have a ResultRelInfo for those
1376+
* triggers too; that can avoid repeated re-opening of the relation. (It
1377+
* also provides a way for EXPLAIN ANALYZE to report the runtimes of such
1378+
* triggers.) So we make additional ResultRelInfo's as needed, and save them
1379+
* in es_trig_target_relations.
13781380
*/
13791381
ResultRelInfo*
13801382
ExecGetTriggerResultRel(EState*estate,Oidrelid)
@@ -1395,6 +1397,23 @@ ExecGetTriggerResultRel(EState *estate, Oid relid)
13951397
rInfo++;
13961398
nr--;
13971399
}
1400+
/* Second, search through the root result relations, if any */
1401+
rInfo=estate->es_root_result_relations;
1402+
nr=estate->es_num_root_result_relations;
1403+
while (nr>0)
1404+
{
1405+
if (RelationGetRelid(rInfo->ri_RelationDesc)==relid)
1406+
returnrInfo;
1407+
rInfo++;
1408+
nr--;
1409+
}
1410+
/* Third, search through the leaf result relations, if any */
1411+
foreach(l,estate->es_leaf_result_relations)
1412+
{
1413+
rInfo= (ResultRelInfo*)lfirst(l);
1414+
if (RelationGetRelid(rInfo->ri_RelationDesc)==relid)
1415+
returnrInfo;
1416+
}
13981417
/* Nope, but maybe we already made an extra ResultRelInfo for it */
13991418
foreach(l,estate->es_trig_target_relations)
14001419
{
@@ -3238,6 +3257,7 @@ EvalPlanQualEnd(EPQState *epqstate)
32383257
void
32393258
ExecSetupPartitionTupleRouting(Relationrel,
32403259
IndexresultRTindex,
3260+
EState*estate,
32413261
PartitionDispatch**pd,
32423262
ResultRelInfo**partitions,
32433263
TupleConversionMap***tup_conv_maps,
@@ -3301,7 +3321,10 @@ ExecSetupPartitionTupleRouting(Relation rel,
33013321
partrel,
33023322
resultRTindex,
33033323
rel,
3304-
0);
3324+
estate->es_instrument);
3325+
3326+
estate->es_leaf_result_relations=
3327+
lappend(estate->es_leaf_result_relations,leaf_part_rri);
33053328

33063329
/*
33073330
* Open partition indices (remember we do not support ON CONFLICT in

‎src/backend/executor/execUtils.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,11 @@ CreateExecutorState(void)
115115
estate->es_num_result_relations=0;
116116
estate->es_result_relation_info=NULL;
117117

118+
estate->es_root_result_relations=NULL;
119+
estate->es_num_root_result_relations=0;
120+
121+
estate->es_leaf_result_relations=NIL;
122+
118123
estate->es_trig_target_relations=NIL;
119124
estate->es_trig_tuple_slot=NULL;
120125
estate->es_trig_oldtup_slot=NULL;

‎src/backend/executor/nodeModifyTable.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1919,6 +1919,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
19191919

19201920
ExecSetupPartitionTupleRouting(rel,
19211921
node->nominalRelation,
1922+
estate,
19221923
&partition_dispatch_info,
19231924
&partitions,
19241925
&partition_tupconv_maps,

‎src/include/executor/executor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ extern void EvalPlanQualSetTuple(EPQState *epqstate, Index rti,
208208
externHeapTupleEvalPlanQualGetTuple(EPQState*epqstate,Indexrti);
209209
externvoidExecSetupPartitionTupleRouting(Relationrel,
210210
IndexresultRTindex,
211+
EState*estate,
211212
PartitionDispatch**pd,
212213
ResultRelInfo**partitions,
213214
TupleConversionMap***tup_conv_maps,

‎src/include/nodes/execnodes.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,9 @@ typedef struct EState
452452
ResultRelInfo*es_root_result_relations;/* array of ResultRelInfos */
453453
intes_num_root_result_relations;/* length of the array */
454454

455+
/* Info about leaf partitions of partitioned table(s) for insert queries: */
456+
List*es_leaf_result_relations;/* List of ResultRelInfos */
457+
455458
/* Stuff used for firing triggers: */
456459
List*es_trig_target_relations;/* trigger-only ResultRelInfos */
457460
TupleTableSlot*es_trig_tuple_slot;/* for trigger output tuples */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp