]> granicus.if.org Git - postgresql/commitdiff
Apply identity sequence values on COPY
authorPeter Eisentraut <peter_e@gmx.net>
Fri, 8 Dec 2017 14:18:18 +0000 (09:18 -0500)
committerPeter Eisentraut <peter_e@gmx.net>
Fri, 8 Dec 2017 14:18:18 +0000 (09:18 -0500)
A COPY into a table should apply identity sequence values just like it
does for ordinary defaults.  This was previously forgotten, leading to
null values being inserted, which in turn would fail because identity
columns have not-null constraints.

Author: Michael Paquier <michael.paquier@gmail.com>
Reported-by: Steven Winfield <steven.winfield@cantabcapital.com>
Bug: #14952

src/backend/commands/copy.c
src/test/regress/expected/identity.out
src/test/regress/sql/identity.sql

index bace390470fbec39fa17f1a6a63496d02016297d..254be28ae4fd4c279f9742148324f96dc9754777 100644 (file)
@@ -23,6 +23,7 @@
 #include "access/sysattr.h"
 #include "access/xact.h"
 #include "access/xlog.h"
+#include "catalog/dependency.h"
 #include "catalog/pg_type.h"
 #include "commands/copy.h"
 #include "commands/defrem.h"
@@ -3067,8 +3068,19 @@ BeginCopyFrom(ParseState *pstate,
                {
                        /* attribute is NOT to be copied from input */
                        /* use default value if one exists */
-                       Expr       *defexpr = (Expr *) build_column_default(cstate->rel,
-                                                                                                                               attnum);
+                       Expr       *defexpr;
+
+                       if (att->attidentity)
+                       {
+                               NextValueExpr *nve = makeNode(NextValueExpr);
+
+                               nve->seqid = getOwnedSequence(RelationGetRelid(cstate->rel),
+                                                                                         attnum);
+                               nve->typeId = att->atttypid;
+                               defexpr = (Expr *) nve;
+                       }
+                       else
+                               defexpr = (Expr *) build_column_default(cstate->rel, attnum);
 
                        if (defexpr != NULL)
                        {
index 5fa585d6cc55b69ec421be1063813616291a43dc..174b420a0414a15a580bda9e29ad311e8625f037 100644 (file)
@@ -153,6 +153,19 @@ SELECT * FROM itest2;
   3 | 
 (3 rows)
 
+-- COPY tests
+CREATE TABLE itest9 (a int GENERATED ALWAYS AS IDENTITY, b text, c bigint);
+COPY itest9 FROM stdin;
+COPY itest9 (b, c) FROM stdin;
+SELECT * FROM itest9 ORDER BY c;
+  a  |  b   |  c  
+-----+------+-----
+ 100 | foo  | 200
+ 101 | bar  | 201
+   1 | foo2 | 202
+   2 | bar2 | 203
+(4 rows)
+
 -- DROP IDENTITY tests
 ALTER TABLE itest4 ALTER COLUMN a DROP IDENTITY;
 ALTER TABLE itest4 ALTER COLUMN a DROP IDENTITY;  -- error
index e1b5a074c96102f3e1288325ae9a14c3acc90e50..6e76dd08c86683e16aa7e4584b2875ce37b6233f 100644 (file)
@@ -78,6 +78,23 @@ UPDATE itest2 SET a = DEFAULT WHERE a = 2;
 SELECT * FROM itest2;
 
 
+-- COPY tests
+
+CREATE TABLE itest9 (a int GENERATED ALWAYS AS IDENTITY, b text, c bigint);
+
+COPY itest9 FROM stdin;
+100    foo     200
+101    bar     201
+\.
+
+COPY itest9 (b, c) FROM stdin;
+foo2   202
+bar2   203
+\.
+
+SELECT * FROM itest9 ORDER BY c;
+
+
 -- DROP IDENTITY tests
 
 ALTER TABLE itest4 ALTER COLUMN a DROP IDENTITY;