mirror of
https://github.com/postgres/postgres.git
synced 2025-12-04 12:02:48 +03:00
Add new OID alias type regrole
The new type has the scope of whole the database cluster so it doesn't behave the same as the existing OID alias types which have database scope, concerning object dependency. To avoid confusion constants of the new type are prohibited from appearing where dependencies are made involving it. Also, add a note to the docs about possible MVCC violation and optimization issues, which are general over the all reg* types. Kyotaro Horiguchi
This commit is contained in:
@@ -113,6 +113,8 @@ static const struct typinfo TypInfo[] = {
|
||||
F_REGPROCIN, F_REGPROCOUT},
|
||||
{"regtype", REGTYPEOID, 0, 4, true, 'i', 'p', InvalidOid,
|
||||
F_REGTYPEIN, F_REGTYPEOUT},
|
||||
{"regrole", REGROLEOID, 0, 4, true, 'i', 'p', InvalidOid,
|
||||
F_REGROLEIN, F_REGROLEOUT},
|
||||
{"text", TEXTOID, 0, -1, false, 'i', 'x', DEFAULT_COLLATION_OID,
|
||||
F_TEXTIN, F_TEXTOUT},
|
||||
{"oid", OIDOID, 0, 4, true, 'i', 'p', InvalidOid,
|
||||
|
||||
@@ -1602,6 +1602,16 @@ find_expr_references_walker(Node *node,
|
||||
add_object_address(OCLASS_TSDICT, objoid, 0,
|
||||
context->addrs);
|
||||
break;
|
||||
|
||||
/*
|
||||
* Dependencies for regrole should be shared among all
|
||||
* databases, so explicitly inhibit to have dependencies.
|
||||
*/
|
||||
case REGROLEOID:
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("constant of the type \'regrole\' cannot be used here")));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -2818,7 +2818,7 @@ getObjectDescription(const ObjectAddress *object)
|
||||
case OCLASS_ROLE:
|
||||
{
|
||||
appendStringInfo(&buffer, _("role %s"),
|
||||
GetUserNameFromId(object->objectId));
|
||||
GetUserNameFromId(object->objectId, false));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2884,7 +2884,7 @@ getObjectDescription(const ObjectAddress *object)
|
||||
ReleaseSysCache(tup);
|
||||
|
||||
if (OidIsValid(useid))
|
||||
usename = GetUserNameFromId(useid);
|
||||
usename = GetUserNameFromId(useid, false);
|
||||
else
|
||||
usename = "public";
|
||||
|
||||
@@ -2924,28 +2924,28 @@ getObjectDescription(const ObjectAddress *object)
|
||||
case DEFACLOBJ_RELATION:
|
||||
appendStringInfo(&buffer,
|
||||
_("default privileges on new relations belonging to role %s"),
|
||||
GetUserNameFromId(defacl->defaclrole));
|
||||
GetUserNameFromId(defacl->defaclrole, false));
|
||||
break;
|
||||
case DEFACLOBJ_SEQUENCE:
|
||||
appendStringInfo(&buffer,
|
||||
_("default privileges on new sequences belonging to role %s"),
|
||||
GetUserNameFromId(defacl->defaclrole));
|
||||
GetUserNameFromId(defacl->defaclrole, false));
|
||||
break;
|
||||
case DEFACLOBJ_FUNCTION:
|
||||
appendStringInfo(&buffer,
|
||||
_("default privileges on new functions belonging to role %s"),
|
||||
GetUserNameFromId(defacl->defaclrole));
|
||||
GetUserNameFromId(defacl->defaclrole, false));
|
||||
break;
|
||||
case DEFACLOBJ_TYPE:
|
||||
appendStringInfo(&buffer,
|
||||
_("default privileges on new types belonging to role %s"),
|
||||
GetUserNameFromId(defacl->defaclrole));
|
||||
GetUserNameFromId(defacl->defaclrole, false));
|
||||
break;
|
||||
default:
|
||||
/* shouldn't get here */
|
||||
appendStringInfo(&buffer,
|
||||
_("default privileges belonging to role %s"),
|
||||
GetUserNameFromId(defacl->defaclrole));
|
||||
GetUserNameFromId(defacl->defaclrole, false));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -4214,7 +4214,7 @@ getObjectIdentityParts(const ObjectAddress *object,
|
||||
{
|
||||
char *username;
|
||||
|
||||
username = GetUserNameFromId(object->objectId);
|
||||
username = GetUserNameFromId(object->objectId, false);
|
||||
if (objname)
|
||||
*objname = list_make1(username);
|
||||
appendStringInfoString(&buffer,
|
||||
@@ -4295,7 +4295,7 @@ getObjectIdentityParts(const ObjectAddress *object,
|
||||
ReleaseSysCache(tup);
|
||||
|
||||
if (OidIsValid(useid))
|
||||
usename = GetUserNameFromId(useid);
|
||||
usename = GetUserNameFromId(useid, false);
|
||||
else
|
||||
usename = "public";
|
||||
|
||||
@@ -4339,7 +4339,7 @@ getObjectIdentityParts(const ObjectAddress *object,
|
||||
|
||||
defacl = (Form_pg_default_acl) GETSTRUCT(tup);
|
||||
|
||||
username = GetUserNameFromId(defacl->defaclrole);
|
||||
username = GetUserNameFromId(defacl->defaclrole, false);
|
||||
appendStringInfo(&buffer,
|
||||
"for role %s",
|
||||
quote_identifier(username));
|
||||
|
||||
@@ -4878,7 +4878,7 @@ check_is_member_of_role(Oid member, Oid role)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("must be member of role \"%s\"",
|
||||
GetUserNameFromId(role))));
|
||||
GetUserNameFromId(role, false))));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -263,13 +263,13 @@ namestrcmp(Name name, const char *str)
|
||||
Datum
|
||||
current_user(PG_FUNCTION_ARGS)
|
||||
{
|
||||
PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(GetUserNameFromId(GetUserId()))));
|
||||
PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(GetUserNameFromId(GetUserId(), false))));
|
||||
}
|
||||
|
||||
Datum
|
||||
session_user(PG_FUNCTION_ARGS)
|
||||
{
|
||||
PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(GetUserNameFromId(GetSessionUserId()))));
|
||||
PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(GetUserNameFromId(GetSessionUserId(), false))));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/syscache.h"
|
||||
#include "utils/tqual.h"
|
||||
#include "utils/acl.h"
|
||||
|
||||
static char *format_operator_internal(Oid operator_oid, bool force_qualify);
|
||||
static char *format_procedure_internal(Oid procedure_oid, bool force_qualify);
|
||||
@@ -1553,6 +1554,109 @@ regdictionarysend(PG_FUNCTION_ARGS)
|
||||
return oidsend(fcinfo);
|
||||
}
|
||||
|
||||
/*
|
||||
* regrolein - converts "rolename" to role OID
|
||||
*
|
||||
* We also accept a numeric OID, for symmetry with the output routine.
|
||||
*
|
||||
* '-' signifies unknown (OID 0). In all other cases, the input must
|
||||
* match an existing pg_authid entry.
|
||||
*
|
||||
* This function is not needed in bootstrap mode, so we don't worry about
|
||||
* making it work then.
|
||||
*/
|
||||
Datum
|
||||
regrolein(PG_FUNCTION_ARGS)
|
||||
{
|
||||
char *role_name_or_oid = PG_GETARG_CSTRING(0);
|
||||
Oid result;
|
||||
|
||||
/* '-' ? */
|
||||
if (strcmp(role_name_or_oid, "-") == 0)
|
||||
PG_RETURN_OID(InvalidOid);
|
||||
|
||||
/* Numeric OID? */
|
||||
if (role_name_or_oid[0] >= '0' &&
|
||||
role_name_or_oid[0] <= '9' &&
|
||||
strspn(role_name_or_oid, "0123456789") == strlen(role_name_or_oid))
|
||||
{
|
||||
result = DatumGetObjectId(DirectFunctionCall1(oidin,
|
||||
CStringGetDatum(role_name_or_oid)));
|
||||
PG_RETURN_OID(result);
|
||||
}
|
||||
|
||||
/* Normal case: see if the name matches any pg_authid entry. */
|
||||
result = get_role_oid(role_name_or_oid, false);
|
||||
|
||||
PG_RETURN_OID(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* to_regrole - converts "rolename" to role OID
|
||||
*
|
||||
* If the name is not found, we return NULL.
|
||||
*/
|
||||
Datum
|
||||
to_regrole(PG_FUNCTION_ARGS)
|
||||
{
|
||||
char *role_name = PG_GETARG_CSTRING(0);
|
||||
Oid result;
|
||||
|
||||
result = get_role_oid(role_name, true);
|
||||
|
||||
if (OidIsValid(result))
|
||||
PG_RETURN_OID(result);
|
||||
else
|
||||
PG_RETURN_NULL();
|
||||
}
|
||||
|
||||
/*
|
||||
* regroleout - converts role OID to "role_name"
|
||||
*/
|
||||
Datum
|
||||
regroleout(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Oid roleoid = PG_GETARG_OID(0);
|
||||
char *result;
|
||||
|
||||
|
||||
if (roleoid == InvalidOid)
|
||||
{
|
||||
result = pstrdup("-");
|
||||
PG_RETURN_CSTRING(result);
|
||||
}
|
||||
|
||||
result = GetUserNameFromId(roleoid, true);
|
||||
if (!result)
|
||||
{
|
||||
/* If OID doesn't match any role, return it numerically */
|
||||
result = (char *) palloc(NAMEDATALEN);
|
||||
snprintf(result, NAMEDATALEN, "%u", roleoid);
|
||||
}
|
||||
PG_RETURN_CSTRING(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* regrolerecv - converts external binary format to regrole
|
||||
*/
|
||||
Datum
|
||||
regrolerecv(PG_FUNCTION_ARGS)
|
||||
{
|
||||
/* Exactly the same as oidrecv, so share code */
|
||||
return oidrecv(fcinfo);
|
||||
}
|
||||
|
||||
/*
|
||||
* regrolesend - converts regrole to binary format
|
||||
*/
|
||||
Datum
|
||||
regrolesend(PG_FUNCTION_ARGS)
|
||||
{
|
||||
/* Exactly the same as oidsend, so share code */
|
||||
return oidsend(fcinfo);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* text_regclass: convert text to regclass
|
||||
|
||||
@@ -3619,6 +3619,7 @@ convert_to_scalar(Datum value, Oid valuetypid, double *scaledvalue,
|
||||
case REGTYPEOID:
|
||||
case REGCONFIGOID:
|
||||
case REGDICTIONARYOID:
|
||||
case REGROLEOID:
|
||||
*scaledvalue = convert_numeric_to_scalar(value, valuetypid);
|
||||
*scaledlobound = convert_numeric_to_scalar(lobound, boundstypid);
|
||||
*scaledhibound = convert_numeric_to_scalar(hibound, boundstypid);
|
||||
@@ -3724,6 +3725,7 @@ convert_numeric_to_scalar(Datum value, Oid typid)
|
||||
case REGTYPEOID:
|
||||
case REGCONFIGOID:
|
||||
case REGDICTIONARYOID:
|
||||
case REGROLEOID:
|
||||
/* we can treat OIDs as integers... */
|
||||
return (double) DatumGetObjectId(value);
|
||||
}
|
||||
|
||||
1
src/backend/utils/cache/catcache.c
vendored
1
src/backend/utils/cache/catcache.c
vendored
@@ -150,6 +150,7 @@ GetCCHashEqFuncs(Oid keytype, PGFunction *hashfunc, RegProcedure *eqfunc)
|
||||
case REGTYPEOID:
|
||||
case REGCONFIGOID:
|
||||
case REGDICTIONARYOID:
|
||||
case REGROLEOID:
|
||||
*hashfunc = hashoid;
|
||||
|
||||
*eqfunc = F_OIDEQ;
|
||||
|
||||
@@ -648,23 +648,29 @@ SetCurrentRoleId(Oid roleid, bool is_superuser)
|
||||
|
||||
|
||||
/*
|
||||
* Get user name from user oid
|
||||
* Get user name from user oid, returns NULL for nonexistent roleid if noerr
|
||||
* is true.
|
||||
*/
|
||||
char *
|
||||
GetUserNameFromId(Oid roleid)
|
||||
GetUserNameFromId(Oid roleid, bool noerr)
|
||||
{
|
||||
HeapTuple tuple;
|
||||
char *result;
|
||||
|
||||
tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("invalid role OID: %u", roleid)));
|
||||
|
||||
result = pstrdup(NameStr(((Form_pg_authid) GETSTRUCT(tuple))->rolname));
|
||||
|
||||
ReleaseSysCache(tuple);
|
||||
{
|
||||
if (!noerr)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("invalid role OID: %u", roleid)));
|
||||
result = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = pstrdup(NameStr(((Form_pg_authid) GETSTRUCT(tuple))->rolname));
|
||||
ReleaseSysCache(tuple);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user