Re: BUG #18877: PostgreSQL triggers assertion failure

Tender Wang <tndrwang@gmail.com>

From: Tender Wang <tndrwang@gmail.com>
To: Tom Lane <tgl@sss.pgh.pa.us>
Cc: luy70@psu.edu, pgsql-bugs@lists.postgresql.org, Alvaro Herrera <alvherre@alvh.no-ip.org>
Date: 2025-04-05T11:47:25Z
Lists: pgsql-bugs
Tom Lane <tgl@sss.pgh.pa.us> 于2025年4月5日周六 11:54写道:

> PG Bug reporting form <noreply@postgresql.org> writes:
> > In the debug build of PostgreSQL 17.4, compiled with `configure
> > --enable-debug --prefix=$(pwd) --exec-prefix=$(pwd) --enable-cassert`,
> > triggered Assertion Failure when executing the following statement:
>
> > ```sql
> > SELECT ALL GROUP BY ALL ( ), CUBE ( CASE WHEN FALSE THEN TRUE END )
> > INTERSECT ALL SELECT ALL FROM JSON_ARRAY ( WITH any_cte_name AS ( ( TABLE
> > v00 ) ) VALUES ( FALSE ) ), any_table_name GROUP BY CUBE ( CASE WHEN TRUE
> > THEN FALSE END );
> > ```
>
> Minimized a bit, that's
>
> regression=# SELECT 1 FROM JSON_ARRAY ( WITH any_cte_name AS ( ( select 1
> ) ) VALUES ( FALSE ) );
> server closed the connection unexpectedly
>
> This is another case of "don't let the parser process the same
> querytree twice".  I can make it go away with
>

Yes, indeed.


>
> diff --git a/src/backend/parser/parse_expr.c
> b/src/backend/parser/parse_expr.c
> index 9caf1e481a2..bc602f00ae3 100644
> --- a/src/backend/parser/parse_expr.c
> +++ b/src/backend/parser/parse_expr.c
> @@ -3772,7 +3772,7 @@ transformJsonArrayQueryConstructor(ParseState
> *pstate,
>         /* Transform query only for counting target list entries. */
>         qpstate = make_parsestate(pstate);
>
> -       query = transformStmt(qpstate, ctor->query);
> +       query = transformStmt(qpstate, copyObject(ctor->query));
>
>         if (count_nonjunk_tlist_entries(query->targetList) != 1)
>                 ereport(ERROR,
>
> However ... it's possible that this isn't the stupidest, most
> brute-force code in Postgres, but I'll wager it's in the top ten.
> Is it really necessary to transform the subquery twice just to
> produce this error?  It seems like the constructed EXPR_SUBLINK
> should produce the same error all by itself.  I tried nuking this
> whole stanza to see whether that would happen, and then there are a
> couple of regression test cases that don't produce the same results.
> But I feel like it could be made to work with a bit more thought.
>

If we use the constructed EXPR_SUBLINK, the following query
SELECT JSON_ARRAY(SELECT i, i FROM (VALUES (1)) foo(I));
will not produce the same results.

If we want to get the same error "subquery must return only one column",
the ResTarget of EXPR_SUBLINK should not be "a". But if not using "a",
we should create a new TargetEntry to replace the targetList of the
transformed sublink's subselect.


-- 
Thanks, Tender Wang

Commits

Same data as JSON: GET /api/v1/messages/:b64id/commits the thread's linked commits as JSON, with link sources. API reference →
  1. Avoid double transformation of json_array()'s subquery.