Only evaluate default values as required when doing COPY FROM
authorAndrew Dunstan <andrew@dunslane.net>
Sun, 1 Oct 2023 14:18:41 +0000 (10:18 -0400)
committerAndrew Dunstan <andrew@dunslane.net>
Sun, 1 Oct 2023 14:18:41 +0000 (10:18 -0400)
Commit 9f8377f7a2 was a little too eager in fetching default values.
Normally this would not matter, but if the default value is not valid
for the type (e.g. a varchar that's too long) it caused an unnecessary
error.

Complaint and fix from Laurenz Albe

Backpatch to release 16.

Discussion: https://postgr.es/m/75a7b7483aeb331aa017328d606d568fc715b90d.camel@cybertec.at

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

index 2d1567d0e42ae5f6ec150964605d4c7f9ad3b3aa..cf0fc9d794d44329ffe977a634d5c76be6c0713f 100644 (file)
@@ -1571,7 +1571,14 @@ BeginCopyFrom(ParseState *pstate,
        /* Get default info if available */
        defexprs[attnum - 1] = NULL;
 
-       if (!att->attgenerated)
+       /*
+        * We only need the default values for columns that do not appear in
+        * the column list, unless the DEFAULT option was given. We never need
+        * default values for generated columns.
+        */
+       if ((cstate->opts.default_print != NULL ||
+            !list_member_int(cstate->attnumlist, attnum)) &&
+           !att->attgenerated)
        {
            Expr       *defexpr = (Expr *) build_column_default(cstate->rel,
                                                                attnum);
index 8a8bf43fdea0fb67ce3cb4827779361929552b9f..a5912c13a8ce6dd76f8104cbd3e0e52e30c297b8 100644 (file)
@@ -240,3 +240,20 @@ SELECT * FROM header_copytest ORDER BY a;
 (5 rows)
 
 drop table header_copytest;
+-- test COPY with overlong column defaults
+create temp table oversized_column_default (
+    col1 varchar(5) DEFAULT 'more than 5 chars',
+    col2 varchar(5));
+-- normal COPY should work
+copy oversized_column_default from stdin;
+-- error if the column is excluded
+copy oversized_column_default (col2) from stdin;
+ERROR:  value too long for type character varying(5)
+\.
+invalid command \.
+-- error if the DEFAULT option is given
+copy oversized_column_default from stdin (default '');
+ERROR:  value too long for type character varying(5)
+\.
+invalid command \.
+drop table oversized_column_default;
index f9da7b1508f38425d42a5bf595944c4b2068da06..7fdb26d14f309e716b5e557965dfb1faac4c163f 100644 (file)
@@ -268,3 +268,18 @@ a  c   b
 
 SELECT * FROM header_copytest ORDER BY a;
 drop table header_copytest;
+
+-- test COPY with overlong column defaults
+create temp table oversized_column_default (
+    col1 varchar(5) DEFAULT 'more than 5 chars',
+    col2 varchar(5));
+-- normal COPY should work
+copy oversized_column_default from stdin;
+\.
+-- error if the column is excluded
+copy oversized_column_default (col2) from stdin;
+\.
+-- error if the DEFAULT option is given
+copy oversized_column_default from stdin (default '');
+\.
+drop table oversized_column_default;