Skip to content

Commit

Permalink
Add new OID alias type regrole
Browse files Browse the repository at this point in the history
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

-- OPENGPDB additions.

I have omitted catalog changes provides within this commit for ABI compat sake.
This is not disallows use of them. One, if need, could use them with help of
extension.

Kirill Reshke
  • Loading branch information
adunstan authored and reshke committed Nov 14, 2024
1 parent ec3ecff commit 2f863c0
Show file tree
Hide file tree
Showing 19 changed files with 224 additions and 31 deletions.
2 changes: 1 addition & 1 deletion contrib/spi/insert_username.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ insert_username(PG_FUNCTION_ARGS)
args[0], relname)));

/* create fields containing name */
newval = CStringGetTextDatum(GetUserNameFromId(GetUserId()));
newval = CStringGetTextDatum(GetUserNameFromId(GetUserId(), false));

/* construct new tuple */
rettuple = SPI_modifytuple(rel, rettuple, 1, &attnum, &newval, NULL);
Expand Down
2 changes: 1 addition & 1 deletion contrib/spi/timetravel.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ timetravel(PG_FUNCTION_ARGS)
}

/* create fields containing name */
newuser = CStringGetTextDatum(GetUserNameFromId(GetUserId()));
newuser = CStringGetTextDatum(GetUserNameFromId(GetUserId(), false));

nulltext = (Datum) NULL;

Expand Down
27 changes: 23 additions & 4 deletions doc/src/sgml/datatype.sgml
Original file line number Diff line number Diff line change
Expand Up @@ -4364,8 +4364,9 @@ SET xmloption TO { DOCUMENT | CONTENT };
an object identifier. There are also several alias types for
<type>oid</>: <type>regproc</>, <type>regprocedure</>,
<type>regoper</>, <type>regoperator</>, <type>regclass</>,
<type>regtype</>, <type>regconfig</>, and <type>regdictionary</>.
<xref linkend="datatype-oid-table"> shows an overview.
<type>regtype</>, <type>regrole</>, <type>regconfig</>, and
<type>regdictionary</>. <xref linkend="datatype-oid-table"> shows
an overview.
</para>

<para>
Expand Down Expand Up @@ -4473,6 +4474,13 @@ SELECT * FROM pg_attribute
<entry><literal>integer</></entry>
</row>

<row>
<entry><type>regrole</></entry>
<entry><structname>pg_authid</></entry>
<entry>role name</entry>
<entry><literal>smithee</></entry>
</row>

<row>
<entry><type>regconfig</></entry>
<entry><structname>pg_ts_config</></entry>
Expand All @@ -4491,7 +4499,8 @@ SELECT * FROM pg_attribute
</table>

<para>
All of the OID alias types accept schema-qualified names, and will
All of the OID alias types for objects grouped by namespace accept
schema-qualified names, and will
display schema-qualified names on output if the object would not
be found in the current search path without being qualified.
The <type>regproc</> and <type>regoper</> alias types will only
Expand All @@ -4503,7 +4512,7 @@ SELECT * FROM pg_attribute
</para>

<para>
An additional property of the OID alias types is the creation of
An additional property of most of the OID alias types is the creation of
dependencies. If a
constant of one of these types appears in a stored expression
(such as a column default expression or view), it creates a dependency
Expand All @@ -4513,7 +4522,17 @@ SELECT * FROM pg_attribute
understands that the default expression depends on the sequence
<literal>my_seq</>; the system will not let the sequence be dropped
without first removing the default expression.
<type>regrole</> is the only exception for the property. Constants of this
type are not allowed in such expressions.
</para>

<note>
<para>
The OID alias types do not completely follow transaction isolation
rules. The planner also treats them as simple constants, which may
result in sub-optimal planning.
</para>
</note>

