]> granicus.if.org Git - postgresql/commitdiff
Add FILLFACTOR to CREATE INDEX.
authorBruce Momjian <bruce@momjian.us>
Sun, 2 Jul 2006 02:23:23 +0000 (02:23 +0000)
committerBruce Momjian <bruce@momjian.us>
Sun, 2 Jul 2006 02:23:23 +0000 (02:23 +0000)
ITAGAKI Takahiro

65 files changed:
doc/src/sgml/ref/alter_index.sgml
doc/src/sgml/ref/alter_table.sgml
doc/src/sgml/ref/create_index.sgml
doc/src/sgml/ref/create_table.sgml
doc/src/sgml/ref/create_table_as.sgml
src/backend/access/common/heaptuple.c
src/backend/access/gin/ginutil.c
src/backend/access/gist/gist.c
src/backend/access/gist/gistutil.c
src/backend/access/gist/gistvacuum.c
src/backend/access/gist/gistxlog.c
src/backend/access/hash/hashpage.c
src/backend/access/hash/hashutil.c
src/backend/access/heap/heapam.c
src/backend/access/heap/hio.c
src/backend/access/index/genam.c
src/backend/access/nbtree/nbtinsert.c
src/backend/access/nbtree/nbtsort.c
src/backend/access/nbtree/nbtutils.c
src/backend/access/transam/xlogutils.c
src/backend/bootstrap/bootparse.y
src/backend/catalog/heap.c
src/backend/catalog/index.c
src/backend/catalog/indexing.c
src/backend/commands/cluster.c
src/backend/commands/define.c
src/backend/commands/indexcmds.c
src/backend/commands/prepare.c
src/backend/commands/sequence.c
src/backend/commands/tablecmds.c
src/backend/commands/typecmds.c
src/backend/commands/vacuum.c
src/backend/commands/vacuumlazy.c
src/backend/commands/view.c
src/backend/executor/execMain.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/nodes/outfuncs.c
src/backend/nodes/readfuncs.c
src/backend/parser/analyze.c
src/backend/parser/gram.y
src/backend/parser/parse_clause.c
src/backend/tcop/utility.c
src/backend/utils/adt/ruleutils.c
src/backend/utils/cache/relcache.c
src/bin/pg_dump/pg_dump.c
src/bin/pg_dump/pg_dump.h
src/include/access/genam.h
src/include/access/gin.h
src/include/access/gist_private.h
src/include/access/hash.h
src/include/access/heapam.h
src/include/access/hio.h
src/include/access/nbtree.h
src/include/catalog/catversion.h
src/include/catalog/heap.h
src/include/catalog/index.h
src/include/catalog/pg_am.h
src/include/catalog/pg_attribute.h
src/include/catalog/pg_class.h
src/include/catalog/pg_proc.h
src/include/commands/defrem.h
src/include/nodes/parsenodes.h
src/include/parser/parse_clause.h
src/include/utils/rel.h

index 929f8709bab71dc0bf49aeaa42f463b9acc36a96..d497dd47afbee917de4c5c78d6f61748f91a38c9 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/alter_index.sgml,v 1.8 2006/02/12 19:11:00 momjian Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/alter_index.sgml,v 1.9 2006/07/02 02:23:17 momjian Exp $
 PostgreSQL documentation
 -->
 
@@ -22,6 +22,8 @@ PostgreSQL documentation
 <synopsis>
 ALTER INDEX <replaceable class="PARAMETER">name</replaceable> RENAME TO <replaceable class="PARAMETER">new_name</replaceable>
 ALTER INDEX <replaceable class="PARAMETER">name</replaceable> SET TABLESPACE <replaceable class="PARAMETER">tablespace_name</replaceable>
+ALTER INDEX <replaceable class="PARAMETER">name</replaceable> SET (FILLFACTOR = <replaceable class="PARAMETER">fillfactor</replaceable>)
+ALTER INDEX <replaceable class="PARAMETER">name</replaceable> RESET (FILLFACTOR)
 </synopsis>
  </refsynopsisdiv>
 
@@ -56,6 +58,26 @@ ALTER INDEX <replaceable class="PARAMETER">name</replaceable> SET TABLESPACE <re
     </listitem>
    </varlistentry>
 
+   <varlistentry>
+    <term><literal>SET (FILLFACTOR)</literal></term>
+    <listitem>
+     <para>
+      This form changes the index's fillfactor to the specified percentage.
+      Index structure is not modified immediately; use <literal>REINDEX</literal>
+      to ensure reflection of the change.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><literal>RESET (FILLFACTOR)</literal></term>
+    <listitem>
+     <para>
+      This form changes the index's fillfactor to the default value.
+     </para>
+    </listitem>
+   </varlistentry>
+
   </variablelist>
   </para>
 
index ee501a1a37261f72cf21f480a846f62df8fb2ce8..ef8e803d6f16ba2b4244643094485af97e2baf60 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/alter_table.sgml,v 1.85 2006/07/02 01:58:36 momjian Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/alter_table.sgml,v 1.86 2006/07/02 02:23:17 momjian Exp $
 PostgreSQL documentation
 -->
 
@@ -46,6 +46,8 @@ where <replaceable class="PARAMETER">action</replaceable> is one of:
     CLUSTER ON <replaceable class="PARAMETER">index_name</replaceable>
     SET WITHOUT CLUSTER
     SET WITHOUT OIDS
+    SET (FILLFACTOR = <replaceable class="PARAMETER">fillfactor</replaceable>)
+    RESET (FILLFACTOR)
     INHERIT <replaceable class="PARAMETER">parent_table</replaceable>
     NO INHERIT <replaceable class="PARAMETER">parent_table</replaceable>
     OWNER TO <replaceable class="PARAMETER">new_owner</replaceable>
@@ -321,6 +323,26 @@ where <replaceable class="PARAMETER">action</replaceable> is one of:
     </listitem>
    </varlistentry>
 
+   <varlistentry>
+    <term><literal>SET (FILLFACTOR)</literal></term>
+    <listitem>
+     <para>
+      This form changes the table's fillfactor to the specified percentage.
+      Table structure is not modified immediately; use <literal>CLUSTER</literal>
+      to ensure reflection of the change.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><literal>RESET</literal></term>
+    <listitem>
+     <para>
+      This form changes the table's fillfactor to the default value.
+     </para>
+    </listitem>
+   </varlistentry>
+
    <varlistentry>
     <term><literal>RENAME</literal></term>
     <listitem>
index 676fa8b4e6e605a483621fb5e282777d557e3112..787184a5e20e7f4ef9444dc08d0ebccb44dc53d3 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/create_index.sgml,v 1.52 2005/11/07 17:36:44 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/create_index.sgml,v 1.53 2006/07/02 02:23:17 momjian Exp $
 PostgreSQL documentation
 -->
 
@@ -22,6 +22,7 @@ PostgreSQL documentation
 <synopsis>
 CREATE [ UNIQUE ] INDEX <replaceable class="parameter">name</replaceable> ON <replaceable class="parameter">table</replaceable> [ USING <replaceable class="parameter">method</replaceable> ]
     ( { <replaceable class="parameter">column</replaceable> | ( <replaceable class="parameter">expression</replaceable> ) } [ <replaceable class="parameter">opclass</replaceable> ] [, ...] )
+    [ WITH (FILLFACTOR = <replaceable>fillfactor</replaceable>) ]
     [ TABLESPACE <replaceable class="parameter">tablespace</replaceable> ]
     [ WHERE <replaceable class="parameter">predicate</replaceable> ]
 </synopsis>
@@ -171,6 +172,15 @@ CREATE [ UNIQUE ] INDEX <replaceable class="parameter">name</replaceable> ON <re
       </listitem>
      </varlistentry>
 
+     <varlistentry>
+      <term><replaceable class="parameter">fillfactor</replaceable></term>
+      <listitem>
+       <para>
+        The index's fillfactor in percentage.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry>
       <term><replaceable class="parameter">tablespace</replaceable></term>
       <listitem>
index 0276dc7ad23fba17374b32210556b49d1ebece0f..c40c37c19ca567c354ff9aa8cc1345ab381a4a03 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/create_table.sgml,v 1.102 2006/06/28 22:01:52 neilc Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/create_table.sgml,v 1.103 2006/07/02 02:23:17 momjian Exp $
 PostgreSQL documentation
 -->
 
@@ -28,6 +28,7 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE <replaceable class="PAR
 ] )
 [ INHERITS ( <replaceable>parent_table</replaceable> [, ... ] ) ]
 [ WITH OIDS | WITHOUT OIDS ]
+[ WITH (FILLFACTOR = <replaceable>fillfactor</replaceable>) ]
 [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
 [ TABLESPACE <replaceable class="PARAMETER">tablespace</replaceable> ]
 
@@ -303,6 +304,15 @@ and <replaceable class="PARAMETER">table_constraint</replaceable> is:
     </listitem>
    </varlistentry>
 
+   <varlistentry>
+    <term><literal>WITH (FILLFACTOR = <replaceable>fillfactor</replaceable>)</literal></term>
+    <listitem>
+     <para>
+      This optional clause specifies the table's fillfactor in percentage.
+     </para>
+    </listitem>
+   </varlistentry>
+
    <varlistentry>
     <term><literal>CONSTRAINT <replaceable class="PARAMETER">constraint_name</replaceable></literal></term>
     <listitem>
index 7e7fa7b6731c5543e4fd78ee93645e276a6d023e..53fb6c0971a95109bddd151966d21f04dd8a3129 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/create_table_as.sgml,v 1.32 2006/02/19 00:04:26 neilc Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/create_table_as.sgml,v 1.33 2006/07/02 02:23:18 momjian Exp $
 PostgreSQL documentation
 -->
 
@@ -23,6 +23,7 @@ PostgreSQL documentation
 CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE <replaceable>table_name</replaceable>
     [ (<replaceable>column_name</replaceable> [, ...] ) ]
     [ WITH OIDS | WITHOUT OIDS ]
+    [ WITH (FILLFACTOR = <replaceable>fillfactor</replaceable>) ]
     [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
     [ TABLESPACE <replaceable class="PARAMETER">tablespace</replaceable> ]
     AS <replaceable>query</replaceable>
@@ -116,6 +117,15 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE <replaceable>table_name
      </listitem>
    </varlistentry>
 
+   <varlistentry>
+    <term><literal>WITH (FILLFACTOR = <replaceable>fillfactor</replaceable>)</literal></term>
+    <listitem>
+     <para>
+      This optional clause specifies the table's fillfactor in percentage.
+     </para>
+    </listitem>
+   </varlistentry>
+
    <varlistentry>
     <term><literal>ON COMMIT</literal></term>
     <listitem>
index 7ec314379ba3120644c12ad08cd9e74b0dbeb751..edd90c8a56fc57cbd158ec6ac47c01b3eee2028f 100644 (file)
@@ -16,7 +16,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/common/heaptuple.c,v 1.107 2006/06/27 02:51:39 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/common/heaptuple.c,v 1.108 2006/07/02 02:23:18 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1738,3 +1738,54 @@ heap_addheader(int natts,                /* max domain index */
 
        return tuple;
 }
+
+/*
+ * build_class_tuple
+ *
+ *     XXX Natts_pg_class_fixed is a hack - see pg_class.h
+ */
+HeapTuple
+build_class_tuple(Form_pg_class pgclass, ArrayType *options)
+{
+       HeapTuple               tuple;
+       HeapTupleHeader td;
+       Form_pg_class   data;   /* contents of tuple */
+       Size                    len;
+       Size                    size;
+       int                             hoff;
+
+       /* size of pg_class tuple with options */
+       if (options)
+               size = offsetof(FormData_pg_class, reloptions) + VARATT_SIZE(options);
+       else
+               size = CLASS_TUPLE_SIZE;
+
+       /* header needs no null bitmap */
+       hoff = offsetof(HeapTupleHeaderData, t_bits);
+       hoff += sizeof(Oid);
+       hoff = MAXALIGN(hoff);
+       len = hoff + size;
+
+       tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + len);
+       tuple->t_data = td = (HeapTupleHeader) ((char *) tuple + HEAPTUPLESIZE);
+
+       tuple->t_len = len;
+       ItemPointerSetInvalid(&(tuple->t_self));
+       tuple->t_tableOid = InvalidOid;
+
+       /* we don't bother to fill the Datum fields */
+
+       td->t_natts = Natts_pg_class_fixed;
+       td->t_hoff = hoff;
+       td->t_infomask = HEAP_HASOID;
+
+       data = (Form_pg_class) ((char *) td + hoff);
+       memcpy(data, pgclass, CLASS_TUPLE_SIZE);
+       if (options)
+       {
+               td->t_natts++;
+               memcpy(data->reloptions, options, VARATT_SIZE(options));
+       }
+
+       return tuple;
+}
index b9cb80a6cf156f2d8dc81c32ba2602f47b8e7962..17e041bc4a86cb9d5b182bca656ca2b402cb8a4c 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *          $PostgreSQL: pgsql/src/backend/access/gin/ginutil.c,v 1.1 2006/05/02 11:28:54 teodor Exp $
+ *          $PostgreSQL: pgsql/src/backend/access/gin/ginutil.c,v 1.2 2006/07/02 02:23:18 momjian Exp $
  *-------------------------------------------------------------------------
  */
 
@@ -201,3 +201,17 @@ GinPageGetCopyPage( Page page ) {
        
        return tmppage;
 }
+
+Datum
+ginoption(PG_FUNCTION_ARGS)
+{
+       ArrayType          *options = (ArrayType *) PG_GETARG_POINTER(0);
+
+       if (options != NULL)
+               ereport(ERROR,
+                       (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                               errmsg("GIN does not support parameters at all")));
+
+       /* Do not use PG_RETURN_NULL. */
+       PG_RETURN_BYTEA_P(NULL);
+}
index 39ff702c3d1f27ad3491c71a011c11f5b87d085c..4137ab4426ff4a965da9010a701ecb0b7fe54725 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/gist/gist.c,v 1.139 2006/06/28 12:00:14 teodor Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/gist/gist.c,v 1.140 2006/07/02 02:23:18 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -44,6 +44,7 @@ static void gistbuildCallback(Relation index,
                                  void *state);
 static void gistdoinsert(Relation r,
                         IndexTuple itup,
+                        Size freespace,
                         GISTSTATE *GISTstate);
 static void gistfindleaf(GISTInsertState *state,
                         GISTSTATE *giststate);
@@ -197,7 +198,8 @@ gistbuildCallback(Relation index,
         * you're inserting single tups, but not when you're initializing the
         * whole index at once.
         */
-       gistdoinsert(index, itup, &buildstate->giststate);
+       gistdoinsert(index, itup, IndexGetPageFreeSpace(index),
+               &buildstate->giststate);
 
        buildstate->indtuples += 1;
        MemoryContextSwitchTo(oldCtx);
@@ -236,7 +238,7 @@ gistinsert(PG_FUNCTION_ARGS)
                values, isnull, true /* size is currently bogus */);
        itup->t_tid = *ht_ctid;
 
-       gistdoinsert(r, itup, &giststate);
+       gistdoinsert(r, itup, 0, &giststate);
 
        /* cleanup */
        freeGISTstate(&giststate);
@@ -253,7 +255,7 @@ gistinsert(PG_FUNCTION_ARGS)
  * so it does not bother releasing palloc'd allocations.
  */
 static void
-gistdoinsert(Relation r, IndexTuple itup, GISTSTATE *giststate)
+gistdoinsert(Relation r, IndexTuple itup, Size freespace, GISTSTATE *giststate)
 {
        GISTInsertState state;
 
@@ -263,6 +265,7 @@ gistdoinsert(Relation r, IndexTuple itup, GISTSTATE *giststate)
        state.itup[0] = (IndexTuple) palloc(IndexTupleSize(itup));
        memcpy(state.itup[0], itup, IndexTupleSize(itup));
        state.ituplen = 1;
+       state.freespace = freespace;
        state.r = r;
        state.key = itup->t_tid;
        state.needInsertComplete = true;
@@ -294,7 +297,11 @@ gistplacetopage(GISTInsertState *state, GISTSTATE *giststate)
         */
 
 
-       if (gistnospace(state->stack->page, state->itup, state->ituplen, (is_leaf) ? InvalidOffsetNumber : state->stack->childoffnum))
+       /*
+        * XXX: If we want to change fillfactors between node and leaf,
+        * fillfactor = (is_leaf ? state->leaf_fillfactor : state->node_fillfactor)
+        */
+       if (gistnospace(state->stack->page, state->itup, state->ituplen, (is_leaf) ? InvalidOffsetNumber : state->stack->childoffnum, state->freespace))
        {
                /* no space for insertion */
                IndexTuple *itvec;
index 3be4fd31f58c68d98fc45983fb7cf7bc5654a93d..ae1fbc7320161c578ad34a932ebbf3ef9769b444 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *                     $PostgreSQL: pgsql/src/backend/access/gist/gistutil.c,v 1.16 2006/06/28 12:00:14 teodor Exp $
+ *                     $PostgreSQL: pgsql/src/backend/access/gist/gistutil.c,v 1.17 2006/07/02 02:23:18 momjian Exp $
  *-------------------------------------------------------------------------
  */
 #include "postgres.h"
@@ -58,9 +58,9 @@ gistfillbuffer(Relation r, Page page, IndexTuple *itup,
  * Check space for itup vector on page
  */
 bool
-gistnospace(Page page, IndexTuple *itvec, int len, OffsetNumber todelete)
+gistnospace(Page page, IndexTuple *itvec, int len, OffsetNumber todelete, Size freespace)
 {
-       unsigned int size = 0, deleted = 0;
+       unsigned int size = freespace, deleted = 0;
        int                     i;
 
        for (i = 0; i < len; i++)
@@ -82,6 +82,7 @@ gistfitpage(IndexTuple *itvec, int len) {
        for(i=0;i<len;i++)
                size += IndexTupleSize(itvec[i]) + sizeof(ItemIdData);
 
+       /* TODO: Consider fillfactor */
        return (size <= GiSTPageSize);
 }
 
@@ -634,3 +635,16 @@ gistNewBuffer(Relation r)
 
        return buffer;
 }
+
+Datum
+gistoption(PG_FUNCTION_ARGS)
+{
+#define GIST_DEFAULT_FILLFACTOR                90
+#define GIST_MIN_FILLFACTOR                    50
+
+       ArrayType          *options = (ArrayType *) PG_GETARG_POINTER(0);
+
+       /* Use index common routine. */
+       PG_RETURN_BYTEA_P(genam_option(options,
+               GIST_MIN_FILLFACTOR, GIST_DEFAULT_FILLFACTOR));
+}
index a47d81db78e2f91be16318cbeb5929f118b59a96..faf7661f96a79851c579e4af948148eebe9465a9 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/gist/gistvacuum.c,v 1.22 2006/05/19 11:10:25 teodor Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/gist/gistvacuum.c,v 1.23 2006/07/02 02:23:18 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -376,7 +376,7 @@ gistVacuumUpdate(GistVacuum *gv, BlockNumber blkno, bool needunion)
                if (curlenaddon)
                {
                        /* insert updated tuples */
-                       if (gistnospace(tempPage, addon, curlenaddon, InvalidOffsetNumber)) {
+                       if (gistnospace(tempPage, addon, curlenaddon, InvalidOffsetNumber, 0)) {
                                /* there is no space on page to insert tuples */
                                res = vacuumSplitPage(gv, tempPage, buffer, addon, curlenaddon);
                                tempPage=NULL; /* vacuumSplitPage() free tempPage */
index c4291c01f816a862cec51bca6a76f39e2393a345..fbae13ef039df54a972b62d04d592e673e29d5ee 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *                      $PostgreSQL: pgsql/src/backend/access/gist/gistxlog.c,v 1.20 2006/05/19 17:15:41 teodor Exp $
+ *                      $PostgreSQL: pgsql/src/backend/access/gist/gistxlog.c,v 1.21 2006/07/02 02:23:18 momjian Exp $
  *-------------------------------------------------------------------------
  */
 #include "postgres.h"
@@ -690,7 +690,7 @@ gistContinueInsert(gistIncompleteInsert *insert)
                         * that wiil be enough space....
                         */
 
-                       if (gistnospace(pages[0], itup, lenitup, *todelete))
+                       if (gistnospace(pages[0], itup, lenitup, *todelete, 0))
                        {
 
                                /* no space left on page, so we must split */
index 488a7c5819f4a0b48dbda26d30e9cbd87c12a3b9..bed0b5dbd729fef8099c96f39a4ffdac4675c1c8 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/hash/hashpage.c,v 1.57 2006/03/31 23:32:05 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/hash/hashpage.c,v 1.58 2006/07/02 02:23:18 momjian Exp $
  *
  * NOTES
  *       Postgres hash pages look like ordinary relation pages.  The opaque
@@ -30,6 +30,7 @@
 
 #include "access/genam.h"
 #include "access/hash.h"
+#include "catalog/index.h"
 #include "miscadmin.h"
 #include "storage/lmgr.h"
 #include "utils/lsyscache.h"
@@ -231,7 +232,7 @@ _hash_metapinit(Relation rel)
                                                                 RelationGetDescr(rel)->attrs[0]->atttypmod);
        item_width = MAXALIGN(sizeof(IndexTupleData)) + MAXALIGN(data_width) +
                sizeof(ItemIdData);             /* include the line pointer */
-       ffactor = (BLCKSZ * 3 / 4) / item_width;
+       ffactor = BLCKSZ * IndexGetFillFactor(rel) / 100 / item_width;
        /* keep to a sane range */
        if (ffactor < 10)
                ffactor = 10;
index 65b8ef948c2fd28236aeeb9622d4057316133bec..fbee1fdc2aa33e435e379d6029100999734c162f 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/hash/hashutil.c,v 1.47 2006/03/05 15:58:21 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/hash/hashutil.c,v 1.48 2006/07/02 02:23:18 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -173,3 +173,16 @@ _hash_checkpage(Relation rel, Buffer buf, int flags)
                                         errhint("Please REINDEX it.")));
        }
 }
+
+Datum
+hashoption(PG_FUNCTION_ARGS)
+{
+#define HASH_MIN_FILLFACTOR                    50
+#define HASH_DEFAULT_FILLFACTOR                75
+
+       ArrayType          *options = (ArrayType *) PG_GETARG_POINTER(0);
+
+       /* Use index common routine. */
+       PG_RETURN_BYTEA_P(genam_option(options,
+               HASH_MIN_FILLFACTOR, HASH_DEFAULT_FILLFACTOR));
+}
index 15556fda538c3cbd4c5b0b6ae170088b2fca232f..cf3344c20091e069f9fc7bb46eb73123a6ad69a9 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.213 2006/05/28 02:27:08 alvherre Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.214 2006/07/02 02:23:18 momjian Exp $
  *
  *
  * INTERFACE ROUTINES
 #include "access/xlogutils.h"
 #include "catalog/catalog.h"
 #include "catalog/namespace.h"
+#include "commands/defrem.h"
 #include "miscadmin.h"
+#include "nodes/parsenodes.h"
+#include "parser/parse_clause.h"
 #include "pgstat.h"
 #include "storage/procarray.h"
+#include "utils/catcache.h"
 #include "utils/inval.h"
 #include "utils/relcache.h"
 
@@ -3588,3 +3592,59 @@ heap_desc(StringInfo buf, uint8 xl_info, char *rec)
        else
                appendStringInfo(buf, "UNKNOWN");
 }
+
+/*
+ * Parse options for heaps.
+ *
+ *     relkind         Kind of relation
+ *     options         Options as text[]
+ */
+bytea *
+heap_option(char relkind, ArrayType *options)
+{
+       /*
+        * XXX: What fillfactor should be default?
+        * overriding databases:
+        *   - Oracle, DB2 = 90%
+        *   - SQL Server = 100%
+        * non-overriding database:
+        *   - Firebird = 70%
+        */
+#define HEAP_MIN_FILLFACTOR                    50
+#define HEAP_DEFAULT_FILLFACTOR                100
+
+       int                             fillfactor;
+       HeapOption         *result;
+
+       DefElem kwds[] =
+       {
+               { T_DefElem, "fillfactor" },
+       };
+
+       /*
+        * parse options
+        */
+       OptionParse(options, lengthof(kwds), kwds, true);
+
+       /* 0: fillfactor */
+       if (kwds[0].arg)
+               fillfactor = (int) defGetInt64(&kwds[0]);
+       else
+               fillfactor = HEAP_DEFAULT_FILLFACTOR;
+       if (fillfactor < HEAP_MIN_FILLFACTOR || 100 < fillfactor)
+       {
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                errmsg("fillfactor=%d should be between %d and 100",
+                 fillfactor, HEAP_MIN_FILLFACTOR)));
+       }
+
+       /*
+        * build option
+        */
+       result = (HeapOption *)
+               MemoryContextAlloc(CacheMemoryContext, sizeof(HeapOption));
+       VARATT_SIZEP(result) = sizeof(HeapOption);
+       result->fillfactor = fillfactor;
+       return (bytea *) result;
+}
index ccaaacefea84547f69326ec26accb0aeaa220020..82fb0a3268a409852d97d46394864b68ede6c4a8 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/heap/hio.c,v 1.61 2006/03/05 15:58:21 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/heap/hio.c,v 1.62 2006/07/02 02:23:18 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -102,12 +102,18 @@ RelationGetBufferForTuple(Relation relation, Size len,
 {
        Buffer          buffer = InvalidBuffer;
        Page            pageHeader;
-       Size            pageFreeSpace;
+       Size            pageFreeSpace,
+                               freespace;
        BlockNumber targetBlock,
                                otherBlock;
        bool            needLock;
 
+       if (relation->rd_options == NULL)
+               elog(ERROR, "RelationGetBufferForTuple %s IS NULL", RelationGetRelationName(relation));
+       Assert(relation->rd_options != NULL);
+
        len = MAXALIGN(len);            /* be conservative */
+       freespace = HeapGetPageFreeSpace(relation);
 
        /*
         * If we're gonna fail for oversize tuple, do it right away
@@ -146,7 +152,7 @@ RelationGetBufferForTuple(Relation relation, Size len,
                 * We have no cached target page, so ask the FSM for an initial
                 * target.
                 */
-               targetBlock = GetPageWithFreeSpace(&relation->rd_node, len);
+               targetBlock = GetPageWithFreeSpace(&relation->rd_node, len + freespace);
 
                /*
                 * If the FSM knows nothing of the rel, try the last page before we
@@ -202,7 +208,7 @@ RelationGetBufferForTuple(Relation relation, Size len,
                 */
                pageHeader = (Page) BufferGetPage(buffer);
                pageFreeSpace = PageGetFreeSpace(pageHeader);
-               if (len <= pageFreeSpace)
+               if (len + freespace <= pageFreeSpace)
                {
                        /* use this page as future insert target, too */
                        relation->rd_targblock = targetBlock;
@@ -235,7 +241,7 @@ RelationGetBufferForTuple(Relation relation, Size len,
                targetBlock = RecordAndGetPageWithFreeSpace(&relation->rd_node,
                                                                                                        targetBlock,
                                                                                                        pageFreeSpace,
-                                                                                                       len);
+                                                                                                       len + freespace);
        }
 
        /*
index 56eabbaf4215df5d677679f1e6f05e56ff6dbc20..cfc2a833cd38917606b5394b5c8cd79bf48dec34 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.55 2006/05/07 01:21:30 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.56 2006/07/02 02:23:18 momjian Exp $
  *
  * NOTES
  *       many of the old access method routines have been turned into
 
 #include "access/genam.h"
 #include "access/heapam.h"
+#include "commands/defrem.h"
 #include "miscadmin.h"
+#include "nodes/parsenodes.h"
+#include "parser/parse_clause.h"
 #include "pgstat.h"
+#include "utils/catcache.h"
 
 
 /* ----------------------------------------------------------------
@@ -260,3 +264,44 @@ systable_endscan(SysScanDesc sysscan)
 
        pfree(sysscan);
 }
+
+/*
+ * Parse options for generic indexes.
+ */
+bytea *
+genam_option(ArrayType *options,
+             int minFillfactor, int defaultFillfactor)
+{
+       int                             fillfactor;
+       IndexOption        *result;
+
+       DefElem kwds[] =
+       {
+               { T_DefElem, "fillfactor" },
+       };
+
+       /*
+        * parse options
+        */
+       OptionParse(options, lengthof(kwds), kwds, true);
+
+       /* 0: fillfactor */
+       if (kwds[0].arg)
+               fillfactor = (int) defGetInt64(&kwds[0]);
+       else
+               fillfactor = defaultFillfactor;
+       if (fillfactor < minFillfactor || 100 < fillfactor)
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                errmsg("fillfactor=%d should be between %d and 100",
+                                fillfactor, minFillfactor)));
+
+       /*
+        * build options
+        */
+       result = (IndexOption *)
+               MemoryContextAlloc(CacheMemoryContext, sizeof(IndexOption));
+       VARATT_SIZEP(result) = sizeof(IndexOption);
+       result->fillfactor = fillfactor;
+       return (bytea *) result;
+}
index 89f8810bde57898cffa07aa76cbc0cd8e1ae601f..3b78843101e55f86adc453852375c3ed45b569b3 100644 (file)
@@ -8,13 +8,14 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.137 2006/05/08 00:00:09 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.138 2006/07/02 02:23:18 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include "postgres.h"
 
