From f55ae5657c99ea8e01caf7454555352f8fa0c70e Mon Sep 17 00:00:00 2001 From: amit Date: Thu, 9 Nov 2017 14:19:31 +0900 Subject: [PATCH 2/2] Make IDENTITY work correctly with partitions In the case of CREATE TABLE PARTITION OF, transformColumnDefinition should look at the parent's attribute of the same name to get the type OID. ColumnDef passed down by gram.y is mostly dummy, so doesn't contain the needed information. Authors: Michael Paquier, Amit Langote --- src/backend/commands/tablecmds.c | 1 + src/backend/parser/parse_utilcmd.c | 40 ++++++++++++++++++++++++++++++++++ src/test/regress/expected/identity.out | 23 +++++++++++++++++++ src/test/regress/sql/identity.sql | 14 ++++++++++++ 4 files changed, 78 insertions(+) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 192de790c4..9597d594e3 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -2258,6 +2258,7 @@ MergeAttributes(List *schema, List *supers, char relpersistence, coldef->raw_default = restdef->raw_default; coldef->cooked_default = restdef->cooked_default; coldef->constraints = restdef->constraints; + coldef->identity = restdef->identity; coldef->is_from_parent = false; list_delete_cell(schema, rest, prev); } diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index 1be36b846a..4dae4b4171 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -241,6 +241,7 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString) cxt.alist = NIL; cxt.pkey = NULL; cxt.ispartitioned = stmt->partspec != NULL; + cxt.partbound = stmt->partbound; cxt.ofType = stmt->ofTypename != NULL; /* @@ -706,6 +707,45 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column) typeOid = col->typeName->typeOid; } + else if (cxt->partbound) + { + Relation rel; + RangeVar *inh = linitial_node(RangeVar, + cxt->inhRelations); + int i; + + Assert(list_length(cxt->inhRelations) == 1); + + /* + * First time opening the parent table. We take an + * AccessExclusiveLock on it due to certain operations + * we do later in DefineRelation(). Don't want to + * risk a lock-upgrade deadlock hazard by taking a + * weaker lock now and stronger one later. + */ + rel = heap_openrv(inh, AccessExclusiveLock); + for (i = 0; i < rel->rd_att->natts; i++) + { + Form_pg_attribute attr = + TupleDescAttr(rel->rd_att, i); + + if (attr->attisdropped) + continue; + if (strcmp(NameStr(attr->attname), + column->colname) == 0) + { + typeOid = attr->atttypid; + break; + } + } + heap_close(rel, NoLock); + + if (i == rel->rd_att->natts) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_COLUMN), + errmsg("column \"%s\" does not exist", + column->colname))); + } else { Type ctype; diff --git a/src/test/regress/expected/identity.out b/src/test/regress/expected/identity.out index 787edd4d06..81ec422bbd 100644 --- a/src/test/regress/expected/identity.out +++ b/src/test/regress/expected/identity.out @@ -354,3 +354,26 @@ Typed table of type: itest_type DROP TYPE itest_type CASCADE; NOTICE: drop cascades to table itest9 +-- partitioned tables +CREATE TABLE itest_parent (f1 date NOT NULL, f2 text, f3 bigint) PARTITION BY RANGE (f1); +CREATE TABLE itest_child PARTITION OF itest_parent ( + f4 WITH OPTIONS GENERATED ALWAYS AS IDENTITY +) FOR VALUES FROM ('2016-07-01') TO ('2016-08-01'); -- error +ERROR: column "f4" does not exist +CREATE TABLE itest_child PARTITION OF itest_parent ( + f2 WITH OPTIONS GENERATED ALWAYS AS IDENTITY +) FOR VALUES FROM ('2016-07-01') TO ('2016-08-01'); -- error +ERROR: identity column type must be smallint, integer, or bigint +CREATE TABLE itest_child PARTITION OF itest_parent ( + f3 WITH OPTIONS GENERATED ALWAYS AS IDENTITY +) FOR VALUES FROM ('2016-07-01') TO ('2016-08-01'); -- ok +\d itest_child + Table "public.itest_child" + Column | Type | Collation | Nullable | Default +--------+--------+-----------+----------+------------------------------ + f1 | date | | not null | + f2 | text | | | + f3 | bigint | | not null | generated always as identity +Partition of: itest_parent FOR VALUES FROM ('07-01-2016') TO ('08-01-2016') + +DROP TABLE itest_parent; diff --git a/src/test/regress/sql/identity.sql b/src/test/regress/sql/identity.sql index b98180f644..fe88abceb9 100644 --- a/src/test/regress/sql/identity.sql +++ b/src/test/regress/sql/identity.sql @@ -205,3 +205,17 @@ CREATE TABLE itest9 OF itest_type ( f1 WITH OPTIONS GENERATED ALWAYS AS IDENTITY); -- ok \d itest9 DROP TYPE itest_type CASCADE; + +-- partitioned tables +CREATE TABLE itest_parent (f1 date NOT NULL, f2 text, f3 bigint) PARTITION BY RANGE (f1); +CREATE TABLE itest_child PARTITION OF itest_parent ( + f4 WITH OPTIONS GENERATED ALWAYS AS IDENTITY +) FOR VALUES FROM ('2016-07-01') TO ('2016-08-01'); -- error +CREATE TABLE itest_child PARTITION OF itest_parent ( + f2 WITH OPTIONS GENERATED ALWAYS AS IDENTITY +) FOR VALUES FROM ('2016-07-01') TO ('2016-08-01'); -- error +CREATE TABLE itest_child PARTITION OF itest_parent ( + f3 WITH OPTIONS GENERATED ALWAYS AS IDENTITY +) FOR VALUES FROM ('2016-07-01') TO ('2016-08-01'); -- ok +\d itest_child +DROP TABLE itest_parent; -- 2.11.0