Re: BUG #14684: pg_dump omits columns in inherited tables / psql -d shows deleted columns

From: "Hans Buschmann" <buschmann(at)nidsa(dot)net>
To: "Tom Lane" <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: <pgsql-bugs(at)postgresql(dot)org>
Subject: Re: BUG #14684: pg_dump omits columns in inherited tables / psql -d shows deleted columns
Date: 2017-06-03 15:48:27
Message-ID: D2B9F2A20670C84685EF7D183F2949E2373DC8@gigant.nidsa.net
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

Thanks for the quick answer.

My point on this topic is consistency:

1. I expect the command add column xxx to a table hierarchy followed by a drop column xxx to the same hierarchy to be logical a null operation.
add columns adds the columns to all inherited tables but drop column removes the column only in the parent table.

2. I expect the \d command to reflect the current logical status of the table

3. I expect all tools to see the same logical status of the tables, e.g. psql \d and pg_dump

In my original post I forgot to mention that the example was on the test machine after pg_dump/pg_restor from the production server.
To better show the problem I wrote a little test case:

---------------------------------------------------------------------------------

-- create database xxxdb template=template0 encoding 'UTF8' lc_collate='C';
-- \c xxxdb
-- create schema archiv;

select version();

ALTER DATABASE xxxdb SET search_path TO public,archiv;

SET search_path TO public,archiv;

drop table if exists of_test_archiv;
drop table if exists of_test;

CREATE TABLE of_test (
id_of integer PRIMARY KEY,
of_season smallint,
of_p_deliver_etd date,
of_p_deliver_eta date,
of_style_cus character varying(35),
CONSTRAINT ck_of_new CHECK ((of_season >= 22)) NO INHERIT
);

CREATE TABLE archiv.of_test_archiv (
id_of integer PRIMARY KEY,
of_season smallint,
of_p_deliver_etd date,
of_p_deliver_eta date,
of_style_cus character varying(35),
CONSTRAINT ck_of_old CHECK ((of_season < 22))
)
INHERITS (public.of_test);

\d of_test

\d of_test_archiv

alter table of_test
add column of_id_off smallint
,add column of_id_for_group smallint
;

alter table of_test
drop column of_style_cus
;

\d of_test

\d of_test_archiv

-- pg_dump -U postgres -d xxxdb -f c:/xxxdb_struct.sql

----------------------------------------------------------------------------------

The log in psql:

version
-------------------------------------------------------------
PostgreSQL 9.6.3, compiled by Visual C++ build 1800, 64-bit
(1 row)

ALTER DATABASE
SET
DROP TABLE
DROP TABLE
CREATE TABLE
CREATE TABLE
Table "public.of_test"
Column | Type | Modifiers
------------------+-----------------------+-----------
id_of | integer | not null
of_season | smallint |
of_p_deliver_etd | date |
of_p_deliver_eta | date |
of_style_cus | character varying(35) |
Indexes:
"of_test_pkey" PRIMARY KEY, btree (id_of)
Check constraints:
"ck_of_new" CHECK (of_season >= 22) NO INHERIT
Number of child tables: 1 (Use \d+ to list them.)

Table "archiv.of_test_archiv"
Column | Type | Modifiers
------------------+-----------------------+-----------
id_of | integer | not null
of_season | smallint |
of_p_deliver_etd | date |
of_p_deliver_eta | date |
of_style_cus | character varying(35) |
Indexes:
"of_test_archiv_pkey" PRIMARY KEY, btree (id_of)
Check constraints:
"ck_of_old" CHECK (of_season < 22)
Inherits: of_test

ALTER TABLE
ALTER TABLE
Table "public.of_test"
Column | Type | Modifiers
------------------+----------+-----------
id_of | integer | not null
of_season | smallint |
of_p_deliver_etd | date |
of_p_deliver_eta | date |
of_id_off | smallint |
of_id_for_group | smallint |
Indexes:
"of_test_pkey" PRIMARY KEY, btree (id_of)
Check constraints:
"ck_of_new" CHECK (of_season >= 22) NO INHERIT
Number of child tables: 1 (Use \d+ to list them.)

