Allow CREATE FOREIGN TABLE to include SERIAL columns.
The behavior is that the required sequence is created locally, which is appropriate because the default expression will be evaluated locally. Per gripe from Brad Nicholson that this case was refused with a confusing error message. We could have improved the error message but it seems better to just allow the case. Also, remove ALTER TABLE's arbitrary prohibition against being applied to foreign tables, which was pretty inconsistent considering we allow it for views, sequences, and other relation types that aren't even called tables. This is needed to avoid breaking pg_dump, which sometimes emits column defaults using separate ALTER TABLE commands. (I think this can happen even when the default is not associated with a sequence, so that was a pre-existing bug once we allowed column defaults for foreign tables.)
This commit is contained in:
parent
a2a480af88
commit
b142068622
4 changed files with 58 additions and 12 deletions
|
@ -2339,3 +2339,37 @@ select c2, count(*) from "S 1"."T 1" where c2 < 500 group by 1 order by 1;
|
|||
407 | 100
|
||||
(13 rows)
|
||||
|
||||
-- ===================================================================
|
||||
-- test serial columns (ie, sequence-based defaults)
|
||||
-- ===================================================================
|
||||
create table loc1 (f1 serial, f2 text);
|
||||
create foreign table rem1 (f1 serial, f2 text)
|
||||
server loopback options(table_name 'loc1');
|
||||
select pg_catalog.setval('rem1_f1_seq', 10, false);
|
||||
setval
|
||||
--------
|
||||
10
|
||||
(1 row)
|
||||
|
||||
insert into loc1(f2) values('hi');
|
||||
insert into rem1(f2) values('hi remote');
|
||||
insert into loc1(f2) values('bye');
|
||||
insert into rem1(f2) values('bye remote');
|
||||
select * from loc1;
|
||||
f1 | f2
|
||||
----+------------
|
||||
1 | hi
|
||||
10 | hi remote
|
||||
2 | bye
|
||||
11 | bye remote
|
||||
(4 rows)
|
||||
|
||||
select * from rem1;
|
||||
f1 | f2
|
||||
----+------------
|
||||
1 | hi
|
||||
10 | hi remote
|
||||
2 | bye
|
||||
11 | bye remote
|
||||
(4 rows)
|
||||
|
||||
|
|
|
@ -369,3 +369,17 @@ select c2, count(*) from "S 1"."T 1" where c2 < 500 group by 1 order by 1;
|
|||
commit;
|
||||
select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
|
||||
select c2, count(*) from "S 1"."T 1" where c2 < 500 group by 1 order by 1;
|
||||
|
||||
-- ===================================================================
|
||||
-- test serial columns (ie, sequence-based defaults)
|
||||
-- ===================================================================
|
||||
create table loc1 (f1 serial, f2 text);
|
||||
create foreign table rem1 (f1 serial, f2 text)
|
||||
server loopback options(table_name 'loc1');
|
||||
select pg_catalog.setval('rem1_f1_seq', 10, false);
|
||||
insert into loc1(f2) values('hi');
|
||||
insert into rem1(f2) values('hi remote');
|
||||
insert into loc1(f2) values('bye');
|
||||
insert into rem1(f2) values('bye remote');
|
||||
select * from loc1;
|
||||
select * from rem1;
|
||||
|
|
|
@ -1440,11 +1440,12 @@ process_owned_by(Relation seqrel, List *owned_by)
|
|||
rel = makeRangeVarFromNameList(relname);
|
||||
tablerel = relation_openrv(rel, AccessShareLock);
|
||||
|
||||
/* Must be a regular table */
|
||||
if (tablerel->rd_rel->relkind != RELKIND_RELATION)
|
||||
/* Must be a regular or foreign table */
|
||||
if (!(tablerel->rd_rel->relkind == RELKIND_RELATION ||
|
||||
tablerel->rd_rel->relkind == RELKIND_FOREIGN_TABLE))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("referenced relation \"%s\" is not a table",
|
||||
errmsg("referenced relation \"%s\" is not a table or foreign table",
|
||||
RelationGetRelationName(tablerel))));
|
||||
|
||||
/* We insist on same owner and schema */
|
||||
|
|
|
@ -10518,19 +10518,16 @@ RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, Oid oldrelid,
|
|||
errmsg("\"%s\" is a composite type", rv->relname),
|
||||
errhint("Use ALTER TYPE instead.")));
|
||||
|
||||
if (reltype != OBJECT_FOREIGN_TABLE && relkind == RELKIND_FOREIGN_TABLE)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("\"%s\" is a foreign table", rv->relname),
|
||||
errhint("Use ALTER FOREIGN TABLE instead.")));
|
||||
|
||||
/*
|
||||
* Don't allow ALTER TABLE .. SET SCHEMA on relations that can't be moved
|
||||
* to a different schema, such as indexes and TOAST tables.
|
||||
*/
|
||||
if (IsA(stmt, AlterObjectSchemaStmt) && relkind != RELKIND_RELATION
|
||||
&& relkind != RELKIND_VIEW && relkind != RELKIND_MATVIEW
|
||||
&& relkind != RELKIND_SEQUENCE && relkind != RELKIND_FOREIGN_TABLE)
|
||||
if (IsA(stmt, AlterObjectSchemaStmt) &&
|
||||
relkind != RELKIND_RELATION &&
|
||||
relkind != RELKIND_VIEW &&
|
||||
relkind != RELKIND_MATVIEW &&
|
||||
relkind != RELKIND_SEQUENCE &&
|
||||
relkind != RELKIND_FOREIGN_TABLE)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("\"%s\" is not a table, view, sequence, or foreign table",
|
||||
|
|
Loading…
Reference in a new issue