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 <oksman....@gmail.com>
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

Reply via email to