Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 50533a6

Browse files
committed
Support comments on FOREIGN DATA WRAPPER and SERVER objects.
This mostly involves making it work with the objectaddress.c framework, which does most of the heavy lifting. In that vein, change GetForeignDataWrapperOidByName to get_foreign_data_wrapper_oid and GetForeignServerOidByName to get_foreign_server_oid, to match the pattern we use for other object types. Robert Haas and Shigeru Hanada
1 parent 7fcc75d commit 50533a6

File tree

11 files changed

+124
-55
lines changed

11 files changed

+124
-55
lines changed

doc/src/sgml/ref/comment.sgml

+2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ COMMENT ON
3333
DATABASE <replaceable class="PARAMETER">object_name</replaceable> |
3434
DOMAIN <replaceable class="PARAMETER">object_name</replaceable> |
3535
EXTENSION <replaceable class="PARAMETER">object_name</replaceable> |
36+
FOREIGN DATA WRAPPER <replaceable class="PARAMETER">object_name</replaceable> |
3637
FOREIGN TABLE <replaceable class="PARAMETER">object_name</replaceable> |
3738
FUNCTION <replaceable class="PARAMETER">function_name</replaceable> ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) |
3839
INDEX <replaceable class="PARAMETER">object_name</replaceable> |
@@ -45,6 +46,7 @@ COMMENT ON
4546
RULE <replaceable class="PARAMETER">rule_name</replaceable> ON <replaceable class="PARAMETER">table_name</replaceable> |
4647
SCHEMA <replaceable class="PARAMETER">object_name</replaceable> |
4748
SEQUENCE <replaceable class="PARAMETER">object_name</replaceable> |
49+
SERVER <replaceable class="PARAMETER">object_name</replaceable> |
4850
TABLESPACE <replaceable class="PARAMETER">object_name</replaceable> |
4951
TEXT SEARCH CONFIGURATION <replaceable class="PARAMETER">object_name</replaceable> |
5052
TEXT SEARCH DICTIONARY <replaceable class="PARAMETER">object_name</replaceable> |

src/backend/catalog/aclchk.c

+29-2
Original file line numberDiff line numberDiff line change
@@ -683,7 +683,7 @@ objectNamesToOids(GrantObjectType objtype, List *objnames)
683683
foreach(cell, objnames)
684684
{
685685
char *fdwname = strVal(lfirst(cell));
686-
Oid fdwid = GetForeignDataWrapperOidByName(fdwname, false);
686+
Oid fdwid = get_foreign_data_wrapper_oid(fdwname, false);
687687

688688
objects = lappend_oid(objects, fdwid);
689689
}
@@ -692,7 +692,7 @@ objectNamesToOids(GrantObjectType objtype, List *objnames)
692692
foreach(cell, objnames)
693693
{
694694
char *srvname = strVal(lfirst(cell));
695-
Oid srvid = GetForeignServerOidByName(srvname, false);
695+
Oid srvid = get_foreign_server_oid(srvname, false);
696696

697697
objects = lappend_oid(objects, srvid);
698698
}
@@ -4588,6 +4588,33 @@ pg_ts_config_ownercheck(Oid cfg_oid, Oid roleid)
45884588
return has_privs_of_role(roleid, ownerId);
45894589
}
45904590

4591+
/*
4592+
* Ownership check for a foreign-data wrapper (specified by OID).
4593+
*/
4594+
bool
4595+
pg_foreign_data_wrapper_ownercheck(Oid srv_oid, Oid roleid)
4596+
{
4597+
HeapTuple tuple;
4598+
Oid ownerId;
4599+
4600+
/* Superusers bypass all permission checking. */
4601+
if (superuser_arg(roleid))
4602+
return true;
4603+
4604+
tuple = SearchSysCache1(FOREIGNDATAWRAPPEROID, ObjectIdGetDatum(srv_oid));
4605+
if (!HeapTupleIsValid(tuple))
4606+
ereport(ERROR,
4607+
(errcode(ERRCODE_UNDEFINED_OBJECT),
4608+
errmsg("foreign-data wrapper with OID %u does not exist",
4609+
srv_oid)));
4610+
4611+
ownerId = ((Form_pg_foreign_data_wrapper) GETSTRUCT(tuple))->fdwowner;
4612+
4613+
ReleaseSysCache(tuple);
4614+
4615+
return has_privs_of_role(roleid, ownerId);
4616+
}
4617+
45914618
/*
45924619
* Ownership check for a foreign server (specified by OID).
45934620
*/

