diff --git a/doc/src/sgml/ref/create_language.sgml b/doc/src/sgml/ref/create_language.sgml
index 457af69183236f3b1e9b4e702d97afdfbfc1259e..3f52578634e0c99d3c7530c0f2660def58dea145 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.48 2009/12/19 01:49:02 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/create_language.sgml,v 1.49 2010/02/23 22:51:42 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -21,8 +21,8 @@ PostgreSQL documentation
 
  <refsynopsisdiv>
 <synopsis>
-CREATE [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</replaceable>
-CREATE [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</replaceable>
+CREATE [ OR REPLACE ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</replaceable>
+CREATE [ OR REPLACE ] [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</replaceable>
     HANDLER <replaceable class="parameter">call_handler</replaceable> [ INLINE <replaceable class="parameter">inline_handler</replaceable> ] [ VALIDATOR <replaceable>valfunction</replaceable> ]
 </synopsis>
  </refsynopsisdiv>
@@ -31,8 +31,7 @@ CREATE [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</
   <title>Description</title>
 
   <para>
-   Using <command>CREATE LANGUAGE</command>, a
-   <productname>PostgreSQL</productname> user can register a new
+   <command>CREATE LANGUAGE</command> registers a new
    procedural language with a <productname>PostgreSQL</productname>
    database.  Subsequently, functions and trigger procedures can be
    defined in this new language.
@@ -40,9 +39,9 @@ CREATE [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</
 
   <para>
    <command>CREATE LANGUAGE</command> effectively associates the
-   language name with a call handler that is responsible for executing
+   language name with handler function(s) that are responsible for executing
    functions written in the language.  Refer to <xref linkend="plhandler">
-   for more information about language call handlers.
+   for more information about language handlers.
   </para>
 
   <para>
@@ -77,6 +76,23 @@ CREATE [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</
    The creator of a language becomes its owner and can later
    drop it, rename it, or assign it to a new owner.
   </para>
+
+  <para>
+   <command>CREATE OR REPLACE LANGUAGE</command> will either create a
+   new language, or replace an existing definition.  If the language
+   already exists, its parameters are updated according to the values
+   specified or taken from <structname>pg_pltemplate</structname>,
+   but the language's ownership and permissions settings do not change,
+   and any existing functions written in the language are assumed to still
+   be valid.  In addition to the normal privilege requirements for creating
+   a language, the user must be superuser or owner of the existing language.
+   The <literal>REPLACE</> case is mainly meant to be used to
+   ensure that the language exists.  If the language has a
+   <structname>pg_pltemplate</structname> entry then <literal>REPLACE</>
+   will not actually change anything about an existing definition, except in
+   the unusual case where the <structname>pg_pltemplate</structname> entry
+   has been modified since the language was created.
+  </para>
  </refsect1>
 
  <refsect1 id="sql-createlanguage-parameters">
@@ -88,7 +104,7 @@ CREATE [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</
 
      <listitem>
       <para>
-       <literal>TRUSTED</literal> specifies that the call handler for
+       <literal>TRUSTED</literal> specifies that
        the language is safe, that is, it does not offer an
        unprivileged user any functionality to bypass access
        restrictions. If this key word is omitted when registering the
diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c
index e51675ee11df3913b88b5d0fd16e5564990b05df..34f33670c3eb211b26209f249424735da5288328 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.89 2010/02/14 18:42:14 rhaas Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/proclang.c,v 1.90 2010/02/23 22:51:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -17,7 +17,6 @@
 #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"
@@ -49,7 +48,7 @@ typedef struct
 	char	   *tmpllibrary;	/* path of shared library */
 } PLTemplate;
 
-static void create_proc_lang(const char *languageName,
+static void create_proc_lang(const char *languageName, bool replace,
 				 Oid languageOwner, Oid handlerOid, Oid inlineOid,
 				 Oid valOid, bool trusted);
 static PLTemplate *find_language_template(const char *languageName);
@@ -73,16 +72,10 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 	Oid			funcargtypes[1];
 
 	/*
-	 * Translate the language name and check that this language doesn't
-	 * already exist
+	 * Translate the language name to lower case
 	 */
 	languageName = case_translate_language_name(stmt->plname);
 
-	if (SearchSysCacheExists1(LANGNAME, PointerGetDatum(languageName)))
-		ereport(ERROR,
-				(errcode(ERRCODE_DUPLICATE_OBJECT),
-				 errmsg("language \"%s\" already exists", languageName)));
-
 	/*
 	 * If we have template information for the language, ignore the supplied
 	 * parameters (if any) and use the template information.
@@ -232,7 +225,8 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 			valOid = InvalidOid;
 
 		/* ok, create it */
-		create_proc_lang(languageName, GetUserId(), handlerOid, inlineOid,
+		create_proc_lang(languageName, stmt->replace, GetUserId(),
+						 handlerOid, inlineOid,
 						 valOid, pltemplate->tmpltrusted);
 	}
 	else
@@ -306,7 +300,8 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 			valOid = InvalidOid;
 
 		/* ok, create it */
-		create_proc_lang(languageName, GetUserId(), handlerOid, inlineOid,
+		create_proc_lang(languageName, stmt->replace, GetUserId(),
+						 handlerOid, inlineOid,
 						 valOid, stmt->pltrusted);
 	}
 }
@@ -315,7 +310,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
  * Guts of language creation.
  */
 static void
-create_proc_lang(const char *languageName,
+create_proc_lang(const char *languageName, bool replace,
 				 Oid languageOwner, Oid handlerOid, Oid inlineOid,
 				 Oid valOid, bool trusted)
 {
@@ -323,19 +318,21 @@ create_proc_lang(const char *languageName,
 	TupleDesc	tupDesc;
 	Datum		values[Natts_pg_language];
 	bool		nulls[Natts_pg_language];
+	bool		replaces[Natts_pg_language];
 	NameData	langname;
+	HeapTuple	oldtup;
 	HeapTuple	tup;
+	bool		is_update;
 	ObjectAddress myself,
 				referenced;
 
-	/*
-	 * Insert the new language into pg_language
-	 */
 	rel = heap_open(LanguageRelationId, RowExclusiveLock);
-	tupDesc = rel->rd_att;
+	tupDesc = RelationGetDescr(rel);
 
+	/* Prepare data to be inserted */
 	memset(values, 0, sizeof(values));
 	memset(nulls, false, sizeof(nulls));
+	memset(replaces, true, sizeof(replaces));
 
 	namestrcpy(&langname, languageName);
 	values[Anum_pg_language_lanname - 1] = NameGetDatum(&langname);
@@ -347,24 +344,62 @@ create_proc_lang(const char *languageName,
 	values[Anum_pg_language_lanvalidator - 1] = ObjectIdGetDatum(valOid);
 	nulls[Anum_pg_language_lanacl - 1] = true;
 
-	tup = heap_form_tuple(tupDesc, values, nulls);
+	/* Check for pre-existing definition */
+	oldtup = SearchSysCache1(LANGNAME, PointerGetDatum(languageName));
 
-	simple_heap_insert(rel, tup);
+	if (HeapTupleIsValid(oldtup))
+	{
+		/* There is one; okay to replace it? */
+		if (!replace)
+			ereport(ERROR,
+					(errcode(ERRCODE_DUPLICATE_OBJECT),
+					 errmsg("language \"%s\" already exists", languageName)));
+		if (!pg_language_ownercheck(HeapTupleGetOid(oldtup), languageOwner))
+			aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_LANGUAGE,
+						   languageName);
 
+		/*
+		 * Do not change existing ownership or permissions.  Note
+		 * dependency-update code below has to agree with this decision.
+		 */
+		replaces[Anum_pg_language_lanowner - 1] = false;
+		replaces[Anum_pg_language_lanacl - 1] = false;
+
+		/* Okay, do it... */
+		tup = heap_modify_tuple(oldtup, tupDesc, values, nulls, replaces);
+		simple_heap_update(rel, &tup->t_self, tup);
+
+		ReleaseSysCache(oldtup);
+		is_update = true;
+	}
+	else
+	{
+		/* Creating a new language */
+		tup = heap_form_tuple(tupDesc, values, nulls);
+		simple_heap_insert(rel, tup);
+		is_update = false;
+	}
+
+	/* Need to update indexes for either the insert or update case */
 	CatalogUpdateIndexes(rel, tup);
 
 	/*
-	 * Create dependencies for language
+	 * Create dependencies for the new language.  If we are updating an
+	 * existing language, first delete any existing pg_depend entries.
+	 * (However, since we are not changing ownership or permissions, the
+	 * shared dependencies do *not* need to change, and we leave them alone.)
 	 */
 	myself.classId = LanguageRelationId;
 	myself.objectId = HeapTupleGetOid(tup);
 	myself.objectSubId = 0;
 
+	if (is_update)
+		deleteDependencyRecordsFor(myself.classId, myself.objectId);
+
 	/* dependency on owner of language */
-	referenced.classId = AuthIdRelationId;
-	referenced.objectId = languageOwner;
-	referenced.objectSubId = 0;
-	recordSharedDependencyOn(&myself, &referenced, SHARED_DEPENDENCY_OWNER);
+	if (!is_update)
+		recordDependencyOnOwner(myself.classId, myself.objectId,
+								languageOwner);
 
 	/* dependency on the PL handler function */
 	referenced.classId = ProcedureRelationId;
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 371d1f245eb4a3a7a8a3ea4ffe182c5629e8909a..22d24ef21a5817bd06a99486af208a54f38579f0 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.462 2010/02/16 22:34:43 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.463 2010/02/23 22:51:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -3237,6 +3237,7 @@ _copyCreatePLangStmt(CreatePLangStmt *from)
 {
 	CreatePLangStmt *newnode = makeNode(CreatePLangStmt);
 
+	COPY_SCALAR_FIELD(replace);
 	COPY_STRING_FIELD(plname);
 	COPY_NODE_FIELD(plhandler);
 	COPY_NODE_FIELD(plinline);
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 7dfc1969f5da87184b358046c4d9c36c964447eb..9a05bcc1c0f1515e4652ac5c47a6345711cb3deb 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -22,7 +22,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.383 2010/02/16 22:34:43 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.384 2010/02/23 22:51:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1710,6 +1710,7 @@ _equalDropPropertyStmt(DropPropertyStmt *a, DropPropertyStmt *b)
 static bool
 _equalCreatePLangStmt(CreatePLangStmt *a, CreatePLangStmt *b)
 {
+	COMPARE_SCALAR_FIELD(replace);
 	COMPARE_STRING_FIELD(plname);
 	COMPARE_NODE_FIELD(plhandler);
 	COMPARE_NODE_FIELD(plinline);
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 94b28bf3d89b2f3a7a4ff75534ed648fc0098ce5..368586a95e6b53504932823b085faff3ea57a8bb 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.710 2010/02/17 04:19:39 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.711 2010/02/23 22:51:42 tgl Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -2882,16 +2882,17 @@ NumericOnly:
 /*****************************************************************************
  *
  *		QUERIES :
- *				CREATE PROCEDURAL LANGUAGE ...
- *				DROP PROCEDURAL LANGUAGE ...
+ *				CREATE [OR REPLACE] [TRUSTED] [PROCEDURAL] LANGUAGE ...
+ *				DROP [PROCEDURAL] LANGUAGE ...
  *
  *****************************************************************************/
 
 CreatePLangStmt:
-			CREATE opt_trusted opt_procedural LANGUAGE ColId_or_Sconst
+			CREATE opt_or_replace opt_trusted opt_procedural LANGUAGE ColId_or_Sconst
 			{
 				CreatePLangStmt *n = makeNode(CreatePLangStmt);
-				n->plname = $5;
+				n->replace = $2;
+				n->plname = $6;
 				/* parameters are all to be supplied by system */
 				n->plhandler = NIL;
 				n->plinline = NIL;
@@ -2899,15 +2900,16 @@ CreatePLangStmt:
 				n->pltrusted = false;
 				$$ = (Node *)n;
 			}
-			| CREATE opt_trusted opt_procedural LANGUAGE ColId_or_Sconst
+			| CREATE opt_or_replace opt_trusted opt_procedural LANGUAGE ColId_or_Sconst
 			  HANDLER handler_name opt_inline_handler opt_validator
 			{
 				CreatePLangStmt *n = makeNode(CreatePLangStmt);
-				n->plname = $5;
-				n->plhandler = $7;
-				n->plinline = $8;
-				n->plvalidator = $9;
-				n->pltrusted = $2;
+				n->replace = $2;
+				n->plname = $6;
+				n->plhandler = $8;
+				n->plinline = $9;
+				n->plvalidator = $10;
+				n->pltrusted = $3;
 				$$ = (Node *)n;
 			}
 		;
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index ca229c8e23d79155a58dfb079f7a8438963e0d50..5a5c040c2518ed31ca9cfbce20d731721961d346 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -13,7 +13,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.430 2010/02/16 22:34:57 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.431 2010/02/23 22:51:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1623,6 +1623,7 @@ typedef struct CreateTrigStmt
 typedef struct CreatePLangStmt
 {
 	NodeTag		type;
+	bool		replace;		/* T => replace if already exists */
 	char	   *plname;			/* PL name */
 	List	   *plhandler;		/* PL call handler function (qual. name) */
 	List	   *plinline;		/* optional inline function (qual. name) */