aboutsummaryrefslogtreecommitdiff
path: root/src/backend/catalog/aclchk.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/catalog/aclchk.c')
-rw-r--r--src/backend/catalog/aclchk.c101
1 files changed, 88 insertions, 13 deletions
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index 01105aae1e6..e07db507c09 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -272,6 +272,9 @@ restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs,
case ACL_KIND_FOREIGN_SERVER:
whole_mask = ACL_ALL_RIGHTS_FOREIGN_SERVER;
break;
+ case ACL_KIND_FOREIGN_TABLE:
+ whole_mask = ACL_ALL_RIGHTS_FOREIGN_TABLE;
+ break;
default:
elog(ERROR, "unrecognized object kind: %d", objkind);
/* not reached, but keep compiler quiet */
@@ -475,6 +478,10 @@ ExecuteGrantStmt(GrantStmt *stmt)
all_privileges = ACL_ALL_RIGHTS_FOREIGN_SERVER;
errormsg = gettext_noop("invalid privilege type %s for foreign server");
break;
+ case ACL_OBJECT_FOREIGN_TABLE:
+ all_privileges = ACL_ALL_RIGHTS_FOREIGN_TABLE;
+ errormsg = gettext_noop("invalid privilege type %s for foreign table");
+ break;
default:
elog(ERROR, "unrecognized GrantStmt.objtype: %d",
(int) stmt->objtype);
@@ -545,6 +552,7 @@ ExecGrantStmt_oids(InternalGrant *istmt)
{
case ACL_OBJECT_RELATION:
case ACL_OBJECT_SEQUENCE:
+ case ACL_OBJECT_FOREIGN_TABLE:
ExecGrant_Relation(istmt);
break;
case ACL_OBJECT_DATABASE:
@@ -594,6 +602,7 @@ objectNamesToOids(GrantObjectType objtype, List *objnames)
{
case ACL_OBJECT_RELATION:
case ACL_OBJECT_SEQUENCE:
+ case ACL_OBJECT_FOREIGN_TABLE:
foreach(cell, objnames)
{
RangeVar *relvar = (RangeVar *) lfirst(cell);
@@ -718,11 +727,13 @@ objectsInSchemaToOids(GrantObjectType objtype, List *nspnames)
switch (objtype)
{
case ACL_OBJECT_RELATION:
- /* Process both regular tables and views */
+ /* Process regular tables, views and foreign tables */
objs = getRelationsInNamespace(namespaceId, RELKIND_RELATION);
objects = list_concat(objects, objs);
objs = getRelationsInNamespace(namespaceId, RELKIND_VIEW);
objects = list_concat(objects, objs);
+ objs = getRelationsInNamespace(namespaceId, RELKIND_FOREIGN_TABLE);
+ objects = list_concat(objects, objs);
break;
case ACL_OBJECT_SEQUENCE:
objs = getRelationsInNamespace(namespaceId, RELKIND_SEQUENCE);
@@ -1689,11 +1700,21 @@ ExecGrant_Relation(InternalGrant *istmt)
errmsg("\"%s\" is not a sequence",
NameStr(pg_class_tuple->relname))));
- /* Adjust the default permissions based on whether it is a sequence */
+ /* Used GRANT FOREIGN TABLE on a non-foreign-table? */
+ if (istmt->objtype == ACL_OBJECT_FOREIGN_TABLE &&
+ pg_class_tuple->relkind != RELKIND_FOREIGN_TABLE)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is not a foreign table",
+ NameStr(pg_class_tuple->relname))));
+
+ /* Adjust the default permissions based on object type */
if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
{
if (pg_class_tuple->relkind == RELKIND_SEQUENCE)
this_privileges = ACL_ALL_RIGHTS_SEQUENCE;
+ else if (pg_class_tuple->relkind == RELKIND_FOREIGN_TABLE)
+ this_privileges = ACL_ALL_RIGHTS_FOREIGN_TABLE;
else
this_privileges = ACL_ALL_RIGHTS_RELATION;
}
@@ -1729,6 +1750,16 @@ ExecGrant_Relation(InternalGrant *istmt)
this_privileges &= (AclMode) ACL_ALL_RIGHTS_SEQUENCE;
}
}
+ else if (pg_class_tuple->relkind == RELKIND_FOREIGN_TABLE)
+ {
+ if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_FOREIGN_TABLE))
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_GRANT_OPERATION),
+ errmsg("foreign table \"%s\" only supports SELECT privileges",
+ NameStr(pg_class_tuple->relname))));
+ }
+ }
else
{
if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_RELATION))
@@ -1781,9 +1812,18 @@ ExecGrant_Relation(InternalGrant *istmt)
&isNull);
if (isNull)
{
- old_acl = acldefault(pg_class_tuple->relkind == RELKIND_SEQUENCE ?
- ACL_OBJECT_SEQUENCE : ACL_OBJECT_RELATION,
- ownerId);
+ switch (pg_class_tuple->relkind)
+ {
+ case RELKIND_SEQUENCE:
+ old_acl = acldefault(ACL_OBJECT_SEQUENCE, ownerId);
+ break;
+ case RELKIND_FOREIGN_TABLE:
+ old_acl = acldefault(ACL_OBJECT_FOREIGN_TABLE, ownerId);
+ break;
+ default:
+ old_acl = acldefault(ACL_OBJECT_RELATION, ownerId);
+ break;
+ }
/* There are no old member roles according to the catalogs */
noldmembers = 0;
oldmembers = NULL;
@@ -1812,12 +1852,26 @@ ExecGrant_Relation(InternalGrant *istmt)
bool replaces[Natts_pg_class];
int nnewmembers;
Oid *newmembers;
+ AclObjectKind aclkind;
/* Determine ID to do the grant as, and available grant options */
select_best_grantor(GetUserId(), this_privileges,
old_acl, ownerId,
&grantorId, &avail_goptions);
+ switch (pg_class_tuple->relkind)
+ {
+ case RELKIND_SEQUENCE:
+ aclkind = ACL_KIND_SEQUENCE;
+ break;
+ case RELKIND_FOREIGN_TABLE:
+ aclkind = ACL_KIND_FOREIGN_TABLE;
+ break;
+ default:
+ aclkind = ACL_KIND_CLASS;
+ break;
+ }
+
/*
* Restrict the privileges to what we can actually grant, and emit
* the standards-mandated warning and error messages.
@@ -1825,9 +1879,7 @@ ExecGrant_Relation(InternalGrant *istmt)
this_privileges =
restrict_and_check_grant(istmt->is_grant, avail_goptions,
istmt->all_privs, this_privileges,
- relOid, grantorId,
- pg_class_tuple->relkind == RELKIND_SEQUENCE
- ? ACL_KIND_SEQUENCE : ACL_KIND_CLASS,
+ relOid, grantorId, aclkind,
NameStr(pg_class_tuple->relname),
0, NULL);
@@ -1909,6 +1961,16 @@ ExecGrant_Relation(InternalGrant *istmt)
this_privileges &= (AclMode) ACL_SELECT;
}
+ else if (pg_class_tuple->relkind == RELKIND_FOREIGN_TABLE &&
+ this_privileges & ~((AclMode) ACL_SELECT))
+ {
+ /* Foreign tables have the same restriction as sequences. */
+ ereport(WARNING,
+ (errcode(ERRCODE_INVALID_GRANT_OPERATION),
+ errmsg("foreign table \"%s\" only supports SELECT column privileges",
+ NameStr(pg_class_tuple->relname))));
+ this_privileges &= (AclMode) ACL_SELECT;
+ }
expand_col_privileges(col_privs->cols, relOid,
this_privileges,
@@ -3080,7 +3142,9 @@ static const char *const no_priv_msg[MAX_ACL_KIND] =
/* ACL_KIND_FDW */
gettext_noop("permission denied for foreign-data wrapper %s"),
/* ACL_KIND_FOREIGN_SERVER */
- gettext_noop("permission denied for foreign server %s")
+ gettext_noop("permission denied for foreign server %s"),
+ /* ACL_KIND_FOREIGN_TABLE */
+ gettext_noop("permission denied for foreign table %s"),
};
static const char *const not_owner_msg[MAX_ACL_KIND] =
@@ -3120,7 +3184,9 @@ static const char *const not_owner_msg[MAX_ACL_KIND] =
/* ACL_KIND_FDW */
gettext_noop("must be owner of foreign-data wrapper %s"),
/* ACL_KIND_FOREIGN_SERVER */
- gettext_noop("must be owner of foreign server %s")
+ gettext_noop("must be owner of foreign server %s"),
+ /* ACL_KIND_FOREIGN_TABLE */
+ gettext_noop("must be owner of foreign table %s"),
};
@@ -3410,9 +3476,18 @@ pg_class_aclmask(Oid table_oid, Oid roleid,
if (isNull)
{
/* No ACL, so build default ACL */
- acl = acldefault(classForm->relkind == RELKIND_SEQUENCE ?
- ACL_OBJECT_SEQUENCE : ACL_OBJECT_RELATION,
- ownerId);
+ switch (classForm->relkind)
+ {
+ case RELKIND_SEQUENCE:
+ acl = acldefault(ACL_OBJECT_SEQUENCE, ownerId);
+ break;
+ case RELKIND_FOREIGN_TABLE:
+ acl = acldefault(ACL_OBJECT_FOREIGN_TABLE, ownerId);
+ break;
+ default:
+ acl = acldefault(ACL_OBJECT_RELATION, ownerId);
+ break;
+ }
aclDatum = (Datum) 0;
}
else