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 06:45:05 -0000 *************** *** 17,32 **** --- 17,36 ---- #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" #include "catalog/pg_proc.h" #include "catalog/pg_type.h" + #include "commands/dbcommands.h" #include "commands/defrem.h" #include "commands/proclang.h" #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); /* --------------------------------------------------------------------- --- 40,58 ---- 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 */ --- 70,75 ---- *************** *** 97,102 **** --- 98,125 ---- (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 --- 194,200 ---- valOid = InvalidOid; /* ok, create it */ ! create_proc_lang(languageName, find_desired_language_owner(pltemplate), handlerOid, valOid, pltemplate->tmpltrusted); } else *************** *** 189,194 **** --- 212,225 ---- 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); } } --- 258,264 ---- valOid = InvalidOid; /* ok, create it */ ! create_proc_lang(languageName, GetUserId(), handlerOid, valOid, stmt->pltrusted); } } *************** *** 236,242 **** */ static void create_proc_lang(const char *languageName, ! Oid handlerOid, Oid valOid, bool trusted) { Relation rel; TupleDesc tupDesc; --- 267,273 ---- */ static void create_proc_lang(const char *languageName, ! Oid languageOwner, Oid handlerOid, Oid valOid, bool trusted) { Relation rel; TupleDesc tupDesc; *************** *** 258,263 **** --- 289,295 ---- 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 **** --- 309,320 ---- 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 **** --- 333,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 + { + return GetUserId(); + } + } + /* * 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);