mirror of
https://github.com/postgres/postgres.git
synced 2026-01-26 09:41:40 +03:00
Allow Boolean reloptions to have ternary values
From the user's point of view these are just Boolean values; from the implementation side we can now distinguish an option that hasn't been set. Reimplement the vacuum_truncate reloption using this type. This could also be used for reloptions vacuum_index_cleanup and buffering, but those additionally need a per-option "alias" for the state where the variable is unset (currently the value "auto"). Author: Nikolay Shaplov <dhyan@nataraj.su> Reviewed-by: Timur Magomedov <t.magomedov@postgrespro.ru> Reviewed-by: Nathan Bossart <nathandbossart@gmail.com> Discussion: https://postgr.es/m/3474141.usfYGdeWWP@thinkpad-pgpro
This commit is contained in:
@@ -40,9 +40,9 @@
|
||||
*
|
||||
* To add an option:
|
||||
*
|
||||
* (i) decide on a type (bool, integer, real, enum, string), name, default
|
||||
* value, upper and lower bounds (if applicable); for strings, consider a
|
||||
* validation routine.
|
||||
* (i) decide on a type (bool, ternary, integer, real, enum, string), name,
|
||||
* default value, upper and lower bounds (if applicable); for strings,
|
||||
* consider a validation routine.
|
||||
* (ii) add a record below (or use add_<type>_reloption).
|
||||
* (iii) add it to the appropriate options struct (perhaps StdRdOptions)
|
||||
* (iv) add it to the appropriate handling routine (perhaps
|
||||
@@ -50,6 +50,10 @@
|
||||
* (v) make sure the lock level is set correctly for that operation
|
||||
* (vi) don't forget to document the option
|
||||
*
|
||||
* From the user's point of view, a 'ternary' is exactly like a Boolean,
|
||||
* so we don't document it separately. On the implementation side, the
|
||||
* handling code can detect the case where the option has not been set.
|
||||
*
|
||||
* The default choice for any new option should be AccessExclusiveLock.
|
||||
* In some cases the lock level can be reduced from there, but the lock
|
||||
* level chosen should always conflict with itself to ensure that multiple
|
||||
@@ -147,15 +151,6 @@ static relopt_bool boolRelOpts[] =
|
||||
},
|
||||
false
|
||||
},
|
||||
{
|
||||
{
|
||||
"vacuum_truncate",
|
||||
"Enables vacuum to truncate empty pages at the end of this table",
|
||||
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
|
||||
ShareUpdateExclusiveLock
|
||||
},
|
||||
true
|
||||
},
|
||||
{
|
||||
{
|
||||
"deduplicate_items",
|
||||
@@ -170,6 +165,24 @@ static relopt_bool boolRelOpts[] =
|
||||
{{NULL}}
|
||||
};
|
||||
|
||||
static relopt_ternary ternaryRelOpts[] =
|
||||
{
|
||||
{
|
||||
{
|
||||
"vacuum_truncate",
|
||||
"Enables vacuum to truncate empty pages at the end of this table",
|
||||
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
|
||||
ShareUpdateExclusiveLock
|
||||
}
|
||||
},
|
||||
/* list terminator */
|
||||
{
|
||||
{
|
||||
NULL
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static relopt_int intRelOpts[] =
|
||||
{
|
||||
{
|
||||
@@ -609,6 +622,13 @@ initialize_reloptions(void)
|
||||
boolRelOpts[i].gen.lockmode));
|
||||
j++;
|
||||
}
|
||||
for (i = 0; ternaryRelOpts[i].gen.name; i++)
|
||||
{
|
||||
Assert(DoLockModesConflict(ternaryRelOpts[i].gen.lockmode,
|
||||
ternaryRelOpts[i].gen.lockmode));
|
||||
j++;
|
||||
}
|
||||
|
||||
for (i = 0; intRelOpts[i].gen.name; i++)
|
||||
{
|
||||
Assert(DoLockModesConflict(intRelOpts[i].gen.lockmode,
|
||||
@@ -649,6 +669,14 @@ initialize_reloptions(void)
|
||||
j++;
|
||||
}
|
||||
|
||||
for (i = 0; ternaryRelOpts[i].gen.name; i++)
|
||||
{
|
||||
relOpts[j] = &ternaryRelOpts[i].gen;
|
||||
relOpts[j]->type = RELOPT_TYPE_TERNARY;
|
||||
relOpts[j]->namelen = strlen(relOpts[j]->name);
|
||||
j++;
|
||||
}
|
||||
|
||||
for (i = 0; intRelOpts[i].gen.name; i++)
|
||||
{
|
||||
relOpts[j] = &intRelOpts[i].gen;
|
||||
@@ -809,6 +837,9 @@ allocate_reloption(bits32 kinds, int type, const char *name, const char *desc,
|
||||
case RELOPT_TYPE_BOOL:
|
||||
size = sizeof(relopt_bool);
|
||||
break;
|
||||
case RELOPT_TYPE_TERNARY:
|
||||
size = sizeof(relopt_ternary);
|
||||
break;
|
||||
case RELOPT_TYPE_INT:
|
||||
size = sizeof(relopt_int);
|
||||
break;
|
||||
@@ -892,6 +923,55 @@ add_local_bool_reloption(local_relopts *relopts, const char *name,
|
||||
add_local_reloption(relopts, (relopt_gen *) newoption, offset);
|
||||
}
|
||||
|
||||
/*
|
||||
* init_ternary_reloption
|
||||
* Allocate and initialize a new ternary reloption
|
||||
*/
|
||||
static relopt_ternary *
|
||||
init_ternary_reloption(bits32 kinds, const char *name, const char *desc,
|
||||
LOCKMODE lockmode)
|
||||
{
|
||||
relopt_ternary *newoption;
|
||||
|
||||
newoption = (relopt_ternary *)
|
||||
allocate_reloption(kinds, RELOPT_TYPE_TERNARY, name, desc, lockmode);
|
||||
|
||||
return newoption;
|
||||
}
|
||||
|
||||
/*
|
||||
* add_ternary_reloption
|
||||
* Add a new ternary reloption
|
||||
*/
|
||||
void
|
||||
add_ternary_reloption(bits32 kinds, const char *name, const char *desc,
|
||||
LOCKMODE lockmode)
|
||||
{
|
||||
relopt_ternary *newoption;
|
||||
|
||||
newoption =
|
||||
init_ternary_reloption(kinds, name, desc, lockmode);
|
||||
|
||||
add_reloption((relopt_gen *) newoption);
|
||||
}
|
||||
|
||||
/*
|
||||
* add_local_ternary_reloption
|
||||
* Add a new ternary local reloption
|
||||
*
|
||||
* 'offset' is offset of ternary-typed field.
|
||||
*/
|
||||
void
|
||||
add_local_ternary_reloption(local_relopts *relopts, const char *name,
|
||||
const char *desc, int offset)
|
||||
{
|
||||
relopt_ternary *newoption;
|
||||
|
||||
newoption =
|
||||
init_ternary_reloption(RELOPT_KIND_LOCAL, name, desc, 0);
|
||||
|
||||
add_local_reloption(relopts, (relopt_gen *) newoption, offset);
|
||||
}
|
||||
|
||||
/*
|
||||
* init_real_reloption
|
||||
@@ -1626,6 +1706,20 @@ parse_one_reloption(relopt_value *option, char *text_str, int text_len,
|
||||
option->gen->name, value)));
|
||||
}
|
||||
break;
|
||||
case RELOPT_TYPE_TERNARY:
|
||||
{
|
||||
bool b;
|
||||
|
||||
parsed = parse_bool(value, &b);
|
||||
option->values.ternary_val = b ? PG_TERNARY_TRUE :
|
||||
PG_TERNARY_FALSE;
|
||||
if (validate && !parsed)
|
||||
ereport(ERROR,
|
||||
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("invalid value for boolean option \"%s\": %s",
|
||||
option->gen->name, value));
|
||||
}
|
||||
break;
|
||||
case RELOPT_TYPE_INT:
|
||||
{
|
||||
relopt_int *optint = (relopt_int *) option->gen;
|
||||
@@ -1789,17 +1883,6 @@ fillRelOptions(void *rdopts, Size basesize,
|
||||
char *itempos = ((char *) rdopts) + elems[j].offset;
|
||||
char *string_val;
|
||||
|
||||
/*
|
||||
* If isset_offset is provided, store whether the reloption is
|
||||
* set there.
|
||||
*/
|
||||
if (elems[j].isset_offset > 0)
|
||||
{
|
||||
char *setpos = ((char *) rdopts) + elems[j].isset_offset;
|
||||
|
||||
*(bool *) setpos = options[i].isset;
|
||||
}
|
||||
|
||||
switch (options[i].gen->type)
|
||||
{
|
||||
case RELOPT_TYPE_BOOL:
|
||||
@@ -1807,6 +1890,10 @@ fillRelOptions(void *rdopts, Size basesize,
|
||||
options[i].values.bool_val :
|
||||
((relopt_bool *) options[i].gen)->default_val;
|
||||
break;
|
||||
case RELOPT_TYPE_TERNARY:
|
||||
*(pg_ternary *) itempos = options[i].isset ?
|
||||
options[i].values.ternary_val : PG_TERNARY_UNSET;
|
||||
break;
|
||||
case RELOPT_TYPE_INT:
|
||||
*(int *) itempos = options[i].isset ?
|
||||
options[i].values.int_val :
|
||||
@@ -1923,8 +2010,8 @@ default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
|
||||
offsetof(StdRdOptions, parallel_workers)},
|
||||
{"vacuum_index_cleanup", RELOPT_TYPE_ENUM,
|
||||
offsetof(StdRdOptions, vacuum_index_cleanup)},
|
||||
{"vacuum_truncate", RELOPT_TYPE_BOOL,
|
||||
offsetof(StdRdOptions, vacuum_truncate), offsetof(StdRdOptions, vacuum_truncate_set)},
|
||||
{"vacuum_truncate", RELOPT_TYPE_TERNARY,
|
||||
offsetof(StdRdOptions, vacuum_truncate)},
|
||||
{"vacuum_max_eager_freeze_failure_rate", RELOPT_TYPE_REAL,
|
||||
offsetof(StdRdOptions, vacuum_max_eager_freeze_failure_rate)}
|
||||
};
|
||||
@@ -2004,7 +2091,6 @@ build_local_reloptions(local_relopts *relopts, Datum options, bool validate)
|
||||
elems[i].optname = opt->option->name;
|
||||
elems[i].opttype = opt->option->type;
|
||||
elems[i].offset = opt->offset;
|
||||
elems[i].isset_offset = 0; /* not supported for local relopts yet */
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
@@ -2224,9 +2224,9 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams params,
|
||||
{
|
||||
StdRdOptions *opts = (StdRdOptions *) rel->rd_options;
|
||||
|
||||
if (opts && opts->vacuum_truncate_set)
|
||||
if (opts && opts->vacuum_truncate != PG_TERNARY_UNSET)
|
||||
{
|
||||
if (opts->vacuum_truncate)
|
||||
if (opts->vacuum_truncate == PG_TERNARY_TRUE)
|
||||
params.truncate = VACOPTVALUE_ENABLED;
|
||||
else
|
||||
params.truncate = VACOPTVALUE_DISABLED;
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
typedef enum relopt_type
|
||||
{
|
||||
RELOPT_TYPE_BOOL,
|
||||
RELOPT_TYPE_TERNARY, /* on, off, unset */
|
||||
RELOPT_TYPE_INT,
|
||||
RELOPT_TYPE_REAL,
|
||||
RELOPT_TYPE_ENUM,
|
||||
@@ -80,6 +81,7 @@ typedef struct relopt_value
|
||||
union
|
||||
{
|
||||
bool bool_val;
|
||||
pg_ternary ternary_val;
|
||||
int int_val;
|
||||
double real_val;
|
||||
int enum_val;
|
||||
@@ -94,6 +96,12 @@ typedef struct relopt_bool
|
||||
bool default_val;
|
||||
} relopt_bool;
|
||||
|
||||
typedef struct relopt_ternary
|
||||
{
|
||||
relopt_gen gen;
|
||||
/* ternaries have no default_val: otherwise they'd just be bools */
|
||||
} relopt_ternary;
|
||||
|
||||
typedef struct relopt_int
|
||||
{
|
||||
relopt_gen gen;
|
||||
@@ -152,19 +160,6 @@ typedef struct
|
||||
const char *optname; /* option's name */
|
||||
relopt_type opttype; /* option's datatype */
|
||||
int offset; /* offset of field in result struct */
|
||||
|
||||
/*
|
||||
* isset_offset is an optional offset of a field in the result struct that
|
||||
* stores whether the option is explicitly set for the relation or if it
|
||||
* just picked up the default value. In most cases, this can be
|
||||
* accomplished by giving the reloption a special out-of-range default
|
||||
* value (e.g., some integer reloptions use -2), but this isn't always
|
||||
* possible. For example, a Boolean reloption cannot be given an
|
||||
* out-of-range default, so we need another way to discover the source of
|
||||
* its value. This offset is only used if given a value greater than
|
||||
* zero.
|
||||
*/
|
||||
int isset_offset;
|
||||
} relopt_parse_elt;
|
||||
|
||||
/* Local reloption definition */
|
||||
@@ -195,6 +190,8 @@ typedef struct local_relopts
|
||||
extern relopt_kind add_reloption_kind(void);
|
||||
extern void add_bool_reloption(bits32 kinds, const char *name, const char *desc,
|
||||
bool default_val, LOCKMODE lockmode);
|
||||
extern void add_ternary_reloption(bits32 kinds, const char *name,
|
||||
const char *desc, LOCKMODE lockmode);
|
||||
extern void add_int_reloption(bits32 kinds, const char *name, const char *desc,
|
||||
int default_val, int min_val, int max_val,
|
||||
LOCKMODE lockmode);
|
||||
@@ -214,6 +211,9 @@ extern void register_reloptions_validator(local_relopts *relopts,
|
||||
extern void add_local_bool_reloption(local_relopts *relopts, const char *name,
|
||||
const char *desc, bool default_val,
|
||||
int offset);
|
||||
extern void add_local_ternary_reloption(local_relopts *relopts,
|
||||
const char *name, const char *desc,
|
||||
int offset);
|
||||
extern void add_local_int_reloption(local_relopts *relopts, const char *name,
|
||||
const char *desc, int default_val,
|
||||
int min_val, int max_val, int offset);
|
||||
|
||||
@@ -543,6 +543,20 @@ Float8GetDatum(float8 X)
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* pg_ternary
|
||||
* Boolean value with an extra "unset" value
|
||||
*
|
||||
* This enum can be used for values that want to distinguish between true,
|
||||
* false, and unset.
|
||||
*/
|
||||
typedef enum pg_ternary
|
||||
{
|
||||
PG_TERNARY_FALSE = 0,
|
||||
PG_TERNARY_TRUE = 1,
|
||||
PG_TERNARY_UNSET = -1
|
||||
} pg_ternary;
|
||||
|
||||
/*
|
||||
* NON_EXEC_STATIC: It's sometimes useful to define a variable or function
|
||||
* that is normally static but extern when using EXEC_BACKEND (see
|
||||
|
||||
@@ -347,8 +347,7 @@ typedef struct StdRdOptions
|
||||
bool user_catalog_table; /* use as an additional catalog relation */
|
||||
int parallel_workers; /* max number of parallel workers */
|
||||
StdRdOptIndexCleanup vacuum_index_cleanup; /* controls index vacuuming */
|
||||
bool vacuum_truncate; /* enables vacuum to truncate a relation */
|
||||
bool vacuum_truncate_set; /* whether vacuum_truncate is set */
|
||||
pg_ternary vacuum_truncate; /* enables vacuum to truncate a relation */
|
||||
|
||||
/*
|
||||
* Fraction of pages in a relation that vacuum can eagerly scan and fail
|
||||
|
||||
@@ -5,7 +5,7 @@ Dummy index AM is a module for testing any facility usable by an index
|
||||
access method, whose code is kept a maximum simple.
|
||||
|
||||
This includes tests for all relation option types:
|
||||
- boolean
|
||||
- boolean & ternary
|
||||
- enum
|
||||
- integer
|
||||
- real
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
PG_MODULE_MAGIC;
|
||||
|
||||
/* parse table for fillRelOptions */
|
||||
static relopt_parse_elt di_relopt_tab[6];
|
||||
static relopt_parse_elt di_relopt_tab[8];
|
||||
|
||||
/* Kind of relation options for dummy index */
|
||||
static relopt_kind di_relopt_kind;
|
||||
@@ -40,6 +40,7 @@ typedef struct DummyIndexOptions
|
||||
int option_int;
|
||||
double option_real;
|
||||
bool option_bool;
|
||||
pg_ternary option_ternary_1;
|
||||
DummyAmEnum option_enum;
|
||||
int option_string_val_offset;
|
||||
int option_string_null_offset;
|
||||
@@ -73,28 +74,41 @@ validate_string_option(const char *value)
|
||||
static void
|
||||
create_reloptions_table(void)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
di_relopt_kind = add_reloption_kind();
|
||||
|
||||
add_int_reloption(di_relopt_kind, "option_int",
|
||||
"Integer option for dummy_index_am",
|
||||
10, -10, 100, AccessExclusiveLock);
|
||||
di_relopt_tab[0].optname = "option_int";
|
||||
di_relopt_tab[0].opttype = RELOPT_TYPE_INT;
|
||||
di_relopt_tab[0].offset = offsetof(DummyIndexOptions, option_int);
|
||||
di_relopt_tab[i].optname = "option_int";
|
||||
di_relopt_tab[i].opttype = RELOPT_TYPE_INT;
|
||||
di_relopt_tab[i].offset = offsetof(DummyIndexOptions, option_int);
|
||||
i++;
|
||||
|
||||
add_real_reloption(di_relopt_kind, "option_real",
|
||||
"Real option for dummy_index_am",
|
||||
3.1415, -10, 100, AccessExclusiveLock);
|
||||
di_relopt_tab[1].optname = "option_real";
|
||||
di_relopt_tab[1].opttype = RELOPT_TYPE_REAL;
|
||||
di_relopt_tab[1].offset = offsetof(DummyIndexOptions, option_real);
|
||||
di_relopt_tab[i].optname = "option_real";
|
||||
di_relopt_tab[i].opttype = RELOPT_TYPE_REAL;
|
||||
di_relopt_tab[i].offset = offsetof(DummyIndexOptions, option_real);
|
||||
i++;
|
||||
|
||||
add_bool_reloption(di_relopt_kind, "option_bool",
|
||||
"Boolean option for dummy_index_am",
|
||||
true, AccessExclusiveLock);
|
||||
di_relopt_tab[2].optname = "option_bool";
|
||||
di_relopt_tab[2].opttype = RELOPT_TYPE_BOOL;
|
||||
di_relopt_tab[2].offset = offsetof(DummyIndexOptions, option_bool);
|
||||
di_relopt_tab[i].optname = "option_bool";
|
||||
di_relopt_tab[i].opttype = RELOPT_TYPE_BOOL;
|
||||
di_relopt_tab[i].offset = offsetof(DummyIndexOptions, option_bool);
|
||||
i++;
|
||||
|
||||
add_ternary_reloption(di_relopt_kind, "option_ternary_1",
|
||||
"One ternary option for dummy_index_am",
|
||||
AccessExclusiveLock);
|
||||
di_relopt_tab[i].optname = "option_ternary_1";
|
||||
di_relopt_tab[i].opttype = RELOPT_TYPE_TERNARY;
|
||||
di_relopt_tab[i].offset = offsetof(DummyIndexOptions, option_ternary_1);
|
||||
i++;
|
||||
|
||||
add_enum_reloption(di_relopt_kind, "option_enum",
|
||||
"Enum option for dummy_index_am",
|
||||
@@ -102,18 +116,20 @@ create_reloptions_table(void)
|
||||
DUMMY_AM_ENUM_ONE,
|
||||
"Valid values are \"one\" and \"two\".",
|
||||
AccessExclusiveLock);
|
||||
di_relopt_tab[3].optname = "option_enum";
|
||||
di_relopt_tab[3].opttype = RELOPT_TYPE_ENUM;
|
||||
di_relopt_tab[3].offset = offsetof(DummyIndexOptions, option_enum);
|
||||
di_relopt_tab[i].optname = "option_enum";
|
||||
di_relopt_tab[i].opttype = RELOPT_TYPE_ENUM;
|
||||
di_relopt_tab[i].offset = offsetof(DummyIndexOptions, option_enum);
|
||||
i++;
|
||||
|
||||
add_string_reloption(di_relopt_kind, "option_string_val",
|
||||
"String option for dummy_index_am with non-NULL default",
|
||||
"DefaultValue", &validate_string_option,
|
||||
AccessExclusiveLock);
|
||||
di_relopt_tab[4].optname = "option_string_val";
|
||||
di_relopt_tab[4].opttype = RELOPT_TYPE_STRING;
|
||||
di_relopt_tab[4].offset = offsetof(DummyIndexOptions,
|
||||
di_relopt_tab[i].optname = "option_string_val";
|
||||
di_relopt_tab[i].opttype = RELOPT_TYPE_STRING;
|
||||
di_relopt_tab[i].offset = offsetof(DummyIndexOptions,
|
||||
option_string_val_offset);
|
||||
i++;
|
||||
|
||||
/*
|
||||
* String option for dummy_index_am with NULL default, and without
|
||||
@@ -123,10 +139,11 @@ create_reloptions_table(void)
|
||||
NULL, /* description */
|
||||
NULL, &validate_string_option,
|
||||
AccessExclusiveLock);
|
||||
di_relopt_tab[5].optname = "option_string_null";
|
||||
di_relopt_tab[5].opttype = RELOPT_TYPE_STRING;
|
||||
di_relopt_tab[5].offset = offsetof(DummyIndexOptions,
|
||||
di_relopt_tab[i].optname = "option_string_null";
|
||||
di_relopt_tab[i].opttype = RELOPT_TYPE_STRING;
|
||||
di_relopt_tab[i].offset = offsetof(DummyIndexOptions,
|
||||
option_string_null_offset);
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ SET client_min_messages TO 'notice';
|
||||
CREATE INDEX dummy_test_idx ON dummy_test_tab
|
||||
USING dummy_index_am (i) WITH (
|
||||
option_bool = false,
|
||||
option_ternary_1,
|
||||
option_int = 5,
|
||||
option_real = 3.1,
|
||||
option_enum = 'two',
|
||||
@@ -31,16 +32,18 @@ SELECT unnest(reloptions) FROM pg_class WHERE relname = 'dummy_test_idx';
|
||||
unnest
|
||||
------------------------
|
||||
option_bool=false
|
||||
option_ternary_1=true
|
||||
option_int=5
|
||||
option_real=3.1
|
||||
option_enum=two
|
||||
option_string_val=null
|
||||
option_string_null=val
|
||||
(6 rows)
|
||||
(7 rows)
|
||||
|
||||
-- ALTER INDEX .. SET
|
||||
ALTER INDEX dummy_test_idx SET (option_int = 10);
|
||||
ALTER INDEX dummy_test_idx SET (option_bool = true);
|
||||
ALTER INDEX dummy_test_idx SET (option_ternary_1 = false);
|
||||
ALTER INDEX dummy_test_idx SET (option_real = 3.2);
|
||||
ALTER INDEX dummy_test_idx SET (option_string_val = 'val2');
|
||||
ALTER INDEX dummy_test_idx SET (option_string_null = NULL);
|
||||
@@ -53,15 +56,17 @@ SELECT unnest(reloptions) FROM pg_class WHERE relname = 'dummy_test_idx';
|
||||
-------------------------
|
||||
option_int=10
|
||||
option_bool=true
|
||||
option_ternary_1=false
|
||||
option_real=3.2
|
||||
option_string_val=val2
|
||||
option_string_null=null
|
||||
option_enum=one
|
||||
(6 rows)
|
||||
(7 rows)
|
||||
|
||||
-- ALTER INDEX .. RESET
|
||||
ALTER INDEX dummy_test_idx RESET (option_int);
|
||||
ALTER INDEX dummy_test_idx RESET (option_bool);
|
||||
ALTER INDEX dummy_test_idx RESET (option_ternary_1);
|
||||
ALTER INDEX dummy_test_idx RESET (option_real);
|
||||
ALTER INDEX dummy_test_idx RESET (option_enum);
|
||||
ALTER INDEX dummy_test_idx RESET (option_string_val);
|
||||
@@ -100,6 +105,21 @@ SELECT unnest(reloptions) FROM pg_class WHERE relname = 'dummy_test_idx';
|
||||
(1 row)
|
||||
|
||||
ALTER INDEX dummy_test_idx RESET (option_bool);
|
||||
-- Ternary
|
||||
ALTER INDEX dummy_test_idx SET (option_ternary_1 = 4); -- error
|
||||
ERROR: invalid value for boolean option "option_ternary_1": 4
|
||||
ALTER INDEX dummy_test_idx SET (option_ternary_1 = 1); -- ok, as true
|
||||
ALTER INDEX dummy_test_idx SET (option_ternary_1 = 3.4); -- error
|
||||
ERROR: invalid value for boolean option "option_ternary_1": 3.4
|
||||
ALTER INDEX dummy_test_idx SET (option_ternary_1 = 'val4'); -- error
|
||||
ERROR: invalid value for boolean option "option_ternary_1": val4
|
||||
SELECT unnest(reloptions) FROM pg_class WHERE relname = 'dummy_test_idx';
|
||||
unnest
|
||||
--------------------
|
||||
option_ternary_1=1
|
||||
(1 row)
|
||||
|
||||
ALTER INDEX dummy_test_idx RESET (option_ternary_1);
|
||||
-- Float
|
||||
ALTER INDEX dummy_test_idx SET (option_real = 4); -- ok
|
||||
ALTER INDEX dummy_test_idx SET (option_real = true); -- error
|
||||
|
||||
@@ -18,6 +18,7 @@ SET client_min_messages TO 'notice';
|
||||
CREATE INDEX dummy_test_idx ON dummy_test_tab
|
||||
USING dummy_index_am (i) WITH (
|
||||
option_bool = false,
|
||||
option_ternary_1,
|
||||
option_int = 5,
|
||||
option_real = 3.1,
|
||||
option_enum = 'two',
|
||||
@@ -30,6 +31,7 @@ SELECT unnest(reloptions) FROM pg_class WHERE relname = 'dummy_test_idx';
|
||||
-- ALTER INDEX .. SET
|
||||
ALTER INDEX dummy_test_idx SET (option_int = 10);
|
||||
ALTER INDEX dummy_test_idx SET (option_bool = true);
|
||||
ALTER INDEX dummy_test_idx SET (option_ternary_1 = false);
|
||||
ALTER INDEX dummy_test_idx SET (option_real = 3.2);
|
||||
ALTER INDEX dummy_test_idx SET (option_string_val = 'val2');
|
||||
ALTER INDEX dummy_test_idx SET (option_string_null = NULL);
|
||||
@@ -40,6 +42,7 @@ SELECT unnest(reloptions) FROM pg_class WHERE relname = 'dummy_test_idx';
|
||||
-- ALTER INDEX .. RESET
|
||||
ALTER INDEX dummy_test_idx RESET (option_int);
|
||||
ALTER INDEX dummy_test_idx RESET (option_bool);
|
||||
ALTER INDEX dummy_test_idx RESET (option_ternary_1);
|
||||
ALTER INDEX dummy_test_idx RESET (option_real);
|
||||
ALTER INDEX dummy_test_idx RESET (option_enum);
|
||||
ALTER INDEX dummy_test_idx RESET (option_string_val);
|
||||
@@ -60,6 +63,13 @@ ALTER INDEX dummy_test_idx SET (option_bool = 3.4); -- error
|
||||
ALTER INDEX dummy_test_idx SET (option_bool = 'val4'); -- error
|
||||
SELECT unnest(reloptions) FROM pg_class WHERE relname = 'dummy_test_idx';
|
||||
ALTER INDEX dummy_test_idx RESET (option_bool);
|
||||
-- Ternary
|
||||
ALTER INDEX dummy_test_idx SET (option_ternary_1 = 4); -- error
|
||||
ALTER INDEX dummy_test_idx SET (option_ternary_1 = 1); -- ok, as true
|
||||
ALTER INDEX dummy_test_idx SET (option_ternary_1 = 3.4); -- error
|
||||
ALTER INDEX dummy_test_idx SET (option_ternary_1 = 'val4'); -- error
|
||||
SELECT unnest(reloptions) FROM pg_class WHERE relname = 'dummy_test_idx';
|
||||
ALTER INDEX dummy_test_idx RESET (option_ternary_1);
|
||||
-- Float
|
||||
ALTER INDEX dummy_test_idx SET (option_real = 4); -- ok
|
||||
ALTER INDEX dummy_test_idx SET (option_real = true); -- error
|
||||
|
||||
@@ -98,6 +98,24 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
|
||||
{fillfactor=13,autovacuum_enabled=false}
|
||||
(1 row)
|
||||
|
||||
-- Tests for ternary options
|
||||
-- behave as boolean option: accept unassigned name and truncated value
|
||||
DROP TABLE reloptions_test;
|
||||
CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
|
||||
SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
|
||||
reloptions
|
||||
------------------------
|
||||
{vacuum_truncate=true}
|
||||
(1 row)
|
||||
|
||||
DROP TABLE reloptions_test;
|
||||
CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
|
||||
SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
|
||||
reloptions
|
||||
------------------------
|
||||
{vacuum_truncate=fals}
|
||||
(1 row)
|
||||
|
||||
-- Test vacuum_truncate option
|
||||
DROP TABLE reloptions_test;
|
||||
CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
|
||||
|
||||
@@ -59,6 +59,17 @@ UPDATE pg_class
|
||||
ALTER TABLE reloptions_test RESET (illegal_option);
|
||||
SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
|
||||
|
||||
-- Tests for ternary options
|
||||
|
||||
-- behave as boolean option: accept unassigned name and truncated value
|
||||
DROP TABLE reloptions_test;
|
||||
CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
|
||||
SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
|
||||
|
||||
DROP TABLE reloptions_test;
|
||||
CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
|
||||
SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
|
||||
|
||||
-- Test vacuum_truncate option
|
||||
DROP TABLE reloptions_test;
|
||||
|
||||
|
||||
@@ -3952,6 +3952,7 @@ pg_sha512_ctx
|
||||
pg_snapshot
|
||||
pg_special_case
|
||||
pg_stack_base_t
|
||||
pg_ternary
|
||||
pg_time_t
|
||||
pg_time_usec_t
|
||||
pg_tz
|
||||
@@ -4079,6 +4080,7 @@ relopt_kind
|
||||
relopt_parse_elt
|
||||
relopt_real
|
||||
relopt_string
|
||||
relopt_ternary
|
||||
relopt_type
|
||||
relopt_value
|
||||
relopts_validator
|
||||
|
||||
Reference in New Issue
Block a user