Commit e440e12c authored by Peter Eisentraut's avatar Peter Eisentraut

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
parent 899beb78
...@@ -23,9 +23,17 @@ PostgreSQL documentation ...@@ -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 ...@@ -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 ...@@ -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,16 +223,32 @@ ALTER TYPE email OWNER TO joe; ...@@ -117,16 +223,32 @@ 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>
<refsect1> <refsect1>
<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 ...@@ -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 ( ...@@ -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 ( ...@@ -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; ...@@ -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; ...@@ -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) ...@@ -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) ...@@ -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 */
......
This diff is collapsed.
...@@ -1508,11 +1508,6 @@ DefineCompositeType(const RangeVar *typevar, List *coldeflist) ...@@ -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, ...@@ -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); ...@@ -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); ...@@ -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); ...@@ -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); ...@@ -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 : ...@@ -657,6 +658,7 @@ stmt :
| AlterOwnerStmt | AlterOwnerStmt
| AlterSeqStmt | AlterSeqStmt
| AlterTableStmt | AlterTableStmt
| AlterCompositeTypeStmt
| AlterRoleSetStmt | AlterRoleSetStmt
| AlterRoleStmt | AlterRoleStmt
| AlterTSConfigurationStmt | AlterTSConfigurationStmt
...@@ -1968,6 +1970,72 @@ reloption_elem: ...@@ -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: ...@@ -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 ...@@ -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: ...@@ -8216,6 +8266,11 @@ where_or_current_clause:
; ;
OptTableFuncElementList:
TableFuncElementList { $$ = $1; }
| /*EMPTY*/ { $$ = NIL; }
;
TableFuncElementList: TableFuncElementList:
TableFuncElement TableFuncElement
{ {
...@@ -10897,6 +10952,7 @@ unreserved_keyword: ...@@ -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) ...@@ -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 ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 ...@@ -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) ...@@ -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; ...@@ -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; ...@@ -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 ...@@ -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; ...@@ -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); ...@@ -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;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment