diff --git a/doc/src/sgml/ref/allfiles.sgml b/doc/src/sgml/ref/allfiles.sgml
index f21410e7c13663c1dd8c61ce0eaba31bd0ac86c1..f02edd4cff2f5653c4c6595c832d87727af28d6c 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.58 2004/06/18 21:24:01 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/allfiles.sgml,v 1.59 2004/06/25 21:55:50 tgl Exp $
 PostgreSQL documentation
 Complete list of usable sgml source files in this directory.
 -->
@@ -13,11 +13,14 @@ Complete list of usable sgml source files in this directory.
 <!entity alterFunction      system "alter_function.sgml">
 <!entity alterGroup         system "alter_group.sgml">
 <!entity alterLanguage      system "alter_language.sgml">
+<!entity alterOperator      system "alter_operator.sgml">
 <!entity alterOperatorClass system "alter_opclass.sgml">
 <!entity alterSchema        system "alter_schema.sgml">
 <!entity alterSequence      system "alter_sequence.sgml">
 <!entity alterTable         system "alter_table.sgml">
+<!entity alterTableSpace    system "alter_tablespace.sgml">
 <!entity alterTrigger       system "alter_trigger.sgml">
+<!entity alterType          system "alter_type.sgml">
 <!entity alterUser          system "alter_user.sgml">
 <!entity analyze            system "analyze.sgml">
 <!entity begin              system "begin.sgml">
diff --git a/doc/src/sgml/ref/alter_aggregate.sgml b/doc/src/sgml/ref/alter_aggregate.sgml
index 112242f14218ebe482018845ea8a1f89c2603341..bfdb1761d5bc662c91fd8c0fd81518d1bc27ffba 100644
--- a/doc/src/sgml/ref/alter_aggregate.sgml
+++ b/doc/src/sgml/ref/alter_aggregate.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/alter_aggregate.sgml,v 1.4 2003/11/29 19:51:38 pgsql Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/alter_aggregate.sgml,v 1.5 2004/06/25 21:55:50 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -21,6 +21,7 @@ PostgreSQL documentation
  <refsynopsisdiv>
 <synopsis>
 ALTER AGGREGATE <replaceable>name</replaceable> ( <replaceable>type</replaceable> ) RENAME TO <replaceable>newname</replaceable>
+ALTER AGGREGATE <replaceable>name</replaceable> ( <replaceable>type</replaceable> ) OWNER TO <replaceable>newowner</replaceable>
 </synopsis>
  </refsynopsisdiv>
   
