diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 3f7fdf16b45e377848d1488a172fed673c76d8bb..dd103573a5d68c2c9f6df2ef106fac6e5ee6a2b4 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.206 2009/08/10 22:13:50 alvherre Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.207 2009/09/22 23:43:37 tgl Exp $ -->
 <!--
  Documentation of the system catalogs, directed toward PostgreSQL developers
  -->
@@ -2941,6 +2941,18 @@
       </entry>
      </row>
 
+     <row>
+      <entry><structfield>laninline</structfield></entry>
+      <entry><type>oid</type></entry>
+      <entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry>
+      <entry>
+       This references a function that is responsible for executing
+       <quote>inline</> anonymous code blocks
+       (<xref linkend="sql-do" endterm="sql-do-title"> blocks).
+       Zero if inline blocks are not supported
+      </entry>
+     </row>
+
      <row>
       <entry><structfield>lanvalidator</structfield></entry>
       <entry><type>oid</type></entry>
@@ -3547,6 +3559,12 @@
       <entry>Name of call handler function</entry>
      </row>
 
+     <row>
+      <entry><structfield>tmplinline</structfield></entry>
+      <entry><type>text</type></entry>
+      <entry>Name of anonymous-block handler function, or NULL if none</entry>
+     </row>
+
      <row>
       <entry><structfield>tmplvalidator</structfield></entry>
       <entry><type>text</type></entry>
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index fa2a12feab1987fd4a0a3066ee4415d2c9a6c7b0..ee28bbb107902560c26ced80fd8a946f07c7d492 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.228 2009/09/13 19:52:29 petere Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.229 2009/09/22 23:43:37 tgl Exp $ -->
 
 <chapter Id="runtime-config">
   <title>Server Configuration</title>
@@ -3964,6 +3964,21 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv;
       </listitem>
      </varlistentry>
 
+     <varlistentry id="guc-default-do-language" xreflabel="default_do_language">
+      <term><varname>default_do_language</varname> (<type>string</type>)</term>
+      <indexterm>
+       <primary><varname>default_do_language</> configuration parameter</primary>
+      </indexterm>
+      <listitem>
+       <para>
+        This parameter specifies the language to use when the
+        <literal>LANGUAGE</> option is omitted in a
+        <xref linkend="sql-do" endterm="sql-do-title"> statement.
+        The default is <literal>plpgsql</literal>.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry id="guc-default-transaction-isolation" xreflabel="default_transaction_isolation">
       <indexterm>
        <primary>transaction isolation level</primary>
diff --git a/doc/src/sgml/keywords.sgml b/doc/src/sgml/keywords.sgml
index cb167ce10b4e3c48c529b3e025cfd04990ec8250..8bfede77d6fe63311de304f75d6aed00e9c26261 100644
--- a/doc/src/sgml/keywords.sgml
+++ b/doc/src/sgml/keywords.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/keywords.sgml,v 2.25 2009/04/06 15:01:36 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/keywords.sgml,v 2.26 2009/09/22 23:43:37 tgl Exp $ -->
 
 <appendix id="sql-keywords-appendix">
  <title><acronym>SQL</acronym> Key Words</title>
@@ -2375,6 +2375,14 @@
     <entry>reserved</entry>
     <entry>reserved</entry>
    </row>
+   <row>
+    <entry><token>INLINE</token></entry>
+    <entry>non-reserved</entry>
+    <entry></entry>
+    <entry></entry>
+    <entry></entry>
+    <entry></entry>
+   </row>
    <row>
     <entry><token>INNER</token></entry>
     <entry>reserved (can be function or type)</entry>
@@ -2575,14 +2583,6 @@
     <entry></entry>
     <entry></entry>
    </row>
-   <row>
-    <entry><token>LANCOMPILER</token></entry>
-    <entry>non-reserved</entry>
-    <entry></entry>
-    <entry></entry>
-    <entry></entry>
-    <entry></entry>
-   </row>
    <row>
     <entry><token>LANGUAGE</token></entry>
     <entry>non-reserved</entry>
diff --git a/doc/src/sgml/ref/allfiles.sgml b/doc/src/sgml/ref/allfiles.sgml
index 6c20b623c49ad8f866edab0b3256de0b736fd639..845033b6b6696b2bfe11e60f93c99c8dcda35974 100644
--- a/doc/src/sgml/ref/allfiles.sgml
+++ b/doc/src/sgml/ref/allfiles.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/allfiles.sgml,v 1.74 2008/12/19 16:25:16 petere Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/allfiles.sgml,v 1.75 2009/09/22 23:43:37 tgl Exp $
 PostgreSQL documentation
 Complete list of usable sgml source files in this directory.
 -->
@@ -77,6 +77,7 @@ Complete list of usable sgml source files in this directory.
 <!entity declare            system "declare.sgml">
 <!entity delete             system "delete.sgml">
 <!entity discard            system "discard.sgml">
+<!entity do                 system "do.sgml">
 <!entity dropAggregate      system "drop_aggregate.sgml">
 <!entity dropCast           system "drop_cast.sgml">
 <!entity dropConversion     system "drop_conversion.sgml">