src/backend/catalog/objectaddress.c

+32-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
#include "catalog/pg_conversion.h"
3131
#include "catalog/pg_database.h"
3232
#include "catalog/pg_extension.h"
33+
#include "catalog/pg_foreign_data_wrapper.h"
34+
#include "catalog/pg_foreign_server.h"
3335
#include "catalog/pg_language.h"
3436
#include "catalog/pg_largeobject.h"
3537
#include "catalog/pg_largeobject_metadata.h"
@@ -52,6 +54,7 @@
5254
#include "commands/proclang.h"
5355
#include "commands/tablespace.h"
5456
#include "commands/trigger.h"
57+
#include "foreign/foreign.h"
5558
#include "libpq/be-fsstubs.h"
5659
#include "miscadmin.h"
5760
#include "nodes/makefuncs.h"
@@ -140,6 +143,8 @@ get_object_address(ObjectType objtype, List *objname, List *objargs,
140143
case OBJECT_ROLE:
141144
case OBJECT_SCHEMA:
142145
case OBJECT_LANGUAGE:
146+
case OBJECT_FDW:
147+
case OBJECT_FOREIGN_SERVER:
143148
address = get_object_address_unqualified(objtype, objname);
144149
break;
145150
case OBJECT_TYPE:
@@ -295,6 +300,12 @@ get_object_address_unqualified(ObjectType objtype, List *qualname)
295300
case OBJECT_LANGUAGE:
296301
msg = gettext_noop("language name cannot be qualified");
297302
break;
303+
case OBJECT_FDW:
304+
msg = gettext_noop("foreign-data wrapper name cannot be qualified");
305+
break;
306+
case OBJECT_FOREIGN_SERVER:
307+
msg = gettext_noop("server name cannot be qualified");
308+
break;
298309
default:
299310
elog(ERROR, "unrecognized objtype: %d", (int) objtype);
300311
msg = NULL; /* placate compiler */
@@ -340,6 +351,16 @@ get_object_address_unqualified(ObjectType objtype, List *qualname)
340351
address.objectId = get_language_oid(name, false);
341352
address.objectSubId = 0;
342353
break;
354+
case OBJECT_FDW:
355+
address.classId = ForeignDataWrapperRelationId;
356+
address.objectId = get_foreign_data_wrapper_oid(name, false);
357+
address.objectSubId = 0;
358+
break;
359+
case OBJECT_FOREIGN_SERVER:
360+
address.classId = ForeignServerRelationId;
361+
address.objectId = get_foreign_server_oid(name, false);
362+
address.objectSubId = 0;
363+
break;
343364
default:
344365
elog(ERROR, "unrecognized objtype: %d", (int) objtype);
345366
/* placate compiler, which doesn't know elog won't return */
@@ -655,6 +676,12 @@ object_exists(ObjectAddress address)
655676
case CastRelationId:
656677
indexoid = CastOidIndexId;
657678
break;
679+
case ForeignDataWrapperRelationId:
680+
cache = FOREIGNDATAWRAPPEROID;
681+
break;
682+
case ForeignServerRelationId:
683+
cache = FOREIGNSERVEROID;
684+
break;
658685
case TSParserRelationId:
659686
cache = TSPARSEROID;
660687
break;
@@ -758,6 +785,11 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
758785
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_EXTENSION,
759786
NameListToString(objname));
760787
break;
788+
case OBJECT_FDW:
789+
if (!pg_foreign_data_wrapper_ownercheck(address.objectId, roleid))
790+
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_FDW,
791+
NameListToString(objname));
792+
break;
761793
case OBJECT_FOREIGN_SERVER:
762794
if (!pg_foreign_server_ownercheck(address.objectId, roleid))
763795
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_FOREIGN_SERVER,
@@ -838,7 +870,6 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
838870
errmsg("must have CREATEROLE privilege")));
839871
}
840872
break;
841-
case OBJECT_FDW:
842873
case OBJECT_TSPARSER:
843874
case OBJECT_TSTEMPLATE:
844875
/* We treat these object types as being owned by superusers */

