Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Eisentraut2002-02-18 23:11:58 +0000
committerPeter Eisentraut2002-02-18 23:11:58 +0000
commit8adf56f77aa0cc8cf4af7a19f0d235fc56fbabc7 (patch)
treecab3054a1a1fba1fe1722bb75a1fc3c06eda964d /src/backend
parent5e035031265aef8608fd32a31897240a3aff3d8d (diff)
Privileges on functions and procedural languages
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/catalog/aclchk.c568
-rw-r--r--src/backend/catalog/pg_proc.c18
-rw-r--r--src/backend/commands/define.c110
-rw-r--r--src/backend/commands/proclang.c13
-rw-r--r--src/backend/executor/execQual.c5
-rw-r--r--src/backend/nodes/copyfuncs.c25
-rw-r--r--src/backend/nodes/equalfuncs.c18
-rw-r--r--src/backend/parser/gram.y154
-rw-r--r--src/backend/parser/keywords.c36
-rw-r--r--src/backend/utils/Gen_fmgrtab.sh8
-rw-r--r--src/backend/utils/adt/acl.c20
-rw-r--r--src/backend/utils/adt/sets.c5
-rw-r--r--src/backend/utils/cache/fcache.c6
-rw-r--r--src/backend/utils/misc/superuser.c14
14 files changed, 775 insertions, 225 deletions
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index 932eeeedbff..0a1948dea24 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.53 2001/11/05 17:46:24 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.54 2002/02/18 23:11:07 petere Exp $
*
* NOTES
* See acl.h.
@@ -18,22 +18,35 @@
#include "postgres.h"
#include "access/heapam.h"
+#include "access/transam.h"
#include "catalog/catalog.h"
#include "catalog/catname.h"
#include "catalog/indexing.h"
#include "catalog/pg_aggregate.h"
#include "catalog/pg_group.h"
+#include "catalog/pg_language.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_shadow.h"
#include "catalog/pg_type.h"
#include "miscadmin.h"
+#include "nodes/parsenodes.h"
+#include "parser/keywords.h"
+#include "parser/parse.h"
#include "parser/parse_agg.h"
#include "parser/parse_func.h"
+#include "parser/parse_expr.h"
#include "utils/acl.h"
#include "utils/syscache.h"
#include "utils/temprel.h"
+
+static void ExecuteGrantStmt_Table(GrantStmt *stmt);
+static void ExecuteGrantStmt_Function(GrantStmt *stmt);
+static void ExecuteGrantStmt_Lang(GrantStmt *stmt);
+
+static const char *privilege_token_string(int token);
+
static int32 aclcheck(Acl *acl, AclId id, AclIdType idtype, AclMode mode);
/* warning messages, now more explicit. */
@@ -65,18 +78,127 @@ dumpacl(Acl *acl)
/*
+ * If is_grant is true, adds the given privileges for the list of
+ * grantees to the existing old_acl. If is_grant is false, the
+ * privileges for the given grantees are removed from old_acl.
+ */
+static Acl*
+merge_acl_with_grant(Acl *old_acl, bool is_grant, List *grantees, char *privileges)
+{
+ List *j;
+ Acl *new_acl;
+
+#ifdef ACLDEBUG
+ dumpacl(old_acl);
+#endif
+ new_acl = old_acl;
+
+ foreach(j, grantees)
+ {
+ PrivGrantee *grantee = (PrivGrantee *) lfirst(j);
+ char *granteeString;
+ char *aclString;
+ AclItem aclitem;
+ unsigned modechg;
+
+ if (grantee->username)
+ granteeString = aclmakeuser("U", grantee->username);
+ else if (grantee->groupname)
+ granteeString = aclmakeuser("G", grantee->groupname);
+ else
+ granteeString = aclmakeuser("A", "");
+
+ aclString = makeAclString(privileges, granteeString,
+ is_grant ? '+' : '-');
+
+ /* Convert string ACL spec into internal form */
+ aclparse(aclString, &aclitem, &modechg);
+ new_acl = aclinsert3(new_acl, &aclitem, modechg);
+
+#ifdef ACLDEBUG
+ dumpacl(new_acl);
+#endif
+ }
+
+ return new_acl;
+}
+
+
+/*
* Called to execute the utility commands GRANT and REVOKE
*/
void
ExecuteGrantStmt(GrantStmt *stmt)
{
- List *i;
- List *j;
-
/* see comment in pg_type.h */
Assert(ACLITEMSIZE == sizeof(AclItem));
- foreach(i, stmt->relnames)
+ switch(stmt->objtype)
+ {
+ case TABLE:
+ ExecuteGrantStmt_Table(stmt);
+ break;
+ case FUNCTION:
+ ExecuteGrantStmt_Function(stmt);
+ break;
+ case LANGUAGE:
+ ExecuteGrantStmt_Lang(stmt);
+ break;
+ default:
+ elog(ERROR, "bogus GrantStmt.objtype %d", stmt->objtype);
+ }
+}
+
+
+static void
+ExecuteGrantStmt_Table(GrantStmt *stmt)
+{
+ List *i;
+ char *privstring;
+
+ if (lfirsti(stmt->privileges) == ALL)
+ privstring = aclmakepriv(ACL_MODE_STR, 0);
+ else
+ {
+ privstring = "";
+ foreach(i, stmt->privileges)
+ {
+ int c = 0;
+
+ switch(lfirsti(i))
+ {
+ case SELECT:
+ c = ACL_MODE_SELECT_CHR;
+ break;
+ case INSERT:
+ c = ACL_MODE_INSERT_CHR;
+ break;
+ case UPDATE:
+ c = ACL_MODE_UPDATE_CHR;
+ break;
+ case DELETE:
+ c = ACL_MODE_DELETE_CHR;
+ break;
+ case RULE:
+ c = ACL_MODE_RULE_CHR;
+ break;
+ case REFERENCES:
+ c = ACL_MODE_REFERENCES_CHR;
+ break;
+ case TRIGGER:
+ c = ACL_MODE_TRIGGER_CHR;
+ break;
+ default:
+ elog(ERROR, "invalid privilege type %s for table object",
+ privilege_token_string(lfirsti(i)));
+ }
+
+ privstring = aclmakepriv(privstring, c);
+ }
+ }
+
+
+ foreach(i, stmt->objects)
{
char *relname = strVal(lfirst(i));
Relation relation;
@@ -120,41 +242,13 @@ ExecuteGrantStmt(GrantStmt *stmt)
aclDatum = SysCacheGetAttr(RELNAME, tuple, Anum_pg_class_relacl,
&isNull);
if (isNull)
- old_acl = acldefault(relname, pg_class_tuple->relowner);
+ old_acl = acldefault(pg_class_tuple->relowner);
else
/* get a detoasted copy of the rel's ACL */
old_acl = DatumGetAclPCopy(aclDatum);
-#ifdef ACLDEBUG
- dumpacl(old_acl);
-#endif
- new_acl = old_acl;
-
- foreach(j, stmt->grantees)
- {
- PrivGrantee *grantee = (PrivGrantee *) lfirst(j);
- char *granteeString;
- char *aclString;
- AclItem aclitem;
- unsigned modechg;
-
- if (grantee->username)
- granteeString = aclmakeuser("U", grantee->username);
- else if (grantee->groupname)
- granteeString = aclmakeuser("G", grantee->groupname);
- else
- granteeString = aclmakeuser("A", "");
-
- aclString = makeAclString(stmt->privileges, granteeString,
- stmt->is_grant ? '+' : '-');
-
- /* Convert string ACL spec into internal form */
- aclparse(aclString, &aclitem, &modechg);
- new_acl = aclinsert3(new_acl, &aclitem, modechg);
-#ifdef ACLDEBUG
- dumpacl(new_acl);
-#endif
- }
+ new_acl = merge_acl_with_grant(old_acl, stmt->is_grant,
+ stmt->grantees, privstring);
/* finished building new ACL value, now insert it */
for (i = 0; i < Natts_pg_class; ++i)
@@ -190,6 +284,267 @@ ExecuteGrantStmt(GrantStmt *stmt)
}
+static Oid
+find_function_with_arglist(char *name, List *arguments)
+{
+ Oid oid;
+ Oid argoids[FUNC_MAX_ARGS];
+ int i;
+ int16 argcount;
+
+ MemSet(argoids, 0, FUNC_MAX_ARGS * sizeof(Oid));
+ argcount = length(arguments);
+ if (argcount > FUNC_MAX_ARGS)
+ elog(ERROR, "functions cannot have more than %d arguments",
+ FUNC_MAX_ARGS);
+
+ for (i = 0; i < argcount; i++)
+ {
+ TypeName *t = (TypeName *) lfirst(arguments);
+ char *typnam = TypeNameToInternalName(t);
+
+ arguments = lnext(arguments);
+
+ if (strcmp(typnam, "opaque") == 0)
+ argoids[i] = InvalidOid;
+ else
+ {
+ argoids[i] = GetSysCacheOid(TYPENAME,
+ PointerGetDatum(typnam),
+ 0, 0, 0);
+ if (!OidIsValid(argoids[i]))
+ elog(ERROR, "type '%s' not found", typnam);
+ }
+ }
+
+ oid = GetSysCacheOid(PROCNAME,
+ PointerGetDatum(name),
+ Int16GetDatum(argcount),
+ PointerGetDatum(argoids),
+ 0);
+
+ if (!OidIsValid(oid))
+ func_error(NULL, name, argcount, argoids, NULL);
+
+ return oid;
+}
+
+
+static void
+ExecuteGrantStmt_Function(GrantStmt *stmt)
+{
+ List *i;
+ char *privstring = NULL;
+
+ if (lfirsti(stmt->privileges) == ALL)
+ privstring = aclmakepriv("", ACL_MODE_SELECT_CHR);
+ else
+ {
+ foreach(i, stmt->privileges)
+ {
+ if (lfirsti(i) != EXECUTE)
+ elog(ERROR, "invalid privilege type %s for function object",
+ privilege_token_string(lfirsti(i)));
+ }
+
+ privstring = aclmakepriv("", ACL_MODE_SELECT_CHR);
+ }
+
+ foreach(i, stmt->objects)
+ {
+ FuncWithArgs *func = (FuncWithArgs *) lfirst(i);
+ Oid oid;
+ Relation relation;
+ HeapTuple tuple;
+ Form_pg_proc pg_proc_tuple;
+ Datum aclDatum;
+ bool isNull;
+ Acl *old_acl;
+ Acl *new_acl;
+ unsigned i;
+ HeapTuple newtuple;
+ Datum values[Natts_pg_proc];
+ char nulls[Natts_pg_proc];
+ char replaces[Natts_pg_proc];
+
+ oid = find_function_with_arglist(func->funcname, func->funcargs);
+ relation = heap_openr(ProcedureRelationName, RowExclusiveLock);
+ tuple = SearchSysCache(PROCOID, ObjectIdGetDatum(oid), 0, 0, 0);
+ if (!HeapTupleIsValid(tuple))
+ {
+ heap_close(relation, RowExclusiveLock);
+ elog(ERROR, "function %u not found", oid);
+ }
+ pg_proc_tuple = (Form_pg_proc) GETSTRUCT(tuple);
+
+ if (pg_proc_tuple->proowner != GetUserId())
+ elog(ERROR, "permission denied");
+
+ /*
+ * If there's no ACL, create a default using the pg_proc.proowner
+ * field.
+ */
+ aclDatum = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_proacl,
+ &isNull);
+ if (isNull)
+ old_acl = acldefault(pg_proc_tuple->proowner);
+ else
+ /* get a detoasted copy of the rel's ACL */
+ old_acl = DatumGetAclPCopy(aclDatum);
+
+ new_acl = merge_acl_with_grant(old_acl, stmt->is_grant,
+ stmt->grantees, privstring);
+
+ /* finished building new ACL value, now insert it */
+ for (i = 0; i < Natts_pg_proc; ++i)
+ {
+ replaces[i] = ' ';
+ nulls[i] = ' '; /* ignored if replaces[i]==' ' anyway */
+ values[i] = (Datum) NULL; /* ignored if replaces[i]==' '
+ * anyway */
+ }
+ replaces[Anum_pg_proc_proacl - 1] = 'r';
+ values[Anum_pg_proc_proacl - 1] = PointerGetDatum(new_acl);
+ newtuple = heap_modifytuple(tuple, relation, values, nulls, replaces);
+
+ ReleaseSysCache(tuple);
+
+ simple_heap_update(relation, &newtuple->t_self, newtuple);
+
+ {
+ /* keep the catalog indexes up to date */
+ Relation idescs[Num_pg_proc_indices];
+
+ CatalogOpenIndices(Num_pg_proc_indices, Name_pg_proc_indices,
+ idescs);
+ CatalogIndexInsert(idescs, Num_pg_proc_indices, relation, newtuple);
+ CatalogCloseIndices(Num_pg_proc_indices, idescs);
+ }
+
+ pfree(old_acl);
+ pfree(new_acl);
+
+ heap_close(relation, RowExclusiveLock);
+ }
+}
+
+
+static void
+ExecuteGrantStmt_Lang(GrantStmt *stmt)
+{
+ List *i;
+ char *privstring = NULL;
+
+ if (lfirsti(stmt->privileges) == ALL)
+ privstring = aclmakepriv("", ACL_MODE_SELECT_CHR);
+ else
+ {
+ foreach(i, stmt->privileges)
+ {
+ if (lfirsti(i) != USAGE)
+ elog(ERROR, "invalid privilege type %s for language object",
+ privilege_token_string(lfirsti(i)));
+ }
+
+ privstring = aclmakepriv("", ACL_MODE_SELECT_CHR);
+ }
+
+ foreach(i, stmt->objects)
+ {
+ char *langname = strVal(lfirst(i));
+ Relation relation;
+ HeapTuple tuple;
+ Form_pg_language pg_language_tuple;
+ Datum aclDatum;
+ bool isNull;
+ Acl *old_acl;
+ Acl *new_acl;
+ unsigned i;
+ HeapTuple newtuple;
+ Datum values[Natts_pg_language];
+ char nulls[Natts_pg_language];
+ char replaces[Natts_pg_language];
+
+ if (!superuser())
+ elog(ERROR, "permission denied");
+
+ relation = heap_openr(LanguageRelationName, RowExclusiveLock);
+ tuple = SearchSysCache(LANGNAME, PointerGetDatum(langname), 0, 0, 0);
+ if (!HeapTupleIsValid(tuple))
+ {
+ heap_close(relation, RowExclusiveLock);
+ elog(ERROR, "language \"%s\" not found", langname);
+ }
+ pg_language_tuple = (Form_pg_language) GETSTRUCT(tuple);
+
+ if (!pg_language_tuple->lanpltrusted)
+ {
+ heap_close(relation, RowExclusiveLock);
+ elog(ERROR, "language \"%s\" is not trusted", langname);
+ }
+
+ /*
+ * If there's no ACL, create a default.
+ */
+ aclDatum = SysCacheGetAttr(LANGNAME, tuple, Anum_pg_language_lanacl,
+ &isNull);
+ if (isNull)
+ old_acl = acldefault(InvalidOid);
+ else
+ /* get a detoasted copy of the rel's ACL */
+ old_acl = DatumGetAclPCopy(aclDatum);
+
+ new_acl = merge_acl_with_grant(old_acl, stmt->is_grant,
+ stmt->grantees, privstring);
+
+ /* finished building new ACL value, now insert it */
+ for (i = 0; i < Natts_pg_language; ++i)
+ {
+ replaces[i] = ' ';
+ nulls[i] = ' '; /* ignored if replaces[i]==' ' anyway */
+ values[i] = (Datum) NULL; /* ignored if replaces[i]==' '
+ * anyway */
+ }
+ replaces[Anum_pg_language_lanacl - 1] = 'r';
+ values[Anum_pg_language_lanacl - 1] = PointerGetDatum(new_acl);
+ newtuple = heap_modifytuple(tuple, relation, values, nulls, replaces);
+
+ ReleaseSysCache(tuple);
+
+ simple_heap_update(relation, &newtuple->t_self, newtuple);
+
+ {
+ /* keep the catalog indexes up to date */
+ Relation idescs[Num_pg_language_indices];
+
+ CatalogOpenIndices(Num_pg_language_indices, Name_pg_language_indices,
+ idescs);
+ CatalogIndexInsert(idescs, Num_pg_language_indices, relation, newtuple);
+ CatalogCloseIndices(Num_pg_language_indices, idescs);
+ }
+
+ pfree(old_acl);
+ pfree(new_acl);
+
+ heap_close(relation, RowExclusiveLock);
+ }
+}
+
+
+
+static const char *
+privilege_token_string(int token)
+{
+ const char *s = TokenString(token);
+
+ if (s)
+ return s;
+ else
+ elog(ERROR, "privilege_token_string: invalid token number");
+ return NULL; /* appease compiler */
+}
+
+
AclId
get_grosysid(char *groname)
@@ -483,7 +838,7 @@ pg_aclcheck(char *relname, Oid userid, AclMode mode)
AclId ownerId;
ownerId = ((Form_pg_class) GETSTRUCT(tuple))->relowner;
- acl = acldefault(relname, ownerId);
+ acl = acldefault(ownerId);
aclDatum = (Datum) 0;
}
else
@@ -721,3 +1076,142 @@ pg_aggr_ownercheck(Oid userid,
return userid == owner_id;
}
+
+
+
+/*
+ * Exported routine for checking a user's access privileges to a function
+ *
+ * Returns an ACLCHECK_* result code.
+ */
+int32
+pg_proc_aclcheck(Oid proc_oid, Oid userid)
+{
+ int32 result;
+ HeapTuple tuple;
+ Datum aclDatum;
+ bool isNull;
+ Acl *acl;
+
+ if (superuser_arg(userid))
+ return ACLCHECK_OK;
+
+ /*
+ * Validate userid
+ */
+ tuple = SearchSysCache(SHADOWSYSID,
+ ObjectIdGetDatum(userid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "pg_proc_aclcheck: invalid user id %u",
+ (unsigned) userid);
+ ReleaseSysCache(tuple);
+
+ /*
+ * Normal case: get the function's ACL from pg_proc
+ */
+ tuple = SearchSysCache(PROCOID,
+ ObjectIdGetDatum(proc_oid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "pg_proc_aclcheck: function %u not found", proc_oid);
+
+ aclDatum = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_proacl,
+ &isNull);
+ if (isNull)
+ {
+ /* No ACL, so build default ACL */
+ AclId ownerId;
+
+ ownerId = ((Form_pg_proc) GETSTRUCT(tuple))->proowner;
+ acl = acldefault(ownerId);
+ aclDatum = (Datum) 0;
+ }
+ else
+ {
+ /* detoast ACL if necessary */
+ acl = DatumGetAclP(aclDatum);
+ }
+
+ /*
+ * Functions only have one kind of privilege, which is encoded as
+ * "SELECT" here.
+ */
+ result = aclcheck(acl, userid, (AclIdType) ACL_IDTYPE_UID, ACL_SELECT);
+
+ /* if we have a detoasted copy, free it */
+ if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
+ pfree(acl);
+
+ ReleaseSysCache(tuple);
+
+ return result;
+}
+
+
+
+/*
+ * Exported routine for checking a user's access privileges to a language
+ *
+ * Returns an ACLCHECK_* result code.
+ */
+int32
+pg_language_aclcheck(Oid lang_oid, Oid userid)
+{
+ int32 result;
+ HeapTuple tuple;
+ Datum aclDatum;
+ bool isNull;
+ Acl *acl;
+
+ if (superuser_arg(userid))
+ return ACLCHECK_OK;
+
+ /*
+ * Validate userid
+ */
+ tuple = SearchSysCache(SHADOWSYSID,
+ ObjectIdGetDatum(userid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "pg_language_aclcheck: invalid user id %u",
+ (unsigned) userid);
+ ReleaseSysCache(tuple);
+
+ /*
+ * Normal case: get the function's ACL from pg_language
+ */
+ tuple = SearchSysCache(LANGOID,
+ ObjectIdGetDatum(lang_oid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "pg_language_aclcheck: language %u not found", lang_oid);
+
+ aclDatum = SysCacheGetAttr(LANGOID, tuple, Anum_pg_language_lanacl,
+ &isNull);
+ if (isNull)
+ {
+ /* No ACL, so build default ACL */
+ acl = acldefault(InvalidOid);
+ aclDatum = (Datum) 0;
+ }
+ else
+ {
+ /* detoast ACL if necessary */
+ acl = DatumGetAclP(aclDatum);
+ }
+
+ /*
+ * Languages only have one kind of privilege, which is encoded as
+ * "SELECT" here.
+ */
+ result = aclcheck(acl, userid, (AclIdType) ACL_IDTYPE_UID, ACL_SELECT);
+
+ /* if we have a detoasted copy, free it */
+ if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
+ pfree(acl);
+
+ ReleaseSysCache(tuple);
+
+ return result;
+}
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index 32d9293f566..3035df4502b 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.63 2001/11/05 17:46:24 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.64 2002/02/18 23:11:08 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -44,7 +44,7 @@ ProcedureCreate(char *procedureName,
bool replace,
bool returnsSet,
char *returnTypeName,
- char *languageName,
+ Oid languageObjectId,
char *prosrc,
char *probin,
bool trusted,
@@ -65,7 +65,6 @@ ProcedureCreate(char *procedureName,
char nulls[Natts_pg_proc];
Datum values[Natts_pg_proc];
char replaces[Natts_pg_proc];
- Oid languageObjectId;
Oid typeObjectId;
List *x;
List *querytree_list;
@@ -82,12 +81,6 @@ ProcedureCreate(char *procedureName,
Assert(PointerIsValid(prosrc));
Assert(PointerIsValid(probin));
- languageObjectId = GetSysCacheOid(LANGNAME,
- PointerGetDatum(languageName),
- 0, 0, 0);
- if (!OidIsValid(languageObjectId))
- elog(ERROR, "language '%s' does not exist", languageName);
-
parameterCount = 0;
MemSet(typev, 0, FUNC_MAX_ARGS * sizeof(Oid));
foreach(x, argList)
@@ -320,6 +313,9 @@ ProcedureCreate(char *procedureName,
elog(ERROR, "ProcedureCreate: cannot change return type of existing function."
"\n\tUse DROP FUNCTION first.");
+ /* do not change existing permissions */
+ replaces[Anum_pg_proc_proacl-1] = ' ';
+
/* Okay, do it... */
tup = heap_modifytuple(oldtup, rel, values, nulls, replaces);
simple_heap_update(rel, &tup->t_self, tup);
@@ -329,6 +325,10 @@ ProcedureCreate(char *procedureName,
else
{
/* Creating a new procedure */
+
+ /* start out with empty permissions */
+ nulls[Anum_pg_proc_proacl-1] = 'n';
+
tup = heap_formtuple(tupDesc, values, nulls);
heap_insert(rel, tup);
}
diff --git a/src/backend/commands/define.c b/src/backend/commands/define.c
index 30a175c659e..140690a5a4b 100644
--- a/src/backend/commands/define.c
+++ b/src/backend/commands/define.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.64 2001/10/28 06:25:42 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.65 2002/02/18 23:11:10 petere Exp $
*
* DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the
@@ -50,6 +50,7 @@
#include "miscadmin.h"
#include "optimizer/cost.h"
#include "parser/parse_expr.h"
+#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/syscache.h"
@@ -60,22 +61,18 @@ static int defGetTypeLength(DefElem *def);
#define DEFAULT_TYPDELIM ','
+/*
+ * Translate the input language name to lower case.
+ */
static void
case_translate_language_name(const char *input, char *output)
{
-/*
- * Translate the input language name to lower case, except if it's "C",
- * translate to upper case.
- */
int i;
for (i = 0; i < NAMEDATALEN - 1 && input[i]; ++i)
output[i] = tolower((unsigned char) input[i]);
output[i] = '\0';
-
- if (strcmp(output, "c") == 0)
- output[0] = 'C';
}
@@ -175,12 +172,12 @@ compute_full_attributes(List *parameters,
*/
static void
-interpret_AS_clause(const char *languageName, const List *as,
+interpret_AS_clause(Oid languageOid, const char *languageName, const List *as,
char **prosrc_str_p, char **probin_str_p)
{
Assert(as != NIL);
- if (strcmp(languageName, "C") == 0)
+ if (languageOid == ClanguageId)
{
/*
* For "C" language, store the file name in probin and, when
@@ -213,29 +210,16 @@ interpret_AS_clause(const char *languageName, const List *as,
void
CreateFunction(ProcedureStmt *stmt)
{
- char *probin_str;
-
/* pathname of executable file that executes this function, if any */
-
- char *prosrc_str;
-
+ char *probin_str;
/* SQL that executes this function, if any */
-
- char *prorettype;
-
+ char *prosrc_str;
/* Type of return value (or member of set of values) from function */
-
+ char *prorettype;
+ /* name of language of function, with case adjusted */
char languageName[NAMEDATALEN];
-
- /*
- * name of language of function, with case adjusted: "C", "internal",
- * "sql", etc.
- */
-
- bool returnsSet;
-
/* The function returns a set of values, as opposed to a singleton. */
-
+ bool returnsSet;
/*
* The following are optional user-supplied attributes of the
* function.
@@ -247,62 +231,28 @@ CreateFunction(ProcedureStmt *stmt)
bool canCache,
isStrict;
+ HeapTuple languageTuple;
+ Form_pg_language languageStruct;
+ Oid languageOid;
+
/* Convert language name to canonical case */
case_translate_language_name(stmt->language, languageName);
- /*
- * Apply appropriate security checks depending on language.
- */
- if (strcmp(languageName, "C") == 0 ||
- strcmp(languageName, "internal") == 0)
- {
- if (!superuser())
- elog(ERROR,
- "Only users with Postgres superuser privilege are "
- "permitted to create a function in the '%s' language.\n\t"
- "Others may use the 'sql' language "
- "or the created procedural languages.",
- languageName);
- }
- else if (strcmp(languageName, "sql") == 0)
- {
- /* No security check needed for SQL functions */
- }
- else
- {
- HeapTuple languageTuple;
- Form_pg_language languageStruct;
-
- /* Lookup the language in the system cache */
- languageTuple = SearchSysCache(LANGNAME,
- PointerGetDatum(languageName),
- 0, 0, 0);
- if (!HeapTupleIsValid(languageTuple))
- elog(ERROR,
- "Unrecognized language specified in a CREATE FUNCTION: "
- "'%s'.\n\tPre-installed languages are SQL, C, and "
- "internal.\n\tAdditional languages may be installed "
- "using 'createlang'.",
- languageName);
+ languageTuple = SearchSysCache(LANGNAME,
+ PointerGetDatum(languageName),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(languageTuple))
+ elog(ERROR, "language \"%s\" does not exist", languageName);
- /* Check that this language is a PL */
- languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
- if (!languageStruct->lanispl)
- elog(ERROR,
- "Language '%s' isn't defined as PL", languageName);
+ languageOid = languageTuple->t_data->t_oid;
+ languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
- /*
- * Functions in untrusted procedural languages are restricted to
- * be defined by postgres superusers only
- */
- if (!languageStruct->lanpltrusted && !superuser())
- elog(ERROR, "Only users with Postgres superuser privilege "
- "are permitted to create a function in the '%s' "
- "language.",
- languageName);
+ if (!((languageStruct->lanpltrusted
+ && pg_language_aclcheck(languageOid, GetUserId()) == ACLCHECK_OK)
+ || superuser()))
+ elog(ERROR, "permission denied");
- ReleaseSysCache(languageTuple);
- }
+ ReleaseSysCache(languageTuple);
/*
* Convert remaining parameters of CREATE to form wanted by
@@ -316,7 +266,7 @@ CreateFunction(ProcedureStmt *stmt)
&byte_pct, &perbyte_cpu, &percall_cpu,
&outin_ratio, &canCache, &isStrict);
- interpret_AS_clause(languageName, stmt->as, &prosrc_str, &probin_str);
+ interpret_AS_clause(languageOid, languageName, stmt->as, &prosrc_str, &probin_str);
/*
* And now that we have all the parameters, and know we're permitted
@@ -326,7 +276,7 @@ CreateFunction(ProcedureStmt *stmt)
stmt->replace,
returnsSet,
prorettype,
- languageName,
+ languageOid,
prosrc_str, /* converted to text later */
probin_str, /* converted to text later */
true, /* (obsolete "trusted") */
diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c
index 120c5d8b008..d9cf0f0814a 100644
--- a/src/backend/commands/proclang.c
+++ b/src/backend/commands/proclang.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.28 2001/06/13 21:44:40 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.29 2002/02/18 23:11:11 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -27,22 +27,18 @@
#include "utils/syscache.h"
+/*
+ * Translate the input language name to lower case.
+ */
static void
case_translate_language_name(const char *input, char *output)
{
-/*-------------------------------------------------------------------------
- Translate the input language name to lower case, except if it's C,
- translate to upper case.
---------------------------------------------------------------------------*/
int i;
for (i = 0; i < NAMEDATALEN && input[i]; ++i)
output[i] = tolower((unsigned char) input[i]);
output[i] = '\0';
-
- if (strcmp(output, "c") == 0)
- output[0] = 'C';
}
@@ -116,6 +112,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
values[i++] = ObjectIdGetDatum(procTup->t_data->t_oid);
values[i++] = DirectFunctionCall1(textin,
CStringGetDatum(stmt->plcompiler));
+ nulls[i] = 'n'; /* lanacl */
ReleaseSysCache(procTup);
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index f78517b1848..e77eeed8030 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.89 2001/10/25 05:49:27 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.90 2002/02/18 23:11:13 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -658,6 +658,9 @@ ExecMakeFunctionResult(FunctionCachePtr fcache,
bool hasSetArg;
int i;
+ if (!fcache->permission_ok)
+ elog(ERROR, "permission denied");
+
/*
* arguments is a list of expressions to evaluate before passing to
* the function manager. We skip the evaluation if it was already
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 6977a6081de..153d257d26c 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.160 2001/11/05 05:00:14 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.161 2002/02/18 23:11:14 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1893,9 +1893,9 @@ _copyGrantStmt(GrantStmt *from)
GrantStmt *newnode = makeNode(GrantStmt);
newnode->is_grant = from->is_grant;
- Node_Copy(from, newnode, relnames);
- if (from->privileges)
- newnode->privileges = pstrdup(from->privileges);
+ newnode->objtype = from->objtype;
+ Node_Copy(from, newnode, objects);
+ Node_Copy(from, newnode, privileges);
Node_Copy(from, newnode, grantees);
return newnode;
@@ -1914,6 +1914,20 @@ _copyPrivGrantee(PrivGrantee *from)
return newnode;
}
+static FuncWithArgs *
+_copyFuncWithArgs(FuncWithArgs *from)
+{
+ FuncWithArgs *newnode = makeNode(FuncWithArgs);
+
+ if (from->funcname)
+ newnode->funcname = pstrdup(from->funcname);
+ else
+ newnode->funcname = NULL;
+ Node_Copy(from, newnode, funcargs);
+
+ return newnode;
+}
+
static ClosePortalStmt *
_copyClosePortalStmt(ClosePortalStmt *from)
{
@@ -2971,6 +2985,9 @@ copyObject(void *from)
case T_PrivGrantee:
retval = _copyPrivGrantee(from);
break;
+ case T_FuncWithArgs:
+ retval = _copyFuncWithArgs(from);
+ break;
default:
elog(ERROR, "copyObject: don't know how to copy node type %d",
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 538a773e31b..886963f8808 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -20,7 +20,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.108 2001/11/05 05:00:14 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.109 2002/02/18 23:11:14 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -758,9 +758,11 @@ _equalGrantStmt(GrantStmt *a, GrantStmt *b)
{
if (a->is_grant != b->is_grant)
return false;
- if (!equal(a->relnames, b->relnames))
+ if (a->objtype != b->objtype)
+ return false;
+ if (!equal(a->objects, b->objects))
return false;
- if (!equalstr(a->privileges, b->privileges))
+ if (!equal(a->privileges, b->privileges))
return false;
if (!equal(a->grantees, b->grantees))
return false;
@@ -776,6 +778,13 @@ _equalPrivGrantee(PrivGrantee *a, PrivGrantee *b)
}
static bool
+_equalFuncWithArgs(FuncWithArgs *a, FuncWithArgs *b)
+{
+ return equalstr(a->funcname, b->funcname)
+ && equal(a->funcargs, b->funcargs);
+}
+
+static bool
_equalClosePortalStmt(ClosePortalStmt *a, ClosePortalStmt *b)
{
if (!equalstr(a->portalname, b->portalname))
@@ -2122,6 +2131,9 @@ equal(void *a, void *b)
case T_PrivGrantee:
retval = _equalPrivGrantee(a, b);
break;
+ case T_FuncWithArgs:
+ retval = _equalFuncWithArgs(a, b);
+ break;
default:
elog(NOTICE, "equal: don't know whether nodes of type %d are equal",
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 11b7dd6e026..a23273c1a7d 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.277 2002/02/18 06:49:20 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.278 2002/02/18 23:11:17 petere Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -56,7 +56,6 @@
#include "nodes/parsenodes.h"
#include "parser/gramparse.h"
#include "storage/lmgr.h"
-#include "utils/acl.h"
#include "utils/numeric.h"
#include "utils/datetime.h"
@@ -122,6 +121,7 @@ static void doNegateFloat(Value *v);
A_Indices *aind;
ResTarget *target;
ParamNo *paramno;
+ PrivTarget *privtarget;
VersionStmt *vstmt;
DefineStmt *dstmt;
@@ -182,10 +182,14 @@ static void doNegateFloat(Value *v);
OptUseOp, opt_class, SpecialRuleRelation
%type <str> opt_level, opt_encoding
-%type <str> privileges, operation_commalist
%type <node> grantee
%type <list> grantee_list
-%type <chr> operation, TriggerOneEvent
+%type <ival> privilege
+%type <list> privileges, privilege_list
+%type <privtarget> privilege_target
+%type <node> function_with_argtypes
+%type <list> function_with_argtypes_list
+%type <chr> TriggerOneEvent
%type <list> stmtblock, stmtmulti,
into_clause, OptTempTableName, relation_name_list,
@@ -323,7 +327,7 @@ static void doNegateFloat(Value *v);
SCHEMA, SCROLL, SECOND_P, SELECT, SESSION, SESSION_USER, SET, SOME, SUBSTRING,
TABLE, TEMPORARY, THEN, TIME, TIMESTAMP,
TO, TRAILING, TRANSACTION, TRIM, TRUE_P,
- UNENCRYPTED, UNION, UNIQUE, UNKNOWN, UPDATE, USER, USING,
+ UNENCRYPTED, UNION, UNIQUE, UNKNOWN, UPDATE, USAGE, USER, USING,
VALUES, VARCHAR, VARYING, VIEW,
WHEN, WHERE, WITH, WORK, YEAR_P, ZONE
@@ -2327,75 +2331,96 @@ from_in: IN
/*****************************************************************************
*
- * GRANT privileges ON [TABLE] relation_name_list TO [GROUP] grantee, ...
+ * GRANT and REVOKE statements
*
*****************************************************************************/
-GrantStmt: GRANT privileges ON opt_table relation_name_list TO grantee_list opt_with_grant
+GrantStmt: GRANT privileges ON privilege_target TO grantee_list opt_grant_grant_option
{
GrantStmt *n = makeNode(GrantStmt);
n->is_grant = true;
- n->relnames = $5;
n->privileges = $2;
- n->grantees = $7;
+ n->objtype = ($4)->objtype;
+ n->objects = ($4)->objs;
+ n->grantees = $6;
$$ = (Node*)n;
}
;
-privileges: ALL PRIVILEGES
- {
- $$ = aclmakepriv(ACL_MODE_STR,0);
- }
- | ALL
+RevokeStmt: REVOKE opt_revoke_grant_option privileges ON privilege_target FROM grantee_list
{
- $$ = aclmakepriv(ACL_MODE_STR,0);
- }
- | operation_commalist
- {
- $$ = $1;
+ GrantStmt *n = makeNode(GrantStmt);
+ n->is_grant = false;
+ n->privileges = $3;
+ n->objtype = ($5)->objtype;
+ n->objects = ($5)->objs;
+ n->grantees = $7;
+ $$ = (Node *)n;
}
;
-operation_commalist: operation
- {
- $$ = aclmakepriv("",$1);
- }
- | operation_commalist ',' operation
- {
- $$ = aclmakepriv($1,$3);
- }
+
+/* either ALL [PRIVILEGES] or a list of individual privileges */
+privileges: privilege_list { $$ = $1; }
+ | ALL { $$ = makeListi1(ALL); }
+ | ALL PRIVILEGES { $$ = makeListi1(ALL); }
;
-operation: SELECT
- {
- $$ = ACL_MODE_SELECT_CHR;
- }
- | INSERT
- {
- $$ = ACL_MODE_INSERT_CHR;
- }
- | UPDATE
- {
- $$ = ACL_MODE_UPDATE_CHR;
- }
- | DELETE
+privilege_list: privilege { $$ = makeListi1($1); }
+ | privilege_list ',' privilege { $$ = lappendi($1, $3); }
+ ;
+
+/* Not all of these privilege types apply to all objects, but that
+ gets sorted out later. */
+privilege: SELECT { $$ = SELECT; }
+ | INSERT { $$ = INSERT; }
+ | UPDATE { $$ = UPDATE; }
+ | DELETE { $$ = DELETE; }
+ | RULE { $$ = RULE; }
+ | REFERENCES { $$ = REFERENCES; }
+ | TRIGGER { $$ = TRIGGER; }
+ | EXECUTE { $$ = EXECUTE; }
+ | USAGE { $$ = USAGE; }
+ ;
+
+
+/* Don't bother trying to fold the first two rules into one using
+ opt_table. You're going to get conflicts. */
+privilege_target: relation_name_list
{
- $$ = ACL_MODE_DELETE_CHR;
+ PrivTarget *n = makeNode(PrivTarget);
+ n->objtype = TABLE;
+ n->objs = $1;
+ $$ = n;
}
- | RULE
+ | TABLE relation_name_list
{
- $$ = ACL_MODE_RULE_CHR;
+ PrivTarget *n = makeNode(PrivTarget);
+ n->objtype = TABLE;
+ n->objs = $2;
+ $$ = n;
}
- | REFERENCES
+ | FUNCTION function_with_argtypes_list
{
- $$ = ACL_MODE_REFERENCES_CHR;
+ PrivTarget *n = makeNode(PrivTarget);
+ n->objtype = FUNCTION;
+ n->objs = $2;
+ $$ = n;
}
- | TRIGGER
+ | LANGUAGE name_list
{
- $$ = ACL_MODE_TRIGGER_CHR;
+ PrivTarget *n = makeNode(PrivTarget);
+ n->objtype = LANGUAGE;
+ n->objs = $2;
+ $$ = n;
}
;
+
+grantee_list: grantee { $$ = makeList1($1); }
+ | grantee_list ',' grantee { $$ = lappend($1, $3); }
+ ;
+
grantee: PUBLIC
{
PrivGrantee *n = makeNode(PrivGrantee);
@@ -2419,31 +2444,33 @@ grantee: PUBLIC
}
;
-grantee_list: grantee { $$ = makeList1($1); }
- | grantee_list ',' grantee { $$ = lappend($1, $3); }
+opt_grant_grant_option: WITH GRANT OPTION
+ {
+ elog(ERROR, "grant options are not implemented");
+ }
+ | /*EMPTY*/
+ ;
-opt_with_grant: WITH GRANT OPTION
+opt_revoke_grant_option: GRANT OPTION FOR
{
- elog(ERROR,"WITH GRANT OPTION is not supported. Only relation owners can set privileges");
- }
+ elog(ERROR, "grant options are not implemented");
+ }
| /*EMPTY*/
;
-/*****************************************************************************
- *
- * REVOKE privileges ON [TABLE] relation_name_list FROM user, ...
- *
- *****************************************************************************/
+function_with_argtypes_list: function_with_argtypes
+ { $$ = makeList1($1); }
+ | function_with_argtypes_list ',' function_with_argtypes
+ { $$ = lappend($1, $3); }
+ ;
-RevokeStmt: REVOKE privileges ON opt_table relation_name_list FROM grantee_list
+function_with_argtypes: func_name func_args
{
- GrantStmt *n = makeNode(GrantStmt);
- n->is_grant = false;
- n->relnames = $5;
- n->privileges = $2;
- n->grantees = $7;
+ FuncWithArgs *n = makeNode(FuncWithArgs);
+ n->funcname = $1;
+ n->funcargs = $2;
$$ = (Node *)n;
}
;
@@ -5876,6 +5903,7 @@ unreserved_keyword:
| UNLISTEN { $$ = "unlisten"; }
| UNTIL { $$ = "until"; }
| UPDATE { $$ = "update"; }
+ | USAGE { $$ = "usage"; }
| VACUUM { $$ = "vacuum"; }
| VALID { $$ = "valid"; }
| VALUES { $$ = "values"; }
diff --git a/src/backend/parser/keywords.c b/src/backend/parser/keywords.c
index fad08c849f1..12b05c6bcd1 100644
--- a/src/backend/parser/keywords.c
+++ b/src/backend/parser/keywords.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.99 2001/10/10 00:02:42 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.100 2002/02/18 23:11:18 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -269,6 +269,7 @@ static ScanKeyword ScanKeywords[] = {
{"unlisten", UNLISTEN},
{"until", UNTIL},
{"update", UPDATE},
+ {"usage", USAGE},
{"user", USER},
{"using", USING},
{"vacuum", VACUUM},
@@ -354,3 +355,36 @@ ScanKeywordLookup(char *text)
return NULL;
}
+
+
+/*
+ * This does the reverse mapping from token number to string.
+ */
+const char *
+TokenString(int token)
+{
+ int i = 0;
+ static char buf[NAMEDATALEN];
+
+ while (i < sizeof(ScanKeywords))
+ {
+ if (ScanKeywords[i].value == token)
+ {
+ int k;
+
+ /* uppercase */
+ for (k = 0; k < NAMEDATALEN; k++)
+ if (ScanKeywords[i].name[k] >= 'a'
+ && ScanKeywords[i].name[k] <= 'z')
+ buf[k] = ScanKeywords[i].name[k] + ('A' - 'a');
+ else
+ buf[k] = ScanKeywords[i].name[k];
+
+ return buf;
+ }
+
+ i++;
+ }
+
+ return NULL;
+}
diff --git a/src/backend/utils/Gen_fmgrtab.sh b/src/backend/utils/Gen_fmgrtab.sh
index cf649ff3cd6..b020c9ce260 100644
--- a/src/backend/utils/Gen_fmgrtab.sh
+++ b/src/backend/utils/Gen_fmgrtab.sh
@@ -9,7 +9,7 @@
#
#
# IDENTIFICATION
-# $Header: /cvsroot/pgsql/src/backend/utils/Attic/Gen_fmgrtab.sh,v 1.20 2001/05/22 12:06:51 momjian Exp $
+# $Header: /cvsroot/pgsql/src/backend/utils/Attic/Gen_fmgrtab.sh,v 1.21 2002/02/18 23:11:20 petere Exp $
#
#-------------------------------------------------------------------------
@@ -164,7 +164,7 @@ FuNkYfMgRsTuFf
tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' < $RAWFILE | \
$AWK '
BEGIN { OFS = ""; }
- { if (seenit[$(NF-1)]++ == 0) print "#define F_", $(NF-1), " ", $1; }' >> "$$-$OIDSFILE"
+ { if (seenit[$(NF-2)]++ == 0) print "#define F_", $(NF-2), " ", $1; }' >> "$$-$OIDSFILE"
if [ $? -ne 0 ]; then
cleanup
@@ -209,7 +209,7 @@ cat > "$$-$TABLEFILE" <<FuNkYfMgRtAbStUfF
FuNkYfMgRtAbStUfF
-$AWK '{ print "extern Datum", $(NF-1), "(PG_FUNCTION_ARGS);"; }' $RAWFILE >> "$$-$TABLEFILE"
+$AWK '{ print "extern Datum", $(NF-2), "(PG_FUNCTION_ARGS);"; }' $RAWFILE >> "$$-$TABLEFILE"
if [ $? -ne 0 ]; then
cleanup
@@ -232,7 +232,7 @@ $AWK 'BEGIN {
Bool["f"] = "false"
}
{ printf (" { %d, \"%s\", %d, %s, %s, %s },\n"), \
- $1, $(NF-1), $9, Bool[$8], Bool[$10], $(NF-1)
+ $1, $(NF-2), $9, Bool[$8], Bool[$10], $(NF-2)
}' $RAWFILE >> "$$-$TABLEFILE"
if [ $? -ne 0 ]; then
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index a868c6c1c05..ef6ebba7fa7 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.66 2001/11/16 23:30:35 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.67 2002/02/18 23:11:22 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -373,7 +373,7 @@ aclitemgt(const AclItem *a1, const AclItem *a2)
* newly-created tables (or any table with a NULL acl entry in pg_class)
*/
Acl *
-acldefault(const char *relname, AclId ownerid)
+acldefault(AclId ownerid)
{
Acl *acl;
AclItem *aip;
@@ -381,16 +381,18 @@ acldefault(const char *relname, AclId ownerid)
#define ACL_WORLD_DEFAULT (ACL_NO)
#define ACL_OWNER_DEFAULT (ACL_INSERT|ACL_SELECT|ACL_UPDATE|ACL_DELETE|ACL_RULE|ACL_REFERENCES|ACL_TRIGGER)
- acl = makeacl(2);
+ acl = makeacl(ownerid ? 2 : 1);
aip = ACL_DAT(acl);
aip[0].ai_idtype = ACL_IDTYPE_WORLD;
aip[0].ai_id = ACL_ID_WORLD;
- aip[0].ai_mode = (IsSystemRelationName(relname) &&
- !IsToastRelationName(relname)) ? ACL_SELECT
- : ACL_WORLD_DEFAULT;
- aip[1].ai_idtype = ACL_IDTYPE_UID;
- aip[1].ai_id = ownerid;
- aip[1].ai_mode = ACL_OWNER_DEFAULT;
+ aip[0].ai_mode = ACL_WORLD_DEFAULT;
+ /* FIXME: The owner's default should vary with the object type. */
+ if (ownerid)
+ {
+ aip[1].ai_idtype = ACL_IDTYPE_UID;
+ aip[1].ai_id = ownerid;
+ aip[1].ai_mode = ACL_OWNER_DEFAULT;
+ }
return acl;
}
diff --git a/src/backend/utils/adt/sets.c b/src/backend/utils/adt/sets.c
index 0cd3b766472..15210f0c841 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.39 2001/10/02 21:39:35 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.40 2002/02/18 23:11:23 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -20,6 +20,7 @@
#include "access/heapam.h"
#include "catalog/catname.h"
#include "catalog/indexing.h"
+#include "catalog/pg_language.h"
#include "catalog/pg_proc.h"
#include "executor/executor.h"
#include "utils/fcache.h"
@@ -54,7 +55,7 @@ SetDefine(char *querystr, char *typename)
false, /* don't replace */
true, /* returnsSet */
typename, /* returnTypeName */
- "sql", /* languageName */
+ SQLlanguageId, /* language */
querystr, /* sourceCode */
fileName, /* fileName */
true, /* trusted */
diff --git a/src/backend/utils/cache/fcache.c b/src/backend/utils/cache/fcache.c
index 92cf46a036d..96fee81349d 100644
--- a/src/backend/utils/cache/fcache.c
+++ b/src/backend/utils/cache/fcache.c
@@ -8,12 +8,14 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/fcache.c,v 1.41 2001/10/06 23:21:44 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/fcache.c,v 1.42 2002/02/18 23:11:25 petere Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
+#include "miscadmin.h"
+#include "utils/acl.h"
#include "utils/fcache.h"
@@ -40,5 +42,7 @@ init_fcache(Oid foid, int nargs, MemoryContext fcacheCxt)
/* Initialize additional info */
retval->setArgsValid = false;
+ retval->permission_ok = pg_proc_aclcheck(foid, GetUserId()) == ACLCHECK_OK;
+
return retval;
}
diff --git a/src/backend/utils/misc/superuser.c b/src/backend/utils/misc/superuser.c
index 2f092028480..f677d64fd3e 100644
--- a/src/backend/utils/misc/superuser.c
+++ b/src/backend/utils/misc/superuser.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/misc/superuser.c,v 1.19 2001/09/08 15:24:00 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/misc/superuser.c,v 1.20 2002/02/18 23:11:26 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -31,15 +31,22 @@
bool
superuser(void)
{
+ return superuser_arg(GetUserId());
+}
+
+
+bool
+superuser_arg(Oid userid)
+{
bool result = false;
HeapTuple utup;
/* Special escape path in case you deleted all your users. */
- if (!IsUnderPostmaster && GetUserId() == BOOTSTRAP_USESYSID)
+ if (!IsUnderPostmaster && userid == BOOTSTRAP_USESYSID)
return true;
utup = SearchSysCache(SHADOWSYSID,
- ObjectIdGetDatum(GetUserId()),
+ ObjectIdGetDatum(userid),
0, 0, 0);
if (HeapTupleIsValid(utup))
{
@@ -49,6 +56,7 @@ superuser(void)
return result;
}
+
/*
* The Postgres user running this command is the owner of the specified
* database.