Disallow setting fillfactor for TOAST tables.
authorAlvaro Herrera
Sat, 4 Apr 2009 00:45:02 +0000 (00:45 +0000)
committerAlvaro Herrera
Sat, 4 Apr 2009 00:45:02 +0000 (00:45 +0000)
To implement this without almost duplicating the reloption table, treat
relopt_kind as a bitmask instead of an integer value.  This decreases the
range of allowed values, but it's not clear that there's need for that much
values anyway.

This patch also makes heap_reloptions explicitly a no-op for relation kinds
other than heap and TOAST tables.

Patch by ITAGAKI Takahiro with minor edits from me.  (In particular I removed
the bit about adding relation kind to an error message, which I intend to
commit separately.)

src/backend/access/common/reloptions.c
src/include/access/reloptions.h

index 880f2db52663a3f094923f4cd722c26079855e82..c8ff85bff546615ea884c5e8968775faec4adbac 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/access/common/reloptions.c,v 1.24 2009/03/24 20:17:09 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/access/common/reloptions.c,v 1.25 2009/04/04 00:45:02 alvherre Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -52,7 +52,7 @@ static relopt_bool boolRelOpts[] =
        {
            "autovacuum_enabled",
            "Enables autovacuum in this relation",
-           RELOPT_KIND_HEAP
+           RELOPT_KIND_HEAP | RELOPT_KIND_TOAST
        },
        true
    },
@@ -106,7 +106,7 @@ static relopt_int intRelOpts[] =
        {
            "autovacuum_vacuum_threshold",
            "Minimum number of tuple updates or deletes prior to vacuum",
-           RELOPT_KIND_HEAP
+           RELOPT_KIND_HEAP | RELOPT_KIND_TOAST
        },
        50, 0, INT_MAX
    },
@@ -114,7 +114,7 @@ static relopt_int intRelOpts[] =
        {
            "autovacuum_analyze_threshold",
            "Minimum number of tuple inserts, updates or deletes prior to analyze",
-           RELOPT_KIND_HEAP
+           RELOPT_KIND_HEAP | RELOPT_KIND_TOAST
        },
        50, 0, INT_MAX
    },
@@ -122,7 +122,7 @@ static relopt_int intRelOpts[] =
        {
            "autovacuum_vacuum_cost_delay",
            "Vacuum cost delay in milliseconds, for autovacuum",
-           RELOPT_KIND_HEAP
+           RELOPT_KIND_HEAP | RELOPT_KIND_TOAST
        },
        20, 0, 100
    },
@@ -130,7 +130,7 @@ static relopt_int intRelOpts[] =
        {
            "autovacuum_vacuum_cost_limit",
            "Vacuum cost amount available before napping, for autovacuum",
-           RELOPT_KIND_HEAP
+           RELOPT_KIND_HEAP | RELOPT_KIND_TOAST
        },
        200, 1, 10000
    },
@@ -138,7 +138,7 @@ static relopt_int intRelOpts[] =
        {
            "autovacuum_freeze_min_age",
            "Minimum age at which VACUUM should freeze a table row, for autovacuum",
-           RELOPT_KIND_HEAP
+           RELOPT_KIND_HEAP | RELOPT_KIND_TOAST
        },
        100000000, 0, 1000000000
    },
@@ -146,7 +146,7 @@ static relopt_int intRelOpts[] =
        {
            "autovacuum_freeze_max_age",
            "Age at which to autovacuum a table to prevent transaction ID wraparound",
-           RELOPT_KIND_HEAP
+           RELOPT_KIND_HEAP | RELOPT_KIND_TOAST
        },
        200000000, 100000000, 2000000000
    },
@@ -154,7 +154,7 @@ static relopt_int intRelOpts[] =
        {
            "autovacuum_freeze_table_age",
            "Age at which VACUUM should perform a full table sweep to replace old Xid values with FrozenXID",
-           RELOPT_KIND_HEAP
+           RELOPT_KIND_HEAP | RELOPT_KIND_TOAST
        }, 150000000, 0, 2000000000
    },
    /* list terminator */
@@ -167,7 +167,7 @@ static relopt_real realRelOpts[] =
        {
            "autovacuum_vacuum_scale_factor",
            "Number of tuple updates or deletes prior to vacuum as a fraction of reltuples",
-           RELOPT_KIND_HEAP
+           RELOPT_KIND_HEAP | RELOPT_KIND_TOAST
        },
        0.2, 0.0, 100.0
    },
