mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	Support explicit placement of the temporary-table schema within search_path.
This is needed to allow a security-definer function to set a truly secure value of search_path. Without it, a malicious user can use temporary objects to execute code with the privileges of the security-definer function. Even pushing the temp schema to the back of the search path is not quite good enough, because a function or operator at the back of the path might still capture control from one nearer the front due to having a more exact datatype match. Hence, disable searching the temp schema altogether for functions and operators. Security: CVE-2007-2138
This commit is contained in:
		@@ -1,4 +1,4 @@
 | 
				
			|||||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.121 2007/04/18 16:44:17 alvherre Exp $ -->
 | 
					<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.122 2007/04/20 02:37:37 tgl Exp $ -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<chapter Id="runtime-config">
 | 
					<chapter Id="runtime-config">
 | 
				
			||||||
  <title>Server Configuration</title>
 | 
					  <title>Server Configuration</title>
 | 
				
			||||||
@@ -3405,9 +3405,17 @@ SELECT * FROM parent WHERE key = 2400;
 | 
				
			|||||||
        mentioned in the path then it will be searched in the specified
 | 
					        mentioned in the path then it will be searched in the specified
 | 
				
			||||||
        order.  If <literal>pg_catalog</> is not in the path then it will
 | 
					        order.  If <literal>pg_catalog</> is not in the path then it will
 | 
				
			||||||
        be searched <emphasis>before</> searching any of the path items.
 | 
					        be searched <emphasis>before</> searching any of the path items.
 | 
				
			||||||
        It should also be noted that the temporary-table schema,
 | 
					       </para>
 | 
				
			||||||
        <literal>pg_temp_<replaceable>nnn</></>, is implicitly searched before any of
 | 
					
 | 
				
			||||||
        these.
 | 
					       <para>
 | 
				
			||||||
 | 
					        Likewise, the current session's temporary-table schema,
 | 
				
			||||||
 | 
					        <literal>pg_temp_<replaceable>nnn</></>, is always searched if it
 | 
				
			||||||
 | 
					        exists.  It can be explicitly listed in the path by using the
 | 
				
			||||||
 | 
					        alias <literal>pg_temp</>.  If it is not listed in the path then
 | 
				
			||||||
 | 
					        it is searched first (before even <literal>pg_catalog</>).  However,
 | 
				
			||||||
 | 
					        the temporary schema is only searched for relation (table, view,
 | 
				
			||||||
 | 
					        sequence, etc) and data type names.  It will never be searched for
 | 
				
			||||||
 | 
					        function or operator names.
 | 
				
			||||||
       </para>
 | 
					       </para>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
       <para>
 | 
					       <para>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
<!--
 | 
					<!--
 | 
				
			||||||
$PostgreSQL: pgsql/doc/src/sgml/ref/create_function.sgml,v 1.73 2007/02/01 19:10:24 momjian Exp $
 | 
					$PostgreSQL: pgsql/doc/src/sgml/ref/create_function.sgml,v 1.74 2007/04/20 02:37:37 tgl Exp $
 | 
				
			||||||
-->
 | 
					-->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<refentry id="SQL-CREATEFUNCTION">
 | 
					<refentry id="SQL-CREATEFUNCTION">
 | 
				
			||||||
