CAST(a.attname AS sql_identifier) AS column_name,
CAST(pr.type AS character_data) AS privilege_type,
CAST(
- CASE WHEN aclcontains(c.relacl,
- makeaclitem(grantee.oid, u_grantor.oid, pr.type, true))
+ CASE WHEN
+ -- object owner always has grant options
+ pg_has_role(grantee.oid, c.relowner, 'USAGE')
+ OR aclcontains(c.relacl,
+ makeaclitem(grantee.oid, u_grantor.oid, pr.type, true))
+ OR aclcontains(a.attacl,
+ makeaclitem(grantee.oid, u_grantor.oid, pr.type, true))
THEN 'YES' ELSE 'NO' END AS character_data) AS is_grantable
FROM pg_attribute a,
UNION ALL
SELECT 0::oid, 'PUBLIC'
) AS grantee (oid, rolname),
- (SELECT 'SELECT' UNION ALL
- SELECT 'INSERT' UNION ALL
- SELECT 'UPDATE' UNION ALL
- SELECT 'REFERENCES') AS pr (type)
+ (VALUES ('SELECT'),
+ ('INSERT'),
+ ('UPDATE'),
+ ('REFERENCES')) AS pr (type)
WHERE a.attrelid = c.oid
AND c.relnamespace = nc.oid
AND a.attnum > 0
AND NOT a.attisdropped
AND c.relkind IN ('r', 'v')
- AND aclcontains(c.relacl,
- makeaclitem(grantee.oid, u_grantor.oid, pr.type, false))
+ AND (aclcontains(c.relacl,
+ makeaclitem(grantee.oid, u_grantor.oid, pr.type, false))
+ OR aclcontains(a.attacl,
+ makeaclitem(grantee.oid, u_grantor.oid, pr.type, false)))
AND (pg_has_role(u_grantor.oid, 'USAGE')
OR pg_has_role(grantee.oid, 'USAGE')
OR grantee.rolname = 'PUBLIC');
AND a.attnum > 0 AND NOT a.attisdropped AND c.relkind in ('r', 'v')
AND (pg_has_role(c.relowner, 'USAGE')
- OR has_table_privilege(c.oid, 'SELECT')
- OR has_table_privilege(c.oid, 'INSERT')
- OR has_table_privilege(c.oid, 'UPDATE')
- OR has_table_privilege(c.oid, 'REFERENCES') );
+ OR has_column_privilege(c.oid, a.attnum,
+ 'SELECT, INSERT, UPDATE, REFERENCES'));
GRANT SELECT ON columns TO PUBLIC;
END AS cardinal_number)
AS position_in_unique_constraint
FROM pg_attribute a,
- (SELECT r.oid AS roid, r.relname, nc.nspname AS nc_nspname,
- nr.nspname AS nr_nspname,
+ (SELECT r.oid AS roid, r.relname, r.relowner,
+ nc.nspname AS nc_nspname, nr.nspname AS nr_nspname,
c.oid AS coid, c.conname, c.contype, c.confkey, c.confrelid,
_pg_expandarray(c.conkey) AS x
FROM pg_namespace nr, pg_class r, pg_namespace nc,
AND nc.oid = c.connamespace
AND c.contype IN ('p', 'u', 'f')
AND r.relkind = 'r'
- AND (NOT pg_is_other_temp_schema(nr.oid))
- AND (pg_has_role(r.relowner, 'USAGE')
- OR has_table_privilege(r.oid, 'SELECT')
- OR has_table_privilege(r.oid, 'INSERT')
- OR has_table_privilege(r.oid, 'UPDATE')
- OR has_table_privilege(r.oid, 'REFERENCES')) ) AS ss
+ AND (NOT pg_is_other_temp_schema(nr.oid)) ) AS ss
WHERE ss.roid = a.attrelid
AND a.attnum = (ss.x).x
- AND NOT a.attisdropped;
+ AND NOT a.attisdropped
+ AND (pg_has_role(relowner, 'USAGE')
+ OR has_column_privilege(roid, a.attnum,
+ 'SELECT, INSERT, UPDATE, REFERENCES'));
GRANT SELECT ON key_column_usage TO PUBLIC;
WHERE c.relkind = 'r'
AND con.contype = 'f'
AND (pkc.contype IN ('p', 'u') OR pkc.contype IS NULL)
- AND pg_has_role(c.relowner, 'USAGE');
+ AND (pg_has_role(c.relowner, 'USAGE')
+ -- SELECT privilege omitted, per SQL standard
+ OR has_table_privilege(c.oid, 'INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER')
+ OR has_any_column_privilege(c.oid, 'INSERT, UPDATE, REFERENCES') );
GRANT SELECT ON referential_constraints TO PUBLIC;
CAST(a.attname AS sql_identifier) AS column_name,
CAST(pr.type AS character_data) AS privilege_type,
CAST(
- CASE WHEN aclcontains(c.relacl,
- makeaclitem(g_grantee.oid, u_grantor.oid, pr.type, true))
+ CASE WHEN
+ -- object owner always has grant options
+ pg_has_role(g_grantee.oid, c.relowner, 'USAGE')
+ OR aclcontains(c.relacl,
+ makeaclitem(g_grantee.oid, u_grantor.oid, pr.type, true))
+ OR aclcontains(a.attacl,
+ makeaclitem(g_grantee.oid, u_grantor.oid, pr.type, true))
THEN 'YES' ELSE 'NO' END AS character_data) AS is_grantable
FROM pg_attribute a,
pg_namespace nc,
pg_authid u_grantor,
pg_authid g_grantee,
- (SELECT 'SELECT' UNION ALL
- SELECT 'INSERT' UNION ALL
- SELECT 'UPDATE' UNION ALL
- SELECT 'REFERENCES') AS pr (type)
+ (VALUES ('SELECT'),
+ ('INSERT'),
+ ('UPDATE'),
+ ('REFERENCES')) AS pr (type)
WHERE a.attrelid = c.oid
AND c.relnamespace = nc.oid
AND a.attnum > 0
AND NOT a.attisdropped
AND c.relkind IN ('r', 'v')
- AND aclcontains(c.relacl,
- makeaclitem(g_grantee.oid, u_grantor.oid, pr.type, false))
+ AND (aclcontains(c.relacl,
+ makeaclitem(g_grantee.oid, u_grantor.oid, pr.type, false))
+ OR aclcontains(a.attacl,
+ makeaclitem(g_grantee.oid, u_grantor.oid, pr.type, false)))
AND (u_grantor.rolname IN (SELECT role_name FROM enabled_roles)
OR g_grantee.rolname IN (SELECT role_name FROM enabled_roles));
CAST(p.proname AS sql_identifier) AS routine_name,
CAST('EXECUTE' AS character_data) AS privilege_type,
CAST(
- CASE WHEN aclcontains(p.proacl,
- makeaclitem(g_grantee.oid, u_grantor.oid, 'EXECUTE', true))
+ CASE WHEN
+ -- object owner always has grant options
+ pg_has_role(g_grantee.oid, p.proowner, 'USAGE')
+ OR aclcontains(p.proacl,
+ makeaclitem(g_grantee.oid, u_grantor.oid, 'EXECUTE', true))
THEN 'YES' ELSE 'NO' END AS character_data) AS is_grantable
FROM pg_proc p,
CAST(c.relname AS sql_identifier) AS table_name,
CAST(pr.type AS character_data) AS privilege_type,
CAST(
- CASE WHEN aclcontains(c.relacl,
- makeaclitem(g_grantee.oid, u_grantor.oid, pr.type, true))
+ CASE WHEN
+ -- object owner always has grant options
+ pg_has_role(g_grantee.oid, c.relowner, 'USAGE')
+ OR aclcontains(c.relacl,
+ makeaclitem(g_grantee.oid, u_grantor.oid, pr.type, true))
THEN 'YES' ELSE 'NO' END AS character_data) AS is_grantable,
CAST('NO' AS character_data) AS with_hierarchy
pg_namespace nc,
pg_authid u_grantor,
pg_authid g_grantee,
- (SELECT 'SELECT' UNION ALL
- SELECT 'INSERT' UNION ALL
- SELECT 'UPDATE' UNION ALL
- SELECT 'DELETE' UNION ALL
- SELECT 'TRUNCATE' UNION ALL
- SELECT 'REFERENCES' UNION ALL
- SELECT 'TRIGGER') AS pr (type)
+ (VALUES ('SELECT'),
+ ('INSERT'),
+ ('UPDATE'),
+ ('DELETE'),
+ ('TRUNCATE'),
+ ('REFERENCES'),
+ ('TRIGGER')) AS pr (type)
WHERE c.relnamespace = nc.oid
AND c.relkind IN ('r', 'v')
CAST('FOREIGN DATA WRAPPER' AS character_data) AS object_type,
CAST('USAGE' AS character_data) AS privilege_type,
CAST(
- CASE WHEN aclcontains(fdw.fdwacl,
- makeaclitem(g_grantee.oid, u_grantor.oid, 'USAGE', true))
+ CASE WHEN
+ -- object owner always has grant options
+ pg_has_role(g_grantee.oid, fdw.fdwowner, 'USAGE')
+ OR aclcontains(fdw.fdwacl,
+ makeaclitem(g_grantee.oid, u_grantor.oid, 'USAGE', true))
THEN 'YES' ELSE 'NO' END AS character_data) AS is_grantable
FROM pg_foreign_data_wrapper fdw,
CAST('FOREIGN SERVER' AS character_data) AS object_type,
CAST('USAGE' AS character_data) AS privilege_type,
CAST(
- CASE WHEN aclcontains(srv.srvacl,
- makeaclitem(g_grantee.oid, u_grantor.oid, 'USAGE', true))
+ CASE WHEN
+ -- object owner always has grant options
+ pg_has_role(g_grantee.oid, srv.srvowner, 'USAGE')
+ OR aclcontains(srv.srvacl,
+ makeaclitem(g_grantee.oid, u_grantor.oid, 'USAGE', true))
THEN 'YES' ELSE 'NO' END AS character_data) AS is_grantable
FROM pg_foreign_server srv,
CAST(p.proname AS sql_identifier) AS routine_name,
CAST('EXECUTE' AS character_data) AS privilege_type,
CAST(
- CASE WHEN aclcontains(p.proacl,
- makeaclitem(grantee.oid, u_grantor.oid, 'EXECUTE', true))
+ CASE WHEN
+ -- object owner always has grant options
+ pg_has_role(grantee.oid, p.proowner, 'USAGE')
+ OR aclcontains(p.proacl,
+ makeaclitem(grantee.oid, u_grantor.oid, 'EXECUTE', true))
THEN 'YES' ELSE 'NO' END AS character_data) AS is_grantable
FROM pg_proc p,
AND c.relkind = 'S'
AND (NOT pg_is_other_temp_schema(nc.oid))
AND (pg_has_role(c.relowner, 'USAGE')
- OR has_table_privilege(c.oid, 'SELECT')
- OR has_table_privilege(c.oid, 'UPDATE') );
+ OR has_table_privilege(c.oid, 'SELECT, UPDATE') );
GRANT SELECT ON sequences TO PUBLIC;
AND (NOT pg_is_other_temp_schema(nr.oid))
AND (pg_has_role(r.relowner, 'USAGE')
-- SELECT privilege omitted, per SQL standard
- OR has_table_privilege(r.oid, 'INSERT')
- OR has_table_privilege(r.oid, 'UPDATE')
- OR has_table_privilege(r.oid, 'DELETE')
- OR has_table_privilege(r.oid, 'TRUNCATE')
- OR has_table_privilege(r.oid, 'REFERENCES')
- OR has_table_privilege(r.oid, 'TRIGGER') )
+ OR has_table_privilege(r.oid, 'INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER')
+ OR has_any_column_privilege(r.oid, 'INSERT, UPDATE, REFERENCES') )
UNION
AND r.relkind = 'r'
AND (NOT pg_is_other_temp_schema(nr.oid))
AND (pg_has_role(r.relowner, 'USAGE')
- OR has_table_privilege(r.oid, 'SELECT')
- OR has_table_privilege(r.oid, 'INSERT')
- OR has_table_privilege(r.oid, 'UPDATE')
- OR has_table_privilege(r.oid, 'DELETE')
- OR has_table_privilege(r.oid, 'TRUNCATE')
- OR has_table_privilege(r.oid, 'REFERENCES')
- OR has_table_privilege(r.oid, 'TRIGGER') );
+ -- SELECT privilege omitted, per SQL standard
+ OR has_table_privilege(r.oid, 'INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER')
+ OR has_any_column_privilege(r.oid, 'INSERT, UPDATE, REFERENCES') );
GRANT SELECT ON table_constraints TO PUBLIC;
CAST(c.relname AS sql_identifier) AS table_name,
CAST(pr.type AS character_data) AS privilege_type,
CAST(
- CASE WHEN aclcontains(c.relacl,
- makeaclitem(grantee.oid, u_grantor.oid, pr.type, true))
+ CASE WHEN
+ -- object owner always has grant options
+ pg_has_role(grantee.oid, c.relowner, 'USAGE')
+ OR aclcontains(c.relacl,
+ makeaclitem(grantee.oid, u_grantor.oid, pr.type, true))
THEN 'YES' ELSE 'NO' END AS character_data) AS is_grantable,
CAST('NO' AS character_data) AS with_hierarchy
UNION ALL
SELECT 0::oid, 'PUBLIC'
) AS grantee (oid, rolname),
- (SELECT 'SELECT' UNION ALL
- SELECT 'INSERT' UNION ALL
- SELECT 'UPDATE' UNION ALL
- SELECT 'DELETE' UNION ALL
- SELECT 'TRUNCATE' UNION ALL
- SELECT 'REFERENCES' UNION ALL
- SELECT 'TRIGGER') AS pr (type)
+ (VALUES ('SELECT'),
+ ('INSERT'),
+ ('UPDATE'),
+ ('DELETE'),
+ ('TRUNCATE'),
+ ('REFERENCES'),
+ ('TRIGGER')) AS pr (type)
WHERE c.relnamespace = nc.oid
AND c.relkind IN ('r', 'v')
AND c.relkind IN ('r', 'v')
AND (NOT pg_is_other_temp_schema(nc.oid))
AND (pg_has_role(c.relowner, 'USAGE')
- OR has_table_privilege(c.oid, 'SELECT')
- OR has_table_privilege(c.oid, 'INSERT')
- OR has_table_privilege(c.oid, 'UPDATE')
- OR has_table_privilege(c.oid, 'DELETE')
- OR has_table_privilege(c.oid, 'TRUNCATE')
- OR has_table_privilege(c.oid, 'REFERENCES')
- OR has_table_privilege(c.oid, 'TRIGGER') );
+ OR has_table_privilege(c.oid, 'SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER')
+ OR has_any_column_privilege(c.oid, 'SELECT, INSERT, UPDATE, REFERENCES') );
GRANT SELECT ON tables TO PUBLIC;
CAST(null AS time_stamp) AS created
FROM pg_namespace n, pg_class c, pg_trigger t,
- (SELECT 4, 'INSERT' UNION ALL
- SELECT 8, 'DELETE' UNION ALL
- SELECT 16, 'UPDATE') AS em (num, text)
+ (VALUES (4, 'INSERT'),
+ (8, 'DELETE'),
+ (16, 'UPDATE')) AS em (num, text)
WHERE n.oid = c.relnamespace
AND c.oid = t.tgrelid
AND (NOT pg_is_other_temp_schema(n.oid))
AND (pg_has_role(c.relowner, 'USAGE')
-- SELECT privilege omitted, per SQL standard
- OR has_table_privilege(c.oid, 'INSERT')
- OR has_table_privilege(c.oid, 'UPDATE')
- OR has_table_privilege(c.oid, 'DELETE')
- OR has_table_privilege(c.oid, 'TRUNCATE')
- OR has_table_privilege(c.oid, 'REFERENCES')
- OR has_table_privilege(c.oid, 'TRIGGER') );
+ OR has_table_privilege(c.oid, 'INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER')
+ OR has_any_column_privilege(c.oid, 'INSERT, UPDATE, REFERENCES') );
GRANT SELECT ON triggers TO PUBLIC;
CAST('FOREIGN DATA WRAPPER' AS character_data) AS object_type,
CAST('USAGE' AS character_data) AS privilege_type,
CAST(
- CASE WHEN aclcontains(fdw.fdwacl,
- makeaclitem(grantee.oid, u_grantor.oid, 'USAGE', true))
+ CASE WHEN
+ -- object owner always has grant options
+ pg_has_role(grantee.oid, fdw.fdwowner, 'USAGE')
+ OR aclcontains(fdw.fdwacl,
+ makeaclitem(grantee.oid, u_grantor.oid, 'USAGE', true))
THEN 'YES' ELSE 'NO' END AS character_data) AS is_grantable
FROM pg_foreign_data_wrapper fdw,
CAST('FOREIGN SERVER' AS character_data) AS object_type,
CAST('USAGE' AS character_data) AS privilege_type,
CAST(
- CASE WHEN aclcontains(srv.srvacl,
- makeaclitem(grantee.oid, u_grantor.oid, 'USAGE', true))
+ CASE WHEN
+ -- object owner always has grant options
+ pg_has_role(grantee.oid, srv.srvowner, 'USAGE')
+ OR aclcontains(srv.srvacl,
+ makeaclitem(grantee.oid, u_grantor.oid, 'USAGE', true))
THEN 'YES' ELSE 'NO' END AS character_data) AS is_grantable
FROM pg_foreign_server srv,
AND c.relkind = 'v'
AND (NOT pg_is_other_temp_schema(nc.oid))
AND (pg_has_role(c.relowner, 'USAGE')
- OR has_table_privilege(c.oid, 'SELECT')
- OR has_table_privilege(c.oid, 'INSERT')
- OR has_table_privilege(c.oid, 'UPDATE')
- OR has_table_privilege(c.oid, 'DELETE')
- OR has_table_privilege(c.oid, 'TRUNCATE')
- OR has_table_privilege(c.oid, 'REFERENCES')
- OR has_table_privilege(c.oid, 'TRIGGER') );
+ OR has_table_privilege(c.oid, 'SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER')
+ OR has_any_column_privilege(c.oid, 'SELECT, INSERT, UPDATE, REFERENCES') );
GRANT SELECT ON views TO PUBLIC;
#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
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);
}
+/*
+ * 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.
static AclMode
convert_table_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, "SELECT") == 0)
- return ACL_SELECT;
- if (pg_strcasecmp(priv_type, "SELECT WITH GRANT OPTION") == 0)
- return ACL_GRANT_OPTION_FOR(ACL_SELECT);
-
- 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);
-
- 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 (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);
-
- 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);
-
- 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);
-
- 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);
-
- 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;
-
- 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 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_database_privilege variants
- * These are all named "has_database_privilege" at the SQL level.
- * They take various combinations of database name, database OID,
+ * 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, false if not, or NULL if object doesn't exist.
+ * 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_database_privilege_name_name
- * Check user privileges on a database given
- * name username, text databasename, and text priv name.
+ * 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_database_privilege_name_name(PG_FUNCTION_ARGS)
+has_any_column_privilege_name_name(PG_FUNCTION_ARGS)
{
- Name username = PG_GETARG_NAME(0);
- text *databasename = PG_GETARG_TEXT_P(1);
+ 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 databaseoid;
+ Oid tableoid;
AclMode mode;
AclResult aclresult;
- roleid = get_roleid_checked(NameStr(*username));
- databaseoid = convert_database_name(databasename);
- mode = convert_database_priv_string(priv_type_text);
+ roleid = get_roleid_checked(NameStr(*rolename));
+ tableoid = convert_table_name(tablename);
+ mode = convert_column_priv_string(priv_type_text);
- aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
+ /* 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_database_privilege_name
- * Check user privileges on a database given
- * text databasename and text priv name.
+ * 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_database_privilege_name(PG_FUNCTION_ARGS)
+has_any_column_privilege_name(PG_FUNCTION_ARGS)
{
- text *databasename = PG_GETARG_TEXT_P(0);
+ text *tablename = PG_GETARG_TEXT_P(0);
text *priv_type_text = PG_GETARG_TEXT_P(1);
Oid roleid;
- Oid databaseoid;
+ Oid tableoid;
AclMode mode;
AclResult aclresult;
roleid = GetUserId();
- databaseoid = convert_database_name(databasename);
- mode = convert_database_priv_string(priv_type_text);
+ tableoid = convert_table_name(tablename);
+ mode = convert_column_priv_string(priv_type_text);
- aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
+ /* 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_database_privilege_name_id
- * Check user privileges on a database given
- * name usename, database oid, and text priv name.
+ * 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_database_privilege_name_id(PG_FUNCTION_ARGS)
+has_any_column_privilege_name_id(PG_FUNCTION_ARGS)
{
Name username = PG_GETARG_NAME(0);
- Oid databaseoid = PG_GETARG_OID(1);
+ 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_database_priv_string(priv_type_text);
+ mode = convert_column_priv_string(priv_type_text);
- if (!SearchSysCacheExists(DATABASEOID,
- ObjectIdGetDatum(databaseoid),
+ if (!SearchSysCacheExists(RELOID,
+ ObjectIdGetDatum(tableoid),
0, 0, 0))
PG_RETURN_NULL();
- aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
+ /* 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_database_privilege_id
- * Check user privileges on a database given
- * database oid, and text priv name.
+ * 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_database_privilege_id(PG_FUNCTION_ARGS)
+has_any_column_privilege_id(PG_FUNCTION_ARGS)
{
- Oid databaseoid = PG_GETARG_OID(0);
+ 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_database_priv_string(priv_type_text);
+ mode = convert_column_priv_string(priv_type_text);
- if (!SearchSysCacheExists(DATABASEOID,
- ObjectIdGetDatum(databaseoid),
+ if (!SearchSysCacheExists(RELOID,
+ ObjectIdGetDatum(tableoid),
0, 0, 0))
PG_RETURN_NULL();
- aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
+ /* 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_database_privilege_id_name
- * Check user privileges on a database given
- * roleid, text databasename, and text priv name.
+ * 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_database_privilege_id_name(PG_FUNCTION_ARGS)
+has_any_column_privilege_id_name(PG_FUNCTION_ARGS)
{
Oid roleid = PG_GETARG_OID(0);
- text *databasename = PG_GETARG_TEXT_P(1);
+ text *tablename = PG_GETARG_TEXT_P(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
- Oid databaseoid;
+ Oid tableoid;
AclMode mode;
AclResult aclresult;
- databaseoid = convert_database_name(databasename);
- mode = convert_database_priv_string(priv_type_text);
+ tableoid = convert_table_name(tablename);
+ mode = convert_column_priv_string(priv_type_text);
- aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
+ /* 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_database_privilege_id_id
- * Check user privileges on a database given
- * roleid, database oid, and text priv name.
+ * 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_database_privilege_id_id(PG_FUNCTION_ARGS)
+has_any_column_privilege_id_id(PG_FUNCTION_ARGS)
{
Oid roleid = PG_GETARG_OID(0);
- Oid databaseoid = PG_GETARG_OID(1);
+ Oid tableoid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
AclMode mode;
AclResult aclresult;
- mode = convert_database_priv_string(priv_type_text);
+ mode = convert_column_priv_string(priv_type_text);
- if (!SearchSysCacheExists(DATABASEOID,
- ObjectIdGetDatum(databaseoid),
+ if (!SearchSysCacheExists(RELOID,
+ ObjectIdGetDatum(tableoid),
0, 0, 0))
PG_RETURN_NULL();
- aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
+ /* 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);
}
-/*
- * Support routines for has_database_privilege family.
- */
/*
- * Given a database name expressed as a string, look it up and return Oid
+ * 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.
*/
-static Oid
-convert_database_name(text *databasename)
-{
- char *dbname = text_to_cstring(databasename);
- Oid oid;
-
- oid = get_database_oid(dbname);
- if (!OidIsValid(oid))
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_DATABASE),
- errmsg("database \"%s\" does not exist", dbname)));
-
- return oid;
-}
/*
- * convert_database_priv_string
- * Convert text string to AclMode value.
+ * 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 AclMode
-convert_database_priv_string(text *priv_type_text)
+static int
+column_privilege_check(Oid tableoid, AttrNumber attnum,
+ Oid roleid, AclMode mode)
{
- char *priv_type = text_to_cstring(priv_type_text);
+ 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, "CREATE") == 0)
- return ACL_CREATE;
- if (pg_strcasecmp(priv_type, "CREATE WITH GRANT OPTION") == 0)
- return ACL_GRANT_OPTION_FOR(ACL_CREATE);
+ if (!SearchSysCacheExists(RELOID,
+ ObjectIdGetDatum(tableoid),
+ 0, 0, 0))
+ return -1;
- 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);
+ aclresult = pg_class_aclcheck(tableoid, roleid, mode);
- 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 (aclresult == ACLCHECK_OK)
+ return true;
- 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);
+ /*
+ * 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);
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("unrecognized privilege type: \"%s\"", priv_type)));
- return ACL_NO_RIGHTS; /* keep compiler quiet */
-}
+ aclresult = pg_attribute_aclcheck(tableoid, attnum, roleid, mode);
+ return (aclresult == ACLCHECK_OK);
+}
/*
- * has_foreign_data_wrapper_privilege variants
- * These are all named "has_foreign_data_wrapper_privilege" at the SQL level.
- * They take various combinations of foreign-data wrapper name,
- * 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_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;
+
+ 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);
+
+ privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
+ if (privresult < 0)
+ PG_RETURN_NULL();
+ PG_RETURN_BOOL(privresult);
+}
/*
- * has_foreign_data_wrapper_privilege
- * Check user privileges on a foreign-data wrapper.
+ * has_column_privilege_name_name_attnum
+ * Check user privileges on a column given
+ * name username, text tablename, int attnum, and text priv name.
*/
-static Datum
-has_foreign_data_wrapper_privilege(Oid roleid, Oid fdwid, text *priv_type_text)
+Datum
+has_column_privilege_name_name_attnum(PG_FUNCTION_ARGS)
{
- 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)));
+ 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;
- aclresult = pg_foreign_data_wrapper_aclcheck(fdwid, roleid, mode);
+ roleid = get_roleid_checked(NameStr(*rolename));
+ tableoid = convert_table_name(tablename);
+ mode = convert_column_priv_string(priv_type_text);
- PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+ privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
+ if (privresult < 0)
+ PG_RETURN_NULL();
+ PG_RETURN_BOOL(privresult);
}
/*
- * has_foreign_data_wrapper_privilege_name_name
- * Check user privileges on a foreign-data wrapper given
- * name username, text fdwname, and text priv name.
+ * 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_foreign_data_wrapper_privilege_name_name(PG_FUNCTION_ARGS)
+has_column_privilege_name_id_name(PG_FUNCTION_ARGS)
{
Name username = PG_GETARG_NAME(0);
- char *fdwname = text_to_cstring(PG_GETARG_TEXT_P(1));
- text *priv_type_text = PG_GETARG_TEXT_P(2);
+ 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);
- return has_foreign_data_wrapper_privilege(get_roleid_checked(NameStr(*username)),
- GetForeignDataWrapperOidByName(fdwname, false),
- priv_type_text);
+ privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
+ if (privresult < 0)
+ PG_RETURN_NULL();
+ PG_RETURN_BOOL(privresult);
}
/*
- * has_foreign_data_wrapper_privilege_name
- * Check user privileges on a foreign-data wrapper given
- * text fdwname and text priv name.
+ * 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);
+}
+
+
+/*
+ * has_database_privilege variants
+ * These are all named "has_database_privilege" at the SQL level.
+ * They take various combinations of database name, database 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, or NULL if object doesn't exist.
+ */
+
+/*
+ * has_database_privilege_name_name
+ * Check user privileges on a database given
+ * name username, text databasename, and text priv name.
+ */
+Datum
+has_database_privilege_name_name(PG_FUNCTION_ARGS)
+{
+ Name username = PG_GETARG_NAME(0);
+ text *databasename = PG_GETARG_TEXT_P(1);
+ text *priv_type_text = PG_GETARG_TEXT_P(2);
+ Oid roleid;
+ Oid databaseoid;
+ AclMode mode;
+ AclResult aclresult;
+
+ roleid = get_roleid_checked(NameStr(*username));
+ databaseoid = convert_database_name(databasename);
+ mode = convert_database_priv_string(priv_type_text);
+
+ aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * has_database_privilege_name
+ * Check user privileges on a database given
+ * text databasename and text priv name.
+ * current_user is assumed
+ */
+Datum
+has_database_privilege_name(PG_FUNCTION_ARGS)
+{
+ text *databasename = PG_GETARG_TEXT_P(0);
+ text *priv_type_text = PG_GETARG_TEXT_P(1);
+ Oid roleid;
+ Oid databaseoid;
+ AclMode mode;
+ AclResult aclresult;
+
+ roleid = GetUserId();
+ databaseoid = convert_database_name(databasename);
+ mode = convert_database_priv_string(priv_type_text);
+
+ aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * has_database_privilege_name_id
+ * Check user privileges on a database given
+ * name usename, database oid, and text priv name.
+ */
+Datum
+has_database_privilege_name_id(PG_FUNCTION_ARGS)
+{
+ Name username = PG_GETARG_NAME(0);
+ Oid databaseoid = 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_database_priv_string(priv_type_text);
+
+ if (!SearchSysCacheExists(DATABASEOID,
+ ObjectIdGetDatum(databaseoid),
+ 0, 0, 0))
+ PG_RETURN_NULL();
+
+ aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * has_database_privilege_id
+ * Check user privileges on a database given
+ * database oid, and text priv name.
+ * current_user is assumed
+ */
+Datum
+has_database_privilege_id(PG_FUNCTION_ARGS)
+{
+ Oid databaseoid = PG_GETARG_OID(0);
+ text *priv_type_text = PG_GETARG_TEXT_P(1);
+ Oid roleid;
+ AclMode mode;
+ AclResult aclresult;
+
+ roleid = GetUserId();
+ mode = convert_database_priv_string(priv_type_text);
+
+ if (!SearchSysCacheExists(DATABASEOID,
+ ObjectIdGetDatum(databaseoid),
+ 0, 0, 0))
+ PG_RETURN_NULL();
+
+ aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * has_database_privilege_id_name
+ * Check user privileges on a database given
+ * roleid, text databasename, and text priv name.
+ */
+Datum
+has_database_privilege_id_name(PG_FUNCTION_ARGS)
+{
+ Oid roleid = PG_GETARG_OID(0);
+ text *databasename = PG_GETARG_TEXT_P(1);
+ text *priv_type_text = PG_GETARG_TEXT_P(2);
+ Oid databaseoid;
+ AclMode mode;
+ AclResult aclresult;
+
+ databaseoid = convert_database_name(databasename);
+ mode = convert_database_priv_string(priv_type_text);
+
+ aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * has_database_privilege_id_id
+ * Check user privileges on a database given
+ * roleid, database oid, and text priv name.
+ */
+Datum
+has_database_privilege_id_id(PG_FUNCTION_ARGS)
+{
+ Oid roleid = PG_GETARG_OID(0);
+ Oid databaseoid = PG_GETARG_OID(1);
+ text *priv_type_text = PG_GETARG_TEXT_P(2);
+ AclMode mode;
+ AclResult aclresult;
+
+ mode = convert_database_priv_string(priv_type_text);
+
+ if (!SearchSysCacheExists(DATABASEOID,
+ ObjectIdGetDatum(databaseoid),
+ 0, 0, 0))
+ PG_RETURN_NULL();
+
+ aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * Support routines for has_database_privilege family.
+ */
+
+/*
+ * Given a database name expressed as a string, look it up and return Oid
+ */
+static Oid
+convert_database_name(text *databasename)
+{
+ char *dbname = text_to_cstring(databasename);
+ Oid oid;
+
+ oid = get_database_oid(dbname);
+ if (!OidIsValid(oid))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_DATABASE),
+ errmsg("database \"%s\" does not exist", dbname)));
+
+ return oid;
+}
+
+/*
+ * convert_database_priv_string
+ * Convert text string to AclMode value.
+ */
+static AclMode
+convert_database_priv_string(text *priv_type_text)
+{
+ 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);
+
+}
+
+
+/*
+ * has_foreign_data_wrapper_privilege variants
+ * These are all named "has_foreign_data_wrapper_privilege" at the SQL level.
+ * They take various combinations of foreign-data wrapper name,
+ * 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.
+ */
+
+/*
+ * has_foreign_data_wrapper_privilege_name_name
+ * Check user privileges on a foreign-data wrapper given
+ * name username, text fdwname, and text priv name.
+ */
+Datum
+has_foreign_data_wrapper_privilege_name_name(PG_FUNCTION_ARGS)
+{
+ Name username = PG_GETARG_NAME(0);
+ text *fdwname = PG_GETARG_TEXT_P(1);
+ text *priv_type_text = PG_GETARG_TEXT_P(2);
+ Oid roleid;
+ Oid fdwid;
+ AclMode mode;
+ AclResult aclresult;
+
+ 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);
+}
+
+/*
+ * has_foreign_data_wrapper_privilege_name
+ * Check user privileges on a foreign-data wrapper given
+ * text fdwname and text priv name.
* current_user is assumed
*/
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;
- return has_foreign_data_wrapper_privilege(GetUserId(),
- GetForeignDataWrapperOidByName(fdwname, false),
- priv_type_text);
+ roleid = GetUserId();
+ 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);
}
/*
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);
}
/*
{
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);
- return has_foreign_data_wrapper_privilege(GetUserId(), fdwid,
- priv_type_text);
+ aclresult = pg_foreign_data_wrapper_aclcheck(fdwid, roleid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
/*
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);
}
/*
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);
+}
- return has_foreign_data_wrapper_privilege(roleid, fdwid, priv_type_text);
+/*
+ * 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 convert_any_priv_string(priv_type_text, foreign_data_wrapper_priv_map);
}
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);
}
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);
}
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.
* privilege, false if not.
*/
-/*
- * 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
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);
}
/*
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);
}
/*
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);
+
+ aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode);
- return has_server_privilege(get_roleid_checked(NameStr(*username)), serverid,
- priv_type_text);
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
/*
{
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);
- return has_server_privilege(GetUserId(), serverid, priv_type_text);
+ aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
/*
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);
+
+ aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode);
- return has_server_privilege(roleid,
- GetForeignServerOidByName(servername, false),
- priv_type_text);
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
/*
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 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 has_server_privilege(roleid, serverid, priv_type_text);
+ return convert_any_priv_string(priv_type_text, server_priv_map);
}
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);
}
/*
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);
}
/*