Skip to content

Commit 0c90f67

Browse files
committed
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
1 parent 0cf56f1 commit 0c90f67

File tree

20 files changed

+235
-31
lines changed

20 files changed

+235
-31
lines changed

contrib/spi/insert_username.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ insert_username(PG_FUNCTION_ARGS)
7979
args[0], relname)));
8080

8181
/* create fields containing name */
82-
newval = CStringGetTextDatum(GetUserNameFromId(GetUserId()));
82+
newval = CStringGetTextDatum(GetUserNameFromId(GetUserId(), false));
8383

8484
/* construct new tuple */
8585
rettuple = SPI_modifytuple(rel, rettuple, 1, &attnum, &newval, NULL);

contrib/spi/timetravel.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ timetravel(PG_FUNCTION_ARGS)
174174
}
175175

176176
/* create fields containing name */
177-
newuser = CStringGetTextDatum(GetUserNameFromId(GetUserId()));
177+
newuser = CStringGetTextDatum(GetUserNameFromId(GetUserId(), false));
178178

179179
nulltext = (Datum) NULL;
180180

doc/src/sgml/datatype.sgml

+23-4
Original file line numberDiff line numberDiff line change
@@ -4321,8 +4321,9 @@ SET xmloption TO { DOCUMENT | CONTENT };
43214321
an object identifier. There are also several alias types for
43224322
<type>oid</>: <type>regproc</>, <type>regprocedure</>,
43234323
<type>regoper</>, <type>regoperator</>, <type>regclass</>,
4324-
<type>regtype</>, <type>regconfig</>, and <type>regdictionary</>.
4325-
<xref linkend="datatype-oid-table"> shows an overview.
4324+
<type>regtype</>, <type>regrole</>, <type>regconfig</>, and
4325+
<type>regdictionary</>. <xref linkend="datatype-oid-table"> shows
4326+
an overview.
43264327
</para>
43274328

43284329
<para>
@@ -4430,6 +4431,13 @@ SELECT * FROM pg_attribute
44304431
<entry><literal>integer</></entry>
44314432
</row>
44324433

4434+
<row>
4435+
<entry><type>regrole</></entry>
4436+
<entry><structname>pg_authid</></entry>
4437+
<entry>role name</entry>
4438+
<entry><literal>smithee</></entry>
4439+
</row>
4440+
44334441
<row>
44344442
<entry><type>regconfig</></entry>
44354443
<entry><structname>pg_ts_config</></entry>
@@ -4448,7 +4456,8 @@ SELECT * FROM pg_attribute
44484456
</table>
44494457

44504458
<para>
4451-
All of the OID alias types accept schema-qualified names, and will
4459+
All of the OID alias types for objects grouped by namespace accept
4460+
schema-qualified names, and will
44524461
display schema-qualified names on output if the object would not
44534462
be found in the current search path without being qualified.
44544463
The <type>regproc</> and <type>regoper</> alias types will only
@@ -4460,7 +4469,7 @@ SELECT * FROM pg_attribute
44604469
</para>
44614470

44624471
<para>
4463-
An additional property of the OID alias types is the creation of
4472+
An additional property of most of the OID alias types is the creation of
44644473
dependencies. If a
44654474
constant of one of these types appears in a stored expression
44664475
(such as a column default expression or view), it creates a dependency
@@ -4470,7 +4479,17 @@ SELECT * FROM pg_attribute
44704479
understands that the default expression depends on the sequence
44714480
<literal>my_seq</>; the system will not let the sequence be dropped
44724481
without first removing the default expression.
4482+
<type>regrole</> is the only exception for the property. Constants of this
4483+
type are not allowed in such expressions.
4484+
</para>
4485+
4486+
<note>
4487+
<para>
4488+
The OID alias types do not completely follow transaction isolation
4489+
rules. The planner also treats them as simple constants, which may
4490+
result in sub-optimal planning.
44734491
</para>
4492+
</note>
44744493

44754494
<para>
44764495
Another identifier type used by the system is <type>xid</>, or transaction

src/backend/bootstrap/bootstrap.c

