On Fri, Jun 20, 2014 at 05:04:06PM +0900, Kyotaro HORIGUCHI wrote:
> Attached is the rebased patch of v11 up to the current master.

I've been studying this patch.

SELECT FOR UPDATE on the inheritance parent fails with a can't-happen error
condition, even when SELECT FOR UPDATE on the child foreign table alone would
have succeeded.

The patch adds zero tests.  Add principal tests to postgres_fdw.sql.  Also,
create a child foreign table in foreign_data.sql; this will make dump/reload
tests of the regression database exercise an inheritance tree that includes a
foreign table.

The inheritance section of ddl.sgml should mention child foreign tables, at
least briefly.  Consider mentioning it in the partitioning section, too.


Your chosen ANALYZE behavior is fair, but the messaging from a database-wide
ANALYZE VERBOSE needs work:

INFO:  analyzing "test_foreign_inherit.parent"
INFO:  "parent": scanned 1 of 1 pages, containing 1 live rows and 0 dead rows; 
1 rows in sample, 1 estimated total rows
INFO:  analyzing "test_foreign_inherit.parent" inheritance tree
WARNING:  relcache reference leak: relation "child" not closed
WARNING:  relcache reference leak: relation "tchild" not closed
WARNING:  relcache reference leak: relation "parent" not closed

Please arrange to omit the 'analyzing "tablename" inheritance tree' message,
since this ANALYZE actually skipped that task.  (The warnings obviously need a
fix, too.)  I do find it awkward that adding a foreign table to an inheritance
tree will make autovacuum stop collecting statistics on that inheritance tree,
but I can't think of a better policy.


The rest of these review comments are strictly observations; they're not
requests for you to change the patch, but they may deserve more discussion.

We use the term "child table" in many messages.  Should that change to
something more inclusive, now that the child may be a foreign table?  Perhaps
one of "child relation", plain "child", or "child foreign table"/"child table"
depending on the actual object?  "child relation" is robust technically, but
it might add more confusion than it removes.  Varying the message depending on
the actual object feels like a waste.  Opinions?

LOCK TABLE on the inheritance parent locks child foreign tables, but LOCK
TABLE fails when given a foreign table directly.  That's odd, but I see no
cause to change it.

A partition root only accepts an UPDATE command if every child is updatable.
Similarly, "UPDATE ... WHERE CURRENT OF cursor_name" fails if any child does
not support it.  That seems fine.  Incidentally, does anyone have a FDW that
supports WHERE CURRENT OF?


The longstanding behavior of CREATE TABLE INHERITS is to reorder local columns
to match the order found in parents.  That is, both of these tables actually
have columns in the order (a,b):

create table parent (a int, b int);
create table child (b int, a int) inherits (parent);

Ordinary dump/reload always uses CREATE TABLE INHERITS, thereby changing
column order in this way.  (pg_dump --binary-upgrade uses ALTER TABLE INHERIT
and some catalog hacks to avoid doing so.)  I've never liked that dump/reload
can change column order, but it's tolerable if you follow the best practice of
always writing out column lists.  The stakes rise for foreign tables, because
column order is inherently significant to file_fdw and probably to certain
other non-RDBMS FDWs.  If pg_dump changes column order in your file_fdw
foreign table, the table breaks.  I would heartily support making pg_dump
preserve column order for all inheritance children.  That doesn't rise to the
level of being a blocker for this patch, though.


I am attaching rough-hewn tests I used during this review.

Thanks,
nm

-- 
Noah Misch
EnterpriseDB                                 http://www.enterprisedb.com
drop schema test_foreign_inherit cascade;
create schema test_foreign_inherit;
set search_path = test_foreign_inherit;

create extension postgres_fdw;
CREATE SERVER loopback FOREIGN DATA WRAPPER postgres_fdw
  OPTIONS (dbname 'test');
CREATE USER MAPPING FOR CURRENT_USER SERVER loopback;

create extension file_fdw;
CREATE SERVER f FOREIGN DATA WRAPPER file_fdw;

create table parent (
        a int,
        b text,
        c date,
        d path
);
insert into parent values (4, 'foo', current_date, '0,0,1,2');

-- regular child
create table tchild () inherits (parent);
insert into tchild values (5, 'oof', current_date - 2, '-1,-1,0,0');

-- cursor update works
begin;
declare c cursor for select 1 from parent where b = 'oof';
fetch from c;
explain analyze update parent set b = null where current of c;
select * from parent;
rollback;

-- "foreign" side
create table _child (
        c date,
        b text,
        extra numeric,
        d path,
        a int
);

-- Foreign child.  No column reorder.
create foreign table child (
        c date,
        b text,
        extra numeric,
        d path,
        a int
) SERVER LOOPBACK OPTIONS (table_name '_child');
alter table child inherit parent;
insert into child (a, b, c, d, extra)
        values (7, 'bar', current_date - 1, '5,5,9,9', 1.1);
\copy (select * from child) to /tmp/child.pgcopy

-- update works
select * from parent;
update parent set b = 'baz' where b = 'bar';

-- cursor update fails, because postgres_fdw doesn't handle WHERE CURRENT OF
begin;
declare c cursor for select 1 from child where b = 'baz';
fetch from c;
update child set b = 'bak' where current of c;
rollback;

-- cursor update fails, even though target isn't in the foreign table
begin;
declare c cursor for select 1 from parent where b = 'oof';
fetch from c;
update parent set b = null where current of c;
rollback;


-- Add a file_fdw child.  No reorder.
create foreign table fchild0 (
        c date,
        b text,
        extra numeric,
        d path,
        a int
) SERVER f OPTIONS (filename '/tmp/child.pgcopy');
alter table fchild0 inherit parent;

-- no more update, since file_fdw doesn't cooperate
select * from parent;
update parent set b = 'baz' where b = 'foo';

select * from child for update of child;
select * from fchild0 for update of fchild0;
select * from parent for update;

-- No LOCK TABLE for foreign tables, ...
begin; lock table child in exclusive mode; rollback;

-- ... but locking indirectly via a parent works.
begin;
select relation::regclass, mode from pg_locks
where mode = 'ExclusiveLock' and relation is not null order by 1;
lock table parent in exclusive mode;
select relation::regclass, mode from pg_locks
where mode = 'ExclusiveLock' and relation is not null order by 1;
rollback;

alter server loopback options (use_remote_estimate 'true');
select * from parent;

analyze verbose;
analyze verbose parent;

-- message correctly observes that foreign table is now allowed
create view v as select 1;
alter table v inherit parent;

-- for testing dump/reload of column-level options
create foreign table nonlocal () inherits (parent)
server loopback options (table_name '_child');
alter foreign table child alter c options (column_name 'c');
alter foreign table nonlocal alter c options (column_name 'c');

-- column reorder breaks the foreign table
create foreign table fchild1 (
        c date,
        b text,
        extra numeric,
        d path,
        a int
) inherits (parent) SERVER f OPTIONS (filename '/tmp/child.pgcopy');

select * from fchild1;
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to