+#include "access/genam.h"
 #include "access/heapam.h"
 #include "access/nbtree.h"
 #include "miscadmin.h"
@@ -25,6 +26,7 @@ typedef struct
 {
        /* context data for _bt_checksplitloc */
        Size            newitemsz;              /* size of new item to be inserted */
+       int                     fillfactor;             /* used when insert at right most */
        bool            is_leaf;                /* T if splitting a leaf page */
        bool            is_rightmost;   /* T if splitting a rightmost page */
 
@@ -986,14 +988,11 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright,
  * it needs to go into!)
  *
  * If the page is the rightmost page on its level, we instead try to arrange
- * for twice as much free space on the right as on the left.  In this way,
+ * for reserving (100-fillfactor)% of free space on left page. In this way,
  * when we are inserting successively increasing keys (consider sequences,
- * timestamps, etc) we will end up with a tree whose pages are about 67% full,
+ * timestamps, etc) we will end up with a tree whose pages are about fillfactor% full,
  * instead of the 50% full result that we'd get without this special case.
- * (We could bias it even further to make the initially-loaded tree more full.
- * But since the steady-state load for a btree is about 70%, we'd likely just
- * be making more page-splitting work for ourselves later on, when we start
- * seeing updates to existing tuples.)
+ * This is the same as initially-loaded tree.
  *
  * We are passed the intended insert position of the new tuple, expressed as
  * the offsetnumber of the tuple it must go in front of.  (This could be
@@ -1027,6 +1026,7 @@ _bt_findsplitloc(Relation rel,
        /* Passed-in newitemsz is MAXALIGNED but does not include line pointer */
        newitemsz += sizeof(ItemIdData);
        state.newitemsz = newitemsz;
+       state.fillfactor = IndexGetFillFactor(rel);
        state.is_leaf = P_ISLEAF(opaque);
        state.is_rightmost = P_RIGHTMOST(opaque);
        state.have_split = false;
@@ -1157,10 +1157,11 @@ _bt_checksplitloc(FindSplitData *state, OffsetNumber firstright,
                if (state->is_rightmost)
                {
                        /*
-                        * On a rightmost page, try to equalize right free space with
-                        * twice the left free space.  See comments for _bt_findsplitloc.
+                        * On a rightmost page, try to reserve (100-fillfactor)% of
+                        * free space on left page. See comments for _bt_findsplitloc.
                         */
-                       delta = (2 * leftfree) - rightfree;
+                       delta = (state->fillfactor * leftfree)
+                               - ((100 - state->fillfactor) * rightfree);
                }
                else
                {
index e7293b47b03206516f7bc2f45ca86613c654b142..05785d98eb59785384b3d22b147395e075b29419 100644 (file)
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsort.c,v 1.102 2006/06/27 16:53:02 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsort.c,v 1.103 2006/07/02 02:23:19 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include "postgres.h"
 
+#include "access/genam.h"
 #include "access/nbtree.h"
 #include "access/xlog.h"
 #include "miscadmin.h"
@@ -120,6 +121,7 @@ typedef struct BTWriteState
 
 
 static Page _bt_blnewpage(uint32 level);
+static Size    _bt_full_threshold(Relation index, Size pagesize, bool leaf);
 static BTPageState *_bt_pagestate(BTWriteState *wstate, uint32 level);
 static void _bt_slideleft(Page page);
 static void _bt_sortaddtup(Page page, Size itemsize,
@@ -327,6 +329,22 @@ _bt_blwritepage(BTWriteState *wstate, Page page, BlockNumber blkno)
        pfree(page);
 }
 
+/*
+ * The steady-state load factor for btrees is usually estimated at 70%.
+ * We choose to pack leaf pages to 90% and upper pages to 70% as defaults.
+ */
+static Size
+_bt_full_threshold(Relation index, Size pagesize, bool leaf)
+{
+       int fillfactor = IndexGetFillFactor(index);
+       if (!leaf)
+       {
+               /* XXX: Is this reasonable? */
+               fillfactor = Max(70, 3 * fillfactor - 200);
+       }
+       return pagesize * (100 - fillfactor) / 100;
+}
+
 /*
  * allocate and initialize a new BTPageState.  the returned structure
  * is suitable for immediate use by _bt_buildadd.
@@ -347,10 +365,8 @@ _bt_pagestate(BTWriteState *wstate, uint32 level)
        state->btps_lastoff = P_HIKEY;
        state->btps_level = level;
        /* set "full" threshold based on level.  See notes at head of file. */
-       if (level > 0)
-               state->btps_full = (PageGetPageSize(state->btps_page) * 3) / 10;
-       else
-               state->btps_full = PageGetPageSize(state->btps_page) / 10;
+       state->btps_full = _bt_full_threshold(wstate->index,
+               PageGetPageSize(state->btps_page), level == 0);
        /* no parent level, yet */
        state->btps_next = NULL;
 
index 5db8f5528845b2abd9879a38617f12d498a75478..93a9b0df6537ad01b436f1dae64698ce31d679f1 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/nbtree/nbtutils.c,v 1.74 2006/05/08 00:00:10 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/nbtree/nbtutils.c,v 1.75 2006/07/02 02:23:19 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1079,3 +1079,16 @@ BTreeShmemInit(void)
        else
                Assert(found);
 }
+
+Datum
+btoption(PG_FUNCTION_ARGS)
+{
+#define BTREE_MIN_FILLFACTOR           50
+#define BTREE_DEFAULT_FILLFACTOR       90
+
+       ArrayType          *options = (ArrayType *) PG_GETARG_POINTER(0);
+
+       /* Use index common routine. */
+       PG_RETURN_BYTEA_P(genam_option(options,
+               BTREE_MIN_FILLFACTOR, BTREE_DEFAULT_FILLFACTOR));
+}
index 39d3e041e454cf749735388adb7fdaa82df0a7b0..da30e39b42d137ea29c29609881f7dd0ec2d30be 100644 (file)
@@ -11,7 +11,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/backend/access/transam/xlogutils.c,v 1.44 2006/04/14 20:27:24 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/xlogutils.c,v 1.45 2006/07/02 02:23:19 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -337,7 +337,7 @@ _xl_remove_hash_entry(XLogRelDesc *rdesc)
        RelationCloseSmgr(&(rdesc->reldata));
 
        memset(rdesc, 0, sizeof(XLogRelDesc));
-       memset(tpgc, 0, sizeof(FormData_pg_class));
+       memset(tpgc, 0, CLASS_TUPLE_SIZE);
        rdesc->reldata.rd_rel = tpgc;
 }
 
index 8b8645bd600721a8730d4871f5125465c90035cb..901c392d7e054dda6ae2bdbedcbf5ada5be18bb2 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/bootstrap/bootparse.y,v 1.80 2006/03/07 01:03:12 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/bootstrap/bootparse.y,v 1.81 2006/07/02 02:23:19 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -19,6 +19,7 @@
 #include <unistd.h>
 
 #include "access/attnum.h"
+#include "access/heapam.h"
 #include "access/htup.h"
 #include "access/itup.h"
 #include "access/skey.h"
@@ -192,6 +193,8 @@ Boot_CreateStmt:
                                                                                                   RELKIND_RELATION,
                                                                                                   $3,
                                                                                                   true);
+                                               boot_reldesc->rd_options =
+                                                       heap_option(RELKIND_RELATION, NULL);
                                                elog(DEBUG4, "bootstrap relation created");
                                        }
                                        else
@@ -209,7 +212,8 @@ Boot_CreateStmt:
                                                                                                          true,
                                                                                                          0,
                                                                                                          ONCOMMIT_NOOP,
-                                                                                                         true);
+                                                                                                         true,
+                                                                                                         NULL);
                                                elog(DEBUG4, "relation created with oid %u", id);
                                        }
                                        do_end();
@@ -252,7 +256,7 @@ Boot_DeclareIndexStmt:
                                                                LexIDStr($8),
                                                                NULL,
                                                                $10,
-                                                               NULL, NIL,
+                                                               NULL, NIL, NIL,
                                                                false, false, false,
                                                                false, false, true, false);
                                        do_end();
@@ -270,7 +274,7 @@ Boot_DeclareUniqueIndexStmt:
                                                                LexIDStr($9),
                                                                NULL,
                                                                $11,
-                                                               NULL, NIL,
+                                                               NULL, NIL, NIL,
                                                                true, false, false,
                                                                false, false, true, false);
                                        do_end();
index 85d1cb5d13a9b7faa555f0d5b68596564a60454d..e2eed023e0206ddf9ed16ed7c2c6a0c04b6febc0 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.302 2006/06/29 16:07:29 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.303 2006/07/02 02:23:19 momjian Exp $
  *
  *
  * INTERFACE ROUTINES
 #include "catalog/pg_type.h"
 #include "commands/tablecmds.h"
 #include "commands/trigger.h"
+#include "commands/defrem.h"
 #include "miscadmin.h"
 #include "nodes/makefuncs.h"
 #include "optimizer/clauses.h"
 #include "optimizer/planmain.h"
 #include "optimizer/var.h"
 #include "parser/parse_coerce.h"
+#include "parser/parse_clause.h"
 #include "parser/parse_expr.h"
 #include "parser/parse_relation.h"
 #include "rewrite/rewriteRemove.h"
 #include "storage/smgr.h"
+#include "utils/catcache.h"
 #include "utils/builtins.h"
 #include "utils/fmgroids.h"
 #include "utils/inval.h"
 #include "utils/lsyscache.h"
+#include "utils/memutils.h"
 #include "utils/relcache.h"
 #include "utils/syscache.h"
 