+2
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ static const struct typinfo TypInfo[] = {
113113
F_REGPROCIN, F_REGPROCOUT},
114114
{"regtype", REGTYPEOID, 0, 4, true, 'i', 'p', InvalidOid,
115115
F_REGTYPEIN, F_REGTYPEOUT},
116+
{"regrole", REGROLEOID, 0, 4, true, 'i', 'p', InvalidOid,
117+
F_REGROLEIN, F_REGROLEOUT},
116118
{"text", TEXTOID, 0, -1, false, 'i', 'x', DEFAULT_COLLATION_OID,
117119
F_TEXTIN, F_TEXTOUT},
118120
{"oid", OIDOID, 0, 4, true, 'i', 'p', InvalidOid,

src/backend/catalog/dependency.c

+10
Original file line numberDiff line numberDiff line change
@@ -1602,6 +1602,16 @@ find_expr_references_walker(Node *node,
16021602
add_object_address(OCLASS_TSDICT, objoid, 0,
16031603
context->addrs);
16041604
break;
1605+
1606+
/*
1607+
* Dependencies for regrole should be shared among all
1608+
* databases, so explicitly inhibit to have dependencies.
1609+
*/
1610+
case REGROLEOID:
1611+
ereport(ERROR,
1612+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1613+
errmsg("constant of the type \'regrole\' cannot be used here")));
1614+
break;
16051615
}
16061616
}
16071617
return false;

src/backend/catalog/objectaddress.c

+10-10
Original file line numberDiff line numberDiff line change
@@ -2818,7 +2818,7 @@ getObjectDescription(const ObjectAddress *object)
28182818
case OCLASS_ROLE:
28192819
{
28202820
appendStringInfo(&buffer, _("role %s"),
2821-
GetUserNameFromId(object->objectId));
2821+
GetUserNameFromId(object->objectId, false));
28222822
break;
28232823
}
28242824

@@ -2884,7 +2884,7 @@ getObjectDescription(const ObjectAddress *object)
28842884
ReleaseSysCache(tup);
28852885

28862886
if (OidIsValid(useid))
2887-
usename = GetUserNameFromId(useid);
2887+
usename = GetUserNameFromId(useid, false);
28882888
else
28892889
usename = "public";
28902890

@@ -2924,28 +2924,28 @@ getObjectDescription(const ObjectAddress *object)
29242924
case DEFACLOBJ_RELATION:
29252925
appendStringInfo(&buffer,
29262926
_("default privileges on new relations belonging to role %s"),
2927-
GetUserNameFromId(defacl->defaclrole));
2927+
GetUserNameFromId(defacl->defaclrole, false));
29282928
break;
29292929
case DEFACLOBJ_SEQUENCE:
29302930
appendStringInfo(&buffer,
29312931
_("default privileges on new sequences belonging to role %s"),
2932-
GetUserNameFromId(defacl->defaclrole));
2932+
GetUserNameFromId(defacl->defaclrole, false));
29332933
break;
29342934
case DEFACLOBJ_FUNCTION:
29352935
appendStringInfo(&buffer,
29362936
_("default privileges on new functions belonging to role %s"),
2937-
GetUserNameFromId(defacl->defaclrole));
2937+
GetUserNameFromId(defacl->defaclrole, false));
29382938
break;
29392939
case DEFACLOBJ_TYPE:
29402940
appendStringInfo(&buffer,
29412941
_("default privileges on new types belonging to role %s"),
2942-
GetUserNameFromId(defacl->defaclrole));
2942+
GetUserNameFromId(defacl->defaclrole, false));
29432943
break;
29442944
default:
29452945
/* shouldn't get here */
29462946
appendStringInfo(&buffer,
29472947
_("default privileges belonging to role %s"),
2948-
GetUserNameFromId(defacl->defaclrole));
2948+
GetUserNameFromId(defacl->defaclrole, false));
29492949
break;
29502950
}
29512951

