Commit 1c855f01 authored by Alvaro Herrera's avatar Alvaro Herrera

Disallow setting fillfactor for TOAST tables.

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