diff --git a/contrib/dbsize/dbsize.c b/contrib/dbsize/dbsize.c
index 44699aa693..0e5e63d1ee 100644
--- a/contrib/dbsize/dbsize.c
+++ b/contrib/dbsize/dbsize.c
@@ -8,12 +8,10 @@
#include "access/heapam.h"
#include "catalog/catalog.h"
-#include "catalog/catname.h"
#include "catalog/namespace.h"
-#include "catalog/pg_database.h"
+#include "commands/dbcommands.h"
#include "fmgr.h"
#include "utils/builtins.h"
-#include "utils/fmgroids.h"
static char *
@@ -46,32 +44,16 @@ database_size(PG_FUNCTION_ARGS)
{
Name dbname = PG_GETARG_NAME(0);
- HeapTuple tuple;
- Relation relation;
- ScanKeyData scanKey;
- HeapScanDesc scan;
Oid dbid;
char *dbpath;
DIR *dirdesc;
struct dirent *direntry;
int64 totalsize;
- relation = heap_openr(DatabaseRelationName, AccessShareLock);
- ScanKeyEntryInitialize(&scanKey, 0, Anum_pg_database_datname,
- F_NAMEEQ, NameGetDatum(dbname));
- scan = heap_beginscan(relation, SnapshotNow, 1, &scanKey);
- tuple = heap_getnext(scan, ForwardScanDirection);
-
- if (!HeapTupleIsValid(tuple))
+ dbid = get_database_oid(NameStr(*dbname));
+ if (!OidIsValid(dbid))
elog(ERROR, "database %s does not exist", NameStr(*dbname));
- dbid = HeapTupleGetOid(tuple);
- if (dbid == InvalidOid)
- elog(ERROR, "invalid database id");
-
- heap_endscan(scan);
- heap_close(relation, NoLock);
-
dbpath = GetDatabasePath(dbid);
dirdesc = opendir(dbpath);
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 8d722a9185..475af47464 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -1,5 +1,5 @@
@@ -4925,57 +4925,11 @@ select current_setting('DateStyle');
false instead. It is the equivalent to the SQL
SET command. For example:
-SHOW show_query_stats;
- show_query_stats
-------------------
- on
-(1 row)
-
select set_config('show_query_stats','off','f');
set_config
------------
off
(1 row)
-
-SHOW show_query_stats;
- show_query_stats
-------------------
- off
-(1 row)
-
-select set_config('show_query_stats','on','t');
- set_config
-------------
- on
-(1 row)
-
-SHOW show_query_stats;
- show_query_stats
-------------------
- off
-(1 row)
-
-BEGIN;
-BEGIN
-select set_config('show_query_stats','on','t');
- set_config
-------------
- on
-(1 row)
-
-SHOW show_query_stats;
- show_query_stats
-------------------
- on
-(1 row)
-
-COMMIT;
-COMMIT
-SHOW show_query_stats;
- show_query_stats
-------------------
- off
-(1 row)
@@ -5002,6 +4956,66 @@ SHOW show_query_stats;
boolean
does current user have access to table
+
+ has_database_privilege(user,
+ database,
+ access)
+
+ boolean
+ does user have access to database
+
+
+ has_database_privilege(database,
+ access)
+
+ boolean
+ does current user have access to database
+
+
+ has_function_privilege(user,
+ function,
+ access)
+
+ boolean
+ does user have access to function
+
+
+ has_function_privilege(function,
+ access)
+
+ boolean
+ does current user have access to function
+
+
+ has_language_privilege(user,
+ language,
+ access)
+
+ boolean
+ does user have access to language
+
+
+ has_language_privilege(language,
+ access)
+
+ boolean
+ does current user have access to language
+
+
+ has_schema_privilege(user,
+ schema,
+ access)
+
+ boolean
+ does user have access to schema
+
+
+ has_schema_privilege(schema,
+ access)
+
+ boolean
+ does current user have access to schema
+
@@ -5009,9 +5023,21 @@ SHOW show_query_stats;
has_table_privilege
+
+ has_database_privilege
+
+
+ has_function_privilege
+
+
+ has_language_privilege
+
+
+ has_schema_privilege
+
- has_table_privilege determines whether a user
+ has_table_privilege checks whether a user
can access a table in a particular way. The user can be
specified by name or by ID
(pg_user.usesysid), or if the argument is
@@ -5032,6 +5058,140 @@ SELECT has_table_privilege('myschema.mytable', 'select');
+
+ has_database_privilege checks whether a user
+ can access a database in a particular way. The possibilities for its
+ arguments are analogous to has_table_privilege.
+ The desired access type must evaluate to
+ CREATE,
+ TEMPORARY, or
+ TEMP (which is equivalent to
+ TEMPORARY).
+
+
+
+ has_function_privilege checks whether a user
+ can access a function in a particular way. The possibilities for its
+ arguments are analogous to has_table_privilege.
+ When specifying a function by a text string rather than by OID,
+ the allowed input is the same as for the regprocedure> datatype.
+ The desired access type must currently evaluate to
+ EXECUTE.
+
+
+
+ has_language_privilege checks whether a user
+ can access a procedural language in a particular way. The possibilities
+ for its arguments are analogous to has_table_privilege.
+ The desired access type must currently evaluate to
+ USAGE.
+
+
+
+ has_schema_privilege checks whether a user
+ can access a schema in a particular way. The possibilities for its
+ arguments are analogous to has_table_privilege.
+ The desired access type must evaluate to
+ CREATE or
+ USAGE.
+
+
+
+ Schema Visibility Inquiry Functions
+
+
+ Name Return Type Description
+
+
+
+
+ pg_table_is_visible(tableOID)
+
+ boolean
+ is table visible in search path
+
+
+ pg_type_is_visible(typeOID)
+
+ boolean
+ is type visible in search path
+
+
+ pg_function_is_visible(functionOID)
+
+ boolean
+ is function visible in search path
+
+
+ pg_operator_is_visible(operatorOID)
+
+ boolean
+ is operator visible in search path
+
+
+ pg_opclass_is_visible(opclassOID)
+
+ boolean
+ is operator class visible in search path
+
+
+
+
+
+
+ pg_table_is_visible
+
+
+ pg_type_is_visible
+
+
+ pg_function_is_visible
+
+
+ pg_operator_is_visible
+
+
+ pg_opclass_is_visible
+
+
+
+ pg_table_is_visible checks whether a table
+ (or view, or any other kind of pg_class> entry) is
+ visible> in the current schema search path. A table
+ is said to be visible if its containing schema is in the search path
+ and no table of the same name appears earlier in the search path.
+ This is equivalent to the statement that the table can be referenced
+ by name without explicit schema qualification.
+ For example, to list the names of all visible tables:
+
+SELECT relname FROM pg_class WHERE pg_table_is_visible(oid);
+
+
+
+
+ pg_type_is_visible,
+ pg_function_is_visible,
+ pg_operator_is_visible, and
+ pg_opclass_is_visible perform the same sort of
+ visibility check for types, functions, operators, and operator classes,
+ respectively. For functions and operators, an object in the search path
+ is visible if there is no object of the same name and argument
+ datatype(s)> earlier in the path. For operator classes,
+ both name and associated index access method are considered.
+
+
+
+ All these functions require object OIDs to identify the object to be
+ checked. If you want to test an object by name, it is convenient to use
+ the OID alias types (regclass>, regtype>,
+ regprocedure>, or regoperator>), for example
+
+SELECT pg_type_is_visible('myschema.widget'::regtype);
+
+ Note that it would not make much sense to test an unqualified name in
+ this way --- if the name can be recognized at all, it must be visible.
+
+
Catalog Information Functions
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index 4999ea4b64..1aab73279f 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -13,7 +13,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.29 2002/08/08 01:44:30 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.30 2002/08/09 16:45:14 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -137,6 +137,13 @@ static void RemoveTempRelations(Oid tempNamespaceId);
static void RemoveTempRelationsCallback(void);
static void NamespaceCallback(Datum arg, Oid relid);
+/* These don't really need to appear in any header file */
+Datum pg_table_is_visible(PG_FUNCTION_ARGS);
+Datum pg_type_is_visible(PG_FUNCTION_ARGS);
+Datum pg_function_is_visible(PG_FUNCTION_ARGS);
+Datum pg_operator_is_visible(PG_FUNCTION_ARGS);
+Datum pg_opclass_is_visible(PG_FUNCTION_ARGS);
+
/*
* RangeVarGetRelid
@@ -1747,3 +1754,47 @@ fetch_search_path(bool includeImplicit)
return result;
}
+
+/*
+ * Export the FooIsVisible functions as SQL-callable functions.
+ */
+
+Datum
+pg_table_is_visible(PG_FUNCTION_ARGS)
+{
+ Oid oid = PG_GETARG_OID(0);
+
+ PG_RETURN_BOOL(RelationIsVisible(oid));
+}
+
+Datum
+pg_type_is_visible(PG_FUNCTION_ARGS)
+{
+ Oid oid = PG_GETARG_OID(0);
+
+ PG_RETURN_BOOL(TypeIsVisible(oid));
+}
+
+Datum
+pg_function_is_visible(PG_FUNCTION_ARGS)
+{
+ Oid oid = PG_GETARG_OID(0);
+
+ PG_RETURN_BOOL(FunctionIsVisible(oid));
+}
+
+Datum
+pg_operator_is_visible(PG_FUNCTION_ARGS)
+{
+ Oid oid = PG_GETARG_OID(0);
+
+ PG_RETURN_BOOL(OperatorIsVisible(oid));
+}
+
+Datum
+pg_opclass_is_visible(PG_FUNCTION_ARGS)
+{
+ Oid oid = PG_GETARG_OID(0);
+
+ PG_RETURN_BOOL(OpclassIsVisible(oid));
+}
diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c
index e244a82d1a..41ef71960d 100644
--- a/src/backend/commands/comment.c
+++ b/src/backend/commands/comment.c
@@ -7,7 +7,7 @@
* Copyright (c) 1996-2001, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.55 2002/08/05 03:29:16 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.56 2002/08/09 16:45:14 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -20,12 +20,12 @@
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/pg_constraint.h"
-#include "catalog/pg_database.h"
#include "catalog/pg_description.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_rewrite.h"
#include "catalog/pg_trigger.h"
#include "commands/comment.h"
+#include "commands/dbcommands.h"
#include "miscadmin.h"
#include "parser/parse_func.h"
#include "parser/parse_oper.h"
@@ -398,34 +398,16 @@ static void
CommentDatabase(List *qualname, char *comment)
{
char *database;
- Relation pg_database;
- ScanKeyData entry;
- HeapScanDesc scan;
- HeapTuple dbtuple;
Oid oid;
if (length(qualname) != 1)
elog(ERROR, "CommentDatabase: database name may not be qualified");
database = strVal(lfirst(qualname));
- /* Only allow comments on the current database */
- if (strcmp(database, DatabaseName) != 0)
- elog(ERROR, "Database comments may only be applied to the current database");
-
- /* First find the tuple in pg_database for the database */
-
- pg_database = heap_openr(DatabaseRelationName, AccessShareLock);
- ScanKeyEntryInitialize(&entry, 0, Anum_pg_database_datname,
- F_NAMEEQ, CStringGetDatum(database));
- scan = heap_beginscan(pg_database, SnapshotNow, 1, &entry);
- dbtuple = heap_getnext(scan, ForwardScanDirection);
-
- /* Validate database exists, and fetch the db oid */
-
- if (!HeapTupleIsValid(dbtuple))
+ /* First get the database OID */
+ oid = get_database_oid(database);
+ if (!OidIsValid(oid))
elog(ERROR, "database \"%s\" does not exist", database);
- AssertTupleDescHasOid(pg_database->rd_att);
- oid = HeapTupleGetOid(dbtuple);
/* Allow if the user matches the database dba or is a superuser */
@@ -433,14 +415,12 @@ CommentDatabase(List *qualname, char *comment)
elog(ERROR, "you are not permitted to comment on database \"%s\"",
database);
+ /* Only allow comments on the current database */
+ if (oid != MyDatabaseId)
+ elog(ERROR, "Database comments may only be applied to the current database");
+
/* Create the comment with the pg_database oid */
-
CreateComments(oid, RelOid_pg_database, 0, comment);
-
- /* Complete the scan and close any opened relations */
-
- heap_endscan(scan);
- heap_close(pg_database, AccessShareLock);
}
/*
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index d043d95b78..53c8391c0c 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.98 2002/08/05 03:29:16 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.99 2002/08/09 16:45:14 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -746,3 +746,78 @@ remove_dbdirs(const char *nominal_loc, const char *alt_loc)
return success;
}
+
+
+/*
+ * get_database_oid - given a database name, look up the OID
+ *
+ * Returns InvalidOid if database name not found.
+ *
+ * This is not actually used in this file, but is exported for use elsewhere.
+ */
+Oid
+get_database_oid(const char *dbname)
+{
+ Relation pg_database;
+ ScanKeyData entry[1];
+ HeapScanDesc scan;
+ HeapTuple dbtuple;
+ Oid oid;
+
+ /* There's no syscache for pg_database, so must look the hard way */
+ pg_database = heap_openr(DatabaseRelationName, AccessShareLock);
+ ScanKeyEntryInitialize(&entry[0], 0x0,
+ Anum_pg_database_datname, F_NAMEEQ,
+ CStringGetDatum(dbname));
+ scan = heap_beginscan(pg_database, SnapshotNow, 1, entry);
+
+ dbtuple = heap_getnext(scan, ForwardScanDirection);
+
+ /* We assume that there can be at most one matching tuple */
+ if (HeapTupleIsValid(dbtuple))
+ oid = HeapTupleGetOid(dbtuple);
+ else
+ oid = InvalidOid;
+
+ heap_endscan(scan);
+ heap_close(pg_database, AccessShareLock);
+
+ return oid;
+}
+
+/*
+ * get_database_owner - given a database OID, fetch the owner's usesysid.
+ *
+ * Errors out if database not found.
+ *
+ * This is not actually used in this file, but is exported for use elsewhere.
+ */
+Oid
+get_database_owner(Oid dbid)
+{
+ Relation pg_database;
+ ScanKeyData entry[1];
+ HeapScanDesc scan;
+ HeapTuple dbtuple;
+ int32 dba;
+
+ /* There's no syscache for pg_database, so must look the hard way */
+ pg_database = heap_openr(DatabaseRelationName, AccessShareLock);
+ ScanKeyEntryInitialize(&entry[0], 0x0,
+ ObjectIdAttributeNumber, F_OIDEQ,
+ ObjectIdGetDatum(dbid));
+ scan = heap_beginscan(pg_database, SnapshotNow, 1, entry);
+
+ dbtuple = heap_getnext(scan, ForwardScanDirection);
+
+ if (!HeapTupleIsValid(dbtuple))
+ elog(ERROR, "database %u does not exist", dbid);
+
+ dba = ((Form_pg_database) GETSTRUCT(dbtuple))->datdba;
+
+ heap_endscan(scan);
+ heap_close(pg_database, AccessShareLock);
+
+ /* XXX some confusion about whether userids are OID or int4 ... */
+ return (Oid) dba;
+}
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index 1b0296965e..494a262f0b 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.74 2002/06/20 20:29:36 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.75 2002/08/09 16:45:14 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -18,6 +18,7 @@
#include "catalog/namespace.h"
#include "catalog/pg_shadow.h"
+#include "commands/dbcommands.h"
#include "miscadmin.h"
#include "utils/acl.h"
#include "utils/builtins.h"
@@ -34,8 +35,16 @@ static const char *aclparse(const char *s, AclItem *aip, unsigned *modechg);
static bool aclitemeq(const AclItem *a1, const AclItem *a2);
static bool aclitemgt(const AclItem *a1, const AclItem *a2);
-static AclMode convert_priv_string(text *priv_type_text);
-static Oid convert_rel_name(text *relname);
+static Oid convert_table_name(text *tablename);
+static AclMode convert_table_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_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);
/*
@@ -646,266 +655,179 @@ aclcontains(PG_FUNCTION_ARGS)
/*
- * has_table_privilege_name_name
- * Check user privileges on a relation given
- * name username, text relname, and text priv name.
+ * has_table_privilege variants
+ * These are all named "has_table_privilege" at the SQL level.
+ * They take various combinations of relation name, relation OID,
+ * user name, user sysid, or implicit user = current_user.
*
- * RETURNS
- * a boolean value
- * 't' indicating user has the privilege
- * 'f' indicating user does not have the privilege
+ * The result is a boolean value: true if user has the indicated
+ * privilege, false if not.
+ */
+
+/*
+ * has_table_privilege_name_name
+ * Check user privileges on a table given
+ * name username, text tablename, and text priv name.
*/
Datum
has_table_privilege_name_name(PG_FUNCTION_ARGS)
{
Name username = PG_GETARG_NAME(0);
- text *relname = PG_GETARG_TEXT_P(1);
+ text *tablename = PG_GETARG_TEXT_P(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
int32 usesysid;
- Oid reloid;
+ Oid tableoid;
AclMode mode;
AclResult aclresult;
- /*
- * Lookup userid based on username
- */
usesysid = get_usesysid(NameStr(*username));
+ tableoid = convert_table_name(tablename);
+ mode = convert_table_priv_string(priv_type_text);
- /*
- * Lookup rel OID based on relname
- */
- reloid = convert_rel_name(relname);
-
- /*
- * Convert priv_type_text to an AclMode
- */
- mode = convert_priv_string(priv_type_text);
-
- /*
- * Check for the privilege
- */
- aclresult = pg_class_aclcheck(reloid, usesysid, mode);
+ aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
-
/*
* has_table_privilege_name
- * Check user privileges on a relation given
- * text relname and text priv name.
+ * Check user privileges on a table given
+ * text tablename and text priv name.
* current_user is assumed
- *
- * RETURNS
- * a boolean value
- * 't' indicating user has the privilege
- * 'f' indicating user does not have the privilege
*/
Datum
has_table_privilege_name(PG_FUNCTION_ARGS)
{
- text *relname = PG_GETARG_TEXT_P(0);
+ text *tablename = PG_GETARG_TEXT_P(0);
text *priv_type_text = PG_GETARG_TEXT_P(1);
int32 usesysid;
- Oid reloid;
+ Oid tableoid;
AclMode mode;
AclResult aclresult;
usesysid = GetUserId();
+ tableoid = convert_table_name(tablename);
+ mode = convert_table_priv_string(priv_type_text);
- /*
- * Lookup rel OID based on relname
- */
- reloid = convert_rel_name(relname);
-
- /*
- * Convert priv_type_text to an AclMode
- */
- mode = convert_priv_string(priv_type_text);
-
- /*
- * Check for the privilege
- */
- aclresult = pg_class_aclcheck(reloid, usesysid, mode);
+ aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
-
/*
* has_table_privilege_name_id
- * Check user privileges on a relation given
- * name usename, rel oid, and text priv name.
- *
- * RETURNS
- * a boolean value
- * 't' indicating user has the privilege
- * 'f' indicating user does not have the privilege
+ * Check user privileges on a table given
+ * name usename, table oid, and text priv name.
*/
Datum
has_table_privilege_name_id(PG_FUNCTION_ARGS)
{
Name username = PG_GETARG_NAME(0);
- Oid reloid = PG_GETARG_OID(1);
+ Oid tableoid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
int32 usesysid;
AclMode mode;
AclResult aclresult;
- /*
- * Lookup userid based on username
- */
usesysid = get_usesysid(NameStr(*username));
+ mode = convert_table_priv_string(priv_type_text);
- /*
- * Convert priv_type_text to an AclMode
- */
- mode = convert_priv_string(priv_type_text);
-
- /*
- * Check for the privilege
- */
- aclresult = pg_class_aclcheck(reloid, usesysid, mode);
+ aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
-
/*
* has_table_privilege_id
- * Check user privileges on a relation given
- * rel oid, and text priv name.
+ * Check user privileges on a table given
+ * table oid, and text priv name.
* current_user is assumed
- *
- * RETURNS
- * a boolean value
- * 't' indicating user has the privilege
- * 'f' indicating user does not have the privilege
*/
Datum
has_table_privilege_id(PG_FUNCTION_ARGS)
{
- Oid reloid = PG_GETARG_OID(0);
+ Oid tableoid = PG_GETARG_OID(0);
text *priv_type_text = PG_GETARG_TEXT_P(1);
int32 usesysid;
AclMode mode;
AclResult aclresult;
usesysid = GetUserId();
+ mode = convert_table_priv_string(priv_type_text);
- /*
- * Convert priv_type_text to an AclMode
- */
- mode = convert_priv_string(priv_type_text);
-
- /*
- * Check for the privilege
- */
- aclresult = pg_class_aclcheck(reloid, usesysid, mode);
+ aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
-
/*
* has_table_privilege_id_name
- * Check user privileges on a relation given
- * usesysid, text relname, and priv name.
- *
- * RETURNS
- * a boolean value
- * 't' indicating user has the privilege
- * 'f' indicating user does not have the privilege
+ * Check user privileges on a table given
+ * usesysid, text tablename, and text priv name.
*/
Datum
has_table_privilege_id_name(PG_FUNCTION_ARGS)
{
int32 usesysid = PG_GETARG_INT32(0);
- text *relname = PG_GETARG_TEXT_P(1);
+ text *tablename = PG_GETARG_TEXT_P(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
- Oid reloid;
+ Oid tableoid;
AclMode mode;
AclResult aclresult;
- /*
- * Lookup rel OID based on relname
- */
- reloid = convert_rel_name(relname);
+ tableoid = convert_table_name(tablename);
+ mode = convert_table_priv_string(priv_type_text);
- /*
- * Convert priv_type_text to an AclMode
- */
- mode = convert_priv_string(priv_type_text);
-
- /*
- * Check for the privilege
- */
- aclresult = pg_class_aclcheck(reloid, usesysid, mode);
+ aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
-
/*
* has_table_privilege_id_id
- * Check user privileges on a relation given
- * usesysid, rel oid, and priv name.
- *
- * RETURNS
- * a boolean value
- * 't' indicating user has the privilege
- * 'f' indicating user does not have the privilege
+ * Check user privileges on a table given
+ * usesysid, table oid, and text priv name.
*/
Datum
has_table_privilege_id_id(PG_FUNCTION_ARGS)
{
int32 usesysid = PG_GETARG_INT32(0);
- Oid reloid = PG_GETARG_OID(1);
+ Oid tableoid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
AclMode mode;
AclResult aclresult;
- /*
- * Convert priv_type_text to an AclMode
- */
- mode = convert_priv_string(priv_type_text);
+ mode = convert_table_priv_string(priv_type_text);
- /*
- * Check for the privilege
- */
- aclresult = pg_class_aclcheck(reloid, usesysid, mode);
+ aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
/*
- * Internal functions.
+ * Support routines for has_table_privilege family.
*/
/*
- * Given a relation name expressed as a string, look it up and return Oid
+ * Given a table name expressed as a string, look it up and return Oid
*/
static Oid
-convert_rel_name(text *relname)
+convert_table_name(text *tablename)
{
RangeVar *relrv;
- relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname,
+ relrv = makeRangeVarFromNameList(textToQualifiedNameList(tablename,
"has_table_privilege"));
return RangeVarGetRelid(relrv, false);
}
/*
- * convert_priv_string
- * Internal function.
- * Return mode from priv_type string
- *
- * RETURNS
- * AclMode
+ * convert_table_priv_string
+ * Convert text string to AclMode value.
*/
static AclMode
-convert_priv_string(text *priv_type_text)
+convert_table_priv_string(text *priv_type_text)
{
char *priv_type;
@@ -936,10 +858,810 @@ convert_priv_string(text *priv_type_text)
if (strcasecmp(priv_type, "TRIGGER") == 0)
return ACL_TRIGGER;
- elog(ERROR, "has_table_privilege: invalid privilege type %s", priv_type);
+ elog(ERROR, "has_table_privilege: invalid privilege type %s",
+ priv_type);
+ return ACL_NO_RIGHTS; /* keep compiler quiet */
+}
+
+
+/*
+ * 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 sysid, or implicit user = current_user.
+ *
+ * The result is a boolean value: true if user has the indicated
+ * privilege, false if not.
+ */
+
+/*
+ * 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);
+ int32 usesysid;
+ Oid databaseoid;
+ AclMode mode;
+ AclResult aclresult;
+
+ usesysid = get_usesysid(NameStr(*username));
+ databaseoid = convert_database_name(databasename);
+ mode = convert_database_priv_string(priv_type_text);
+
+ aclresult = pg_database_aclcheck(databaseoid, usesysid, 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);
+ int32 usesysid;
+ Oid databaseoid;
+ AclMode mode;
+ AclResult aclresult;
+
+ usesysid = GetUserId();
+ databaseoid = convert_database_name(databasename);
+ mode = convert_database_priv_string(priv_type_text);
+
+ aclresult = pg_database_aclcheck(databaseoid, usesysid, 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);
+ int32 usesysid;
+ AclMode mode;
+ AclResult aclresult;
+
+ usesysid = get_usesysid(NameStr(*username));
+ mode = convert_database_priv_string(priv_type_text);
+
+ aclresult = pg_database_aclcheck(databaseoid, usesysid, 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);
+ int32 usesysid;
+ AclMode mode;
+ AclResult aclresult;
+
+ usesysid = GetUserId();
+ mode = convert_database_priv_string(priv_type_text);
+
+ aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * has_database_privilege_id_name
+ * Check user privileges on a database given
+ * usesysid, text databasename, and text priv name.
+ */
+Datum
+has_database_privilege_id_name(PG_FUNCTION_ARGS)
+{
+ int32 usesysid = PG_GETARG_INT32(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, usesysid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * has_database_privilege_id_id
+ * Check user privileges on a database given
+ * usesysid, database oid, and text priv name.
+ */
+Datum
+has_database_privilege_id_id(PG_FUNCTION_ARGS)
+{
+ int32 usesysid = PG_GETARG_INT32(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);
+
+ aclresult = pg_database_aclcheck(databaseoid, usesysid, 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;
+ Oid oid;
+
+ dbname = DatumGetCString(DirectFunctionCall1(textout,
+ PointerGetDatum(databasename)));
+
+ oid = get_database_oid(dbname);
+ if (!OidIsValid(oid))
+ elog(ERROR, "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)
+{
+ char *priv_type;
+
+ priv_type = DatumGetCString(DirectFunctionCall1(textout,
+ PointerGetDatum(priv_type_text)));
/*
- * We should never get here, but stop the compiler from complaining
+ * Return mode from priv_type string
*/
- return ACL_NO_RIGHTS;
+ if (strcasecmp(priv_type, "CREATE") == 0)
+ return ACL_CREATE;
+
+ if (strcasecmp(priv_type, "TEMPORARY") == 0)
+ return ACL_CREATE_TEMP;
+
+ if (strcasecmp(priv_type, "TEMP") == 0)
+ return ACL_CREATE_TEMP;
+
+ elog(ERROR, "has_database_privilege: invalid privilege type %s",
+ priv_type);
+ return ACL_NO_RIGHTS; /* keep compiler quiet */
+}
+
+
+/*
+ * has_function_privilege variants
+ * These are all named "has_function_privilege" at the SQL level.
+ * They take various combinations of function name, function OID,
+ * user name, user sysid, or implicit user = current_user.
+ *
+ * The result is a boolean value: true if user has the indicated
+ * privilege, false if not.
+ */
+
+/*
+ * has_function_privilege_name_name
+ * Check user privileges on a function given
+ * name username, text functionname, and text priv name.
+ */
+Datum
+has_function_privilege_name_name(PG_FUNCTION_ARGS)
+{
+ Name username = PG_GETARG_NAME(0);
+ text *functionname = PG_GETARG_TEXT_P(1);
+ text *priv_type_text = PG_GETARG_TEXT_P(2);
+ int32 usesysid;
+ Oid functionoid;
+ AclMode mode;
+ AclResult aclresult;
+
+ usesysid = get_usesysid(NameStr(*username));
+ functionoid = convert_function_name(functionname);
+ mode = convert_function_priv_string(priv_type_text);
+
+ aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * has_function_privilege_name
+ * Check user privileges on a function given
+ * text functionname and text priv name.
+ * current_user is assumed
+ */
+Datum
+has_function_privilege_name(PG_FUNCTION_ARGS)
+{
+ text *functionname = PG_GETARG_TEXT_P(0);
+ text *priv_type_text = PG_GETARG_TEXT_P(1);
+ int32 usesysid;
+ Oid functionoid;
+ AclMode mode;
+ AclResult aclresult;
+
+ usesysid = GetUserId();
+ functionoid = convert_function_name(functionname);
+ mode = convert_function_priv_string(priv_type_text);
+
+ aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * has_function_privilege_name_id
+ * Check user privileges on a function given
+ * name usename, function oid, and text priv name.
+ */
+Datum
+has_function_privilege_name_id(PG_FUNCTION_ARGS)
+{
+ Name username = PG_GETARG_NAME(0);
+ Oid functionoid = PG_GETARG_OID(1);
+ text *priv_type_text = PG_GETARG_TEXT_P(2);
+ int32 usesysid;
+ AclMode mode;
+ AclResult aclresult;
+
+ usesysid = get_usesysid(NameStr(*username));
+ mode = convert_function_priv_string(priv_type_text);
+
+ aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * has_function_privilege_id
+ * Check user privileges on a function given
+ * function oid, and text priv name.
+ * current_user is assumed
+ */
+Datum
+has_function_privilege_id(PG_FUNCTION_ARGS)
+{
+ Oid functionoid = PG_GETARG_OID(0);
+ text *priv_type_text = PG_GETARG_TEXT_P(1);
+ int32 usesysid;
+ AclMode mode;
+ AclResult aclresult;
+
+ usesysid = GetUserId();
+ mode = convert_function_priv_string(priv_type_text);
+
+ aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * has_function_privilege_id_name
+ * Check user privileges on a function given
+ * usesysid, text functionname, and text priv name.
+ */
+Datum
+has_function_privilege_id_name(PG_FUNCTION_ARGS)
+{
+ int32 usesysid = PG_GETARG_INT32(0);
+ text *functionname = PG_GETARG_TEXT_P(1);
+ text *priv_type_text = PG_GETARG_TEXT_P(2);
+ Oid functionoid;
+ AclMode mode;
+ AclResult aclresult;
+
+ functionoid = convert_function_name(functionname);
+ mode = convert_function_priv_string(priv_type_text);
+
+ aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * has_function_privilege_id_id
+ * Check user privileges on a function given
+ * usesysid, function oid, and text priv name.
+ */
+Datum
+has_function_privilege_id_id(PG_FUNCTION_ARGS)
+{
+ int32 usesysid = PG_GETARG_INT32(0);
+ Oid functionoid = PG_GETARG_OID(1);
+ text *priv_type_text = PG_GETARG_TEXT_P(2);
+ AclMode mode;
+ AclResult aclresult;
+
+ mode = convert_function_priv_string(priv_type_text);
+
+ aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * Support routines for has_function_privilege family.
+ */
+
+/*
+ * Given a function name expressed as a string, look it up and return Oid
+ */
+static Oid
+convert_function_name(text *functionname)
+{
+ char *funcname;
+ Oid oid;
+
+ funcname = DatumGetCString(DirectFunctionCall1(textout,
+ PointerGetDatum(functionname)));
+
+ oid = DatumGetObjectId(DirectFunctionCall1(regprocedurein,
+ CStringGetDatum(funcname)));
+
+ if (!OidIsValid(oid))
+ elog(ERROR, "function \"%s\" does not exist", funcname);
+
+ return oid;
+}
+
+/*
+ * convert_function_priv_string
+ * Convert text string to AclMode value.
+ */
+static AclMode
+convert_function_priv_string(text *priv_type_text)
+{
+ char *priv_type;
+
+ priv_type = DatumGetCString(DirectFunctionCall1(textout,
+ PointerGetDatum(priv_type_text)));
+
+ /*
+ * Return mode from priv_type string
+ */
+ if (strcasecmp(priv_type, "EXECUTE") == 0)
+ return ACL_EXECUTE;
+
+ elog(ERROR, "has_function_privilege: invalid privilege type %s",
+ priv_type);
+ return ACL_NO_RIGHTS; /* keep compiler quiet */
+}
+
+
+/*
+ * has_language_privilege variants
+ * These are all named "has_language_privilege" at the SQL level.
+ * They take various combinations of language name, language OID,
+ * user name, user sysid, or implicit user = current_user.
+ *
+ * The result is a boolean value: true if user has the indicated
+ * privilege, false if not.
+ */
+
+/*
+ * has_language_privilege_name_name
+ * Check user privileges on a language given
+ * name username, text languagename, and text priv name.
+ */
+Datum
+has_language_privilege_name_name(PG_FUNCTION_ARGS)
+{
+ Name username = PG_GETARG_NAME(0);
+ text *languagename = PG_GETARG_TEXT_P(1);
+ text *priv_type_text = PG_GETARG_TEXT_P(2);
+ int32 usesysid;
+ Oid languageoid;
+ AclMode mode;
+ AclResult aclresult;
+
+ usesysid = get_usesysid(NameStr(*username));
+ languageoid = convert_language_name(languagename);
+ mode = convert_language_priv_string(priv_type_text);
+
+ aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * has_language_privilege_name
+ * Check user privileges on a language given
+ * text languagename and text priv name.
+ * current_user is assumed
+ */
+Datum
+has_language_privilege_name(PG_FUNCTION_ARGS)
+{
+ text *languagename = PG_GETARG_TEXT_P(0);
+ text *priv_type_text = PG_GETARG_TEXT_P(1);
+ int32 usesysid;
+ Oid languageoid;
+ AclMode mode;
+ AclResult aclresult;
+
+ usesysid = GetUserId();
+ languageoid = convert_language_name(languagename);
+ mode = convert_language_priv_string(priv_type_text);
+
+ aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * has_language_privilege_name_id
+ * Check user privileges on a language given
+ * name usename, language oid, and text priv name.
+ */
+Datum
+has_language_privilege_name_id(PG_FUNCTION_ARGS)
+{
+ Name username = PG_GETARG_NAME(0);
+ Oid languageoid = PG_GETARG_OID(1);
+ text *priv_type_text = PG_GETARG_TEXT_P(2);
+ int32 usesysid;
+ AclMode mode;
+ AclResult aclresult;
+
+ usesysid = get_usesysid(NameStr(*username));
+ mode = convert_language_priv_string(priv_type_text);
+
+ aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * has_language_privilege_id
+ * Check user privileges on a language given
+ * language oid, and text priv name.
+ * current_user is assumed
+ */
+Datum
+has_language_privilege_id(PG_FUNCTION_ARGS)
+{
+ Oid languageoid = PG_GETARG_OID(0);
+ text *priv_type_text = PG_GETARG_TEXT_P(1);
+ int32 usesysid;
+ AclMode mode;
+ AclResult aclresult;
+
+ usesysid = GetUserId();
+ mode = convert_language_priv_string(priv_type_text);
+
+ aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * has_language_privilege_id_name
+ * Check user privileges on a language given
+ * usesysid, text languagename, and text priv name.
+ */
+Datum
+has_language_privilege_id_name(PG_FUNCTION_ARGS)
+{
+ int32 usesysid = PG_GETARG_INT32(0);
+ text *languagename = PG_GETARG_TEXT_P(1);
+ text *priv_type_text = PG_GETARG_TEXT_P(2);
+ Oid languageoid;
+ AclMode mode;
+ AclResult aclresult;
+
+ languageoid = convert_language_name(languagename);
+ mode = convert_language_priv_string(priv_type_text);
+
+ aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * has_language_privilege_id_id
+ * Check user privileges on a language given
+ * usesysid, language oid, and text priv name.
+ */
+Datum
+has_language_privilege_id_id(PG_FUNCTION_ARGS)
+{
+ int32 usesysid = PG_GETARG_INT32(0);
+ Oid languageoid = PG_GETARG_OID(1);
+ text *priv_type_text = PG_GETARG_TEXT_P(2);
+ AclMode mode;
+ AclResult aclresult;
+
+ mode = convert_language_priv_string(priv_type_text);
+
+ aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * Support routines for has_language_privilege family.
+ */
+
+/*
+ * Given a language name expressed as a string, look it up and return Oid
+ */
+static Oid
+convert_language_name(text *languagename)
+{
+ char *langname;
+ Oid oid;
+
+ langname = DatumGetCString(DirectFunctionCall1(textout,
+ PointerGetDatum(languagename)));
+
+ oid = GetSysCacheOid(LANGNAME,
+ CStringGetDatum(langname),
+ 0, 0, 0);
+ if (!OidIsValid(oid))
+ elog(ERROR, "language \"%s\" does not exist", langname);
+
+ return oid;
+}
+
+/*
+ * convert_language_priv_string
+ * Convert text string to AclMode value.
+ */
+static AclMode
+convert_language_priv_string(text *priv_type_text)
+{
+ char *priv_type;
+
+ priv_type = DatumGetCString(DirectFunctionCall1(textout,
+ PointerGetDatum(priv_type_text)));
+
+ /*
+ * Return mode from priv_type string
+ */
+ if (strcasecmp(priv_type, "USAGE") == 0)
+ return ACL_USAGE;
+
+ elog(ERROR, "has_language_privilege: invalid privilege type %s",
+ priv_type);
+ return ACL_NO_RIGHTS; /* keep compiler quiet */
+}
+
+
+/*
+ * has_schema_privilege variants
+ * These are all named "has_schema_privilege" at the SQL level.
+ * They take various combinations of schema name, schema OID,
+ * user name, user sysid, or implicit user = current_user.
+ *
+ * The result is a boolean value: true if user has the indicated
+ * privilege, false if not.
+ */
+
+/*
+ * has_schema_privilege_name_name
+ * Check user privileges on a schema given
+ * name username, text schemaname, and text priv name.
+ */
+Datum
+has_schema_privilege_name_name(PG_FUNCTION_ARGS)
+{
+ Name username = PG_GETARG_NAME(0);
+ text *schemaname = PG_GETARG_TEXT_P(1);
+ text *priv_type_text = PG_GETARG_TEXT_P(2);
+ int32 usesysid;
+ Oid schemaoid;
+ AclMode mode;
+ AclResult aclresult;
+
+ usesysid = get_usesysid(NameStr(*username));
+ schemaoid = convert_schema_name(schemaname);
+ mode = convert_schema_priv_string(priv_type_text);
+
+ aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * has_schema_privilege_name
+ * Check user privileges on a schema given
+ * text schemaname and text priv name.
+ * current_user is assumed
+ */
+Datum
+has_schema_privilege_name(PG_FUNCTION_ARGS)
+{
+ text *schemaname = PG_GETARG_TEXT_P(0);
+ text *priv_type_text = PG_GETARG_TEXT_P(1);
+ int32 usesysid;
+ Oid schemaoid;
+ AclMode mode;
+ AclResult aclresult;
+
+ usesysid = GetUserId();
+ schemaoid = convert_schema_name(schemaname);
+ mode = convert_schema_priv_string(priv_type_text);
+
+ aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * has_schema_privilege_name_id
+ * Check user privileges on a schema given
+ * name usename, schema oid, and text priv name.
+ */
+Datum
+has_schema_privilege_name_id(PG_FUNCTION_ARGS)
+{
+ Name username = PG_GETARG_NAME(0);
+ Oid schemaoid = PG_GETARG_OID(1);
+ text *priv_type_text = PG_GETARG_TEXT_P(2);
+ int32 usesysid;
+ AclMode mode;
+ AclResult aclresult;
+
+ usesysid = get_usesysid(NameStr(*username));
+ mode = convert_schema_priv_string(priv_type_text);
+
+ aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * has_schema_privilege_id
+ * Check user privileges on a schema given
+ * schema oid, and text priv name.
+ * current_user is assumed
+ */
+Datum
+has_schema_privilege_id(PG_FUNCTION_ARGS)
+{
+ Oid schemaoid = PG_GETARG_OID(0);
+ text *priv_type_text = PG_GETARG_TEXT_P(1);
+ int32 usesysid;
+ AclMode mode;
+ AclResult aclresult;
+
+ usesysid = GetUserId();
+ mode = convert_schema_priv_string(priv_type_text);
+
+ aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * has_schema_privilege_id_name
+ * Check user privileges on a schema given
+ * usesysid, text schemaname, and text priv name.
+ */
+Datum
+has_schema_privilege_id_name(PG_FUNCTION_ARGS)
+{
+ int32 usesysid = PG_GETARG_INT32(0);
+ text *schemaname = PG_GETARG_TEXT_P(1);
+ text *priv_type_text = PG_GETARG_TEXT_P(2);
+ Oid schemaoid;
+ AclMode mode;
+ AclResult aclresult;
+
+ schemaoid = convert_schema_name(schemaname);
+ mode = convert_schema_priv_string(priv_type_text);
+
+ aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * has_schema_privilege_id_id
+ * Check user privileges on a schema given
+ * usesysid, schema oid, and text priv name.
+ */
+Datum
+has_schema_privilege_id_id(PG_FUNCTION_ARGS)
+{
+ int32 usesysid = PG_GETARG_INT32(0);
+ Oid schemaoid = PG_GETARG_OID(1);
+ text *priv_type_text = PG_GETARG_TEXT_P(2);
+ AclMode mode;
+ AclResult aclresult;
+
+ mode = convert_schema_priv_string(priv_type_text);
+
+ aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+}
+
+/*
+ * Support routines for has_schema_privilege family.
+ */
+
+/*
+ * Given a schema name expressed as a string, look it up and return Oid
+ */
+static Oid
+convert_schema_name(text *schemaname)
+{
+ char *nspname;
+ Oid oid;
+
+ nspname = DatumGetCString(DirectFunctionCall1(textout,
+ PointerGetDatum(schemaname)));
+
+ oid = GetSysCacheOid(NAMESPACENAME,
+ CStringGetDatum(nspname),
+ 0, 0, 0);
+ if (!OidIsValid(oid))
+ elog(ERROR, "schema \"%s\" does not exist", nspname);
+
+ return oid;
+}
+
+/*
+ * convert_schema_priv_string
+ * Convert text string to AclMode value.
+ */
+static AclMode
+convert_schema_priv_string(text *priv_type_text)
+{
+ char *priv_type;
+
+ priv_type = DatumGetCString(DirectFunctionCall1(textout,
+ PointerGetDatum(priv_type_text)));
+
+ /*
+ * Return mode from priv_type string
+ */
+ if (strcasecmp(priv_type, "CREATE") == 0)
+ return ACL_CREATE;
+
+ if (strcasecmp(priv_type, "USAGE") == 0)
+ return ACL_USAGE;
+
+ elog(ERROR, "has_schema_privilege: invalid privilege type %s",
+ priv_type);
+ return ACL_NO_RIGHTS; /* keep compiler quiet */
}
diff --git a/src/backend/utils/adt/sets.c b/src/backend/utils/adt/sets.c
index 609e20219c..d4ba7a1805 100644
--- a/src/backend/utils/adt/sets.c
+++ b/src/backend/utils/adt/sets.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.50 2002/08/05 03:29:17 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.51 2002/08/09 16:45:14 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -25,6 +25,7 @@
#include "catalog/pg_proc.h"
#include "executor/executor.h"
#include "utils/fcache.h"
+#include "utils/fmgroids.h"
#include "utils/sets.h"
#include "utils/syscache.h"
@@ -58,7 +59,7 @@ SetDefine(char *querystr, Oid elemType)
true, /* returnsSet */
elemType, /* returnType */
SQLlanguageId, /* language */
- SQLvalidatorId,
+ F_FMGR_SQL_VALIDATOR,
querystr, /* prosrc */
fileName, /* probin */
false, /* not aggregate */
diff --git a/src/backend/utils/misc/superuser.c b/src/backend/utils/misc/superuser.c
index 9652b5c01a..735ad7adf3 100644
--- a/src/backend/utils/misc/superuser.c
+++ b/src/backend/utils/misc/superuser.c
@@ -10,19 +10,17 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/misc/superuser.c,v 1.23 2002/06/20 20:29:40 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/misc/superuser.c,v 1.24 2002/08/09 16:45:14 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "access/heapam.h"
-#include "catalog/catname.h"
-#include "catalog/pg_database.h"
#include "catalog/pg_shadow.h"
+#include "commands/dbcommands.h"
#include "utils/syscache.h"
#include "miscadmin.h"
-#include "utils/fmgroids.h"
/*
@@ -69,25 +67,9 @@ superuser_arg(Oid userid)
bool
is_dbadmin(Oid dbid)
{
- Relation pg_database;
- ScanKeyData entry[1];
- HeapScanDesc scan;
- HeapTuple dbtuple;
- int32 dba;
+ Oid dba;
- /* There's no syscache for pg_database, so must look the hard way */
- pg_database = heap_openr(DatabaseRelationName, AccessShareLock);
- ScanKeyEntryInitialize(&entry[0], 0x0,
- ObjectIdAttributeNumber, F_OIDEQ,
- ObjectIdGetDatum(dbid));
- scan = heap_beginscan(pg_database, SnapshotNow, 1, entry);
- dbtuple = heap_getnext(scan, ForwardScanDirection);
- if (!HeapTupleIsValid(dbtuple))
- elog(ERROR, "database %u does not exist", dbid);
- dba = ((Form_pg_database) GETSTRUCT(dbtuple))->datdba;
- heap_endscan(scan);
- heap_close(pg_database, AccessShareLock);
+ dba = get_database_owner(dbid);
- /* XXX some confusion about whether userids are OID or int4 ... */
- return (GetUserId() == (Oid) dba);
+ return (GetUserId() == dba);
}
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index f3dfa81879..792b2858f1 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: catversion.h,v 1.146 2002/08/06 05:40:45 ishii Exp $
+ * $Id: catversion.h,v 1.147 2002/08/09 16:45:14 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 200208061
+#define CATALOG_VERSION_NO 200208091
#endif
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index afd8a782cc..c4717e7b51 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: pg_proc.h,v 1.252 2002/08/06 05:40:45 ishii Exp $
+ * $Id: pg_proc.h,v 1.253 2002/08/09 16:45:15 tgl Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
@@ -2675,15 +2675,15 @@ DATA(insert OID = 1915 ( numeric_uplus PGNSP PGUID 12 f f t f i 1 1700 "1700
DESCR("unary plus");
DATA(insert OID = 1922 ( has_table_privilege PGNSP PGUID 12 f f t f s 3 16 "19 25 25" has_table_privilege_name_name - _null_ ));
-DESCR("user privilege on relation by username, relname");
+DESCR("user privilege on relation by username, rel name");
DATA(insert OID = 1923 ( has_table_privilege PGNSP PGUID 12 f f t f s 3 16 "19 26 25" has_table_privilege_name_id - _null_ ));
DESCR("user privilege on relation by username, rel oid");
DATA(insert OID = 1924 ( has_table_privilege PGNSP PGUID 12 f f t f s 3 16 "23 25 25" has_table_privilege_id_name - _null_ ));
-DESCR("user privilege on relation by usesysid, relname");
+DESCR("user privilege on relation by usesysid, rel name");
DATA(insert OID = 1925 ( has_table_privilege PGNSP PGUID 12 f f t f s 3 16 "23 26 25" has_table_privilege_id_id - _null_ ));
DESCR("user privilege on relation by usesysid, rel oid");
DATA(insert OID = 1926 ( has_table_privilege PGNSP PGUID 12 f f t f s 2 16 "25 25" has_table_privilege_name - _null_ ));
-DESCR("current user privilege on relation by relname");
+DESCR("current user privilege on relation by rel name");
DATA(insert OID = 1927 ( has_table_privilege PGNSP PGUID 12 f f t f s 2 16 "26 25" has_table_privilege_id - _null_ ));
DESCR("current user privilege on relation by rel oid");
@@ -2881,11 +2881,23 @@ DESCR("int8 to bitstring");
DATA(insert OID = 2076 ( int8 PGNSP PGUID 12 f f t f i 1 20 "1560" bittoint8 - _null_ ));
DESCR("bitstring to int8");
-DATA(insert OID = 2090 ( current_setting PGNSP PGUID 12 f f t f s 1 25 "25" show_config_by_name - _null_ ));
+DATA(insert OID = 2077 ( current_setting PGNSP PGUID 12 f f t f s 1 25 "25" show_config_by_name - _null_ ));
DESCR("SHOW X as a function");
-DATA(insert OID = 2091 ( set_config PGNSP PGUID 12 f f f f v 3 25 "25 25 16" set_config_by_name - _null_ ));
+DATA(insert OID = 2078 ( set_config PGNSP PGUID 12 f f f f v 3 25 "25 25 16" set_config_by_name - _null_ ));
DESCR("SET X as a function");
+DATA(insert OID = 2079 ( pg_table_is_visible PGNSP PGUID 12 f f t f s 1 16 "26" pg_table_is_visible - _null_ ));
+DESCR("is table visible in search path?");
+DATA(insert OID = 2080 ( pg_type_is_visible PGNSP PGUID 12 f f t f s 1 16 "26" pg_type_is_visible - _null_ ));
+DESCR("is type visible in search path?");
+DATA(insert OID = 2081 ( pg_function_is_visible PGNSP PGUID 12 f f t f s 1 16 "26" pg_function_is_visible - _null_ ));
+DESCR("is function visible in search path?");
+DATA(insert OID = 2082 ( pg_operator_is_visible PGNSP PGUID 12 f f t f s 1 16 "26" pg_operator_is_visible - _null_ ));
+DESCR("is operator visible in search path?");
+DATA(insert OID = 2083 ( pg_opclass_is_visible PGNSP PGUID 12 f f t f s 1 16 "26" pg_opclass_is_visible - _null_ ));
+DESCR("is opclass visible in search path?");
+
+
/* Aggregates (moved here from pg_aggregate for 7.3) */
DATA(insert OID = 2100 ( avg PGNSP PGUID 12 t f f f i 1 1700 "20" aggregate_dummy - _null_ ));
@@ -2983,7 +2995,58 @@ DATA(insert OID = 2247 ( fmgr_c_validator PGNSP PGUID 12 f f t f s 1 26 "23" f
DESCR("(internal)");
DATA(insert OID = 2248 ( fmgr_sql_validator PGNSP PGUID 12 f f t f s 1 26 "23" fmgr_sql_validator - _null_ ));
DESCR("(internal)");
-#define SQLvalidatorId 2248
+
+DATA(insert OID = 2250 ( has_database_privilege PGNSP PGUID 12 f f t f s 3 16 "19 25 25" has_database_privilege_name_name - _null_ ));
+DESCR("user privilege on database by username, database name");
+DATA(insert OID = 2251 ( has_database_privilege PGNSP PGUID 12 f f t f s 3 16 "19 26 25" has_database_privilege_name_id - _null_ ));
+DESCR("user privilege on database by username, database oid");
+DATA(insert OID = 2252 ( has_database_privilege PGNSP PGUID 12 f f t f s 3 16 "23 25 25" has_database_privilege_id_name - _null_ ));
+DESCR("user privilege on database by usesysid, database name");
+DATA(insert OID = 2253 ( has_database_privilege PGNSP PGUID 12 f f t f s 3 16 "23 26 25" has_database_privilege_id_id - _null_ ));
+DESCR("user privilege on database by usesysid, database oid");
+DATA(insert OID = 2254 ( has_database_privilege PGNSP PGUID 12 f f t f s 2 16 "25 25" has_database_privilege_name - _null_ ));
+DESCR("current user privilege on database by database name");
+DATA(insert OID = 2255 ( has_database_privilege PGNSP PGUID 12 f f t f s 2 16 "26 25" has_database_privilege_id - _null_ ));
+DESCR("current user privilege on database by database oid");
+
+DATA(insert OID = 2256 ( has_function_privilege PGNSP PGUID 12 f f t f s 3 16 "19 25 25" has_function_privilege_name_name - _null_ ));
+DESCR("user privilege on function by username, function name");
+DATA(insert OID = 2257 ( has_function_privilege PGNSP PGUID 12 f f t f s 3 16 "19 26 25" has_function_privilege_name_id - _null_ ));
+DESCR("user privilege on function by username, function oid");
+DATA(insert OID = 2258 ( has_function_privilege PGNSP PGUID 12 f f t f s 3 16 "23 25 25" has_function_privilege_id_name - _null_ ));
+DESCR("user privilege on function by usesysid, function name");
+DATA(insert OID = 2259 ( has_function_privilege PGNSP PGUID 12 f f t f s 3 16 "23 26 25" has_function_privilege_id_id - _null_ ));
+DESCR("user privilege on function by usesysid, function oid");
+DATA(insert OID = 2260 ( has_function_privilege PGNSP PGUID 12 f f t f s 2 16 "25 25" has_function_privilege_name - _null_ ));
+DESCR("current user privilege on function by function name");
+DATA(insert OID = 2261 ( has_function_privilege PGNSP PGUID 12 f f t f s 2 16 "26 25" has_function_privilege_id - _null_ ));
+DESCR("current user privilege on function by function oid");
+
+DATA(insert OID = 2262 ( has_language_privilege PGNSP PGUID 12 f f t f s 3 16 "19 25 25" has_language_privilege_name_name - _null_ ));
+DESCR("user privilege on language by username, language name");
+DATA(insert OID = 2263 ( has_language_privilege PGNSP PGUID 12 f f t f s 3 16 "19 26 25" has_language_privilege_name_id - _null_ ));
+DESCR("user privilege on language by username, language oid");
+DATA(insert OID = 2264 ( has_language_privilege PGNSP PGUID 12 f f t f s 3 16 "23 25 25" has_language_privilege_id_name - _null_ ));
+DESCR("user privilege on language by usesysid, language name");
+DATA(insert OID = 2265 ( has_language_privilege PGNSP PGUID 12 f f t f s 3 16 "23 26 25" has_language_privilege_id_id - _null_ ));
+DESCR("user privilege on language by usesysid, language oid");
+DATA(insert OID = 2266 ( has_language_privilege PGNSP PGUID 12 f f t f s 2 16 "25 25" has_language_privilege_name - _null_ ));
+DESCR("current user privilege on language by language name");
+DATA(insert OID = 2267 ( has_language_privilege PGNSP PGUID 12 f f t f s 2 16 "26 25" has_language_privilege_id - _null_ ));
+DESCR("current user privilege on language by language oid");
+
+DATA(insert OID = 2268 ( has_schema_privilege PGNSP PGUID 12 f f t f s 3 16 "19 25 25" has_schema_privilege_name_name - _null_ ));
+DESCR("user privilege on schema by username, schema name");
+DATA(insert OID = 2269 ( has_schema_privilege PGNSP PGUID 12 f f t f s 3 16 "19 26 25" has_schema_privilege_name_id - _null_ ));
+DESCR("user privilege on schema by username, schema oid");
+DATA(insert OID = 2270 ( has_schema_privilege PGNSP PGUID 12 f f t f s 3 16 "23 25 25" has_schema_privilege_id_name - _null_ ));
+DESCR("user privilege on schema by usesysid, schema name");
+DATA(insert OID = 2271 ( has_schema_privilege PGNSP PGUID 12 f f t f s 3 16 "23 26 25" has_schema_privilege_id_id - _null_ ));
+DESCR("user privilege on schema by usesysid, schema oid");
+DATA(insert OID = 2272 ( has_schema_privilege PGNSP PGUID 12 f f t f s 2 16 "25 25" has_schema_privilege_name - _null_ ));
+DESCR("current user privilege on schema by schema name");
+DATA(insert OID = 2273 ( has_schema_privilege PGNSP PGUID 12 f f t f s 2 16 "26 25" has_schema_privilege_id - _null_ ));
+DESCR("current user privilege on schema by schema oid");
/*
* Symbolic values for provolatile column: these indicate whether the result
diff --git a/src/include/commands/dbcommands.h b/src/include/commands/dbcommands.h
index d0cccbda46..89e3f471f7 100644
--- a/src/include/commands/dbcommands.h
+++ b/src/include/commands/dbcommands.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: dbcommands.h,v 1.24 2002/06/20 20:29:49 momjian Exp $
+ * $Id: dbcommands.h,v 1.25 2002/08/09 16:45:16 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -20,4 +20,7 @@ extern void createdb(const CreatedbStmt *stmt);
extern void dropdb(const char *dbname);
extern void AlterDatabaseSet(AlterDatabaseSetStmt *stmt);
+extern Oid get_database_oid(const char *dbname);
+extern Oid get_database_owner(Oid dbid);
+
#endif /* DBCOMMANDS_H */
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index a138e2d2ff..01d5a4e730 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: builtins.h,v 1.189 2002/08/06 14:11:05 tgl Exp $
+ * $Id: builtins.h,v 1.190 2002/08/09 16:45:16 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -29,6 +29,30 @@ 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_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);
+extern Datum has_database_privilege_id_id(PG_FUNCTION_ARGS);
+extern Datum has_database_privilege_name(PG_FUNCTION_ARGS);
+extern Datum has_database_privilege_id(PG_FUNCTION_ARGS);
+extern Datum has_function_privilege_name_name(PG_FUNCTION_ARGS);
+extern Datum has_function_privilege_name_id(PG_FUNCTION_ARGS);
+extern Datum has_function_privilege_id_name(PG_FUNCTION_ARGS);
+extern Datum has_function_privilege_id_id(PG_FUNCTION_ARGS);
+extern Datum has_function_privilege_name(PG_FUNCTION_ARGS);
+extern Datum has_function_privilege_id(PG_FUNCTION_ARGS);
+extern Datum has_language_privilege_name_name(PG_FUNCTION_ARGS);
+extern Datum has_language_privilege_name_id(PG_FUNCTION_ARGS);
+extern Datum has_language_privilege_id_name(PG_FUNCTION_ARGS);
+extern Datum has_language_privilege_id_id(PG_FUNCTION_ARGS);
+extern Datum has_language_privilege_name(PG_FUNCTION_ARGS);
+extern Datum has_language_privilege_id(PG_FUNCTION_ARGS);
+extern Datum has_schema_privilege_name_name(PG_FUNCTION_ARGS);
+extern Datum has_schema_privilege_name_id(PG_FUNCTION_ARGS);
+extern Datum has_schema_privilege_id_name(PG_FUNCTION_ARGS);
+extern Datum has_schema_privilege_id_id(PG_FUNCTION_ARGS);
+extern Datum has_schema_privilege_name(PG_FUNCTION_ARGS);
+extern Datum has_schema_privilege_id(PG_FUNCTION_ARGS);
/* bool.c */
extern Datum boolin(PG_FUNCTION_ARGS);