Re: The output sql generated by pg_dump for a create function refers to a modified table name

From: "Jonathan S(dot) Katz" <jkatz(at)postgresql(dot)org>
To: vignesh C <vignesh21(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: The output sql generated by pg_dump for a create function refers to a modified table name
Date: 2023-02-17 14:06:09
Message-ID: 7aec721c-f75a-c769-55c3-2130e9159506@postgresql.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: 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

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Drouvot, Bertrand 2023-02-17 14:13:17 Re: Change xl_hash_vacuum_one_page.ntuples from int to uint16
Previous Message Laurenz Albe 2023-02-17 12:23:12 Re: Move defaults toward ICU in 16?