@@ -66,7 +70,8 @@ static void AddNewRelationTuple(Relation pg_class_desc,
                                        Relation new_rel_desc,
                                        Oid new_rel_oid, Oid new_type_oid,
                                        Oid relowner,
-                                       char relkind);
+                                       char relkind,
+                                       ArrayType *options);
 static Oid AddNewRelationType(const char *typeName,
                                   Oid typeNamespace,
                                   Oid new_rel_oid,
@@ -558,7 +563,8 @@ AddNewRelationTuple(Relation pg_class_desc,
                                        Oid new_rel_oid,
                                        Oid new_type_oid,
                                        Oid relowner,
-                                       char relkind)
+                                       char relkind,
+                                       ArrayType *options)
 {
        Form_pg_class new_rel_reltup;
        HeapTuple       tup;
@@ -596,15 +602,8 @@ AddNewRelationTuple(Relation pg_class_desc,
 
        new_rel_desc->rd_att->tdtypeid = new_type_oid;
 
-       /* ----------------
-        *      now form a tuple to add to pg_class
-        *      XXX Natts_pg_class_fixed is a hack - see pg_class.h
-        * ----------------
-        */
-       tup = heap_addheader(Natts_pg_class_fixed,
-                                                true,
-                                                CLASS_TUPLE_SIZE,
-                                                (void *) new_rel_reltup);
+       /* now form a tuple to add to pg_class */
+       tup = build_class_tuple(new_rel_reltup, options);
 
        /* force tuple to have the desired OID */
        HeapTupleSetOid(tup, new_rel_oid);
@@ -661,6 +660,8 @@ AddNewRelationType(const char *typeName,
  *             heap_create_with_catalog
  *
  *             creates a new cataloged relation.  see comments above.
+ *
+ *             if opaque is specified, it must be allocated in CacheMemoryContext.
  * --------------------------------
  */
 Oid
@@ -675,10 +676,12 @@ heap_create_with_catalog(const char *relname,
                                                 bool oidislocal,
                                                 int oidinhcount,
                                                 OnCommitAction oncommit,
-                                                bool allow_system_table_mods)
+                                                bool allow_system_table_mods,
+                                                ArrayType *options)
 {
        Relation        pg_class_desc;
        Relation        new_rel_desc;
+       bytea      *new_rel_options;
        Oid                     new_type_oid;
 
        pg_class_desc = heap_open(RelationRelationId, RowExclusiveLock);
@@ -695,6 +698,13 @@ heap_create_with_catalog(const char *relname,
                                (errcode(ERRCODE_DUPLICATE_TABLE),
                                 errmsg("relation \"%s\" already exists", relname)));
 
+       /*
+        * Parse options to check if option is valid.
+        */
+       new_rel_options = heap_option(relkind, options);
+       Assert(!new_rel_options ||
+               GetMemoryChunkContext(new_rel_options) == CacheMemoryContext);
+
        /*
         * Allocate an OID for the relation, unless we were told what to use.
         *
@@ -718,6 +728,7 @@ heap_create_with_catalog(const char *relname,
                                                           relkind,
                                                           shared_relation,
                                                           allow_system_table_mods);
+       new_rel_desc->rd_options = new_rel_options;
 
        Assert(relid == RelationGetRelid(new_rel_desc));
 
@@ -745,7 +756,8 @@ heap_create_with_catalog(const char *relname,
                                                relid,
                                                new_type_oid,
                                                ownerid,
-                                               relkind);
+                                               relkind,
+                                               options);
 
        /*
         * now add tuples to pg_attribute for the attributes in our new relation.
index d0f216475ea5cbed9f127284274782741c49a1c3..9143f6068a5b3c4e8f1faee3bcb49e728a335bfa 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.266 2006/05/10 23:18:39 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.267 2006/07/02 02:23:19 momjian Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -37,6 +37,7 @@
 #include "executor/executor.h"
 #include "miscadmin.h"
 #include "optimizer/clauses.h"
+#include "parser/parse_clause.h"
 #include "parser/parse_expr.h"
 #include "storage/procarray.h"
 #include "storage/smgr.h"
@@ -53,7 +54,8 @@
 static TupleDesc ConstructTupleDescriptor(Relation heapRelation,
                                                 IndexInfo *indexInfo,
                                                 Oid *classObjectId);
-static void UpdateRelationRelation(Relation pg_class, Relation indexRelation);
+static void UpdateRelationRelation(Relation pg_class, Relation indexRelation,
+                                                                  ArrayType *options);
 static void InitializeAttributeOids(Relation indexRelation,
                                                int numatts, Oid indexoid);
 static void AppendAttributeTuples(Relation indexRelation, int numatts);
@@ -241,15 +243,12 @@ ConstructTupleDescriptor(Relation heapRelation,
  * ----------------------------------------------------------------
  */
 static void
-UpdateRelationRelation(Relation pg_class, Relation indexRelation)
+UpdateRelationRelation(Relation pg_class, Relation indexRelation,
+                                          ArrayType *options)
 {
        HeapTuple       tuple;
 
-       /* XXX Natts_pg_class_fixed is a hack - see pg_class.h */
-       tuple = heap_addheader(Natts_pg_class_fixed,
-                                                  true,
-                                                  CLASS_TUPLE_SIZE,
-                                                  (void *) indexRelation->rd_rel);
+       tuple = build_class_tuple(indexRelation->rd_rel, options);
 
        /*
         * the new tuple must have the oid already chosen for the index. sure
@@ -467,6 +466,7 @@ index_create(Oid heapRelationId,
                         Oid accessMethodObjectId,
                         Oid tableSpaceId,
                         Oid *classObjectId,
+                        List *options,
                         bool isprimary,
                         bool istoast,
                         bool isconstraint,
@@ -481,6 +481,9 @@ index_create(Oid heapRelationId,
        Oid                     namespaceId;
        int                     i;
 
+       ArrayType          *array;
+       RegProcedure    amoption;
+
        pg_class = heap_open(RelationRelationId, RowExclusiveLock);
 
        /*
@@ -578,12 +581,41 @@ index_create(Oid heapRelationId,
        indexRelation->rd_rel->relkind = RELKIND_INDEX;
        indexRelation->rd_rel->relhasoids = false;
 
+       /*
+        * AM specific options.
+        */
+       array = OptionBuild(NULL, options);
+       if (indexRelation->rd_am)
+       {
+               amoption = indexRelation->rd_am->amoption;
+       }
+       else
+       {
+               HeapTuple               tuple;
+
+               /*
+                * We may use the access method before initializing relation,
+                * so we pick up AM from syscache directly.
+                */
+               tuple = SearchSysCache(AMOID,
+                                                          ObjectIdGetDatum(accessMethodObjectId),
+                                                          0, 0, 0);
+               if (!HeapTupleIsValid(tuple))
+                       elog(ERROR, "cache lookup failed for access method %u",
+                               accessMethodObjectId);
+               amoption = ((Form_pg_am) GETSTRUCT(tuple))->amoption;
+               ReleaseSysCache(tuple);
+       }
+       indexRelation->rd_options = index_option(amoption, array);
+
        /*
         * store index's pg_class entry
         */
-       UpdateRelationRelation(pg_class, indexRelation);
+       UpdateRelationRelation(pg_class, indexRelation, array);
 
        /* done with pg_class */
+       if (array)
+               pfree(array);
        heap_close(pg_class, RowExclusiveLock);
 
        /*
@@ -1751,3 +1783,23 @@ reindex_relation(Oid relid, bool toast_too)
 
        return result;
 }
+
+/*
+ * Parse options for indexes.
+ *
+ *     amoption        Oid of option parser.
+ *     options         Options as text[]
+ */
+bytea *index_option(RegProcedure amoption, ArrayType *options)
+{
+       Datum           datum;
+
+       Assert(RegProcedureIsValid(amoption));
+
+       datum = OidFunctionCall1(amoption, PointerGetDatum(options));
+
+       if (DatumGetPointer(datum) == NULL)
+               return NULL;
+
+       return DatumGetByteaP(datum);
+}
index 8b96dbe5a6e540992ae46f41530a1d0d1cc5afb0..2ed1a156a4c872070b6fbaadfc6a12292298dee2 100644 (file)
@@ -9,16 +9,19 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/catalog/indexing.c,v 1.111 2006/03/05 15:58:22 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/catalog/indexing.c,v 1.112 2006/07/02 02:23:19 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "postgres.h"
 
 #include "access/genam.h"
+#include "access/heapam.h"
 #include "catalog/index.h"
 #include "catalog/indexing.h"
 #include "executor/executor.h"
+#include "utils/syscache.h"
+#include "commands/defrem.h"
 
 
 /*
index 381b6ed596230d4e029df9b1bae9c1586e3eac3a..08b76e96d5feb17b51b651fb98f51048b5d20c91 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.147 2006/05/02 22:25:10 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.148 2006/07/02 02:23:19 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -566,6 +566,8 @@ make_new_heap(Oid OIDOldHeap, const char *NewName, Oid NewTableSpace)
                                tupdesc;
        Oid                     OIDNewHeap;
        Relation        OldHeap;
+       HeapTuple       tuple;
+       ArrayType  *options;
 
        OldHeap = heap_open(OIDOldHeap, AccessExclusiveLock);
        OldHeapDesc = RelationGetDescr(OldHeap);
@@ -576,6 +578,26 @@ make_new_heap(Oid OIDOldHeap, const char *NewName, Oid NewTableSpace)
         */
        tupdesc = CreateTupleDescCopyConstr(OldHeapDesc);
 
+       /*
+        * Use options of the old heap for new heap.
+        */
+       tuple = SearchSysCache(RELOID,
+                                                  ObjectIdGetDatum(OIDOldHeap),
+                                                  0, 0, 0);
+       if (tuple)
+       {
+               Datum   datum;
+               bool    isNull;
+               datum = SysCacheGetAttr(RELOID, tuple,
+            Anum_pg_class_reloptions, &isNull);
+               options = isNull ? NULL : DatumGetArrayTypeP(datum);
+       }
+       else
+       {
+               /* should not happen */
+               options = NULL;
+       }
+
        OIDNewHeap = heap_create_with_catalog(NewName,
                                                                                  RelationGetNamespace(OldHeap),
                                                                                  NewTableSpace,
@@ -587,7 +609,10 @@ make_new_heap(Oid OIDOldHeap, const char *NewName, Oid NewTableSpace)
                                                                                  true,
                                                                                  0,
                                                                                  ONCOMMIT_NOOP,
-                                                                                 allowSystemTableMods);
+                                                                                 allowSystemTableMods,
+                                                                                 options);
+
+       ReleaseSysCache(tuple);
 
        /*
         * Advance command counter so that the newly-created relation's catalog
index 98cded67cc45a4dd7cd3df3b371426748cc65459..ebde8f109502ccd55755ddc46ae4f86f02586493 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/define.c,v 1.95 2006/03/14 22:48:18 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/define.c,v 1.96 2006/07/02 02:23:19 momjian Exp $
  *
  * DESCRIPTION
  *       The "DefineFoo" routines take the parse tree and pick out the
@@ -110,6 +110,7 @@ defGetNumeric(DefElem *def)
                case T_Integer:
                        return (double) intVal(def->arg);
                case T_Float:
+               case T_String:  /* XXX: needs strict check? */
                        return floatVal(def->arg);
                default:
                        ereport(ERROR,
@@ -127,14 +128,30 @@ bool
 defGetBoolean(DefElem *def)
 {
        /*
-        * Presently, boolean flags must simply be present or absent. Later we
-        * could allow 'flag = t', 'flag = f', etc.
+        * Presently, boolean flags must simply be present/absent or
+        * integer 0/1. Later we could allow 'flag = t', 'flag = f', etc.
         */
        if (def->arg == NULL)
                return true;
+       switch (nodeTag(def->arg))
+       {
+               case T_Integer:
+                       switch (intVal(def->arg))
+                       {
+                       case 0:
+                               return false;
+                       case 1:
+                               return true;
+                       }
+                       break;
+               default:
+                       break;
+       }
+
+       /* on error */
        ereport(ERROR,
                        (errcode(ERRCODE_SYNTAX_ERROR),
-                        errmsg("%s does not take a parameter",
+                        errmsg("%s requires a boolean value",
                                        def->defname)));
        return false;                           /* keep compiler quiet */
 }
@@ -155,7 +172,7 @@ defGetInt64(DefElem *def)
                case T_Integer:
                        return (int64) intVal(def->arg);
                case T_Float:
-
+               case T_String:  /* XXX: needs strict check? */
                        /*
                         * Values too large for int4 will be represented as Float
                         * constants by the lexer.      Accept these if they are valid int8
@@ -275,3 +292,12 @@ defGetTypeLength(DefElem *def)
                                        def->defname, defGetString(def))));
        return 0;                                       /* keep compiler quiet */
 }
+
+DefElem *
+defWithOids(bool value)
+{
+       DefElem *f = makeNode(DefElem);
+       f->defname = "oids";
+       f->arg = (Node *)makeInteger(value);
+       return f;
+}
index e3813a2ca53c29fbacd65f5c1df35c194889217a..7e35258ac09e17facb4b19a5294eac674b4d7f33 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.141 2006/06/07 17:20:17 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.142 2006/07/02 02:23:19 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -77,6 +77,7 @@ static bool relationHasPrimaryKey(Relation rel);
  * 'isconstraint': index is for a PRIMARY KEY or UNIQUE constraint,
  *             so build a pg_constraint entry for it.
  * 'is_alter_table': this is due to an ALTER rather than a CREATE operation.
+ * 'options': options passed by WITH.
  * 'check_rights': check for CREATE rights in the namespace.  (This should
  *             be true except when ALTER is deleting/recreating an index.)
  * 'skip_build': make the catalog entries but leave the index file empty;
@@ -92,6 +93,7 @@ DefineIndex(RangeVar *heapRelation,
                        List *attributeList,
                        Expr *predicate,
                        List *rangetable,
+                       List *options,
                        bool unique,
                        bool primary,
                        bool isconstraint,
@@ -397,7 +399,7 @@ DefineIndex(RangeVar *heapRelation,
 
        index_create(relationId, indexRelationName, indexRelationId,
                                 indexInfo, accessMethodId, tablespaceId, classObjectId,
-                                primary, false, isconstraint,
+                                options, primary, false, isconstraint,
                                 allowSystemTableMods, skip_build);
 }
 
index d89c01a62e5c8ef8574eb96debcfec195cc6d30d..27ccb3fb87926c743ba1f43743485fbdf4217a17 100644 (file)
@@ -10,7 +10,7 @@
  * Copyright (c) 2002-2006, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.53 2006/06/20 22:51:59 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.54 2006/07/02 02:23:19 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -196,6 +196,7 @@ ExecuteQuery(ExecuteStmt *stmt, ParamListInfo params,
                                        (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                                         errmsg("prepared statement is not a SELECT")));
                query->into = copyObject(stmt->into);
+               query->intoOptions = copyObject(stmt->intoOptions);
                query->intoHasOids = stmt->into_has_oids;
                query->intoOnCommit = stmt->into_on_commit;
                if (stmt->into_tbl_space)
index 10ebe56b6a9d676d85dbcc8f2b2deac89ab4ab8c..65712c2092c976f43a6e5f2b0dde03123ef2c6cc 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/sequence.c,v 1.132 2006/03/31 23:32:06 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/sequence.c,v 1.133 2006/07/02 02:23:19 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -180,7 +180,7 @@ DefineSequence(CreateSeqStmt *seq)
        stmt->relation = seq->sequence;
        stmt->inhRelations = NIL;
        stmt->constraints = NIL;
-       stmt->hasoids = MUST_NOT_HAVE_OIDS;
+       stmt->options = list_make1(defWithOids(false));
        stmt->oncommit = ONCOMMIT_NOOP;
        stmt->tablespacename = NULL;
 
@@ -205,7 +205,17 @@ DefineSequence(CreateSeqStmt *seq)
 
        /* Now form & insert sequence tuple */
        tuple = heap_formtuple(tupDesc, value, null);
-       simple_heap_insert(rel, tuple);
+
+       {
+               /*
+                * HACK: Sequences insert only one tuple during initialize.
+                * We treat sequences as heaps then.
+                */
+               HeapOption opaque = { sizeof(HeapOption), 100 };
+               rel->rd_options = (bytea *) &opaque;
+               simple_heap_insert(rel, tuple);
+               rel->rd_options = NULL;
+       }
 
        Assert(ItemPointerGetOffsetNumber(&(tuple->t_self)) == FirstOffsetNumber);
 
index d22db6e45b1aea88a8c80514e31e92a07ac93775..f3331c69040a7c36c61185e2d8709d6a0948ff36 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.189 2006/07/02 01:58:36 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.190 2006/07/02 02:23:19 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -62,7 +62,6 @@
 #include "utils/relcache.h"
 #include "utils/syscache.h"
 
-
 /*
  * ON COMMIT action list
  */
@@ -196,6 +195,7 @@ static void ATRewriteTables(List **wqueue);
 static void ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap);
 static AlteredTableInfo *ATGetQueueEntry(List **wqueue, Relation rel);
 static void ATSimplePermissions(Relation rel, bool allowView);
+static void ATSimplePermissionsRelationOrIndex(Relation rel);
 static void ATSimpleRecursion(List **wqueue, Relation rel,
                                  AlterTableCmd *cmd, bool recurse);
 static void ATOneLevelRecursion(List **wqueue, Relation rel,
@@ -248,6 +248,7 @@ static void ATExecDropCluster(Relation rel);
 static void ATPrepSetTableSpace(AlteredTableInfo *tab, Relation rel,
                                        char *tablespacename);
 static void ATExecSetTableSpace(Oid tableOid, Oid newTableSpace);
+static void ATExecSetOptions(Relation rel, List *newOptions);
 static void ATExecEnableDisableTrigger(Relation rel, char *trigname,
                                                   bool enable, bool skip_system);
 static void ATExecAddInherits(Relation rel, RangeVar *parent);
@@ -285,6 +286,7 @@ DefineRelation(CreateStmt *stmt, char relkind)
        ListCell   *listptr;
        int                     i;
        AttrNumber      attnum;
+       ArrayType  *options;
 
        /*
         * Truncate relname to appropriate length (probably a waste of time, as
@@ -366,7 +368,7 @@ DefineRelation(CreateStmt *stmt, char relkind)
         */
        descriptor = BuildDescForRelation(schema);
 
-       localHasOids = interpretOidsOption(stmt->hasoids);
+       localHasOids = interpretOidsOption(stmt->options);
        descriptor->tdhasoid = (localHasOids || parentOidCount > 0);
 
        if (old_constraints != NIL)
@@ -426,6 +428,7 @@ DefineRelation(CreateStmt *stmt, char relkind)
                }
        }
 
+       options = OptionBuild(NULL, stmt->options);
        relationId = heap_create_with_catalog(relname,
                                                                                  namespaceId,
                                                                                  tablespaceId,
@@ -437,7 +440,10 @@ DefineRelation(CreateStmt *stmt, char relkind)
                                                                                  localHasOids,
                                                                                  parentOidCount,
                                                                                  stmt->oncommit,
-                                                                                 allowSystemTableMods);
+                                                                                 allowSystemTableMods,
+                                                                                 options);
+       if (options)
+               pfree(options);
 
        StoreCatalogInheritance(relationId, inheritOids);
 
@@ -2092,10 +2098,17 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
                        pass = AT_PASS_DROP;
                        break;
                case AT_SetTableSpace:  /* SET TABLESPACE */
+                       ATSimplePermissionsRelationOrIndex(rel);
                        /* This command never recurses */
                        ATPrepSetTableSpace(tab, rel, cmd->name);
                        pass = AT_PASS_MISC;    /* doesn't actually matter */
                        break;
+               case AT_SetOptions:             /* SET (...) */
+                       ATSimplePermissionsRelationOrIndex(rel);
+                       /* This command never recurses */
+                       /* No command-specific prep needed */
+                       pass = AT_PASS_MISC;
+                       break;
                case AT_EnableTrig:             /* ENABLE TRIGGER variants */
                case AT_EnableTrigAll:
                case AT_EnableTrigUser:
@@ -2266,6 +2279,9 @@ ATExecCmd(AlteredTableInfo *tab, Relation rel, AlterTableCmd *cmd)
                         * Nothing to do here; Phase 3 does the work
                         */
                        break;
+               case AT_SetOptions:             /* SET (...) */
+                       ATExecSetOptions(rel, (List *) cmd->def);
+                       break;
                case AT_EnableTrig:             /* ENABLE TRIGGER name */
                        ATExecEnableDisableTrigger(rel, cmd->name, true, false);
                        break;
@@ -2776,6 +2792,35 @@ ATSimplePermissions(Relation rel, bool allowView)
                                                RelationGetRelationName(rel))));
 }
 
+/*
+ * ATSimplePermissionsRelationOrIndex
+ *
+ * - Ensure that it is a relation or an index
+ * - Ensure this user is the owner
+ * - Ensure that it is not a system table
+ */
+static void
+ATSimplePermissionsRelationOrIndex(Relation rel)
+{
+       if (rel->rd_rel->relkind != RELKIND_RELATION &&
+               rel->rd_rel->relkind != RELKIND_INDEX)
+               ereport(ERROR,
+                               (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+                                errmsg("\"%s\" is not a table or index",
+                                               RelationGetRelationName(rel))));
+
+       /* Permissions checks */
+       if (!pg_class_ownercheck(RelationGetRelid(rel), GetUserId()))
+               aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
+                                          RelationGetRelationName(rel));
+
+       if (!allowSystemTableMods && IsSystemRelation(rel))
+               ereport(ERROR,
+                               (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+                                errmsg("permission denied: \"%s\" is a system catalog",
+                                               RelationGetRelationName(rel))));
+}
+
 /*
  * ATSimpleRecursion
  *
@@ -3804,6 +3849,7 @@ ATExecAddIndex(AlteredTableInfo *tab, Relation rel,
                                stmt->indexParams,              /* parameters */
                                (Expr *) stmt->whereClause,
                                stmt->rangetable,
+                               stmt->options,
                                stmt->unique,
                                stmt->primary,
                                stmt->isconstraint,
@@ -5690,28 +5736,6 @@ ATPrepSetTableSpace(AlteredTableInfo *tab, Relation rel, char *tablespacename)
        Oid                     tablespaceId;
        AclResult       aclresult;
 
-       /*
-        * We do our own permission checking because we want to allow this on
-        * indexes.
-        */
-       if (rel->rd_rel->relkind != RELKIND_RELATION &&
-               rel->rd_rel->relkind != RELKIND_INDEX)
-               ereport(ERROR,
-                               (errcode(ERRCODE_WRONG_OBJECT_TYPE),
-                                errmsg("\"%s\" is not a table or index",
-                                               RelationGetRelationName(rel))));
-
-       /* Permissions checks */
-       if (!pg_class_ownercheck(RelationGetRelid(rel), GetUserId()))
-               aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
-                                          RelationGetRelationName(rel));
-
-       if (!allowSystemTableMods && IsSystemRelation(rel))
-               ereport(ERROR,
-                               (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-                                errmsg("permission denied: \"%s\" is a system catalog",
-                                               RelationGetRelationName(rel))));
-
        /* Check that the tablespace exists */
        tablespaceId = get_tablespace_oid(tablespacename);
        if (!OidIsValid(tablespaceId))
