diff options
Diffstat (limited to 'src/backend/utils/adt/acl.c')
-rw-r--r-- | src/backend/utils/adt/acl.c | 1186 |
1 files changed, 933 insertions, 253 deletions
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c index cb0ebf46941..64d55b6b1ce 100644 --- a/src/backend/utils/adt/acl.c +++ b/src/backend/utils/adt/acl.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.146 2009/01/22 20:16:06 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.147 2009/02/06 21:15:11 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -32,6 +32,12 @@ #include "utils/syscache.h" +typedef struct +{ + const char *name; + AclMode value; +} priv_map; + /* * We frequently need to test whether a given role is a member of some other * role. In most of these tests the "given role" is the same, namely the @@ -77,17 +83,25 @@ static Acl *recursive_revoke(Acl *acl, Oid grantee, AclMode revoke_privs, static int oidComparator(const void *arg1, const void *arg2); static AclMode convert_priv_string(text *priv_type_text); +static AclMode convert_any_priv_string(text *priv_type_text, + const priv_map *privileges); static Oid convert_table_name(text *tablename); static AclMode convert_table_priv_string(text *priv_type_text); +static AttrNumber convert_column_name(Oid tableoid, text *column); +static AclMode convert_column_priv_string(text *priv_type_text); static Oid convert_database_name(text *databasename); static AclMode convert_database_priv_string(text *priv_type_text); +static Oid convert_foreign_data_wrapper_name(text *fdwname); +static AclMode convert_foreign_data_wrapper_priv_string(text *priv_type_text); static Oid convert_function_name(text *functionname); static AclMode convert_function_priv_string(text *priv_type_text); static Oid convert_language_name(text *languagename); static AclMode convert_language_priv_string(text *priv_type_text); static Oid convert_schema_name(text *schemaname); static AclMode convert_schema_priv_string(text *priv_type_text); +static Oid convert_server_name(text *servername); +static AclMode convert_server_priv_string(text *priv_type_text); static Oid convert_tablespace_name(text *tablespacename); static AclMode convert_tablespace_priv_string(text *priv_type_text); static AclMode convert_role_priv_string(text *priv_type_text); @@ -1420,6 +1434,63 @@ convert_priv_string(text *priv_type_text) /* + * convert_any_priv_string: recognize privilege strings for has_foo_privilege + * + * We accept a comma-separated list of case-insensitive privilege names, + * producing a bitmask of the OR'd privilege bits. We are liberal about + * whitespace between items, not so much about whitespace within items. + * The allowed privilege names are given as an array of priv_map structs, + * terminated by one with a NULL name pointer. + */ +static AclMode +convert_any_priv_string(text *priv_type_text, + const priv_map *privileges) +{ + AclMode result = 0; + char *priv_type = text_to_cstring(priv_type_text); + char *chunk; + char *next_chunk; + + /* We rely on priv_type being a private, modifiable string */ + for (chunk = priv_type; chunk; chunk = next_chunk) + { + int chunk_len; + const priv_map *this_priv; + + /* Split string at commas */ + next_chunk = strchr(chunk, ','); + if (next_chunk) + *next_chunk++ = '\0'; + + /* Drop leading/trailing whitespace in this chunk */ + while (*chunk && isspace((unsigned char) *chunk)) + chunk++; + chunk_len = strlen(chunk); + while (chunk_len > 0 && isspace((unsigned char) chunk[chunk_len - 1])) + chunk_len--; + chunk[chunk_len] = '\0'; + + /* Match to the privileges list */ + for (this_priv = privileges; this_priv->name; this_priv++) + { + if (pg_strcasecmp(this_priv->name, chunk) == 0) + { + result |= this_priv->value; + break; + } + } + if (!this_priv->name) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("unrecognized privilege type: \"%s\"", chunk))); + } + + pfree(priv_type); + return result; +} + + +/* * has_table_privilege variants * These are all named "has_table_privilege" at the SQL level. * They take various combinations of relation name, relation OID, @@ -1610,55 +1681,651 @@ convert_table_name(text *tablename) static AclMode convert_table_priv_string(text *priv_type_text) { - char *priv_type = text_to_cstring(priv_type_text); + static const priv_map table_priv_map[] = { + { "SELECT", ACL_SELECT }, + { "SELECT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_SELECT) }, + { "INSERT", ACL_INSERT }, + { "INSERT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_INSERT) }, + { "UPDATE", ACL_UPDATE }, + { "UPDATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_UPDATE) }, + { "DELETE", ACL_DELETE }, + { "DELETE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_DELETE) }, + { "TRUNCATE", ACL_TRUNCATE }, + { "TRUNCATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_TRUNCATE) }, + { "REFERENCES", ACL_REFERENCES }, + { "REFERENCES WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_REFERENCES) }, + { "TRIGGER", ACL_TRIGGER }, + { "TRIGGER WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_TRIGGER) }, + { "RULE", 0 }, /* ignore old RULE privileges */ + { "RULE WITH GRANT OPTION", 0 }, + { NULL, 0 } + }; + + return convert_any_priv_string(priv_type_text, table_priv_map); +} + + +/* + * has_any_column_privilege variants + * These are all named "has_any_column_privilege" at the SQL level. + * They take various combinations of relation name, relation OID, + * user name, user OID, or implicit user = current_user. + * + * The result is a boolean value: true if user has the indicated + * privilege for any column of the table, false if not. The variants + * that take a relation OID return NULL if the OID doesn't exist. + */ + +/* + * has_any_column_privilege_name_name + * Check user privileges on any column of a table given + * name username, text tablename, and text priv name. + */ +Datum +has_any_column_privilege_name_name(PG_FUNCTION_ARGS) +{ + Name rolename = PG_GETARG_NAME(0); + text *tablename = PG_GETARG_TEXT_P(1); + text *priv_type_text = PG_GETARG_TEXT_P(2); + Oid roleid; + Oid tableoid; + AclMode mode; + AclResult aclresult; + + roleid = get_roleid_checked(NameStr(*rolename)); + tableoid = convert_table_name(tablename); + mode = convert_column_priv_string(priv_type_text); + + /* First check at table level, then examine each column if needed */ + aclresult = pg_class_aclcheck(tableoid, roleid, mode); + if (aclresult != ACLCHECK_OK) + aclresult = pg_attribute_aclcheck_all(tableoid, roleid, mode, + ACLMASK_ANY); + + PG_RETURN_BOOL(aclresult == ACLCHECK_OK); +} + +/* + * has_any_column_privilege_name + * Check user privileges on any column of a table given + * text tablename and text priv name. + * current_user is assumed + */ +Datum +has_any_column_privilege_name(PG_FUNCTION_ARGS) +{ + text *tablename = PG_GETARG_TEXT_P(0); + text *priv_type_text = PG_GETARG_TEXT_P(1); + Oid roleid; + Oid tableoid; + AclMode mode; + AclResult aclresult; + + roleid = GetUserId(); + tableoid = convert_table_name(tablename); + mode = convert_column_priv_string(priv_type_text); + + /* First check at table level, then examine each column if needed */ + aclresult = pg_class_aclcheck(tableoid, roleid, mode); + if (aclresult != ACLCHECK_OK) + aclresult = pg_attribute_aclcheck_all(tableoid, roleid, mode, + ACLMASK_ANY); + + PG_RETURN_BOOL(aclresult == ACLCHECK_OK); +} + +/* + * has_any_column_privilege_name_id + * Check user privileges on any column of a table given + * name usename, table oid, and text priv name. + */ +Datum +has_any_column_privilege_name_id(PG_FUNCTION_ARGS) +{ + Name username = PG_GETARG_NAME(0); + Oid tableoid = PG_GETARG_OID(1); + text *priv_type_text = PG_GETARG_TEXT_P(2); + Oid roleid; + AclMode mode; + AclResult aclresult; + + roleid = get_roleid_checked(NameStr(*username)); + mode = convert_column_priv_string(priv_type_text); + + if (!SearchSysCacheExists(RELOID, + ObjectIdGetDatum(tableoid), + 0, 0, 0)) + PG_RETURN_NULL(); + + /* First check at table level, then examine each column if needed */ + aclresult = pg_class_aclcheck(tableoid, roleid, mode); + if (aclresult != ACLCHECK_OK) + aclresult = pg_attribute_aclcheck_all(tableoid, roleid, mode, + ACLMASK_ANY); + + PG_RETURN_BOOL(aclresult == ACLCHECK_OK); +} + +/* + * has_any_column_privilege_id + * Check user privileges on any column of a table given + * table oid, and text priv name. + * current_user is assumed + */ +Datum +has_any_column_privilege_id(PG_FUNCTION_ARGS) +{ + Oid tableoid = PG_GETARG_OID(0); + text *priv_type_text = PG_GETARG_TEXT_P(1); + Oid roleid; + AclMode mode; + AclResult aclresult; + + roleid = GetUserId(); + mode = convert_column_priv_string(priv_type_text); + + if (!SearchSysCacheExists(RELOID, + ObjectIdGetDatum(tableoid), + 0, 0, 0)) + PG_RETURN_NULL(); + + /* First check at table level, then examine each column if needed */ + aclresult = pg_class_aclcheck(tableoid, roleid, mode); + if (aclresult != ACLCHECK_OK) + aclresult = pg_attribute_aclcheck_all(tableoid, roleid, mode, + ACLMASK_ANY); + + PG_RETURN_BOOL(aclresult == ACLCHECK_OK); +} + +/* + * has_any_column_privilege_id_name + * Check user privileges on any column of a table given + * roleid, text tablename, and text priv name. + */ +Datum +has_any_column_privilege_id_name(PG_FUNCTION_ARGS) +{ + Oid roleid = PG_GETARG_OID(0); + text *tablename = PG_GETARG_TEXT_P(1); + text *priv_type_text = PG_GETARG_TEXT_P(2); + Oid tableoid; + AclMode mode; + AclResult aclresult; + + tableoid = convert_table_name(tablename); + mode = convert_column_priv_string(priv_type_text); + + /* First check at table level, then examine each column if needed */ + aclresult = pg_class_aclcheck(tableoid, roleid, mode); + if (aclresult != ACLCHECK_OK) + aclresult = pg_attribute_aclcheck_all(tableoid, roleid, mode, + ACLMASK_ANY); + + PG_RETURN_BOOL(aclresult == ACLCHECK_OK); +} + +/* + * has_any_column_privilege_id_id + * Check user privileges on any column of a table given + * roleid, table oid, and text priv name. + */ +Datum +has_any_column_privilege_id_id(PG_FUNCTION_ARGS) +{ + Oid roleid = PG_GETARG_OID(0); + Oid tableoid = PG_GETARG_OID(1); + text *priv_type_text = PG_GETARG_TEXT_P(2); + AclMode mode; + AclResult aclresult; + + mode = convert_column_priv_string(priv_type_text); + + if (!SearchSysCacheExists(RELOID, + ObjectIdGetDatum(tableoid), + 0, 0, 0)) + PG_RETURN_NULL(); + + /* First check at table level, then examine each column if needed */ + aclresult = pg_class_aclcheck(tableoid, roleid, mode); + if (aclresult != ACLCHECK_OK) + aclresult = pg_attribute_aclcheck_all(tableoid, roleid, mode, + ACLMASK_ANY); + + PG_RETURN_BOOL(aclresult == ACLCHECK_OK); +} + + +/* + * has_column_privilege variants + * These are all named "has_column_privilege" at the SQL level. + * They take various combinations of relation name, relation OID, + * column name, column attnum, user name, user OID, or + * implicit user = current_user. + * + * The result is a boolean value: true if user has the indicated + * privilege, false if not. The variants that take a relation OID + * and an integer attnum return NULL (rather than throwing an error) + * if the column doesn't exist or is dropped. + */ + +/* + * column_privilege_check: check column privileges, but don't throw an error + * for dropped column or table + * + * Returns 1 if have the privilege, 0 if not, -1 if dropped column/table. + */ +static int +column_privilege_check(Oid tableoid, AttrNumber attnum, + Oid roleid, AclMode mode) +{ + AclResult aclresult; + HeapTuple attTuple; + Form_pg_attribute attributeForm; /* - * Return mode from priv_type string + * First check if we have the privilege at the table level. We check + * existence of the pg_class row before risking calling pg_class_aclcheck. + * Note: it might seem there's a race condition against concurrent DROP, + * but really it's safe because there will be no syscache flush between + * here and there. So if we see the row in the syscache, so will + * pg_class_aclcheck. */ - if (pg_strcasecmp(priv_type, "SELECT") == 0) - return ACL_SELECT; - if (pg_strcasecmp(priv_type, "SELECT WITH GRANT OPTION") == 0) - return ACL_GRANT_OPTION_FOR(ACL_SELECT); + if (!SearchSysCacheExists(RELOID, + ObjectIdGetDatum(tableoid), + 0, 0, 0)) + return -1; - if (pg_strcasecmp(priv_type, "INSERT") == 0) - return ACL_INSERT; - if (pg_strcasecmp(priv_type, "INSERT WITH GRANT OPTION") == 0) - return ACL_GRANT_OPTION_FOR(ACL_INSERT); + aclresult = pg_class_aclcheck(tableoid, roleid, mode); - if (pg_strcasecmp(priv_type, "UPDATE") == 0) - return ACL_UPDATE; - if (pg_strcasecmp(priv_type, "UPDATE WITH GRANT OPTION") == 0) - return ACL_GRANT_OPTION_FOR(ACL_UPDATE); + if (aclresult == ACLCHECK_OK) + return true; - if (pg_strcasecmp(priv_type, "DELETE") == 0) - return ACL_DELETE; - if (pg_strcasecmp(priv_type, "DELETE WITH GRANT OPTION") == 0) - return ACL_GRANT_OPTION_FOR(ACL_DELETE); + /* + * No table privilege, so try per-column privileges. Again, we have to + * check for dropped attribute first, and we rely on the syscache not to + * notice a concurrent drop before pg_attribute_aclcheck fetches the row. + */ + attTuple = SearchSysCache(ATTNUM, + ObjectIdGetDatum(tableoid), + Int16GetDatum(attnum), + 0, 0); + if (!HeapTupleIsValid(attTuple)) + return -1; + attributeForm = (Form_pg_attribute) GETSTRUCT(attTuple); + if (attributeForm->attisdropped) + { + ReleaseSysCache(attTuple); + return -1; + } + ReleaseSysCache(attTuple); - if (pg_strcasecmp(priv_type, "TRUNCATE") == 0) - return ACL_TRUNCATE; - if (pg_strcasecmp(priv_type, "TRUNCATE WITH GRANT OPTION") == 0) - return ACL_GRANT_OPTION_FOR(ACL_TRUNCATE); + aclresult = pg_attribute_aclcheck(tableoid, attnum, roleid, mode); - if (pg_strcasecmp(priv_type, "REFERENCES") == 0) - return ACL_REFERENCES; - if (pg_strcasecmp(priv_type, "REFERENCES WITH GRANT OPTION") == 0) - return ACL_GRANT_OPTION_FOR(ACL_REFERENCES); + return (aclresult == ACLCHECK_OK); +} - if (pg_strcasecmp(priv_type, "TRIGGER") == 0) - return ACL_TRIGGER; - if (pg_strcasecmp(priv_type, "TRIGGER WITH GRANT OPTION") == 0) - return ACL_GRANT_OPTION_FOR(ACL_TRIGGER); +/* + * has_column_privilege_name_name_name + * Check user privileges on a column given + * name username, text tablename, text colname, and text priv name. + */ +Datum +has_column_privilege_name_name_name(PG_FUNCTION_ARGS) +{ + Name rolename = PG_GETARG_NAME(0); + text *tablename = PG_GETARG_TEXT_P(1); + text *column = PG_GETARG_TEXT_P(2); + text *priv_type_text = PG_GETARG_TEXT_P(3); + Oid roleid; + Oid tableoid; + AttrNumber colattnum; + AclMode mode; + int privresult; - if (pg_strcasecmp(priv_type, "RULE") == 0) - return 0; /* ignore old RULE privileges */ - if (pg_strcasecmp(priv_type, "RULE WITH GRANT OPTION") == 0) - return 0; + roleid = get_roleid_checked(NameStr(*rolename)); + tableoid = convert_table_name(tablename); + colattnum = convert_column_name(tableoid, column); + mode = convert_column_priv_string(priv_type_text); - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("unrecognized privilege type: \"%s\"", priv_type))); - return ACL_NO_RIGHTS; /* keep compiler quiet */ + privresult = column_privilege_check(tableoid, colattnum, roleid, mode); + if (privresult < 0) + PG_RETURN_NULL(); + PG_RETURN_BOOL(privresult); +} + +/* + * has_column_privilege_name_name_attnum + * Check user privileges on a column given + * name username, text tablename, int attnum, and text priv name. + */ +Datum +has_column_privilege_name_name_attnum(PG_FUNCTION_ARGS) +{ + Name rolename = PG_GETARG_NAME(0); + text *tablename = PG_GETARG_TEXT_P(1); + AttrNumber colattnum = PG_GETARG_INT16(2); + text *priv_type_text = PG_GETARG_TEXT_P(3); + Oid roleid; + Oid tableoid; + AclMode mode; + int privresult; + + roleid = get_roleid_checked(NameStr(*rolename)); + tableoid = convert_table_name(tablename); + mode = convert_column_priv_string(priv_type_text); + + privresult = column_privilege_check(tableoid, colattnum, roleid, mode); + if (privresult < 0) + PG_RETURN_NULL(); + PG_RETURN_BOOL(privresult); +} + +/* + * has_column_privilege_name_id_name + * Check user privileges on a column given + * name username, table oid, text colname, and text priv name. + */ +Datum +has_column_privilege_name_id_name(PG_FUNCTION_ARGS) +{ + Name username = PG_GETARG_NAME(0); + Oid tableoid = PG_GETARG_OID(1); + text *column = PG_GETARG_TEXT_P(2); + text *priv_type_text = PG_GETARG_TEXT_P(3); + Oid roleid; + AttrNumber colattnum; + AclMode mode; + int privresult; + + roleid = get_roleid_checked(NameStr(*username)); + colattnum = convert_column_name(tableoid, column); + mode = convert_column_priv_string(priv_type_text); + + privresult = column_privilege_check(tableoid, colattnum, roleid, mode); + if (privresult < 0) + PG_RETURN_NULL(); + PG_RETURN_BOOL(privresult); +} + +/* + * has_column_privilege_name_id_attnum + * Check user privileges on a column given + * name username, table oid, int attnum, and text priv name. + */ +Datum +has_column_privilege_name_id_attnum(PG_FUNCTION_ARGS) +{ + Name username = PG_GETARG_NAME(0); + Oid tableoid = PG_GETARG_OID(1); + AttrNumber colattnum = PG_GETARG_INT16(2); + text *priv_type_text = PG_GETARG_TEXT_P(3); + Oid roleid; + AclMode mode; + int privresult; + + roleid = get_roleid_checked(NameStr(*username)); + mode = convert_column_priv_string(priv_type_text); + + privresult = column_privilege_check(tableoid, colattnum, roleid, mode); + if (privresult < 0) + PG_RETURN_NULL(); + PG_RETURN_BOOL(privresult); +} + +/* + * has_column_privilege_id_name_name + * Check user privileges on a column given + * oid roleid, text tablename, text colname, and text priv name. + */ +Datum +has_column_privilege_id_name_name(PG_FUNCTION_ARGS) +{ + Oid roleid = PG_GETARG_OID(0); + text *tablename = PG_GETARG_TEXT_P(1); + text *column = PG_GETARG_TEXT_P(2); + text *priv_type_text = PG_GETARG_TEXT_P(3); + Oid tableoid; + AttrNumber colattnum; + AclMode mode; + int privresult; + + tableoid = convert_table_name(tablename); + colattnum = convert_column_name(tableoid, column); + mode = convert_column_priv_string(priv_type_text); + + privresult = column_privilege_check(tableoid, colattnum, roleid, mode); + if (privresult < 0) + PG_RETURN_NULL(); + PG_RETURN_BOOL(privresult); +} + +/* + * has_column_privilege_id_name_attnum + * Check user privileges on a column given + * oid roleid, text tablename, int attnum, and text priv name. + */ +Datum +has_column_privilege_id_name_attnum(PG_FUNCTION_ARGS) +{ + Oid roleid = PG_GETARG_OID(0); + text *tablename = PG_GETARG_TEXT_P(1); + AttrNumber colattnum = PG_GETARG_INT16(2); + text *priv_type_text = PG_GETARG_TEXT_P(3); + Oid tableoid; + AclMode mode; + int privresult; + + tableoid = convert_table_name(tablename); + mode = convert_column_priv_string(priv_type_text); + + privresult = column_privilege_check(tableoid, colattnum, roleid, mode); + if (privresult < 0) + PG_RETURN_NULL(); + PG_RETURN_BOOL(privresult); +} + +/* + * has_column_privilege_id_id_name + * Check user privileges on a column given + * oid roleid, table oid, text colname, and text priv name. + */ +Datum +has_column_privilege_id_id_name(PG_FUNCTION_ARGS) +{ + Oid roleid = PG_GETARG_OID(0); + Oid tableoid = PG_GETARG_OID(1); + text *column = PG_GETARG_TEXT_P(2); + text *priv_type_text = PG_GETARG_TEXT_P(3); + AttrNumber colattnum; + AclMode mode; + int privresult; + + colattnum = convert_column_name(tableoid, column); + mode = convert_column_priv_string(priv_type_text); + + privresult = column_privilege_check(tableoid, colattnum, roleid, mode); + if (privresult < 0) + PG_RETURN_NULL(); + PG_RETURN_BOOL(privresult); +} + +/* + * has_column_privilege_id_id_attnum + * Check user privileges on a column given + * oid roleid, table oid, int attnum, and text priv name. + */ +Datum +has_column_privilege_id_id_attnum(PG_FUNCTION_ARGS) +{ + Oid roleid = PG_GETARG_OID(0); + Oid tableoid = PG_GETARG_OID(1); + AttrNumber colattnum = PG_GETARG_INT16(2); + text *priv_type_text = PG_GETARG_TEXT_P(3); + AclMode mode; + int privresult; + + mode = convert_column_priv_string(priv_type_text); + + privresult = column_privilege_check(tableoid, colattnum, roleid, mode); + if (privresult < 0) + PG_RETURN_NULL(); + PG_RETURN_BOOL(privresult); +} + +/* + * has_column_privilege_name_name + * Check user privileges on a column given + * text tablename, text colname, and text priv name. + * current_user is assumed + */ +Datum +has_column_privilege_name_name(PG_FUNCTION_ARGS) +{ + text *tablename = PG_GETARG_TEXT_P(0); + text *column = PG_GETARG_TEXT_P(1); + text *priv_type_text = PG_GETARG_TEXT_P(2); + Oid roleid; + Oid tableoid; + AttrNumber colattnum; + AclMode mode; + int privresult; + + roleid = GetUserId(); + tableoid = convert_table_name(tablename); + colattnum = convert_column_name(tableoid, column); + mode = convert_column_priv_string(priv_type_text); + + privresult = column_privilege_check(tableoid, colattnum, roleid, mode); + if (privresult < 0) + PG_RETURN_NULL(); + PG_RETURN_BOOL(privresult); +} + +/* + * has_column_privilege_name_attnum + * Check user privileges on a column given + * text tablename, int attnum, and text priv name. + * current_user is assumed + */ +Datum +has_column_privilege_name_attnum(PG_FUNCTION_ARGS) +{ + text *tablename = PG_GETARG_TEXT_P(0); + AttrNumber colattnum = PG_GETARG_INT16(1); + text *priv_type_text = PG_GETARG_TEXT_P(2); + Oid roleid; + Oid tableoid; + AclMode mode; + int privresult; + + roleid = GetUserId(); + tableoid = convert_table_name(tablename); + mode = convert_column_priv_string(priv_type_text); + + privresult = column_privilege_check(tableoid, colattnum, roleid, mode); + if (privresult < 0) + PG_RETURN_NULL(); + PG_RETURN_BOOL(privresult); +} + +/* + * has_column_privilege_id_name + * Check user privileges on a column given + * table oid, text colname, and text priv name. + * current_user is assumed + */ +Datum +has_column_privilege_id_name(PG_FUNCTION_ARGS) +{ + Oid tableoid = PG_GETARG_OID(0); + text *column = PG_GETARG_TEXT_P(1); + text *priv_type_text = PG_GETARG_TEXT_P(2); + Oid roleid; + AttrNumber colattnum; + AclMode mode; + int privresult; + + roleid = GetUserId(); + colattnum = convert_column_name(tableoid, column); + mode = convert_column_priv_string(priv_type_text); + + privresult = column_privilege_check(tableoid, colattnum, roleid, mode); + if (privresult < 0) + PG_RETURN_NULL(); + PG_RETURN_BOOL(privresult); +} + +/* + * has_column_privilege_id_attnum + * Check user privileges on a column given + * table oid, int attnum, and text priv name. + * current_user is assumed + */ +Datum +has_column_privilege_id_attnum(PG_FUNCTION_ARGS) +{ + Oid tableoid = PG_GETARG_OID(0); + AttrNumber colattnum = PG_GETARG_INT16(1); + text *priv_type_text = PG_GETARG_TEXT_P(2); + Oid roleid; + AclMode mode; + int privresult; + + roleid = GetUserId(); + mode = convert_column_priv_string(priv_type_text); + + privresult = column_privilege_check(tableoid, colattnum, roleid, mode); + if (privresult < 0) + PG_RETURN_NULL(); + PG_RETURN_BOOL(privresult); +} + +/* + * Support routines for has_column_privilege family. + */ + +/* + * Given a table OID and a column name expressed as a string, look it up + * and return the column number + */ +static AttrNumber +convert_column_name(Oid tableoid, text *column) +{ + AttrNumber attnum; + char *colname; + + colname = text_to_cstring(column); + attnum = get_attnum(tableoid, colname); + if (attnum == InvalidAttrNumber) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_COLUMN), + errmsg("column \"%s\" of relation \"%s\" does not exist", + colname, get_rel_name(tableoid)))); + pfree(colname); + return attnum; +} + +/* + * convert_column_priv_string + * Convert text string to AclMode value. + */ +static AclMode +convert_column_priv_string(text *priv_type_text) +{ + static const priv_map column_priv_map[] = { + { "SELECT", ACL_SELECT }, + { "SELECT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_SELECT) }, + { "INSERT", ACL_INSERT }, + { "INSERT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_INSERT) }, + { "UPDATE", ACL_UPDATE }, + { "UPDATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_UPDATE) }, + { "REFERENCES", ACL_REFERENCES }, + { "REFERENCES WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_REFERENCES) }, + { NULL, 0 } + }; + + return convert_any_priv_string(priv_type_text, column_priv_map); } @@ -1856,35 +2523,20 @@ convert_database_name(text *databasename) static AclMode convert_database_priv_string(text *priv_type_text) { - char *priv_type = text_to_cstring(priv_type_text); - - /* - * Return mode from priv_type string - */ - if (pg_strcasecmp(priv_type, "CREATE") == 0) - return ACL_CREATE; - if (pg_strcasecmp(priv_type, "CREATE WITH GRANT OPTION") == 0) - return ACL_GRANT_OPTION_FOR(ACL_CREATE); - - if (pg_strcasecmp(priv_type, "TEMPORARY") == 0) - return ACL_CREATE_TEMP; - if (pg_strcasecmp(priv_type, "TEMPORARY WITH GRANT OPTION") == 0) - return ACL_GRANT_OPTION_FOR(ACL_CREATE_TEMP); + static const priv_map database_priv_map[] = { + { "CREATE", ACL_CREATE }, + { "CREATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE) }, + { "TEMPORARY", ACL_CREATE_TEMP }, + { "TEMPORARY WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE_TEMP) }, + { "TEMP", ACL_CREATE_TEMP }, + { "TEMP WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE_TEMP) }, + { "CONNECT", ACL_CONNECT }, + { "CONNECT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CONNECT) }, + { NULL, 0 } + }; + + return convert_any_priv_string(priv_type_text, database_priv_map); - if (pg_strcasecmp(priv_type, "TEMP") == 0) - return ACL_CREATE_TEMP; - if (pg_strcasecmp(priv_type, "TEMP WITH GRANT OPTION") == 0) - return ACL_GRANT_OPTION_FOR(ACL_CREATE_TEMP); - - if (pg_strcasecmp(priv_type, "CONNECT") == 0) - return ACL_CONNECT; - if (pg_strcasecmp(priv_type, "CONNECT WITH GRANT OPTION") == 0) - return ACL_GRANT_OPTION_FOR(ACL_CONNECT); - - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("unrecognized privilege type: \"%s\"", priv_type))); - return ACL_NO_RIGHTS; /* keep compiler quiet */ } @@ -1895,34 +2547,8 @@ convert_database_priv_string(text *priv_type_text) * fdw OID, user name, user OID, or implicit user = current_user. * * The result is a boolean value: true if user has the indicated - * privilege, false if not. The variants that take an OID return - * NULL if the OID doesn't exist. - */ - -/* - * has_foreign_data_wrapper_privilege - * Check user privileges on a foreign-data wrapper. + * privilege, false if not. */ -static Datum -has_foreign_data_wrapper_privilege(Oid roleid, Oid fdwid, text *priv_type_text) -{ - AclResult aclresult; - AclMode mode = ACL_NO_RIGHTS; - char *priv_type = text_to_cstring(priv_type_text); - - if (pg_strcasecmp(priv_type, "USAGE") == 0) - mode = ACL_USAGE; - else if (pg_strcasecmp(priv_type, "USAGE WITH GRANT OPTION") == 0) - mode = ACL_GRANT_OPTION_FOR(ACL_USAGE); - else - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("unrecognized privilege type: \"%s\"", priv_type))); - - aclresult = pg_foreign_data_wrapper_aclcheck(fdwid, roleid, mode); - - PG_RETURN_BOOL(aclresult == ACLCHECK_OK); -} /* * has_foreign_data_wrapper_privilege_name_name @@ -1933,12 +2559,20 @@ Datum has_foreign_data_wrapper_privilege_name_name(PG_FUNCTION_ARGS) { Name username = PG_GETARG_NAME(0); - char *fdwname = text_to_cstring(PG_GETARG_TEXT_P(1)); + text *fdwname = PG_GETARG_TEXT_P(1); text *priv_type_text = PG_GETARG_TEXT_P(2); + Oid roleid; + Oid fdwid; + AclMode mode; + AclResult aclresult; - return has_foreign_data_wrapper_privilege(get_roleid_checked(NameStr(*username)), - GetForeignDataWrapperOidByName(fdwname, false), - priv_type_text); + roleid = get_roleid_checked(NameStr(*username)); + fdwid = convert_foreign_data_wrapper_name(fdwname); + mode = convert_foreign_data_wrapper_priv_string(priv_type_text); + + aclresult = pg_foreign_data_wrapper_aclcheck(fdwid, roleid, mode); + + PG_RETURN_BOOL(aclresult == ACLCHECK_OK); } /* @@ -1950,12 +2584,20 @@ has_foreign_data_wrapper_privilege_name_name(PG_FUNCTION_ARGS) Datum has_foreign_data_wrapper_privilege_name(PG_FUNCTION_ARGS) { - char *fdwname = text_to_cstring(PG_GETARG_TEXT_P(0)); + text *fdwname = PG_GETARG_TEXT_P(0); text *priv_type_text = PG_GETARG_TEXT_P(1); + Oid roleid; + Oid fdwid; + AclMode mode; + AclResult aclresult; + + roleid = GetUserId(); + fdwid = convert_foreign_data_wrapper_name(fdwname); + mode = convert_foreign_data_wrapper_priv_string(priv_type_text); - return has_foreign_data_wrapper_privilege(GetUserId(), - GetForeignDataWrapperOidByName(fdwname, false), - priv_type_text); + aclresult = pg_foreign_data_wrapper_aclcheck(fdwid, roleid, mode); + + PG_RETURN_BOOL(aclresult == ACLCHECK_OK); } /* @@ -1969,14 +2611,16 @@ has_foreign_data_wrapper_privilege_name_id(PG_FUNCTION_ARGS) Name username = PG_GETARG_NAME(0); Oid fdwid = PG_GETARG_OID(1); text *priv_type_text = PG_GETARG_TEXT_P(2); + Oid roleid; + AclMode mode; + AclResult aclresult; - if (!SearchSysCacheExists(FOREIGNDATAWRAPPEROID, - ObjectIdGetDatum(fdwid), - 0, 0, 0)) - PG_RETURN_NULL(); + roleid = get_roleid_checked(NameStr(*username)); + mode = convert_foreign_data_wrapper_priv_string(priv_type_text); + + aclresult = pg_foreign_data_wrapper_aclcheck(fdwid, roleid, mode); - return has_foreign_data_wrapper_privilege(get_roleid_checked(NameStr(*username)), - fdwid, priv_type_text); + PG_RETURN_BOOL(aclresult == ACLCHECK_OK); } /* @@ -1990,14 +2634,16 @@ has_foreign_data_wrapper_privilege_id(PG_FUNCTION_ARGS) { Oid fdwid = PG_GETARG_OID(0); text *priv_type_text = PG_GETARG_TEXT_P(1); + Oid roleid; + AclMode mode; + AclResult aclresult; - if (!SearchSysCacheExists(FOREIGNDATAWRAPPEROID, - ObjectIdGetDatum(fdwid), - 0, 0, 0)) - PG_RETURN_NULL(); + roleid = GetUserId(); + mode = convert_foreign_data_wrapper_priv_string(priv_type_text); + + aclresult = pg_foreign_data_wrapper_aclcheck(fdwid, roleid, mode); - return has_foreign_data_wrapper_privilege(GetUserId(), fdwid, - priv_type_text); + PG_RETURN_BOOL(aclresult == ACLCHECK_OK); } /* @@ -2009,12 +2655,18 @@ Datum has_foreign_data_wrapper_privilege_id_name(PG_FUNCTION_ARGS) { Oid roleid = PG_GETARG_OID(0); - char *fdwname = text_to_cstring(PG_GETARG_TEXT_P(1)); + text *fdwname = PG_GETARG_TEXT_P(1); text *priv_type_text = PG_GETARG_TEXT_P(2); + Oid fdwid; + AclMode mode; + AclResult aclresult; + + fdwid = convert_foreign_data_wrapper_name(fdwname); + mode = convert_foreign_data_wrapper_priv_string(priv_type_text); + + aclresult = pg_foreign_data_wrapper_aclcheck(fdwid, roleid, mode); - return has_foreign_data_wrapper_privilege(roleid, - GetForeignDataWrapperOidByName(fdwname, false), - priv_type_text); + PG_RETURN_BOOL(aclresult == ACLCHECK_OK); } /* @@ -2028,13 +2680,45 @@ has_foreign_data_wrapper_privilege_id_id(PG_FUNCTION_ARGS) Oid roleid = PG_GETARG_OID(0); Oid fdwid = PG_GETARG_OID(1); text *priv_type_text = PG_GETARG_TEXT_P(2); + AclMode mode; + AclResult aclresult; - if (!SearchSysCacheExists(FOREIGNDATAWRAPPEROID, - ObjectIdGetDatum(fdwid), - 0, 0, 0)) - PG_RETURN_NULL(); + mode = convert_foreign_data_wrapper_priv_string(priv_type_text); + + aclresult = pg_foreign_data_wrapper_aclcheck(fdwid, roleid, mode); + + PG_RETURN_BOOL(aclresult == ACLCHECK_OK); +} + +/* + * Support routines for has_foreign_data_wrapper_privilege family. + */ + +/* + * Given a FDW name expressed as a string, look it up and return Oid + */ +static Oid +convert_foreign_data_wrapper_name(text *fdwname) +{ + char *fdwstr = text_to_cstring(fdwname); + + return GetForeignDataWrapperOidByName(fdwstr, false); +} + +/* + * convert_foreign_data_wrapper_priv_string + * Convert text string to AclMode value. + */ +static AclMode +convert_foreign_data_wrapper_priv_string(text *priv_type_text) +{ + static const priv_map foreign_data_wrapper_priv_map[] = { + { "USAGE", ACL_USAGE }, + { "USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_USAGE) }, + { NULL, 0 } + }; - return has_foreign_data_wrapper_privilege(roleid, fdwid, priv_type_text); + return convert_any_priv_string(priv_type_text, foreign_data_wrapper_priv_map); } @@ -2234,20 +2918,13 @@ convert_function_name(text *functionname) static AclMode convert_function_priv_string(text *priv_type_text) { - char *priv_type = text_to_cstring(priv_type_text); - - /* - * Return mode from priv_type string - */ - if (pg_strcasecmp(priv_type, "EXECUTE") == 0) - return ACL_EXECUTE; - if (pg_strcasecmp(priv_type, "EXECUTE WITH GRANT OPTION") == 0) - return ACL_GRANT_OPTION_FOR(ACL_EXECUTE); + static const priv_map function_priv_map[] = { + { "EXECUTE", ACL_EXECUTE }, + { "EXECUTE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_EXECUTE) }, + { NULL, 0 } + }; - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("unrecognized privilege type: \"%s\"", priv_type))); - return ACL_NO_RIGHTS; /* keep compiler quiet */ + return convert_any_priv_string(priv_type_text, function_priv_map); } @@ -2447,20 +3124,13 @@ convert_language_name(text *languagename) static AclMode convert_language_priv_string(text *priv_type_text) { - char *priv_type = text_to_cstring(priv_type_text); - - /* - * Return mode from priv_type string - */ - if (pg_strcasecmp(priv_type, "USAGE") == 0) - return ACL_USAGE; - if (pg_strcasecmp(priv_type, "USAGE WITH GRANT OPTION") == 0) - return ACL_GRANT_OPTION_FOR(ACL_USAGE); + static const priv_map language_priv_map[] = { + { "USAGE", ACL_USAGE }, + { "USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_USAGE) }, + { NULL, 0 } + }; - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("unrecognized privilege type: \"%s\"", priv_type))); - return ACL_NO_RIGHTS; /* keep compiler quiet */ + return convert_any_priv_string(priv_type_text, language_priv_map); } @@ -2660,27 +3330,18 @@ convert_schema_name(text *schemaname) static AclMode convert_schema_priv_string(text *priv_type_text) { - char *priv_type = text_to_cstring(priv_type_text); - - /* - * Return mode from priv_type string - */ - if (pg_strcasecmp(priv_type, "CREATE") == 0) - return ACL_CREATE; - if (pg_strcasecmp(priv_type, "CREATE WITH GRANT OPTION") == 0) - return ACL_GRANT_OPTION_FOR(ACL_CREATE); - - if (pg_strcasecmp(priv_type, "USAGE") == 0) - return ACL_USAGE; - if (pg_strcasecmp(priv_type, "USAGE WITH GRANT OPTION") == 0) - return ACL_GRANT_OPTION_FOR(ACL_USAGE); - - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("unrecognized privilege type: \"%s\"", priv_type))); - return ACL_NO_RIGHTS; /* keep compiler quiet */ + static const priv_map schema_priv_map[] = { + { "CREATE", ACL_CREATE }, + { "CREATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE) }, + { "USAGE", ACL_USAGE }, + { "USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_USAGE) }, + { NULL, 0 } + }; + + return convert_any_priv_string(priv_type_text, schema_priv_map); } + /* * has_server_privilege variants * These are all named "has_server_privilege" at the SQL level. @@ -2692,31 +3353,6 @@ convert_schema_priv_string(text *priv_type_text) */ /* - * has_server_privilege - * Check user privileges on a foreign server. - */ -static Datum -has_server_privilege(Oid roleid, Oid serverid, text *priv_type_text) -{ - AclResult aclresult; - AclMode mode = ACL_NO_RIGHTS; - char *priv_type = text_to_cstring(priv_type_text); - - if (pg_strcasecmp(priv_type, "USAGE") == 0) - mode = ACL_USAGE; - else if (pg_strcasecmp(priv_type, "USAGE WITH GRANT OPTION") == 0) - mode = ACL_GRANT_OPTION_FOR(ACL_USAGE); - else - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("unrecognized privilege type: \"%s\"", priv_type))); - - aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode); - - PG_RETURN_BOOL(aclresult == ACLCHECK_OK); -} - -/* * has_server_privilege_name_name * Check user privileges on a foreign server given * name username, text servername, and text priv name. @@ -2725,12 +3361,20 @@ Datum has_server_privilege_name_name(PG_FUNCTION_ARGS) { Name username = PG_GETARG_NAME(0); - char *servername = text_to_cstring(PG_GETARG_TEXT_P(1)); + text *servername = PG_GETARG_TEXT_P(1); text *priv_type_text = PG_GETARG_TEXT_P(2); + Oid roleid; + Oid serverid; + AclMode mode; + AclResult aclresult; + + roleid = get_roleid_checked(NameStr(*username)); + serverid = convert_server_name(servername); + mode = convert_server_priv_string(priv_type_text); + + aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode); - return has_server_privilege(get_roleid_checked(NameStr(*username)), - GetForeignServerOidByName(servername, false), - priv_type_text); + PG_RETURN_BOOL(aclresult == ACLCHECK_OK); } /* @@ -2742,12 +3386,20 @@ has_server_privilege_name_name(PG_FUNCTION_ARGS) Datum has_server_privilege_name(PG_FUNCTION_ARGS) { - char *servername = text_to_cstring(PG_GETARG_TEXT_P(0)); + text *servername = PG_GETARG_TEXT_P(0); text *priv_type_text = PG_GETARG_TEXT_P(1); + Oid roleid; + Oid serverid; + AclMode mode; + AclResult aclresult; + + roleid = GetUserId(); + serverid = convert_server_name(servername); + mode = convert_server_priv_string(priv_type_text); + + aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode); - return has_server_privilege(GetUserId(), - GetForeignServerOidByName(servername, false), - priv_type_text); + PG_RETURN_BOOL(aclresult == ACLCHECK_OK); } /* @@ -2761,14 +3413,16 @@ has_server_privilege_name_id(PG_FUNCTION_ARGS) Name username = PG_GETARG_NAME(0); Oid serverid = PG_GETARG_OID(1); text *priv_type_text = PG_GETARG_TEXT_P(2); + Oid roleid; + AclMode mode; + AclResult aclresult; - if (!SearchSysCacheExists(FOREIGNSERVEROID, - ObjectIdGetDatum(serverid), - 0, 0, 0)) - PG_RETURN_NULL(); + roleid = get_roleid_checked(NameStr(*username)); + mode = convert_server_priv_string(priv_type_text); - return has_server_privilege(get_roleid_checked(NameStr(*username)), serverid, - priv_type_text); + aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode); + + PG_RETURN_BOOL(aclresult == ACLCHECK_OK); } /* @@ -2782,13 +3436,16 @@ has_server_privilege_id(PG_FUNCTION_ARGS) { Oid serverid = PG_GETARG_OID(0); text *priv_type_text = PG_GETARG_TEXT_P(1); + Oid roleid; + AclMode mode; + AclResult aclresult; - if (!SearchSysCacheExists(FOREIGNSERVEROID, - ObjectIdGetDatum(serverid), - 0, 0, 0)) - PG_RETURN_NULL(); + roleid = GetUserId(); + mode = convert_server_priv_string(priv_type_text); + + aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode); - return has_server_privilege(GetUserId(), serverid, priv_type_text); + PG_RETURN_BOOL(aclresult == ACLCHECK_OK); } /* @@ -2800,12 +3457,18 @@ Datum has_server_privilege_id_name(PG_FUNCTION_ARGS) { Oid roleid = PG_GETARG_OID(0); - char *servername = text_to_cstring(PG_GETARG_TEXT_P(1)); + text *servername = PG_GETARG_TEXT_P(1); text *priv_type_text = PG_GETARG_TEXT_P(2); + Oid serverid; + AclMode mode; + AclResult aclresult; + + serverid = convert_server_name(servername); + mode = convert_server_priv_string(priv_type_text); - return has_server_privilege(roleid, - GetForeignServerOidByName(servername, false), - priv_type_text); + aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode); + + PG_RETURN_BOOL(aclresult == ACLCHECK_OK); } /* @@ -2819,13 +3482,45 @@ has_server_privilege_id_id(PG_FUNCTION_ARGS) Oid roleid = PG_GETARG_OID(0); Oid serverid = PG_GETARG_OID(1); text *priv_type_text = PG_GETARG_TEXT_P(2); + AclMode mode; + AclResult aclresult; - if (!SearchSysCacheExists(FOREIGNSERVEROID, - ObjectIdGetDatum(serverid), - 0, 0, 0)) - PG_RETURN_NULL(); + mode = convert_server_priv_string(priv_type_text); + + aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode); + + PG_RETURN_BOOL(aclresult == ACLCHECK_OK); +} + +/* + * Support routines for has_server_privilege family. + */ + +/* + * Given a server name expressed as a string, look it up and return Oid + */ +static Oid +convert_server_name(text *servername) +{ + char *serverstr = text_to_cstring(servername); - return has_server_privilege(roleid, serverid, priv_type_text); + return GetForeignServerOidByName(serverstr, false); +} + +/* + * convert_server_priv_string + * Convert text string to AclMode value. + */ +static AclMode +convert_server_priv_string(text *priv_type_text) +{ + static const priv_map server_priv_map[] = { + { "USAGE", ACL_USAGE }, + { "USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_USAGE) }, + { NULL, 0 } + }; + + return convert_any_priv_string(priv_type_text, server_priv_map); } @@ -3009,20 +3704,13 @@ convert_tablespace_name(text *tablespacename) static AclMode convert_tablespace_priv_string(text *priv_type_text) { - char *priv_type = text_to_cstring(priv_type_text); - - /* - * Return mode from priv_type string - */ - if (pg_strcasecmp(priv_type, "CREATE") == 0) - return ACL_CREATE; - if (pg_strcasecmp(priv_type, "CREATE WITH GRANT OPTION") == 0) - return ACL_GRANT_OPTION_FOR(ACL_CREATE); + static const priv_map tablespace_priv_map[] = { + { "CREATE", ACL_CREATE }, + { "CREATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE) }, + { NULL, 0 } + }; - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("unrecognized privilege type: \"%s\"", priv_type))); - return ACL_NO_RIGHTS; /* keep compiler quiet */ + return convert_any_priv_string(priv_type_text, tablespace_priv_map); } /* @@ -3192,25 +3880,17 @@ pg_has_role_id_id(PG_FUNCTION_ARGS) static AclMode convert_role_priv_string(text *priv_type_text) { - char *priv_type = text_to_cstring(priv_type_text); - - /* - * Return mode from priv_type string - */ - if (pg_strcasecmp(priv_type, "USAGE") == 0) - return ACL_USAGE; - if (pg_strcasecmp(priv_type, "MEMBER") == 0) - return ACL_CREATE; - if (pg_strcasecmp(priv_type, "USAGE WITH GRANT OPTION") == 0 || - pg_strcasecmp(priv_type, "USAGE WITH ADMIN OPTION") == 0 || - pg_strcasecmp(priv_type, "MEMBER WITH GRANT OPTION") == 0 || - pg_strcasecmp(priv_type, "MEMBER WITH ADMIN OPTION") == 0) - return ACL_GRANT_OPTION_FOR(ACL_CREATE); - - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("unrecognized privilege type: \"%s\"", priv_type))); - return ACL_NO_RIGHTS; /* keep compiler quiet */ + static const priv_map role_priv_map[] = { + { "USAGE", ACL_USAGE }, + { "MEMBER", ACL_CREATE }, + { "USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE) }, + { "USAGE WITH ADMIN OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE) }, + { "MEMBER WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE) }, + { "MEMBER WITH ADMIN OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE) }, + { NULL, 0 } + }; + + return convert_any_priv_string(priv_type_text, role_priv_map); } /* |