diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 6260c25445a7aa9ddf0417b375422495ee44b533..c813ba98ded7874de4cb802f2da6144c6f964975 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -1,6 +1,6 @@
 <!--
  Documentation of the system catalogs, directed toward PostgreSQL developers
- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.112 2005/08/24 17:24:17 tgl Exp $
+ $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.113 2005/09/08 20:07:41 tgl Exp $
  -->
 
 <chapter id="catalogs">
@@ -168,6 +168,11 @@
       <entry>operators</entry>
      </row>
 
+     <row>
+      <entry><link linkend="catalog-pg-pltemplate"><structname>pg_pltemplate</structname></link></entry>
+      <entry>template data for procedural languages</entry>
+     </row>
+
      <row>
       <entry><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link></entry>
       <entry>functions and procedures</entry>
@@ -3027,6 +3032,106 @@
  </sect1>
 
 
+ <sect1 id="catalog-pg-pltemplate">
+  <title><structname>pg_pltemplate</structname></title>
+
+  <indexterm zone="catalog-pg-pltemplate">
+   <primary>pg_pltemplate</primary>
+  </indexterm>
+
+  <para>
+   The catalog <structname>pg_pltemplate</structname> stores
+   <quote>template</> information for procedural languages.
+   A template for a language allows the language to be created in a
+   particular database by a simple <command>CREATE LANGUAGE</> command,
+   with no need to specify implementation details.
+  </para>
+
+  <para>
+   Unlike most system catalogs, <structname>pg_pltemplate</structname>
+   is shared across all databases of a cluster: there is only one
+   copy of <structname>pg_pltemplate</structname> per cluster, not
+   one per database.  This allows the information to be accessible in
+   each database as it is needed.
+  </para>
+
+  <table>
+   <title><structname>pg_pltemplate</> Columns</title>
+
+   <tgroup cols=4>
+    <thead>
+     <row>
+      <entry>Name</entry>
+      <entry>Type</entry>
+      <entry>References</entry>
+      <entry>Description</entry>
+     </row>
+    </thead>
+
+    <tbody>
+     <row>
+      <entry><structfield>tmplname</structfield></entry>
+      <entry><type>name</type></entry>
+      <entry></entry>
+      <entry>Name of the language this template is for</entry>
+     </row>
+
+     <row>
+      <entry><structfield>tmpltrusted</structfield></entry>
+      <entry><type>boolean</type></entry>
+      <entry></entry>
+      <entry>True if language is considered trusted</entry>
+     </row>
+
+     <row>
+      <entry><structfield>tmplhandler</structfield></entry>
+      <entry><type>text</type></entry>
+      <entry></entry>
+      <entry>Name of call handler function</entry>
+     </row>
+
+     <row>
+      <entry><structfield>tmplvalidator</structfield></entry>
+      <entry><type>text</type></entry>
+      <entry></entry>
+      <entry>Name of validator function, or NULL if none</entry>
+     </row>
+
+     <row>
+      <entry><structfield>tmpllibrary</structfield></entry>
+      <entry><type>text</type></entry>
+      <entry></entry>
+      <entry>Path of shared library that implements language</entry>
+     </row>
+
+     <row>
+      <entry><structfield>tmplacl</structfield></entry>
+      <entry><type>aclitem[]</type></entry>
+      <entry></entry>
+      <entry>Access privileges for template (not yet used)</entry>
+     </row>
+
+    </tbody>
+   </tgroup>
+  </table>
+
+  <para>
+   There are not currently any commands that manipulate procedural language
+   templates; to change the built-in information, a superuser must modify
+   the table using ordinary INSERT, DELETE, or UPDATE commands.  It is
+   likely that a future release of <productname>PostgreSQL</productname>
+   will offer commands to change the entries in a cleaner fashion.
+  </para>
+
+  <para>
+   When implemented, the <structfield>tmplacl</structfield> field will provide
+   access control for the template itself (i.e., the right to create a
+   language using it), not for the languages created from the template.
+  </para>
+
+ </sect1>
+
+
  <sect1 id="catalog-pg-proc">
   <title><structname>pg_proc</structname></title>
 
