Hi,

This small patch implements a new GUC (default_index_tablespace) plus supporting code. Originated from a customer request, the feature intends to make creation of indexes on SSD-backed tablespaces easy and convenient (almost transparent) for users: the DBA can just set it and indexes will be placed in the specified tablespace --as opposed to the same tablespace where the referenced table is-- without having to specify it every time.

Feedback appreciated.



Thanks,

  / J.L.
*** a/doc/src/sgml/config.sgml
--- b/doc/src/sgml/config.sgml
***************
*** 5622,5627 **** COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv;
--- 5622,5664 ----
        </listitem>
       </varlistentry>
  
+      <varlistentry id="guc-default-index-tablespace" 
xreflabel="default_index_tablespace">
+       <term><varname>default_index_tablespace</varname> (<type>string</type>)
+       <indexterm>
+        <primary><varname>default_index_tablespace</> configuration 
parameter</primary>
+       </indexterm>
+       <indexterm><primary>tablespace</><secondary>default</></>
+       </term>
+       <listitem>
+        <para>
+         This variable specifies the default tablespace in which to create
+         indexes when a <command>CREATE INDEX</> command does
+         not explicitly specify a tablespace.
+        </para>
+ 
+        <para>
+         The value is either the name of a tablespace, or an empty string
+         to specify using the default tablespace of the current database
+         unless the <xref linkend="guc-default-tablespace"> is defined,
+         in which case the rules for that parameter apply.
+         If the value does not match the name of any existing tablespace,
+         <productname>PostgreSQL</> will automatically use the default
+         tablespace of the current database; the user must have 
+         <literal>CREATE</> privilege for it, or creation attempts will fail.
+        </para>
+ 
+        <para>
+         This variable is not used for indexes on temporary tables; for them,
+         <xref linkend="guc-temp-tablespaces"> is consulted instead.
+        </para>
+ 
+        <para>
+         For more information on tablespaces,
+         see <xref linkend="manage-ag-tablespaces">.
+        </para>
+       </listitem>
+      </varlistentry>
+ 
       <varlistentry id="guc-temp-tablespaces" xreflabel="temp_tablespaces">
        <term><varname>temp_tablespaces</varname> (<type>string</type>)
        <indexterm>
*** a/src/backend/commands/indexcmds.c
--- b/src/backend/commands/indexcmds.c
***************
*** 417,423 **** DefineIndex(Oid relationId,
        }
        else
        {
!               tablespaceId = 
GetDefaultTablespace(rel->rd_rel->relpersistence);
                /* note InvalidOid is OK in this case */
        }
  
--- 417,423 ----
        }
        else
        {
!               tablespaceId = GetIndexTablespace(rel->rd_rel->relpersistence);
                /* note InvalidOid is OK in this case */
        }
  
*** a/src/backend/commands/tablespace.c
--- b/src/backend/commands/tablespace.c
***************
*** 86,91 ****
--- 86,92 ----
  
  /* GUC variables */
  char     *default_tablespace = NULL;
+ char     *default_index_tblspc = NULL;
  char     *temp_tablespaces = NULL;
  
  
***************
*** 1085,1090 **** GetDefaultTablespace(char relpersistence)
--- 1086,1149 ----
  
  
  /*
+  * GetIndexTablespace -- get the OID of the tablespace for an index
+  *
+  * Temporary objects have different default tablespaces, hence the
+  * relpersistence parameter must be specified.
+  *
+  * May return InvalidOid to indicate "use the database's default tablespace".
+  *
+  * Note that caller is expected to check appropriate permissions for any
+  * result other than InvalidOid.
+  *
+  * This exists to hide (and possibly optimize the use of) the
+  * default_index_tablespace GUC variable.
+  */
+ Oid
+ GetIndexTablespace(char relpersistence)
+ {
+       Oid                     result;
+       const char             *tablespace;
+ 
+       /* The temp-table case is handled elsewhere */
+       if (relpersistence == RELPERSISTENCE_TEMP)
+       {
+               PrepareTempTablespaces();
+               return GetNextTempTableSpace();
+       }
+ 
+       /* Fast path for empty GUC: check defaults */
+       if (default_index_tblspc == NULL || default_index_tblspc[0] == '\0')
+       {
+               /* if default_tablespace is also empty, return immediately */
+               if (default_tablespace == NULL || default_tablespace[0] == '\0')
+                       return InvalidOid;
+                 else
+                         tablespace = default_tablespace;
+       }
+       else
+               tablespace = default_index_tblspc;
+ 
+       /*
+        * It is tempting to cache this lookup for more speed, but then we would
+        * fail to detect the case where the tablespace was dropped since the 
GUC
+        * variable was set.  Note also that we don't complain if the value 
fails
+        * to refer to an existing tablespace; we just silently return 
InvalidOid,
+        * causing the new object to be created in the database's tablespace.
+        */
+       result = get_tablespace_oid(tablespace, true);
+ 
+       /*
+        * Allow explicit specification of database's default tablespace in
+        * default_tablespace without triggering permissions checks.
+        */
+       if (result == MyDatabaseTableSpace)
+               result = InvalidOid;
+       return result;
+ }
+ 
+ 
+ /*
   * Routines for handling the GUC variable 'temp_tablespaces'.
   */
  
*** a/src/backend/utils/misc/guc.c
--- b/src/backend/utils/misc/guc.c
***************
*** 109,114 **** extern int     CommitDelay;
--- 109,115 ----
  extern int    CommitSiblings;
  extern char *default_tablespace;
  extern char *temp_tablespaces;
+ extern char *default_index_tblspc;
  extern bool ignore_checksum_failure;
  extern bool synchronize_seqscans;
  
***************
*** 2894,2899 **** static struct config_string ConfigureNamesString[] =
--- 2895,2911 ----
        },
  
        {
+               {"default_index_tablespace", PGC_USERSET, CLIENT_CONN_STATEMENT,
+                       gettext_noop("Sets the default tablespace to create 
indexes in."),
+                       gettext_noop("An empty string selects the database's 
default tablespace."),
+                       GUC_IS_NAME
+               },
+               &default_index_tblspc,
+               "",
+               check_default_tablespace, NULL, NULL
+       },
+ 
+       {
                {"temp_tablespaces", PGC_USERSET, CLIENT_CONN_STATEMENT,
                        gettext_noop("Sets the tablespace(s) to use for 
temporary tables and sort files."),
                        NULL,
*** a/src/include/commands/tablespace.h
--- b/src/include/commands/tablespace.h
***************
*** 49,54 **** extern Oid       
AlterTableSpaceOptions(AlterTableSpaceOptionsStmt *stmt);
--- 49,55 ----
  extern void TablespaceCreateDbspace(Oid spcNode, Oid dbNode, bool isRedo);
  
  extern Oid    GetDefaultTablespace(char relpersistence);
+ extern Oid    GetIndexTablespace(char relpersistence);
  
  extern void PrepareTempTablespaces(void);
  
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to