Skip to content

Commit c86bcd0

Browse files
committed
add modify grammar, consider partition table, visible coulumns should be more than one
1 parent cd9a63f commit c86bcd0

File tree

7 files changed

+130
-17
lines changed

7 files changed

+130
-17
lines changed

src/backend/commands/sequence.c

-1
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,6 @@ DefineSequence(ParseState *pstate, CreateSeqStmt *seq)
162162
ColumnDef *coldef = makeNode(ColumnDef);
163163

164164
coldef->inhcount = 0;
165-
coldef->is_invisible = false;
166165
coldef->is_local = true;
167166
coldef->is_not_null = true;
168167
coldef->is_from_type = false;

src/backend/commands/tablecmds.c

+81
Original file line numberDiff line numberDiff line change
@@ -382,8 +382,10 @@ static ObjectAddress ATExecDropNotNull(Relation rel, const char *colName, LOCKMO
382382
static void ATPrepSetNotNull(Relation rel, bool recurse, bool recursing);
383383
static ObjectAddress ATExecSetNotNull(AlteredTableInfo *tab, Relation rel,
384384
const char *colName, LOCKMODE lockmode);
385+
static void ATPrepSetVisible(Relation rel, bool recurse, bool recursing);
385386
static ObjectAddress ATExecSetVisible(AlteredTableInfo *tab, Relation rel,
386387
const char *colName, LOCKMODE lockmode);
388+
static void ATPrepSetInvisible(Relation rel, bool recurse, bool recursing);
387389
static ObjectAddress ATExecSetInvisible(AlteredTableInfo *tab, Relation rel,
388390
const char *colName, LOCKMODE lockmode);
389391
static ObjectAddress ATExecColumnDefault(Relation rel, const char *colName,
@@ -560,6 +562,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
560562
static char *validnsps[] = HEAP_RELOPT_NAMESPACES;
561563
Oid ofTypeId;
562564
ObjectAddress address;
565+
int invisibleColumnCount;
563566

564567
/*
565568
* Truncate relname to appropriate length (probably a waste of time, as
@@ -744,6 +747,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
744747
rawDefaults = NIL;
745748
cookedDefaults = NIL;
746749
attnum = 0;
750+
invisibleColumnCount = 0;
747751

748752
foreach(listptr, stmt->tableElts)
749753
{
@@ -788,9 +792,20 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
788792
attr->attidentity = colDef->identity;
789793

790794
if (colDef->is_invisible)
795+
{
791796
attr->attisinvisible = colDef->is_invisible;
797+
invisibleColumnCount++;
798+
}
792799
}
793800

801+
/*
802+
* table must have at least one column that is not invisible
803+
*/
804+
if (invisibleColumnCount == attnum)
805+
ereport(ERROR,
806+
(errcode(ERRCODE_SYNTAX_ERROR),
807+
errmsg("table must have at least one column that is not invisible")));
808+
794809
/*
795810
* Create the relation. Inherited defaults and constraints are passed in
796811
* for immediate handling --- since they don't need parsing, they can be
@@ -2003,6 +2018,7 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
20032018
* merge the column options into the column from the type
20042019
*/
20052020
coldef->is_not_null = restdef->is_not_null;
2021+
coldef->is_invisible = restdef->is_invisible;
20062022
coldef->raw_default = restdef->raw_default;
20072023
coldef->cooked_default = restdef->cooked_default;
20082024
coldef->constraints = restdef->constraints;
@@ -2246,6 +2262,7 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
22462262
def->inhcount = 1;
22472263
def->is_local = false;
22482264
def->is_not_null = attribute->attnotnull;
2265+
def->is_invisible = attribute->attisinvisible;
22492266
def->is_from_type = false;
22502267
def->storage = attribute->attstorage;
22512268
def->raw_default = NULL;
@@ -3843,12 +3860,14 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
38433860
break;
38443861
case AT_SetVisible: /* ALTER COLUMN SET VISIBLE */
38453862
ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
3863+
ATPrepSetVisible(rel, recurse, recursing);
38463864
ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode);
38473865
/* No command-specific prep needed */
38483866
pass = AT_PASS_ADD_CONSTR;
38493867
break;
38503868
case AT_SetInvisible: /* ALTER COLUMN SET INVISIBLE */
38513869
ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
3870+
ATPrepSetInvisible(rel, recurse, recursing);
38523871
ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode);
38533872
/* No command-specific prep needed */
38543873
pass = AT_PASS_ADD_CONSTR;
@@ -6272,6 +6291,25 @@ ATExecSetNotNull(AlteredTableInfo *tab, Relation rel,
62726291
return address;
62736292
}
62746293