@@ -175,7 +175,7 @@ static relopt_real realRelOpts[] =
        {
            "autovacuum_analyze_scale_factor",
            "Number of tuple inserts, updates or deletes prior to analyze as a fraction of reltuples",
-           RELOPT_KIND_HEAP
+           RELOPT_KIND_HEAP | RELOPT_KIND_TOAST
        },
        0.1, 0.0, 100.0
    },
@@ -190,7 +190,7 @@ static relopt_string stringRelOpts[] =
 };
 
 static relopt_gen **relOpts = NULL;
-static int last_assigned_kind = RELOPT_KIND_LAST_DEFAULT + 1;
+static bits32 last_assigned_kind = RELOPT_KIND_LAST_DEFAULT << 1;
 
 static int     num_custom_options = 0;
 static relopt_gen **custom_options = NULL;
@@ -275,14 +275,20 @@ initialize_reloptions(void)
  *         Create a new relopt_kind value, to be used in custom reloptions by
  *         user-defined AMs.
  */
-int
+relopt_kind
 add_reloption_kind(void)
 {
+   relopt_kind     kind;
+
+   /* don't hand out the last bit so that the wraparound check is portable */
    if (last_assigned_kind >= RELOPT_KIND_MAX)
        ereport(ERROR,
-               (errmsg("user-defined relation parameter types limit exceeded")));
+               (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+                errmsg("user-defined relation parameter types limit exceeded")));
 
-   return last_assigned_kind++;
+   kind = (relopt_kind) last_assigned_kind;
+   last_assigned_kind <<= 1;
+   return kind;
 }
 
 /*
@@ -325,7 +331,7 @@ add_reloption(relopt_gen *newoption)
  *         (for types other than string)
  */
 static relopt_gen *
