On Mon, 2023-09-25 at 09:54 +0200, Laurenz Albe wrote: > In v16 and later, the following fails: > > CREATE TABLE boom (t character varying(5) DEFAULT 'a long string'); > > COPY boom FROM STDIN; > ERROR: value too long for type character varying(5) > > In PostgreSQL v15 and earlier, the COPY statement succeeds. > > The error is thrown in BeginCopyFrom in line 1578 (HEAD) > > defexpr = expression_planner(defexpr); > > Bisecting shows that the regression was introduced by commit 9f8377f7a2, > which introduced DEFAULT values for COPY FROM.
I suggest the attached fix, which evaluates default values only if the DEFAULT option was specified or if the column does not appear in the column list of COPY. Yours, Laurenz Albe
From 4af982c56df57a1a0f04340d394c297559fbabb5 Mon Sep 17 00:00:00 2001 From: Laurenz Albe <laurenz.a...@cybertec.at> Date: Mon, 25 Sep 2023 10:56:15 +0200 Subject: [PATCH] Evaluate defaults in COPY FROM only if necessary Since commit 9f8377f7a2, we evaluate the column default values in COPY FROM for all columns except generated ones, because they could be needed if the input value matches the DEFAULT option. This can cause a surprising regression: CREATE TABLE boom (t character varying(5) DEFAULT 'a long string'); COPY boom FROM STDIN; ERROR: value too long for type character varying(5) This worked before 9f8377f7a2, since default values were only evaluated for columns that were not specified in the column list. To fix, fetch the default values only if the DEFAULT option was specified or for columns not specified in the column list. --- src/backend/commands/copyfrom.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/backend/commands/copyfrom.c b/src/backend/commands/copyfrom.c index 70871ed819..320b764aa9 100644 --- a/src/backend/commands/copyfrom.c +++ b/src/backend/commands/copyfrom.c @@ -1567,7 +1567,14 @@ BeginCopyFrom(ParseState *pstate, /* Get default info if available */ defexprs[attnum - 1] = NULL; - if (!att->attgenerated) + /* + * We need the default values only for columns that do not appear in the + * column list or if the DEFAULT option was given. We also don't need + * it for generated columns. + */ + if ((!list_member_int(cstate->attnumlist, attnum) || + cstate->opts.default_print != NULL) && + !att->attgenerated) { Expr *defexpr = (Expr *) build_column_default(cstate->rel, attnum); -- 2.41.0