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

Commit501ed02

Browse files
committed
Fix transition tables for partition/inheritance.
We disallow row-level triggers with transition tables on child tables.Transition tables for triggers on the parent table contain only thosecolumns present in the parent. (We can't mix tuple formats in asingle transition table.)Patch by Thomas MunroDiscussion:https://postgr.es/m/CA%2BTgmoZzTBBAsEUh4MazAN7ga%3D8SsMC-Knp-6cetts9yNZUCcg%40mail.gmail.com
1 parent99255d7 commit501ed02

File tree

13 files changed

+1143
-110
lines changed

13 files changed

+1143
-110
lines changed

‎doc/src/sgml/ref/create_trigger.sgml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,20 @@ UPDATE OF <replaceable>column_name1</replaceable> [, <replaceable>column_name2</
458458
rows.
459459
</para>
460460

461+
<para>
462+
Modifying a partitioned table or a table with inheritance children fires
463+
statement-level triggers directly attached to that table, but not
464+
statement-level triggers for its partitions or child tables. In contrast,
465+
row-level triggers are fired for all affected partitions or child tables.
466+
If a statement-level trigger has been defined with transition relations
467+
named by a <literal>REFERENCING</literal> clause, then before and after
468+
images of rows are visible from all affected partitions or child tables.
469+
In the case of inheritance children, the row images include only columns
470+
that are present in the table that the trigger is attached to. Currently,
471+
row-level triggers with transition relations cannot be defined on
472+
partitions or inheritance child tables.
473+
</para>
474+
461475
<para>
462476
In <productname>PostgreSQL</productname> versions before 7.3, it was
463477
necessary to declare trigger functions as returning the placeholder

‎src/backend/catalog/pg_inherits.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,30 @@ has_subclass(Oid relationId)
273273
returnresult;
274274
}
275275

276+
/*
277+
* has_superclass - does this relation inherit from another? The caller
278+
* should hold a lock on the given relation so that it can't be concurrently
279+
* added to or removed from an inheritance hierarchy.
280+
*/
281+
bool
282+
has_superclass(OidrelationId)
283+
{
284+
Relationcatalog;
285+
SysScanDescscan;
286+
ScanKeyDataskey;
287+
boolresult;
288+
289+
catalog=heap_open(InheritsRelationId,AccessShareLock);
290+
ScanKeyInit(&skey,Anum_pg_inherits_inhrelid,BTEqualStrategyNumber,
291+
F_OIDEQ,ObjectIdGetDatum(relationId));
292+
scan=systable_beginscan(catalog,InheritsRelidSeqnoIndexId, true,
293+
NULL,1,&skey);
294+
result=HeapTupleIsValid(systable_getnext(scan));
295+
systable_endscan(scan);
296+
heap_close(catalog,AccessShareLock);
297+
298+
returnresult;
299+
}
276300

277301
/*
278302
* Given two type OIDs, determine whether the first is a complex type

‎src/backend/commands/copy.c

Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,8 @@ typedef struct CopyStateData
171171
ResultRelInfo*partitions;/* Per partition result relation */
172172
TupleConversionMap**partition_tupconv_maps;
173173
TupleTableSlot*partition_tuple_slot;
174+
TransitionCaptureState*transition_capture;
175+
TupleConversionMap**transition_tupconv_maps;
174176

175177
/*
176178
* These variables are used to reduce overhead in textual COPY FROM.
@@ -1436,6 +1438,36 @@ BeginCopy(ParseState *pstate,
14361438
cstate->num_partitions=num_partitions;
14371439
cstate->partition_tupconv_maps=partition_tupconv_maps;
14381440
cstate->partition_tuple_slot=partition_tuple_slot;
1441+
1442+
/*
1443+
* If there are any triggers with transition tables on the named
1444+
* relation, we need to be prepared to capture transition tuples
1445+
* from child relations too.
1446+
*/
1447+
cstate->transition_capture=
1448+
MakeTransitionCaptureState(rel->trigdesc);
1449+
1450+
/*
1451+
* If we are capturing transition tuples, they may need to be
1452+
* converted from partition format back to partitioned table
1453+
* format (this is only ever necessary if a BEFORE trigger
1454+
* modifies the tuple).
1455+
*/
1456+
if (cstate->transition_capture!=NULL)
1457+
{
1458+
inti;
1459+
1460+
cstate->transition_tupconv_maps= (TupleConversionMap**)
1461+
palloc0(sizeof(TupleConversionMap*)*
1462+
cstate->num_partitions);
1463+
for (i=0;i<cstate->num_partitions;++i)
1464+
{
1465+
cstate->transition_tupconv_maps[i]=
1466+
convert_tuples_by_name(RelationGetDescr(cstate->partitions[i].ri_RelationDesc),
1467+
RelationGetDescr(rel),
1468+
gettext_noop("could not convert row type"));
1469+
}
1470+
}
14391471
}
14401472
}
14411473
else
@@ -2591,6 +2623,35 @@ CopyFrom(CopyState cstate)
25912623
*/
25922624
estate->es_result_relation_info=resultRelInfo;
25932625