@@ -4214,7 +4214,7 @@ getObjectIdentityParts(const ObjectAddress *object,
42144214
{
42154215
char *username;
42164216

4217-
username = GetUserNameFromId(object->objectId);
4217+
username = GetUserNameFromId(object->objectId, false);
42184218
if (objname)
42194219
*objname = list_make1(username);
42204220
appendStringInfoString(&buffer,
@@ -4295,7 +4295,7 @@ getObjectIdentityParts(const ObjectAddress *object,
42954295
ReleaseSysCache(tup);
42964296

42974297
if (OidIsValid(useid))
4298-
usename = GetUserNameFromId(useid);
4298+
usename = GetUserNameFromId(useid, false);
42994299
else
43004300
usename = "public";
43014301

@@ -4339,7 +4339,7 @@ getObjectIdentityParts(const ObjectAddress *object,
43394339

43404340
defacl = (Form_pg_default_acl) GETSTRUCT(tup);
43414341

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

src/backend/utils/adt/acl.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -4878,7 +4878,7 @@ check_is_member_of_role(Oid member, Oid role)
48784878
ereport(ERROR,
48794879
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
48804880
errmsg("must be member of role \"%s\"",
4881-
GetUserNameFromId(role))));
4881+
GetUserNameFromId(role, false))));
48824882
}
48834883

48844884
/*

src/backend/utils/adt/name.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -263,13 +263,13 @@ namestrcmp(Name name, const char *str)
263263
Datum
264264
current_user(PG_FUNCTION_ARGS)
265265
{
266-
PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(GetUserNameFromId(GetUserId()))));
266+
PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(GetUserNameFromId(GetUserId(), false))));
267267
}
268268

269269
Datum
270270
session_user(PG_FUNCTION_ARGS)
271271
{
272-
PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(GetUserNameFromId(GetSessionUserId()))));
272+
PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(GetUserNameFromId(GetSessionUserId(), false))));
273273
}
274274

275275

src/backend/utils/adt/regproc.c

+104
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include "utils/lsyscache.h"
4141
#include "utils/syscache.h"
4242
#include "utils/tqual.h"
43+
#include "utils/acl.h"
4344

4445
static char *format_operator_internal(Oid operator_oid, bool force_qualify);
4546
static char *format_procedure_internal(Oid procedure_oid, bool force_qualify);
@@ -1553,6 +1554,109 @@ regdictionarysend(PG_FUNCTION_ARGS)
15531554
return oidsend(fcinfo);
15541555
}
15551556

1557+
/*
1558+
* regrolein - converts "rolename" to role OID
1559+
*
1560+
* We also accept a numeric OID, for symmetry with the output routine.
1561+
*
1562+
* '-' signifies unknown (OID 0). In all other cases, the input must
1563+
* match an existing pg_authid entry.
1564+
*
1565+
* This function is not needed in bootstrap mode, so we don't worry about
1566+
* making it work then.
1567+
*/
1568+
Datum
1569+
regrolein(PG_FUNCTION_ARGS)
1570+
{
1571+
char *role_name_or_oid = PG_GETARG_CSTRING(0);
1572+
Oid result;
1573+
1574+
/* '-' ? */
1575+
if (strcmp(role_name_or_oid, "-") == 0)
1576+
PG_RETURN_OID(InvalidOid);
1577+
1578+
/* Numeric OID? */
1579+
if (role_name_or_oid[0] >= '0' &&
1580+
role_name_or_oid[0] <= '9' &&
1581+
strspn(role_name_or_oid, "0123456789") == strlen(role_name_or_oid))
1582+
{
1583+
result = DatumGetObjectId(DirectFunctionCall1(oidin,
1584+
CStringGetDatum(role_name_or_oid)));
1585+
PG_RETURN_OID(result);
1586+
}
1587+
1588+
/* Normal case: see if the name matches any pg_authid entry. */
1589+
result = get_role_oid(role_name_or_oid, false);
1590+
1591+
PG_RETURN_OID(result);
1592+
}
1593+
1594+
/*
1595+
* to_regrole - converts "rolename" to role OID
1596+
*
1597+
* If the name is not found, we return NULL.
1598+
*/
1599+
Datum
1600+
to_regrole(PG_FUNCTION_ARGS)
1601+
{
1602+
char *role_name = PG_GETARG_CSTRING(0);
1603+
Oid result;
1604+
1605+
result = get_role_oid(role_name, true);
1606+
1607+
if (OidIsValid(result))
1608+
PG_RETURN_OID(result);
1609+
else
1610+
PG_RETURN_NULL();
1611+
}
1612+
1613+
/*
1614+
* regroleout - converts role OID to "role_name"
1615+
*/
1616+
Datum
1617+
regroleout(PG_FUNCTION_ARGS)
1618+
{
1619+
Oid roleoid = PG_GETARG_OID(0);
1620+
char *result;
1621+
1622+
1623+
if (roleoid == InvalidOid)
1624+
{
1625+
result = pstrdup("-");
1626+
PG_RETURN_CSTRING(result);
1627+
}
1628+
1629+
result = GetUserNameFromId(roleoid, true);
1630+
if (!result)
1631+
{
1632+
/* If OID doesn't match any role, return it numerically */
1633+
result = (char *) palloc(NAMEDATALEN);
1634+
snprintf(result, NAMEDATALEN, "%u", roleoid);
1635+
}
1636+
PG_RETURN_CSTRING(result);
1637+
}
1638+
1639+
/*
1640+
* regrolerecv - converts external binary format to regrole
1641+
*/
1642+
Datum
1643+
regrolerecv(PG_FUNCTION_ARGS)
1644+
{
1645+
/* Exactly the same as oidrecv, so share code */
1646+
return oidrecv(fcinfo);
1647+
}
1648+
1649+
/*
1650+
* regrolesend - converts regrole to binary format
1651+
*/
1652+
Datum
1653+
regrolesend(PG_FUNCTION_ARGS)
1654+
{
1655+
/* Exactly the same as oidsend, so share code */
1656+
return oidsend(fcinfo);
1657+
}
1658+
1659+
15561660

15571661
/*
15581662
* text_regclass: convert text to regclass

src/backend/utils/adt/selfuncs.c

+2
Original file line numberDiff line numberDiff line change
@@ -3619,6 +3619,7 @@ convert_to_scalar(Datum value, Oid valuetypid, double *scaledvalue,
36193619
case REGTYPEOID:
36203620
case REGCONFIGOID:
36213621
case REGDICTIONARYOID:
3622+
case REGROLEOID:
36223623
*scaledvalue = convert_numeric_to_scalar(value, valuetypid);
36233624
*scaledlobound = convert_numeric_to_scalar(lobound, boundstypid);
36243625
*scaledhibound = convert_numeric_to_scalar(hibound, boundstypid);
@@ -3724,6 +3725,7 @@ convert_numeric_to_scalar(Datum value, Oid typid)
37243725
case REGTYPEOID:
37253726
case REGCONFIGOID:
37263727
case REGDICTIONARYOID:
3728+
case REGROLEOID:
37273729
/* we can treat OIDs as integers... */
37283730
return (double) DatumGetObjectId(value);
37293731
}

src/backend/utils/cache/catcache.c

+1
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ GetCCHashEqFuncs(Oid keytype, PGFunction *hashfunc, RegProcedure *eqfunc)
150150
case REGTYPEOID:
151151
case REGCONFIGOID:
152152
case REGDICTIONARYOID:
153+
case REGROLEOID:
153154
*hashfunc = hashoid;
154155

155156
*eqfunc = F_OIDEQ;

src/backend/utils/init/miscinit.c

+15-9
Original file line numberDiff line numberDiff line change
@@ -648,23 +648,29 @@ SetCurrentRoleId(Oid roleid, bool is_superuser)
648648

649649

650650
/*
651-
* Get user name from user oid
651+
* Get user name from user oid, returns NULL for nonexistent roleid if noerr
652+
* is true.
652653
*/
653654
char *
654-
GetUserNameFromId(Oid roleid)
655+
GetUserNameFromId(Oid roleid, bool noerr)
655656
{
656657
HeapTuple tuple;
657658
char *result;
658659

659660
tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
660661
if (!HeapTupleIsValid(tuple))
661-
ereport(ERROR,
662-
(errcode(ERRCODE_UNDEFINED_OBJECT),
663-
errmsg("invalid role OID: %u", roleid)));
664-
665-
result = pstrdup(NameStr(((Form_pg_authid) GETSTRUCT(tuple))->rolname));
666-
667-
ReleaseSysCache(tuple);
662+
{
663+
if (!noerr)
664+
ereport(ERROR,
665+
(errcode(ERRCODE_UNDEFINED_OBJECT),
666+
errmsg("invalid role OID: %u", roleid)));
667+
result = NULL;
668+
}
669+
else
670+
{
671+
result = pstrdup(NameStr(((Form_pg_authid) GETSTRUCT(tuple))->rolname));
672+
ReleaseSysCache(tuple);
673+
}
668674
return result;
669675
}
670676

0 commit comments

Comments
 (0)