src/backend/commands/foreigncmds.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -686,7 +686,7 @@ RemoveForeignDataWrapper(DropFdwStmt *stmt)
686686
Oid fdwId;
687687
ObjectAddress object;
688688

689-
fdwId = GetForeignDataWrapperOidByName(stmt->fdwname, true);
689+
fdwId = get_foreign_data_wrapper_oid(stmt->fdwname, true);
690690

691691
if (!superuser())
692692
ereport(ERROR,
@@ -959,7 +959,7 @@ RemoveForeignServer(DropForeignServerStmt *stmt)
959959
Oid srvId;
960960
ObjectAddress object;
961961

962-
srvId = GetForeignServerOidByName(stmt->servername, true);
962+
srvId = get_foreign_server_oid(stmt->servername, true);
963963

964964
if (!OidIsValid(srvId))
965965
{

src/backend/foreign/foreign.c

+41-41
Original file line numberDiff line numberDiff line change
@@ -79,26 +79,6 @@ GetForeignDataWrapper(Oid fdwid)
7979
}
8080

8181

82-
/*
83-
* GetForeignDataWrapperOidByName - look up the foreign-data wrapper
84-
* OID by name.
85-
*/
86-
Oid
87-
GetForeignDataWrapperOidByName(const char *fdwname, bool missing_ok)
88-
{
89-
Oid fdwId;
90-
91-
fdwId = GetSysCacheOid1(FOREIGNDATAWRAPPERNAME, CStringGetDatum(fdwname));
92-
93-
if (!OidIsValid(fdwId) && !missing_ok)
94-
ereport(ERROR,
95-
(errcode(ERRCODE_UNDEFINED_OBJECT),
96-
errmsg("foreign-data wrapper \"%s\" does not exist",
97-
fdwname)));
98-
99-
return fdwId;
100-
}
101-
10282

10383
/*
10484
* GetForeignDataWrapperByName - look up the foreign-data wrapper
@@ -107,7 +87,7 @@ GetForeignDataWrapperOidByName(const char *fdwname, bool missing_ok)
10787
ForeignDataWrapper *
10888
GetForeignDataWrapperByName(const char *fdwname, bool missing_ok)
10989
{
110-
Oid fdwId = GetForeignDataWrapperOidByName(fdwname, missing_ok);
90+
Oid fdwId = get_foreign_data_wrapper_oid(fdwname, missing_ok);
11191

11292
if (!OidIsValid(fdwId))
11393
return NULL;
@@ -171,32 +151,13 @@ GetForeignServer(Oid serverid)
171151
}
172152

173153

174-
/*
175-
* GetForeignServerByName - look up the foreign server oid by name.
176-
*/
177-
Oid
178-
GetForeignServerOidByName(const char *srvname, bool missing_ok)
179-
{
180-
Oid serverid;
181-
182-
serverid = GetSysCacheOid1(FOREIGNSERVERNAME, CStringGetDatum(srvname));
183-
184-
if (!OidIsValid(serverid) && !missing_ok)
185-
ereport(ERROR,
186-
(errcode(ERRCODE_UNDEFINED_OBJECT),
187-
errmsg("server \"%s\" does not exist", srvname)));
188-
189-
return serverid;
190-
}
191-
192-
193154
/*
194155
* GetForeignServerByName - look up the foreign server definition by name.
195156
*/
196157
ForeignServer *
197158
GetForeignServerByName(const char *srvname, bool missing_ok)
198159
{
199-
Oid serverid = GetForeignServerOidByName(srvname, missing_ok);
160+
Oid serverid = get_foreign_server_oid(srvname, missing_ok);
200161

201162
if (!OidIsValid(serverid))
202163
return NULL;
@@ -538,3 +499,42 @@ postgresql_fdw_validator(PG_FUNCTION_ARGS)
538499

539500
PG_RETURN_BOOL(true);
540501
}
502+
503+
/*
504+
* get_foreign_data_wrapper_oid - given a FDW name, look up the OID
505+
*
506+
* If missing_ok is false, throw an error if name not found. If true, just
507+
* return InvalidOid.
508+
*/
509+
Oid
510+
get_foreign_data_wrapper_oid(const char *fdwname, bool missing_ok)
511+
{
512+
Oid oid;
513+
514+
oid = GetSysCacheOid1(FOREIGNDATAWRAPPERNAME, CStringGetDatum(fdwname));
515+
if (!OidIsValid(oid) && !missing_ok)
516+
ereport(ERROR,
517+
(errcode(ERRCODE_UNDEFINED_OBJECT),
518+
errmsg("foreign-data wrapper \"%s\" does not exist",
519+
fdwname)));
520+
return oid;
521+
}
522+
523+
/*
524+
* get_foreign_server_oid - given a FDW name, look up the OID
525+
*
526+
* If missing_ok is false, throw an error if name not found. If true, just
527+
* return InvalidOid.
528+
*/
529+
Oid
530+
get_foreign_server_oid(const char *servername, bool missing_ok)
531+
{
532+
Oid oid;
533+
534+
oid = GetSysCacheOid1(FOREIGNSERVERNAME, CStringGetDatum(servername));
535+
if (!OidIsValid(oid) && !missing_ok)
536+
ereport(ERROR,
537+
(errcode(ERRCODE_UNDEFINED_OBJECT),
538+
errmsg("server \"%s\" does not exist", servername)));
539+
return oid;
540+
}

src/backend/parser/gram.y

+8-5
Original file line numberDiff line numberDiff line change
@@ -4787,11 +4787,12 @@ opt_restart_seqs:
47874787
* the object associated with the comment. The form of the statement is:
47884788
*
47894789
* COMMENT ON [ [ DATABASE | DOMAIN | INDEX | SEQUENCE | TABLE | TYPE | VIEW |
4790-
* COLLATION | CONVERSION | LANGUAGE | OPERATOR CLASS | LARGE OBJECT |
4791-
* CAST | COLUMN | SCHEMA | TABLESPACE | EXTENSION | ROLE |
4792-
* TEXT SEARCH PARSER | TEXT SEARCH DICTIONARY |
4793-
* TEXT SEARCH TEMPLATE | TEXT SEARCH CONFIGURATION |
4794-
* FOREIGN TABLE ] <objname> |
4790+
* COLLATION | CONVERSION | LANGUAGE | OPERATOR CLASS |
4791+
* LARGE OBJECT | CAST | COLUMN | SCHEMA | TABLESPACE |
4792+
* EXTENSION | ROLE | TEXT SEARCH PARSER |
4793+
* TEXT SEARCH DICTIONARY | TEXT SEARCH TEMPLATE |
4794+
* TEXT SEARCH CONFIGURATION | FOREIGN TABLE |
4795+
* FOREIGN DATA WRAPPER | SERVER ] <objname> |
47954796
* AGGREGATE <aggname> (arg1, ...) |
47964797
* FUNCTION <funcname> (arg1, arg2, ...) |
47974798
* OPERATOR <op> (leftoperand_typ, rightoperand_typ) |
@@ -4971,6 +4972,8 @@ comment_type:
49714972
| EXTENSION { $$ = OBJECT_EXTENSION; }
49724973
| ROLE { $$ = OBJECT_ROLE; }
49734974
| FOREIGN TABLE { $$ = OBJECT_FOREIGN_TABLE; }
4975+
| SERVER { $$ = OBJECT_FOREIGN_SERVER; }
4976+
| FOREIGN DATA_P WRAPPER { $$ = OBJECT_FDW; }
49744977
;
49754978

49764979
comment_text:

src/backend/utils/adt/acl.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -3162,7 +3162,7 @@ convert_foreign_data_wrapper_name(text *fdwname)
31623162
{
31633163
char *fdwstr = text_to_cstring(fdwname);
31643164

3165-
return GetForeignDataWrapperOidByName(fdwstr, false);
3165+
return get_foreign_data_wrapper_oid(fdwstr, false);
31663166
}
31673167

31683168
/*
@@ -3928,7 +3928,7 @@ convert_server_name(text *servername)
39283928
{
39293929
char *serverstr = text_to_cstring(servername);
39303930

3931-
return GetForeignServerOidByName(serverstr, false);
3931+
return get_foreign_server_oid(serverstr, false);
39323932
}
39333933

39343934
/*

src/include/foreign/foreign.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,13 @@ typedef struct ForeignTable
7070

7171
extern ForeignServer *GetForeignServer(Oid serverid);
7272
extern ForeignServer *GetForeignServerByName(const char *name, bool missing_ok);
73-
extern Oid GetForeignServerOidByName(const char *name, bool missing_ok);
7473
extern UserMapping *GetUserMapping(Oid userid, Oid serverid);
7574
extern ForeignDataWrapper *GetForeignDataWrapper(Oid fdwid);
7675
extern ForeignDataWrapper *GetForeignDataWrapperByName(const char *name,
7776
bool missing_ok);
78-
extern Oid GetForeignDataWrapperOidByName(const char *name, bool missing_ok);
7977
extern ForeignTable *GetForeignTable(Oid relid);
8078

79+
extern Oid get_foreign_data_wrapper_oid(const char *fdwname, bool missing_ok);
80+
extern Oid get_foreign_server_oid(const char *servername, bool missing_ok);
81+
8182
#endif /* FOREIGN_H */

src/include/utils/acl.h

+1
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,7 @@ extern bool pg_collation_ownercheck(Oid coll_oid, Oid roleid);
315315
extern bool pg_conversion_ownercheck(Oid conv_oid, Oid roleid);
316316
extern bool pg_ts_dict_ownercheck(Oid dict_oid, Oid roleid);
317317
extern bool pg_ts_config_ownercheck(Oid cfg_oid, Oid roleid);
318+
extern bool pg_foreign_data_wrapper_ownercheck(Oid srv_oid, Oid roleid);
318319
extern bool pg_foreign_server_ownercheck(Oid srv_oid, Oid roleid);
319320
extern bool pg_extension_ownercheck(Oid ext_oid, Oid roleid);
320321
extern bool has_createrole_privilege(Oid roleid);

src/test/regress/expected/foreign_data.out

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ CREATE ROLE regress_test_role_super SUPERUSER;
1414
CREATE ROLE regress_test_indirect;
1515
CREATE ROLE unprivileged_role;
1616
CREATE FOREIGN DATA WRAPPER dummy;
17+
COMMENT ON FOREIGN DATA WRAPPER dummy IS 'useless';
1718
CREATE FOREIGN DATA WRAPPER postgresql VALIDATOR postgresql_fdw_validator;
1819
-- At this point we should have 2 built-in wrappers and no servers.
1920
SELECT fdwname, fdwhandler::regproc, fdwvalidator::regproc, fdwoptions FROM pg_foreign_data_wrapper ORDER BY 1, 2, 3;
@@ -211,6 +212,7 @@ DROP ROLE regress_test_role_super;
211212

212213
CREATE FOREIGN DATA WRAPPER foo;
213214
CREATE SERVER s1 FOREIGN DATA WRAPPER foo;
215+
COMMENT ON SERVER s1 IS 'foreign server';
214216
CREATE USER MAPPING FOR current_user SERVER s1;
215217
\dew+
216218
List of foreign-data wrappers

src/test/regress/sql/foreign_data.sql

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ CREATE ROLE regress_test_indirect;
2121
CREATE ROLE unprivileged_role;
2222

2323
CREATE FOREIGN DATA WRAPPER dummy;
24+
COMMENT ON FOREIGN DATA WRAPPER dummy IS 'useless';
2425
CREATE FOREIGN DATA WRAPPER postgresql VALIDATOR postgresql_fdw_validator;
2526

2627
-- At this point we should have 2 built-in wrappers and no servers.
@@ -99,6 +100,7 @@ DROP ROLE regress_test_role_super;
99100

100101
CREATE FOREIGN DATA WRAPPER foo;
101102
CREATE SERVER s1 FOREIGN DATA WRAPPER foo;
103+
COMMENT ON SERVER s1 IS 'foreign server';
102104
CREATE USER MAPPING FOR current_user SERVER s1;
103105
\dew+
104106
\des+

0 commit comments

Comments
 (0)