@@ -29,8 +30,7 @@ ALTER AGGREGATE <replaceable>name</replaceable> ( <replaceable>type</replaceable
 
   <para>
    <command>ALTER AGGREGATE</command> changes the definition of an
-   aggregate function.  The only currently available functionality is to
-   rename the aggregate function.
+   aggregate function.
   </para>
  </refsect1>
   
@@ -65,6 +65,16 @@ ALTER AGGREGATE <replaceable>name</replaceable> ( <replaceable>type</replaceable
      </para>
     </listitem>
    </varlistentry>
+
+   <varlistentry>
+    <term><replaceable class="parameter">newowner</replaceable></term>
+    <listitem>
+     <para>
+      The new owner of the aggregate function.
+      You must be a superuser to change an aggregate's owner.
+     </para>
+    </listitem>
+   </varlistentry>
   </variablelist>
  </refsect1>
 
@@ -76,6 +86,14 @@ ALTER AGGREGATE <replaceable>name</replaceable> ( <replaceable>type</replaceable
    <type>integer</type> to <literal>my_average</literal>:
 <programlisting>
 ALTER AGGREGATE myavg(integer) RENAME TO my_average;
+</programlisting>
+  </para>
+
+  <para>
+   To change the owner of the aggregate function <literal>myavg</literal> for type
+   <type>integer</type> to <literal>joe</literal>:
+<programlisting>
+ALTER AGGREGATE myavg(integer) OWNER TO joe;
 </programlisting>
   </para>
  </refsect1>
diff --git a/doc/src/sgml/ref/alter_conversion.sgml b/doc/src/sgml/ref/alter_conversion.sgml
index 08d167eb3ccc73dd3e0a543d9aa9641cc9488318..024d03212cb70ff13afc1249458ea5d421703b6f 100644
--- a/doc/src/sgml/ref/alter_conversion.sgml
+++ b/doc/src/sgml/ref/alter_conversion.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/alter_conversion.sgml,v 1.4 2003/11/29 19:51:38 pgsql Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/alter_conversion.sgml,v 1.5 2004/06/25 21:55:50 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -21,6 +21,7 @@ PostgreSQL documentation
  <refsynopsisdiv>
 <synopsis>
 ALTER CONVERSION <replaceable>name</replaceable> RENAME TO <replaceable>newname</replaceable>
+ALTER CONVERSION <replaceable>name</replaceable> OWNER TO <replaceable>newowner</replaceable>
 </synopsis>
  </refsynopsisdiv>
   
@@ -29,7 +30,6 @@ ALTER CONVERSION <replaceable>name</replaceable> RENAME TO <replaceable>newname<
 
   <para>
    <command>ALTER CONVERSION</command> changes the definition of a
-   conversion.  The only currently available functionality is to rename the
    conversion.
   </para>
  </refsect1>
@@ -55,6 +55,16 @@ ALTER CONVERSION <replaceable>name</replaceable> RENAME TO <replaceable>newname<
      </para>
     </listitem>
    </varlistentry>
+
+   <varlistentry>
+    <term><replaceable class="parameter">newowner</replaceable></term>
+    <listitem>
+     <para>
+      The new owner of the conversion. To change the owner of a conversion,
+      you must be a superuser.
+     </para>
+    </listitem>
+   </varlistentry>
   </variablelist>
  </refsect1>
 
@@ -66,6 +76,14 @@ ALTER CONVERSION <replaceable>name</replaceable> RENAME TO <replaceable>newname<
    <literal>latin1_to_unicode</literal>:
 <programlisting>
 ALTER CONVERSION iso_8859_1_to_utf_8 RENAME TO latin1_to_unicode;
+</programlisting>
+  </para>
+
+  <para>
+   To change the owner of the conversion <literal>iso_8859_1_to_utf_8</literal> to
+   <literal>joe</literal>:
+<programlisting>
+ALTER CONVERSION iso_8859_1_to_utf_8 OWNER TO joe;
 </programlisting>
   </para>
  </refsect1>
diff --git a/doc/src/sgml/ref/alter_function.sgml b/doc/src/sgml/ref/alter_function.sgml
index 71ae81893b3d0a2c3b886a5596d6b58f23612f3c..00dfcac007abee773266deb5f54b8315634dec33 100644
--- a/doc/src/sgml/ref/alter_function.sgml
+++ b/doc/src/sgml/ref/alter_function.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/alter_function.sgml,v 1.4 2003/11/29 19:51:38 pgsql Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/alter_function.sgml,v 1.5 2004/06/25 21:55:50 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -21,6 +21,7 @@ PostgreSQL documentation
  <refsynopsisdiv>
 <synopsis>
 ALTER FUNCTION <replaceable>name</replaceable> ( [ <replaceable class="parameter">type</replaceable> [, ...] ] ) RENAME TO <replaceable>newname</replaceable>
+ALTER FUNCTION <replaceable>name</replaceable> ( [ <replaceable class="parameter">type</replaceable> [, ...] ] ) OWNER TO <replaceable>newowner</replaceable>
 </synopsis>
  </refsynopsisdiv>
   
@@ -29,7 +30,7 @@ ALTER FUNCTION <replaceable>name</replaceable> ( [ <replaceable class="parameter
 
   <para>
    <command>ALTER FUNCTION</command> changes the definition of a
-   function.  The only functionality is to rename the function.
+   function.
   </para>
  </refsect1>
   
@@ -63,6 +64,19 @@ ALTER FUNCTION <replaceable>name</replaceable> ( [ <replaceable class="parameter
      </para>
     </listitem>
    </varlistentry>
+
+   <varlistentry>
+    <term><replaceable class="parameter">newowner</replaceable></term>
+    <listitem>
+     <para>
+      The new owner of the function.
+      To change the owner of a function, you must be a superuser.
+      Note that if the function is marked
+      <literal>SECURITY DEFINER</literal>,
+      it will subsequently execute as the new owner.
+     </para>
+    </listitem>
+   </varlistentry>
   </variablelist>
  </refsect1>
 
@@ -74,6 +88,14 @@ ALTER FUNCTION <replaceable>name</replaceable> ( [ <replaceable class="parameter
    <type>integer</type> to <literal>square_root</literal>:
 <programlisting>
 ALTER FUNCTION sqrt(integer) RENAME TO square_root;
+</programlisting>
+  </para>
+
+  <para>
+   To change the owner of the function <literal>sqrt</literal> for type
+   <type>integer</type> to <literal>joe</literal>:
+<programlisting>
+ALTER FUNCTION sqrt(integer) OWNER TO joe;
 </programlisting>
   </para>
  </refsect1>
@@ -84,7 +106,7 @@ ALTER FUNCTION sqrt(integer) RENAME TO square_root;
   <para>
    There is an <command>ALTER FUNCTION</command> statement in the SQL
    standard, but it does not provide the option to rename the
-   function.
+   function or change the owner.
   </para>
  </refsect1>
 
diff --git a/doc/src/sgml/ref/alter_opclass.sgml b/doc/src/sgml/ref/alter_opclass.sgml
index 8a5e308570323f6d8a118c23baf7e80bcc76ba58..d4171ceb2f9adf0f8081e57ca69e5e81ab0ac217 100644
--- a/doc/src/sgml/ref/alter_opclass.sgml
+++ b/doc/src/sgml/ref/alter_opclass.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/alter_opclass.sgml,v 1.4 2003/11/29 19:51:38 pgsql Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/alter_opclass.sgml,v 1.5 2004/06/25 21:55:50 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -21,6 +21,7 @@ PostgreSQL documentation
  <refsynopsisdiv>
 <synopsis>
 ALTER OPERATOR CLASS <replaceable>name</replaceable> USING <replaceable class="parameter">index_method</replaceable> RENAME TO <replaceable>newname</replaceable>
+ALTER OPERATOR CLASS <replaceable>name</replaceable> USING <replaceable class="parameter">index_method</replaceable> OWNER TO <replaceable>newowner</replaceable>
 </synopsis>
  </refsynopsisdiv>
   
@@ -29,8 +30,7 @@ ALTER OPERATOR CLASS <replaceable>name</replaceable> USING <replaceable class="p
 
   <para>
    <command>ALTER OPERATOR CLASS</command> changes the definition of
-   an operator class.  The only functionality is to rename the
-   operator class.
+   an operator class.
   </para>
  </refsect1>
   
@@ -65,7 +65,17 @@ ALTER OPERATOR CLASS <replaceable>name</replaceable> USING <replaceable class="p
      </para>
     </listitem>
    </varlistentry>
-  </variablelist>
+
+   <varlistentry>
+    <term><replaceable class="parameter">newowner</replaceable></term>
+    <listitem>
+     <para>
+      The new owner of the operator class.
+      You must be a superuser to change the owner of an operator class.
+     </para>
+    </listitem>
+   </varlistentry>
+ </variablelist>
  </refsect1>
 
  <refsect1>
diff --git a/doc/src/sgml/ref/alter_operator.sgml b/doc/src/sgml/ref/alter_operator.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..cfec153f2bbd47aecd575ff1d1f61c4eb2a8e674
--- /dev/null
+++ b/doc/src/sgml/ref/alter_operator.sgml
@@ -0,0 +1,127 @@
+<!--
+$PostgreSQL: pgsql/doc/src/sgml/ref/alter_operator.sgml,v 1.1 2004/06/25 21:55:50 tgl Exp $
+PostgreSQL documentation
+-->
+
+<refentry id="SQL-ALTEROPERATOR">
+ <refmeta>
+  <refentrytitle id="SQL-ALTEROPERATOR-TITLE">ALTER OPERATOR</refentrytitle>
+  <refmiscinfo>SQL - Language Statements</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+  <refname>ALTER OPERATOR</refname>
+  <refpurpose>change the definition of an operator</refpurpose>
+ </refnamediv>  
+  
+ <indexterm zone="sql-alteroperator">
+  <primary>ALTER OPERATOR</primary>
+ </indexterm>
+
+ <refsynopsisdiv>
+<synopsis>
+ALTER OPERATOR <replaceable>name</replaceable> ( { <replaceable>lefttype</replaceable> | NONE } , { <replaceable>righttype</replaceable> | NONE } ) OWNER TO <replaceable>newowner</replaceable>
+</synopsis>
+ </refsynopsisdiv>
+  
+ <refsect1>
+  <title>Description</title>
+
+  <para>
+   <command>ALTER OPERATOR</command> changes the definition of
+   an operator.  The only currently available functionality is to change the
+   owner of the operator.
+  </para>
+ </refsect1>
+  
+ <refsect1>
+  <title>Parameters</title>
+
+  <variablelist>
+   <varlistentry>
+    <term><replaceable class="parameter">name</replaceable></term>
+    <listitem>
+     <para>
+      The name (optionally schema-qualified) of an existing operator.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><replaceable class="parameter">lefttype</replaceable></term>
+    <listitem>
+     <para>
+      The data type of the operator's left operand; write
+      <literal>NONE</literal> if the operator has no left operand.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><replaceable class="parameter">righttype</replaceable></term>
+    <listitem>
+     <para>
+      The data type of the operator's right operand; write
+      <literal>NONE</literal> if the operator has no right operand.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><replaceable class="parameter">newowner</replaceable></term>
+    <listitem>
+     <para>
+      The new owner of the operator.
+      You must be a superuser to change the owner of an operator.
+     </para>
+    </listitem>
+   </varlistentry>
+  </variablelist>
+ </refsect1>
+
+ <refsect1>
+  <title>Examples</title>
+
+  <para>
+   Change the owner of a custom operator <literal>a @@ b</literal> for type <type>text</type>:
+<programlisting>
+ALTER OPERATOR @@ (text, text) OWNER TO joe;
+</programlisting>
+  </para>
+ </refsect1>
+ 
+ <refsect1>
+  <title>Compatibility</title>
+
+  <para>
+   There is no <command>ALTER OPERATOR</command> statement in
+   the SQL standard.
+  </para>
+ </refsect1>
+
+ <refsect1>
+  <title>See Also</title>
+
+  <simplelist type="inline">
+   <member><xref linkend="sql-createoperator" endterm="sql-createoperator-title"></member>
+   <member><xref linkend="sql-dropoperator" endterm="sql-dropoperator-title"></member>
+  </simplelist>
+ </refsect1>
+</refentry>
+
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-omittag:nil
+sgml-shorttag:t
+sgml-minimize-attributes:nil
+sgml-always-quote-attributes:t
+sgml-indent-step:1
+sgml-indent-data:t
+sgml-parent-document:nil
+sgml-default-dtd-file:"../reference.ced"
+sgml-exposed-tags:nil
+sgml-local-catalogs:"/usr/lib/sgml/catalog"
+sgml-local-ecat-files:nil
+End:
+-->
diff --git a/doc/src/sgml/ref/alter_schema.sgml b/doc/src/sgml/ref/alter_schema.sgml
index 866db7286890c5b4c69f22bb6bf2ac52f725d3f6..702df1da39608eb3fdd302730da16f4ee8d2fad6 100644
--- a/doc/src/sgml/ref/alter_schema.sgml
+++ b/doc/src/sgml/ref/alter_schema.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/alter_schema.sgml,v 1.6 2003/11/29 19:51:38 pgsql Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/alter_schema.sgml,v 1.7 2004/06/25 21:55:50 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -21,6 +21,7 @@ PostgreSQL documentation
  <refsynopsisdiv>
 <synopsis>
 ALTER SCHEMA <replaceable>name</replaceable> RENAME TO <replaceable>newname</replaceable>
+ALTER SCHEMA <replaceable>name</replaceable> OWNER TO <replaceable>newowner</replaceable>
 </synopsis>
  </refsynopsisdiv>
 
@@ -29,9 +30,9 @@ ALTER SCHEMA <replaceable>name</replaceable> RENAME TO <replaceable>newname</rep
 
   <para>
    <command>ALTER SCHEMA</command> changes the definition of a schema.
-   The only functionality is to rename the schema.  To rename a schema
-   you must own the schema and have the privilege
-   <literal>CREATE</literal> for the database.
+   To rename a schema you must own the schema and have the privilege
+   <literal>CREATE</literal> for the database.  To change the owner
+   of a schema, you must be a superuser.
   </para>
  </refsect1>
 
@@ -43,7 +44,7 @@ ALTER SCHEMA <replaceable>name</replaceable> RENAME TO <replaceable>newname</rep
     <term><replaceable>name</replaceable></term>
     <listitem>
      <para>
-      Name of a schema
+      The name of an existing schema.
      </para>
     </listitem>
    </varlistentry>
@@ -52,7 +53,18 @@ ALTER SCHEMA <replaceable>name</replaceable> RENAME TO <replaceable>newname</rep
     <term><replaceable>newname</replaceable></term>
     <listitem>
      <para>
-      The new name of the schema
+      The new name of the schema.  The new name cannot
+      begin with <literal>pg_</literal>, as such names
+      are reserved for system schemas.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><replaceable class="parameter">newowner</replaceable></term>
+    <listitem>
+     <para>
+      The new owner of the schema.
      </para>
     </listitem>
    </varlistentry>
diff --git a/doc/src/sgml/ref/alter_tablespace.sgml b/doc/src/sgml/ref/alter_tablespace.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..bdfe4b815532b5e1dc4d4d01f94721d7058e38f5
--- /dev/null
+++ b/doc/src/sgml/ref/alter_tablespace.sgml
@@ -0,0 +1,125 @@
+<!--
+$PostgreSQL: pgsql/doc/src/sgml/ref/alter_tablespace.sgml,v 1.1 2004/06/25 21:55:50 tgl Exp $
+PostgreSQL documentation
+-->
+
+<refentry id="SQL-ALTERTABLESPACE">
+ <refmeta>
+  <refentrytitle id="SQL-ALTERTABLESPACE-TITLE">ALTER TABLESPACE</refentrytitle>
+  <refmiscinfo>SQL - Language Statements</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+  <refname>ALTER TABLESPACE</refname>
+  <refpurpose>change the definition of a tablespace</refpurpose>
+ </refnamediv>  
+  
+ <indexterm zone="sql-altertablespace">
+  <primary>ALTER TABLESPACE</primary>
+ </indexterm>
+
+ <refsynopsisdiv>
+<synopsis>
+ALTER TABLESPACE <replaceable>name</replaceable> RENAME TO <replaceable>newname</replaceable>
+ALTER TABLESPACE <replaceable>name</replaceable> OWNER TO <replaceable>newowner</replaceable>
+</synopsis>
+ </refsynopsisdiv>
+  
+ <refsect1>
+  <title>Description</title>
+
+  <para>
+   <command>ALTER TABLESPACE</command> changes the definition of
+   a tablespace.
+  </para>
+ </refsect1>
+  
+ <refsect1>
+  <title>Parameters</title>
+
+  <variablelist>
+   <varlistentry>
+    <term><replaceable class="parameter">name</replaceable></term>
+    <listitem>
+     <para>
+      The name of an existing tablespace.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><replaceable class="parameter">newname</replaceable></term>
+    <listitem>
+     <para>
+      The new name of the tablespace.  The new name cannot
+      begin with <literal>pg_</literal>, as such names
+      are reserved for system tablespaces.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><replaceable class="parameter">newowner</replaceable></term>
+    <listitem>
+     <para>
+      The new owner of the tablespace.
+      You must be a superuser to change the owner of a tablespace.
+     </para>
+    </listitem>
+   </varlistentry>
+  </variablelist>
+ </refsect1>
+
+ <refsect1>
+  <title>Examples</title>
+
+  <para>
+   Rename tablespace <literal>index_space</literal> to <literal>fast_raid</literal>:
+<programlisting>
+ALTER TABLESPACE index_space RENAME TO fast_raid;
+</programlisting>
+  </para>
+
+  <para>
+   Change the owner of tablespace <literal>index_space</literal>:
+<programlisting>
+ALTER TABLESPACE index_space OWNER TO mary;
+</programlisting>
+  </para>
+ </refsect1>
+ 
+ <refsect1>
+  <title>Compatibility</title>
+
+  <para>
+   There is no <command>ALTER TABLESPACE</command> statement in
+   the SQL standard.
+  </para>
+ </refsect1>
+
+ <refsect1>
+  <title>See Also</title>
+
+  <simplelist type="inline">
+   <member><xref linkend="sql-createtablespace" endterm="sql-createtablespace-title"></member>
+   <member><xref linkend="sql-droptablespace" endterm="sql-droptablespace-title"></member>
+  </simplelist>
+ </refsect1>
+</refentry>
+
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-omittag:nil
+sgml-shorttag:t
+sgml-minimize-attributes:nil
+sgml-always-quote-attributes:t
+sgml-indent-step:1
+sgml-indent-data:t
+sgml-parent-document:nil
+sgml-default-dtd-file:"../reference.ced"
+sgml-exposed-tags:nil
+sgml-local-catalogs:"/usr/lib/sgml/catalog"
+sgml-local-ecat-files:nil
+End:
+-->
diff --git a/doc/src/sgml/ref/alter_type.sgml b/doc/src/sgml/ref/alter_type.sgml
new file mode 100644
index 0000000000000000000000000000000000000000..33830c04c0499e43095eacd7baffa30817b0e3ee
--- /dev/null
+++ b/doc/src/sgml/ref/alter_type.sgml
@@ -0,0 +1,106 @@
+<!--
+$PostgreSQL: pgsql/doc/src/sgml/ref/alter_type.sgml,v 1.1 2004/06/25 21:55:50 tgl Exp $
+PostgreSQL documentation
+-->
+
+<refentry id="SQL-ALTERTYPE">
+ <refmeta>
+  <refentrytitle id="sql-altertype-title">ALTER TYPE</refentrytitle>
+  <refmiscinfo>SQL - Language Statements</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+  <refname>
+   ALTER TYPE
+  </refname>
+  <refpurpose>
+   change the definition of a type
+  </refpurpose>
+ </refnamediv>
+
+ <indexterm zone="sql-altertype">
+  <primary>ALTER TYPE</primary>
+ </indexterm>
+
+ <refsynopsisdiv>
+  <synopsis>
+ALTER TYPE <replaceable class="PARAMETER">name</replaceable> OWNER TO <replaceable class="PARAMETER">new_owner</replaceable> 
+  </synopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+  <title>Description</title>
+
+  <para>
+   <command>ALTER TYPE</command> changes the definition of an existing type.
+   The only currently available capability is changing the owner of a type.
+  </para>
+ </refsect1>
+
+ <refsect1>
+  <title>Parameters</title>
+
+   <para>
+    <variablelist>
+     <varlistentry>
+      <term><replaceable class="PARAMETER">name</replaceable></term>
+      <listitem>
+       <para>
+        The name (possibly schema-qualified) of an existing type to
+        alter.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><replaceable class="PARAMETER">new_owner</replaceable></term>
+      <listitem>
+       <para>
+        The user name of the new owner of the type.
+        You must be a superuser to change a type's owner.
+       </para>
+      </listitem>
+     </varlistentry>
+
+    </variablelist>
+   </para>
+  </refsect1>
+
+ <refsect1>
+  <title>Examples</title>
+
+  <para> 
+   To change the owner of the user-defined type <literal>email</literal>
+   to <literal>joe</literal>:
+   <programlisting>
+ALTER TYPE email OWNER TO joe;
+   </programlisting>
+  </para>
+ </refsect1>
+
+ <refsect1>
+  <title>Compatibility</title>
+    
+  <para>
+   There is no <command>ALTER TYPE</command> statement in the SQL
+   standard.
+  </para>
+ </refsect1>
+</refentry>
+
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-omittag:nil
+sgml-shorttag:t
+sgml-minimize-attributes:nil
+sgml-always-quote-attributes:t
+sgml-indent-step:1
+sgml-indent-data:t
+sgml-parent-document:nil
+sgml-default-dtd-file:"../reference.ced"
+sgml-exposed-tags:nil
+sgml-local-catalogs:"/usr/lib/sgml/catalog"
+sgml-local-ecat-files:nil
+End:
+-->
diff --git a/doc/src/sgml/ref/create_operator.sgml b/doc/src/sgml/ref/create_operator.sgml
index 1001b8f33fb4e8310880c9d87058823b2731fa75..029d1af0d9009befee6c68d2079ec933cfb7ceb0 100644
--- a/doc/src/sgml/ref/create_operator.sgml
+++ b/doc/src/sgml/ref/create_operator.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/create_operator.sgml,v 1.41 2003/12/11 20:13:53 petere Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/create_operator.sgml,v 1.42 2004/06/25 21:55:50 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -109,13 +109,13 @@ CREATE OPERATOR <replaceable>name</replaceable> (
       <term><replaceable class="parameter">name</replaceable></term>
       <listitem>
        <para>
-	The name of the operator to be defined. See above for allowable
-	characters.  The name may be schema-qualified, for example
-	<literal>CREATE OPERATOR myschema.+ (...)</>.  If not, then
-	the operator is created in the current schema.  Two operators
-	in the same schema can have the same name if they operate on
-	different data types.  This is called
-	<firstterm>overloading</>.
+        The name of the operator to be defined. See above for allowable
+        characters.  The name may be schema-qualified, for example
+        <literal>CREATE OPERATOR myschema.+ (...)</>.  If not, then
+        the operator is created in the current schema.  Two operators
+        in the same schema can have the same name if they operate on
+        different data types.  This is called
+        <firstterm>overloading</>.
        </para>
       </listitem>
      </varlistentry>
@@ -124,7 +124,7 @@ CREATE OPERATOR <replaceable>name</replaceable> (
       <term><replaceable class="parameter">funcname</replaceable></term>
       <listitem>
        <para>
-	The function used to implement this operator.
+        The function used to implement this operator.
        </para>
       </listitem>
      </varlistentry>
@@ -133,8 +133,8 @@ CREATE OPERATOR <replaceable>name</replaceable> (
       <term><replaceable class="parameter">lefttype</replaceable></term>
       <listitem>
        <para>
-	The data type of the operator's left operand, if any.
-	This option would be omitted for a left-unary operator.
+        The data type of the operator's left operand, if any.
+        This option would be omitted for a left-unary operator.
        </para>
       </listitem>
      </varlistentry>
@@ -143,8 +143,8 @@ CREATE OPERATOR <replaceable>name</replaceable> (
       <term><replaceable class="parameter">righttype</replaceable></term>
       <listitem>
        <para>
-	The data type of the operator's right operand, if any.
-	This option would be omitted for a right-unary operator.
+        The data type of the operator's right operand, if any.
+        This option would be omitted for a right-unary operator.
        </para>
       </listitem>
      </varlistentry>
@@ -153,7 +153,7 @@ CREATE OPERATOR <replaceable>name</replaceable> (
       <term><replaceable class="parameter">com_op</replaceable></term>
       <listitem>
        <para>
-	The commutator of this operator.
+        The commutator of this operator.
        </para>
       </listitem>
      </varlistentry>
@@ -162,7 +162,7 @@ CREATE OPERATOR <replaceable>name</replaceable> (
       <term><replaceable class="parameter">neg_op</replaceable></term>
       <listitem>
        <para>
-	The negator of this operator.
+        The negator of this operator.
        </para>
       </listitem>
      </varlistentry>
@@ -171,7 +171,7 @@ CREATE OPERATOR <replaceable>name</replaceable> (
       <term><replaceable class="parameter">res_proc</replaceable></term>
       <listitem>
        <para>
-	The restriction selectivity estimator function for this operator.
+        The restriction selectivity estimator function for this operator.
        </para>
       </listitem>
      </varlistentry>
@@ -180,7 +180,7 @@ CREATE OPERATOR <replaceable>name</replaceable> (
       <term><replaceable class="parameter">join_proc</replaceable></term>
       <listitem>
        <para>
-	The join selectivity estimator function for this operator.
+        The join selectivity estimator function for this operator.
        </para>
       </listitem>
      </varlistentry>
@@ -207,8 +207,8 @@ CREATE OPERATOR <replaceable>name</replaceable> (
       <term><replaceable class="parameter">left_sort_op</replaceable></term>
       <listitem>
        <para>
-	If this operator can support a merge join, the less-than
-	operator that sorts the left-hand data type of this operator.
+        If this operator can support a merge join, the less-than
+        operator that sorts the left-hand data type of this operator.
        </para>
       </listitem>
      </varlistentry>
@@ -217,8 +217,8 @@ CREATE OPERATOR <replaceable>name</replaceable> (
       <term><replaceable class="parameter">right_sort_op</replaceable></term>
       <listitem>
        <para>
-	If this operator can support a merge join, the less-than
-	operator that sorts the right-hand data type of this operator.
+        If this operator can support a merge join, the less-than
+        operator that sorts the right-hand data type of this operator.
        </para>
       </listitem>
      </varlistentry>
@@ -227,8 +227,8 @@ CREATE OPERATOR <replaceable>name</replaceable> (
       <term><replaceable class="parameter">less_than_op</replaceable></term>
       <listitem>
        <para>
-	If this operator can support a merge join, the less-than
-	operator that compares the input data types of this operator.
+        If this operator can support a merge join, the less-than
+        operator that compares the input data types of this operator.
        </para>
       </listitem>
      </varlistentry>
@@ -237,8 +237,8 @@ CREATE OPERATOR <replaceable>name</replaceable> (
       <term><replaceable class="parameter">greater_than_op</replaceable></term>
       <listitem>
        <para>
-	If this operator can support a merge join, the greater-than
-	operator that compares the input data types of this operator.
+        If this operator can support a merge join, the greater-than
+        operator that compares the input data types of this operator.
        </para>
       </listitem>
      </varlistentry>
@@ -263,7 +263,8 @@ COMMUTATOR = OPERATOR(myschema.===) ,
 
   <para>
    Use <command>DROP OPERATOR</command> to delete user-defined
-   operators from a database.
+   operators from a database.  Use <command>ALTER OPERATOR</command>
+   to modify operators in a database.
   </para>
  </refsect1>
   
diff --git a/doc/src/sgml/ref/create_schema.sgml b/doc/src/sgml/ref/create_schema.sgml
index 8668612cc6aaa97cf273874e93bac21d196a1b6b..4f56341ce361a296e89c81e2809ec4863e0d4969 100644
--- a/doc/src/sgml/ref/create_schema.sgml
+++ b/doc/src/sgml/ref/create_schema.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/create_schema.sgml,v 1.12 2004/06/18 06:13:05 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/create_schema.sgml,v 1.13 2004/06/25 21:55:50 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -64,7 +64,9 @@ CREATE SCHEMA AUTHORIZATION <replaceable class="parameter">username</replaceable
       <listitem>
        <para>
         The name of a schema to be created.  If this is omitted, the user name
-        is used as the schema name.
+        is used as the schema name.  The name cannot
+        begin with <literal>pg_</literal>, as such names
+        are reserved for system schemas.
        </para>
       </listitem>
      </varlistentry>
diff --git a/doc/src/sgml/ref/create_tablespace.sgml b/doc/src/sgml/ref/create_tablespace.sgml
index 9f670a817d63b0773b1cde4270e76888b9319646..08ff4e3254bc937cc1674ff433be0d430e518ecd 100644
--- a/doc/src/sgml/ref/create_tablespace.sgml
+++ b/doc/src/sgml/ref/create_tablespace.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/create_tablespace.sgml,v 1.1 2004/06/18 06:13:05 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/create_tablespace.sgml,v 1.2 2004/06/25 21:55:50 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -56,7 +56,9 @@ CREATE TABLESPACE <replaceable class="parameter">tablespacename</replaceable> [
       <term><replaceable class="parameter">tablespacename</replaceable></term>
       <listitem>
        <para>
-        The name of a tablespace to be created.
+        The name of a tablespace to be created.  The name cannot
+        begin with <literal>pg_</literal>, as such names
+        are reserved for system tablespaces.
        </para>
       </listitem>
      </varlistentry>
@@ -133,6 +135,7 @@ CREATE TABLESPACE indexspace OWNER genevieve LOCATION '/data/indexes';
    <member><xref linkend="sql-createindex" endterm="sql-createindex-title"></member>
    <member><xref linkend="sql-createsequence" endterm="sql-createsequence-title"></member>
    <member><xref linkend="sql-droptablespace" endterm="sql-droptablespace-title"></member>
+   <member><xref linkend="sql-altertablespace" endterm="sql-altertablespace-title"></member>
   </simplelist>
  </refsect1>
 
diff --git a/doc/src/sgml/ref/create_type.sgml b/doc/src/sgml/ref/create_type.sgml
index b35a1805ca484d6d2f3e16402e450cc6782a4598..b7d1ac64e0aa0ae4c3efb93d9504275ad1530972 100644
--- a/doc/src/sgml/ref/create_type.sgml
+++ b/doc/src/sgml/ref/create_type.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/create_type.sgml,v 1.51 2004/06/06 00:41:25 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/create_type.sgml,v 1.52 2004/06/25 21:55:50 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -546,6 +546,7 @@ CREATE TABLE big_objs (
   <simplelist type="inline">
    <member><xref linkend="sql-createfunction" endterm="sql-createfunction-title"></member>
    <member><xref linkend="sql-droptype" endterm="sql-droptype-title"></member>
+   <member><xref linkend="sql-altertype" endterm="sql-altertype-title"></member>
   </simplelist>
  </refsect1>
 
diff --git a/doc/src/sgml/ref/drop_operator.sgml b/doc/src/sgml/ref/drop_operator.sgml
index 5b17ebec1b5bd508718199a2ea6c5ca7d77afe2f..b928e721936e3b13d4a86a7e2bd5c315cb5504ae 100644
--- a/doc/src/sgml/ref/drop_operator.sgml
+++ b/doc/src/sgml/ref/drop_operator.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/drop_operator.sgml,v 1.24 2003/12/02 00:26:59 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/drop_operator.sgml,v 1.25 2004/06/25 21:55:50 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -20,7 +20,7 @@ PostgreSQL documentation
 
  <refsynopsisdiv>
 <synopsis>
-DROP OPERATOR <replaceable class="PARAMETER">name</replaceable> ( <replaceable class="PARAMETER">lefttype</replaceable> | NONE , <replaceable class="PARAMETER">righttype</replaceable> | NONE ) [ CASCADE | RESTRICT ]
+DROP OPERATOR <replaceable class="PARAMETER">name</replaceable> ( { <replaceable class="PARAMETER">lefttype</replaceable> | NONE } , { <replaceable class="PARAMETER">righttype</replaceable> | NONE } ) [ CASCADE | RESTRICT ]
 </synopsis>
  </refsynopsisdiv>
 
@@ -128,6 +128,7 @@ DROP OPERATOR ! (bigint, none);
 
   <simplelist type="inline">
    <member><xref linkend="sql-createoperator" endterm="sql-createoperator-title"></member>
+   <member><xref linkend="sql-alteroperator" endterm="sql-alteroperator-title"></member>
   </simplelist>
  </refsect1>
 
diff --git a/doc/src/sgml/ref/drop_tablespace.sgml b/doc/src/sgml/ref/drop_tablespace.sgml
index ba8415208e3661d6160063410bae22681f343f61..bd4fb6dcd5e9899482fca13c2590471814b8bd8a 100644
--- a/doc/src/sgml/ref/drop_tablespace.sgml
+++ b/doc/src/sgml/ref/drop_tablespace.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/drop_tablespace.sgml,v 1.1 2004/06/18 06:13:05 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/drop_tablespace.sgml,v 1.2 2004/06/25 21:55:50 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -80,6 +80,7 @@ DROP TABLESPACE mystuff;
 
   <simplelist type="inline">
    <member><xref linkend="sql-createtablespace" endterm="sql-createtablespace-title"></member>
+   <member><xref linkend="sql-altertablespace" endterm="sql-altertablespace-title"></member>
   </simplelist>
  </refsect1>
 
diff --git a/doc/src/sgml/ref/drop_type.sgml b/doc/src/sgml/ref/drop_type.sgml
index 3ac172b5b4b5d2085b28b31d52d60b9dea050878..da0f6bc8b63f6d89919e1aec02e4800395f443ea 100644
--- a/doc/src/sgml/ref/drop_type.sgml
+++ b/doc/src/sgml/ref/drop_type.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/drop_type.sgml,v 1.25 2003/11/29 19:51:38 pgsql Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/drop_type.sgml,v 1.26 2004/06/25 21:55:50 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -95,6 +95,7 @@ DROP TYPE box;
 
   <simplelist type="inline">
    <member><xref linkend="sql-createtype" endterm="sql-createtype-title"></member>
+   <member><xref linkend="sql-altertype" endterm="sql-altertype-title"></member>
   </simplelist>
  </refsect1>
 
diff --git a/doc/src/sgml/reference.sgml b/doc/src/sgml/reference.sgml
index b5d42361ce76496c1066b7da09054b1e983ba93e..5230e07119e98d0c4eb0c6e65df90298ed705ff2 100644
--- a/doc/src/sgml/reference.sgml
+++ b/doc/src/sgml/reference.sgml
@@ -1,5 +1,5 @@
 <!-- reference.sgml
-$PostgreSQL: pgsql/doc/src/sgml/reference.sgml,v 1.49 2004/06/18 21:24:04 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/reference.sgml,v 1.50 2004/06/25 21:55:51 tgl Exp $
 
 PostgreSQL Reference Manual
 -->
@@ -45,11 +45,14 @@ PostgreSQL Reference Manual
    &alterFunction;
    &alterGroup;
    &alterLanguage;
+   &alterOperator;
    &alterOperatorClass;
    &alterSchema;
    &alterSequence;
    &alterTable;
+   &alterTableSpace;
    &alterTrigger;
+   &alterType;
    &alterUser;
    &analyze;
    &begin;
diff --git a/src/backend/commands/aggregatecmds.c b/src/backend/commands/aggregatecmds.c
index c8865b3dbde3851708699a5d66edfc638af29707..a787f7ad43fffef162841999a0c0ceadcce9562f 100644
--- a/src/backend/commands/aggregatecmds.c
+++ b/src/backend/commands/aggregatecmds.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/aggregatecmds.c,v 1.18 2004/05/26 04:41:09 neilc Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/aggregatecmds.c,v 1.19 2004/06/25 21:55:53 tgl Exp $
  *
  * DESCRIPTION
  *	  The "DefineFoo" routines take the parse tree and pick out the
@@ -223,10 +223,9 @@ RenameAggregate(List *name, TypeName *basetype, const char *newname)
 
 	/*
 	 * if a basetype is passed in, then attempt to find an aggregate for
-	 * that specific type.
-	 *
-	 * else attempt to find an aggregate with a basetype of ANYOID. This
-	 * means that the aggregate is to apply to all basetypes (eg, COUNT).
+	 * that specific type; else attempt to find an aggregate with a basetype
+	 * of ANYOID. This means that the aggregate applies to all basetypes
+	 * (eg, COUNT).
 	 */
 	if (basetype)
 		basetypeOid = typenameTypeId(basetype);
@@ -288,3 +287,60 @@ RenameAggregate(List *name, TypeName *basetype, const char *newname)
 	heap_close(rel, NoLock);
 	heap_freetuple(tup);
 }
+
+/*
+ * Change aggregate owner
+ */
+void
+AlterAggregateOwner(List *name, TypeName *basetype, AclId newOwnerSysId)
+{
+	Oid			basetypeOid;
+	Oid			procOid;
+	HeapTuple	tup;
+	Form_pg_proc procForm;
+	Relation	rel;
+
+	/*
+	 * if a basetype is passed in, then attempt to find an aggregate for
+	 * that specific type; else attempt to find an aggregate with a basetype
+	 * of ANYOID. This means that the aggregate applies to all basetypes
+	 * (eg, COUNT).
+	 */
+	if (basetype)
+		basetypeOid = typenameTypeId(basetype);
+	else
+		basetypeOid = ANYOID;
+
+	rel = heap_openr(ProcedureRelationName, RowExclusiveLock);
+
+	procOid = find_aggregate_func(name, basetypeOid, false);
+
+	tup = SearchSysCacheCopy(PROCOID,
+							 ObjectIdGetDatum(procOid),
+							 0, 0, 0);
+	if (!HeapTupleIsValid(tup)) /* should not happen */
+		elog(ERROR, "cache lookup failed for function %u", procOid);
+	procForm = (Form_pg_proc) GETSTRUCT(tup);
+
+	/* 
+	 * If the new owner is the same as the existing owner, consider the
+	 * command to have succeeded.  This is for dump restoration purposes.
+	 */
+	if (procForm->proowner != newOwnerSysId)
+	{
+		/* Otherwise, must be superuser to change object ownership */
+		if (!superuser())
+			ereport(ERROR,
+					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+					 errmsg("must be superuser to change owner")));
+
+		/* Modify the owner --- okay to scribble on tup because it's a copy */
+		procForm->proowner = newOwnerSysId;
+
+		simple_heap_update(rel, &tup->t_self, tup);
+		CatalogUpdateIndexes(rel, tup);
+	}
+
+	heap_close(rel, NoLock);
+	heap_freetuple(tup);
+}
diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c
index 40a28103c77c07199912b9d89f85fa25ae3e48a0..50516e1f0465d877254634c6c04eea3c26497b75 100644
--- a/src/backend/commands/alter.c
+++ b/src/backend/commands/alter.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/alter.c,v 1.7 2004/05/26 04:41:09 neilc Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/alter.c,v 1.8 2004/06/25 21:55:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -25,7 +25,9 @@
 #include "commands/proclang.h"
 #include "commands/schemacmds.h"
 #include "commands/tablecmds.h"
+#include "commands/tablespace.h"
 #include "commands/trigger.h"
+#include "commands/typecmds.h"
 #include "commands/user.h"
 #include "miscadmin.h"
 #include "parser/parse_clause.h"
@@ -35,6 +37,10 @@
 #include "utils/syscache.h"
 
 
+/*
+ * Executes an ALTER OBJECT / RENAME TO statement.  Based on the object
+ * type, the function appropriate to that type is executed.
+ */
 void
 ExecRenameStmt(RenameStmt *stmt)
 {
@@ -74,6 +80,10 @@ ExecRenameStmt(RenameStmt *stmt)
 			RenameSchema(stmt->subname, stmt->newname);
 			break;
 
+		case OBJECT_TABLESPACE:
+			RenameTableSpace(stmt->subname, stmt->newname);
+			break;
+
 		case OBJECT_USER:
 			RenameUser(stmt->subname, stmt->newname);
 			break;
@@ -133,3 +143,62 @@ ExecRenameStmt(RenameStmt *stmt)
 				 (int) stmt->renameType);
 	}
 }
+
+/*
+ * Executes an ALTER OBJECT / OWNER TO statement.  Based on the object
+ * type, the function appropriate to that type is executed.
+ */
+void
+ExecAlterOwnerStmt(AlterOwnerStmt *stmt)
+{
+	AclId	newowner = get_usesysid(stmt->newowner);
+
+	switch (stmt->objectType)
+	{
+		case OBJECT_AGGREGATE:
+			AlterAggregateOwner(stmt->object,
+								(TypeName *) linitial(stmt->objarg),
+								newowner);
+			break;
+
+		case OBJECT_CONVERSION:
+			AlterConversionOwner(stmt->object, newowner);
+			break;
+
+		case OBJECT_DATABASE:
+			AlterDatabaseOwner((char *) linitial(stmt->object), newowner);
+			break;
+
+		case OBJECT_FUNCTION:
+			AlterFunctionOwner(stmt->object, stmt->objarg, newowner);
+			break;
+
+		case OBJECT_OPERATOR:
+			AlterOperatorOwner(stmt->object,
+							   (TypeName *) linitial(stmt->objarg),
+							   (TypeName *) lsecond(stmt->objarg),
+							   newowner);
+			break;
+
+		case OBJECT_OPCLASS:
+			AlterOpClassOwner(stmt->object, stmt->addname, newowner);
+			break;
+
+		case OBJECT_SCHEMA:
+			AlterSchemaOwner((char *) linitial(stmt->object), newowner);
+			break;
+
+		case OBJECT_TABLESPACE:
+			AlterTableSpaceOwner((char *) linitial(stmt->object), newowner);
+			break;
+
+		case OBJECT_TYPE:
+		case OBJECT_DOMAIN:		/* same as TYPE */
+			AlterTypeOwner(stmt->object, newowner);
+			break;
+
+		default:
+			elog(ERROR, "unrecognized AlterOwnerStmt type: %d",
+				 (int) stmt->objectType);
+	}
+}
diff --git a/src/backend/commands/conversioncmds.c b/src/backend/commands/conversioncmds.c
index 1e55398f86ea2141b8982fd767144e2cc22310e4..298085f160b842887ede1fef1dea6a52b0e71fef 100644
--- a/src/backend/commands/conversioncmds.c
+++ b/src/backend/commands/conversioncmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/conversioncmds.c,v 1.12 2003/11/29 19:51:47 pgsql Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/conversioncmds.c,v 1.13 2004/06/25 21:55:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -171,3 +171,55 @@ RenameConversion(List *name, const char *newname)
 	heap_close(rel, NoLock);
 	heap_freetuple(tup);
 }
+
+/*
+ * Change conversion owner
+ */
+void
+AlterConversionOwner(List *name, AclId newOwnerSysId)
+{
+	Oid			conversionOid;
+	HeapTuple	tup;
+	Relation	rel;
+	Form_pg_conversion	convForm;
+
+	rel = heap_openr(ConversionRelationName, RowExclusiveLock);
+
+	conversionOid = FindConversionByName(name);
+	if (!OidIsValid(conversionOid))
+		ereport(ERROR,
+				(errcode(ERRCODE_UNDEFINED_OBJECT),
+				 errmsg("conversion \"%s\" does not exist",
+						NameListToString(name))));
+
+	tup = SearchSysCacheCopy(CONOID,
+							 ObjectIdGetDatum(conversionOid),
+							 0, 0, 0);
+	if (!HeapTupleIsValid(tup)) /* should not happen */
+		elog(ERROR, "cache lookup failed for conversion %u", conversionOid);
+
+	convForm = (Form_pg_conversion) GETSTRUCT(tup);
+
+	/* 
+	 * If the new owner is the same as the existing owner, consider the
+	 * command to have succeeded.  This is for dump restoration purposes.
+	 */
+	if (convForm->conowner != newOwnerSysId)
+	{
+		/* Otherwise, must be superuser to change object ownership */
+		if (!superuser())
+			ereport(ERROR,
+					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+					 errmsg("must be superuser to change owner")));
+
+		/* Modify the owner --- okay to scribble on tup because it's a copy */
+		convForm->conowner = newOwnerSysId;
+
+		simple_heap_update(rel, &tup->t_self, tup);
+
+		CatalogUpdateIndexes(rel, tup);
+	}
+
+	heap_close(rel, NoLock);
+	heap_freetuple(tup);
+}
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index 8fbebecd8744beb6a059e442ec6fe471b249d075..b9e8c83627437757a8cc13ba3a912146aa1180a0 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.136 2004/06/18 06:13:22 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.137 2004/06/25 21:55:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -666,7 +666,7 @@ RenameDatabase(const char *oldname, const char *newname)
 	/* rename */
 	newtup = heap_copytuple(tup);
 	namestrcpy(&(((Form_pg_database) GETSTRUCT(newtup))->datname), newname);
-	simple_heap_update(rel, &tup->t_self, newtup);
+	simple_heap_update(rel, &newtup->t_self, newtup);
 	CatalogUpdateIndexes(rel, newtup);
 
 	systable_endscan(scan);
@@ -758,7 +758,7 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt)
 	CatalogUpdateIndexes(rel, newtuple);
 
 	systable_endscan(scan);
-	heap_close(rel, RowExclusiveLock);
+	heap_close(rel, NoLock);
 }
 
 
@@ -766,14 +766,14 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt)
  * ALTER DATABASE name OWNER TO newowner
  */
 void
-AlterDatabaseOwner(const char *dbname, const char *newowner)
+AlterDatabaseOwner(const char *dbname, AclId newOwnerSysId)
 {
-	AclId		newdatdba;
 	HeapTuple	tuple,
 				newtuple;
 	Relation	rel;
 	ScanKeyData scankey;
 	SysScanDesc scan;
+	Form_pg_database	datForm;
 
 	rel = heap_openr(DatabaseRelationName, RowExclusiveLock);
 	ScanKeyInit(&scankey,
@@ -788,21 +788,27 @@ AlterDatabaseOwner(const char *dbname, const char *newowner)
 				(errcode(ERRCODE_UNDEFINED_DATABASE),
 				 errmsg("database \"%s\" does not exist", dbname)));
 
-	/* obtain sysid of proposed owner */
-	newdatdba = get_usesysid(newowner); /* will ereport if no such user */
+	newtuple = heap_copytuple(tuple);
+	datForm = (Form_pg_database) GETSTRUCT(newtuple);
 
-	/* changing owner's database for someone else: must be superuser */
-	/* note that the someone else need not have any permissions */
-	if (!superuser())
-		ereport(ERROR,
-				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-				 errmsg("must be superuser to change owner's database for another user")));
+	/* 
+	 * If the new owner is the same as the existing owner, consider the
+	 * command to have succeeded.  This is to be consistent with other objects.
+	 */
+	if (datForm->datdba != newOwnerSysId)
+	{
+		/* changing owner's database for someone else: must be superuser */
+		/* note that the someone else need not have any permissions */
+		if (!superuser())
+			ereport(ERROR,
+					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+					 errmsg("must be superuser to change owner")));
 
-	/* change owner */
-	newtuple = heap_copytuple(tuple);
-	((Form_pg_database) GETSTRUCT(newtuple))->datdba = newdatdba;
-	simple_heap_update(rel, &tuple->t_self, newtuple);
-	CatalogUpdateIndexes(rel, newtuple);
+		/* change owner */
+		datForm->datdba = newOwnerSysId;
+		simple_heap_update(rel, &newtuple->t_self, newtuple);
+		CatalogUpdateIndexes(rel, newtuple);
+	}
 
 	systable_endscan(scan);
 	heap_close(rel, NoLock);
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 7747eb1d7766ed2e3aa34ed3b988b6cccd253c0b..20ee9fa3445bd01f86fd8e78a9ab445837431df6 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.48 2004/06/16 01:26:42 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.49 2004/06/25 21:55:53 tgl Exp $
  *
  * DESCRIPTION
  *	  These routines take the parse tree and pick out the
@@ -723,6 +723,60 @@ RenameFunction(List *name, List *argtypes, const char *newname)
 	heap_freetuple(tup);
 }
 
+/*
+ * Change function owner
+ */
+void
+AlterFunctionOwner(List *name, List *argtypes, AclId newOwnerSysId)
+{
+	Oid			procOid;
+	HeapTuple	tup;
+	Form_pg_proc procForm;
+	Relation	rel;
+
+	rel = heap_openr(ProcedureRelationName, RowExclusiveLock);
+
+	procOid = LookupFuncNameTypeNames(name, argtypes, false);
+
+	tup = SearchSysCacheCopy(PROCOID,
+							 ObjectIdGetDatum(procOid),
+							 0, 0, 0);
+	if (!HeapTupleIsValid(tup)) /* should not happen */
+		elog(ERROR, "cache lookup failed for function %u", procOid);
+	procForm = (Form_pg_proc) GETSTRUCT(tup);
+
+	if (procForm->proisagg)
+		ereport(ERROR,
+				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+				 errmsg("\"%s\" is an aggregate function",
+						NameListToString(name)),
+		 errhint("Use ALTER AGGREGATE to change owner of aggregate functions.")));
+
+	/* 
+	 * If the new owner is the same as the existing owner, consider the
+	 * command to have succeeded.  This is for dump restoration purposes.
+	 */
+	if (procForm->proowner != newOwnerSysId)
+	{
+		/* Otherwise, must be superuser to change object ownership */
+		if (!superuser())
+			ereport(ERROR,
+					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+					 errmsg("must be superuser to change owner")));
+
+		/* Modify the owner --- okay to scribble on tup because it's a copy */
+		procForm->proowner = newOwnerSysId;
+
+		simple_heap_update(rel, &tup->t_self, tup);
+
+		CatalogUpdateIndexes(rel, tup);
+	}
+
+	heap_close(rel, NoLock);
+	heap_freetuple(tup);
+}
+
+
 
 /*
  * SetFunctionReturnType - change declared return type of a function
diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c
index db5c2ccabc92a67927dcbf8a391a79848a99469a..d9c0c1deade0a8fbeee12bd57959f01ec1a44de9 100644
--- a/src/backend/commands/opclasscmds.c
+++ b/src/backend/commands/opclasscmds.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/opclasscmds.c,v 1.25 2004/05/26 04:41:11 neilc Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/opclasscmds.c,v 1.26 2004/06/25 21:55:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -871,3 +871,92 @@ RenameOpClass(List *name, const char *access_method, const char *newname)
 	heap_close(rel, NoLock);
 	heap_freetuple(tup);
 }
+
+/*
+ * Change opclass owner
+ */
+void
+AlterOpClassOwner(List *name, const char *access_method, AclId newOwnerSysId)
+{
+	Oid			opcOid;
+	Oid			amOid;
+	Oid			namespaceOid;
+	char	   *schemaname;
+	char	   *opcname;
+	HeapTuple	tup;
+	Relation	rel;
+	Form_pg_opclass	opcForm;
+
+	amOid = GetSysCacheOid(AMNAME,
+						   CStringGetDatum(access_method),
+						   0, 0, 0);
+	if (!OidIsValid(amOid))
+		ereport(ERROR,
+				(errcode(ERRCODE_UNDEFINED_OBJECT),
+				 errmsg("access method \"%s\" does not exist",
+						access_method)));
+
+	rel = heap_openr(OperatorClassRelationName, RowExclusiveLock);
+
+	/*
+	 * Look up the opclass
+	 */
+	DeconstructQualifiedName(name, &schemaname, &opcname);
+
+	if (schemaname)
+	{
+		namespaceOid = LookupExplicitNamespace(schemaname);
+
+		tup = SearchSysCacheCopy(CLAAMNAMENSP,
+								 ObjectIdGetDatum(amOid),
+								 PointerGetDatum(opcname),
+								 ObjectIdGetDatum(namespaceOid),
+								 0);
+		if (!HeapTupleIsValid(tup))
+			ereport(ERROR,
+					(errcode(ERRCODE_UNDEFINED_OBJECT),
+					 errmsg("operator class \"%s\" does not exist for access method \"%s\"",
+							opcname, access_method)));
+
+	}
+	else
+	{
+		opcOid = OpclassnameGetOpcid(amOid, opcname);
+		if (!OidIsValid(opcOid))
+			ereport(ERROR,
+					(errcode(ERRCODE_UNDEFINED_OBJECT),
+					 errmsg("operator class \"%s\" does not exist for access method \"%s\"",
+							opcname, access_method)));
+
+		tup = SearchSysCacheCopy(CLAOID,
+								 ObjectIdGetDatum(opcOid),
+								 0, 0, 0);
+		if (!HeapTupleIsValid(tup))		/* should not happen */
+			elog(ERROR, "cache lookup failed for opclass %u", opcOid);
+		namespaceOid = ((Form_pg_opclass) GETSTRUCT(tup))->opcnamespace;
+	}
+	opcForm = (Form_pg_opclass) GETSTRUCT(tup);
+
+	/* 
+	 * If the new owner is the same as the existing owner, consider the
+	 * command to have succeeded.  This is for dump restoration purposes.
+	 */
+	if (opcForm->opcowner != newOwnerSysId)
+	{
+		/* Otherwise, must be superuser to change object ownership */
+		if (!superuser())
+			ereport(ERROR,
+					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+					 errmsg("must be superuser to change owner")));
+
+		/* Modify the owner --- okay to scribble on tup because it's a copy */
+		opcForm->opcowner = newOwnerSysId;
+
+		simple_heap_update(rel, &tup->t_self, tup);
+
+		CatalogUpdateIndexes(rel, tup);
+	}
+
+	heap_close(rel, NoLock);
+	heap_freetuple(tup);
+}
diff --git a/src/backend/commands/operatorcmds.c b/src/backend/commands/operatorcmds.c
index d2ffae2ce56ea39c94b54b5fcc36b440b43f9fa9..8fbe0d1128bf83ed50bac5b9ac8db7b464d0e7c1 100644
--- a/src/backend/commands/operatorcmds.c
+++ b/src/backend/commands/operatorcmds.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/operatorcmds.c,v 1.16 2004/05/26 04:41:11 neilc Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/operatorcmds.c,v 1.17 2004/06/25 21:55:53 tgl Exp $
  *
  * DESCRIPTION
  *	  The "DefineFoo" routines take the parse tree and pick out the
@@ -37,6 +37,7 @@
 #include "access/heapam.h"
 #include "catalog/catname.h"
 #include "catalog/dependency.h"
+#include "catalog/indexing.h"
 #include "catalog/namespace.h"
 #include "catalog/pg_operator.h"
 #include "commands/defrem.h"
@@ -263,3 +264,55 @@ RemoveOperatorById(Oid operOid)
 
 	heap_close(relation, RowExclusiveLock);
 }
+
+/*
+ * change operator owner
+ */
+void
+AlterOperatorOwner(List *name, TypeName *typeName1, TypeName *typeName2,
+				   AclId newOwnerSysId)
+{
+	Oid			operOid;
+	HeapTuple	tup;
+	Relation	rel;
+	Form_pg_operator	oprForm;
+
+	rel = heap_openr(OperatorRelationName, RowExclusiveLock);
+
+	operOid = LookupOperNameTypeNames(name, typeName1, typeName2,
+									  false);
+
+	tup = SearchSysCacheCopy(OPEROID,
+						 ObjectIdGetDatum(operOid),
+						 0, 0, 0);
+	if (!HeapTupleIsValid(tup)) /* should not happen */
+		elog(ERROR, "cache lookup failed for operator %u", operOid);
+
+	oprForm = (Form_pg_operator) GETSTRUCT(tup);
+
+	/* 
+	 * If the new owner is the same as the existing owner, consider the
+	 * command to have succeeded.  This is for dump restoration purposes.
+	 */
+	if (oprForm->oprowner != newOwnerSysId)
+	{
+		/* Otherwise, must be superuser to change object ownership */
+		if (!superuser())
+			ereport(ERROR,
+					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+					 errmsg("must be superuser to change owner")));
+
+		/* Modify the owner --- okay to scribble on tup because it's a copy */
+		oprForm->oprowner = newOwnerSysId;
+
+		simple_heap_update(rel, &tup->t_self, tup);
+
+		CatalogUpdateIndexes(rel, tup);
+	}
+
+	heap_close(rel, NoLock);
+	heap_freetuple(tup);
+
+}
+
+
diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c
index 8366ea634a024345550839f5456455a515afa3a3..35e18c9bfbd3df7739ca81c3fa7d7b4a014a9e65 100644
--- a/src/backend/commands/schemacmds.c
+++ b/src/backend/commands/schemacmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/schemacmds.c,v 1.19 2004/06/18 06:13:23 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/schemacmds.c,v 1.20 2004/06/25 21:55:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -307,3 +307,48 @@ RenameSchema(const char *oldname, const char *newname)
 	heap_close(rel, NoLock);
 	heap_freetuple(tup);
 }
+
+/*
+ * Change schema owner
+ */
+void
+AlterSchemaOwner(const char *name, AclId newOwnerSysId)
+{
+	HeapTuple	tup;
+	Relation	rel;
+	Form_pg_namespace	nspForm;
+
+	rel = heap_openr(NamespaceRelationName, RowExclusiveLock);
+
+	tup = SearchSysCacheCopy(NAMESPACENAME,
+							 CStringGetDatum(name),
+							 0, 0, 0);
+	if (!HeapTupleIsValid(tup))
+		ereport(ERROR,
+				(errcode(ERRCODE_UNDEFINED_SCHEMA),
+				 errmsg("schema \"%s\" does not exist", name)));
+	nspForm = (Form_pg_namespace) GETSTRUCT(tup);
+
+	/* 
+	 * If the new owner is the same as the existing owner, consider the
+	 * command to have succeeded.  This is for dump restoration purposes.
+	 */
+	if (nspForm->nspowner != newOwnerSysId)
+	{
+		/* Otherwise, must be superuser to change object ownership */
+		if (!superuser())
+			ereport(ERROR,
+					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+					 errmsg("must be superuser to change owner")));
+
+		/* Modify the owner --- okay to scribble on tup because it's a copy */
+		nspForm->nspowner = newOwnerSysId;
+
+		simple_heap_update(rel, &tup->t_self, tup);
+
+		CatalogUpdateIndexes(rel, tup);
+	}
+
+	heap_close(rel, NoLock);
+	heap_freetuple(tup);
+}
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 8fd07e396aee850737729d63d7a16f133097a8e0..cfd8bd80cc0e6f41ff2d42996b3d127070426566 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.116 2004/06/18 06:13:23 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.117 2004/06/25 21:55:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1921,11 +1921,6 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
 			pass = AT_PASS_MISC;
 			break;
 		case AT_ChangeOwner:	/* ALTER OWNER */
-			/* check that we are the superuser */
-			if (!superuser())
-				ereport(ERROR,
-					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-				errmsg("must be superuser to alter owner")));
 			/* This command never recurses */
 			/* No command-specific prep needed */
 			pass = AT_PASS_MISC;
@@ -5097,42 +5092,55 @@ ATExecChangeOwner(Oid relationOid, int32 newOwnerSysId)
 							NameStr(tuple_class->relname))));
 	}
 