@@ -5732,6 +5756,89 @@ ATPrepSetTableSpace(AlteredTableInfo *tab, Relation rel, char *tablespacename)
        tab->newTableSpace = tablespaceId;
 }
 
+/*
+ * ALTER TABLE/INDEX SET (...)
+ */
+static void
+ATExecSetOptions(Relation rel, List *newOptions)
+{
+       Oid                     relid;
+       Relation        pgclass;
+       HeapTuple       tuple;
+       Datum           datum;
+       bool            isnull;
+       ArrayType  *mergedOptions;
+       bytea      *options;
+
+       if (list_length(newOptions) == 0)
+               return; /* do nothing */
+
+       relid = RelationGetRelid(rel);
+       pgclass = heap_open(RelationRelationId, RowExclusiveLock);
+       tuple = SearchSysCache(RELOID,
+                                                  ObjectIdGetDatum(relid),
+                                                  0, 0, 0);
+       if (!HeapTupleIsValid(tuple))
+               elog(ERROR, "cache lookup failed for relation %u", relid);
+
+       datum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_reloptions, &isnull);
+
+       mergedOptions = OptionBuild(
+               isnull ? NULL : DatumGetArrayTypeP(datum), newOptions);
+
+       switch (rel->rd_rel->relkind)
+       {
+               case RELKIND_RELATION:
+               case RELKIND_TOASTVALUE:
+                       options = heap_option(rel->rd_rel->relkind, mergedOptions);
+                       break;
+               case RELKIND_INDEX:
+                       options = index_option(rel->rd_am->amoption, mergedOptions);
+                       break;
+               default:
+                       elog(ERROR, "unexpected RELKIND=%c", rel->rd_rel->relkind);
+                       options = NULL; /* keep compiler quiet */
+                       break;
+       }
+
+       if (rel->rd_options != options)
+       {
+               HeapTuple       newtuple;
+               Datum           repl_val[Natts_pg_class];
+               char            repl_null[Natts_pg_class];
+               char            repl_repl[Natts_pg_class];
+
+               /* XXX: This is not necessarily required. */
+               if (rel->rd_options)
+                       pfree(rel->rd_options);
+               rel->rd_options = options;
+
+               memset(repl_repl, ' ', sizeof(repl_repl));
+               memset(repl_null, ' ', sizeof(repl_null));
+               repl_repl[Anum_pg_class_reloptions - 1] = 'r';
+
+               if (mergedOptions)
+                       repl_val[Anum_pg_class_reloptions - 1] =
+                               PointerGetDatum(mergedOptions);
+               else
+                       repl_null[Anum_pg_class_reloptions - 1] = 'n';
+
+               newtuple = heap_modifytuple(tuple, RelationGetDescr(pgclass),
+                       repl_val, repl_null, repl_repl);
+
+               simple_heap_update(pgclass, &newtuple->t_self, newtuple);
+               CatalogUpdateIndexes(pgclass, newtuple);
+
+               heap_freetuple(newtuple);
+       }
+
+       if (mergedOptions)
+               pfree(mergedOptions);
+
+       ReleaseSysCache(tuple);
+       heap_close(pgclass, RowExclusiveLock);
+}
+
 /*
  * Execute ALTER TABLE SET TABLESPACE for cases where there is no tuple
  * rewriting to be done, so we just want to copy the data as fast as possible.
@@ -6553,7 +6660,8 @@ AlterTableCreateToastTable(Oid relOid, bool silent)
                                                                                   true,
                                                                                   0,
                                                                                   ONCOMMIT_NOOP,
-                                                                                  true);
+                                                                                  true,
+                                                                                  NULL);
 
        /* make the toast relation visible, else index creation will fail */
        CommandCounterIncrement();
@@ -6587,7 +6695,7 @@ AlterTableCreateToastTable(Oid relOid, bool silent)
                                                           indexInfo,
                                                           BTREE_AM_OID,
                                                           rel->rd_rel->reltablespace,
-                                                          classObjectId,
+                                                          classObjectId, NIL,
                                                           true, true, false, true, false);
 
        /*
index b907d677e05fc9aa10ee8e11f853c0bf2e23b5d9..0387d050cdeacca1815aa83a4ae336833184c0ac 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.91 2006/06/21 18:09:53 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.92 2006/07/02 02:23:19 momjian Exp $
  *
  * DESCRIPTION
  *       The "DefineFoo" routines take the parse tree and pick out the
@@ -1130,7 +1130,7 @@ DefineCompositeType(const RangeVar *typevar, List *coldeflist)
        createStmt->tableElts = coldeflist;
        createStmt->inhRelations = NIL;
        createStmt->constraints = NIL;
-       createStmt->hasoids = MUST_NOT_HAVE_OIDS;
+       createStmt->options = list_make1(defWithOids(false));
        createStmt->oncommit = ONCOMMIT_NOOP;
        createStmt->tablespacename = NULL;
 
index 4381369bc034b168b3cd6f1a51f8871c28665a1e..24a93e998de1a4cbf634b64c110edc30bdf492aa 100644 (file)
@@ -13,7 +13,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.330 2006/05/10 23:18:39 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.331 2006/07/02 02:23:19 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -242,6 +242,7 @@ static int  vac_cmp_blk(const void *left, const void *right);
 static int     vac_cmp_offno(const void *left, const void *right);
 static int     vac_cmp_vtlinks(const void *left, const void *right);
 static bool enough_space(VacPage vacpage, Size len);
+static Size    PageGetFreeSpaceWithFillFactor(Relation relation, Page page);
 
 
 /****************************************************************************
@@ -1282,7 +1283,7 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
                                           relname, blkno)));
                        PageInit(page, BufferGetPageSize(buf), 0);
                        MarkBufferDirty(buf);
-                       vacpage->free = ((PageHeader) page)->pd_upper - ((PageHeader) page)->pd_lower;
+                       vacpage->free = PageGetFreeSpaceWithFillFactor(onerel, page);
                        free_space += vacpage->free;
                        empty_pages++;
                        empty_end_pages++;
@@ -1297,7 +1298,7 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
                {
                        VacPage         vacpagecopy;
 
-                       vacpage->free = ((PageHeader) page)->pd_upper - ((PageHeader) page)->pd_lower;
+                       vacpage->free = PageGetFreeSpaceWithFillFactor(onerel, page);
                        free_space += vacpage->free;
                        empty_pages++;
                        empty_end_pages++;
@@ -1465,14 +1466,14 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
                {
                        /* Some tuples are removable; figure free space after removal */
                        PageRepairFragmentation(tempPage, NULL);
-                       vacpage->free = ((PageHeader) tempPage)->pd_upper - ((PageHeader) tempPage)->pd_lower;
+                       vacpage->free = PageGetFreeSpaceWithFillFactor(onerel, tempPage);
                        pfree(tempPage);
                        do_reap = true;
                }
                else
                {
                        /* Just use current available space */
-                       vacpage->free = ((PageHeader) page)->pd_upper - ((PageHeader) page)->pd_lower;
+                       vacpage->free = PageGetFreeSpaceWithFillFactor(onerel, page);
                        /* Need to reap the page if it has ~LP_USED line pointers */
                        do_reap = (vacpage->offsets_free > 0);
                }
@@ -2709,8 +2710,7 @@ move_plain_tuple(Relation rel,
 
        END_CRIT_SECTION();
 
-       dst_vacpage->free = ((PageHeader) dst_page)->pd_upper -
-               ((PageHeader) dst_page)->pd_lower;
+       dst_vacpage->free = PageGetFreeSpaceWithFillFactor(rel, dst_page);
        LockBuffer(dst_buf, BUFFER_LOCK_UNLOCK);
        LockBuffer(old_buf, BUFFER_LOCK_UNLOCK);
 
@@ -3119,6 +3119,8 @@ vac_update_fsm(Relation onerel, VacPageList fraged_pages,
         * vacuumlazy.c does, we'd be skewing that statistic.
         */
        threshold = GetAvgFSMRequestSize(&onerel->rd_node);
+       if (threshold < HeapGetPageFreeSpace(onerel))
+               threshold = HeapGetPageFreeSpace(onerel);
 
        pageSpaces = (PageFreeSpaceInfo *)
                palloc(nPages * sizeof(PageFreeSpaceInfo));
@@ -3385,6 +3387,18 @@ enough_space(VacPage vacpage, Size len)
        return false;
 }
 
+static Size
+PageGetFreeSpaceWithFillFactor(Relation relation, Page page)
+{
+       PageHeader      pd = (PageHeader) page;
+       Size            pagefree = HeapGetPageFreeSpace(relation);
+       Size            freespace = pd->pd_upper - pd->pd_lower;
+
+       if (freespace > pagefree)
+               return freespace - pagefree;
+       else
+               return 0;
+}
 
 /*
  * vacuum_delay_point --- check for interrupts and cost-based delay.
index 00fda19231077304daec40b6049ffb8d1f4881a2..8e97fa47563d37acb3f3cf5290a2920254434d58 100644 (file)
@@ -31,7 +31,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.70 2006/05/02 22:25:10 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.71 2006/07/02 02:23:20 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -149,6 +149,8 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt)
        /* Set threshold for interesting free space = average request size */
        /* XXX should we scale it up or down?  Adjust vacuum.c too, if so */
        vacrelstats->threshold = GetAvgFSMRequestSize(&onerel->rd_node);
+       if (vacrelstats->threshold < HeapGetPageFreeSpace(onerel))
+               vacrelstats->threshold = HeapGetPageFreeSpace(onerel);
 
        /* Open all indexes of the relation */
        vac_open_indexes(onerel, ShareUpdateExclusiveLock, &nindexes, &Irel);
index 490e0aa351966e47dfb4bd8d8e09a6582b50ed9c..12f06b0b24d77117de21ff2d8fed48af6c53d8fd 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/view.c,v 1.94 2006/03/14 22:48:18 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/view.c,v 1.95 2006/07/02 02:23:20 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -17,6 +17,7 @@
 #include "access/heapam.h"
 #include "catalog/dependency.h"
 #include "catalog/namespace.h"
+#include "commands/defrem.h"
 #include "commands/tablecmds.h"
 #include "commands/view.h"
 #include "miscadmin.h"
@@ -195,7 +196,7 @@ DefineVirtualRelation(const RangeVar *relation, List *tlist, bool replace)
                createStmt->tableElts = attrList;
                createStmt->inhRelations = NIL;
                createStmt->constraints = NIL;
-               createStmt->hasoids = MUST_NOT_HAVE_OIDS;
+               createStmt->options = list_make1(defWithOids(false));
                createStmt->oncommit = ONCOMMIT_NOOP;
                createStmt->tablespacename = NULL;
 
index b39e7a587b18159aae255bb7b7a459b6cc222229..bb03b9358c680b2b4c2ac05cbfe4023478e90a8c 100644 (file)
@@ -26,7 +26,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.271 2006/06/16 18:42:21 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.272 2006/07/02 02:23:20 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -45,6 +45,7 @@
 #include "miscadmin.h"
 #include "optimizer/clauses.h"
 #include "optimizer/var.h"
+#include "parser/parse_clause.h"
 #include "parser/parsetree.h"
 #include "storage/smgr.h"
 #include "utils/acl.h"
@@ -729,6 +730,7 @@ InitPlan(QueryDesc *queryDesc, int eflags)
                AclResult       aclresult;
                Oid                     intoRelationId;
                TupleDesc       tupdesc;
+               ArrayType  *options;
 
                /*
                 * Check consistency of arguments
@@ -786,6 +788,7 @@ InitPlan(QueryDesc *queryDesc, int eflags)
                 */
                tupdesc = CreateTupleDescCopy(tupType);
 
+               options = OptionBuild(NULL, parseTree->intoOptions);
                intoRelationId = heap_create_with_catalog(intoName,
                                                                                                  namespaceId,
                                                                                                  tablespaceId,
@@ -797,7 +800,10 @@ InitPlan(QueryDesc *queryDesc, int eflags)
                                                                                                  true,
                                                                                                  0,
                                                                                                  parseTree->intoOnCommit,
-                                                                                                 allowSystemTableMods);
+                                                                                                 allowSystemTableMods,
+                                                                                                 options);
+               if (options)
+                       pfree(options);
 
                FreeTupleDesc(tupdesc);
 
index 7277e539e8d50c938061bc172ed263b4a13a31b3..4e1a098c5ee30206574c8df14db0635ef5e2f7f8 100644 (file)
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.339 2006/07/02 01:58:36 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.340 2006/07/02 02:23:20 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1640,6 +1640,7 @@ _copyConstraint(Constraint *from)
        COPY_NODE_FIELD(raw_expr);
        COPY_STRING_FIELD(cooked_expr);
        COPY_NODE_FIELD(keys);
+       COPY_NODE_FIELD(options);
        COPY_STRING_FIELD(indexspace);
 
        return newnode;
@@ -1680,6 +1681,7 @@ _copyQuery(Query *from)
        COPY_SCALAR_FIELD(resultRelation);
        COPY_NODE_FIELD(into);
        COPY_SCALAR_FIELD(intoHasOids);
+       COPY_NODE_FIELD(intoOptions);
        COPY_SCALAR_FIELD(intoOnCommit);
        COPY_STRING_FIELD(intoTableSpaceName);
        COPY_SCALAR_FIELD(hasAggs);
@@ -1746,7 +1748,7 @@ _copySelectStmt(SelectStmt *from)
        COPY_NODE_FIELD(distinctClause);
        COPY_NODE_FIELD(into);
        COPY_NODE_FIELD(intoColNames);
-       COPY_SCALAR_FIELD(intoHasOids);
+       COPY_NODE_FIELD(intoOptions);
        COPY_SCALAR_FIELD(intoOnCommit);
        COPY_STRING_FIELD(intoTableSpaceName);
        COPY_NODE_FIELD(targetList);
@@ -1929,7 +1931,7 @@ _copyCreateStmt(CreateStmt *from)
        COPY_NODE_FIELD(tableElts);
        COPY_NODE_FIELD(inhRelations);
        COPY_NODE_FIELD(constraints);
-       COPY_SCALAR_FIELD(hasoids);
+       COPY_NODE_FIELD(options);
        COPY_SCALAR_FIELD(oncommit);
        COPY_STRING_FIELD(tablespacename);
 
@@ -2021,6 +2023,7 @@ _copyIndexStmt(IndexStmt *from)
        COPY_STRING_FIELD(accessMethod);
        COPY_STRING_FIELD(tableSpace);
        COPY_NODE_FIELD(indexParams);
+       COPY_NODE_FIELD(options);
        COPY_NODE_FIELD(whereClause);
        COPY_NODE_FIELD(rangetable);
        COPY_SCALAR_FIELD(unique);
@@ -2638,8 +2641,8 @@ _copyExecuteStmt(ExecuteStmt *from)
 
        COPY_STRING_FIELD(name);
        COPY_NODE_FIELD(into);
-       COPY_SCALAR_FIELD(into_contains_oids);
        COPY_SCALAR_FIELD(into_has_oids);
+       COPY_NODE_FIELD(intoOptions);
        COPY_SCALAR_FIELD(into_on_commit);
        COPY_STRING_FIELD(into_tbl_space);
        COPY_NODE_FIELD(params);
index 56d8d09a02ef382ea037a3b693c6abe60f604890..3af0acb10a210aabd2749f235c1e5e7895c77fbd 100644 (file)
@@ -18,7 +18,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.273 2006/06/27 03:43:20 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.274 2006/07/02 02:23:20 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -659,6 +659,7 @@ _equalQuery(Query *a, Query *b)
        COMPARE_SCALAR_FIELD(resultRelation);
        COMPARE_NODE_FIELD(into);
        COMPARE_SCALAR_FIELD(intoHasOids);
+       COMPARE_NODE_FIELD(intoOptions);
        COMPARE_SCALAR_FIELD(intoOnCommit);
        COMPARE_STRING_FIELD(intoTableSpaceName);
        COMPARE_SCALAR_FIELD(hasAggs);
@@ -717,7 +718,7 @@ _equalSelectStmt(SelectStmt *a, SelectStmt *b)
        COMPARE_NODE_FIELD(distinctClause);
        COMPARE_NODE_FIELD(into);
        COMPARE_NODE_FIELD(intoColNames);
-       COMPARE_SCALAR_FIELD(intoHasOids);
+       COMPARE_NODE_FIELD(intoOptions);
        COMPARE_SCALAR_FIELD(intoOnCommit);
        COMPARE_STRING_FIELD(intoTableSpaceName);
        COMPARE_NODE_FIELD(targetList);
@@ -873,7 +874,7 @@ _equalCreateStmt(CreateStmt *a, CreateStmt *b)
        COMPARE_NODE_FIELD(tableElts);
        COMPARE_NODE_FIELD(inhRelations);
        COMPARE_NODE_FIELD(constraints);
-       COMPARE_SCALAR_FIELD(hasoids);
+       COMPARE_NODE_FIELD(options);
        COMPARE_SCALAR_FIELD(oncommit);
        COMPARE_STRING_FIELD(tablespacename);
 
@@ -951,6 +952,7 @@ _equalIndexStmt(IndexStmt *a, IndexStmt *b)
        COMPARE_STRING_FIELD(accessMethod);
        COMPARE_STRING_FIELD(tableSpace);
        COMPARE_NODE_FIELD(indexParams);
+       COMPARE_NODE_FIELD(options);
        COMPARE_NODE_FIELD(whereClause);
        COMPARE_NODE_FIELD(rangetable);
        COMPARE_SCALAR_FIELD(unique);
@@ -1471,8 +1473,8 @@ _equalExecuteStmt(ExecuteStmt *a, ExecuteStmt *b)
 {
        COMPARE_STRING_FIELD(name);
        COMPARE_NODE_FIELD(into);
-       COMPARE_SCALAR_FIELD(into_contains_oids);
        COMPARE_SCALAR_FIELD(into_has_oids);
+       COMPARE_NODE_FIELD(intoOptions);
        COMPARE_SCALAR_FIELD(into_on_commit);
        COMPARE_STRING_FIELD(into_tbl_space);
        COMPARE_NODE_FIELD(params);
@@ -1673,6 +1675,7 @@ _equalConstraint(Constraint *a, Constraint *b)
        COMPARE_NODE_FIELD(raw_expr);
        COMPARE_STRING_FIELD(cooked_expr);
        COMPARE_NODE_FIELD(keys);
+       COMPARE_NODE_FIELD(options);
        COMPARE_STRING_FIELD(indexspace);
 
        return true;
index 7444001acb8927bc9671bbae0a722216ebff4ff1..d8653605635a82b294b3e5760053fa2f055994a2 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.275 2006/07/01 18:38:32 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.276 2006/07/02 02:23:20 momjian Exp $
  *
  * NOTES
  *       Every node type that can appear in stored rules' parsetrees *must*
@@ -1325,7 +1325,7 @@ _outCreateStmt(StringInfo str, CreateStmt *node)
        WRITE_NODE_FIELD(tableElts);
        WRITE_NODE_FIELD(inhRelations);
        WRITE_NODE_FIELD(constraints);
-       WRITE_ENUM_FIELD(hasoids, ContainsOids);
+       WRITE_NODE_FIELD(options);
        WRITE_ENUM_FIELD(oncommit, OnCommitAction);
        WRITE_STRING_FIELD(tablespacename);
 }
@@ -1340,6 +1340,7 @@ _outIndexStmt(StringInfo str, IndexStmt *node)
        WRITE_STRING_FIELD(accessMethod);
        WRITE_STRING_FIELD(tableSpace);
        WRITE_NODE_FIELD(indexParams);
+       WRITE_NODE_FIELD(options);
        WRITE_NODE_FIELD(whereClause);
        WRITE_NODE_FIELD(rangetable);
        WRITE_BOOL_FIELD(unique);
@@ -1373,7 +1374,7 @@ _outSelectStmt(StringInfo str, SelectStmt *node)
        WRITE_NODE_FIELD(distinctClause);
        WRITE_NODE_FIELD(into);
        WRITE_NODE_FIELD(intoColNames);
-       WRITE_ENUM_FIELD(intoHasOids, ContainsOids);
+       WRITE_NODE_FIELD(intoOptions);
        WRITE_ENUM_FIELD(intoOnCommit, OnCommitAction);
        WRITE_STRING_FIELD(intoTableSpaceName);
        WRITE_NODE_FIELD(targetList);
@@ -1509,6 +1510,7 @@ _outQuery(StringInfo str, Query *node)
        WRITE_INT_FIELD(resultRelation);
        WRITE_NODE_FIELD(into);
        WRITE_BOOL_FIELD(intoHasOids);
