temp table same name real table

Started by v.brusa@joinsnc.comover 5 years ago5 messagesgeneral
Jump to latest
#1v.brusa@joinsnc.com
v.brusa@joinsnc.com

Hi all,
I have this strange behavior when I use temp table with same name of a
permanent table in a function.
Postgres version is:
PostgreSQL 11.3 (Debian 11.3-1.pgdg90+1) on x86_64-pc-linux-gnu,
compiled by gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516, 64-bit
I use a query panel from pgAdmin

droptableifexists taba;
createtable taba (cola text);
insertinto taba(cola) values ('val_permanent');

createorreplacefunction test_temp_table(_is_temp
boolean, scan refcursor) RETURNS refcursor AS
$BODY$
BEGIN
if _is_temp then
createtemptable taba oncommitdropasselect * from public.taba withnodata;
insertinto taba(cola) values ('val_temp');
else

endif;

open scan for
select * from taba;

return scan;

END;
$BODY$
LANGUAGE plpgsql VOLATILE;

select test_temp_table(true,'scan'); fetchallfrom scan;
-- return data in temp table taba that is 'val_temp'

select test_temp_table(false,'scan'); fetchallfrom scan;
-- return data in permanent table taba that is 'val_permanent'

select test_temp_table(true,'scan'); fetchallfrom scan;
-- return data in permanent table taba that is 'val_permanent' and dont see temporary table

If I force a change in search_path the code works correctly.

droptableifexists taba;
createtable taba (cola text);
insertinto taba(cola) values ('val_permanent');

createorreplacefunction test_temp_table(_is_temp
boolean, scan refcursor) RETURNS refcursor AS
$BODY$
BEGIN

if _is_temp then
set search_path=pg_temp,public;
createtemptable taba oncommitdropasselect * from public.taba withnodata;
insertinto taba(cola) values ('val_temp');
else
set search_path=public;
endif;

open scan for
select * from taba;

return scan;

END;
$BODY$
LANGUAGE plpgsql VOLATILE;

select test_temp_table(true,'scan'); fetchallfrom scan;
-- return data in temp table taba that is 'val_temp'

select test_temp_table(false,'scan'); fetchallfrom scan;
-- return data in permanent table taba that is 'val_permanent'

select test_temp_table(true,'scan'); fetchallfrom scan;
-- return data in temp table taba that is 'val_temp'

it would seem that whenfunctionreferences permanent
tablefirsttimeinnext calling (select * from taba;)
temptableisnotandisnottrue postgres documentation (Existing permanent
tableswith the same name are not visible to the currentsessionwhile the
temporarytableexists, unless they are referenced withschema-qualified
names)

any idea?

thanks

Vittorio Brusa Zappellini