-	/*
-	 * Okay, this is a valid tuple: change its ownership and write to the
-	 * heap.
+	/* 
+	 * If the new owner is the same as the existing owner, consider the
+	 * command to have succeeded.  This is for dump restoration purposes.
 	 */
-	tuple_class->relowner = newOwnerSysId;
-	simple_heap_update(class_rel, &tuple->t_self, tuple);
+	if (tuple_class->relowner != newOwnerSysId)
+	{
+		/* Otherwise, check that we are the superuser */
+		if (!superuser())
+			ereport(ERROR,
+				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+			errmsg("must be superuser to change owner")));
 
-	/* Keep the catalog indexes up to date */
-	CatalogUpdateIndexes(class_rel, tuple);
+		/*
+		 * Okay, this is a valid tuple: change its ownership and write to the
+		 * heap.
+		 */
+		tuple_class->relowner = newOwnerSysId;
+		simple_heap_update(class_rel, &tuple->t_self, tuple);
 
-	/*
-	 * If we are operating on a table, also change the ownership of any
-	 * indexes that belong to the table, as well as the table's toast
-	 * table (if it has one)
-	 */
-	if (tuple_class->relkind == RELKIND_RELATION ||
-		tuple_class->relkind == RELKIND_TOASTVALUE)
-	{
-		List	   *index_oid_list;
-		ListCell   *i;
+		/* Keep the catalog indexes up to date */
+		CatalogUpdateIndexes(class_rel, tuple);
 
-		/* Find all the indexes belonging to this relation */
-		index_oid_list = RelationGetIndexList(target_rel);
+		/*
+		 * If we are operating on a table, also change the ownership of any
+		 * indexes that belong to the table, as well as the table's toast
+		 * table (if it has one)
+		 */
+		if (tuple_class->relkind == RELKIND_RELATION ||
+			tuple_class->relkind == RELKIND_TOASTVALUE)
+		{
+			List	   *index_oid_list;
+			ListCell   *i;
 
-		/* For each index, recursively change its ownership */
-		foreach(i, index_oid_list)
-			ATExecChangeOwner(lfirst_oid(i), newOwnerSysId);
+			/* Find all the indexes belonging to this relation */
+			index_oid_list = RelationGetIndexList(target_rel);
 
-		list_free(index_oid_list);
-	}
+			/* For each index, recursively change its ownership */
+			foreach(i, index_oid_list)
+				ATExecChangeOwner(lfirst_oid(i), newOwnerSysId);
 
-	if (tuple_class->relkind == RELKIND_RELATION)
-	{
-		/* If it has a toast table, recurse to change its ownership */
-		if (tuple_class->reltoastrelid != InvalidOid)
-			ATExecChangeOwner(tuple_class->reltoastrelid, newOwnerSysId);
+			list_free(index_oid_list);
+		}
+
+		if (tuple_class->relkind == RELKIND_RELATION)
+		{
+			/* If it has a toast table, recurse to change its ownership */
+			if (tuple_class->reltoastrelid != InvalidOid)
+				ATExecChangeOwner(tuple_class->reltoastrelid, newOwnerSysId);
+		}
 	}
 
 	heap_freetuple(tuple);
diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c
index 61e36d5b5c2deaf3483022fc4d0e817c69da4abf..847985456f7007ea2f91064646c3318fefeafd7e 100644
--- a/src/backend/commands/tablespace.c
+++ b/src/backend/commands/tablespace.c
@@ -45,7 +45,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.3 2004/06/21 04:06:06 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.4 2004/06/25 21:55:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -669,3 +669,123 @@ get_tablespace_name(Oid spc_oid)
 
 	return result;
 }
+
+/*
+ * Rename a tablespace
+ */
+void
+RenameTableSpace(const char *oldname, const char *newname)
+{
+	Relation rel;
+	ScanKeyData	entry[1];
+	HeapScanDesc scan;
+	HeapTuple	tup;
+	HeapTuple	newtuple;
+	Form_pg_tablespace newform;
+
+	/* Search pg_tablespace */
+	rel = heap_openr(TableSpaceRelationName, RowExclusiveLock);
+
+	ScanKeyInit(&entry[0],
+				Anum_pg_tablespace_spcname,
+				BTEqualStrategyNumber, F_NAMEEQ,
+				CStringGetDatum(oldname));
+	scan = heap_beginscan(rel, SnapshotNow, 1, entry);
+	tup = heap_getnext(scan, ForwardScanDirection);
+	if (!HeapTupleIsValid(tup))
+		ereport(ERROR,
+				(errcode(ERRCODE_UNDEFINED_OBJECT),
+				 errmsg("tablespace \"%s\" does not exist",
+						oldname)));
+
+	newtuple = heap_copytuple(tup);
+	newform = (Form_pg_tablespace) GETSTRUCT(newtuple);
+
+	heap_endscan(scan);
+
+	/* Must be owner or superuser */
+	if (newform->spcowner != GetUserId() && !superuser())
+		aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_TABLESPACE, oldname);
+
+	/* Validate new name */
+	if (!allowSystemTableMods && IsReservedName(newname))
+		ereport(ERROR,
+				(errcode(ERRCODE_RESERVED_NAME),
+				 errmsg("unacceptable tablespace name \"%s\"", newname),
+		errdetail("The prefix \"pg_\" is reserved for system tablespaces.")));
+
+	/* Make sure the new name doesn't exist */
+	ScanKeyInit(&entry[0],
+				Anum_pg_tablespace_spcname,
+				BTEqualStrategyNumber, F_NAMEEQ,
+				CStringGetDatum(newname));
+	scan = heap_beginscan(rel, SnapshotNow, 1, entry);
+	tup = heap_getnext(scan, ForwardScanDirection);
+	if (HeapTupleIsValid(tup))
+		ereport(ERROR,
+				(errcode(ERRCODE_DUPLICATE_OBJECT),
+				 errmsg("tablespace \"%s\" already exists",
+						newname)));
+	
+	heap_endscan(scan);
+
+	/* OK, update the entry */
+	namestrcpy(&(newform->spcname), newname);
+
+	simple_heap_update(rel, &newtuple->t_self, newtuple);
+	CatalogUpdateIndexes(rel, newtuple);
+
+	heap_close(rel, NoLock);
+}
+
+/*
+ * Change tablespace owner
+ */
+void
+AlterTableSpaceOwner(const char *name, AclId newOwnerSysId)
+{
+	Relation rel;
+	ScanKeyData	entry[1];
+	HeapScanDesc scandesc;
+	Form_pg_tablespace spcForm;
+	HeapTuple	tup;
+	HeapTuple	newtuple;
+
+	/* Search pg_tablespace */
+	rel = heap_openr(TableSpaceRelationName, RowExclusiveLock);
+
+	ScanKeyInit(&entry[0],
+				Anum_pg_tablespace_spcname,
+				BTEqualStrategyNumber, F_NAMEEQ,
+				CStringGetDatum(name));
+	scandesc = heap_beginscan(rel, SnapshotNow, 1, entry);
+	tup = heap_getnext(scandesc, ForwardScanDirection);
+	if (!HeapTupleIsValid(tup))
+		ereport(ERROR,
+				(errcode(ERRCODE_UNDEFINED_OBJECT),
+				 errmsg("tablespace \"%s\" does not exist", name)));
+
+	newtuple = heap_copytuple(tup);
+	spcForm = (Form_pg_tablespace) GETSTRUCT(newtuple);
+
+	/* 
+	 * If the new owner is the same as the existing owner, consider the
+	 * command to have succeeded.  This is for dump restoration purposes.
+	 */
+	if (spcForm->spcowner != newOwnerSysId)
+	{
+		/* Otherwise, must be superuser to change object ownership */
+		if (!superuser())
+			ereport(ERROR,
+					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+					 errmsg("must be superuser to change owner")));
+
+		/* Modify the owner */
+		spcForm->spcowner = newOwnerSysId;
+		simple_heap_update(rel, &newtuple->t_self, newtuple);
+		CatalogUpdateIndexes(rel, newtuple);
+	}
+
+	heap_endscan(scandesc);
+	heap_close(rel, NoLock);
+}
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index d087ad8895cb4145c8e3bce3d0f85caa12c9f22e..f9f1caa863074dfa4030906b0d8c2d80ddd73013 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.60 2004/06/18 06:13:23 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.61 2004/06/25 21:55:53 tgl Exp $
  *
  * DESCRIPTION
  *	  The "DefineFoo" routines take the parse tree and pick out the
