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,29 **** PostgreSQL documentation --- 24,30 ---- 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,70 **** ALTER VIEW [ IF EXISTS ] name RESET --- 66,89 ---- + + 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.index bea890f177..1b4d66dcd9 100644 *** a/src/backend/commands/view.c --- b/src/backend/commands/view.c *************** *** 277,283 **** 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)))); /* XXX would it be safe to allow atttypmod to change? Not sure */ if (newattr->atttypid != oldattr->atttypid || newattr->atttypmod != oldattr->atttypmod) --- 277,284 ---- (errcode(ERRCODE_INVALID_TABLE_DEFINITION), errmsg("cannot change name of view column \"%s\" to \"%s\"", NameStr(oldattr->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/grindex 3f67aaf30e..18e4d7636a 100644 *** a/src/backend/parser/gram.y --- b/src/backend/parser/gram.y *************** *** 8775,8780 **** RenameStmt: ALTER AGGREGATE aggregate_with_argtypes RENAME TO name --- 8775,8802 ---- 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-coindex 2b1e3cda4a..2837939e93 100644 *** a/src/bin/psql/tab-complete.c --- b/src/bin/psql/tab-complete.c *************** *** 1797,1804 **** 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", "SET SCHEMA"); /* ALTER MATERIALIZED VIEW */ else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny)) COMPLETE_WITH("ALTER COLUMN", "OWNER TO", "RENAME TO", --- 1797,1816 ---- COMPLETE_WITH("TO"); /* ALTER VIEW */ else if (Matches("ALTER", "VIEW", MatchAny)) ! 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", "OWNER TO", "RENAME TO", diff --git a/src/test/regress/expeindex 2fd36ca9a1..9a92629fd7 100644 *** a/src/test/regress/expected/create_view.out --- b/src/test/regress/expected/create_view.out *************** *** 64,69 **** ERROR: cannot drop columns from view --- 64,70 ---- 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,1194 **** select pg_get_viewdef('vv1', true); --- 1190,1218 ---- 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,1788 **** 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 DETAIL: drop cascades to table t1 drop cascades to view temporal1 drop cascades to view temporal2 --- 1806,1812 ---- drop cascades to view aliased_view_3 drop cascades to view aliased_view_4 DROP SCHEMA testviewschm2 CASCADE; ! NOTICE: drop cascades to 64 other objects DETAIL: drop cascades to table t1 drop cascades to view temporal1 drop cascades to view temporal2 *************** *** 1818,1823 **** drop cascades to view v3 --- 1842,1848 ---- 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.sqindex 8c0f45cc52..be5d90727a 100644 *** a/src/test/regress/sql/create_view.sql --- b/src/test/regress/sql/create_view.sql *************** *** 391,396 **** select pg_get_viewdef('vv1', true); --- 391,402 ---- 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);