aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/src/sgml/func.sgml30
-rw-r--r--src/backend/utils/adt/acl.c214
-rw-r--r--src/include/catalog/catversion.h4
-rw-r--r--src/include/catalog/pg_proc.h15
-rw-r--r--src/include/utils/builtins.h8
-rw-r--r--src/test/regress/expected/privileges.out22
-rw-r--r--src/test/regress/sql/privileges.sql17
7 files changed, 304 insertions, 6 deletions
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index b84f7d18dd7..4e5b08d8e43 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.483 2009/07/22 18:07:26 petere Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.484 2009/08/03 21:11:39 joe Exp $ -->
<chapter id="functions">
<title>Functions and Operators</title>
@@ -11789,6 +11789,21 @@ SET search_path TO <replaceable>schema</> <optional>, <replaceable>schema</>, ..
<entry>does current user have privilege for foreign server</entry>
</row>
<row>
+ <entry><literal><function>has_sequence_privilege</function>(<parameter>user</parameter>,
+ <parameter>sequence</parameter>,
+ <parameter>privilege</parameter>)</literal>
+ </entry>
+ <entry><type>boolean</type></entry>
+ <entry>does user have privilege for sequence</entry>
+ </row>
+ <row>
+ <entry><literal><function>has_sequence_privilege</function>(<parameter>sequence</parameter>,
+ <parameter>privilege</parameter>)</literal>
+ </entry>
+ <entry><type>boolean</type></entry>
+ <entry>does current user have privilege for sequence</entry>
+ </row>
+ <row>
<entry><literal><function>has_table_privilege</function>(<parameter>user</parameter>,
<parameter>table</parameter>,
<parameter>privilege</parameter>)</literal>
@@ -11862,6 +11877,9 @@ SET search_path TO <replaceable>schema</> <optional>, <replaceable>schema</>, ..
<primary>has_server_privilege</primary>
</indexterm>
<indexterm>
+ <primary>has_sequence_privilege</primary>
+ </indexterm>
+ <indexterm>
<primary>has_table_privilege</primary>
</indexterm>
<indexterm>
@@ -11901,6 +11919,16 @@ SELECT has_table_privilege('joe', 'mytable', 'INSERT, SELECT WITH GRANT OPTION')
</para>
<para>
+ <function>has_sequence_privilege</function> checks whether a user
+ can access a sequence in a particular way. The possibilities for its
+ arguments are analogous to <function>has_table_privilege</function>.
+ The desired access privilege type must evaluate to one of
+ <literal>USAGE</literal>,
+ <literal>SELECT</literal>, or
+ <literal>UPDATE</literal>.
+ </para>
+
+ <para>
<function>has_any_column_privilege</function> checks whether a user can
access any column of a table in a particular way.
Its argument possibilities
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index 67c4ea36e36..83d93ad3483 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.148 2009/06/11 14:49:03 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.149 2009/08/03 21:11:39 joe Exp $
*
*-------------------------------------------------------------------------
*/
@@ -20,6 +20,7 @@
#include "catalog/pg_authid.h"
#include "catalog/pg_auth_members.h"
#include "catalog/pg_type.h"
+#include "catalog/pg_class.h"
#include "commands/dbcommands.h"
#include "commands/tablespace.h"
#include "foreign/foreign.h"
@@ -88,6 +89,7 @@ static AclMode convert_any_priv_string(text *priv_type_text,
static Oid convert_table_name(text *tablename);
static AclMode convert_table_priv_string(text *priv_type_text);
+static AclMode convert_sequence_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);
@@ -1704,6 +1706,216 @@ convert_table_priv_string(text *priv_type_text)
return convert_any_priv_string(priv_type_text, table_priv_map);
}
+/*
+ * has_sequence_privilege variants
+ * These are all named "has_sequence_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. The variants that take a relation OID
+ * return NULL if the OID doesn't exist.
+ */
+
+/*
+ * has_sequence_privilege_name_name
+ * Check user privileges on a sequence given
+ * name username, text sequencename, and text priv name.
+ */
+Datum
+has_sequence_privilege_name_name(PG_FUNCTION_ARGS)
+{
+ Name rolename = PG_GETARG_NAME(0);
+ text *sequencename = PG_GETARG_TEXT_P(1);
+ text *priv_type_text = PG_GETARG_TEXT_P(2);
+ Oid roleid;
+ Oid sequenceoid;
+ AclMode mode;
+ AclResult aclresult;
+
+ roleid = get_roleid_checked(NameStr(*rolename));
+ mode = convert_sequence_priv_string(priv_type_text);
+ sequenceoid = convert_table_name(sequencename);
+ if (get_rel_relkind(sequenceoid) != RELKIND_SEQUENCE)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is not a sequence",
+ text_to_cstring(sequencename))));
+
+ aclresult = pg_class_aclcheck(sequenceoid, roleid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * has_sequence_privilege_name
+ * Check user privileges on a sequence given
+ * text sequencename and text priv name.
+ * current_user is assumed
+ */
+Datum
+has_sequence_privilege_name(PG_FUNCTION_ARGS)
+{
+ text *sequencename = PG_GETARG_TEXT_P(0);
+ text *priv_type_text = PG_GETARG_TEXT_P(1);
+ Oid roleid;
+ Oid sequenceoid;
+ AclMode mode;
+ AclResult aclresult;
+
+ roleid = GetUserId();
+ mode = convert_sequence_priv_string(priv_type_text);
+ sequenceoid = convert_table_name(sequencename);
+ if (get_rel_relkind(sequenceoid) != RELKIND_SEQUENCE)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is not a sequence",
+ text_to_cstring(sequencename))));
+
+ aclresult = pg_class_aclcheck(sequenceoid, roleid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * has_sequence_privilege_name_id
+ * Check user privileges on a sequence given
+ * name usename, sequence oid, and text priv name.
+ */
+Datum
+has_sequence_privilege_name_id(PG_FUNCTION_ARGS)
+{
+ Name username = PG_GETARG_NAME(0);
+ Oid sequenceoid = PG_GETARG_OID(1);
+ text *priv_type_text = PG_GETARG_TEXT_P(2);
+ Oid roleid;
+ AclMode mode;
+ AclResult aclresult;
+ char relkind;
+
+ roleid = get_roleid_checked(NameStr(*username));
+ mode = convert_sequence_priv_string(priv_type_text);
+ relkind = get_rel_relkind(sequenceoid);
+ if (relkind == '\0')
+ PG_RETURN_NULL();
+ else if (relkind != RELKIND_SEQUENCE)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is not a sequence",
+ get_rel_name(sequenceoid))));
+
+ aclresult = pg_class_aclcheck(sequenceoid, roleid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * has_sequence_privilege_id
+ * Check user privileges on a sequence given
+ * sequence oid, and text priv name.
+ * current_user is assumed
+ */
+Datum
+has_sequence_privilege_id(PG_FUNCTION_ARGS)
+{
+ Oid sequenceoid = PG_GETARG_OID(0);
+ text *priv_type_text = PG_GETARG_TEXT_P(1);
+ Oid roleid;
+ AclMode mode;
+ AclResult aclresult;
+ char relkind;
+
+ roleid = GetUserId();
+ mode = convert_sequence_priv_string(priv_type_text);
+ relkind = get_rel_relkind(sequenceoid);
+ if (relkind == '\0')
+ PG_RETURN_NULL();
+ else if (relkind != RELKIND_SEQUENCE)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is not a sequence",
+ get_rel_name(sequenceoid))));
+
+ aclresult = pg_class_aclcheck(sequenceoid, roleid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * has_sequence_privilege_id_name
+ * Check user privileges on a sequence given
+ * roleid, text sequencename, and text priv name.
+ */
+Datum
+has_sequence_privilege_id_name(PG_FUNCTION_ARGS)
+{
+ Oid roleid = PG_GETARG_OID(0);
+ text *sequencename = PG_GETARG_TEXT_P(1);
+ text *priv_type_text = PG_GETARG_TEXT_P(2);
+ Oid sequenceoid;
+ AclMode mode;
+ AclResult aclresult;
+
+ mode = convert_sequence_priv_string(priv_type_text);
+ sequenceoid = convert_table_name(sequencename);
+ if (get_rel_relkind(sequenceoid) != RELKIND_SEQUENCE)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is not a sequence",
+ text_to_cstring(sequencename))));
+
+ aclresult = pg_class_aclcheck(sequenceoid, roleid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * has_sequence_privilege_id_id
+ * Check user privileges on a sequence given
+ * roleid, sequence oid, and text priv name.
+ */
+Datum
+has_sequence_privilege_id_id(PG_FUNCTION_ARGS)
+{
+ Oid roleid = PG_GETARG_OID(0);
+ Oid sequenceoid = PG_GETARG_OID(1);
+ text *priv_type_text = PG_GETARG_TEXT_P(2);
+ AclMode mode;
+ AclResult aclresult;
+ char relkind;
+
+ mode = convert_sequence_priv_string(priv_type_text);
+ relkind = get_rel_relkind(sequenceoid);
+ if (relkind == '\0')
+ PG_RETURN_NULL();
+ else if (relkind != RELKIND_SEQUENCE)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is not a sequence",
+ get_rel_name(sequenceoid))));
+
+ aclresult = pg_class_aclcheck(sequenceoid, roleid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * convert_sequence_priv_string
+ * Convert text string to AclMode value.
+ */
+static AclMode
+convert_sequence_priv_string(text *priv_type_text)
+{
+ static const priv_map sequence_priv_map[] = {
+ { "USAGE", ACL_USAGE },
+ { "SELECT", ACL_SELECT },
+ { "UPDATE", ACL_UPDATE },
+ { NULL, 0 }
+ };
+
+ return convert_any_priv_string(priv_type_text, sequence_priv_map);
+}
+
/*
* has_any_column_privilege variants
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index dc1b41d06bb..c1b8f6b6a89 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.535 2009/08/02 22:14:52 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.536 2009/08/03 21:11:39 joe Exp $
*
*-------------------------------------------------------------------------
*/
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 200908021
+#define CATALOG_VERSION_NO 200908031
#endif
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index d5884faa4a6..89effab1491 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.547 2009/07/29 20:56:20 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.548 2009/08/03 21:11:39 joe Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
@@ -2918,6 +2918,19 @@ DESCR("current user privilege on relation by rel name");
DATA(insert OID = 1927 ( has_table_privilege PGNSP PGUID 12 1 0 0 f f f t f s 2 0 16 "26 25" _null_ _null_ _null_ _null_ has_table_privilege_id _null_ _null_ _null_ ));
DESCR("current user privilege on relation by rel oid");
+DATA(insert OID = 2181 ( has_sequence_privilege PGNSP PGUID 12 1 0 0 f f f t f s 3 0 16 "19 25 25" _null_ _null_ _null_ _null_ has_sequence_privilege_name_name _null_ _null_ _null_ ));
+DESCR("user privilege on sequence by username, seq name");
+DATA(insert OID = 2182 ( has_sequence_privilege PGNSP PGUID 12 1 0 0 f f f t f s 3 0 16 "19 26 25" _null_ _null_ _null_ _null_ has_sequence_privilege_name_id _null_ _null_ _null_ ));
+DESCR("user privilege on sequence by username, seq oid");
+DATA(insert OID = 2183 ( has_sequence_privilege PGNSP PGUID 12 1 0 0 f f f t f s 3 0 16 "26 25 25" _null_ _null_ _null_ _null_ has_sequence_privilege_id_name _null_ _null_ _null_ ));
+DESCR("user privilege on sequence by user oid, seq name");
+DATA(insert OID = 2184 ( has_sequence_privilege PGNSP PGUID 12 1 0 0 f f f t f s 3 0 16 "26 26 25" _null_ _null_ _null_ _null_ has_sequence_privilege_id_id _null_ _null_ _null_ ));
+DESCR("user privilege on sequence by user oid, seq oid");
+DATA(insert OID = 2185 ( has_sequence_privilege PGNSP PGUID 12 1 0 0 f f f t f s 2 0 16 "25 25" _null_ _null_ _null_ _null_ has_sequence_privilege_name _null_ _null_ _null_ ));
+DESCR("current user privilege on sequence by seq name");
+DATA(insert OID = 2186 ( has_sequence_privilege PGNSP PGUID 12 1 0 0 f f f t f s 2 0 16 "26 25" _null_ _null_ _null_ _null_ has_sequence_privilege_id _null_ _null_ _null_ ));
+DESCR("current user privilege on sequence by seq oid");
+
DATA(insert OID = 3012 ( has_column_privilege PGNSP PGUID 12 1 0 0 f f f t f s 4 0 16 "19 25 25 25" _null_ _null_ _null_ _null_ has_column_privilege_name_name_name _null_ _null_ _null_ ));
DESCR("user privilege on column by username, rel name, col name");
DATA(insert OID = 3013 ( has_column_privilege PGNSP PGUID 12 1 0 0 f f f t f s 4 0 16 "19 25 21 25" _null_ _null_ _null_ _null_ has_column_privilege_name_name_attnum _null_ _null_ _null_ ));
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index 481eacf9b9f..4b92cbcb608 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.336 2009/08/01 19:59:41 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.337 2009/08/03 21:11:39 joe Exp $
*
*-------------------------------------------------------------------------
*/
@@ -46,6 +46,12 @@ extern Datum has_table_privilege_id_name(PG_FUNCTION_ARGS);
extern Datum has_table_privilege_id_id(PG_FUNCTION_ARGS);
extern Datum has_table_privilege_name(PG_FUNCTION_ARGS);
extern Datum has_table_privilege_id(PG_FUNCTION_ARGS);
+extern Datum has_sequence_privilege_name_name(PG_FUNCTION_ARGS);
+extern Datum has_sequence_privilege_name_id(PG_FUNCTION_ARGS);
+extern Datum has_sequence_privilege_id_name(PG_FUNCTION_ARGS);
+extern Datum has_sequence_privilege_id_id(PG_FUNCTION_ARGS);
+extern Datum has_sequence_privilege_name(PG_FUNCTION_ARGS);
+extern Datum has_sequence_privilege_id(PG_FUNCTION_ARGS);
extern Datum has_database_privilege_name_name(PG_FUNCTION_ARGS);
extern Datum has_database_privilege_name_id(PG_FUNCTION_ARGS);
extern Datum has_database_privilege_id_name(PG_FUNCTION_ARGS);
diff --git a/src/test/regress/expected/privileges.out b/src/test/regress/expected/privileges.out
index a17ff59d0c8..809b6562171 100644
--- a/src/test/regress/expected/privileges.out
+++ b/src/test/regress/expected/privileges.out
@@ -815,8 +815,30 @@ SELECT has_table_privilege('regressuser1', 'atest4', 'SELECT WITH GRANT OPTION')
t
(1 row)
+-- has_sequence_privilege tests
+\c -
+CREATE SEQUENCE x_seq;
+GRANT USAGE on x_seq to regressuser2;
+SELECT has_sequence_privilege('regressuser1', 'atest1', 'SELECT');
+ERROR: "atest1" is not a sequence
+SELECT has_sequence_privilege('regressuser1', 'x_seq', 'INSERT');
+ERROR: unrecognized privilege type: "INSERT"
+SELECT has_sequence_privilege('regressuser1', 'x_seq', 'SELECT');
+ has_sequence_privilege
+------------------------
+ f
+(1 row)
+
+SET SESSION AUTHORIZATION regressuser2;
+SELECT has_sequence_privilege('x_seq', 'USAGE');
+ has_sequence_privilege
+------------------------
+ t
+(1 row)
+
-- clean up
\c
+drop sequence x_seq;
DROP FUNCTION testfunc2(int);
DROP FUNCTION testfunc4(boolean);
DROP VIEW atestv1;
diff --git a/src/test/regress/sql/privileges.sql b/src/test/regress/sql/privileges.sql
index 5aa1012f3f6..917e8e5da4e 100644
--- a/src/test/regress/sql/privileges.sql
+++ b/src/test/regress/sql/privileges.sql
@@ -469,10 +469,27 @@ SELECT has_table_privilege('regressuser3', 'atest4', 'SELECT'); -- false
SELECT has_table_privilege('regressuser1', 'atest4', 'SELECT WITH GRANT OPTION'); -- true
+-- has_sequence_privilege tests
+\c -
+
+CREATE SEQUENCE x_seq;
+
+GRANT USAGE on x_seq to regressuser2;
+
+SELECT has_sequence_privilege('regressuser1', 'atest1', 'SELECT');
+SELECT has_sequence_privilege('regressuser1', 'x_seq', 'INSERT');
+SELECT has_sequence_privilege('regressuser1', 'x_seq', 'SELECT');
+
+SET SESSION AUTHORIZATION regressuser2;
+
+SELECT has_sequence_privilege('x_seq', 'USAGE');
+
-- clean up
\c
+drop sequence x_seq;
+
DROP FUNCTION testfunc2(int);
DROP FUNCTION testfunc4(boolean);