@@ -2042,14 +2042,7 @@ GetDomainConstraints(Oid typeOid)
 }
 
 /*
- * ALTER DOMAIN .. OWNER TO
- *
- * Eventually this should allow changing ownership of other kinds of types,
- * but some thought must be given to handling complex types.  (A table's
- * rowtype probably shouldn't be allowed as target, but what of a standalone
- * composite type?)
- *
- * Assumes that permission checks have been completed earlier.
+ * Change the owner of a type.
  */
 void
 AlterTypeOwner(List *names, AclId newOwnerSysId)
@@ -2084,19 +2077,36 @@ AlterTypeOwner(List *names, AclId newOwnerSysId)
 		elog(ERROR, "cache lookup failed for type %u", typeOid);
 	typTup = (Form_pg_type) GETSTRUCT(tup);
 
-	/* Check that this is actually a domain */
-	if (typTup->typtype != 'd')
+	/*
+	 * If it's a composite type, we need to check that it really is a 
+ 	 * free-standing composite type, and not a table's underlying type.
+	 * We want people to use ALTER TABLE not ALTER TYPE for that case.
+	 */
+	if (typTup->typtype == 'c' && get_rel_relkind(typTup->typrelid) != 'c')
 		ereport(ERROR,
 				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("\"%s\" is not a domain",
+				 errmsg("\"%s\" is a table's row type",
 						TypeNameToString(typename))));
 