<para>
Another identifier type used by the system is <type>xid</>, or transaction
Expand Down
2 changes: 2 additions & 0 deletions src/backend/bootstrap/bootstrap.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,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,
Expand Down
10 changes: 10 additions & 0 deletions src/backend/catalog/dependency.c
Original file line number Diff line number Diff line change
Expand Up @@ -1685,6 +1685,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;
Expand Down
22 changes: 12 additions & 10 deletions src/backend/catalog/objectaddress.c
Original file line number Diff line number Diff line change
Expand Up @@ -2130,7 +2130,7 @@ getObjectDescription(const ObjectAddress *object)
case OCLASS_ROLE:
{
appendStringInfo(&buffer, _("role %s"),
GetUserNameFromId(object->objectId));
GetUserNameFromId(object->objectId, false));
break;
}

Expand Down Expand Up @@ -2196,7 +2196,7 @@ getObjectDescription(const ObjectAddress *object)
ReleaseSysCache(tup);

if (OidIsValid(useid))
usename = GetUserNameFromId(useid);
usename = GetUserNameFromId(useid, false);
else
usename = "public";

Expand Down Expand Up @@ -2236,28 +2236,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;
}

Expand Down Expand Up @@ -3331,7 +3331,7 @@ getObjectIdentity(const ObjectAddress *object)
{
char *username;

username = GetUserNameFromId(object->objectId);
username = GetUserNameFromId(object->objectId, false);
appendStringInfoString(&buffer,
quote_identifier(username));
break;
Expand Down Expand Up @@ -3402,7 +3402,7 @@ getObjectIdentity(const ObjectAddress *object)
ReleaseSysCache(tup);

if (OidIsValid(useid))
usename = quote_identifier(GetUserNameFromId(useid));
usename = quote_identifier(GetUserNameFromId(useid, false));
else
usename = "public";

Expand All @@ -3419,6 +3419,7 @@ getObjectIdentity(const ObjectAddress *object)

HeapTuple tup;
Form_pg_default_acl defacl;
char* username;

defaclrel = heap_open(DefaultAclRelationId, AccessShareLock);

Expand All @@ -3438,9 +3439,10 @@ getObjectIdentity(const ObjectAddress *object)

defacl = (Form_pg_default_acl) GETSTRUCT(tup);

username = GetUserNameFromId(defacl->defaclrole, false);
appendStringInfo(&buffer,
"for role %s",
quote_identifier(GetUserNameFromId(defacl->defaclrole)));
quote_identifier(username));

if (OidIsValid(defacl->defaclnamespace))
{
Expand Down
2 changes: 1 addition & 1 deletion src/backend/utils/adt/acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -5123,7 +5123,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))));
}

/*
Expand Down
4 changes: 2 additions & 2 deletions src/backend/utils/adt/name.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))));
}


Expand Down
104 changes: 104 additions & 0 deletions src/backend/utils/adt/regproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,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);
Expand Down Expand Up @@ -1490,6 +1491,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
Expand Down
1 change: 1 addition & 0 deletions src/backend/utils/adt/selfuncs.c
Original file line number Diff line number Diff line change
Expand Up @@ -3726,6 +3726,7 @@ convert_numeric_to_scalar(Datum value, Oid typid, bool *failure)
case REGTYPEOID:
case REGCONFIGOID:
case REGDICTIONARYOID:
case REGROLEOID:
/* we can treat OIDs as integers... */
return (double) DatumGetObjectId(value);
}
Expand Down
1 change: 1 addition & 0 deletions src/backend/utils/cache/catcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ GetCCHashEqFuncs(Oid keytype, PGFunction *hashfunc, RegProcedure *eqfunc)
case REGTYPEOID:
case REGCONFIGOID:
case REGDICTIONARYOID:
case REGROLEOID:
*hashfunc = hashoid;

*eqfunc = F_OIDEQ;
Expand Down
24 changes: 15 additions & 9 deletions src/backend/utils/init/miscinit.c
Original file line number Diff line number Diff line change
Expand Up @@ -595,23 +595,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;
}

Expand Down
Loading

0 comments on commit 2f863c0

Please sign in to comment.