On Thu, 25 Jan 2007, Jeremy Drake wrote:
> On Thu, 25 Jan 2007, Jeremy Drake wrote:
>
> > I think that an ALTER LANGUAGE OWNER TO is the proper response to these
> > things, and unless I hear otherwise I will attempt to add this to my
> > patch.
>
> Here is the patch which adds this. It also allows ALTER LANGUAGE RENAME
> TO for the owner, which I missed before. I would appreciate someone with
> more knowledge of the permissions infrastructure to take a look at it
> since I am fairly new to it and may not fully understand its intricacies.
>
I have refactored the owner checking of languages in the same manner as it
is for other owned objects. I have changed to using standard permissions
error messages (aclcheck_error) for the language permissions errors.
I consider this patch ready for review, assuming the permissions rules
outlined by Tom Lane on -hackers are valid. For reference, here are the
rules that this patch is intended to implement:
On Wed, 24 Jan 2007, Tom Lane wrote:
> In detail, it'd look something like:
>
> * For an untrusted language: must be superuser to either create or use
> the language (no change from current rules). Ownership of the
> pg_language entry is really irrelevant, as is its ACL.
>
> * For a trusted language:
>
> * if pg_pltemplate.something is ON: either a superuser or the current
> DB's owner can CREATE the language. In either case the pg_language
> entry will be marked as owned by the DB owner (pg_database.datdba),
> which means that subsequently he (or a superuser) can grant or deny
> USAGE within his DB.
>
> * if pg_pltemplate.something is OFF: must be superuser to CREATE the
> language; subsequently it will be owned by you, so only you or another
> superuser can grant or deny USAGE (same behavior as currently).
The only difference from this is, that when superuser is required, the
owner of the language is not the superuser who created it, but
BOOTSTRAP_SUPERUSERID. This is because my interpretation was that the
"same behavior as currently" took precedence. The current behavior in cvs
is that languages have no owner, and for purposes where one would be
needed it is assumed to be BOOTSTRAP_SUPERUSERID.
Is this valid, or should I instead set the owner to GetUserId() in those
cases?
--
Academic politics is the most vicious and bitter form of politics,
because the stakes are so low.
-- Wallace SayreIndex: doc/src/sgml/ref/alter_language.sgml
===================================================================
RCS file:
/data/local/jeremyd/postgres/cvsuproot/pgsql/doc/src/sgml/ref/alter_language.sgml,v
retrieving revision 1.6
diff -c -r1.6 alter_language.sgml
*** doc/src/sgml/ref/alter_language.sgml 16 Sep 2006 00:30:16 -0000
1.6
--- doc/src/sgml/ref/alter_language.sgml 26 Jan 2007 01:01:40 -0000
***************
*** 21,26 ****
--- 21,28 ----
<refsynopsisdiv>
<synopsis>
ALTER LANGUAGE <replaceable>name</replaceable> RENAME TO
<replaceable>newname</replaceable>
+
+ ALTER LANGUAGE <replaceable>name</replaceable> OWNER TO
<replaceable>new_owner</replaceable>
</synopsis>
</refsynopsisdiv>
***************
*** 48,53 ****
--- 50,64 ----
</varlistentry>
<varlistentry>
+ <term><replaceable>new_owner</replaceable></term>
+ <listitem>
+ <para>
+ The new owner of the language.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><replaceable>newname</replaceable></term>
<listitem>
<para>
Index: src/backend/catalog/aclchk.c
===================================================================
RCS file:
/data/local/jeremyd/postgres/cvsuproot/pgsql/src/backend/catalog/aclchk.c,v
retrieving revision 1.135
diff -c -r1.135 aclchk.c
*** src/backend/catalog/aclchk.c 23 Jan 2007 05:07:17 -0000 1.135
--- src/backend/catalog/aclchk.c 26 Jan 2007 23:53:03 -0000
***************
*** 1003,1013 ****
/*
* Get owner ID and working copy of existing ACL. If there's no
ACL,
* substitute the proper default.
- *
- * Note: for now, languages are treated as owned by the
bootstrap
- * user. We should add an owner column to pg_language instead.
*/
! ownerId = BOOTSTRAP_SUPERUSERID;
aclDatum = SysCacheGetAttr(LANGNAME, tuple,
Anum_pg_language_lanacl,
&isNull);
if (isNull)
--- 1003,1010 ----
/*
* Get owner ID and working copy of existing ACL. If there's no
ACL,
* substitute the proper default.
*/
! ownerId = pg_language_tuple->lanowner;
aclDatum = SysCacheGetAttr(LANGNAME, tuple,
Anum_pg_language_lanacl,
&isNull);
if (isNull)
***************
*** 1770,1777 ****
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("language with OID %u does not exist",
lang_oid)));
! /* XXX pg_language should have an owner column, but doesn't */
! ownerId = BOOTSTRAP_SUPERUSERID;
aclDatum = SysCacheGetAttr(LANGOID, tuple, Anum_pg_language_lanacl,
&isNull);
--- 1767,1773 ----
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("language with OID %u does not exist",
lang_oid)));
! ownerId = ((Form_pg_language) GETSTRUCT(tuple))->lanowner;
aclDatum = SysCacheGetAttr(LANGOID, tuple, Anum_pg_language_lanacl,
&isNull);
***************
*** 2148,2153 ****
--- 2144,2177 ----
}
/*
+ * Ownership check for a procedural language (specified by OID)
+ */
+ bool
+ pg_language_ownercheck(Oid lan_oid, Oid roleid)
+ {
+ HeapTuple tuple;
+ Oid ownerId;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(roleid))
+ return true;
+
+ tuple = SearchSysCache(LANGOID,
+ ObjectIdGetDatum(lan_oid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_FUNCTION),
+ errmsg("language with OID %u does not exist",
lan_oid)));
+
+ ownerId = ((Form_pg_language) GETSTRUCT(tuple))->lanowner;
+
+ ReleaseSysCache(tuple);
+
+ return has_privs_of_role(roleid, ownerId);
+ }
+
+ /*
* Ownership check for a namespace (specified by OID).
*/
bool
Index: src/backend/commands/alter.c
===================================================================
RCS file:
/data/local/jeremyd/postgres/cvsuproot/pgsql/src/backend/commands/alter.c,v
retrieving revision 1.22
diff -c -r1.22 alter.c
*** src/backend/commands/alter.c 23 Jan 2007 05:07:17 -0000 1.22
--- src/backend/commands/alter.c 25 Jan 2007 23:55:41 -0000
***************
*** 203,208 ****
--- 203,212 ----
AlterFunctionOwner(stmt->object, stmt->objarg,
newowner);
break;
+ case OBJECT_LANGUAGE:
+ AlterLanguageOwner((char *) linitial(stmt->object),
newowner);
+ break;
+
case OBJECT_OPERATOR:
Assert(list_length(stmt->objarg) == 2);
AlterOperatorOwner(stmt->object,
Index: src/backend/commands/proclang.c
===================================================================
RCS file:
/data/local/jeremyd/postgres/cvsuproot/pgsql/src/backend/commands/proclang.c,v
retrieving revision 1.71
diff -c -r1.71 proclang.c
*** src/backend/commands/proclang.c 22 Jan 2007 01:35:20 -0000 1.71
--- src/backend/commands/proclang.c 27 Jan 2007 00:20:19 -0000
***************
*** 17,22 ****
--- 17,24 ----
#include "access/heapam.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
+ #include "catalog/pg_authid.h"
+ #include "catalog/pg_database.h"
#include "catalog/pg_language.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_pltemplate.h"
***************
*** 27,32 ****
--- 29,35 ----
#include "miscadmin.h"
#include "parser/gramparse.h"
#include "parser/parse_func.h"
+ #include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
***************
*** 36,49 ****
typedef struct
{
bool tmpltrusted; /* trusted? */
char *tmplhandler; /* name of handler function */
char *tmplvalidator; /* name of validator function, or NULL
*/
char *tmpllibrary; /* path of shared library */
} PLTemplate;
static void create_proc_lang(const char *languageName,
! Oid handlerOid, Oid valOid, bool trusted);
static PLTemplate *find_language_template(const char *languageName);
/* ---------------------------------------------------------------------
--- 39,57 ----
typedef struct
{
bool tmpltrusted; /* trusted? */
+ bool tmpldbaallowed; /* db owner allowed to create? */
char *tmplhandler; /* name of handler function */
char *tmplvalidator; /* name of validator function, or NULL
*/
char *tmpllibrary; /* path of shared library */
} PLTemplate;
static void create_proc_lang(const char *languageName,
! Oid languageOwner, Oid handlerOid, Oid valOid,
bool trusted);
static PLTemplate *find_language_template(const char *languageName);
+ static void AlterLanguageOwner_internal(HeapTuple tup, Relation rel, Oid
newOwnerId);
+
+ static Oid get_current_datdba();
+ static Oid find_desired_language_owner (PLTemplate *pltemplate);
/* ---------------------------------------------------------------------
***************
*** 61,74 ****
Oid funcargtypes[1];
/*
- * Check permission
- */
- if (!superuser())
- ereport(ERROR,
- (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- errmsg("must be superuser to create procedural
language")));
-
- /*
* Translate the language name and check that this language doesn't
* already exist
*/
--- 69,74 ----
***************
*** 97,102 ****
--- 97,124 ----
(errmsg("using pg_pltemplate
information instead of CREATE LANGUAGE parameters")));
/*
+ * Check permission
+ */
+ if (pltemplate->tmpltrusted && pltemplate->tmpldbaallowed)
+ {
+ if (!pg_database_ownercheck(MyDatabaseId,
GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER,
ACL_KIND_DATABASE,
+
get_database_name(MyDatabaseId));
+ }
+ else if (!superuser())
+ {
+ if (!pltemplate->tmpltrusted)
+ ereport(ERROR,
+
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser to
create untrusted procedural language")));
+ else
+ ereport(ERROR,
+
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser to
create procedural language \"%s\"", languageName),
+ errhint("Column
pg_pltemplate.tmpldbaallowed has been set to false for this language.")));
+ }
+
+ /*
* Find or create the handler function, which we force to be in
the
* pg_catalog schema. If already present, it must have the
correct
* return type.
***************
*** 171,177 ****
valOid = InvalidOid;
/* ok, create it */
! create_proc_lang(languageName, handlerOid, valOid,
pltemplate->tmpltrusted);
}
else
--- 193,199 ----
valOid = InvalidOid;
/* ok, create it */
! create_proc_lang(languageName,
find_desired_language_owner(pltemplate), handlerOid, valOid,
pltemplate->tmpltrusted);
}
else
***************
*** 189,194 ****
--- 211,224 ----
errhint("The supported languages are
listed in the pg_pltemplate system catalog.")));
/*
+ * Check permission
+ */
+ if (!superuser())
+ ereport(ERROR,
+
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser to create
custom procedural language")));
+
+ /*
* Lookup the PL handler function and check that it is of the
expected
* return type
*/
***************
*** 227,233 ****
valOid = InvalidOid;
/* ok, create it */
! create_proc_lang(languageName, handlerOid, valOid,
stmt->pltrusted);
}
}
--- 257,263 ----
valOid = InvalidOid;
/* ok, create it */
! create_proc_lang(languageName, BOOTSTRAP_SUPERUSERID,
handlerOid, valOid, stmt->pltrusted);
}
}
***************
*** 236,242 ****
*/
static void
create_proc_lang(const char *languageName,
! Oid handlerOid, Oid valOid, bool trusted)
{
Relation rel;
TupleDesc tupDesc;
--- 266,272 ----
*/
static void
create_proc_lang(const char *languageName,
! Oid languageOwner, Oid handlerOid, Oid valOid,
bool trusted)
{
Relation rel;
TupleDesc tupDesc;
***************
*** 258,263 ****
--- 288,294 ----
namestrcpy(&langname, languageName);
values[Anum_pg_language_lanname - 1] = NameGetDatum(&langname);
+ values[Anum_pg_language_lanowner - 1] = ObjectIdGetDatum(languageOwner);
values[Anum_pg_language_lanispl - 1] = BoolGetDatum(true);
values[Anum_pg_language_lanpltrusted - 1] = BoolGetDatum(trusted);
values[Anum_pg_language_lanplcallfoid - 1] =
ObjectIdGetDatum(handlerOid);
***************
*** 277,282 ****
--- 308,319 ----
myself.objectId = HeapTupleGetOid(tup);
myself.objectSubId = 0;
+ /* dependency on owner of language */
+ referenced.classId = AuthIdRelationId;
+ referenced.objectId = languageOwner;
+ referenced.objectSubId = 0;
+ recordSharedDependencyOn(&myself, &referenced, SHARED_DEPENDENCY_OWNER);
+
/* dependency on the PL handler function */
referenced.classId = ProcedureRelationId;
referenced.objectId = handlerOid;
***************
*** 295,300 ****
--- 332,371 ----
heap_close(rel, RowExclusiveLock);
}
+ static Oid get_current_datdba()
+ {
+ /* find datdba for current db */
+ HeapTuple tuple;
+ Oid dba;
+
+ tuple = SearchSysCache(DATABASEOID,
+ ObjectIdGetDatum(MyDatabaseId),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_DATABASE),
+ errmsg("database with OID %u does not exist",
MyDatabaseId)));
+
+ dba = ((Form_pg_database) GETSTRUCT(tuple))->datdba;
+
+ ReleaseSysCache(tuple);
+ return dba;
+ }
+
+
+ static Oid find_desired_language_owner (PLTemplate *pltemplate)
+ {
+ if (pltemplate->tmpltrusted && pltemplate->tmpldbaallowed)
+ {
+ return get_current_datdba();
+ }
+ else
+ {
+ /* current behaviour */
+ return BOOTSTRAP_SUPERUSERID;
+ }
+ }
+
/*
* Look to see if we have template information for the given language name.
*/
***************
*** 325,330 ****
--- 396,402 ----
result = (PLTemplate *) palloc0(sizeof(PLTemplate));
result->tmpltrusted = tmpl->tmpltrusted;
+ result->tmpldbaallowed = tmpl->tmpldbaallowed;
/* Remaining fields are variable-width so we need heap_getattr
*/
datum = heap_getattr(tup, Anum_pg_pltemplate_tmplhandler,
***************
*** 382,395 ****
ObjectAddress object;
/*
- * Check permission
- */
- if (!superuser())
- ereport(ERROR,
- (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- errmsg("must be superuser to drop procedural
language")));
-
- /*
* Translate the language name, check that the language exists
*/
languageName = case_translate_language_name(stmt->plname);
--- 454,459 ----
***************
*** 411,416 ****
--- 475,487 ----
return;
}
+ /*
+ * Check permission
+ */
+ if (!pg_language_ownercheck(HeapTupleGetOid(langTup), GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_LANGUAGE,
+ languageName);
+
object.classId = LanguageRelationId;
object.objectId = HeapTupleGetOid(langTup);
object.objectSubId = 0;
***************
*** 478,488 ****
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("language \"%s\" already exists",
newname)));
! /* must be superuser, since we do not have owners for PLs */
! if (!superuser())
! ereport(ERROR,
! (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
! errmsg("must be superuser to rename procedural
language")));
/* rename */
namestrcpy(&(((Form_pg_language) GETSTRUCT(tup))->lanname), newname);
--- 549,558 ----
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("language \"%s\" already exists",
newname)));
! /* must be owner of PL */
! if (!pg_language_ownercheck(HeapTupleGetOid(tup), GetUserId()))
! aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_LANGUAGE,
! oldname);
/* rename */
namestrcpy(&(((Form_pg_language) GETSTRUCT(tup))->lanname), newname);
***************
*** 492,494 ****
--- 562,670 ----
heap_close(rel, NoLock);
heap_freetuple(tup);
}
+
+ /*
+ * Change language owner
+ */
+ void
+ AlterLanguageOwner(const char *name, Oid newOwnerId)
+ {
+ HeapTuple tup;
+ Relation rel;
+
+ /* Translate name for consistency with CREATE */
+ name = case_translate_language_name(name);
+
+ rel = heap_open(LanguageRelationId, RowExclusiveLock);
+
+ tup = SearchSysCache(LANGNAME,
+ CStringGetDatum(name),
+ 0, 0, 0);
+
+ if (!HeapTupleIsValid(tup))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("language \"%s\" does not exist",
name)));
+
+ AlterLanguageOwner_internal(tup, rel, newOwnerId);
+
+ ReleaseSysCache(tup);
+ heap_close(rel, RowExclusiveLock);
+ }
+
+ static void
+ AlterLanguageOwner_internal(HeapTuple tup, Relation rel, Oid newOwnerId)
+ {
+ Form_pg_language lanForm;
+
+ Assert(tup->t_tableOid == LanguageRelationId);
+ Assert(RelationGetRelid(rel) == LanguageRelationId);
+
+ lanForm = (Form_pg_language) GETSTRUCT(tup);
+
+ /*
+ * If the new owner is the same as the existing owner, consider the
+ * command to have succeeded. This is for dump restoration purposes.
+ */
+ if (lanForm->lanowner != newOwnerId)
+ {
+ Datum repl_val[Natts_pg_language];
+ char repl_null[Natts_pg_language];
+ char repl_repl[Natts_pg_language];
+ Acl *newAcl;
+ Datum aclDatum;
+ bool isNull;
+ HeapTuple newtuple;
+ AclResult aclresult;
+
+ /* Otherwise, must be owner of the existing object */
+ if (!pg_language_ownercheck(HeapTupleGetOid(tup), GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_LANGUAGE,
+ NameStr(lanForm->lanname));
+
+ /* Must be able to become new owner */
+ check_is_member_of_role(GetUserId(), newOwnerId);
+
+ /*
+ * must have rights to create this language
+ */
+ if (!has_privs_of_role(newOwnerId, find_desired_language_owner
(find_language_template (NameStr(lanForm->lanname)))))
+ {
+ ereport(ERROR,
+
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("new user must be allowed to
create this language")));
+ }
+
+ memset(repl_null, ' ', sizeof(repl_null));
+ memset(repl_repl, ' ', sizeof(repl_repl));
+
+ repl_repl[Anum_pg_language_lanowner - 1] = 'r';
+ repl_val[Anum_pg_language_lanowner - 1] =
ObjectIdGetDatum(newOwnerId);
+
+ /*
+ * Determine the modified ACL for the new owner. This is only
+ * necessary when the ACL is non-null.
+ */
+ aclDatum = SysCacheGetAttr(LANGNAME, tup,
+
Anum_pg_language_lanacl,
+ &isNull);
+ if (!isNull)
+ {
+ newAcl = aclnewowner(DatumGetAclP(aclDatum),
+
lanForm->lanowner, newOwnerId);
+ repl_repl[Anum_pg_language_lanacl - 1] = 'r';
+ repl_val[Anum_pg_language_lanacl - 1] =
PointerGetDatum(newAcl);
+ }
+
+ newtuple = heap_modifytuple(tup, RelationGetDescr(rel),
repl_val, repl_null, repl_repl);
+
+ simple_heap_update(rel, &newtuple->t_self, newtuple);
+ CatalogUpdateIndexes(rel, newtuple);
+
+ heap_freetuple(newtuple);
+
+ /* Update owner dependency reference */
+ changeDependencyOnOwner(LanguageRelationId,
HeapTupleGetOid(tup),
+ newOwnerId);
+ }
+ }
Index: src/backend/parser/gram.y
===================================================================
RCS file:
/data/local/jeremyd/postgres/cvsuproot/pgsql/src/backend/parser/gram.y,v
retrieving revision 2.577
diff -c -r2.577 gram.y
*** src/backend/parser/gram.y 25 Jan 2007 11:53:51 -0000 2.577
--- src/backend/parser/gram.y 25 Jan 2007 23:55:10 -0000
***************
*** 4596,4601 ****
--- 4596,4609 ----
n->newowner = $7;
$$ = (Node *)n;
}
+ | ALTER LANGUAGE name OWNER TO RoleId
+ {
+ AlterOwnerStmt *n =
makeNode(AlterOwnerStmt);
+ n->objectType = OBJECT_LANGUAGE;
+ n->object = list_make1($3);
+ n->newowner = $6;
+ $$ = (Node *)n;
+ }
| ALTER OPERATOR any_operator '(' oper_argtypes ')'
OWNER TO RoleId
{
AlterOwnerStmt *n =
makeNode(AlterOwnerStmt);
Index: src/backend/tcop/utility.c
===================================================================
RCS file:
/data/local/jeremyd/postgres/cvsuproot/pgsql/src/backend/tcop/utility.c,v
retrieving revision 1.271
diff -c -r1.271 utility.c
*** src/backend/tcop/utility.c 23 Jan 2007 05:07:18 -0000 1.271
--- src/backend/tcop/utility.c 26 Jan 2007 00:53:24 -0000
***************
*** 1530,1535 ****
--- 1530,1538 ----
case OBJECT_FUNCTION:
tag = "ALTER FUNCTION";
break;
+ case OBJECT_LANGUAGE:
+ tag = "ALTER LANGUAGE";
+ break;
case OBJECT_OPERATOR:
tag = "ALTER OPERATOR";
break;
Index: src/bin/psql/tab-complete.c
===================================================================
RCS file:
/data/local/jeremyd/postgres/cvsuproot/pgsql/src/bin/psql/tab-complete.c,v
retrieving revision 1.157
diff -c -r1.157 tab-complete.c
*** src/bin/psql/tab-complete.c 5 Jan 2007 22:19:49 -0000 1.157
--- src/bin/psql/tab-complete.c 27 Jan 2007 00:40:45 -0000
***************
*** 651,657 ****
/* ALTER LANGUAGE <name> */
else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
pg_strcasecmp(prev2_wd, "LANGUAGE") == 0)
! COMPLETE_WITH_CONST("RENAME TO");
/* ALTER USER,ROLE <name> */
else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
--- 651,662 ----
/* ALTER LANGUAGE <name> */
else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
pg_strcasecmp(prev2_wd, "LANGUAGE") == 0)
! {
! static const char *const list_ALTERLANGUAGE[] =
! {"OWNER TO", "RENAME TO", NULL};
!
! COMPLETE_WITH_LIST(list_ALTERLANGUAGE);
! }
/* ALTER USER,ROLE <name> */
else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
Index: src/include/catalog/pg_language.h
===================================================================
RCS file:
/data/local/jeremyd/postgres/cvsuproot/pgsql/src/include/catalog/pg_language.h,v
retrieving revision 1.29
diff -c -r1.29 pg_language.h
*** src/include/catalog/pg_language.h 5 Jan 2007 22:19:52 -0000 1.29
--- src/include/catalog/pg_language.h 25 Jan 2007 03:51:13 -0000
***************
*** 36,41 ****
--- 36,42 ----
CATALOG(pg_language,2612)
{
NameData lanname;
+ Oid lanowner; /* language owner */
bool lanispl; /* Is a procedural language */
bool lanpltrusted; /* PL is trusted */
Oid lanplcallfoid; /* Call handler for PL */
***************
*** 54,79 ****
* compiler constants for pg_language
* ----------------
*/
! #define Natts_pg_language 6
#define Anum_pg_language_lanname 1
! #define Anum_pg_language_lanispl 2
! #define Anum_pg_language_lanpltrusted 3
! #define Anum_pg_language_lanplcallfoid 4
! #define Anum_pg_language_lanvalidator 5
! #define Anum_pg_language_lanacl 6
/* ----------------
* initial contents of pg_language
* ----------------
*/
! DATA(insert OID = 12 ( "internal" f f 0 2246 _null_ ));
DESCR("Built-in functions");
#define INTERNALlanguageId 12
! DATA(insert OID = 13 ( "c" f f 0 2247 _null_ ));
DESCR("Dynamically-loaded C functions");
#define ClanguageId 13
! DATA(insert OID = 14 ( "sql" f t 0 2248 _null_ ));
DESCR("SQL-language functions");
#define SQLlanguageId 14
--- 55,81 ----
* compiler constants for pg_language
* ----------------
*/
! #define Natts_pg_language 7
#define Anum_pg_language_lanname 1
! #define Anum_pg_language_lanowner 2
! #define Anum_pg_language_lanispl 3
! #define Anum_pg_language_lanpltrusted 4
! #define Anum_pg_language_lanplcallfoid 5
! #define Anum_pg_language_lanvalidator 6
! #define Anum_pg_language_lanacl 7
/* ----------------
* initial contents of pg_language
* ----------------
*/
! DATA(insert OID = 12 ( "internal" PGUID f f 0 2246 _null_ ));
DESCR("Built-in functions");
#define INTERNALlanguageId 12
! DATA(insert OID = 13 ( "c" PGUID f f 0 2247 _null_ ));
DESCR("Dynamically-loaded C functions");
#define ClanguageId 13
! DATA(insert OID = 14 ( "sql" PGUID f t 0 2248 _null_ ));
DESCR("SQL-language functions");
#define SQLlanguageId 14
Index: src/include/catalog/pg_pltemplate.h
===================================================================
RCS file:
/data/local/jeremyd/postgres/cvsuproot/pgsql/src/include/catalog/pg_pltemplate.h,v
retrieving revision 1.3
diff -c -r1.3 pg_pltemplate.h
*** src/include/catalog/pg_pltemplate.h 5 Jan 2007 22:19:53 -0000 1.3
--- src/include/catalog/pg_pltemplate.h 25 Jan 2007 01:36:57 -0000
***************
*** 37,42 ****
--- 37,43 ----
{
NameData tmplname; /* name of PL */
bool tmpltrusted; /* PL is trusted? */
+ bool tmpldbaallowed; /* PL is installable by db owner? */
text tmplhandler; /* name of call handler function */
text tmplvalidator; /* name of validator function, or NULL
*/
text tmpllibrary; /* path of shared library */
***************
*** 54,66 ****
* compiler constants for pg_pltemplate
* ----------------
*/
! #define Natts_pg_pltemplate 6
#define Anum_pg_pltemplate_tmplname 1
#define Anum_pg_pltemplate_tmpltrusted 2
! #define Anum_pg_pltemplate_tmplhandler 3
! #define Anum_pg_pltemplate_tmplvalidator 4
! #define Anum_pg_pltemplate_tmpllibrary 5
! #define Anum_pg_pltemplate_tmplacl 6
/* ----------------
--- 55,68 ----
* compiler constants for pg_pltemplate
* ----------------
*/
! #define Natts_pg_pltemplate 7
#define Anum_pg_pltemplate_tmplname 1
#define Anum_pg_pltemplate_tmpltrusted 2
! #define Anum_pg_pltemplate_tmpldbaallowed 3
! #define Anum_pg_pltemplate_tmplhandler 4
! #define Anum_pg_pltemplate_tmplvalidator 5
! #define Anum_pg_pltemplate_tmpllibrary 6
! #define Anum_pg_pltemplate_tmplacl 7
/* ----------------
***************
*** 68,78 ****
* ----------------
*/
! DATA(insert ( "plpgsql" t "plpgsql_call_handler"
"plpgsql_validator" "$libdir/plpgsql" _null_ ));
! DATA(insert ( "pltcl" t "pltcl_call_handler" _null_ "$libdir/pltcl"
_null_ ));
! DATA(insert ( "pltclu" f "pltclu_call_handler" _null_
"$libdir/pltcl" _null_ ));
! DATA(insert ( "plperl" t "plperl_call_handler"
"plperl_validator" "$libdir/plperl" _null_ ));
! DATA(insert ( "plperlu" f "plperl_call_handler"
"plperl_validator" "$libdir/plperl" _null_ ));
! DATA(insert ( "plpythonu" f "plpython_call_handler" _null_
"$libdir/plpython" _null_ ));
#endif /* PG_PLTEMPLATE_H */
--- 70,80 ----
* ----------------
*/
! DATA(insert ( "plpgsql" t t "plpgsql_call_handler"
"plpgsql_validator" "$libdir/plpgsql" _null_ ));
! DATA(insert ( "pltcl" t t "pltcl_call_handler" _null_ "$libdir/pltcl"
_null_ ));
! DATA(insert ( "pltclu" f t "pltclu_call_handler" _null_
"$libdir/pltcl" _null_ ));
! DATA(insert ( "plperl" t t "plperl_call_handler"
"plperl_validator" "$libdir/plperl" _null_ ));
! DATA(insert ( "plperlu" f t "plperl_call_handler"
"plperl_validator" "$libdir/plperl" _null_ ));
! DATA(insert ( "plpythonu" f t "plpython_call_handler" _null_
"$libdir/plpython" _null_ ));
#endif /* PG_PLTEMPLATE_H */
Index: src/include/commands/proclang.h
===================================================================
RCS file:
/data/local/jeremyd/postgres/cvsuproot/pgsql/src/include/commands/proclang.h,v
retrieving revision 1.11
diff -c -r1.11 proclang.h
*** src/include/commands/proclang.h 8 Sep 2005 20:07:42 -0000 1.11
--- src/include/commands/proclang.h 26 Jan 2007 00:37:51 -0000
***************
*** 15,20 ****
--- 15,21 ----
extern void DropProceduralLanguage(DropPLangStmt *stmt);
extern void DropProceduralLanguageById(Oid langOid);
extern void RenameLanguage(const char *oldname, const char *newname);
+ extern void AlterLanguageOwner(const char *name, Oid newOwnerId);
extern bool PLTemplateExists(const char *languageName);
#endif /* PROCLANG_H */
Index: src/include/utils/acl.h
===================================================================
RCS file: /data/local/jeremyd/postgres/cvsuproot/pgsql/src/include/utils/acl.h,v
retrieving revision 1.100
diff -c -r1.100 acl.h
*** src/include/utils/acl.h 23 Jan 2007 05:07:18 -0000 1.100
--- src/include/utils/acl.h 27 Jan 2007 00:05:16 -0000
***************
*** 274,279 ****
--- 274,280 ----
extern bool pg_type_ownercheck(Oid type_oid, Oid roleid);
extern bool pg_oper_ownercheck(Oid oper_oid, Oid roleid);
extern bool pg_proc_ownercheck(Oid proc_oid, Oid roleid);
+ extern bool pg_language_ownercheck(Oid lan_oid, Oid roleid);
extern bool pg_namespace_ownercheck(Oid nsp_oid, Oid roleid);
extern bool pg_tablespace_ownercheck(Oid spc_oid, Oid roleid);
extern bool pg_opclass_ownercheck(Oid opc_oid, Oid roleid);
---------------------------(end of broadcast)---------------------------
TIP 6: explain analyze is your friend