+       WRITE_NODE_FIELD(intoOptions);
        WRITE_ENUM_FIELD(intoOnCommit, OnCommitAction);
        WRITE_STRING_FIELD(intoTableSpaceName);
        WRITE_BOOL_FIELD(hasAggs);
@@ -1762,12 +1764,14 @@ _outConstraint(StringInfo str, Constraint *node)
                case CONSTR_PRIMARY:
                        appendStringInfo(str, "PRIMARY_KEY");
                        WRITE_NODE_FIELD(keys);
+                       WRITE_NODE_FIELD(options);
                        WRITE_STRING_FIELD(indexspace);
                        break;
 
                case CONSTR_UNIQUE:
                        appendStringInfo(str, "UNIQUE");
                        WRITE_NODE_FIELD(keys);
+                       WRITE_NODE_FIELD(options);
                        WRITE_STRING_FIELD(indexspace);
                        break;
 
index dd6995a1722e766137e478f858c096466586835e..0e061c44c553b7b175dc86609d9a6ae83d72b0f1 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.189 2006/04/30 18:30:39 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.190 2006/07/02 02:23:20 momjian Exp $
  *
  * NOTES
  *       Path and Plan nodes do not have any readfuncs support, because we
@@ -141,6 +141,7 @@ _readQuery(void)
        READ_INT_FIELD(resultRelation);
        READ_NODE_FIELD(into);
        READ_BOOL_FIELD(intoHasOids);
+       READ_NODE_FIELD(intoOptions);
        READ_ENUM_FIELD(intoOnCommit, OnCommitAction);
        READ_STRING_FIELD(intoTableSpaceName);
        READ_BOOL_FIELD(hasAggs);
index 8b9b9eab536a1f9655b2495a81d03b359ec5503f..9e66ca1ab65cb3d146697ac619bde843d156e732 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *     $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.336 2006/06/27 03:43:20 momjian Exp $
+ *     $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.337 2006/07/02 02:23:20 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -757,7 +757,7 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt,
        cxt.blist = NIL;
        cxt.alist = NIL;
        cxt.pkey = NULL;
-       cxt.hasoids = interpretOidsOption(stmt->hasoids);
+       cxt.hasoids = interpretOidsOption(stmt->options);
 
        /*
         * Run through each primary element in the table creation clause. Separate
@@ -1282,6 +1282,7 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
 
                index->relation = cxt->relation;
                index->accessMethod = DEFAULT_INDEX_TYPE;
+               index->options = constraint->options;
                index->tableSpace = constraint->indexspace;
                index->indexParams = NIL;
                index->whereClause = NULL;
@@ -1881,7 +1882,8 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
        if (stmt->intoColNames)
                applyColumnNames(qry->targetList, stmt->intoColNames);
 
-       qry->intoHasOids = interpretOidsOption(stmt->intoHasOids);
+       qry->intoHasOids = interpretOidsOption(stmt->intoOptions);
+       qry->intoOptions = copyObject(stmt->intoOptions);
        qry->intoOnCommit = stmt->intoOnCommit;
        qry->intoTableSpaceName = stmt->intoTableSpaceName;
 
@@ -2752,7 +2754,7 @@ transformExecuteStmt(ParseState *pstate, ExecuteStmt *stmt)
 
        paramtypes = FetchPreparedStatementParams(stmt->name);
 
-       stmt->into_has_oids = interpretOidsOption(stmt->into_contains_oids);
+       stmt->into_has_oids = interpretOidsOption(stmt->intoOptions);
 
        if (stmt->params || paramtypes)
        {
index 9ad722528e19c2279abfc35b52833715f027bb9c..f09a7a6b2de1303298433fa8b5a91a1fc54582e0 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.549 2006/07/02 01:58:36 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.550 2006/07/02 02:23:21 momjian Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
@@ -53,6 +53,7 @@
 
 #include "catalog/index.h"
 #include "catalog/namespace.h"
+#include "commands/defrem.h"
 #include "nodes/makefuncs.h"
 #include "parser/gramparse.h"
 #include "storage/lmgr.h"
@@ -123,7 +124,6 @@ static void doNegateFloat(Value *v);
        JoinType                        jtype;
        DropBehavior            dbehavior;
        OnCommitAction          oncommit;
-       ContainsOids            withoids;
        List                            *list;
        Node                            *node;
        Value                           *value;
@@ -228,11 +228,11 @@ static void doNegateFloat(Value *v);
 
 %type <list>   stmtblock stmtmulti
                                OptTableElementList TableElementList OptInherit definition
-                               opt_distinct opt_definition func_args func_args_list
+                               OptWith opt_distinct opt_definition func_args func_args_list
                                func_as createfunc_opt_list alterfunc_opt_list
                                aggr_args aggr_args_list old_aggr_definition old_aggr_list
                                oper_argtypes RuleActionList RuleActionMulti
-                               opt_column_list columnList opt_name_list
+                               opt_column_list columnList opt_name_list 
                                sort_clause opt_sort_clause sortby_list index_params
                                name_list from_clause from_list opt_array_bounds
                                qualified_name_list any_name any_name_list
@@ -255,7 +255,6 @@ static void doNegateFloat(Value *v);
 
 %type <boolean>  TriggerForType OptTemp
 %type <oncommit> OnCommitOption
-%type <withoids> OptWithOids
 
 %type <node>   for_locking_item
 %type <list>   for_locking_clause opt_for_locking_clause for_locking_items
@@ -1559,6 +1558,32 @@ alter_rel_cmd:
                                        n->name = $3;
                                        $$ = (Node *)n;
                                }
+                       /* ALTER [TABLE|INDEX] <name> SET (...) */
+                       | SET definition
+                               {
+                                       AlterTableCmd *n = makeNode(AlterTableCmd);
+                                       n->subtype = AT_SetOptions;
+                                       n->def = (Node *)$2;
+                                       $$ = (Node *)n;
+                               }
+                       | RESET definition
+                               {
+                                       AlterTableCmd *n;
+                                       ListCell          *cell;
+                                       
+                                       foreach(cell, $2)
+                                       {
+                                               if (((DefElem *) lfirst(cell))->arg != NULL)
+                                                       ereport(ERROR,
+                                                                       (errcode(ERRCODE_SYNTAX_ERROR),
+                                                                        errmsg("parameters for RESET should not take values")));
+                                       }
+
+                                       n = makeNode(AlterTableCmd);
+                                       n->subtype = AT_SetOptions;
+                                       n->def = (Node *)$2;
+                                       $$ = (Node *)n;
+                               }
                ;
 
 alter_column_default:
@@ -1744,7 +1769,7 @@ opt_using:
  *****************************************************************************/
 
 CreateStmt:    CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
-                       OptInherit OptWithOids OnCommitOption OptTableSpace
+                       OptInherit OptWith OnCommitOption OptTableSpace
                                {
                                        CreateStmt *n = makeNode(CreateStmt);
                                        $4->istemp = $2;
@@ -1752,13 +1777,13 @@ CreateStmt:     CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
                                        n->tableElts = $6;
                                        n->inhRelations = $8;
                                        n->constraints = NIL;
-                                       n->hasoids = $9;
+                                       n->options = $9;
                                        n->oncommit = $10;
                                        n->tablespacename = $11;
                                        $$ = (Node *)n;
                                }
                | CREATE OptTemp TABLE qualified_name OF qualified_name
-                       '(' OptTableElementList ')' OptWithOids OnCommitOption OptTableSpace
+                       '(' OptTableElementList ')' OptWith OnCommitOption OptTableSpace
                                {
                                        /* SQL99 CREATE TABLE OF <UDT> (cols) seems to be satisfied
                                         * by our inheritance capabilities. Let's try it...
@@ -1769,7 +1794,7 @@ CreateStmt:       CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
                                        n->tableElts = $8;
                                        n->inhRelations = list_make1($6);
                                        n->constraints = NIL;
-                                       n->hasoids = $10;
+                                       n->options = $10;
                                        n->oncommit = $11;
                                        n->tablespacename = $12;
                                        $$ = (Node *)n;
@@ -1905,7 +1930,7 @@ ColConstraintElem:
                                        n->indexspace = $2;
                                        $$ = (Node *)n;
                                }
-                       | PRIMARY KEY OptConsTableSpace
+                       | PRIMARY KEY opt_definition OptConsTableSpace
                                {
                                        Constraint *n = makeNode(Constraint);
                                        n->contype = CONSTR_PRIMARY;
@@ -1913,7 +1938,8 @@ ColConstraintElem:
                                        n->raw_expr = NULL;
                                        n->cooked_expr = NULL;
                                        n->keys = NULL;
-                                       n->indexspace = $3;
+                                       n->options = $3;
+                                       n->indexspace = $4;
                                        $$ = (Node *)n;
                                }
                        | CHECK '(' a_expr ')'
@@ -2085,7 +2111,7 @@ ConstraintElem:
                                        n->indexspace = $5;
                                        $$ = (Node *)n;
                                }
-                       | PRIMARY KEY '(' columnList ')' OptConsTableSpace
+                       | PRIMARY KEY '(' columnList ')' opt_definition OptConsTableSpace
                                {
                                        Constraint *n = makeNode(Constraint);
                                        n->contype = CONSTR_PRIMARY;
@@ -2093,7 +2119,8 @@ ConstraintElem:
                                        n->raw_expr = NULL;
                                        n->cooked_expr = NULL;
                                        n->keys = $4;
-                                       n->indexspace = $6;
+                                       n->options = $6;
+                                       n->indexspace = $7;
                                        $$ = (Node *)n;
                                }
                        | FOREIGN KEY '(' columnList ')' REFERENCES qualified_name
@@ -2187,10 +2214,13 @@ OptInherit: INHERITS '(' qualified_name_list ')'        { $$ = $3; }
                        | /*EMPTY*/                                                             { $$ = NIL; }
                ;
 
-OptWithOids:
-                       WITH OIDS                                                               { $$ = MUST_HAVE_OIDS; }
-                       | WITHOUT OIDS                                                  { $$ = MUST_NOT_HAVE_OIDS; }
-                       | /*EMPTY*/                                                             { $$ = DEFAULT_OIDS; }
+OptWith:
+                       WITH OIDS                                               { $$ = list_make1(defWithOids(true)); }
+                       | WITHOUT OIDS                                  { $$ = list_make1(defWithOids(false)); }
+                       | WITH definition                               { $$ = $2; }
+                       | WITH OIDS WITH definition             { $$ = lappend($4, defWithOids(true)); }
+                       | WITHOUT OIDS WITH definition  { $$ = lappend($4, defWithOids(false)); }
+                       | /*EMPTY*/                                             { $$ = NIL; }
                ;
 
 OnCommitOption:  ON COMMIT DROP                                { $$ = ONCOMMIT_DROP; }
@@ -2215,7 +2245,7 @@ OptConsTableSpace:   USING INDEX TABLESPACE name  { $$ = $4; }
 
 CreateAsStmt:
                CREATE OptTemp TABLE qualified_name OptCreateAs
-                       OptWithOids OnCommitOption OptTableSpace AS SelectStmt
+                       OptWith OnCommitOption OptTableSpace AS SelectStmt
                                {
                                        /*
                                         * When the SelectStmt is a set-operation tree, we must
@@ -2232,7 +2262,7 @@ CreateAsStmt:
                                        $4->istemp = $2;
                                        n->into = $4;
                                        n->intoColNames = $5;
-                                       n->intoHasOids = $6;
+                                       n->intoOptions = $6;
                                        n->intoOnCommit = $7;
                                        n->intoTableSpaceName = $8;
                                        $$ = $10;
@@ -3630,7 +3660,7 @@ opt_granted_by: GRANTED BY RoleId                                         { $$ = $3; }
  *****************************************************************************/
 
 IndexStmt:     CREATE index_opt_unique INDEX index_name ON qualified_name
-                       access_method_clause '(' index_params ')' OptTableSpace where_clause
+                       access_method_clause '(' index_params ')' opt_definition OptTableSpace where_clause
                                {
                                        IndexStmt *n = makeNode(IndexStmt);
                                        n->unique = $2;
@@ -3638,8 +3668,9 @@ IndexStmt:        CREATE index_opt_unique INDEX index_name ON qualified_name
                                        n->relation = $6;
                                        n->accessMethod = $7;
                                        n->indexParams = $9;
-                                       n->tableSpace = $11;
-                                       n->whereClause = $12;
+                                       n->options = $11;
+                                       n->tableSpace = $12;
+                                       n->whereClause = $13;
                                        $$ = (Node *)n;
                                }
                ;
@@ -5264,7 +5295,7 @@ ExecuteStmt: EXECUTE name execute_param_clause
                                        $$ = (Node *) n;
                                }
                        | CREATE OptTemp TABLE qualified_name OptCreateAs
-                               OptWithOids OnCommitOption OptTableSpace AS
+                               OptWith OnCommitOption OptTableSpace AS
                                EXECUTE name execute_param_clause
                                {
                                        ExecuteStmt *n = makeNode(ExecuteStmt);
@@ -5272,7 +5303,7 @@ ExecuteStmt: EXECUTE name execute_param_clause
                                        n->params = $12;
                                        $4->istemp = $2;
                                        n->into = $4;
-                                       n->into_contains_oids = $6;
+                                       n->intoOptions = $6;
                                        n->into_on_commit = $7;
                                        n->into_tbl_space = $8;
                                        if ($5)
@@ -5606,7 +5637,6 @@ simple_select:
                                        n->targetList = $3;
                                        n->into = $4;
                                        n->intoColNames = NIL;
-                                       n->intoHasOids = DEFAULT_OIDS;
                                        n->fromClause = $5;
                                        n->whereClause = $6;
                                        n->groupClause = $7;
index 9bdb91b47445b9972be2433f50e11e81cdeeb8a2..a4fe1999fe5154991228b35c2fadd12a4995d0bc 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.149 2006/03/16 00:31:55 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.150 2006/07/02 02:23:21 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -17,6 +17,7 @@
 
 #include "access/heapam.h"
 #include "catalog/heap.h"
+#include "commands/defrem.h"
 #include "nodes/makefuncs.h"
 #include "optimizer/clauses.h"
 #include "optimizer/tlist.h"
@@ -33,6 +34,7 @@
 #include "rewrite/rewriteManip.h"
 #include "utils/builtins.h"
 #include "utils/guc.h"
+#include "utils/memutils.h"
 
 
 #define ORDER_CLAUSE 0
@@ -64,6 +66,8 @@ static Node *buildMergedJoinVar(ParseState *pstate, JoinType jointype,
                                   Var *l_colvar, Var *r_colvar);
 static TargetEntry *findTargetlistEntry(ParseState *pstate, Node *node,
                                        List **tlist, int clause);
+static bool OptionMatches(text *t, const char* kw, char **str, Size *len);
+static Datum OptionToText(DefElem *def);
 
 
 /*
@@ -212,29 +216,280 @@ interpretInhOption(InhOption inhOpt)
 }
 
 /*
- * Given an enum that indicates whether WITH / WITHOUT OIDS was
+ * Given a List that indicates whether WITH / WITHOUT OIDS was
  * specified by the user, return true iff the specified table/result
  * set should be created with OIDs. This needs to be done after
  * parsing the query string because the return value can depend upon
  * the default_with_oids GUC var.
  */
 bool
-interpretOidsOption(ContainsOids opt)
+interpretOidsOption(List *options)
 {
-       switch (opt)
+       ListCell   *cell;
+
+       foreach(cell, options)
        {
-               case MUST_HAVE_OIDS:
-                       return true;
+               DefElem    *def = (DefElem *) lfirst(cell);
 
-               case MUST_NOT_HAVE_OIDS:
-                       return false;
+               if (pg_strcasecmp(def->defname, "oids") == 0)
+                       return defGetBoolean(def);
+       }
+
+       /* oids option is not specified. */
+       return default_with_oids;
+}
 
-               case DEFAULT_OIDS:
-                       return default_with_oids;
+/*
+ * Test if t is start with 'kw='.
+ */
+static bool
+OptionMatches(text *t, const char* kw, char **str, Size *len)
+{
+       char   *text_str = (char *) VARATT_DATA(t);
+       int             text_len = VARATT_SIZE(t) - VARHDRSZ;
+       Size    kwlen = strlen(kw);
+
+       if (text_len > kwlen && text_str[kwlen] == '=' && 
+        pg_strncasecmp(text_str, kw, kwlen) == 0)
+       {
+               *str = text_str + kwlen + 1;
+               *len = text_len - kwlen - 1;
+               return true;
        }
 
-       elog(ERROR, "bogus ContainsOids value: %d", opt);
-       return false;                           /* keep compiler quiet */
+       return false;
+}
+
+/*
+ * Flatten a DefElem to a text like as 'defname=arg'.
+ */
+static Datum
+OptionToText(DefElem *def)
+{
+       text   *t;
+       char   *value = defGetString(def);
+       Size    len = VARHDRSZ + strlen(def->defname) + 1 + strlen(value);
+
+       t = palloc(len + 1);
+       VARATT_SIZEP(t) = len;
+       sprintf((char *) VARATT_DATA(t), "%s=%s", def->defname, value);
+
+       return PointerGetDatum(t);
+}
+
+/*
+ * Merge option array and option list.
+ *
+ *     array   Existing option, or NULL if new option.
+ *     list    List of DefElems to be added to array.
+ */
+ArrayType *
+OptionBuild(ArrayType *array, List *list)
+{
+       ListCell                   *cell;
+       bool                       *used;
+       int                                     index;
+       int                                     o;
+       ArrayType                  *result;
+       ArrayBuildState    *astate;
+       MemoryContext           myContext;
+       MemoryContext           oldContext;
+
+       if (list_length(list) == 0)
+       {
+               /* no additinal elements, so just clone. */
+               if (array == NULL)
+                       return NULL;
+               result = palloc(VARATT_SIZE(array));
+               memcpy(result, array, VARATT_SIZE(array));
+               return result;
+       }
+
+       /* Make a temporary context to hold all the junk */
+       myContext = AllocSetContextCreate(CurrentMemoryContext,
+                                                                         "OptionBuild",
+                                                                         ALLOCSET_DEFAULT_MINSIZE,
+                                                                         ALLOCSET_DEFAULT_INITSIZE,
+                                                                         ALLOCSET_DEFAULT_MAXSIZE);
+       oldContext = MemoryContextSwitchTo(myContext);
+
+       astate = NULL;
+       used = (bool *) palloc0(sizeof(bool) * list_length(list));
+
+       if (array)
+       {
+               Assert(ARR_ELEMTYPE(array) == TEXTOID);
+               Assert(ARR_NDIM(array) == 1);
+               Assert(ARR_LBOUND(array)[0] == 1);
+
+               for (o = 1; o <= ARR_DIMS(array)[0]; o++)
+               {
+                       bool            isnull;
+                       Datum           datum;
+
+                       datum = array_ref(array, 1, &o,
+                                               -1 /* varlenarray */ ,
+                                               -1 /* TEXT's typlen */ ,
+                                               false /* TEXT's typbyval */ ,
+                                               'i' /* TEXT's typalign */ ,
+                                               &isnull);
+                       if (isnull)
+                               continue;
+
+                       index = 0;
+                       foreach(cell, list)
+                       {
+                               DefElem    *def = lfirst(cell);
+
+                               /*
+                                * We ignore 'oids' item because it is stored
+                                * in pg_class.relhasoids.
+                                */
+                               if (!used[index] &&
+                                       pg_strcasecmp(def->defname, "oids") != 0)
+                               {
+                                       char   *value_str;
+                                       Size    value_len;
+                                       if (OptionMatches(DatumGetTextP(datum),
+                                               def->defname, &value_str, &value_len))
+                                       {
+                                               used[index] = true;
+                                               if (def->arg)
+                                               {
+                                                       /* Replace an existing option. */
+                                                       datum = OptionToText(def);
+                                                       goto next;      /* skip remain items in list */
+                                               }
+                                               else
+                                               {
+                                                       /* Remove the option from array. */
+                                                       goto skip;
+                                               }
+                                       }
+                               }
+
+                               index++;
+                       }
+
+                       /*
+                        * The datum is an existing parameter and is not modified.
+                        * Fall down.
+                        */
+
+next:
+                       astate = accumArrayResult(astate, datum, false, TEXTOID, myContext);
+skip:
+                       ;
+               }
+       }
+
+       /*
+        * add options not in array
+        */
+       index = 0;
+       foreach(cell, list)
+       {
+               DefElem    *def = lfirst(cell);
+
+               if (!used[index] && def->arg &&
+                       pg_strcasecmp(def->defname, "oids") != 0)
+               {
+                       astate = accumArrayResult(astate, OptionToText(def),
+                               false, TEXTOID, myContext);
+               }
+
+               index++;
+       }
+
+       if (astate)
+               result = DatumGetArrayTypeP(makeArrayResult(astate, oldContext));
+       else
+               result = NULL;
+
+       MemoryContextSwitchTo(oldContext);
+       MemoryContextDelete(myContext);
+       return result;
+}
+
+/*
+ * Support routine to parse options.
+ *
+ *     options List of DefElems
+ *     num             length of kwds
+ *     kwds    supported keywords
+ *     strict  Throw error if unsupported option is found.
+ *
+ * FIXME: memory is leaked in kwds[].arg.
+ */
+void
+OptionParse(ArrayType *options, Size num, DefElem kwds[], bool strict)
+{
+       Size    k;
+       int             o;
+
+       for (k = 0; k < num; k++)
+       {
+               Assert(kwds[k].defname);
+               kwds[k].arg = NULL;
+       }
+
+       if (options == NULL)
+               return; /* use default for all */
+
+       Assert(ARR_ELEMTYPE(options) == TEXTOID);
+       Assert(ARR_NDIM(options) == 1);
+       Assert(ARR_LBOUND(options)[0] == 1);
+
+       for (o = 1; o <= ARR_DIMS(options)[0]; o++)
+       {
+               bool            isnull;
+               Datum           datum;
+
+               datum = array_ref(options, 1, &o,
+                                         -1 /* varlenarray */ ,
+                                         -1 /* TEXT's typlen */ ,
+                                         false /* TEXT's typbyval */ ,
+                                         'i' /* TEXT's typalign */ ,
+                                         &isnull);
+               if (isnull)
+                       continue;
+
+               for (k = 0; k < num; k++)
+               {
+                       char       *value_str;
+                       Size            value_len;
+
+                       if (OptionMatches(DatumGetTextP(datum),
+                               kwds[k].defname, &value_str, &value_len))
+                       {
+                               char   *value;
+
+                               if (kwds[k].arg != NULL)
+                                       ereport(ERROR,
+                                                       (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                                        errmsg("duplicated parameter %s",
+                                                        kwds[k].defname)));
+
+                               /* copy value as Value node */
+                               value = (char *) palloc(value_len + 1);
+                               strncpy(value, value_str, value_len);
+                               value[value_len] = '\0';
+                               kwds[k].arg = (Node *) makeString(value);
+                               goto next;      /* skip remain keywords */
+                       }
+               }
+
+               /* parameter is not in kwds */
+               if (strict)
+               {
+                       char *c = DatumGetCString(DirectFunctionCall1(textout, datum));
+
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                        errmsg("unsupported parameter %s", c)));
+               }
+next:;
+       }
 }
 
 /*
index 749b96cb45cf47e3490589b7ee68a9dc6f9b51ea..23bc8537a159630261405c7fbe37d1cfee31c318 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.258 2006/06/16 20:23:44 adunstan Exp $
+ *       $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.259 2006/07/02 02:23:21 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -794,6 +794,7 @@ ProcessUtility(Node *parsetree,
                                                        stmt->indexParams,      /* parameters */
                                                        (Expr *) stmt->whereClause,
                                                        stmt->rangetable,
