Обсуждение: ALTER TABLE

Поиск
Список
Период
Сортировка

ALTER TABLE

От
Gena Gurchonok
Дата:
============================================================================
                         POSTGRESQL BUG REPORT TEMPLATE
============================================================================

Your name               : Gena Gurchonok
Your email address      : gena@rt.mipt.ru

System Configuration
---------------------
   Architecture (example: Intel Pentium): intel Celeron 500
   Operating System (example: Linux 2.0.26 ELF): 2.2.16 ELF
   PostgreSQL version (example: PostgreSQL-7.0):   PostgreSQL-7.0.2
   Compiler used (example:  gcc 2.8.0): pgcc-2.91.66


Please enter a FULL description of your problem:
------------------------------------------------

When I renaming table using ALTER TABLE,
it doesn't change table name in RI triggers. This results in backend
crash due to invalid arguments for RI_Check trigger procedure.


Please describe a way to repeat the problem.   Please try to provide a
concise reproducible example, if at all possible:
----------------------------------------------------------------------

CREATE TABLE "pr1" (
        "id" int4 ,
        PRIMARY KEY ("id")
);

CREATE TABLE "fr" (
        "f_id" int4 NOT NULL,
        CONSTRAINT fr_fkey FOREIGN KEY (f_id)
        REFERENCES pr1(id)
        MATCH FULL
        ON DELETE RESTRICT
        ON UPDATE CASCADE
        NOT DEFERRABLE
        INITIALLY IMMEDIATE
);

insert into pr1 values(1);
insert into fr values(1);

alter table fr rename to fr2;

delete from pr1;

As the result we have:
pqReadData() -- backend closed the channel unexpectedly.
        This probably means the backend terminated abnormally
        before or while processing the request.
The connection to the server was lost. Attempting reset: Failed.

pg_dump gives

\connect - gena
CREATE TABLE "pr1" (
        "id" int4 NOT NULL,
        PRIMARY KEY ("id")
);
CREATE TABLE "fr2" (
        "f_id" int4 NOT NULL
);
COPY "pr1" FROM stdin;
1
\.
COPY "fr2" FROM stdin;
1
\.
CREATE CONSTRAINT TRIGGER "fr_fkey" AFTER DELETE ON "pr1"  NOT DEFERRABLE INITIALLY IMMEDIATE FOR EACH ROW EXECUTE
PROCEDURE"RI_FKey_restrict_del" ('fr_fkey', 'fr', 'pr1', 'FULL', 'f_id', 'id'); 
CREATE CONSTRAINT TRIGGER "fr_fkey" AFTER UPDATE ON "pr1"  NOT DEFERRABLE INITIALLY IMMEDIATE FOR EACH ROW EXECUTE
PROCEDURE"RI_FKey_cascade_upd" ('fr_fkey', 'fr', 'pr1', 'FULL', 'f_id', 'id'); 
CREATE CONSTRAINT TRIGGER "fr_fkey" AFTER INSERT OR UPDATE ON "fr2"  NOT DEFERRABLE INITIALLY IMMEDIATE FOR EACH ROW
EXECUTEPROCEDURE "RI_FKey_check_ins" ('fr_fkey', 'fr', 'pr1', 'FULL', 'f_id', 'id'); 

please take a look at TRIGGERS' arguments

Re: ALTER TABLE

От
Bruce Momjian
Дата:
I can confirm that this is a bug, and crashes in the current development
tree.


