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.98.2) (envelope-from ) id 1x7YTc-00000000TgU-2OK4 for pgsql-bugs@arkaria.postgresql.org; Fri, 18 Sep 2026 13:18:04 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.98.2) (envelope-from ) id 1x7YTb-00000001JEw-3h1I for pgsql-bugs@arkaria.postgresql.org; Fri, 18 Sep 2026 13:18:03 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1x7Oc2-00000007PCW-3gSy for pgsql-bugs@lists.postgresql.org; Fri, 18 Sep 2026 02:46:06 +0000 Received: from mahout.postgresql.org ([2001:4800:3e1:1::227]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1x7Oc1-00000000FUc-1Gs2 for pgsql-bugs@lists.postgresql.org; Fri, 18 Sep 2026 02:46:06 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=postgresql.org; s=20171124; h=Message-ID:Date:Reply-To:Cc:From:To:Subject: Content-Transfer-Encoding:MIME-Version:Content-Type:Sender:Content-ID: Content-Description:In-Reply-To:References; bh=fGEkmw+PiPTBv/QLfvKfnTZAXQqzoeSmxM0YYHX0hlE=; b=4Nh5JsZA0o2U4+sWHyzGvCsbo0 eS9jDEx9AkOHtIAKsqt888L7W8PrqhX2QG9WmGoF7N51M9iBzciqDBqFG+I35LkVXkq9QLKLmtTPv AKK6+9cg6MWAjXZI4UW+WeL2qlcKCVldNygRA+yZyYJ81J0vucFqttFrjcsg71fGGkfMrw/prllYr s62cJsyH1sHH1uYh6zinv3IkaGz+K22dMUfntK38Lc3iWs38xZsZFlIoWR6TgiW9UbTOb+j3ps3uW EBT8wemGGjDRMOfU/x+VASUDVPUBWGll42g0O5fkcmYMwmDhd+IZbzmUQCBjZTAQ8qykgvAUdZOg1 Xp2/Ptvg==; Received: from wrigleys.postgresql.org ([2a02:16a8:dc51::60]) by mahout.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1x7Oc0-001pbR-2j for pgsql-bugs@lists.postgresql.org; Fri, 18 Sep 2026 02:46:04 +0000 Received: from localhost ([127.0.0.1] helo=wrigleys.postgresql.org) by wrigleys.postgresql.org with esmtp (Exim 4.98.2) (envelope-from ) id 1x7Obz-00000006ovm-3LSH for pgsql-bugs@lists.postgresql.org; Fri, 18 Sep 2026 02:46:03 +0000 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Subject: BUG #19695: JSON_VALUE ... RETURNING jsonb returns NULL for later evaluation once one evaluation returns NULL To: pgsql-bugs@lists.postgresql.org From: PG Bug reporting form Cc: chaitanyyachoudhary@gmail.com Reply-To: chaitanyyachoudhary@gmail.com, pgsql-bugs@lists.postgresql.org Date: Fri, 18 Sep 2026 02:45:17 +0000 Message-ID: <19695-2f2c573ef1660737@postgresql.org> X-Auto-Response-Suppress: All Auto-Submitted: auto-generated List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk The following bug has been logged on the website: Bug reference: 19695 Logged by: Chaitanya Choudhary Email address: chaitanyyachoudhary@gmail.com PostgreSQL version: 18.6 Operating system: macOS 26 (aarch64), Homebrew build of 18.6 Description: =20 Within one statement, after a JSON_VALUE(... RETURNING jsonb) or RETURNING json evaluation yields SQL NULL, every later evaluation of that expression in the same statement also yields NULL, even when the input has a value. Other RETURNING types are not affected. Steps to reproduce: SELECT JSON_VALUE('123', '$' RETURNING jsonb), JSON_VALUE('null', '$' RETURNING jsonb); -- 123 | (null) correct SELECT JSON_VALUE('null', '$' RETURNING jsonb), JSON_VALUE('123', '$' RETURNING jsonb); -- (null) | (null) expected (null) | 123 The same across rows of a scan: SELECT JSON_VALUE(x, '$' RETURNING jsonb) FROM (VALUES ('1'::jsonb), ('null'), ('2')) v(x); -- 1, (null), (null) expected 1, (null), 2 SELECT JSON_VALUE(x, '$' RETURNING jsonb) FROM (VALUES ('1'::jsonb), ('2')) v(x); -- 1, 2 correct: no NULL came first RETURNING int is not affected: SELECT JSON_VALUE('null', '$' RETURNING int), JSON_VALUE('123', '$' RETURNING int); -- (null) | 123 A NULL produced by a JSON null item, by EMPTY (no match), or by an error converted to NULL under NULL ON ERROR all trigger it. RETURNING json behaves like RETURNING jsonb. JSON_QUERY and JSON_EXISTS are not affected. Notes on the cause: The result depends on what earlier rows or earlier calls in the same statement returned, so some state persists across evaluations of the expression. The RETURNING json/jsonb coercion runs through ExecEvalJsonCoercion() in src/backend/executor/execExprInterp.c, which calls json_populate_type() with a per-expression cache (op->d.jsonexpr_coercion.json_coercion_cache) and with op->resnull passed by pointer as the isnull argument. That cache lives for the statement and is the only state shared between the evaluations. I have not traced the exact line where the null is retained. The code involved is unchanged between 18.6 and master as of 2026-09-17.