Thread

Commits

  1. Fix confusion about the return rowtype of SQL-language procedures.

  1. 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
    
  2. 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