]> granicus.if.org Git - postgresql/commitdiff
Fix CREATE TABLE / LIKE with bigint identity column
authorPeter Eisentraut <peter_e@gmx.net>
Wed, 7 Mar 2018 19:38:35 +0000 (14:38 -0500)
committerPeter Eisentraut <peter_e@gmx.net>
Tue, 13 Mar 2018 13:41:36 +0000 (09:41 -0400)
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
Reviewed-by: Michael Paquier <michael@paquier.xyz>
src/backend/commands/sequence.c
src/test/regress/expected/create_table_like.out
src/test/regress/sql/create_table_like.sql

index 5c2ce789468463e353d0418f5c8ad53fca7eb24e..2f3ee462361144682f6a75896e208d91a172898e 100644 (file)
@@ -1760,12 +1760,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);
 
index d640bce17998c47bf7805f004701c9174e7e5bf8..0d8438a9abddc1ef468dcd71874872e325a10b57 100644 (file)
@@ -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
index 32d861621bf5b3955b8b7f23c984cb1075e3f723..42cad6826b0f15837bc36ecda61d54f2079aac1b 100644 (file)
@@ -37,7 +37,7 @@ INSERT INTO inhg VALUES ('x', 'foo',  'y');  /* fails due to constraint */
 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;