Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1u13B9-00D6wb-Lu for pgsql-bugs@arkaria.postgresql.org; Sat, 05 Apr 2025 13:03:19 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1u13B7-00D95u-T9 for pgsql-bugs@arkaria.postgresql.org; Sat, 05 Apr 2025 13:03:17 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1u13B7-00D95V-AY for pgsql-bugs@lists.postgresql.org; Sat, 05 Apr 2025 13:03:17 +0000 Received: from fout-a3-smtp.messagingengine.com ([103.168.172.146]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1u13B4-003Xq5-0F for pgsql-bugs@lists.postgresql.org; Sat, 05 Apr 2025 13:03:16 +0000 Received: from phl-compute-02.internal (phl-compute-02.phl.internal [10.202.2.42]) by mailfout.phl.internal (Postfix) with ESMTP id 501BC1380178; Sat, 5 Apr 2025 09:03:11 -0400 (EDT) Received: from phl-mailfrontend-01 ([10.202.2.162]) by phl-compute-02.internal (MEProxy); Sat, 05 Apr 2025 09:03:11 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:content-type:date:date:feedback-id:feedback-id :from:from:in-reply-to:in-reply-to:message-id:mime-version :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm2; t=1743858191; x=1743944591; bh=o /lnwYkBOru7puSsHyi3vhdBJvy7o+Ti4C5wOrEiVg0=; b=JpAdm7WUKGCxy+tV7 /OAjojic9jp+rtAaUQdlS2Gm0kMUblYLlwhikha/V3Lmrl80VNClvLYVjdVSS8tG wU2v99bgTcYLYdW9nCNsCtvNV09BptfKY/sriDzSkNmgLQls9isM98928a0q6Pdo +rYuG/8ZT3f1l7yKxOgftK/rDLQxzJgdm+QAvun+QqTqHP7JwwaV1lkeqHVxdlUc snU6pKAFsCEUdj7z1JtS5LQ/M3gkcyiHWfQT9pCleq1J+KasPBFgeZAKuxu1r0b9 vf9aQ4IsB3z84NeIe5jzoCG68FHwoNV/rYEyWJq77g5/o6DtgzQgf8vwMdDmA2mq 0xrgg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgdduleeggedvucetufdoteggodetrf dotffvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdggtfgfnhhsuhgsshgtrhhisggv pdfurfetoffkrfgpnffqhgenuceurghilhhouhhtmecufedttdenucenucfjughrpeffhf fvvefukfggtggugfgjsehmkeerredttdejnecuhfhrohhmpeetlhhvrghrohcujfgvrhhr vghrrgcuoegrlhhvhhgvrhhrvgesrghlvhhhrdhnohdqihhprdhorhhgqeenucggtffrrg htthgvrhhnpeduleekkefgtddttedtkefguddvieffleetgeejiefhteehkeevfeettddu vdfhueenucffohhmrghinhepvghnthgvrhhprhhishgvuggsrdgtohhmnecuvehluhhsth gvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomheprghlvhhhvghrrhgvsegr lhhvhhdrnhhoqdhiphdrohhrghdpnhgspghrtghpthhtohepfedpmhhouggvpehsmhhtph houhhtpdhrtghpthhtohepphhgshhqlhdqsghughhssehlihhsthhsrdhpohhsthhgrhgv shhqlhdrohhrghdprhgtphhtthhopehluhihjedtsehpshhurdgvughupdhrtghpthhtoh epthhglhesshhsshdrphhghhdrphgrrdhush X-ME-Proxy: Feedback-ID: ia2694551:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sat, 5 Apr 2025 09:03:10 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alvh.no-ip.org; s=schmee; t=1743858188; bh=Xf1F7WIHhXFHp4j9p0fmtbId4HA06Cz5PjdvGb4l+1A=; h=Date:From:To:Cc:Subject:In-Reply-To:From; b=Y/8l/N6luXUzBE8KzTu9twBARTLKwzOo+YGApn8/hlbvfhK0oNwJrW0nsa3OSWzZA YOKBeo8MhINX8ItJtLmG/CNVG5lOtWYieYR6ZRqIToHEUeIFc/FiKYuS/35QtiO7l9 Vk93JKsTm+9PANIO5IWhSiajhY4XegnJWnBV9m/ZCoR/qltcQth/e9EL2I0EZWuc/b DlTyLW/r15E3TrjK2IDK7w004vrs5ZmCLvak5Z12+ie7bcaA1QwRplVLoRjxLG4ZED Mdb4efLs2xJjv2AhwqP0ntHSUmdnEiynTas7hxI5Q+ozKBuKIkRtPm6xTq2NWhBDqN JR6XlnZe3SwfQ== Received: by schmee.alvh.no-ip.org (Postfix, from userid 1000) id 3D2BB8F; Sat, 5 Apr 2025 15:03:08 +0200 (CEST) Date: Sat, 5 Apr 2025 15:03:08 +0200 From: Alvaro Herrera To: Tom Lane Cc: luy70@psu.edu, pgsql-bugs@lists.postgresql.org Subject: Re: BUG #18877: PostgreSQL triggers assertion failure Message-ID: <202504051303.fhpbodkciqry@alvherre.pgsql> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="ibz3cgmi3xh26lo3" Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <2387814.1743825262@sss.pgh.pa.us> List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --ibz3cgmi3xh26lo3 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit On 2025-Apr-04, Tom Lane wrote: > 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. Ugh, yeah, this is really dumb. This quick-and-dirty patch (not final form) gets us halfway there, by checking the targetlist after transforming the query. I think this is the behavior we want, although it's a bit scary that we have so few test cases for this. Anyway, if we only do this, this query from the regression tests still doesn't work the way we want: SELECT JSON_ARRAY(SELECT FROM (VALUES (1)) foo(i)); It causes an error to be raised _during_ transformation, namely +ERROR: table "q" has 0 columns available but 1 columns specified which we'd like to report differently. I think we want to verify the targetlist length of ctor->query before transformation, but I'm not sure exactly how, yet. -- Álvaro Herrera Breisgau, Deutschland — https://www.EnterpriseDB.com/ --ibz3cgmi3xh26lo3 Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="transformonce.patch" diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 9caf1e481a2..1dcbd70a509 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -3766,30 +3766,12 @@ transformJsonArrayQueryConstructor(ParseState *pstate, ResTarget *target = makeNode(ResTarget); JsonArrayAgg *agg = makeNode(JsonArrayAgg); ColumnRef *colref = makeNode(ColumnRef); - Query *query; - ParseState *qpstate; - - /* Transform query only for counting target list entries. */ - qpstate = make_parsestate(pstate); - - query = transformStmt(qpstate, ctor->query); - - if (count_nonjunk_tlist_entries(query->targetList) != 1) - ereport(ERROR, - errcode(ERRCODE_SYNTAX_ERROR), - errmsg("subquery must return only one column"), - parser_errposition(pstate, ctor->location)); - - free_parsestate(qpstate); + Node *transformed; colref->fields = list_make2(makeString(pstrdup("q")), makeString(pstrdup("a"))); colref->location = ctor->location; - /* - * No formatting necessary, so set formatted_expr to be the same as - * raw_expr. - */ agg->arg = makeJsonValueExpr((Expr *) colref, (Expr *) colref, ctor->format); agg->absent_on_null = ctor->absent_on_null; @@ -3820,7 +3802,32 @@ transformJsonArrayQueryConstructor(ParseState *pstate, sublink->subselect = (Node *) select; sublink->location = ctor->location; - return transformExprRecurse(pstate, (Node *) sublink); + transformed = transformExprRecurse(pstate, (Node *) sublink); + + /* + * Verify that the query (which has been installed as the subselect in the + * sublink) returns exactly one column after transformation. + */ + { + Query *query; + RangeTblEntry *rte; + + query = castNode(Query, (castNode(SubLink, transformed))->subselect); + Assert(list_length(query->rtable) == 1); + + rte = linitial_node(RangeTblEntry, query->rtable); + Assert(rte->rtekind == RTE_SUBQUERY); + + /* Transfer our attention to the subquery */ + query = rte->subquery; + if (count_nonjunk_tlist_entries(query->targetList) != 1) + ereport(ERROR, + errcode(ERRCODE_SYNTAX_ERROR), + errmsg("subquery must return only one column"), + parser_errposition(pstate, ctor->location)); + } + + return transformed; } /* --ibz3cgmi3xh26lo3--