6294+
static void
6295+
ATPrepSetVisible(Relation rel, bool recurse, bool recursing)
6296+
{
6297+
/*
6298+
* If the parent is a partitioned table, Set Visible
6299+
* constraints must be added to the child tables.
6300+
*/
6301+
if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
6302+
{
6303+
PartitionDesc partdesc = RelationGetPartitionDesc(rel);
6304+
6305+
if (partdesc && partdesc->nparts > 0 && !recurse && !recursing)
6306+
ereport(ERROR,
6307+
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
6308+
errmsg("cannot add constraint to only the partitioned table when partitions exist"),
6309+
errhint("Do not specify the ONLY keyword.")));
6310+
}
6311+
}
6312+
62756313
/*
62766314
* Return the address of the modified column. If the column was already Invisible,
62776315
* InvalidObjectAddress is returned.
@@ -6328,6 +6366,25 @@ ATExecSetVisible(AlteredTableInfo *tab, Relation rel,
63286366
return address;
63296367
}
63306368

6369+
static void
6370+
ATPrepSetInvisible(Relation rel, bool recurse, bool recursing)
6371+
{
6372+
/*
6373+
* If the parent is a partitioned table, Set Invisible
6374+
* constraints must be added to the child tables.
6375+
*/
6376+
if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
6377+
{
6378+
PartitionDesc partdesc = RelationGetPartitionDesc(rel);
6379+
6380+
if (partdesc && partdesc->nparts > 0 && !recurse && !recursing)
6381+
ereport(ERROR,
6382+
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
6383+
errmsg("cannot add constraint to only the partitioned table when partitions exist"),
6384+
errhint("Do not specify the ONLY keyword.")));
6385+
}
6386+
}
6387+
63316388
/*
63326389
* Return the address of the modified column. If the column was already Invisible,
63336390
* InvalidObjectAddress is returned.
@@ -6365,6 +6422,30 @@ ATExecSetInvisible(AlteredTableInfo *tab, Relation rel,
63656422

63666423
if (!((Form_pg_attribute) GETSTRUCT(tuple))->attisinvisible)
63676424
{
6425+
TupleDesc tupleDesc = RelationGetDescr(rel);
6426+
int numattrs = tupleDesc->natts;
6427+
int i;
6428+
bool visible_only = true;
6429+
Form_pg_attribute attr;
6430+
6431+
for (i = 0; i < numattrs; ++i) {
6432+
if (i == attnum - 1) {
6433+
continue;
6434+
}
6435+
6436+
attr = TupleDescAttr(tupleDesc, i);
6437+
6438+
if (!attr->attisinvisible) {
6439+
visible_only = false;
6440+
break;
6441+
}
6442+
}
6443+
6444+
if (visible_only)
6445+
ereport(ERROR,
6446+
(errcode(ERRCODE_SYNTAX_ERROR),
6447+
errmsg("table must have at least one column that is not invisible")));
6448+
63686449
((Form_pg_attribute) GETSTRUCT(tuple))->attisinvisible = true;
63696450

63706451
CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);

src/backend/parser/gram.y

+26-12
Original file line numberDiff line numberDiff line change
@@ -666,7 +666,7 @@ static bool polar_is_ignore_user_defined_tablespace(char *tablespace_name);
666666
LEADER LEADING LEAKPROOF LEARNER LEAST LEFT LEVEL LIKE LIMIT LISTEN LOAD LOCAL
667667
LOCALTIME LOCALTIMESTAMP LOCATION LOCK_P LOCKED LOGGED LOGS
668668

669-
MAPPING MATCH MATERIALIZED MAXVALUE METHOD MINUTE_P MINVALUE MODE MONTH_P MOVE
669+
MAPPING MATCH MATERIALIZED MAXVALUE METHOD MINUTE_P MINVALUE MODE MODIFY MONTH_P MOVE
670670

671671
NAME_P NAMES NATIONAL NATURAL NCHAR NEW NEXT NO NODE NONE
672672
NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF
@@ -2201,6 +2201,22 @@ alter_table_cmd:
22012201
n->name = $3;
22022202
$$ = (Node *)n;
22032203
}
2204+
/* ALTER TABLE <name> MODIFY <colname> VISIBLE */
2205+
| MODIFY opt_column ColId VISIBLE
2206+
{
2207+
AlterTableCmd *n = makeNode(AlterTableCmd);
2208+
n->subtype = AT_SetVisible;
2209+
n->name = $3;
2210+
$$ = (Node *)n;
2211+
}
2212+
/* ALTER TABLE <name> MODIFY <colname> INVISIBLE */
2213+
| MODIFY opt_column ColId INVISIBLE
2214+
{
2215+
AlterTableCmd *n = makeNode(AlterTableCmd);
2216+
n->subtype = AT_SetInvisible;
2217+
n->name = $3;
2218+
$$ = (Node *)n;
2219+
}
22042220
/* ALTER TABLE <name> ALTER [COLUMN] <colname> RESET ( column_parameter = value [, ... ] ) */
22052221
| ALTER opt_column ColId RESET reloptions
22062222
{
@@ -3445,7 +3461,6 @@ columnDef: ColId Typename create_generic_options ColQualList
34453461
n->colname = $1;
34463462
n->typeName = $2;
34473463
n->inhcount = 0;
3448-
n->is_invisible = false;
34493464
n->is_local = true;
34503465
n->is_not_null = false;
34513466
n->is_from_type = false;
@@ -3467,7 +3482,6 @@ columnOptions: ColId ColQualList
34673482
n->colname = $1;
34683483
n->typeName = NULL;
34693484
n->inhcount = 0;
3470-
n->is_invisible = false;
34713485
n->is_local = true;
34723486
n->is_not_null = false;
34733487
n->is_from_type = false;
@@ -3486,7 +3500,6 @@ columnOptions: ColId ColQualList
34863500
n->colname = $1;
34873501
n->typeName = NULL;
34883502
n->inhcount = 0;
3489-
n->is_invisible = false;
34903503
n->is_local = true;
34913504
n->is_not_null = false;
34923505
n->is_from_type = false;
@@ -3547,7 +3560,14 @@ ColConstraint:
35473560
* or be part of a_expr NOT LIKE or similar constructs).
35483561
*/
35493562
ColConstraintElem:
3550-
NOT NULL_P
3563+
INVISIBLE
3564+
{
3565+
Constraint *n = makeNode(Constraint);
3566+
n->contype = CONSTR_INVISIBLE;
3567+
n->location = @1;
3568+
$$ = (Node *)n;
3569+
}
3570+
| NOT NULL_P
35513571
{
35523572
Constraint *n = makeNode(Constraint);
35533573
n->contype = CONSTR_NOTNULL;
@@ -3628,13 +3648,6 @@ ColConstraintElem:
36283648
n->initially_valid = true;
36293649
$$ = (Node *)n;
36303650
}
3631-
| INVISIBLE
3632-
{
3633-
Constraint *n = makeNode(Constraint);
3634-
n->contype = CONSTR_INVISIBLE;
3635-
n->location = @1;
3636-
$$ = (Node *)n;
3637-
}
36383651
;
36393652