-	/* Modify the owner --- okay to scribble on typTup because it's a copy */
-	typTup->typowner = newOwnerSysId;
+	/* 
+	 * If the new owner is the same as the existing owner, consider the
+	 * command to have succeeded.  This is for dump restoration purposes.
+	 */
+	if (typTup->typowner != newOwnerSysId)
+	{
+		/* Otherwise, must be superuser to change object ownership */
+		if (!superuser())
+			ereport(ERROR,
+					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+					 errmsg("must be superuser to change owner")));
+
+		/* Modify the owner --- okay to scribble on typTup because it's a copy */
+		typTup->typowner = newOwnerSysId;
 
-	simple_heap_update(rel, &tup->t_self, tup);
+		simple_heap_update(rel, &tup->t_self, tup);
 
-	CatalogUpdateIndexes(rel, tup);
+		CatalogUpdateIndexes(rel, tup);
+	}
 
 	/* Clean up */
 	heap_close(rel, RowExclusiveLock);
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 90983e6db0ba53339c9410de907c8b402ea4beff..17adc9cf5fde2ebe12012d9b7202116eea43f8e2 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.286 2004/06/18 06:13:28 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.287 2004/06/25 21:55:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1937,6 +1937,21 @@ _copyRenameStmt(RenameStmt *from)
 	return newnode;
 }
 
+static AlterOwnerStmt *
+_copyAlterOwnerStmt(AlterOwnerStmt *from)
+{
+	AlterOwnerStmt *newnode = makeNode(AlterOwnerStmt);
+
+	COPY_NODE_FIELD(relation);
+	COPY_NODE_FIELD(object);
+	COPY_NODE_FIELD(objarg);
+	COPY_STRING_FIELD(addname);
+	COPY_STRING_FIELD(newowner);
+	COPY_SCALAR_FIELD(objectType);
+
+	return newnode;
+}
+
 static RuleStmt *
 _copyRuleStmt(RuleStmt *from)
 {
@@ -2080,17 +2095,6 @@ _copyCreatedbStmt(CreatedbStmt *from)
 	return newnode;
 }
 
-static AlterDbOwnerStmt *
-_copyAlterDbOwnerStmt(AlterDbOwnerStmt *from)
-{
-	AlterDbOwnerStmt *newnode = makeNode(AlterDbOwnerStmt);
-
-	COPY_STRING_FIELD(dbname);
-	COPY_STRING_FIELD(uname);
-
-	return newnode;
-}
-
 static AlterDatabaseSetStmt *
 _copyAlterDatabaseSetStmt(AlterDatabaseSetStmt *from)
 {
@@ -2874,6 +2878,9 @@ copyObject(void *from)
 		case T_RenameStmt:
 			retval = _copyRenameStmt(from);
 			break;
+		case T_AlterOwnerStmt:
+			retval = _copyAlterOwnerStmt(from);
+			break;
 		case T_RuleStmt:
 			retval = _copyRuleStmt(from);
 			break;
@@ -2910,9 +2917,6 @@ copyObject(void *from)
 		case T_CreatedbStmt:
 			retval = _copyCreatedbStmt(from);
 			break;
-		case T_AlterDbOwnerStmt:
-			retval = _copyAlterDbOwnerStmt(from);
-			break;
 		case T_AlterDatabaseSetStmt:
 			retval = _copyAlterDatabaseSetStmt(from);
 			break;
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 47ec31577274487b3dc6e0c5fcec1cd941086adb..f46c7b44205663e72fbdb4e4d07d27123c2990f0 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -18,7 +18,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.225 2004/06/18 06:13:28 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.226 2004/06/25 21:55:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -991,6 +991,19 @@ _equalRenameStmt(RenameStmt *a, RenameStmt *b)
 	return true;
 }
 
+static bool
+_equalAlterOwnerStmt(AlterOwnerStmt *a, AlterOwnerStmt *b)
+{
+	COMPARE_NODE_FIELD(relation);
+	COMPARE_NODE_FIELD(object);
+	COMPARE_NODE_FIELD(objarg);
+	COMPARE_STRING_FIELD(addname);
+	COMPARE_STRING_FIELD(newowner);
+	COMPARE_SCALAR_FIELD(objectType);
+
+	return true;
+}
+
 static bool
 _equalRuleStmt(RuleStmt *a, RuleStmt *b)
 {
@@ -1110,15 +1123,6 @@ _equalCreatedbStmt(CreatedbStmt *a, CreatedbStmt *b)
 	return true;
 }
 
-static bool
-_equalAlterDbOwnerStmt(AlterDbOwnerStmt *a, AlterDbOwnerStmt *b)
-{
-	COMPARE_STRING_FIELD(dbname);
-	COMPARE_STRING_FIELD(uname);
-
-	return true;
-}
-
 static bool
 _equalAlterDatabaseSetStmt(AlterDatabaseSetStmt *a, AlterDatabaseSetStmt *b)
 {
@@ -2008,6 +2012,9 @@ equal(void *a, void *b)
 		case T_RenameStmt:
 			retval = _equalRenameStmt(a, b);
 			break;
+		case T_AlterOwnerStmt:
+			retval = _equalAlterOwnerStmt(a, b);
+			break;
 		case T_RuleStmt:
 			retval = _equalRuleStmt(a, b);
 			break;
@@ -2044,9 +2051,6 @@ equal(void *a, void *b)
 		case T_CreatedbStmt:
 			retval = _equalCreatedbStmt(a, b);
 			break;
-		case T_AlterDbOwnerStmt:
-			retval = _equalAlterDbOwnerStmt(a, b);
-			break;
 		case T_AlterDatabaseSetStmt:
 			retval = _equalAlterDatabaseSetStmt(a, b);
 			break;
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 9dc53604c61f2ed5cb66e06fc417c732fb32992d..7da8affbf910100808dbdfd7935755d8e1a9fe3f 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.462 2004/06/18 06:13:31 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.463 2004/06/25 21:55:55 tgl Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -131,7 +131,7 @@ static void doNegateFloat(Value *v);
 }
 
 %type <node>	stmt schema_stmt
-		AlterDatabaseSetStmt AlterDomainStmt AlterGroupStmt
+		AlterDatabaseSetStmt AlterDomainStmt AlterGroupStmt AlterOwnerStmt
 		AlterSeqStmt AlterTableStmt AlterUserStmt AlterUserSetStmt
 		AnalyzeStmt ClosePortalStmt ClusterStmt CommentStmt
 		ConstraintsSetStmt CopyStmt CreateAsStmt CreateCastStmt
@@ -152,7 +152,6 @@ static void doNegateFloat(Value *v);
 		VariableResetStmt VariableSetStmt VariableShowStmt
 		ViewStmt CheckPointStmt CreateConversionStmt
 		DeallocateStmt PrepareStmt ExecuteStmt
-		AlterDbOwnerStmt
 
 %type <node>	select_no_parens select_with_parens select_clause
 				simple_select
@@ -487,10 +486,10 @@ stmtmulti:	stmtmulti ';' stmt
 		;
 
 stmt :
-			AlterDbOwnerStmt
-			| AlterDatabaseSetStmt
+			AlterDatabaseSetStmt
 			| AlterDomainStmt
 			| AlterGroupStmt
+			| AlterOwnerStmt
 			| AlterSeqStmt
 			| AlterTableStmt
 			| AlterUserSetStmt
@@ -3670,6 +3669,14 @@ RenameStmt: ALTER AGGREGATE func_name '(' aggr_argtype ')' RENAME TO name
 					n->newname = $6;
 					$$ = (Node *)n;
 				}
+			| ALTER TABLESPACE name RENAME TO name
+				{
+					RenameStmt *n = makeNode(RenameStmt);
+					n->renameType = OBJECT_TABLESPACE;
+					n->subname = $3;
+					n->newname = $6;
+					$$ = (Node *)n;
+				}
 		;
 
 opt_column: COLUMN									{ $$ = COLUMN; }
@@ -3677,6 +3684,99 @@ opt_column: COLUMN									{ $$ = COLUMN; }
 		;
 
 
+/*****************************************************************************
+ *
+ * ALTER THING name OWNER TO newname.  
+ *
+ *****************************************************************************/
+
+AlterOwnerStmt: ALTER AGGREGATE func_name '(' aggr_argtype ')' OWNER TO UserId
+				{
+					AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
+					n->objectType = OBJECT_AGGREGATE;
+					n->object = $3;
+					n->objarg = list_make1($5);
+					n->newowner = $9;
+					$$ = (Node *)n;
+				}
+			| ALTER CONVERSION_P any_name OWNER TO UserId
+				{
+					AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
+					n->objectType = OBJECT_CONVERSION;
+					n->object = $3;
+					n->newowner = $6;
+					$$ = (Node *)n;
+				}
+			| ALTER DATABASE database_name OWNER TO UserId
+				{
+					AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
+					n->objectType = OBJECT_DATABASE;
+					n->object = list_make1($3);
+					n->newowner = $6;
+					$$ = (Node *)n;
+				}
+			| ALTER DOMAIN_P any_name OWNER TO UserId
+				{
+					AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
+					n->objectType = OBJECT_DOMAIN;
+					n->object = $3;
+					n->newowner = $6;
+					$$ = (Node *)n;
+				}
+			| ALTER FUNCTION func_name func_args OWNER TO UserId
+				{
+					AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
+					n->objectType = OBJECT_FUNCTION;
+					n->object = $3;
+					n->objarg = extractArgTypes($4);
+					n->newowner = $7;
+					$$ = (Node *)n;
+				}
+			| ALTER OPERATOR any_operator '(' oper_argtypes ')' OWNER TO UserId
+				{
+					AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
+					n->objectType = OBJECT_OPERATOR;
+					n->object = $3;
+					n->objarg = $5;
+					n->newowner = $9;
+					$$ = (Node *)n;
+				}
+			| ALTER OPERATOR CLASS any_name USING access_method OWNER TO UserId
+				{
+					AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
+					n->objectType = OBJECT_OPCLASS;
+					n->object = $4;
+					n->addname = $6;
+					n->newowner = $9;
+					$$ = (Node *)n;
+				}
+			| ALTER SCHEMA name OWNER TO UserId
+				{
+					AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
+					n->objectType = OBJECT_SCHEMA;
+					n->object = list_make1($3);
+					n->newowner = $6;
+					$$ = (Node *)n;
+				}
+			| ALTER TYPE_P any_name OWNER TO UserId
+				{
+					AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
+					n->objectType = OBJECT_TYPE;
+					n->object = $3;
+					n->newowner = $6;
+					$$ = (Node *)n;
+				}
+			| ALTER TABLESPACE name OWNER TO UserId
+				{
+					AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
+					n->objectType = OBJECT_TABLESPACE;
+					n->object = list_make1($3);
+					n->newowner = $6;
+					$$ = (Node *)n;
+				}
+		;
+
+
 /*****************************************************************************
  *
  *		QUERY:	Define Rewrite Rule
@@ -4019,15 +4119,6 @@ opt_equal:	'='										{}
  *
  *****************************************************************************/
 
-AlterDbOwnerStmt: ALTER DATABASE database_name OWNER TO UserId
-				{
-					AlterDbOwnerStmt *n = makeNode(AlterDbOwnerStmt);
-					n->dbname = $3;
-					n->uname = $6;
-					$$ = (Node *)n;
-				}
-		;
-
 AlterDatabaseSetStmt:
 			ALTER DATABASE database_name SET set_rest
 				{
@@ -4126,15 +4217,6 @@ AlterDomainStmt:
 					n->behavior = $7;
 					$$ = (Node *)n;
 				}
