]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Fix validation of COPY FORCE_NOT_NULL/FORCE_NULL for the all-column cases
authorMichael Paquier <michael@paquier.xyz>
Wed, 16 Oct 2024 23:45:56 +0000 (08:45 +0900)
committerMichael Paquier <michael@paquier.xyz>
Wed, 16 Oct 2024 23:45:56 +0000 (08:45 +0900)
This commit adds missing checks for COPY FORCE_NOT_NULL and FORCE_NULL
when applied to all columns via "*".  These options now correctly
require CSV mode and are disallowed in COPY TO, making their behavior
consistent with FORCE_QUOTE.

Some regression tests are added to verify the correct behavior for the
all-columns case, including FORCE_QUOTE, which was not tested.

Backpatch down to 17, where support for the all-column grammar with
FORCE_NOT_NULL and FORCE_NULL has been added.

Author: Joel Jacobson
Reviewed-by: Zhang Mingli
Discussion: https://postgr.es/m/65030d1d-5f90-4fa4-92eb-f5f50389858e@app.fastmail.com
Backpatch-through: 17

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

index 3bb579a3a4464f3efd0af8d27e0215210104d902..e557982071da51c93e92345ecde308fb422d442e 100644 (file)
@@ -783,12 +783,14 @@ ProcessCopyOptions(ParseState *pstate,
                                                "COPY FROM")));
 
        /* Check force_notnull */
-       if (!opts_out->csv_mode && opts_out->force_notnull != NIL)
+       if (!opts_out->csv_mode && (opts_out->force_notnull != NIL ||
+                                                               opts_out->force_notnull_all))
                ereport(ERROR,
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                /*- translator: %s is the name of a COPY option, e.g. ON_ERROR */
                                 errmsg("COPY %s requires CSV mode", "FORCE_NOT_NULL")));
-       if (opts_out->force_notnull != NIL && !is_from)
+       if ((opts_out->force_notnull != NIL || opts_out->force_notnull_all) &&
+               !is_from)
                ereport(ERROR,
                                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR,
@@ -797,13 +799,15 @@ ProcessCopyOptions(ParseState *pstate,
                                                "COPY TO")));
 
        /* Check force_null */
-       if (!opts_out->csv_mode && opts_out->force_null != NIL)
+       if (!opts_out->csv_mode && (opts_out->force_null != NIL ||
+                                                               opts_out->force_null_all))
                ereport(ERROR,
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                /*- translator: %s is the name of a COPY option, e.g. ON_ERROR */
                                 errmsg("COPY %s requires CSV mode", "FORCE_NULL")));
 
-       if (opts_out->force_null != NIL && !is_from)
+       if ((opts_out->force_null != NIL || opts_out->force_null_all) &&
+               !is_from)
                ereport(ERROR,
                                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR,
index 94063b5f1412a0079e546f8ec29da6e162a569f0..695b1b2d635a4527cba3bf66c4408b867a03783b 100644 (file)
@@ -98,16 +98,28 @@ LINE 1: COPY x from stdin (on_error unsupported);
                            ^
 COPY x from stdin (format TEXT, force_quote(a));
 ERROR:  COPY FORCE_QUOTE requires CSV mode
+COPY x from stdin (format TEXT, force_quote *);
+ERROR:  COPY FORCE_QUOTE requires CSV mode
 COPY x from stdin (format CSV, force_quote(a));
 ERROR:  COPY FORCE_QUOTE cannot be used with COPY FROM
+COPY x from stdin (format CSV, force_quote *);
+ERROR:  COPY FORCE_QUOTE cannot be used with COPY FROM
 COPY x from stdin (format TEXT, force_not_null(a));
 ERROR:  COPY FORCE_NOT_NULL requires CSV mode
+COPY x from stdin (format TEXT, force_not_null *);
+ERROR:  COPY FORCE_NOT_NULL requires CSV mode
 COPY x to stdout (format CSV, force_not_null(a));
 ERROR:  COPY FORCE_NOT_NULL cannot be used with COPY TO
+COPY x to stdout (format CSV, force_not_null *);
+ERROR:  COPY FORCE_NOT_NULL cannot be used with COPY TO
 COPY x from stdin (format TEXT, force_null(a));
 ERROR:  COPY FORCE_NULL requires CSV mode
+COPY x from stdin (format TEXT, force_null *);
+ERROR:  COPY FORCE_NULL requires CSV mode
 COPY x to stdout (format CSV, force_null(a));
 ERROR:  COPY FORCE_NULL cannot be used with COPY TO
+COPY x to stdout (format CSV, force_null *);
+ERROR:  COPY FORCE_NULL cannot be used with COPY TO
 COPY x to stdout (format BINARY, on_error unsupported);
 ERROR:  COPY ON_ERROR cannot be used with COPY TO
 LINE 1: COPY x to stdout (format BINARY, on_error unsupported);
index 8687e4e4cab2c9f9435c47f1b90fef4207e10482..6b75b6c7ea8fd78fa046514acfb8f45204e89fe3 100644 (file)
@@ -75,11 +75,17 @@ COPY x from stdin (format BINARY, null 'x');
 COPY x from stdin (format BINARY, on_error ignore);
 COPY x from stdin (on_error unsupported);
 COPY x from stdin (format TEXT, force_quote(a));
+COPY x from stdin (format TEXT, force_quote *);
 COPY x from stdin (format CSV, force_quote(a));
+COPY x from stdin (format CSV, force_quote *);
 COPY x from stdin (format TEXT, force_not_null(a));
+COPY x from stdin (format TEXT, force_not_null *);
 COPY x to stdout (format CSV, force_not_null(a));
+COPY x to stdout (format CSV, force_not_null *);
 COPY x from stdin (format TEXT, force_null(a));
+COPY x from stdin (format TEXT, force_null *);
 COPY x to stdout (format CSV, force_null(a));
+COPY x to stdout (format CSV, force_null *);
 COPY x to stdout (format BINARY, on_error unsupported);
 COPY x from stdin (log_verbosity unsupported);