36403653
generated_when:
@@ -15545,6 +15558,7 @@ unreserved_keyword:
1554515558
| MINUTE_P
1554615559
| MINVALUE
1554715560
| MODE
15561+
| MODIFY
1554815562
| MONTH_P
1554915563
| MOVE
1555015564
| NAME_P

src/include/parser/kwlist.h

+1
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ PG_KEYWORD("method", METHOD, UNRESERVED_KEYWORD)
261261
PG_KEYWORD("minute", MINUTE_P, UNRESERVED_KEYWORD)
262262
PG_KEYWORD("minvalue", MINVALUE, UNRESERVED_KEYWORD)
263263
PG_KEYWORD("mode", MODE, UNRESERVED_KEYWORD)
264+
PG_KEYWORD("modify", MODIFY, UNRESERVED_KEYWORD)
264265
PG_KEYWORD("month", MONTH_P, UNRESERVED_KEYWORD)
265266
PG_KEYWORD("move", MOVE, UNRESERVED_KEYWORD)
266267
PG_KEYWORD("name", NAME_P, UNRESERVED_KEYWORD)

src/test/regress/expected/invisible.out

+7-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ CREATE TABLE TEST_INVISIBLE_TBL3(
1414
a INT INVISIBLE,
1515
b INT
1616
);
17+
create TABLE TEST_INVISIBLE_TBL4(
18+
a int INVISIBLE
19+
);
20+
ERROR: table must have at least one column that is not invisible
1721
INSERT INTO TEST_INVISIBLE_TBL1 VALUES (1, 1, 'A');
1822
ERROR: INSERT has more expressions than target columns
1923
LINE 1: INSERT INTO TEST_INVISIBLE_TBL1 VALUES (1, 1, 'A');
@@ -85,7 +89,9 @@ SELECT * FROM TEST_INVISIBLE_TBL1;
8589
B
8690
(2 rows)
8791