diff --git a/doc/src/sgml/ref/create_language.sgml b/doc/src/sgml/ref/create_language.sgml
index ae02995e37fea41c6bdda02a85a006d180409a89..4c0463ddec1f251eafb1f9a70fe8798de94c5d00 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.45 2008/11/14 10:22:46 petere Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/create_language.sgml,v 1.46 2009/09/22 23:43:37 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -23,7 +23,7 @@ PostgreSQL documentation
 <synopsis>
 CREATE [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</replaceable>
 CREATE [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</replaceable>
-    HANDLER <replaceable class="parameter">call_handler</replaceable> [ VALIDATOR <replaceable>valfunction</replaceable> ]
+    HANDLER <replaceable class="parameter">call_handler</replaceable> [ INLINE <replaceable class="parameter">inline_handler</replaceable> ] [ VALIDATOR <replaceable>valfunction</replaceable> ]
 </synopsis>
  </refsynopsisdiv>
 
@@ -133,7 +133,7 @@ CREATE [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</
       <para>
        <replaceable class="parameter">call_handler</replaceable> is
        the name of a previously registered function that will be
-       called to execute the procedural language functions.  The call
+       called to execute the procedural language's functions.  The call
        handler for a procedural language must be written in a compiled
        language such as C with version 1 call convention and
        registered with <productname>PostgreSQL</productname> as a
@@ -144,6 +144,27 @@ CREATE [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</
      </listitem>
     </varlistentry>
 
+    <varlistentry>
+     <term><literal>INLINE</literal> <replaceable class="parameter">inline_handler</replaceable></term>
+
+     <listitem>
+      <para>
+       <replaceable class="parameter">inline_handler</replaceable> is the
+       name of a previously registered function that will be called
+       to execute an anonymous code block
+       (<xref linkend="sql-do" endterm="sql-do-title"> command)
+       in this language.
+       If no <replaceable class="parameter">inline_handler</replaceable>
+       function is specified, the language does not support anonymous code
+       blocks.
+       The handler function must take one argument of
+       type <type>internal</type>, which will be the <command>DO</> command's
+       internal representation, and it will typically return
+       <type>void</>.  The return value of the handler is ignored.
+      </para>
+     </listitem>
+    </varlistentry>
+
     <varlistentry>
      <term><literal>VALIDATOR</literal> <replaceable class="parameter">valfunction</replaceable></term>
 
@@ -216,7 +237,8 @@ CREATE [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</
   </para>
 
   <para>
-   The call handler function and the validator function (if any)
+   The call handler function, the inline handler function (if any),
+   and the validator function (if any)
    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;
@@ -230,7 +252,7 @@ CREATE [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">name</
    In <productname>PostgreSQL</productname> versions before 7.3, it was
    necessary to declare handler functions as returning the placeholder
    type <type>opaque</>, rather than <type>language_handler</>.
-   To support loading 
+   To support loading
    of old dump files, <command>CREATE LANGUAGE</> will accept a function
    declared as returning <type>opaque</>, but it will issue a notice and
    change the function's declared return type to <type>language_handler</>.
diff --git a/doc/src/sgml/ref/do.sgml b/doc/src/sgml/ref/do.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..2fb538066303d82e5ccc103afdfd40814e3db453
--- /dev/null
+++ b/doc/src/sgml/ref/do.sgml
@@ -0,0 +1,122 @@
+<!--
+$PostgreSQL: pgsql/doc/src/sgml/ref/do.sgml,v 1.1 2009/09/22 23:43:37 tgl Exp $
+PostgreSQL documentation
+-->
+
+<refentry id="SQL-DO">
+ <refmeta>
+  <refentrytitle id="sql-do-title">DO</refentrytitle>
+  <manvolnum>7</manvolnum>
+  <refmiscinfo>SQL - Language Statements</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+  <refname>DO</refname>
+  <refpurpose>execute an anonymous code block</refpurpose>
+ </refnamediv>
+
+ <indexterm zone="sql-do">
+  <primary>DO</primary>
+ </indexterm>
+
+ <indexterm zone="sql-do">
+  <primary>anonymous code blocks</primary>
+ </indexterm>
+
+ <refsynopsisdiv>
+<synopsis>
+DO <replaceable class="PARAMETER">code</replaceable> [ LANGUAGE <replaceable class="PARAMETER">lang_name</replaceable> ]
+</synopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+  <title>Description</title>
+
+  <para>
+   <command>DO</command> executes an anonymous code block, or in other
+   words a transient anonymous function in a procedural language.
+  </para>
+
+  <para>
+   The code block is treated as though it were the body of a function
+   with no parameters, returning <type>void</>.  It is parsed and
+   executed a single time.
+  </para>
+ </refsect1>
+
+ <refsect1>
+  <title>Parameters</title>
+
+  <variablelist>
+   <varlistentry>
+    <term><replaceable class="PARAMETER">code</replaceable></term>
+    <listitem>
+     <para>
+      The procedural language code to be executed.  This must be specified
+      as a string literal, just as in <command>CREATE FUNCTION</>.
+      Use of a dollar-quoted literal is recommended.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><replaceable class="PARAMETER">lang_name</replaceable></term>
+    <listitem>
+     <para>
+      The name of the procedural language the code is written in.
+      If omitted, the default is determined by the runtime parameter
+      <xref linkend="guc-default-do-language">.
+     </para>
+    </listitem>
+   </varlistentry>
+  </variablelist>
+ </refsect1>
+
+ <refsect1>
+  <title>Notes</title>
+
+  <para>
+   The procedural language to be used must already have been installed
+   into the current database by means of <command>CREATE LANGUAGE</>.
+  </para>
+
+  <para>
+   The user must have <literal>USAGE</> privilege for the procedural
+   language, or must be a superuser if the language is untrusted.
+   This is the same privilege requirement as for creating a function
+   in the language.
+  </para>
+ </refsect1>
+
+ <refsect1 id="sql-do-examples">
+  <title id="sql-do-examples-title">Examples</title>
+  <para>
+   Execute a simple PL/pgsql loop without needing to create a function:
+<programlisting>
+DO $$
+DECLARE r record;
+BEGIN
+    FOR r IN SELECT rtrim(roomno) AS roomno, comment FROM Room ORDER BY roomno
+    LOOP
+        RAISE NOTICE '%, %', r.roomno, r.comment;
+    END LOOP;
+END$$;
+</programlisting>
+  </para>
+ </refsect1>
+ <refsect1>
+  <title>Compatibility</title>
+
+  <para>
+   There is no <command>DO</command> statement in the SQL standard.
+  </para>
+ </refsect1>
+
+ <refsect1>
+  <title>See Also</title>
+
+  <simplelist type="inline">
+   <member><xref linkend="sql-createlanguage" endterm="sql-createlanguage-title"></member>
+  </simplelist>
+ </refsect1>
+</refentry>
diff --git a/doc/src/sgml/reference.sgml b/doc/src/sgml/reference.sgml
index d3a862959d900c224ecd0207fcc86f652cfe1974..48f8040541dfda098d658bac66b54f719e4dce2b 100644
--- a/doc/src/sgml/reference.sgml
+++ b/doc/src/sgml/reference.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/reference.sgml,v 1.67 2008/12/19 16:25:16 petere Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/reference.sgml,v 1.68 2009/09/22 23:43:37 tgl Exp $ -->
 
 <part id="reference">
  <title>Reference</title>
@@ -105,6 +105,7 @@
    &declare;
    &delete;
    &discard;
+   &do;
    &dropAggregate;
    &dropCast;
    &dropConversion;
diff --git a/doc/src/sgml/xplang.sgml b/doc/src/sgml/xplang.sgml
index 9882d835e35f6c345b2078f5824dc85906746d4f..b48b78f95ba6ae27b766afda31174ada22b03378 100644
--- a/doc/src/sgml/xplang.sgml
+++ b/doc/src/sgml/xplang.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/xplang.sgml,v 1.34 2007/02/01 00:28:18 momjian Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/xplang.sgml,v 1.35 2009/09/22 23:43:37 tgl Exp $ -->
 
  <chapter id="xplang">
   <title id="xplang-title">Procedural Languages</title>
@@ -75,9 +75,9 @@ createlang plpgsql template1
     </title>
 
     <para>
-     A procedural language is installed in a database in four steps,
+     A procedural language is installed in a database in five steps,
      which must be carried out by a database superuser.  (For languages
-     known to <command>CREATE LANGUAGE</>, the second and third steps
+     known to <command>CREATE LANGUAGE</>, the second through fourth steps
      can be omitted, because they will be carried out automatically
      if needed.)
     </para>
@@ -110,12 +110,28 @@ CREATE FUNCTION <replaceable>handler_function_name</replaceable>()
     </step>
 
     <step performance="optional" id="xplang-install-cr3">
+     <para>
+      Optionally, the language handler can provide an <quote>inline</>
+      handler function that executes anonymous code blocks
+      (<xref linkend="sql-do" endterm="sql-do-title"> commands)
+      written in this language.  If an inline handler function
+      is provided by the language, declare it with a command like
+<synopsis>
+CREATE FUNCTION <replaceable>inline_function_name</replaceable>(internal)
+    RETURNS void
+    AS '<replaceable>path-to-shared-object</replaceable>'
+    LANGUAGE C;
+</synopsis>
+     </para>
+    </step>
+
+    <step performance="optional" id="xplang-install-cr4">
      <para>
       Optionally, the language handler can provide a <quote>validator</>
       function that checks a function definition for correctness without
       actually executing it.  The validator function is called by
       <command>CREATE FUNCTION</> if it exists.  If a validator function
-      is provided by the handler, declare it with a command like
+      is provided by the language, declare it with a command like
 <synopsis>
 CREATE FUNCTION <replaceable>validator_function_name</replaceable>(oid)
     RETURNS void
@@ -125,12 +141,13 @@ CREATE FUNCTION <replaceable>validator_function_name</replaceable>(oid)
      </para>
     </step>
 
-    <step performance="required" id="xplang-install-cr4">
+    <step performance="required" id="xplang-install-cr5">
      <para>
       The PL must be declared with the command
 <synopsis>
 CREATE <optional>TRUSTED</optional> <optional>PROCEDURAL</optional> LANGUAGE <replaceable>language-name</replaceable>
     HANDLER <replaceable>handler_function_name</replaceable>
+    <optional>INLINE <replaceable>inline_function_name</replaceable></optional>
     <optional>VALIDATOR <replaceable>validator_function_name</replaceable></optional> ;
 </synopsis>
       The optional key word <literal>TRUSTED</literal> specifies that
@@ -173,10 +190,13 @@ CREATE FUNCTION plpgsql_call_handler() RETURNS language_handler AS
      </para>
 
      <para>
-      <application>PL/pgSQL</application> has a validator function,
-      so we declare that too:
+      <application>PL/pgSQL</application> has an inline handler function
+      and a validator function, so we declare those too:
 
 <programlisting>
+CREATE FUNCTION plpgsql_inline_handler(internal) RETURNS void AS
+    '$libdir/plpgsql' LANGUAGE C;
+
 CREATE FUNCTION plpgsql_validator(oid) RETURNS void AS
     '$libdir/plpgsql' LANGUAGE C;
 </programlisting>
@@ -187,6 +207,7 @@ CREATE FUNCTION plpgsql_validator(oid) RETURNS void AS
 <programlisting>
 CREATE TRUSTED PROCEDURAL LANGUAGE plpgsql
     HANDLER plpgsql_call_handler
+    INLINE plpgsql_inline_handler
     VALIDATOR plpgsql_validator;
 </programlisting>
       then defines that the previously declared functions
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index 64920f5d2a89c7504ee375ad6e153f2d31836cba..41c6d1e2fb16314f8b8ed7d04dbce3e754dc0715 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.164 2009/06/11 14:48:55 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.165 2009/09/22 23:43:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -782,11 +782,12 @@ sql_function_parse_error_callback(void *arg)
 
 /*
  * Adjust a syntax error occurring inside the function body of a CREATE
- * FUNCTION command.  This can be used by any function validator, not only
- * for SQL-language functions.	It is assumed that the syntax error position
- * is initially relative to the function body string (as passed in).  If
- * possible, we adjust the position to reference the original CREATE command;
- * if we can't manage that, we set up an "internal query" syntax error instead.
+ * FUNCTION or DO command.  This can be used by any function validator or
+ * anonymous-block handler, not only for SQL-language functions.
+ * It is assumed that the syntax error position is initially relative to the
+ * function body string (as passed in).  If possible, we adjust the position
+ * to reference the original command text; if we can't manage that, we set
+ * up an "internal query" syntax error instead.
  *
  * Returns true if a syntax error was processed, false if not.
  */
@@ -843,8 +844,8 @@ function_parse_error_transpose(const char *prosrc)
 
 /*
  * Try to locate the string literal containing the function body in the
- * given text of the CREATE FUNCTION command.  If successful, return the
- * character (not byte) index within the command corresponding to the
+ * given text of the CREATE FUNCTION or DO command.  If successful, return
+ * the character (not byte) index within the command corresponding to the
  * given character index within the literal.  If not successful, return 0.
  */
 static int
@@ -852,7 +853,7 @@ match_prosrc_to_query(const char *prosrc, const char *queryText,
 					  int cursorpos)
 {
 	/*
-	 * Rather than fully parsing the CREATE FUNCTION command, we just scan the
+	 * Rather than fully parsing the original command, we just scan the
 	 * command looking for $prosrc$ or 'prosrc'.  This could be fooled (though
 	 * not in any very probable scenarios), so fail if we find more than one
 	 * match.
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 2151fd94f09d0e4a270c8654028881c2c1515c1d..cf206b3f090fee193cd2fd2d943a02f4d09d386c 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.110 2009/06/11 14:48:55 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.111 2009/09/22 23:43:37 tgl Exp $
  *
  * DESCRIPTION
  *	  These routines take the parse tree and pick out the
@@ -1915,3 +1915,110 @@ AlterFunctionNamespace(List *name, List *argtypes, bool isagg,
 
 	heap_close(procRel, RowExclusiveLock);
 }
+
+
+/*
+ * ExecuteDoStmt
+ *		Execute inline procedural-language code
+ */
+void
+ExecuteDoStmt(DoStmt *stmt)
+{
+	InlineCodeBlock *codeblock = makeNode(InlineCodeBlock);
+	ListCell   *arg;
+	DefElem    *as_item = NULL;
+	DefElem    *language_item = NULL;
+	char	   *language;
+	char	   *languageName;
+	Oid			laninline;
+	HeapTuple	languageTuple;
+	Form_pg_language languageStruct;
+
+	/* Process options we got from gram.y */
+	foreach(arg, stmt->args)
+	{
+		DefElem    *defel = (DefElem *) lfirst(arg);
+
+		if (strcmp(defel->defname, "as") == 0)
+		{
+			if (as_item)
+				ereport(ERROR,
+						(errcode(ERRCODE_SYNTAX_ERROR),
+						 errmsg("conflicting or redundant options")));
+			as_item = defel;
+		}
+		else if (strcmp(defel->defname, "language") == 0)
+		{
+			if (language_item)
+				ereport(ERROR,
+						(errcode(ERRCODE_SYNTAX_ERROR),
+						 errmsg("conflicting or redundant options")));
+			language_item = defel;
+		}
+		else
+			elog(ERROR, "option \"%s\" not recognized",
+				 defel->defname);
+	}
+
+	if (as_item)
+		codeblock->source_text = strVal(as_item->arg);
+	else
+		ereport(ERROR,
+				(errcode(ERRCODE_SYNTAX_ERROR),
+				 errmsg("no inline code specified")));
+
+	/* if LANGUAGE option wasn't specified, use the default language */
+	if (language_item)
+		language = strVal(language_item->arg);
+	else
+		language = default_do_language;
+
+	/* Convert language name to canonical case */
+	languageName = case_translate_language_name(language);
+
+	/* Look up the language and validate permissions */
+	languageTuple = SearchSysCache(LANGNAME,
+								   PointerGetDatum(languageName),
+								   0, 0, 0);
+	if (!HeapTupleIsValid(languageTuple))
+		ereport(ERROR,
+				(errcode(ERRCODE_UNDEFINED_OBJECT),
+				 errmsg("language \"%s\" does not exist", languageName),
+				 (PLTemplateExists(languageName) ?
+				  errhint("Use CREATE LANGUAGE to load the language into the database.") : 0)));
+
+	codeblock->langOid = HeapTupleGetOid(languageTuple);
+	languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
+
+	if (languageStruct->lanpltrusted)
+	{
+		/* if trusted language, need USAGE privilege */
+		AclResult	aclresult;
+
+		aclresult = pg_language_aclcheck(codeblock->langOid, GetUserId(),
+										 ACL_USAGE);
+		if (aclresult != ACLCHECK_OK)
+			aclcheck_error(aclresult, ACL_KIND_LANGUAGE,
+						   NameStr(languageStruct->lanname));
+	}
+	else
+	{
+		/* if untrusted language, must be superuser */
+		if (!superuser())
+			aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_LANGUAGE,
+						   NameStr(languageStruct->lanname));
+	}
+
+	/* get the handler function's OID */
+	laninline = languageStruct->laninline;
+	if (!OidIsValid(laninline))
+		ereport(ERROR,
+				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+				 errmsg("language \"%s\" does not support inline code execution",
+						NameStr(languageStruct->lanname))));
+
+	ReleaseSysCache(languageTuple);
+
+	/* execute the inline handler */
+	OidFunctionCall1(laninline, PointerGetDatum(codeblock));
+}
diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c
index 27af379d7e154ba93b8ddd74ac5c21c00f2d621c..2a5bcd6363de918ad6028e346b6e848d4433bf64 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.86 2009/07/12 17:12:33 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/proclang.c,v 1.87 2009/09/22 23:43:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -44,12 +44,14 @@ typedef struct
 	bool		tmpltrusted;	/* trusted? */
 	bool		tmpldbacreate;	/* db owner allowed to create? */
 	char	   *tmplhandler;	/* name of handler function */
+	char	   *tmplinline;		/* name of anonymous-block handler, or NULL */
 	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);
+				 Oid languageOwner, Oid handlerOid, Oid inlineOid,
+				 Oid valOid, bool trusted);
 static PLTemplate *find_language_template(const char *languageName);
 static void AlterLanguageOwner_internal(HeapTuple tup, Relation rel,
 							Oid newOwnerId);
@@ -65,6 +67,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 	char	   *languageName;
 	PLTemplate *pltemplate;
 	Oid			handlerOid,
+				inlineOid,
 				valOid;
 	Oid			funcrettype;
 	Oid			funcargtypes[1];
@@ -154,6 +157,44 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 										 0);
 		}
 
+		/*
+		 * Likewise for the anonymous block handler, if required;
+		 * but we don't care about its return type.
+		 */
+		if (pltemplate->tmplinline)
+		{
+			funcname = SystemFuncName(pltemplate->tmplinline);
+			funcargtypes[0] = INTERNALOID;
+			inlineOid = LookupFuncName(funcname, 1, funcargtypes, true);
+			if (!OidIsValid(inlineOid))
+			{
+				inlineOid = ProcedureCreate(pltemplate->tmplinline,
+											PG_CATALOG_NAMESPACE,
+											false, /* replace */
+											false, /* returnsSet */
+											VOIDOID,
+											ClanguageId,
+											F_FMGR_C_VALIDATOR,
+											pltemplate->tmplinline,
+											pltemplate->tmpllibrary,
+											false, /* isAgg */
+											false, /* isWindowFunc */
+											false, /* security_definer */
+											true, /* isStrict */
+											PROVOLATILE_VOLATILE,
+											buildoidvector(funcargtypes, 1),
+											PointerGetDatum(NULL),
+											PointerGetDatum(NULL),
+											PointerGetDatum(NULL),
+											NIL,
+											PointerGetDatum(NULL),
+											1,
+											0);
+			}
+		}
+		else
+			inlineOid = InvalidOid;
+
 		/*
 		 * Likewise for the validator, if required; but we don't care about
 		 * its return type.
@@ -177,7 +218,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 										 false, /* isAgg */
 										 false, /* isWindowFunc */
 										 false, /* security_definer */
-										 false, /* isStrict */
+										 true, /* isStrict */
 										 PROVOLATILE_VOLATILE,
 										 buildoidvector(funcargtypes, 1),
 										 PointerGetDatum(NULL),
@@ -193,8 +234,8 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 			valOid = InvalidOid;
 
 		/* ok, create it */
-		create_proc_lang(languageName, GetUserId(), handlerOid, valOid,
-						 pltemplate->tmpltrusted);
+		create_proc_lang(languageName, GetUserId(), handlerOid, inlineOid,
+						 valOid, pltemplate->tmpltrusted);
 	}
 	else
 	{
@@ -246,6 +287,16 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 						 NameListToString(stmt->plhandler))));
 		}
 
