Commit f2a42783 authored by Peter Eisentraut's avatar Peter Eisentraut

Propagate ALTER TYPE operations to typed tables

This adds RESTRICT/CASCADE flags to ALTER TYPE ... ADD/DROP/ALTER/
RENAME ATTRIBUTE to control whether to alter typed tables as well.
parent fc946c39
...@@ -26,15 +26,15 @@ PostgreSQL documentation ...@@ -26,15 +26,15 @@ PostgreSQL documentation
ALTER TYPE <replaceable class="PARAMETER">name</replaceable> <replaceable class="PARAMETER">action</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 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> RENAME TO <replaceable class="PARAMETER">new_name</replaceable> [ CASCADE | RESTRICT ]
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>
ALTER TYPE <replaceable class="PARAMETER">name</replaceable> ADD VALUE <replaceable class="PARAMETER">new_enum_value</replaceable> [ { BEFORE | AFTER } <replaceable class="PARAMETER">existing_enum_value</replaceable> ] ALTER TYPE <replaceable class="PARAMETER">name</replaceable> ADD VALUE <replaceable class="PARAMETER">new_enum_value</replaceable> [ { BEFORE | AFTER } <replaceable class="PARAMETER">existing_enum_value</replaceable> ]
<phrase>where <replaceable class="PARAMETER">action</replaceable> is one of:</phrase> <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> ADD ATTRIBUTE <replaceable class="PARAMETER">attribute_name</replaceable> <replaceable class="PARAMETER">data_type</replaceable> [ CASCADE | RESTRICT ]
DROP ATTRIBUTE [ IF EXISTS ] <replaceable class="PARAMETER">attribute_name</replaceable> DROP ATTRIBUTE [ IF EXISTS ] <replaceable class="PARAMETER">attribute_name</replaceable> [ CASCADE | RESTRICT ]
ALTER ATTRIBUTE <replaceable class="PARAMETER">attribute_name</replaceable> [ SET DATA ] TYPE <replaceable class="PARAMETER">data_type</replaceable> ALTER ATTRIBUTE <replaceable class="PARAMETER">attribute_name</replaceable> [ SET DATA ] TYPE <replaceable class="PARAMETER">data_type</replaceable> [ CASCADE | RESTRICT ]
</synopsis> </synopsis>
</refsynopsisdiv> </refsynopsisdiv>
...@@ -116,6 +116,26 @@ ALTER TYPE <replaceable class="PARAMETER">name</replaceable> ADD VALUE <replacea ...@@ -116,6 +116,26 @@ ALTER TYPE <replaceable class="PARAMETER">name</replaceable> ADD VALUE <replacea
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><literal>CASCADE</literal></term>
<listitem>
<para>
Automatically propagate the operation to typed tables of the
type being altered.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>RESTRICT</literal></term>
<listitem>
<para>
Refuse the operation if the type being altered is the type of a
typed table. This is the default.
</para>
</listitem>
</varlistentry>
</variablelist> </variablelist>
</para> </para>
......
...@@ -125,11 +125,7 @@ ExecRenameStmt(RenameStmt *stmt) ...@@ -125,11 +125,7 @@ ExecRenameStmt(RenameStmt *stmt)
} }
case OBJECT_COLUMN: case OBJECT_COLUMN:
case OBJECT_ATTRIBUTE: case OBJECT_ATTRIBUTE:
renameatt(relid, renameatt(relid, stmt);
stmt->subname, /* old att name */
stmt->newname, /* new att name */
interpretInhOption(stmt->relation->inhOpt), /* recursive? */
0); /* expected inhcount */
break; break;
case OBJECT_TRIGGER: case OBJECT_TRIGGER:
renametrig(relid, renametrig(relid,
......
...@@ -269,8 +269,11 @@ static void ATSimpleRecursion(List **wqueue, Relation rel, ...@@ -269,8 +269,11 @@ 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 ATTypedTableRecursion(List **wqueue, Relation rel, AlterTableCmd *cmd,
static void ATPrepAddColumn(List **wqueue, Relation rel, bool recurse, LOCKMODE lockmode);
static List *find_typed_table_dependencies(Oid typeOid, const char *typeName,
DropBehavior behavior);
static void ATPrepAddColumn(List **wqueue, Relation rel, bool recurse, bool recursing,
AlterTableCmd *cmd, LOCKMODE lockmode); AlterTableCmd *cmd, LOCKMODE lockmode);
static void ATExecAddColumn(AlteredTableInfo *tab, Relation rel, static void ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
ColumnDef *colDef, bool isOid, LOCKMODE lockmode); ColumnDef *colDef, bool isOid, LOCKMODE lockmode);
...@@ -290,7 +293,8 @@ static void ATExecSetOptions(Relation rel, const char *colName, ...@@ -290,7 +293,8 @@ static void ATExecSetOptions(Relation rel, const char *colName,
Node *options, bool isReset, LOCKMODE lockmode); Node *options, bool isReset, LOCKMODE lockmode);
static void ATExecSetStorage(Relation rel, const char *colName, static void ATExecSetStorage(Relation rel, const char *colName,
Node *newValue, LOCKMODE lockmode); Node *newValue, LOCKMODE lockmode);
static void ATPrepDropColumn(Relation rel, bool recurse, AlterTableCmd *cmd); static void ATPrepDropColumn(List **wqueue, Relation rel, bool recurse, bool recursing,
AlterTableCmd *cmd, LOCKMODE lockmode);
static void ATExecDropColumn(List **wqueue, Relation rel, const char *colName, static void ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
DropBehavior behavior, DropBehavior behavior,
bool recurse, bool recursing, bool recurse, bool recursing,
...@@ -1942,14 +1946,16 @@ setRelhassubclassInRelation(Oid relationId, bool relhassubclass) ...@@ -1942,14 +1946,16 @@ setRelhassubclassInRelation(Oid relationId, bool relhassubclass)
/* /*
* renameatt - changes the name of a attribute in a relation * renameatt_internal - workhorse for renameatt
*/ */
void static void
renameatt(Oid myrelid, renameatt_internal(Oid myrelid,
const char *oldattname, const char *oldattname,
const char *newattname, const char *newattname,
bool recurse, bool recurse,
int expected_parents) bool recursing,
int expected_parents,
DropBehavior behavior)
{ {
Relation targetrelation; Relation targetrelation;
Relation attrelation; Relation attrelation;
...@@ -1964,15 +1970,11 @@ renameatt(Oid myrelid, ...@@ -1964,15 +1970,11 @@ renameatt(Oid myrelid,
*/ */
targetrelation = relation_open(myrelid, AccessExclusiveLock); targetrelation = relation_open(myrelid, AccessExclusiveLock);
if (targetrelation->rd_rel->reloftype) if (targetrelation->rd_rel->reloftype && !recursing)
ereport(ERROR, ereport(ERROR,
(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
...@@ -2038,7 +2040,7 @@ renameatt(Oid myrelid, ...@@ -2038,7 +2040,7 @@ renameatt(Oid myrelid,
if (childrelid == myrelid) if (childrelid == myrelid)
continue; continue;
/* note we need not recurse again */ /* note we need not recurse again */
renameatt(childrelid, oldattname, newattname, false, numparents); renameatt_internal(childrelid, oldattname, newattname, false, true, numparents, behavior);
} }
} }
else else
...@@ -2057,6 +2059,20 @@ renameatt(Oid myrelid, ...@@ -2057,6 +2059,20 @@ renameatt(Oid myrelid,
oldattname))); oldattname)));
} }
/* rename attributes in typed tables of composite type */
if (targetrelation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
{
List *child_oids;
ListCell *lo;
child_oids = find_typed_table_dependencies(targetrelation->rd_rel->reltype,
RelationGetRelationName(targetrelation),
behavior);
foreach(lo, child_oids)
renameatt_internal(lfirst_oid(lo), oldattname, newattname, true, true, 0, behavior);
}
attrelation = heap_open(AttributeRelationId, RowExclusiveLock); attrelation = heap_open(AttributeRelationId, RowExclusiveLock);
atttup = SearchSysCacheCopyAttName(myrelid, oldattname); atttup = SearchSysCacheCopyAttName(myrelid, oldattname);
...@@ -2116,6 +2132,22 @@ renameatt(Oid myrelid, ...@@ -2116,6 +2132,22 @@ renameatt(Oid myrelid,
} }
/*
* renameatt - changes the name of a attribute in a relation
*/
void
renameatt(Oid myrelid, RenameStmt *stmt)
{
renameatt_internal(myrelid,
stmt->subname, /* old att name */
stmt->newname, /* new att name */
interpretInhOption(stmt->relation->inhOpt), /* recursive? */
false, /* recursing? */
0, /* expected inhcount */
stmt->behavior);
}
/* /*
* Execute ALTER TABLE/INDEX/SEQUENCE/VIEW RENAME * Execute ALTER TABLE/INDEX/SEQUENCE/VIEW RENAME
* *
...@@ -2649,14 +2681,14 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd, ...@@ -2649,14 +2681,14 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
case AT_AddColumn: /* ADD COLUMN */ case AT_AddColumn: /* ADD COLUMN */
ATSimplePermissions(rel, false, true); ATSimplePermissions(rel, false, true);
/* Performs own recursion */ /* Performs own recursion */
ATPrepAddColumn(wqueue, rel, recurse, cmd, lockmode); ATPrepAddColumn(wqueue, rel, recurse, recursing, 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, false); ATSimplePermissions(rel, true, false);
/* Performs own recursion */ /* Performs own recursion */
ATPrepAddColumn(wqueue, rel, recurse, cmd, lockmode); ATPrepAddColumn(wqueue, rel, recurse, recursing, cmd, lockmode);
pass = AT_PASS_ADD_COL; pass = AT_PASS_ADD_COL;
break; break;
case AT_ColumnDefault: /* ALTER COLUMN DEFAULT */ case AT_ColumnDefault: /* ALTER COLUMN DEFAULT */
...@@ -2704,7 +2736,7 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd, ...@@ -2704,7 +2736,7 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
break; break;
case AT_DropColumn: /* DROP COLUMN */ case AT_DropColumn: /* DROP COLUMN */
ATSimplePermissions(rel, false, true); ATSimplePermissions(rel, false, true);
ATPrepDropColumn(rel, recurse, cmd); ATPrepDropColumn(wqueue, rel, recurse, recursing, cmd, lockmode);
/* Recursion occurs during execution phase */ /* Recursion occurs during execution phase */
pass = AT_PASS_DROP; pass = AT_PASS_DROP;
break; break;
...@@ -3671,6 +3703,37 @@ ATOneLevelRecursion(List **wqueue, Relation rel, ...@@ -3671,6 +3703,37 @@ ATOneLevelRecursion(List **wqueue, Relation rel,
} }
} }
/*
* ATTypedTableRecursion
*
* Propagate ALTER TYPE operations to the typed tables of that type.
* Also check the RESTRICT/CASCADE behavior.
*/
static void
ATTypedTableRecursion(List **wqueue, Relation rel, AlterTableCmd *cmd,
LOCKMODE lockmode)
{
ListCell *child;
List *children;
Assert(rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE);
children = find_typed_table_dependencies(rel->rd_rel->reltype,
RelationGetRelationName(rel),
cmd->behavior);
foreach(child, children)
{
Oid childrelid = lfirst_oid(child);
Relation childrel;
childrel = relation_open(childrelid, lockmode);
CheckTableNotInUse(childrel, "ALTER TABLE");
ATPrepCmd(wqueue, childrel, cmd, false, true, lockmode);
relation_close(childrel, NoLock);
}
}
/* /*
* find_composite_type_dependencies * find_composite_type_dependencies
...@@ -3778,17 +3841,17 @@ find_composite_type_dependencies(Oid typeOid, ...@@ -3778,17 +3841,17 @@ find_composite_type_dependencies(Oid typeOid,
* find_typed_table_dependencies * find_typed_table_dependencies
* *
* Check to see if a composite type is being used as the type of a * 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 * typed table. Abort if any are found and behavior is RESTRICT.
* operation into such tables, but for now, just error out if we find * Else return the list of tables.
* any.
*/ */
static void static List *
find_typed_table_dependencies(Oid typeOid, const char *typeName) find_typed_table_dependencies(Oid typeOid, const char *typeName, DropBehavior behavior)
{ {
Relation classRel; Relation classRel;
ScanKeyData key[1]; ScanKeyData key[1];
HeapScanDesc scan; HeapScanDesc scan;
HeapTuple tuple; HeapTuple tuple;
List *result = NIL;
classRel = heap_open(RelationRelationId, AccessShareLock); classRel = heap_open(RelationRelationId, AccessShareLock);
...@@ -3801,14 +3864,20 @@ find_typed_table_dependencies(Oid typeOid, const char *typeName) ...@@ -3801,14 +3864,20 @@ find_typed_table_dependencies(Oid typeOid, const char *typeName)
if (HeapTupleIsValid(tuple = heap_getnext(scan, ForwardScanDirection))) if (HeapTupleIsValid(tuple = heap_getnext(scan, ForwardScanDirection)))
{ {
if (behavior == DROP_RESTRICT)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
errmsg("cannot alter type \"%s\" because it is the type of a typed table", errmsg("cannot alter type \"%s\" because it is the type of a typed table",
typeName))); typeName),
errhint("Use ALTER ... CASCADE to alter the typed tables too.")));
else
result = lappend_oid(result, HeapTupleGetOid(tuple));
} }
heap_endscan(scan); heap_endscan(scan);
heap_close(classRel, AccessShareLock); heap_close(classRel, AccessShareLock);
return result;
} }
...@@ -3821,10 +3890,10 @@ find_typed_table_dependencies(Oid typeOid, const char *typeName) ...@@ -3821,10 +3890,10 @@ find_typed_table_dependencies(Oid typeOid, const char *typeName)
* AlterTableCmd's. * AlterTableCmd's.
*/ */
static void static void
ATPrepAddColumn(List **wqueue, Relation rel, bool recurse, ATPrepAddColumn(List **wqueue, Relation rel, bool recurse, bool recursing,
AlterTableCmd *cmd, LOCKMODE lockmode) AlterTableCmd *cmd, LOCKMODE lockmode)
{ {
if (rel->rd_rel->reloftype) if (rel->rd_rel->reloftype && !recursing)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE), (errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("cannot add column to typed table"))); errmsg("cannot add column to typed table")));
...@@ -3860,8 +3929,7 @@ ATPrepAddColumn(List **wqueue, Relation rel, bool recurse, ...@@ -3860,8 +3929,7 @@ ATPrepAddColumn(List **wqueue, Relation rel, bool recurse,
} }
if (rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE) if (rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
find_typed_table_dependencies(rel->rd_rel->reltype, ATTypedTableRecursion(wqueue, rel, cmd, lockmode);
RelationGetRelationName(rel));
} }
static void static void
...@@ -4162,7 +4230,7 @@ ATPrepAddOids(List **wqueue, Relation rel, bool recurse, AlterTableCmd *cmd, LOC ...@@ -4162,7 +4230,7 @@ ATPrepAddOids(List **wqueue, Relation rel, bool recurse, AlterTableCmd *cmd, LOC
cdef->storage = 0; cdef->storage = 0;
cmd->def = (Node *) cdef; cmd->def = (Node *) cdef;
} }
ATPrepAddColumn(wqueue, rel, recurse, cmd, lockmode); ATPrepAddColumn(wqueue, rel, recurse, false, cmd, lockmode);
} }
/* /*
...@@ -4586,18 +4654,17 @@ ATExecSetStorage(Relation rel, const char *colName, Node *newValue, LOCKMODE loc ...@@ -4586,18 +4654,17 @@ ATExecSetStorage(Relation rel, const char *colName, Node *newValue, LOCKMODE loc
* correctly.) * correctly.)
*/ */
static void static void
ATPrepDropColumn(Relation rel, bool recurse, AlterTableCmd *cmd) ATPrepDropColumn(List **wqueue, Relation rel, bool recurse, bool recursing,
AlterTableCmd *cmd, LOCKMODE lockmode)
{ {
if (rel->rd_rel->reloftype) if (rel->rd_rel->reloftype && !recursing)
ereport(ERROR, ereport(ERROR,
(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) if (rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
find_typed_table_dependencies(rel->rd_rel->reltype, ATTypedTableRecursion(wqueue, rel, cmd, lockmode);
RelationGetRelationName(rel));
/* No command-specific prep needed except saving recurse flag */
if (recurse) if (recurse)
cmd->subtype = AT_DropColumnRecurse; cmd->subtype = AT_DropColumnRecurse;
} }
...@@ -6060,7 +6127,7 @@ ATPrepAlterColumnType(List **wqueue, ...@@ -6060,7 +6127,7 @@ ATPrepAlterColumnType(List **wqueue,
NewColumnValue *newval; NewColumnValue *newval;
ParseState *pstate = make_parsestate(NULL); ParseState *pstate = make_parsestate(NULL);
if (rel->rd_rel->reloftype) if (rel->rd_rel->reloftype && !recursing)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE), (errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("cannot alter column type of typed table"))); errmsg("cannot alter column type of typed table")));
...@@ -6178,9 +6245,6 @@ ATPrepAlterColumnType(List **wqueue, ...@@ -6178,9 +6245,6 @@ ATPrepAlterColumnType(List **wqueue,
find_composite_type_dependencies(rel->rd_rel->reltype, find_composite_type_dependencies(rel->rd_rel->reltype,
NULL, NULL,
RelationGetRelationName(rel)); RelationGetRelationName(rel));
find_typed_table_dependencies(rel->rd_rel->reltype,
RelationGetRelationName(rel));
} }
ReleaseSysCache(tuple); ReleaseSysCache(tuple);
...@@ -6198,6 +6262,9 @@ ATPrepAlterColumnType(List **wqueue, ...@@ -6198,6 +6262,9 @@ ATPrepAlterColumnType(List **wqueue,
(errcode(ERRCODE_INVALID_TABLE_DEFINITION), (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
errmsg("type of inherited column \"%s\" must be changed in child tables too", errmsg("type of inherited column \"%s\" must be changed in child tables too",
colName))); colName)));
if (tab->relkind == RELKIND_COMPOSITE_TYPE)
ATTypedTableRecursion(wqueue, rel, cmd, lockmode);
} }
static void static void
......
...@@ -2803,6 +2803,7 @@ _copyRenameStmt(RenameStmt *from) ...@@ -2803,6 +2803,7 @@ _copyRenameStmt(RenameStmt *from)
COPY_NODE_FIELD(objarg); COPY_NODE_FIELD(objarg);
COPY_STRING_FIELD(subname); COPY_STRING_FIELD(subname);
COPY_STRING_FIELD(newname); COPY_STRING_FIELD(newname);
COPY_SCALAR_FIELD(behavior);
return newnode; return newnode;
} }
......
...@@ -1306,6 +1306,7 @@ _equalRenameStmt(RenameStmt *a, RenameStmt *b) ...@@ -1306,6 +1306,7 @@ _equalRenameStmt(RenameStmt *a, RenameStmt *b)
COMPARE_NODE_FIELD(objarg); COMPARE_NODE_FIELD(objarg);
COMPARE_STRING_FIELD(subname); COMPARE_STRING_FIELD(subname);
COMPARE_STRING_FIELD(newname); COMPARE_STRING_FIELD(newname);
COMPARE_SCALAR_FIELD(behavior);
return true; return true;
} }
......
...@@ -2003,41 +2003,43 @@ alter_type_cmds: ...@@ -2003,41 +2003,43 @@ alter_type_cmds:
; ;
alter_type_cmd: alter_type_cmd:
/* ALTER TYPE <name> ADD ATTRIBUTE <coldef> */ /* ALTER TYPE <name> ADD ATTRIBUTE <coldef> [RESTRICT|CASCADE] */
ADD_P ATTRIBUTE TableFuncElement ADD_P ATTRIBUTE TableFuncElement opt_drop_behavior
{ {
AlterTableCmd *n = makeNode(AlterTableCmd); AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_AddColumn; n->subtype = AT_AddColumn;
n->def = $3; n->def = $3;
n->behavior = $4;
$$ = (Node *)n; $$ = (Node *)n;
} }
/* ALTER TYPE <name> DROP ATTRIBUTE IF EXISTS <attname> */ /* ALTER TYPE <name> DROP ATTRIBUTE IF EXISTS <attname> [RESTRICT|CASCADE] */
| DROP ATTRIBUTE IF_P EXISTS ColId | DROP ATTRIBUTE IF_P EXISTS ColId opt_drop_behavior
{ {
AlterTableCmd *n = makeNode(AlterTableCmd); AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_DropColumn; n->subtype = AT_DropColumn;
n->name = $5; n->name = $5;
n->behavior = DROP_RESTRICT; /* currently no effect */ n->behavior = $6;
n->missing_ok = TRUE; n->missing_ok = TRUE;
$$ = (Node *)n; $$ = (Node *)n;
} }
/* ALTER TYPE <name> DROP ATTRIBUTE <attname> */ /* ALTER TYPE <name> DROP ATTRIBUTE <attname> [RESTRICT|CASCADE] */
| DROP ATTRIBUTE ColId opt_drop_behavior | DROP ATTRIBUTE ColId opt_drop_behavior
{ {
AlterTableCmd *n = makeNode(AlterTableCmd); AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_DropColumn; n->subtype = AT_DropColumn;
n->name = $3; n->name = $3;
n->behavior = DROP_RESTRICT; /* currently no effect */ n->behavior = $4;
n->missing_ok = FALSE; n->missing_ok = FALSE;
$$ = (Node *)n; $$ = (Node *)n;
} }
/* ALTER TYPE <name> ALTER ATTRIBUTE <attname> [SET DATA] TYPE <typename> */ /* ALTER TYPE <name> ALTER ATTRIBUTE <attname> [SET DATA] TYPE <typename> [RESTRICT|CASCADE] */
| ALTER ATTRIBUTE ColId opt_set_data TYPE_P Typename | ALTER ATTRIBUTE ColId opt_set_data TYPE_P Typename opt_drop_behavior
{ {
AlterTableCmd *n = makeNode(AlterTableCmd); AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_AlterColumnType; n->subtype = AT_AlterColumnType;
n->name = $3; n->name = $3;
n->def = (Node *) $6; n->def = (Node *) $6;
n->behavior = $7;
$$ = (Node *)n; $$ = (Node *)n;
} }
; ;
...@@ -6005,13 +6007,14 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name ...@@ -6005,13 +6007,14 @@ 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 | ALTER TYPE_P any_name RENAME ATTRIBUTE name TO name opt_drop_behavior
{ {
RenameStmt *n = makeNode(RenameStmt); RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_ATTRIBUTE; n->renameType = OBJECT_ATTRIBUTE;
n->relation = makeRangeVarFromAnyName($3, @3, yyscanner); n->relation = makeRangeVarFromAnyName($3, @3, yyscanner);
n->subname = $6; n->subname = $6;
n->newname = $8; n->newname = $8;
n->behavior = $9;
$$ = (Node *)n; $$ = (Node *)n;
} }
; ;
......
...@@ -42,11 +42,7 @@ extern void CheckTableNotInUse(Relation rel, const char *stmt); ...@@ -42,11 +42,7 @@ extern void CheckTableNotInUse(Relation rel, const char *stmt);
extern void ExecuteTruncate(TruncateStmt *stmt); extern void ExecuteTruncate(TruncateStmt *stmt);
extern void renameatt(Oid myrelid, extern void renameatt(Oid myrelid, RenameStmt *stmt);
const char *oldattname,
const char *newattname,
bool recurse,
int expected_parents);
extern void RenameRelation(Oid myrelid, extern void RenameRelation(Oid myrelid,
const char *newrelname, const char *newrelname,
......
...@@ -2073,6 +2073,7 @@ typedef struct RenameStmt ...@@ -2073,6 +2073,7 @@ typedef struct RenameStmt
char *subname; /* name of contained object (column, rule, char *subname; /* name of contained object (column, rule,
* trigger, etc) */ * trigger, etc) */
char *newname; /* the new name */ char *newname; /* the new name */
DropBehavior behavior; /* RESTRICT or CASCADE behavior */
} RenameStmt; } RenameStmt;
/* ---------------------- /* ----------------------
......
...@@ -1760,13 +1760,100 @@ ALTER TYPE test_type1 ALTER ATTRIBUTE b TYPE varchar; -- fails ...@@ -1760,13 +1760,100 @@ ALTER TYPE test_type1 ALTER ATTRIBUTE b TYPE varchar; -- fails
ERROR: cannot alter type "test_type1" because column "test_tbl1"."y" uses it ERROR: cannot alter type "test_type1" because column "test_tbl1"."y" uses it
CREATE TYPE test_type2 AS (a int, b text); CREATE TYPE test_type2 AS (a int, b text);
CREATE TABLE test_tbl2 OF test_type2; CREATE TABLE test_tbl2 OF test_type2;
\d test_type2
Composite type "public.test_type2"
Column | Type
--------+---------
a | integer
b | text
\d test_tbl2
Table "public.test_tbl2"
Column | Type | Modifiers
--------+---------+-----------
a | integer |
b | text |
Typed table of type: test_type2
ALTER TYPE test_type2 ADD ATTRIBUTE c text; -- fails ALTER TYPE test_type2 ADD ATTRIBUTE c text; -- fails
ERROR: cannot alter type "test_type2" because it is the type of a typed table ERROR: cannot alter type "test_type2" because it is the type of a typed table
HINT: Use ALTER ... CASCADE to alter the typed tables too.
ALTER TYPE test_type2 ADD ATTRIBUTE c text CASCADE;
\d test_type2
Composite type "public.test_type2"
Column | Type
--------+---------
a | integer
b | text
c | text
\d test_tbl2
Table "public.test_tbl2"
Column | Type | Modifiers
--------+---------+-----------
a | integer |
b | text |
c | text |
Typed table of type: test_type2
ALTER TYPE test_type2 ALTER ATTRIBUTE b TYPE varchar; -- fails 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 ERROR: cannot alter type "test_type2" because it is the type of a typed table
HINT: Use ALTER ... CASCADE to alter the typed tables too.
ALTER TYPE test_type2 ALTER ATTRIBUTE b TYPE varchar CASCADE;
\d test_type2
Composite type "public.test_type2"
Column | Type
--------+-------------------
a | integer
b | character varying
c | text
\d test_tbl2
Table "public.test_tbl2"
Column | Type | Modifiers
--------+-------------------+-----------
a | integer |
b | character varying |
c | text |
Typed table of type: test_type2
ALTER TYPE test_type2 DROP ATTRIBUTE b; -- fails ALTER TYPE test_type2 DROP ATTRIBUTE b; -- fails
ERROR: cannot alter type "test_type2" because it is the type of a typed table 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 HINT: Use ALTER ... CASCADE to alter the typed tables too.
ALTER TYPE test_type2 DROP ATTRIBUTE b CASCADE;
\d test_type2
Composite type "public.test_type2"
Column | Type
--------+---------
a | integer
c | text
\d test_tbl2
Table "public.test_tbl2"
Column | Type | Modifiers
--------+---------+-----------
a | integer |
c | text |
Typed table of type: test_type2
ALTER TYPE test_type2 RENAME ATTRIBUTE a TO aa; -- fails
ERROR: cannot alter type "test_type2" because it is the type of a typed table ERROR: cannot alter type "test_type2" because it is the type of a typed table
HINT: Use ALTER ... CASCADE to alter the typed tables too.
ALTER TYPE test_type2 RENAME ATTRIBUTE a TO aa CASCADE;
\d test_type2
Composite type "public.test_type2"
Column | Type
--------+---------
aa | integer
c | text
\d test_tbl2
Table "public.test_tbl2"
Column | Type | Modifiers
--------+---------+-----------
aa | integer |
c | text |
Typed table of type: test_type2
CREATE TYPE test_type_empty AS (); CREATE TYPE test_type_empty AS ();
DROP TYPE test_type_empty; DROP TYPE test_type_empty;
...@@ -1272,10 +1272,28 @@ ALTER TYPE test_type1 ALTER ATTRIBUTE b TYPE varchar; -- fails ...@@ -1272,10 +1272,28 @@ ALTER TYPE test_type1 ALTER ATTRIBUTE b TYPE varchar; -- fails
CREATE TYPE test_type2 AS (a int, b text); CREATE TYPE test_type2 AS (a int, b text);
CREATE TABLE test_tbl2 OF test_type2; CREATE TABLE test_tbl2 OF test_type2;
\d test_type2
\d test_tbl2
ALTER TYPE test_type2 ADD ATTRIBUTE c text; -- fails ALTER TYPE test_type2 ADD ATTRIBUTE c text; -- fails
ALTER TYPE test_type2 ADD ATTRIBUTE c text CASCADE;
\d test_type2
\d test_tbl2
ALTER TYPE test_type2 ALTER ATTRIBUTE b TYPE varchar; -- fails ALTER TYPE test_type2 ALTER ATTRIBUTE b TYPE varchar; -- fails
ALTER TYPE test_type2 ALTER ATTRIBUTE b TYPE varchar CASCADE;
\d test_type2
\d test_tbl2
ALTER TYPE test_type2 DROP ATTRIBUTE b; -- fails ALTER TYPE test_type2 DROP ATTRIBUTE b; -- fails
ALTER TYPE test_type2 RENAME ATTRIBUTE b TO bb; -- fails ALTER TYPE test_type2 DROP ATTRIBUTE b CASCADE;
\d test_type2
\d test_tbl2
ALTER TYPE test_type2 RENAME ATTRIBUTE a TO aa; -- fails
ALTER TYPE test_type2 RENAME ATTRIBUTE a TO aa CASCADE;
\d test_type2
\d test_tbl2
CREATE TYPE test_type_empty AS (); CREATE TYPE test_type_empty AS ();
DROP TYPE test_type_empty; 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