Bug / shortcoming in has_*_privilege

Started by Jim Nasbyover 15 years ago19 messages
#1Jim Nasby
jim@nasby.net

test_us@workbook=# select has_table_privilege( 'public', 'test', 'SELECT' );
ERROR: role "public" does not exist
test_us@workbook=#

So there's no way to see if a particular privilege has been granted to public. ISTM 'public' should be accepted, since you can't use it as a role name anyway...

test_us@workbook=# create role public;
ERROR: role name "public" is reserved
test_us@workbook=# create role "public";
ERROR: role name "public" is reserved
--
Jim C. Nasby, Database Architect jim@nasby.net
512.569.9461 (cell) http://jim.nasby.net

#2Robert Haas
robertmhaas@gmail.com
In reply to: Jim Nasby (#1)
Re: Bug / shortcoming in has_*_privilege

On Thu, Jun 10, 2010 at 5:54 PM, Jim Nasby <jim@nasby.net> wrote:

test_us@workbook=# select has_table_privilege( 'public', 'test', 'SELECT' );
ERROR:  role "public" does not exist
test_us@workbook=#

So there's no way to see if a particular privilege has been granted to public. ISTM 'public' should be accepted, since you can't use it as a role name anyway...

test_us@workbook=# create role public;
ERROR:  role name "public" is reserved
test_us@workbook=# create role "public";
ERROR:  role name "public" is reserved

It's a bit sticky - you could make that work for
has_table_privilege(name, oid, text) or has_table_privilege(name,
text, text), but what would you do about the versions whose first
argument is an oid? It would seem a bit awkward to have the behavior
by asymmetrical, although I guess we could...

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise Postgres Company

#3Tom Lane
tgl@sss.pgh.pa.us
In reply to: Robert Haas (#2)
Re: Bug / shortcoming in has_*_privilege

Robert Haas <robertmhaas@gmail.com> writes:

On Thu, Jun 10, 2010 at 5:54 PM, Jim Nasby <jim@nasby.net> wrote:

So there's no way to see if a particular privilege has been granted to public. ISTM 'public' should be accepted, since you can't use it as a role name anyway...

It's a bit sticky - you could make that work for
has_table_privilege(name, oid, text) or has_table_privilege(name,
text, text), but what would you do about the versions whose first
argument is an oid?

Nothing. The only reason to use those forms is in a join against
pg_authid, and the "public" group doesn't have an entry there.

regards, tom lane

#4Nasby, Jim
JNasby@enovafinancial.com
In reply to: Tom Lane (#3)
Re: Bug / shortcoming in has_*_privilege

On Jun 11, 2010, at 5:18 AM, Tom Lane wrote:

Robert Haas <robertmhaas@gmail.com> writes:

On Thu, Jun 10, 2010 at 5:54 PM, Jim Nasby <jim@nasby.net> wrote:

So there's no way to see if a particular privilege has been granted to public. ISTM 'public' should be accepted, since you can't use it as a role name anyway...

It's a bit sticky - you could make that work for
has_table_privilege(name, oid, text) or has_table_privilege(name,
text, text), but what would you do about the versions whose first
argument is an oid?

Nothing. The only reason to use those forms is in a join against
pg_authid, and the "public" group doesn't have an entry there.

Cool, I'll have CMD come up with a patch.
--
Jim "Decibel!" Nasby jnasby@EnovaFinancial.com
Primary: 512-579-9024 Backup: 512-569-9461

#5Simon Riggs
simon@2ndQuadrant.com
In reply to: Tom Lane (#3)
Re: Bug / shortcoming in has_*_privilege

On Thu, 2010-06-10 at 23:18 -0400, Tom Lane wrote:

Robert Haas <robertmhaas@gmail.com> writes:

On Thu, Jun 10, 2010 at 5:54 PM, Jim Nasby <jim@nasby.net> wrote:

So there's no way to see if a particular privilege has been granted to public. ISTM 'public' should be accepted, since you can't use it as a role name anyway...

It's a bit sticky - you could make that work for
has_table_privilege(name, oid, text) or has_table_privilege(name,
text, text), but what would you do about the versions whose first
argument is an oid?

Nothing. The only reason to use those forms is in a join against
pg_authid, and the "public" group doesn't have an entry there.

ISTM this bug should be on the open items list...

--
Simon Riggs www.2ndQuadrant.com
PostgreSQL Development, 24x7 Support, Training and Services

#6Robert Haas
robertmhaas@gmail.com
In reply to: Simon Riggs (#5)
Re: Bug / shortcoming in has_*_privilege

On Wed, Aug 11, 2010 at 3:57 AM, Simon Riggs <simon@2ndquadrant.com> wrote:

On Thu, 2010-06-10 at 23:18 -0400, Tom Lane wrote:

Robert Haas <robertmhaas@gmail.com> writes:

On Thu, Jun 10, 2010 at 5:54 PM, Jim Nasby <jim@nasby.net> wrote:

So there's no way to see if a particular privilege has been granted to public. ISTM 'public' should be accepted, since you can't use it as a role name anyway...

It's a bit sticky - you could make that work for
has_table_privilege(name, oid, text) or has_table_privilege(name,
text, text), but what would you do about the versions whose first
argument is an oid?

Nothing.  The only reason to use those forms is in a join against
pg_authid, and the "public" group doesn't have an entry there.

ISTM this bug should be on the open items list...

I don't think this is a bug.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise Postgres Company

#7Stephen Frost
sfrost@snowman.net
In reply to: Robert Haas (#6)
Re: Bug / shortcoming in has_*_privilege

* Robert Haas (robertmhaas@gmail.com) wrote:

On Wed, Aug 11, 2010 at 3:57 AM, Simon Riggs <simon@2ndquadrant.com> wrote:

On Thu, 2010-06-10 at 23:18 -0400, Tom Lane wrote:

Nothing.  The only reason to use those forms is in a join against
pg_authid, and the "public" group doesn't have an entry there.

ISTM this bug should be on the open items list...

I don't think this is a bug.

Agreed, and it's certainly not something that needs to be dealt with for
9.0..

Thanks,

Stephen

#8Simon Riggs
simon@2ndQuadrant.com
In reply to: Robert Haas (#6)
Re: Bug / shortcoming in has_*_privilege

On Wed, 2010-08-11 at 06:48 -0400, Robert Haas wrote:

On Wed, Aug 11, 2010 at 3:57 AM, Simon Riggs <simon@2ndquadrant.com> wrote:

On Thu, 2010-06-10 at 23:18 -0400, Tom Lane wrote:

Robert Haas <robertmhaas@gmail.com> writes:

On Thu, Jun 10, 2010 at 5:54 PM, Jim Nasby <jim@nasby.net> wrote:

So there's no way to see if a particular privilege has been granted to public. ISTM 'public' should be accepted, since you can't use it as a role name anyway...

It's a bit sticky - you could make that work for
has_table_privilege(name, oid, text) or has_table_privilege(name,
text, text), but what would you do about the versions whose first
argument is an oid?

Nothing. The only reason to use those forms is in a join against
pg_authid, and the "public" group doesn't have an entry there.

ISTM this bug should be on the open items list...

I don't think this is a bug.

It clearly rates higher in importance than most of the things on the
open items list of late...

--
Simon Riggs www.2ndQuadrant.com
PostgreSQL Development, 24x7 Support, Training and Services

#9Robert Haas
robertmhaas@gmail.com
In reply to: Simon Riggs (#8)
Re: Bug / shortcoming in has_*_privilege

On Wed, Aug 11, 2010 at 8:51 AM, Simon Riggs <simon@2ndquadrant.com> wrote:

On Wed, 2010-08-11 at 06:48 -0400, Robert Haas wrote:

On Wed, Aug 11, 2010 at 3:57 AM, Simon Riggs <simon@2ndquadrant.com> wrote:

On Thu, 2010-06-10 at 23:18 -0400, Tom Lane wrote:

Robert Haas <robertmhaas@gmail.com> writes:

On Thu, Jun 10, 2010 at 5:54 PM, Jim Nasby <jim@nasby.net> wrote:

So there's no way to see if a particular privilege has been granted to public. ISTM 'public' should be accepted, since you can't use it as a role name anyway...

It's a bit sticky - you could make that work for
has_table_privilege(name, oid, text) or has_table_privilege(name,
text, text), but what would you do about the versions whose first
argument is an oid?

Nothing.  The only reason to use those forms is in a join against
pg_authid, and the "public" group doesn't have an entry there.

ISTM this bug should be on the open items list...

I don't think this is a bug.

It clearly rates higher in importance than most of the things on the
open items list of late...

First, I don't think that's true. WALreceiver crashing on AIX, the
backup procedure in the manual possibly being wrong, and the
documentation failing to be installed sometimes all seem like they are
clearly more serious issues than this. I am sort of wondering why no
one is working on those issues; apparently, nobody other than me minds
if it takes another three months to get 9.0 out the door. Frankly, I
think the ExplainOnePlan bit is more important, too, although I'm
starting to think we should fix that for 9.1 rather than 9.0.

Second, even if it were true, the fact that something is important
does not make it a bug fix.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise Postgres Company

#10Tom Lane
tgl@sss.pgh.pa.us
In reply to: Robert Haas (#9)
Re: Bug / shortcoming in has_*_privilege

Robert Haas <robertmhaas@gmail.com> writes:

On Wed, Aug 11, 2010 at 8:51 AM, Simon Riggs <simon@2ndquadrant.com> wrote:

It clearly rates higher in importance than most of the things on the
open items list of late...

First, I don't think that's true. WALreceiver crashing on AIX, the
backup procedure in the manual possibly being wrong, and the
documentation failing to be installed sometimes all seem like they are
clearly more serious issues than this. I am sort of wondering why no
one is working on those issues; apparently, nobody other than me minds
if it takes another three months to get 9.0 out the door.

Quite. At this point, the only things that should be on the open items
list are things that would be release stoppers, which is to say things
that are regressions from prior releases or design errors that we don't
want to ever get into a release. This item is not a bug but a feature
omission, and one of rather long standing.

Frankly, I
think the ExplainOnePlan bit is more important, too, although I'm
starting to think we should fix that for 9.1 rather than 9.0.

See above. We are not changing that in 9.0 anymore.

regards, tom lane

#11Alvaro Herrera
alvherre@commandprompt.com
In reply to: Jim Nasby (#1)
1 attachment(s)
Re: Bug / shortcoming in has_*_privilege

Excerpts from Jim Nasby's message of jue jun 10 17:54:43 -0400 2010:

test_us@workbook=# select has_table_privilege( 'public', 'test', 'SELECT' );
ERROR: role "public" does not exist

Here's a patch implementing this idea.

I'm not too sure about the wording in the doc changes. If somebody
wants to propose something better, I'm all ears. To facilitate
bikeshedding, here's a relevant extract:

has_table_privilege checks whether a user can access a table in
a particular way. The user can be specified by name; as public,
to indicate the PUBLIC pseudo-role; by OID (pg_authid.oid), or,
if the argument is omitted, current_user is assumed.

(the first appearance of public is <literal>public</>. I had first made
it <quote> but that didn't feel right.)

Another thing that could raise eyebrows is that I chose to remove the
"missing_ok" argument from get_role_oid_or_public, so it's not a perfect
mirror of it. None of the current callers need it, but perhaps people
would like these functions to be consistent.

--
Álvaro Herrera <alvherre@commandprompt.com>
The PostgreSQL Company - Command Prompt, Inc.
PostgreSQL Replication, Consulting, Custom Development, 24x7 support

Attachments:

public-has-privileges-3.patchapplication/octet-stream; name=public-has-privileges-3.patchDownload
*** a/doc/src/sgml/func.sgml
--- b/doc/src/sgml/func.sgml
***************
*** 12349,12357 **** SET search_path TO <replaceable>schema</> <optional>, <replaceable>schema</>, ..
     <para>
      <function>has_table_privilege</function> checks whether a user
      can access a table in a particular way.  The user can be
!     specified by name or by OID
!     (<literal>pg_authid.oid</literal>), or if the argument is
!     omitted
      <function>current_user</function> is assumed.  The table can be specified
      by name or by OID.  (Thus, there are actually six variants of
      <function>has_table_privilege</function>, which can be distinguished by
--- 12349,12357 ----
     <para>
      <function>has_table_privilege</function> checks whether a user
      can access a table in a particular way.  The user can be
!     specified by name; as <literal>public</>, to indicate the PUBLIC pseudo-role; by OID
!     (<literal>pg_authid.oid</literal>), or, if the argument is
!     omitted,
      <function>current_user</function> is assumed.  The table can be specified
      by name or by OID.  (Thus, there are actually six variants of
      <function>has_table_privilege</function>, which can be distinguished by
***************
*** 12497,12503 **** SELECT has_function_privilege('joeuser', 'myfunc(int, text)', 'execute');
      <function>pg_has_role</function> checks whether a user
      can access a role in a particular way.
      Its argument possibilities
!     are analogous to <function>has_table_privilege</function>.
      The desired access privilege type must evaluate to some combination of
      <literal>MEMBER</literal> or
      <literal>USAGE</literal>.
--- 12497,12504 ----
      <function>pg_has_role</function> checks whether a user
      can access a role in a particular way.
      Its argument possibilities
!     are analogous to <function>has_table_privilege</function>,
!     except that <literal>public</> is not allowed as user name.
      The desired access privilege type must evaluate to some combination of
      <literal>MEMBER</literal> or
      <literal>USAGE</literal>.
*** a/src/backend/utils/adt/acl.c
--- b/src/backend/utils/adt/acl.c
***************
*** 113,118 **** static AclMode convert_role_priv_string(text *priv_type_text);
--- 113,119 ----
  static AclResult pg_role_aclcheck(Oid role_oid, Oid roleid, AclMode mode);
  
  static void RoleMembershipCacheCallback(Datum arg, int cacheid, ItemPointer tuplePtr);
+ static Oid get_role_oid_or_public(const char *rolname);
  
  
  /*
***************
*** 1791,1797 **** has_table_privilege_name_name(PG_FUNCTION_ARGS)
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid(NameStr(*rolename), false);
  	tableoid = convert_table_name(tablename);
  	mode = convert_table_priv_string(priv_type_text);
  
--- 1792,1798 ----
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid_or_public(NameStr(*rolename));
  	tableoid = convert_table_name(tablename);
  	mode = convert_table_priv_string(priv_type_text);
  
***************
*** 1840,1846 **** has_table_privilege_name_id(PG_FUNCTION_ARGS)
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid(NameStr(*username), false);
  	mode = convert_table_priv_string(priv_type_text);
  
  	if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(tableoid)))
--- 1841,1847 ----
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid_or_public(NameStr(*username));
  	mode = convert_table_priv_string(priv_type_text);
  
  	if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(tableoid)))
***************
*** 1998,2004 **** has_sequence_privilege_name_name(PG_FUNCTION_ARGS)
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid(NameStr(*rolename), false);
  	mode = convert_sequence_priv_string(priv_type_text);
  	sequenceoid = convert_table_name(sequencename);
  	if (get_rel_relkind(sequenceoid) != RELKIND_SEQUENCE)
--- 1999,2005 ----
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid_or_public(NameStr(*rolename));
  	mode = convert_sequence_priv_string(priv_type_text);
  	sequenceoid = convert_table_name(sequencename);
  	if (get_rel_relkind(sequenceoid) != RELKIND_SEQUENCE)
***************
*** 2058,2064 **** has_sequence_privilege_name_id(PG_FUNCTION_ARGS)
  	AclResult	aclresult;
  	char		relkind;
  
! 	roleid = get_role_oid(NameStr(*username), false);
  	mode = convert_sequence_priv_string(priv_type_text);
  	relkind = get_rel_relkind(sequenceoid);
  	if (relkind == '\0')
--- 2059,2065 ----
  	AclResult	aclresult;
  	char		relkind;
  
! 	roleid = get_role_oid_or_public(NameStr(*username));
  	mode = convert_sequence_priv_string(priv_type_text);
  	relkind = get_rel_relkind(sequenceoid);
  	if (relkind == '\0')
***************
*** 2209,2215 **** has_any_column_privilege_name_name(PG_FUNCTION_ARGS)
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid(NameStr(*rolename), false);
  	tableoid = convert_table_name(tablename);
  	mode = convert_column_priv_string(priv_type_text);
  
--- 2210,2216 ----
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid_or_public(NameStr(*rolename));
  	tableoid = convert_table_name(tablename);
  	mode = convert_column_priv_string(priv_type_text);
  
***************
*** 2266,2272 **** has_any_column_privilege_name_id(PG_FUNCTION_ARGS)
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid(NameStr(*username), false);
  	mode = convert_column_priv_string(priv_type_text);
  
  	if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(tableoid)))
--- 2267,2273 ----
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid_or_public(NameStr(*username));
  	mode = convert_column_priv_string(priv_type_text);
  
  	if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(tableoid)))
***************
*** 2451,2457 **** has_column_privilege_name_name_name(PG_FUNCTION_ARGS)
  	AclMode		mode;
  	int			privresult;
  
! 	roleid = get_role_oid(NameStr(*rolename), false);
  	tableoid = convert_table_name(tablename);
  	colattnum = convert_column_name(tableoid, column);
  	mode = convert_column_priv_string(priv_type_text);
--- 2452,2458 ----
  	AclMode		mode;
  	int			privresult;
  
! 	roleid = get_role_oid_or_public(NameStr(*rolename));
  	tableoid = convert_table_name(tablename);
  	colattnum = convert_column_name(tableoid, column);
  	mode = convert_column_priv_string(priv_type_text);
***************
*** 2479,2485 **** has_column_privilege_name_name_attnum(PG_FUNCTION_ARGS)
  	AclMode		mode;
  	int			privresult;
  
! 	roleid = get_role_oid(NameStr(*rolename), false);
  	tableoid = convert_table_name(tablename);
  	mode = convert_column_priv_string(priv_type_text);
  
--- 2480,2486 ----
  	AclMode		mode;
  	int			privresult;
  
! 	roleid = get_role_oid_or_public(NameStr(*rolename));
  	tableoid = convert_table_name(tablename);
  	mode = convert_column_priv_string(priv_type_text);
  
***************
*** 2506,2512 **** has_column_privilege_name_id_name(PG_FUNCTION_ARGS)
  	AclMode		mode;
  	int			privresult;
  
! 	roleid = get_role_oid(NameStr(*username), false);
  	colattnum = convert_column_name(tableoid, column);
  	mode = convert_column_priv_string(priv_type_text);
  
--- 2507,2513 ----
  	AclMode		mode;
  	int			privresult;
  
! 	roleid = get_role_oid_or_public(NameStr(*username));
  	colattnum = convert_column_name(tableoid, column);
  	mode = convert_column_priv_string(priv_type_text);
  
***************
*** 2532,2538 **** has_column_privilege_name_id_attnum(PG_FUNCTION_ARGS)
  	AclMode		mode;
  	int			privresult;
  
! 	roleid = get_role_oid(NameStr(*username), false);
  	mode = convert_column_priv_string(priv_type_text);
  
  	privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
--- 2533,2539 ----
  	AclMode		mode;
  	int			privresult;
  
! 	roleid = get_role_oid_or_public(NameStr(*username));
  	mode = convert_column_priv_string(priv_type_text);
  
  	privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
***************
*** 2823,2829 **** has_database_privilege_name_name(PG_FUNCTION_ARGS)
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid(NameStr(*username), false);
  	databaseoid = convert_database_name(databasename);
  	mode = convert_database_priv_string(priv_type_text);
  
--- 2824,2830 ----
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid_or_public(NameStr(*username));
  	databaseoid = convert_database_name(databasename);
  	mode = convert_database_priv_string(priv_type_text);
  
***************
*** 2872,2878 **** has_database_privilege_name_id(PG_FUNCTION_ARGS)
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid(NameStr(*username), false);
  	mode = convert_database_priv_string(priv_type_text);
  
  	if (!SearchSysCacheExists1(DATABASEOID, ObjectIdGetDatum(databaseoid)))
--- 2873,2879 ----
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid_or_public(NameStr(*username));
  	mode = convert_database_priv_string(priv_type_text);
  
  	if (!SearchSysCacheExists1(DATABASEOID, ObjectIdGetDatum(databaseoid)))
***************
*** 3021,3027 **** has_foreign_data_wrapper_privilege_name_name(PG_FUNCTION_ARGS)
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid(NameStr(*username), false);
  	fdwid = convert_foreign_data_wrapper_name(fdwname);
  	mode = convert_foreign_data_wrapper_priv_string(priv_type_text);
  
--- 3022,3028 ----
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid_or_public(NameStr(*username));
  	fdwid = convert_foreign_data_wrapper_name(fdwname);
  	mode = convert_foreign_data_wrapper_priv_string(priv_type_text);
  
***************
*** 3070,3076 **** has_foreign_data_wrapper_privilege_name_id(PG_FUNCTION_ARGS)
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid(NameStr(*username), false);
  	mode = convert_foreign_data_wrapper_priv_string(priv_type_text);
  
  	aclresult = pg_foreign_data_wrapper_aclcheck(fdwid, roleid, mode);
--- 3071,3077 ----
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid_or_public(NameStr(*username));
  	mode = convert_foreign_data_wrapper_priv_string(priv_type_text);
  
  	aclresult = pg_foreign_data_wrapper_aclcheck(fdwid, roleid, mode);
***************
*** 3203,3209 **** has_function_privilege_name_name(PG_FUNCTION_ARGS)
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid(NameStr(*username), false);
  	functionoid = convert_function_name(functionname);
  	mode = convert_function_priv_string(priv_type_text);
  
--- 3204,3210 ----
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid_or_public(NameStr(*username));
  	functionoid = convert_function_name(functionname);
  	mode = convert_function_priv_string(priv_type_text);
  
***************
*** 3252,3258 **** has_function_privilege_name_id(PG_FUNCTION_ARGS)
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid(NameStr(*username), false);
  	mode = convert_function_priv_string(priv_type_text);
  
  	if (!SearchSysCacheExists1(PROCOID, ObjectIdGetDatum(functionoid)))
--- 3253,3259 ----
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid_or_public(NameStr(*username));
  	mode = convert_function_priv_string(priv_type_text);
  
  	if (!SearchSysCacheExists1(PROCOID, ObjectIdGetDatum(functionoid)))
***************
*** 3403,3409 **** has_language_privilege_name_name(PG_FUNCTION_ARGS)
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid(NameStr(*username), false);
  	languageoid = convert_language_name(languagename);
  	mode = convert_language_priv_string(priv_type_text);
  
--- 3404,3410 ----
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid_or_public(NameStr(*username));
  	languageoid = convert_language_name(languagename);
  	mode = convert_language_priv_string(priv_type_text);
  
***************
*** 3452,3458 **** has_language_privilege_name_id(PG_FUNCTION_ARGS)
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid(NameStr(*username), false);
  	mode = convert_language_priv_string(priv_type_text);
  
  	if (!SearchSysCacheExists1(LANGOID, ObjectIdGetDatum(languageoid)))
--- 3453,3459 ----
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid_or_public(NameStr(*username));
  	mode = convert_language_priv_string(priv_type_text);
  
  	if (!SearchSysCacheExists1(LANGOID, ObjectIdGetDatum(languageoid)))
***************
*** 3594,3600 **** has_schema_privilege_name_name(PG_FUNCTION_ARGS)
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid(NameStr(*username), false);
  	schemaoid = convert_schema_name(schemaname);
  	mode = convert_schema_priv_string(priv_type_text);
  
--- 3595,3601 ----
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid_or_public(NameStr(*username));
  	schemaoid = convert_schema_name(schemaname);
  	mode = convert_schema_priv_string(priv_type_text);
  
***************
*** 3643,3649 **** has_schema_privilege_name_id(PG_FUNCTION_ARGS)
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid(NameStr(*username), false);
  	mode = convert_schema_priv_string(priv_type_text);
  
  	if (!SearchSysCacheExists1(NAMESPACEOID, ObjectIdGetDatum(schemaoid)))
--- 3644,3650 ----
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid_or_public(NameStr(*username));
  	mode = convert_schema_priv_string(priv_type_text);
  
  	if (!SearchSysCacheExists1(NAMESPACEOID, ObjectIdGetDatum(schemaoid)))
***************
*** 3787,3793 **** has_server_privilege_name_name(PG_FUNCTION_ARGS)
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid(NameStr(*username), false);
  	serverid = convert_server_name(servername);
  	mode = convert_server_priv_string(priv_type_text);
  
--- 3788,3794 ----
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid_or_public(NameStr(*username));
  	serverid = convert_server_name(servername);
  	mode = convert_server_priv_string(priv_type_text);
  
***************
*** 3836,3842 **** has_server_privilege_name_id(PG_FUNCTION_ARGS)
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid(NameStr(*username), false);
  	mode = convert_server_priv_string(priv_type_text);
  
  	aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode);
--- 3837,3843 ----
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid_or_public(NameStr(*username));
  	mode = convert_server_priv_string(priv_type_text);
  
  	aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode);
***************
*** 3969,3975 **** has_tablespace_privilege_name_name(PG_FUNCTION_ARGS)
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid(NameStr(*username), false);
  	tablespaceoid = convert_tablespace_name(tablespacename);
  	mode = convert_tablespace_priv_string(priv_type_text);
  
--- 3970,3976 ----
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid_or_public(NameStr(*username));
  	tablespaceoid = convert_tablespace_name(tablespacename);
  	mode = convert_tablespace_priv_string(priv_type_text);
  
***************
*** 4018,4024 **** has_tablespace_privilege_name_id(PG_FUNCTION_ARGS)
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid(NameStr(*username), false);
  	mode = convert_tablespace_priv_string(priv_type_text);
  
  	aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
--- 4019,4025 ----
  	AclMode		mode;
  	AclResult	aclresult;
  
! 	roleid = get_role_oid_or_public(NameStr(*username));
  	mode = convert_tablespace_priv_string(priv_type_text);
  
  	aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
***************
*** 4821,4823 **** get_role_oid(const char *rolname, bool missing_ok)
--- 4822,4839 ----
  				 errmsg("role \"%s\" does not exist", rolname)));
  	return oid;
  }
+ 
+ /*
+  * get_role_oid_or_public - As above, but return ACL_ID_PUBLIC if the
+  * 		role name is "public".
+  */
+ static Oid
+ get_role_oid_or_public(const char *rolname)
+ {
+ 	Oid			oid;
+ 
+ 	if (strcmp(rolname, "public") == 0)
+ 		return ACL_ID_PUBLIC;
+ 
+ 	return get_role_oid(rolname, false);
+ }
#12Tom Lane
tgl@sss.pgh.pa.us
In reply to: Alvaro Herrera (#11)
Re: Bug / shortcoming in has_*_privilege

Alvaro Herrera <alvherre@commandprompt.com> writes:

Another thing that could raise eyebrows is that I chose to remove the
"missing_ok" argument from get_role_oid_or_public, so it's not a perfect
mirror of it. None of the current callers need it, but perhaps people
would like these functions to be consistent.

Well, it can't be really consistent anyway: if you did have a missing_ok
argument then you'd need an unusual return convention so you could
distinguish "missing" from "public". As long as this is a static
function I don't see a strong need for it to mimic the API of the
general get_whatever_oid functions.

regards, tom lane

#13KaiGai Kohei
kaigai@ak.jp.nec.com
In reply to: Alvaro Herrera (#11)
Re: Bug / shortcoming in has_*_privilege

(2010/09/07 6:16), Alvaro Herrera wrote:

Excerpts from Jim Nasby's message of jue jun 10 17:54:43 -0400 2010:

test_us@workbook=# select has_table_privilege( 'public', 'test', 'SELECT' );
ERROR: role "public" does not exist

Here's a patch implementing this idea.

I checked this patch.

It seems to me it replaces whole of get_role_oid() in has_*_privilege
functions by the new get_role_oid_or_public(), so this patch allows
to accept the pseudo "public" user in consistent way.

The pg_has_role_*() functions are exception. It will raise an error
with error message of "role "public" does not exist".
Is it an expected bahavior, isn't it?

I'm not too sure about the wording in the doc changes. If somebody
wants to propose something better, I'm all ears. To facilitate
bikeshedding, here's a relevant extract:

has_table_privilege checks whether a user can access a table in
a particular way. The user can be specified by name; as public,
to indicate the PUBLIC pseudo-role; by OID (pg_authid.oid), or,
if the argument is omitted, current_user is assumed.

(the first appearance of public is<literal>public</>. I had first made
it<quote> but that didn't feel right.)

It seems to me fair enough, but I'm not a native in English.

Another thing that could raise eyebrows is that I chose to remove the
"missing_ok" argument from get_role_oid_or_public, so it's not a perfect
mirror of it. None of the current callers need it, but perhaps people
would like these functions to be consistent.

Tom Lane suggested to add missing_ok argument, although it is not a must-
requirement.

Thanks,
--
KaiGai Kohei <kaigai@ak.jp.nec.com>

#14Alvaro Herrera
alvherre@commandprompt.com
In reply to: KaiGai Kohei (#13)
Re: Bug / shortcoming in has_*_privilege

Excerpts from KaiGai Kohei's message of mar oct 05 00:06:05 -0400 2010:

(2010/09/07 6:16), Alvaro Herrera wrote:

Excerpts from Jim Nasby's message of jue jun 10 17:54:43 -0400 2010:

test_us@workbook=# select has_table_privilege( 'public', 'test', 'SELECT' );
ERROR: role "public" does not exist

Here's a patch implementing this idea.

I checked this patch.

Thanks.

It seems to me it replaces whole of get_role_oid() in has_*_privilege
functions by the new get_role_oid_or_public(), so this patch allows
to accept the pseudo "public" user in consistent way.

Yes.

The pg_has_role_*() functions are exception. It will raise an error
with error message of "role "public" does not exist".
Is it an expected bahavior, isn't it?

Yes. You cannot grant "public" to roles; according to the definition of
public, this doesn't make sense. Accordingly, I chose to reject
"public" as an input for pg_has_role and friends.

Another thing that could raise eyebrows is that I chose to remove the
"missing_ok" argument from get_role_oid_or_public, so it's not a perfect
mirror of it. None of the current callers need it, but perhaps people
would like these functions to be consistent.

Tom Lane suggested to add missing_ok argument, although it is not a must-
requirement.

Actually I think he suggested the opposite.

--
Álvaro Herrera <alvherre@commandprompt.com>
The PostgreSQL Company - Command Prompt, Inc.
PostgreSQL Replication, Consulting, Custom Development, 24x7 support

#15KaiGai Kohei
kaigai@ak.jp.nec.com
In reply to: Alvaro Herrera (#14)
Re: Bug / shortcoming in has_*_privilege

(2010/10/07 2:05), Alvaro Herrera wrote:

Another thing that could raise eyebrows is that I chose to remove the
"missing_ok" argument from get_role_oid_or_public, so it's not a perfect
mirror of it. None of the current callers need it, but perhaps people
would like these functions to be consistent.

Tom Lane suggested to add missing_ok argument, although it is not a must-
requirement.

Actually I think he suggested the opposite.

Ahh, I understood his suggestion as literal.

Well, I'd like to mark this patch as 'ready for committer'.

Thanks,
--
KaiGai Kohei <kaigai@ak.jp.nec.com>

#16Itagaki Takahiro
itagaki.takahiro@gmail.com
In reply to: Alvaro Herrera (#11)
Re: Bug / shortcoming in has_*_privilege

Hi,

On Tue, Sep 7, 2010 at 6:16 AM, Alvaro Herrera
<alvherre@commandprompt.com> wrote:

Excerpts from Jim Nasby's message of jue jun 10 17:54:43 -0400 2010:

test_us@workbook=# select has_table_privilege( 'public', 'test', 'SELECT' );
ERROR:  role "public" does not exist

Here's a patch implementing this idea.

It specially treats only "public" in all lower cases, right?
The pseudo-role name is described as "PUBLIC" (upper) in docs,
but we accept only "public" (lower) as the pseudo-name.

BTW, does the patch need to be back-patched to older versions?
Since they use get_roleid_checked() instead of get_role_oid(), the fix
cannot be applied cleanly to them, though it will be similar codes.

--
Itagaki Takahiro

#17Robert Haas
robertmhaas@gmail.com
In reply to: Itagaki Takahiro (#16)
Re: Bug / shortcoming in has_*_privilege

On Tue, Oct 12, 2010 at 10:05 PM, Itagaki Takahiro
<itagaki.takahiro@gmail.com> wrote:

BTW, does the patch need to be back-patched to older versions?
Since they use get_roleid_checked() instead of get_role_oid(), the fix
cannot be applied cleanly to them, though it will be similar codes.

I would interpret this a a feature, not a bug fix, so no back-patch.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#18Alvaro Herrera
alvherre@commandprompt.com
In reply to: Itagaki Takahiro (#16)
Re: Bug / shortcoming in has_*_privilege

Excerpts from Itagaki Takahiro's message of mar oct 12 23:05:36 -0300 2010:

Hi,

On Tue, Sep 7, 2010 at 6:16 AM, Alvaro Herrera
<alvherre@commandprompt.com> wrote:

Excerpts from Jim Nasby's message of jue jun 10 17:54:43 -0400 2010:

test_us@workbook=# select has_table_privilege( 'public', 'test', 'SELECT' );
ERROR:  role "public" does not exist

Here's a patch implementing this idea.

It specially treats only "public" in all lower cases, right?
The pseudo-role name is described as "PUBLIC" (upper) in docs,
but we accept only "public" (lower) as the pseudo-name.

Yeah, only lowercase. Identifiers other than "public" (all lowercase)
are allowed as role names, so we cannot use them for this purpose. Keep
in mind that the docs say PUBLIC without the quotes, which is lowercased.

BTW, does the patch need to be back-patched to older versions?

There's no intention to do so.

--
Álvaro Herrera <alvherre@commandprompt.com>
The PostgreSQL Company - Command Prompt, Inc.
PostgreSQL Replication, Consulting, Custom Development, 24x7 support

#19Itagaki Takahiro
itagaki.takahiro@gmail.com
In reply to: Alvaro Herrera (#18)
Re: Bug / shortcoming in has_*_privilege

<alvherre@commandprompt.com> wrote:

Excerpts from Jim Nasby's message of jue jun 10 17:54:43 -0400 2010:

test_us@workbook=# select has_table_privilege( 'public', 'test', 'SELECT' );
ERROR:  role "public" does not exist

Here's a patch implementing this idea.

I applied it almost as-is, except an unused variable in
get_role_oid_or_public().

BTW, does the patch need to be back-patched to older versions?

There's no intention to do so.

OK. Applied only to HEAD. The issue was reported as a bug,
but we will consider the change as an improvement.

--
Itagaki Takahiro