On Tue, Apr 6, 2021 at 8:18 PM Himanshu Upadhyaya
<upadhyaya.himan...@gmail.com> wrote:
>
> Hi,
>
> While working on one of the issue, I have noticed below unexpected behavior 
> with "PREPARE TRANSACTION".
>
> We are getting this unexpected behavior with PREPARE TRANSACTION when it is 
> mixed with Temporary Objects. Please consider the below setup and SQL block.
>
> set max_prepared_transactions to 1 (or any non zero value), this is to enable 
> the “prepare transaction”.
>
> Now please try to run the below set of statements.
> [BLOCK-1:]
> postgres=# create temp table fullname (first text, last text);
> CREATE TABLE
> postgres=# BEGIN;
> BEGIN
> postgres=*# create function longname(fullname) returns text language sql
> postgres-*# as $$select $1.first || ' ' || $1.last$$;
> CREATE FUNCTION
> postgres=*# prepare transaction 'mytran';
> ERROR:  cannot PREPARE a transaction that has operated on temporary objects
>
> Above error is expected.
>
> The problem is if we again try to create the same function in the “PREPARE 
> TRANSACTION” as below.
>
> [BLOCK-2:]
> postgres=# BEGIN;
> BEGIN
> postgres=*# create function longname(fullname) returns text language sql
> as $$select $1.first || ' ' || $1.last$$;
> CREATE FUNCTION
> postgres=*# PREPARE transaction 'mytran';
> PREPARE TRANSACTION
>
> Now, this time we succeed and not getting the above error (”ERROR:  cannot 
> PREPARE a transaction that has operated on temporary objects), like the way 
> we were getting with BLOCK-1
>
> This is happening because we set MyXactFlags in relation_open function call, 
> and here relation_open is getting called from load_typcache_tupdesc, but in 
> the second run of “create function…” in the above #2 block will not call 
> load_typcache_tupdesc because of the below condition(typentry->tupDesc == 
> NULL) in  lookup_type_cache().
>
>         /*
>          * If it's a composite type (row type), get tupdesc if requested
>          */
>         if ((flags & TYPECACHE_TUPDESC) &&
>                 typentry->tupDesc == NULL &&
>                 typentry->typtype == TYPTYPE_COMPOSITE)
>         {
>                 load_typcache_tupdesc(typentry);
>         }
>
> We set typentry->tupDesc to non NULL(and populates it with proper tuple 
> descriptor in the cache) value during our first call to “create function…” in 
> BLOCK-1.
> We have logic in file xact.c::PrepareTransaction() to simply error out if we 
> have accessed any temporary object in the current transaction but because of 
> the above-described issue of not setting XACT_FLAGS_ACCESSEDTEMPNAMESPACE in 
> MyXactFlags second run of “create function..” Works and PREPARE TRANSACTION 
> succeeds(but it should fail).
>
> Please find attached the proposed patch to FIX this issue.

I was able to reproduce the issue with your patch and your patch fixes
the issue.

Few comments:
1) We can drop the table after this test.
+CREATE TEMP TABLE temp_tbl (first TEXT, last TEXT);
+BEGIN;
+CREATE FUNCTION longname(temp_tbl) RETURNS TEXT LANGUAGE SQL
+AS $$SELECT $1.first || ' ' || $1.last$$;
+PREPARE TRANSACTION 'temp_tbl_access';
+
+BEGIN;
+CREATE FUNCTION longname(temp_tbl) RETURNS TEXT LANGUAGE SQL
+AS $$SELECT $1.first || ' ' || $1.last$$;
+PREPARE TRANSACTION 'temp_tbl_access';

2) +-- Test for accessing Temporary table
+-- in prepare transaction.
can be changed to
-- Test for accessing cached temporary table in a prepared transaction.

3) +-- These cases must fail and generate errors about Temporary objects.
can be changed to
-- These cases should fail with cannot access temporary object error.

Regards,
Vignesh


Reply via email to