Disallow setting fillfactor for TOAST tables.
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Sat, 4 Apr 2009 00:45:02 +0000 (00:45 +0000)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
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 3d78ef27d5c7f68d4ef3a34c8a3b00e8e94cdeaa..ae14e1193bcafbeb2b832e427f37287729aa7021 100644 (file)
@@ -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 efcd769768877874a9520f824ad95ef140e6d699..4eb7cf43ffa38d4ddcab044b89270832ce0c8125 100644 (file)
@@ -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,