BUG #3692: Conflicting create table statements throw unexpected error
The following bug has been logged online:
Bug reference: 3692
Logged by: Bill Moran
Email address: wmoran@collaborativefusion.com
PostgreSQL version: 8.2.5
Operating system: FreeBSD
Description: Conflicting create table statements throw unexpected
error
Details:
(also occurs on 8.1.10)
Issuing a statement like:
CREATE TABLE table2 AS SELECT * FROM table1;
simultaneously in two separate sessions should result in an error like
"ERROR: relation "table2" already exists" (in one or the other of the
sessions, depending on the exact timing of things).
However, if table1 has enough rows that the command takes a while to execute
(a few seconds seems to be all it takes) the error is far more cryptic:
ERROR: duplicate key violates unique constraint "pg_type_typname_nsp_index"
It seems to me that there's some sort of race condition that if the second
command starts before the first has completed, the backend doesn't really
understand what went wrong.
For a front end, this is tough to parse. A "relation exists" error on a
table should probably be 42P07, but the duplicate key violation results in
23505, which means a front end will likely behave incorrectly.
"Bill Moran" <wmoran@collaborativefusion.com> writes:
Issuing a statement like:
CREATE TABLE table2 AS SELECT * FROM table1;
simultaneously in two separate sessions should result in an error like
"ERROR: relation "table2" already exists" (in one or the other of the
sessions, depending on the exact timing of things).
This isn't really fixable, or at least the cure would be worse than the
disease. The "already exists" message is just a pre-check and it cannot
detect an uncommitted concurrent attempt to insert the same table name.
The place where the rubber really meets the road is during unique index
insertion. We might be able to fix things so that you get a unique
index complaint about pg_class.relname instead of pg_type, but that
would be about it.
regards, tom lane
In response to Tom Lane <tgl@sss.pgh.pa.us>:
"Bill Moran" <wmoran@collaborativefusion.com> writes:
Issuing a statement like:
CREATE TABLE table2 AS SELECT * FROM table1;
simultaneously in two separate sessions should result in an error like
"ERROR: relation "table2" already exists" (in one or the other of the
sessions, depending on the exact timing of things).This isn't really fixable, or at least the cure would be worse than the
disease. The "already exists" message is just a pre-check and it cannot
detect an uncommitted concurrent attempt to insert the same table name.
The place where the rubber really meets the road is during unique index
insertion. We might be able to fix things so that you get a unique
index complaint about pg_class.relname instead of pg_type, but that
would be about it.
I figured it was something along those lines, otherwise it would have
already been "fixed".
I haven't had time to look at the code, so I'm speaking from a position
of ignorance, but would it be terribly difficult to catch the unique
constraint error, then re-run the pre-check to determine if it's
occurring as a result of trying to create an existing table, and
translate the error to a friendlier one before reporting to the client?
That doesn't seem unreasonable to me, but (as I already admitted) I
haven't looked at the code yet ...
--
Bill Moran
Collaborative Fusion Inc.
http://people.collaborativefusion.com/~wmoran/
wmoran@collaborativefusion.com
Phone: 412-422-3463x4023
Bill Moran wrote:
In response to Tom Lane <tgl@sss.pgh.pa.us>:
"Bill Moran" <wmoran@collaborativefusion.com> writes:
Issuing a statement like:
CREATE TABLE table2 AS SELECT * FROM table1;
simultaneously in two separate sessions should result in an error like
"ERROR: relation "table2" already exists" (in one or the other of the
sessions, depending on the exact timing of things).This isn't really fixable, or at least the cure would be worse than the
disease. The "already exists" message is just a pre-check and it cannot
detect an uncommitted concurrent attempt to insert the same table name.
The place where the rubber really meets the road is during unique index
insertion. We might be able to fix things so that you get a unique
index complaint about pg_class.relname instead of pg_type, but that
would be about it.I figured it was something along those lines, otherwise it would have
already been "fixed".I haven't had time to look at the code, so I'm speaking from a position
of ignorance, but would it be terribly difficult to catch the unique
constraint error, then re-run the pre-check to determine if it's
occurring as a result of trying to create an existing table, and
translate the error to a friendlier one before reporting to the client?
The problem we have with that is that unique index violations are not
separable from the elog(ERROR) they generate, so yes, it is terribly
difficult.
Maybe it would work to have a PG_TRY block around that code and compare
the error code with the one for unique index violation, in which case
the error is turned into "relation already exists".
--
Alvaro Herrera http://www.CommandPrompt.com/
PostgreSQL Replication, Consulting, Custom Development, 24x7 support
In response to Alvaro Herrera <alvherre@commandprompt.com>:
Bill Moran wrote:
In response to Tom Lane <tgl@sss.pgh.pa.us>:
"Bill Moran" <wmoran@collaborativefusion.com> writes:
Issuing a statement like:
CREATE TABLE table2 AS SELECT * FROM table1;
simultaneously in two separate sessions should result in an error like
"ERROR: relation "table2" already exists" (in one or the other of the
sessions, depending on the exact timing of things).This isn't really fixable, or at least the cure would be worse than the
disease. The "already exists" message is just a pre-check and it cannot
detect an uncommitted concurrent attempt to insert the same table name.
The place where the rubber really meets the road is during unique index
insertion. We might be able to fix things so that you get a unique
index complaint about pg_class.relname instead of pg_type, but that
would be about it.I figured it was something along those lines, otherwise it would have
already been "fixed".I haven't had time to look at the code, so I'm speaking from a position
of ignorance, but would it be terribly difficult to catch the unique
constraint error, then re-run the pre-check to determine if it's
occurring as a result of trying to create an existing table, and
translate the error to a friendlier one before reporting to the client?The problem we have with that is that unique index violations are not
separable from the elog(ERROR) they generate, so yes, it is terribly
difficult.Maybe it would work to have a PG_TRY block around that code and compare
the error code with the one for unique index violation, in which case
the error is turned into "relation already exists".
That was my hope, but I'm hoping from a position of ignorance, as
I've yet to have a chance to look at the code, and doubt I'll get a
chance for at least a week.
--
Bill Moran
Collaborative Fusion Inc.
http://people.collaborativefusion.com/~wmoran/
wmoran@collaborativefusion.com
Phone: 412-422-3463x4023
Added to TODO:
o Prevent concurrent CREATE TABLE table1 from sometimes returning
a cryptic error message
http://archives.postgresql.org/pgsql-bugs/2007-10/msg00169.php
---------------------------------------------------------------------------
Bill Moran wrote:
The following bug has been logged online:
Bug reference: 3692
Logged by: Bill Moran
Email address: wmoran@collaborativefusion.com
PostgreSQL version: 8.2.5
Operating system: FreeBSD
Description: Conflicting create table statements throw unexpected
error
Details:(also occurs on 8.1.10)
Issuing a statement like:
CREATE TABLE table2 AS SELECT * FROM table1;simultaneously in two separate sessions should result in an error like
"ERROR: relation "table2" already exists" (in one or the other of the
sessions, depending on the exact timing of things).However, if table1 has enough rows that the command takes a while to execute
(a few seconds seems to be all it takes) the error is far more cryptic:
ERROR: duplicate key violates unique constraint "pg_type_typname_nsp_index"It seems to me that there's some sort of race condition that if the second
command starts before the first has completed, the backend doesn't really
understand what went wrong.For a front end, this is tough to parse. A "relation exists" error on a
table should probably be 42P07, but the duplicate key violation results in
23505, which means a front end will likely behave incorrectly.---------------------------(end of broadcast)---------------------------
TIP 1: if posting/reading through Usenet, please send an appropriate
subscribe-nomail command to majordomo@postgresql.org so that your
message can get through to the mailing list cleanly
--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://postgres.enterprisedb.com
+ If your life is a hard drive, Christ can be your backup. +