diff options
author | Robert Haas <rhaas@postgresql.org> | 2017-08-18 13:01:05 -0400 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2017-08-18 13:01:05 -0400 |
commit | c4b841ba6aa9252ab9dacd59d317aba8cfa9b31a (patch) | |
tree | f04bad7b7d401e1639c2fad616242dced8609c52 /src/backend/commands/copy.c | |
parent | a20aac890a89e6f88e841dedbbfa8d9d5f7309fc (diff) |
Fix interaction of triggers, partitioning, and EXPLAIN ANALYZE.
Add a new EState member es_leaf_result_relations, so that the trigger
code knows about ResultRelInfos created by tuple routing. Also make
sure ExplainPrintTriggers knows about partition-related
ResultRelInfos.
Etsuro Fujita, reviewed by Amit Langote
Discussion: http://postgr.es/m/57163e18-8e56-da83-337a-22f2c0008051@lab.ntt.co.jp
Diffstat (limited to 'src/backend/commands/copy.c')
-rw-r--r-- | src/backend/commands/copy.c | 110 |
1 files changed, 57 insertions, 53 deletions
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index a258965c200..375a25fbcf8 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -1415,59 +1415,6 @@ BeginCopy(ParseState *pstate, (errcode(ERRCODE_UNDEFINED_COLUMN), errmsg("table \"%s\" does not have OIDs", RelationGetRelationName(cstate->rel)))); - - /* - * If there are any triggers with transition tables on the named - * relation, we need to be prepared to capture transition tuples. - */ - cstate->transition_capture = MakeTransitionCaptureState(rel->trigdesc); - - /* Initialize state for CopyFrom tuple routing. */ - if (is_from && rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) - { - PartitionDispatch *partition_dispatch_info; - ResultRelInfo *partitions; - TupleConversionMap **partition_tupconv_maps; - TupleTableSlot *partition_tuple_slot; - int num_parted, - num_partitions; - - ExecSetupPartitionTupleRouting(rel, - 1, - &partition_dispatch_info, - &partitions, - &partition_tupconv_maps, - &partition_tuple_slot, - &num_parted, &num_partitions); - cstate->partition_dispatch_info = partition_dispatch_info; - cstate->num_dispatch = num_parted; - cstate->partitions = partitions; - cstate->num_partitions = num_partitions; - cstate->partition_tupconv_maps = partition_tupconv_maps; - cstate->partition_tuple_slot = partition_tuple_slot; - - /* - * If we are capturing transition tuples, they may need to be - * converted from partition format back to partitioned table - * format (this is only ever necessary if a BEFORE trigger - * modifies the tuple). - */ - if (cstate->transition_capture != NULL) - { - int i; - - cstate->transition_tupconv_maps = (TupleConversionMap **) - palloc0(sizeof(TupleConversionMap *) * - cstate->num_partitions); - for (i = 0; i < cstate->num_partitions; ++i) - { - cstate->transition_tupconv_maps[i] = - convert_tuples_by_name(RelationGetDescr(cstate->partitions[i].ri_RelationDesc), - RelationGetDescr(rel), - gettext_noop("could not convert row type")); - } - } - } } else { @@ -2483,6 +2430,63 @@ CopyFrom(CopyState cstate) estate->es_trig_tuple_slot = ExecInitExtraTupleSlot(estate); /* + * If there are any triggers with transition tables on the named relation, + * we need to be prepared to capture transition tuples. + */ + cstate->transition_capture = + MakeTransitionCaptureState(cstate->rel->trigdesc); + + /* + * If the named relation is a partitioned table, initialize state for + * CopyFrom tuple routing. + */ + if (cstate->rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) + { + PartitionDispatch *partition_dispatch_info; + ResultRelInfo *partitions; + TupleConversionMap **partition_tupconv_maps; + TupleTableSlot *partition_tuple_slot; + int num_parted, + num_partitions; + + ExecSetupPartitionTupleRouting(cstate->rel, + 1, + estate, + &partition_dispatch_info, + &partitions, + &partition_tupconv_maps, + &partition_tuple_slot, + &num_parted, &num_partitions); + cstate->partition_dispatch_info = partition_dispatch_info; + cstate->num_dispatch = num_parted; + cstate->partitions = partitions; + cstate->num_partitions = num_partitions; + cstate->partition_tupconv_maps = partition_tupconv_maps; + cstate->partition_tuple_slot = partition_tuple_slot; + + /* + * If we are capturing transition tuples, they may need to be + * converted from partition format back to partitioned table format + * (this is only ever necessary if a BEFORE trigger modifies the + * tuple). + */ + if (cstate->transition_capture != NULL) + { + int i; + + cstate->transition_tupconv_maps = (TupleConversionMap **) + palloc0(sizeof(TupleConversionMap *) * cstate->num_partitions); + for (i = 0; i < cstate->num_partitions; ++i) + { + cstate->transition_tupconv_maps[i] = + convert_tuples_by_name(RelationGetDescr(cstate->partitions[i].ri_RelationDesc), + RelationGetDescr(cstate->rel), + gettext_noop("could not convert row type")); + } + } + } + + /* * It's more efficient to prepare a bunch of tuples for insertion, and * insert them in one heap_multi_insert() call, than call heap_insert() * separately for every tuple. However, we can't do that if there are |