#2Michael Lewis
mlewis@entrata.com
In reply to: v.brusa@joinsnc.com (#1)
Re: temp table same name real table

On Wed, Sep 30, 2020, 7:27 AM v.brusa@joinsnc.com <v.brusa@joinsnc.com>
wrote:

Hi all,
I have this strange behavior when I use temp table with same name of a
permanent table in a function.

IMO, you are asking for strange behavior when you overload a table name.

I expect that one of the people who work down deep down in the code will
say it is a caching thing that saves system table lookups. It also may be
required to ensure consistent behavior when you use the same table name
(non specified schema) then you should always get the same table.

Still, it might be simple to use exceptions and try to read the pg_temp
table and if it does not exist, try the public schema.

Or, just schema qualify the fetch call with a string that is computed for
which schema you want to use.

Show quoted text
#3Tom Lane
tgl@sss.pgh.pa.us
In reply to: Michael Lewis (#2)
Re: temp table same name real table

Michael Lewis <mlewis@entrata.com> writes:

IMO, you are asking for strange behavior when you overload a table name.

I expect that one of the people who work down deep down in the code will
say it is a caching thing that saves system table lookups.

Yeah, I think that on the second call, plpgsql caches a query plan that
references the permanent table, and then it sees no reason to reconsider
that plan on the third call. (Change of search_path is one of the
conditions that would prompt throwing away the cached plan, which
fits that part of the report. But creating a temp table that happens
to shadow a real table is not one.)

If you really really need to do this, I'd counsel using EXECUTE to
ensure no caching happens. But I concur with Michael that it's
fundamentally a bad idea.

regards, tom lane

#4David G. Johnston
david.g.johnston@gmail.com
In reply to: Tom Lane (#3)
Re: temp table same name real table

On Wed, Sep 30, 2020 at 7:41 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:

If you really really need to do this, I'd counsel using EXECUTE to
ensure no caching happens. But I concur with Michael that it's
fundamentally a bad idea.

Agreed, though the documentation seems a bit loose here. The fact that the
temp table hides the permanent one is a side-effect of pg_temp being placed
first in the default search_path. If it is explicitly placed last the
permanent table would be found again.

Adding a reminder that search_path searching happens only during new plan
creation (even if we don't generally cover caching implementation in
detail, though I didn't look around for this one) seems like a good value.

I propose the following:

diff --git a/doc/src/sgml/ref/create_table.sgml
b/doc/src/sgml/ref/create_table.sgml
index 087cad184c..a400334092 100644
--- a/doc/src/sgml/ref/create_table.sgml
+++ b/doc/src/sgml/ref/create_table.sgml
@@ -171,8 +171,9 @@ WITH ( MODULUS <replaceable
class="parameter">numeric_literal</replaceable>, REM
       If specified, the table is created as a temporary table.
       Temporary tables are automatically dropped at the end of a
       session, or optionally at the end of the current transaction
-      (see <literal>ON COMMIT</literal> below).  Existing permanent
-      tables with the same name are not visible to the current session
+      (see <literal>ON COMMIT</literal> below).  The default
+      search_path includes the temporary schema first and so identically
+      named existing permanent tables are not chosen for new plans
       while the temporary table exists, unless they are referenced
       with schema-qualified names. Any indexes created on a temporary
       table are automatically temporary as well.

David J.

#5David G. Johnston
david.g.johnston@gmail.com
In reply to: David G. Johnston (#4)
Re: temp table same name real table

Moving this over to -hackers and the commitfest

/messages/by-id/CAKFQuwaZjsaQ9KdDKjcwgGo3axg2t0BdBVYJiHf=H9nbvsxQbQ@mail.gmail.com

David J.

On Thu, Oct 1, 2020 at 5:14 PM David G. Johnston <david.g.johnston@gmail.com>
wrote:

Show quoted text

On Wed, Sep 30, 2020 at 7:41 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:

If you really really need to do this, I'd counsel using EXECUTE to
ensure no caching happens. But I concur with Michael that it's
fundamentally a bad idea.

Agreed, though the documentation seems a bit loose here. The fact that
the temp table hides the permanent one is a side-effect of pg_temp being
placed first in the default search_path. If it is explicitly placed last
the permanent table would be found again.

Adding a reminder that search_path searching happens only during new plan
creation (even if we don't generally cover caching implementation in
detail, though I didn't look around for this one) seems like a good value.

I propose the following:

diff --git a/doc/src/sgml/ref/create_table.sgml
b/doc/src/sgml/ref/create_table.sgml
index 087cad184c..a400334092 100644
--- a/doc/src/sgml/ref/create_table.sgml
+++ b/doc/src/sgml/ref/create_table.sgml
@@ -171,8 +171,9 @@ WITH ( MODULUS <replaceable
class="parameter">numeric_literal</replaceable>, REM
If specified, the table is created as a temporary table.
Temporary tables are automatically dropped at the end of a
session, or optionally at the end of the current transaction
-      (see <literal>ON COMMIT</literal> below).  Existing permanent
-      tables with the same name are not visible to the current session
+      (see <literal>ON COMMIT</literal> below).  The default
+      search_path includes the temporary schema first and so identically
+      named existing permanent tables are not chosen for new plans
while the temporary table exists, unless they are referenced
with schema-qualified names. Any indexes created on a temporary
table are automatically temporary as well.

David J.