diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2007-03-26 16:58:41 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2007-03-26 16:58:41 +0000 |
commit | 55a7cf80a0769d38f03bd728717da855902041b1 (patch) | |
tree | 147a3aa02b95844de61c869232c2dbe802914e67 | |
parent | 66daeb074b3fbdb071a5631c066f5e41d554220e (diff) | |
download | postgresql-55a7cf80a0769d38f03bd728717da855902041b1.tar.gz postgresql-55a7cf80a0769d38f03bd728717da855902041b1.zip |
Allow non-superuser database owners to create procedural languages.
A DBA is allowed to create a language in his database if it's marked
"tmpldbacreate" in pg_pltemplate. The factory default is that this is set
for all standard trusted languages, but of course a superuser may adjust
the settings. In service of this, add the long-foreseen owner column to
pg_language; renaming, dropping, and altering owner of a PL now follow
normal ownership rules instead of being superuser-only.
Jeremy Drake, with some editorialization by Tom Lane.
-rw-r--r-- | doc/src/sgml/catalogs.sgml | 17 | ||||
-rw-r--r-- | doc/src/sgml/ref/alter_language.sgml | 19 | ||||
-rw-r--r-- | doc/src/sgml/ref/create_language.sgml | 20 | ||||
-rw-r--r-- | doc/src/sgml/ref/drop_language.sgml | 6 | ||||
-rw-r--r-- | src/backend/catalog/aclchk.c | 38 | ||||
-rw-r--r-- | src/backend/commands/alter.c | 6 | ||||
-rw-r--r-- | src/backend/commands/proclang.c | 162 | ||||
-rw-r--r-- | src/backend/parser/gram.y | 16 | ||||
-rw-r--r-- | src/backend/tcop/utility.c | 5 | ||||
-rw-r--r-- | src/bin/pg_dump/pg_backup_archiver.c | 5 | ||||
-rw-r--r-- | src/bin/pg_dump/pg_dump.c | 16 | ||||
-rw-r--r-- | src/bin/psql/tab-complete.c | 9 | ||||
-rw-r--r-- | src/include/catalog/catversion.h | 4 | ||||
-rw-r--r-- | src/include/catalog/pg_language.h | 26 | ||||
-rw-r--r-- | src/include/catalog/pg_pltemplate.h | 26 | ||||
-rw-r--r-- | src/include/commands/proclang.h | 1 | ||||
-rw-r--r-- | src/include/utils/acl.h | 3 |
17 files changed, 295 insertions, 84 deletions
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index d89cd8a4984..7d325d1dde5 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.147 2007/03/22 15:46:56 momjian Exp $ --> +<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.148 2007/03/26 16:58:37 tgl Exp $ --> <!-- Documentation of the system catalogs, directed toward PostgreSQL developers --> @@ -2656,6 +2656,13 @@ </row> <row> + <entry><structfield>lanowner</structfield></entry> + <entry><type>oid</type></entry> + <entry><literal><link linkend="catalog-pg-authid"><structname>pg_authid</structname></link>.oid</literal></entry> + <entry>Owner of the language</entry> + </row> + + <row> <entry><structfield>lanispl</structfield></entry> <entry><type>bool</type></entry> <entry></entry> @@ -3265,7 +3272,7 @@ <table> <title><structname>pg_pltemplate</> Columns</title> - <tgroup cols=4> + <tgroup cols=3> <thead> <row> <entry>Name</entry> @@ -3288,6 +3295,12 @@ </row> <row> + <entry><structfield>tmpldbacreate</structfield></entry> + <entry><type>boolean</type></entry> + <entry>True if language may be created by a database owner</entry> + </row> + + <row> <entry><structfield>tmplhandler</structfield></entry> <entry><type>text</type></entry> <entry>Name of call handler function</entry> diff --git a/doc/src/sgml/ref/alter_language.sgml b/doc/src/sgml/ref/alter_language.sgml index 9c336f163bf..e0cdb9d5a56 100644 --- a/doc/src/sgml/ref/alter_language.sgml +++ b/doc/src/sgml/ref/alter_language.sgml @@ -1,5 +1,5 @@ <!-- -$PostgreSQL: pgsql/doc/src/sgml/ref/alter_language.sgml,v 1.6 2006/09/16 00:30:16 momjian Exp $ +$PostgreSQL: pgsql/doc/src/sgml/ref/alter_language.sgml,v 1.7 2007/03/26 16:58:38 tgl Exp $ PostgreSQL documentation --> @@ -20,7 +20,8 @@ PostgreSQL documentation <refsynopsisdiv> <synopsis> -ALTER LANGUAGE <replaceable>name</replaceable> RENAME TO <replaceable>newname</replaceable> +ALTER [ PROCEDURAL ] LANGUAGE <replaceable>name</replaceable> RENAME TO <replaceable>newname</replaceable> +ALTER [ PROCEDURAL ] LANGUAGE <replaceable>name</replaceable> OWNER TO <replaceable>new_owner</replaceable> </synopsis> </refsynopsisdiv> @@ -29,8 +30,9 @@ ALTER LANGUAGE <replaceable>name</replaceable> RENAME TO <replaceable>newname</r <para> <command>ALTER LANGUAGE</command> changes the definition of a - language. The only functionality is to rename the language. Only - a superuser can rename languages. + procedural language. The only functionality is to rename the language or + assign a new owner. You must be superuser or owner of the language to + use <command>ALTER LANGUAGE</command>. </para> </refsect1> @@ -55,6 +57,15 @@ ALTER LANGUAGE <replaceable>name</replaceable> RENAME TO <replaceable>newname</r </para> </listitem> </varlistentry> + + <varlistentry> + <term><replaceable>new_owner</replaceable></term> + <listitem> + <para> + The new owner of the language + </para> + </listitem> + </varlistentry> </variablelist> </refsect1> diff --git a/doc/src/sgml/ref/create_language.sgml b/doc/src/sgml/ref/create_language.sgml index b09b38bee99..bb853feb19c 100644 --- a/doc/src/sgml/ref/create_language.sgml +++ b/doc/src/sgml/ref/create_language.sgml @@ -1,5 +1,5 @@ <!-- -$PostgreSQL: pgsql/doc/src/sgml/ref/create_language.sgml,v 1.43 2007/01/31 23:26:03 momjian Exp $ +$PostgreSQL: pgsql/doc/src/sgml/ref/create_language.sgml,v 1.44 2007/03/26 16:58:38 tgl Exp $ PostgreSQL documentation --> @@ -34,9 +34,7 @@ CREATE [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</ <productname>PostgreSQL</productname> user can register a new procedural language with a <productname>PostgreSQL</productname> database. Subsequently, functions and trigger procedures can be - defined in this new language. The user must have the - <productname>PostgreSQL</productname> superuser privilege to - register a new language. + defined in this new language. </para> <para> @@ -64,6 +62,20 @@ CREATE [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</ old dump files, which are likely to contain out-of-date information about language support functions. </para> + + <para> + Ordinarily, the user must have the + <productname>PostgreSQL</productname> superuser privilege to + register a new language. However, the owner of a database can register + a new language within that database if the language is listed in + the <structname>pg_pltemplate</structname> catalog and is marked + as allowed to be created by database owners (<structfield>tmpldbacreate</> + is true). The default is that trusted languages can be created + by database owners, but this can be adjusted by superusers by modifying + the contents of <structname>pg_pltemplate</structname>. + The creator of a language becomes its owner and can later + drop it, rename it, or assign it to a new owner. + </para> </refsect1> <refsect1 id="sql-createlanguage-parameters"> diff --git a/doc/src/sgml/ref/drop_language.sgml b/doc/src/sgml/ref/drop_language.sgml index ad37287da67..1e3c960a720 100644 --- a/doc/src/sgml/ref/drop_language.sgml +++ b/doc/src/sgml/ref/drop_language.sgml @@ -1,5 +1,5 @@ <!-- -$PostgreSQL: pgsql/doc/src/sgml/ref/drop_language.sgml,v 1.24 2007/01/31 23:26:03 momjian Exp $ +$PostgreSQL: pgsql/doc/src/sgml/ref/drop_language.sgml,v 1.25 2007/03/26 16:58:38 tgl Exp $ PostgreSQL documentation --> @@ -31,6 +31,8 @@ DROP [ PROCEDURAL ] LANGUAGE [ IF EXISTS ] <replaceable class="PARAMETER">name</ <command>DROP LANGUAGE</command> will remove the definition of the previously registered procedural language called <replaceable class="parameter">name</replaceable>. + You must be superuser or owner of the language to + use <command>DROP LANGUAGE</command>. </para> </refsect1> @@ -43,7 +45,7 @@ DROP [ PROCEDURAL ] LANGUAGE [ IF EXISTS ] <replaceable class="PARAMETER">name</ <term><literal>IF EXISTS</literal></term> <listitem> <para> - Do not throw an error if the function does not exist. A notice is issued + Do not throw an error if the language does not exist. A notice is issued in this case. </para> </listitem> diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c index a2b64c78b3f..b837ba4e91c 100644 --- a/src/backend/catalog/aclchk.c +++ b/src/backend/catalog/aclchk.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.137 2007/02/14 01:58:56 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.138 2007/03/26 16:58:38 tgl Exp $ * * NOTES * See acl.h. @@ -1003,11 +1003,8 @@ ExecGrant_Language(InternalGrant *istmt) /* * 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; + ownerId = pg_language_tuple->lanowner; aclDatum = SysCacheGetAttr(LANGNAME, tuple, Anum_pg_language_lanacl, &isNull); if (isNull) @@ -1770,8 +1767,7 @@ pg_language_aclmask(Oid lang_oid, Oid roleid, (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; + ownerId = ((Form_pg_language) GETSTRUCT(tuple))->lanowner; aclDatum = SysCacheGetAttr(LANGOID, tuple, Anum_pg_language_lanacl, &isNull); @@ -2148,6 +2144,34 @@ pg_proc_ownercheck(Oid proc_oid, Oid roleid) } /* + * 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 diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c index 30b7ebde002..118e4adb166 100644 --- a/src/backend/commands/alter.c +++ b/src/backend/commands/alter.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/alter.c,v 1.22 2007/01/23 05:07:17 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/alter.c,v 1.23 2007/03/26 16:58:38 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -203,6 +203,10 @@ ExecAlterOwnerStmt(AlterOwnerStmt *stmt) 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, diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c index 028ab5e5217..e396e0018d0 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 - * $PostgreSQL: pgsql/src/backend/commands/proclang.c,v 1.71 2007/01/22 01:35:20 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/proclang.c,v 1.72 2007/03/26 16:58:38 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -17,16 +17,19 @@ #include "access/heapam.h" #include "catalog/dependency.h" #include "catalog/indexing.h" +#include "catalog/pg_authid.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,13 +39,14 @@ typedef struct { bool tmpltrusted; /* trusted? */ + bool tmpldbacreate; /* 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 handlerOid, Oid valOid, bool trusted); + Oid languageOwner, Oid handlerOid, Oid valOid, bool trusted); static PLTemplate *find_language_template(const char *languageName); @@ -61,14 +65,6 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) 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 */ @@ -97,6 +93,21 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) (errmsg("using pg_pltemplate information instead of CREATE LANGUAGE parameters"))); /* + * Check permission + */ + if (!superuser()) + { + if (!pltemplate->tmpldbacreate) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("must be superuser to create procedural language \"%s\"", + languageName))); + if (!pg_database_ownercheck(MyDatabaseId, GetUserId())) + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE, + get_database_name(MyDatabaseId)); + } + + /* * 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,7 +182,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) valOid = InvalidOid; /* ok, create it */ - create_proc_lang(languageName, handlerOid, valOid, + create_proc_lang(languageName, GetUserId(), handlerOid, valOid, pltemplate->tmpltrusted); } else @@ -189,6 +200,14 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) 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,7 +246,8 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) valOid = InvalidOid; /* ok, create it */ - create_proc_lang(languageName, handlerOid, valOid, stmt->pltrusted); + create_proc_lang(languageName, GetUserId(), handlerOid, valOid, + stmt->pltrusted); } } @@ -236,7 +256,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) */ static void create_proc_lang(const char *languageName, - Oid handlerOid, Oid valOid, bool trusted) + Oid languageOwner, Oid handlerOid, Oid valOid, bool trusted) { Relation rel; TupleDesc tupDesc; @@ -258,6 +278,7 @@ create_proc_lang(const char *languageName, 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,6 +298,12 @@ create_proc_lang(const char *languageName, 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; @@ -325,6 +352,7 @@ find_language_template(const char *languageName) result = (PLTemplate *) palloc0(sizeof(PLTemplate)); result->tmpltrusted = tmpl->tmpltrusted; + result->tmpldbacreate = tmpl->tmpldbacreate; /* Remaining fields are variable-width so we need heap_getattr */ datum = heap_getattr(tup, Anum_pg_pltemplate_tmplhandler, @@ -382,14 +410,6 @@ DropProceduralLanguage(DropPLangStmt *stmt) 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); @@ -411,6 +431,13 @@ DropProceduralLanguage(DropPLangStmt *stmt) 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,11 +505,10 @@ RenameLanguage(const char *oldname, const char *newname) (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"))); + /* 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,3 +518,87 @@ RenameLanguage(const char *oldname, const char *newname) heap_close(rel, NoLock); heap_freetuple(tup); } + +/* + * Change language owner + */ +void +AlterLanguageOwner(const char *name, Oid newOwnerId) +{ + HeapTuple tup; + Relation rel; + Form_pg_language lanForm; + + /* 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))); + 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; + + /* 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); + + 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); + } + + ReleaseSysCache(tup); + heap_close(rel, RowExclusiveLock); +} diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 75404716d5a..8cad738a357 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.583 2007/03/19 23:38:29 wieck Exp $ + * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.584 2007/03/26 16:58:39 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -4447,12 +4447,12 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name n->newname = $6; $$ = (Node *)n; } - | ALTER LANGUAGE name RENAME TO name + | ALTER opt_procedural LANGUAGE name RENAME TO name { RenameStmt *n = makeNode(RenameStmt); n->renameType = OBJECT_LANGUAGE; - n->subname = $3; - n->newname = $6; + n->subname = $4; + n->newname = $7; $$ = (Node *)n; } | ALTER OPERATOR CLASS any_name USING access_method RENAME TO name @@ -4654,6 +4654,14 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId n->newowner = $7; $$ = (Node *)n; } + | ALTER opt_procedural LANGUAGE name OWNER TO RoleId + { + AlterOwnerStmt *n = makeNode(AlterOwnerStmt); + n->objectType = OBJECT_LANGUAGE; + n->object = list_make1($4); + n->newowner = $7; + $$ = (Node *)n; + } | ALTER OPERATOR any_operator '(' oper_argtypes ')' OWNER TO RoleId { AlterOwnerStmt *n = makeNode(AlterOwnerStmt); diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index be274a72f10..daf23fd0fe5 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.274 2007/03/13 00:33:42 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.275 2007/03/26 16:58:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1551,6 +1551,9 @@ CreateCommandTag(Node *parsetree) case OBJECT_FUNCTION: tag = "ALTER FUNCTION"; break; + case OBJECT_LANGUAGE: + tag = "ALTER LANGUAGE"; + break; case OBJECT_OPERATOR: tag = "ALTER OPERATOR"; break; diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c index cd979cfaddf..981168bfa7c 100644 --- a/src/bin/pg_dump/pg_backup_archiver.c +++ b/src/bin/pg_dump/pg_backup_archiver.c @@ -15,7 +15,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.143 2007/03/18 16:50:44 neilc Exp $ + * $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.144 2007/03/26 16:58:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -2440,6 +2440,7 @@ _getObjectDescription(PQExpBuffer buf, TocEntry *te, ArchiveHandle *AH) /* objects named by just a name */ if (strcmp(type, "DATABASE") == 0 || + strcmp(type, "PROCEDURAL LANGUAGE") == 0 || strcmp(type, "SCHEMA") == 0) { appendPQExpBuffer(buf, "%s %s", type, fmtId(te->tag)); @@ -2583,6 +2584,7 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat strcmp(te->desc, "OPERATOR") == 0 || strcmp(te->desc, "OPERATOR CLASS") == 0 || strcmp(te->desc, "OPERATOR FAMILY") == 0 || + strcmp(te->desc, "PROCEDURAL LANGUAGE") == 0 || strcmp(te->desc, "SCHEMA") == 0 || strcmp(te->desc, "TABLE") == 0 || strcmp(te->desc, "TYPE") == 0 || @@ -2603,7 +2605,6 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat strcmp(te->desc, "DEFAULT") == 0 || strcmp(te->desc, "FK CONSTRAINT") == 0 || strcmp(te->desc, "INDEX") == 0 || - strcmp(te->desc, "PROCEDURAL LANGUAGE") == 0 || strcmp(te->desc, "RULE") == 0 || strcmp(te->desc, "TRIGGER") == 0) { diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 61bf13eb4fd..b0c9e70a46f 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -12,7 +12,7 @@ * by PostgreSQL * * IDENTIFICATION - * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.464 2007/03/22 20:47:12 momjian Exp $ + * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.465 2007/03/26 16:58:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -4030,7 +4030,19 @@ getProcLangs(int *numProcLangs) /* Make sure we are in proper schema */ selectSourceSchema("pg_catalog"); - if (g_fout->remoteVersion >= 80100) + if (g_fout->remoteVersion >= 80300) + { + /* pg_language has a lanowner column */ + appendPQExpBuffer(query, "SELECT tableoid, oid, " + "lanname, lanpltrusted, lanplcallfoid, " + "lanvalidator, lanacl, " + "(%s lanowner) as lanowner " + "FROM pg_language " + "WHERE lanispl " + "ORDER BY oid", + username_subquery); + } + else if (g_fout->remoteVersion >= 80100) { /* Languages are owned by the bootstrap superuser, OID 10 */ appendPQExpBuffer(query, "SELECT tableoid, oid, *, " diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c index 63db48546bf..970bbecadf8 100644 --- a/src/bin/psql/tab-complete.c +++ b/src/bin/psql/tab-complete.c @@ -3,7 +3,7 @@ * * Copyright (c) 2000-2007, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.159 2007/02/23 18:20:59 momjian Exp $ + * $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.160 2007/03/26 16:58:40 tgl Exp $ */ /*---------------------------------------------------------------------- @@ -651,7 +651,12 @@ psql_completion(char *text, int start, int end) /* ALTER LANGUAGE <name> */ else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && pg_strcasecmp(prev2_wd, "LANGUAGE") == 0) - COMPLETE_WITH_CONST("RENAME TO"); + { + 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 && diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index e7ab0e78f02..79dd0cdb10e 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -37,7 +37,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.394 2007/03/25 11:56:04 ishii Exp $ + * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.395 2007/03/26 16:58:41 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 200703251 +#define CATALOG_VERSION_NO 200703261 #endif diff --git a/src/include/catalog/pg_language.h b/src/include/catalog/pg_language.h index a7e449e5139..bf4fdd2774f 100644 --- a/src/include/catalog/pg_language.h +++ b/src/include/catalog/pg_language.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_language.h,v 1.29 2007/01/05 22:19:52 momjian Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_language.h,v 1.30 2007/03/26 16:58:41 tgl Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -35,11 +35,12 @@ CATALOG(pg_language,2612) { - NameData lanname; + NameData lanname; /* Language name */ + Oid lanowner; /* Language's owner */ bool lanispl; /* Is a procedural language */ bool lanpltrusted; /* PL is trusted */ Oid lanplcallfoid; /* Call handler for PL */ - Oid lanvalidator; /* optional validation function */ + Oid lanvalidator; /* Optional validation function */ aclitem lanacl[1]; /* Access privileges */ } FormData_pg_language; @@ -54,26 +55,27 @@ typedef FormData_pg_language *Form_pg_language; * compiler constants for pg_language * ---------------- */ -#define Natts_pg_language 6 +#define Natts_pg_language 7 #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 +#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" f f 0 2246 _null_ )); +DATA(insert OID = 12 ( "internal" PGUID f f 0 2246 _null_ )); DESCR("Built-in functions"); #define INTERNALlanguageId 12 -DATA(insert OID = 13 ( "c" f f 0 2247 _null_ )); +DATA(insert OID = 13 ( "c" PGUID f f 0 2247 _null_ )); DESCR("Dynamically-loaded C functions"); #define ClanguageId 13 -DATA(insert OID = 14 ( "sql" f t 0 2248 _null_ )); +DATA(insert OID = 14 ( "sql" PGUID f t 0 2248 _null_ )); DESCR("SQL-language functions"); #define SQLlanguageId 14 diff --git a/src/include/catalog/pg_pltemplate.h b/src/include/catalog/pg_pltemplate.h index a5c05f4d069..7f33eed49e3 100644 --- a/src/include/catalog/pg_pltemplate.h +++ b/src/include/catalog/pg_pltemplate.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_pltemplate.h,v 1.3 2007/01/05 22:19:53 momjian Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_pltemplate.h,v 1.4 2007/03/26 16:58:41 tgl Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -37,6 +37,7 @@ CATALOG(pg_pltemplate,1136) BKI_SHARED_RELATION BKI_WITHOUT_OIDS { NameData tmplname; /* name of PL */ bool tmpltrusted; /* PL is trusted? */ + bool tmpldbacreate; /* 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,13 +55,14 @@ typedef FormData_pg_pltemplate *Form_pg_pltemplate; * compiler constants for pg_pltemplate * ---------------- */ -#define Natts_pg_pltemplate 6 +#define Natts_pg_pltemplate 7 #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 +#define Anum_pg_pltemplate_tmpldbacreate 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,11 +70,11 @@ typedef FormData_pg_pltemplate *Form_pg_pltemplate; * ---------------- */ -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_ )); +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 f "pltclu_call_handler" _null_ "$libdir/pltcl" _null_ )); +DATA(insert ( "plperl" t t "plperl_call_handler" "plperl_validator" "$libdir/plperl" _null_ )); +DATA(insert ( "plperlu" f f "plperl_call_handler" "plperl_validator" "$libdir/plperl" _null_ )); +DATA(insert ( "plpythonu" f f "plpython_call_handler" _null_ "$libdir/plpython" _null_ )); #endif /* PG_PLTEMPLATE_H */ diff --git a/src/include/commands/proclang.h b/src/include/commands/proclang.h index 7f38a8542ac..0ae128285d1 100644 --- a/src/include/commands/proclang.h +++ b/src/include/commands/proclang.h @@ -15,6 +15,7 @@ extern void CreateProceduralLanguage(CreatePLangStmt *stmt); 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 */ diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h index 14522bc6fb1..5eb054e1466 100644 --- a/src/include/utils/acl.h +++ b/src/include/utils/acl.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.100 2007/01/23 05:07:18 tgl Exp $ + * $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.101 2007/03/26 16:58:41 tgl Exp $ * * NOTES * An ACL array is simply an array of AclItems, representing the union @@ -274,6 +274,7 @@ extern bool pg_class_ownercheck(Oid class_oid, Oid roleid); 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); |