Index: 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 ----
ALTER LANGUAGE name RENAME TO newname
+
+ ALTER LANGUAGE name OWNER TO new_owner
***************
*** 48,53 ****
--- 50,64 ----
+ new_owner
+
+
+ The new owner of the language.
+
+
+
+
+
newname
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 */
else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
pg_strcasecmp(prev2_wd, "LANGUAGE") == 0)
! COMPLETE_WITH_CONST("RENAME TO");
/* ALTER USER,ROLE */
else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
--- 651,662 ----
/* ALTER LANGUAGE */
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 */
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);