Thread
Commits
-
Fix confusion about the return rowtype of SQL-language procedures.
- 6ee3261e9bb6 17.0 landed
- dc1503d5b8b3 12.19 landed
- 6f66fadad91b 15.7 landed
- 649bbba1134d 14.12 landed
- 40d1bdeb72b2 16.3 landed
- 28184f039e33 13.15 landed
-
A server crash with a SQL procedure returning a user-defined type on 14.8
Yahor Yuzefovich <yahor@cockroachlabs.com> — 2024-03-11T22:19:37Z
Hello there, I believe I encountered a bug with the following reproduction steps: CREATE TYPE typ AS (a INT, b INT); CREATE PROCEDURE p_udt(OUT typ) AS $$ SELECT (1, 2); $$ LANGUAGE SQL; CALL p_udt(NULL); which results in a server crash on version 14.8: server closed the connection unexpectedly This probably means the server terminated abnormally before or while processing the request. The connection to the server was lost. Attempting reset: WARNING: terminating connection because of crash of another server process DETAIL: The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory. HINT: In a moment you should be able to reconnect to the database and repeat your command. Failed. Best, Yahor Yuzefovich
-
Re: A server crash with a SQL procedure returning a user-defined type on 14.8
Tom Lane <tgl@sss.pgh.pa.us> — 2024-03-12T19:50:43Z
Yahor Yuzefovich <yahor@cockroachlabs.com> 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