+		/* validate the inline function */
+		if (stmt->plinline)
+		{
+			funcargtypes[0] = INTERNALOID;
+			inlineOid = LookupFuncName(stmt->plinline, 1, funcargtypes, false);
+			/* return value is ignored, so we don't check the type */
+		}
+		else
+			inlineOid = InvalidOid;
+
 		/* validate the validator function */
 		if (stmt->plvalidator)
 		{
@@ -257,8 +308,8 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 			valOid = InvalidOid;
 
 		/* ok, create it */
-		create_proc_lang(languageName, GetUserId(), handlerOid, valOid,
-						 stmt->pltrusted);
+		create_proc_lang(languageName, GetUserId(), handlerOid, inlineOid,
+						 valOid, stmt->pltrusted);
 	}
 }
 
@@ -267,7 +318,8 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
  */
 static void
 create_proc_lang(const char *languageName,
-				 Oid languageOwner, Oid handlerOid, Oid valOid, bool trusted)
+				 Oid languageOwner, Oid handlerOid, Oid inlineOid,
+				 Oid valOid, bool trusted)
 {
 	Relation	rel;
 	TupleDesc	tupDesc;
@@ -293,6 +345,7 @@ create_proc_lang(const char *languageName,
 	values[Anum_pg_language_lanispl - 1] = BoolGetDatum(true);
 	values[Anum_pg_language_lanpltrusted - 1] = BoolGetDatum(trusted);
 	values[Anum_pg_language_lanplcallfoid - 1] = ObjectIdGetDatum(handlerOid);
+	values[Anum_pg_language_laninline - 1] = ObjectIdGetDatum(inlineOid);
 	values[Anum_pg_language_lanvalidator - 1] = ObjectIdGetDatum(valOid);
 	nulls[Anum_pg_language_lanacl - 1] = true;
 
@@ -321,6 +374,15 @@ create_proc_lang(const char *languageName,
 	referenced.objectSubId = 0;
 	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
 
+	/* dependency on the inline handler function, if any */
+	if (OidIsValid(inlineOid))
+	{
+		referenced.classId = ProcedureRelationId;
+		referenced.objectId = inlineOid;
+		referenced.objectSubId = 0;
+		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+	}
+
 	/* dependency on the validator function, if any */
 	if (OidIsValid(valOid))
 	{
@@ -371,6 +433,11 @@ find_language_template(const char *languageName)
 		if (!isnull)
 			result->tmplhandler = TextDatumGetCString(datum);
 
+		datum = heap_getattr(tup, Anum_pg_pltemplate_tmplinline,
+							 RelationGetDescr(rel), &isnull);
+		if (!isnull)
+			result->tmplinline = TextDatumGetCString(datum);
+
 		datum = heap_getattr(tup, Anum_pg_pltemplate_tmplvalidator,
 							 RelationGetDescr(rel), &isnull);
 		if (!isnull)
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 48039b86cb9735e0389d4e3d0e1f49ed50e69398..5feff5d1691d75f5b431ced8180573179f3eb761 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.437 2009/07/30 02:45:37 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.438 2009/09/22 23:43:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2561,6 +2561,16 @@ _copyRemoveFuncStmt(RemoveFuncStmt *from)
 	return newnode;
 }
 
+static DoStmt *
+_copyDoStmt(DoStmt *from)
+{
+	DoStmt	   *newnode = makeNode(DoStmt);
+
+	COPY_NODE_FIELD(args);
+
+	return newnode;
+}
+
 static RemoveOpClassStmt *
 _copyRemoveOpClassStmt(RemoveOpClassStmt *from)
 {
@@ -3104,6 +3114,7 @@ _copyCreatePLangStmt(CreatePLangStmt *from)
 
 	COPY_STRING_FIELD(plname);
 	COPY_NODE_FIELD(plhandler);
+	COPY_NODE_FIELD(plinline);
 	COPY_NODE_FIELD(plvalidator);
 	COPY_SCALAR_FIELD(pltrusted);
 
@@ -3797,6 +3808,9 @@ copyObject(void *from)
 		case T_RemoveFuncStmt:
 			retval = _copyRemoveFuncStmt(from);
 			break;
+		case T_DoStmt:
+			retval = _copyDoStmt(from);
+			break;
 		case T_RemoveOpClassStmt:
 			retval = _copyRemoveOpClassStmt(from);
 			break;
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 6c75f2e2747f0e94c69a3cd026596a2cb912b1c1..d7ed08cc68b77755781f036ee014150be2a2c29d 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.360 2009/07/30 02:45:37 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.361 2009/09/22 23:43:38 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1212,6 +1212,14 @@ _equalRemoveFuncStmt(RemoveFuncStmt *a, RemoveFuncStmt *b)
 	return true;
 }
 
+static bool
+_equalDoStmt(DoStmt *a, DoStmt *b)
+{
+	COMPARE_NODE_FIELD(args);
+
+	return true;
+}
+
 static bool
 _equalRemoveOpClassStmt(RemoveOpClassStmt *a, RemoveOpClassStmt *b)
 {
@@ -1667,6 +1675,7 @@ _equalCreatePLangStmt(CreatePLangStmt *a, CreatePLangStmt *b)
 {
 	COMPARE_STRING_FIELD(plname);
 	COMPARE_NODE_FIELD(plhandler);
+	COMPARE_NODE_FIELD(plinline);
 	COMPARE_NODE_FIELD(plvalidator);
 	COMPARE_SCALAR_FIELD(pltrusted);
 
@@ -2576,6 +2585,9 @@ equal(void *a, void *b)
 		case T_RemoveFuncStmt:
 			retval = _equalRemoveFuncStmt(a, b);
 			break;
+		case T_DoStmt:
+			retval = _equalDoStmt(a, b);
+			break;
 		case T_RemoveOpClassStmt:
 			retval = _equalRemoveOpClassStmt(a, b);
 			break;
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 81d57f65fb5c20954835a6567965b84a70213090..9a203a5a48dd10ada3f107eae8a747ca6ff9c9ec 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.678 2009/09/21 20:10:21 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.679 2009/09/22 23:43:38 tgl Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -196,7 +196,7 @@ static TypeName *TableFuncTypeName(List *columns);
 		CreateSchemaStmt CreateSeqStmt CreateStmt CreateTableSpaceStmt
 		CreateFdwStmt CreateForeignServerStmt CreateAssertStmt CreateTrigStmt
 		CreateUserStmt CreateUserMappingStmt CreateRoleStmt
-		CreatedbStmt DeclareCursorStmt DefineStmt DeleteStmt DiscardStmt
+		CreatedbStmt DeclareCursorStmt DefineStmt DeleteStmt DiscardStmt DoStmt
 		DropGroupStmt DropOpClassStmt DropOpFamilyStmt DropPLangStmt DropStmt
 		DropAssertStmt DropTrigStmt DropRuleStmt DropCastStmt DropRoleStmt
 		DropUserStmt DropdbStmt DropTableSpaceStmt DropFdwStmt
@@ -246,7 +246,6 @@ static TypeName *TableFuncTypeName(List *columns);
 %type <list>	OptSchemaEltList
 
 %type <boolean> TriggerActionTime TriggerForSpec opt_trusted opt_restart_seqs
-%type <str>		opt_lancompiler
 
 %type <ival>	TriggerEvents TriggerOneEvent
 %type <value>	TriggerFuncArg
@@ -256,7 +255,7 @@ static TypeName *TableFuncTypeName(List *columns);
 				index_name name file_name cluster_index_specification
 
 %type <list>	func_name handler_name qual_Op qual_all_Op subquery_Op
-				opt_class opt_validator validator_clause
+				opt_class opt_inline_handler opt_validator validator_clause
 
 %type <range>	qualified_name OptConstrFromTable
 
@@ -295,12 +294,12 @@ static TypeName *TableFuncTypeName(List *columns);
 				execute_param_clause using_clause returning_clause
 				enum_val_list table_func_column_list
 				create_generic_options alter_generic_options
-				relation_expr_list
+				relation_expr_list dostmt_opt_list
 
 %type <range>	OptTempTableName
 %type <into>	into_clause create_as_target
 
-%type <defelt>	createfunc_opt_item common_func_opt_item
+%type <defelt>	createfunc_opt_item common_func_opt_item dostmt_opt_item
 %type <fun_param> func_arg func_arg_with_default table_func_column
 %type <fun_param_mode> arg_class
 %type <typnam>	func_return func_type
@@ -481,7 +480,7 @@ static TypeName *TableFuncTypeName(List *columns);
 	HANDLER HAVING HEADER_P HOLD HOUR_P
 
 	IDENTITY_P IF_P ILIKE IMMEDIATE IMMUTABLE IMPLICIT_P IN_P
-	INCLUDING INCREMENT INDEX INDEXES INHERIT INHERITS INITIALLY
+	INCLUDING INCREMENT INDEX INDEXES INHERIT INHERITS INITIALLY INLINE_P
 	INNER_P INOUT INPUT_P INSENSITIVE INSERT INSTEAD INT_P INTEGER
 	INTERSECT INTERVAL INTO INVOKER IS ISNULL ISOLATION
 
@@ -489,7 +488,7 @@ static TypeName *TableFuncTypeName(List *columns);
 
 	KEY
 
-	LANCOMPILER LANGUAGE LARGE_P LAST_P LC_COLLATE_P LC_CTYPE_P LEADING
+	LANGUAGE LARGE_P LAST_P LC_COLLATE_P LC_CTYPE_P LEADING
 	LEAST LEFT LEVEL LIKE LIMIT LISTEN LOAD LOCAL LOCALTIME LOCALTIMESTAMP
 	LOCATION LOCK_P LOGIN_P
 
@@ -676,6 +675,7 @@ stmt :
 			| DefineStmt
 			| DeleteStmt
 			| DiscardStmt
+			| DoStmt
 			| DropAssertStmt
 			| DropCastStmt
 			| DropFdwStmt
@@ -2771,19 +2771,20 @@ CreatePLangStmt:
 				n->plname = $5;
 				/* parameters are all to be supplied by system */
 				n->plhandler = NIL;
+				n->plinline = NIL;
 				n->plvalidator = NIL;
 				n->pltrusted = false;
 				$$ = (Node *)n;
 			}
 			| CREATE opt_trusted opt_procedural LANGUAGE ColId_or_Sconst
-			  HANDLER handler_name opt_validator opt_lancompiler
+			  HANDLER handler_name opt_inline_handler opt_validator
 			{
 				CreatePLangStmt *n = makeNode(CreatePLangStmt);
 				n->plname = $5;
 				n->plhandler = $7;
-				n->plvalidator = $8;
+				n->plinline = $8;
+				n->plvalidator = $9;
 				n->pltrusted = $2;
-				/* LANCOMPILER is now ignored entirely */
 				$$ = (Node *)n;
 			}
 		;
@@ -2802,6 +2803,11 @@ handler_name:
 			| name attrs				{ $$ = lcons(makeString($1), $2); }
 		;
 
+opt_inline_handler:
+			INLINE_P handler_name					{ $$ = $2; }
+			| /*EMPTY*/								{ $$ = NIL; }
+		;
+
 validator_clause:
 			VALIDATOR handler_name					{ $$ = $2; }
 			| NO VALIDATOR							{ $$ = NIL; }
@@ -2812,11 +2818,6 @@ opt_validator:
 			| /*EMPTY*/								{ $$ = NIL; }
 		;
 
-opt_lancompiler:
-			LANCOMPILER Sconst						{ $$ = $2; }
-			| /*EMPTY*/								{ $$ = NULL; }
-		;
-
 DropPLangStmt:
 			DROP opt_procedural LANGUAGE ColId_or_Sconst opt_drop_behavior
 				{
@@ -5139,6 +5140,38 @@ any_operator:
 					{ $$ = lcons(makeString($1), $3); }
 		;
 
+/*****************************************************************************
+ *
+ *		DO <anonymous code block> [ LANGUAGE language ]
+ *
+ * We use a DefElem list for future extensibility, and to allow flexibility
+ * in the clause order.
+ *
+ *****************************************************************************/
+
+DoStmt: DO dostmt_opt_list
+				{
+					DoStmt *n = makeNode(DoStmt);
+					n->args = $2;
+					$$ = (Node *)n;
+				}
+		;
+
+dostmt_opt_list:
+			dostmt_opt_item						{ $$ = list_make1($1); }
+			| dostmt_opt_list dostmt_opt_item	{ $$ = lappend($1, $2); }
+		;
+
+dostmt_opt_item:
+			Sconst
+				{
+					$$ = makeDefElem("as", (Node *)makeString($1));
+				}
+			| LANGUAGE ColId_or_Sconst
+				{
+					$$ = makeDefElem("language", (Node *)makeString($2));
+				}
+		;
 
 /*****************************************************************************
  *
@@ -10362,6 +10395,7 @@ unreserved_keyword:
 			| INDEXES
 			| INHERIT
 			| INHERITS
+			| INLINE_P
 			| INPUT_P
 			| INSENSITIVE
 			| INSERT
@@ -10369,7 +10403,6 @@ unreserved_keyword:
 			| INVOKER
 			| ISOLATION
 			| KEY
-			| LANCOMPILER
 			| LANGUAGE
 			| LARGE_P
 			| LAST_P
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index c6fefccfc6f6110298f22f005b9405efb7462355..0d2079fc0aaba3aa1b045dcbfd2c61ebae055575 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.313 2009/07/29 20:56:19 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.314 2009/09/22 23:43:38 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -840,6 +840,10 @@ ProcessUtility(Node *parsetree,
 			}
 			break;
 
+		case T_DoStmt:
+			ExecuteDoStmt((DoStmt *) parsetree);
+			break;
+
 		case T_CreatedbStmt:
 			PreventTransactionChain(isTopLevel, "CREATE DATABASE");
 			createdb((CreatedbStmt *) parsetree);
@@ -1761,6 +1765,10 @@ CreateCommandTag(Node *parsetree)
 			}
 			break;
 
+		case T_DoStmt:
+			tag = "DO";
+			break;
+
 		case T_CreatedbStmt:
 			tag = "CREATE DATABASE";
 			break;
@@ -2276,6 +2284,10 @@ GetCommandLogLevel(Node *parsetree)
 			lev = LOGSTMT_DDL;
 			break;
 
+		case T_DoStmt:
+			lev = LOGSTMT_ALL;
+			break;
+
 		case T_CreatedbStmt:
 			lev = LOGSTMT_DDL;
 			break;
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 17bbbd7cb4aa9f4ed3579e4fe210bc8afbb5e6fa..cb743bb55ef4219dc311cf967aeb4aade81bd629 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -10,7 +10,7 @@
  * Written by Peter Eisentraut <peter_e@gmx.net>.
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.518 2009/09/17 21:15:18 petere Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.519 2009/09/22 23:43:38 tgl Exp $
  *
  *--------------------------------------------------------------------
  */
@@ -385,6 +385,8 @@ char	   *external_pid_file;
 
 char	   *pgstat_temp_directory;
 
+char	   *default_do_language;
+
 int			tcp_keepalives_idle;
 int			tcp_keepalives_interval;
 int			tcp_keepalives_count;
@@ -2539,6 +2541,15 @@ static struct config_string ConfigureNamesString[] =
 	},
 #endif   /* USE_SSL */
 
+	{
+		{"default_do_language", PGC_USERSET, CLIENT_CONN_STATEMENT,
+			gettext_noop("Sets the language used in DO statement if LANGUAGE is not specified."),
+			NULL
+		},
+		&default_do_language,
+		"plpgsql", NULL, NULL
+	},
+
 	/* End-of-list marker */
 	{
 		{NULL, 0, 0, NULL, NULL}, NULL, NULL, NULL, NULL
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index b10775cc2df8de67966a7cfb29e83368e9639a90..d6cf7e21c732ede9b2cb42c3f29cc5b4ab929cd6 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -422,6 +422,7 @@
 #temp_tablespaces = ''			# a list of tablespace names, '' uses
 					# only default tablespace
 #check_function_bodies = on
+#default_do_language = 'plpgsql'
 #default_transaction_isolation = 'read committed'
 #default_transaction_read_only = off
 #session_replication_role = 'origin'
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 5856dc7049a0fd3a9cb5ab5322d04002f13841d5..34ebc27168dbd853ca8d658d6339eaf63cac56b5 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.547 2009/09/11 19:17:04 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.548 2009/09/22 23:43:38 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -4445,6 +4445,7 @@ getProcLangs(int *numProcLangs)
 	int			i_lanname;
 	int			i_lanpltrusted;
 	int			i_lanplcallfoid;
+	int			i_laninline;
 	int			i_lanvalidator;
 	int			i_lanacl;
 	int			i_lanowner;
@@ -4452,7 +4453,19 @@ getProcLangs(int *numProcLangs)
 	/* Make sure we are in proper schema */
 	selectSourceSchema("pg_catalog");
 
-	if (g_fout->remoteVersion >= 80300)
+	if (g_fout->remoteVersion >= 80500)
+	{
+		/* pg_language has a laninline column */
+		appendPQExpBuffer(query, "SELECT tableoid, oid, "
+						  "lanname, lanpltrusted, lanplcallfoid, "
+						  "laninline, lanvalidator,  lanacl, "
+						  "(%s lanowner) AS lanowner "
+						  "FROM pg_language "
+						  "WHERE lanispl "
+						  "ORDER BY oid",
+						  username_subquery);
+	}
+	else if (g_fout->remoteVersion >= 80300)
 	{
 		/* pg_language has a lanowner column */
 		appendPQExpBuffer(query, "SELECT tableoid, oid, "
@@ -4515,6 +4528,7 @@ getProcLangs(int *numProcLangs)
 	i_lanpltrusted = PQfnumber(res, "lanpltrusted");
 	i_lanplcallfoid = PQfnumber(res, "lanplcallfoid");
 	/* these may fail and return -1: */
+	i_laninline = PQfnumber(res, "laninline");
 	i_lanvalidator = PQfnumber(res, "lanvalidator");
 	i_lanacl = PQfnumber(res, "lanacl");
 	i_lanowner = PQfnumber(res, "lanowner");
@@ -4529,6 +4543,10 @@ getProcLangs(int *numProcLangs)
 		planginfo[i].dobj.name = strdup(PQgetvalue(res, i, i_lanname));
 		planginfo[i].lanpltrusted = *(PQgetvalue(res, i, i_lanpltrusted)) == 't';
 		planginfo[i].lanplcallfoid = atooid(PQgetvalue(res, i, i_lanplcallfoid));
+		if (i_laninline >= 0)
+			planginfo[i].laninline = atooid(PQgetvalue(res, i, i_laninline));
+		else
+			planginfo[i].laninline = InvalidOid;
 		if (i_lanvalidator >= 0)
 			planginfo[i].lanvalidator = atooid(PQgetvalue(res, i, i_lanvalidator));
 		else
@@ -6994,6 +7012,7 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
 	char	   *qlanname;
 	char	   *lanschema;
 	FuncInfo   *funcInfo;
+	FuncInfo   *inlineInfo = NULL;
 	FuncInfo   *validatorInfo = NULL;
 
 	if (dataOnly)
@@ -7011,6 +7030,13 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
 	if (funcInfo != NULL && !funcInfo->dobj.dump)
 		funcInfo = NULL;		/* treat not-dumped same as not-found */
 
+	if (OidIsValid(plang->laninline))
+	{
+		inlineInfo = findFuncByOid(plang->laninline);
+		if (inlineInfo != NULL && !inlineInfo->dobj.dump)
+			inlineInfo = NULL;
+	}
+
 	if (OidIsValid(plang->lanvalidator))
 	{
 		validatorInfo = findFuncByOid(plang->lanvalidator);
@@ -7024,6 +7050,7 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
 	 * dump it.
 	 */
 	useParams = (funcInfo != NULL &&
+				 (inlineInfo != NULL || !OidIsValid(plang->laninline)) &&
 				 (validatorInfo != NULL || !OidIsValid(plang->lanvalidator)));
 
 	if (!useParams && !shouldDumpProcLangs())
@@ -7054,6 +7081,16 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
 	{
 		appendPQExpBuffer(defqry, " HANDLER %s",
 						  fmtId(funcInfo->dobj.name));
+		if (OidIsValid(plang->laninline))
+		{
+			appendPQExpBuffer(defqry, " INLINE ");
+			/* Cope with possibility that inline is in different schema */
+			if (inlineInfo->dobj.namespace != funcInfo->dobj.namespace)
+				appendPQExpBuffer(defqry, "%s.",
+							fmtId(inlineInfo->dobj.namespace->dobj.name));
+			appendPQExpBuffer(defqry, "%s",
+							  fmtId(inlineInfo->dobj.name));
+		}
 		if (OidIsValid(plang->lanvalidator))
 		{
 			appendPQExpBuffer(defqry, " VALIDATOR ");
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index 6b84d59723dbe8506e8189dd03a425b71065501c..beec160110c590bb5feb3642309ca02f21b61236 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.156 2009/08/02 22:14:52 tgl Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.157 2009/09/22 23:43:40 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -357,6 +357,7 @@ typedef struct _procLangInfo
 	DumpableObject dobj;
 	bool		lanpltrusted;
 	Oid			lanplcallfoid;
+	Oid			laninline;
 	Oid			lanvalidator;
 	char	   *lanacl;
 	char	   *lanowner;		/* name of owner, or empty string */
diff --git a/src/bin/scripts/droplang.c b/src/bin/scripts/droplang.c
index 7038e08b8af57bc79abe324cad52f1762b473b03..16898e264a9cc3e9704c8e85867ddc1a1228087c 100644
--- a/src/bin/scripts/droplang.c
+++ b/src/bin/scripts/droplang.c
@@ -5,7 +5,7 @@
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/bin/scripts/droplang.c,v 1.31 2009/02/26 16:02:39 petere Exp $
+ * $PostgreSQL: pgsql/src/bin/scripts/droplang.c,v 1.32 2009/09/22 23:43:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -38,7 +38,6 @@ main(int argc, char *argv[])
 	const char *progname;
 	int			optindex;
 	int			c;
-
 	bool		listlangs = false;
 	const char *dbname = NULL;
 	char	   *host = NULL;
@@ -47,19 +46,20 @@ main(int argc, char *argv[])
 	enum trivalue prompt_password = TRI_DEFAULT;
 	bool		echo = false;
 	char	   *langname = NULL;
-
 	char	   *p;
 	Oid			lanplcallfoid;
+	Oid			laninline;
 	Oid			lanvalidator;
 	char	   *handler;
+	char	   *inline_handler;
 	char	   *validator;
 	char	   *handler_ns;
+	char	   *inline_ns;
 	char	   *validator_ns;
 	bool		keephandler;
+	bool		keepinline;
 	bool		keepvalidator;
-
 	PQExpBufferData sql;
-
 	PGconn	   *conn;
 	PGresult   *result;
 
@@ -190,10 +190,10 @@ main(int argc, char *argv[])
 	executeCommand(conn, "SET search_path = pg_catalog;", progname, echo);
 
 	/*
-	 * Make sure the language is installed and find the OIDs of the handler
-	 * and validator functions
+	 * Make sure the language is installed and find the OIDs of the
+	 * language support functions
 	 */
-	printfPQExpBuffer(&sql, "SELECT lanplcallfoid, lanvalidator "
+	printfPQExpBuffer(&sql, "SELECT lanplcallfoid, laninline, lanvalidator "
 					  "FROM pg_language WHERE lanname = '%s' AND lanispl;",
 					  langname);
 	result = executeQuery(conn, sql.data, progname, echo);
@@ -206,7 +206,8 @@ main(int argc, char *argv[])
 		exit(1);
 	}
 	lanplcallfoid = atooid(PQgetvalue(result, 0, 0));
-	lanvalidator = atooid(PQgetvalue(result, 0, 1));
+	laninline = atooid(PQgetvalue(result, 0, 1));
+	lanvalidator = atooid(PQgetvalue(result, 0, 2));
 	PQclear(result);
 
 	/*
@@ -260,6 +261,44 @@ main(int argc, char *argv[])
 		handler_ns = NULL;
 	}
 
+	/*
+	 * Check that the inline function isn't used by some other language
+	 */
+	if (OidIsValid(laninline))
+	{
+		printfPQExpBuffer(&sql, "SELECT count(*) FROM pg_language "
+						  "WHERE laninline = %u AND lanname <> '%s';",
+						  laninline, langname);
+		result = executeQuery(conn, sql.data, progname, echo);
+		if (strcmp(PQgetvalue(result, 0, 0), "0") == 0)
+			keepinline = false;
+		else
+			keepinline = true;
+		PQclear(result);
+	}
+	else
+		keepinline = true;	/* don't try to delete it */
+
+	/*
+	 * Find the inline handler name
+	 */
+	if (!keepinline)
+	{
+		printfPQExpBuffer(&sql, "SELECT proname, (SELECT nspname "
+						  "FROM pg_namespace ns WHERE ns.oid = pronamespace) "
+						  "AS prons FROM pg_proc WHERE oid = %u;",
+						  laninline);
+		result = executeQuery(conn, sql.data, progname, echo);
+		inline_handler = strdup(PQgetvalue(result, 0, 0));
+		inline_ns = strdup(PQgetvalue(result, 0, 1));
+		PQclear(result);
+	}
+	else
+	{
+		inline_handler = NULL;
+		inline_ns = NULL;
+	}
+
 	/*
 	 * Check that the validator function isn't used by some other language
 	 */
@@ -305,6 +344,9 @@ main(int argc, char *argv[])
 	if (!keephandler)
 		appendPQExpBuffer(&sql, "DROP FUNCTION \"%s\".\"%s\" ();\n",
 						  handler_ns, handler);
+	if (!keepinline)
+		appendPQExpBuffer(&sql, "DROP FUNCTION \"%s\".\"%s\" (internal);\n",
+						  inline_ns, inline_handler);
 	if (!keepvalidator)
 		appendPQExpBuffer(&sql, "DROP FUNCTION \"%s\".\"%s\" (oid);\n",
 						  validator_ns, validator);
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index e162aa71076875a76e5c8836e960bcc974bf3674..5e0fc241549e41442871cc96b6779049dc1e204c 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.538 2009/09/01 03:53:08 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.539 2009/09/22 23:43:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*							yyyymmddN */
-#define CATALOG_VERSION_NO	200908311
+#define CATALOG_VERSION_NO	200909221
 
 #endif
diff --git a/src/include/catalog/pg_language.h b/src/include/catalog/pg_language.h
index dd8d35e830df744cda258fefdb156f5d25caf209..dff946b4119da7c24bbf98356bda1fc09cc475fc 100644
--- a/src/include/catalog/pg_language.h
+++ b/src/include/catalog/pg_language.h
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_language.h,v 1.34 2009/01/01 17:23:57 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_language.h,v 1.35 2009/09/22 23:43:41 tgl Exp $
  *
  * NOTES
  *	  the genbki.sh script reads this file and generates .bki
@@ -35,6 +35,7 @@ CATALOG(pg_language,2612)
 	bool		lanispl;		/* Is a procedural language */
 	bool		lanpltrusted;	/* PL is trusted */
 	Oid			lanplcallfoid;	/* Call handler for PL */
+	Oid			laninline;		/* Optional anonymous-block handler function */
 	Oid			lanvalidator;	/* Optional validation function */
 	aclitem		lanacl[1];		/* Access privileges */
 } FormData_pg_language;
@@ -50,27 +51,28 @@ typedef FormData_pg_language *Form_pg_language;
  *		compiler constants for pg_language
  * ----------------
  */
-#define Natts_pg_language				7
+#define Natts_pg_language				8
 #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
+#define Anum_pg_language_laninline		6
+#define Anum_pg_language_lanvalidator	7
+#define Anum_pg_language_lanacl			8
 
 /* ----------------
  *		initial contents of pg_language
  * ----------------
  */
 
-DATA(insert OID = 12 ( "internal" PGUID f f 0 2246 _null_ ));
+DATA(insert OID = 12 ( "internal"	PGUID f f 0 0 2246 _null_ ));
 DESCR("built-in functions");
 #define INTERNALlanguageId 12
-DATA(insert OID = 13 ( "c" PGUID f f 0 2247 _null_ ));
+DATA(insert OID = 13 ( "c"			PGUID f f 0 0 2247 _null_ ));
 DESCR("dynamically-loaded C functions");
 #define ClanguageId 13
-DATA(insert OID = 14 ( "sql" PGUID f t 0 2248 _null_ ));
+DATA(insert OID = 14 ( "sql"		PGUID f t 0 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 9775133ceb5584a9ad6bfededfc2afd58dd155aa..2065a5332bb218ffbd0e8a6deebd51fc43f2912c 100644
--- a/src/include/catalog/pg_pltemplate.h
+++ b/src/include/catalog/pg_pltemplate.h
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_pltemplate.h,v 1.7 2009/01/01 17:23:57 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_pltemplate.h,v 1.8 2009/09/22 23:43:41 tgl Exp $
  *
  * NOTES
  *	  the genbki.sh script reads this file and generates .bki
@@ -34,6 +34,7 @@ CATALOG(pg_pltemplate,1136) BKI_SHARED_RELATION BKI_WITHOUT_OIDS
 	bool		tmpltrusted;	/* PL is trusted? */
 	bool		tmpldbacreate;	/* PL is installable by db owner? */
 	text		tmplhandler;	/* name of call handler function */
+	text		tmplinline;		/* name of anonymous-block handler, or NULL */
 	text		tmplvalidator;	/* name of validator function, or NULL */
 	text		tmpllibrary;	/* path of shared library */
 	aclitem		tmplacl[1];		/* access privileges for template */
@@ -50,14 +51,15 @@ typedef FormData_pg_pltemplate *Form_pg_pltemplate;
  *		compiler constants for pg_pltemplate
  * ----------------
  */
-#define Natts_pg_pltemplate					7
+#define Natts_pg_pltemplate					8
 #define Anum_pg_pltemplate_tmplname			1
 #define Anum_pg_pltemplate_tmpltrusted		2
 #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
+#define Anum_pg_pltemplate_tmplinline		5
+#define Anum_pg_pltemplate_tmplvalidator	6
+#define Anum_pg_pltemplate_tmpllibrary		7
+#define Anum_pg_pltemplate_tmplacl			8
 
 
 /* ----------------
@@ -65,11 +67,11 @@ typedef FormData_pg_pltemplate *Form_pg_pltemplate;
  * ----------------
  */
 
-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_ ));
+DATA(insert ( "plpgsql"		t t "plpgsql_call_handler" "plpgsql_inline_handler" "plpgsql_validator" "$libdir/plpgsql" _null_ ));
+DATA(insert ( "pltcl"		t t "pltcl_call_handler" _null_ _null_ "$libdir/pltcl" _null_ ));
+DATA(insert ( "pltclu"		f f "pltclu_call_handler" _null_ _null_ "$libdir/pltcl" _null_ ));
+DATA(insert ( "plperl"		t t "plperl_call_handler" _null_ "plperl_validator" "$libdir/plperl" _null_ ));
+DATA(insert ( "plperlu"		f f "plperl_call_handler" _null_ "plperl_validator" "$libdir/plperl" _null_ ));
+DATA(insert ( "plpythonu"	f f "plpython_call_handler" _null_ _null_ "$libdir/plpython" _null_ ));
 
 #endif   /* PG_PLTEMPLATE_H */
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index 4396a497385be58ddbce3ab84c5a9b3a012b5ae4..89bb227a90f27caa6d7c861a6ae390be0b6e5c52 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/commands/defrem.h,v 1.96 2009/07/29 20:56:20 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/commands/defrem.h,v 1.97 2009/09/22 23:43:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -61,6 +61,7 @@ extern void DropCast(DropCastStmt *stmt);
 extern void DropCastById(Oid castOid);
 extern void AlterFunctionNamespace(List *name, List *argtypes, bool isagg,
 					   const char *newschema);
+extern void ExecuteDoStmt(DoStmt *stmt);
 
 /* commands/operatorcmds.c */
 extern void DefineOperator(List *names, List *parameters);
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index 6be4bf3959806b475dbfdbd09f40567aceae95d9..d842c9c3199f83d83f5822a502fd510be300794c 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.225 2009/09/17 20:49:29 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.226 2009/09/22 23:43:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -274,6 +274,7 @@ typedef enum NodeTag
 	T_CreateFunctionStmt,
 	T_AlterFunctionStmt,
 	T_RemoveFuncStmt,
+	T_DoStmt,
 	T_RenameStmt,
 	T_RuleStmt,
 	T_NotifyStmt,
@@ -388,7 +389,8 @@ typedef enum NodeTag
 	T_TriggerData = 950,		/* in commands/trigger.h */
 	T_ReturnSetInfo,			/* in nodes/execnodes.h */
 	T_WindowObjectData,			/* private in nodeWindowAgg.c */
-	T_TIDBitmap					/* in nodes/tidbitmap.h */
+	T_TIDBitmap,				/* in nodes/tidbitmap.h */
+	T_InlineCodeBlock			/* in nodes/parsenodes.h */
 } NodeTag;
 
 /*
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index f0b3941abf8f0c6b0faa3b383cc8f56bd2fc635c..1ce28b77541ff6cb835576b56b4ff01baf8847f2 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -13,7 +13,7 @@
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.401 2009/08/02 22:14:53 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.402 2009/09/22 23:43:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1570,6 +1570,7 @@ typedef struct CreatePLangStmt
 	NodeTag		type;
 	char	   *plname;			/* PL name */
 	List	   *plhandler;		/* PL call handler function (qual. name) */
+	List	   *plinline;		/* optional inline function (qual. name) */
 	List	   *plvalidator;	/* optional validator function (qual. name) */
 	bool		pltrusted;		/* PL is trusted */
 } CreatePLangStmt;
@@ -1922,6 +1923,25 @@ typedef struct RemoveFuncStmt
 	bool		missing_ok;		/* skip error if missing? */
 } RemoveFuncStmt;
 
+/* ----------------------
+ *		DO Statement
+ *
+ * DoStmt is the raw parser output, InlineCodeBlock is the execution-time API
+ * ----------------------
+ */
+typedef struct DoStmt
+{
+	NodeTag		type;
+	List	   *args;			/* List of DefElem nodes */
+} DoStmt;
+
+typedef struct InlineCodeBlock
+{
+	NodeTag		type;
+	char	   *source_text;	/* source text of anonymous code block */
+	Oid			langOid;		/* OID of selected language */
+} InlineCodeBlock;
+
 /* ----------------------
  *		Drop Operator Class Statement
  * ----------------------
diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h
index 23f5d87a7a68deb78c0eadea8c147704b1ea7a8d..d1fd91795b60386ad169b575871d3992bdd0cea3 100644
--- a/src/include/parser/kwlist.h
+++ b/src/include/parser/kwlist.h
@@ -11,7 +11,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/include/parser/kwlist.h,v 1.2 2009/04/06 08:42:53 heikki Exp $
+ *	  $PostgreSQL: pgsql/src/include/parser/kwlist.h,v 1.3 2009/09/22 23:43:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -187,6 +187,7 @@ PG_KEYWORD("indexes", INDEXES, UNRESERVED_KEYWORD)
 PG_KEYWORD("inherit", INHERIT, UNRESERVED_KEYWORD)
 PG_KEYWORD("inherits", INHERITS, UNRESERVED_KEYWORD)
 PG_KEYWORD("initially", INITIALLY, RESERVED_KEYWORD)
+PG_KEYWORD("inline", INLINE_P, UNRESERVED_KEYWORD)
 PG_KEYWORD("inner", INNER_P, TYPE_FUNC_NAME_KEYWORD)
 PG_KEYWORD("inout", INOUT, COL_NAME_KEYWORD)
 PG_KEYWORD("input", INPUT_P, UNRESERVED_KEYWORD)
@@ -204,7 +205,6 @@ PG_KEYWORD("isnull", ISNULL, TYPE_FUNC_NAME_KEYWORD)
 PG_KEYWORD("isolation", ISOLATION, UNRESERVED_KEYWORD)
 PG_KEYWORD("join", JOIN, TYPE_FUNC_NAME_KEYWORD)
 PG_KEYWORD("key", KEY, UNRESERVED_KEYWORD)
-PG_KEYWORD("lancompiler", LANCOMPILER, UNRESERVED_KEYWORD)
 PG_KEYWORD("language", LANGUAGE, UNRESERVED_KEYWORD)
 PG_KEYWORD("large", LARGE_P, UNRESERVED_KEYWORD)
 PG_KEYWORD("last", LAST_P, UNRESERVED_KEYWORD)
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 6f4acdef70185aaaecf0a64541d6e534e2e5b229..435a722aa0b6b7f93657e5eade41a9ba1a35f00a 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -7,7 +7,7 @@
  * Copyright (c) 2000-2009, PostgreSQL Global Development Group
  * Written by Peter Eisentraut <peter_e@gmx.net>.
  *
- * $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.104 2009/09/03 22:08:05 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.105 2009/09/22 23:43:41 tgl Exp $
  *--------------------------------------------------------------------
  */
 #ifndef GUC_H
@@ -178,6 +178,8 @@ extern char *HbaFileName;
 extern char *IdentFileName;
 extern char *external_pid_file;
 
+extern char *default_do_language;
+
 extern int	tcp_keepalives_idle;
 extern int	tcp_keepalives_interval;
 extern int	tcp_keepalives_count;
diff --git a/src/interfaces/ecpg/preproc/ecpg.trailer b/src/interfaces/ecpg/preproc/ecpg.trailer
index 6040a4b012d50a271bcceb7aa5aba04f6e64dcbb..5eb43937ca8d68721042417993a1e8f46d942f4d 100644
--- a/src/interfaces/ecpg/preproc/ecpg.trailer
+++ b/src/interfaces/ecpg/preproc/ecpg.trailer
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.trailer,v 1.11 2009/08/14 13:28:22 meskes Exp $ */
+/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.trailer,v 1.12 2009/09/22 23:43:42 tgl Exp $ */
 
 statements: /*EMPTY*/
                 | statements statement
@@ -1614,12 +1614,12 @@ ECPGunreserved_con:	  ABORT_P			{ $$ = make_str("abort"); }
 		| INDEXES			{ $$ = make_str("indexes"); }
 		| INHERIT			{ $$ = make_str("inherit"); }
 		| INHERITS			{ $$ = make_str("inherits"); }
+		| INLINE_P			{ $$ = make_str("inline"); }
 		| INSENSITIVE		{ $$ = make_str("insensitive"); }
 		| INSERT			{ $$ = make_str("insert"); }
 		| INSTEAD			{ $$ = make_str("instead"); }
 		| ISOLATION			{ $$ = make_str("isolation"); }
 		| KEY				{ $$ = make_str("key"); }
-		| LANCOMPILER		{ $$ = make_str("lancompiler"); }
 		| LANGUAGE			{ $$ = make_str("language"); }
 		| LARGE_P			{ $$ = make_str("large"); }
 		| LAST_P			{ $$ = make_str("last"); }
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index c589aa1994dbe39926a359611f6791ce46d07f68..604b7dbf0865479afd8e8301bf5ede35e1064f66 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.138 2009/09/20 01:53:32 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.139 2009/09/22 23:43:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -95,6 +95,7 @@ static PLpgSQL_function *do_compile(FunctionCallInfo fcinfo,
 		   PLpgSQL_function *function,
 		   PLpgSQL_func_hashkey *hashkey,
 		   bool forValidator);
+static void add_dummy_return(PLpgSQL_function *function);
 static PLpgSQL_row *build_row_from_class(Oid classOid);
 static PLpgSQL_row *build_row_from_vars(PLpgSQL_variable **vars, int numvars);
 static PLpgSQL_type *build_datatype(HeapTuple typeTup, int32 typmod);
@@ -670,36 +671,11 @@ do_compile(FunctionCallInfo fcinfo,
 	 * If it has OUT parameters or returns VOID or returns a set, we allow
 	 * control to fall off the end without an explicit RETURN statement. The
 	 * easiest way to implement this is to add a RETURN statement to the end
-	 * of the statement list during parsing.  However, if the outer block has
-	 * an EXCEPTION clause, we need to make a new outer block, since the added
-	 * RETURN shouldn't act like it is inside the EXCEPTION clause.
+	 * of the statement list during parsing.
 	 */
 	if (num_out_args > 0 || function->fn_rettype == VOIDOID ||
 		function->fn_retset)
-	{
-		if (function->action->exceptions != NULL)
-		{
-			PLpgSQL_stmt_block *new;
-
-			new = palloc0(sizeof(PLpgSQL_stmt_block));
-			new->cmd_type = PLPGSQL_STMT_BLOCK;
-			new->body = list_make1(function->action);
-
-			function->action = new;
-		}
-		if (function->action->body == NIL ||
-			((PLpgSQL_stmt *) llast(function->action->body))->cmd_type != PLPGSQL_STMT_RETURN)
-		{
-			PLpgSQL_stmt_return *new;
-
-			new = palloc0(sizeof(PLpgSQL_stmt_return));
-			new->cmd_type = PLPGSQL_STMT_RETURN;
-			new->expr = NULL;
-			new->retvarno = function->out_param_varno;
-
-			function->action->body = lappend(function->action->body, new);
-		}
-	}
+		add_dummy_return(function);
 
 	/*
 	 * Complete the function's info
@@ -735,12 +711,150 @@ do_compile(FunctionCallInfo fcinfo,
 	return function;
 }
 
+/* ----------
+ * plpgsql_compile_inline	Make an execution tree for an anonymous code block.
+ *
+ * Note: this is generally parallel to do_compile(); is it worth trying to
+ * merge the two?
+ *
+ * Note: we assume the block will be thrown away so there is no need to build
+ * persistent data structures.
+ * ----------
+ */
+PLpgSQL_function *
+plpgsql_compile_inline(char *proc_source)
+{
+	char	   *func_name = "inline_code_block";
+	PLpgSQL_function *function;
+	ErrorContextCallback plerrcontext;
+	Oid			typinput;
+	PLpgSQL_variable *var;
+	int			parse_rc;
+	MemoryContext func_cxt;
+	int			i;
+
+	/*
+	 * Setup the scanner input and error info.	We assume that this function
+	 * cannot be invoked recursively, so there's no need to save and restore
+	 * the static variables used here.
+	 */
+	plpgsql_scanner_init(proc_source);
+
+	plpgsql_error_funcname = func_name;
+	plpgsql_error_lineno = 0;
+
+	/*
+	 * Setup error traceback support for ereport()
+	 */
+	plerrcontext.callback = plpgsql_compile_error_callback;
+	plerrcontext.arg = proc_source;
+	plerrcontext.previous = error_context_stack;
+	error_context_stack = &plerrcontext;
+
+	plpgsql_ns_init();
+	plpgsql_ns_push(func_name);
+	plpgsql_DumpExecTree = false;
+
+	datums_alloc = 128;
+	plpgsql_nDatums = 0;
+	plpgsql_Datums = palloc(sizeof(PLpgSQL_datum *) * datums_alloc);
+	datums_last = 0;
+
+	/* Do extra syntax checking if check_function_bodies is on */
+	plpgsql_check_syntax = check_function_bodies;
+
+	/* Function struct does not live past current statement */
+	function = (PLpgSQL_function *) palloc0(sizeof(PLpgSQL_function));
+
+	plpgsql_curr_compile = function;
+
+	/*
+	 * All the rest of the compile-time storage (e.g. parse tree) is kept in
+	 * its own memory context, so it can be reclaimed easily.
+	 */
+	func_cxt = AllocSetContextCreate(CurrentMemoryContext,
+									 "PL/PgSQL function context",
+									 ALLOCSET_DEFAULT_MINSIZE,
+									 ALLOCSET_DEFAULT_INITSIZE,
+									 ALLOCSET_DEFAULT_MAXSIZE);
+	compile_tmp_cxt = MemoryContextSwitchTo(func_cxt);
+
+	function->fn_name = pstrdup(func_name);
+	function->fn_is_trigger = false;
+	function->fn_cxt = func_cxt;
+	function->out_param_varno = -1;		/* set up for no OUT param */
+
+	/* Set up as though in a function returning VOID */
+	function->fn_rettype = VOIDOID;
+	function->fn_retset = false;
+	function->fn_retistuple = false;
+	/* a bit of hardwired knowledge about type VOID here */
+	function->fn_retbyval = true;
+	function->fn_rettyplen = sizeof(int32);
+	getTypeInputInfo(VOIDOID, &typinput, &function->fn_rettypioparam);
+	fmgr_info(typinput, &(function->fn_retinput));
+
+	/*
+	 * Remember if function is STABLE/IMMUTABLE.  XXX would it be better
+	 * to set this TRUE inside a read-only transaction?  Not clear.
+	 */
+	function->fn_readonly = false;
+
+	/*
+	 * Create the magic FOUND variable.
+	 */
+	var = plpgsql_build_variable("found", 0,
+								 plpgsql_build_datatype(BOOLOID, -1),
+								 true);
+	function->found_varno = var->dno;
+
+	/*
+	 * Now parse the function's text
+	 */
+	parse_rc = plpgsql_yyparse();
+	if (parse_rc != 0)
+		elog(ERROR, "plpgsql parser returned %d", parse_rc);
+	function->action = plpgsql_yylval.program;
+
+	plpgsql_scanner_finish();
+
+	/*
+	 * If it returns VOID (always true at the moment), we allow control to
+	 * fall off the end without an explicit RETURN statement.
+	 */
+	if (function->fn_rettype == VOIDOID)
+		add_dummy_return(function);
+
+	/*
+	 * Complete the function's info
+	 */
+	function->fn_nargs = 0;
+	function->ndatums = plpgsql_nDatums;
+	function->datums = palloc(sizeof(PLpgSQL_datum *) * plpgsql_nDatums);
+	for (i = 0; i < plpgsql_nDatums; i++)
+		function->datums[i] = plpgsql_Datums[i];
+
+	/*
+	 * Pop the error context stack
+	 */
+	error_context_stack = plerrcontext.previous;
+	plpgsql_error_funcname = NULL;
+	plpgsql_error_lineno = 0;
+
+	plpgsql_check_syntax = false;
+
+	MemoryContextSwitchTo(compile_tmp_cxt);
+	compile_tmp_cxt = NULL;
+	return function;
+}
+
 
 /*
- * error context callback to let us supply a call-stack traceback. If
- * we are validating, the function source is passed as an
- * argument. This function is public only for the sake of an assertion
- * in gram.y
+ * error context callback to let us supply a call-stack traceback.
+ * If we are validating or executing an anonymous code block, the function
+ * source text is passed as an argument.
+ *
+ * This function is public only for the sake of an assertion in gram.y
  */
 void
 plpgsql_compile_error_callback(void *arg)
@@ -749,7 +863,7 @@ plpgsql_compile_error_callback(void *arg)
 	{
 		/*
 		 * Try to convert syntax error position to reference text of original
-		 * CREATE FUNCTION command.
+		 * CREATE FUNCTION or DO command.
 		 */
 		if (function_parse_error_transpose((const char *) arg))
 			return;
@@ -766,6 +880,42 @@ plpgsql_compile_error_callback(void *arg)
 }
 
 
+/*
+ * Add a dummy RETURN statement to the given function's body
+ */
+static void
+add_dummy_return(PLpgSQL_function *function)
+{
+	/*
+	 * If the outer block has an EXCEPTION clause, we need to make a new outer
+	 * block, since the added RETURN shouldn't act like it is inside the
+	 * EXCEPTION clause.
+	 */
+	if (function->action->exceptions != NULL)
+	{
+		PLpgSQL_stmt_block *new;
+
+		new = palloc0(sizeof(PLpgSQL_stmt_block));
+		new->cmd_type = PLPGSQL_STMT_BLOCK;
+		new->body = list_make1(function->action);
+
+		function->action = new;
+	}
+	if (function->action->body == NIL ||
+		((PLpgSQL_stmt *) llast(function->action->body))->cmd_type != PLPGSQL_STMT_RETURN)
+	{
+		PLpgSQL_stmt_return *new;
+
+		new = palloc0(sizeof(PLpgSQL_stmt_return));
+		new->cmd_type = PLPGSQL_STMT_RETURN;
+		new->expr = NULL;
+		new->retvarno = function->out_param_varno;
+
+		function->action->body = lappend(function->action->body, new);
+	}
+}
+
+
 /* ----------
  * plpgsql_parse_word		The scanner calls this to postparse
  *				any single word not found by a
diff --git a/src/pl/plpgsql/src/pl_handler.c b/src/pl/plpgsql/src/pl_handler.c
index 2abe67c85262fe8361ad8b22cee8302d82f5429e..4f506eb97ca29e3b718dc60b563695a137c43843 100644
--- a/src/pl/plpgsql/src/pl_handler.c
+++ b/src/pl/plpgsql/src/pl_handler.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_handler.c,v 1.45 2009/08/04 21:22:46 alvherre Exp $
+ *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_handler.c,v 1.46 2009/09/22 23:43:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -114,6 +114,57 @@ plpgsql_call_handler(PG_FUNCTION_ARGS)
 	return retval;
 }
 
+/* ----------
+ * plpgsql_inline_handler
+ *
+ * Called by PostgreSQL to execute an anonymous code block
+ * ----------
+ */
+PG_FUNCTION_INFO_V1(plpgsql_inline_handler);
+
+Datum
+plpgsql_inline_handler(PG_FUNCTION_ARGS)
+{
+	InlineCodeBlock *codeblock = (InlineCodeBlock *) DatumGetPointer(PG_GETARG_DATUM(0));
+	PLpgSQL_function *func;
+	FunctionCallInfoData fake_fcinfo;
+	FmgrInfo	flinfo;
+	Datum		retval;
+	int			rc;
+
+	Assert(IsA(codeblock, InlineCodeBlock));
+
+	/*
+	 * Connect to SPI manager
+	 */
+	if ((rc = SPI_connect()) != SPI_OK_CONNECT)
+		elog(ERROR, "SPI_connect failed: %s", SPI_result_code_string(rc));
+
+	/* Compile the anonymous code block */
+	func = plpgsql_compile_inline(codeblock->source_text);
+
+	/*
+	 * Set up a fake fcinfo with just enough info to satisfy
+	 * plpgsql_exec_function().  In particular note that this sets things up
+	 * with no arguments passed.
+	 */
+	MemSet(&fake_fcinfo, 0, sizeof(fake_fcinfo));
+	MemSet(&flinfo, 0, sizeof(flinfo));
+	fake_fcinfo.flinfo = &flinfo;
+	flinfo.fn_oid = InvalidOid;
+	flinfo.fn_mcxt = CurrentMemoryContext;
+
+	retval = plpgsql_exec_function(func, &fake_fcinfo);
+
+	/*
+	 * Disconnect from SPI manager
+	 */
+	if ((rc = SPI_finish()) != SPI_OK_FINISH)
+		elog(ERROR, "SPI_finish failed: %s", SPI_result_code_string(rc));
+
+	return retval;
+}
+
 /* ----------
  * plpgsql_validator
  *
diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h
index 21c9edb52cad02219aba6a3dc7de668bbfc62de3..fb627e7a898128e0540374938634e57be076023e 100644
--- a/src/pl/plpgsql/src/plpgsql.h
+++ b/src/pl/plpgsql/src/plpgsql.h
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.115 2009/08/04 21:22:46 alvherre Exp $
+ *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.116 2009/09/22 23:43:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -799,6 +799,7 @@ extern PLpgSQL_plugin **plugin_ptr;
  */
 extern PLpgSQL_function *plpgsql_compile(FunctionCallInfo fcinfo,
 				bool forValidator);
+extern PLpgSQL_function *plpgsql_compile_inline(char *proc_source);
 extern int	plpgsql_parse_word(const char *word);
 extern int	plpgsql_parse_dblword(const char *word);
 extern int	plpgsql_parse_tripword(const char *word);
@@ -828,6 +829,7 @@ extern void plpgsql_compile_error_callback(void *arg);
  */
 extern void _PG_init(void);
 extern Datum plpgsql_call_handler(PG_FUNCTION_ARGS);
+extern Datum plpgsql_inline_handler(PG_FUNCTION_ARGS);
 extern Datum plpgsql_validator(PG_FUNCTION_ARGS);
 
 /* ----------
diff --git a/src/test/regress/expected/plpgsql.out b/src/test/regress/expected/plpgsql.out
index 078c14d81583e8d5afd68fbb314925df70fad38e..ca4c9dc23314f8defe5ff606701d198814495cb5 100644
--- a/src/test/regress/expected/plpgsql.out
+++ b/src/test/regress/expected/plpgsql.out
@@ -3861,3 +3861,40 @@ NOTICE:  foo\bar!baz
 (1 row)
 
 drop function strtest();
+-- Test anonymous code blocks.
+DO $$
+DECLARE r record;
+BEGIN 
+    FOR r IN SELECT rtrim(roomno) AS roomno, comment FROM Room ORDER BY roomno
+    LOOP
+        RAISE NOTICE '%, %', r.roomno, r.comment;
+    END LOOP;
+END$$ LANGUAGE plpgsql;
+NOTICE:  001, Entrance
+NOTICE:  002, Office
+NOTICE:  003, Office
+NOTICE:  004, Technical
+NOTICE:  101, Office
+NOTICE:  102, Conference
+NOTICE:  103, Restroom
+NOTICE:  104, Technical
+NOTICE:  105, Office
+NOTICE:  106, Office
+-- these are to check syntax error reporting
+DO LANGUAGE plpgsql $$begin return 1; end$$;
+ERROR:  RETURN cannot have a parameter in function returning void at or near "1"
+LINE 1: DO LANGUAGE plpgsql $$begin return 1; end$$;
+                                           ^
+DO LANGUAGE plpgsql $$
+DECLARE r record;
+BEGIN 
+    FOR r IN SELECT rtrim(roomno) AS roomno, foo FROM Room ORDER BY roomno
+    LOOP
+        RAISE NOTICE '%, %', r.roomno, r.comment;
+    END LOOP;
+END$$;
+ERROR:  column "foo" does not exist
+LINE 1:  SELECT rtrim(roomno) AS roomno, foo FROM Room ORDER BY room...
+                                         ^
+QUERY:   SELECT rtrim(roomno) AS roomno, foo FROM Room ORDER BY roomno
+CONTEXT:  PL/pgSQL function "inline_code_block" line 3 at FOR over SELECT rows
diff --git a/src/test/regress/sql/plpgsql.sql b/src/test/regress/sql/plpgsql.sql
index da12211847858025dbea6a22ff8a6cdd45bfd757..96f89144b7735fa866ea31ff2fbbb78ea240d3f5 100644
--- a/src/test/regress/sql/plpgsql.sql
+++ b/src/test/regress/sql/plpgsql.sql
@@ -3079,3 +3079,26 @@ $$ language plpgsql;
 select strtest();
 
 drop function strtest();
+
+-- Test anonymous code blocks.
+
+DO $$
+DECLARE r record;
+BEGIN 
+    FOR r IN SELECT rtrim(roomno) AS roomno, comment FROM Room ORDER BY roomno
+    LOOP
+        RAISE NOTICE '%, %', r.roomno, r.comment;
+    END LOOP;
+END$$ LANGUAGE plpgsql;
+
+-- these are to check syntax error reporting
+DO LANGUAGE plpgsql $$begin return 1; end$$;
+
+DO LANGUAGE plpgsql $$
+DECLARE r record;
+BEGIN 
+    FOR r IN SELECT rtrim(roomno) AS roomno, foo FROM Room ORDER BY roomno
+    LOOP
+        RAISE NOTICE '%, %', r.roomno, r.comment;
+    END LOOP;
+END$$;