From 132de6de3bd5e429069169cc3572332300eb2197 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Wed, 7 Mar 2018 14:38:35 -0500 Subject: [PATCH 1/2] Fix CREATE TABLE / LIKE with bigint identity column CREATE TABLE / LIKE with a bigint identity column would fail on platforms where long is 32 bits. Copying the sequence values used makeInteger(), which would truncate the 64-bit sequence data to 32 bits. To fix, use makeFloat() instead, like the parser. (This does not actually make use of floats, but stores the values as strings.) Bug: #15096 --- src/backend/commands/sequence.c | 19 +++++++++++------ src/test/regress/expected/create_table_like.out | 28 ++++++++++++------------- src/test/regress/sql/create_table_like.sql | 2 +- 3 files changed, 28 insertions(+), 21 deletions(-) diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c index ef3ca8c00b..dcc0aa536a 100644 --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -1752,12 +1752,19 @@ sequence_options(Oid relid) elog(ERROR, "cache lookup failed for sequence %u", relid); pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple); - options = lappend(options, makeDefElem("cache", (Node *) makeInteger(pgsform->seqcache), -1)); - options = lappend(options, makeDefElem("cycle", (Node *) makeInteger(pgsform->seqcycle), -1)); - options = lappend(options, makeDefElem("increment", (Node *) makeInteger(pgsform->seqincrement), -1)); - options = lappend(options, makeDefElem("maxvalue", (Node *) makeInteger(pgsform->seqmax), -1)); - options = lappend(options, makeDefElem("minvalue", (Node *) makeInteger(pgsform->seqmin), -1)); - options = lappend(options, makeDefElem("start", (Node *) makeInteger(pgsform->seqstart), -1)); + /* Use makeFloat() for 64-bit integers, like gram.y does. */ + options = lappend(options, + makeDefElem("cache", (Node *) makeFloat(psprintf(INT64_FORMAT, pgsform->seqcache)), -1)); + options = lappend(options, + makeDefElem("cycle", (Node *) makeInteger(pgsform->seqcycle), -1)); + options = lappend(options, + makeDefElem("increment", (Node *) makeFloat(psprintf(INT64_FORMAT, pgsform->seqincrement)), -1)); + options = lappend(options, + makeDefElem("maxvalue", (Node *) makeFloat(psprintf(INT64_FORMAT, pgsform->seqmax)), -1)); + options = lappend(options, + makeDefElem("minvalue", (Node *) makeFloat(psprintf(INT64_FORMAT, pgsform->seqmin)), -1)); + options = lappend(options, + makeDefElem("start", (Node *) makeFloat(psprintf(INT64_FORMAT, pgsform->seqstart)), -1)); ReleaseSysCache(pgstuple); diff --git a/src/test/regress/expected/create_table_like.out b/src/test/regress/expected/create_table_like.out index 52ff18c8ca..8d4543bfe8 100644 --- a/src/test/regress/expected/create_table_like.out +++ b/src/test/regress/expected/create_table_like.out @@ -66,13 +66,13 @@ SELECT * FROM inhg; /* Two records with three columns in order x=x, xx=text, y=y (2 rows) DROP TABLE inhg; -CREATE TABLE test_like_id_1 (a int GENERATED ALWAYS AS IDENTITY, b text); +CREATE TABLE test_like_id_1 (a bigint GENERATED ALWAYS AS IDENTITY, b text); \d test_like_id_1 Table "public.test_like_id_1" - Column | Type | Collation | Nullable | Default ---------+---------+-----------+----------+------------------------------ - a | integer | | not null | generated always as identity - b | text | | | + Column | Type | Collation | Nullable | Default +--------+--------+-----------+----------+------------------------------ + a | bigint | | not null | generated always as identity + b | text | | | INSERT INTO test_like_id_1 (b) VALUES ('b1'); SELECT * FROM test_like_id_1; @@ -83,11 +83,11 @@ SELECT * FROM test_like_id_1; CREATE TABLE test_like_id_2 (LIKE test_like_id_1); \d test_like_id_2 - Table "public.test_like_id_2" - Column | Type | Collation | Nullable | Default ---------+---------+-----------+----------+--------- - a | integer | | not null | - b | text | | | + Table "public.test_like_id_2" + Column | Type | Collation | Nullable | Default +--------+--------+-----------+----------+--------- + a | bigint | | not null | + b | text | | | INSERT INTO test_like_id_2 (b) VALUES ('b2'); ERROR: null value in column "a" violates not-null constraint @@ -100,10 +100,10 @@ SELECT * FROM test_like_id_2; -- identity was not copied CREATE TABLE test_like_id_3 (LIKE test_like_id_1 INCLUDING IDENTITY); \d test_like_id_3 Table "public.test_like_id_3" - Column | Type | Collation | Nullable | Default ---------+---------+-----------+----------+------------------------------ - a | integer | | not null | generated always as identity - b | text | | | + Column | Type | Collation | Nullable | Default +--------+--------+-----------+----------+------------------------------ + a | bigint | | not null | generated always as identity + b | text | | | INSERT INTO test_like_id_3 (b) VALUES ('b3'); SELECT * FROM test_like_id_3; -- identity was copied and applied diff --git a/src/test/regress/sql/create_table_like.sql b/src/test/regress/sql/create_table_like.sql index 32d861621b..42cad6826b 100644 --- a/src/test/regress/sql/create_table_like.sql +++ b/src/test/regress/sql/create_table_like.sql @@ -37,7 +37,7 @@ CREATE TABLE inhg (x text, LIKE inhx INCLUDING CONSTRAINTS, y text); /* Copies c SELECT * FROM inhg; /* Two records with three columns in order x=x, xx=text, y=y */ DROP TABLE inhg; -CREATE TABLE test_like_id_1 (a int GENERATED ALWAYS AS IDENTITY, b text); +CREATE TABLE test_like_id_1 (a bigint GENERATED ALWAYS AS IDENTITY, b text); \d test_like_id_1 INSERT INTO test_like_id_1 (b) VALUES ('b1'); SELECT * FROM test_like_id_1; base-commit: bcdd40538a11a39fee55ef1c4b79085717a5fb76 -- 2.16.2