diff --git a/doc/src/sgml/ref/create_language.sgml b/doc/src/sgml/ref/create_language.sgml
index 29bcade195dca2c414f3e28c72a098059a2d03ad..e76dd58687ae6ec3c43264b5632bde0853a0074a 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.40 2005/09/05 23:50:48 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/create_language.sgml,v 1.41 2005/09/08 20:07:41 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -48,22 +48,19 @@ CREATE [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</
 
   <para>
    There are two forms of the <command>CREATE LANGUAGE</command> command.
-   In the first form, the user merely supplies the name of the desired
+   In the first form, the user supplies just the name of the desired
    language, and the <productname>PostgreSQL</productname> server consults
-   an internal table to determine the correct parameters.  In
-   the second form, the user supplies the language parameters along with
-   the language name.  The second form must be used to create a language
-   that is not present in the internal table, but this form is considered
-   obsolescent.  (It is expected that future releases of
-   <productname>PostgreSQL</productname> will replace the internal table
-   with a system catalog that can be extended to support additional
-   languages.)
+   the <link linkend="catalog-pg-pltemplate"><structname>pg_pltemplate</structname></link>
+   system catalog to determine the correct parameters.  In the second form,
+   the user supplies the language parameters along with the language name.
+   The second form can be used to create a language that is not defined in
+   <structname>pg_pltemplate</>, but this approach is considered obsolescent.
   </para>
 
   <para>
-   When the server finds an entry in its internal table for the given
-   language name, it will use the table data even if the given command
-   includes language parameters.  This behavior simplifies loading of
+   When the server finds an entry in the <structname>pg_pltemplate</> catalog
+   for the given language name, it will use the catalog data even if the
+   command includes language parameters.  This behavior simplifies loading of
    old dump files, which are likely to contain out-of-date information
    about language support functions.
   </para>
@@ -165,8 +162,8 @@ CREATE [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</
 
   <para>
    The <literal>TRUSTED</> option and the support function name(s) are
-   ignored if the server has information about the specified language
-   name in its internal table.
+   ignored if the server has an entry for the specified language
+   name in <structname>pg_pltemplate</>.
   </para>
  </refsect1>
 
@@ -207,9 +204,9 @@ CREATE [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</
 
   <para>
    The call handler function and the validator function (if any)
-   must already exist if the server does not have information about
-   the language in its internal table.  But when there is an entry
-   in the internal table, the functions need not already exist;
+   must already exist if the server does not have an entry for the language
+   in <structname>pg_pltemplate</>.  But when there is an entry,
+   the functions need not already exist;
    they will be automatically defined if not present in the database.
    (This can result in <command>CREATE LANGUAGE</> failing, if the
    shared library that implements the language is not available in
@@ -239,8 +236,8 @@ CREATE LANGUAGE plpgsql;
   </para>
 
   <para>
-   For a language not known in the server's internal table, a sequence
-   such as this is needed:
+   For a language not known in the <structname>pg_pltemplate</> catalog, a
+   sequence such as this is needed:
 <programlisting>
 CREATE FUNCTION plsample_call_handler() RETURNS language_handler
     AS '$libdir/plsample'
diff --git a/doc/src/sgml/ref/createlang.sgml b/doc/src/sgml/ref/createlang.sgml
index f9f8dc1ea78fb5ec2d61762f50aa8d22477e6870..0e613caf00382db6d614b10f7ca92b318a479f85 100644
--- a/doc/src/sgml/ref/createlang.sgml
+++ b/doc/src/sgml/ref/createlang.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/createlang.sgml,v 1.36 2005/09/05 23:50:48 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/createlang.sgml,v 1.37 2005/09/08 20:07:41 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -40,11 +40,9 @@ PostgreSQL documentation
   <para>
    <application>createlang</application> is a utility for adding a new 
    programming language to a <productname>PostgreSQL</productname> database.
-   <application>createlang</application> can handle all the languages
-   supplied in the default <productname>PostgreSQL</> distribution, but
-   not languages provided by other parties.  See
+   <application>createlang</application> is just a wrapper around the
    <xref linkend="sql-createlanguage" endterm="sql-createlanguage-title">
-   for additional information.
+   command, which see for additional information.
   </para>
  </refsect1>
 
diff --git a/src/backend/catalog/Makefile b/src/backend/catalog/Makefile
index c2dd227d1d9e9c1357e6c4cac0cc799cdd8e4dd7..67a46e93c0cf1f8141807221d3cc250632c4f9b4 100644
--- a/src/backend/catalog/Makefile
+++ b/src/backend/catalog/Makefile
@@ -2,7 +2,7 @@
 #
 # Makefile for backend/catalog
 #
-# $PostgreSQL: pgsql/src/backend/catalog/Makefile,v 1.56 2005/07/14 05:13:39 tgl Exp $
+# $PostgreSQL: pgsql/src/backend/catalog/Makefile,v 1.57 2005/09/08 20:07:41 tgl Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -32,8 +32,9 @@ POSTGRES_BKI_SRCS := $(addprefix $(top_srcdir)/src/include/catalog/,\
 	pg_operator.h pg_opclass.h pg_am.h pg_amop.h pg_amproc.h \
 	pg_language.h pg_largeobject.h pg_aggregate.h pg_statistic.h \
 	pg_rewrite.h pg_trigger.h pg_listener.h pg_description.h pg_cast.h \
-	pg_namespace.h pg_conversion.h pg_database.h pg_shdepend.h \
-	pg_authid.h pg_auth_members.h pg_tablespace.h pg_depend.h \
+	pg_namespace.h pg_conversion.h pg_depend.h \
+	pg_database.h pg_tablespace.h pg_pltemplate.h \
+	pg_authid.h pg_auth_members.h pg_shdepend.h \
 	indexing.h \
     )
 
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index d6bb902274efc8a042a8a271d0ec3db4b6dd36e8..c2bb4a2d9c8ccb6428f2da19f8606b4f993cad1a 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.66 2005/08/22 17:38:20 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.67 2005/09/08 20:07:41 tgl Exp $
  *
  * DESCRIPTION
  *	  These routines take the parse tree and pick out the
@@ -44,6 +44,7 @@
 #include "catalog/pg_proc.h"
 #include "catalog/pg_type.h"
 #include "commands/defrem.h"
+#include "commands/proclang.h"
 #include "miscadmin.h"
 #include "optimizer/cost.h"
 #include "parser/parse_func.h"
@@ -543,17 +544,11 @@ CreateFunction(CreateFunctionStmt *stmt)
 								   PointerGetDatum(languageName),
 								   0, 0, 0);
 	if (!HeapTupleIsValid(languageTuple))
-		/* Add any new languages to this list to invoke the hint. */
 		ereport(ERROR,
 				(errcode(ERRCODE_UNDEFINED_OBJECT),
 				 errmsg("language \"%s\" does not exist", languageName),
-				 (strcmp(languageName, "plperl") == 0 ||
-				  strcmp(languageName, "plperlu") == 0 ||
-				  strcmp(languageName, "plpgsql") == 0 ||
-				  strcmp(languageName, "plpythonu") == 0 ||
-				  strcmp(languageName, "pltcl") == 0 ||
-				  strcmp(languageName, "pltclu") == 0) ?
-				 errhint("You need to use \"createlang\" to load the language into the database.") : 0));
+				 (PLTemplateExists(languageName) ?
+				  errhint("Use CREATE LANGUAGE to load the language into the database.") : 0)));
 
 	languageOid = HeapTupleGetOid(languageTuple);
 	languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c
