From 4ab8e69094452286a5894f1b2b237304808f4391 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 9 Aug 2002 16:45:16 +0000 Subject: [PATCH] has_table_privilege spawns scions has_database_privilege, has_function_privilege, has_language_privilege, has_schema_privilege to let SQL queries test all the new privilege types in 7.3. Also, add functions pg_table_is_visible, pg_type_is_visible, pg_function_is_visible, pg_operator_is_visible, pg_opclass_is_visible to test whether objects contained in schemas are visible in the current search path. Do some minor cleanup to centralize accesses to pg_database, as well. --- contrib/dbsize/dbsize.c | 24 +- doc/src/sgml/func.sgml | 256 +++++-- src/backend/catalog/namespace.c | 53 +- src/backend/commands/comment.c | 38 +- src/backend/commands/dbcommands.c | 77 ++- src/backend/utils/adt/acl.c | 1014 ++++++++++++++++++++++++---- src/backend/utils/adt/sets.c | 5 +- src/backend/utils/misc/superuser.c | 28 +- src/include/catalog/catversion.h | 4 +- src/include/catalog/pg_proc.h | 77 ++- src/include/commands/dbcommands.h | 5 +- src/include/utils/builtins.h | 26 +- 12 files changed, 1325 insertions(+), 282 deletions(-) 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);