Re: The output sql generated by pg_dump for a create function refers to a modified table name - Mailing list pgsql-hackers

From Jonathan S. Katz
Subject Re: The output sql generated by pg_dump for a create function refers to a modified table name
Date
Msg-id 7aec721c-f75a-c769-55c3-2130e9159506@postgresql.org
Whole thread Raw
In response to The output sql generated by pg_dump for a create function refers to a modified table name  (vignesh C <vignesh21@gmail.com>)
Responses Re: The output sql generated by pg_dump for a create function refers to a modified table name
List pgsql-hackers
On 2/17/23 5:22 AM, vignesh C wrote:
> Hi,
> 
> The output sql generated by pg_dump for the below function refers to a
> modified table name:
> create table t1 (c1 int);
> create table t2 (c1 int);
> 
> CREATE OR REPLACE FUNCTION test_fun(c1 int)
> RETURNS void
> LANGUAGE SQL
> BEGIN  ATOMIC
>       WITH delete_t1 AS (
>           DELETE FROM t1 WHERE c1 = $1
>       )
>       INSERT INTO t1 (c1) SELECT $1 FROM t2;
> END;
> 
> The below sql output created by pg_dump refers to t1_1 which should
> have been t1:
> CREATE FUNCTION public.test_fun(c1 integer) RETURNS void
>      LANGUAGE sql
>      BEGIN ATOMIC
>   WITH delete_t1 AS (
>            DELETE FROM public.t1
>             WHERE (t1_1.c1 = test_fun.c1)
>           )
>    INSERT INTO public.t1 (c1)  SELECT test_fun.c1
>              FROM public.t2;
> END;
> 
> pg_get_function_sqlbody also returns similar result:
> select proname, pg_get_function_sqlbody(oid) from pg_proc where
> proname = 'test_fun';
>   proname  |          pg_get_function_sqlbody
> ----------+-------------------------------------------
>   test_fun | BEGIN ATOMIC                             +
>            |  WITH delete_t1 AS (                     +
>            |           DELETE FROM t1                 +
>            |            WHERE (t1_1.c1 = test_fun.c1) +
>            |          )                               +
>            |   INSERT INTO t1 (c1)  SELECT test_fun.c1+
>            |             FROM t2;                     +
>            | END
> (1 row)

Thanks for reproducing and demonstrating that this was more generally 
applicable. For context, this was initially discovered when testing the 
DDL replication patch[1] under that context.

> I felt the problem here is with set_rtable_names function which
> changes the relation name t1 to t1_1 while parsing the statement:
> /*
> * If the selected name isn't unique, append digits to make it so, and
> * make a new hash entry for it once we've got a unique name.  For a
> * very long input name, we might have to truncate to stay within
> * NAMEDATALEN.
> */
> 
> During the query generation we will set the table names before
> generating each statement, in our case the table t1 would have been
> added already to the hash table during the first insert statement
> generation. Next time it will try to set the relation names again for
> the next statement, i.e delete statement, if the entry with same name
> already exists, it will change the name to t1_1 by appending a digit
> to keep the has entry unique.

Good catch. Do you have thoughts on how we can adjust the naming logic 
to handle cases like this?

Jonathan

[1] 
https://www.postgresql.org/message-id/e947fa21-24b2-f922-375a-d4f763ef3e4b%40postgresql.org

Attachment

pgsql-hackers by date:

Previous
From: Laurenz Albe
Date:
Subject: Re: Move defaults toward ICU in 16?
Next
From: "Drouvot, Bertrand"
Date:
Subject: Re: Change xl_hash_vacuum_one_page.ntuples from int to uint16