2626+
/*
2627+
* If we're capturing transition tuples, we might need to convert
2628+
* from the partition rowtype to parent rowtype.
2629+
*/
2630+
if (cstate->transition_capture!=NULL)
2631+
{
2632+
if (resultRelInfo->ri_TrigDesc&&
2633+
(resultRelInfo->ri_TrigDesc->trig_insert_before_row||
2634+
resultRelInfo->ri_TrigDesc->trig_insert_instead_row))
2635+
{
2636+
/*
2637+
* If there are any BEFORE or INSTEAD triggers on the
2638+
* partition, we'll have to be ready to convert their
2639+
* result back to tuplestore format.
2640+
*/
2641+
cstate->transition_capture->tcs_original_insert_tuple=NULL;
2642+
cstate->transition_capture->tcs_map=
2643+
cstate->transition_tupconv_maps[leaf_part_index];
2644+
}
2645+
else
2646+
{
2647+
/*
2648+
* Otherwise, just remember the original unconverted
2649+
* tuple, to avoid a needless round trip conversion.
2650+
*/
2651+
cstate->transition_capture->tcs_original_insert_tuple=tuple;
2652+
cstate->transition_capture->tcs_map=NULL;
2653+
}
2654+
}
25942655
/*
25952656
* We might need to convert from the parent rowtype to the
25962657
* partition rowtype.
@@ -2703,7 +2764,7 @@ CopyFrom(CopyState cstate)
27032764

27042765
/* AFTER ROW INSERT Triggers */
27052766
ExecARInsertTriggers(estate,resultRelInfo,tuple,
2706-
recheckIndexes);
2767+
recheckIndexes,cstate->transition_capture);
27072768

27082769
list_free(recheckIndexes);
27092770
}
@@ -2856,7 +2917,7 @@ CopyFromInsertBatch(CopyState cstate, EState *estate, CommandId mycid,
28562917
estate, false,NULL,NIL);
28572918
ExecARInsertTriggers(estate,resultRelInfo,
28582919
bufferedTuples[i],
2859-
recheckIndexes);
2920+
recheckIndexes,NULL);
28602921
list_free(recheckIndexes);
28612922
}
28622923
}
@@ -2866,14 +2927,15 @@ CopyFromInsertBatch(CopyState cstate, EState *estate, CommandId mycid,
28662927
* anyway.
28672928
*/
28682929
elseif (resultRelInfo->ri_TrigDesc!=NULL&&
2869-
resultRelInfo->ri_TrigDesc->trig_insert_after_row)
2930+
(resultRelInfo->ri_TrigDesc->trig_insert_after_row||
2931+
resultRelInfo->ri_TrigDesc->trig_insert_new_table))
28702932
{
28712933
for (i=0;i<nBufferedTuples;i++)
28722934
{
28732935
cstate->cur_lineno=firstBufferedLineNo+i;
28742936
ExecARInsertTriggers(estate,resultRelInfo,
28752937
bufferedTuples[i],
2876-
NIL);
2938+
NIL,NULL);
28772939
}
28782940
}
28792941

‎src/backend/commands/tablecmds.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10933,6 +10933,7 @@ ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode)
1093310933
Relationparent_rel;
1093410934
List*children;
1093510935
ObjectAddressaddress;
10936+
constchar*trigger_name;
1093610937

1093710938
/*
1093810939
* A self-exclusive lock is needed here. See the similar case in
@@ -11014,6 +11015,19 @@ ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode)
1101411015
RelationGetRelationName(child_rel),
1101511016
RelationGetRelationName(parent_rel))));
1101611017

11018+
/*
11019+
* If child_rel has row-level triggers with transition tables, we
11020+
* currently don't allow it to become an inheritance child. See also
11021+
* prohibitions in ATExecAttachPartition() and CreateTrigger().
11022+
*/
11023+
trigger_name=FindTriggerIncompatibleWithInheritance(child_rel->trigdesc);
11024+
if (trigger_name!=NULL)
11025+
ereport(ERROR,
11026+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
11027+
errmsg("trigger \"%s\" prevents table \"%s\" from becoming an inheritance child",
11028+
trigger_name,RelationGetRelationName(child_rel)),
11029+
errdetail("ROW triggers with transition tables are not supported in inheritance hierarchies")));
11030+
1101711031
/* OK to create inheritance */
1101811032
CreateInheritance(child_rel,parent_rel);
1101911033

@@ -13418,6 +13432,7 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd)
1341813432
TupleDesctupleDesc;
1341913433
boolskip_validate= false;
1342013434
ObjectAddressaddress;
13435+
constchar*trigger_name;
1342113436

1342213437
attachRel=heap_openrv(cmd->name,AccessExclusiveLock);
1342313438

@@ -13547,6 +13562,19 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd)
1354713562
errdetail("New partition should contain only the columns present in parent.")));
1354813563
}
1354913564

13565+
/*
13566+
* If child_rel has row-level triggers with transition tables, we
13567+
* currently don't allow it to become a partition. See also prohibitions
13568+
* in ATExecAddInherit() and CreateTrigger().
13569+
*/
13570+
trigger_name=FindTriggerIncompatibleWithInheritance(attachRel->trigdesc);
13571+
if (trigger_name!=NULL)
13572+
ereport(ERROR,
13573+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
13574+
errmsg("trigger \"%s\" prevents table \"%s\" from becoming a partition",
13575+
trigger_name,RelationGetRelationName(attachRel)),
13576+
errdetail("ROW triggers with transition tables are not supported on partitions")));
13577+
1355013578
/* OK to create inheritance. Rest of the checks performed there */
1355113579
CreateInheritance(attachRel,rel);
1355213580

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp