Subject: Re: COPY: validate option presence rather than option values

From: Masahiko Sawada <[email-masked]>
Date: Fri, 26 Jun 2026 14:09:26 -0700

On Tue, May 5, 2026 at 9:26 PM Chao Li <[email-masked]> wrote:
>
> Hi,
>
> While testing COPY TO (FORMAT json), I noticed that the doc says FORCE_ARRAY is only allowed with FORMAT json:
> ```
>    <varlistentry id="sql-copy-params-force-array">
>     <term><literal>FORCE_ARRAY</literal></term>
>     <listitem>
>      <para>
>       Force output of square brackets as array decorations at the beginning
>       and end of output, and commas between the rows. It is allowed only in
>       <command>COPY TO</command>, and only when using
>       <literal>json</literal> format. The default is
>       <literal>false</literal>.
>      </para>
>     </listitem>
>    </varlistentry>
> ```
>
> However, this succeeds:
> ```
> evantest=# copy t1 to stdout (format csv, force_array false);
> 1
> ```
>
> So this is clearly validating the parsed value of force_array, rather than whether the option was specified at all.

Hmm, I'm not sure this is actually a problem in practice. It seems
straightforward to me that the documentation stating 'it is allowed
only when...' can be interpreted as 'it is allowed to be enabled only
when...'. My concern is that the proposed patch could make the command
unnecessarily less flexible. This is especially true in cases where
users programmatically generate a template COPY query and pass
explicit boolean values (true/false) to the options. Also, other
commands like VACUUM handle their boolean options in the exact same
manner:

=# vacuum (parallel 1, full) pg_class;
ERROR:  VACUUM FULL cannot be performed in parallel
=# vacuum (parallel 1, full off) pg_class;
VACUUM

Regards,

-- 
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com

---

From: Chao Li <[email-masked]>
Date: Mon, 29 Jun 2026 11:21:46 +0800

> On Jun 27, 2026, at 05:09, Masahiko Sawada <[email-masked]> wrote:
> 

It seems there is no consistency even within the VACUUM command. BUFFER_USAGE_LIMIT is checked based on its presence, not its value:
```
evantest=# vacuum (full, BUFFER_USAGE_LIMIT 0) t;
ERROR: BUFFER_USAGE_LIMIT cannot be specified for VACUUM FULL
```

Here, 0 disables BUFFER_USAGE_LIMIT, but it is still not allowed when the option is not supposed to be used.

I posted a similar patch [1], and Fujii-san expressed the same opinion as you. So, let me withdraw both patches for now.

[1] https://www.postgresql.org/message-id/CD33AC99-0175-4AD9-A33F-88E57736DA8E%40gmail.com

Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/