diff options
-rw-r--r-- | doc/src/sgml/perform.sgml | 4 | ||||
-rw-r--r-- | doc/src/sgml/ref/copy.sgml | 4 | ||||
-rw-r--r-- | src/backend/commands/copy.c | 29 | ||||
-rw-r--r-- | src/test/regress/input/copy.source | 6 | ||||
-rw-r--r-- | src/test/regress/output/copy.source | 6 |
5 files changed, 44 insertions, 5 deletions
diff --git a/doc/src/sgml/perform.sgml b/doc/src/sgml/perform.sgml index 262f30fd4c7..7373af860cf 100644 --- a/doc/src/sgml/perform.sgml +++ b/doc/src/sgml/perform.sgml @@ -1535,8 +1535,8 @@ SELECT * FROM x, y, a, b, c WHERE something AND somethingelse; needs to be written, because in case of an error, the files containing the newly loaded data will be removed anyway. However, this consideration only applies when - <xref linkend="guc-wal-level"/> is <literal>minimal</literal> as all commands - must write WAL otherwise. + <xref linkend="guc-wal-level"/> is <literal>minimal</literal> for + non-partitioned tables as all commands must write WAL otherwise. </para> </sect2> diff --git a/doc/src/sgml/ref/copy.sgml b/doc/src/sgml/ref/copy.sgml index 13a8b68d951..9f3c85bf7f9 100644 --- a/doc/src/sgml/ref/copy.sgml +++ b/doc/src/sgml/ref/copy.sgml @@ -224,7 +224,9 @@ COPY { <replaceable class="parameter">table_name</replaceable> [ ( <replaceable This is intended as a performance option for initial data loading. Rows will be frozen only if the table being loaded has been created or truncated in the current subtransaction, there are no cursors - open and there are no older snapshots held by this transaction. + open and there are no older snapshots held by this transaction. It is + currently not possible to perform a <command>COPY FREEZE</command> on + a partitioned table. </para> <para> Note that all other sessions will immediately be able to see the data diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index a61f3bca4fb..7e5249e1e20 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -2416,11 +2416,20 @@ CopyFrom(CopyState cstate) * go into pages containing tuples from any other transactions --- but this * must be the case if we have a new table or new relfilenode, so we need * no additional work to enforce that. + * + * We currently don't support this optimization if the COPY target is a + * partitioned table as we currently only lazily initialize partition + * information when routing the first tuple to the partition. We cannot + * know at this stage if we can perform this optimization. It should be + * possible to improve on this, but it does mean maintaining heap insert + * option flags per partition and setting them when we first open the + * partition. *---------- */ /* createSubid is creation check, newRelfilenodeSubid is truncation check */ - if (cstate->rel->rd_createSubid != InvalidSubTransactionId || - cstate->rel->rd_newRelfilenodeSubid != InvalidSubTransactionId) + if (cstate->rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE && + (cstate->rel->rd_createSubid != InvalidSubTransactionId || + cstate->rel->rd_newRelfilenodeSubid != InvalidSubTransactionId)) { hi_options |= HEAP_INSERT_SKIP_FSM; if (!XLogIsNeeded()) @@ -2441,6 +2450,22 @@ CopyFrom(CopyState cstate) if (cstate->freeze) { /* + * We currently disallow COPY FREEZE on partitioned tables. The + * reason for this is that we've simply not yet opened the partitions + * to determine if the optimization can be applied to them. We could + * go and open them all here, but doing so may be quite a costly + * overhead for small copies. In any case, we may just end up routing + * tuples to a small number of partitions. It seems better just to + * raise an ERROR for partitioned tables. + */ + if (cstate->rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) + { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot perform FREEZE on a partitioned table"))); + } + + /* * Tolerate one registration for the benefit of FirstXactSnapshot. * Scan-bearing queries generally create at least two registrations, * though relying on that is fragile, as is ignoring ActiveSnapshot. diff --git a/src/test/regress/input/copy.source b/src/test/regress/input/copy.source index 4cb03c566fa..aefc99167af 100644 --- a/src/test/regress/input/copy.source +++ b/src/test/regress/input/copy.source @@ -159,6 +159,12 @@ truncate parted_copytest; copy parted_copytest from '@abs_builddir@/results/parted_copytest.csv'; +-- Ensure COPY FREEZE errors for partitioned tables. +begin; +truncate parted_copytest; +copy parted_copytest from '@abs_builddir@/results/parted_copytest.csv' (freeze); +rollback; + select tableoid::regclass,count(*),sum(a) from parted_copytest group by tableoid order by tableoid::regclass::name; diff --git a/src/test/regress/output/copy.source b/src/test/regress/output/copy.source index ddd652c7128..b16247230a0 100644 --- a/src/test/regress/output/copy.source +++ b/src/test/regress/output/copy.source @@ -113,6 +113,12 @@ insert into parted_copytest select x,1,'One' from generate_series(1011,1020) x; copy (select * from parted_copytest order by a) to '@abs_builddir@/results/parted_copytest.csv'; truncate parted_copytest; copy parted_copytest from '@abs_builddir@/results/parted_copytest.csv'; +-- Ensure COPY FREEZE errors for partitioned tables. +begin; +truncate parted_copytest; +copy parted_copytest from '@abs_builddir@/results/parted_copytest.csv' (freeze); +ERROR: cannot perform FREEZE on a partitioned table +rollback; select tableoid::regclass,count(*),sum(a) from parted_copytest group by tableoid order by tableoid::regclass::name; tableoid | count | sum |