From 5bcf8ede45c780e4ac394397bd0413118f3a162f Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Fri, 9 Dec 2011 20:42:30 +0200 Subject: [PATCH] Add ALTER FOREIGN DATA WRAPPER / RENAME and ALTER SERVER / RENAME --- .../sgml/ref/alter_foreign_data_wrapper.sgml | 22 +++++- doc/src/sgml/ref/alter_server.sgml | 21 +++++ src/backend/commands/alter.c | 8 ++ src/backend/commands/foreigncmds.c | 76 +++++++++++++++++++ src/backend/parser/gram.y | 16 ++++ src/include/commands/defrem.h | 2 + src/test/regress/expected/foreign_data.out | 31 ++++++++ src/test/regress/sql/foreign_data.sql | 8 ++ 8 files changed, 183 insertions(+), 1 deletion(-) diff --git a/doc/src/sgml/ref/alter_foreign_data_wrapper.sgml b/doc/src/sgml/ref/alter_foreign_data_wrapper.sgml index 59cf9c65e7..7376804403 100644 --- a/doc/src/sgml/ref/alter_foreign_data_wrapper.sgml +++ b/doc/src/sgml/ref/alter_foreign_data_wrapper.sgml @@ -26,6 +26,7 @@ ALTER FOREIGN DATA WRAPPER name [ VALIDATOR validator_function | NO VALIDATOR ] [ OPTIONS ( [ ADD | SET | DROP ] option ['value'] [, ... ]) ] ALTER FOREIGN DATA WRAPPER name OWNER TO new_owner +ALTER FOREIGN DATA WRAPPER name RENAME TO new_name @@ -122,6 +123,24 @@ ALTER FOREIGN DATA WRAPPER name OWN + + + new_owner + + + The user name of the new owner of the foreign-data wrapper. + + + + + + new_name + + + The new name for the foreign-data wrapper. + + + @@ -150,7 +169,8 @@ ALTER FOREIGN DATA WRAPPER dbi VALIDATOR bob.myvalidator; ALTER FOREIGN DATA WRAPPER conforms to ISO/IEC 9075-9 (SQL/MED), except that the HANDLER, - VALIDATOR and OWNER TO clauses are extensions. + VALIDATOR, OWNER TO, and RENAME + clauses are extensions. diff --git a/doc/src/sgml/ref/alter_server.sgml b/doc/src/sgml/ref/alter_server.sgml index c27b4c06a1..248efd9163 100644 --- a/doc/src/sgml/ref/alter_server.sgml +++ b/doc/src/sgml/ref/alter_server.sgml @@ -24,6 +24,7 @@ PostgreSQL documentation ALTER SERVER server_name [ VERSION 'new_version' ] [ OPTIONS ( [ ADD | SET | DROP ] option ['value'] [, ... ] ) ] ALTER SERVER server_name OWNER TO new_owner +ALTER SERVER server_name RENAME TO new_name @@ -82,6 +83,24 @@ ALTER SERVER server_name OWNER TO < + + + new_owner + + + The user name of the new owner of the foreign server. + + + + + + new_name + + + The new name for the foreign server. + + + @@ -108,6 +127,8 @@ ALTER SERVER foo VERSION '8.4' OPTIONS (SET host 'baz'); ALTER SERVER conforms to ISO/IEC 9075-9 (SQL/MED). + The OWNER TO and RENAME forms are + PostgreSQL extensions. diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c index eb0584e991..f9be3a9a4e 100644 --- a/src/backend/commands/alter.c +++ b/src/backend/commands/alter.c @@ -65,6 +65,14 @@ ExecRenameStmt(RenameStmt *stmt) RenameDatabase(stmt->subname, stmt->newname); break; + case OBJECT_FDW: + RenameForeignDataWrapper(stmt->subname, stmt->newname); + break; + + case OBJECT_FOREIGN_SERVER: + RenameForeignServer(stmt->subname, stmt->newname); + break; + case OBJECT_FUNCTION: RenameFunction(stmt->object, stmt->objarg, stmt->newname); break; diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c index b30ff40923..5e58713da7 100644 --- a/src/backend/commands/foreigncmds.c +++ b/src/backend/commands/foreigncmds.c @@ -200,6 +200,82 @@ GetUserOidFromMapping(const char *username, bool missing_ok) } +/* + * Rename foreign-data wrapper + */ +void +RenameForeignDataWrapper(const char *oldname, const char *newname) +{ + HeapTuple tup; + Relation rel; + + rel = heap_open(ForeignDataWrapperRelationId, RowExclusiveLock); + + tup = SearchSysCacheCopy1(FOREIGNDATAWRAPPERNAME, CStringGetDatum(oldname)); + if (!HeapTupleIsValid(tup)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("foreign-data wrapper \"%s\" does not exist", oldname))); + + /* make sure the new name doesn't exist */ + if (SearchSysCacheExists1(FOREIGNDATAWRAPPERNAME, CStringGetDatum(newname))) + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("foreign-data wrapper \"%s\" already exists", newname))); + + /* must be owner of FDW */ + if (!pg_foreign_data_wrapper_ownercheck(HeapTupleGetOid(tup), GetUserId())) + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_FDW, + oldname); + + /* rename */ + namestrcpy(&(((Form_pg_foreign_data_wrapper) GETSTRUCT(tup))->fdwname), newname); + simple_heap_update(rel, &tup->t_self, tup); + CatalogUpdateIndexes(rel, tup); + + heap_close(rel, NoLock); + heap_freetuple(tup); +} + + +/* + * Rename foreign server + */ +void +RenameForeignServer(const char *oldname, const char *newname) +{ + HeapTuple tup; + Relation rel; + + rel = heap_open(ForeignServerRelationId, RowExclusiveLock); + + tup = SearchSysCacheCopy1(FOREIGNSERVERNAME, CStringGetDatum(oldname)); + if (!HeapTupleIsValid(tup)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("server \"%s\" does not exist", oldname))); + + /* make sure the new name doesn't exist */ + if (SearchSysCacheExists1(FOREIGNSERVERNAME, CStringGetDatum(newname))) + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("server \"%s\" already exists", newname))); + + /* must be owner of server */ + if (!pg_foreign_server_ownercheck(HeapTupleGetOid(tup), GetUserId())) + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_FOREIGN_SERVER, + oldname); + + /* rename */ + namestrcpy(&(((Form_pg_foreign_server) GETSTRUCT(tup))->srvname), newname); + simple_heap_update(rel, &tup->t_self, tup); + CatalogUpdateIndexes(rel, tup); + + heap_close(rel, NoLock); + heap_freetuple(tup); +} + + /* * Change foreign-data wrapper owner. * diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 2a497d1b79..c3e0ee1877 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -6434,6 +6434,14 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name n->newname = $6; $$ = (Node *)n; } + | ALTER FOREIGN DATA_P WRAPPER name RENAME TO name + { + RenameStmt *n = makeNode(RenameStmt); + n->renameType = OBJECT_FDW; + n->subname = $5; + n->newname = $8; + $$ = (Node *)n; + } | ALTER FUNCTION function_with_argtypes RENAME TO name { RenameStmt *n = makeNode(RenameStmt); @@ -6485,6 +6493,14 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name n->newname = $6; $$ = (Node *)n; } + | ALTER SERVER name RENAME TO name + { + RenameStmt *n = makeNode(RenameStmt); + n->renameType = OBJECT_FOREIGN_SERVER; + n->subname = $3; + n->newname = $6; + $$ = (Node *)n; + } | ALTER TABLE relation_expr RENAME TO name { RenameStmt *n = makeNode(RenameStmt); diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h index 70d3a8fe02..1390351697 100644 --- a/src/include/commands/defrem.h +++ b/src/include/commands/defrem.h @@ -146,6 +146,8 @@ extern text *serialize_deflist(List *deflist); extern List *deserialize_deflist(Datum txt); /* commands/foreigncmds.c */ +extern void RenameForeignServer(const char *oldname, const char *newname); +extern void RenameForeignDataWrapper(const char *oldname, const char *newname); extern void AlterForeignServerOwner(const char *name, Oid newOwnerId); extern void AlterForeignDataWrapperOwner(const char *name, Oid newOwnerId); extern void CreateForeignDataWrapper(CreateFdwStmt *stmt); diff --git a/src/test/regress/expected/foreign_data.out b/src/test/regress/expected/foreign_data.out index 314748c6d4..122e28532a 100644 --- a/src/test/regress/expected/foreign_data.out +++ b/src/test/regress/expected/foreign_data.out @@ -177,6 +177,17 @@ RESET ROLE; postgresql | foreign_data_user | - | postgresql_fdw_validator | | | (3 rows) +ALTER FOREIGN DATA WRAPPER foo RENAME TO foo1; +\dew+ + List of foreign-data wrappers + Name | Owner | Handler | Validator | Access privileges | FDW Options | Description +------------+-------------------------+---------+--------------------------+-------------------+------------------------------+------------- + dummy | foreign_data_user | - | - | | | useless + foo1 | regress_test_role_super | - | - | | (b '3', c '4', a '2', d '5') | + postgresql | foreign_data_user | - | postgresql_fdw_validator | | | +(3 rows) + +ALTER FOREIGN DATA WRAPPER foo1 RENAME TO foo; -- DROP FOREIGN DATA WRAPPER DROP FOREIGN DATA WRAPPER nonexistent; -- ERROR ERROR: foreign-data wrapper "nonexistent" does not exist @@ -427,6 +438,26 @@ privileges for foreign-data wrapper foo t2 | regress_test_role | foo | | | | | (10 rows) +ALTER SERVER s8 RENAME to s8new; +\des+ + List of foreign servers + Name | Owner | Foreign-data wrapper | Access privileges | Type | Version | FDW Options | Description +-------+-----------------------+----------------------+-----------------------------------------+--------+---------+--------------------------------------+------------- + s1 | regress_test_indirect | foo | foreign_data_user=U/foreign_data_user +| | 1.1 | (servername 's1') | + | | | regress_test_role=U/foreign_data_user | | | | + s2 | foreign_data_user | foo | | | 1.1 | (host 'a', dbname 'b') | + s3 | foreign_data_user | foo | | oracle | | ("tns name" 'orcl', port '1521') | + s4 | foreign_data_user | foo | | oracle | | (host 'a', dbname 'b') | + s5 | foreign_data_user | foo | | | 15.0 | | + s6 | foreign_data_user | foo | foreign_data_user=U/foreign_data_user +| | 16.0 | (host 'a', dbname 'b') | + | | | regress_test_role2=U*/foreign_data_user | | | | + s7 | foreign_data_user | foo | | oracle | 17.0 | (host 'a', dbname 'b') | + s8new | foreign_data_user | postgresql | | | | (dbname 'db1', connect_timeout '30') | + t1 | regress_test_role | foo | | | | | + t2 | regress_test_role | foo | | | | | +(10 rows) + +ALTER SERVER s8new RENAME to s8; -- DROP SERVER DROP SERVER nonexistent; -- ERROR ERROR: server "nonexistent" does not exist diff --git a/src/test/regress/sql/foreign_data.sql b/src/test/regress/sql/foreign_data.sql index bfdb32afdc..e99e7079b1 100644 --- a/src/test/regress/sql/foreign_data.sql +++ b/src/test/regress/sql/foreign_data.sql @@ -84,6 +84,10 @@ ALTER FOREIGN DATA WRAPPER foo OPTIONS (ADD e '6'); -- ERROR RESET ROLE; \dew+ +ALTER FOREIGN DATA WRAPPER foo RENAME TO foo1; +\dew+ +ALTER FOREIGN DATA WRAPPER foo1 RENAME TO foo; + -- DROP FOREIGN DATA WRAPPER DROP FOREIGN DATA WRAPPER nonexistent; -- ERROR DROP FOREIGN DATA WRAPPER IF EXISTS nonexistent; @@ -181,6 +185,10 @@ RESET ROLE; DROP ROLE regress_test_indirect; -- ERROR \des+ +ALTER SERVER s8 RENAME to s8new; +\des+ +ALTER SERVER s8new RENAME to s8; + -- DROP SERVER DROP SERVER nonexistent; -- ERROR DROP SERVER IF EXISTS nonexistent;