Commit fa2952d8 authored by Tom Lane's avatar Tom Lane

Fix missing role dependencies for some schema and type ACLs.

This patch fixes several related cases in which pg_shdepend entries were
never made, or were lost, for references to roles appearing in the ACLs of
schemas and/or types.  While that did no immediate harm, if a referenced
role were later dropped, the drop would be allowed and would leave a
dangling reference in the object's ACL.  That still wasn't a big problem
for normal database usage, but it would cause obscure failures in
subsequent dump/reload or pg_upgrade attempts, taking the form of
attempts to grant privileges to all-numeric role names.  (I think I've
seen field reports matching that symptom, but can't find any right now.)

Several cases are fixed here:

1. ALTER DOMAIN SET/DROP DEFAULT would lose the dependencies for any
existing ACL entries for the domain.  This case is ancient, dating
back as far as we've had pg_shdepend tracking at all.

2. If a default type privilege applies, CREATE TYPE recorded the
ACL properly but forgot to install dependency entries for it.
This dates to the addition of default privileges for types in 9.2.

3. If a default schema privilege applies, CREATE SCHEMA recorded the
ACL properly but forgot to install dependency entries for it.
This dates to the addition of default privileges for schemas in v10
(commit ab89e465).

Another somewhat-related problem is that when creating a relation
rowtype or implicit array type, TypeCreate would apply any available
default type privileges to that type, which we don't really want
since such an object isn't supposed to have privileges of its own.
(You can't, for example, drop such privileges once they've been added
to an array type.)

ab89e465 is also to blame for a race condition in the regression tests:
privileges.sql transiently installed globally-applicable default
privileges on schemas, which sometimes got absorbed into the ACLs of
schemas created by concurrent test scripts.  This should have resulted
in failures when privileges.sql tried to drop the role holding such
privileges; but thanks to the bug fixed here, it instead led to dangling
ACLs in the final state of the regression database.  We'd managed not to
notice that, but it became obvious in the wake of commit da906766, which
allowed the race condition to occur in pg_upgrade tests.

To fix, add a function recordDependencyOnNewAcl to encapsulate what
callers of get_user_default_acl need to do; while the original call
sites got that right via ad-hoc code, none of the later-added ones
have.  Also change GenerateTypeDependencies to generate these
dependencies, which requires adding the typacl to its parameter list.
(That might be annoying if there are any extensions calling that
function directly; but if there are, they're most likely buggy in the
same way as the core callers were, so they need work anyway.)  While
I was at it, I changed GenerateTypeDependencies to accept most of its
parameters in the form of a Form_pg_type pointer, making its parameter
list a bit less unwieldy and mistake-prone.

The test race condition is fixed just by wrapping the addition and
removal of default privileges into a single transaction, so that that
state is never visible externally.  We might eventually prefer to
separate out tests of default privileges into a script that runs by
itself, but that would be a bigger change and would make the tests
run slower overall.

Back-patch relevant parts to all supported branches.

Discussion: https://postgr.es/m/15719.1541725287@sss.pgh.pa.us
parent c670d0fa
...@@ -5445,7 +5445,10 @@ get_default_acl_internal(Oid roleId, Oid nsp_oid, char objtype) ...@@ -5445,7 +5445,10 @@ get_default_acl_internal(Oid roleId, Oid nsp_oid, char objtype)
/* /*
* Get default permissions for newly created object within given schema * Get default permissions for newly created object within given schema
* *
* Returns NULL if built-in system defaults should be used * Returns NULL if built-in system defaults should be used.
*
* If the result is not NULL, caller must call recordDependencyOnNewAcl
* once the OID of the new object is known.
*/ */
Acl * Acl *
get_user_default_acl(ObjectType objtype, Oid ownerId, Oid nsp_oid) get_user_default_acl(ObjectType objtype, Oid ownerId, Oid nsp_oid)
...@@ -5520,6 +5523,30 @@ get_user_default_acl(ObjectType objtype, Oid ownerId, Oid nsp_oid) ...@@ -5520,6 +5523,30 @@ get_user_default_acl(ObjectType objtype, Oid ownerId, Oid nsp_oid)
return result; return result;
} }
/*
* Record dependencies on roles mentioned in a new object's ACL.
*/
void
recordDependencyOnNewAcl(Oid classId, Oid objectId, int32 objsubId,
Oid ownerId, Acl *acl)
{
int nmembers;
Oid *members;
/* Nothing to do if ACL is defaulted */
if (acl == NULL)
return;
/* Extract roles mentioned in ACL */
nmembers = aclmembers(acl, &members);
/* Update the shared dependency ACL info */
updateAclDependencies(classId, objectId, objsubId,
ownerId,
0, NULL,
nmembers, members);
}
/* /*
* Record initial privileges for the top-level object passed in. * Record initial privileges for the top-level object passed in.
* *
......
...@@ -1375,6 +1375,7 @@ heap_create_with_catalog(const char *relname, ...@@ -1375,6 +1375,7 @@ heap_create_with_catalog(const char *relname,
myself.classId = RelationRelationId; myself.classId = RelationRelationId;
myself.objectId = relid; myself.objectId = relid;
myself.objectSubId = 0; myself.objectSubId = 0;
referenced.classId = NamespaceRelationId; referenced.classId = NamespaceRelationId;
referenced.objectId = relnamespace; referenced.objectId = relnamespace;
referenced.objectSubId = 0; referenced.objectSubId = 0;
...@@ -1382,6 +1383,8 @@ heap_create_with_catalog(const char *relname, ...@@ -1382,6 +1383,8 @@ heap_create_with_catalog(const char *relname,
recordDependencyOnOwner(RelationRelationId, relid, ownerid); recordDependencyOnOwner(RelationRelationId, relid, ownerid);
recordDependencyOnNewAcl(RelationRelationId, relid, 0, ownerid, relacl);
recordDependencyOnCurrentExtension(&myself, false); recordDependencyOnCurrentExtension(&myself, false);
if (reloftypeid) if (reloftypeid)
...@@ -1391,18 +1394,6 @@ heap_create_with_catalog(const char *relname, ...@@ -1391,18 +1394,6 @@ heap_create_with_catalog(const char *relname,
referenced.objectSubId = 0; referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
} }
if (relacl != NULL)
{
int nnewmembers;
Oid *newmembers;
nnewmembers = aclmembers(relacl, &newmembers);
updateAclDependencies(RelationRelationId, relid, 0,
ownerid,
0, NULL,
nnewmembers, newmembers);
}
} }
/* Post creation hook for new relation */ /* Post creation hook for new relation */
......
...@@ -100,6 +100,9 @@ NamespaceCreate(const char *nspName, Oid ownerId, bool isTemp) ...@@ -100,6 +100,9 @@ NamespaceCreate(const char *nspName, Oid ownerId, bool isTemp)
/* dependency on owner */ /* dependency on owner */
recordDependencyOnOwner(NamespaceRelationId, nspoid, ownerId); recordDependencyOnOwner(NamespaceRelationId, nspoid, ownerId);
/* dependences on roles mentioned in default ACL */
recordDependencyOnNewAcl(NamespaceRelationId, nspoid, 0, ownerId, nspacl);
/* dependency on extension ... but not for magic temp schemas */ /* dependency on extension ... but not for magic temp schemas */
if (!isTemp) if (!isTemp)
recordDependencyOnCurrentExtension(&myself, false); recordDependencyOnCurrentExtension(&myself, false);
......
...@@ -654,17 +654,9 @@ ProcedureCreate(const char *procedureName, ...@@ -654,17 +654,9 @@ ProcedureCreate(const char *procedureName,
recordDependencyOnOwner(ProcedureRelationId, retval, proowner); recordDependencyOnOwner(ProcedureRelationId, retval, proowner);
/* dependency on any roles mentioned in ACL */ /* dependency on any roles mentioned in ACL */
if (!is_update && proacl != NULL) if (!is_update)
{ recordDependencyOnNewAcl(ProcedureRelationId, retval, 0,
int nnewmembers; proowner, proacl);
Oid *newmembers;
nnewmembers = aclmembers(proacl, &newmembers);
updateAclDependencies(ProcedureRelationId, retval, 0,
proowner,
0, NULL,
nnewmembers, newmembers);
}
/* dependency on extension */ /* dependency on extension */
recordDependencyOnCurrentExtension(&myself, is_update); recordDependencyOnCurrentExtension(&myself, is_update);
......
...@@ -147,23 +147,13 @@ TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId) ...@@ -147,23 +147,13 @@ TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
* Create dependencies. We can/must skip this in bootstrap mode. * Create dependencies. We can/must skip this in bootstrap mode.
*/ */
if (!IsBootstrapProcessingMode()) if (!IsBootstrapProcessingMode())
GenerateTypeDependencies(typeNamespace, GenerateTypeDependencies(typoid,
typoid, (Form_pg_type) GETSTRUCT(tup),
InvalidOid, NULL,
NULL,
0, 0,
ownerId,
F_SHELL_IN,
F_SHELL_OUT,
InvalidOid,
InvalidOid,
InvalidOid,
InvalidOid,
InvalidOid,
InvalidOid,
false, false,
InvalidOid, false,
InvalidOid,
NULL,
false); false);
/* Post creation hook for new shell type */ /* Post creation hook for new shell type */
...@@ -225,14 +215,15 @@ TypeCreate(Oid newTypeOid, ...@@ -225,14 +215,15 @@ TypeCreate(Oid newTypeOid,
{ {
Relation pg_type_desc; Relation pg_type_desc;
Oid typeObjectId; Oid typeObjectId;
bool isDependentType;
bool rebuildDeps = false; bool rebuildDeps = false;
Acl *typacl;
HeapTuple tup; HeapTuple tup;
bool nulls[Natts_pg_type]; bool nulls[Natts_pg_type];
bool replaces[Natts_pg_type]; bool replaces[Natts_pg_type];
Datum values[Natts_pg_type]; Datum values[Natts_pg_type];
NameData name; NameData name;
int i; int i;
Acl *typacl = NULL;
ObjectAddress address; ObjectAddress address;
/* /*
...@@ -320,6 +311,17 @@ TypeCreate(Oid newTypeOid, ...@@ -320,6 +311,17 @@ TypeCreate(Oid newTypeOid,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION), (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("fixed-size types must have storage PLAIN"))); errmsg("fixed-size types must have storage PLAIN")));
/*
* This is a dependent type if it's an implicitly-created array type, or
* if it's a relation rowtype that's not a composite type. For such types
* we'll leave the ACL empty, and we'll skip creating some dependency
* records because there will be a dependency already through the
* depended-on type or relation. (Caution: this is closely intertwined
* with some behavior in GenerateTypeDependencies.)
*/
isDependentType = isImplicitArray ||
(OidIsValid(relationOid) && relationKind != RELKIND_COMPOSITE_TYPE);
/* /*
* initialize arrays needed for heap_form_tuple or heap_modify_tuple * initialize arrays needed for heap_form_tuple or heap_modify_tuple
*/ */
...@@ -379,8 +381,14 @@ TypeCreate(Oid newTypeOid, ...@@ -379,8 +381,14 @@ TypeCreate(Oid newTypeOid,
else else
nulls[Anum_pg_type_typdefault - 1] = true; nulls[Anum_pg_type_typdefault - 1] = true;
typacl = get_user_default_acl(OBJECT_TYPE, ownerId, /*
typeNamespace); * Initialize the type's ACL, too. But dependent types don't get one.
*/
if (isDependentType)
typacl = NULL;
else
typacl = get_user_default_acl(OBJECT_TYPE, ownerId,
typeNamespace);
if (typacl != NULL) if (typacl != NULL)
values[Anum_pg_type_typacl - 1] = PointerGetDatum(typacl); values[Anum_pg_type_typacl - 1] = PointerGetDatum(typacl);
else else
...@@ -462,25 +470,15 @@ TypeCreate(Oid newTypeOid, ...@@ -462,25 +470,15 @@ TypeCreate(Oid newTypeOid,
* Create dependencies. We can/must skip this in bootstrap mode. * Create dependencies. We can/must skip this in bootstrap mode.
*/ */
if (!IsBootstrapProcessingMode()) if (!IsBootstrapProcessingMode())
GenerateTypeDependencies(typeNamespace, GenerateTypeDependencies(typeObjectId,
typeObjectId, (Form_pg_type) GETSTRUCT(tup),
relationOid,
relationKind,
ownerId,
inputProcedure,
outputProcedure,
receiveProcedure,
sendProcedure,
typmodinProcedure,
typmodoutProcedure,
analyzeProcedure,
elementType,
isImplicitArray,
baseType,
typeCollation,
(defaultTypeBin ? (defaultTypeBin ?
stringToNode(defaultTypeBin) : stringToNode(defaultTypeBin) :
NULL), NULL),
typacl,
relationKind,
isImplicitArray,
isDependentType,
rebuildDeps); rebuildDeps);
/* Post creation hook for new type */ /* Post creation hook for new type */
...@@ -499,6 +497,17 @@ TypeCreate(Oid newTypeOid, ...@@ -499,6 +497,17 @@ TypeCreate(Oid newTypeOid,
/* /*
* GenerateTypeDependencies: build the dependencies needed for a type * GenerateTypeDependencies: build the dependencies needed for a type
* *
* Most of what this function needs to know about the type is passed as the
* new pg_type row, typeForm. But we can't get at the varlena fields through
* that, so defaultExpr and typacl are passed separately. (typacl is really
* "Acl *", but we declare it "void *" to avoid including acl.h in pg_type.h.)
*
* relationKind and isImplicitArray aren't visible in the pg_type row either,
* so they're also passed separately.
*
* isDependentType is true if this is an implicit array or relation rowtype;
* that means it doesn't need its own dependencies on owner etc.
*
* If rebuild is true, we remove existing dependencies and rebuild them * If rebuild is true, we remove existing dependencies and rebuild them
* from scratch. This is needed for ALTER TYPE, and also when replacing * from scratch. This is needed for ALTER TYPE, and also when replacing
* a shell type. We don't remove an existing extension dependency, though. * a shell type. We don't remove an existing extension dependency, though.
...@@ -508,23 +517,13 @@ TypeCreate(Oid newTypeOid, ...@@ -508,23 +517,13 @@ TypeCreate(Oid newTypeOid,
* that type will become a member of the extension.) * that type will become a member of the extension.)
*/ */
void void
GenerateTypeDependencies(Oid typeNamespace, GenerateTypeDependencies(Oid typeObjectId,
Oid typeObjectId, Form_pg_type typeForm,
Oid relationOid, /* only for relation rowtypes */
char relationKind, /* ditto */
Oid owner,
Oid inputProcedure,
Oid outputProcedure,
Oid receiveProcedure,
Oid sendProcedure,
Oid typmodinProcedure,
Oid typmodoutProcedure,
Oid analyzeProcedure,
Oid elementType,
bool isImplicitArray,
Oid baseType,
Oid typeCollation,
Node *defaultExpr, Node *defaultExpr,
void *typacl,
char relationKind, /* only for relation rowtypes */
bool isImplicitArray,
bool isDependentType,
bool rebuild) bool rebuild)
{ {
ObjectAddress myself, ObjectAddress myself,
...@@ -542,79 +541,80 @@ GenerateTypeDependencies(Oid typeNamespace, ...@@ -542,79 +541,80 @@ GenerateTypeDependencies(Oid typeNamespace,
myself.objectSubId = 0; myself.objectSubId = 0;
/* /*
* Make dependencies on namespace, owner, extension. * Make dependencies on namespace, owner, ACL, extension.
* *
* For a relation rowtype (that's not a composite type), we should skip * Skip these for a dependent type, since it will have such dependencies
* these because we'll depend on them indirectly through the pg_class * indirectly through its depended-on type or relation.
* entry. Likewise, skip for implicit arrays since we'll depend on them
* through the element type.
*/ */
if ((!OidIsValid(relationOid) || relationKind == RELKIND_COMPOSITE_TYPE) && if (!isDependentType)
!isImplicitArray)
{ {
referenced.classId = NamespaceRelationId; referenced.classId = NamespaceRelationId;
referenced.objectId = typeNamespace; referenced.objectId = typeForm->typnamespace;
referenced.objectSubId = 0; referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
recordDependencyOnOwner(TypeRelationId, typeObjectId, owner); recordDependencyOnOwner(TypeRelationId, typeObjectId,
typeForm->typowner);
recordDependencyOnNewAcl(TypeRelationId, typeObjectId, 0,
typeForm->typowner, typacl);
recordDependencyOnCurrentExtension(&myself, rebuild); recordDependencyOnCurrentExtension(&myself, rebuild);
} }
/* Normal dependencies on the I/O functions */ /* Normal dependencies on the I/O functions */
if (OidIsValid(inputProcedure)) if (OidIsValid(typeForm->typinput))
{ {
referenced.classId = ProcedureRelationId; referenced.classId = ProcedureRelationId;
referenced.objectId = inputProcedure; referenced.objectId = typeForm->typinput;
referenced.objectSubId = 0; referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
} }
if (OidIsValid(outputProcedure)) if (OidIsValid(typeForm->typoutput))
{ {
referenced.classId = ProcedureRelationId; referenced.classId = ProcedureRelationId;
referenced.objectId = outputProcedure; referenced.objectId = typeForm->typoutput;
referenced.objectSubId = 0; referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
} }
if (OidIsValid(receiveProcedure)) if (OidIsValid(typeForm->typreceive))
{ {
referenced.classId = ProcedureRelationId; referenced.classId = ProcedureRelationId;
referenced.objectId = receiveProcedure; referenced.objectId = typeForm->typreceive;
referenced.objectSubId = 0; referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
} }
if (OidIsValid(sendProcedure)) if (OidIsValid(typeForm->typsend))
{ {
referenced.classId = ProcedureRelationId; referenced.classId = ProcedureRelationId;
referenced.objectId = sendProcedure; referenced.objectId = typeForm->typsend;
referenced.objectSubId = 0; referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
} }
if (OidIsValid(typmodinProcedure)) if (OidIsValid(typeForm->typmodin))
{ {
referenced.classId = ProcedureRelationId; referenced.classId = ProcedureRelationId;
referenced.objectId = typmodinProcedure; referenced.objectId = typeForm->typmodin;
referenced.objectSubId = 0; referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
} }
if (OidIsValid(typmodoutProcedure)) if (OidIsValid(typeForm->typmodout))
{ {
referenced.classId = ProcedureRelationId; referenced.classId = ProcedureRelationId;
referenced.objectId = typmodoutProcedure; referenced.objectId = typeForm->typmodout;
referenced.objectSubId = 0; referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
} }
if (OidIsValid(analyzeProcedure)) if (OidIsValid(typeForm->typanalyze))
{ {
referenced.classId = ProcedureRelationId; referenced.classId = ProcedureRelationId;
referenced.objectId = analyzeProcedure; referenced.objectId = typeForm->typanalyze;
referenced.objectSubId = 0; referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
} }
...@@ -628,10 +628,10 @@ GenerateTypeDependencies(Oid typeNamespace, ...@@ -628,10 +628,10 @@ GenerateTypeDependencies(Oid typeNamespace,
* relation is, and not otherwise. And in the latter, of course we get the * relation is, and not otherwise. And in the latter, of course we get the
* opposite effect. * opposite effect.
*/ */
if (OidIsValid(relationOid)) if (OidIsValid(typeForm->typrelid))
{ {
referenced.classId = RelationRelationId; referenced.classId = RelationRelationId;
referenced.objectId = relationOid; referenced.objectId = typeForm->typrelid;
referenced.objectSubId = 0; referenced.objectSubId = 0;
if (relationKind != RELKIND_COMPOSITE_TYPE) if (relationKind != RELKIND_COMPOSITE_TYPE)
...@@ -645,30 +645,31 @@ GenerateTypeDependencies(Oid typeNamespace, ...@@ -645,30 +645,31 @@ GenerateTypeDependencies(Oid typeNamespace,
* dependent on the element type. Otherwise, if it has an element type, * dependent on the element type. Otherwise, if it has an element type,
* the dependency is a normal one. * the dependency is a normal one.
*/ */
if (OidIsValid(elementType)) if (OidIsValid(typeForm->typelem))
{ {
referenced.classId = TypeRelationId; referenced.classId = TypeRelationId;
referenced.objectId = elementType; referenced.objectId = typeForm->typelem;
referenced.objectSubId = 0; referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, recordDependencyOn(&myself, &referenced,
isImplicitArray ? DEPENDENCY_INTERNAL : DEPENDENCY_NORMAL); isImplicitArray ? DEPENDENCY_INTERNAL : DEPENDENCY_NORMAL);
} }
/* Normal dependency from a domain to its base type. */ /* Normal dependency from a domain to its base type. */
if (OidIsValid(baseType)) if (OidIsValid(typeForm->typbasetype))
{ {
referenced.classId = TypeRelationId; referenced.classId = TypeRelationId;
referenced.objectId = baseType; referenced.objectId = typeForm->typbasetype;
referenced.objectSubId = 0; referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
} }
/* Normal dependency from a domain to its collation. */ /* Normal dependency from a domain to its collation. */
/* We know the default collation is pinned, so don't bother recording it */ /* We know the default collation is pinned, so don't bother recording it */
if (OidIsValid(typeCollation) && typeCollation != DEFAULT_COLLATION_OID) if (OidIsValid(typeForm->typcollation) &&
typeForm->typcollation != DEFAULT_COLLATION_OID)
{ {
referenced.classId = CollationRelationId; referenced.classId = CollationRelationId;
referenced.objectId = typeCollation; referenced.objectId = typeForm->typcollation;
referenced.objectSubId = 0; referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
} }
......
...@@ -2179,6 +2179,9 @@ AlterDomainDefault(List *names, Node *defaultRaw) ...@@ -2179,6 +2179,9 @@ AlterDomainDefault(List *names, Node *defaultRaw)
Relation rel; Relation rel;
char *defaultValue; char *defaultValue;
Node *defaultExpr = NULL; /* NULL if no default specified */ Node *defaultExpr = NULL; /* NULL if no default specified */
Acl *typacl;
Datum aclDatum;
bool isNull;
Datum new_record[Natts_pg_type]; Datum new_record[Natts_pg_type];
bool new_record_nulls[Natts_pg_type]; bool new_record_nulls[Natts_pg_type];
bool new_record_repl[Natts_pg_type]; bool new_record_repl[Natts_pg_type];
...@@ -2270,25 +2273,23 @@ AlterDomainDefault(List *names, Node *defaultRaw) ...@@ -2270,25 +2273,23 @@ AlterDomainDefault(List *names, Node *defaultRaw)
CatalogTupleUpdate(rel, &tup->t_self, newtuple); CatalogTupleUpdate(rel, &tup->t_self, newtuple);
/* Must extract ACL for use of GenerateTypeDependencies */
aclDatum = heap_getattr(newtuple, Anum_pg_type_typacl,
RelationGetDescr(rel), &isNull);
if (isNull)
typacl = NULL;
else
typacl = DatumGetAclPCopy(aclDatum);
/* Rebuild dependencies */ /* Rebuild dependencies */
GenerateTypeDependencies(typTup->typnamespace, GenerateTypeDependencies(domainoid,
domainoid, (Form_pg_type) GETSTRUCT(newtuple),
InvalidOid, /* typrelid is n/a */ defaultExpr,
typacl,
0, /* relation kind is n/a */ 0, /* relation kind is n/a */
typTup->typowner,
typTup->typinput,
typTup->typoutput,
typTup->typreceive,
typTup->typsend,
typTup->typmodin,
typTup->typmodout,
typTup->typanalyze,
InvalidOid,
false, /* a domain isn't an implicit array */ false, /* a domain isn't an implicit array */
typTup->typbasetype, false, /* nor is it any kind of dependent type */
typTup->typcollation, true); /* We do need to rebuild dependencies */
defaultExpr,
true); /* Rebuild is true */
InvokeObjectPostAlterHook(TypeRelationId, domainoid, 0); InvokeObjectPostAlterHook(TypeRelationId, domainoid, 0);
......
...@@ -323,23 +323,13 @@ extern ObjectAddress TypeCreate(Oid newTypeOid, ...@@ -323,23 +323,13 @@ extern ObjectAddress TypeCreate(Oid newTypeOid,
bool typeNotNull, bool typeNotNull,
Oid typeCollation); Oid typeCollation);
extern void GenerateTypeDependencies(Oid typeNamespace, extern void GenerateTypeDependencies(Oid typeObjectId,
Oid typeObjectId, Form_pg_type typeForm,
Oid relationOid,
char relationKind,
Oid owner,
Oid inputProcedure,
Oid outputProcedure,
Oid receiveProcedure,
Oid sendProcedure,
Oid typmodinProcedure,
Oid typmodoutProcedure,
Oid analyzeProcedure,
Oid elementType,
bool isImplicitArray,
Oid baseType,
Oid typeCollation,
Node *defaultExpr, Node *defaultExpr,
void *typacl,
char relationKind, /* only for relation rowtypes */
bool isImplicitArray,
bool isDependentType,
bool rebuild); bool rebuild);
extern void RenameTypeInternal(Oid typeOid, const char *newTypeName, extern void RenameTypeInternal(Oid typeOid, const char *newTypeName,
......
...@@ -189,6 +189,8 @@ typedef enum ...@@ -189,6 +189,8 @@ typedef enum
extern Acl *acldefault(ObjectType objtype, Oid ownerId); extern Acl *acldefault(ObjectType objtype, Oid ownerId);
extern Acl *get_user_default_acl(ObjectType objtype, Oid ownerId, extern Acl *get_user_default_acl(ObjectType objtype, Oid ownerId,
Oid nsp_oid); Oid nsp_oid);
extern void recordDependencyOnNewAcl(Oid classId, Oid objectId, int32 objsubId,
Oid ownerId, Acl *acl);
extern Acl *aclupdate(const Acl *old_acl, const AclItem *mod_aip, extern Acl *aclupdate(const Acl *old_acl, const AclItem *mod_aip,
int modechg, Oid ownerId, DropBehavior behavior); int modechg, Oid ownerId, DropBehavior behavior);
......
...@@ -1571,6 +1571,12 @@ SELECT has_table_privilege('regress_priv_user1', 'testns.acltest1', 'INSERT'); - ...@@ -1571,6 +1571,12 @@ SELECT has_table_privilege('regress_priv_user1', 'testns.acltest1', 'INSERT'); -
ALTER DEFAULT PRIVILEGES FOR ROLE regress_priv_user1 REVOKE EXECUTE ON FUNCTIONS FROM public; ALTER DEFAULT PRIVILEGES FOR ROLE regress_priv_user1 REVOKE EXECUTE ON FUNCTIONS FROM public;
ALTER DEFAULT PRIVILEGES IN SCHEMA testns GRANT USAGE ON SCHEMAS TO regress_priv_user2; -- error ALTER DEFAULT PRIVILEGES IN SCHEMA testns GRANT USAGE ON SCHEMAS TO regress_priv_user2; -- error
ERROR: cannot use IN SCHEMA clause when using GRANT/REVOKE ON SCHEMAS ERROR: cannot use IN SCHEMA clause when using GRANT/REVOKE ON SCHEMAS
--
-- Testing blanket default grants is very hazardous since it might change
-- the privileges attached to objects created by concurrent regression tests.
-- To avoid that, be sure to revoke the privileges again before committing.
--
BEGIN;
ALTER DEFAULT PRIVILEGES GRANT USAGE ON SCHEMAS TO regress_priv_user2; ALTER DEFAULT PRIVILEGES GRANT USAGE ON SCHEMAS TO regress_priv_user2;
CREATE SCHEMA testns2; CREATE SCHEMA testns2;
SELECT has_schema_privilege('regress_priv_user2', 'testns2', 'USAGE'); -- yes SELECT has_schema_privilege('regress_priv_user2', 'testns2', 'USAGE'); -- yes
...@@ -1614,6 +1620,7 @@ SELECT has_schema_privilege('regress_priv_user2', 'testns4', 'CREATE'); -- yes ...@@ -1614,6 +1620,7 @@ SELECT has_schema_privilege('regress_priv_user2', 'testns4', 'CREATE'); -- yes
(1 row) (1 row)
ALTER DEFAULT PRIVILEGES REVOKE ALL ON SCHEMAS FROM regress_priv_user2; ALTER DEFAULT PRIVILEGES REVOKE ALL ON SCHEMAS FROM regress_priv_user2;
COMMIT;
CREATE SCHEMA testns5; CREATE SCHEMA testns5;
SELECT has_schema_privilege('regress_priv_user2', 'testns5', 'USAGE'); -- no SELECT has_schema_privilege('regress_priv_user2', 'testns5', 'USAGE'); -- no
has_schema_privilege has_schema_privilege
......
...@@ -935,6 +935,13 @@ ALTER DEFAULT PRIVILEGES FOR ROLE regress_priv_user1 REVOKE EXECUTE ON FUNCTIONS ...@@ -935,6 +935,13 @@ ALTER DEFAULT PRIVILEGES FOR ROLE regress_priv_user1 REVOKE EXECUTE ON FUNCTIONS
ALTER DEFAULT PRIVILEGES IN SCHEMA testns GRANT USAGE ON SCHEMAS TO regress_priv_user2; -- error ALTER DEFAULT PRIVILEGES IN SCHEMA testns GRANT USAGE ON SCHEMAS TO regress_priv_user2; -- error
--
-- Testing blanket default grants is very hazardous since it might change
-- the privileges attached to objects created by concurrent regression tests.
-- To avoid that, be sure to revoke the privileges again before committing.
--
BEGIN;
ALTER DEFAULT PRIVILEGES GRANT USAGE ON SCHEMAS TO regress_priv_user2; ALTER DEFAULT PRIVILEGES GRANT USAGE ON SCHEMAS TO regress_priv_user2;
CREATE SCHEMA testns2; CREATE SCHEMA testns2;
...@@ -958,6 +965,8 @@ SELECT has_schema_privilege('regress_priv_user2', 'testns4', 'CREATE'); -- yes ...@@ -958,6 +965,8 @@ SELECT has_schema_privilege('regress_priv_user2', 'testns4', 'CREATE'); -- yes
ALTER DEFAULT PRIVILEGES REVOKE ALL ON SCHEMAS FROM regress_priv_user2; ALTER DEFAULT PRIVILEGES REVOKE ALL ON SCHEMAS FROM regress_priv_user2;
COMMIT;
CREATE SCHEMA testns5; CREATE SCHEMA testns5;
SELECT has_schema_privilege('regress_priv_user2', 'testns5', 'USAGE'); -- no SELECT has_schema_privilege('regress_priv_user2', 'testns5', 'USAGE'); -- no
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment