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 1rk89H-00AYrj-53 for pgsql-bugs@arkaria.postgresql.org; Tue, 12 Mar 2024 19:50:55 +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 1rk89E-001Se0-TV for pgsql-bugs@arkaria.postgresql.org; Tue, 12 Mar 2024 19:50:53 +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.94.2) (envelope-from ) id 1rk89E-001ScT-Kz for pgsql-bugs@lists.postgresql.org; Tue, 12 Mar 2024 19:50:53 +0000 Received: from sss.pgh.pa.us ([68.162.161.243]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1rk897-004AfH-69 for pgsql-bugs@lists.postgresql.org; Tue, 12 Mar 2024 19:50:51 +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 42CJoh6i1718614; Tue, 12 Mar 2024 15:50:43 -0400 From: Tom Lane To: Yahor Yuzefovich cc: pgsql-bugs@lists.postgresql.org, Peter Eisentraut Subject: Re: A server crash with a SQL procedure returning a user-defined type on 14.8 In-reply-to: References: Comments: In-reply-to Yahor Yuzefovich message dated "Mon, 11 Mar 2024 15:19:37 -0700" MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-ID: <1718612.1710273043.1@sss.pgh.pa.us> Date: Tue, 12 Mar 2024 15:50:43 -0400 Message-ID: <1718613.1710273043@sss.pgh.pa.us> List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk Yahor Yuzefovich writes: > CREATE TYPE typ AS (a INT, b INT); CREATE PROCEDURE p_udt(OUT typ) AS $$ > SELECT (1, 2); $$ LANGUAGE SQL; CALL p_udt(NULL); Thanks for the report. What seems to be happening is that functions.c is getting confused as to whether it should return a record containing a record, or just a record. check_sql_fn_retval explains: * If the target list has one non-junk entry, and that expression has * or can be coerced to the declared return type, take it as the * result. This allows, for example, 'SELECT func2()', where func2 * has the same composite return type as the function that's calling * it. This provision creates some ambiguity --- maybe the expression * was meant to be the lone field of the composite result --- but it * works well enough as long as we don't get too enthusiastic about * inventing coercions from scalar to composite types. As far as I know, that is fine for functions. But it's not fine for procedures: those are marked as returning RECORD if there are any output parameters at all, and the code for CALL expects that it's going to get back a record containing one column per output parameter, so we can't flatten that into a record containing two ints. This has been busted since we invented procedures, I think. This is easy to fix if we add a parameter to check_sql_fn_retval indicating whether we're considering a function or a procedure. While that's not problematic in HEAD, I'm worried that there might be external callers of that function in the back branches. I guess we can use the old trick of making the existing function into a wrapper in the back branches. regards, tom lane