Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 5397759

Browse files
committed
Disallow ALTER TABLE ONLY / DROP EXPRESSION
The current implementation cannot handle this correctly, so just forbid it for now. GENERATED clauses must be attached to the column definition and cannot be added later like DEFAULT, so if a child table has a generation expression that the parent does not have, the child column will necessarily be an attlocal column. So to implement ALTER TABLE ONLY / DROP EXPRESSION, we'd need extra code to update attislocal of the direct child tables, somewhat similar to how DROP COLUMN does it, so that the resulting state can be properly dumped and restored. Discussion: https://www.postgresql.org/message-id/flat/15830.1575468847%40sss.pgh.pa.us
1 parent a58a631 commit 5397759

File tree

3 files changed

+26
-9
lines changed

3 files changed

+26
-9
lines changed

src/backend/commands/tablecmds.c

+19-3
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ static ObjectAddress ATExecAddIdentity(Relation rel, const char *colName,
412412
static ObjectAddress ATExecSetIdentity(Relation rel, const char *colName,
413413
Node *def, LOCKMODE lockmode);
414414
static ObjectAddress ATExecDropIdentity(Relation rel, const char *colName, bool missing_ok, LOCKMODE lockmode);
415-
static void ATPrepDropExpression(Relation rel, AlterTableCmd *cmd, bool recursing);
415+
static void ATPrepDropExpression(Relation rel, AlterTableCmd *cmd, bool recurse, bool recursing, LOCKMODE lockmode);
416416
static ObjectAddress ATExecDropExpression(Relation rel, const char *colName, bool missing_ok, LOCKMODE lockmode);
417417
static ObjectAddress ATExecSetStatistics(Relation rel, const char *colName, int16 colNum,
418418
Node *newValue, LOCKMODE lockmode);
@@ -4141,7 +4141,7 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
41414141
case AT_DropExpression: /* ALTER COLUMN DROP EXPRESSION */
41424142
ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
41434143
ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context);
4144-
ATPrepDropExpression(rel, cmd, recursing);
4144+
ATPrepDropExpression(rel, cmd, recurse, recursing, lockmode);
41454145
pass = AT_PASS_DROP;
41464146
break;
41474147
case AT_SetStatistics: /* ALTER COLUMN SET STATISTICS */
@@ -7238,8 +7238,24 @@ ATExecDropIdentity(Relation rel, const char *colName, bool missing_ok, LOCKMODE
72387238
* ALTER TABLE ALTER COLUMN DROP EXPRESSION
72397239
*/
72407240
static void
7241-
ATPrepDropExpression(Relation rel, AlterTableCmd *cmd, bool recursing)
7241+
ATPrepDropExpression(Relation rel, AlterTableCmd *cmd, bool recurse, bool recursing, LOCKMODE lockmode)
72427242
{
7243+
/*
7244+
* Reject ONLY if there are child tables. We could implement this, but it
7245+
* is a bit complicated. GENERATED clauses must be attached to the column
7246+
* definition and cannot be added later like DEFAULT, so if a child table
7247+
* has a generation expression that the parent does not have, the child
7248+
* column will necessarily be an attlocal column. So to implement ONLY
7249+
* here, we'd need extra code to update attislocal of the direct child
7250+
* tables, somewhat similar to how DROP COLUMN does it, so that the
7251+
* resulting state can be properly dumped and restored.
7252+
*/
7253+
if (!recurse &&
7254+
find_inheritance_children(RelationGetRelid(rel), lockmode))
7255+
ereport(ERROR,
7256+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
7257+
errmsg("ALTER TABLE / DROP EXPRESSION must be applied to child tables too")));
7258+
72437259
/*
72447260
* Cannot drop generation expression from inherited columns.
72457261
*/

src/test/regress/expected/generated.out

+6-5
Original file line numberDiff line numberDiff line change
@@ -805,13 +805,14 @@ CREATE TABLE gtest30 (
805805
b int GENERATED ALWAYS AS (a * 2) STORED
806806
);
807807
CREATE TABLE gtest30_1 () INHERITS (gtest30);
808-
ALTER TABLE ONLY gtest30 ALTER COLUMN b DROP EXPRESSION;
808+
ALTER TABLE ONLY gtest30 ALTER COLUMN b DROP EXPRESSION; -- error
809+
ERROR: ALTER TABLE / DROP EXPRESSION must be applied to child tables too
809810
\d gtest30
810-
Table "public.gtest30"
811-
Column | Type | Collation | Nullable | Default
812-
--------+---------+-----------+----------+---------
811+
Table "public.gtest30"
812+
Column | Type | Collation | Nullable | Default
813+
--------+---------+-----------+----------+------------------------------------
813814
a | integer | | |
814-
b | integer | | |
815+
b | integer | | | generated always as (a * 2) stored
815816
Number of child tables: 1 (Use \d+ to list them.)
816817

817818
\d gtest30_1

src/test/regress/sql/generated.sql

+1-1
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ CREATE TABLE gtest30 (
411411
b int GENERATED ALWAYS AS (a * 2) STORED
412412
);
413413
CREATE TABLE gtest30_1 () INHERITS (gtest30);
414-
ALTER TABLE ONLY gtest30 ALTER COLUMN b DROP EXPRESSION;
414+
ALTER TABLE ONLY gtest30 ALTER COLUMN b DROP EXPRESSION; -- error
415415
\d gtest30
416416
\d gtest30_1
417417
ALTER TABLE gtest30_1 ALTER COLUMN b DROP EXPRESSION; -- error

0 commit comments

Comments
 (0)