+                                                       stmt->options,
                                                        stmt->unique,
                                                        stmt->primary,
                                                        stmt->isconstraint,
index 182d3cf1072536a5c7bf988a56a8ebd2fd09149d..2ddbb64763c6ac7b3d4de923d4703688439172cc 100644 (file)
@@ -2,7 +2,7 @@
  * ruleutils.c - Functions to convert stored expressions/querytrees
  *                             back to source text
  *
- *       $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.224 2006/06/16 18:42:22 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.225 2006/07/02 02:23:21 momjian Exp $
  **********************************************************************/
 
 #include "postgres.h"
@@ -187,6 +187,7 @@ static char *generate_relation_name(Oid relid);
 static char *generate_function_name(Oid funcid, int nargs, Oid *argtypes);
 static char *generate_operator_name(Oid operid, Oid arg1, Oid arg2);
 static text *string_to_text(char *str);
+static char *flatten_reloptions(Oid relid);
 
 #define only_marker(rte)  ((rte)->inh ? "" : "ONLY ")
 
@@ -756,9 +757,20 @@ pg_get_indexdef_worker(Oid indexrelid, int colno, int prettyFlags)
        }
 
        if (!colno)
-       {
                appendStringInfoChar(&buf, ')');
 
+       /*
+        * If it has options, append "WITH (options)"
+        */
+       str = flatten_reloptions(indexrelid);
+       if (str)
+       {
+               appendStringInfo(&buf, " WITH (%s)", str);
+               pfree(str);
+       }
+
+       if (!colno)
+       {
                /*
                 * If it's a partial index, decompile and append the predicate
                 */
@@ -1004,6 +1016,17 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
                                decompile_column_index_array(val, conForm->conrelid, &buf);
 
                                appendStringInfo(&buf, ")");
+
+                               if (fullCommand && OidIsValid(conForm->conrelid))
+                               {
+                                       char   *options = flatten_reloptions(conForm->conrelid);
+                                       if (options)
+                                       {
+                                               appendStringInfo(&buf, " WITH (%s)", options);
+                                               pfree(options);
+                                       }
+                               }
+
                                break;
                        }
                case CONSTRAINT_CHECK:
@@ -4913,3 +4936,36 @@ string_to_text(char *str)
 
        return result;
 }
+
+static char *
+flatten_reloptions(Oid relid)
+{
+       HeapTuple       tuple;
+       char       *result = NULL;
+
+       tuple = SearchSysCache(RELOID,
+                                                  ObjectIdGetDatum(relid),
+                                                  0, 0, 0);
+       if (tuple)
+       {
+               bool    isnull;
+               Datum   reloptions;
+               reloptions = SysCacheGetAttr(RELOID, tuple,
+            Anum_pg_class_reloptions, &isnull);
+               if (!isnull)
+               {
+                       Datum   sep,
+                                       txt;
+                       sep = DirectFunctionCall1(textin, CStringGetDatum(", "));
+                       /*
+                        * OID 395 = array_to_text.
+                        * DirectFunctionCall2(array_to_text) is not available here.
+                        */
+                       txt = OidFunctionCall2(395, reloptions, sep);
+                       result = DatumGetCString(DirectFunctionCall1(textout, txt));
+               }
+               ReleaseSysCache(tuple);
+       }
+
+       return result;
+}
index 82de42020e89ec1a2e9c0fdadc9633d91e4d9086..50edf7691a4e7ca763a5c9a6926341f15b024855 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.242 2006/06/16 18:42:22 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.243 2006/07/02 02:23:21 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -47,6 +47,8 @@
 #include "catalog/pg_proc.h"
 #include "catalog/pg_rewrite.h"
 #include "catalog/pg_type.h"
+#include "catalog/heap.h"
+#include "catalog/index.h"
 #include "commands/trigger.h"
 #include "miscadmin.h"
 #include "optimizer/clauses.h"
@@ -54,6 +56,7 @@
 #include "optimizer/prep.h"
 #include "storage/fd.h"
 #include "storage/smgr.h"
+#include "utils/array.h"
 #include "utils/builtins.h"
 #include "utils/catcache.h"
 #include "utils/fmgroids.h"
@@ -71,7 +74,7 @@
  */
 #define RELCACHE_INIT_FILENAME "pg_internal.init"
 
-#define RELCACHE_INIT_FILEMAGIC                0x573262        /* version ID value */
+#define RELCACHE_INIT_FILEMAGIC                0x573263        /* version ID value */
 
 /*
  *             hardcoded tuple descriptors.  see include/catalog/pg_attribute.h
@@ -183,6 +186,7 @@ static void RelationClearRelation(Relation relation, bool rebuild);
 static void RelationReloadClassinfo(Relation relation);
 static void RelationFlushRelation(Relation relation);
 static bool load_relcache_init_file(void);
+static void    write_item(const void *data, Size len, FILE *fp);
 static void write_relcache_init_file(void);
 
 static void formrdesc(const char *relationName, Oid relationReltype,
@@ -206,6 +210,7 @@ static void IndexSupportInitialize(oidvector *indclass,
 static OpClassCacheEnt *LookupOpclassInfo(Oid operatorClassOid,
                                  StrategyNumber numStrats,
                                  StrategyNumber numSupport);
+static void RelationParseOptions(Relation relation, HeapTuple tuple);
 
 
 /*
@@ -309,6 +314,7 @@ AllocateRelationDesc(Relation relation, Form_pg_class relp)
 
        /* initialize relation tuple form */
        relation->rd_rel = relationForm;
+       relation->rd_options = NULL;
 
        /* and allocate attribute tuple form storage */
        relation->rd_att = CreateTemplateTupleDesc(relationForm->relnatts,
@@ -321,6 +327,53 @@ AllocateRelationDesc(Relation relation, Form_pg_class relp)
        return relation;
 }
 
+/*
+ * RelationParseOptions
+ */
+static void
+RelationParseOptions(Relation relation, HeapTuple tuple)
+{
+       ArrayType          *options;
+
+       Assert(tuple);
+
+       switch (relation->rd_rel->relkind)
+       {
+       case RELKIND_RELATION:
+       case RELKIND_TOASTVALUE:
+       case RELKIND_UNCATALOGED:
+       case RELKIND_INDEX:
+               break;
+       default:
+               /* other relation should not have options. */
+               relation->rd_options = NULL;
+               return;
+       }
+
+       /* SysCacheGetAttr is not available here. */
+       if (heap_attisnull(tuple, Anum_pg_class_reloptions))
+               options = NULL;
+       else
+               options = (ArrayType *) ((Form_pg_class) GETSTRUCT(tuple))->reloptions;
+
+       switch (relation->rd_rel->relkind)
+       {
+       case RELKIND_RELATION:
+       case RELKIND_TOASTVALUE:
+       case RELKIND_UNCATALOGED:
+               relation->rd_options = heap_option(
+                       relation->rd_rel->relkind, options);
+               break;
+       case RELKIND_INDEX:
+               relation->rd_options = index_option(
+                       relation->rd_am->amoption, options);
+               break;
+       default:
+               /* should not happen */
+               break;
+       }
+}
+
 /*
  *             RelationBuildTupleDesc
  *
@@ -725,11 +778,6 @@ RelationBuildDesc(Oid targetRelId, Relation oldrelation)
         */
        relation = AllocateRelationDesc(oldrelation, relp);
 
-       /*
-        * now we can free the memory allocated for pg_class_tuple
-        */
-       heap_freetuple(pg_class_tuple);
-
        /*
         * initialize the relation's relation id (relation->rd_id)
         */
@@ -785,6 +833,14 @@ RelationBuildDesc(Oid targetRelId, Relation oldrelation)
        /* make sure relation is marked as having no open file yet */
        relation->rd_smgr = NULL;
 
+       /* Build AM-specific fields. */
+       RelationParseOptions(relation, pg_class_tuple);
+
+       /*
+        * now we can free the memory allocated for pg_class_tuple
+        */
+       heap_freetuple(pg_class_tuple);
+
        /*
         * Insert newly created relation into relcache hash tables.
         */
@@ -1210,6 +1266,7 @@ formrdesc(const char *relationName, Oid relationReltype,
         * data from pg_class and replace what we've done here.
         */
        relation->rd_rel = (Form_pg_class) palloc0(CLASS_TUPLE_SIZE);
+       relation->rd_options = NULL;
 
        namestrcpy(&relation->rd_rel->relname, relationName);
        relation->rd_rel->relnamespace = PG_CATALOG_NAMESPACE;
@@ -1297,6 +1354,11 @@ formrdesc(const char *relationName, Oid relationReltype,
                relation->rd_rel->relhasindex = true;
        }
 
+       /*
+        * initialize the rd_options field to default value
+        */
+       relation->rd_options = heap_option(RELKIND_RELATION, NULL);
+
        /*
         * add new reldesc to relcache
         */
@@ -1475,6 +1537,9 @@ RelationReloadClassinfo(Relation relation)
                         RelationGetRelid(relation));
        relp = (Form_pg_class) GETSTRUCT(pg_class_tuple);
        memcpy(relation->rd_rel, relp, CLASS_TUPLE_SIZE);
+       if (relation->rd_options)
+               pfree(relation->rd_options);
+       RelationParseOptions(relation, pg_class_tuple);
        heap_freetuple(pg_class_tuple);
        /* We must recalculate physical address in case it changed */
        RelationInitPhysicalAddr(relation);
@@ -1581,6 +1646,8 @@ RelationClearRelation(Relation relation, bool rebuild)
                pfree(relation->rd_am);
        if (relation->rd_rel)
                pfree(relation->rd_rel);
+       if (relation->rd_options)
+               pfree(relation->rd_options);
        list_free(relation->rd_indexlist);
        if (relation->rd_indexcxt)
                MemoryContextDelete(relation->rd_indexcxt);
@@ -2111,6 +2178,7 @@ RelationBuildLocalRelation(const char *relname,
         * initialize relation tuple form (caller may add/override data later)
         */
        rel->rd_rel = (Form_pg_class) palloc0(CLASS_TUPLE_SIZE);
+       rel->rd_options = NULL;
 
        namestrcpy(&rel->rd_rel->relname, relname);
        rel->rd_rel->relnamespace = relnamespace;
@@ -3032,6 +3100,22 @@ load_relcache_init_file(void)
                        has_not_null |= rel->rd_att->attrs[i]->attnotnull;
                }
 
+               /* next read the access method specific field */
+               if ((nread = fread(&len, 1, sizeof(len), fp)) != sizeof(len))
+                       goto read_failed;
+               if (len > 0)
+               {
+                       rel->rd_options = palloc(len);
+                       if ((nread = fread(rel->rd_options, 1, len, fp)) != len)
+                               goto read_failed;
+                       if (len != VARATT_SIZE(rel->rd_options))
+                               goto read_failed;
+               }
+               else
+               {
+                       rel->rd_options = NULL;
+               }
+
                /* mark not-null status */
                if (has_not_null)
                {
@@ -3215,6 +3299,15 @@ read_failed:
        return false;
 }
 
+static void
+write_item(const void *data, Size len, FILE *fp)
+{
+       if (fwrite(&len, 1, sizeof(len), fp) != sizeof(len))
+               elog(FATAL, "could not write init file");
+       if (fwrite(data, 1, len, fp) != len)
+               elog(FATAL, "could not write init file");
+}
+
 /*
  * Write out a new initialization file with the current contents
  * of the relcache.
@@ -3277,39 +3370,24 @@ write_relcache_init_file(void)
        {
                Relation        rel = idhentry->reldesc;
                Form_pg_class relform = rel->rd_rel;
-               Size            len;
-
-               /*
-                * first write the relcache entry proper
-                */
-               len = sizeof(RelationData);
 
-               /* first, write the relation descriptor length */
-               if (fwrite(&len, 1, sizeof(len), fp) != sizeof(len))
-                       elog(FATAL, "could not write init file");
-
-               /* next, write out the Relation structure */
-               if (fwrite(rel, 1, len, fp) != len)
-                       elog(FATAL, "could not write init file");
+               /* first write the relcache entry proper */
+               write_item(rel, sizeof(RelationData), fp);
 
                /* next write the relation tuple form */
-               len = sizeof(FormData_pg_class);
-               if (fwrite(&len, 1, sizeof(len), fp) != sizeof(len))
-                       elog(FATAL, "could not write init file");
-
-               if (fwrite(relform, 1, len, fp) != len)
-                       elog(FATAL, "could not write init file");
+               write_item(relform, CLASS_TUPLE_SIZE, fp);
 
                /* next, do all the attribute tuple form data entries */
                for (i = 0; i < relform->relnatts; i++)
                {
-                       len = ATTRIBUTE_TUPLE_SIZE;
-                       if (fwrite(&len, 1, sizeof(len), fp) != sizeof(len))
-                               elog(FATAL, "could not write init file");
-                       if (fwrite(rel->rd_att->attrs[i], 1, len, fp) != len)
-                               elog(FATAL, "could not write init file");
+                       write_item(rel->rd_att->attrs[i],
+                               ATTRIBUTE_TUPLE_SIZE, fp);
                }
 
+               /* next, do the access method specific field */
+               write_item(rel->rd_options,
+            (rel->rd_options ? VARATT_SIZE(rel->rd_options) : 0), fp);
+
                /* If it's an index, there's more to do */
                if (rel->rd_rel->relkind == RELKIND_INDEX)
                {
@@ -3317,36 +3395,19 @@ write_relcache_init_file(void)
 
                        /* write the pg_index tuple */
                        /* we assume this was created by heap_copytuple! */
-                       len = HEAPTUPLESIZE + rel->rd_indextuple->t_len;
-                       if (fwrite(&len, 1, sizeof(len), fp) != sizeof(len))
-                               elog(FATAL, "could not write init file");
-
-                       if (fwrite(rel->rd_indextuple, 1, len, fp) != len)
-                               elog(FATAL, "could not write init file");
+                       write_item(rel->rd_indextuple,
+                               HEAPTUPLESIZE + rel->rd_indextuple->t_len, fp);
 
                        /* next, write the access method tuple form */
-                       len = sizeof(FormData_pg_am);
-                       if (fwrite(&len, 1, sizeof(len), fp) != sizeof(len))
-                               elog(FATAL, "could not write init file");
-
-                       if (fwrite(am, 1, len, fp) != len)
-                               elog(FATAL, "could not write init file");
+                       write_item(am, sizeof(FormData_pg_am), fp);
 
                        /* next, write the vector of operator OIDs */
-                       len = relform->relnatts * (am->amstrategies * sizeof(Oid));
-                       if (fwrite(&len, 1, sizeof(len), fp) != sizeof(len))
-                               elog(FATAL, "could not write init file");
-
-                       if (fwrite(rel->rd_operator, 1, len, fp) != len)
-                               elog(FATAL, "could not write init file");
+                       write_item(rel->rd_operator, relform->relnatts *
+                               (am->amstrategies * sizeof(Oid)), fp);
 
                        /* finally, write the vector of support procedures */
-                       len = relform->relnatts * (am->amsupport * sizeof(RegProcedure));
-                       if (fwrite(&len, 1, sizeof(len), fp) != sizeof(len))
-                               elog(FATAL, "could not write init file");
-
-                       if (fwrite(rel->rd_support, 1, len, fp) != len)
-                               elog(FATAL, "could not write init file");
+                       write_item(rel->rd_support, relform->relnatts *
+                               (am->amsupport * sizeof(RegProcedure)), fp);
                }
 
                /* also make a list of their OIDs, for RelationIdIsInInitFile */
index 4f76eae1468bbbd8d6dbf60d532213bbf45cc486..6afa917f6bd64895d29777a8a97c258fb7a85b71 100644 (file)
@@ -12,7 +12,7 @@
  *     by PostgreSQL
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.438 2006/06/09 19:46:09 tgl Exp $
+ *       $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.439 2006/07/02 02:23:21 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2594,6 +2594,7 @@ getTables(int *numTables)
        int                     i_owning_tab;
        int                     i_owning_col;
        int                     i_reltablespace;
+       int                     i_reloptions;
 
        /* Make sure we are in proper schema */
        selectSourceSchema("pg_catalog");
@@ -2618,7 +2619,36 @@ getTables(int *numTables)
         * we cannot correctly identify inherited columns, serial columns, etc.
         */
 
