Skip to content
Snippets Groups Projects
Commit 1c855f01 authored by Alvaro Herrera's avatar Alvaro Herrera
Browse files

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
No related branches found
No related tags found
No related merge requests found
...@@ -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,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment