mirror of
https://github.com/postgres/postgres.git
synced 2025-04-22 23:02:54 +03:00
Add ALTER TYPE ... ADD/DROP/ALTER/RENAME ATTRIBUTE
Like with tables, this also requires allowing the existence of composite types with zero attributes. reviewed by KaiGai Kohei
This commit is contained in:
parent
899beb7894
commit
e440e12c56
@ -23,9 +23,17 @@ PostgreSQL documentation
|
|||||||
|
|
||||||
<refsynopsisdiv>
|
<refsynopsisdiv>
|
||||||
<synopsis>
|
<synopsis>
|
||||||
ALTER TYPE <replaceable class="PARAMETER">name</replaceable> RENAME TO <replaceable class="PARAMETER">new_name</replaceable>
|
ALTER TYPE <replaceable class="PARAMETER">name</replaceable> <replaceable class="PARAMETER">action</replaceable> [, ... ]
|
||||||
ALTER TYPE <replaceable class="PARAMETER">name</replaceable> OWNER TO <replaceable class="PARAMETER">new_owner</replaceable>
|
ALTER TYPE <replaceable class="PARAMETER">name</replaceable> OWNER TO <replaceable class="PARAMETER">new_owner</replaceable>
|
||||||
|
ALTER TYPE <replaceable class="PARAMETER">name</replaceable> RENAME ATTRIBUTE <replaceable class="PARAMETER">attribute_name</replaceable> TO <replaceable class="PARAMETER">new_attribute_name</replaceable>
|
||||||
|
ALTER TYPE <replaceable class="PARAMETER">name</replaceable> RENAME TO <replaceable class="PARAMETER">new_name</replaceable>
|
||||||
ALTER TYPE <replaceable class="PARAMETER">name</replaceable> SET SCHEMA <replaceable class="PARAMETER">new_schema</replaceable>
|
ALTER TYPE <replaceable class="PARAMETER">name</replaceable> SET SCHEMA <replaceable class="PARAMETER">new_schema</replaceable>
|
||||||
|
|
||||||
|
<phrase>where <replaceable class="PARAMETER">action</replaceable> is one of:</phrase>
|
||||||
|
|
||||||
|
ADD ATTRIBUTE <replaceable class="PARAMETER">attribute_name</replaceable> <replaceable class="PARAMETER">data_type</replaceable>
|
||||||
|
DROP ATTRIBUTE [ IF EXISTS ] <replaceable class="PARAMETER">attribute_name</replaceable>
|
||||||
|
ALTER ATTRIBUTE <replaceable class="PARAMETER">attribute_name</replaceable> [ SET DATA ] TYPE <replaceable class="PARAMETER">data_type</replaceable>
|
||||||
</synopsis>
|
</synopsis>
|
||||||
</refsynopsisdiv>
|
</refsynopsisdiv>
|
||||||
|
|
||||||
@ -34,6 +42,76 @@ ALTER TYPE <replaceable class="PARAMETER">name</replaceable> SET SCHEMA <replace
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
<command>ALTER TYPE</command> changes the definition of an existing type.
|
<command>ALTER TYPE</command> changes the definition of an existing type.
|
||||||
|
There are several subforms:
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><literal>ADD ATTRIBUTE</literal></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
This form adds a new attribute to a composite type, using the same syntax as
|
||||||
|
<xref linkend="SQL-CREATETYPE">.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><literal>DROP ATTRIBUTE [ IF EXISTS ]</literal></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
This form drops an attribute from a composite type.
|
||||||
|
If <literal>IF EXISTS</literal> is specified and the attribute
|
||||||
|
does not exist, no error is thrown. In this case a notice
|
||||||
|
is issued instead.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><literal>SET DATA TYPE</literal></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
This form changes the type of an attribute of a composite type.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><literal>OWNER</literal></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
This form changes the owner of the type.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><literal>RENAME</literal></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
This form changes the name of the type or the name of an
|
||||||
|
individual attribute of a composite type.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><literal>SET SCHEMA</literal></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
This form moves the type into another schema.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The <literal>ADD ATTRIBUTE</literal>, <literal>DROP
|
||||||
|
ATTRIBUTE</literal>, and <literal>ALTER ATTRIBUTE</literal> actions
|
||||||
|
can be combined into a list of multiple alterations to apply in
|
||||||
|
parallel. For example, it is possible to add several attributes
|
||||||
|
and/or alter the type of several attributes in a single command.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@ -90,6 +168,34 @@ ALTER TYPE <replaceable class="PARAMETER">name</replaceable> SET SCHEMA <replace
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><replaceable class="PARAMETER">attribute_name</replaceable></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The name of the attribute to add, alter, or drop.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><replaceable class="PARAMETER">new_attribute_name</replaceable></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The new name of the attribute begin renamed.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><replaceable class="PARAMETER">data_type</replaceable></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The data type of the attribute to add, or the new type of the
|
||||||
|
attribute to alter.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
@ -117,6 +223,13 @@ ALTER TYPE email OWNER TO joe;
|
|||||||
to <literal>customers</literal>:
|
to <literal>customers</literal>:
|
||||||
<programlisting>
|
<programlisting>
|
||||||
ALTER TYPE email SET SCHEMA customers;
|
ALTER TYPE email SET SCHEMA customers;
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
To add a new attribute to a type:
|
||||||
|
<programlisting>
|
||||||
|
ALTER TYPE compfoo ADD ATTRIBUTE f3 int;
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
@ -125,8 +238,17 @@ ALTER TYPE email SET SCHEMA customers;
|
|||||||
<title>Compatibility</title>
|
<title>Compatibility</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
There is no <command>ALTER TYPE</command> statement in the SQL
|
The variants to add and drop attributes are part of the SQL
|
||||||
standard.
|
standard; the other variants are PostgreSQL extensions.
|
||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1 id="SQL-ALTERTYPE-see-also">
|
||||||
|
<title>See Also</title>
|
||||||
|
|
||||||
|
<simplelist type="inline">
|
||||||
|
<member><xref linkend="sql-createtype"></member>
|
||||||
|
<member><xref linkend="sql-droptype"></member>
|
||||||
|
</simplelist>
|
||||||
|
</refsect1>
|
||||||
</refentry>
|
</refentry>
|
||||||
|
@ -22,7 +22,7 @@ PostgreSQL documentation
|
|||||||
<refsynopsisdiv>
|
<refsynopsisdiv>
|
||||||
<synopsis>
|
<synopsis>
|
||||||
CREATE TYPE <replaceable class="parameter">name</replaceable> AS
|
CREATE TYPE <replaceable class="parameter">name</replaceable> AS
|
||||||
( <replaceable class="PARAMETER">attribute_name</replaceable> <replaceable class="PARAMETER">data_type</replaceable> [, ... ] )
|
( [ <replaceable class="PARAMETER">attribute_name</replaceable> <replaceable class="PARAMETER">data_type</replaceable> [, ... ] ] )
|
||||||
|
|
||||||
CREATE TYPE <replaceable class="parameter">name</replaceable> AS ENUM
|
CREATE TYPE <replaceable class="parameter">name</replaceable> AS ENUM
|
||||||
( [ '<replaceable class="parameter">label</replaceable>' [, ... ] ] )
|
( [ '<replaceable class="parameter">label</replaceable>' [, ... ] ] )
|
||||||
@ -768,10 +768,18 @@ CREATE TABLE big_objs (
|
|||||||
<title>Compatibility</title>
|
<title>Compatibility</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
This <command>CREATE TYPE</command> command is a
|
The first form of the <command>CREATE TYPE</command> command, which
|
||||||
<productname>PostgreSQL</productname> extension. There is a
|
creates a composite type, conforms to the <acronym>SQL</> standard.
|
||||||
<command>CREATE TYPE</command> statement in the <acronym>SQL</> standard
|
The other forms are <productname>PostgreSQL</productname>
|
||||||
that is rather different in detail.
|
extensions. The <command>CREATE TYPE</command> statement in
|
||||||
|
the <acronym>SQL</> standard also defines other forms that are not
|
||||||
|
implemented in <productname>PostgreSQL</>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The ability to create a composite type with zero attributes is
|
||||||
|
a <productname>PostgreSQL</productname>-specific deviation from the
|
||||||
|
standard (analogous to <command>CREATE TABLE</command>).
|
||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
@ -779,10 +787,10 @@ CREATE TABLE big_objs (
|
|||||||
<title>See Also</title>
|
<title>See Also</title>
|
||||||
|
|
||||||
<simplelist type="inline">
|
<simplelist type="inline">
|
||||||
<member><xref linkend="sql-createfunction"></member>
|
|
||||||
<member><xref linkend="sql-droptype"></member>
|
|
||||||
<member><xref linkend="sql-altertype"></member>
|
<member><xref linkend="sql-altertype"></member>
|
||||||
<member><xref linkend="sql-createdomain"></member>
|
<member><xref linkend="sql-createdomain"></member>
|
||||||
|
<member><xref linkend="sql-createfunction"></member>
|
||||||
|
<member><xref linkend="sql-droptype"></member>
|
||||||
</simplelist>
|
</simplelist>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ DROP TYPE box;
|
|||||||
This command is similar to the corresponding command in the SQL
|
This command is similar to the corresponding command in the SQL
|
||||||
standard, apart from the <literal>IF EXISTS</>
|
standard, apart from the <literal>IF EXISTS</>
|
||||||
option, which is a <productname>PostgreSQL</> extension.
|
option, which is a <productname>PostgreSQL</> extension.
|
||||||
But note that the <command>CREATE TYPE</command> command
|
But note that much of the <command>CREATE TYPE</command> command
|
||||||
and the data type extension mechanisms in
|
and the data type extension mechanisms in
|
||||||
<productname>PostgreSQL</productname> differ from the SQL standard.
|
<productname>PostgreSQL</productname> differ from the SQL standard.
|
||||||
</para>
|
</para>
|
||||||
@ -107,8 +107,8 @@ DROP TYPE box;
|
|||||||
<title>See Also</title>
|
<title>See Also</title>
|
||||||
|
|
||||||
<simplelist type="inline">
|
<simplelist type="inline">
|
||||||
<member><xref linkend="sql-createtype"></member>
|
|
||||||
<member><xref linkend="sql-altertype"></member>
|
<member><xref linkend="sql-altertype"></member>
|
||||||
|
<member><xref linkend="sql-createtype"></member>
|
||||||
</simplelist>
|
</simplelist>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
@ -89,6 +89,7 @@ ExecRenameStmt(RenameStmt *stmt)
|
|||||||
case OBJECT_VIEW:
|
case OBJECT_VIEW:
|
||||||
case OBJECT_INDEX:
|
case OBJECT_INDEX:
|
||||||
case OBJECT_COLUMN:
|
case OBJECT_COLUMN:
|
||||||
|
case OBJECT_ATTRIBUTE:
|
||||||
case OBJECT_TRIGGER:
|
case OBJECT_TRIGGER:
|
||||||
{
|
{
|
||||||
Oid relid;
|
Oid relid;
|
||||||
@ -123,6 +124,7 @@ ExecRenameStmt(RenameStmt *stmt)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OBJECT_COLUMN:
|
case OBJECT_COLUMN:
|
||||||
|
case OBJECT_ATTRIBUTE:
|
||||||
renameatt(relid,
|
renameatt(relid,
|
||||||
stmt->subname, /* old att name */
|
stmt->subname, /* old att name */
|
||||||
stmt->newname, /* new att name */
|
stmt->newname, /* new att name */
|
||||||
|
@ -263,12 +263,13 @@ static void ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
|
|||||||
static void ATRewriteTables(List **wqueue, LOCKMODE lockmode);
|
static void ATRewriteTables(List **wqueue, LOCKMODE lockmode);
|
||||||
static void ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode);
|
static void ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode);
|
||||||
static AlteredTableInfo *ATGetQueueEntry(List **wqueue, Relation rel);
|
static AlteredTableInfo *ATGetQueueEntry(List **wqueue, Relation rel);
|
||||||
static void ATSimplePermissions(Relation rel, bool allowView);
|
static void ATSimplePermissions(Relation rel, bool allowView, bool allowType);
|
||||||
static void ATSimplePermissionsRelationOrIndex(Relation rel);
|
static void ATSimplePermissionsRelationOrIndex(Relation rel);
|
||||||
static void ATSimpleRecursion(List **wqueue, Relation rel,
|
static void ATSimpleRecursion(List **wqueue, Relation rel,
|
||||||
AlterTableCmd *cmd, bool recurse, LOCKMODE lockmode);
|
AlterTableCmd *cmd, bool recurse, LOCKMODE lockmode);
|
||||||
static void ATOneLevelRecursion(List **wqueue, Relation rel,
|
static void ATOneLevelRecursion(List **wqueue, Relation rel,
|
||||||
AlterTableCmd *cmd, LOCKMODE lockmode);
|
AlterTableCmd *cmd, LOCKMODE lockmode);
|
||||||
|
static void find_typed_table_dependencies(Oid typeOid, const char *typeName);
|
||||||
static void ATPrepAddColumn(List **wqueue, Relation rel, bool recurse,
|
static void ATPrepAddColumn(List **wqueue, Relation rel, bool recurse,
|
||||||
AlterTableCmd *cmd, LOCKMODE lockmode);
|
AlterTableCmd *cmd, LOCKMODE lockmode);
|
||||||
static void ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
|
static void ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
|
||||||
@ -1978,6 +1979,10 @@ renameatt(Oid myrelid,
|
|||||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||||
errmsg("cannot rename column of typed table")));
|
errmsg("cannot rename column of typed table")));
|
||||||
|
|
||||||
|
if (targetrelation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
|
||||||
|
find_typed_table_dependencies(targetrelation->rd_rel->reltype,
|
||||||
|
RelationGetRelationName(targetrelation));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Renaming the columns of sequences or toast tables doesn't actually
|
* Renaming the columns of sequences or toast tables doesn't actually
|
||||||
* break anything from the system's point of view, since internal
|
* break anything from the system's point of view, since internal
|
||||||
@ -2368,8 +2373,13 @@ AlterTable(AlterTableStmt *stmt)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* For mostly-historical reasons, we allow ALTER TABLE to apply to
|
* For mostly-historical reasons, we allow ALTER TABLE to apply to
|
||||||
* all relation types.
|
* almost all relation types.
|
||||||
*/
|
*/
|
||||||
|
if (rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||||
|
errmsg("\"%s\" is not a table",
|
||||||
|
RelationGetRelationName(rel))));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OBJECT_INDEX:
|
case OBJECT_INDEX:
|
||||||
@ -2388,6 +2398,14 @@ AlterTable(AlterTableStmt *stmt)
|
|||||||
RelationGetRelationName(rel))));
|
RelationGetRelationName(rel))));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case OBJECT_TYPE:
|
||||||
|
if (rel->rd_rel->relkind != RELKIND_COMPOSITE_TYPE)
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||||
|
errmsg("\"%s\" is not a composite type",
|
||||||
|
RelationGetRelationName(rel))));
|
||||||
|
break;
|
||||||
|
|
||||||
case OBJECT_VIEW:
|
case OBJECT_VIEW:
|
||||||
if (rel->rd_rel->relkind != RELKIND_VIEW)
|
if (rel->rd_rel->relkind != RELKIND_VIEW)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
@ -2639,14 +2657,14 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
|
|||||||
switch (cmd->subtype)
|
switch (cmd->subtype)
|
||||||
{
|
{
|
||||||
case AT_AddColumn: /* ADD COLUMN */
|
case AT_AddColumn: /* ADD COLUMN */
|
||||||
ATSimplePermissions(rel, false);
|
ATSimplePermissions(rel, false, true);
|
||||||
/* Performs own recursion */
|
/* Performs own recursion */
|
||||||
ATPrepAddColumn(wqueue, rel, recurse, cmd, lockmode);
|
ATPrepAddColumn(wqueue, rel, recurse, cmd, lockmode);
|
||||||
pass = AT_PASS_ADD_COL;
|
pass = AT_PASS_ADD_COL;
|
||||||
break;
|
break;
|
||||||
case AT_AddColumnToView: /* add column via CREATE OR REPLACE
|
case AT_AddColumnToView: /* add column via CREATE OR REPLACE
|
||||||
* VIEW */
|
* VIEW */
|
||||||
ATSimplePermissions(rel, true);
|
ATSimplePermissions(rel, true, false);
|
||||||
/* Performs own recursion */
|
/* Performs own recursion */
|
||||||
ATPrepAddColumn(wqueue, rel, recurse, cmd, lockmode);
|
ATPrepAddColumn(wqueue, rel, recurse, cmd, lockmode);
|
||||||
pass = AT_PASS_ADD_COL;
|
pass = AT_PASS_ADD_COL;
|
||||||
@ -2659,19 +2677,19 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
|
|||||||
* substitutes default values into INSERTs before it expands
|
* substitutes default values into INSERTs before it expands
|
||||||
* rules.
|
* rules.
|
||||||
*/
|
*/
|
||||||
ATSimplePermissions(rel, true);
|
ATSimplePermissions(rel, true, false);
|
||||||
ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode);
|
ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode);
|
||||||
/* No command-specific prep needed */
|
/* No command-specific prep needed */
|
||||||
pass = cmd->def ? AT_PASS_ADD_CONSTR : AT_PASS_DROP;
|
pass = cmd->def ? AT_PASS_ADD_CONSTR : AT_PASS_DROP;
|
||||||
break;
|
break;
|
||||||
case AT_DropNotNull: /* ALTER COLUMN DROP NOT NULL */
|
case AT_DropNotNull: /* ALTER COLUMN DROP NOT NULL */
|
||||||
ATSimplePermissions(rel, false);
|
ATSimplePermissions(rel, false, false);
|
||||||
ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode);
|
ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode);
|
||||||
/* No command-specific prep needed */
|
/* No command-specific prep needed */
|
||||||
pass = AT_PASS_DROP;
|
pass = AT_PASS_DROP;
|
||||||
break;
|
break;
|
||||||
case AT_SetNotNull: /* ALTER COLUMN SET NOT NULL */
|
case AT_SetNotNull: /* ALTER COLUMN SET NOT NULL */
|
||||||
ATSimplePermissions(rel, false);
|
ATSimplePermissions(rel, false, false);
|
||||||
ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode);
|
ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode);
|
||||||
/* No command-specific prep needed */
|
/* No command-specific prep needed */
|
||||||
pass = AT_PASS_ADD_CONSTR;
|
pass = AT_PASS_ADD_CONSTR;
|
||||||
@ -2689,25 +2707,25 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
|
|||||||
pass = AT_PASS_MISC;
|
pass = AT_PASS_MISC;
|
||||||
break;
|
break;
|
||||||
case AT_SetStorage: /* ALTER COLUMN SET STORAGE */
|
case AT_SetStorage: /* ALTER COLUMN SET STORAGE */
|
||||||
ATSimplePermissions(rel, false);
|
ATSimplePermissions(rel, false, false);
|
||||||
ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode);
|
ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode);
|
||||||
/* No command-specific prep needed */
|
/* No command-specific prep needed */
|
||||||
pass = AT_PASS_MISC;
|
pass = AT_PASS_MISC;
|
||||||
break;
|
break;
|
||||||
case AT_DropColumn: /* DROP COLUMN */
|
case AT_DropColumn: /* DROP COLUMN */
|
||||||
ATSimplePermissions(rel, false);
|
ATSimplePermissions(rel, false, true);
|
||||||
ATPrepDropColumn(rel, recurse, cmd);
|
ATPrepDropColumn(rel, recurse, cmd);
|
||||||
/* Recursion occurs during execution phase */
|
/* Recursion occurs during execution phase */
|
||||||
pass = AT_PASS_DROP;
|
pass = AT_PASS_DROP;
|
||||||
break;
|
break;
|
||||||
case AT_AddIndex: /* ADD INDEX */
|
case AT_AddIndex: /* ADD INDEX */
|
||||||
ATSimplePermissions(rel, false);
|
ATSimplePermissions(rel, false, false);
|
||||||
/* This command never recurses */
|
/* This command never recurses */
|
||||||
/* No command-specific prep needed */
|
/* No command-specific prep needed */
|
||||||
pass = AT_PASS_ADD_INDEX;
|
pass = AT_PASS_ADD_INDEX;
|
||||||
break;
|
break;
|
||||||
case AT_AddConstraint: /* ADD CONSTRAINT */
|
case AT_AddConstraint: /* ADD CONSTRAINT */
|
||||||
ATSimplePermissions(rel, false);
|
ATSimplePermissions(rel, false, false);
|
||||||
/* Recursion occurs during execution phase */
|
/* Recursion occurs during execution phase */
|
||||||
/* No command-specific prep needed except saving recurse flag */
|
/* No command-specific prep needed except saving recurse flag */
|
||||||
if (recurse)
|
if (recurse)
|
||||||
@ -2715,7 +2733,7 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
|
|||||||
pass = AT_PASS_ADD_CONSTR;
|
pass = AT_PASS_ADD_CONSTR;
|
||||||
break;
|
break;
|
||||||
case AT_DropConstraint: /* DROP CONSTRAINT */
|
case AT_DropConstraint: /* DROP CONSTRAINT */
|
||||||
ATSimplePermissions(rel, false);
|
ATSimplePermissions(rel, false, false);
|
||||||
/* Recursion occurs during execution phase */
|
/* Recursion occurs during execution phase */
|
||||||
/* No command-specific prep needed except saving recurse flag */
|
/* No command-specific prep needed except saving recurse flag */
|
||||||
if (recurse)
|
if (recurse)
|
||||||
@ -2723,7 +2741,7 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
|
|||||||
pass = AT_PASS_DROP;
|
pass = AT_PASS_DROP;
|
||||||
break;
|
break;
|
||||||
case AT_AlterColumnType: /* ALTER COLUMN TYPE */
|
case AT_AlterColumnType: /* ALTER COLUMN TYPE */
|
||||||
ATSimplePermissions(rel, false);
|
ATSimplePermissions(rel, false, true);
|
||||||
/* Performs own recursion */
|
/* Performs own recursion */
|
||||||
ATPrepAlterColumnType(wqueue, tab, rel, recurse, recursing, cmd, lockmode);
|
ATPrepAlterColumnType(wqueue, tab, rel, recurse, recursing, cmd, lockmode);
|
||||||
pass = AT_PASS_ALTER_TYPE;
|
pass = AT_PASS_ALTER_TYPE;
|
||||||
@ -2735,20 +2753,20 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
|
|||||||
break;
|
break;
|
||||||
case AT_ClusterOn: /* CLUSTER ON */
|
case AT_ClusterOn: /* CLUSTER ON */
|
||||||
case AT_DropCluster: /* SET WITHOUT CLUSTER */
|
case AT_DropCluster: /* SET WITHOUT CLUSTER */
|
||||||
ATSimplePermissions(rel, false);
|
ATSimplePermissions(rel, false, false);
|
||||||
/* These commands never recurse */
|
/* These commands never recurse */
|
||||||
/* No command-specific prep needed */
|
/* No command-specific prep needed */
|
||||||
pass = AT_PASS_MISC;
|
pass = AT_PASS_MISC;
|
||||||
break;
|
break;
|
||||||
case AT_AddOids: /* SET WITH OIDS */
|
case AT_AddOids: /* SET WITH OIDS */
|
||||||
ATSimplePermissions(rel, false);
|
ATSimplePermissions(rel, false, false);
|
||||||
/* Performs own recursion */
|
/* Performs own recursion */
|
||||||
if (!rel->rd_rel->relhasoids || recursing)
|
if (!rel->rd_rel->relhasoids || recursing)
|
||||||
ATPrepAddOids(wqueue, rel, recurse, cmd, lockmode);
|
ATPrepAddOids(wqueue, rel, recurse, cmd, lockmode);
|
||||||
pass = AT_PASS_ADD_COL;
|
pass = AT_PASS_ADD_COL;
|
||||||
break;
|
break;
|
||||||
case AT_DropOids: /* SET WITHOUT OIDS */
|
case AT_DropOids: /* SET WITHOUT OIDS */
|
||||||
ATSimplePermissions(rel, false);
|
ATSimplePermissions(rel, false, false);
|
||||||
/* Performs own recursion */
|
/* Performs own recursion */
|
||||||
if (rel->rd_rel->relhasoids)
|
if (rel->rd_rel->relhasoids)
|
||||||
{
|
{
|
||||||
@ -2775,7 +2793,7 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
|
|||||||
pass = AT_PASS_MISC;
|
pass = AT_PASS_MISC;
|
||||||
break;
|
break;
|
||||||
case AT_AddInherit: /* INHERIT */
|
case AT_AddInherit: /* INHERIT */
|
||||||
ATSimplePermissions(rel, false);
|
ATSimplePermissions(rel, false, false);
|
||||||
/* This command never recurses */
|
/* This command never recurses */
|
||||||
ATPrepAddInherit(rel);
|
ATPrepAddInherit(rel);
|
||||||
pass = AT_PASS_MISC;
|
pass = AT_PASS_MISC;
|
||||||
@ -2793,7 +2811,7 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
|
|||||||
case AT_EnableReplicaRule:
|
case AT_EnableReplicaRule:
|
||||||
case AT_DisableRule:
|
case AT_DisableRule:
|
||||||
case AT_DropInherit: /* NO INHERIT */
|
case AT_DropInherit: /* NO INHERIT */
|
||||||
ATSimplePermissions(rel, false);
|
ATSimplePermissions(rel, false, false);
|
||||||
/* These commands never recurse */
|
/* These commands never recurse */
|
||||||
/* No command-specific prep needed */
|
/* No command-specific prep needed */
|
||||||
pass = AT_PASS_MISC;
|
pass = AT_PASS_MISC;
|
||||||
@ -3519,7 +3537,7 @@ ATGetQueueEntry(List **wqueue, Relation rel)
|
|||||||
* - Ensure that it is not a system table
|
* - Ensure that it is not a system table
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
ATSimplePermissions(Relation rel, bool allowView)
|
ATSimplePermissions(Relation rel, bool allowView, bool allowType)
|
||||||
{
|
{
|
||||||
if (rel->rd_rel->relkind != RELKIND_RELATION)
|
if (rel->rd_rel->relkind != RELKIND_RELATION)
|
||||||
{
|
{
|
||||||
@ -3531,6 +3549,14 @@ ATSimplePermissions(Relation rel, bool allowView)
|
|||||||
errmsg("\"%s\" is not a table or view",
|
errmsg("\"%s\" is not a table or view",
|
||||||
RelationGetRelationName(rel))));
|
RelationGetRelationName(rel))));
|
||||||
}
|
}
|
||||||
|
else if (allowType)
|
||||||
|
{
|
||||||
|
if (rel->rd_rel->relkind != RELKIND_COMPOSITE_TYPE)
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||||
|
errmsg("\"%s\" is not a table or composite type",
|
||||||
|
RelationGetRelationName(rel))));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||||
@ -3758,6 +3784,44 @@ find_composite_type_dependencies(Oid typeOid,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* find_typed_table_dependencies
|
||||||
|
*
|
||||||
|
* Check to see if a composite type is being used as the type of a
|
||||||
|
* typed table. Eventually, we'd like to propagate the alter
|
||||||
|
* operation into such tables, but for now, just error out if we find
|
||||||
|
* any.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
find_typed_table_dependencies(Oid typeOid, const char *typeName)
|
||||||
|
{
|
||||||
|
Relation classRel;
|
||||||
|
ScanKeyData key[1];
|
||||||
|
HeapScanDesc scan;
|
||||||
|
HeapTuple tuple;
|
||||||
|
|
||||||
|
classRel = heap_open(RelationRelationId, AccessShareLock);
|
||||||
|
|
||||||
|
ScanKeyInit(&key[0],
|
||||||
|
Anum_pg_class_reloftype,
|
||||||
|
BTEqualStrategyNumber, F_OIDEQ,
|
||||||
|
ObjectIdGetDatum(typeOid));
|
||||||
|
|
||||||
|
scan = heap_beginscan(classRel, SnapshotNow, 1, key);
|
||||||
|
|
||||||
|
if (HeapTupleIsValid(tuple = heap_getnext(scan, ForwardScanDirection)))
|
||||||
|
{
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
|
errmsg("cannot alter type \"%s\" because it is the type of a typed table",
|
||||||
|
typeName)));
|
||||||
|
}
|
||||||
|
|
||||||
|
heap_endscan(scan);
|
||||||
|
heap_close(classRel, AccessShareLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ALTER TABLE ADD COLUMN
|
* ALTER TABLE ADD COLUMN
|
||||||
*
|
*
|
||||||
@ -3804,6 +3868,10 @@ ATPrepAddColumn(List **wqueue, Relation rel, bool recurse,
|
|||||||
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
|
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
|
||||||
errmsg("column must be added to child tables too")));
|
errmsg("column must be added to child tables too")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
|
||||||
|
find_typed_table_dependencies(rel->rd_rel->reltype,
|
||||||
|
RelationGetRelationName(rel));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -4007,7 +4075,7 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
|
|||||||
* defaults, not even for domain-typed columns. And in any case we
|
* defaults, not even for domain-typed columns. And in any case we
|
||||||
* mustn't invoke Phase 3 on a view, since it has no storage.
|
* mustn't invoke Phase 3 on a view, since it has no storage.
|
||||||
*/
|
*/
|
||||||
if (relkind != RELKIND_VIEW && attribute.attnum > 0)
|
if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE && attribute.attnum > 0)
|
||||||
{
|
{
|
||||||
defval = (Expr *) build_column_default(rel, attribute.attnum);
|
defval = (Expr *) build_column_default(rel, attribute.attnum);
|
||||||
|
|
||||||
@ -4535,6 +4603,10 @@ ATPrepDropColumn(Relation rel, bool recurse, AlterTableCmd *cmd)
|
|||||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||||
errmsg("cannot drop column from typed table")));
|
errmsg("cannot drop column from typed table")));
|
||||||
|
|
||||||
|
if (rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
|
||||||
|
find_typed_table_dependencies(rel->rd_rel->reltype,
|
||||||
|
RelationGetRelationName(rel));
|
||||||
|
|
||||||
/* No command-specific prep needed except saving recurse flag */
|
/* No command-specific prep needed except saving recurse flag */
|
||||||
if (recurse)
|
if (recurse)
|
||||||
cmd->subtype = AT_DropColumnRecurse;
|
cmd->subtype = AT_DropColumnRecurse;
|
||||||
@ -4554,7 +4626,7 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
|
|||||||
|
|
||||||
/* At top level, permission check was done in ATPrepCmd, else do it */
|
/* At top level, permission check was done in ATPrepCmd, else do it */
|
||||||
if (recursing)
|
if (recursing)
|
||||||
ATSimplePermissions(rel, false);
|
ATSimplePermissions(rel, false, true);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get the number of the attribute
|
* get the number of the attribute
|
||||||
@ -4858,7 +4930,7 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
|
|||||||
|
|
||||||
/* At top level, permission check was done in ATPrepCmd, else do it */
|
/* At top level, permission check was done in ATPrepCmd, else do it */
|
||||||
if (recursing)
|
if (recursing)
|
||||||
ATSimplePermissions(rel, false);
|
ATSimplePermissions(rel, false, false);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Call AddRelationNewConstraints to do the work, making sure it works on
|
* Call AddRelationNewConstraints to do the work, making sure it works on
|
||||||
@ -5801,7 +5873,7 @@ ATExecDropConstraint(Relation rel, const char *constrName,
|
|||||||
|
|
||||||
/* At top level, permission check was done in ATPrepCmd, else do it */
|
/* At top level, permission check was done in ATPrepCmd, else do it */
|
||||||
if (recursing)
|
if (recursing)
|
||||||
ATSimplePermissions(rel, false);
|
ATSimplePermissions(rel, false, false);
|
||||||
|
|
||||||
conrel = heap_open(ConstraintRelationId, RowExclusiveLock);
|
conrel = heap_open(ConstraintRelationId, RowExclusiveLock);
|
||||||
|
|
||||||
@ -6033,6 +6105,8 @@ ATPrepAlterColumnType(List **wqueue,
|
|||||||
/* make sure datatype is legal for a column */
|
/* make sure datatype is legal for a column */
|
||||||
CheckAttributeType(colName, targettype, false);
|
CheckAttributeType(colName, targettype, false);
|
||||||
|
|
||||||
|
if (tab->relkind == RELKIND_RELATION)
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* Set up an expression to transform the old data value to the new type.
|
* Set up an expression to transform the old data value to the new type.
|
||||||
* If a USING option was given, transform and use that expression, else
|
* If a USING option was given, transform and use that expression, else
|
||||||
@ -6103,6 +6177,21 @@ ATPrepAlterColumnType(List **wqueue,
|
|||||||
newval->expr = (Expr *) transform;
|
newval->expr = (Expr *) transform;
|
||||||
|
|
||||||
tab->newvals = lappend(tab->newvals, newval);
|
tab->newvals = lappend(tab->newvals, newval);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tab->relkind == RELKIND_COMPOSITE_TYPE)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* For composite types, do this check now. Tables will check
|
||||||
|
* it later when the table is being rewritten.
|
||||||
|
*/
|
||||||
|
find_composite_type_dependencies(rel->rd_rel->reltype,
|
||||||
|
NULL,
|
||||||
|
RelationGetRelationName(rel));
|
||||||
|
|
||||||
|
find_typed_table_dependencies(rel->rd_rel->reltype,
|
||||||
|
RelationGetRelationName(rel));
|
||||||
|
}
|
||||||
|
|
||||||
ReleaseSysCache(tuple);
|
ReleaseSysCache(tuple);
|
||||||
|
|
||||||
@ -7367,7 +7456,7 @@ ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode)
|
|||||||
* Must be owner of both parent and child -- child was checked by
|
* Must be owner of both parent and child -- child was checked by
|
||||||
* ATSimplePermissions call in ATPrepCmd
|
* ATSimplePermissions call in ATPrepCmd
|
||||||
*/
|
*/
|
||||||
ATSimplePermissions(parent_rel, false);
|
ATSimplePermissions(parent_rel, false, false);
|
||||||
|
|
||||||
/* Permanent rels cannot inherit from temporary ones */
|
/* Permanent rels cannot inherit from temporary ones */
|
||||||
if (parent_rel->rd_istemp && !child_rel->rd_istemp)
|
if (parent_rel->rd_istemp && !child_rel->rd_istemp)
|
||||||
|
@ -1508,11 +1508,6 @@ DefineCompositeType(const RangeVar *typevar, List *coldeflist)
|
|||||||
Oid typeNamespace;
|
Oid typeNamespace;
|
||||||
Oid relid;
|
Oid relid;
|
||||||
|
|
||||||
if (coldeflist == NIL)
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
|
||||||
errmsg("composite type must have at least one attribute")));
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* now set the parameters for keys/inheritance etc. All of these are
|
* now set the parameters for keys/inheritance etc. All of these are
|
||||||
* uninteresting for composite types...
|
* uninteresting for composite types...
|
||||||
|
@ -131,6 +131,7 @@ static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args,
|
|||||||
List *args, int location);
|
List *args, int location);
|
||||||
static List *mergeTableFuncParameters(List *func_args, List *columns);
|
static List *mergeTableFuncParameters(List *func_args, List *columns);
|
||||||
static TypeName *TableFuncTypeName(List *columns);
|
static TypeName *TableFuncTypeName(List *columns);
|
||||||
|
static RangeVar *makeRangeVarFromAnyName(List *names, int position, core_yyscan_t yyscanner);
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
@ -184,7 +185,7 @@ static TypeName *TableFuncTypeName(List *columns);
|
|||||||
AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterFdwStmt
|
AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterFdwStmt
|
||||||
AlterForeignServerStmt AlterGroupStmt
|
AlterForeignServerStmt AlterGroupStmt
|
||||||
AlterObjectSchemaStmt AlterOwnerStmt AlterSeqStmt AlterTableStmt
|
AlterObjectSchemaStmt AlterOwnerStmt AlterSeqStmt AlterTableStmt
|
||||||
AlterUserStmt AlterUserMappingStmt AlterUserSetStmt
|
AlterCompositeTypeStmt AlterUserStmt AlterUserMappingStmt AlterUserSetStmt
|
||||||
AlterRoleStmt AlterRoleSetStmt
|
AlterRoleStmt AlterRoleSetStmt
|
||||||
AlterDefaultPrivilegesStmt DefACLAction
|
AlterDefaultPrivilegesStmt DefACLAction
|
||||||
AnalyzeStmt ClosePortalStmt ClusterStmt CommentStmt
|
AnalyzeStmt ClosePortalStmt ClusterStmt CommentStmt
|
||||||
@ -218,8 +219,8 @@ static TypeName *TableFuncTypeName(List *columns);
|
|||||||
%type <node> alter_column_default opclass_item opclass_drop alter_using
|
%type <node> alter_column_default opclass_item opclass_drop alter_using
|
||||||
%type <ival> add_drop opt_asc_desc opt_nulls_order
|
%type <ival> add_drop opt_asc_desc opt_nulls_order
|
||||||
|
|
||||||
%type <node> alter_table_cmd
|
%type <node> alter_table_cmd alter_type_cmd
|
||||||
%type <list> alter_table_cmds
|
%type <list> alter_table_cmds alter_type_cmds
|
||||||
|
|
||||||
%type <dbehavior> opt_drop_behavior
|
%type <dbehavior> opt_drop_behavior
|
||||||
|
|
||||||
@ -295,7 +296,7 @@ static TypeName *TableFuncTypeName(List *columns);
|
|||||||
reloption_list group_clause TriggerFuncArgs select_limit
|
reloption_list group_clause TriggerFuncArgs select_limit
|
||||||
opt_select_limit opclass_item_list opclass_drop_list
|
opt_select_limit opclass_item_list opclass_drop_list
|
||||||
opt_opfamily transaction_mode_list_or_empty
|
opt_opfamily transaction_mode_list_or_empty
|
||||||
TableFuncElementList opt_type_modifiers
|
OptTableFuncElementList TableFuncElementList opt_type_modifiers
|
||||||
prep_type_clause
|
prep_type_clause
|
||||||
execute_param_clause using_clause returning_clause
|
execute_param_clause using_clause returning_clause
|
||||||
opt_enum_val_list enum_val_list table_func_column_list
|
opt_enum_val_list enum_val_list table_func_column_list
|
||||||
@ -462,7 +463,7 @@ static TypeName *TableFuncTypeName(List *columns);
|
|||||||
/* ordinary key words in alphabetical order */
|
/* ordinary key words in alphabetical order */
|
||||||
%token <keyword> ABORT_P ABSOLUTE_P ACCESS ACTION ADD_P ADMIN AFTER
|
%token <keyword> ABORT_P ABSOLUTE_P ACCESS ACTION ADD_P ADMIN AFTER
|
||||||
AGGREGATE ALL ALSO ALTER ALWAYS ANALYSE ANALYZE AND ANY ARRAY AS ASC
|
AGGREGATE ALL ALSO ALTER ALWAYS ANALYSE ANALYZE AND ANY ARRAY AS ASC
|
||||||
ASSERTION ASSIGNMENT ASYMMETRIC AT AUTHORIZATION
|
ASSERTION ASSIGNMENT ASYMMETRIC AT ATTRIBUTE AUTHORIZATION
|
||||||
|
|
||||||
BACKWARD BEFORE BEGIN_P BETWEEN BIGINT BINARY BIT
|
BACKWARD BEFORE BEGIN_P BETWEEN BIGINT BINARY BIT
|
||||||
BOOLEAN_P BOTH BY
|
BOOLEAN_P BOTH BY
|
||||||
@ -657,6 +658,7 @@ stmt :
|
|||||||
| AlterOwnerStmt
|
| AlterOwnerStmt
|
||||||
| AlterSeqStmt
|
| AlterSeqStmt
|
||||||
| AlterTableStmt
|
| AlterTableStmt
|
||||||
|
| AlterCompositeTypeStmt
|
||||||
| AlterRoleSetStmt
|
| AlterRoleSetStmt
|
||||||
| AlterRoleStmt
|
| AlterRoleStmt
|
||||||
| AlterTSConfigurationStmt
|
| AlterTSConfigurationStmt
|
||||||
@ -1968,6 +1970,72 @@ reloption_elem:
|
|||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* ALTER TYPE
|
||||||
|
*
|
||||||
|
* really variants of the ALTER TABLE subcommands with different spellings
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
AlterCompositeTypeStmt:
|
||||||
|
ALTER TYPE_P any_name alter_type_cmds
|
||||||
|
{
|
||||||
|
AlterTableStmt *n = makeNode(AlterTableStmt);
|
||||||
|
|
||||||
|
/* can't use qualified_name, sigh */
|
||||||
|
n->relation = makeRangeVarFromAnyName($3, @3, yyscanner);
|
||||||
|
n->cmds = $4;
|
||||||
|
n->relkind = OBJECT_TYPE;
|
||||||
|
$$ = (Node *)n;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
alter_type_cmds:
|
||||||
|
alter_type_cmd { $$ = list_make1($1); }
|
||||||
|
| alter_type_cmds ',' alter_type_cmd { $$ = lappend($1, $3); }
|
||||||
|
;
|
||||||
|
|
||||||
|
alter_type_cmd:
|
||||||
|
/* ALTER TYPE <name> ADD ATTRIBUTE <coldef> */
|
||||||
|
ADD_P ATTRIBUTE TableFuncElement
|
||||||
|
{
|
||||||
|
AlterTableCmd *n = makeNode(AlterTableCmd);
|
||||||
|
n->subtype = AT_AddColumn;
|
||||||
|
n->def = $3;
|
||||||
|
$$ = (Node *)n;
|
||||||
|
}
|
||||||
|
/* ALTER TYPE <name> DROP ATTRIBUTE IF EXISTS <attname> */
|
||||||
|
| DROP ATTRIBUTE IF_P EXISTS ColId
|
||||||
|
{
|
||||||
|
AlterTableCmd *n = makeNode(AlterTableCmd);
|
||||||
|
n->subtype = AT_DropColumn;
|
||||||
|
n->name = $5;
|
||||||
|
n->behavior = DROP_RESTRICT; /* currently no effect */
|
||||||
|
n->missing_ok = TRUE;
|
||||||
|
$$ = (Node *)n;
|
||||||
|
}
|
||||||
|
/* ALTER TYPE <name> DROP ATTRIBUTE <attname> */
|
||||||
|
| DROP ATTRIBUTE ColId opt_drop_behavior
|
||||||
|
{
|
||||||
|
AlterTableCmd *n = makeNode(AlterTableCmd);
|
||||||
|
n->subtype = AT_DropColumn;
|
||||||
|
n->name = $3;
|
||||||
|
n->behavior = DROP_RESTRICT; /* currently no effect */
|
||||||
|
n->missing_ok = FALSE;
|
||||||
|
$$ = (Node *)n;
|
||||||
|
}
|
||||||
|
/* ALTER TYPE <name> ALTER ATTRIBUTE <attname> [SET DATA] TYPE <typename> */
|
||||||
|
| ALTER ATTRIBUTE ColId opt_set_data TYPE_P Typename
|
||||||
|
{
|
||||||
|
AlterTableCmd *n = makeNode(AlterTableCmd);
|
||||||
|
n->subtype = AT_AlterColumnType;
|
||||||
|
n->name = $3;
|
||||||
|
n->def = (Node *) $6;
|
||||||
|
$$ = (Node *)n;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
*
|
*
|
||||||
* QUERY :
|
* QUERY :
|
||||||
@ -3678,39 +3746,12 @@ DefineStmt:
|
|||||||
n->definition = NIL;
|
n->definition = NIL;
|
||||||
$$ = (Node *)n;
|
$$ = (Node *)n;
|
||||||
}
|
}
|
||||||
| CREATE TYPE_P any_name AS '(' TableFuncElementList ')'
|
| CREATE TYPE_P any_name AS '(' OptTableFuncElementList ')'
|
||||||
{
|
{
|
||||||
CompositeTypeStmt *n = makeNode(CompositeTypeStmt);
|
CompositeTypeStmt *n = makeNode(CompositeTypeStmt);
|
||||||
RangeVar *r = makeNode(RangeVar);
|
|
||||||
|
|
||||||
/* can't use qualified_name, sigh */
|
/* can't use qualified_name, sigh */
|
||||||
switch (list_length($3))
|
n->typevar = makeRangeVarFromAnyName($3, @3, yyscanner);
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
r->catalogname = NULL;
|
|
||||||
r->schemaname = NULL;
|
|
||||||
r->relname = strVal(linitial($3));
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
r->catalogname = NULL;
|
|
||||||
r->schemaname = strVal(linitial($3));
|
|
||||||
r->relname = strVal(lsecond($3));
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
r->catalogname = strVal(linitial($3));
|
|
||||||
r->schemaname = strVal(lsecond($3));
|
|
||||||
r->relname = strVal(lthird($3));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
|
||||||
errmsg("improper qualified name (too many dotted names): %s",
|
|
||||||
NameListToString($3)),
|
|
||||||
parser_errposition(@3)));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
r->location = @3;
|
|
||||||
n->typevar = r;
|
|
||||||
n->coldeflist = $6;
|
n->coldeflist = $6;
|
||||||
$$ = (Node *)n;
|
$$ = (Node *)n;
|
||||||
}
|
}
|
||||||
@ -5836,6 +5877,15 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
|
|||||||
n->newname = $6;
|
n->newname = $6;
|
||||||
$$ = (Node *)n;
|
$$ = (Node *)n;
|
||||||
}
|
}
|
||||||
|
| ALTER TYPE_P any_name RENAME ATTRIBUTE name TO name
|
||||||
|
{
|
||||||
|
RenameStmt *n = makeNode(RenameStmt);
|
||||||
|
n->renameType = OBJECT_ATTRIBUTE;
|
||||||
|
n->relation = makeRangeVarFromAnyName($3, @3, yyscanner);
|
||||||
|
n->subname = $6;
|
||||||
|
n->newname = $8;
|
||||||
|
$$ = (Node *)n;
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
opt_column: COLUMN { $$ = COLUMN; }
|
opt_column: COLUMN { $$ = COLUMN; }
|
||||||
@ -8216,6 +8266,11 @@ where_or_current_clause:
|
|||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
OptTableFuncElementList:
|
||||||
|
TableFuncElementList { $$ = $1; }
|
||||||
|
| /*EMPTY*/ { $$ = NIL; }
|
||||||
|
;
|
||||||
|
|
||||||
TableFuncElementList:
|
TableFuncElementList:
|
||||||
TableFuncElement
|
TableFuncElement
|
||||||
{
|
{
|
||||||
@ -10897,6 +10952,7 @@ unreserved_keyword:
|
|||||||
| ASSERTION
|
| ASSERTION
|
||||||
| ASSIGNMENT
|
| ASSIGNMENT
|
||||||
| AT
|
| AT
|
||||||
|
| ATTRIBUTE
|
||||||
| BACKWARD
|
| BACKWARD
|
||||||
| BEFORE
|
| BEFORE
|
||||||
| BEGIN_P
|
| BEGIN_P
|
||||||
@ -11857,6 +11913,47 @@ TableFuncTypeName(List *columns)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert a list of (dotted) names to a RangeVar (like
|
||||||
|
* makeRangeVarFromNameList, but with position support). The
|
||||||
|
* "AnyName" refers to the any_name production in the grammar.
|
||||||
|
*/
|
||||||
|
static RangeVar *
|
||||||
|
makeRangeVarFromAnyName(List *names, int position, core_yyscan_t yyscanner)
|
||||||
|
{
|
||||||
|
RangeVar *r = makeNode(RangeVar);
|
||||||
|
|
||||||
|
switch (list_length(names))
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
r->catalogname = NULL;
|
||||||
|
r->schemaname = NULL;
|
||||||
|
r->relname = strVal(linitial(names));
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
r->catalogname = NULL;
|
||||||
|
r->schemaname = strVal(linitial(names));
|
||||||
|
r->relname = strVal(lsecond(names));
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
r->catalogname = strVal(linitial(names));;
|
||||||
|
r->schemaname = strVal(lsecond(names));
|
||||||
|
r->relname = strVal(lthird(names));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||||
|
errmsg("improper qualified name (too many dotted names): %s",
|
||||||
|
NameListToString(names)),
|
||||||
|
parser_errposition(position)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
r->location = position;
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Must undefine this stuff before including scan.c, since it has different
|
* Must undefine this stuff before including scan.c, since it has different
|
||||||
* definitions for these macros.
|
* definitions for these macros.
|
||||||
|
@ -839,6 +839,9 @@ transformOfType(ParseState *pstate, CreateStmtContext *cxt, TypeName *ofTypename
|
|||||||
Form_pg_attribute attr = tupdesc->attrs[i];
|
Form_pg_attribute attr = tupdesc->attrs[i];
|
||||||
ColumnDef *n = makeNode(ColumnDef);
|
ColumnDef *n = makeNode(ColumnDef);
|
||||||
|
|
||||||
|
if (attr->attisdropped)
|
||||||
|
continue;
|
||||||
|
|
||||||
n->colname = pstrdup(NameStr(attr->attname));
|
n->colname = pstrdup(NameStr(attr->attname));
|
||||||
n->typeName = makeTypeNameFromOid(attr->atttypid, attr->atttypmod);
|
n->typeName = makeTypeNameFromOid(attr->atttypid, attr->atttypmod);
|
||||||
n->constraints = NULL;
|
n->constraints = NULL;
|
||||||
|
@ -1657,6 +1657,7 @@ CreateCommandTag(Node *parsetree)
|
|||||||
case OBJECT_TSCONFIGURATION:
|
case OBJECT_TSCONFIGURATION:
|
||||||
tag = "ALTER TEXT SEARCH CONFIGURATION";
|
tag = "ALTER TEXT SEARCH CONFIGURATION";
|
||||||
break;
|
break;
|
||||||
|
case OBJECT_ATTRIBUTE:
|
||||||
case OBJECT_TYPE:
|
case OBJECT_TYPE:
|
||||||
tag = "ALTER TYPE";
|
tag = "ALTER TYPE";
|
||||||
break;
|
break;
|
||||||
@ -1780,6 +1781,9 @@ CreateCommandTag(Node *parsetree)
|
|||||||
case OBJECT_SEQUENCE:
|
case OBJECT_SEQUENCE:
|
||||||
tag = "ALTER SEQUENCE";
|
tag = "ALTER SEQUENCE";
|
||||||
break;
|
break;
|
||||||
|
case OBJECT_TYPE:
|
||||||
|
tag = "ALTER TYPE";
|
||||||
|
break;
|
||||||
case OBJECT_VIEW:
|
case OBJECT_VIEW:
|
||||||
tag = "ALTER VIEW";
|
tag = "ALTER VIEW";
|
||||||
break;
|
break;
|
||||||
|
@ -7249,13 +7249,7 @@ dumpCompositeType(Archive *fout, TypeInfo *tyinfo)
|
|||||||
res = PQexec(g_conn, query->data);
|
res = PQexec(g_conn, query->data);
|
||||||
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
|
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
|
||||||
|
|
||||||
/* Expecting at least a single result */
|
|
||||||
ntups = PQntuples(res);
|
ntups = PQntuples(res);
|
||||||
if (ntups < 1)
|
|
||||||
{
|
|
||||||
write_msg(NULL, "query returned no rows: %s\n", query->data);
|
|
||||||
exit_nicely();
|
|
||||||
}
|
|
||||||
|
|
||||||
i_attname = PQfnumber(res, "attname");
|
i_attname = PQfnumber(res, "attname");
|
||||||
i_atttypdefn = PQfnumber(res, "atttypdefn");
|
i_atttypdefn = PQfnumber(res, "atttypdefn");
|
||||||
@ -7356,12 +7350,12 @@ dumpCompositeTypeColComments(Archive *fout, TypeInfo *tyinfo)
|
|||||||
res = PQexec(g_conn, query->data);
|
res = PQexec(g_conn, query->data);
|
||||||
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
|
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
|
||||||
|
|
||||||
/* Expecting at least a single result */
|
|
||||||
ntups = PQntuples(res);
|
ntups = PQntuples(res);
|
||||||
if (ntups < 1)
|
if (ntups < 1)
|
||||||
{
|
{
|
||||||
write_msg(NULL, "query returned no rows: %s\n", query->data);
|
PQclear(res);
|
||||||
exit_nicely();
|
destroyPQExpBuffer(query);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pgClassOid = atooid(PQgetvalue(res, 0, PQfnumber(res, "tableoid")));
|
pgClassOid = atooid(PQgetvalue(res, 0, PQfnumber(res, "tableoid")));
|
||||||
|
@ -1253,15 +1253,45 @@ psql_completion(char *text, int start, int end)
|
|||||||
COMPLETE_WITH_LIST(list_ALTERTEXTSEARCH3);
|
COMPLETE_WITH_LIST(list_ALTERTEXTSEARCH3);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* complete ALTER TYPE <foo> with OWNER TO, SET SCHEMA */
|
/* complete ALTER TYPE <foo> with actions */
|
||||||
else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
|
else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
|
||||||
pg_strcasecmp(prev2_wd, "TYPE") == 0)
|
pg_strcasecmp(prev2_wd, "TYPE") == 0)
|
||||||
{
|
{
|
||||||
static const char *const list_ALTERTYPE[] =
|
static const char *const list_ALTERTYPE[] =
|
||||||
{"OWNER TO", "RENAME TO", "SET SCHEMA", NULL};
|
{"ADD ATTRIBUTE", "ALTER ATTRIBUTE", "DROP ATTRIBUTE",
|
||||||
|
"OWNER TO", "RENAME", "SET SCHEMA", NULL};
|
||||||
|
|
||||||
COMPLETE_WITH_LIST(list_ALTERTYPE);
|
COMPLETE_WITH_LIST(list_ALTERTYPE);
|
||||||
}
|
}
|
||||||
|
/* ALTER TYPE <foo> RENAME */
|
||||||
|
else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 &&
|
||||||
|
pg_strcasecmp(prev3_wd, "TYPE") == 0 &&
|
||||||
|
pg_strcasecmp(prev_wd, "RENAME") == 0)
|
||||||
|
{
|
||||||
|
static const char *const list_ALTERTYPE[] =
|
||||||
|
{"ATTRIBUTE", "TO", NULL};
|
||||||
|
|
||||||
|
COMPLETE_WITH_LIST(list_ALTERTYPE);
|
||||||
|
}
|
||||||
|
/* ALTER TYPE xxx RENAME ATTRIBUTE yyy */
|
||||||
|
else if (pg_strcasecmp(prev5_wd, "TYPE") == 0 &&
|
||||||
|
pg_strcasecmp(prev3_wd, "RENAME") == 0 &&
|
||||||
|
pg_strcasecmp(prev2_wd, "ATTRIBUTE") == 0)
|
||||||
|
COMPLETE_WITH_CONST("TO");
|
||||||
|
|
||||||
|
/* If we have TYPE <sth> ALTER/DROP/RENAME ATTRIBUTE, provide list of attributes */
|
||||||
|
else if (pg_strcasecmp(prev4_wd, "TYPE") == 0 &&
|
||||||
|
(pg_strcasecmp(prev2_wd, "ALTER") == 0 ||
|
||||||
|
pg_strcasecmp(prev2_wd, "DROP") == 0 ||
|
||||||
|
pg_strcasecmp(prev2_wd, "RENAME") == 0) &&
|
||||||
|
pg_strcasecmp(prev_wd, "ATTRIBUTE") == 0)
|
||||||
|
COMPLETE_WITH_ATTR(prev3_wd, "");
|
||||||
|
/* ALTER TYPE ALTER ATTRIBUTE <foo> */
|
||||||
|
else if ((pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
|
||||||
|
pg_strcasecmp(prev2_wd, "ATTRIBUTE") == 0))
|
||||||
|
{
|
||||||
|
COMPLETE_WITH_CONST("TYPE");
|
||||||
|
}
|
||||||
/* complete ALTER GROUP <foo> */
|
/* complete ALTER GROUP <foo> */
|
||||||
else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
|
else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
|
||||||
pg_strcasecmp(prev2_wd, "GROUP") == 0)
|
pg_strcasecmp(prev2_wd, "GROUP") == 0)
|
||||||
|
@ -1046,6 +1046,7 @@ typedef struct SetOperationStmt
|
|||||||
typedef enum ObjectType
|
typedef enum ObjectType
|
||||||
{
|
{
|
||||||
OBJECT_AGGREGATE,
|
OBJECT_AGGREGATE,
|
||||||
|
OBJECT_ATTRIBUTE, /* type's attribute, when distinct from column */
|
||||||
OBJECT_CAST,
|
OBJECT_CAST,
|
||||||
OBJECT_COLUMN,
|
OBJECT_COLUMN,
|
||||||
OBJECT_CONSTRAINT,
|
OBJECT_CONSTRAINT,
|
||||||
|
@ -49,6 +49,7 @@ PG_KEYWORD("assertion", ASSERTION, UNRESERVED_KEYWORD)
|
|||||||
PG_KEYWORD("assignment", ASSIGNMENT, UNRESERVED_KEYWORD)
|
PG_KEYWORD("assignment", ASSIGNMENT, UNRESERVED_KEYWORD)
|
||||||
PG_KEYWORD("asymmetric", ASYMMETRIC, RESERVED_KEYWORD)
|
PG_KEYWORD("asymmetric", ASYMMETRIC, RESERVED_KEYWORD)
|
||||||
PG_KEYWORD("at", AT, UNRESERVED_KEYWORD)
|
PG_KEYWORD("at", AT, UNRESERVED_KEYWORD)
|
||||||
|
PG_KEYWORD("attribute", ATTRIBUTE, UNRESERVED_KEYWORD)
|
||||||
PG_KEYWORD("authorization", AUTHORIZATION, TYPE_FUNC_NAME_KEYWORD)
|
PG_KEYWORD("authorization", AUTHORIZATION, TYPE_FUNC_NAME_KEYWORD)
|
||||||
PG_KEYWORD("backward", BACKWARD, UNRESERVED_KEYWORD)
|
PG_KEYWORD("backward", BACKWARD, UNRESERVED_KEYWORD)
|
||||||
PG_KEYWORD("before", BEFORE, UNRESERVED_KEYWORD)
|
PG_KEYWORD("before", BEFORE, UNRESERVED_KEYWORD)
|
||||||
|
@ -854,7 +854,7 @@ select * from myview;
|
|||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
alter table myview drop d;
|
alter table myview drop d;
|
||||||
ERROR: "myview" is not a table
|
ERROR: "myview" is not a table or composite type
|
||||||
drop view myview;
|
drop view myview;
|
||||||
-- test some commands to make sure they fail on the dropped column
|
-- test some commands to make sure they fail on the dropped column
|
||||||
analyze atacc1(a);
|
analyze atacc1(a);
|
||||||
@ -1472,6 +1472,11 @@ select * from another;
|
|||||||
(3 rows)
|
(3 rows)
|
||||||
|
|
||||||
drop table another;
|
drop table another;
|
||||||
|
-- table's row type
|
||||||
|
create table tab1 (a int, b text);
|
||||||
|
create table tab2 (x int, y tab1);
|
||||||
|
alter table tab1 alter column b type varchar; -- fails
|
||||||
|
ERROR: cannot alter table "tab1" because column "tab2"."y" uses its rowtype
|
||||||
--
|
--
|
||||||
-- lock levels
|
-- lock levels
|
||||||
--
|
--
|
||||||
@ -1683,3 +1688,85 @@ drop cascades to view alter2.v1
|
|||||||
drop cascades to function alter2.plus1(integer)
|
drop cascades to function alter2.plus1(integer)
|
||||||
drop cascades to type alter2.posint
|
drop cascades to type alter2.posint
|
||||||
drop cascades to type alter2.ctype
|
drop cascades to type alter2.ctype
|
||||||
|
--
|
||||||
|
-- composite types
|
||||||
|
--
|
||||||
|
CREATE TYPE test_type AS (a int);
|
||||||
|
\d test_type
|
||||||
|
Composite type "public.test_type"
|
||||||
|
Column | Type
|
||||||
|
--------+---------
|
||||||
|
a | integer
|
||||||
|
|
||||||
|
ALTER TYPE nosuchtype ADD ATTRIBUTE b text; -- fails
|
||||||
|
ERROR: relation "nosuchtype" does not exist
|
||||||
|
ALTER TYPE test_type ADD ATTRIBUTE b text;
|
||||||
|
\d test_type
|
||||||
|
Composite type "public.test_type"
|
||||||
|
Column | Type
|
||||||
|
--------+---------
|
||||||
|
a | integer
|
||||||
|
b | text
|
||||||
|
|
||||||
|
ALTER TYPE test_type ADD ATTRIBUTE b text; -- fails
|
||||||
|
ERROR: column "b" of relation "test_type" already exists
|
||||||
|
ALTER TYPE test_type ALTER ATTRIBUTE b SET DATA TYPE varchar;
|
||||||
|
\d test_type
|
||||||
|
Composite type "public.test_type"
|
||||||
|
Column | Type
|
||||||
|
--------+-------------------
|
||||||
|
a | integer
|
||||||
|
b | character varying
|
||||||
|
|
||||||
|
ALTER TYPE test_type ALTER ATTRIBUTE b SET DATA TYPE integer;
|
||||||
|
\d test_type
|
||||||
|
Composite type "public.test_type"
|
||||||
|
Column | Type
|
||||||
|
--------+---------
|
||||||
|
a | integer
|
||||||
|
b | integer
|
||||||
|
|
||||||
|
ALTER TYPE test_type DROP ATTRIBUTE b;
|
||||||
|
\d test_type
|
||||||
|
Composite type "public.test_type"
|
||||||
|
Column | Type
|
||||||
|
--------+---------
|
||||||
|
a | integer
|
||||||
|
|
||||||
|
ALTER TYPE test_type DROP ATTRIBUTE c; -- fails
|
||||||
|
ERROR: column "c" of relation "test_type" does not exist
|
||||||
|
ALTER TYPE test_type DROP ATTRIBUTE IF EXISTS c;
|
||||||
|
NOTICE: column "c" of relation "test_type" does not exist, skipping
|
||||||
|
ALTER TYPE test_type DROP ATTRIBUTE a, ADD ATTRIBUTE d boolean;
|
||||||
|
\d test_type
|
||||||
|
Composite type "public.test_type"
|
||||||
|
Column | Type
|
||||||
|
--------+---------
|
||||||
|
d | boolean
|
||||||
|
|
||||||
|
ALTER TYPE test_type RENAME ATTRIBUTE a TO aa;
|
||||||
|
ERROR: column "a" does not exist
|
||||||
|
ALTER TYPE test_type RENAME ATTRIBUTE d TO dd;
|
||||||
|
\d test_type
|
||||||
|
Composite type "public.test_type"
|
||||||
|
Column | Type
|
||||||
|
--------+---------
|
||||||
|
dd | boolean
|
||||||
|
|
||||||
|
DROP TYPE test_type;
|
||||||
|
CREATE TYPE test_type1 AS (a int, b text);
|
||||||
|
CREATE TABLE test_tbl1 (x int, y test_type1);
|
||||||
|
ALTER TYPE test_type1 ALTER ATTRIBUTE b TYPE varchar; -- fails
|
||||||
|
ERROR: cannot alter type "test_type1" because column "test_tbl1"."y" uses it
|
||||||
|
CREATE TYPE test_type2 AS (a int, b text);
|
||||||
|
CREATE TABLE test_tbl2 OF test_type2;
|
||||||
|
ALTER TYPE test_type2 ADD ATTRIBUTE c text; -- fails
|
||||||
|
ERROR: cannot alter type "test_type2" because it is the type of a typed table
|
||||||
|
ALTER TYPE test_type2 ALTER ATTRIBUTE b TYPE varchar; -- fails
|
||||||
|
ERROR: cannot alter type "test_type2" because it is the type of a typed table
|
||||||
|
ALTER TYPE test_type2 DROP ATTRIBUTE b; -- fails
|
||||||
|
ERROR: cannot alter type "test_type2" because it is the type of a typed table
|
||||||
|
ALTER TYPE test_type2 RENAME ATTRIBUTE b TO bb; -- fails
|
||||||
|
ERROR: cannot alter type "test_type2" because it is the type of a typed table
|
||||||
|
CREATE TYPE test_type_empty AS ();
|
||||||
|
DROP TYPE test_type_empty;
|
||||||
|
@ -1090,6 +1090,11 @@ select * from another;
|
|||||||
|
|
||||||
drop table another;
|
drop table another;
|
||||||
|
|
||||||
|
-- table's row type
|
||||||
|
create table tab1 (a int, b text);
|
||||||
|
create table tab2 (x int, y tab1);
|
||||||
|
alter table tab1 alter column b type varchar; -- fails
|
||||||
|
|
||||||
--
|
--
|
||||||
-- lock levels
|
-- lock levels
|
||||||
--
|
--
|
||||||
@ -1224,3 +1229,53 @@ select alter2.plus1(41);
|
|||||||
|
|
||||||
-- clean up
|
-- clean up
|
||||||
drop schema alter2 cascade;
|
drop schema alter2 cascade;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- composite types
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TYPE test_type AS (a int);
|
||||||
|
\d test_type
|
||||||
|
|
||||||
|
ALTER TYPE nosuchtype ADD ATTRIBUTE b text; -- fails
|
||||||
|
|
||||||
|
ALTER TYPE test_type ADD ATTRIBUTE b text;
|
||||||
|
\d test_type
|
||||||
|
|
||||||
|
ALTER TYPE test_type ADD ATTRIBUTE b text; -- fails
|
||||||
|
|
||||||
|
ALTER TYPE test_type ALTER ATTRIBUTE b SET DATA TYPE varchar;
|
||||||
|
\d test_type
|
||||||
|
|
||||||
|
ALTER TYPE test_type ALTER ATTRIBUTE b SET DATA TYPE integer;
|
||||||
|
\d test_type
|
||||||
|
|
||||||
|
ALTER TYPE test_type DROP ATTRIBUTE b;
|
||||||
|
\d test_type
|
||||||
|
|
||||||
|
ALTER TYPE test_type DROP ATTRIBUTE c; -- fails
|
||||||
|
|
||||||
|
ALTER TYPE test_type DROP ATTRIBUTE IF EXISTS c;
|
||||||
|
|
||||||
|
ALTER TYPE test_type DROP ATTRIBUTE a, ADD ATTRIBUTE d boolean;
|
||||||
|
\d test_type
|
||||||
|
|
||||||
|
ALTER TYPE test_type RENAME ATTRIBUTE a TO aa;
|
||||||
|
ALTER TYPE test_type RENAME ATTRIBUTE d TO dd;
|
||||||
|
\d test_type
|
||||||
|
|
||||||
|
DROP TYPE test_type;
|
||||||
|
|
||||||
|
CREATE TYPE test_type1 AS (a int, b text);
|
||||||
|
CREATE TABLE test_tbl1 (x int, y test_type1);
|
||||||
|
ALTER TYPE test_type1 ALTER ATTRIBUTE b TYPE varchar; -- fails
|
||||||
|
|
||||||
|
CREATE TYPE test_type2 AS (a int, b text);
|
||||||
|
CREATE TABLE test_tbl2 OF test_type2;
|
||||||
|
ALTER TYPE test_type2 ADD ATTRIBUTE c text; -- fails
|
||||||
|
ALTER TYPE test_type2 ALTER ATTRIBUTE b TYPE varchar; -- fails
|
||||||
|
ALTER TYPE test_type2 DROP ATTRIBUTE b; -- fails
|
||||||
|
ALTER TYPE test_type2 RENAME ATTRIBUTE b TO bb; -- fails
|
||||||
|
|
||||||
|
CREATE TYPE test_type_empty AS ();
|
||||||
|
DROP TYPE test_type_empty;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user