diff --git a/doc/src/sgml/ref/alter_view.sgml b/doc/src/sgml/ref/alter_view.sgml
index 2e9edc1975..b66160bfb8 100644
--- a/doc/src/sgml/ref/alter_view.sgml
+++ b/doc/src/sgml/ref/alter_view.sgml
@@ -24,6 +24,7 @@ PostgreSQL documentation
ALTER VIEW [ IF EXISTS ] name ALTER [ COLUMN ] column_name SET DEFAULT expression
ALTER VIEW [ IF EXISTS ] name ALTER [ COLUMN ] column_name DROP DEFAULT
ALTER VIEW [ IF EXISTS ] name OWNER TO { new_owner | CURRENT_USER | SESSION_USER }
+ALTER VIEW [ IF EXISTS ] name RENAME [ COLUMN ] column_name TO new_column_name
ALTER VIEW [ IF EXISTS ] name RENAME TO new_name
ALTER VIEW [ IF EXISTS ] name SET SCHEMA new_schema
ALTER VIEW [ IF EXISTS ] name SET ( view_option_name [= view_option_value] [, ... ] )
@@ -65,6 +66,24 @@ ALTER VIEW [ IF EXISTS ] name RESET
+
+ column_name
+
+
+ Name of an existing column.
+
+
+
+
+
+ new_column_name
+
+
+ New name for an existing column.
+
+
+
+
IF EXISTS
diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c
index 9fa433a975..9b5148093b 100644
--- a/src/backend/commands/view.c
+++ b/src/backend/commands/view.c
@@ -276,7 +276,8 @@ checkViewTupleDesc(TupleDesc newdesc, TupleDesc olddesc)
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
errmsg("cannot change name of view column \"%s\" to \"%s\"",
NameStr(oldattr->attname),
- NameStr(newattr->attname))));
+ NameStr(newattr->attname)),
+ errhint("Use ALTER VIEW ... RENAME COLUMN ... to change name of view column instead.")));
/* XXX would it be safe to allow atttypmod to change? Not sure */
if (newattr->atttypid != oldattr->atttypid ||
newattr->atttypmod != oldattr->atttypmod)
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 2f7bd662e8..c5086846de 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -8777,6 +8777,28 @@ RenameStmt: ALTER AGGREGATE aggregate_with_argtypes RENAME TO name
n->missing_ok = true;
$$ = (Node *)n;
}
+ | ALTER VIEW qualified_name RENAME opt_column name TO name
+ {
+ RenameStmt *n = makeNode(RenameStmt);
+ n->renameType = OBJECT_COLUMN;
+ n->relationType = OBJECT_VIEW;
+ n->relation = $3;
+ n->subname = $6;
+ n->newname = $8;
+ n->missing_ok = false;
+ $$ = (Node *)n;
+ }
+ | ALTER VIEW IF_P EXISTS qualified_name RENAME opt_column name TO name
+ {
+ RenameStmt *n = makeNode(RenameStmt);
+ n->renameType = OBJECT_COLUMN;
+ n->relationType = OBJECT_VIEW;
+ n->relation = $5;
+ n->subname = $8;
+ n->newname = $10;
+ n->missing_ok = true;
+ $$ = (Node *)n;
+ }
| ALTER MATERIALIZED VIEW qualified_name RENAME opt_column name TO name
{
RenameStmt *n = makeNode(RenameStmt);
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 1578568a91..172e00b46e 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -1797,8 +1797,20 @@ psql_completion(const char *text, int start, int end)
COMPLETE_WITH("TO");
/* ALTER VIEW */
else if (Matches("ALTER", "VIEW", MatchAny))
- COMPLETE_WITH("ALTER COLUMN", "OWNER TO", "RENAME TO",
+ COMPLETE_WITH("ALTER COLUMN", "OWNER TO", "RENAME",
"SET SCHEMA");
+ /* ALTER VIEW xxx RENAME */
+ else if (Matches("ALTER", "VIEW", MatchAny, "RENAME"))
+ COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'TO'");
+ else if (Matches("ALTER", "VIEW", MatchAny, "ALTER|RENAME", "COLUMN"))
+ COMPLETE_WITH_ATTR(prev3_wd, "");
+ /* ALTER VIEW xxx RENAME yyy */
+ else if (Matches("ALTER", "VIEW", MatchAny, "RENAME", MatchAnyExcept("TO")))
+ COMPLETE_WITH("TO");
+ /* ALTER VIEW xxx RENAME COLUMN yyy */
+ else if (Matches("ALTER", "VIEW", MatchAny, "RENAME", "COLUMN", MatchAnyExcept("TO")))
+ COMPLETE_WITH("TO");
+
/* ALTER MATERIALIZED VIEW */
else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny))
COMPLETE_WITH("ALTER COLUMN", "CLUSTER ON", "DEPENDS ON EXTENSION",
diff --git a/src/test/regress/expected/create_view.out b/src/test/regress/expected/create_view.out
index 2fd36ca9a1..9a92629fd7 100644
--- a/src/test/regress/expected/create_view.out
+++ b/src/test/regress/expected/create_view.out
@@ -64,6 +64,7 @@ ERROR: cannot drop columns from view
CREATE OR REPLACE VIEW viewtest AS
SELECT 1, * FROM viewtest_tbl;
ERROR: cannot change name of view column "a" to "?column?"
+HINT: Use ALTER VIEW ... RENAME COLUMN ... to change name of view column instead.
-- should fail
CREATE OR REPLACE VIEW viewtest AS
SELECT a, b::numeric FROM viewtest_tbl;
@@ -1189,6 +1190,29 @@ select pg_get_viewdef('vv1', true);
CROSS JOIN tt6) j(aa, bb, cc_1, cc, dd);
(1 row)
+create view v4 as select * from v1;
+alter view v1 rename column a to x;
+select pg_get_viewdef('v1', true);
+ pg_get_viewdef
+---------------------------------------------------
+ SELECT tt2.b, +
+ tt3.c, +
+ tt2.a AS x, +
+ tt3.ax +
+ FROM tt2 +
+ JOIN tt3 tt3(ax, b, c, c_1, e) USING (b, c);
+(1 row)
+
+select pg_get_viewdef('v4', true);
+ pg_get_viewdef
+----------------
+ SELECT v1.b, +
+ v1.c, +
+ v1.x AS a,+
+ v1.ax +
+ FROM v1;
+(1 row)
+
-- Unnamed FULL JOIN USING is lots of fun too
create table tt7 (x int, xx int, y int);
alter table tt7 drop column xx;
@@ -1782,7 +1806,7 @@ drop cascades to view aliased_view_2
drop cascades to view aliased_view_3
drop cascades to view aliased_view_4
DROP SCHEMA testviewschm2 CASCADE;
-NOTICE: drop cascades to 63 other objects
+NOTICE: drop cascades to 64 other objects
DETAIL: drop cascades to table t1
drop cascades to view temporal1
drop cascades to view temporal2
@@ -1818,6 +1842,7 @@ drop cascades to view v3
drop cascades to table tt5
drop cascades to table tt6
drop cascades to view vv1
+drop cascades to view v4
drop cascades to table tt7
drop cascades to table tt8
drop cascades to view vv2
diff --git a/src/test/regress/sql/create_view.sql b/src/test/regress/sql/create_view.sql
index 8c0f45cc52..be5d90727a 100644
--- a/src/test/regress/sql/create_view.sql
+++ b/src/test/regress/sql/create_view.sql
@@ -391,6 +391,12 @@ select pg_get_viewdef('vv1', true);
alter table tt5 drop column c;
select pg_get_viewdef('vv1', true);
+create view v4 as select * from v1;
+alter view v1 rename column a to x;
+select pg_get_viewdef('v1', true);
+select pg_get_viewdef('v4', true);
+
+
-- Unnamed FULL JOIN USING is lots of fun too
create table tt7 (x int, xx int, y int);