summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Eisentraut2003-06-27 14:45:32 +0000
committerPeter Eisentraut2003-06-27 14:45:32 +0000
commit6baf6776d1178ed7bb24137be89584266764995d (patch)
tree8e1d7ed4a8196f0273da9d8deadb4425fa588299
parent0a5cba94152bab7349baa72c7f5f4bfaa05d37d3 (diff)
First batch of object rename commands.
-rw-r--r--doc/src/sgml/ref/allfiles.sgml37
-rw-r--r--doc/src/sgml/ref/alter_aggregate.sgml128
-rw-r--r--doc/src/sgml/ref/alter_conversion.sgml117
-rw-r--r--doc/src/sgml/ref/alter_database.sgml40
-rw-r--r--doc/src/sgml/ref/alter_function.sgml127
-rw-r--r--doc/src/sgml/ref/alter_group.sgml37
-rw-r--r--doc/src/sgml/ref/alter_language.sgml107
-rw-r--r--doc/src/sgml/ref/alter_opclass.sgml116
-rw-r--r--doc/src/sgml/ref/alter_schema.sgml108
-rw-r--r--doc/src/sgml/ref/alter_user.sgml19
-rw-r--r--doc/src/sgml/ref/create_aggregate.sgml17
-rw-r--r--doc/src/sgml/ref/create_conversion.sgml9
-rw-r--r--doc/src/sgml/ref/create_function.sgml1
-rw-r--r--doc/src/sgml/ref/create_language.sgml19
-rw-r--r--doc/src/sgml/ref/create_opclass.sgml19
-rw-r--r--doc/src/sgml/ref/create_schema.sgml14
-rw-r--r--doc/src/sgml/ref/drop_aggregate.sgml1
-rw-r--r--doc/src/sgml/ref/drop_conversion.sgml1
-rw-r--r--doc/src/sgml/ref/drop_function.sgml1
-rw-r--r--doc/src/sgml/ref/drop_language.sgml2
-rw-r--r--doc/src/sgml/ref/drop_opclass.sgml1
-rw-r--r--doc/src/sgml/ref/drop_schema.sgml1
-rw-r--r--doc/src/sgml/reference.sgml6
-rw-r--r--src/backend/catalog/aclchk.c37
-rw-r--r--src/backend/catalog/namespace.c8
-rw-r--r--src/backend/commands/Makefile2
-rw-r--r--src/backend/commands/aggregatecmds.c73
-rw-r--r--src/backend/commands/alter.c159
-rw-r--r--src/backend/commands/analyze.c2
-rw-r--r--src/backend/commands/comment.c38
-rw-r--r--src/backend/commands/conversioncmds.c60
-rw-r--r--src/backend/commands/dbcommands.c155
-rw-r--r--src/backend/commands/functioncmds.c66
-rw-r--r--src/backend/commands/indexcmds.c5
-rw-r--r--src/backend/commands/opclasscmds.c93
-rw-r--r--src/backend/commands/proclang.c44
-rw-r--r--src/backend/commands/schemacmds.c58
-rw-r--r--src/backend/commands/user.c106
-rw-r--r--src/backend/commands/vacuum.c2
-rw-r--r--src/backend/nodes/copyfuncs.c4
-rw-r--r--src/backend/nodes/equalfuncs.c4
-rw-r--r--src/backend/parser/gram.y162
-rw-r--r--src/backend/parser/parse_expr.c2
-rw-r--r--src/backend/parser/parse_target.c2
-rw-r--r--src/backend/tcop/utility.c171
-rw-r--r--src/backend/utils/adt/misc.c3
-rw-r--r--src/backend/utils/init/globals.c2
-rw-r--r--src/backend/utils/init/miscinit.c16
-rw-r--r--src/backend/utils/init/postinit.c4
-rw-r--r--src/backend/utils/misc/superuser.c15
-rw-r--r--src/include/commands/alter.h21
-rw-r--r--src/include/commands/conversioncmds.h1
-rw-r--r--src/include/commands/dbcommands.h5
-rw-r--r--src/include/commands/defrem.h4
-rw-r--r--src/include/commands/proclang.h1
-rw-r--r--src/include/commands/schemacmds.h2
-rw-r--r--src/include/commands/user.h2
-rw-r--r--src/include/miscadmin.h4
-rw-r--r--src/include/nodes/parsenodes.h96
-rw-r--r--src/include/utils/acl.h1
60 files changed, 1967 insertions, 391 deletions
diff --git a/doc/src/sgml/ref/allfiles.sgml b/doc/src/sgml/ref/allfiles.sgml
index 91e62e4f82..5fe712a89d 100644
--- a/doc/src/sgml/ref/allfiles.sgml
+++ b/doc/src/sgml/ref/allfiles.sgml
@@ -4,42 +4,17 @@ PostgreSQL documentation
Complete list of usable sgml source files in this directory.
-->
-<!-- these will go into the "operators" reference chapter -->
-<!entity all system "all.sgml">
-<!entity any system "any.sgml">
-<!entity between system "between.sgml">
-<!entity in system "in.sgml">
-<!entity like system "like.sgml">
-
-<!-- these will go into the "functions" reference chapter -->
-<!entity avg system "avg.sgml">
-<!entity cast system "cast.sgml">
-<!entity charLength system "char_length.sgml">
-<!entity count system "count.sgml">
-<!entity currentDate system "current_date.sgml">
-<!entity currentTime system "current_time.sgml">
-<!entity currentTimestamp system "current_timestamp.sgml">
-<!entity currentUser system "current_user.sgml">
-<!entity exists system "exists.sgml">
-<!entity extract system "extract.sgml">
-<!entity initcap system "initcap.sgml">
-<!entity lower system "lower.sgml">
-<!entity lpad system "lpad.sgml">
-<!entity max system "max.sgml">
-<!entity min system "min.sgml">
-<!entity position system "position.sgml">
-<!entity rpad system "rpad.sgml">
-<!entity substring system "substring.sgml">
-<!entity sum system "sum.sgml">
-<!entity translate system "translate.sgml">
-<!entity trim system "trim.sgml">
-<!entity upper system "upper.sgml">
-
<!-- SQL commands -->
<!entity abort system "abort.sgml">
+<!entity alterAggregate system "alter_aggregate.sgml">
+<!entity alterConversion system "alter_conversion.sgml">
<!entity alterDatabase system "alter_database.sgml">
<!entity alterDomain system "alter_domain.sgml">
+<!entity alterFunction system "alter_function.sgml">
<!entity alterGroup system "alter_group.sgml">
+<!entity alterLanguage system "alter_language.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 alterTrigger system "alter_trigger.sgml">
diff --git a/doc/src/sgml/ref/alter_aggregate.sgml b/doc/src/sgml/ref/alter_aggregate.sgml
new file mode 100644
index 0000000000..37fdeb49f3
--- /dev/null
+++ b/doc/src/sgml/ref/alter_aggregate.sgml
@@ -0,0 +1,128 @@
+<!--
+$Header$
+PostgreSQL documentation
+-->
+
+<refentry id="SQL-ALTERAGGREGATE">
+ <refmeta>
+ <refentrytitle id="SQL-ALTERAGGREGATE-TITLE">ALTER AGGREGATE</refentrytitle>
+ <refmiscinfo>SQL - Language Statements</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname>ALTER AGGREGATE</refname>
+ <refpurpose>change the definition of an aggregate function</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+<synopsis>
+ALTER AGGREGATE <replaceable>name</replaceable> ( <replaceable>type</replaceable> ) RENAME TO <replaceable>newname</replaceable>
+</synopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para>
+ <command>ALTER AGGREGATE</command> changes the definition of an
+ aggregate function. The only functionality is to rename the
+ aggregate function.
+ </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 aggregate function.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><replaceable class="parameter">type</replaceable></term>
+ <listitem>
+ <para>
+ The argument data type of the aggregate function, or
+ <literal>*</literal> if the function accepts any data type.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><replaceable class="parameter">newname</replaceable></term>
+ <listitem>
+ <para>
+ The new name of the aggregate function.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Diagnostics</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><computeroutput>ALTER AGGREGATE</computeroutput></term>
+ <listitem>
+ <para>
+ Message returned if the command was successful.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Examples</title>
+
+ <para>
+ To rename the aggregate function <literal>myavg</literal> for type
+ <type>integer</type> to <literal>my_average</literal>:
+<programlisting>
+ALTER AGGREGATE myavg(integer) RENAME TO my_average;
+</programlisting>
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>Compatibility</title>
+
+ <para>
+ There is no <command>ALTER AGGREGATE</command> statement in the SQL
+ standard.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+
+ <simplelist type="inline">
+ <member><xref linkend="sql-createaggregate" endterm="sql-createaggregate-title"></member>
+ <member><xref linkend="sql-dropaggregate" endterm="sql-dropaggregate-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_conversion.sgml b/doc/src/sgml/ref/alter_conversion.sgml
new file mode 100644
index 0000000000..b11589cc9c
--- /dev/null
+++ b/doc/src/sgml/ref/alter_conversion.sgml
@@ -0,0 +1,117 @@
+<!--
+$Header$
+PostgreSQL documentation
+-->
+
+<refentry id="SQL-ALTERCONVERSION">
+ <refmeta>
+ <refentrytitle id="SQL-ALTERCONVERSION-TITLE">ALTER CONVERSION</refentrytitle>
+ <refmiscinfo>SQL - Language Statements</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname>ALTER CONVERSION</refname>
+ <refpurpose>change the definition of a conversion</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+<synopsis>
+ALTER CONVERSION <replaceable>name</replaceable> RENAME TO <replaceable>newname</replaceable>
+</synopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para>
+ <command>ALTER CONVERSION</command> changes the definition of a
+ conversion. The only functionality is to rename the conversion.
+ </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 conversion.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><replaceable class="parameter">newname</replaceable></term>
+ <listitem>
+ <para>
+ The new name of the conversion.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Diagnostics</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><computeroutput>ALTER CONVERSION</computeroutput></term>
+ <listitem>
+ <para>
+ Message returned if the command was successful.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Examples</title>
+
+ <para>
+ To rename the conversion <literal>iso_8859_1_to_utf_8</literal> to
+ <literal>latin1_to_unicode</literal>:
+<programlisting>
+ALTER CONVERSION iso_8859_1_to_utf_8 RENAME TO latin1_to_unicode;
+</programlisting>
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>Compatibility</title>
+
+ <para>
+ There is no <command>ALTER CONVERSION</command> statement in the SQL
+ standard.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+
+ <simplelist type="inline">
+ <member><xref linkend="sql-createconversion" endterm="sql-createconversion-title"></member>
+ <member><xref linkend="sql-dropconversion" endterm="sql-dropconversion-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_database.sgml b/doc/src/sgml/ref/alter_database.sgml
index b96ee6f576..e9739c73ae 100644
--- a/doc/src/sgml/ref/alter_database.sgml
+++ b/doc/src/sgml/ref/alter_database.sgml
@@ -18,6 +18,8 @@ PostgreSQL documentation
<synopsis>
ALTER DATABASE <replaceable class="PARAMETER">name</replaceable> SET <replaceable>variable</replaceable> { TO | = } { <replaceable>value</replaceable> | DEFAULT }
ALTER DATABASE <replaceable class="PARAMETER">name</replaceable> RESET <replaceable>variable</replaceable>
+
+ALTER DATABASE <replaceable class="PARAMETER">name</replaceable> RENAME TO <replaceable>newname</replaceable>
</synopsis>
</refsynopsisdiv>
@@ -25,20 +27,29 @@ ALTER DATABASE <replaceable class="PARAMETER">name</replaceable> RESET <replacea
<title>Description</title>
<para>
- <command>ALTER DATABASE</command> is used to change the session
- default of a run-time configuration variable for a
- <productname>PostgreSQL</productname> database. Whenever a new
- session is subsequently started in that database, the specified
- value becomes the session default value.
- The database-specific default
- overrides whatever setting is present in <filename>postgresql.conf</>
- or has been received from the <command>postmaster</command> command line.
+ <command>ALTER DATABASE</command> is used to change the attributes
+ of a database.
</para>
<para>
- Only the database owner or a superuser can change the session defaults for a
+ The first two forms change the session default of a run-time
+ configuration variable for a <productname>PostgreSQL</productname>
+ database. Whenever a new session is subsequently started in that
+ database, the specified value becomes the session default value.
+ The database-specific default overrides whatever setting is present
+ in <filename>postgresql.conf</> or has been received from the
+ <command>postmaster</command> command line. Only the database
+ owner or a superuser can change the session defaults for a
database.
</para>
+
+ <para>
+ The third form changes the name of the database. Only the database
+ owner can rename a database, and only if he has the
+ <literal>CREATEDB</literal> privilege. The current database cannot
+ be renamed. (Connect to a different database if you need to do
+ that.)
+ </para>
</refsect1>
<refsect1>
@@ -76,7 +87,16 @@ ALTER DATABASE <replaceable class="PARAMETER">name</replaceable> RESET <replacea
</para>
</listitem>
</varlistentry>
- </variablelist>
+
+ <varlistentry>
+ <term><replaceable>newname</replaceable></term>
+ <listitem>
+ <para>
+ The new name of the database.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
</refsect1>
<refsect1>
diff --git a/doc/src/sgml/ref/alter_function.sgml b/doc/src/sgml/ref/alter_function.sgml
new file mode 100644
index 0000000000..771e8a66b9
--- /dev/null
+++ b/doc/src/sgml/ref/alter_function.sgml
@@ -0,0 +1,127 @@
+<!--
+$Header$
+PostgreSQL documentation
+-->
+
+<refentry id="SQL-ALTERFUNCTION">
+ <refmeta>
+ <refentrytitle id="SQL-ALTERFUNCTION-TITLE">ALTER FUNCTION</refentrytitle>
+ <refmiscinfo>SQL - Language Statements</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname>ALTER FUNCTION</refname>
+ <refpurpose>change the definition of a function</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+<synopsis>
+ALTER FUNCTION <replaceable>name</replaceable> ( [ <replaceable class="parameter">type</replaceable> [, ...] ] ) RENAME TO <replaceable>newname</replaceable>
+</synopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para>
+ <command>ALTER FUNCTION</command> changes the definition of a
+ function. The only functionality is to rename the function.
+ </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 function.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><replaceable class="parameter">type</replaceable></term>
+ <listitem>
+ <para>
+ The data type of an argument of the function.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><replaceable class="parameter">newname</replaceable></term>
+ <listitem>
+ <para>
+ The new name of the function.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Diagnostics</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><computeroutput>ALTER FUNCTION</computeroutput></term>
+ <listitem>
+ <para>
+ Message returned if the command was successful.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Examples</title>
+
+ <para>
+ To rename the function <literal>sqrt</literal> for type
+ <type>integer</type> to <literal>square_root</literal>:
+<programlisting>
+ALTER FUNCTION sqrt(integer) RENAME TO square_root;
+</programlisting>
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>Compatibility</title>
+
+ <para>
+ There is an <command>ALTER FUNCTION</command> statement in the SQL
+ standard, but it does not provide the option to rename the
+ function.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+
+ <simplelist type="inline">
+ <member><xref linkend="sql-createfunction" endterm="sql-createfunction-title"></member>
+ <member><xref linkend="sql-dropfunction" endterm="sql-dropfunction-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_group.sgml b/doc/src/sgml/ref/alter_group.sgml
index c06e92b854..54eb574b29 100644
--- a/doc/src/sgml/ref/alter_group.sgml
+++ b/doc/src/sgml/ref/alter_group.sgml
@@ -11,13 +11,15 @@ PostgreSQL documentation
<refnamediv>
<refname>ALTER GROUP</refname>
- <refpurpose>add users to a group or remove users from a group</refpurpose>
+ <refpurpose>change a user group</refpurpose>
</refnamediv>
<refsynopsisdiv>
<synopsis>
ALTER GROUP <replaceable class="PARAMETER">groupname</replaceable> ADD USER <replaceable class="PARAMETER">username</replaceable> [, ... ]
ALTER GROUP <replaceable class="PARAMETER">groupname</replaceable> DROP USER <replaceable class="PARAMETER">username</replaceable> [, ... ]
+
+ALTER GROUP <replaceable class="PARAMETER">groupname</replaceable> RENAME TO <replaceable>newname</replaceable>
</synopsis>
</refsynopsisdiv>
@@ -25,16 +27,16 @@ ALTER GROUP <replaceable class="PARAMETER">groupname</replaceable> DROP USER <re
<title>Description</title>
<para>
- <command>ALTER GROUP</command> is used to add or remove users from a
- group. Only database superusers can use this command.
- Adding a user to a group does not create the user. Similarly, removing
- a user from a group does not drop the user itself.
+ <command>ALTER GROUP</command> is used to change a user group. The
+ first two variants add or remove users from a group. Only database
+ superusers can use this command. Adding a user to a group does not
+ create the user. Similarly, removing a user from a group does not
+ drop the user itself.
</para>
<para>
- Use <xref linkend="SQL-CREATEGROUP" endterm="SQL-CREATEGROUP-title">
- to create a new group and <xref linkend="SQL-DROPGROUP"
- endterm="SQL-DROPGROUP-title"> to remove a group.
+ The third variant changes the name of the group. Only a database
+ superuser can rename groups.
</para>
</refsect1>
@@ -60,6 +62,15 @@ ALTER GROUP <replaceable class="PARAMETER">groupname</replaceable> DROP USER <re
</para>
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><replaceable>newname</replaceable></term>
+ <listitem>
+ <para>
+ The new name of the group.
+ </para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
@@ -104,6 +115,16 @@ ALTER GROUP workers DROP USER beth;
standard. The concept of roles is similar.
</para>
</refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+
+ <simplelist type="inline">
+ <member><xref linkend="sql-creategroup" endterm="sql-creategroup-title"></member>
+ <member><xref linkend="sql-dropgroup" endterm="sql-dropgroup-title"></member>
+ </simplelist>
+ </refsect1>
+
</refentry>
<!-- Keep this comment at the end of the file
diff --git a/doc/src/sgml/ref/alter_language.sgml b/doc/src/sgml/ref/alter_language.sgml
new file mode 100644
index 0000000000..f5507f4578
--- /dev/null
+++ b/doc/src/sgml/ref/alter_language.sgml
@@ -0,0 +1,107 @@
+<!--
+$Header$
+PostgreSQL documentation
+-->
+
+<refentry id="SQL-ALTERLANGUAGE">
+ <refmeta>
+ <refentrytitle id="SQL-ALTERLANGUAGE-title">ALTER LANGUAGE</refentrytitle>
+ <refmiscinfo>SQL - Language Statements</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname>ALTER LANGUAGE</refname>
+ <refpurpose>change the definition of a procedural language</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+<synopsis>
+ALTER LANGUAGE <replaceable>name</replaceable> RENAME TO <replaceable>newname</replaceable>
+</synopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para>
+ <command>ALTER LANGUAGE</command> changes the definition of a
+ language. The only functionality is to rename the language. Only
+ a superuser can rename languages.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>Parameter</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><replaceable>name</replaceable></term>
+ <listitem>
+ <para>
+ Name of a language
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><replaceable>newname</replaceable></term>
+ <listitem>
+ <para>
+ The new name of the language
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Diagnostics</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><computeroutput>ALTER LANGUAGE</computeroutput></term>
+ <listitem>
+ <para>
+ Message returned if the alteration was successful.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Compatibility</title>
+
+ <para>
+ There is no <command>ALTER LANGUAGE</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>
+ <member><xref linkend="sql-droplanguage" endterm="sql-droplanguage-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_opclass.sgml b/doc/src/sgml/ref/alter_opclass.sgml
new file mode 100644
index 0000000000..e2cc11d4a2
--- /dev/null
+++ b/doc/src/sgml/ref/alter_opclass.sgml
@@ -0,0 +1,116 @@
+<!--
+$Header$
+PostgreSQL documentation
+-->
+
+<refentry id="SQL-ALTEROPCLASS">
+ <refmeta>
+ <refentrytitle id="SQL-ALTEROPCLASS-TITLE">ALTER OPERATOR CLASS</refentrytitle>
+ <refmiscinfo>SQL - Language Statements</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname>ALTER OPERATOR CLASS</refname>
+ <refpurpose>change the definition of an operator class</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+<synopsis>
+ALTER OPERATOR CLASS <replaceable>name</replaceable> USING <replaceable class="parameter">index_method</replaceable> RENAME TO <replaceable>newname</replaceable>
+</synopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para>
+ <command>ALTER OPERATOR CLASS</command> changes the definition of
+ an operator class. The only functionality is to rename the
+ operator class.
+ </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
+ class.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><replaceable class="parameter">index_method</replaceable></term>
+ <listitem>
+ <para>
+ The name of the index method this operator class is for.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><replaceable class="parameter">newname</replaceable></term>
+ <listitem>
+ <para>
+ The new name of the operator class.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Diagnostics</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><computeroutput>ALTER OPERATOR CLASS</computeroutput></term>
+ <listitem>
+ <para>
+ Message returned if the command was successful.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Compatibility</title>
+
+ <para>
+ There is no <command>ALTER OPERATOR CLASS</command> statement in
+ the SQL standard.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+
+ <simplelist type="inline">
+ <member><xref linkend="sql-createopclass" endterm="sql-createopclass-title"></member>
+ <member><xref linkend="sql-dropopclass" endterm="sql-dropopclass-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
new file mode 100644
index 0000000000..510c874d48
--- /dev/null
+++ b/doc/src/sgml/ref/alter_schema.sgml
@@ -0,0 +1,108 @@
+<!--
+$Header$
+PostgreSQL documentation
+-->
+
+<refentry id="SQL-ALTERSCHEMA">
+ <refmeta>
+ <refentrytitle id="SQL-ALTERSCHEMA-title">ALTER SCHEMA</refentrytitle>
+ <refmiscinfo>SQL - Schema Statements</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname>ALTER SCHEMA</refname>
+ <refpurpose>change the definition of a schema</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+<synopsis>
+ALTER SCHEMA <replaceable>name</replaceable> RENAME TO <replaceable>newname</replaceable>
+</synopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <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.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>Parameter</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><replaceable>name</replaceable></term>
+ <listitem>
+ <para>
+ Name of a schema
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><replaceable>newname</replaceable></term>
+ <listitem>
+ <para>
+ The new name of the schema
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Diagnostics</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><computeroutput>ALTER SCHEMA</computeroutput></term>
+ <listitem>
+ <para>
+ Message returned if the alteration was successful.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Compatibility</title>
+
+ <para>
+ There is no <command>ALTER SCHEMA</command> statement in the SQL
+ standard.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+
+ <simplelist type="inline">
+ <member><xref linkend="sql-createschema" endterm="sql-createschema-title"></member>
+ <member><xref linkend="sql-dropschema" endterm="sql-dropschema-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_user.sgml b/doc/src/sgml/ref/alter_user.sgml
index 165398e487..fb4284e552 100644
--- a/doc/src/sgml/ref/alter_user.sgml
+++ b/doc/src/sgml/ref/alter_user.sgml
@@ -25,6 +25,8 @@ where <replaceable class="PARAMETER">option</replaceable> can be:
| CREATEUSER | NOCREATEUSER
| VALID UNTIL '<replaceable class="PARAMETER">abstime</replaceable>'
+ALTER USER <replaceable class="PARAMETER">username</replaceable> RENAME TO <replaceable>newname</replaceable>
+
ALTER USER <replaceable class="PARAMETER">username</replaceable> SET <replaceable>variable</replaceable> { TO | = } { <replaceable>value</replaceable> | DEFAULT }
ALTER USER <replaceable class="PARAMETER">username</replaceable> RESET <replaceable>variable</replaceable>
</synopsis>
@@ -48,7 +50,13 @@ ALTER USER <replaceable class="PARAMETER">username</replaceable> RESET <replacea
</para>
<para>
- The second and the third variant change a user's session default for
+ The second variant changes the name of the user. Only a database
+ superuser can rename user accounts. The session user cannot be
+ renamed. (Connect as a different user if you need to do that.)
+ </para>
+
+ <para>
+ The third and the fourth variant change a user's session default for
a specified configuration variable. Whenever the user subsequently
starts a new session, the specified value becomes the session default,
overriding whatever setting is present in <filename>postgresql.conf</>
@@ -131,6 +139,15 @@ ALTER USER <replaceable class="PARAMETER">username</replaceable> RESET <replacea
</varlistentry>
<varlistentry>
+ <term><replaceable>newname</replaceable></term>
+ <listitem>
+ <para>
+ The new name of the user.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><replaceable>variable</replaceable></term>
<term><replaceable>value</replaceable></term>
<listitem>
diff --git a/doc/src/sgml/ref/create_aggregate.sgml b/doc/src/sgml/ref/create_aggregate.sgml
index 84b20cc551..de0f6ae622 100644
--- a/doc/src/sgml/ref/create_aggregate.sgml
+++ b/doc/src/sgml/ref/create_aggregate.sgml
@@ -231,14 +231,6 @@ CREATE AGGREGATE <replaceable class="PARAMETER">name</replaceable> (
</refsect1>
<refsect1>
- <title>Notes</title>
-
- <para>
- Use <command>DROP AGGREGATE</command> to drop aggregate functions.
- </para>
- </refsect1>
-
- <refsect1>
<title>Examples</title>
<para>
@@ -255,6 +247,15 @@ CREATE AGGREGATE <replaceable class="PARAMETER">name</replaceable> (
standard does not provide for user-defined aggregate function.
</para>
</refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+
+ <simplelist type="inline">
+ <member><xref linkend="sql-alteraggregate" endterm="sql-alteraggregate-title"></member>
+ <member><xref linkend="sql-dropaggregate" endterm="sql-dropaggregate-title"></member>
+ </simplelist>
+ </refsect1>
</refentry>
<!-- Keep this comment at the end of the file
diff --git a/doc/src/sgml/ref/create_conversion.sgml b/doc/src/sgml/ref/create_conversion.sgml
index 2eff0b56f6..2966a47db4 100644
--- a/doc/src/sgml/ref/create_conversion.sgml
+++ b/doc/src/sgml/ref/create_conversion.sgml
@@ -171,10 +171,11 @@ CREATE CONVERSION myconv FOR 'UNICODE' TO 'LATIN1' FROM myfunc;
<refsect1 id="sql-createconversion-seealso">
<title>See Also</title>
- <para>
- <xref linkend="sql-createfunction" endterm="sql-createfunction-title">,
- <xref linkend="sql-dropconversion" endterm="sql-dropconversion-title">
- </para>
+ <simplelist type="inline">
+ <member><xref linkend="sql-alterconversion" endterm="sql-alterconversion-title"></member>
+ <member><xref linkend="sql-createfunction" endterm="sql-createfunction-title"></member>
+ <member><xref linkend="sql-dropconversion" endterm="sql-dropconversion-title"></member>
+ </simplelist>
</refsect1>
</refentry>
diff --git a/doc/src/sgml/ref/create_function.sgml b/doc/src/sgml/ref/create_function.sgml
index cce6f1eb6f..6e424445e3 100644
--- a/doc/src/sgml/ref/create_function.sgml
+++ b/doc/src/sgml/ref/create_function.sgml
@@ -404,6 +404,7 @@ CREATE FUNCTION add(integer, integer) RETURNS integer
<title>See Also</title>
<para>
+ <xref linkend="sql-alterfunction" endterm="sql-alterfunction-title">,
<xref linkend="sql-dropfunction" endterm="sql-dropfunction-title">,
<xref linkend="sql-grant" endterm="sql-grant-title">,
<xref linkend="sql-load" endterm="sql-load-title">,
diff --git a/doc/src/sgml/ref/create_language.sgml b/doc/src/sgml/ref/create_language.sgml
index 3992d8e53a..3d683b32c3 100644
--- a/doc/src/sgml/ref/create_language.sgml
+++ b/doc/src/sgml/ref/create_language.sgml
@@ -238,16 +238,15 @@ CREATE LANGUAGE plsample
<refsect1>
<title>See Also</title>
- <para>
- <simplelist type="inline">
- <member><xref linkend="app-createlang"></member>
- <member><xref linkend="sql-createfunction" endterm="sql-createfunction-title"></member>
- <member><xref linkend="app-droplang"></member>
- <member><xref linkend="sql-droplanguage" endterm="sql-droplanguage-title"></member>
- <member><xref linkend="sql-grant" endterm="sql-grant-title"></member>
- <member><xref linkend="sql-revoke" endterm="sql-revoke-title"></member>
- </simplelist>
- </para>
+ <simplelist type="inline">
+ <member><xref linkend="sql-alterlanguage" endterm="sql-alterlanguage-title"></member>
+ <member><xref linkend="sql-createfunction" endterm="sql-createfunction-title"></member>
+ <member><xref linkend="sql-droplanguage" endterm="sql-droplanguage-title"></member>
+ <member><xref linkend="sql-grant" endterm="sql-grant-title"></member>
+ <member><xref linkend="sql-revoke" endterm="sql-revoke-title"></member>
+ <member><xref linkend="app-createlang"></member>
+ <member><xref linkend="app-droplang"></member>
+ </simplelist>
</refsect1>
</refentry>
diff --git a/doc/src/sgml/ref/create_opclass.sgml b/doc/src/sgml/ref/create_opclass.sgml
index f61a9d4a8c..b1854bdb3a 100644
--- a/doc/src/sgml/ref/create_opclass.sgml
+++ b/doc/src/sgml/ref/create_opclass.sgml
@@ -217,16 +217,6 @@ CREATE OPERATOR CLASS <replaceable class="parameter">name</replaceable> [ DEFAUL
</refsect1>
<refsect1>
- <title>Notes</title>
-
- <para>
- Refer to
- <xref linkend="sql-dropopclass" endterm="sql-dropopclass-title">
- to delete user-defined operator classes from a database.
- </para>
- </refsect1>
-
- <refsect1>
<title>Examples</title>
<para>
@@ -263,6 +253,15 @@ CREATE OPERATOR CLASS gist__int_ops
standard.
</para>
</refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+
+ <simplelist type="inline">
+ <member><xref linkend="sql-alteropclass" endterm="sql-alteropclass-title"></member>
+ <member><xref linkend="sql-dropopclass" endterm="sql-dropopclass-title"></member>
+ </simplelist>
+ </refsect1>
</refentry>
<!-- Keep this comment at the end of the file
diff --git a/doc/src/sgml/ref/create_schema.sgml b/doc/src/sgml/ref/create_schema.sgml
index 2ac248ef7e..6d2c076dab 100644
--- a/doc/src/sgml/ref/create_schema.sgml
+++ b/doc/src/sgml/ref/create_schema.sgml
@@ -123,10 +123,6 @@ CREATE SCHEMA AUTHORIZATION <replaceable class="parameter">username</replaceable
privilege for the current database. (Of course, superusers bypass
this check.)
</para>
-
- <para>
- Use <command>DROP SCHEMA</command> to remove a schema.
- </para>
</refsect1>
<refsect1>
@@ -196,6 +192,16 @@ CREATE VIEW hollywood.winners AS
<literal>CREATE</> privilege on his schema to someone else.
</para>
</refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+
+ <simplelist type="inline">
+ <member><xref linkend="sql-alterschema" endterm="sql-alterschema-title"></member>
+ <member><xref linkend="sql-dropschema" endterm="sql-dropschema-title"></member>
+ </simplelist>
+ </refsect1>
+
</refentry>
<!-- Keep this comment at the end of the file
diff --git a/doc/src/sgml/ref/drop_aggregate.sgml b/doc/src/sgml/ref/drop_aggregate.sgml
index 26c926cb50..26f4870f6e 100644
--- a/doc/src/sgml/ref/drop_aggregate.sgml
+++ b/doc/src/sgml/ref/drop_aggregate.sgml
@@ -124,6 +124,7 @@ DROP AGGREGATE myavg(integer);
<title>See Also</title>
<simplelist type="inline">
+ <member><xref linkend="sql-alteraggregate" endterm="sql-alteraggregate-title"></member>
<member><xref linkend="sql-createaggregate" endterm="sql-createaggregate-title"></member>
</simplelist>
</refsect1>
diff --git a/doc/src/sgml/ref/drop_conversion.sgml b/doc/src/sgml/ref/drop_conversion.sgml
index 7cf254c791..a6a9c613d0 100644
--- a/doc/src/sgml/ref/drop_conversion.sgml
+++ b/doc/src/sgml/ref/drop_conversion.sgml
@@ -79,6 +79,7 @@ DROP CONVERSION myname;
<title>See Also</title>
<simplelist type="inline">
+ <member><xref linkend="sql-alterconversion" endterm="sql-alterconversion-title"></member>
<member><xref linkend="sql-createconversion" endterm="sql-createconversion-title"></member>
</simplelist>
</refsect1>
diff --git a/doc/src/sgml/ref/drop_function.sgml b/doc/src/sgml/ref/drop_function.sgml
index 9b5938d479..7c24064447 100644
--- a/doc/src/sgml/ref/drop_function.sgml
+++ b/doc/src/sgml/ref/drop_function.sgml
@@ -126,6 +126,7 @@ DROP FUNCTION sqrt(integer);
<simplelist type="inline">
<member><xref linkend="sql-createfunction" endterm="sql-createfunction-title"></member>
+ <member><xref linkend="sql-alterfunction" endterm="sql-alterfunction-title"></member>
</simplelist>
</refsect1>
diff --git a/doc/src/sgml/ref/drop_language.sgml b/doc/src/sgml/ref/drop_language.sgml
index a973b339ea..520ac84354 100644
--- a/doc/src/sgml/ref/drop_language.sgml
+++ b/doc/src/sgml/ref/drop_language.sgml
@@ -118,7 +118,9 @@ DROP LANGUAGE plsample;
<title>See Also</title>
<simplelist type="inline">
+ <member><xref linkend="sql-alterlanguage" endterm="sql-alterlanguage-title"></member>
<member><xref linkend="sql-createlanguage" endterm="sql-createlanguage-title"></member>
+ <member><xref linkend="app-droplang"></member>
</simplelist>
</refsect1>
diff --git a/doc/src/sgml/ref/drop_opclass.sgml b/doc/src/sgml/ref/drop_opclass.sgml
index 7214cce2e0..730c32b5b6 100644
--- a/doc/src/sgml/ref/drop_opclass.sgml
+++ b/doc/src/sgml/ref/drop_opclass.sgml
@@ -116,6 +116,7 @@ DROP OPERATOR CLASS widget_ops USING btree;
<title>See Also</title>
<simplelist type="inline">
+ <member><xref linkend="sql-alteropclass" endterm="sql-alteropclass-title"></member>
<member><xref linkend="sql-createopclass" endterm="sql-createopclass-title"></member>
</simplelist>
</refsect1>
diff --git a/doc/src/sgml/ref/drop_schema.sgml b/doc/src/sgml/ref/drop_schema.sgml
index 6b8a559b1b..f50a58c32c 100644
--- a/doc/src/sgml/ref/drop_schema.sgml
+++ b/doc/src/sgml/ref/drop_schema.sgml
@@ -120,6 +120,7 @@ DROP SCHEMA mystuff CASCADE;
<title>See Also</title>
<simplelist type="inline">
+ <member><xref linkend="sql-alterschema" endterm="sql-alterschema-title"></member>
<member><xref linkend="sql-createschema" endterm="sql-createschema-title"></member>
</simplelist>
</refsect1>
diff --git a/doc/src/sgml/reference.sgml b/doc/src/sgml/reference.sgml
index ed733f2208..7420d6b1e0 100644
--- a/doc/src/sgml/reference.sgml
+++ b/doc/src/sgml/reference.sgml
@@ -38,9 +38,15 @@ PostgreSQL Reference Manual
</partintro>
&abort;
+ &alterAggregate;
+ &alterConversion;
&alterDatabase;
&alterDomain;
+ &alterFunction;
&alterGroup;
+ &alterLanguage;
+ &alterOperatorClass;
+ &alterSchema;
&alterSequence;
&alterTable;
&alterTrigger;
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index 820c1b8d4d..a6cbc05acb 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -1327,3 +1327,40 @@ pg_opclass_ownercheck(Oid opc_oid, AclId userid)
return userid == owner_id;
}
+
+
+/*
+ * Ownership check for database (specified as OID)
+ */
+bool
+pg_database_ownercheck(Oid db_oid, AclId userid)
+{
+ Relation pg_database;
+ ScanKeyData entry[1];
+ HeapScanDesc scan;
+ HeapTuple dbtuple;
+ int32 dba;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(userid))
+ return true;
+
+ /* There's no syscache for pg_database, so must look the hard way */
+ pg_database = heap_openr(DatabaseRelationName, AccessShareLock);
+ ScanKeyEntryInitialize(&entry[0], 0x0,
+ ObjectIdAttributeNumber, F_OIDEQ,
+ ObjectIdGetDatum(db_oid));
+ scan = heap_beginscan(pg_database, SnapshotNow, 1, entry);
+
+ dbtuple = heap_getnext(scan, ForwardScanDirection);
+
+ if (!HeapTupleIsValid(dbtuple))
+ elog(ERROR, "database %u does not exist", db_oid);
+
+ dba = ((Form_pg_database) GETSTRUCT(dbtuple))->datdba;
+
+ heap_endscan(scan);
+ heap_close(pg_database, AccessShareLock);
+
+ return userid == dba;
+}
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index fbfb95d067..4c0087b5e5 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -160,7 +160,7 @@ RangeVarGetRelid(const RangeVar *relation, bool failOK)
*/
if (relation->catalogname)
{
- if (strcmp(relation->catalogname, DatabaseName) != 0)
+ if (strcmp(relation->catalogname, get_database_name(MyDatabaseId)) != 0)
elog(ERROR, "Cross-database references are not implemented");
}
@@ -207,7 +207,7 @@ RangeVarGetCreationNamespace(const RangeVar *newRelation)
*/
if (newRelation->catalogname)
{
- if (strcmp(newRelation->catalogname, DatabaseName) != 0)
+ if (strcmp(newRelation->catalogname, get_database_name(MyDatabaseId)) != 0)
elog(ERROR, "Cross-database references are not implemented");
}
@@ -1146,7 +1146,7 @@ DeconstructQualifiedName(List *names,
/*
* We check the catalog name and then ignore it.
*/
- if (strcmp(catalogname, DatabaseName) != 0)
+ if (strcmp(catalogname, get_database_name(MyDatabaseId)) != 0)
elog(ERROR, "Cross-database references are not implemented");
break;
default:
@@ -1596,7 +1596,7 @@ InitTempTableNamespace(void)
if (pg_database_aclcheck(MyDatabaseId, GetSessionUserId(),
ACL_CREATE_TEMP) != ACLCHECK_OK)
elog(ERROR, "%s: not authorized to create temp tables",
- DatabaseName);
+ get_database_name(MyDatabaseId));
snprintf(namespaceName, sizeof(namespaceName), "pg_temp_%d", MyBackendId);
diff --git a/src/backend/commands/Makefile b/src/backend/commands/Makefile
index d60547b202..c74f45b0db 100644
--- a/src/backend/commands/Makefile
+++ b/src/backend/commands/Makefile
@@ -12,7 +12,7 @@ subdir = src/backend/commands
top_builddir = ../../..
include $(top_builddir)/src/Makefile.global
-OBJS = aggregatecmds.o analyze.o async.o cluster.o comment.o \
+OBJS = aggregatecmds.o alter.o analyze.o async.o cluster.o comment.o \
conversioncmds.o copy.o \
dbcommands.o define.o explain.o functioncmds.o \
indexcmds.o lockcmds.o operatorcmds.o opclasscmds.o \
diff --git a/src/backend/commands/aggregatecmds.c b/src/backend/commands/aggregatecmds.c
index d65d3abce5..8d85e0d7ff 100644
--- a/src/backend/commands/aggregatecmds.c
+++ b/src/backend/commands/aggregatecmds.c
@@ -25,6 +25,7 @@
#include "access/heapam.h"
#include "catalog/catname.h"
#include "catalog/dependency.h"
+#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/pg_aggregate.h"
#include "catalog/pg_proc.h"
@@ -193,3 +194,75 @@ RemoveAggregate(RemoveAggrStmt *stmt)
performDeletion(&object, stmt->behavior);
}
+
+
+void
+RenameAggregate(List *name, TypeName *basetype, const char *newname)
+{
+ Oid basetypeOid;
+ Oid procOid;
+ Oid namespaceOid;
+ Oid oid_array[FUNC_MAX_ARGS];
+ HeapTuple tup;
+ Relation rel;
+ AclResult aclresult;
+
+ /*
+ * 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).
+ */
+ if (basetype)
+ basetypeOid = typenameTypeId(basetype);
+ else
+ basetypeOid = ANYOID;
+
+ rel = heap_openr(ProcedureRelationName, RowExclusiveLock);
+
+ procOid = find_aggregate_func("RenameAggregate", name, basetypeOid);
+
+ tup = SearchSysCacheCopy(PROCOID,
+ ObjectIdGetDatum(procOid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tup)) /* should not happen */
+ elog(ERROR, "RenameAggregate: couldn't find pg_proc tuple for %s",
+ NameListToString(name));
+
+ namespaceOid = ((Form_pg_proc) GETSTRUCT(tup))->pronamespace;
+
+ /* make sure the new name doesn't exist */
+ MemSet(oid_array, 0, sizeof(oid_array));
+ oid_array[0] = basetypeOid;
+ if (SearchSysCacheExists(PROCNAMENSP,
+ CStringGetDatum(newname),
+ Int16GetDatum(1),
+ PointerGetDatum(oid_array),
+ ObjectIdGetDatum(namespaceOid)))
+ {
+ if (basetypeOid == ANYOID)
+ elog(ERROR, "function %s(*) already exists in schema %s",
+ newname, get_namespace_name(namespaceOid));
+ else
+ elog(ERROR, "function %s(%s) already exists in schema %s",
+ newname, format_type_be(basetypeOid), get_namespace_name(namespaceOid));
+ }
+
+ /* must be owner */
+ if (!pg_proc_ownercheck(procOid, GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, NameListToString(name));
+
+ /* must have CREATE privilege on namespace */
+ aclresult = pg_namespace_aclcheck(namespaceOid, GetUserId(), ACL_CREATE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult, get_namespace_name(namespaceOid));
+
+ /* rename */
+ namestrcpy(&(((Form_pg_proc) GETSTRUCT(tup))->proname), newname);
+ 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
new file mode 100644
index 0000000000..dc91bb025b
--- /dev/null
+++ b/src/backend/commands/alter.c
@@ -0,0 +1,159 @@
+/*-------------------------------------------------------------------------
+ *
+ * alter.c
+ * Drivers for generic alter commands
+ *
+ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * $Header$
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/htup.h"
+#include "catalog/catalog.h"
+#include "catalog/namespace.h"
+#include "catalog/pg_class.h"
+#include "commands/alter.h"
+#include "commands/conversioncmds.h"
+#include "commands/dbcommands.h"
+#include "commands/defrem.h"
+#include "commands/proclang.h"
+#include "commands/schemacmds.h"
+#include "commands/tablecmds.h"
+#include "commands/trigger.h"
+#include "commands/user.h"
+#include "miscadmin.h"
+#include "parser/parse_clause.h"
+#include "utils/acl.h"
+#include "utils/lsyscache.h"
+#include "utils/syscache.h"
+
+
+static void
+CheckOwnership(RangeVar *rel, bool noCatalogs)
+{
+ Oid relOid;
+ HeapTuple tuple;
+
+ relOid = RangeVarGetRelid(rel, false);
+ tuple = SearchSysCache(RELOID,
+ ObjectIdGetDatum(relOid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "Relation \"%s\" does not exist", rel->relname);
+
+ if (!pg_class_ownercheck(relOid, GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, rel->relname);
+
+ if (noCatalogs)
+ {
+ if (!allowSystemTableMods &&
+ IsSystemClass((Form_pg_class) GETSTRUCT(tuple)))
+ elog(ERROR, "relation \"%s\" is a system catalog",
+ rel->relname);
+ }
+
+ ReleaseSysCache(tuple);
+}
+
+
+void
+ExecRenameStmt(RenameStmt *stmt)
+{
+ switch (stmt->renameType)
+ {
+ case OBJECT_AGGREGATE:
+ RenameAggregate(stmt->object, (TypeName *) lfirst(stmt->objarg), stmt->newname);
+ break;
+
+ case OBJECT_CONVERSION:
+ RenameConversion(stmt->object, stmt->newname);
+ break;
+
+ case OBJECT_DATABASE:
+ RenameDatabase(stmt->subname, stmt->newname);
+ break;
+
+ case OBJECT_FUNCTION:
+ RenameFunction(stmt->object, stmt->objarg, stmt->newname);
+ break;
+
+ case OBJECT_GROUP:
+ RenameGroup(stmt->subname, stmt->newname);
+ break;
+
+ case OBJECT_LANGUAGE:
+ RenameLanguage(stmt->subname, stmt->newname);
+ break;
+
+ case OBJECT_OPCLASS:
+ RenameOpClass(stmt->object, stmt->subname, stmt->newname);
+ break;
+
+ case OBJECT_SCHEMA:
+ RenameSchema(stmt->subname, stmt->newname);
+ break;
+
+ case OBJECT_USER:
+ RenameUser(stmt->subname, stmt->newname);
+ break;
+
+ case OBJECT_TABLE:
+ case OBJECT_COLUMN:
+ case OBJECT_TRIGGER:
+ {
+ Oid relid;
+
+ CheckOwnership(stmt->relation, true);
+
+ relid = RangeVarGetRelid(stmt->relation, false);
+
+ switch (stmt->renameType)
+ {
+ case OBJECT_TABLE:
+ {
+ /*
+ * RENAME TABLE requires that we (still) hold
+ * CREATE rights on the containing namespace, as
+ * well as ownership of the table.
+ */
+ Oid namespaceId = get_rel_namespace(relid);
+ AclResult aclresult;
+
+ aclresult = pg_namespace_aclcheck(namespaceId,
+ GetUserId(),
+ ACL_CREATE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult,
+ get_namespace_name(namespaceId));
+
+ renamerel(relid, stmt->newname);
+ break;
+ }
+ case OBJECT_COLUMN:
+ renameatt(relid,
+ stmt->subname, /* old att name */
+ stmt->newname, /* new att name */
+ interpretInhOption(stmt->relation->inhOpt), /* recursive? */
+ false); /* recursing already? */
+ break;
+ case OBJECT_TRIGGER:
+ renametrig(relid,
+ stmt->subname, /* old att name */
+ stmt->newname); /* new att name */
+ break;
+ default:
+ /*can't happen*/;
+ }
+ break;
+ }
+
+ default:
+ elog(ERROR, "invalid object type for RenameStmt: %d", stmt->renameType);
+ }
+}
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index 96af28ab9c..a9d3ddab56 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -192,7 +192,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
onerel = relation_open(relid, AccessShareLock);
if (!(pg_class_ownercheck(RelationGetRelid(onerel), GetUserId()) ||
- (is_dbadmin(MyDatabaseId) && !onerel->rd_rel->relisshared)))
+ (pg_database_ownercheck(MyDatabaseId, GetUserId()) && !onerel->rd_rel->relisshared)))
{
/* No need for a WARNING if we already complained during VACUUM */
if (!vacstmt->vacuum)
diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c
index c15bf3109b..dcb6410d18 100644
--- a/src/backend/commands/comment.c
+++ b/src/backend/commands/comment.c
@@ -71,40 +71,40 @@ CommentObject(CommentStmt *stmt)
{
switch (stmt->objtype)
{
- case COMMENT_ON_INDEX:
- case COMMENT_ON_SEQUENCE:
- case COMMENT_ON_TABLE:
- case COMMENT_ON_VIEW:
+ case OBJECT_INDEX:
+ case OBJECT_SEQUENCE:
+ case OBJECT_TABLE:
+ case OBJECT_VIEW:
CommentRelation(stmt->objtype, stmt->objname, stmt->comment);
break;
- case COMMENT_ON_COLUMN:
+ case OBJECT_COLUMN:
CommentAttribute(stmt->objname, stmt->comment);
break;
- case COMMENT_ON_DATABASE:
+ case OBJECT_DATABASE:
CommentDatabase(stmt->objname, stmt->comment);
break;
- case COMMENT_ON_RULE:
+ case OBJECT_RULE:
CommentRule(stmt->objname, stmt->comment);
break;
- case COMMENT_ON_TYPE:
+ case OBJECT_TYPE:
CommentType(stmt->objname, stmt->comment);
break;
- case COMMENT_ON_AGGREGATE:
+ case OBJECT_AGGREGATE:
CommentAggregate(stmt->objname, stmt->objargs, stmt->comment);
break;
- case COMMENT_ON_FUNCTION:
+ case OBJECT_FUNCTION:
CommentProc(stmt->objname, stmt->objargs, stmt->comment);
break;
- case COMMENT_ON_OPERATOR:
+ case OBJECT_OPERATOR:
CommentOperator(stmt->objname, stmt->objargs, stmt->comment);
break;
- case COMMENT_ON_TRIGGER:
+ case OBJECT_TRIGGER:
CommentTrigger(stmt->objname, stmt->comment);
break;
- case COMMENT_ON_SCHEMA:
+ case OBJECT_SCHEMA:
CommentNamespace(stmt->objname, stmt->comment);
break;
- case COMMENT_ON_CONSTRAINT:
+ case OBJECT_CONSTRAINT:
CommentConstraint(stmt->objname, stmt->comment);
break;
default:
@@ -301,22 +301,22 @@ CommentRelation(int objtype, List *relname, char *comment)
switch (objtype)
{
- case COMMENT_ON_INDEX:
+ case OBJECT_INDEX:
if (relation->rd_rel->relkind != RELKIND_INDEX)
elog(ERROR, "relation \"%s\" is not an index",
RelationGetRelationName(relation));
break;
- case COMMENT_ON_SEQUENCE:
+ case OBJECT_SEQUENCE:
if (relation->rd_rel->relkind != RELKIND_SEQUENCE)
elog(ERROR, "relation \"%s\" is not a sequence",
RelationGetRelationName(relation));
break;
- case COMMENT_ON_TABLE:
+ case OBJECT_TABLE:
if (relation->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "relation \"%s\" is not a table",
RelationGetRelationName(relation));
break;
- case COMMENT_ON_VIEW:
+ case OBJECT_VIEW:
if (relation->rd_rel->relkind != RELKIND_VIEW)
elog(ERROR, "relation \"%s\" is not a view",
RelationGetRelationName(relation));
@@ -410,7 +410,7 @@ CommentDatabase(List *qualname, char *comment)
/* Allow if the user matches the database dba or is a superuser */
- if (!(superuser() || is_dbadmin(oid)))
+ if (!pg_database_ownercheck(oid, GetUserId()))
elog(ERROR, "you are not permitted to comment on database \"%s\"",
database);
diff --git a/src/backend/commands/conversioncmds.c b/src/backend/commands/conversioncmds.c
index 082cfc476d..0aa68a492b 100644
--- a/src/backend/commands/conversioncmds.c
+++ b/src/backend/commands/conversioncmds.c
@@ -15,7 +15,10 @@
#include "postgres.h"
#include "catalog/pg_conversion.h"
+#include "access/heapam.h"
#include "catalog/catalog.h"
+#include "catalog/catname.h"
+#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/pg_type.h"
#include "mb/pg_wchar.h"
@@ -23,7 +26,9 @@
#include "miscadmin.h"
#include "parser/parse_func.h"
#include "utils/acl.h"
+#include "utils/builtins.h"
#include "utils/lsyscache.h"
+#include "utils/syscache.h"
/*
@@ -98,3 +103,58 @@ DropConversionCommand(List *name, DropBehavior behavior)
ConversionDrop(conversionOid, behavior);
}
+
+/*
+ * Rename conversion
+ */
+void
+RenameConversion(List *name, const char *newname)
+{
+ Oid conversionOid;
+ Oid namespaceOid;
+ HeapTuple tup;
+ Relation rel;
+ AclResult aclresult;
+
+ rel = heap_openr(ConversionRelationName, RowExclusiveLock);
+
+ conversionOid = FindConversionByName(name);
+ if (!OidIsValid(conversionOid))
+ elog(ERROR, "conversion %s not found", NameListToString(name));
+
+ tup = SearchSysCacheCopy(CONOID,
+ ObjectIdGetDatum(conversionOid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tup)) /* should not happen */
+ elog(ERROR, "couldn't find pg_conversion tuple for %s",
+ NameListToString(name));
+
+ namespaceOid = ((Form_pg_conversion) GETSTRUCT(tup))->connamespace;
+
+ /* make sure the new name doesn't exist */
+ if (SearchSysCacheExists(CONNAMENSP,
+ CStringGetDatum(newname),
+ ObjectIdGetDatum(namespaceOid),
+ 0, 0))
+ {
+ elog(ERROR, "conversion %s already exists in schema %s",
+ newname, get_namespace_name(namespaceOid));
+ }
+
+ /* must be owner */
+ if (!superuser() && ((Form_pg_conversion) GETSTRUCT(tup))->conowner != GetUserId())
+ aclcheck_error(ACLCHECK_NOT_OWNER, NameListToString(name));
+
+ /* must have CREATE privilege on namespace */
+ aclresult = pg_namespace_aclcheck(namespaceOid, GetUserId(), ACL_CREATE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult, get_namespace_name(namespaceOid));
+
+ /* rename */
+ namestrcpy(&(((Form_pg_conversion) GETSTRUCT(tup))->conname), newname);
+ 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 f59cec79ea..de62845639 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -20,6 +20,7 @@
#include <unistd.h>
#include <sys/stat.h>
+#include "access/genam.h"
#include "access/heapam.h"
#include "catalog/catname.h"
#include "catalog/catalog.h"
@@ -31,6 +32,7 @@
#include "miscadmin.h"
#include "storage/freespace.h"
#include "storage/sinval.h"
+#include "utils/acl.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
@@ -402,13 +404,13 @@ dropdb(const char *dbname)
char *nominal_loc;
char dbpath[MAXPGPATH];
Relation pgdbrel;
- HeapScanDesc pgdbscan;
+ SysScanDesc pgdbscan;
ScanKeyData key;
HeapTuple tup;
AssertArg(dbname);
- if (strcmp(dbname, DatabaseName) == 0)
+ if (strcmp(dbname, get_database_name(MyDatabaseId)) == 0)
elog(ERROR, "DROP DATABASE: cannot be executed on the currently open database");
PreventTransactionChain((void *) dbname, "DROP DATABASE");
@@ -454,9 +456,9 @@ dropdb(const char *dbname)
ScanKeyEntryInitialize(&key, 0, ObjectIdAttributeNumber,
F_OIDEQ, ObjectIdGetDatum(db_id));
- pgdbscan = heap_beginscan(pgdbrel, SnapshotNow, 1, &key);
+ pgdbscan = systable_beginscan(pgdbrel, DatabaseOidIndex, true, SnapshotNow, 1, &key);
- tup = heap_getnext(pgdbscan, ForwardScanDirection);
+ tup = systable_getnext(pgdbscan);
if (!HeapTupleIsValid(tup))
{
/*
@@ -470,7 +472,7 @@ dropdb(const char *dbname)
/* Remove the database's tuple from pg_database */
simple_heap_delete(pgdbrel, &tup->t_self);
- heap_endscan(pgdbscan);
+ systable_endscan(pgdbscan);
/*
* Delete any comments associated with the database
@@ -513,6 +515,94 @@ dropdb(const char *dbname)
}
+/*
+ * Rename database
+ */
+void
+RenameDatabase(const char *oldname, const char *newname)
+{
+ HeapTuple tup, newtup;
+ Relation rel;
+ SysScanDesc scan, scan2;
+ ScanKeyData key, key2;
+
+ /*
+ * Obtain AccessExclusiveLock so that no new session gets started
+ * while the rename is in progress.
+ */
+ rel = heap_openr(DatabaseRelationName, AccessExclusiveLock);
+
+ ScanKeyEntryInitialize(&key, 0, Anum_pg_database_datname,
+ F_NAMEEQ, NameGetDatum(oldname));
+ scan = systable_beginscan(rel, DatabaseNameIndex, true, SnapshotNow, 1, &key);
+
+ tup = systable_getnext(scan);
+ if (!HeapTupleIsValid(tup))
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
+ errmsg("database \"%s\" does not exist", oldname)));
+
+ /*
+ * XXX Client applications probably store the current database
+ * somewhere, so renaming it could cause confusion. On the other
+ * hand, there may not be an actual problem besides a little
+ * confusion, so think about this and decide.
+ */
+ if (HeapTupleGetOid(tup) == MyDatabaseId)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
+ errmsg("current database may not be renamed")));
+
+ /*
+ * Make sure the database does not have active sessions. Might
+ * not be necessary, but it's consistent with other database
+ * operations.
+ */
+ if (DatabaseHasActiveBackends(HeapTupleGetOid(tup), false))
+ elog(ERROR, "database \"%s\" is being accessed by other users", oldname);
+
+ /* make sure the new name doesn't exist */
+ ScanKeyEntryInitialize(&key2, 0, Anum_pg_database_datname,
+ F_NAMEEQ, NameGetDatum(newname));
+ scan2 = systable_beginscan(rel, DatabaseNameIndex, true, SnapshotNow, 1, &key2);
+ if (HeapTupleIsValid(systable_getnext(scan2)))
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
+ errmsg("database \"%s\" already exists", newname)));
+ }
+ systable_endscan(scan2);
+
+ /* must be owner */
+ if (!pg_database_ownercheck(HeapTupleGetOid(tup), GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, oldname);
+
+ /* must have createdb */
+ if (!have_createdb_privilege())
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
+ errmsg("permission denied")));
+ }
+
+ /* rename */
+ newtup = heap_copytuple(tup);
+ namestrcpy(&(((Form_pg_database) GETSTRUCT(newtup))->datname), newname);
+ simple_heap_update(rel, &tup->t_self, newtup);
+ CatalogUpdateIndexes(rel, newtup);
+
+ systable_endscan(scan);
+ heap_close(rel, NoLock);
+
+ /*
+ * Force dirty buffers out to disk, so that newly-connecting
+ * backends will see the renamed database in pg_database right
+ * away. (They'll see an uncommitted tuple, but they don't care;
+ * see GetRawDatabaseInfo.)
+ */
+ BufferSync();
+}
+
/*
* ALTER DATABASE name SET ...
@@ -525,7 +615,7 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt)
newtuple;
Relation rel;
ScanKeyData scankey;
- HeapScanDesc scan;
+ SysScanDesc scan;
Datum repl_val[Natts_pg_database];
char repl_null[Natts_pg_database];
char repl_repl[Natts_pg_database];
@@ -535,8 +625,8 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt)
rel = heap_openr(DatabaseRelationName, RowExclusiveLock);
ScanKeyEntryInitialize(&scankey, 0, Anum_pg_database_datname,
F_NAMEEQ, NameGetDatum(stmt->dbname));
- scan = heap_beginscan(rel, SnapshotNow, 1, &scankey);
- tuple = heap_getnext(scan, ForwardScanDirection);
+ scan = systable_beginscan(rel, DatabaseNameIndex, true, SnapshotNow, 1, &scankey);
+ tuple = systable_getnext(scan);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "database \"%s\" does not exist", stmt->dbname);
@@ -583,7 +673,7 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt)
/* Update indexes */
CatalogUpdateIndexes(rel, newtuple);
- heap_endscan(scan);
+ systable_endscan(scan);
heap_close(rel, RowExclusiveLock);
}
@@ -601,7 +691,7 @@ get_db_info(const char *name, Oid *dbIdP, int4 *ownerIdP,
{
Relation relation;
ScanKeyData scanKey;
- HeapScanDesc scan;
+ SysScanDesc scan;
HeapTuple tuple;
bool gottuple;
@@ -613,9 +703,9 @@ get_db_info(const char *name, Oid *dbIdP, int4 *ownerIdP,
ScanKeyEntryInitialize(&scanKey, 0, Anum_pg_database_datname,
F_NAMEEQ, NameGetDatum(name));
- scan = heap_beginscan(relation, SnapshotNow, 1, &scanKey);
+ scan = systable_beginscan(relation, DatabaseNameIndex, true, SnapshotNow, 1, &scanKey);
- tuple = heap_getnext(scan, ForwardScanDirection);
+ tuple = systable_getnext(scan);
gottuple = HeapTupleIsValid(tuple);
if (gottuple)
@@ -667,7 +757,7 @@ get_db_info(const char *name, Oid *dbIdP, int4 *ownerIdP,
}
}
- heap_endscan(scan);
+ systable_endscan(scan);
heap_close(relation, AccessShareLock);
return gottuple;
@@ -790,7 +880,7 @@ get_database_oid(const char *dbname)
{
Relation pg_database;
ScanKeyData entry[1];
- HeapScanDesc scan;
+ SysScanDesc scan;
HeapTuple dbtuple;
Oid oid;
@@ -799,9 +889,9 @@ get_database_oid(const char *dbname)
ScanKeyEntryInitialize(&entry[0], 0x0,
Anum_pg_database_datname, F_NAMEEQ,
CStringGetDatum(dbname));
- scan = heap_beginscan(pg_database, SnapshotNow, 1, entry);
+ scan = systable_beginscan(pg_database, DatabaseNameIndex, true, SnapshotNow, 1, entry);
- dbtuple = heap_getnext(scan, ForwardScanDirection);
+ dbtuple = systable_getnext(scan);
/* We assume that there can be at most one matching tuple */
if (HeapTupleIsValid(dbtuple))
@@ -809,45 +899,46 @@ get_database_oid(const char *dbname)
else
oid = InvalidOid;
- heap_endscan(scan);
+ systable_endscan(scan);
heap_close(pg_database, AccessShareLock);
return oid;
}
+
/*
- * get_database_owner - given a database OID, fetch the owner's usesysid.
+ * get_database_name - given a database OID, look up the name
*
- * Errors out if database not found.
+ * Returns InvalidOid if database name not found.
*
* This is not actually used in this file, but is exported for use elsewhere.
*/
-Oid
-get_database_owner(Oid dbid)
+char *
+get_database_name(Oid dbid)
{
Relation pg_database;
ScanKeyData entry[1];
- HeapScanDesc scan;
+ SysScanDesc scan;
HeapTuple dbtuple;
- int32 dba;
+ char *result;
/* There's no syscache for pg_database, so must look the hard way */
pg_database = heap_openr(DatabaseRelationName, AccessShareLock);
ScanKeyEntryInitialize(&entry[0], 0x0,
ObjectIdAttributeNumber, F_OIDEQ,
ObjectIdGetDatum(dbid));
- scan = heap_beginscan(pg_database, SnapshotNow, 1, entry);
+ scan = systable_beginscan(pg_database, DatabaseOidIndex, true, SnapshotNow, 1, entry);
- dbtuple = heap_getnext(scan, ForwardScanDirection);
+ dbtuple = systable_getnext(scan);
- if (!HeapTupleIsValid(dbtuple))
- elog(ERROR, "database %u does not exist", dbid);
-
- dba = ((Form_pg_database) GETSTRUCT(dbtuple))->datdba;
+ /* We assume that there can be at most one matching tuple */
+ if (HeapTupleIsValid(dbtuple))
+ result = pstrdup(NameStr(((Form_pg_database) GETSTRUCT(dbtuple))->datname));
+ else
+ result = NULL;
- heap_endscan(scan);
+ systable_endscan(scan);
heap_close(pg_database, AccessShareLock);
- /* XXX some confusion about whether userids are OID or int4 ... */
- return (Oid) dba;
+ return result;
}
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 51d9617dfb..69b3dee2d1 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -592,6 +592,72 @@ RemoveFunctionById(Oid funcOid)
/*
+ * Rename function
+ */
+void
+RenameFunction(List *name, List *argtypes, const char *newname)
+{
+ Oid procOid;
+ Oid namespaceOid;
+ Oid oid_array[FUNC_MAX_ARGS];
+ HeapTuple tup;
+ Relation rel;
+ AclResult aclresult;
+ int16 nargs;
+
+ rel = heap_openr(ProcedureRelationName, RowExclusiveLock);
+
+ procOid = LookupFuncNameTypeNames(name, argtypes, "RenameFunction");
+
+ tup = SearchSysCacheCopy(PROCOID,
+ ObjectIdGetDatum(procOid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tup)) /* should not happen */
+ elog(ERROR, "RenameFunction: couldn't find pg_proc tuple for %s",
+ NameListToString(name));
+
+ if (((Form_pg_proc) GETSTRUCT(tup))->proisagg)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
+ errmsg("%s is an aggregate function", NameListToString(name)),
+ errhint("Use ALTER AGGREGATE to rename aggregate functions.")));
+
+ namespaceOid = ((Form_pg_proc) GETSTRUCT(tup))->pronamespace;
+
+ /* make sure the new name doesn't exist */
+ nargs = compute_parameter_types(argtypes, ((Form_pg_proc) GETSTRUCT(tup))->prolang, oid_array);
+ if (SearchSysCacheExists(PROCNAMENSP,
+ CStringGetDatum(newname),
+ Int16GetDatum(nargs),
+ PointerGetDatum(oid_array),
+ ObjectIdGetDatum(namespaceOid)))
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
+ errmsg("function %s with the same argument types already exists in schema %s",
+ newname, get_namespace_name(namespaceOid))));
+ }
+
+ /* must be owner */
+ if (!pg_proc_ownercheck(procOid, GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, NameListToString(name));
+
+ /* must have CREATE privilege on namespace */
+ aclresult = pg_namespace_aclcheck(namespaceOid, GetUserId(), ACL_CREATE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult, get_namespace_name(namespaceOid));
+
+ /* rename */
+ namestrcpy(&(((Form_pg_proc) GETSTRUCT(tup))->proname), newname);
+ 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
*
* This is presently only used for adjusting legacy functions that return
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 7838266005..c26d52d164 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -24,6 +24,7 @@
#include "catalog/namespace.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_proc.h"
+#include "commands/dbcommands.h"
#include "commands/defrem.h"
#include "commands/tablecmds.h"
#include "executor/executor.h"
@@ -644,10 +645,10 @@ ReindexDatabase(const char *dbname, bool force, bool all)
AssertArg(dbname);
- if (strcmp(dbname, DatabaseName) != 0)
+ if (strcmp(dbname, get_database_name(MyDatabaseId)) != 0)
elog(ERROR, "REINDEX DATABASE: Can be executed only on the currently open database.");
- if (!(superuser() || is_dbadmin(MyDatabaseId)))
+ if (!pg_database_ownercheck(MyDatabaseId, GetUserId()))
elog(ERROR, "REINDEX DATABASE: Permission denied.");
if (!allowSystemTableMods)
diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c
index c78dde0214..24202ee09e 100644
--- a/src/backend/commands/opclasscmds.c
+++ b/src/backend/commands/opclasscmds.c
@@ -550,7 +550,7 @@ RemoveOpClassById(Oid opclassOid)
ObjectIdGetDatum(opclassOid),
0, 0, 0);
if (!HeapTupleIsValid(tup)) /* should not happen */
- elog(ERROR, "RemoveOpClassById: couldn't find pg_class entry %u",
+ elog(ERROR, "RemoveOpClassById: couldn't find pg_opclass entry %u",
opclassOid);
simple_heap_delete(rel, &tup->t_self);
@@ -595,3 +595,94 @@ RemoveOpClassById(Oid opclassOid)
systable_endscan(scan);
heap_close(rel, RowExclusiveLock);
}
+
+
+/*
+ * Rename opclass
+ */
+void
+RenameOpClass(List *name, const char *access_method, const char *newname)
+{
+ Oid opcOid;
+ Oid amOid;
+ Oid namespaceOid;
+ char *schemaname;
+ char *opcname;
+ HeapTuple tup;
+ Relation rel;
+ AclResult aclresult;
+
+ amOid = GetSysCacheOid(AMNAME,
+ CStringGetDatum(access_method),
+ 0, 0, 0);
+ if (!OidIsValid(amOid))
+ elog(ERROR, "access method \"%s\" not found", 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))
+ elog(ERROR, "operator class \"%s\" for access method \"%s\" does not exist",
+ opcname, access_method);
+
+ opcOid = HeapTupleGetOid(tup);
+ }
+ else
+ {
+ opcOid = OpclassnameGetOpcid(amOid, opcname);
+ if (!OidIsValid(opcOid))
+ elog(ERROR, "operator class \"%s\" for access method \"%s\" does not exist",
+ opcname, access_method);
+
+ tup = SearchSysCacheCopy(CLAOID,
+ ObjectIdGetDatum(opcOid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tup)) /* should not happen */
+ elog(ERROR, "couldn't find pg_opclass tuple for %u", opcOid);
+
+ namespaceOid = ((Form_pg_opclass) GETSTRUCT(tup))->opcnamespace;
+ }
+
+ /* make sure the new name doesn't exist */
+ if (SearchSysCacheExists(CLAAMNAMENSP,
+ ObjectIdGetDatum(amOid),
+ CStringGetDatum(newname),
+ ObjectIdGetDatum(namespaceOid),
+ 0))
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
+ errmsg("operator class \"%s\" for access method \"%s\" already exists in schema \"%s\"",
+ newname, access_method, get_namespace_name(namespaceOid))));
+ }
+
+ /* must be owner */
+ if (!pg_opclass_ownercheck(opcOid, GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, NameListToString(name));
+
+ /* must have CREATE privilege on namespace */
+ aclresult = pg_namespace_aclcheck(namespaceOid, GetUserId(), ACL_CREATE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult, get_namespace_name(namespaceOid));
+
+ /* rename */
+ namestrcpy(&(((Form_pg_opclass) GETSTRUCT(tup))->opcname), newname);
+ simple_heap_update(rel, &tup->t_self, tup);
+ CatalogUpdateIndexes(rel, tup);
+
+ heap_close(rel, NoLock);
+ heap_freetuple(tup);
+}
diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c
index 47f7d79510..6d3c61d5f8 100644
--- a/src/backend/commands/proclang.c
+++ b/src/backend/commands/proclang.c
@@ -231,3 +231,47 @@ DropProceduralLanguageById(Oid langOid)
heap_close(rel, RowExclusiveLock);
}
+
+/*
+ * Rename language
+ */
+void
+RenameLanguage(const char *oldname, const char *newname)
+{
+ HeapTuple tup;
+ Relation rel;
+
+ rel = heap_openr(ShadowRelationName, RowExclusiveLock);
+
+ tup = SearchSysCacheCopy(LANGNAME,
+ CStringGetDatum(oldname),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tup))
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
+ errmsg("language \"%s\" does not exist", oldname)));
+
+ /* make sure the new name doesn't exist */
+ if (SearchSysCacheExists(LANGNAME,
+ CStringGetDatum(newname),
+ 0, 0, 0))
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
+ errmsg("language \"%s\" already exists", newname)));
+ }
+
+ /* must be superuser */
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
+ errmsg("permission denied")));
+
+ /* rename */
+ namestrcpy(&(((Form_pg_language) GETSTRUCT(tup))->lanname), newname);
+ 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 d5bcda29f8..6689ffa79a 100644
--- a/src/backend/commands/schemacmds.c
+++ b/src/backend/commands/schemacmds.c
@@ -18,8 +18,10 @@
#include "catalog/catalog.h"
#include "catalog/catname.h"
#include "catalog/dependency.h"
+#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/pg_namespace.h"
+#include "commands/dbcommands.h"
#include "commands/schemacmds.h"
#include "miscadmin.h"
#include "parser/analyze.h"
@@ -86,7 +88,7 @@ CreateSchemaCommand(CreateSchemaStmt *stmt)
*/
aclresult = pg_database_aclcheck(MyDatabaseId, saved_userid, ACL_CREATE);
if (aclresult != ACLCHECK_OK)
- aclcheck_error(aclresult, DatabaseName);
+ aclcheck_error(aclresult, get_database_name(MyDatabaseId));
if (!allowSystemTableMods && IsReservedName(schemaName))
elog(ERROR, "CREATE SCHEMA: Illegal schema name: \"%s\" -- pg_ is reserved for system schemas",
@@ -212,3 +214,57 @@ RemoveSchemaById(Oid schemaOid)
heap_close(relation, RowExclusiveLock);
}
+
+
+/*
+ * Rename schema
+ */
+void
+RenameSchema(const char *oldname, const char *newname)
+{
+ HeapTuple tup;
+ Relation rel;
+ AclResult aclresult;
+
+ rel = heap_openr(NamespaceRelationName, RowExclusiveLock);
+
+ tup = SearchSysCacheCopy(NAMESPACENAME,
+ CStringGetDatum(oldname),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tup))
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
+ errmsg("schema \"%s\" does not exist", oldname)));
+
+ /* make sure the new name doesn't exist */
+ if (HeapTupleIsValid(
+ SearchSysCache(NAMESPACENAME,
+ CStringGetDatum(newname),
+ 0, 0, 0)))
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
+ errmsg("schema \"%s\" already exists", newname)));
+ }
+
+ /* must be owner */
+ if (!pg_namespace_ownercheck(HeapTupleGetOid(tup), GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, oldname);
+
+ /* must have CREATE privilege on database */
+ aclresult = pg_database_aclcheck(MyDatabaseId, GetUserId(), ACL_CREATE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult, get_database_name(MyDatabaseId));
+
+ if (!allowSystemTableMods && IsReservedName(newname))
+ elog(ERROR, "illegal schema name: \"%s\" -- pg_ is reserved for system schemas",
+ newname);
+
+ /* rename */
+ namestrcpy(&(((Form_pg_namespace) GETSTRUCT(tup))->nspname), newname);
+ simple_heap_update(rel, &tup->t_self, tup);
+ CatalogUpdateIndexes(rel, tup);
+
+ heap_close(rel, NoLock);
+ heap_freetuple(tup);
+}
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index a35f1d0d46..9640f76c6f 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -1091,6 +1091,64 @@ DropUser(DropUserStmt *stmt)
}
+/*
+ * Rename user
+ */
+void
+RenameUser(const char *oldname, const char *newname)
+{
+ HeapTuple tup;
+ Relation rel;
+
+ /* ExclusiveLock because we need to update the password file */
+ rel = heap_openr(ShadowRelationName, ExclusiveLock);
+
+ tup = SearchSysCacheCopy(SHADOWNAME,
+ CStringGetDatum(oldname),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tup))
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
+ errmsg("user \"%s\" does not exist", oldname)));
+
+ /*
+ * XXX Client applications probably store the session user
+ * somewhere, so renaming it could cause confusion. On the other
+ * hand, there may not be an actual problem besides a little
+ * confusion, so think about this and decide.
+ */
+ if (((Form_pg_shadow) GETSTRUCT(tup))->usesysid == GetSessionUserId())
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
+ errmsg("session user may not be renamed")));
+
+ /* make sure the new name doesn't exist */
+ if (SearchSysCacheExists(SHADOWNAME,
+ CStringGetDatum(newname),
+ 0, 0, 0))
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
+ errmsg("user \"%s\" already exists", newname)));
+ }
+
+ /* must be superuser */
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
+ errmsg("permission denied")));
+
+ /* rename */
+ namestrcpy(&(((Form_pg_shadow) GETSTRUCT(tup))->usename), newname);
+ simple_heap_update(rel, &tup->t_self, tup);
+ CatalogUpdateIndexes(rel, tup);
+
+ heap_close(rel, NoLock);
+ heap_freetuple(tup);
+
+ user_file_update_needed = true;
+}
+
/*
* CheckPgUserAclNotNull
@@ -1566,3 +1624,51 @@ DropGroup(DropGroupStmt *stmt)
*/
group_file_update_needed = true;
}
+
+
+/*
+ * Rename group
+ */
+void
+RenameGroup(const char *oldname, const char *newname)
+{
+ HeapTuple tup;
+ Relation rel;
+
+ /* ExclusiveLock because we need to update the flat group file */
+ rel = heap_openr(GroupRelationName, ExclusiveLock);
+
+ tup = SearchSysCacheCopy(GRONAME,
+ CStringGetDatum(oldname),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tup))
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
+ errmsg("group \"%s\" does not exist", oldname)));
+
+ /* make sure the new name doesn't exist */
+ if (SearchSysCacheExists(GRONAME,
+ CStringGetDatum(newname),
+ 0, 0, 0))
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
+ errmsg("a group \"%s\" already exists", newname)));
+ }
+
+ /* must be superuser */
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
+ errmsg("permission denied")));
+
+ /* rename */
+ namestrcpy(&(((Form_pg_group) GETSTRUCT(tup))->groname), newname);
+ simple_heap_update(rel, &tup->t_self, tup);
+ CatalogUpdateIndexes(rel, tup);
+
+ heap_close(rel, NoLock);
+ heap_freetuple(tup);
+
+ group_file_update_needed = true;
+}
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index c29b5f6524..e0deeb7c9f 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -771,7 +771,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind)
onerel = relation_open(relid, lmode);
if (!(pg_class_ownercheck(RelationGetRelid(onerel), GetUserId()) ||
- (is_dbadmin(MyDatabaseId) && !onerel->rd_rel->relisshared)))
+ (pg_database_ownercheck(MyDatabaseId, GetUserId()) && !onerel->rd_rel->relisshared)))
{
elog(WARNING, "Skipping \"%s\" --- only table or database owner can VACUUM it",
RelationGetRelationName(onerel));
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 7720121c7e..ade3eacaba 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -1881,7 +1881,9 @@ _copyRenameStmt(RenameStmt *from)
RenameStmt *newnode = makeNode(RenameStmt);
COPY_NODE_FIELD(relation);
- COPY_STRING_FIELD(oldname);
+ COPY_NODE_FIELD(object);
+ COPY_NODE_FIELD(objarg);
+ COPY_STRING_FIELD(subname);
COPY_STRING_FIELD(newname);
COPY_SCALAR_FIELD(renameType);
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 732db9e102..ceda089861 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -909,7 +909,9 @@ static bool
_equalRenameStmt(RenameStmt *a, RenameStmt *b)
{
COMPARE_NODE_FIELD(relation);
- COMPARE_STRING_FIELD(oldname);
+ COMPARE_NODE_FIELD(object);
+ COMPARE_NODE_FIELD(objarg);
+ COMPARE_STRING_FIELD(subname);
COMPARE_STRING_FIELD(newname);
COMPARE_SCALAR_FIELD(renameType);
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 5c300752c1..39dad26de4 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -111,6 +111,7 @@ static void doNegateFloat(Value *v);
Node *node;
Value *value;
ColumnRef *columnref;
+ ObjectType objtype;
TypeName *typnam;
DefElem *defelt;
@@ -250,8 +251,8 @@ static void doNegateFloat(Value *v);
%type <boolean> copy_from opt_hold
-%type <ival> reindex_type drop_type fetch_count
- opt_column event comment_type cursor_options
+%type <ival> fetch_count opt_column event cursor_options
+%type <objtype> reindex_type drop_type comment_type
%type <node> fetch_direction select_limit_value select_offset_value
@@ -2227,7 +2228,7 @@ DropTrigStmt:
n->relation = $5;
n->property = $3;
n->behavior = $6;
- n->removeType = DROP_TRIGGER;
+ n->removeType = OBJECT_TRIGGER;
$$ = (Node *) n;
}
;
@@ -2265,7 +2266,7 @@ DropAssertStmt:
n->relation = NULL;
n->property = $3;
n->behavior = $4;
- n->removeType = DROP_TRIGGER; /* XXX */
+ n->removeType = OBJECT_TRIGGER; /* XXX */
elog(ERROR, "DROP ASSERTION is not yet supported");
$$ = (Node *) n;
}
@@ -2283,7 +2284,7 @@ DefineStmt:
CREATE AGGREGATE func_name definition
{
DefineStmt *n = makeNode(DefineStmt);
- n->kind = DEFINE_STMT_AGGREGATE;
+ n->kind = OBJECT_AGGREGATE;
n->defnames = $3;
n->definition = $4;
$$ = (Node *)n;
@@ -2291,7 +2292,7 @@ DefineStmt:
| CREATE OPERATOR any_operator definition
{
DefineStmt *n = makeNode(DefineStmt);
- n->kind = DEFINE_STMT_OPERATOR;
+ n->kind = OBJECT_OPERATOR;
n->defnames = $3;
n->definition = $4;
$$ = (Node *)n;
@@ -2299,7 +2300,7 @@ DefineStmt:
| CREATE TYPE_P any_name definition
{
DefineStmt *n = makeNode(DefineStmt);
- n->kind = DEFINE_STMT_TYPE;
+ n->kind = OBJECT_TYPE;
n->defnames = $3;
n->definition = $4;
$$ = (Node *)n;
@@ -2469,14 +2470,14 @@ DropStmt: DROP drop_type any_name_list opt_drop_behavior
}
;
-drop_type: TABLE { $$ = DROP_TABLE; }
- | SEQUENCE { $$ = DROP_SEQUENCE; }
- | VIEW { $$ = DROP_VIEW; }
- | INDEX { $$ = DROP_INDEX; }
- | TYPE_P { $$ = DROP_TYPE; }
- | DOMAIN_P { $$ = DROP_DOMAIN; }
- | CONVERSION_P { $$ = DROP_CONVERSION; }
- | SCHEMA { $$ = DROP_SCHEMA; }
+drop_type: TABLE { $$ = OBJECT_TABLE; }
+ | SEQUENCE { $$ = OBJECT_SEQUENCE; }
+ | VIEW { $$ = OBJECT_VIEW; }
+ | INDEX { $$ = OBJECT_INDEX; }
+ | TYPE_P { $$ = OBJECT_TYPE; }
+ | DOMAIN_P { $$ = OBJECT_DOMAIN; }
+ | CONVERSION_P { $$ = OBJECT_CONVERSION; }
+ | SCHEMA { $$ = OBJECT_SCHEMA; }
;
any_name_list:
@@ -2531,7 +2532,7 @@ CommentStmt:
IS comment_text
{
CommentStmt *n = makeNode(CommentStmt);
- n->objtype = COMMENT_ON_AGGREGATE;
+ n->objtype = OBJECT_AGGREGATE;
n->objname = $4;
n->objargs = makeList1($6);
n->comment = $9;
@@ -2540,7 +2541,7 @@ CommentStmt:
| COMMENT ON FUNCTION func_name func_args IS comment_text
{
CommentStmt *n = makeNode(CommentStmt);
- n->objtype = COMMENT_ON_FUNCTION;
+ n->objtype = OBJECT_FUNCTION;
n->objname = $4;
n->objargs = $5;
n->comment = $7;
@@ -2550,7 +2551,7 @@ CommentStmt:
IS comment_text
{
CommentStmt *n = makeNode(CommentStmt);
- n->objtype = COMMENT_ON_OPERATOR;
+ n->objtype = OBJECT_OPERATOR;
n->objname = $4;
n->objargs = $6;
n->comment = $9;
@@ -2559,7 +2560,7 @@ CommentStmt:
| COMMENT ON CONSTRAINT name ON any_name IS comment_text
{
CommentStmt *n = makeNode(CommentStmt);
- n->objtype = COMMENT_ON_CONSTRAINT;
+ n->objtype = OBJECT_CONSTRAINT;
n->objname = lappend($6, makeString($4));
n->objargs = NIL;
n->comment = $8;
@@ -2568,7 +2569,7 @@ CommentStmt:
| COMMENT ON RULE name ON any_name IS comment_text
{
CommentStmt *n = makeNode(CommentStmt);
- n->objtype = COMMENT_ON_RULE;
+ n->objtype = OBJECT_RULE;
n->objname = lappend($6, makeString($4));
n->objargs = NIL;
n->comment = $8;
@@ -2578,7 +2579,7 @@ CommentStmt:
{
/* Obsolete syntax supported for awhile for compatibility */
CommentStmt *n = makeNode(CommentStmt);
- n->objtype = COMMENT_ON_RULE;
+ n->objtype = OBJECT_RULE;
n->objname = makeList1(makeString($4));
n->objargs = NIL;
n->comment = $6;
@@ -2587,7 +2588,7 @@ CommentStmt:
| COMMENT ON TRIGGER name ON any_name IS comment_text
{
CommentStmt *n = makeNode(CommentStmt);
- n->objtype = COMMENT_ON_TRIGGER;
+ n->objtype = OBJECT_TRIGGER;
n->objname = lappend($6, makeString($4));
n->objargs = NIL;
n->comment = $8;
@@ -2596,15 +2597,15 @@ CommentStmt:
;
comment_type:
- COLUMN { $$ = COMMENT_ON_COLUMN; }
- | DATABASE { $$ = COMMENT_ON_DATABASE; }
- | SCHEMA { $$ = COMMENT_ON_SCHEMA; }
- | INDEX { $$ = COMMENT_ON_INDEX; }
- | SEQUENCE { $$ = COMMENT_ON_SEQUENCE; }
- | TABLE { $$ = COMMENT_ON_TABLE; }
- | DOMAIN_P { $$ = COMMENT_ON_TYPE; }
- | TYPE_P { $$ = COMMENT_ON_TYPE; }
- | VIEW { $$ = COMMENT_ON_VIEW; }
+ COLUMN { $$ = OBJECT_COLUMN; }
+ | DATABASE { $$ = OBJECT_DATABASE; }
+ | SCHEMA { $$ = OBJECT_SCHEMA; }
+ | INDEX { $$ = OBJECT_INDEX; }
+ | SEQUENCE { $$ = OBJECT_SEQUENCE; }
+ | TABLE { $$ = OBJECT_TABLE; }
+ | DOMAIN_P { $$ = OBJECT_TYPE; }
+ | TYPE_P { $$ = OBJECT_TYPE; }
+ | VIEW { $$ = OBJECT_VIEW; }
;
comment_text:
@@ -3317,7 +3318,7 @@ ReindexStmt:
| REINDEX DATABASE name opt_force
{
ReindexStmt *n = makeNode(ReindexStmt);
- n->kind = REINDEX_DATABASE;
+ n->kind = OBJECT_DATABASE;
n->name = $3;
n->relation = NULL;
n->force = $4;
@@ -3326,8 +3327,8 @@ ReindexStmt:
;
reindex_type:
- INDEX { $$ = REINDEX_INDEX; }
- | TABLE { $$ = REINDEX_TABLE; }
+ INDEX { $$ = OBJECT_INDEX; }
+ | TABLE { $$ = OBJECT_TABLE; }
;
opt_force: FORCE { $$ = TRUE; }
@@ -3337,31 +3338,104 @@ opt_force: FORCE { $$ = TRUE; }
/*****************************************************************************
*
- * QUERY:
- * rename <attrname1> in <relname> [*] to <attrname2>
- * rename <relname1> to <relname2>
+ * ALTER THING name RENAME TO newname
*
*****************************************************************************/
-RenameStmt: ALTER TABLE relation_expr RENAME opt_column opt_name TO name
+RenameStmt: ALTER AGGREGATE func_name '(' aggr_argtype ')' RENAME TO name
+ {
+ RenameStmt *n = makeNode(RenameStmt);
+ n->renameType = OBJECT_AGGREGATE;
+ n->object = $3;
+ n->objarg = makeList1($5);
+ n->newname = $9;
+ $$ = (Node *)n;
+ }
+ | ALTER CONVERSION_P any_name RENAME TO name
+ {
+ RenameStmt *n = makeNode(RenameStmt);
+ n->renameType = OBJECT_CONVERSION;
+ n->object = $3;
+ n->newname = $6;
+ $$ = (Node *)n;
+ }
+ | ALTER DATABASE database_name RENAME TO database_name
+ {
+ RenameStmt *n = makeNode(RenameStmt);
+ n->renameType = OBJECT_DATABASE;
+ n->subname = $3;
+ n->newname = $6;
+ $$ = (Node *)n;
+ }
+ | ALTER FUNCTION func_name func_args RENAME TO name
+ {
+ RenameStmt *n = makeNode(RenameStmt);
+ n->renameType = OBJECT_FUNCTION;
+ n->object = $3;
+ n->objarg = $4;
+ n->newname = $7;
+ $$ = (Node *)n;
+ }
+ | ALTER GROUP_P UserId RENAME TO UserId
+ {
+ RenameStmt *n = makeNode(RenameStmt);
+ n->renameType = OBJECT_GROUP;
+ n->subname = $3;
+ n->newname = $6;
+ $$ = (Node *)n;
+ }
+ | ALTER LANGUAGE name RENAME TO name
+ {
+ RenameStmt *n = makeNode(RenameStmt);
+ n->renameType = OBJECT_LANGUAGE;
+ n->subname = $3;
+ n->newname = $6;
+ $$ = (Node *)n;
+ }
+ | ALTER OPERATOR CLASS any_name USING access_method RENAME TO name
+ {
+ RenameStmt *n = makeNode(RenameStmt);
+ n->renameType = OBJECT_OPCLASS;
+ n->object = $4;
+ n->subname = $6;
+ n->newname = $9;
+ $$ = (Node *)n;
+ }
+ | ALTER SCHEMA name RENAME TO name
+ {
+ RenameStmt *n = makeNode(RenameStmt);
+ n->renameType = OBJECT_SCHEMA;
+ n->subname = $3;
+ n->newname = $6;
+ $$ = (Node *)n;
+ }
+ | ALTER TABLE relation_expr RENAME opt_column opt_name TO name
{
RenameStmt *n = makeNode(RenameStmt);
n->relation = $3;
- n->oldname = $6;
+ n->subname = $6;
n->newname = $8;
if ($6 == NULL)
- n->renameType = RENAME_TABLE;
+ n->renameType = OBJECT_TABLE;
else
- n->renameType = RENAME_COLUMN;
+ n->renameType = OBJECT_COLUMN;
$$ = (Node *)n;
}
| ALTER TRIGGER name ON relation_expr RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
n->relation = $5;
- n->oldname = $3;
+ n->subname = $3;
n->newname = $8;
- n->renameType = RENAME_TRIGGER;
+ n->renameType = OBJECT_TRIGGER;
+ $$ = (Node *)n;
+ }
+ | ALTER USER UserId RENAME TO UserId
+ {
+ RenameStmt *n = makeNode(RenameStmt);
+ n->renameType = OBJECT_USER;
+ n->subname = $3;
+ n->newname = $6;
$$ = (Node *)n;
}
;
@@ -3454,7 +3528,7 @@ DropRuleStmt:
n->relation = $5;
n->property = $3;
n->behavior = $6;
- n->removeType = DROP_RULE;
+ n->removeType = OBJECT_RULE;
$$ = (Node *) n;
}
;
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index 58398b0f13..1dc9a5103b 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -1077,7 +1077,7 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
/*
* We check the catalog name and then ignore it.
*/
- if (strcmp(name1, DatabaseName) != 0)
+ if (strcmp(name1, get_database_name(MyDatabaseId)) != 0)
elog(ERROR, "Cross-database references are not implemented");
/* Whole-row reference? */
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
index 16ee138801..cfa190e5a7 100644
--- a/src/backend/parser/parse_target.c
+++ b/src/backend/parser/parse_target.c
@@ -144,7 +144,7 @@ transformTargetList(ParseState *pstate, List *targetlist)
* We check the catalog name and then ignore
* it.
*/
- if (strcmp(name1, DatabaseName) != 0)
+ if (strcmp(name1, get_database_name(MyDatabaseId)) != 0)
elog(ERROR, "Cross-database references are not implemented");
schemaname = strVal(lsecond(fields));
relname = strVal(lthird(fields));
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index d62d1f5ee1..0794c8bc1d 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -20,6 +20,7 @@
#include "catalog/catalog.h"
#include "catalog/namespace.h"
#include "catalog/pg_shadow.h"
+#include "commands/alter.h"
#include "commands/async.h"
#include "commands/cluster.h"
#include "commands/comment.h"
@@ -362,56 +363,51 @@ ProcessUtility(Node *parsetree,
switch (stmt->removeType)
{
- case DROP_TABLE:
+ case OBJECT_TABLE:
rel = makeRangeVarFromNameList(names);
CheckDropPermissions(rel, RELKIND_RELATION);
RemoveRelation(rel, stmt->behavior);
break;
- case DROP_SEQUENCE:
+ case OBJECT_SEQUENCE:
rel = makeRangeVarFromNameList(names);
CheckDropPermissions(rel, RELKIND_SEQUENCE);
RemoveRelation(rel, stmt->behavior);
break;
- case DROP_VIEW:
+ case OBJECT_VIEW:
rel = makeRangeVarFromNameList(names);
CheckDropPermissions(rel, RELKIND_VIEW);
RemoveView(rel, stmt->behavior);
break;
- case DROP_INDEX:
+ case OBJECT_INDEX:
rel = makeRangeVarFromNameList(names);
CheckDropPermissions(rel, RELKIND_INDEX);
RemoveIndex(rel, stmt->behavior);
break;
- case DROP_TYPE:
+ case OBJECT_TYPE:
/* RemoveType does its own permissions checks */
RemoveType(names, stmt->behavior);
break;
- case DROP_DOMAIN:
-
- /*
- * RemoveDomain does its own permissions
- * checks
- */
+ case OBJECT_DOMAIN:
+ /* RemoveDomain does its own permissions checks */
RemoveDomain(names, stmt->behavior);
break;
- case DROP_CONVERSION:
+ case OBJECT_CONVERSION:
DropConversionCommand(names, stmt->behavior);
break;
- case DROP_SCHEMA:
-
- /*
- * RemoveSchema does its own permissions
- * checks
- */
+ case OBJECT_SCHEMA:
+ /* RemoveSchema does its own permissions checks */
RemoveSchema(names, stmt->behavior);
break;
+
+ default:
+ elog(ERROR, "invalid object type for DropStmt: %d", stmt->removeType);
}
/*
@@ -454,57 +450,7 @@ ProcessUtility(Node *parsetree,
* schema
*/
case T_RenameStmt:
- {
- RenameStmt *stmt = (RenameStmt *) parsetree;
- Oid relid;
-
- CheckOwnership(stmt->relation, true);
-
- relid = RangeVarGetRelid(stmt->relation, false);
-
- switch (stmt->renameType)
- {
- case RENAME_TABLE:
- {
- /*
- * RENAME TABLE requires that we (still) hold
- * CREATE rights on the containing namespace,
- * as well as ownership of the table.
- */
- Oid namespaceId = get_rel_namespace(relid);
- AclResult aclresult;
-
- aclresult = pg_namespace_aclcheck(namespaceId,
- GetUserId(),
- ACL_CREATE);
- if (aclresult != ACLCHECK_OK)
- aclcheck_error(aclresult,
- get_namespace_name(namespaceId));
-
- renamerel(relid, stmt->newname);
- break;
- }
- case RENAME_COLUMN:
- renameatt(relid,
- stmt->oldname, /* old att name */
- stmt->newname, /* new att name */
- interpretInhOption(stmt->relation->inhOpt), /* recursive? */
- false); /* recursing already? */
- break;
- case RENAME_TRIGGER:
- renametrig(relid,
- stmt->oldname, /* old att name */
- stmt->newname); /* new att name */
- break;
- case RENAME_RULE:
- elog(ERROR, "ProcessUtility: Invalid type for RENAME: %d",
- stmt->renameType);
- break;
- default:
- elog(ERROR, "ProcessUtility: Invalid type for RENAME: %d",
- stmt->renameType);
- }
- }
+ ExecRenameStmt((RenameStmt *) parsetree);
break;
/* various Alter Table forms */
@@ -694,15 +640,17 @@ ProcessUtility(Node *parsetree,
switch (stmt->kind)
{
- case DEFINE_STMT_AGGREGATE:
+ case OBJECT_AGGREGATE:
DefineAggregate(stmt->defnames, stmt->definition);
break;
- case DEFINE_STMT_OPERATOR:
+ case OBJECT_OPERATOR:
DefineOperator(stmt->defnames, stmt->definition);
break;
- case DEFINE_STMT_TYPE:
+ case OBJECT_TYPE:
DefineType(stmt->defnames, stmt->definition);
break;
+ default:
+ elog(ERROR, "invalid object type for DefineStmt: %d", stmt->kind);
}
}
break;
@@ -906,16 +854,18 @@ ProcessUtility(Node *parsetree,
switch (stmt->removeType)
{
- case DROP_RULE:
+ case OBJECT_RULE:
/* RemoveRewriteRule checks permissions */
RemoveRewriteRule(relId, stmt->property,
stmt->behavior);
break;
- case DROP_TRIGGER:
+ case OBJECT_TRIGGER:
/* DropTrigger checks permissions */
DropTrigger(relId, stmt->property,
stmt->behavior);
break;
+ default:
+ elog(ERROR, "invalid object type for DropPropertyStmt: %d", stmt->removeType);
}
}
break;
@@ -986,17 +936,19 @@ ProcessUtility(Node *parsetree,
switch (stmt->kind)
{
- case REINDEX_INDEX:
+ case OBJECT_INDEX:
CheckOwnership(stmt->relation, false);
ReindexIndex(stmt->relation, stmt->force);
break;
- case REINDEX_TABLE:
+ case OBJECT_TABLE:
CheckOwnership(stmt->relation, false);
ReindexTable(stmt->relation, stmt->force);
break;
- case REINDEX_DATABASE:
+ case OBJECT_DATABASE:
ReindexDatabase(stmt->name, stmt->force, false);
break;
+ default:
+ elog(ERROR, "invalid object type for ReindexStmt: %d", stmt->kind);
}
break;
}
@@ -1238,28 +1190,28 @@ CreateCommandTag(Node *parsetree)
case T_DropStmt:
switch (((DropStmt *) parsetree)->removeType)
{
- case DROP_TABLE:
+ case OBJECT_TABLE:
tag = "DROP TABLE";
break;
- case DROP_SEQUENCE:
+ case OBJECT_SEQUENCE:
tag = "DROP SEQUENCE";
break;
- case DROP_VIEW:
+ case OBJECT_VIEW:
tag = "DROP VIEW";
break;
- case DROP_INDEX:
+ case OBJECT_INDEX:
tag = "DROP INDEX";
break;
- case DROP_TYPE:
+ case OBJECT_TYPE:
tag = "DROP TYPE";
break;
- case DROP_DOMAIN:
+ case OBJECT_DOMAIN:
tag = "DROP DOMAIN";
break;
- case DROP_CONVERSION:
+ case OBJECT_CONVERSION:
tag = "DROP CONVERSION";
break;
- case DROP_SCHEMA:
+ case OBJECT_SCHEMA:
tag = "DROP SCHEMA";
break;
default:
@@ -1280,10 +1232,41 @@ CreateCommandTag(Node *parsetree)
break;
case T_RenameStmt:
- if (((RenameStmt *) parsetree)->renameType == RENAME_TRIGGER)
- tag = "ALTER TRIGGER";
- else
- tag = "ALTER TABLE";
+ switch (((RenameStmt *) parsetree)->renameType)
+ {
+ case OBJECT_AGGREGATE:
+ tag = "ALTER AGGREGATE";
+ break;
+ case OBJECT_CONVERSION:
+ tag = "ALTER CONVERSION";
+ break;
+ case OBJECT_DATABASE:
+ tag = "ALTER DATABASE";
+ break;
+ case OBJECT_FUNCTION:
+ tag = "ALTER FUNCTION";
+ break;
+ case OBJECT_GROUP:
+ tag = "ALTER GROUP";
+ break;
+ case OBJECT_LANGUAGE:
+ tag = "ALTER LANGUAGE";
+ break;
+ case OBJECT_OPCLASS:
+ tag = "ALTER OPERATOR CLASS";
+ break;
+ case OBJECT_SCHEMA:
+ tag = "ALTER SCHEMA";
+ break;
+ case OBJECT_TRIGGER:
+ tag = "ALTER TRIGGER";
+ break;
+ case OBJECT_USER:
+ tag = "ALTER USER";
+ break;
+ default:
+ tag = "ALTER TABLE";
+ }
break;
case T_AlterTableStmt:
@@ -1305,13 +1288,13 @@ CreateCommandTag(Node *parsetree)
case T_DefineStmt:
switch (((DefineStmt *) parsetree)->kind)
{
- case DEFINE_STMT_AGGREGATE:
+ case OBJECT_AGGREGATE:
tag = "CREATE AGGREGATE";
break;
- case DEFINE_STMT_OPERATOR:
+ case OBJECT_OPERATOR:
tag = "CREATE OPERATOR";
break;
- case DEFINE_STMT_TYPE:
+ case OBJECT_TYPE:
tag = "CREATE TYPE";
break;
default:
@@ -1421,10 +1404,10 @@ CreateCommandTag(Node *parsetree)
case T_DropPropertyStmt:
switch (((DropPropertyStmt *) parsetree)->removeType)
{
- case DROP_TRIGGER:
+ case OBJECT_TRIGGER:
tag = "DROP TRIGGER";
break;
- case DROP_RULE:
+ case OBJECT_RULE:
tag = "DROP RULE";
break;
default:
diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c
index e557f7562f..3f9d216731 100644
--- a/src/backend/utils/adt/misc.c
+++ b/src/backend/utils/adt/misc.c
@@ -54,7 +54,6 @@ current_database(PG_FUNCTION_ARGS)
db = (Name) palloc(NAMEDATALEN);
- namestrcpy(db, DatabaseName);
-
+ namestrcpy(db, get_database_name(MyDatabaseId));
PG_RETURN_NAME(db);
}
diff --git a/src/backend/utils/init/globals.c b/src/backend/utils/init/globals.c
index 14e9528cdf..ff804092c8 100644
--- a/src/backend/utils/init/globals.c
+++ b/src/backend/utils/init/globals.c
@@ -52,9 +52,7 @@ char pg_pathname[MAXPGPATH]; /* full path to postgres
BackendId MyBackendId;
-char *DatabaseName = NULL;
char *DatabasePath = NULL;
-
Oid MyDatabaseId = InvalidOid;
/* these are initialized for the bootstrap/standalone case: */
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index 3845a468a0..2837a07751 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -105,22 +105,6 @@ SetDatabasePath(const char *path)
}
}
-void
-SetDatabaseName(const char *name)
-{
- if (DatabaseName)
- {
- free(DatabaseName);
- DatabaseName = NULL;
- }
- /* use strdup since this is done before memory contexts are set up */
- if (name)
- {
- DatabaseName = strdup(name);
- AssertState(DatabaseName);
- }
-}
-
/*
* Set data directory, but make sure it's an absolute path. Use this,
* never set DataDir directly.
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index cd4049c02d..c5316ca838 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -228,13 +228,11 @@ InitPostgres(const char *dbname, const char *username)
bool bootstrap = IsBootstrapProcessingMode();
/*
- * Set up the global variables holding database name, id, and path.
+ * Set up the global variables holding database id and path.
*
* We take a shortcut in the bootstrap case, otherwise we have to look up
* the db name in pg_database.
*/
- SetDatabaseName(dbname);
-
if (bootstrap)
{
MyDatabaseId = TemplateDbOid;
diff --git a/src/backend/utils/misc/superuser.c b/src/backend/utils/misc/superuser.c
index 9eba92d3f4..9f70bcf34c 100644
--- a/src/backend/utils/misc/superuser.c
+++ b/src/backend/utils/misc/superuser.c
@@ -58,18 +58,3 @@ superuser_arg(AclId userid)
}
return result;
}
-
-
-/*
- * The Postgres user running this command is the owner of the specified
- * database.
- */
-bool
-is_dbadmin(Oid dbid)
-{
- AclId dba;
-
- dba = get_database_owner(dbid);
-
- return (GetUserId() == dba);
-}
diff --git a/src/include/commands/alter.h b/src/include/commands/alter.h
new file mode 100644
index 0000000000..3c9dcf192b
--- /dev/null
+++ b/src/include/commands/alter.h
@@ -0,0 +1,21 @@
+/*-------------------------------------------------------------------------
+ *
+ * alter.h
+ * prototypes for alter.h
+ *
+ *
+ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id$
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef ALTER_H
+#define ALTER_H
+
+#include "nodes/parsenodes.h"
+
+extern void ExecRenameStmt(RenameStmt *stmt);
+
+#endif /* ALTER_H */
diff --git a/src/include/commands/conversioncmds.h b/src/include/commands/conversioncmds.h
index f7f64d158b..e8081b6c10 100644
--- a/src/include/commands/conversioncmds.h
+++ b/src/include/commands/conversioncmds.h
@@ -19,5 +19,6 @@
extern void CreateConversionCommand(CreateConversionStmt *parsetree);
extern void DropConversionCommand(List *conversion_name, DropBehavior behavior);
+extern void RenameConversion(List *name, const char *newname);
#endif /* CONVERSIONCMDS_H */
diff --git a/src/include/commands/dbcommands.h b/src/include/commands/dbcommands.h
index eb6978176c..8987d78446 100644
--- a/src/include/commands/dbcommands.h
+++ b/src/include/commands/dbcommands.h
@@ -18,9 +18,10 @@
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 Oid get_database_oid(const char *dbname);
-extern Oid get_database_owner(Oid dbid);
+extern Oid get_database_oid(const char *dbname);
+extern char * get_database_name(Oid dbid);
#endif /* DBCOMMANDS_H */
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index 4ba1c5d297..232a6ada65 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -38,6 +38,7 @@ extern void RemoveFunction(RemoveFuncStmt *stmt);
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 CreateCast(CreateCastStmt *stmt);
extern void DropCast(DropCastStmt *stmt);
extern void DropCastById(Oid castOid);
@@ -50,12 +51,13 @@ extern void RemoveOperatorById(Oid operOid);
/* 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);
/* 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);
/* support routines in commands/define.c */
diff --git a/src/include/commands/proclang.h b/src/include/commands/proclang.h
index f4fde9b108..a446773cd4 100644
--- a/src/include/commands/proclang.h
+++ b/src/include/commands/proclang.h
@@ -14,5 +14,6 @@
extern void CreateProceduralLanguage(CreatePLangStmt *stmt);
extern void DropProceduralLanguage(DropPLangStmt *stmt);
extern void DropProceduralLanguageById(Oid langOid);
+extern void RenameLanguage(const char *oldname, const char *newname);
#endif /* PROCLANG_H */
diff --git a/src/include/commands/schemacmds.h b/src/include/commands/schemacmds.h
index da20cd41e0..f28ec8fa34 100644
--- a/src/include/commands/schemacmds.h
+++ b/src/include/commands/schemacmds.h
@@ -22,4 +22,6 @@ extern void CreateSchemaCommand(CreateSchemaStmt *parsetree);
extern void RemoveSchema(List *names, DropBehavior behavior);
extern void RemoveSchemaById(Oid schemaOid);
+extern void RenameSchema(const char *oldname, const char *newname);
+
#endif /* SCHEMACMDS_H */
diff --git a/src/include/commands/user.h b/src/include/commands/user.h
index 5114d0c561..dab3895d32 100644
--- a/src/include/commands/user.h
+++ b/src/include/commands/user.h
@@ -22,10 +22,12 @@ extern void CreateUser(CreateUserStmt *stmt);
extern void AlterUser(AlterUserStmt *stmt);
extern void AlterUserSet(AlterUserSetStmt *stmt);
extern void DropUser(DropUserStmt *stmt);
+extern void RenameUser(const char *oldname, const char *newname);
extern void CreateGroup(CreateGroupStmt *stmt);
extern void AlterGroup(AlterGroupStmt *stmt, const char *tag);
extern void DropGroup(DropGroupStmt *stmt);
+extern void RenameGroup(const char *oldname, const char *newname);
extern Datum update_pg_pwd_and_pg_group(PG_FUNCTION_ARGS);
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
index 26510f096f..226d8ded49 100644
--- a/src/include/miscadmin.h
+++ b/src/include/miscadmin.h
@@ -192,7 +192,6 @@ extern char *VirtualHost;
* POSTGRES directory path definitions. *
*****************************************************************************/
-extern char *DatabaseName;
extern char *DatabasePath;
/* in utils/misc/database.c */
@@ -200,7 +199,6 @@ extern void GetRawDatabaseInfo(const char *name, Oid *db_id, char *path);
extern char *ExpandDatabasePath(const char *path);
/* now in utils/init/miscinit.c */
-extern void SetDatabaseName(const char *name);
extern void SetDatabasePath(const char *path);
extern char *GetUserNameFromId(AclId userid);
@@ -226,8 +224,6 @@ extern char *convertstr(unsigned char *buff, int len, int dest);
/* in utils/misc/superuser.c */
extern bool superuser(void); /* current user is superuser */
extern bool superuser_arg(AclId userid); /* given user is superuser */
-extern bool is_dbadmin(Oid dbid); /* current user is owner of
- * database */
/*****************************************************************************
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 9270b5339f..7b50246ab1 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -668,6 +668,36 @@ typedef struct SetOperationStmt
* field in Query.
*****************************************************************************/
+/*
+ * When a command can act on several kinds of objects with only one
+ * parse structure required, use these constants to designate the
+ * object type.
+ */
+
+typedef enum ObjectType {
+ OBJECT_AGGREGATE,
+ OBJECT_CAST,
+ OBJECT_COLUMN,
+ OBJECT_CONSTRAINT,
+ OBJECT_CONVERSION,
+ OBJECT_DATABASE,
+ OBJECT_DOMAIN,
+ OBJECT_FUNCTION,
+ OBJECT_GROUP,
+ OBJECT_INDEX,
+ OBJECT_LANGUAGE,
+ OBJECT_OPCLASS,
+ OBJECT_OPERATOR,
+ OBJECT_RULE,
+ OBJECT_SCHEMA,
+ OBJECT_SEQUENCE,
+ OBJECT_TABLE,
+ OBJECT_TRIGGER,
+ OBJECT_TYPE,
+ OBJECT_USER,
+ OBJECT_VIEW
+} ObjectType;
+
/* ----------------------
* Create Schema Statement
*
@@ -1076,17 +1106,10 @@ typedef struct AlterSeqStmt
* Create {Aggregate|Operator|Type} Statement
* ----------------------
*/
-typedef enum DefineStmtKind
-{
- DEFINE_STMT_AGGREGATE,
- DEFINE_STMT_OPERATOR,
- DEFINE_STMT_TYPE
-} DefineStmtKind;
-
typedef struct DefineStmt
{
NodeTag type;
- DefineStmtKind kind; /* see above */
+ ObjectType kind; /* aggregate, operator, type */
List *defnames; /* qualified name (list of Value strings) */
List *definition; /* a list of DefElem */
} DefineStmt;
@@ -1139,20 +1162,11 @@ typedef struct CreateOpClassItem
* ----------------------
*/
-#define DROP_TABLE 1
-#define DROP_SEQUENCE 2
-#define DROP_VIEW 3
-#define DROP_INDEX 4
-#define DROP_TYPE 5
-#define DROP_DOMAIN 6
-#define DROP_CONVERSION 7
-#define DROP_SCHEMA 8
-
typedef struct DropStmt
{
NodeTag type;
List *objects; /* list of sublists of names (as Values) */
- int removeType; /* see #defines above */
+ ObjectType removeType; /* object type */
DropBehavior behavior; /* RESTRICT or CASCADE behavior */
} DropStmt;
@@ -1164,15 +1178,12 @@ typedef struct DropStmt
* ----------------------
*/
-#define DROP_RULE 100
-#define DROP_TRIGGER 101
-
typedef struct DropPropertyStmt
{
NodeTag type;
RangeVar *relation; /* owning relation */
char *property; /* name of rule, trigger, etc */
- int removeType; /* see #defines above */
+ ObjectType removeType; /* OBJECT_RULE or OBJECT_TRIGGER */
DropBehavior behavior; /* RESTRICT or CASCADE behavior */
} DropPropertyStmt;
@@ -1190,25 +1201,10 @@ typedef struct TruncateStmt
* Comment On Statement
* ----------------------
*/
-#define COMMENT_ON_AGGREGATE 100
-#define COMMENT_ON_COLUMN 101
-#define COMMENT_ON_CONSTRAINT 102
-#define COMMENT_ON_DATABASE 103
-#define COMMENT_ON_FUNCTION 104
-#define COMMENT_ON_INDEX 105
-#define COMMENT_ON_OPERATOR 106
-#define COMMENT_ON_RULE 107
-#define COMMENT_ON_SCHEMA 108
-#define COMMENT_ON_SEQUENCE 109
-#define COMMENT_ON_TABLE 110
-#define COMMENT_ON_TRIGGER 111
-#define COMMENT_ON_TYPE 112
-#define COMMENT_ON_VIEW 113
-
typedef struct CommentStmt
{
NodeTag type;
- int objtype; /* Object's type, see codes above */
+ ObjectType objtype; /* Object's type */
List *objname; /* Qualified name of the object */
List *objargs; /* Arguments if needed (eg, for functions) */
char *comment; /* Comment to insert, or NULL to remove */
@@ -1352,21 +1348,16 @@ typedef struct RemoveOpClassStmt
/* ----------------------
* Alter Object Rename Statement
* ----------------------
- * Currently supports renaming tables, table columns, and triggers.
- * If renaming a table, oldname is ignored.
*/
-#define RENAME_TABLE 110
-#define RENAME_COLUMN 111
-#define RENAME_TRIGGER 112
-#define RENAME_RULE 113
-
typedef struct RenameStmt
{
NodeTag type;
- RangeVar *relation; /* owning relation */
- char *oldname; /* name of rule, trigger, etc */
+ RangeVar *relation; /* in case it's a table */
+ List *object; /* in case it's some other object */
+ List *objarg; /* argument types, if applicable */
+ char *subname; /* name of contained object (column, rule, trigger, etc) */
char *newname; /* the new name */
- int renameType; /* RENAME_TABLE, RENAME_COLUMN, etc */
+ ObjectType renameType; /* OBJECT_TABLE, OBJECT_COLUMN, etc */
} RenameStmt;
/* ----------------------
@@ -1614,17 +1605,10 @@ typedef struct ConstraintsSetStmt
* REINDEX Statement
* ----------------------
*/
-typedef enum ReindexStmtKind
-{
- REINDEX_INDEX,
- REINDEX_TABLE,
- REINDEX_DATABASE
-} ReindexStmtKind;
-
typedef struct ReindexStmt
{
NodeTag type;
- ReindexStmtKind kind; /* see above */
+ ObjectType kind; /* OBJECT_INDEX, OBJECT_TABLE, OBJECT_DATABASE */
RangeVar *relation; /* Table or index to reindex */
const char *name; /* name of database to reindex */
bool force;
diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h
index e2947f892d..1e50afc9a5 100644
--- a/src/include/utils/acl.h
+++ b/src/include/utils/acl.h
@@ -216,5 +216,6 @@ extern bool pg_oper_ownercheck(Oid oper_oid, AclId userid);
extern bool pg_proc_ownercheck(Oid proc_oid, AclId userid);
extern bool pg_namespace_ownercheck(Oid nsp_oid, AclId userid);
extern bool pg_opclass_ownercheck(Oid opc_oid, AclId userid);
+extern bool pg_database_ownercheck(Oid db_oid, AclId userid);
#endif /* ACL_H */