Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1oVZcJ-0003nG-4b for pgsql-bugs@arkaria.postgresql.org; Tue, 06 Sep 2022 14:31:55 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1oVZcH-0008Kw-D1 for pgsql-bugs@arkaria.postgresql.org; Tue, 06 Sep 2022 14:31:53 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1oVZcH-0008Kn-4j for pgsql-bugs@lists.postgresql.org; Tue, 06 Sep 2022 14:31:53 +0000 Received: from sss.pgh.pa.us ([66.207.139.130]) by magus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1oVZcE-00066A-Pb for pgsql-bugs@lists.postgresql.org; Tue, 06 Sep 2022 14:31:52 +0000 Received: from sss1.sss.pgh.pa.us (localhost [127.0.0.1]) by sss.pgh.pa.us (8.15.2/8.15.2) with ESMTP id 286EVm1G3160311; Tue, 6 Sep 2022 10:31:48 -0400 From: Tom Lane To: Wilco Kruijer cc: pgsql-bugs@lists.postgresql.org Subject: Re: NULL returned when using RETURNING in main query in combination with a CTE containing FOR UPDATE. In-reply-to: References: Comments: In-reply-to Wilco Kruijer message dated "Tue, 06 Sep 2022 12:28:59 +0200" MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-ID: <3160309.1662474708.1@sss.pgh.pa.us> Date: Tue, 06 Sep 2022 10:31:48 -0400 Message-ID: <3160310.1662474708@sss.pgh.pa.us> List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk Wilco Kruijer writes: > wilco=> with before as ( > select balance from acc_balance where acc_name = 'Wilco' FOR UPDATE > ) > update acc_balance set balance = 300 where acc_name = 'Wilco' > returning balance - (select balance from before) as delta, (select balance > from before limit 1) as before, balance; You seem to be assuming that the WITH query will run before the UPDATE happens. As formulated, it will not, because the UPDATE proper does not use its value. So we don't get around to executing it until the RETURNING clause demands its value. I don't recall exactly why FOR UPDATE causes the already-modified row to not be visible, but if it were visible you'd get the updated balance not the original. So you really want no-FOR-UPDATE semantics here, to see the balance from before the query started. regards, tom lane