-       if (g_fout->remoteVersion >= 80000)
+       if (g_fout->remoteVersion >= 80200)
+       {
+               /*
+                * Left join to pick up dependency info linking sequences to their
+                * serial column, if any
+                */
+               appendPQExpBuffer(query,
+                                                 "SELECT c.tableoid, c.oid, relname, "
+                                                 "relacl, relkind, relnamespace, "
+                                                 "(%s relowner) as rolname, "
+                                                 "relchecks, reltriggers, "
+                                                 "relhasindex, relhasrules, relhasoids, "
+                                                 "d.refobjid as owning_tab, "
+                                                 "d.refobjsubid as owning_col, "
+                                                 "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
+                                                 "array_to_string(c.reloptions, ', ') as reloptions "
+                                                 "from pg_class c "
+                                                 "left join pg_depend d on "
+                                                 "(c.relkind = '%c' and "
+                                                 "d.classid = c.tableoid and d.objid = c.oid and "
+                                                 "d.objsubid = 0 and "
+                                                 "d.refclassid = c.tableoid and d.deptype = 'i') "
+                                                 "where relkind in ('%c', '%c', '%c', '%c') "
+                                                 "order by c.oid",
+                                                 username_subquery,
+                                                 RELKIND_SEQUENCE,
+                                                 RELKIND_RELATION, RELKIND_SEQUENCE,
+                                                 RELKIND_VIEW, RELKIND_COMPOSITE_TYPE);
+       }
+       else if (g_fout->remoteVersion >= 80000)
        {
                /*
                 * Left join to pick up dependency info linking sequences to their
@@ -2632,7 +2662,8 @@ getTables(int *numTables)
                                                  "relhasindex, relhasrules, relhasoids, "
                                                  "d.refobjid as owning_tab, "
                                                  "d.refobjsubid as owning_col, "
-                                                 "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace "
+                                                 "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
+                                                 "NULL as reloptions "
                                                  "from pg_class c "
                                                  "left join pg_depend d on "
                                                  "(c.relkind = '%c' and "
@@ -2660,7 +2691,8 @@ getTables(int *numTables)
                                                  "relhasindex, relhasrules, relhasoids, "
                                                  "d.refobjid as owning_tab, "
                                                  "d.refobjsubid as owning_col, "
-                                                 "NULL as reltablespace "
+                                                 "NULL as reltablespace, "
+                                                 "NULL as reloptions "
                                                  "from pg_class c "
                                                  "left join pg_depend d on "
                                                  "(c.relkind = '%c' and "
@@ -2684,7 +2716,8 @@ getTables(int *numTables)
                                                  "relhasindex, relhasrules, relhasoids, "
                                                  "NULL::oid as owning_tab, "
                                                  "NULL::int4 as owning_col, "
-                                                 "NULL as reltablespace "
+                                                 "NULL as reltablespace, "
+                                                 "NULL as reloptions "
                                                  "from pg_class "
                                                  "where relkind in ('%c', '%c', '%c') "
                                                  "order by oid",
@@ -2703,7 +2736,8 @@ getTables(int *numTables)
                                                  "'t'::bool as relhasoids, "
                                                  "NULL::oid as owning_tab, "
                                                  "NULL::int4 as owning_col, "
-                                                 "NULL as reltablespace "
+                                                 "NULL as reltablespace, "
+                                                 "NULL as reloptions "
                                                  "from pg_class "
                                                  "where relkind in ('%c', '%c', '%c') "
                                                  "order by oid",
@@ -2732,7 +2766,8 @@ getTables(int *numTables)
                                                  "'t'::bool as relhasoids, "
                                                  "NULL::oid as owning_tab, "
                                                  "NULL::int4 as owning_col, "
-                                                 "NULL as reltablespace "
+                                                 "NULL as reltablespace, "
+                                                 "NULL as reloptions "
                                                  "from pg_class c "
                                                  "where relkind in ('%c', '%c') "
                                                  "order by oid",
@@ -2774,6 +2809,7 @@ getTables(int *numTables)
        i_owning_tab = PQfnumber(res, "owning_tab");
        i_owning_col = PQfnumber(res, "owning_col");
        i_reltablespace = PQfnumber(res, "reltablespace");
+       i_reloptions = PQfnumber(res, "reloptions");
 
        for (i = 0; i < ntups; i++)
        {
@@ -2803,6 +2839,7 @@ getTables(int *numTables)
                        tblinfo[i].owning_col = atoi(PQgetvalue(res, i, i_owning_col));
                }
                tblinfo[i].reltablespace = strdup(PQgetvalue(res, i, i_reltablespace));
+               tblinfo[i].reloptions = strdup(PQgetvalue(res, i, i_reloptions));
 
                /* other fields were zeroed above */
 
@@ -2952,7 +2989,8 @@ getIndexes(TableInfo tblinfo[], int numTables)
                                i_conname,
                                i_contableoid,
                                i_conoid,
-                               i_tablespace;
+                               i_tablespace,
+                               i_options;
        int                     ntups;
 
        for (i = 0; i < numTables; i++)
@@ -2981,7 +3019,33 @@ getIndexes(TableInfo tblinfo[], int numTables)
                 * assume an index won't have more than one internal dependency.
                 */
                resetPQExpBuffer(query);
-               if (g_fout->remoteVersion >= 80000)
+               if (g_fout->remoteVersion >= 80200)
+               {
+                       appendPQExpBuffer(query,
+                                                         "SELECT t.tableoid, t.oid, "
+                                                         "t.relname as indexname, "
+                                        "pg_catalog.pg_get_indexdef(i.indexrelid) as indexdef, "
+                                                         "t.relnatts as indnkeys, "
+                                                         "i.indkey, i.indisclustered, "
+                                                         "c.contype, c.conname, "
+                                                         "c.tableoid as contableoid, "
+                                                         "c.oid as conoid, "
+                                                         "(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) as tablespace, "
+                                                         "array_to_string(t.reloptions, ', ') as options "
+                                                         "FROM pg_catalog.pg_index i "
+                                         "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
+                                                         "LEFT JOIN pg_catalog.pg_depend d "
+                                                         "ON (d.classid = t.tableoid "
+                                                         "AND d.objid = t.oid "
+                                                         "AND d.deptype = 'i') "
+                                                         "LEFT JOIN pg_catalog.pg_constraint c "
+                                                         "ON (d.refclassid = c.tableoid "
+                                                         "AND d.refobjid = c.oid) "
+                                                         "WHERE i.indrelid = '%u'::pg_catalog.oid "
+                                                         "ORDER BY indexname",
+                                                         tbinfo->dobj.catId.oid);
+               }
+               else if (g_fout->remoteVersion >= 80000)
                {
                        appendPQExpBuffer(query,
                                                          "SELECT t.tableoid, t.oid, "
@@ -2992,7 +3056,8 @@ getIndexes(TableInfo tblinfo[], int numTables)
                                                          "c.contype, c.conname, "
                                                          "c.tableoid as contableoid, "
                                                          "c.oid as conoid, "
-                                                         "(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) as tablespace "
+                                                         "(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) as tablespace, "
+                                                         "null as options "
                                                          "FROM pg_catalog.pg_index i "
                                          "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
                                                          "LEFT JOIN pg_catalog.pg_depend d "
@@ -3017,7 +3082,8 @@ getIndexes(TableInfo tblinfo[], int numTables)
                                                          "c.contype, c.conname, "
                                                          "c.tableoid as contableoid, "
                                                          "c.oid as conoid, "
-                                                         "NULL as tablespace "
+                                                         "NULL as tablespace, "
+                                                         "null as options "
                                                          "FROM pg_catalog.pg_index i "
                                          "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
                                                          "LEFT JOIN pg_catalog.pg_depend d "
@@ -3044,7 +3110,8 @@ getIndexes(TableInfo tblinfo[], int numTables)
                                                          "t.relname as conname, "
                                                          "0::oid as contableoid, "
                                                          "t.oid as conoid, "
-                                                         "NULL as tablespace "
+                                                         "NULL as tablespace, "
+                                                         "null as options "
                                                          "FROM pg_index i, pg_class t "
                                                          "WHERE t.oid = i.indexrelid "
                                                          "AND i.indrelid = '%u'::oid "
@@ -3066,7 +3133,8 @@ getIndexes(TableInfo tblinfo[], int numTables)
                                                          "t.relname as conname, "
                                                          "0::oid as contableoid, "
                                                          "t.oid as conoid, "
-                                                         "NULL as tablespace "
+                                                         "NULL as tablespace, "
+                                                         "null as options "
                                                          "FROM pg_index i, pg_class t "
                                                          "WHERE t.oid = i.indexrelid "
                                                          "AND i.indrelid = '%u'::oid "
@@ -3091,6 +3159,7 @@ getIndexes(TableInfo tblinfo[], int numTables)
                i_contableoid = PQfnumber(res, "contableoid");
                i_conoid = PQfnumber(res, "conoid");
                i_tablespace = PQfnumber(res, "tablespace");
+               i_options = PQfnumber(res, "options");
 
                indxinfo = (IndxInfo *) malloc(ntups * sizeof(IndxInfo));
                constrinfo = (ConstraintInfo *) malloc(ntups * sizeof(ConstraintInfo));
@@ -3109,6 +3178,7 @@ getIndexes(TableInfo tblinfo[], int numTables)
                        indxinfo[j].indexdef = strdup(PQgetvalue(res, j, i_indexdef));
                        indxinfo[j].indnkeys = atoi(PQgetvalue(res, j, i_indnkeys));
                        indxinfo[j].tablespace = strdup(PQgetvalue(res, j, i_tablespace));
+                       indxinfo[j].options = strdup(PQgetvalue(res, j, i_options));
 
                        /*
                         * In pre-7.4 releases, indkeys may contain more entries than
@@ -7245,6 +7315,9 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                        appendPQExpBuffer(q, ")");
                }
 
+               if (tbinfo->reloptions && strlen(tbinfo->reloptions) > 0)
+                       appendPQExpBuffer(q, "\nWITH (%s)", tbinfo->reloptions);
+
                appendPQExpBuffer(q, ";\n");
 
                /* Loop dumping statistics and storage statements */
@@ -7542,7 +7615,12 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
                                                          fmtId(attname));
                }
 
-               appendPQExpBuffer(q, ");\n");
+               appendPQExpBuffer(q, ")");
+
+               if (indxinfo->options && strlen(indxinfo->options) > 0)
+                       appendPQExpBuffer(q, " WITH (%s)", indxinfo->options);
+
+               appendPQExpBuffer(q, ";\n");
 
                /* If the index is clustered, we need to record that. */
                if (indxinfo->indisclustered)
index 66e7e7798be168acb2a7cec56547865dd3031d9f..33b0fbf05896cb0f69770a318f4271081cafc54a 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.125 2006/03/05 15:58:51 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.126 2006/07/02 02:23:21 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -180,6 +180,7 @@ typedef struct _tableInfo
        char       *relacl;
        char            relkind;
        char       *reltablespace;      /* relation tablespace */
+       char       *reloptions;         /* options specified by WITH (...) */
        bool            hasindex;               /* does it have any indexes? */
        bool            hasrules;               /* does it have any rules? */
        bool            hasoids;                /* does it have OIDs? */
@@ -247,6 +248,7 @@ typedef struct _indxInfo
        TableInfo  *indextable;         /* link to table the index is for */
        char       *indexdef;
        char       *tablespace;         /* tablespace in which index is stored */
+       char       *options;            /* options specified by WITH (...) */
        int                     indnkeys;
        Oid                *indkeys;
        bool            indisclustered;
index c1859a0c6d1ccc0fd6e245c848c3af36af116386..c7ebae99315cddde0f202313fdcfd38e7e2cd324 100644 (file)
@@ -7,13 +7,14 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/genam.h,v 1.60 2006/05/10 23:18:39 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/access/genam.h,v 1.61 2006/07/02 02:23:22 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef GENAM_H
 #define GENAM_H
 
+#include "access/heapam.h"
 #include "access/itup.h"
 #include "access/relscan.h"
 #include "access/sdir.h"
@@ -144,4 +145,13 @@ extern SysScanDesc systable_beginscan(Relation heapRelation,
 extern HeapTuple systable_getnext(SysScanDesc sysscan);
 extern void systable_endscan(SysScanDesc sysscan);
 
+
+typedef HeapOption     IndexOption;
+
+extern bytea *genam_option(ArrayType *options,
+                           int minFillfactor, int defaultFillfactor);
+
+#define IndexGetFillFactor(relation)   HeapGetFillFactor(relation)
+#define IndexGetPageFreeSpace(relation)        HeapGetPageFreeSpace(relation)
+
 #endif   /* GENAM_H */
index 8fff7f42326c3ab0468a95d6e43b177e844d7741..4749eca192a25999b8b98f84e6ae5cf5e80f70c1 100644 (file)
@@ -3,7 +3,7 @@
  *    header file for postgres inverted index access method implementation.
  *
  *  Copyright (c) 2006, PostgreSQL Global Development Group
- *  $PostgreSQL: pgsql/src/include/access/gin.h,v 1.1 2006/05/02 11:28:55 teodor Exp $
+ *  $PostgreSQL: pgsql/src/include/access/gin.h,v 1.2 2006/07/02 02:23:22 momjian Exp $
  *--------------------------------------------------------------------------
  */
 
@@ -213,6 +213,7 @@ typedef struct ginxlogDeletePage {
 } ginxlogDeletePage;
 
 /* ginutil.c */
+extern Datum ginoption(PG_FUNCTION_ARGS);
 extern void initGinState( GinState *state, Relation index );
 extern Buffer GinNewBuffer(Relation index);
 extern void GinInitBuffer(Buffer b, uint32 f);
index 7a55a31216838b80031bd2449b8b566f3358a80e..5be99712b00171c595b610fc71350c671030524f 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/gist_private.h,v 1.18 2006/06/28 12:00:14 teodor Exp $
+ * $PostgreSQL: pgsql/src/include/access/gist_private.h,v 1.19 2006/07/02 02:23:22 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -202,6 +202,7 @@ typedef struct
        Relation        r;
        IndexTuple *itup;                       /* in/out, points to compressed entry */
        int                     ituplen;                /* length of itup */
+       Size            freespace;              /* free space to be left */
        GISTInsertStack *stack;
        bool            needInsertComplete;
 
@@ -271,8 +272,9 @@ extern Datum gistgetmulti(PG_FUNCTION_ARGS);
 #define GiSTPageSize   \
     ( BLCKSZ - SizeOfPageHeaderData - MAXALIGN(sizeof(GISTPageOpaqueData)) ) 
 
+extern Datum gistoption(PG_FUNCTION_ARGS);
 extern bool gistfitpage(IndexTuple *itvec, int len);
-extern bool gistnospace(Page page, IndexTuple *itvec, int len, OffsetNumber todelete);
+extern bool gistnospace(Page page, IndexTuple *itvec, int len, OffsetNumber todelete, Size freespace);
 extern void gistcheckpage(Relation rel, Buffer buf);
 extern Buffer gistNewBuffer(Relation r);
 extern OffsetNumber gistfillbuffer(Relation r, Page page, IndexTuple *itup,
index 226b164ac8584ede3af9eb051db315896e7a25ea..59cf5c9961a1a57f4d8043b69d55848b71609e88 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/hash.h,v 1.69 2006/05/02 22:25:10 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/access/hash.h,v 1.70 2006/07/02 02:23:22 momjian Exp $
  *
  * NOTES
  *             modeled after Margo Seltzer's hash implementation for unix.
@@ -234,6 +234,7 @@ extern Datum hashmarkpos(PG_FUNCTION_ARGS);
 extern Datum hashrestrpos(PG_FUNCTION_ARGS);
 extern Datum hashbulkdelete(PG_FUNCTION_ARGS);
 extern Datum hashvacuumcleanup(PG_FUNCTION_ARGS);
+extern Datum hashoption(PG_FUNCTION_ARGS);
 
 /*
  * Datatype-specific hash functions in hashfunc.c.
index 7301be4ae348797cbcc89f4c323c8c7f2383beae..085501be7d2ad9228041b8b51c47fe8f3ab542f4 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/heapam.h,v 1.112 2006/06/27 02:51:39 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/access/heapam.h,v 1.113 2006/07/02 02:23:22 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -22,6 +22,7 @@
 #include "nodes/primnodes.h"
 #include "storage/block.h"
 #include "storage/lmgr.h"
+#include "utils/array.h"
 #include "utils/rel.h"
 #include "utils/tqual.h"
 
@@ -227,4 +228,32 @@ extern MinimalTuple minimal_tuple_from_heap_tuple(HeapTuple htup);
 extern HeapTuple heap_addheader(int natts, bool withoid,
                           Size structlen, void *structure);
 
+extern HeapTuple build_class_tuple(Form_pg_class pgclass, ArrayType *options);
+
+/*
+ * HeapOption
+ *     Internal data of heaps.
+ */
+typedef struct HeapOption
+{
+       int32   vl_len;
+       int             fillfactor;
+} HeapOption;
+
+extern bytea *heap_option(char relkind, ArrayType *options);
+
+/*
+ * HeapGetFillFactor
+ *             Returns the heap's fillfactor.
+ */
+#define HeapGetFillFactor(relation) \
+       (((HeapOption*)(relation)->rd_options)->fillfactor)
+
+/*
+ * HeapGetPageFreeSpace
+ *             Returns the heap's freespace per page in bytes.
+ */
+#define HeapGetPageFreeSpace(relation) \
+       (BLCKSZ * (100 - HeapGetFillFactor(relation)) / 100)
+
 #endif   /* HEAPAM_H */
index a18d6934d5848d534fc9e4a2f0ee35f1d0638883..ab03fd4a643336f98eeb0848253a59ca15e4b080 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/hio.h,v 1.30 2006/03/05 15:58:53 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/access/hio.h,v 1.31 2006/07/02 02:23:22 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -19,6 +19,6 @@
 extern void RelationPutHeapTuple(Relation relation, Buffer buffer,
                                         HeapTuple tuple);
 extern Buffer RelationGetBufferForTuple(Relation relation, Size len,
-                                                 Buffer otherBuffer, bool use_fsm);
+                                       Buffer otherBuffer, bool use_fsm);
 
 #endif   /* HIO_H */
index a58048ace97302fc66b4a1f41dee1325e9ea28c9..e5981d092c0f70a53955ce6fb6f72368bd3a9c7c 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.98 2006/05/08 00:00:10 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.99 2006/07/02 02:23:22 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -453,6 +453,7 @@ extern Datum btmarkpos(PG_FUNCTION_ARGS);
 extern Datum btrestrpos(PG_FUNCTION_ARGS);
 extern Datum btbulkdelete(PG_FUNCTION_ARGS);
 extern Datum btvacuumcleanup(PG_FUNCTION_ARGS);
+extern Datum btoption(PG_FUNCTION_ARGS);
 
 /*
  * prototypes for functions in nbtinsert.c
index 06f0a125bfdfc0f3b5f3b52d405ad52ddb1f1bab..10e71559bc1e0ad18bf66b7c45af85548b5c51ed 100644 (file)
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.334 2006/05/24 11:01:39 teodor Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.335 2006/07/02 02:23:22 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     200605241
+#define CATALOG_VERSION_NO     200607011
 
 #endif
index 9edcdb21fbc87f97bc130941c80996b3fa7c6119..23604ec2ee1b883accd2d2b62adb8e9c513e0781 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/heap.h,v 1.82 2006/06/27 18:35:05 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/heap.h,v 1.83 2006/07/02 02:23:22 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -17,6 +17,7 @@
 #include "catalog/pg_attribute.h"
 #include "nodes/parsenodes.h"
 #include "parser/parse_node.h"
+#include "utils/array.h"
 #include "utils/rel.h"
 
 
@@ -54,7 +55,8 @@ extern Oid heap_create_with_catalog(const char *relname,
                                                 bool oidislocal,
                                                 int oidinhcount,
                                                 OnCommitAction oncommit,
-                                                bool allow_system_table_mods);
+                                                bool allow_system_table_mods,
+                                                ArrayType *options);
 
 extern void heap_drop_with_catalog(Oid relid);
 
index 6819426d49eff200e7e38f164a1c7e07b2b0f3d3..f4b1bc983046b9f7188a5f9617514307e7506869 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/index.h,v 1.66 2006/05/10 23:18:39 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/index.h,v 1.67 2006/07/02 02:23:22 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -17,6 +17,7 @@
 #include "access/itup.h"
 #include "catalog/pg_index.h"
 #include "nodes/execnodes.h"
+#include "utils/array.h"
 
 
 #define DEFAULT_INDEX_TYPE     "btree"
@@ -37,6 +38,7 @@ extern Oid index_create(Oid heapRelationId,
                         Oid accessMethodObjectId,
                         Oid tableSpaceId,
                         Oid *classObjectId,
+                        List *options,
                         bool isprimary,
                         bool istoast,
                         bool isconstraint,
@@ -70,4 +72,6 @@ extern double IndexBuildHeapScan(Relation heapRelation,
 extern void reindex_index(Oid indexId);
 extern bool reindex_relation(Oid relid, bool toast_too);
 
+extern bytea *index_option(RegProcedure amoption, ArrayType *options);
+
 #endif   /* INDEX_H */
index 141b42e02d71dd18d95d2fe8dc0b06fbb2733f56..5e0d1cf4b6e7156e73d0577eb2728f67490b483f 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_am.h,v 1.43 2006/05/24 11:01:39 teodor Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_am.h,v 1.44 2006/07/02 02:23:22 momjian Exp $
  *
  * NOTES
  *             the genbki.sh script reads this file and generates .bki
@@ -65,6 +65,7 @@ CATALOG(pg_am,2601)
        regproc         ambulkdelete;   /* bulk-delete function */
        regproc         amvacuumcleanup;        /* post-VACUUM cleanup function */
        regproc         amcostestimate; /* estimate cost of an indexscan */
+       regproc         amoption;               /* parse AM-specific parameters */
 } FormData_pg_am;
 
 /* ----------------
@@ -78,7 +79,7 @@ typedef FormData_pg_am *Form_pg_am;
  *             compiler constants for pg_am
  * ----------------
  */
-#define Natts_pg_am                                            23
+#define Natts_pg_am                                            24
 #define Anum_pg_am_amname                              1
 #define Anum_pg_am_amstrategies                        2
 #define Anum_pg_am_amsupport                   3
@@ -102,22 +103,23 @@ typedef FormData_pg_am *Form_pg_am;
 #define Anum_pg_am_ambulkdelete                        21
 #define Anum_pg_am_amvacuumcleanup             22
 #define Anum_pg_am_amcostestimate              23
+#define Anum_pg_am_amoption                            24
 
 /* ----------------
  *             initial contents of pg_am
  * ----------------
  */
 
-DATA(insert OID = 403 (  btree 5 1 1 t t t t f t t btinsert btbeginscan btgettuple btgetmulti btrescan btendscan btmarkpos btrestrpos btbuild btbulkdelete btvacuumcleanup btcostestimate ));
+DATA(insert OID = 403 (  btree 5 1 1 t t t t f t t btinsert btbeginscan btgettuple btgetmulti btrescan btendscan btmarkpos btrestrpos btbuild btbulkdelete btvacuumcleanup btcostestimate btoption ));
 DESCR("b-tree index access method");
 #define BTREE_AM_OID 403
-DATA(insert OID = 405 (  hash  1 1 0 f f f f f t f hashinsert hashbeginscan hashgettuple hashgetmulti hashrescan hashendscan hashmarkpos hashrestrpos hashbuild hashbulkdelete hashvacuumcleanup hashcostestimate ));
+DATA(insert OID = 405 (  hash  1 1 0 f f f f f t f hashinsert hashbeginscan hashgettuple hashgetmulti hashrescan hashendscan hashmarkpos hashrestrpos hashbuild hashbulkdelete hashvacuumcleanup hashcostestimate hashoption ));
 DESCR("hash index access method");
 #define HASH_AM_OID 405
-DATA(insert OID = 783 (  gist  100 7 0 f t t t t t t gistinsert gistbeginscan gistgettuple gistgetmulti gistrescan gistendscan gistmarkpos gistrestrpos gistbuild gistbulkdelete gistvacuumcleanup gistcostestimate ));
+DATA(insert OID = 783 (  gist  100 7 0 f t t t t t t gistinsert gistbeginscan gistgettuple gistgetmulti gistrescan gistendscan gistmarkpos gistrestrpos gistbuild gistbulkdelete gistvacuumcleanup gistcostestimate gistoption ));
 DESCR("GiST index access method");
 #define GIST_AM_OID 783
-DATA(insert OID = 2742 (  gin  100 4 0 f f f f t t f gininsert ginbeginscan gingettuple gingetmulti ginrescan ginendscan ginmarkpos ginrestrpos ginbuild ginbulkdelete ginvacuumcleanup gincostestimate ));
+DATA(insert OID = 2742 (  gin  100 4 0 f f f f t t f gininsert ginbeginscan gingettuple gingetmulti ginrescan ginendscan ginmarkpos ginrestrpos ginbuild ginbulkdelete ginvacuumcleanup gincostestimate ginoption ));
 DESCR("GIN index access method");
 #define GIN_AM_OID 2742
 
index 327e9544d7c181609bcdeed552cc555890d878b4..c0be03ac4d30b2f6c66d123fba2ff3566e83075c 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_attribute.h,v 1.120 2006/03/05 15:58:54 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_attribute.h,v 1.121 2006/07/02 02:23:22 momjian Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
@@ -404,7 +404,8 @@ DATA(insert ( 1249 tableoid                 26 0  4  -7 0 -1 -1 t p i t f f t 0));
 { 1259, {"relhaspkey"},    16, -1,     1, 22, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
 { 1259, {"relhasrules"},   16, -1,     1, 23, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
 { 1259, {"relhassubclass"},16, -1,     1, 24, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
-{ 1259, {"relacl"},             1034, -1, -1, 25, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }
+{ 1259, {"reloptions"},  1009, -1, -1, 25, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
+{ 1259, {"relacl"},             1034, -1, -1, 26, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }
 
 DATA(insert ( 1259 relname                     19 -1 NAMEDATALEN       1 0 -1 -1 f p i t f f t 0));
 DATA(insert ( 1259 relnamespace                26 -1 4   2 0 -1 -1 t p i t f f t 0));
@@ -430,7 +431,8 @@ DATA(insert ( 1259 relhasoids               16 -1 1  21 0 -1 -1 t p c t f f t 0));
 DATA(insert ( 1259 relhaspkey          16 -1 1  22 0 -1 -1 t p c t f f t 0));
 DATA(insert ( 1259 relhasrules         16 -1 1  23 0 -1 -1 t p c t f f t 0));
 DATA(insert ( 1259 relhassubclass      16 -1 1  24 0 -1 -1 t p c t f f t 0));
-DATA(insert ( 1259 relacl                1034 -1 -1 25 1 -1 -1 f x i f f f t 0));
+DATA(insert ( 1259 reloptions    1009 -1 -1 25 1 -1 -1 f x i f f f t 0));
+DATA(insert ( 1259 relacl                1034 -1 -1 26 1 -1 -1 f x i f f f t 0));
 DATA(insert ( 1259 ctid                                27 0  6  -1 0 -1 -1 f p s t f f t 0));
 DATA(insert ( 1259 oid                         26 0  4  -2 0 -1 -1 t p i t f f t 0));
 DATA(insert ( 1259 xmin                                28 0  4  -3 0 -1 -1 t p i t f f t 0));
index a059ae9ddc39ad594b31eaa9a2e1f5ae7a5e3e28..32b3406aa87cfbb0498d8a230926d7ebc9660537 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_class.h,v 1.92 2006/05/28 02:27:08 alvherre Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_class.h,v 1.93 2006/07/02 02:23:22 momjian Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
@@ -75,9 +75,8 @@ CATALOG(pg_class,1259) BKI_BOOTSTRAP
        bool            relhasrules;    /* has associated rules */
        bool            relhassubclass; /* has derived classes */
 
-       /*
-        * relacl may or may not be present, see note above!
-        */
+       /* following fields may or may not be present, see note above! */
+       text            reloptions[1];  /* access method specific data */
        aclitem         relacl[1];              /* we declare this just for the catalog */
 } FormData_pg_class;
 
@@ -104,7 +103,7 @@ typedef FormData_pg_class *Form_pg_class;
  * ----------------
  */
 #define Natts_pg_class_fixed                   24
-#define Natts_pg_class                                 25
+#define Natts_pg_class                                 26
 #define Anum_pg_class_relname                  1
 #define Anum_pg_class_relnamespace             2
 #define Anum_pg_class_reltype                  3
@@ -129,7 +128,8 @@ typedef FormData_pg_class *Form_pg_class;
 #define Anum_pg_class_relhaspkey               22
 #define Anum_pg_class_relhasrules              23
 #define Anum_pg_class_relhassubclass   24
-#define Anum_pg_class_relacl                   25
+#define Anum_pg_class_reloptions               25
+#define Anum_pg_class_relacl                   26
 
 /* ----------------
  *             initial contents of pg_class
@@ -139,13 +139,13 @@ typedef FormData_pg_class *Form_pg_class;
  * ----------------
  */
 
-DATA(insert OID = 1247 (  pg_type              PGNSP 71 PGUID 0 1247 0 0 0 0 0 f f r 23 0 0 0 0 0 t f f f _null_ ));
+DATA(insert OID = 1247 (  pg_type              PGNSP 71 PGUID 0 1247 0 0 0 0 0 f f r 23 0 0 0 0 0 t f f f _null_ _null_ ));
 DESCR("");
-DATA(insert OID = 1249 (  pg_attribute PGNSP 75 PGUID 0 1249 0 0 0 0 0 f f r 17 0 0 0 0 0 f f f f _null_ ));
+DATA(insert OID = 1249 (  pg_attribute PGNSP 75 PGUID 0 1249 0 0 0 0 0 f f r 17 0 0 0 0 0 f f f f _null_ _null_ ));
 DESCR("");
-DATA(insert OID = 1255 (  pg_proc              PGNSP 81 PGUID 0 1255 0 0 0 0 0 f f r 18 0 0 0 0 0 t f f f _null_ ));
+DATA(insert OID = 1255 (  pg_proc              PGNSP 81 PGUID 0 1255 0 0 0 0 0 f f r 18 0 0 0 0 0 t f f f _null_ _null_ ));
 DESCR("");
-DATA(insert OID = 1259 (  pg_class             PGNSP 83 PGUID 0 1259 0 0 0 0 0 f f r 25 0 0 0 0 0 t f f f _null_ ));
+DATA(insert OID = 1259 (  pg_class             PGNSP 83 PGUID 0 1259 0 0 0 0 0 f f r 26 0 0 0 0 0 t f f f _null_ _null_ ));
 DESCR("");
 
 #define                  RELKIND_INDEX                   'i'           /* secondary index */
index e0aa6ec3f33679705b027f6bbb74733ae2cbffca..aba5eee5fef40f758ae4c13c597af5a2157f4622 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.413 2006/06/06 17:59:57 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.414 2006/07/02 02:23:22 momjian Exp $
  *
  * NOTES
  *       The script catalog/genbki.sh reads this file and generates .bki
@@ -680,6 +680,8 @@ DATA(insert OID = 972 (  btvacuumcleanup   PGNSP PGUID 12 f f t f v 2 2281 "2281
 DESCR("btree(internal)");
 DATA(insert OID = 1268 (  btcostestimate   PGNSP PGUID 12 f f t f v 8 2278 "2281 2281 2281 2281 2281 2281 2281 2281" _null_ _null_ _null_  btcostestimate - _null_ ));
 DESCR("btree(internal)");
+DATA(insert OID = 2785 (  btoption                PGNSP PGUID 12 f f t f v 1 2281 "2281" _null_ _null_ _null_  btoption - _null_ ));
+DESCR("btree(internal)");
 
 DATA(insert OID = 339 (  poly_same                PGNSP PGUID 12 f f t f i 2 16 "604 604" _null_ _null_ _null_ poly_same - _null_ ));
 DESCR("same as?");
@@ -797,6 +799,8 @@ DATA(insert OID = 425 (  hashvacuumcleanup PGNSP PGUID 12 f f t f v 2 2281 "2281
 DESCR("hash(internal)");
 DATA(insert OID = 438 (  hashcostestimate  PGNSP PGUID 12 f f t f v 8 2278 "2281 2281 2281 2281 2281 2281 2281 2281" _null_ _null_ _null_  hashcostestimate - _null_ ));
 DESCR("hash(internal)");
+DATA(insert OID = 2786 (  hashoption      PGNSP PGUID 12 f f t f v 1 2281 "2281" _null_ _null_ _null_  hashoption - _null_ ));
+DESCR("hash(internal)");
 
 DATA(insert OID = 449 (  hashint2                 PGNSP PGUID 12 f f t f i 1 23 "21" _null_ _null_ _null_      hashint2 - _null_ ));
 DESCR("hash");
@@ -1063,6 +1067,8 @@ DATA(insert OID = 2561 (  gistvacuumcleanup   PGNSP PGUID 12 f f t f v 2 2281 "2
 DESCR("gist(internal)");
 DATA(insert OID = 772 (  gistcostestimate  PGNSP PGUID 12 f f t f v 8 2278 "2281 2281 2281 2281 2281 2281 2281 2281" _null_ _null_ _null_  gistcostestimate - _null_ ));
 DESCR("gist(internal)");
+DATA(insert OID = 2787 (  gistoption      PGNSP PGUID 12 f f t f v 1 2281 "2281" _null_ _null_ _null_  gistoption - _null_ ));
+DESCR("gist(internal)");
 
 DATA(insert OID = 784 (  tintervaleq      PGNSP PGUID 12 f f t f i 2 16 "704 704" _null_ _null_ _null_ tintervaleq - _null_ ));
 DESCR("equal");
@@ -3849,6 +3855,8 @@ DATA(insert OID = 2740 (  ginvacuumcleanup PGNSP PGUID 12 f f t f v 2 2281 "2281
 DESCR("gin(internal)");
 DATA(insert OID = 2741 (  gincostestimate  PGNSP PGUID 12 f f t f v 8 2278 "2281 2281 2281 2281 2281 2281 2281 2281" _null_ _null_ _null_  gincostestimate - _null_ ));
 DESCR("gin(internal)");
+DATA(insert OID = 2788 (  ginoption               PGNSP PGUID 12 f f t f v 1 2281 "2281" _null_ _null_ _null_  ginoption - _null_ ));
+DESCR("gin(internal)");
 
 /* GIN array support */
 DATA(insert OID = 2743 (  ginarrayextract    PGNSP PGUID 12 f f t f i 2 2281 "2277 2281" _null_ _null_ _null_  ginarrayextract - _null_ ));
index f6ed06f3dbf292dec1b9b0617b28e98657cf9a08..e0678db4cf1fa3b62ac8f8cb8a99de9d18efb57b 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/commands/defrem.h,v 1.72 2006/04/15 17:45:41 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/commands/defrem.h,v 1.73 2006/07/02 02:23:23 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -26,6 +26,7 @@ extern void DefineIndex(RangeVar *heapRelation,
                        List *attributeList,
                        Expr *predicate,
                        List *rangetable,
+                       List *options,
                        bool unique,
                        bool primary,
                        bool isconstraint,
@@ -95,4 +96,6 @@ extern List *defGetQualifiedName(DefElem *def);
 extern TypeName *defGetTypeName(DefElem *def);
 extern int     defGetTypeLength(DefElem *def);
 
+extern DefElem *defWithOids(bool value);
+
 #endif   /* DEFREM_H */
index f9c1524bc986e4296cead00bcf50764665f839e8..6cda429d3e648f0e09e729a74d20aea1244484dd 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.313 2006/07/02 01:58:36 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.314 2006/07/02 02:23:23 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -93,6 +93,7 @@ typedef struct Query
 
        RangeVar   *into;                       /* target relation for SELECT INTO */
        bool            intoHasOids;    /* should target relation contain OIDs? */
+       List       *intoOptions;                /* options passed by WITH */
        OnCommitAction  intoOnCommit;           /* what do we do at COMMIT? */
        char       *intoTableSpaceName; /* table space to use, or NULL */
 
@@ -693,15 +694,6 @@ typedef enum SetOperation
        SETOP_EXCEPT
 } SetOperation;
 
-typedef enum ContainsOids
-{
-       MUST_HAVE_OIDS,                         /* WITH OIDS explicitly specified */
-       MUST_NOT_HAVE_OIDS,                     /* WITHOUT OIDS explicitly specified */
-       DEFAULT_OIDS                            /* neither specified; use the default, which
-                                                                * is the value of the default_with_oids GUC
-                                                                * var */
-} ContainsOids;
-
 typedef struct SelectStmt
 {
        NodeTag         type;
@@ -709,14 +701,14 @@ typedef struct SelectStmt
        /*
         * These fields are used only in "leaf" SelectStmts.
         *
-        * into, intoColNames, intoHasOids, intoOnCommit, and
+        * into, intoColNames, intoOptions, intoOnCommit, and
         * intoTableSpaceName are a kluge; they belong somewhere else...
         */
        List       *distinctClause; /* NULL, list of DISTINCT ON exprs, or
                                                                 * lcons(NIL,NIL) for all (SELECT DISTINCT) */
        RangeVar   *into;                       /* target table (for select into table) */
        List       *intoColNames;       /* column names for into table */
-       ContainsOids intoHasOids;       /* should target table have OIDs? */
+       List       *intoOptions;        /* options passed by WITH */
        OnCommitAction  intoOnCommit;           /* what do we do at COMMIT? */
        char       *intoTableSpaceName;         /* table space to use, or NULL */
        List       *targetList;         /* the target list (of ResTarget) */
@@ -869,6 +861,7 @@ typedef enum AlterTableType
        AT_DropCluster,                         /* SET WITHOUT CLUSTER */
        AT_DropOids,                            /* SET WITHOUT OIDS */
        AT_SetTableSpace,                       /* SET TABLESPACE */
+       AT_SetOptions,                          /* SET (...) -- AM specific parameters */
        AT_EnableTrig,                          /* ENABLE TRIGGER name */
        AT_DisableTrig,                         /* DISABLE TRIGGER name */
        AT_EnableTrigAll,                       /* ENABLE TRIGGER ALL */
@@ -1024,7 +1017,7 @@ typedef struct CreateStmt
        List       *inhRelations;       /* relations to inherit from (list of
                                                                 * inhRelation) */
        List       *constraints;        /* constraints (list of Constraint nodes) */
-       ContainsOids hasoids;           /* should it have OIDs? */
+       List       *options;                    /* options passed by WITH */
        OnCommitAction oncommit;        /* what do we do at COMMIT? */
        char       *tablespacename; /* table space to use, or NULL */
 } CreateStmt;
@@ -1082,6 +1075,7 @@ typedef struct Constraint
        Node       *raw_expr;           /* expr, as untransformed parse tree */
        char       *cooked_expr;        /* expr, as nodeToString representation */
        List       *keys;                       /* String nodes naming referenced column(s) */
+       List       *options;                    /* options passed by WITH */
        char       *indexspace;         /* index tablespace for PKEY/UNIQUE
                                                                 * constraints; NULL for default */
 } Constraint;
@@ -1435,6 +1429,7 @@ typedef struct IndexStmt
        char       *accessMethod;       /* name of access method (eg. btree) */
        char       *tableSpace;         /* tablespace, or NULL to use parent's */
        List       *indexParams;        /* a list of IndexElem */
+       List       *options;                    /* options passed by WITH */
        Node       *whereClause;        /* qualification (partial-index predicate) */
        List       *rangetable;         /* range table for qual and/or expressions,
                                                                 * filled in by transformStmt() */
@@ -1891,8 +1886,8 @@ typedef struct ExecuteStmt
        NodeTag                 type;
        char               *name;                               /* The name of the plan to execute */
        RangeVar           *into;                               /* Optional table to store results in */
-       ContainsOids    into_contains_oids;     /* Should it have OIDs? */
        bool                    into_has_oids;          /* Merge GUC info with user input */
+       List               *intoOptions;                        /* options passed by WITH */
        OnCommitAction  into_on_commit;         /* What do we do at COMMIT? */
        char               *into_tbl_space;             /* Tablespace to use, or NULL */
        List               *params;                             /* Values to assign to parameters */
index efe5a8aba6fb11fe618969c2891af464cd0185b1..dc04bcb0bb89b97956eb6bde6021dbf5a693a01f 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/parser/parse_clause.h,v 1.44 2006/03/05 15:58:57 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/parser/parse_clause.h,v 1.45 2006/07/02 02:23:23 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 #define PARSE_CLAUSE_H
 
 #include "parser/parse_node.h"
+#include "utils/array.h"
 
 extern void transformFromClause(ParseState *pstate, List *frmList);
 extern int setTargetTable(ParseState *pstate, RangeVar *relation,
                           bool inh, bool alsoSource, AclMode requiredPerms);
 extern bool interpretInhOption(InhOption inhOpt);
-extern bool interpretOidsOption(ContainsOids opt);
+extern bool interpretOidsOption(List *options);
+
+extern ArrayType *OptionBuild(ArrayType *array, List *list);
+extern void OptionParse(ArrayType *options, Size num, DefElem kwds[],
+                                               bool strict);
 
 extern Node *transformWhereClause(ParseState *pstate, Node *clause,
                                         const char *constructName);
index 015d7ddc9e973b23c39264eb923162769752885c..9d2e4a8bee8bf5151ab8818c367e755b5cc128b8 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/rel.h,v 1.89 2006/04/25 22:46:05 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/utils/rel.h,v 1.90 2006/07/02 02:23:23 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -115,6 +115,7 @@ typedef struct RelationAmInfo
        FmgrInfo        ambulkdelete;
        FmgrInfo        amvacuumcleanup;
        FmgrInfo        amcostestimate;
+       FmgrInfo        amoption;
 } RelationAmInfo;
 
 
@@ -142,8 +143,14 @@ typedef struct RelationData
         * survived into; or zero if the rel was not created in the current top
         * transaction.  This should be relied on only for optimization purposes;
         * it is possible for new-ness to be "forgotten" (eg, after CLUSTER).
+        *
+        * rd_options and rd_amcache are alike, but different in terms of
+        * lifetime. Invalidation of rd_options is at the change of pg_class
+        * and of rd_amcache is at the change of AM's metapages. Also, rd_options
+        * is serialized in the relcache init file, but rd_amcache is not.
         */
        Form_pg_class rd_rel;           /* RELATION tuple */
+       bytea      *rd_options;         /* parsed rd_rel->reloptions */
        TupleDesc       rd_att;                 /* tuple descriptor */
        Oid                     rd_id;                  /* relation's object id */
        List       *rd_indexlist;       /* list of OIDs of indexes on relation */