index 499523ae00758161131969a69067bc28a1ff7de2..4155dc179ad1057b339e2f64f4ae789a02695f56 100644
--- a/src/backend/commands/proclang.c
+++ b/src/backend/commands/proclang.c
@@ -7,18 +7,20 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/proclang.c,v 1.61 2005/09/05 23:50:48 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/proclang.c,v 1.62 2005/09/08 20:07:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "postgres.h"
 
+#include "access/genam.h"
 #include "access/heapam.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/namespace.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/proclang.h"
@@ -35,11 +37,10 @@
 
 typedef struct
 {
-	char	   *lanname;		/* PL name */
-	bool		lantrusted;		/* trusted? */
-	char	   *lanhandler;		/* name of handler function */
-	char	   *lanvalidator;	/* name of validator function, or NULL */
-	char	   *lanlibrary;		/* path of shared library */
+	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,
@@ -90,12 +91,19 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 	{
 		List	*funcname;
 
+		/*
+		 * Give a notice if we are ignoring supplied parameters.
+		 */
+		if (stmt->plhandler)
+			ereport(NOTICE,
+					(errmsg("using pg_pltemplate information instead of CREATE LANGUAGE parameters")));
+
 		/*
 		 * 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.
 		 */
-		funcname = SystemFuncName(pltemplate->lanhandler);
+		funcname = SystemFuncName(pltemplate->tmplhandler);
 		handlerOid = LookupFuncName(funcname, 0, funcargtypes, true);
 		if (OidIsValid(handlerOid))
 		{
@@ -108,15 +116,15 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 		}
 		else
 		{
-			handlerOid = ProcedureCreate(pltemplate->lanhandler,
+			handlerOid = ProcedureCreate(pltemplate->tmplhandler,
 										 PG_CATALOG_NAMESPACE,
 										 false,		/* replace */
 										 false,		/* returnsSet */
 										 LANGUAGE_HANDLEROID,
 										 ClanguageId,
 										 F_FMGR_C_VALIDATOR,
-										 pltemplate->lanhandler,
-										 pltemplate->lanlibrary,
+										 pltemplate->tmplhandler,
+										 pltemplate->tmpllibrary,
 										 false,		/* isAgg */
 										 false,		/* security_definer */
 										 false,		/* isStrict */
@@ -131,22 +139,22 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 		 * Likewise for the validator, if required; but we don't care about
 		 * its return type.
 		 */
-		if (pltemplate->lanvalidator)
+		if (pltemplate->tmplvalidator)
 		{
-			funcname = SystemFuncName(pltemplate->lanvalidator);
+			funcname = SystemFuncName(pltemplate->tmplvalidator);
 			funcargtypes[0] = OIDOID;
 			valOid = LookupFuncName(funcname, 1, funcargtypes, true);
 			if (!OidIsValid(valOid))
 			{
-				valOid = ProcedureCreate(pltemplate->lanvalidator,
+				valOid = ProcedureCreate(pltemplate->tmplvalidator,
 										 PG_CATALOG_NAMESPACE,
 										 false,		/* replace */
 										 false,		/* returnsSet */
 										 VOIDOID,
 										 ClanguageId,
 										 F_FMGR_C_VALIDATOR,
-										 pltemplate->lanvalidator,
-										 pltemplate->lanlibrary,
+										 pltemplate->tmplvalidator,
+										 pltemplate->tmpllibrary,
 										 false,		/* isAgg */
 										 false,		/* security_definer */
 										 false,		/* isStrict */
@@ -162,7 +170,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 
 		/* ok, create it */
 		create_proc_lang(languageName, handlerOid, valOid,
-						 pltemplate->lantrusted);
+						 pltemplate->tmpltrusted);
 	}
 	else
 	{
@@ -170,17 +178,13 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 		 * No template, so use the provided information.  If there's
 		 * no handler clause, the user is trying to rely on a template
 		 * that we don't have, so complain accordingly.
-		 *
-		 * XXX In 8.2, replace the detail message with a hint to look in
-		 * pg_pltemplate.
 		 */
 		if (!stmt->plhandler)
 			ereport(ERROR,
 					(errcode(ERRCODE_UNDEFINED_OBJECT),
 					 errmsg("unsupported language \"%s\"",
 							languageName),
-					 errdetail("Supported languages are plpgsql, pltcl, pltclu, "
-							   "plperl, plperlu, and plpythonu.")));
+					 errhint("The supported languages are listed in the pg_pltemplate system catalog.")));
 
 		/*
 		 * Lookup the PL handler function and check that it is of the expected
@@ -291,41 +295,76 @@ create_proc_lang(const char *languageName,
 
 /*
  * Look to see if we have template information for the given language name.
- *
- * XXX for PG 8.1, the template info is hard-wired.  This is to be replaced
- * by a shared system catalog in 8.2.
- *
- * XXX if you add languages to this list, add them also to the errdetail
- * message above and the list in functioncmds.c.  Those hard-wired lists
- * should go away in 8.2, also.
  */
 static PLTemplate *
 find_language_template(const char *languageName)
 {
-	static PLTemplate templates[] = {
-		{ "plpgsql", true, "plpgsql_call_handler", "plpgsql_validator",
-		  "$libdir/plpgsql" },
-		{ "pltcl", true, "pltcl_call_handler", NULL,
-		  "$libdir/pltcl" },
-		{ "pltclu", false, "pltclu_call_handler", NULL,
-		  "$libdir/pltcl" },
-		{ "plperl", true, "plperl_call_handler", "plperl_validator",
-		  "$libdir/plperl" },
-		{ "plperlu", false, "plperl_call_handler", "plperl_validator",
-		  "$libdir/plperl" },
-		{ "plpythonu", false, "plpython_call_handler", NULL,
-		  "$libdir/plpython" },
-		{ NULL, false, NULL, NULL, NULL }
-	};
-
-	PLTemplate *ptr;
-
-	for (ptr = templates; ptr->lanname != NULL; ptr++)
+	PLTemplate *result;
+	Relation	rel;
+	SysScanDesc scan;
+	ScanKeyData key;
+	HeapTuple	tup;
+
+	rel = heap_open(PLTemplateRelationId, AccessShareLock);
+
+	ScanKeyInit(&key,
+				Anum_pg_pltemplate_tmplname,
+				BTEqualStrategyNumber, F_NAMEEQ,
+				NameGetDatum(languageName));
+	scan = systable_beginscan(rel, PLTemplateNameIndexId, true,
+							  SnapshotNow, 1, &key);
+
+	tup = systable_getnext(scan);
+	if (HeapTupleIsValid(tup))
 	{
-		if (strcmp(languageName, ptr->lanname) == 0)
-			return ptr;
+		Form_pg_pltemplate tmpl = (Form_pg_pltemplate) GETSTRUCT(tup);
+		Datum		datum;
+		bool		isnull;
+
+		result = (PLTemplate *) palloc0(sizeof(PLTemplate));
+		result->tmpltrusted = tmpl->tmpltrusted;
+
+		/* Remaining fields are variable-width so we need heap_getattr */
+		datum = heap_getattr(tup, Anum_pg_pltemplate_tmplhandler,
+							 RelationGetDescr(rel), &isnull);
+		if (!isnull)
+			result->tmplhandler =
+				DatumGetCString(DirectFunctionCall1(textout, datum));
+
+		datum = heap_getattr(tup, Anum_pg_pltemplate_tmplvalidator,
+							 RelationGetDescr(rel), &isnull);
+		if (!isnull)
+			result->tmplvalidator =
+				DatumGetCString(DirectFunctionCall1(textout, datum));
+
+		datum = heap_getattr(tup, Anum_pg_pltemplate_tmpllibrary,
+							 RelationGetDescr(rel), &isnull);
+		if (!isnull)
+			result->tmpllibrary =
+				DatumGetCString(DirectFunctionCall1(textout, datum));
+
+		/* Ignore template if handler or library info is missing */
+		if (!result->tmplhandler || !result->tmpllibrary)
+			result = NULL;
 	}
-	return NULL;
+	else
+		result = NULL;
+
+	systable_endscan(scan);
+
+	heap_close(rel, AccessShareLock);
+
+	return result;
+}
+
+
+/*
+ * This just returns TRUE if we have a valid template for a given language
+ */
+bool
+PLTemplateExists(const char *languageName)
+{
+	return (find_language_template(languageName) != NULL);
 }
 
 
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 3b3b792847d1b05fde27010b0efba33c981748fa..745975a2b563c86332a16c9b794abc51a3e80aa8 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.300 2005/08/15 23:00:14 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.301 2005/09/08 20:07:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*							yyyymmddN */
-#define CATALOG_VERSION_NO	200508152
+#define CATALOG_VERSION_NO	200509081
 
 #endif
diff --git a/src/include/catalog/indexing.h b/src/include/catalog/indexing.h
index 0c4c095e40a47156fce6dadd91a9a4565161f7a7..bb4ce868fb1b943ee5ee3151730991b7c0ad0361 100644
--- a/src/include/catalog/indexing.h
+++ b/src/include/catalog/indexing.h
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/indexing.h,v 1.90 2005/07/14 05:13:42 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/indexing.h,v 1.91 2005/09/08 20:07:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -93,6 +93,9 @@ DECLARE_UNIQUE_INDEX(pg_auth_members_role_member_index,2694, on pg_auth_members
 DECLARE_UNIQUE_INDEX(pg_auth_members_member_role_index,2695, on pg_auth_members using btree(member oid_ops, roleid oid_ops));
 #define AuthMemMemRoleIndexId	2695
 
+DECLARE_UNIQUE_INDEX(pg_autovacuum_vacrelid_index,1250, on pg_autovacuum using btree(vacrelid oid_ops));
+#define AutovacuumRelidIndexId	1250
+
 DECLARE_UNIQUE_INDEX(pg_cast_oid_index,2660, on pg_cast using btree(oid oid_ops));
 #define CastOidIndexId  2660
 DECLARE_UNIQUE_INDEX(pg_cast_source_target_index,2661, on pg_cast using btree(castsource oid_ops, casttarget oid_ops));
@@ -169,6 +172,9 @@ DECLARE_UNIQUE_INDEX(pg_operator_oid_index,2688, on pg_operator using btree(oid
 DECLARE_UNIQUE_INDEX(pg_operator_oprname_l_r_n_index,2689, on pg_operator using btree(oprname name_ops, oprleft oid_ops, oprright oid_ops, oprnamespace oid_ops));
 #define OperatorNameNspIndexId  2689
 
+DECLARE_UNIQUE_INDEX(pg_pltemplate_name_index,1137, on pg_pltemplate using btree(tmplname name_ops));
+#define PLTemplateNameIndexId  1137
+
 DECLARE_UNIQUE_INDEX(pg_proc_oid_index,2690, on pg_proc using btree(oid oid_ops));
 #define ProcedureOidIndexId  2690
 DECLARE_UNIQUE_INDEX(pg_proc_proname_args_nsp_index,2691, on pg_proc using btree(proname name_ops, proargtypes oidvector_ops, pronamespace oid_ops));
@@ -210,9 +216,6 @@ DECLARE_UNIQUE_INDEX(pg_type_oid_index,2703, on pg_type using btree(oid oid_ops)
 DECLARE_UNIQUE_INDEX(pg_type_typname_nsp_index,2704, on pg_type using btree(typname name_ops, typnamespace oid_ops));
 #define TypeNameNspIndexId  2704
 
-DECLARE_UNIQUE_INDEX(pg_autovacuum_vacrelid_index,1250, on pg_autovacuum using btree(vacrelid oid_ops));
-#define AutovacuumRelidIndexId	1250
-
 /* last step of initialization script: build the indexes declared above */
 BUILD_INDICES
 
diff --git a/src/include/catalog/pg_pltemplate.h b/src/include/catalog/pg_pltemplate.h
new file mode 100644
index 0000000000000000000000000000000000000000..3c4ff9f868a2cf55e6a2cc913c1612da0fb29348
--- /dev/null
+++ b/src/include/catalog/pg_pltemplate.h
@@ -0,0 +1,78 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_pltemplate.h
+ *	  definition of the system "PL template" relation (pg_pltemplate)
+ *	  along with the relation's initial contents.
+ *
+ *
+ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * $PostgreSQL: pgsql/src/include/catalog/pg_pltemplate.h,v 1.1 2005/09/08 20:07:42 tgl Exp $
+ *
+ * NOTES
+ *	  the genbki.sh script reads this file and generates .bki
+ *	  information from the DATA() statements.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_PLTEMPLATE_H
+#define PG_PLTEMPLATE_H
+
+/* ----------------
+ *		postgres.h contains the system type definitions and the
+ *		CATALOG(), BKI_BOOTSTRAP and DATA() sugar words so this file
+ *		can be read by both genbki.sh and the C compiler.
+ * ----------------
+ */
+
+/* ----------------
+ *		pg_pltemplate definition.  cpp turns this into
+ *		typedef struct FormData_pg_pltemplate
+ * ----------------
+ */
+#define PLTemplateRelationId	1136
+
+CATALOG(pg_pltemplate,1136) BKI_SHARED_RELATION BKI_WITHOUT_OIDS
+{
+	NameData	tmplname;		/* name of PL */
+	bool		tmpltrusted;	/* PL is trusted? */
+	text		tmplhandler;	/* name of call handler function */
+	text		tmplvalidator;	/* name of validator function, or NULL */
+	text		tmpllibrary;	/* path of shared library */
+	aclitem		tmplacl[1];		/* access privileges for template */
+} FormData_pg_pltemplate;
+
+/* ----------------
+ *		Form_pg_pltemplate corresponds to a pointer to a row with
+ *		the format of pg_pltemplate relation.
+ * ----------------
+ */
+typedef FormData_pg_pltemplate *Form_pg_pltemplate;
+
+/* ----------------
+ *		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
+
+
+/* ----------------
+ *		initial contents of 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_ ));
+
+#endif   /* PG_PLTEMPLATE_H */
diff --git a/src/include/commands/proclang.h b/src/include/commands/proclang.h
index a446773cd45d5829eb4ba357fa80fcbf74bb1c8f..7f38a8542ac2782cdece5905859b8e6687ca1476 100644
--- a/src/include/commands/proclang.h
+++ b/src/include/commands/proclang.h
@@ -15,5 +15,6 @@ 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 bool PLTemplateExists(const char *languageName);
 
 #endif   /* PROCLANG_H */
diff --git a/src/test/regress/expected/sanity_check.out b/src/test/regress/expected/sanity_check.out
index a6210a1705f112c806fe2ebf2c07d96dc93e7cec..250de98595e853742ce4a6c121a74cbdb1c8ff14 100644
--- a/src/test/regress/expected/sanity_check.out
+++ b/src/test/regress/expected/sanity_check.out
@@ -55,6 +55,7 @@ SELECT relname, relhasindex
  pg_namespace        | t
  pg_opclass          | t
  pg_operator         | t
+ pg_pltemplate       | t
  pg_proc             | t
  pg_rewrite          | t
  pg_shdepend         | t
@@ -67,7 +68,7 @@ SELECT relname, relhasindex
  shighway            | t
  tenk1               | t
  tenk2               | t
-(57 rows)
+(58 rows)
 
 --
 -- another sanity check: every system catalog that has OIDs should have