Disallow COPY FREEZE on partitioned tables
This didn't actually work: COPY would fail to flush the right files, and instead would try to flush a non-existing file, causing the whole transaction to fail. Cope by raising an error as soon as the command is sent instead, to avoid a nasty later surprise. Of course, it would be much better to make it work, but we don't have a patch for that yet, and we don't know if we'll want to backpatch one when we do. Reported-by: Tomas Vondra Author: David Rowley Reviewed-by: Amit Langote, Steve Singer, Tomas Vondra
This commit is contained in:
parent
fc47e99a15
commit
5c9a5513a3
|
@ -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
|
needs to be written, because in case of an error, the files
|
||||||
containing the newly loaded data will be removed anyway.
|
containing the newly loaded data will be removed anyway.
|
||||||
However, this consideration only applies when
|
However, this consideration only applies when
|
||||||
<xref linkend="guc-wal-level"/> is <literal>minimal</literal> as all commands
|
<xref linkend="guc-wal-level"/> is <literal>minimal</literal> for
|
||||||
must write WAL otherwise.
|
non-partitioned tables as all commands must write WAL otherwise.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
|
@ -224,7 +224,9 @@ COPY { <replaceable class="parameter">table_name</replaceable> [ ( <replaceable
|
||||||
This is intended as a performance option for initial data loading.
|
This is intended as a performance option for initial data loading.
|
||||||
Rows will be frozen only if the table being loaded has been created
|
Rows will be frozen only if the table being loaded has been created
|
||||||
or truncated in the current subtransaction, there are no cursors
|
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>
|
||||||
<para>
|
<para>
|
||||||
Note that all other sessions will immediately be able to see the data
|
Note that all other sessions will immediately be able to see the data
|
||||||
|
|
|
@ -2416,11 +2416,20 @@ CopyFrom(CopyState cstate)
|
||||||
* go into pages containing tuples from any other transactions --- but this
|
* 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
|
* must be the case if we have a new table or new relfilenode, so we need
|
||||||
* no additional work to enforce that.
|
* 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 */
|
/* createSubid is creation check, newRelfilenodeSubid is truncation check */
|
||||||
if (cstate->rel->rd_createSubid != InvalidSubTransactionId ||
|
if (cstate->rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE &&
|
||||||
cstate->rel->rd_newRelfilenodeSubid != InvalidSubTransactionId)
|
(cstate->rel->rd_createSubid != InvalidSubTransactionId ||
|
||||||
|
cstate->rel->rd_newRelfilenodeSubid != InvalidSubTransactionId))
|
||||||
{
|
{
|
||||||
hi_options |= HEAP_INSERT_SKIP_FSM;
|
hi_options |= HEAP_INSERT_SKIP_FSM;
|
||||||
if (!XLogIsNeeded())
|
if (!XLogIsNeeded())
|
||||||
|
@ -2440,6 +2449,22 @@ CopyFrom(CopyState cstate)
|
||||||
*/
|
*/
|
||||||
if (cstate->freeze)
|
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.
|
* Tolerate one registration for the benefit of FirstXactSnapshot.
|
||||||
* Scan-bearing queries generally create at least two registrations,
|
* Scan-bearing queries generally create at least two registrations,
|
||||||
|
|
|
@ -159,6 +159,12 @@ truncate parted_copytest;
|
||||||
|
|
||||||
copy parted_copytest from '@abs_builddir@/results/parted_copytest.csv';
|
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
|
select tableoid::regclass,count(*),sum(a) from parted_copytest
|
||||||
group by tableoid order by tableoid::regclass::name;
|
group by tableoid order by tableoid::regclass::name;
|
||||||
|
|
||||||
|
|
|
@ -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';
|
copy (select * from parted_copytest order by a) to '@abs_builddir@/results/parted_copytest.csv';
|
||||||
truncate parted_copytest;
|
truncate parted_copytest;
|
||||||
copy parted_copytest from '@abs_builddir@/results/parted_copytest.csv';
|
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
|
select tableoid::regclass,count(*),sum(a) from parted_copytest
|
||||||
group by tableoid order by tableoid::regclass::name;
|
group by tableoid order by tableoid::regclass::name;
|
||||||
tableoid | count | sum
|
tableoid | count | sum
|
||||||
|
|
Loading…
Reference in New Issue