-allocate_reloption(int kind, int type, char *name, char *desc)
+allocate_reloption(bits32 kinds, int type, char *name, char *desc)
 {
    MemoryContext   oldcxt;
    size_t          size;
@@ -358,7 +364,7 @@ allocate_reloption(int kind, int type, char *name, char *desc)
        newoption->desc = pstrdup(desc);
    else
        newoption->desc = NULL;
-   newoption->kind = kind;
+   newoption->kinds = kinds;
    newoption->namelen = strlen(name);
    newoption->type = type;
 
@@ -372,11 +378,11 @@ allocate_reloption(int kind, int type, char *name, char *desc)
  *         Add a new boolean reloption
  */
 void
-add_bool_reloption(int kind, char *name, char *desc, bool default_val)
+add_bool_reloption(bits32 kinds, char *name, char *desc, bool default_val)
 {
    relopt_bool    *newoption;
 
-   newoption = (relopt_bool *) allocate_reloption(kind, RELOPT_TYPE_BOOL,
+   newoption = (relopt_bool *) allocate_reloption(kinds, RELOPT_TYPE_BOOL,
                                                   name, desc);
    newoption->default_val = default_val;
 
@@ -388,12 +394,12 @@ add_bool_reloption(int kind, char *name, char *desc, bool default_val)
  *         Add a new integer reloption
  */
 void
-add_int_reloption(int kind, char *name, char *desc, int default_val,
+add_int_reloption(bits32 kinds, char *name, char *desc, int default_val,
                  int min_val, int max_val)
 {
    relopt_int     *newoption;
 
-   newoption = (relopt_int *) allocate_reloption(kind, RELOPT_TYPE_INT,
+   newoption = (relopt_int *) allocate_reloption(kinds, RELOPT_TYPE_INT,
                                                  name, desc);
    newoption->default_val = default_val;
    newoption->min = min_val;
@@ -407,12 +413,12 @@ add_int_reloption(int kind, char *name, char *desc, int default_val,
  *         Add a new float reloption
  */
 void
-add_real_reloption(int kind, char *name, char *desc, double default_val,
+add_real_reloption(bits32 kinds, char *name, char *desc, double default_val,
                  double min_val, double max_val)
 {
    relopt_real    *newoption;
 
-   newoption = (relopt_real *) allocate_reloption(kind, RELOPT_TYPE_REAL,
+   newoption = (relopt_real *) allocate_reloption(kinds, RELOPT_TYPE_REAL,
                                                   name, desc);
    newoption->default_val = default_val;
    newoption->min = min_val;
@@ -431,7 +437,7 @@ add_real_reloption(int kind, char *name, char *desc, double default_val,
  * the validation.
  */
 void
-add_string_reloption(int kind, char *name, char *desc, char *default_val,
+add_string_reloption(bits32 kinds, char *name, char *desc, char *default_val,
                     validate_string_relopt validator)
 {
    MemoryContext   oldcxt;
@@ -450,7 +456,7 @@ add_string_reloption(int kind, char *name, char *desc, char *default_val,
        newoption->gen.desc = pstrdup(desc);
    else
        newoption->gen.desc = NULL;
-   newoption->gen.kind = kind;
+   newoption->gen.kinds = kinds;
    newoption->gen.namelen = strlen(name);
    newoption->gen.type = RELOPT_TYPE_STRING;
    newoption->validate_cb = validator;
@@ -784,7 +790,7 @@ parseRelOptions(Datum options, bool validate, relopt_kind kind,
    /* Build a list of expected options, based on kind */
 
    for (i = 0; relOpts[i]; i++)
-       if (relOpts[i]->kind == kind)
+       if (relOpts[i]->kinds & kind)
            numoptions++;
 
    if (numoptions == 0)
@@ -797,7 +803,7 @@ parseRelOptions(Datum options, bool validate, relopt_kind kind,
 
    for (i = 0, j = 0; relOpts[i]; i++)
    {
-       if (relOpts[i]->kind == kind)
+       if (relOpts[i]->kinds & kind)
        {
            reloptions[j].gen = relOpts[i];
            reloptions[j].isset = false;
@@ -1116,7 +1122,16 @@ default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
 bytea *
 heap_reloptions(char relkind, Datum reloptions, bool validate)
 {
-   return default_reloptions(reloptions, validate, RELOPT_KIND_HEAP);
+   switch (relkind)
+   {
+       case RELKIND_TOASTVALUE:
+           return default_reloptions(reloptions, validate, RELOPT_KIND_TOAST);
+       case RELKIND_RELATION:
+           return default_reloptions(reloptions, validate, RELOPT_KIND_HEAP);
+       default:
+           /* sequences, composite types and views are not supported */
+           return NULL;
+   }
 }
 
 
index b40d95a0fba8af50b07d843fafa33146d60e9f21..5ecc9345f1b60995c2f488e55a21c278740422c5 100644 (file)
@@ -11,7 +11,7 @@
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/reloptions.h,v 1.13 2009/03/23 16:36:27 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/access/reloptions.h,v 1.14 2009/04/04 00:45:02 alvherre Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -33,15 +33,15 @@ typedef enum relopt_type
 /* kinds supported by reloptions */
 typedef enum relopt_kind
 {
-   RELOPT_KIND_HEAP,
-   /* XXX do we need a separate kind for TOAST tables? */
-   RELOPT_KIND_BTREE,
-   RELOPT_KIND_HASH,
-   RELOPT_KIND_GIN,
-   RELOPT_KIND_GIST,
+   RELOPT_KIND_HEAP    = (1 << 0),
+   RELOPT_KIND_TOAST   = (1 << 1),
+   RELOPT_KIND_BTREE   = (1 << 2),
+   RELOPT_KIND_HASH    = (1 << 3),
+   RELOPT_KIND_GIN     = (1 << 4),
+   RELOPT_KIND_GIST    = (1 << 5),
    /* if you add a new kind, make sure you update "last_default" too */
    RELOPT_KIND_LAST_DEFAULT = RELOPT_KIND_GIST,
-   RELOPT_KIND_MAX = 255
+   RELOPT_KIND_MAX = (1 << 31)
 } relopt_kind;
 
 /* reloption namespaces allowed for heaps -- currently only TOAST */
@@ -52,7 +52,7 @@ typedef struct relopt_gen
 {
    const char *name;   /* must be first (used as list termination marker) */
    const char *desc;
-   relopt_kind kind;
+   bits32      kinds;
    int         namelen;
    relopt_type type;
 } relopt_gen;
@@ -232,14 +232,14 @@ typedef struct
     (char *)(optstruct) + (optstruct)->member)
 
 
-extern int add_reloption_kind(void);
-extern void add_bool_reloption(int kind, char *name, char *desc,
+extern relopt_kind add_reloption_kind(void);
+extern void add_bool_reloption(bits32 kinds, char *name, char *desc,
                   bool default_val);
-extern void add_int_reloption(int kind, char *name, char *desc,
+extern void add_int_reloption(bits32 kinds, char *name, char *desc,
                  int default_val, int min_val, int max_val);
-extern void add_real_reloption(int kind, char *name, char *desc,
+extern void add_real_reloption(bits32 kinds, char *name, char *desc,
                   double default_val, double min_val, double max_val);
-extern void add_string_reloption(int kind, char *name, char *desc,
+extern void add_string_reloption(bits32 kinds, char *name, char *desc,
                     char *default_val, validate_string_relopt validator);
 
 extern Datum transformRelOptions(Datum oldOptions, List *defList,