88-
ALTER TABLE TEST_INVISIBLE_TBL1 ALTER COLUMN a SET VISIBLE;
92+
ALTER TABLE TEST_INVISIBLE_TBL1 ALTER COLUMN a SET INVISIBLE;
93+
ERROR: table must have at least one column that is not invisible
94+
ALTER TABLE TEST_INVISIBLE_TBL1 MODIFY a SET VISIBLE;
8995
SELECT * FROM TEST_INVISIBLE_TBL1;
9096
a | c
9197
---+---

src/test/regress/expected/invisible.out.replica

+8-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@ CREATE TABLE TEST_INVISIBLE_TBL3(
1616
a INT INVISIBLE,
1717
b INT
1818
);
19-
ERROR: cannot execute INSERT in a read-only transaction
19+
ERROR: cannot execute CREATE TABLE in a read-only transaction
20+
create TABLE TEST_INVISIBLE_TBL4(
21+
a int INVISIBLE
22+
);
23+
ERROR: cannot execute CREATE TABLE in a read-only transaction
2024
INSERT INTO TEST_INVISIBLE_TBL1 VALUES (1, 1, 'A');
2125
ERROR: cannot execute INSERT in a read-only transaction
2226
INSERT INTO TEST_INVISIBLE_TBL1 VALUES (1, 'A');
@@ -88,7 +92,9 @@ SELECT * FROM TEST_INVISIBLE_TBL1;
8892
B
8993
(2 rows)
9094

91-
ALTER TABLE TEST_INVISIBLE_TBL1 ALTER COLUMN a SET VISIBLE;
95+
ALTER TABLE TEST_INVISIBLE_TBL1 ALTER COLUMN a SET INVISIBLE;
96+
ERROR: cannot execute ALTER TABLE in a read-only transaction
97+
ALTER TABLE TEST_INVISIBLE_TBL1 MODIFY a SET VISIBLE;
9298
ERROR: cannot execute ALTER TABLE in a read-only transaction
9399
SELECT * FROM TEST_INVISIBLE_TBL1;
94100
a | c

src/test/regress/sql/invisible.sql

+7-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ CREATE TABLE TEST_INVISIBLE_TBL3(
1818
b INT
1919
);
2020

21+
create TABLE TEST_INVISIBLE_TBL4(
22+
a int INVISIBLE
23+
);
24+
2125

2226
INSERT INTO TEST_INVISIBLE_TBL1 VALUES (1, 1, 'A');
2327
INSERT INTO TEST_INVISIBLE_TBL1 VALUES (1, 'A');
@@ -47,7 +51,9 @@ SELECT a, b FROM TEST_INVISIBLE_TBL3;
4751
ALTER TABLE TEST_INVISIBLE_TBL1 ALTER COLUMN b SET INVISIBLE;
4852
SELECT * FROM TEST_INVISIBLE_TBL1;
4953

50-
ALTER TABLE TEST_INVISIBLE_TBL1 ALTER COLUMN a SET VISIBLE;
54+
ALTER TABLE TEST_INVISIBLE_TBL1 ALTER COLUMN a SET INVISIBLE;
55+
56+
ALTER TABLE TEST_INVISIBLE_TBL1 MODIFY a VISIBLE;
5157
SELECT * FROM TEST_INVISIBLE_TBL1;
5258

5359
DROP TABLE TEST_INVISIBLE_TBL1;

0 commit comments

Comments
 (0)