BUG #16149: Prepared COPY queries always report 0 parameters when described

Started by PG Bug reporting formover 6 years ago2 messagesbugs
Jump to latest
#1PG Bug reporting form
noreply@postgresql.org

The following bug has been logged on the website:

Bug reference: 16149
Logged by: Steven Fackler
Email address: sfackler@gmail.com
PostgreSQL version: 12.1
Operating system: Debian Buster
Description:

When a Postgres backend describes a prepared `COPY ... TO STDOUT query`, it
always reports 0 query parameters regardless of how many are actually
present. Here's a simple example program that demonstrates the issue:

```
#include <libpq-fe.h>
#include <assert.h>
#include <stdio.h>

int main() {
PGconn *conn = PQconnectdb("host=localhost port=5433 user=postgres");
assert(PQstatus(conn) == CONNECTION_OK);

PGresult *result = PQprepare(conn, "a", "COPY (SELECT $1::TEXT) TO STDOUT",
0, NULL);
assert(PQresultStatus(result) == PGRES_COMMAND_OK);

result = PQdescribePrepared(conn, "a");
assert(PQresultStatus(result) == PGRES_COMMAND_OK);
printf("nparams: %d\n", PQnparams(result));

result = PQexecPrepared(conn, "a", 0, NULL, NULL, NULL, 0);
assert(PQresultStatus(result) == PGRES_FATAL_ERROR);
printf("error: %s\n", PQresultErrorField(result,
PG_DIAG_MESSAGE_PRIMARY));
```

When run, it prints the following:

```
nparams: 0
error: there is no parameter $1
```

If you change the query to just the inner `SELECT $1::TEXT`, the number of
parameters is correctly reported, but interestingly the error message
changes:

```
nparams: 1
error: bind message supplies 0 parameters, but prepared statement "a"
requires 1
```

From some quick Googling, I did see this StackOverflow post[1]https://stackoverflow.com/a/22963085 stating that
COPY queries don't support parameters, but if that's the case it seems like
an error should be reported at the preparation stage. I also don't see
anything about that in the documentation for COPY[2]https://www.postgresql.org/docs/12/sql-copy.html, though I may have
missed it! I see the same behavior on Postgres 11.1 as well, if that's
relevant.

[1]: https://stackoverflow.com/a/22963085
[2]: https://www.postgresql.org/docs/12/sql-copy.html

#2David G. Johnston
david.g.johnston@gmail.com
In reply to: PG Bug reporting form (#1)
Re: BUG #16149: Prepared COPY queries always report 0 parameters when described

On Wed, Dec 4, 2019 at 5:22 PM PG Bug reporting form <noreply@postgresql.org>
wrote:

The following bug has been logged on the website:

Bug reference: 16149
Logged by: Steven Fackler
Email address: sfackler@gmail.com
PostgreSQL version: 12.1
Operating system: Debian Buster
Description:

When a Postgres backend describes a prepared `COPY ... TO STDOUT query`, it
always reports 0 query parameters regardless of how many are actually
present

Working as designed though I agree with the comment below that somehow it
has escaped documentation that this command is a utility command and
"query" cannot contain parameters.

PGresult *result = PQprepare(conn, "a", "COPY (SELECT $1::TEXT) TO

STDOUT",
0, NULL);

[...]

result = PQexecPrepared(conn, "a", 0, NULL, NULL, NULL, 0);
When run, it prints the following:

```
nparams: 0
error: there is no parameter $1
```

Yep - though this is the odd error message - but it almost reads like
because you are using execPrepared the code is expecting a planned and
parameterized statement and is complaining, oddly, that it wasn't provided
one. Its OK to give it a statement that can accept parameters but has zero
but NOT OK to give it one that doesn't accept parameters at all.

If you change the query to just the inner `SELECT $1::TEXT`, the number of
parameters is correctly reported, but interestingly the error message
changes:

```
nparams: 1
error: bind message supplies 0 parameters, but prepared statement "a"
requires 1
```

Not that interesting, the PQexecPrepared call supplies zero parameter
values but the SELECT query is indeed expecting one.

From some quick Googling, I did see this StackOverflow post[1] stating that
COPY queries don't support parameters,

Yes

but if that's the case it seems like
an error should be reported at the preparation stage.

Seems reasonable...

I also don't see
anything about that in the documentation for COPY[2], though I may have
missed it!

I do not either.

I see the same behavior on Postgres 11.1 as well, if that's

relevant.

It supports the conclusion that the behavior is likely intentional.

David J.