@@ -508,6 +508,54 @@ SELECT * FROM dup(42);
 | 
				
			|||||||
  </para>
 | 
					  </para>
 | 
				
			||||||
 </refsect1>
 | 
					 </refsect1>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 <refsect1 id="sql-createfunction-security">
 | 
				
			||||||
 | 
					  <title>Writing <literal>SECURITY DEFINER</literal> Functions Safely</title>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   <para>
 | 
				
			||||||
 | 
					    Because a <literal>SECURITY DEFINER</literal> function is executed
 | 
				
			||||||
 | 
					    with the privileges of the user that created it, care is needed to
 | 
				
			||||||
 | 
					    ensure that the function cannot be misused.  For security,
 | 
				
			||||||
 | 
					    <xref linkend="guc-search-path"> should be set to exclude any schemas
 | 
				
			||||||
 | 
					    writable by untrusted users.  This prevents
 | 
				
			||||||
 | 
					    malicious users from creating objects that mask objects used by the
 | 
				
			||||||
 | 
					    function.  Particularly important is in this regard is the
 | 
				
			||||||
 | 
					    temporary-table schema, which is searched first by default, and
 | 
				
			||||||
 | 
					    is normally writable by anyone.  A secure arrangement can be had
 | 
				
			||||||
 | 
					    by forcing the temporary schema to be searched last.  To do this,
 | 
				
			||||||
 | 
					    write <literal>pg_temp</> as the last entry in <varname>search_path</>.
 | 
				
			||||||
 | 
					    This function illustrates safe usage:
 | 
				
			||||||
 | 
					   </para>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<programlisting>
 | 
				
			||||||
 | 
					CREATE FUNCTION check_password(uname TEXT, pass TEXT)
 | 
				
			||||||
 | 
					RETURNS BOOLEAN AS $$
 | 
				
			||||||
 | 
					DECLARE passed BOOLEAN;
 | 
				
			||||||
 | 
					        old_path TEXT;
 | 
				
			||||||
 | 
					BEGIN
 | 
				
			||||||
 | 
					        -- Save old search_path; notice we must qualify current_setting
 | 
				
			||||||
 | 
					        -- to ensure we invoke the right function
 | 
				
			||||||
 | 
					        old_path := pg_catalog.current_setting('search_path');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        -- Set a secure search_path: trusted schemas, then 'pg_temp'.
 | 
				
			||||||
 | 
					        -- We set is_local = true so that the old value will be restored
 | 
				
			||||||
 | 
					        -- in event of an error before we reach the function end.
 | 
				
			||||||
 | 
					        PERFORM pg_catalog.set_config('search_path', 'admin, pg_temp', true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        -- Do whatever secure work we came for.
 | 
				
			||||||
 | 
					        SELECT  (pwd = $2) INTO passed
 | 
				
			||||||
 | 
					        FROM    pwds
 | 
				
			||||||
 | 
					        WHERE   username = $1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        -- Restore caller's search_path
 | 
				
			||||||
 | 
					        PERFORM pg_catalog.set_config('search_path', old_path, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        RETURN passed;
 | 
				
			||||||
 | 
					END;
 | 
				
			||||||
 | 
					$$ LANGUAGE plpgsql SECURITY DEFINER;
 | 
				
			||||||
 | 
					</programlisting>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 </refsect1>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 <refsect1 id="sql-createfunction-compat">
 | 
					 <refsect1 id="sql-createfunction-compat">
 | 
				
			||||||
  <title>Compatibility</title>
 | 
					  <title>Compatibility</title>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/release.sgml,v 1.500 2007/04/19 13:02:49 momjian Exp $ -->
 | 
					<!-- $PostgreSQL: pgsql/doc/src/sgml/release.sgml,v 1.501 2007/04/20 02:37:37 tgl Exp $ -->
 | 
				
			||||||
<!--
 | 
					<!--
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Typical markup:
 | 
					Typical markup:
 | 
				
			||||||
@@ -44,7 +44,8 @@ do it for earlier branch release files.
 | 
				
			|||||||
   </note>
 | 
					   </note>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   <para>
 | 
					   <para>
 | 
				
			||||||
    This release contains fixes from 8.2.3.
 | 
					    This release contains a variety of fixes from 8.2.3,
 | 
				
			||||||
 | 
					    including a security fix.
 | 
				
			||||||
   </para>
 | 
					   </para>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   <sect2>
 | 
					   <sect2>
 | 
				
			||||||
@@ -63,8 +64,24 @@ do it for earlier branch release files.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
     <listitem>
 | 
					     <listitem>
 | 
				
			||||||
     <para>
 | 
					     <para>
 | 
				
			||||||
      Fix <varname>shared_preload_libraries</> for Win32 by forcing reload in each backend
 | 
					      Support explicit placement of the temporary-table schema within
 | 
				
			||||||
      (Korry Douglas)
 | 
					      <varname>search_path</>, and disable searching it for functions
 | 
				
			||||||
 | 
					      and operators (Tom)
 | 
				
			||||||
 | 
					     </para>
 | 
				
			||||||
 | 
					     <para>
 | 
				
			||||||
 | 
					      This is needed to allow a security-definer function to set a
 | 
				
			||||||
 | 
					      truly secure value of <varname>search_path</>.  Without it,
 | 
				
			||||||
 | 
					      an unprivileged SQL user can use temporary objects to execute code
 | 
				
			||||||
 | 
					      with the privileges of the security-definer function (CVE-2007-2138).
 | 
				
			||||||
 | 
					      See <xref linkend="sql-createfunction"
 | 
				
			||||||
 | 
					      endterm="sql-createfunction-title"> for more information.
 | 
				
			||||||
 | 
					     </para>
 | 
				
			||||||
 | 
					     </listitem>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     <listitem>
 | 
				
			||||||
 | 
					     <para>
 | 
				
			||||||
 | 
					      Fix <varname>shared_preload_libraries</> for Windows
 | 
				
			||||||
 | 
					      by forcing reload in each backend (Korry Douglas)
 | 
				
			||||||
     </para>
 | 
					     </para>
 | 
				
			||||||
     </listitem>
 | 
					     </listitem>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -77,20 +94,21 @@ do it for earlier branch release files.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
     <listitem>
 | 
					     <listitem>
 | 
				
			||||||
     <para>
 | 
					     <para>
 | 
				
			||||||
      <filename>/contrib/tsearch2</> fixes (Teodor)
 | 
					      <filename>/contrib/tsearch2</> crash fixes (Teodor)
 | 
				
			||||||
     </para>
 | 
					     </para>
 | 
				
			||||||
     </listitem>
 | 
					     </listitem>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
     <listitem>
 | 
					     <listitem>
 | 
				
			||||||
     <para>
 | 
					     <para>
 | 
				
			||||||
      Require <command>COMMIT TRANSACTION</> to be executed in the same database as
 | 
					      Require <command>COMMIT PREPARED</> to be executed in the same
 | 
				
			||||||
      it was prepared (Heikki)
 | 
					      database as the transaction was prepared in (Heikki)
 | 
				
			||||||
     </para>
 | 
					     </para>
 | 
				
			||||||
     </listitem>
 | 
					     </listitem>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
     <listitem>
 | 
					     <listitem>
 | 
				
			||||||
     <para>
 | 
					     <para>
 | 
				
			||||||
      Allow Win32 <command>pg_dump</> to do binary backups larger than two gigabytes (Magnus)
 | 
					      Allow <command>pg_dump</> to do binary backups larger than two gigabytes
 | 
				
			||||||
 | 
					      on Windows (Magnus)
 | 
				
			||||||
     </para>
 | 
					     </para>
 | 
				
			||||||
     </listitem>
 | 
					     </listitem>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -108,13 +126,8 @@ do it for earlier branch release files.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
     <listitem>
 | 
					     <listitem>
 | 
				
			||||||
     <para>
 | 
					     <para>
 | 
				
			||||||
      Improve detection of <acronym>POSIX</>-style time zone names (Tom)
 | 
					      Fix potential-data-corruption bug in how <command>VACUUM FULL</> handles
 | 
				
			||||||
     </para>
 | 
					      <command>UPDATE</> chains (Tom, Pavan Deolasee)
 | 
				
			||||||
     </listitem>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
     <listitem>
 | 
					 | 
				
			||||||
     <para>
 | 
					 | 
				
			||||||
      Fix bug in how <command>VACUUM FULL</> handles <command>UPDATE</> chains (Tom, Pavan Deolasee)
 | 
					 | 
				
			||||||
     </para>
 | 
					     </para>
 | 
				
			||||||
     </listitem>
 | 
					     </listitem>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -126,14 +139,36 @@ do it for earlier branch release files.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
     <listitem>
 | 
					     <listitem>
 | 
				
			||||||
     <para>
 | 
					     <para>
 | 
				
			||||||
      Fix <command>pg_dump</> so it can dump a sequence using <option>-t</> when not also dumping the owning table
 | 
					      Fix <command>pg_dump</> so it can dump a serial column's sequence
 | 
				
			||||||
 | 
					      using <option>-t</> when not also dumping the owning table
 | 
				
			||||||
      (Tom)
 | 
					      (Tom)
 | 
				
			||||||
     </para>
 | 
					     </para>
 | 
				
			||||||
     </listitem>
 | 
					     </listitem>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
     <listitem>
 | 
					     <listitem>
 | 
				
			||||||
     <para>
 | 
					     <para>
 | 
				
			||||||
      Improve outer join and bitmap join selection logic (Tom)
 | 
					      Planner fixes, including improving outer join and bitmap scan
 | 
				
			||||||
 | 
					      selection logic (Tom)
 | 
				
			||||||
 | 
					     </para>
 | 
				
			||||||
 | 
					     </listitem>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     <listitem>
 | 
				
			||||||
 | 
					     <para>
 | 
				
			||||||
 | 
					      Fix possible wrong answers or crash when a PL/pgSQL function tries
 | 
				
			||||||
 | 
					      to <literal>RETURN</> from within an <literal>EXCEPTION</> block
 | 
				
			||||||
 | 
					      (Tom)
 | 
				
			||||||
 | 
					     </para>
 | 
				
			||||||
 | 
					     </listitem>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     <listitem>
 | 
				
			||||||
 | 
					     <para>
 | 
				
			||||||
 | 
					      Fix PANIC during enlargement of a hash index (Tom)
 | 
				
			||||||
 | 
					     </para>
 | 
				
			||||||
 | 
					     </listitem>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     <listitem>
 | 
				
			||||||
 | 
					     <para>
 | 
				
			||||||
 | 
					      Fix POSIX-style timezone specs to follow new USA DST rules (Tom)
 | 
				
			||||||
     </para>
 | 
					     </para>
 | 
				
			||||||
     </listitem>
 | 
					     </listitem>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -3040,7 +3075,8 @@ do it for earlier branch release files.
 | 
				
			|||||||
   </note>
 | 
					   </note>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   <para>
 | 
					   <para>
 | 
				
			||||||
    This release contains fixes from 8.1.8.
 | 
					    This release contains a variety of fixes from 8.1.8,
 | 
				
			||||||
 | 
					    including a security fix.
 | 
				
			||||||
   </para>
 | 
					   </para>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   <sect2>
 | 
					   <sect2>
 | 
				
			||||||
@@ -3061,39 +3097,57 @@ do it for earlier branch release files.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
     <listitem>
 | 
					     <listitem>
 | 
				
			||||||
     <para>
 | 
					     <para>
 | 
				
			||||||
      Fix <function>to_char()</> so it properly upper/lower cases localized day or month
 | 
					      Support explicit placement of the temporary-table schema within
 | 
				
			||||||
      names (Pavel Stehule)
 | 
					      <varname>search_path</>, and disable searching it for functions
 | 
				
			||||||
 | 
					      and operators (Tom)
 | 
				
			||||||
 | 
					     </para>
 | 
				
			||||||
 | 
					     <para>
 | 
				
			||||||
 | 
					      This is needed to allow a security-definer function to set a
 | 
				
			||||||
 | 
					      truly secure value of <varname>search_path</>.  Without it,
 | 
				
			||||||
 | 
					      an unprivileged SQL user can use temporary objects to execute code
 | 
				
			||||||
 | 
					      with the privileges of the security-definer function (CVE-2007-2138).
 | 
				
			||||||
 | 
					      See <xref linkend="sql-createfunction"
 | 
				
			||||||
 | 
					      endterm="sql-createfunction-title"> for more information.
 | 
				
			||||||
     </para>
 | 
					     </para>
 | 
				
			||||||
     </listitem>
 | 
					     </listitem>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
     <listitem>
 | 
					     <listitem>
 | 
				
			||||||
     <para>
 | 
					     <para>
 | 
				
			||||||
      <filename>/contrib/tsearch2</> fixes (Teodor)
 | 
					      <filename>/contrib/tsearch2</> crash fixes (Teodor)
 | 
				
			||||||
     </para>
 | 
					     </para>
 | 
				
			||||||
     </listitem>
 | 
					     </listitem>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
     <listitem>
 | 
					     <listitem>
 | 
				
			||||||
     <para>
 | 
					     <para>
 | 
				
			||||||
      Require <command>COMMIT TRANSACTION</> to be executed in the same database as
 | 
					      Require <command>COMMIT PREPARED</> to be executed in the same
 | 
				
			||||||
      it was prepared (Heikki)
 | 
					      database as the transaction was prepared in (Heikki)
 | 
				
			||||||
     </para>
 | 
					     </para>
 | 
				
			||||||
     </listitem>
 | 
					     </listitem>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
     <listitem>
 | 
					     <listitem>
 | 
				
			||||||
     <para>
 | 
					     <para>
 | 
				
			||||||
      Improve detection of <acronym>POSIX</>-style time zone names (Tom)
 | 
					      Fix potential-data-corruption bug in how <command>VACUUM FULL</> handles
 | 
				
			||||||
 | 
					      <command>UPDATE</> chains (Tom, Pavan Deolasee)
 | 
				
			||||||
     </para>
 | 
					     </para>
 | 
				
			||||||
     </listitem>
 | 
					     </listitem>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
     <listitem>
 | 
					     <listitem>
 | 
				
			||||||
     <para>
 | 
					     <para>
 | 
				
			||||||
      Fix bug in how <command>VACUUM FULL</> handles <command>UPDATE</> chains (Tom, Pavan Deolasee)
 | 
					      Planner fixes, including improving outer join and bitmap scan
 | 
				
			||||||
 | 
					      selection logic (Tom)
 | 
				
			||||||
     </para>
 | 
					     </para>
 | 
				
			||||||
     </listitem>
 | 
					     </listitem>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
     <listitem>
 | 
					     <listitem>
 | 
				
			||||||
     <para>
 | 
					     <para>
 | 
				
			||||||
      Improve outer join and bitmap join selection logic (Tom)
 | 
					      Fix PANIC during enlargement of a hash index (bug introduced in 8.1.6)
 | 
				
			||||||
 | 
					      (Tom)
 | 
				
			||||||
 | 
					     </para>
 | 
				
			||||||
 | 
					     </listitem>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     <listitem>
 | 
				
			||||||
 | 
					     <para>
 | 
				
			||||||
 | 
					      Fix POSIX-style timezone specs to follow new USA DST rules (Tom)
 | 
				
			||||||
     </para>
 | 
					     </para>
 | 
				
			||||||
     </listitem>
 | 
					     </listitem>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -6061,7 +6115,8 @@ psql -t -f fixseq.sql db1 | psql -e db1
 | 
				
			|||||||
   </note>
 | 
					   </note>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   <para>
 | 
					   <para>
 | 
				
			||||||
    This release contains fixes from 8.0.12.
 | 
					    This release contains a variety of fixes from 8.0.12,
 | 
				
			||||||
 | 
					    including a security fix.
 | 
				
			||||||
   </para>
 | 
					   </para>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   <sect2>
 | 
					   <sect2>
 | 
				
			||||||
@@ -6082,25 +6137,43 @@ psql -t -f fixseq.sql db1 | psql -e db1
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
     <listitem>
 | 
					     <listitem>
 | 
				
			||||||
     <para>
 | 
					     <para>
 | 
				
			||||||
      <filename>/contrib/tsearch2</> fixes (Teodor)
 | 
					      Support explicit placement of the temporary-table schema within
 | 
				
			||||||
 | 
					      <varname>search_path</>, and disable searching it for functions
 | 
				
			||||||
 | 
					      and operators (Tom)
 | 
				
			||||||
 | 
					     </para>
 | 
				
			||||||
 | 
					     <para>
 | 
				
			||||||
 | 
					      This is needed to allow a security-definer function to set a
 | 
				
			||||||
 | 
					      truly secure value of <varname>search_path</>.  Without it,
 | 
				
			||||||
 | 
					      an unprivileged SQL user can use temporary objects to execute code
 | 
				
			||||||
 | 
					      with the privileges of the security-definer function (CVE-2007-2138).
 | 
				
			||||||
 | 
					      See <xref linkend="sql-createfunction"
 | 
				
			||||||
 | 
					      endterm="sql-createfunction-title"> for more information.
 | 
				
			||||||
     </para>
 | 
					     </para>
 | 
				
			||||||
     </listitem>
 | 
					     </listitem>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
     <listitem>
 | 
					     <listitem>
 | 
				
			||||||
     <para>
 | 
					     <para>
 | 
				
			||||||
      Improve detection of <acronym>POSIX</>-style time zone names (Tom)
 | 
					      <filename>/contrib/tsearch2</> crash fixes (Teodor)
 | 
				
			||||||
     </para>
 | 
					     </para>
 | 
				
			||||||
     </listitem>
 | 
					     </listitem>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
     <listitem>
 | 
					     <listitem>
 | 
				
			||||||
     <para>
 | 
					     <para>
 | 
				
			||||||
      Fix bug in how <command>VACUUM FULL</> handles <command>UPDATE</> chains (Tom, Pavan Deolasee)
 | 
					      Fix potential-data-corruption bug in how <command>VACUUM FULL</> handles
 | 
				
			||||||
 | 
					      <command>UPDATE</> chains (Tom, Pavan Deolasee)
 | 
				
			||||||
     </para>
 | 
					     </para>
 | 
				
			||||||
     </listitem>
 | 
					     </listitem>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
     <listitem>
 | 
					     <listitem>
 | 
				
			||||||
     <para>
 | 
					     <para>
 | 
				
			||||||
      <filename>/contrib/tsearch2</> fixes (Teodor)
 | 
					      Fix PANIC during enlargement of a hash index (bug introduced in 8.0.10)
 | 
				
			||||||
 | 
					      (Tom)
 | 
				
			||||||
 | 
					     </para>
 | 
				
			||||||
 | 
					     </listitem>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     <listitem>
 | 
				
			||||||
 | 
					     <para>
 | 
				
			||||||
 | 
					      Fix POSIX-style timezone specs to follow new USA DST rules (Tom)
 | 
				
			||||||
     </para>
 | 
					     </para>
 | 
				
			||||||
     </listitem>
 | 
					     </listitem>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -9552,7 +9625,8 @@ typedefs (Michael)</para></listitem>
 | 
				
			|||||||
   </note>
 | 
					   </note>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   <para>
 | 
					   <para>
 | 
				
			||||||
    This release contains a variety of fixes from 7.4.16.
 | 
					    This release contains fixes from 7.4.16,
 | 
				
			||||||
 | 
					    including a security fix.
 | 
				
			||||||
   </para>
 | 
					   </para>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   <sect2>
 | 
					   <sect2>
 | 
				
			||||||
@@ -9573,13 +9647,37 @@ typedefs (Michael)</para></listitem>
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
     <listitem>
 | 
					     <listitem>
 | 
				
			||||||
     <para>
 | 
					     <para>
 | 
				
			||||||
      <filename>/contrib/tsearch2</> fixes (Teodor)
 | 
					      Support explicit placement of the temporary-table schema within
 | 
				
			||||||
 | 
					      <varname>search_path</>, and disable searching it for functions
 | 
				
			||||||
 | 
					      and operators (Tom)
 | 
				
			||||||
 | 
					     </para>
 | 
				
			||||||
 | 
					     <para>
 | 
				
			||||||
 | 
					      This is needed to allow a security-definer function to set a
 | 
				
			||||||
 | 
					      truly secure value of <varname>search_path</>.  Without it,
 | 
				
			||||||
 | 
					      an unprivileged SQL user can use temporary objects to execute code
 | 
				
			||||||
 | 
					      with the privileges of the security-definer function (CVE-2007-2138).
 | 
				
			||||||
 | 
					      See <xref linkend="sql-createfunction"
 | 
				
			||||||
 | 
					      endterm="sql-createfunction-title"> for more information.
 | 
				
			||||||
     </para>
 | 
					     </para>
 | 
				
			||||||
     </listitem>
 | 
					     </listitem>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
     <listitem>
 | 
					     <listitem>
 | 
				
			||||||
     <para>
 | 
					     <para>
 | 
				
			||||||
      Fix bug in how <command>VACUUM FULL</> handles <command>UPDATE</> chains (Tom, Pavan Deolasee)
 | 
					      <filename>/contrib/tsearch2</> crash fixes (Teodor)
 | 
				
			||||||
 | 
					     </para>
 | 
				
			||||||
 | 
					     </listitem>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     <listitem>
 | 
				
			||||||
 | 
					     <para>
 | 
				
			||||||
 | 
					      Fix potential-data-corruption bug in how <command>VACUUM FULL</> handles
 | 
				
			||||||
 | 
					      <command>UPDATE</> chains (Tom, Pavan Deolasee)
 | 
				
			||||||
 | 
					     </para>
 | 
				
			||||||
 | 
					     </listitem>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     <listitem>
 | 
				
			||||||
 | 
					     <para>
 | 
				
			||||||
 | 
					      Fix PANIC during enlargement of a hash index (bug introduced in 7.4.15)
 | 
				
			||||||
 | 
					      (Tom)
 | 
				
			||||||
     </para>
 | 
					     </para>
 | 
				
			||||||
     </listitem>
 | 
					     </listitem>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -12714,7 +12812,8 @@ DROP SCHEMA information_schema CASCADE;
 | 
				
			|||||||
   </note>
 | 
					   </note>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   <para>
 | 
					   <para>
 | 
				
			||||||
    This release contains a variety of fixes from 7.3.18.
 | 
					    This release contains fixes from 7.3.18,
 | 
				
			||||||
 | 
					    including a security fix.
 | 
				
			||||||
   </para>
 | 
					   </para>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   <sect2>
 | 
					   <sect2>
 | 
				
			||||||
@@ -12735,7 +12834,24 @@ DROP SCHEMA information_schema CASCADE;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
     <listitem>
 | 
					     <listitem>
 | 
				
			||||||
     <para>
 | 
					     <para>
 | 
				
			||||||
      Fix bug in how <command>VACUUM FULL</> handles <command>UPDATE</> chains (Tom, Pavan Deolasee)
 | 
					      Support explicit placement of the temporary-table schema within
 | 
				
			||||||
 | 
					      <varname>search_path</>, and disable searching it for functions
 | 
				
			||||||
 | 
					      and operators (Tom)
 | 
				
			||||||
 | 
					     </para>
 | 
				
			||||||
 | 
					     <para>
 | 
				
			||||||
 | 
					      This is needed to allow a security-definer function to set a
 | 
				
			||||||
 | 
					      truly secure value of <varname>search_path</>.  Without it,
 | 
				
			||||||
 | 
					      an unprivileged SQL user can use temporary objects to execute code
 | 
				
			||||||
 | 
					      with the privileges of the security-definer function (CVE-2007-2138).
 | 
				
			||||||
 | 
					      See <xref linkend="sql-createfunction"
 | 
				
			||||||
 | 
					      endterm="sql-createfunction-title"> for more information.
 | 
				
			||||||
 | 
					     </para>
 | 
				
			||||||
 | 
					     </listitem>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     <listitem>
 | 
				
			||||||
 | 
					     <para>
 | 
				
			||||||
 | 
					      Fix potential-data-corruption bug in how <command>VACUUM FULL</> handles
 | 
				
			||||||
 | 
					      <command>UPDATE</> chains (Tom, Pavan Deolasee)
 | 
				
			||||||
     </para>
 | 
					     </para>
 | 
				
			||||||
     </listitem>
 | 
					     </listitem>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * IDENTIFICATION
 | 
					 * IDENTIFICATION
 | 
				
			||||||
 *	  $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.138 2007/03/26 16:58:38 tgl Exp $
 | 
					 *	  $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.139 2007/04/20 02:37:37 tgl Exp $
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * NOTES
 | 
					 * NOTES
 | 
				
			||||||
 *	  See acl.h.
 | 
					 *	  See acl.h.
 | 
				
			||||||
@@ -1833,7 +1833,7 @@ pg_namespace_aclmask(Oid nsp_oid, Oid roleid,
 | 
				
			|||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (isTempNamespace(nsp_oid))
 | 
						if (isTempNamespace(nsp_oid))
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (pg_database_aclcheck(MyDatabaseId, GetUserId(),
 | 
							if (pg_database_aclcheck(MyDatabaseId, roleid,
 | 
				
			||||||
								 ACL_CREATE_TEMP) == ACLCHECK_OK)
 | 
													 ACL_CREATE_TEMP) == ACLCHECK_OK)
 | 
				
			||||||
			return mask & ACL_ALL_RIGHTS_NAMESPACE;
 | 
								return mask & ACL_ALL_RIGHTS_NAMESPACE;
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,7 +13,7 @@
 | 
				
			|||||||
 * Portions Copyright (c) 1994, Regents of the University of California
 | 
					 * Portions Copyright (c) 1994, Regents of the University of California
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * IDENTIFICATION
 | 
					 * IDENTIFICATION
 | 
				
			||||||
 *	  $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.95 2007/04/12 22:34:45 neilc Exp $
 | 
					 *	  $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.96 2007/04/20 02:37:37 tgl Exp $
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *-------------------------------------------------------------------------
 | 
					 *-------------------------------------------------------------------------
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@@ -62,12 +62,30 @@
 | 
				
			|||||||
 * SQL99.  Also, this provides a way to search the system namespace first
 | 
					 * SQL99.  Also, this provides a way to search the system namespace first
 | 
				
			||||||
 * without thereby making it the default creation target namespace.)
 | 
					 * without thereby making it the default creation target namespace.)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * For security reasons, searches using the search path will ignore the temp
 | 
				
			||||||
 | 
					 * namespace when searching for any object type other than relations and
 | 
				
			||||||
 | 
					 * types.  (We must allow types since temp tables have rowtypes.)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 * The default creation target namespace is always the first element of the
 | 
					 * The default creation target namespace is always the first element of the
 | 
				
			||||||
 * explicit list.  If the explicit list is empty, there is no default target.
 | 
					 * explicit list.  If the explicit list is empty, there is no default target.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * In bootstrap mode, the search path is set equal to 'pg_catalog', so that
 | 
					 * The textual specification of search_path can include "$user" to refer to
 | 
				
			||||||
 | 
					 * the namespace named the same as the current user, if any.  (This is just
 | 
				
			||||||
 | 
					 * ignored if there is no such namespace.)  Also, it can include "pg_temp"
 | 
				
			||||||
 | 
					 * to refer to the current backend's temp namespace.  This is usually also
 | 
				
			||||||
 | 
					 * ignorable if the temp namespace hasn't been set up, but there's a special
 | 
				
			||||||
 | 
					 * case: if "pg_temp" appears first then it should be the default creation
 | 
				
			||||||
 | 
					 * target.  We kluge this case a little bit so that the temp namespace isn't
 | 
				
			||||||
 | 
					 * set up until the first attempt to create something in it.  (The reason for
 | 
				
			||||||
 | 
					 * klugery is that we can't create the temp namespace outside a transaction,
 | 
				
			||||||
 | 
					 * but initial GUC processing of search_path happens outside a transaction.)
 | 
				
			||||||
 | 
					 * activeTempCreationPending is TRUE if "pg_temp" appears first in the string
 | 
				
			||||||
 | 
					 * but is not reflected in activeCreationNamespace because the namespace isn't
 | 
				
			||||||
 | 
					 * set up yet.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * In bootstrap mode, the search path is set equal to "pg_catalog", so that
 | 
				
			||||||
 * the system namespace is the only one searched or inserted into.
 | 
					 * the system namespace is the only one searched or inserted into.
 | 
				
			||||||
 * initdb is also careful to set search_path to 'pg_catalog' for its
 | 
					 * initdb is also careful to set search_path to "pg_catalog" for its
 | 
				
			||||||
 * post-bootstrap standalone backend runs.	Otherwise the default search
 | 
					 * post-bootstrap standalone backend runs.	Otherwise the default search
 | 
				
			||||||
 * path is determined by GUC.  The factory default path contains the PUBLIC
 | 
					 * path is determined by GUC.  The factory default path contains the PUBLIC
 | 
				
			||||||
 * namespace (if it exists), preceded by the user's personal namespace
 | 
					 * namespace (if it exists), preceded by the user's personal namespace
 | 
				
			||||||
@@ -102,15 +120,20 @@ static List *activeSearchPath = NIL;
 | 
				
			|||||||
/* default place to create stuff; if InvalidOid, no default */
 | 
					/* default place to create stuff; if InvalidOid, no default */
 | 
				
			||||||
static Oid	activeCreationNamespace = InvalidOid;
 | 
					static Oid	activeCreationNamespace = InvalidOid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* if TRUE, activeCreationNamespace is wrong, it should be temp namespace */
 | 
				
			||||||
 | 
					static bool activeTempCreationPending = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* These variables are the values last derived from namespace_search_path: */
 | 
					/* These variables are the values last derived from namespace_search_path: */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static List *baseSearchPath = NIL;
 | 
					static List *baseSearchPath = NIL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static Oid	baseCreationNamespace = InvalidOid;
 | 
					static Oid	baseCreationNamespace = InvalidOid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool baseTempCreationPending = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static Oid	namespaceUser = InvalidOid;
 | 
					static Oid	namespaceUser = InvalidOid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* The above three values are valid only if baseSearchPathValid */
 | 
					/* The above four values are valid only if baseSearchPathValid */
 | 
				
			||||||
static bool baseSearchPathValid = true;
 | 
					static bool baseSearchPathValid = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Override requests are remembered in a stack of OverrideStackEntry structs */
 | 
					/* Override requests are remembered in a stack of OverrideStackEntry structs */
 | 
				
			||||||
@@ -262,6 +285,14 @@ RangeVarGetCreationNamespace(const RangeVar *newRelation)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	if (newRelation->schemaname)
 | 
						if (newRelation->schemaname)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 | 
							/* check for pg_temp alias */
 | 
				
			||||||
 | 
							if (strcmp(newRelation->schemaname, "pg_temp") == 0)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								/* Initialize temp namespace if first time through */
 | 
				
			||||||
 | 
								if (!OidIsValid(myTempNamespace))
 | 
				
			||||||
 | 
									InitTempTableNamespace();
 | 
				
			||||||
 | 
								return myTempNamespace;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		/* use exact schema given */
 | 
							/* use exact schema given */
 | 
				
			||||||
		namespaceId = GetSysCacheOid(NAMESPACENAME,
 | 
							namespaceId = GetSysCacheOid(NAMESPACENAME,
 | 
				
			||||||
									 CStringGetDatum(newRelation->schemaname),
 | 
														 CStringGetDatum(newRelation->schemaname),
 | 
				
			||||||
@@ -277,6 +308,12 @@ RangeVarGetCreationNamespace(const RangeVar *newRelation)
 | 
				
			|||||||
	{
 | 
						{
 | 
				
			||||||
		/* use the default creation namespace */
 | 
							/* use the default creation namespace */
 | 
				
			||||||
		recomputeNamespacePath();
 | 
							recomputeNamespacePath();
 | 
				
			||||||
 | 
							if (activeTempCreationPending)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								/* Need to initialize temp namespace */
 | 
				
			||||||
 | 
								InitTempTableNamespace();
 | 
				
			||||||
 | 
								return myTempNamespace;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		namespaceId = activeCreationNamespace;
 | 
							namespaceId = activeCreationNamespace;
 | 
				
			||||||
		if (!OidIsValid(namespaceId))
 | 
							if (!OidIsValid(namespaceId))
 | 
				
			||||||
			ereport(ERROR,
 | 
								ereport(ERROR,
 | 
				
			||||||
@@ -549,12 +586,16 @@ FuncnameGetCandidates(List *names, int nargs)
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			/* Consider only procs that are in the search path */
 | 
								/*
 | 
				
			||||||
 | 
								 * Consider only procs that are in the search path and are not
 | 
				
			||||||
 | 
								 * in the temp namespace.
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
			ListCell   *nsp;
 | 
								ListCell   *nsp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			foreach(nsp, activeSearchPath)
 | 
								foreach(nsp, activeSearchPath)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				if (procform->pronamespace == lfirst_oid(nsp))
 | 
									if (procform->pronamespace == lfirst_oid(nsp) &&
 | 
				
			||||||
 | 
										procform->pronamespace != myTempNamespace)
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				pathpos++;
 | 
									pathpos++;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@@ -770,6 +811,9 @@ OpernameGetOprid(List *names, Oid oprleft, Oid oprright)
 | 
				
			|||||||
		Oid			namespaceId = lfirst_oid(l);
 | 
							Oid			namespaceId = lfirst_oid(l);
 | 
				
			||||||
		int			i;
 | 
							int			i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (namespaceId == myTempNamespace)
 | 
				
			||||||
 | 
								continue;			/* do not look in temp namespace */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (i = 0; i < catlist->n_members; i++)
 | 
							for (i = 0; i < catlist->n_members; i++)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			HeapTuple	opertup = &catlist->members[i]->tuple;
 | 
								HeapTuple	opertup = &catlist->members[i]->tuple;
 | 
				
			||||||
@@ -872,12 +916,16 @@ OpernameGetCandidates(List *names, char oprkind)
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			/* Consider only opers that are in the search path */
 | 
								/*
 | 
				
			||||||
 | 
								 * Consider only opers that are in the search path and are not
 | 
				
			||||||
 | 
								 * in the temp namespace.
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
			ListCell   *nsp;
 | 
								ListCell   *nsp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			foreach(nsp, activeSearchPath)
 | 
								foreach(nsp, activeSearchPath)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				if (operform->oprnamespace == lfirst_oid(nsp))
 | 
									if (operform->oprnamespace == lfirst_oid(nsp) &&
 | 
				
			||||||
 | 
										operform->oprnamespace != myTempNamespace)
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				pathpos++;
 | 
									pathpos++;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@@ -1025,6 +1073,9 @@ OpclassnameGetOpcid(Oid amid, const char *opcname)
 | 
				
			|||||||
	{
 | 
						{
 | 
				
			||||||
		Oid			namespaceId = lfirst_oid(l);
 | 
							Oid			namespaceId = lfirst_oid(l);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (namespaceId == myTempNamespace)
 | 
				
			||||||
 | 
								continue;			/* do not look in temp namespace */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		opcid = GetSysCacheOid(CLAAMNAMENSP,
 | 
							opcid = GetSysCacheOid(CLAAMNAMENSP,
 | 
				
			||||||
							   ObjectIdGetDatum(amid),
 | 
												   ObjectIdGetDatum(amid),
 | 
				
			||||||
							   PointerGetDatum(opcname),
 | 
												   PointerGetDatum(opcname),
 | 
				
			||||||
@@ -1108,6 +1159,9 @@ OpfamilynameGetOpfid(Oid amid, const char *opfname)
 | 
				
			|||||||
	{
 | 
						{
 | 
				
			||||||
		Oid			namespaceId = lfirst_oid(l);
 | 
							Oid			namespaceId = lfirst_oid(l);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (namespaceId == myTempNamespace)
 | 
				
			||||||
 | 
								continue;			/* do not look in temp namespace */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		opfid = GetSysCacheOid(OPFAMILYAMNAMENSP,
 | 
							opfid = GetSysCacheOid(OPFAMILYAMNAMENSP,
 | 
				
			||||||
							   ObjectIdGetDatum(amid),
 | 
												   ObjectIdGetDatum(amid),
 | 
				
			||||||
							   PointerGetDatum(opfname),
 | 
												   PointerGetDatum(opfname),
 | 
				
			||||||
@@ -1190,6 +1244,9 @@ ConversionGetConid(const char *conname)
 | 
				
			|||||||
	{
 | 
						{
 | 
				
			||||||
		Oid			namespaceId = lfirst_oid(l);
 | 
							Oid			namespaceId = lfirst_oid(l);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (namespaceId == myTempNamespace)
 | 
				
			||||||
 | 
								continue;			/* do not look in temp namespace */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		conid = GetSysCacheOid(CONNAMENSP,
 | 
							conid = GetSysCacheOid(CONNAMENSP,
 | 
				
			||||||
							   PointerGetDatum(conname),
 | 
												   PointerGetDatum(conname),
 | 
				
			||||||
							   ObjectIdGetDatum(namespaceId),
 | 
												   ObjectIdGetDatum(namespaceId),
 | 
				
			||||||
@@ -1316,6 +1373,19 @@ LookupExplicitNamespace(const char *nspname)
 | 
				
			|||||||
	Oid			namespaceId;
 | 
						Oid			namespaceId;
 | 
				
			||||||
	AclResult	aclresult;
 | 
						AclResult	aclresult;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* check for pg_temp alias */
 | 
				
			||||||
 | 
						if (strcmp(nspname, "pg_temp") == 0)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (OidIsValid(myTempNamespace))
 | 
				
			||||||
 | 
								return myTempNamespace;
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * Since this is used only for looking up existing objects, there
 | 
				
			||||||
 | 
							 * is no point in trying to initialize the temp namespace here;
 | 
				
			||||||
 | 
							 * and doing so might create problems for some callers.
 | 
				
			||||||
 | 
							 * Just fall through and give the "does not exist" error.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	namespaceId = GetSysCacheOid(NAMESPACENAME,
 | 
						namespaceId = GetSysCacheOid(NAMESPACENAME,
 | 
				
			||||||
								 CStringGetDatum(nspname),
 | 
													 CStringGetDatum(nspname),
 | 
				
			||||||
								 0, 0, 0);
 | 
													 0, 0, 0);
 | 
				
			||||||
@@ -1336,7 +1406,11 @@ LookupExplicitNamespace(const char *nspname)
 | 
				
			|||||||
 * LookupCreationNamespace
 | 
					 * LookupCreationNamespace
 | 
				
			||||||
 *		Look up the schema and verify we have CREATE rights on it.
 | 
					 *		Look up the schema and verify we have CREATE rights on it.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * This is just like LookupExplicitNamespace except for the permission check.
 | 
					 * This is just like LookupExplicitNamespace except for the permission check,
 | 
				
			||||||
 | 
					 * and that we are willing to create pg_temp if needed.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Note: calling this may result in a CommandCounterIncrement operation,
 | 
				
			||||||
 | 
					 * if we have to create or clean out the temp namespace.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
Oid
 | 
					Oid
 | 
				
			||||||
LookupCreationNamespace(const char *nspname)
 | 
					LookupCreationNamespace(const char *nspname)
 | 
				
			||||||
@@ -1344,6 +1418,15 @@ LookupCreationNamespace(const char *nspname)
 | 
				
			|||||||
	Oid			namespaceId;
 | 
						Oid			namespaceId;
 | 
				
			||||||
	AclResult	aclresult;
 | 
						AclResult	aclresult;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* check for pg_temp alias */
 | 
				
			||||||
 | 
						if (strcmp(nspname, "pg_temp") == 0)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							/* Initialize temp namespace if first time through */
 | 
				
			||||||
 | 
							if (!OidIsValid(myTempNamespace))
 | 
				
			||||||
 | 
								InitTempTableNamespace();
 | 
				
			||||||
 | 
							return myTempNamespace;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	namespaceId = GetSysCacheOid(NAMESPACENAME,
 | 
						namespaceId = GetSysCacheOid(NAMESPACENAME,
 | 
				
			||||||
								 CStringGetDatum(nspname),
 | 
													 CStringGetDatum(nspname),
 | 
				
			||||||
								 0, 0, 0);
 | 
													 0, 0, 0);
 | 
				
			||||||
@@ -1369,21 +1452,28 @@ LookupCreationNamespace(const char *nspname)
 | 
				
			|||||||
 * Note: this does not apply any permissions check.  Callers must check
 | 
					 * Note: this does not apply any permissions check.  Callers must check
 | 
				
			||||||
 * for CREATE rights on the selected namespace when appropriate.
 | 
					 * for CREATE rights on the selected namespace when appropriate.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * This is *not* used for tables.  Hence, the TEMP table namespace is
 | 
					 * Note: calling this may result in a CommandCounterIncrement operation,
 | 
				
			||||||
 * never selected as the creation target.
 | 
					 * if we have to create or clean out the temp namespace.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
Oid
 | 
					Oid
 | 
				
			||||||
QualifiedNameGetCreationNamespace(List *names, char **objname_p)
 | 
					QualifiedNameGetCreationNamespace(List *names, char **objname_p)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char	   *schemaname;
 | 
						char	   *schemaname;
 | 
				
			||||||
	char	   *objname;
 | 
					 | 
				
			||||||
	Oid			namespaceId;
 | 
						Oid			namespaceId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* deconstruct the name list */
 | 
						/* deconstruct the name list */
 | 
				
			||||||
	DeconstructQualifiedName(names, &schemaname, &objname);
 | 
						DeconstructQualifiedName(names, &schemaname, objname_p);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (schemaname)
 | 
						if (schemaname)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 | 
							/* check for pg_temp alias */
 | 
				
			||||||
 | 
							if (strcmp(schemaname, "pg_temp") == 0)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								/* Initialize temp namespace if first time through */
 | 
				
			||||||
 | 
								if (!OidIsValid(myTempNamespace))
 | 
				
			||||||
 | 
									InitTempTableNamespace();
 | 
				
			||||||
 | 
								return myTempNamespace;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		/* use exact schema given */
 | 
							/* use exact schema given */
 | 
				
			||||||
		namespaceId = GetSysCacheOid(NAMESPACENAME,
 | 
							namespaceId = GetSysCacheOid(NAMESPACENAME,
 | 
				
			||||||
									 CStringGetDatum(schemaname),
 | 
														 CStringGetDatum(schemaname),
 | 
				
			||||||
@@ -1398,6 +1488,12 @@ QualifiedNameGetCreationNamespace(List *names, char **objname_p)
 | 
				
			|||||||
	{
 | 
						{
 | 
				
			||||||
		/* use the default creation namespace */
 | 
							/* use the default creation namespace */
 | 
				
			||||||
		recomputeNamespacePath();
 | 
							recomputeNamespacePath();
 | 
				
			||||||
 | 
							if (activeTempCreationPending)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								/* Need to initialize temp namespace */
 | 
				
			||||||
 | 
								InitTempTableNamespace();
 | 
				
			||||||
 | 
								return myTempNamespace;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		namespaceId = activeCreationNamespace;
 | 
							namespaceId = activeCreationNamespace;
 | 
				
			||||||
		if (!OidIsValid(namespaceId))
 | 
							if (!OidIsValid(namespaceId))
 | 
				
			||||||
			ereport(ERROR,
 | 
								ereport(ERROR,
 | 
				
			||||||
@@ -1405,7 +1501,6 @@ QualifiedNameGetCreationNamespace(List *names, char **objname_p)
 | 
				
			|||||||
					 errmsg("no schema has been selected to create in")));
 | 
										 errmsg("no schema has been selected to create in")));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	*objname_p = objname;
 | 
					 | 
				
			||||||
	return namespaceId;
 | 
						return namespaceId;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1634,6 +1729,7 @@ PushOverrideSearchPath(OverrideSearchPath *newpath)
 | 
				
			|||||||
	/* And make it active. */
 | 
						/* And make it active. */
 | 
				
			||||||
	activeSearchPath = entry->searchPath;
 | 
						activeSearchPath = entry->searchPath;
 | 
				
			||||||
	activeCreationNamespace = entry->creationNamespace;
 | 
						activeCreationNamespace = entry->creationNamespace;
 | 
				
			||||||
 | 
						activeTempCreationPending = false;			/* XXX is this OK? */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	MemoryContextSwitchTo(oldcxt);
 | 
						MemoryContextSwitchTo(oldcxt);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -1667,12 +1763,14 @@ PopOverrideSearchPath(void)
 | 
				
			|||||||
		entry = (OverrideStackEntry *) linitial(overrideStack);
 | 
							entry = (OverrideStackEntry *) linitial(overrideStack);
 | 
				
			||||||
		activeSearchPath = entry->searchPath;
 | 
							activeSearchPath = entry->searchPath;
 | 
				
			||||||
		activeCreationNamespace = entry->creationNamespace;
 | 
							activeCreationNamespace = entry->creationNamespace;
 | 
				
			||||||
 | 
							activeTempCreationPending = false;			/* XXX is this OK? */
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		/* If not baseSearchPathValid, this is useless but harmless */
 | 
							/* If not baseSearchPathValid, this is useless but harmless */
 | 
				
			||||||
		activeSearchPath = baseSearchPath;
 | 
							activeSearchPath = baseSearchPath;
 | 
				
			||||||
		activeCreationNamespace = baseCreationNamespace;
 | 
							activeCreationNamespace = baseCreationNamespace;
 | 
				
			||||||
 | 
							activeTempCreationPending = baseTempCreationPending;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1706,6 +1804,10 @@ FindConversionByName(List *name)
 | 
				
			|||||||
		foreach(l, activeSearchPath)
 | 
							foreach(l, activeSearchPath)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			namespaceId = lfirst_oid(l);
 | 
								namespaceId = lfirst_oid(l);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (namespaceId == myTempNamespace)
 | 
				
			||||||
 | 
									continue;			/* do not look in temp namespace */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			conoid = FindConversion(conversion_name, namespaceId);
 | 
								conoid = FindConversion(conversion_name, namespaceId);
 | 
				
			||||||
			if (OidIsValid(conoid))
 | 
								if (OidIsValid(conoid))
 | 
				
			||||||
				return conoid;
 | 
									return conoid;
 | 
				
			||||||
@@ -1731,6 +1833,9 @@ FindDefaultConversionProc(int4 for_encoding, int4 to_encoding)
 | 
				
			|||||||
	{
 | 
						{
 | 
				
			||||||
		Oid			namespaceId = lfirst_oid(l);
 | 
							Oid			namespaceId = lfirst_oid(l);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (namespaceId == myTempNamespace)
 | 
				
			||||||
 | 
								continue;			/* do not look in temp namespace */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		proc = FindDefaultConversion(namespaceId, for_encoding, to_encoding);
 | 
							proc = FindDefaultConversion(namespaceId, for_encoding, to_encoding);
 | 
				
			||||||
		if (OidIsValid(proc))
 | 
							if (OidIsValid(proc))
 | 
				
			||||||
			return proc;
 | 
								return proc;
 | 
				
			||||||
@@ -1752,6 +1857,7 @@ recomputeNamespacePath(void)
 | 
				
			|||||||
	List	   *oidlist;
 | 
						List	   *oidlist;
 | 
				
			||||||
	List	   *newpath;
 | 
						List	   *newpath;
 | 
				
			||||||
	ListCell   *l;
 | 
						ListCell   *l;
 | 
				
			||||||
 | 
						bool		temp_missing;
 | 
				
			||||||
	Oid			firstNS;
 | 
						Oid			firstNS;
 | 
				
			||||||
	MemoryContext oldcxt;
 | 
						MemoryContext oldcxt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1781,6 +1887,7 @@ recomputeNamespacePath(void)
 | 
				
			|||||||
	 * already been accepted.)	Don't make duplicate entries, either.
 | 
						 * already been accepted.)	Don't make duplicate entries, either.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	oidlist = NIL;
 | 
						oidlist = NIL;
 | 
				
			||||||
 | 
						temp_missing = false;
 | 
				
			||||||
	foreach(l, namelist)
 | 
						foreach(l, namelist)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		char	   *curname = (char *) lfirst(l);
 | 
							char	   *curname = (char *) lfirst(l);
 | 
				
			||||||
@@ -1810,6 +1917,21 @@ recomputeNamespacePath(void)
 | 
				
			|||||||
					oidlist = lappend_oid(oidlist, namespaceId);
 | 
										oidlist = lappend_oid(oidlist, namespaceId);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							else if (strcmp(curname, "pg_temp") == 0)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								/* pg_temp --- substitute temp namespace, if any */
 | 
				
			||||||
 | 
								if (OidIsValid(myTempNamespace))
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									if (!list_member_oid(oidlist, myTempNamespace))
 | 
				
			||||||
 | 
										oidlist = lappend_oid(oidlist, myTempNamespace);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									/* If it ought to be the creation namespace, set flag */
 | 
				
			||||||
 | 
									if (oidlist == NIL)
 | 
				
			||||||
 | 
										temp_missing = true;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			/* normal namespace reference */
 | 
								/* normal namespace reference */
 | 
				
			||||||
@@ -1825,7 +1947,9 @@ recomputeNamespacePath(void)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Remember the first member of the explicit list.
 | 
						 * Remember the first member of the explicit list.  (Note: this is
 | 
				
			||||||
 | 
						 * nominally wrong if temp_missing, but we need it anyway to distinguish
 | 
				
			||||||
 | 
						 * explicit from implicit mention of pg_catalog.)
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (oidlist == NIL)
 | 
						if (oidlist == NIL)
 | 
				
			||||||
		firstNS = InvalidOid;
 | 
							firstNS = InvalidOid;
 | 
				
			||||||
@@ -1856,6 +1980,7 @@ recomputeNamespacePath(void)
 | 
				
			|||||||
	list_free(baseSearchPath);
 | 
						list_free(baseSearchPath);
 | 
				
			||||||
	baseSearchPath = newpath;
 | 
						baseSearchPath = newpath;
 | 
				
			||||||
	baseCreationNamespace = firstNS;
 | 
						baseCreationNamespace = firstNS;
 | 
				
			||||||
 | 
						baseTempCreationPending = temp_missing;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Mark the path valid. */
 | 
						/* Mark the path valid. */
 | 
				
			||||||
	baseSearchPathValid = true;
 | 
						baseSearchPathValid = true;
 | 
				
			||||||
@@ -1864,6 +1989,7 @@ recomputeNamespacePath(void)
 | 
				
			|||||||
	/* And make it active. */
 | 
						/* And make it active. */
 | 
				
			||||||
	activeSearchPath = baseSearchPath;
 | 
						activeSearchPath = baseSearchPath;
 | 
				
			||||||
	activeCreationNamespace = baseCreationNamespace;
 | 
						activeCreationNamespace = baseCreationNamespace;
 | 
				
			||||||
 | 
						activeTempCreationPending = baseTempCreationPending;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Clean up. */
 | 
						/* Clean up. */
 | 
				
			||||||
	pfree(rawname);
 | 
						pfree(rawname);
 | 
				
			||||||
@@ -1881,6 +2007,8 @@ InitTempTableNamespace(void)
 | 
				
			|||||||
	char		namespaceName[NAMEDATALEN];
 | 
						char		namespaceName[NAMEDATALEN];
 | 
				
			||||||
	Oid			namespaceId;
 | 
						Oid			namespaceId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Assert(!OidIsValid(myTempNamespace));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * First, do permission check to see if we are authorized to make temp
 | 
						 * First, do permission check to see if we are authorized to make temp
 | 
				
			||||||
	 * tables.	We use a nonstandard error message here since "databasename:
 | 
						 * tables.	We use a nonstandard error message here since "databasename:
 | 
				
			||||||
@@ -1940,16 +2068,6 @@ InitTempTableNamespace(void)
 | 
				
			|||||||
	baseSearchPathValid = false;	/* need to rebuild list */
 | 
						baseSearchPathValid = false;	/* need to rebuild list */
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Remove all temp tables from the temporary namespace.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
ResetTempTableNamespace(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (OidIsValid(myTempNamespace))
 | 
					 | 
				
			||||||
		RemoveTempRelations(myTempNamespace);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * End-of-transaction cleanup for namespaces.
 | 
					 * End-of-transaction cleanup for namespaces.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@@ -1995,6 +2113,7 @@ AtEOXact_Namespace(bool isCommit)
 | 
				
			|||||||
		/* If not baseSearchPathValid, this is useless but harmless */
 | 
							/* If not baseSearchPathValid, this is useless but harmless */
 | 
				
			||||||
		activeSearchPath = baseSearchPath;
 | 
							activeSearchPath = baseSearchPath;
 | 
				
			||||||
		activeCreationNamespace = baseCreationNamespace;
 | 
							activeCreationNamespace = baseCreationNamespace;
 | 
				
			||||||
 | 
							activeTempCreationPending = baseTempCreationPending;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2046,12 +2165,14 @@ AtEOSubXact_Namespace(bool isCommit, SubTransactionId mySubid,
 | 
				
			|||||||
		entry = (OverrideStackEntry *) linitial(overrideStack);
 | 
							entry = (OverrideStackEntry *) linitial(overrideStack);
 | 
				
			||||||
		activeSearchPath = entry->searchPath;
 | 
							activeSearchPath = entry->searchPath;
 | 
				
			||||||
		activeCreationNamespace = entry->creationNamespace;
 | 
							activeCreationNamespace = entry->creationNamespace;
 | 
				
			||||||
 | 
							activeTempCreationPending = false;			/* XXX is this OK? */
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		/* If not baseSearchPathValid, this is useless but harmless */
 | 
							/* If not baseSearchPathValid, this is useless but harmless */
 | 
				
			||||||
		activeSearchPath = baseSearchPath;
 | 
							activeSearchPath = baseSearchPath;
 | 
				
			||||||
		activeCreationNamespace = baseCreationNamespace;
 | 
							activeCreationNamespace = baseCreationNamespace;
 | 
				
			||||||
 | 
							activeTempCreationPending = baseTempCreationPending;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2099,6 +2220,16 @@ RemoveTempRelationsCallback(int code, Datum arg)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Remove all temp tables from the temporary namespace.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					ResetTempTableNamespace(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (OidIsValid(myTempNamespace))
 | 
				
			||||||
 | 
							RemoveTempRelations(myTempNamespace);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Routines for handling the GUC variable 'search_path'.
 | 
					 * Routines for handling the GUC variable 'search_path'.
 | 
				
			||||||
@@ -2132,8 +2263,9 @@ assign_search_path(const char *newval, bool doit, GucSource source)
 | 
				
			|||||||
	{
 | 
						{
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * Verify that all the names are either valid namespace names or
 | 
							 * Verify that all the names are either valid namespace names or
 | 
				
			||||||
		 * "$user".  We do not require $user to correspond to a valid
 | 
							 * "$user" or "pg_temp".  We do not require $user to correspond to a
 | 
				
			||||||
		 * namespace.  We do not check for USAGE rights, either; should we?
 | 
							 * valid namespace, and pg_temp might not exist yet.  We do not check
 | 
				
			||||||
 | 
							 * for USAGE rights, either; should we?
 | 
				
			||||||
		 *
 | 
							 *
 | 
				
			||||||
		 * When source == PGC_S_TEST, we are checking the argument of an ALTER
 | 
							 * When source == PGC_S_TEST, we are checking the argument of an ALTER
 | 
				
			||||||
		 * DATABASE SET or ALTER USER SET command.	It could be that the
 | 
							 * DATABASE SET or ALTER USER SET command.	It could be that the
 | 
				
			||||||
@@ -2147,6 +2279,8 @@ assign_search_path(const char *newval, bool doit, GucSource source)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			if (strcmp(curname, "$user") == 0)
 | 
								if (strcmp(curname, "$user") == 0)
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
 | 
								if (strcmp(curname, "pg_temp") == 0)
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
			if (!SearchSysCacheExists(NAMESPACENAME,
 | 
								if (!SearchSysCacheExists(NAMESPACENAME,
 | 
				
			||||||
									  CStringGetDatum(curname),
 | 
														  CStringGetDatum(curname),
 | 
				
			||||||
									  0, 0, 0))
 | 
														  0, 0, 0))
 | 
				
			||||||
@@ -2190,10 +2324,12 @@ InitializeSearchPath(void)
 | 
				
			|||||||
		baseSearchPath = list_make1_oid(PG_CATALOG_NAMESPACE);
 | 
							baseSearchPath = list_make1_oid(PG_CATALOG_NAMESPACE);
 | 
				
			||||||
		MemoryContextSwitchTo(oldcxt);
 | 
							MemoryContextSwitchTo(oldcxt);
 | 
				
			||||||
		baseCreationNamespace = PG_CATALOG_NAMESPACE;
 | 
							baseCreationNamespace = PG_CATALOG_NAMESPACE;
 | 
				
			||||||
 | 
							baseTempCreationPending = false;
 | 
				
			||||||
		baseSearchPathValid = true;
 | 
							baseSearchPathValid = true;
 | 
				
			||||||
		namespaceUser = GetUserId();
 | 
							namespaceUser = GetUserId();
 | 
				
			||||||
		activeSearchPath = baseSearchPath;
 | 
							activeSearchPath = baseSearchPath;
 | 
				
			||||||
		activeCreationNamespace = baseCreationNamespace;
 | 
							activeCreationNamespace = baseCreationNamespace;
 | 
				
			||||||
 | 
							activeTempCreationPending = baseTempCreationPending;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
@@ -2227,6 +2363,9 @@ NamespaceCallback(Datum arg, Oid relid)
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 * The returned list includes the implicitly-prepended namespaces only if
 | 
					 * The returned list includes the implicitly-prepended namespaces only if
 | 
				
			||||||
 * includeImplicit is true.
 | 
					 * includeImplicit is true.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Note: calling this may result in a CommandCounterIncrement operation,
 | 
				
			||||||
 | 
					 * if we have to create or clean out the temp namespace.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
List *
 | 
					List *
 | 
				
			||||||
fetch_search_path(bool includeImplicit)
 | 
					fetch_search_path(bool includeImplicit)
 | 
				
			||||||
@@ -2235,6 +2374,19 @@ fetch_search_path(bool includeImplicit)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	recomputeNamespacePath();
 | 
						recomputeNamespacePath();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * If the temp namespace should be first, force it to exist.  This is
 | 
				
			||||||
 | 
						 * so that callers can trust the result to reflect the actual default
 | 
				
			||||||
 | 
						 * creation namespace.  It's a bit bogus to do this here, since
 | 
				
			||||||
 | 
						 * current_schema() is supposedly a stable function without side-effects,
 | 
				
			||||||
 | 
						 * but the alternatives seem worse.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (activeTempCreationPending)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							InitTempTableNamespace();
 | 
				
			||||||
 | 
							recomputeNamespacePath();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	result = list_copy(activeSearchPath);
 | 
						result = list_copy(activeSearchPath);
 | 
				
			||||||
	if (!includeImplicit)
 | 
						if (!includeImplicit)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -137,3 +137,61 @@ CREATE TEMP TABLE temptest4(col int REFERENCES temptest3);
 | 
				
			|||||||
COMMIT;
 | 
					COMMIT;
 | 
				
			||||||
ERROR:  unsupported ON COMMIT and foreign key combination
 | 
					ERROR:  unsupported ON COMMIT and foreign key combination
 | 
				
			||||||
DETAIL:  Table "temptest4" references "temptest3", but they do not have the same ON COMMIT setting.
 | 
					DETAIL:  Table "temptest4" references "temptest3", but they do not have the same ON COMMIT setting.
 | 
				
			||||||
 | 
					-- Test manipulation of temp schema's placement in search path
 | 
				
			||||||
 | 
					create table public.whereami (f1 text);
 | 
				
			||||||
 | 
					insert into public.whereami values ('public');
 | 
				
			||||||
 | 
					create temp table whereami (f1 text);
 | 
				
			||||||
 | 
					insert into whereami values ('temp');
 | 
				
			||||||
 | 
					create function public.whoami() returns text
 | 
				
			||||||
 | 
					  as $$select 'public'::text$$ language sql;
 | 
				
			||||||
 | 
					create function pg_temp.whoami() returns text
 | 
				
			||||||
 | 
					  as $$select 'temp'::text$$ language sql;
 | 
				
			||||||
 | 
					-- default should have pg_temp implicitly first, but only for tables
 | 
				
			||||||
 | 
					select * from whereami;
 | 
				
			||||||
 | 
					  f1  
 | 
				
			||||||
 | 
					------
 | 
				
			||||||
 | 
					 temp
 | 
				
			||||||
 | 
					(1 row)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					select whoami();
 | 
				
			||||||
 | 
					 whoami 
 | 
				
			||||||
 | 
					--------
 | 
				
			||||||
 | 
					 public
 | 
				
			||||||
 | 
					(1 row)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- can list temp first explicitly, but it still doesn't affect functions
 | 
				
			||||||
 | 
					set search_path = pg_temp, public;
 | 
				
			||||||
 | 
					select * from whereami;
 | 
				
			||||||
 | 
					  f1  
 | 
				
			||||||
 | 
					------
 | 
				
			||||||
 | 
					 temp
 | 
				
			||||||
 | 
					(1 row)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					select whoami();
 | 
				
			||||||
 | 
					 whoami 
 | 
				
			||||||
 | 
					--------
 | 
				
			||||||
 | 
					 public
 | 
				
			||||||
 | 
					(1 row)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- or put it last for security
 | 
				
			||||||
 | 
					set search_path = public, pg_temp;
 | 
				
			||||||
 | 
					select * from whereami;
 | 
				
			||||||
 | 
					   f1   
 | 
				
			||||||
 | 
					--------
 | 
				
			||||||
 | 
					 public
 | 
				
			||||||
 | 
					(1 row)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					select whoami();
 | 
				
			||||||
 | 
					 whoami 
 | 
				
			||||||
 | 
					--------
 | 
				
			||||||
 | 
					 public
 | 
				
			||||||
 | 
					(1 row)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- you can invoke a temp function explicitly, though
 | 
				
			||||||
 | 
					select pg_temp.whoami();
 | 
				
			||||||
 | 
					 whoami 
 | 
				
			||||||
 | 
					--------
 | 
				
			||||||
 | 
					 temp
 | 
				
			||||||
 | 
					(1 row)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					drop table public.whereami;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -118,3 +118,36 @@ BEGIN;
 | 
				
			|||||||
CREATE TEMP TABLE temptest3(col int PRIMARY KEY) ON COMMIT DELETE ROWS;
 | 
					CREATE TEMP TABLE temptest3(col int PRIMARY KEY) ON COMMIT DELETE ROWS;
 | 
				
			||||||
CREATE TEMP TABLE temptest4(col int REFERENCES temptest3);
 | 
					CREATE TEMP TABLE temptest4(col int REFERENCES temptest3);
 | 
				
			||||||
COMMIT;
 | 
					COMMIT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- Test manipulation of temp schema's placement in search path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					create table public.whereami (f1 text);
 | 
				
			||||||
 | 
					insert into public.whereami values ('public');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					create temp table whereami (f1 text);
 | 
				
			||||||
 | 
					insert into whereami values ('temp');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					create function public.whoami() returns text
 | 
				
			||||||
 | 
					  as $$select 'public'::text$$ language sql;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					create function pg_temp.whoami() returns text
 | 
				
			||||||
 | 
					  as $$select 'temp'::text$$ language sql;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- default should have pg_temp implicitly first, but only for tables
 | 
				
			||||||
 | 
					select * from whereami;
 | 
				
			||||||
 | 
					select whoami();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- can list temp first explicitly, but it still doesn't affect functions
 | 
				
			||||||
 | 
					set search_path = pg_temp, public;
 | 
				
			||||||
 | 
					select * from whereami;
 | 
				
			||||||
 | 
					select whoami();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- or put it last for security
 | 
				
			||||||
 | 
					set search_path = public, pg_temp;
 | 
				
			||||||
 | 
					select * from whereami;
 | 
				
			||||||
 | 
					select whoami();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- you can invoke a temp function explicitly, though
 | 
				
			||||||
 | 
					select pg_temp.whoami();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					drop table public.whereami;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user