mirror of https://github.com/postgres/postgres
This includes more tests dedicated to relation options, bringing the coverage of this code close to 100%, and the module can be used for other purposes, like a base template for an index AM implementation. Author: Nikolay Sharplov, Michael Paquier Reviewed-by: Álvaro Herrera, Dent John Discussion: https://postgr.es/m/17071942.m9zZutALE6@x200mpull/47/head
parent
69f9410807
commit
640c19869f
@ -0,0 +1,3 @@ |
|||||||
|
# Generated subdirectories |
||||||
|
/log/ |
||||||
|
/results/ |
@ -0,0 +1,20 @@ |
|||||||
|
# src/test/modules/dummy_index_am/Makefile
|
||||||
|
|
||||||
|
MODULES = dummy_index_am
|
||||||
|
|
||||||
|
EXTENSION = dummy_index_am
|
||||||
|
DATA = dummy_index_am--1.0.sql
|
||||||
|
PGFILEDESC = "dummy_index_am - index access method template"
|
||||||
|
|
||||||
|
REGRESS = reloptions
|
||||||
|
|
||||||
|
ifdef USE_PGXS |
||||||
|
PG_CONFIG = pg_config
|
||||||
|
PGXS := $(shell $(PG_CONFIG) --pgxs)
|
||||||
|
include $(PGXS) |
||||||
|
else |
||||||
|
subdir = src/test/modules/dummy_index_am
|
||||||
|
top_builddir = ../../../..
|
||||||
|
include $(top_builddir)/src/Makefile.global |
||||||
|
include $(top_srcdir)/contrib/contrib-global.mk |
||||||
|
endif |
@ -0,0 +1,11 @@ |
|||||||
|
Dummy Index AM |
||||||
|
============== |
||||||
|
|
||||||
|
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 |
||||||
|
- integer |
||||||
|
- real |
||||||
|
- strings (with and without NULL as default) |
@ -0,0 +1,19 @@ |
|||||||
|
/* src/test/modules/dummy_index_am/dummy_index_am--1.0.sql */ |
||||||
|
|
||||||
|
-- complain if script is sourced in psql, rather than via CREATE EXTENSION |
||||||
|
\echo Use "CREATE EXTENSION dummy_index_am" to load this file. \quit |
||||||
|
|
||||||
|
CREATE FUNCTION dihandler(internal) |
||||||
|
RETURNS index_am_handler |
||||||
|
AS 'MODULE_PATHNAME' |
||||||
|
LANGUAGE C; |
||||||
|
|
||||||
|
-- Access method |
||||||
|
CREATE ACCESS METHOD dummy_index_am TYPE INDEX HANDLER dihandler; |
||||||
|
COMMENT ON ACCESS METHOD dummy_index_am IS 'dummy index access method'; |
||||||
|
|
||||||
|
-- Operator classes |
||||||
|
CREATE OPERATOR CLASS int4_ops |
||||||
|
DEFAULT FOR TYPE int4 USING dummy_index_am AS |
||||||
|
OPERATOR 1 = (int4, int4), |
||||||
|
FUNCTION 1 hashint4(int4); |
@ -0,0 +1,312 @@ |
|||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
* |
||||||
|
* dummy_index_am.c |
||||||
|
* Index AM template main file. |
||||||
|
* |
||||||
|
* Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group |
||||||
|
* Portions Copyright (c) 1994, Regents of the University of California |
||||||
|
* |
||||||
|
* IDENTIFICATION |
||||||
|
* src/test/modules/dummy_index_am/dummy_index_am.c |
||||||
|
* |
||||||
|
*------------------------------------------------------------------------- |
||||||
|
*/ |
||||||
|
#include "postgres.h" |
||||||
|
|
||||||
|
#include "access/amapi.h" |
||||||
|
#include "access/reloptions.h" |
||||||
|
#include "catalog/index.h" |
||||||
|
#include "nodes/pathnodes.h" |
||||||
|
#include "utils/guc.h" |
||||||
|
#include "utils/rel.h" |
||||||
|
|
||||||
|
PG_MODULE_MAGIC; |
||||||
|
|
||||||
|
void _PG_init(void); |
||||||
|
|
||||||
|
/* parse table for fillRelOptions */ |
||||||
|
relopt_parse_elt di_relopt_tab[5]; |
||||||
|
|
||||||
|
/* Kind of relation options for dummy index */ |
||||||
|
relopt_kind di_relopt_kind; |
||||||
|
|
||||||
|
/* Dummy index options */ |
||||||
|
typedef struct DummyIndexOptions |
||||||
|
{ |
||||||
|
int32 vl_len_; /* varlena header (do not touch directly!) */ |
||||||
|
int option_int; |
||||||
|
double option_real; |
||||||
|
bool option_bool; |
||||||
|
int option_string_val_offset; |
||||||
|
int option_string_null_offset; |
||||||
|
} DummyIndexOptions; |
||||||
|
|
||||||
|
/* Handler for index AM */ |
||||||
|
PG_FUNCTION_INFO_V1(dihandler); |
||||||
|
|
||||||
|
/*
|
||||||
|
* Validation function for string relation options. |
||||||
|
*/ |
||||||
|
static void |
||||||
|
validate_string_option(const char *value) |
||||||
|
{ |
||||||
|
ereport(NOTICE, |
||||||
|
(errmsg("new option value for string parameter %s", |
||||||
|
value ? value : "NULL"))); |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* This function creates a full set of relation option types, |
||||||
|
* with various patterns. |
||||||
|
*/ |
||||||
|
static void |
||||||
|
create_reloptions_table(void) |
||||||
|
{ |
||||||
|
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); |
||||||
|
|
||||||
|
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); |
||||||
|
|
||||||
|
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); |
||||||
|
|
||||||
|
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[3].optname = "option_string_val"; |
||||||
|
di_relopt_tab[3].opttype = RELOPT_TYPE_STRING; |
||||||
|
di_relopt_tab[3].offset = offsetof(DummyIndexOptions, |
||||||
|
option_string_val_offset); |
||||||
|
|
||||||
|
/*
|
||||||
|
* String option for dummy_index_am with NULL default, and without |
||||||
|
* description. |
||||||
|
*/ |
||||||
|
add_string_reloption(di_relopt_kind, "option_string_null", |
||||||
|
NULL, /* description */ |
||||||
|
NULL, &validate_string_option, |
||||||
|
AccessExclusiveLock); |
||||||
|
di_relopt_tab[4].optname = "option_string_null"; |
||||||
|
di_relopt_tab[4].opttype = RELOPT_TYPE_STRING; |
||||||
|
di_relopt_tab[4].offset = offsetof(DummyIndexOptions, |
||||||
|
option_string_null_offset); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Build a new index. |
||||||
|
*/ |
||||||
|
static IndexBuildResult * |
||||||
|
dibuild(Relation heap, Relation index, IndexInfo *indexInfo) |
||||||
|
{ |
||||||
|
IndexBuildResult *result; |
||||||
|
|
||||||
|
result = (IndexBuildResult *) palloc(sizeof(IndexBuildResult)); |
||||||
|
|
||||||
|
/* let's pretend that no tuples were scanned */ |
||||||
|
result->heap_tuples = 0; |
||||||
|
/* and no index tuples were created (that is true) */ |
||||||
|
result->index_tuples = 0; |
||||||
|
|
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Build an empty index for the initialiation fork. |
||||||
|
*/ |
||||||
|
static void |
||||||
|
dibuildempty(Relation index) |
||||||
|
{ |
||||||
|
/* No need to build an init fork for a dummy index */ |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Insert new tuple to index AM. |
||||||
|
*/ |
||||||
|
static bool |
||||||
|
diinsert(Relation index, Datum *values, bool *isnull, |
||||||
|
ItemPointer ht_ctid, Relation heapRel, |
||||||
|
IndexUniqueCheck checkUnique, |
||||||
|
IndexInfo *indexInfo) |
||||||
|
{ |
||||||
|
/* nothing to do */ |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Bulk deletion of all index entries pointing to a set of table tuples. |
||||||
|
*/ |
||||||
|
static IndexBulkDeleteResult * |
||||||
|
dibulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, |
||||||
|
IndexBulkDeleteCallback callback, void *callback_state) |
||||||
|
{ |
||||||
|
/*
|
||||||
|
* There is nothing to delete. Return NULL as there is nothing to pass to |
||||||
|
* amvacuumcleanup. |
||||||
|
*/ |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Post-VACUUM cleanup for index AM. |
||||||
|
*/ |
||||||
|
static IndexBulkDeleteResult * |
||||||
|
divacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats) |
||||||
|
{ |
||||||
|
/* Index has not been modified, so returning NULL is fine */ |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Estimate cost of index AM. |
||||||
|
*/ |
||||||
|
static void |
||||||
|
dicostestimate(PlannerInfo *root, IndexPath *path, double loop_count, |
||||||
|
Cost *indexStartupCost, Cost *indexTotalCost, |
||||||
|
Selectivity *indexSelectivity, double *indexCorrelation, |
||||||
|
double *indexPages) |
||||||
|
{ |
||||||
|
/* Tell planner to never use this index! */ |
||||||
|
*indexStartupCost = 1.0e10; |
||||||
|
*indexTotalCost = 1.0e10; |
||||||
|
|
||||||
|
/* Do not care about the rest */ |
||||||
|
*indexSelectivity = 1; |
||||||
|
*indexCorrelation = 0; |
||||||
|
*indexPages = 1; |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse relation options for index AM, returning a DummyIndexOptions |
||||||
|
* structure filled with option values. |
||||||
|
*/ |
||||||
|
static bytea * |
||||||
|
dioptions(Datum reloptions, bool validate) |
||||||
|
{ |
||||||
|
relopt_value *options; |
||||||
|
int numoptions; |
||||||
|
DummyIndexOptions *rdopts; |
||||||
|
|
||||||
|
/* Parse the user-given reloptions */ |
||||||
|
options = parseRelOptions(reloptions, validate, di_relopt_kind, &numoptions); |
||||||
|
rdopts = allocateReloptStruct(sizeof(DummyIndexOptions), options, numoptions); |
||||||
|
fillRelOptions((void *) rdopts, sizeof(DummyIndexOptions), options, numoptions, |
||||||
|
validate, di_relopt_tab, lengthof(di_relopt_tab)); |
||||||
|
|
||||||
|
return (bytea *) rdopts; |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Validator for index AM. |
||||||
|
*/ |
||||||
|
static bool |
||||||
|
divalidate(Oid opclassoid) |
||||||
|
{ |
||||||
|
/* Index is dummy so we are happy with any opclass */ |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Begin scan of index AM. |
||||||
|
*/ |
||||||
|
static IndexScanDesc |
||||||
|
dibeginscan(Relation r, int nkeys, int norderbys) |
||||||
|
{ |
||||||
|
IndexScanDesc scan; |
||||||
|
|
||||||
|
/* Let's pretend we are doing something */ |
||||||
|
scan = RelationGetIndexScan(r, nkeys, norderbys); |
||||||
|
return scan; |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Rescan of index AM. |
||||||
|
*/ |
||||||
|
static void |
||||||
|
direscan(IndexScanDesc scan, ScanKey scankey, int nscankeys, |
||||||
|
ScanKey orderbys, int norderbys) |
||||||
|
{ |
||||||
|
/* nothing to do */ |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* End scan of index AM. |
||||||
|
*/ |
||||||
|
static void |
||||||
|
diendscan(IndexScanDesc scan) |
||||||
|
{ |
||||||
|
/* nothing to do */ |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Index AM handler function: returns IndexAmRoutine with access method |
||||||
|
* parameters and callbacks. |
||||||
|
*/ |
||||||
|
Datum |
||||||
|
dihandler(PG_FUNCTION_ARGS) |
||||||
|
{ |
||||||
|
IndexAmRoutine *amroutine = makeNode(IndexAmRoutine); |
||||||
|
|
||||||
|
amroutine->amstrategies = 0; |
||||||
|
amroutine->amsupport = 1; |
||||||
|
amroutine->amcanorder = false; |
||||||
|
amroutine->amcanorderbyop = false; |
||||||
|
amroutine->amcanbackward = false; |
||||||
|
amroutine->amcanunique = false; |
||||||
|
amroutine->amcanmulticol = false; |
||||||
|
amroutine->amoptionalkey = false; |
||||||
|
amroutine->amsearcharray = false; |
||||||
|
amroutine->amsearchnulls = false; |
||||||
|
amroutine->amstorage = false; |
||||||
|
amroutine->amclusterable = false; |
||||||
|
amroutine->ampredlocks = false; |
||||||
|
amroutine->amcanparallel = false; |
||||||
|
amroutine->amcaninclude = false; |
||||||
|
amroutine->amkeytype = InvalidOid; |
||||||
|
|
||||||
|
amroutine->ambuild = dibuild; |
||||||
|
amroutine->ambuildempty = dibuildempty; |
||||||
|
amroutine->aminsert = diinsert; |
||||||
|
amroutine->ambulkdelete = dibulkdelete; |
||||||
|
amroutine->amvacuumcleanup = divacuumcleanup; |
||||||
|
amroutine->amcanreturn = NULL; |
||||||
|
amroutine->amcostestimate = dicostestimate; |
||||||
|
amroutine->amoptions = dioptions; |
||||||
|
amroutine->amproperty = NULL; |
||||||
|
amroutine->ambuildphasename = NULL; |
||||||
|
amroutine->amvalidate = divalidate; |
||||||
|
amroutine->ambeginscan = dibeginscan; |
||||||
|
amroutine->amrescan = direscan; |
||||||
|
amroutine->amgettuple = NULL; |
||||||
|
amroutine->amgetbitmap = NULL; |
||||||
|
amroutine->amendscan = diendscan; |
||||||
|
amroutine->ammarkpos = NULL; |
||||||
|
amroutine->amrestrpos = NULL; |
||||||
|
amroutine->amestimateparallelscan = NULL; |
||||||
|
amroutine->aminitparallelscan = NULL; |
||||||
|
amroutine->amparallelrescan = NULL; |
||||||
|
|
||||||
|
PG_RETURN_POINTER(amroutine); |
||||||
|
} |
||||||
|
|
||||||
|
void |
||||||
|
_PG_init(void) |
||||||
|
{ |
||||||
|
create_reloptions_table(); |
||||||
|
} |
@ -0,0 +1,5 @@ |
|||||||
|
# dummy_index_am extension |
||||||
|
comment = 'dummy_index_am - index access method template' |
||||||
|
default_version = '1.0' |
||||||
|
module_pathname = '$libdir/dummy_index_am' |
||||||
|
relocatable = true |
@ -0,0 +1,115 @@ |
|||||||
|
-- Tests for relation options |
||||||
|
CREATE EXTENSION dummy_index_am; |
||||||
|
CREATE TABLE dummy_test_tab (i int4); |
||||||
|
-- Test with default values. |
||||||
|
CREATE INDEX dummy_test_idx ON dummy_test_tab |
||||||
|
USING dummy_index_am (i); |
||||||
|
SELECT unnest(reloptions) FROM pg_class WHERE relname = 'dummy_test_idx'; |
||||||
|
unnest |
||||||
|
-------- |
||||||
|
(0 rows) |
||||||
|
|
||||||
|
DROP INDEX dummy_test_idx; |
||||||
|
-- Test with full set of options. |
||||||
|
CREATE INDEX dummy_test_idx ON dummy_test_tab |
||||||
|
USING dummy_index_am (i) WITH ( |
||||||
|
option_bool = false, |
||||||
|
option_int = 5, |
||||||
|
option_real = 3.1, |
||||||
|
option_string_val = NULL, |
||||||
|
option_string_null = 'val'); |
||||||
|
NOTICE: new option value for string parameter null |
||||||
|
NOTICE: new option value for string parameter val |
||||||
|
SELECT unnest(reloptions) FROM pg_class WHERE relname = 'dummy_test_idx'; |
||||||
|
unnest |
||||||
|
------------------------ |
||||||
|
option_bool=false |
||||||
|
option_int=5 |
||||||
|
option_real=3.1 |
||||||
|
option_string_val=null |
||||||
|
option_string_null=val |
||||||
|
(5 rows) |
||||||
|
|
||||||
|
-- Silence validation checks for strings |
||||||
|
SET client_min_messages TO 'warning'; |
||||||
|
-- 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_real = 3.2); |
||||||
|
ALTER INDEX dummy_test_idx SET (option_string_val = 'val2'); |
||||||
|
ALTER INDEX dummy_test_idx SET (option_string_null = NULL); |
||||||
|
SELECT unnest(reloptions) FROM pg_class WHERE relname = 'dummy_test_idx'; |
||||||
|
unnest |
||||||
|
------------------------- |
||||||
|
option_int=10 |
||||||
|
option_bool=true |
||||||
|
option_real=3.2 |
||||||
|
option_string_val=val2 |
||||||
|
option_string_null=null |
||||||
|
(5 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_real); |
||||||
|
ALTER INDEX dummy_test_idx RESET (option_string_val); |
||||||
|
ALTER INDEX dummy_test_idx RESET (option_string_null); |
||||||
|
SELECT unnest(reloptions) FROM pg_class WHERE relname = 'dummy_test_idx'; |
||||||
|
unnest |
||||||
|
-------- |
||||||
|
(0 rows) |
||||||
|
|
||||||
|
-- Cross-type checks for reloption values |
||||||
|
-- Integer |
||||||
|
ALTER INDEX dummy_test_idx SET (option_int = 3.3); -- ok |
||||||
|
ALTER INDEX dummy_test_idx SET (option_int = true); -- error |
||||||
|
ERROR: invalid value for integer option "option_int": true |
||||||
|
ALTER INDEX dummy_test_idx SET (option_int = 'val3'); -- error |
||||||
|
ERROR: invalid value for integer option "option_int": val3 |
||||||
|
SELECT unnest(reloptions) FROM pg_class WHERE relname = 'dummy_test_idx'; |
||||||
|
unnest |
||||||
|
---------------- |
||||||
|
option_int=3.3 |
||||||
|
(1 row) |
||||||
|
|
||||||
|
ALTER INDEX dummy_test_idx RESET (option_int); |
||||||
|
-- Boolean |
||||||
|
ALTER INDEX dummy_test_idx SET (option_bool = 4); -- error |
||||||
|
ERROR: invalid value for boolean option "option_bool": 4 |
||||||
|
ALTER INDEX dummy_test_idx SET (option_bool = 1); -- ok, as true |
||||||
|
ALTER INDEX dummy_test_idx SET (option_bool = 3.4); -- error |
||||||
|
ERROR: invalid value for boolean option "option_bool": 3.4 |
||||||
|
ALTER INDEX dummy_test_idx SET (option_bool = 'val4'); -- error |
||||||
|
ERROR: invalid value for boolean option "option_bool": val4 |
||||||
|
SELECT unnest(reloptions) FROM pg_class WHERE relname = 'dummy_test_idx'; |
||||||
|
unnest |
||||||
|
--------------- |
||||||
|
option_bool=1 |
||||||
|
(1 row) |
||||||
|
|
||||||
|
ALTER INDEX dummy_test_idx RESET (option_bool); |
||||||
|
-- Float |
||||||
|
ALTER INDEX dummy_test_idx SET (option_real = 4); -- ok |
||||||
|
ALTER INDEX dummy_test_idx SET (option_real = true); -- error |
||||||
|
ERROR: invalid value for floating point option "option_real": true |
||||||
|
ALTER INDEX dummy_test_idx SET (option_real = 'val5'); -- error |
||||||
|
ERROR: invalid value for floating point option "option_real": val5 |
||||||
|
SELECT unnest(reloptions) FROM pg_class WHERE relname = 'dummy_test_idx'; |
||||||
|
unnest |
||||||
|
--------------- |
||||||
|
option_real=4 |
||||||
|
(1 row) |
||||||
|
|
||||||
|
ALTER INDEX dummy_test_idx RESET (option_real); |
||||||
|
-- String |
||||||
|
ALTER INDEX dummy_test_idx SET (option_string_val = 4); -- ok |
||||||
|
ALTER INDEX dummy_test_idx SET (option_string_val = 3.5); -- ok |
||||||
|
ALTER INDEX dummy_test_idx SET (option_string_val = true); -- ok, as "true" |
||||||
|
SELECT unnest(reloptions) FROM pg_class WHERE relname = 'dummy_test_idx'; |
||||||
|
unnest |
||||||
|
------------------------ |
||||||
|
option_string_val=true |
||||||
|
(1 row) |
||||||
|
|
||||||
|
ALTER INDEX dummy_test_idx RESET (option_string_val); |
||||||
|
DROP INDEX dummy_test_idx; |
@ -0,0 +1,68 @@ |
|||||||
|
-- Tests for relation options |
||||||
|
CREATE EXTENSION dummy_index_am; |
||||||
|
|
||||||
|
CREATE TABLE dummy_test_tab (i int4); |
||||||
|
|
||||||
|
-- Test with default values. |
||||||
|
CREATE INDEX dummy_test_idx ON dummy_test_tab |
||||||
|
USING dummy_index_am (i); |
||||||
|
SELECT unnest(reloptions) FROM pg_class WHERE relname = 'dummy_test_idx'; |
||||||
|
DROP INDEX dummy_test_idx; |
||||||
|
|
||||||
|
-- Test with full set of options. |
||||||
|
CREATE INDEX dummy_test_idx ON dummy_test_tab |
||||||
|
USING dummy_index_am (i) WITH ( |
||||||
|
option_bool = false, |
||||||
|
option_int = 5, |
||||||
|
option_real = 3.1, |
||||||
|
option_string_val = NULL, |
||||||
|
option_string_null = 'val'); |
||||||
|
SELECT unnest(reloptions) FROM pg_class WHERE relname = 'dummy_test_idx'; |
||||||
|
|
||||||
|
-- Silence validation checks for strings |
||||||
|
SET client_min_messages TO 'warning'; |
||||||
|
|
||||||
|
-- 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_real = 3.2); |
||||||
|
ALTER INDEX dummy_test_idx SET (option_string_val = 'val2'); |
||||||
|
ALTER INDEX dummy_test_idx SET (option_string_null = NULL); |
||||||
|
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_real); |
||||||
|
ALTER INDEX dummy_test_idx RESET (option_string_val); |
||||||
|
ALTER INDEX dummy_test_idx RESET (option_string_null); |
||||||
|
SELECT unnest(reloptions) FROM pg_class WHERE relname = 'dummy_test_idx'; |
||||||
|
|
||||||
|
-- Cross-type checks for reloption values |
||||||
|
-- Integer |
||||||
|
ALTER INDEX dummy_test_idx SET (option_int = 3.3); -- ok |
||||||
|
ALTER INDEX dummy_test_idx SET (option_int = true); -- error |
||||||
|
ALTER INDEX dummy_test_idx SET (option_int = 'val3'); -- error |
||||||
|
SELECT unnest(reloptions) FROM pg_class WHERE relname = 'dummy_test_idx'; |
||||||
|
ALTER INDEX dummy_test_idx RESET (option_int); |
||||||
|
-- Boolean |
||||||
|
ALTER INDEX dummy_test_idx SET (option_bool = 4); -- error |
||||||
|
ALTER INDEX dummy_test_idx SET (option_bool = 1); -- ok, as true |
||||||
|
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); |
||||||
|
-- Float |
||||||
|
ALTER INDEX dummy_test_idx SET (option_real = 4); -- ok |
||||||
|
ALTER INDEX dummy_test_idx SET (option_real = true); -- error |
||||||
|
ALTER INDEX dummy_test_idx SET (option_real = 'val5'); -- error |
||||||
|
SELECT unnest(reloptions) FROM pg_class WHERE relname = 'dummy_test_idx'; |
||||||
|
ALTER INDEX dummy_test_idx RESET (option_real); |
||||||
|
-- String |
||||||
|
ALTER INDEX dummy_test_idx SET (option_string_val = 4); -- ok |
||||||
|
ALTER INDEX dummy_test_idx SET (option_string_val = 3.5); -- ok |
||||||
|
ALTER INDEX dummy_test_idx SET (option_string_val = true); -- ok, as "true" |
||||||
|
SELECT unnest(reloptions) FROM pg_class WHERE relname = 'dummy_test_idx'; |
||||||
|
ALTER INDEX dummy_test_idx RESET (option_string_val); |
||||||
|
|
||||||
|
DROP INDEX dummy_test_idx; |
Loading…
Reference in new issue