Added the ability to specify IF EXISTS when renaming a column of an object
(table, view, etc.).
For example: ALTER TABLE distributors RENAME COLUMN IF EXISTS address TO
city;
If the column does not exist, a notice is issued instead of throwing an
error.
From 32bd8ced5dcb923575e1311e7353399b04c245fa Mon Sep 17 00:00:00 2001
From: David Oksman <[email protected]>
Date: Mon, 22 Mar 2021 21:22:00 +0200
Subject: [PATCH] rename column if exists
---
doc/src/sgml/ref/alter_foreign_table.sgml | 2 +-
doc/src/sgml/ref/alter_materialized_view.sgml | 2 +-
doc/src/sgml/ref/alter_table.sgml | 4 +-
doc/src/sgml/ref/alter_type.sgml | 7 +-
doc/src/sgml/ref/alter_view.sgml | 2 +-
src/backend/commands/tablecmds.c | 80 ++++++++-----
src/backend/nodes/copyfuncs.c | 1 +
src/backend/nodes/equalfuncs.c | 1 +
src/backend/parser/gram.y | 109 ++++++++++++++++++
src/include/nodes/parsenodes.h | 1 +
src/test/regress/expected/alter_table.out | 12 ++
src/test/regress/expected/foreign_data.out | 2 +
src/test/regress/sql/alter_table.sql | 11 ++
src/test/regress/sql/foreign_data.sql | 1 +
14 files changed, 196 insertions(+), 39 deletions(-)
diff --git a/doc/src/sgml/ref/alter_foreign_table.sgml b/doc/src/sgml/ref/alter_foreign_table.sgml
index 7ca03f3..e0f3761 100644
--- a/doc/src/sgml/ref/alter_foreign_table.sgml
+++ b/doc/src/sgml/ref/alter_foreign_table.sgml
@@ -24,7 +24,7 @@ PostgreSQL documentation
ALTER FOREIGN TABLE [ IF EXISTS ] [ ONLY ] <replaceable class="parameter">name</replaceable> [ * ]
<replaceable class="parameter">action</replaceable> [, ... ]
ALTER FOREIGN TABLE [ IF EXISTS ] [ ONLY ] <replaceable class="parameter">name</replaceable> [ * ]
- RENAME [ COLUMN ] <replaceable class="parameter">column_name</replaceable> TO <replaceable class="parameter">new_column_name</replaceable>
+ RENAME [ COLUMN ] [ IF EXISTS ] <replaceable class="parameter">column_name</replaceable> TO <replaceable class="parameter">new_column_name</replaceable>
ALTER FOREIGN TABLE [ IF EXISTS ] <replaceable class="parameter">name</replaceable>
RENAME TO <replaceable class="parameter">new_name</replaceable>
ALTER FOREIGN TABLE [ IF EXISTS ] <replaceable class="parameter">name</replaceable>
diff --git a/doc/src/sgml/ref/alter_materialized_view.sgml b/doc/src/sgml/ref/alter_materialized_view.sgml
index 27f60f6..8f9ce5c 100644
--- a/doc/src/sgml/ref/alter_materialized_view.sgml
+++ b/doc/src/sgml/ref/alter_materialized_view.sgml
@@ -26,7 +26,7 @@ ALTER MATERIALIZED VIEW [ IF EXISTS ] <replaceable class="parameter">name</repla
ALTER MATERIALIZED VIEW <replaceable class="parameter">name</replaceable>
[ NO ] DEPENDS ON EXTENSION <replaceable class="parameter">extension_name</replaceable>
ALTER MATERIALIZED VIEW [ IF EXISTS ] <replaceable class="parameter">name</replaceable>
- RENAME [ COLUMN ] <replaceable class="parameter">column_name</replaceable> TO <replaceable class="parameter">new_column_name</replaceable>
+ RENAME [ COLUMN ] [ IF EXISTS ] <replaceable class="parameter">column_name</replaceable> TO <replaceable class="parameter">new_column_name</replaceable>
ALTER MATERIALIZED VIEW [ IF EXISTS ] <replaceable class="parameter">name</replaceable>
RENAME TO <replaceable class="parameter">new_name</replaceable>
ALTER MATERIALIZED VIEW [ IF EXISTS ] <replaceable class="parameter">name</replaceable>
diff --git a/doc/src/sgml/ref/alter_table.sgml b/doc/src/sgml/ref/alter_table.sgml
index 80a8efa..fb2c7a7 100644
--- a/doc/src/sgml/ref/alter_table.sgml
+++ b/doc/src/sgml/ref/alter_table.sgml
@@ -24,7 +24,7 @@ PostgreSQL documentation
ALTER TABLE [ IF EXISTS ] [ ONLY ] <replaceable class="parameter">name</replaceable> [ * ]
<replaceable class="parameter">action</replaceable> [, ... ]
ALTER TABLE [ IF EXISTS ] [ ONLY ] <replaceable class="parameter">name</replaceable> [ * ]
- RENAME [ COLUMN ] <replaceable class="parameter">column_name</replaceable> TO <replaceable class="parameter">new_column_name</replaceable>
+ RENAME [ COLUMN ] [ IF EXISTS ] <replaceable class="parameter">column_name</replaceable> TO <replaceable class="parameter">new_column_name</replaceable>
ALTER TABLE [ IF EXISTS ] [ ONLY ] <replaceable class="parameter">name</replaceable> [ * ]
RENAME CONSTRAINT <replaceable class="parameter">constraint_name</replaceable> TO <replaceable class="parameter">new_constraint_name</replaceable>
ALTER TABLE [ IF EXISTS ] <replaceable class="parameter">name</replaceable>
@@ -1008,7 +1008,7 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
<term><literal>IF EXISTS</literal></term>
<listitem>
<para>
- Do not throw an error if the table does not exist. A notice is issued
+ Do not throw an error if the table or the column does not exist. A notice is issued
in this case.
</para>
</listitem>
diff --git a/doc/src/sgml/ref/alter_type.sgml b/doc/src/sgml/ref/alter_type.sgml
index 21887e8..2513c73 100644
--- a/doc/src/sgml/ref/alter_type.sgml
+++ b/doc/src/sgml/ref/alter_type.sgml
@@ -26,7 +26,7 @@ PostgreSQL documentation
ALTER TYPE <replaceable class="parameter">name</replaceable> OWNER TO { <replaceable class="parameter">new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
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> RENAME ATTRIBUTE <replaceable class="parameter">attribute_name</replaceable> TO <replaceable class="parameter">new_attribute_name</replaceable> [ CASCADE | RESTRICT ]
+ALTER TYPE <replaceable class="parameter">name</replaceable> RENAME ATTRIBUTE [ IF EXISTS ] <replaceable class="parameter">attribute_name</replaceable> TO <replaceable class="parameter">new_attribute_name</replaceable> [ CASCADE | RESTRICT ]
ALTER TYPE <replaceable class="parameter">name</replaceable> <replaceable class="parameter">action</replaceable> [, ... ]
ALTER TYPE <replaceable class="parameter">name</replaceable> ADD VALUE [ IF NOT EXISTS ] <replaceable class="parameter">new_enum_value</replaceable> [ { BEFORE | AFTER } <replaceable class="parameter">neighbor_enum_value</replaceable> ]
ALTER TYPE <replaceable class="parameter">name</replaceable> RENAME VALUE <replaceable class="parameter">existing_enum_value</replaceable> TO <replaceable class="parameter">new_enum_value</replaceable>
@@ -76,11 +76,14 @@ ALTER TYPE <replaceable class="parameter">name</replaceable> SET ( <replaceable
</varlistentry>
<varlistentry>
- <term><literal>RENAME ATTRIBUTE</literal></term>
+ <term><literal>RENAME ATTRIBUTE [ IF EXISTS ]</literal></term>
<listitem>
<para>
This form is only usable with composite types.
It changes the name of an individual attribute of the 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>
diff --git a/doc/src/sgml/ref/alter_view.sgml b/doc/src/sgml/ref/alter_view.sgml
index 98c312c..9dc3f5e 100644
--- a/doc/src/sgml/ref/alter_view.sgml
+++ b/doc/src/sgml/ref/alter_view.sgml
@@ -24,7 +24,7 @@ PostgreSQL documentation
ALTER VIEW [ IF EXISTS ] <replaceable class="parameter">name</replaceable> ALTER [ COLUMN ] <replaceable class="parameter">column_name</replaceable> SET DEFAULT <replaceable class="parameter">expression</replaceable>
ALTER VIEW [ IF EXISTS ] <replaceable class="parameter">name</replaceable> ALTER [ COLUMN ] <replaceable class="parameter">column_name</replaceable> DROP DEFAULT
ALTER VIEW [ IF EXISTS ] <replaceable class="parameter">name</replaceable> OWNER TO { <replaceable class="parameter">new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
-ALTER VIEW [ IF EXISTS ] <replaceable class="parameter">name</replaceable> RENAME [ COLUMN ] <replaceable class="parameter">column_name</replaceable> TO <replaceable class="parameter">new_column_name</replaceable>
+ALTER VIEW [ IF EXISTS ] <replaceable class="parameter">name</replaceable> RENAME [ COLUMN ] [ IF EXISTS ] <replaceable class="parameter">column_name</replaceable> TO <replaceable class="parameter">new_column_name</replaceable>
ALTER VIEW [ IF EXISTS ] <replaceable class="parameter">name</replaceable> RENAME TO <replaceable class="parameter">new_name</replaceable>
ALTER VIEW [ IF EXISTS ] <replaceable class="parameter">name</replaceable> SET SCHEMA <replaceable class="parameter">new_schema</replaceable>
ALTER VIEW [ IF EXISTS ] <replaceable class="parameter">name</replaceable> SET ( <replaceable class="parameter">view_option_name</replaceable> [= <replaceable class="parameter">view_option_value</replaceable>] [, ... ] )
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 22f3c5e..19e7529 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -3338,45 +3338,45 @@ renameatt_internal(Oid myrelid,
atttup = SearchSysCacheCopyAttName(myrelid, oldattname);
if (!HeapTupleIsValid(atttup))
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_COLUMN),
- errmsg("column \"%s\" does not exist",
- oldattname)));
- attform = (Form_pg_attribute) GETSTRUCT(atttup);
+ attnum = InvalidAttrNumber;
+ else
+ {
+ attform = (Form_pg_attribute) GETSTRUCT(atttup);
- attnum = attform->attnum;
- if (attnum <= 0)
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("cannot rename system column \"%s\"",
- oldattname)));
+ attnum = attform->attnum;
+ if (attnum <= 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot rename system column \"%s\"",
+ oldattname)));
- /*
- * if the attribute is inherited, forbid the renaming. if this is a
- * top-level call to renameatt(), then expected_parents will be 0, so the
- * effect of this code will be to prohibit the renaming if the attribute
- * is inherited at all. if this is a recursive call to renameatt(),
- * expected_parents will be the number of parents the current relation has
- * within the inheritance hierarchy being processed, so we'll prohibit the
- * renaming only if there are additional parents from elsewhere.
- */
- if (attform->attinhcount > expected_parents)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
- errmsg("cannot rename inherited column \"%s\"",
- oldattname)));
+ /*
+ * if the attribute is inherited, forbid the renaming. if this is a
+ * top-level call to renameatt(), then expected_parents will be 0, so the
+ * effect of this code will be to prohibit the renaming if the attribute
+ * is inherited at all. if this is a recursive call to renameatt(),
+ * expected_parents will be the number of parents the current relation has
+ * within the inheritance hierarchy being processed, so we'll prohibit the
+ * renaming only if there are additional parents from elsewhere.
+ */
+ if (attform->attinhcount > expected_parents)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ errmsg("cannot rename inherited column \"%s\"",
+ oldattname)));
- /* new name should not already exist */
- (void) check_for_column_name_collision(targetrelation, newattname, false);
+ /* new name should not already exist */
+ (void) check_for_column_name_collision(targetrelation, newattname, false);
- /* apply the update */
- namestrcpy(&(attform->attname), newattname);
+ /* apply the update */
+ namestrcpy(&(attform->attname), newattname);
- CatalogTupleUpdate(attrelation, &atttup->t_self, atttup);
+ CatalogTupleUpdate(attrelation, &atttup->t_self, atttup);
- InvokeObjectPostAlterHook(RelationRelationId, myrelid, attnum);
+ InvokeObjectPostAlterHook(RelationRelationId, myrelid, attnum);
- heap_freetuple(atttup);
+ heap_freetuple(atttup);
+ }
table_close(attrelation, RowExclusiveLock);
@@ -3438,6 +3438,22 @@ renameatt(RenameStmt *stmt)
0, /* expected inhcount */
stmt->behavior);
+ if (attnum == InvalidAttrNumber)
+ {
+ if (!stmt->sub_missing_ok)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_COLUMN),
+ errmsg("column \"%s\" does not exist",
+ stmt->subname)));
+ else
+ {
+ ereport(NOTICE,
+ (errmsg("column \"%s\" does not exist, skipping",
+ stmt->subname)));
+ return InvalidObjectAddress;
+ }
+ }
+
ObjectAddressSubSet(address, RelationRelationId, relid, attnum);
return address;
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 2c20541..acc5c9e 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -3693,6 +3693,7 @@ _copyRenameStmt(const RenameStmt *from)
COPY_STRING_FIELD(newname);
COPY_SCALAR_FIELD(behavior);
COPY_SCALAR_FIELD(missing_ok);
+ COPY_SCALAR_FIELD(sub_missing_ok);
return newnode;
}
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 3e980c4..ae8ab4d 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -1449,6 +1449,7 @@ _equalRenameStmt(const RenameStmt *a, const RenameStmt *b)
COMPARE_STRING_FIELD(newname);
COMPARE_SCALAR_FIELD(behavior);
COMPARE_SCALAR_FIELD(missing_ok);
+ COMPARE_SCALAR_FIELD(sub_missing_ok);
return true;
}
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index bc43641..dd75fac 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -8697,6 +8697,18 @@ RenameStmt: ALTER AGGREGATE aggregate_with_argtypes RENAME TO name
n->missing_ok = false;
$$ = (Node *)n;
}
+ | ALTER TABLE relation_expr RENAME opt_column IF_P EXISTS name TO name
+ {
+ RenameStmt *n = makeNode(RenameStmt);
+ n->renameType = OBJECT_COLUMN;
+ n->relationType = OBJECT_TABLE;
+ n->relation = $3;
+ n->subname = $8;
+ n->newname = $10;
+ n->missing_ok = false;
+ n->sub_missing_ok = true;
+ $$ = (Node *)n;
+ }
| ALTER TABLE IF_P EXISTS relation_expr RENAME opt_column name TO name
{
RenameStmt *n = makeNode(RenameStmt);
@@ -8708,6 +8720,18 @@ RenameStmt: ALTER AGGREGATE aggregate_with_argtypes RENAME TO name
n->missing_ok = true;
$$ = (Node *)n;
}
+ | ALTER TABLE IF_P EXISTS relation_expr RENAME opt_column IF_P EXISTS name TO name
+ {
+ RenameStmt *n = makeNode(RenameStmt);
+ n->renameType = OBJECT_COLUMN;
+ n->relationType = OBJECT_TABLE;
+ n->relation = $5;
+ n->subname = $10;
+ n->newname = $12;
+ n->missing_ok = true;
+ n->sub_missing_ok = true;
+ $$ = (Node *)n;
+ }
| ALTER VIEW qualified_name RENAME opt_column name TO name
{
RenameStmt *n = makeNode(RenameStmt);
@@ -8719,6 +8743,18 @@ RenameStmt: ALTER AGGREGATE aggregate_with_argtypes RENAME TO name
n->missing_ok = false;
$$ = (Node *)n;
}
+ | ALTER VIEW qualified_name RENAME opt_column IF_P EXISTS name TO name
+ {
+ RenameStmt *n = makeNode(RenameStmt);
+ n->renameType = OBJECT_COLUMN;
+ n->relationType = OBJECT_VIEW;
+ n->relation = $3;
+ n->subname = $8;
+ n->newname = $10;
+ n->missing_ok = false;
+ n->sub_missing_ok = true;
+ $$ = (Node *)n;
+ }
| ALTER VIEW IF_P EXISTS qualified_name RENAME opt_column name TO name
{
RenameStmt *n = makeNode(RenameStmt);
@@ -8730,6 +8766,18 @@ RenameStmt: ALTER AGGREGATE aggregate_with_argtypes RENAME TO name
n->missing_ok = true;
$$ = (Node *)n;
}
+ | ALTER VIEW IF_P EXISTS qualified_name RENAME opt_column IF_P EXISTS name TO name
+ {
+ RenameStmt *n = makeNode(RenameStmt);
+ n->renameType = OBJECT_COLUMN;
+ n->relationType = OBJECT_VIEW;
+ n->relation = $5;
+ n->subname = $10;
+ n->newname = $12;
+ n->missing_ok = true;
+ n->sub_missing_ok = true;
+ $$ = (Node *)n;
+ }
| ALTER MATERIALIZED VIEW qualified_name RENAME opt_column name TO name
{
RenameStmt *n = makeNode(RenameStmt);
@@ -8741,6 +8789,18 @@ RenameStmt: ALTER AGGREGATE aggregate_with_argtypes RENAME TO name
n->missing_ok = false;
$$ = (Node *)n;
}
+ | ALTER MATERIALIZED VIEW qualified_name RENAME opt_column IF_P EXISTS name TO name
+ {
+ RenameStmt *n = makeNode(RenameStmt);
+ n->renameType = OBJECT_COLUMN;
+ n->relationType = OBJECT_MATVIEW;
+ n->relation = $4;
+ n->subname = $9;
+ n->newname = $11;
+ n->missing_ok = false;
+ n->sub_missing_ok = true;
+ $$ = (Node *)n;
+ }
| ALTER MATERIALIZED VIEW IF_P EXISTS qualified_name RENAME opt_column name TO name
{
RenameStmt *n = makeNode(RenameStmt);
@@ -8752,6 +8812,18 @@ RenameStmt: ALTER AGGREGATE aggregate_with_argtypes RENAME TO name
n->missing_ok = true;
$$ = (Node *)n;
}
+ | ALTER MATERIALIZED VIEW IF_P EXISTS qualified_name RENAME opt_column IF_P EXISTS name TO name
+ {
+ RenameStmt *n = makeNode(RenameStmt);
+ n->renameType = OBJECT_COLUMN;
+ n->relationType = OBJECT_MATVIEW;
+ n->relation = $6;
+ n->subname = $11;
+ n->newname = $13;
+ n->missing_ok = true;
+ n->sub_missing_ok = true;
+ $$ = (Node *)n;
+ }
| ALTER TABLE relation_expr RENAME CONSTRAINT name TO name
{
RenameStmt *n = makeNode(RenameStmt);
@@ -8783,6 +8855,18 @@ RenameStmt: ALTER AGGREGATE aggregate_with_argtypes RENAME TO name
n->missing_ok = false;
$$ = (Node *)n;
}
+ | ALTER FOREIGN TABLE relation_expr RENAME opt_column IF_P EXISTS name TO name
+ {
+ RenameStmt *n = makeNode(RenameStmt);
+ n->renameType = OBJECT_COLUMN;
+ n->relationType = OBJECT_FOREIGN_TABLE;
+ n->relation = $4;
+ n->subname = $9;
+ n->newname = $11;
+ n->missing_ok = false;
+ n->sub_missing_ok = true;
+ $$ = (Node *)n;
+ }
| ALTER FOREIGN TABLE IF_P EXISTS relation_expr RENAME opt_column name TO name
{
RenameStmt *n = makeNode(RenameStmt);
@@ -8794,6 +8878,18 @@ RenameStmt: ALTER AGGREGATE aggregate_with_argtypes RENAME TO name
n->missing_ok = true;
$$ = (Node *)n;
}
+ | ALTER FOREIGN TABLE IF_P EXISTS relation_expr RENAME opt_column IF_P EXISTS name TO name
+ {
+ RenameStmt *n = makeNode(RenameStmt);
+ n->renameType = OBJECT_COLUMN;
+ n->relationType = OBJECT_FOREIGN_TABLE;
+ n->relation = $6;
+ n->subname = $11;
+ n->newname = $13;
+ n->missing_ok = true;
+ n->sub_missing_ok = true;
+ $$ = (Node *)n;
+ }
| ALTER RULE name ON qualified_name RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
@@ -8915,6 +9011,19 @@ RenameStmt: ALTER AGGREGATE aggregate_with_argtypes RENAME TO name
n->missing_ok = false;
$$ = (Node *)n;
}
+ | ALTER TYPE_P any_name RENAME ATTRIBUTE IF_P EXISTS name TO name opt_drop_behavior
+ {
+ RenameStmt *n = makeNode(RenameStmt);
+ n->renameType = OBJECT_ATTRIBUTE;
+ n->relationType = OBJECT_TYPE;
+ n->relation = makeRangeVarFromAnyName($3, @3, yyscanner);
+ n->subname = $8;
+ n->newname = $10;
+ n->behavior = $11;
+ n->missing_ok = false;
+ n->sub_missing_ok = true;
+ $$ = (Node *)n;
+ }
;
opt_column: COLUMN
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 68425eb..2f1c142 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -2980,6 +2980,7 @@ typedef struct RenameStmt
char *newname; /* the new name */
DropBehavior behavior; /* RESTRICT or CASCADE behavior */
bool missing_ok; /* skip error if missing? */
+ bool sub_missing_ok; /* skip error if contained object missing? */
} RenameStmt;
/* ----------------------
diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out
index bb3f873..fc94c57 100644
--- a/src/test/regress/expected/alter_table.out
+++ b/src/test/regress/expected/alter_table.out
@@ -1736,6 +1736,15 @@ alter table dropColumnExists drop column non_existing; --fail
ERROR: column "non_existing" of relation "dropcolumnexists" does not exist
alter table dropColumnExists drop column if exists non_existing; --succeed
NOTICE: column "non_existing" of relation "dropcolumnexists" does not exist, skipping
+-- rename column if exists
+create table renameColumnExists ();
+alter table renameColumnExists rename column c1 to c2; -- fails
+ERROR: column "c1" does not exist
+alter table renameColumnExists rename column if exists c1 to c2; -- succeeds
+NOTICE: column "c1" does not exist, skipping
+alter table renameColumnExists add column c1 int;
+alter table renameColumnExists rename column if exists c1 to c2; -- succeeds
+drop table renameColumnExists;
select relname, attname, attinhcount, attislocal
from pg_class join pg_attribute on (pg_class.oid = pg_attribute.attrelid)
where relname in ('p1','p2','c1','gc1') and attnum > 0 and not attisdropped
@@ -2981,6 +2990,9 @@ ALTER TYPE test_type RENAME ATTRIBUTE d TO dd;
--------+---------+-----------+----------+---------
dd | boolean | | |
+ALTER TYPE test_type RENAME ATTRIBUTE IF EXISTS d TO dd;
+NOTICE: column "d" does not exist, skipping
+ALTER TYPE test_type RENAME ATTRIBUTE IF EXISTS dd TO d;
DROP TYPE test_type;
CREATE TYPE test_type1 AS (a int, b text);
CREATE TABLE test_tbl1 (x int, y test_type1);
diff --git a/src/test/regress/expected/foreign_data.out b/src/test/regress/expected/foreign_data.out
index e4cdb78..1f75e51 100644
--- a/src/test/regress/expected/foreign_data.out
+++ b/src/test/regress/expected/foreign_data.out
@@ -880,6 +880,8 @@ ALTER FOREIGN TABLE ft1 DROP COLUMN c9;
ALTER FOREIGN TABLE ft1 SET SCHEMA foreign_schema;
ALTER FOREIGN TABLE ft1 SET TABLESPACE ts; -- ERROR
ERROR: relation "ft1" does not exist
+ALTER FOREIGN TABLE foreign_schema.ft1 RENAME IF EXISTS no_column TO foreign_column_1;
+NOTICE: column "no_column" does not exist, skipping
ALTER FOREIGN TABLE foreign_schema.ft1 RENAME c1 TO foreign_column_1;
ALTER FOREIGN TABLE foreign_schema.ft1 RENAME TO foreign_table_1;
\d foreign_schema.foreign_table_1
diff --git a/src/test/regress/sql/alter_table.sql b/src/test/regress/sql/alter_table.sql
index 4cc55d8..41b2252 100644
--- a/src/test/regress/sql/alter_table.sql
+++ b/src/test/regress/sql/alter_table.sql
@@ -1240,6 +1240,14 @@ create table dropColumnExists ();
alter table dropColumnExists drop column non_existing; --fail
alter table dropColumnExists drop column if exists non_existing; --succeed
+-- rename column if exists
+create table renameColumnExists ();
+alter table renameColumnExists rename column c1 to c2; -- fails
+alter table renameColumnExists rename column if exists c1 to c2; -- succeeds
+alter table renameColumnExists add column c1 int;
+alter table renameColumnExists rename column if exists c1 to c2; -- succeeds
+drop table renameColumnExists;
+
select relname, attname, attinhcount, attislocal
from pg_class join pg_attribute on (pg_class.oid = pg_attribute.attrelid)
where relname in ('p1','p2','c1','gc1') and attnum > 0 and not attisdropped
@@ -1911,6 +1919,9 @@ ALTER TYPE test_type RENAME ATTRIBUTE a TO aa;
ALTER TYPE test_type RENAME ATTRIBUTE d TO dd;
\d test_type
+ALTER TYPE test_type RENAME ATTRIBUTE IF EXISTS d TO dd;
+ALTER TYPE test_type RENAME ATTRIBUTE IF EXISTS dd TO d;
+
DROP TYPE test_type;
CREATE TYPE test_type1 AS (a int, b text);
diff --git a/src/test/regress/sql/foreign_data.sql b/src/test/regress/sql/foreign_data.sql
index 73f9f62..7e1258f 100644
--- a/src/test/regress/sql/foreign_data.sql
+++ b/src/test/regress/sql/foreign_data.sql
@@ -408,6 +408,7 @@ ALTER FOREIGN TABLE ft1 DROP COLUMN IF EXISTS no_column;
ALTER FOREIGN TABLE ft1 DROP COLUMN c9;
ALTER FOREIGN TABLE ft1 SET SCHEMA foreign_schema;
ALTER FOREIGN TABLE ft1 SET TABLESPACE ts; -- ERROR
+ALTER FOREIGN TABLE foreign_schema.ft1 RENAME IF EXISTS no_column TO foreign_column_1;
ALTER FOREIGN TABLE foreign_schema.ft1 RENAME c1 TO foreign_column_1;
ALTER FOREIGN TABLE foreign_schema.ft1 RENAME TO foreign_table_1;
\d foreign_schema.foreign_table_1
--
2.31.0