-			/* ALTER DOMAIN <domain> OWNER TO UserId */
-			| ALTER DOMAIN_P any_name OWNER TO UserId
-				{
-					AlterDomainStmt *n = makeNode(AlterDomainStmt);
-					n->subtype = 'U';
-					n->typename = $3;
-					n->name = $6;
-					$$ = (Node *)n;
-				}
 			;
 
 opt_as:		AS										{}
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index d12cf0d750f9303cfb40face12b6878f7ef16624..a3e727472abbc0e366dbb14bcdab6901de07c52e 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.219 2004/06/18 06:13:38 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.220 2004/06/25 21:55:57 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -236,14 +236,14 @@ check_xact_readonly(Node *parsetree)
 	switch (nodeTag(parsetree))
 	{
 		case T_AlterDatabaseSetStmt:
-		case T_AlterDbOwnerStmt:
 		case T_AlterDomainStmt:
 		case T_AlterGroupStmt:
+		case T_AlterOwnerStmt:
 		case T_AlterSeqStmt:
 		case T_AlterTableStmt:
-		case T_RenameStmt:
 		case T_AlterUserStmt:
 		case T_AlterUserSetStmt:
+		case T_RenameStmt:
 		case T_CommentStmt:
 		case T_DefineStmt:
 		case T_CreateCastStmt:
@@ -527,6 +527,10 @@ ProcessUtility(Node *parsetree,
 			ExecRenameStmt((RenameStmt *) parsetree);
 			break;
 
+		case T_AlterOwnerStmt:
+			ExecAlterOwnerStmt((AlterOwnerStmt *) parsetree);
+			break;
+
 		case T_AlterTableStmt:
 			AlterTable((AlterTableStmt *) parsetree);
 			break;
@@ -567,16 +571,6 @@ ProcessUtility(Node *parsetree,
 												  stmt->name,
 												  stmt->behavior);
 						break;
-					case 'U':	/* OWNER TO */
-						/* check that we are the superuser */
-						if (!superuser())
-							ereport(ERROR,
-								(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-							errmsg("must be superuser to alter owner")));
-						/* get_usesysid raises an error if no such user */
-						AlterTypeOwner(stmt->typename,
-									   get_usesysid(stmt->name));
-						break;
 					default:	/* oops */
 						elog(ERROR, "unrecognized alter domain type: %d",
 							 (int) stmt->subtype);
@@ -689,13 +683,6 @@ ProcessUtility(Node *parsetree,
 			createdb((CreatedbStmt *) parsetree);
 			break;
 
-		case T_AlterDbOwnerStmt:
-			{
-				AlterDbOwnerStmt *stmt = (AlterDbOwnerStmt *) parsetree;
-				AlterDatabaseOwner(stmt->dbname, stmt->uname);
-			}
-			break;
-
 		case T_AlterDatabaseSetStmt:
 			AlterDatabaseSet((AlterDatabaseSetStmt *) parsetree);
 			break;
@@ -1258,6 +1245,44 @@ CreateCommandTag(Node *parsetree)
 			}
 			break;
 
+		case T_AlterOwnerStmt:
+			switch (((AlterOwnerStmt *) parsetree)->objectType)
+			{
+				case OBJECT_AGGREGATE:
+					tag = "ALTER AGGREGATE";
+					break;
+				case OBJECT_CONVERSION:
+					tag = "ALTER CONVERSION";
+					break;
+				case OBJECT_DATABASE:
+					tag = "ALTER DATABASE";
+					break;
+				case OBJECT_DOMAIN:
+					tag = "ALTER DOMAIN";
+					break;
+				case OBJECT_FUNCTION:
+					tag = "ALTER FUNCTION";
+					break;
+				case OBJECT_OPERATOR:
+					tag = "ALTER OPERATOR";
+					break;
+				case OBJECT_OPCLASS:
+					tag = "ALTER OPERATOR CLASS";
+					break;
+				case OBJECT_SCHEMA:
+					tag = "ALTER SCHEMA";
+					break;
+				case OBJECT_TABLESPACE:
+					tag = "ALTER TABLESPACE";
+					break;
+				case OBJECT_TYPE:
+					tag = "ALTER TYPE";
+					break;
+				default:
+					tag = "ALTER TABLE";
+			}
+			break;
+
 		case T_AlterTableStmt:
 			tag = "ALTER TABLE";
 			break;
@@ -1335,10 +1360,6 @@ CreateCommandTag(Node *parsetree)
 			tag = "CREATE DATABASE";
 			break;
 
-		case T_AlterDbOwnerStmt:
-			tag = "ALTER DATABASE";
-			break;
-
 		case T_AlterDatabaseSetStmt:
 			tag = "ALTER DATABASE";
 			break;
diff --git a/src/include/commands/alter.h b/src/include/commands/alter.h
index 58717ae03f56cd9c3af470c6642849525e944144..2914fbbd8a636246d0649538f57098c44b0a0d87 100644
--- a/src/include/commands/alter.h
+++ b/src/include/commands/alter.h
@@ -1,13 +1,13 @@
 /*-------------------------------------------------------------------------
  *
  * alter.h
- *	  prototypes for alter.h
+ *	  prototypes for commands/alter.c
  *
  *
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/commands/alter.h,v 1.3 2003/11/29 22:40:59 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/commands/alter.h,v 1.4 2004/06/25 21:55:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -18,4 +18,6 @@
 
 extern void ExecRenameStmt(RenameStmt *stmt);
 
+extern void ExecAlterOwnerStmt(AlterOwnerStmt *stmt);
+
 #endif   /* ALTER_H */
diff --git a/src/include/commands/conversioncmds.h b/src/include/commands/conversioncmds.h
index 8ea65326c7cea8a11507c1fe061db45a07b544a4..a5146981177fc7f928a07d7f18828ca39ebe3581 100644
--- a/src/include/commands/conversioncmds.h
+++ b/src/include/commands/conversioncmds.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/commands/conversioncmds.h,v 1.6 2003/11/29 22:40:59 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/commands/conversioncmds.h,v 1.7 2004/06/25 21:55:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -20,5 +20,6 @@
 extern void CreateConversionCommand(CreateConversionStmt *parsetree);
 extern void DropConversionCommand(List *conversion_name, DropBehavior behavior);
 extern void RenameConversion(List *name, const char *newname);
+extern void AlterConversionOwner(List *name, AclId newOwnerSysId);
 
 #endif   /* CONVERSIONCMDS_H */
diff --git a/src/include/commands/dbcommands.h b/src/include/commands/dbcommands.h
index 30b73d4daf1c585d7f2816e445081bce2922a7c4..c481e8c9d91eeeeb0cc3fcc3ca32ffca010e7aa7 100644
--- a/src/include/commands/dbcommands.h
+++ b/src/include/commands/dbcommands.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/commands/dbcommands.h,v 1.31 2004/05/26 13:56:59 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/commands/dbcommands.h,v 1.32 2004/06/25 21:55:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -20,7 +20,7 @@ extern void createdb(const CreatedbStmt *stmt);
 extern void dropdb(const char *dbname);
 extern void RenameDatabase(const char *oldname, const char *newname);
 extern void AlterDatabaseSet(AlterDatabaseSetStmt *stmt);
-extern void AlterDatabaseOwner(const char *dbname, const char *uname);
+extern void AlterDatabaseOwner(const char *dbname, AclId newOwnerSysId);
 
 extern Oid	get_database_oid(const char *dbname);
 extern char *get_database_name(Oid dbid);
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index 8670a41a763771ba642428c744938e786da3690a..afe6cf0ac15617876bedbc79c44f000688f22ca6 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/commands/defrem.h,v 1.58 2004/06/18 06:14:08 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/commands/defrem.h,v 1.59 2004/06/25 21:55:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -48,6 +48,7 @@ extern void RemoveFunctionById(Oid funcOid);
 extern void SetFunctionReturnType(Oid funcOid, Oid newRetType);
 extern void SetFunctionArgType(Oid funcOid, int argIndex, Oid newArgType);
 extern void RenameFunction(List *name, List *argtypes, const char *newname);
+extern void AlterFunctionOwner(List *name, List *argtypes, AclId newOwnerSysId);
 extern void CreateCast(CreateCastStmt *stmt);
 extern void DropCast(DropCastStmt *stmt);
 extern void DropCastById(Oid castOid);
@@ -56,17 +57,21 @@ extern void DropCastById(Oid castOid);
 extern void DefineOperator(List *names, List *parameters);
 extern void RemoveOperator(RemoveOperStmt *stmt);
 extern void RemoveOperatorById(Oid operOid);
+extern void AlterOperatorOwner(List *name, TypeName *typeName1,
+							   TypeName *typename2, AclId newOwnerSysId);
 
 /* commands/aggregatecmds.c */
 extern void DefineAggregate(List *names, List *parameters);
 extern void RemoveAggregate(RemoveAggrStmt *stmt);
 extern void RenameAggregate(List *name, TypeName *basetype, const char *newname);
+extern void AlterAggregateOwner(List *name, TypeName *basetype, AclId newOwnerSysId);
 
 /* commands/opclasscmds.c */
 extern void DefineOpClass(CreateOpClassStmt *stmt);
 extern void RemoveOpClass(RemoveOpClassStmt *stmt);
 extern void RemoveOpClassById(Oid opclassOid);
 extern void RenameOpClass(List *name, const char *access_method, const char *newname);
+extern void AlterOpClassOwner(List *name, const char *access_method, AclId newOwnerSysId); 
 
 /* support routines in commands/define.c */
 
diff --git a/src/include/commands/schemacmds.h b/src/include/commands/schemacmds.h
index 6f772e6b3e80b2e18738222d765ce9a734a05eec..96e03d80ad89826c8783fa65863e1515676532e0 100644
--- a/src/include/commands/schemacmds.h
+++ b/src/include/commands/schemacmds.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/commands/schemacmds.h,v 1.6 2003/11/29 22:40:59 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/commands/schemacmds.h,v 1.7 2004/06/25 21:55:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -23,5 +23,6 @@ extern void RemoveSchema(List *names, DropBehavior behavior);
 extern void RemoveSchemaById(Oid schemaOid);
 
 extern void RenameSchema(const char *oldname, const char *newname);
+extern void AlterSchemaOwner(const char *name, AclId newOwnerSysId);
 
 #endif   /* SCHEMACMDS_H */
diff --git a/src/include/commands/tablespace.h b/src/include/commands/tablespace.h
index 129413ac14b46b9ef975ffefab370a108520022c..17821493f45994e98a0cd6fa417833de02077b6a 100644
--- a/src/include/commands/tablespace.h
+++ b/src/include/commands/tablespace.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/commands/tablespace.h,v 1.1 2004/06/18 06:14:08 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/commands/tablespace.h,v 1.2 2004/06/25 21:55:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -26,4 +26,7 @@ extern Oid	get_tablespace_oid(const char *tablespacename);
 
 extern char *get_tablespace_name(Oid spc_oid);
 
+extern void RenameTableSpace(const char *oldname, const char *newname);
+extern void AlterTableSpaceOwner(const char *name, AclId newOwnerSysId);
+
 #endif   /* TABLESPACE_H */
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index 531b7e6c654a3c8ee20016e72dc02584c02aec76..258bdc7b61ecfcb12cebb7ff483fcce562581476 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.158 2004/06/18 06:14:11 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.159 2004/06/25 21:55:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -270,7 +270,7 @@ typedef enum NodeTag
 	T_DeclareCursorStmt,
 	T_CreateTableSpaceStmt,
 	T_DropTableSpaceStmt,
-	T_AlterDbOwnerStmt,
+	T_AlterOwnerStmt,
 
 	T_A_Expr = 800,
 	T_ColumnRef,
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 4c24fe9e27bfbfaccae75ba8e37ef739dc5cef7b..22d18ef4f70e665dda8e583d83ad2390a4e3d8f4 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.259 2004/06/18 06:14:11 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.260 2004/06/25 21:55:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -838,12 +838,10 @@ typedef struct AlterDomainStmt
 								 *	O = alter column set not null
 								 *	C = add constraint
 								 *	X = drop constraint
-								 *	U = change owner
 								 *------------
 								 */
 	List	   *typename;		/* domain to work on */
-	char	   *name;			/* column or constraint name to act on, or
-								 * new owner */
+	char	   *name;			/* column or constraint name to act on */
 	Node	   *def;			/* definition of default or constraint */
 	DropBehavior behavior;		/* RESTRICT or CASCADE for DROP cases */
 } AlterDomainStmt;
@@ -1445,6 +1443,22 @@ typedef struct RenameStmt
 	ObjectType	renameType;		/* OBJECT_TABLE, OBJECT_COLUMN, etc */
 } RenameStmt;
 
+/* ----------------------
+ *		Alter Object Owner Statement 
+ * ----------------------
+ */
+typedef struct AlterOwnerStmt
+{
+	NodeTag		type;
+	RangeVar   *relation;		/* in case it's a table */
+	List	   *object;			/* in case it's some other object */
+	List	   *objarg;			/* argument types, if applicable */
+	char	   *addname;		/* additional name if needed */
+	char	   *newowner;		/* the new owner */
+	ObjectType	objectType;		/* OBJECT_TABLE, OBJECT_TYPE, etc */
+} AlterOwnerStmt;
+
+
 /* ----------------------
  *		Create Rule Statement
  * ----------------------
@@ -1560,13 +1574,6 @@ typedef struct CreatedbStmt
  *	Alter Database
  * ----------------------
  */
-typedef struct AlterDbOwnerStmt
-{
-	NodeTag		type;
-	char	   *dbname;
-	char	   *uname;
-} AlterDbOwnerStmt;
-
 typedef struct AlterDatabaseSetStmt
 {
 	NodeTag		type;