Table "archiv.of_test_archiv"
Column | Type | Modifiers
------------------+-----------------------+-----------
id_of | integer | not null
of_season | smallint |
of_p_deliver_etd | date |
of_p_deliver_eta | date |
of_style_cus | character varying(35) |
of_id_off | smallint |
of_id_for_group | smallint |
Indexes:
"of_test_archiv_pkey" PRIMARY KEY, btree (id_of)
Check constraints:
"ck_of_old" CHECK (of_season < 22)
Inherits: of_test

---------------------------------------------------------------------------------------

Please note the ordering of the columns in of_test_archiv !!!

The dump output shows (in parts):

...

CREATE TABLE of_test (
id_of integer NOT NULL,
of_season smallint,
of_p_deliver_etd date,
of_p_deliver_eta date,
of_id_off smallint,
of_id_for_group smallint,
CONSTRAINT ck_of_new CHECK ((of_season >= 22)) NO INHERIT
);

ALTER TABLE of_test OWNER TO postgres;

SET search_path = archiv, pg_catalog;

--
-- Name: of_test_archiv; Type: TABLE; Schema: archiv; Owner: postgres
--

CREATE TABLE of_test_archiv (
id_of integer,
of_season smallint,
of_p_deliver_etd date,
of_p_deliver_eta date,
of_style_cus character varying(35),
CONSTRAINT ck_of_old CHECK ((of_season < 22))
)
INHERITS (public.of_test);

ALTER TABLE of_test_archiv OWNER TO postgres;

...
-----------------------------------------------------------------------------------

Here the table creation of of_test_archiv misses the newly added columns and still has the dropped column.

When you later restore the dump on a different machine (e.g. as backup), the definition of the of_test_archiv table changes in psql \d:

xxxdb=# \d of_test_archiv
Table "archiv.of_test_archiv"
Column | Type | Modifiers
------------------+-----------------------+-----------
id_of | integer | not null
of_season | smallint |
of_p_deliver_etd | date |
of_p_deliver_eta | date |
of_id_off | smallint |
of_id_for_group | smallint |
of_style_cus | character varying(35) |
Indexes:
"of_test_archiv_pkey" PRIMARY KEY, btree (id_of)
Check constraints:
"ck_of_old" CHECK (of_season < 22)
Inherits: of_test

xxxdb=# alter table of_test_archiv no inherit of_test;
ALTER TABLE
xxxdb=# \d of_test_archiv
Table "archiv.of_test_archiv"
Column | Type | Modifiers
------------------+-----------------------+-----------
id_of | integer | not null
of_season | smallint |
of_p_deliver_etd | date |
of_p_deliver_eta | date |
of_id_off | smallint |
of_id_for_group | smallint |
of_style_cus | character varying(35) |
Indexes:
"of_test_archiv_pkey" PRIMARY KEY, btree (id_of)
Check constraints:
"ck_of_old" CHECK (of_season < 22)

Now table of_test_archiv has of_style_cus as a column, even when in the original database this column was not more part of the table definition (see above)

The dump/restore operation is no longer logical invariant to the table structure.

Because I have many of these inherited tables and I am still in the process of restructuring the data, about a year ago I got an error of restoring the production database to the dev machine bcause of inheritence error (I cant remember exactly and could not nail it down at the time: it seemed to be a type error because of column ordering).

So it is possible that you get more serious data problems by changing columns in inherited tables.

I would expect that pg_dump recognizes the same table struct as psql \d at any time.

BTW: the bloat output (e.g. NOTICE: merging column "id_of" with inherited definition) appears in psql window even when output is redirected with \o

In response to

Responses

Browse pgsql-bugs by date

  From Date Subject
Next Message Tom Lane 2017-06-03 16:15:41 Re: BUG #14684: pg_dump omits columns in inherited tables / psql -d shows deleted columns
Previous Message Tom Lane 2017-06-03 02:43:35 Re: BUG #14686: OpenSSL 1.1.0+ breaks PostgreSQL's sslcompression assumption, defaults to SSL_OP_NO_COMPRESSION