On Fri, Jan 25, 2013 at 11:08:56PM -0500, Tom Lane wrote: > Bruce Momjian <br...@momjian.us> writes: > > ! ereport(ERROR, > > ! > > (ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE, > > ! errmsg("cannot perform FREEZE > > because of previous table activity in the current transaction"))); > > [ itch... ] What is "table activity"? I always thought of tables as > being rather passive objects. And anyway, isn't this backwards? What > we're complaining of is *lack* of activity. I don't see why this isn't > using the same message as the other code path, namely
Well, here is an example of this message: BEGIN; TRUNCATE vistest; SAVEPOINT s1; COPY vistest FROM stdin CSV FREEZE; ERROR: cannot perform FREEZE because of previous table activity in the current transaction COMMIT; Clearly it was truncated in the same transaction, but the savepoint somehow invalidates the freeze. There is a C comment about it: * BEGIN; * TRUNCATE t; * SAVEPOINT save; * TRUNCATE t; * ROLLBACK TO save; * COPY ... I changed it to: ERROR: cannot perform FREEZE because of transaction activity after table creation or truncation -- Bruce Momjian <br...@momjian.us> http://momjian.us EnterpriseDB http://enterprisedb.com + It's impossible for everything to be true. +
diff --git a/doc/src/sgml/ref/copy.sgml b/doc/src/sgml/ref/copy.sgml new file mode 100644 index 6a0fabc..2137c67 *** a/doc/src/sgml/ref/copy.sgml --- b/doc/src/sgml/ref/copy.sgml *************** COPY { <replaceable class="parameter">ta *** 190,207 **** would be after running the <command>VACUUM FREEZE</> command. This is intended as a performance option for initial data loading. Rows will be frozen only if the table being loaded has been created ! in the current subtransaction, there are no cursors open and there ! are no older snapshots held by this transaction. If those conditions ! are not met the command will continue without error though will not ! freeze rows. It is also possible in rare cases that the request ! cannot be honoured for internal reasons, hence <literal>FREEZE</literal> ! is more of a guideline than a hard rule. </para> <para> Note that all other sessions will immediately be able to see the data once it has been successfully loaded. This violates the normal rules ! of MVCC visibility and by specifying this option the user acknowledges ! explicitly that this is understood. </para> </listitem> </varlistentry> --- 190,203 ---- would be after running the <command>VACUUM FREEZE</> command. 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. </para> <para> Note that all other sessions will immediately be able to see the data once it has been successfully loaded. This violates the normal rules ! of MVCC visibility and users specifying should be aware of the ! potential problems this might cause. </para> </listitem> </varlistentry> diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c new file mode 100644 index 8778e8b..49cc8dd *** a/src/backend/commands/copy.c --- b/src/backend/commands/copy.c *************** CopyFrom(CopyState cstate) *** 1978,1985 **** * ROLLBACK TO save; * COPY ... * - * However this is OK since at worst we will fail to make the optimization. - * * Also, if the target file is new-in-transaction, we assume that checking * FSM for free space is a waste of time, even if we must use WAL because * of archiving. This could possibly be wrong, but it's unlikely. --- 1978,1983 ---- *************** CopyFrom(CopyState cstate) *** 1991,1996 **** --- 1989,1995 ---- * no additional work to enforce that. *---------- */ + /* createSubid is creation check, newRelfilenodeSubid is truncation check */ if (cstate->rel->rd_createSubid != InvalidSubTransactionId || cstate->rel->rd_newRelfilenodeSubid != InvalidSubTransactionId) { *************** CopyFrom(CopyState cstate) *** 2006,2023 **** * after xact cleanup. Note that the stronger test of exactly * which subtransaction created it is crucial for correctness * of this optimisation. - * - * As noted above rd_newRelfilenodeSubid is not set in all cases - * where we can apply the optimization, so in those rare cases - * where we cannot honour the request we do so silently. */ ! if (cstate->freeze && ! ThereAreNoPriorRegisteredSnapshots() && ! ThereAreNoReadyPortals() && ! (cstate->rel->rd_newRelfilenodeSubid == GetCurrentSubTransactionId() || ! cstate->rel->rd_createSubid == GetCurrentSubTransactionId())) ! hi_options |= HEAP_INSERT_FROZEN; } /* * We need a ResultRelInfo so we can use the regular executor's --- 2005,2031 ---- * after xact cleanup. Note that the stronger test of exactly * which subtransaction created it is crucial for correctness * of this optimisation. */ ! if (cstate->freeze) ! { ! if (!ThereAreNoPriorRegisteredSnapshots() || !ThereAreNoReadyPortals()) ! ereport(ERROR, ! (ERRCODE_INVALID_TRANSACTION_STATE, ! errmsg("cannot perform FREEZE because of prior transaction activity"))); ! ! if (cstate->rel->rd_createSubid == GetCurrentSubTransactionId() || ! cstate->rel->rd_newRelfilenodeSubid == GetCurrentSubTransactionId()) ! hi_options |= HEAP_INSERT_FROZEN; ! else ! ereport(ERROR, ! (ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE, ! errmsg("cannot perform FREEZE because of transaction activity after table creation or truncation"))); ! } } + else if (cstate->freeze) + ereport(ERROR, + (ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE, + errmsg("cannot perform FREEZE because the table was not created or truncated in the current transaction"))); /* * We need a ResultRelInfo so we can use the regular executor's diff --git a/src/test/regress/expected/copy2.out b/src/test/regress/expected/copy2.out new file mode 100644 index 78c601f..5777b24 *** a/src/test/regress/expected/copy2.out --- b/src/test/regress/expected/copy2.out *************** SELECT * FROM vistest; *** 334,355 **** COMMIT; TRUNCATE vistest; COPY vistest FROM stdin CSV FREEZE; BEGIN; INSERT INTO vistest VALUES ('z'); SAVEPOINT s1; TRUNCATE vistest; ROLLBACK TO SAVEPOINT s1; COPY vistest FROM stdin CSV FREEZE; ! SELECT * FROM vistest; ! a ! ---- ! p ! g ! z ! d3 ! e ! (5 rows) ! COMMIT; CREATE FUNCTION truncate_in_subxact() RETURNS VOID AS $$ --- 334,353 ---- COMMIT; TRUNCATE vistest; COPY vistest FROM stdin CSV FREEZE; + ERROR: cannot perform FREEZE because the table was not created or truncated in the current transaction + BEGIN; + TRUNCATE vistest; + SAVEPOINT s1; + COPY vistest FROM stdin CSV FREEZE; + ERROR: cannot perform FREEZE because of transaction activity after table creation or truncation + COMMIT; BEGIN; INSERT INTO vistest VALUES ('z'); SAVEPOINT s1; TRUNCATE vistest; ROLLBACK TO SAVEPOINT s1; COPY vistest FROM stdin CSV FREEZE; ! ERROR: cannot perform FREEZE because the table was not created or truncated in the current transaction COMMIT; CREATE FUNCTION truncate_in_subxact() RETURNS VOID AS $$ diff --git a/src/test/regress/sql/copy2.sql b/src/test/regress/sql/copy2.sql new file mode 100644 index 55568e6..c46128b *** a/src/test/regress/sql/copy2.sql --- b/src/test/regress/sql/copy2.sql *************** p *** 234,239 **** --- 234,247 ---- g \. BEGIN; + TRUNCATE vistest; + SAVEPOINT s1; + COPY vistest FROM stdin CSV FREEZE; + m + k + \. + COMMIT; + BEGIN; INSERT INTO vistest VALUES ('z'); SAVEPOINT s1; TRUNCATE vistest; *************** COPY vistest FROM stdin CSV FREEZE; *** 242,248 **** d3 e \. - SELECT * FROM vistest; COMMIT; CREATE FUNCTION truncate_in_subxact() RETURNS VOID AS $$ --- 250,255 ----
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers