В письме от вторник, 19 марта 2019 г. 16:09:13 MSK пользователь Michael Paquier написал:
> > So I created src/test/modules/dummy_index, it does no real indexing, but > > it > > has all types of reloptions that can be set (reloption_int, > > reloption_real, > > reloption_bool, reloption_string and reloption_string2). It also has set > > of > > boolean GUC variables that enables test output concerning certain > > reloption: (do_test_reloption_int, do_test_reloption_real, > > do_test_reloption_bool and do_test_reloption_string and > > do_test_reloption_string2) also set > > do_test_reloptions to true to get any output at all. > > Dummy index will print this output when index is created, and when record > > is inserted (this needed to check if your ALTER TABLE did well) > > Then you just use normal regression tests: turns on test output, sets some > > reloption and check test output, that it properly reaches the access > > method > > internals. > > Thanks for doing the effort to split that stuff. This looks like an > interesting base template for anybody willing to look after some > basics with index AMs, like what's done for FDWs with blackhole_fdw. I am not sure it is good template. Most methods are empty, and does not show any example of how it should work. If I am to create a template I would try to create index that just do seq scan of indexed values. It would have all code index must have, but the code of the index algorithm iteslf would be minimal. But it is another task. > Perhaps the name should be dummy_am_index or dummy_index_am? > dummy_index does not sound bad either. Actually I do not see any reason to do it, all indexes in postgres are implemented as access methods, so it sounds as double naming for me. But I actually do not care about this name, if you think adding _am is better, so I did it. But i did not remove .c file names and did not change di- suffix to dia- in the code. Is it ok for you? > > While writing this module I kept in mind the idea that this module can be > > also used for other am-related tests, so I separated the code into two > > parts: dummy_index.c has only code related to implementation of an empty > > access method, and all code related to reloptions tests were stored into > > direloptions.c. So in future somebody can add di[what_ever_he_wants].c > > whith his own tests code, add necessary calls to dummy_index.c, create > > some GUC variables, and has his own feature tested. > > Here are some comments. I think that this could be simplified > further more. > > The README file could have a more consistent format with the rest. > See for example dummy_seclabel/README. You could add a small > example with its usage. Good notion. Fixed it. > Is there any point in having string_option2? String reloptions are > already tested with string_option. There are two reasons for that: 1. We should test both behavior with validation function, and without one. For this we need two options, because we can change this in runtime 2. The implementation of string functions is a bit tricky. It allocates some more memory after the Option structure, and string values are placed there. It works well with one string option, but I was not sure that is works properly for two of them. I can imagine a bug that will show itself only with a second option. So we anyway should test two. > Also => s/Seconf/Second/. > s/valudate/validate/. Thanks. I tried my best with aspell, but still missed something. > +-- Test behavior of second string option (there can be issues with second > one) What are those issues? This issues are listed in README. And also I've written them above. To prevent confusion I've removed this issue notion. :-) One who want to know more, can read README file ;-) > + } else > + { > Code format does not follow the Postgres guidelines. You could fix > all that with an indent run. Oups, it's my favorite codestyle, I fall back to it when does not pay attention. I've reindented the code, a good idea. Should come to it myself.... > The ranges of the different values are not tested, wouldn't it be > better to test that as well? My idea was to test only things that can't be tested in regression tests. Ranges are tested in regression tests ( I also wrote that tests) and it is better to leave it there. But the question is good, I would mention it in README file, to make it clear.... > The way the test is configured with the strong dependencies between > the reloption types and the GUCs is much bug-prone I think. All of > that is present only to print a couple of WARNING messages with > specific values of values. So, why not removing the GUCs and the > printing logic which shows a subset of values? I am afraid that we will get a mess that will work well, but it would be difficult for a human to find any logic in the output. And sooner or later we will need it, when something will go wrong and somebody will try to find out why. So it is better to test one option at a time, and that's why mute test output for other options. > Please note that these > are visible directly via pg_class.reloptions. So we could shave quite > some code. Values from pg_class are well tested in regression test. My point here is to check that they reach index internal as expected. And there is a long way between pg_class.reloptions and index internals. > Please note that the compilation of the module fails. > nodes/relation.h maybe is access/relation.h? You may want to review > all that. Hm... I do not quite understand how it get there and why in worked for me before. But I changed it to nodes/pathnodes.h It was here because it is needed for PlannerInfo symbol. PS. Sorry for long delays. I do not always have much time to do postgres...
diff --git a/.gitignore b/.gitignore index 794e35b..37331c2 100644 diff --git a/src/test/modules/Makefile b/src/test/modules/Makefile index dfd0956..742078e 100644 --- a/src/test/modules/Makefile +++ b/src/test/modules/Makefile @@ -7,6 +7,7 @@ include $(top_builddir)/src/Makefile.global SUBDIRS = \ brin \ commit_ts \ + dummy_index_am \ dummy_seclabel \ snapshot_too_old \ test_bloomfilter \ diff --git a/src/test/modules/dummy_index_am/.gitignore b/src/test/modules/dummy_index_am/.gitignore new file mode 100644 index 0000000..5dcb3ff --- /dev/null +++ b/src/test/modules/dummy_index_am/.gitignore @@ -0,0 +1,4 @@ +# Generated subdirectories +/log/ +/results/ +/tmp_check/ diff --git a/src/test/modules/dummy_index_am/Makefile b/src/test/modules/dummy_index_am/Makefile new file mode 100644 index 0000000..695941b --- /dev/null +++ b/src/test/modules/dummy_index_am/Makefile @@ -0,0 +1,21 @@ +# contrib/bloom/Makefile + +MODULE_big = dummy_index_am +OBJS = dummy_index.o direloptions.o $(WIN32RES) + +EXTENSION = dummy_index_am +DATA = dummy_index_am--1.0.sql +PGFILEDESC = "dummy index access method - needed for all kinds of tests" + +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 diff --git a/src/test/modules/dummy_index_am/README b/src/test/modules/dummy_index_am/README new file mode 100644 index 0000000..61f80d3 --- /dev/null +++ b/src/test/modules/dummy_index_am/README @@ -0,0 +1,45 @@ +Dummy index AM +============== + +Dummy index, an index module for testing am-related internal calls that can't be +properly tested inside production indexes, but better to be tested inside actual +access method module. + +Guidelines: +1. Keep this index as simple as as possible. It should not do any real indexing +(unless you need it for your tests), if you need it make it as simple as +possible; +2. Keep all code related to feature you test inside id[name_of_a_feature].c +file. dummy_index.c file should contain code that is needed for everyone, and +make calls to feature-related code; +3. Code related to your feature tests should be enabled and disabled by GUC +variables. Create as many boolean GUC variables as you need and set them on so +your test will know when it is time to do test output. Thus output from +different features tests are not interfered; +4. Add section to this README file that describes the general idea of what your +tests do. + +Reloptions tests +================ + +Some relotions testing are done in regression tests. There we can check if new +option value properly reaches pg_class, minimum/maximum checks, etc. But we +can't check if option value successfully reached index internal code when we are +dealing with production indexes. But we can do it here in Dummy index. +Here we check that values of reloptions properly reaches am-internals, and that +all reloption-related code works as expected. Several GUC variables are defined +to control test's output. do_test_reloptions turns on and off any +reloptions-related output. You will also get some test output in the case when +no relation options is set at all. do_test_reloption_int, +do_test_reloption_real, do_test_reloption_bool and do_test_reloption_string +allows to enable test output for int, real, boolean and string options. +do_test_reloption_string2 enables test output for another string option. We need +second string option, because a) string reloption implementation is a bit +tricky, and it is better to check that second value works as well; b) better to +check both cases: string option with validation function and without one, so we +need two string options. + + +Authors +======= +Nikolay Shaplov <dh...@nataraj.su> (Dummy index core, reloptions tests) diff --git a/src/test/modules/dummy_index_am/direloptions.c b/src/test/modules/dummy_index_am/direloptions.c new file mode 100644 index 0000000..3c7cca5 --- /dev/null +++ b/src/test/modules/dummy_index_am/direloptions.c @@ -0,0 +1,219 @@ +/*------------------------------------------------------------------------- + * + * direloptions.c + * Functions and variables needed for reloptions tests. + * + * Copyright (c) 2019, PostgreSQL Global Development Group + * + * IDENTIFICATION + * src/test/modules/dummy_index_am/direloptions.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include "utils/rel.h" +#include "access/reloptions.h" +#include "utils/guc.h" + +#include "dummy_index.h" + + +/* parse table for fillRelOptions */ +relopt_parse_elt di_relopt_tab[5]; + + +/* Kind of relation options for dummy index */ +relopt_kind di_relopt_kind; + +/* GUC variables */ +static bool do_test_reloptions = false; +static bool do_test_reloption_int = false; +static bool do_test_reloption_real = false; +static bool do_test_reloption_bool = false; +static bool do_test_reloption_string = false; +static bool do_test_reloption_string2 = false; + +/* + * This function creates reloptions that would be used in reloptions tests + */ +void +create_reloptions_table() +{ + di_relopt_kind = add_reloption_kind(); + + add_int_reloption(di_relopt_kind, "int_option", + "Int option used for relotions test purposes", + 10, -10, 100); + di_relopt_tab[0].optname = "int_option"; + di_relopt_tab[0].opttype = RELOPT_TYPE_INT; + di_relopt_tab[0].offset = offsetof(DummyIndexOptions, int_option); + + add_real_reloption(di_relopt_kind, "real_option", + "Real option used for relotions test purposes", + 3.1415, -10, 100); + di_relopt_tab[1].optname = "real_option"; + di_relopt_tab[1].opttype = RELOPT_TYPE_REAL; + di_relopt_tab[1].offset = offsetof(DummyIndexOptions, real_option); + + + add_bool_reloption(di_relopt_kind, "bool_option", + "Boolean option used for relotions test purposes", + true); + di_relopt_tab[2].optname = "bool_option"; + di_relopt_tab[2].opttype = RELOPT_TYPE_BOOL; + di_relopt_tab[2].offset = offsetof(DummyIndexOptions, bool_option); + + add_string_reloption(di_relopt_kind, "string_option", + "String option used for relotions test purposes", + "DefaultValue", &validate_string_option); + di_relopt_tab[3].optname = "string_option"; + di_relopt_tab[3].opttype = RELOPT_TYPE_STRING; + di_relopt_tab[3].offset = offsetof(DummyIndexOptions, string_option_offset); + + add_string_reloption(di_relopt_kind, "string_option2", + "Second string option used for relotions test purposes", + "SecondDefaultValue", &validate_string_option); + di_relopt_tab[4].optname = "string_option2"; + di_relopt_tab[4].opttype = RELOPT_TYPE_STRING; + di_relopt_tab[4].offset = offsetof(DummyIndexOptions, string_option2_offset); + +} + +/* + * This function creates GUC variables that allows to turn on and off test + * output for different relopntions + */ +void +create_reloptions_test_GUC() +{ + DefineCustomBoolVariable("dummy_index.do_test_reloptions", + "Set to true if you are going to test reloptions.", + NULL, + &do_test_reloptions, + false, + PGC_USERSET, + 0, + NULL, + NULL, + NULL); + + DefineCustomBoolVariable("dummy_index.do_test_reloption_int", + "Set to true if you are going to test int reloption.", + NULL, + &do_test_reloption_int, + false, + PGC_USERSET, + 0, + NULL, + NULL, + NULL); + + DefineCustomBoolVariable("dummy_index.do_test_reloption_real", + "Set to true if you are going to test real reloption.", + NULL, + &do_test_reloption_real, + false, + PGC_USERSET, + 0, + NULL, + NULL, + NULL); + + DefineCustomBoolVariable("dummy_index.do_test_reloption_bool", + "Set to true if you are going to test boolean reloption.", + NULL, + &do_test_reloption_bool, + false, + PGC_USERSET, + 0, + NULL, + NULL, + NULL); + + DefineCustomBoolVariable("dummy_index.do_test_reloption_string", + "Set to true if you are going to test string reloption.", + NULL, + &do_test_reloption_string, + false, + PGC_USERSET, + 0, + NULL, + NULL, + NULL); + DefineCustomBoolVariable("dummy_index.do_test_reloption_string2", + "Set to true if you are going to test second string reloption.", + NULL, + &do_test_reloption_string2, + false, + PGC_USERSET, + 0, + NULL, + NULL, + NULL); +} + +/* + * Function prints output for reloptions tests if GUC variables switches are + * properly set on. + */ +void +print_reloptions_test_output(Relation index) +{ + if (do_test_reloptions) + { + if (!index->rd_options) + { + elog(WARNING, "No reloptions is set, default values will be chosen in module runtime"); + } + else + { + DummyIndexOptions *opt; + + opt = (DummyIndexOptions *) index->rd_options; + if (do_test_reloption_int) + { + elog(WARNING, "int_option = %d", opt->int_option); + } + if (do_test_reloption_real) + { + elog(WARNING, "real_option = %f", opt->real_option); + } + if (do_test_reloption_bool) + { + elog(WARNING, "bool_option = %d", opt->bool_option); + } + if (do_test_reloption_string) + { + char *str; + + str = (char *) opt + opt->string_option_offset; + elog(WARNING, "string_option = '%s'", str); + } + if (do_test_reloption_string2) + { + char *str; + + str = (char *) opt + opt->string_option2_offset; + elog(WARNING, "string_option2 = '%s'", str); + } + } + } +} + +/* + * Validation function for string_option reloption + */ +void +validate_string_option(const char *value) +{ + if (do_test_reloptions && do_test_reloption_string) + { + if (value) + elog(WARNING, "Validating string option '%s'", value); + else + elog(WARNING, "Validating string option with NULL value"); + } + if (!value || *value == 'I') + elog(ERROR, "This seems to be invalid value. Please set valid value"); +} diff --git a/src/test/modules/dummy_index_am/dummy_index.c b/src/test/modules/dummy_index_am/dummy_index.c new file mode 100644 index 0000000..bd4c665 --- /dev/null +++ b/src/test/modules/dummy_index_am/dummy_index.c @@ -0,0 +1,197 @@ +/*------------------------------------------------------------------------- + * + * dummy_index.c + * Dummy index AM main file. + * + * Copyright (c) 2019, PostgreSQL Global Development Group + * + * IDENTIFICATION + * src/test/modules/dummy_index_am/dummy_index.c + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include "access/amapi.h" +#include "catalog/index.h" +#include "access/reloptions.h" +#include "utils/guc.h" +#include "dummy_index.h" + + +PG_FUNCTION_INFO_V1(dihandler); +PG_MODULE_MAGIC; + +void +_PG_init(void) + +{ + create_reloptions_table(); + create_reloptions_test_GUC(); +} + +/* + * Dummy index handler function: return 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->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); +} + +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; + + print_reloptions_test_output(index); + + return result; +} + +void +dibuildempty(Relation index) +{ + /* Let's see what will happen if nothing is done here */ + /* Add tests for reloptions here */ +} + +bool +diinsert(Relation index, Datum *values, bool *isnull, + ItemPointer ht_ctid, Relation heapRel, + IndexUniqueCheck checkUnique, + IndexInfo *indexInfo) +{ + /* This is Dummy Index we do nothing on insert :-) */ + print_reloptions_test_output(index); + return false; + +} + +IndexBulkDeleteResult * +dibulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, + IndexBulkDeleteCallback callback, void *callback_state) +{ + /* + * Do not delete anything; Return NULL as we have nothing to pass to + * amvacuumcleanup + */ + return NULL; +} + +IndexBulkDeleteResult * +divacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats) +{ + /* Index have not been modified, so it is absolutely right to return NULL */ + return NULL; +} + +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; /* AKA disable_cost */ + *indexTotalCost = 1.0e10; /* AKA disable_cost */ + + /* Do not care about the rest */ + *indexSelectivity = 1; + *indexCorrelation = 0; + *indexPages = 1; +} + +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; +} + +bool +divalidate(Oid opclassoid) +{ + /* Index does not really work so we are happy with any opclass */ + return true; +} + +IndexScanDesc +dibeginscan(Relation r, int nkeys, int norderbys) +{ + IndexScanDesc scan; + + /* Let's pretend we are doing something, just in case */ + scan = RelationGetIndexScan(r, nkeys, norderbys); + return scan; +} + +void +direscan(IndexScanDesc scan, ScanKey scankey, int nscankeys, + ScanKey orderbys, int norderbys) +{ + /* Just do nothing */ +} + +void +diendscan(IndexScanDesc scan) +{ + /* Do nothing */ +} diff --git a/src/test/modules/dummy_index_am/dummy_index.h b/src/test/modules/dummy_index_am/dummy_index.h new file mode 100644 index 0000000..fa6e405 --- /dev/null +++ b/src/test/modules/dummy_index_am/dummy_index.h @@ -0,0 +1,66 @@ +/*------------------------------------------------------------------------- + * + * dummy_index.h + * Header for dummy_index_am index. + * + * Copyright (c) 2019, PostgreSQL Global Development Group + * + * IDENTIFICATION + * src/test/modules/dummy_index_am/dummy_index.h + * + *------------------------------------------------------------------------- + */ +#ifndef _DUMMY_INDEX_H_ +#define _DUMMY_INDEX_H_ + +#include "nodes/pathnodes.h" + +/* Dummy index options */ +typedef struct DummyIndexOptions +{ + int32 vl_len_; /* varlena header (do not touch directly!) */ + int int_option; /* for reloptions test purposes */ + double real_option; /* for reloptions test purposes */ + bool bool_option; /* for reloptions test purposes */ + int string_option_offset; /* for reloptions test purposes */ + int string_option2_offset; /* for reloptions test purposes */ +} DummyIndexOptions; + +extern void _PG_init(void); + +/* index access method interface functions */ +extern bool divalidate(Oid opclassoid); +extern bool diinsert(Relation index, Datum *values, bool *isnull, + ItemPointer ht_ctid, Relation heapRel, + IndexUniqueCheck checkUnique, + struct IndexInfo *indexInfo); +extern IndexScanDesc dibeginscan(Relation r, int nkeys, int norderbys); +extern void direscan(IndexScanDesc scan, ScanKey scankey, int nscankeys, + ScanKey orderbys, int norderbys); +extern void diendscan(IndexScanDesc scan); +extern IndexBuildResult *dibuild(Relation heap, Relation index, + struct IndexInfo *indexInfo); +extern void dibuildempty(Relation index); +extern IndexBulkDeleteResult *dibulkdelete(IndexVacuumInfo *info, + IndexBulkDeleteResult *stats, IndexBulkDeleteCallback callback, + void *callback_state); +extern IndexBulkDeleteResult *divacuumcleanup(IndexVacuumInfo *info, + IndexBulkDeleteResult *stats); +extern bytea *dioptions(Datum reloptions, bool validate); +extern void dicostestimate(PlannerInfo *root, IndexPath *path, + double loop_count, Cost *indexStartupCost, + Cost *indexTotalCost, Selectivity *indexSelectivity, + double *indexCorrelation, double *indexPages); + +/* direoptions.c */ +/* Functions and variables needed for reloptions tests*/ + +extern relopt_parse_elt di_relopt_tab[5]; +extern relopt_kind di_relopt_kind; + +extern void create_reloptions_table(void); +extern void create_reloptions_test_GUC(void); +extern void print_reloptions_test_output(Relation index); +extern void validate_string_option(const char *value); + +#endif diff --git a/src/test/modules/dummy_index_am/dummy_index_am--1.0.sql b/src/test/modules/dummy_index_am/dummy_index_am--1.0.sql new file mode 100644 index 0000000..8049c43 --- /dev/null +++ b/src/test/modules/dummy_index_am/dummy_index_am--1.0.sql @@ -0,0 +1,20 @@ +/* src/test/modules/dummy_index/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 am is access method for test purposes'; + +-- Opclasses + +CREATE OPERATOR CLASS int4_ops +DEFAULT FOR TYPE int4 USING dummy_index_am AS + OPERATOR 1 =(int4, int4), + FUNCTION 1 hashint4(int4); diff --git a/src/test/modules/dummy_index_am/dummy_index_am.control b/src/test/modules/dummy_index_am/dummy_index_am.control new file mode 100644 index 0000000..93fb57b --- /dev/null +++ b/src/test/modules/dummy_index_am/dummy_index_am.control @@ -0,0 +1,5 @@ +# dummy_index extension +comment = 'dummmy_index_am access method that does nothin and is used for test purposes' +default_version = '1.0' +module_pathname = '$libdir/dummy_index_am' +relocatable = true diff --git a/src/test/modules/dummy_index_am/expected/reloptions.out b/src/test/modules/dummy_index_am/expected/reloptions.out new file mode 100644 index 0000000..f80b2fc --- /dev/null +++ b/src/test/modules/dummy_index_am/expected/reloptions.out @@ -0,0 +1,97 @@ +CREATE EXTENSION dummy_index_am; +SET dummy_index.do_test_reloptions to true; +CREATE TABLE tst (i int4); +-- Test reloptions behavior when no reloption is set +CREATE INDEX test_idx ON tst USING dummy_index_am (i); +WARNING: No reloptions is set, default values will be chosen in module runtime +DROP INDEX test_idx; +-- Test behavior of int option (default and non default values) +SET dummy_index.do_test_reloption_int to true; +CREATE INDEX test_idx ON tst USING dummy_index_am (i) WITH (bool_option = false); +WARNING: int_option = 10 +DROP INDEX test_idx; +CREATE INDEX test_idx ON tst USING dummy_index_am (i) WITH (int_option = 5); +WARNING: int_option = 5 +ALTER INDEX test_idx SET (int_option = 3); +INSERT INTO tst VALUES(1); +WARNING: int_option = 3 +ALTER INDEX test_idx SET (bool_option = false); +ALTER INDEX test_idx RESET (int_option); +INSERT INTO tst VALUES(1); +WARNING: int_option = 10 +DROP INDEX test_idx; +SET dummy_index.do_test_reloption_int to false; +-- Test behavior of real option (default and non default values) +SET dummy_index.do_test_reloption_real to true; +CREATE INDEX test_idx ON tst USING dummy_index_am (i) WITH (bool_option = false); +WARNING: real_option = 3.141500 +DROP INDEX test_idx; +CREATE INDEX test_idx ON tst USING dummy_index_am (i) WITH (real_option = 5); +WARNING: real_option = 5.000000 +ALTER INDEX test_idx SET (real_option = 3); +INSERT INTO tst VALUES(1); +WARNING: real_option = 3.000000 +ALTER INDEX test_idx SET (bool_option = false); +ALTER INDEX test_idx RESET (real_option); +INSERT INTO tst VALUES(1); +WARNING: real_option = 3.141500 +DROP INDEX test_idx; +SET dummy_index.do_test_reloption_real to false; +-- Test behavior of bool option (default and non default values) +SET dummy_index.do_test_reloption_bool to true; +CREATE INDEX test_idx ON tst USING dummy_index_am (i) WITH (int_option = 5); +WARNING: bool_option = 1 +DROP INDEX test_idx; +CREATE INDEX test_idx ON tst USING dummy_index_am (i) WITH (bool_option = false); +WARNING: bool_option = 0 +ALTER INDEX test_idx SET (bool_option = true); +INSERT INTO tst VALUES(1); +WARNING: bool_option = 1 +ALTER INDEX test_idx SET (int_option = 5, bool_option = false); +ALTER INDEX test_idx RESET (bool_option); +INSERT INTO tst VALUES(1); +WARNING: bool_option = 1 +DROP INDEX test_idx; +SET dummy_index.do_test_reloption_bool to false; +-- Test behavior of string option (default and non default values + validate +-- function) +SET dummy_index.do_test_reloption_string to true; +CREATE INDEX test_idx ON tst USING dummy_index_am (i) WITH (int_option = 5); +WARNING: string_option = 'DefaultValue' +DROP INDEX test_idx; +CREATE INDEX test_idx ON tst USING dummy_index_am (i) WITH (string_option = +"Invalid_value"); +WARNING: Validating string option 'Invalid_value' +ERROR: This seems to be invalid value. Please set valid value +CREATE INDEX test_idx ON tst USING dummy_index_am (i) WITH (string_option = +"Valid_value"); +WARNING: Validating string option 'Valid_value' +WARNING: string_option = 'Valid_value' +ALTER INDEX test_idx SET (string_option = "Valid_value_2", int_option = 5); +WARNING: Validating string option 'Valid_value_2' +INSERT INTO tst VALUES(1); +WARNING: string_option = 'Valid_value_2' +ALTER INDEX test_idx RESET (string_option); +INSERT INTO tst VALUES(1); +WARNING: string_option = 'DefaultValue' +DROP INDEX test_idx; +SET dummy_index.do_test_reloption_string to false; +-- Test behavior of second string option +-- Testing default and non default values + _no_ validate function) +SET dummy_index.do_test_reloption_string2 to true; +CREATE INDEX test_idx ON tst USING dummy_index_am (i) WITH (string_option = +"Something"); +WARNING: string_option2 = 'SecondDefaultValue' +DROP INDEX test_idx; +CREATE INDEX test_idx ON tst USING dummy_index_am (i) WITH (string_option2 = +"Some_value"); +WARNING: string_option2 = 'Some_value' +ALTER INDEX test_idx SET (string_option2 = "Valid_value_2", int_option = 5); +INSERT INTO tst VALUES(1); +WARNING: string_option2 = 'Valid_value_2' +ALTER INDEX test_idx RESET (string_option2); +INSERT INTO tst VALUES(1); +WARNING: string_option2 = 'SecondDefaultValue' +DROP INDEX test_idx; +SET dummy_index.do_test_reloption_string2 to false; +SET dummy_index.do_test_reloptions to false; diff --git a/src/test/modules/dummy_index_am/sql/reloptions.sql b/src/test/modules/dummy_index_am/sql/reloptions.sql new file mode 100644 index 0000000..804a358 --- /dev/null +++ b/src/test/modules/dummy_index_am/sql/reloptions.sql @@ -0,0 +1,101 @@ +CREATE EXTENSION dummy_index_am; + +SET dummy_index.do_test_reloptions to true; + +CREATE TABLE tst (i int4); + +-- Test reloptions behavior when no reloption is set +CREATE INDEX test_idx ON tst USING dummy_index_am (i); +DROP INDEX test_idx; + +-- Test behavior of int option (default and non default values) +SET dummy_index.do_test_reloption_int to true; + +CREATE INDEX test_idx ON tst USING dummy_index_am (i) WITH (bool_option = false); +DROP INDEX test_idx; + +CREATE INDEX test_idx ON tst USING dummy_index_am (i) WITH (int_option = 5); + +ALTER INDEX test_idx SET (int_option = 3); +INSERT INTO tst VALUES(1); +ALTER INDEX test_idx SET (bool_option = false); +ALTER INDEX test_idx RESET (int_option); +INSERT INTO tst VALUES(1); + +DROP INDEX test_idx; +SET dummy_index.do_test_reloption_int to false; + +-- Test behavior of real option (default and non default values) +SET dummy_index.do_test_reloption_real to true; + +CREATE INDEX test_idx ON tst USING dummy_index_am (i) WITH (bool_option = false); +DROP INDEX test_idx; + +CREATE INDEX test_idx ON tst USING dummy_index_am (i) WITH (real_option = 5); + +ALTER INDEX test_idx SET (real_option = 3); +INSERT INTO tst VALUES(1); +ALTER INDEX test_idx SET (bool_option = false); +ALTER INDEX test_idx RESET (real_option); +INSERT INTO tst VALUES(1); + +DROP INDEX test_idx; +SET dummy_index.do_test_reloption_real to false; + +-- Test behavior of bool option (default and non default values) +SET dummy_index.do_test_reloption_bool to true; + +CREATE INDEX test_idx ON tst USING dummy_index_am (i) WITH (int_option = 5); +DROP INDEX test_idx; + +CREATE INDEX test_idx ON tst USING dummy_index_am (i) WITH (bool_option = false); + +ALTER INDEX test_idx SET (bool_option = true); +INSERT INTO tst VALUES(1); +ALTER INDEX test_idx SET (int_option = 5, bool_option = false); +ALTER INDEX test_idx RESET (bool_option); +INSERT INTO tst VALUES(1); + +DROP INDEX test_idx; +SET dummy_index.do_test_reloption_bool to false; + +-- Test behavior of string option (default and non default values + validate +-- function) +SET dummy_index.do_test_reloption_string to true; + +CREATE INDEX test_idx ON tst USING dummy_index_am (i) WITH (int_option = 5); +DROP INDEX test_idx; + +CREATE INDEX test_idx ON tst USING dummy_index_am (i) WITH (string_option = +"Invalid_value"); + +CREATE INDEX test_idx ON tst USING dummy_index_am (i) WITH (string_option = +"Valid_value"); + +ALTER INDEX test_idx SET (string_option = "Valid_value_2", int_option = 5); +INSERT INTO tst VALUES(1); +ALTER INDEX test_idx RESET (string_option); +INSERT INTO tst VALUES(1); + +DROP INDEX test_idx; +SET dummy_index.do_test_reloption_string to false; + +-- Test behavior of second string option +-- Testing default and non default values + _no_ validate function) +SET dummy_index.do_test_reloption_string2 to true; + +CREATE INDEX test_idx ON tst USING dummy_index_am (i) WITH (string_option = +"Something"); +DROP INDEX test_idx; + +CREATE INDEX test_idx ON tst USING dummy_index_am (i) WITH (string_option2 = +"Some_value"); + +ALTER INDEX test_idx SET (string_option2 = "Valid_value_2", int_option = 5); +INSERT INTO tst VALUES(1); +ALTER INDEX test_idx RESET (string_option2); +INSERT INTO tst VALUES(1); + +DROP INDEX test_idx; +SET dummy_index.do_test_reloption_string2 to false; +SET dummy_index.do_test_reloptions to false;