> ============================================================================
>                          POSTGRESQL BUG REPORT TEMPLATE
> ============================================================================
>
> Your name               : Gena Gurchonok
> Your email address      : gena@rt.mipt.ru
>
> System Configuration
> ---------------------
>    Architecture (example: Intel Pentium): intel Celeron 500
>    Operating System (example: Linux 2.0.26 ELF): 2.2.16 ELF
>    PostgreSQL version (example: PostgreSQL-7.0):   PostgreSQL-7.0.2
>    Compiler used (example:  gcc 2.8.0): pgcc-2.91.66
>
>
> Please enter a FULL description of your problem:
> ------------------------------------------------
>
> When I renaming table using ALTER TABLE,
> it doesn't change table name in RI triggers. This results in backend
> crash due to invalid arguments for RI_Check trigger procedure.
>
>
> Please describe a way to repeat the problem.   Please try to provide a
> concise reproducible example, if at all possible:
> ----------------------------------------------------------------------
>
> CREATE TABLE "pr1" (
>         "id" int4 ,
>         PRIMARY KEY ("id")
> );
>
> CREATE TABLE "fr" (
>         "f_id" int4 NOT NULL,
>         CONSTRAINT fr_fkey FOREIGN KEY (f_id)
>         REFERENCES pr1(id)
>         MATCH FULL
>         ON DELETE RESTRICT
>         ON UPDATE CASCADE
>         NOT DEFERRABLE
>         INITIALLY IMMEDIATE
> );
>
> insert into pr1 values(1);
> insert into fr values(1);
>
> alter table fr rename to fr2;
>
> delete from pr1;
>
> As the result we have:
> pqReadData() -- backend closed the channel unexpectedly.
>         This probably means the backend terminated abnormally
>         before or while processing the request.
> The connection to the server was lost. Attempting reset: Failed.
>
> pg_dump gives
>
> \connect - gena
> CREATE TABLE "pr1" (
>         "id" int4 NOT NULL,
>         PRIMARY KEY ("id")
> );
> CREATE TABLE "fr2" (
>         "f_id" int4 NOT NULL
> );
> COPY "pr1" FROM stdin;
> 1
> \.
> COPY "fr2" FROM stdin;
> 1
> \.
> CREATE CONSTRAINT TRIGGER "fr_fkey" AFTER DELETE ON "pr1"  NOT DEFERRABLE INITIALLY IMMEDIATE FOR EACH ROW EXECUTE
PROCEDURE"RI_FKey_restrict_del" ('fr_fkey', 'fr', 'pr1', 'FULL', 'f_id', 'id'); 
> CREATE CONSTRAINT TRIGGER "fr_fkey" AFTER UPDATE ON "pr1"  NOT DEFERRABLE INITIALLY IMMEDIATE FOR EACH ROW EXECUTE
PROCEDURE"RI_FKey_cascade_upd" ('fr_fkey', 'fr', 'pr1', 'FULL', 'f_id', 'id'); 
> CREATE CONSTRAINT TRIGGER "fr_fkey" AFTER INSERT OR UPDATE ON "fr2"  NOT DEFERRABLE INITIALLY IMMEDIATE FOR EACH ROW
EXECUTEPROCEDURE "RI_FKey_check_ins" ('fr_fkey', 'fr', 'pr1', 'FULL', 'f_id', 'id'); 
>
> please take a look at TRIGGERS' arguments
>
>
>


--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026

Re: ALTER TABLE

От
Tom Lane
Дата:
Gena Gurchonok <gena@rt.mipt.ru> writes:
> When I renaming table using ALTER TABLE,
> it doesn't change table name in RI triggers. This results in backend
> crash due to invalid arguments for RI_Check trigger procedure.

Yes, this is a known bug.  Two bugs actually, first being that the
trigger definitions don't track the rename (they should probably be
storing OID not relname, although that would complicate dump/restore).
Second is that the table opens in the triggers themselves neglect to
check for open failure :-(, which results in crashes later on.

            regards, tom lane

Re: ALTER TABLE

От
Tom Lane
Дата:
Stephan Szabo <sszabo@megazone23.bigpanda.com> writes:
>> Yes, this is a known bug.  Two bugs actually, first being that the
>> trigger definitions don't track the rename (they should probably be
>> storing OID not relname, although that would complicate dump/restore).

> I do plan on trying to move all the table/attribute storage to OIDs.
> I actually don't think it'll be too hard on dump/restore, since they
> should be able to get rewritten as an ALTER TABLE ADD CONSTRAINT
> rather than the CREATE CONSTRAINT TRIGGER, so it should just be
> a matter of turning the oids back into rel/attrib names at dump time.

That's doable, certainly, but I think it will be a little bit fragile.
How will pg_dump know which arguments of which triggers need to be
processed in this fashion?  Some ugly hardwired assumptions will be
needed AFAICS.

I think this ties into the discussions we've had on-and-off about not
storing enough metadata.  It'd be better if the FK constraints were
stored explicitly in some system table or other, in a form designed
for inspection, and not solely stored in a form designed for execution.
It's the same kind of problem we have with SERIAL columns...

            regards, tom lane

Re: ALTER TABLE

От
Tom Lane
Дата:
Stephan Szabo <sszabo@megazone23.bigpanda.com> writes:
> I believe these are all the cases I saw of heap_openr with no lock
> and no check in the actual trigger functions (patch to
> hopefully elog(ERROR) instead of crashing attached).
> [ patch snipped ]

We had a discussion about that on 11-July and the consensus seemed to be
that the real problem is heap_open's definition; it's too easy to forget
when you need to check for failure return.  I have just committed
changes that split heap_open into two routines: heap_open() now ALWAYS
elogs on failure, regardless of lock mode, while heap_open_nofail() is
what to call if you really want a NULL return on failure.  (Likewise for
heap_openr() of course.)  I found only about three places in the whole
backend that really wanted the _nofail() case.

Accordingly, this patch is not needed anymore in current sources, though
it'd still be the most convenient fix for 7.0.* series if anyone is
concerned enough to apply it.

A possibly more important issue: why are the RI triggers opening the
referenced rel with NoLock anyway?  Doesn't that leave you open to
someone deleting the referenced rel out from under you while you are
working with it?  Seems like at minimum you should grab AccessShareLock.
        regards, tom lane