From a04c95bf53c31d7b2dfcfa260a28c9779c3ad746 Mon Sep 17 00:00:00 2001 From: Andrew Dunstan Date: Mon, 25 Nov 2024 15:28:12 -0500 Subject: [PATCH v20 01/16] [TEST] Add loadable modules as tests of the amapi If the index access method API meets the needs of future access methods, then surely it must at least meet the needs of present access methods. Copying and renaming hash and btree as "xash" and "xtree", respectively, those access methods should perform exactly the same as the in-core hash and btree methods. Alas, they do not. Running the standard in-core regression and isolation tests against these add-on index access methods fail in some notable ways. Rather than suffer the maintenance headaches of copying and slightly modifying the regression and isolation test suites, add a script to copy such files and insert "USING xtree" and "USING xash" clauses in the appropriate places. The regression tests fail after applying this patch. That's the point of the patch, not an oversight. To not be a burden, these modules are skipped during `make check-world`, and the directories are entirely omitted from the meson build system. --- src/include/access/hash.h | 3 +- src/test/modules/Makefile | 3 +- src/test/modules/xash/.gitignore | 5 + src/test/modules/xash/Makefile | 69 ++ src/test/modules/xash/access/xash.c | 82 ++ src/test/modules/xash/expected/.gitignore | 1 + .../xash/isolation/expected/.gitignore | 1 + .../modules/xash/isolation/specs/.gitignore | 1 + src/test/modules/xash/module.c | 43 ++ src/test/modules/xash/sql/.gitignore | 1 + src/test/modules/xash/t/.gitignore | 0 src/test/modules/xash/xash--1.0.sql | 406 ++++++++++ src/test/modules/xash/xash.conf | 1 + src/test/modules/xash/xash.control | 5 + src/test/modules/xtree/.gitignore | 5 + src/test/modules/xtree/Makefile | 69 ++ src/test/modules/xtree/access/xtree.c | 81 ++ src/test/modules/xtree/expected/.gitignore | 1 + .../xtree/isolation/expected/.gitignore | 1 + .../modules/xtree/isolation/specs/.gitignore | 1 + src/test/modules/xtree/module.c | 17 + src/test/modules/xtree/sql/.gitignore | 1 + src/test/modules/xtree/xtree--1.0.sql | 714 ++++++++++++++++++ src/test/modules/xtree/xtree.conf | 1 + src/test/modules/xtree/xtree.control | 5 + src/tools/clone_tests.pl | 449 +++++++++++ 26 files changed, 1963 insertions(+), 3 deletions(-) create mode 100644 src/test/modules/xash/.gitignore create mode 100644 src/test/modules/xash/Makefile create mode 100644 src/test/modules/xash/access/xash.c create mode 100644 src/test/modules/xash/expected/.gitignore create mode 100644 src/test/modules/xash/isolation/expected/.gitignore create mode 100644 src/test/modules/xash/isolation/specs/.gitignore create mode 100644 src/test/modules/xash/module.c create mode 100644 src/test/modules/xash/sql/.gitignore create mode 100644 src/test/modules/xash/t/.gitignore create mode 100644 src/test/modules/xash/xash--1.0.sql create mode 100644 src/test/modules/xash/xash.conf create mode 100644 src/test/modules/xash/xash.control create mode 100644 src/test/modules/xtree/.gitignore create mode 100644 src/test/modules/xtree/Makefile create mode 100644 src/test/modules/xtree/access/xtree.c create mode 100644 src/test/modules/xtree/expected/.gitignore create mode 100644 src/test/modules/xtree/isolation/expected/.gitignore create mode 100644 src/test/modules/xtree/isolation/specs/.gitignore create mode 100644 src/test/modules/xtree/module.c create mode 100644 src/test/modules/xtree/sql/.gitignore create mode 100644 src/test/modules/xtree/xtree--1.0.sql create mode 100644 src/test/modules/xtree/xtree.conf create mode 100644 src/test/modules/xtree/xtree.control create mode 100755 src/tools/clone_tests.pl diff --git a/src/include/access/hash.h b/src/include/access/hash.h index 073ad29b19b..305c2ffdc13 100644 --- a/src/include/access/hash.h +++ b/src/include/access/hash.h @@ -273,8 +273,7 @@ typedef struct HashOptions } HashOptions; #define HashGetFillFactor(relation) \ - (AssertMacro(relation->rd_rel->relkind == RELKIND_INDEX && \ - relation->rd_rel->relam == HASH_AM_OID), \ + (AssertMacro(relation->rd_rel->relkind == RELKIND_INDEX), \ (relation)->rd_options ? \ ((HashOptions *) (relation)->rd_options)->fillfactor : \ HASH_DEFAULT_FILLFACTOR) diff --git a/src/test/modules/Makefile b/src/test/modules/Makefile index 4e4be3fa511..114b04376ac 100644 --- a/src/test/modules/Makefile +++ b/src/test/modules/Makefile @@ -4,6 +4,8 @@ subdir = src/test/modules top_builddir = ../../.. include $(top_builddir)/src/Makefile.global +# Subdirectories "xash" and "xtree" are excluded from the list, to prevent +# `make check-world` from failing SUBDIRS = \ brin \ commit_ts \ @@ -43,7 +45,6 @@ SUBDIRS = \ worker_spi \ xid_wraparound - ifeq ($(enable_injection_points),yes) SUBDIRS += injection_points gin typcache else diff --git a/src/test/modules/xash/.gitignore b/src/test/modules/xash/.gitignore new file mode 100644 index 00000000000..eaf4d5699ed --- /dev/null +++ b/src/test/modules/xash/.gitignore @@ -0,0 +1,5 @@ +/log/ +/output_iso/ +/results/ +/tmp_check/ +/tmp_check_iso/ diff --git a/src/test/modules/xash/Makefile b/src/test/modules/xash/Makefile new file mode 100644 index 00000000000..e2c06d0e8f3 --- /dev/null +++ b/src/test/modules/xash/Makefile @@ -0,0 +1,69 @@ +# xash/Makefile + +REGRESS_SHLIB=$(abs_top_builddir)/src/test/regress/regress$(DLSUFFIX) +export REGRESS_SHLIB + +MODULE_big = xash +OBJS = $(WIN32RES) access/xash.o module.o + +EXTENSION = xash +DATA = xash--1.0.sql +PGFILEDESC = "test copy of hash" + +LDFLAGS_SL += $(filter -lm, $(LIBS)) + +# If the caller supplied a pklibdir, use that. The build system will supply +# this, and perhaps also folks making installcheck from pgxs, and maybe others. +# +ifdef pkglibdir +REGRESS_OPTS = --dlpath=$(pkglibdir) +else +REGRESS_OPTS = --dlpath=$(top_builddir)/src/test/regress +endif + +# The xash module does not supply its own regression tests. Instead, it copies +# regression tests from elsewhere in the project and changes hash indexes +# contained within those tests to xash instead. The tests to use are parsed +# from parallel_schedule and isolation_schedule, as below. +CLONE_SCRIPT=../../../tools/clone_tests.pl +REGRESS_BY_REFERENCE=$(shell $(PERL) $(CLONE_SCRIPT) --schedule=../../regress/parallel_schedule) +ISOLATION_BY_REFERENCE=$(shell $(PERL) $(CLONE_SCRIPT) --schedule=../../isolation/isolation_schedule) + +REGRESS_OPTS += --load-extension=xash +REGRESS_OPTS += --temp-config $(srcdir)/xash.conf +REGRESS = $(REGRESS_BY_REFERENCE) + +ISOLATION_OPTS = --load-extension=xash +ISOLATION_OPTS += --inputdir=isolation +ISOLATION_OPTS += --temp-config $(srcdir)/xash.conf +ISOLATION = $(ISOLATION_BY_REFERENCE) + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = src/test/modules/xash +top_builddir = ../../../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif + +$(OBJS): tests_by_reference + +.PHONY: tests_by_reference +tests_by_reference: + $(PERL) $(CLONE_SCRIPT) \ + --regress="$(REGRESS_BY_REFERENCE)" \ + --isolation="$(ISOLATION_BY_REFERENCE)" \ + --src_idx_am=hash \ + --dst_idx_am=xash \ + --src_sql=../../regress/sql \ + --src_expected=../../regress/expected \ + --dst_sql=./sql \ + --dst_expected=./expected \ + --src_spec=../../isolation/specs \ + --src_iso_expected=../../isolation/expected \ + --dst_spec=./isolation/specs \ + --dst_iso_expected=./isolation/expected \ + --datadir_prefix="/../../regress" diff --git a/src/test/modules/xash/access/xash.c b/src/test/modules/xash/access/xash.c new file mode 100644 index 00000000000..c1a8ffbe2d8 --- /dev/null +++ b/src/test/modules/xash/access/xash.c @@ -0,0 +1,82 @@ +/*------------------------------------------------------------------------- + * + * xash.c + * Implementation of an index AM by reference to Hash. + * + * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/test/modules/xash/access/xash.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include "access/hash.h" +#include "commands/vacuum.h" +#include "utils/index_selfuncs.h" + +/* + * Xash handler function: return IndexAmRoutine with access method parameters + * and callbacks. + */ +PG_FUNCTION_INFO_V1(xash_indexam_handler); +Datum +xash_indexam_handler(PG_FUNCTION_ARGS) +{ + IndexAmRoutine *amroutine = makeNode(IndexAmRoutine); + + amroutine->amstrategies = HTMaxStrategyNumber; + amroutine->amsupport = HASHNProcs; + amroutine->amoptsprocnum = HASHOPTIONS_PROC; + amroutine->amcanorder = false; + amroutine->amcanorderbyop = false; + amroutine->amcanbackward = true; + amroutine->amcanunique = false; + amroutine->amcanmulticol = false; + amroutine->amoptionalkey = false; + amroutine->amsearcharray = false; + amroutine->amsearchnulls = false; + amroutine->amstorage = false; + amroutine->amclusterable = false; + amroutine->ampredlocks = true; + amroutine->amcanparallel = false; + amroutine->amtranslatestrategy = hashtranslatestrategy; + amroutine->amtranslatecmptype = hashtranslatecmptype; + amroutine->amcanbuildparallel = false; + amroutine->amcaninclude = false; + amroutine->amusemaintenanceworkmem = false; + amroutine->amsummarizing = false; + amroutine->amparallelvacuumoptions = + VACUUM_OPTION_PARALLEL_BULKDEL; + amroutine->amkeytype = INT4OID; + + amroutine->ambuild = hashbuild; + amroutine->ambuildempty = hashbuildempty; + amroutine->aminsert = hashinsert; + amroutine->aminsertcleanup = NULL; + amroutine->ambulkdelete = hashbulkdelete; + amroutine->amvacuumcleanup = hashvacuumcleanup; + amroutine->amcanreturn = NULL; + amroutine->amcostestimate = hashcostestimate; + amroutine->amgettreeheight = NULL; + amroutine->amoptions = hashoptions; + amroutine->amproperty = NULL; + amroutine->ambuildphasename = NULL; + amroutine->amvalidate = hashvalidate; + amroutine->amadjustmembers = hashadjustmembers; + amroutine->ambeginscan = hashbeginscan; + amroutine->amrescan = hashrescan; + amroutine->amgettuple = hashgettuple; + amroutine->amgetbitmap = hashgetbitmap; + amroutine->amendscan = hashendscan; + amroutine->ammarkpos = NULL; + amroutine->amrestrpos = NULL; + amroutine->amestimateparallelscan = NULL; + amroutine->aminitparallelscan = NULL; + amroutine->amparallelrescan = NULL; + + PG_RETURN_POINTER(amroutine); +} diff --git a/src/test/modules/xash/expected/.gitignore b/src/test/modules/xash/expected/.gitignore new file mode 100644 index 00000000000..e87afd97c3b --- /dev/null +++ b/src/test/modules/xash/expected/.gitignore @@ -0,0 +1 @@ +/*.out diff --git a/src/test/modules/xash/isolation/expected/.gitignore b/src/test/modules/xash/isolation/expected/.gitignore new file mode 100644 index 00000000000..e87afd97c3b --- /dev/null +++ b/src/test/modules/xash/isolation/expected/.gitignore @@ -0,0 +1 @@ +/*.out diff --git a/src/test/modules/xash/isolation/specs/.gitignore b/src/test/modules/xash/isolation/specs/.gitignore new file mode 100644 index 00000000000..e9404350671 --- /dev/null +++ b/src/test/modules/xash/isolation/specs/.gitignore @@ -0,0 +1 @@ +/*.spec diff --git a/src/test/modules/xash/module.c b/src/test/modules/xash/module.c new file mode 100644 index 00000000000..30e19b94ec9 --- /dev/null +++ b/src/test/modules/xash/module.c @@ -0,0 +1,43 @@ +/*------------------------------------------------------------------------- + * + * module.c + * EnterpriseDB xash plugin. + * + * Portions Copyright (c) 2022, EnterpriseDB Corporation. All Rights Reserved. + * + * IDENTIFICATION + * xash/module.c + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include "fmgr.h" + +PG_MODULE_MAGIC; + +/*---- GUC variables ----*/ + + +/*---- Function declarations ----*/ + +void _PG_init(void); +void _PG_fini(void); + +/*---- Function definitions ----*/ + +/* + * Module load callback + */ +void +_PG_init(void) +{ +} + +/* + * Module unload callback + */ +void +_PG_fini(void) +{ +} diff --git a/src/test/modules/xash/sql/.gitignore b/src/test/modules/xash/sql/.gitignore new file mode 100644 index 00000000000..606aaaa1c26 --- /dev/null +++ b/src/test/modules/xash/sql/.gitignore @@ -0,0 +1 @@ +/*.sql diff --git a/src/test/modules/xash/t/.gitignore b/src/test/modules/xash/t/.gitignore new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/test/modules/xash/xash--1.0.sql b/src/test/modules/xash/xash--1.0.sql new file mode 100644 index 00000000000..4f69c104c08 --- /dev/null +++ b/src/test/modules/xash/xash--1.0.sql @@ -0,0 +1,406 @@ +/* xash/xash--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION xash" to load this file. \quit + +CREATE FUNCTION xash_indexam_handler(internal) +RETURNS index_am_handler +AS 'MODULE_PATHNAME' +LANGUAGE C; + +-- Access method +CREATE ACCESS METHOD xash TYPE INDEX HANDLER xash_indexam_handler; +COMMENT ON ACCESS METHOD xash IS 'test copy of hash'; + + +-- Operator families +CREATE OPERATOR FAMILY "array_ops" USING "xash"; + +CREATE OPERATOR FAMILY "bpchar_ops" USING "xash"; + +CREATE OPERATOR FAMILY "char_ops" USING "xash"; + +CREATE OPERATOR FAMILY "date_ops" USING "xash"; + +CREATE OPERATOR FAMILY "float_ops" USING "xash"; + +ALTER OPERATOR FAMILY "float_ops" USING "xash" ADD + OPERATOR 1 =("float4","float8"), + OPERATOR 1 =("float8","float4"); + + +CREATE OPERATOR FAMILY "network_ops" USING "xash"; + +CREATE OPERATOR FAMILY "integer_ops" USING "xash"; + +ALTER OPERATOR FAMILY "integer_ops" USING "xash" ADD + OPERATOR 1 =("int2","int4"), + OPERATOR 1 =("int2","int8"), + OPERATOR 1 =("int4","int2"), + OPERATOR 1 =("int4","int8"), + OPERATOR 1 =("int8","int2"), + OPERATOR 1 =("int8","int4"); + + +CREATE OPERATOR FAMILY "interval_ops" USING "xash"; + +CREATE OPERATOR FAMILY "macaddr_ops" USING "xash"; + +CREATE OPERATOR FAMILY "macaddr8_ops" USING "xash"; + +CREATE OPERATOR FAMILY "numeric_ops" USING "xash"; + +CREATE OPERATOR FAMILY "oid_ops" USING "xash"; + +CREATE OPERATOR FAMILY "oidvector_ops" USING "xash"; + +CREATE OPERATOR FAMILY "record_ops" USING "xash"; + +CREATE OPERATOR FAMILY "text_ops" USING "xash"; + +ALTER OPERATOR FAMILY "text_ops" USING "xash" ADD + OPERATOR 1 =("name","text"), + OPERATOR 1 =("text","name"); + + +CREATE OPERATOR FAMILY "time_ops" USING "xash"; + +CREATE OPERATOR FAMILY "timestamptz_ops" USING "xash"; + +CREATE OPERATOR FAMILY "timetz_ops" USING "xash"; + +CREATE OPERATOR FAMILY "timestamp_ops" USING "xash"; + +CREATE OPERATOR FAMILY "bool_ops" USING "xash"; + +CREATE OPERATOR FAMILY "bytea_ops" USING "xash"; + +CREATE OPERATOR FAMILY "xid_ops" USING "xash"; + +CREATE OPERATOR FAMILY "xid8_ops" USING "xash"; + +CREATE OPERATOR FAMILY "cid_ops" USING "xash"; + +CREATE OPERATOR FAMILY "tid_ops" USING "xash"; + +CREATE OPERATOR FAMILY "text_pattern_ops" USING "xash"; + +CREATE OPERATOR FAMILY "bpchar_pattern_ops" USING "xash"; + +CREATE OPERATOR FAMILY "aclitem_ops" USING "xash"; + +CREATE OPERATOR FAMILY "uuid_ops" USING "xash"; + +CREATE OPERATOR FAMILY "pg_lsn_ops" USING "xash"; + +CREATE OPERATOR FAMILY "enum_ops" USING "xash"; + +CREATE OPERATOR FAMILY "range_ops" USING "xash"; + +CREATE OPERATOR FAMILY "jsonb_ops" USING "xash"; + +CREATE OPERATOR FAMILY "multirange_ops" USING "xash"; + +-- Operator classes + +CREATE OPERATOR CLASS "array_ops" + DEFAULT FOR TYPE "anyarray" USING "xash" FAMILY "array_ops" AS + OPERATOR 1 =("anyarray","anyarray"), + FUNCTION 1 "hash_array", + FUNCTION 2 "hash_array_extended"; + + + +CREATE OPERATOR CLASS "bpchar_ops" + DEFAULT FOR TYPE "bpchar" USING "xash" FAMILY "bpchar_ops" AS + OPERATOR 1 =("bpchar","bpchar"), + FUNCTION 1 "hashbpchar", + FUNCTION 2 "hashbpcharextended"; + + + +CREATE OPERATOR CLASS "char_ops" + DEFAULT FOR TYPE "char" USING "xash" FAMILY "char_ops" AS + OPERATOR 1 =("char","char"), + FUNCTION 1 "hashchar", + FUNCTION 2 "hashcharextended"; + + + +CREATE OPERATOR CLASS "date_ops" + DEFAULT FOR TYPE "date" USING "xash" FAMILY "date_ops" AS + OPERATOR 1 =("date","date"), + FUNCTION 1 "hashint4", + FUNCTION 2 "hashint4extended"; + + + +CREATE OPERATOR CLASS "float4_ops" + DEFAULT FOR TYPE "float4" USING "xash" FAMILY "float_ops" AS + OPERATOR 1 =("float4","float4"), + FUNCTION 1 "hashfloat4", + FUNCTION 2 "hashfloat4extended"; + + + +CREATE OPERATOR CLASS "float8_ops" + DEFAULT FOR TYPE "float8" USING "xash" FAMILY "float_ops" AS + OPERATOR 1 =("float8","float8"), + FUNCTION 1 "hashfloat8", + FUNCTION 2 "hashfloat8extended"; + + + +CREATE OPERATOR CLASS "inet_ops" + DEFAULT FOR TYPE "inet" USING "xash" FAMILY "network_ops" AS + OPERATOR 1 =("inet","inet"), + FUNCTION 1 "hashinet", + FUNCTION 2 "hashinetextended"; + + + +CREATE OPERATOR CLASS "int2_ops" + DEFAULT FOR TYPE "int2" USING "xash" FAMILY "integer_ops" AS + OPERATOR 1 =("int2","int2"), + FUNCTION 1 "hashint2", + FUNCTION 2 "hashint2extended"; + + + +CREATE OPERATOR CLASS "int4_ops" + DEFAULT FOR TYPE "int4" USING "xash" FAMILY "integer_ops" AS + OPERATOR 1 =("int4","int4"), + FUNCTION 1 "hashint4", + FUNCTION 2 "hashint4extended"; + + + +CREATE OPERATOR CLASS "int8_ops" + DEFAULT FOR TYPE "int8" USING "xash" FAMILY "integer_ops" AS + OPERATOR 1 =("int8","int8"), + FUNCTION 1 "hashint8", + FUNCTION 2 "hashint8extended"; + + + +CREATE OPERATOR CLASS "interval_ops" + DEFAULT FOR TYPE "interval" USING "xash" FAMILY "interval_ops" AS + OPERATOR 1 =("interval","interval"), + FUNCTION 1 "interval_hash", + FUNCTION 2 "interval_hash_extended"; + + + +CREATE OPERATOR CLASS "macaddr_ops" + DEFAULT FOR TYPE "macaddr" USING "xash" FAMILY "macaddr_ops" AS + OPERATOR 1 =("macaddr","macaddr"), + FUNCTION 1 "hashmacaddr", + FUNCTION 2 "hashmacaddrextended"; + + + +CREATE OPERATOR CLASS "macaddr8_ops" + DEFAULT FOR TYPE "macaddr8" USING "xash" FAMILY "macaddr8_ops" AS + OPERATOR 1 =("macaddr8","macaddr8"), + FUNCTION 1 "hashmacaddr8", + FUNCTION 2 "hashmacaddr8extended"; + + + +CREATE OPERATOR CLASS "name_ops" + DEFAULT FOR TYPE "name" USING "xash" FAMILY "text_ops" AS + OPERATOR 1 =("name","name"), + FUNCTION 1 "hashname", + FUNCTION 2 "hashnameextended"; + + + +CREATE OPERATOR CLASS "numeric_ops" + DEFAULT FOR TYPE "numeric" USING "xash" FAMILY "numeric_ops" AS + OPERATOR 1 =("numeric","numeric"), + FUNCTION 1 "hash_numeric", + FUNCTION 2 "hash_numeric_extended"; + + + +CREATE OPERATOR CLASS "oid_ops" + DEFAULT FOR TYPE "oid" USING "xash" FAMILY "oid_ops" AS + OPERATOR 1 =("oid","oid"), + FUNCTION 1 "hashoid", + FUNCTION 2 "hashoidextended"; + + + +CREATE OPERATOR CLASS "oidvector_ops" + DEFAULT FOR TYPE "oidvector" USING "xash" FAMILY "oidvector_ops" AS + OPERATOR 1 =("oidvector","oidvector"), + FUNCTION 1 "hashoidvector", + FUNCTION 2 "hashoidvectorextended"; + + + +CREATE OPERATOR CLASS "record_ops" + DEFAULT FOR TYPE "record" USING "xash" FAMILY "record_ops" AS + OPERATOR 1 =("record","record"), + FUNCTION 1 "hash_record", + FUNCTION 2 "hash_record_extended"; + + + +CREATE OPERATOR CLASS "text_ops" + DEFAULT FOR TYPE "text" USING "xash" FAMILY "text_ops" AS + OPERATOR 1 =("text","text"), + FUNCTION 1 "hashtext", + FUNCTION 2 "hashtextextended"; + + + +CREATE OPERATOR CLASS "time_ops" + DEFAULT FOR TYPE "time" USING "xash" FAMILY "time_ops" AS + OPERATOR 1 =("time","time"), + FUNCTION 1 "time_hash", + FUNCTION 2 "time_hash_extended"; + + + +CREATE OPERATOR CLASS "timestamptz_ops" + DEFAULT FOR TYPE "timestamptz" USING "xash" FAMILY "timestamptz_ops" AS + OPERATOR 1 =("timestamptz","timestamptz"), + FUNCTION 1 "timestamp_hash", + FUNCTION 2 "timestamp_hash_extended"; + + + +CREATE OPERATOR CLASS "timetz_ops" + DEFAULT FOR TYPE "timetz" USING "xash" FAMILY "timetz_ops" AS + OPERATOR 1 =("timetz","timetz"), + FUNCTION 1 "timetz_hash", + FUNCTION 2 "timetz_hash_extended"; + + + +CREATE OPERATOR CLASS "timestamp_ops" + DEFAULT FOR TYPE "timestamp" USING "xash" FAMILY "timestamp_ops" AS + OPERATOR 1 =("timestamp","timestamp"), + FUNCTION 1 "timestamp_hash", + FUNCTION 2 "timestamp_hash_extended"; + + + +CREATE OPERATOR CLASS "bool_ops" + DEFAULT FOR TYPE "bool" USING "xash" FAMILY "bool_ops" AS + OPERATOR 1 =("bool","bool"), + FUNCTION 1 "hashchar", + FUNCTION 2 "hashcharextended"; + + + +CREATE OPERATOR CLASS "bytea_ops" + DEFAULT FOR TYPE "bytea" USING "xash" FAMILY "bytea_ops" AS + OPERATOR 1 =("bytea","bytea"), + FUNCTION 1 "hashvarlena", + FUNCTION 2 "hashvarlenaextended"; + + + +CREATE OPERATOR CLASS "xid_ops" + DEFAULT FOR TYPE "xid" USING "xash" FAMILY "xid_ops" AS + OPERATOR 1 =("xid","xid"), + FUNCTION 1 "hashint4", + FUNCTION 2 "hashint4extended"; + + + +CREATE OPERATOR CLASS "xid8_ops" + DEFAULT FOR TYPE "xid8" USING "xash" FAMILY "xid8_ops" AS + OPERATOR 1 =("xid8","xid8"), + FUNCTION 1 "hashint8", + FUNCTION 2 "hashint8extended"; + + + +CREATE OPERATOR CLASS "cid_ops" + DEFAULT FOR TYPE "cid" USING "xash" FAMILY "cid_ops" AS + OPERATOR 1 =("cid","cid"), + FUNCTION 1 "hashint4", + FUNCTION 2 "hashint4extended"; + + + +CREATE OPERATOR CLASS "tid_ops" + DEFAULT FOR TYPE "tid" USING "xash" FAMILY "tid_ops" AS + OPERATOR 1 =("tid","tid"), + FUNCTION 1 "hashtid", + FUNCTION 2 "hashtidextended"; + + + +CREATE OPERATOR CLASS "text_pattern_ops" + FOR TYPE "text" USING "xash" FAMILY "text_pattern_ops" AS + OPERATOR 1 =("text","text"), + FUNCTION 1 "hashtext", + FUNCTION 2 "hashtextextended"; + + + +CREATE OPERATOR CLASS "bpchar_pattern_ops" + FOR TYPE "bpchar" USING "xash" FAMILY "bpchar_pattern_ops" AS + OPERATOR 1 =("bpchar","bpchar"), + FUNCTION 1 "hashbpchar", + FUNCTION 2 "hashbpcharextended"; + + + +CREATE OPERATOR CLASS "aclitem_ops" + DEFAULT FOR TYPE "aclitem" USING "xash" FAMILY "aclitem_ops" AS + OPERATOR 1 =("aclitem","aclitem"), + FUNCTION 1 "hash_aclitem", + FUNCTION 2 "hash_aclitem_extended"; + + + +CREATE OPERATOR CLASS "uuid_ops" + DEFAULT FOR TYPE "uuid" USING "xash" FAMILY "uuid_ops" AS + OPERATOR 1 =("uuid","uuid"), + FUNCTION 1 "uuid_hash", + FUNCTION 2 "uuid_hash_extended"; + + + +CREATE OPERATOR CLASS "pg_lsn_ops" + DEFAULT FOR TYPE "pg_lsn" USING "xash" FAMILY "pg_lsn_ops" AS + OPERATOR 1 =("pg_lsn","pg_lsn"), + FUNCTION 1 "pg_lsn_hash", + FUNCTION 2 "pg_lsn_hash_extended"; + + + +CREATE OPERATOR CLASS "enum_ops" + DEFAULT FOR TYPE "anyenum" USING "xash" FAMILY "enum_ops" AS + OPERATOR 1 =("anyenum","anyenum"), + FUNCTION 1 "hashenum", + FUNCTION 2 "hashenumextended"; + + + +CREATE OPERATOR CLASS "range_ops" + DEFAULT FOR TYPE "anyrange" USING "xash" FAMILY "range_ops" AS + OPERATOR 1 =("anyrange","anyrange"), + FUNCTION 1 "hash_range", + FUNCTION 2 "hash_range_extended"; + + + +CREATE OPERATOR CLASS "multirange_ops" + DEFAULT FOR TYPE "anymultirange" USING "xash" FAMILY "multirange_ops" AS + OPERATOR 1 =("anymultirange","anymultirange"), + FUNCTION 1 "hash_multirange", + FUNCTION 2 "hash_multirange_extended"; + + + +CREATE OPERATOR CLASS "jsonb_ops" + DEFAULT FOR TYPE "jsonb" USING "xash" FAMILY "jsonb_ops" AS + OPERATOR 1 =("jsonb","jsonb"), + FUNCTION 1 "jsonb_hash", + FUNCTION 2 "jsonb_hash_extended"; diff --git a/src/test/modules/xash/xash.conf b/src/test/modules/xash/xash.conf new file mode 100644 index 00000000000..0b9f46dfb03 --- /dev/null +++ b/src/test/modules/xash/xash.conf @@ -0,0 +1 @@ +shared_preload_libraries = 'xash' diff --git a/src/test/modules/xash/xash.control b/src/test/modules/xash/xash.control new file mode 100644 index 00000000000..254fcb29144 --- /dev/null +++ b/src/test/modules/xash/xash.control @@ -0,0 +1,5 @@ +# xash extension +comment = 'test copy of hash' +default_version = '1.0' +module_pathname = '$libdir/xash' +relocatable = true diff --git a/src/test/modules/xtree/.gitignore b/src/test/modules/xtree/.gitignore new file mode 100644 index 00000000000..eaf4d5699ed --- /dev/null +++ b/src/test/modules/xtree/.gitignore @@ -0,0 +1,5 @@ +/log/ +/output_iso/ +/results/ +/tmp_check/ +/tmp_check_iso/ diff --git a/src/test/modules/xtree/Makefile b/src/test/modules/xtree/Makefile new file mode 100644 index 00000000000..da2ccbc2f8c --- /dev/null +++ b/src/test/modules/xtree/Makefile @@ -0,0 +1,69 @@ +# xtree/Makefile + +REGRESS_SHLIB=$(abs_top_builddir)/src/test/regress/regress$(DLSUFFIX) +export REGRESS_SHLIB + +MODULE_big = xtree +OBJS = $(WIN32RES) access/xtree.o module.o + +EXTENSION = xtree +DATA = xtree--1.0.sql +PGFILEDESC = "test copy of btree" + +LDFLAGS_SL += $(filter -lm, $(LIBS)) + +# If the caller supplied a pklibdir, use that. The build system will supply +# this, and perhaps also folks making installcheck from pgxs, and maybe others. +# +ifdef pkglibdir +REGRESS_OPTS = --dlpath=$(pkglibdir) +else +REGRESS_OPTS = --dlpath=$(top_builddir)/src/test/regress +endif + +# The xtree module does not supply its own regression tests. Instead, it copies +# regression tests from elsewhere in the project and changes hash indexes +# contained within those tests to xtree instead. The tests to use are parsed +# from parallel_schedule and isolation_schedule, as below. +CLONE_SCRIPT=../../../tools/clone_tests.pl +REGRESS_BY_REFERENCE=$(shell $(PERL) $(CLONE_SCRIPT) --schedule=../../regress/parallel_schedule) +ISOLATION_BY_REFERENCE=$(shell $(PERL) $(CLONE_SCRIPT) --schedule=../../isolation/isolation_schedule) + +REGRESS_OPTS += --load-extension=xtree +REGRESS_OPTS += --temp-config $(srcdir)/xtree.conf +REGRESS = $(REGRESS_BY_REFERENCE) + +ISOLATION_OPTS = --load-extension=xtree +ISOLATION_OPTS += --inputdir=isolation +ISOLATION_OPTS += --temp-config $(srcdir)/xtree.conf +ISOLATION = $(ISOLATION_BY_REFERENCE) + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = src/test/modules/xtree +top_builddir = ../../../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif + +$(OBJS): tests_by_reference + +.PHONY: tests_by_reference +tests_by_reference: + $(PERL) $(CLONE_SCRIPT) \ + --regress="$(REGRESS_BY_REFERENCE)" \ + --isolation="$(ISOLATION_BY_REFERENCE)" \ + --src_idx_am=btree \ + --dst_idx_am=xtree \ + --src_sql=../../regress/sql \ + --src_expected=../../regress/expected \ + --dst_sql=./sql \ + --dst_expected=./expected \ + --src_spec=../../isolation/specs \ + --src_iso_expected=../../isolation/expected \ + --dst_spec=./isolation/specs \ + --dst_iso_expected=./isolation/expected \ + --datadir_prefix="/../../regress" diff --git a/src/test/modules/xtree/access/xtree.c b/src/test/modules/xtree/access/xtree.c new file mode 100644 index 00000000000..9323a2809ae --- /dev/null +++ b/src/test/modules/xtree/access/xtree.c @@ -0,0 +1,81 @@ +/*------------------------------------------------------------------------- + * + * xtree.c + * Implementation of an index AM by reference to B-Tree. + * + * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/test/modules/xtree/access/xtree.c + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" +#include "access/nbtree.h" +#include "commands/vacuum.h" +#include "utils/index_selfuncs.h" + +/* + * Xtree handler function: return IndexAmRoutine with access method parameters + * and callbacks. + */ +PG_FUNCTION_INFO_V1(xtree_indexam_handler); +Datum +xtree_indexam_handler(PG_FUNCTION_ARGS) +{ + IndexAmRoutine *amroutine = makeNode(IndexAmRoutine); + + amroutine->amstrategies = BTMaxStrategyNumber; + amroutine->amsupport = BTNProcs; + amroutine->amoptsprocnum = BTOPTIONS_PROC; + amroutine->amcanorder = true; + amroutine->amcanorderbyop = false; + amroutine->amcanbackward = true; + amroutine->amcanunique = true; + amroutine->amcanmulticol = true; + amroutine->amoptionalkey = true; + amroutine->amsearcharray = true; + amroutine->amsearchnulls = true; + amroutine->amstorage = false; + amroutine->amclusterable = true; + amroutine->ampredlocks = true; + amroutine->amcanparallel = true; + amroutine->amtranslatestrategy = bttranslatestrategy; + amroutine->amtranslatecmptype = bttranslatecmptype; + amroutine->amcanbuildparallel = true; + amroutine->amcaninclude = true; + amroutine->amusemaintenanceworkmem = false; + amroutine->amsummarizing = false; + amroutine->amparallelvacuumoptions = + VACUUM_OPTION_PARALLEL_BULKDEL | VACUUM_OPTION_PARALLEL_COND_CLEANUP; + amroutine->amkeytype = InvalidOid; + + amroutine->ambuild = btbuild; + amroutine->ambuildempty = btbuildempty; + amroutine->aminsert = btinsert; + amroutine->aminsertcleanup = NULL; + amroutine->ambulkdelete = btbulkdelete; + amroutine->amvacuumcleanup = btvacuumcleanup; + amroutine->amcanreturn = btcanreturn; + amroutine->amcostestimate = btcostestimate; + amroutine->amgettreeheight = btgettreeheight; + amroutine->amoptions = btoptions; + amroutine->amproperty = btproperty; + amroutine->ambuildphasename = btbuildphasename; + amroutine->amvalidate = btvalidate; + amroutine->amadjustmembers = btadjustmembers; + amroutine->ambeginscan = btbeginscan; + amroutine->amrescan = btrescan; + amroutine->amgettuple = btgettuple; + amroutine->amgetbitmap = btgetbitmap; + amroutine->amendscan = btendscan; + amroutine->ammarkpos = btmarkpos; + amroutine->amrestrpos = btrestrpos; + amroutine->amestimateparallelscan = btestimateparallelscan; + amroutine->aminitparallelscan = btinitparallelscan; + amroutine->amparallelrescan = btparallelrescan; + + PG_RETURN_POINTER(amroutine); +} diff --git a/src/test/modules/xtree/expected/.gitignore b/src/test/modules/xtree/expected/.gitignore new file mode 100644 index 00000000000..e87afd97c3b --- /dev/null +++ b/src/test/modules/xtree/expected/.gitignore @@ -0,0 +1 @@ +/*.out diff --git a/src/test/modules/xtree/isolation/expected/.gitignore b/src/test/modules/xtree/isolation/expected/.gitignore new file mode 100644 index 00000000000..e87afd97c3b --- /dev/null +++ b/src/test/modules/xtree/isolation/expected/.gitignore @@ -0,0 +1 @@ +/*.out diff --git a/src/test/modules/xtree/isolation/specs/.gitignore b/src/test/modules/xtree/isolation/specs/.gitignore new file mode 100644 index 00000000000..e9404350671 --- /dev/null +++ b/src/test/modules/xtree/isolation/specs/.gitignore @@ -0,0 +1 @@ +/*.spec diff --git a/src/test/modules/xtree/module.c b/src/test/modules/xtree/module.c new file mode 100644 index 00000000000..b39aa22750e --- /dev/null +++ b/src/test/modules/xtree/module.c @@ -0,0 +1,17 @@ +/*------------------------------------------------------------------------- + * + * module.c + * EnterpriseDB xtree plugin. + * + * Portions Copyright (c) 2022, EnterpriseDB Corporation. All Rights Reserved. + * + * IDENTIFICATION + * xtree/module.c + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include "fmgr.h" + +PG_MODULE_MAGIC; diff --git a/src/test/modules/xtree/sql/.gitignore b/src/test/modules/xtree/sql/.gitignore new file mode 100644 index 00000000000..606aaaa1c26 --- /dev/null +++ b/src/test/modules/xtree/sql/.gitignore @@ -0,0 +1 @@ +/*.sql diff --git a/src/test/modules/xtree/xtree--1.0.sql b/src/test/modules/xtree/xtree--1.0.sql new file mode 100644 index 00000000000..f5f745ecea6 --- /dev/null +++ b/src/test/modules/xtree/xtree--1.0.sql @@ -0,0 +1,714 @@ +/* xtree/xtree--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION xtree" to load this file. \quit + +CREATE FUNCTION xtree_indexam_handler(internal) +RETURNS index_am_handler +AS 'MODULE_PATHNAME' +LANGUAGE C; + +-- Access method +CREATE ACCESS METHOD xtree TYPE INDEX HANDLER xtree_indexam_handler; +COMMENT ON ACCESS METHOD xtree IS 'test copy of btree'; + + +-- Operator families +CREATE OPERATOR FAMILY "array_ops" USING "xtree"; + +CREATE OPERATOR FAMILY "bit_ops" USING "xtree"; + +CREATE OPERATOR FAMILY "bool_ops" USING "xtree"; + +CREATE OPERATOR FAMILY "bpchar_ops" USING "xtree"; + +CREATE OPERATOR FAMILY "bytea_ops" USING "xtree"; + +CREATE OPERATOR FAMILY "char_ops" USING "xtree"; + +CREATE OPERATOR FAMILY "datetime_ops" USING "xtree"; + +ALTER OPERATOR FAMILY "datetime_ops" USING "xtree" ADD + OPERATOR 1 <("date","timestamp"), + OPERATOR 2 <=("date","timestamp"), + OPERATOR 3 =("date","timestamp"), + OPERATOR 4 >=("date","timestamp"), + OPERATOR 5 >("date","timestamp"), + OPERATOR 1 <("date","timestamptz"), + OPERATOR 2 <=("date","timestamptz"), + OPERATOR 3 =("date","timestamptz"), + OPERATOR 4 >=("date","timestamptz"), + OPERATOR 5 >("date","timestamptz"), + OPERATOR 1 <("timestamp","date"), + OPERATOR 2 <=("timestamp","date"), + OPERATOR 3 =("timestamp","date"), + OPERATOR 4 >=("timestamp","date"), + OPERATOR 5 >("timestamp","date"), + OPERATOR 1 <("timestamp","timestamptz"), + OPERATOR 2 <=("timestamp","timestamptz"), + OPERATOR 3 =("timestamp","timestamptz"), + OPERATOR 4 >=("timestamp","timestamptz"), + OPERATOR 5 >("timestamp","timestamptz"), + OPERATOR 1 <("timestamptz","date"), + OPERATOR 2 <=("timestamptz","date"), + OPERATOR 3 =("timestamptz","date"), + OPERATOR 4 >=("timestamptz","date"), + OPERATOR 5 >("timestamptz","date"), + OPERATOR 1 <("timestamptz","timestamp"), + OPERATOR 2 <=("timestamptz","timestamp"), + OPERATOR 3 =("timestamptz","timestamp"), + OPERATOR 4 >=("timestamptz","timestamp"), + OPERATOR 5 >("timestamptz","timestamp"), + FUNCTION 1 ("date", "timestamp") "date_cmp_timestamp", + FUNCTION 1 ("date", "timestamptz") "date_cmp_timestamptz", + FUNCTION 1 ("timestamp", "date") "timestamp_cmp_date", + FUNCTION 1 ("timestamp", "timestamptz") "timestamp_cmp_timestamptz", + FUNCTION 1 ("timestamptz", "date") "timestamptz_cmp_date", + FUNCTION 1 ("timestamptz", "timestamp") "timestamptz_cmp_timestamp", + FUNCTION 3 ("date", "interval") "in_range"("date","date","interval","bool","bool"), + FUNCTION 3 ("timestamp", "interval") "in_range"("timestamp","timestamp","interval","bool","bool"), + FUNCTION 3 ("timestamptz", "interval") "in_range"("timestamptz","timestamptz","interval","bool","bool"); + + +CREATE OPERATOR FAMILY "float_ops" USING "xtree"; + +ALTER OPERATOR FAMILY "float_ops" USING "xtree" ADD + OPERATOR 1 <("float4","float8"), + OPERATOR 2 <=("float4","float8"), + OPERATOR 3 =("float4","float8"), + OPERATOR 4 >=("float4","float8"), + OPERATOR 5 >("float4","float8"), + OPERATOR 1 <("float8","float4"), + OPERATOR 2 <=("float8","float4"), + OPERATOR 3 =("float8","float4"), + OPERATOR 4 >=("float8","float4"), + OPERATOR 5 >("float8","float4"), + FUNCTION 1 ("float4", "float8") "btfloat48cmp", + FUNCTION 1 ("float8", "float4") "btfloat84cmp", + FUNCTION 3 ("float4", "float8") "in_range"("float4","float4","float8","bool","bool"); + + +CREATE OPERATOR FAMILY "network_ops" USING "xtree"; + +CREATE OPERATOR FAMILY "integer_ops" USING "xtree"; + +ALTER OPERATOR FAMILY "integer_ops" USING "xtree" ADD + OPERATOR 1 <("int2","int4"), + OPERATOR 2 <=("int2","int4"), + OPERATOR 3 =("int2","int4"), + OPERATOR 4 >=("int2","int4"), + OPERATOR 5 >("int2","int4"), + OPERATOR 1 <("int2","int8"), + OPERATOR 2 <=("int2","int8"), + OPERATOR 3 =("int2","int8"), + OPERATOR 4 >=("int2","int8"), + OPERATOR 5 >("int2","int8"), + OPERATOR 1 <("int4","int2"), + OPERATOR 2 <=("int4","int2"), + OPERATOR 3 =("int4","int2"), + OPERATOR 4 >=("int4","int2"), + OPERATOR 5 >("int4","int2"), + OPERATOR 1 <("int4","int8"), + OPERATOR 2 <=("int4","int8"), + OPERATOR 3 =("int4","int8"), + OPERATOR 4 >=("int4","int8"), + OPERATOR 5 >("int4","int8"), + OPERATOR 1 <("int8","int2"), + OPERATOR 2 <=("int8","int2"), + OPERATOR 3 =("int8","int2"), + OPERATOR 4 >=("int8","int2"), + OPERATOR 5 >("int8","int2"), + OPERATOR 1 <("int8","int4"), + OPERATOR 2 <=("int8","int4"), + OPERATOR 3 =("int8","int4"), + OPERATOR 4 >=("int8","int4"), + OPERATOR 5 >("int8","int4"), + FUNCTION 1 ("int2", "int4") "btint24cmp", + FUNCTION 1 ("int2", "int8") "btint28cmp", + FUNCTION 3 ("int2", "int8") "in_range"("int2","int2","int8","bool","bool"), + FUNCTION 3 ("int2", "int4") "in_range"("int2","int2","int4","bool","bool"), + FUNCTION 1 ("int4", "int8") "btint48cmp", + FUNCTION 1 ("int4", "int2") "btint42cmp", + FUNCTION 3 ("int4", "int8") "in_range"("int4","int4","int8","bool","bool"), + FUNCTION 3 ("int4", "int2") "in_range"("int4","int4","int2","bool","bool"), + FUNCTION 1 ("int8", "int4") "btint84cmp", + FUNCTION 1 ("int8", "int2") "btint82cmp"; + + +CREATE OPERATOR FAMILY "interval_ops" USING "xtree"; + +CREATE OPERATOR FAMILY "macaddr_ops" USING "xtree"; + +CREATE OPERATOR FAMILY "macaddr8_ops" USING "xtree"; + +CREATE OPERATOR FAMILY "numeric_ops" USING "xtree"; + +CREATE OPERATOR FAMILY "oid_ops" USING "xtree"; + +CREATE OPERATOR FAMILY "oidvector_ops" USING "xtree"; + +CREATE OPERATOR FAMILY "record_ops" USING "xtree"; + +CREATE OPERATOR FAMILY "record_image_ops" USING "xtree"; + +CREATE OPERATOR FAMILY "text_ops" USING "xtree"; + +ALTER OPERATOR FAMILY "text_ops" USING "xtree" ADD + OPERATOR 1 <("name","text"), + OPERATOR 2 <=("name","text"), + OPERATOR 3 =("name","text"), + OPERATOR 4 >=("name","text"), + OPERATOR 5 >("name","text"), + OPERATOR 1 <("text","name"), + OPERATOR 2 <=("text","name"), + OPERATOR 3 =("text","name"), + OPERATOR 4 >=("text","name"), + OPERATOR 5 >("text","name"), + FUNCTION 1 ("name", "text") "btnametextcmp", + FUNCTION 1 ("text", "name") "bttextnamecmp"; + + +CREATE OPERATOR FAMILY "time_ops" USING "xtree"; + +ALTER OPERATOR FAMILY "time_ops" USING "xtree" ADD + FUNCTION 3 ("time", "interval") "in_range"("time","time","interval","bool","bool"); + + +CREATE OPERATOR FAMILY "timetz_ops" USING "xtree"; + +ALTER OPERATOR FAMILY "timetz_ops" USING "xtree" ADD + FUNCTION 3 ("timetz", "interval") "in_range"("timetz","timetz","interval","bool","bool"); + + +CREATE OPERATOR FAMILY "varbit_ops" USING "xtree"; + +CREATE OPERATOR FAMILY "text_pattern_ops" USING "xtree"; + +CREATE OPERATOR FAMILY "bpchar_pattern_ops" USING "xtree"; + +CREATE OPERATOR FAMILY "money_ops" USING "xtree"; + +CREATE OPERATOR FAMILY "tid_ops" USING "xtree"; + +CREATE OPERATOR FAMILY "xid8_ops" USING "xtree"; + +CREATE OPERATOR FAMILY "uuid_ops" USING "xtree"; + +CREATE OPERATOR FAMILY "pg_lsn_ops" USING "xtree"; + +CREATE OPERATOR FAMILY "enum_ops" USING "xtree"; + +CREATE OPERATOR FAMILY "tsvector_ops" USING "xtree"; + +CREATE OPERATOR FAMILY "tsquery_ops" USING "xtree"; + +CREATE OPERATOR FAMILY "range_ops" USING "xtree"; + +CREATE OPERATOR FAMILY "jsonb_ops" USING "xtree"; + +CREATE OPERATOR FAMILY "multirange_ops" USING "xtree"; + +-- Operator classes + +CREATE OPERATOR CLASS "array_ops" + DEFAULT FOR TYPE "anyarray" USING "xtree" FAMILY "array_ops" AS + OPERATOR 1 <("anyarray","anyarray"), + OPERATOR 2 <=("anyarray","anyarray"), + OPERATOR 3 =("anyarray","anyarray"), + OPERATOR 4 >=("anyarray","anyarray"), + OPERATOR 5 >("anyarray","anyarray"), + FUNCTION 1 "btarraycmp"; + + + +CREATE OPERATOR CLASS "bit_ops" + DEFAULT FOR TYPE "bit" USING "xtree" FAMILY "bit_ops" AS + OPERATOR 1 <("bit","bit"), + OPERATOR 2 <=("bit","bit"), + OPERATOR 3 =("bit","bit"), + OPERATOR 4 >=("bit","bit"), + OPERATOR 5 >("bit","bit"), + FUNCTION 1 "bitcmp", + FUNCTION 4 "btequalimage"; + + + +CREATE OPERATOR CLASS "bool_ops" + DEFAULT FOR TYPE "bool" USING "xtree" FAMILY "bool_ops" AS + OPERATOR 1 <("bool","bool"), + OPERATOR 2 <=("bool","bool"), + OPERATOR 3 =("bool","bool"), + OPERATOR 4 >=("bool","bool"), + OPERATOR 5 >("bool","bool"), + FUNCTION 1 "btboolcmp", + FUNCTION 4 "btequalimage"; + + + +CREATE OPERATOR CLASS "bpchar_ops" + DEFAULT FOR TYPE "bpchar" USING "xtree" FAMILY "bpchar_ops" AS + OPERATOR 1 <("bpchar","bpchar"), + OPERATOR 2 <=("bpchar","bpchar"), + OPERATOR 3 =("bpchar","bpchar"), + OPERATOR 4 >=("bpchar","bpchar"), + OPERATOR 5 >("bpchar","bpchar"), + FUNCTION 1 "bpcharcmp", + FUNCTION 2 "bpchar_sortsupport", + FUNCTION 4 "btvarstrequalimage"; + + + +CREATE OPERATOR CLASS "bytea_ops" + DEFAULT FOR TYPE "bytea" USING "xtree" FAMILY "bytea_ops" AS + OPERATOR 1 <("bytea","bytea"), + OPERATOR 2 <=("bytea","bytea"), + OPERATOR 3 =("bytea","bytea"), + OPERATOR 4 >=("bytea","bytea"), + OPERATOR 5 >("bytea","bytea"), + FUNCTION 1 "byteacmp", + FUNCTION 2 "bytea_sortsupport", + FUNCTION 4 "btequalimage"; + + + +CREATE OPERATOR CLASS "char_ops" + DEFAULT FOR TYPE "char" USING "xtree" FAMILY "char_ops" AS + OPERATOR 1 <("char","char"), + OPERATOR 2 <=("char","char"), + OPERATOR 3 =("char","char"), + OPERATOR 4 >=("char","char"), + OPERATOR 5 >("char","char"), + FUNCTION 1 "btcharcmp", + FUNCTION 4 "btequalimage"; + + + +CREATE OPERATOR CLASS "date_ops" + DEFAULT FOR TYPE "date" USING "xtree" FAMILY "datetime_ops" AS + OPERATOR 1 <("date","date"), + OPERATOR 2 <=("date","date"), + OPERATOR 3 =("date","date"), + OPERATOR 4 >=("date","date"), + OPERATOR 5 >("date","date"), + FUNCTION 1 "date_cmp", + FUNCTION 2 "date_sortsupport", + FUNCTION 4 "btequalimage"; + + + +CREATE OPERATOR CLASS "float4_ops" + DEFAULT FOR TYPE "float4" USING "xtree" FAMILY "float_ops" AS + OPERATOR 1 <("float4","float4"), + OPERATOR 2 <=("float4","float4"), + OPERATOR 3 =("float4","float4"), + OPERATOR 4 >=("float4","float4"), + OPERATOR 5 >("float4","float4"), + FUNCTION 1 "btfloat4cmp", + FUNCTION 2 "btfloat4sortsupport"; + + + +CREATE OPERATOR CLASS "float8_ops" + DEFAULT FOR TYPE "float8" USING "xtree" FAMILY "float_ops" AS + OPERATOR 1 <("float8","float8"), + OPERATOR 2 <=("float8","float8"), + OPERATOR 3 =("float8","float8"), + OPERATOR 4 >=("float8","float8"), + OPERATOR 5 >("float8","float8"), + FUNCTION 1 "btfloat8cmp", + FUNCTION 2 "btfloat8sortsupport", + FUNCTION 3 "in_range"("float8","float8","float8","bool","bool"); + + + +CREATE OPERATOR CLASS "inet_ops" + DEFAULT FOR TYPE "inet" USING "xtree" FAMILY "network_ops" AS + OPERATOR 1 <("inet","inet"), + OPERATOR 2 <=("inet","inet"), + OPERATOR 3 =("inet","inet"), + OPERATOR 4 >=("inet","inet"), + OPERATOR 5 >("inet","inet"), + FUNCTION 1 "network_cmp", + FUNCTION 2 "network_sortsupport", + FUNCTION 4 "btequalimage"; + + + +CREATE OPERATOR CLASS "int2_ops" + DEFAULT FOR TYPE "int2" USING "xtree" FAMILY "integer_ops" AS + OPERATOR 1 <("int2","int2"), + OPERATOR 2 <=("int2","int2"), + OPERATOR 3 =("int2","int2"), + OPERATOR 4 >=("int2","int2"), + OPERATOR 5 >("int2","int2"), + FUNCTION 1 "btint2cmp", + FUNCTION 2 "btint2sortsupport", + FUNCTION 4 "btequalimage", + FUNCTION 3 "in_range"("int2","int2","int2","bool","bool"); + + + +CREATE OPERATOR CLASS "int4_ops" + DEFAULT FOR TYPE "int4" USING "xtree" FAMILY "integer_ops" AS + OPERATOR 1 <("int4","int4"), + OPERATOR 2 <=("int4","int4"), + OPERATOR 3 =("int4","int4"), + OPERATOR 4 >=("int4","int4"), + OPERATOR 5 >("int4","int4"), + FUNCTION 1 "btint4cmp", + FUNCTION 2 "btint4sortsupport", + FUNCTION 4 "btequalimage", + FUNCTION 3 "in_range"("int4","int4","int4","bool","bool"); + + + +CREATE OPERATOR CLASS "int8_ops" + DEFAULT FOR TYPE "int8" USING "xtree" FAMILY "integer_ops" AS + OPERATOR 1 <("int8","int8"), + OPERATOR 2 <=("int8","int8"), + OPERATOR 3 =("int8","int8"), + OPERATOR 4 >=("int8","int8"), + OPERATOR 5 >("int8","int8"), + FUNCTION 1 "btint8cmp", + FUNCTION 2 "btint8sortsupport", + FUNCTION 4 "btequalimage", + FUNCTION 3 "in_range"("int8","int8","int8","bool","bool"); + + + +CREATE OPERATOR CLASS "interval_ops" + DEFAULT FOR TYPE "interval" USING "xtree" FAMILY "interval_ops" AS + OPERATOR 1 <("interval","interval"), + OPERATOR 2 <=("interval","interval"), + OPERATOR 3 =("interval","interval"), + OPERATOR 4 >=("interval","interval"), + OPERATOR 5 >("interval","interval"), + FUNCTION 1 "interval_cmp", + FUNCTION 3 "in_range"("interval","interval","interval","bool","bool"); + + + +CREATE OPERATOR CLASS "macaddr_ops" + DEFAULT FOR TYPE "macaddr" USING "xtree" FAMILY "macaddr_ops" AS + OPERATOR 1 <("macaddr","macaddr"), + OPERATOR 2 <=("macaddr","macaddr"), + OPERATOR 3 =("macaddr","macaddr"), + OPERATOR 4 >=("macaddr","macaddr"), + OPERATOR 5 >("macaddr","macaddr"), + FUNCTION 1 "macaddr_cmp", + FUNCTION 2 "macaddr_sortsupport", + FUNCTION 4 "btequalimage"; + + + +CREATE OPERATOR CLASS "macaddr8_ops" + DEFAULT FOR TYPE "macaddr8" USING "xtree" FAMILY "macaddr8_ops" AS + OPERATOR 1 <("macaddr8","macaddr8"), + OPERATOR 2 <=("macaddr8","macaddr8"), + OPERATOR 3 =("macaddr8","macaddr8"), + OPERATOR 4 >=("macaddr8","macaddr8"), + OPERATOR 5 >("macaddr8","macaddr8"), + FUNCTION 1 "macaddr8_cmp", + FUNCTION 4 "btequalimage"; + + + +CREATE OPERATOR CLASS "name_ops" + DEFAULT FOR TYPE "name" USING "xtree" FAMILY "text_ops" AS + OPERATOR 1 <("name","name"), + OPERATOR 2 <=("name","name"), + OPERATOR 3 =("name","name"), + OPERATOR 4 >=("name","name"), + OPERATOR 5 >("name","name"), + FUNCTION 1 "btnamecmp", + FUNCTION 2 "btnamesortsupport", + FUNCTION 4 "btvarstrequalimage"; + + + +CREATE OPERATOR CLASS "numeric_ops" + DEFAULT FOR TYPE "numeric" USING "xtree" FAMILY "numeric_ops" AS + OPERATOR 1 <("numeric","numeric"), + OPERATOR 2 <=("numeric","numeric"), + OPERATOR 3 =("numeric","numeric"), + OPERATOR 4 >=("numeric","numeric"), + OPERATOR 5 >("numeric","numeric"), + FUNCTION 1 "numeric_cmp", + FUNCTION 2 "numeric_sortsupport", + FUNCTION 3 "in_range"("numeric","numeric","numeric","bool","bool"); + + + +CREATE OPERATOR CLASS "oid_ops" + DEFAULT FOR TYPE "oid" USING "xtree" FAMILY "oid_ops" AS + OPERATOR 1 <("oid","oid"), + OPERATOR 2 <=("oid","oid"), + OPERATOR 3 =("oid","oid"), + OPERATOR 4 >=("oid","oid"), + OPERATOR 5 >("oid","oid"), + FUNCTION 1 "btoidcmp", + FUNCTION 2 "btoidsortsupport", + FUNCTION 4 "btequalimage"; + + + +CREATE OPERATOR CLASS "oidvector_ops" + DEFAULT FOR TYPE "oidvector" USING "xtree" FAMILY "oidvector_ops" AS + OPERATOR 1 <("oidvector","oidvector"), + OPERATOR 2 <=("oidvector","oidvector"), + OPERATOR 3 =("oidvector","oidvector"), + OPERATOR 4 >=("oidvector","oidvector"), + OPERATOR 5 >("oidvector","oidvector"), + FUNCTION 1 "btoidvectorcmp", + FUNCTION 4 "btequalimage"; + + + +CREATE OPERATOR CLASS "record_ops" + DEFAULT FOR TYPE "record" USING "xtree" FAMILY "record_ops" AS + OPERATOR 1 <("record","record"), + OPERATOR 2 <=("record","record"), + OPERATOR 3 =("record","record"), + OPERATOR 4 >=("record","record"), + OPERATOR 5 >("record","record"), + FUNCTION 1 "btrecordcmp"; + + + +CREATE OPERATOR CLASS "record_image_ops" + FOR TYPE "record" USING "xtree" FAMILY "record_image_ops" AS + OPERATOR 1 *<("record","record"), + OPERATOR 2 *<=("record","record"), + OPERATOR 3 *=("record","record"), + OPERATOR 4 *>=("record","record"), + OPERATOR 5 *>("record","record"), + FUNCTION 1 "btrecordimagecmp"; + + + +CREATE OPERATOR CLASS "text_ops" + DEFAULT FOR TYPE "text" USING "xtree" FAMILY "text_ops" AS + OPERATOR 1 <("text","text"), + OPERATOR 2 <=("text","text"), + OPERATOR 3 =("text","text"), + OPERATOR 4 >=("text","text"), + OPERATOR 5 >("text","text"), + FUNCTION 1 "bttextcmp", + FUNCTION 2 "bttextsortsupport", + FUNCTION 4 "btvarstrequalimage"; + + + +CREATE OPERATOR CLASS "time_ops" + DEFAULT FOR TYPE "time" USING "xtree" FAMILY "time_ops" AS + OPERATOR 1 <("time","time"), + OPERATOR 2 <=("time","time"), + OPERATOR 3 =("time","time"), + OPERATOR 4 >=("time","time"), + OPERATOR 5 >("time","time"), + FUNCTION 1 "time_cmp", + FUNCTION 4 "btequalimage"; + + + +CREATE OPERATOR CLASS "timestamptz_ops" + DEFAULT FOR TYPE "timestamptz" USING "xtree" FAMILY "datetime_ops" AS + OPERATOR 1 <("timestamptz","timestamptz"), + OPERATOR 2 <=("timestamptz","timestamptz"), + OPERATOR 3 =("timestamptz","timestamptz"), + OPERATOR 4 >=("timestamptz","timestamptz"), + OPERATOR 5 >("timestamptz","timestamptz"), + FUNCTION 1 "timestamptz_cmp", + FUNCTION 2 "timestamp_sortsupport", + FUNCTION 4 "btequalimage"; + + + +CREATE OPERATOR CLASS "timetz_ops" + DEFAULT FOR TYPE "timetz" USING "xtree" FAMILY "timetz_ops" AS + OPERATOR 1 <("timetz","timetz"), + OPERATOR 2 <=("timetz","timetz"), + OPERATOR 3 =("timetz","timetz"), + OPERATOR 4 >=("timetz","timetz"), + OPERATOR 5 >("timetz","timetz"), + FUNCTION 1 "timetz_cmp", + FUNCTION 4 "btequalimage"; + + + +CREATE OPERATOR CLASS "varbit_ops" + DEFAULT FOR TYPE "varbit" USING "xtree" FAMILY "varbit_ops" AS + OPERATOR 1 <("varbit","varbit"), + OPERATOR 2 <=("varbit","varbit"), + OPERATOR 3 =("varbit","varbit"), + OPERATOR 4 >=("varbit","varbit"), + OPERATOR 5 >("varbit","varbit"), + FUNCTION 1 "varbitcmp", + FUNCTION 4 "btequalimage"; + + + +CREATE OPERATOR CLASS "timestamp_ops" + DEFAULT FOR TYPE "timestamp" USING "xtree" FAMILY "datetime_ops" AS + OPERATOR 1 <("timestamp","timestamp"), + OPERATOR 2 <=("timestamp","timestamp"), + OPERATOR 3 =("timestamp","timestamp"), + OPERATOR 4 >=("timestamp","timestamp"), + OPERATOR 5 >("timestamp","timestamp"), + FUNCTION 1 "timestamp_cmp", + FUNCTION 2 "timestamp_sortsupport", + FUNCTION 4 "btequalimage"; + + + +CREATE OPERATOR CLASS "text_pattern_ops" + FOR TYPE "text" USING "xtree" FAMILY "text_pattern_ops" AS + OPERATOR 1 ~<~("text","text"), + OPERATOR 2 ~<=~("text","text"), + OPERATOR 3 =("text","text"), + OPERATOR 4 ~>=~("text","text"), + OPERATOR 5 ~>~("text","text"), + FUNCTION 1 "bttext_pattern_cmp", + FUNCTION 2 "bttext_pattern_sortsupport", + FUNCTION 4 "btequalimage"; + + + +CREATE OPERATOR CLASS "bpchar_pattern_ops" + FOR TYPE "bpchar" USING "xtree" FAMILY "bpchar_pattern_ops" AS + OPERATOR 1 ~<~("bpchar","bpchar"), + OPERATOR 2 ~<=~("bpchar","bpchar"), + OPERATOR 3 =("bpchar","bpchar"), + OPERATOR 4 ~>=~("bpchar","bpchar"), + OPERATOR 5 ~>~("bpchar","bpchar"), + FUNCTION 1 "btbpchar_pattern_cmp", + FUNCTION 2 "btbpchar_pattern_sortsupport", + FUNCTION 4 "btequalimage"; + + + +CREATE OPERATOR CLASS "money_ops" + DEFAULT FOR TYPE "money" USING "xtree" FAMILY "money_ops" AS + OPERATOR 1 <("money","money"), + OPERATOR 2 <=("money","money"), + OPERATOR 3 =("money","money"), + OPERATOR 4 >=("money","money"), + OPERATOR 5 >("money","money"), + FUNCTION 1 "cash_cmp", + FUNCTION 4 "btequalimage"; + + + +CREATE OPERATOR CLASS "tid_ops" + DEFAULT FOR TYPE "tid" USING "xtree" FAMILY "tid_ops" AS + OPERATOR 1 <("tid","tid"), + OPERATOR 2 <=("tid","tid"), + OPERATOR 3 =("tid","tid"), + OPERATOR 4 >=("tid","tid"), + OPERATOR 5 >("tid","tid"), + FUNCTION 1 "bttidcmp", + FUNCTION 4 "btequalimage"; + + + +CREATE OPERATOR CLASS "xid8_ops" + DEFAULT FOR TYPE "xid8" USING "xtree" FAMILY "xid8_ops" AS + OPERATOR 1 <("xid8","xid8"), + OPERATOR 2 <=("xid8","xid8"), + OPERATOR 3 =("xid8","xid8"), + OPERATOR 4 >=("xid8","xid8"), + OPERATOR 5 >("xid8","xid8"), + FUNCTION 1 "xid8cmp", + FUNCTION 4 "btequalimage"; + + + +CREATE OPERATOR CLASS "uuid_ops" + DEFAULT FOR TYPE "uuid" USING "xtree" FAMILY "uuid_ops" AS + OPERATOR 1 <("uuid","uuid"), + OPERATOR 2 <=("uuid","uuid"), + OPERATOR 3 =("uuid","uuid"), + OPERATOR 4 >=("uuid","uuid"), + OPERATOR 5 >("uuid","uuid"), + FUNCTION 1 "uuid_cmp", + FUNCTION 2 "uuid_sortsupport", + FUNCTION 4 "btequalimage"; + + + +CREATE OPERATOR CLASS "pg_lsn_ops" + DEFAULT FOR TYPE "pg_lsn" USING "xtree" FAMILY "pg_lsn_ops" AS + OPERATOR 1 <("pg_lsn","pg_lsn"), + OPERATOR 2 <=("pg_lsn","pg_lsn"), + OPERATOR 3 =("pg_lsn","pg_lsn"), + OPERATOR 4 >=("pg_lsn","pg_lsn"), + OPERATOR 5 >("pg_lsn","pg_lsn"), + FUNCTION 1 "pg_lsn_cmp", + FUNCTION 4 "btequalimage"; + + + +CREATE OPERATOR CLASS "enum_ops" + DEFAULT FOR TYPE "anyenum" USING "xtree" FAMILY "enum_ops" AS + OPERATOR 1 <("anyenum","anyenum"), + OPERATOR 2 <=("anyenum","anyenum"), + OPERATOR 3 =("anyenum","anyenum"), + OPERATOR 4 >=("anyenum","anyenum"), + OPERATOR 5 >("anyenum","anyenum"), + FUNCTION 1 "enum_cmp", + FUNCTION 4 "btequalimage"; + + + +CREATE OPERATOR CLASS "tsvector_ops" + DEFAULT FOR TYPE "tsvector" USING "xtree" FAMILY "tsvector_ops" AS + OPERATOR 1 <("tsvector","tsvector"), + OPERATOR 2 <=("tsvector","tsvector"), + OPERATOR 3 =("tsvector","tsvector"), + OPERATOR 4 >=("tsvector","tsvector"), + OPERATOR 5 >("tsvector","tsvector"), + FUNCTION 1 "tsvector_cmp"; + + + +CREATE OPERATOR CLASS "tsquery_ops" + DEFAULT FOR TYPE "tsquery" USING "xtree" FAMILY "tsquery_ops" AS + OPERATOR 1 <("tsquery","tsquery"), + OPERATOR 2 <=("tsquery","tsquery"), + OPERATOR 3 =("tsquery","tsquery"), + OPERATOR 4 >=("tsquery","tsquery"), + OPERATOR 5 >("tsquery","tsquery"), + FUNCTION 1 "tsquery_cmp"; + + + +CREATE OPERATOR CLASS "range_ops" + DEFAULT FOR TYPE "anyrange" USING "xtree" FAMILY "range_ops" AS + OPERATOR 1 <("anyrange","anyrange"), + OPERATOR 2 <=("anyrange","anyrange"), + OPERATOR 3 =("anyrange","anyrange"), + OPERATOR 4 >=("anyrange","anyrange"), + OPERATOR 5 >("anyrange","anyrange"), + FUNCTION 1 "range_cmp"; + + + +CREATE OPERATOR CLASS "multirange_ops" + DEFAULT FOR TYPE "anymultirange" USING "xtree" FAMILY "multirange_ops" AS + OPERATOR 1 <("anymultirange","anymultirange"), + OPERATOR 2 <=("anymultirange","anymultirange"), + OPERATOR 3 =("anymultirange","anymultirange"), + OPERATOR 4 >=("anymultirange","anymultirange"), + OPERATOR 5 >("anymultirange","anymultirange"), + FUNCTION 1 "multirange_cmp"; + + + +CREATE OPERATOR CLASS "jsonb_ops" + DEFAULT FOR TYPE "jsonb" USING "xtree" FAMILY "jsonb_ops" AS + OPERATOR 1 <("jsonb","jsonb"), + OPERATOR 2 <=("jsonb","jsonb"), + OPERATOR 3 =("jsonb","jsonb"), + OPERATOR 4 >=("jsonb","jsonb"), + OPERATOR 5 >("jsonb","jsonb"), + FUNCTION 1 "jsonb_cmp"; diff --git a/src/test/modules/xtree/xtree.conf b/src/test/modules/xtree/xtree.conf new file mode 100644 index 00000000000..5d990b84729 --- /dev/null +++ b/src/test/modules/xtree/xtree.conf @@ -0,0 +1 @@ +shared_preload_libraries = 'xtree' diff --git a/src/test/modules/xtree/xtree.control b/src/test/modules/xtree/xtree.control new file mode 100644 index 00000000000..0edd4b286d8 --- /dev/null +++ b/src/test/modules/xtree/xtree.control @@ -0,0 +1,5 @@ +# xtree extension +comment = 'test copy of btree' +default_version = '1.0' +module_pathname = '$libdir/xtree' +relocatable = true diff --git a/src/tools/clone_tests.pl b/src/tools/clone_tests.pl new file mode 100755 index 00000000000..c1c50ad90b0 --- /dev/null +++ b/src/tools/clone_tests.pl @@ -0,0 +1,449 @@ +# Make modified copies of regression tests from elsewhere in the source tree, +# for use in testing a loadable module. This copying mechanism saves us the +# bloat of committing the same regression tests in the modules as elsewhere. +# +# Copyright (c) 2000-2024, PostgreSQL Global Development Group + +=pod + +=head1 NAME + +clone_tests.pl - script for copying regression and isolation test files from +elsewhere in the postgresql source tree to a module, modifying the test to +exercise one or more table or index AMs provided by the module. + +=head1 SYNOPSIS + + copy_regression_test.pl \ + --src_idx_am=btree \ + --dst_idx_am=xtree \ + --schedule=../../regress/parallel_schedule + --regress=../../regress/sql + --datadir_prefix=/../../regress + + copy_regression_test.pl --schedule=../../regress/parallel_schedule + +=head1 OPTIONS + +=over + +=item --src_tbl_am + +=item --dst_tbl_am + +Optional argument pairs. Multiple pairs may be specified. + +The name of a table AM used (or potentially used) in the original test for +which we'd like to use a different table AM in the modified test. For each +src_tbl_am specified, there should be a dst_tbl_am also given, with the order +of the arguments determining which source maps to which destination. + +=item --src_idx_am + +=item --dst_idx_am + +Like src_tbl_am and dst_tbl_am, but for index AMs. + +=item --schedule + +A schedule file listing all regression or isolation tests. If given, a space +separated list of all tests, in order, will be printed on STDOUT. + +=item --regress + +=item --isolation + +A space separated list of regression or isolation tests to be processed, such +as the list returned by this script when handed a regression tests schedule +file via the C<--schedule> option. + +=item --src_sql + +=item --src_expected + +The directory path to read the regression tests' .sql and .out files. + +=item --src_spec + +=item --src_iso_expected + +The directory path to read the isolation tests' .sql and .out files. + + "dst_sql=s" => \$dst_sql, + "dst_iso_expected=s" => \$dst_iso_expected, + +=item --dst_sql + +=item --dst_expected + +The directory path to write the regression tests' modified .sql and .out files. + +=item --dst_spec + +=item --dst_iso_expected + +The directory path to write the isolation tests' modified .spec and .out files. + +=item --datadir_prefix + +A prefix to be prepended to paths of data files within the tests being +translated. For instace, to convert tests from C that +contain a snippet like: + +=over 4 + +\set filename :abs_srcdir '/data/hash.data' + +=back + +into a line in the resulting translated test like: + +=over 4 + +\set filename :abs_srcdir '/../../regress/data/hash.data' + +=back + +provide the argument C<--datadir_prefix="/../../regress">. + +=back + +=cut + +use strict; +# use warnings FATAL => 'all'; +use IO::File; +use Getopt::Long; +use FindBin; +use lib "$FindBin::RealBin/../perl/"; + +sub push_path +{ + my ($aryref, $option_name, $path) = @_; + die "$option_name: No such file: $path" unless -f $path; + push (@$aryref, $path); +} + +sub require_equal_length_arrays +{ + my ($ary1, $ary2, $name) = @_; + die "different number of src_$name and dst_$name arguments given" + unless(scalar(@$ary1) == scalar(@$ary2)); +} + + + +my (@src_tbl_am, + @src_idx_am, + @src_regress, + @src_expected, + @src_spec, + @src_output_iso, + @dst_tbl_am, + @dst_idx_am, + @dst_regress, + @dst_expected, + @dst_spec, + @dst_output_iso, + @schedule, + $regress, + $src_sql, + $src_expected, + $dst_sql, + $dst_expected, + $isolation, + $src_spec, + $src_iso_expected, + $dst_spec, + $dst_iso_expected, + $datadir_prefix); +GetOptions( + "src_tbl_am=s" => \@src_tbl_am, + "src_idx_am=s" => \@src_idx_am, + "dst_tbl_am=s" => \@dst_tbl_am, + "dst_idx_am=s" => \@dst_idx_am, + "schedule=s" => \@schedule, + "regress=s" => \$regress, + "src_sql=s" => \$src_sql, + "src_expected=s" => \$src_expected, + "dst_sql=s" => \$dst_sql, + "dst_expected=s" => \$dst_expected, + "isolation=s" => \$isolation, + "src_spec=s" => \$src_spec, + "src_iso_expected=s" => \$src_iso_expected, + "dst_spec=s" => \$dst_spec, + "dst_iso_expected=s" => \$dst_iso_expected, + "datadir_prefix=s" => \$datadir_prefix, + ); + +my @regress = grep /\w+/, split(/\s+/, $regress); +foreach my $regress (@regress) +{ + push (@src_regress, "$src_sql/$regress.sql"); + push (@dst_regress, "$dst_sql/$regress.sql"); + push (@src_expected, "$src_expected/$regress.out"); + push (@dst_expected, "$dst_expected/$regress.out"); +} +my @isolation = grep /\w+/, split(/\s+/, $isolation); +foreach my $isolation (@isolation) +{ + push (@src_spec, "$src_spec/$isolation.spec"); + push (@dst_spec, "$dst_spec/$isolation.spec"); + push (@src_output_iso, "$src_iso_expected/$isolation.out"); + push (@dst_output_iso, "$dst_iso_expected/$isolation.out"); +} +require_equal_length_arrays(\@src_tbl_am, \@dst_tbl_am, "tbl_am"); +require_equal_length_arrays(\@src_idx_am, \@dst_idx_am, "idx_am"); + +# First, define some regular expressions that make copying and modifying random +# code more robust. +# + +# Compiled regular expression for matching a single character (or escaped char) +# within a quote except one that ends the quote +our $quotecharre; +$quotecharre = qr{ + (?: + '' # double single-quote, does not close + | + (?> [^']) # Non-closing singlequote, without backtracking + | + (?>\\') # backslash escaped single-quote, without backtracking + ) + }msx; + +# Compiled regular expression for matching a SQL quoted string +our $quotere; +$quotere = qr{ + (?: + ' # Begin quote + $quotecharre* # Any number of characters within the quote + ' # End quote + ) + }msx; + + + +# Compiled regular expression for matching a code snippet that is balanced +# relative to (), [], {} pairings, while not being fooled by unbalanced +# snippets if they are within a single-quoted string. +our $balancedre; +$balancedre = qr{( + (?: + # A quote, which might include unbalanced + # parens/brackets/braces + (?> $quotere ) + | + # non-special characters, no backtracking + (?> [^(){}\[\]]+ ) + | + \( # begin balanced parens + (?-1) # ... recurse + \) # end balanced parens + | + \[ # begin balanced brackets + (?-1) # ... recurse + \] # end balanced brackets + | + \{ # begin balanced braces + (?-1) # ... recurse + \} # end balanced braces + )* + )}xms; + +our $unqualifiednamere = qr/\b\w+\b/; +our $qualifiednamere = qr/\b\w+(?:\.\w+\b)?/; + +sub convert_indexes_to_use_am +{ + my ($code, $srcam, $dstam) = @_; + + # If the srcam is btree, then we need to modify CREATE INDEX statments that + # say "USING btree" but also ones that omit a USING clause entirely. For + # all other srcam, we look for an explicit "USING srcam". + my $using_srcam_re; + if (lc($srcam) eq 'btree') + { + $using_srcam_re = qr{ + # Optionally, an explicit USING clause + (?: USING \s+ $srcam )? + }msix; + } + else + { + $using_srcam_re = qr{ + # Mandatory explicit USING clause + (?: USING \s+ $srcam ) + # No alternative + }msix; + } + + $code =~ s{ ( # Begin capture of \$1 + CREATE + \s+ + (?: UNIQUE \s+ )? + INDEX + \s+ + (?: CONCURRENTLY \s+ )? + (?: + (?!CONCURRENTLY) # Don't match "concurrently" as a name + $unqualifiednamere # Index name is optional + \s+ + )? + ON + \s+ + $qualifiednamere + ) # End capture of \$1 + \s* + $using_srcam_re + ( # Begin capture of \$2 + \s* + \( + ) # End capture of \$2 + } + {$1 USING $dstam $2}msigx; + + return $code; +} + +sub convert_tables_to_use_am +{ + my ($code, $srcam, $dstam) = @_; + + # If the srcam is heap, then we need to modify CREATE TABLE statments that + # say "USING heap" but also ones that omit a USING clause entirely. For + # all other srcam, we look for an explicit "USING srcam". + my $using_srcam_re; + if (lc($srcam) eq 'heap') + { + $using_srcam_re = qr{ + # Optionally, an explicit USING clause + (?: USING \s+ $srcam )? + }msix; + } + else + { + $using_srcam_re = qr{ + # Mandatory explicit USING clause + (?: USING \s+ $srcam ) + # No alternative + }msix; + } + + # We don't need to capture the entire CREATE TABLE statement. We just need + # the prefix up to where the optional USING clause belongs, so that we can + # add or replace with our own USING $dstam clause. + # + # We're not worried about whether the CREATE TABLE statement that we + # capture is syntactically correct, so long as we don't break valid syntax + # with our replacement. If the test we modify has an intentionally invalid + # syntax, we still want to insert our "USING $dstam" clause, so long as we + # can reasonably determine where to do so. + $code =~ s{ ( # Begin capture of \$1 + CREATE + \s+ + (?: (?: TEMPORARY | TEMP ) \s+ )? + (?: UNLOGGED \s+ )? + TABLE + \s+ + (?: IF \s+ NOT \s+ EXISTS \s+ )? + (?! IF ) # Don't match "if" as the qualified name + $qualifiednamere \s* + (?: OF \s+ $qualifiednamere \s* )? + (?: PARTITION \s+ OF \s+ $qualifiednamere \s* )? + \( $balancedre \) \s* + (?: FOR \s+ VALUES \s+ (?:IN|FROM|TO|WITH) \s* \( $balancedre \) \s* )? + (?: INHERITS \s* \( $balancedre \) \s* )? + (?: PARTITION \s+ BY \s+ (?:RANGE|LIST|HASH) \s+ \( $balancedre \) \s* )? + ) # End capture of \$1 + $using_srcam_re + } + {$1 USING $dstam }msigx; + + return $code; +} + +sub convert_expected_output +{ + my ($code, $srcam, $dstam) = @_; + $srcam = lc($srcam); + $dstam = lc($dstam); + + # Convert anticipated error which includes the index AM in the error message + $code =~ s{ERROR: access method "$srcam" does not support included columns} + {ERROR: access method "$dstam" does not support included columns}g; + + # Convert \d table output that embeds the index AM name in the output + $code =~ s{("$unqualifiednamere")(?: UNIQUE,)? $srcam(?= \($balancedre\))}{$1 $dstam}g; + + return $code; +} + +sub convert_code +{ + my ($input, $output) = @_; + + my $code = slurp($input); + for (my $i = 0; $i < scalar(@src_tbl_am); $i++) + { + $code = convert_tables_to_use_am($code, $src_tbl_am[$i], $dst_tbl_am[$i]); + $code = convert_expected_output($code, $src_tbl_am[$i], $dst_tbl_am[$i]); + } + for (my $i = 0; $i < scalar(@src_idx_am); $i++) + { + $code = convert_indexes_to_use_am($code, $src_idx_am[$i], $dst_idx_am[$i]); + $code = convert_expected_output($code, $src_idx_am[$i], $dst_idx_am[$i]); + } + if (defined $datadir_prefix) + { + $code =~ s{(?=/data/\w+\.data)}{$datadir_prefix}g; + } + spew($output, $code); +} + +sub slurp +{ + my ($path) = @_; + my $fh = IO::File->new($path) or die "Cannot read $path: $!"; + my $results; + { + undef(local $/); + $results = <$fh>; + } + $fh->close(); + return $results; +} + +sub spew +{ + my ($path, $contents) = @_; + my $fh = IO::File->new(">$path") or die "Cannot write $path: $!"; + $fh->print($contents); + $fh->close(); +} + +# Handle user supplied arguments for translating tests, and/or the arguments for +# parsing a regression or isolation schedule file. At present, the build system +# never invokes this script to do both together, but if that ever changes, we assume +# the order we do them in doesn't matter. +# + +# First, translate the tests, if requested... +convert_code($src_regress[$_], $dst_regress[$_]) for (0..$#src_regress); +convert_code($src_expected[$_], $dst_expected[$_]) for (0..$#src_expected); +convert_code($src_spec[$_], $dst_spec[$_]) for (0..$#src_spec); +convert_code($src_output_iso[$_], $dst_output_iso[$_]) for (0..$#src_output_iso); + +# Then, parse the schedule files, if requested... +my $schedule = ""; +foreach my $path (@schedule) +{ + my $code = slurp($path); + while ($code =~ m/^test:(.*)$/mg) + { + $schedule .= $1; + } +} + +# The build system reads the schedule from our stdout... +print($schedule, "\n"); base-commit: 363a6e8c6fcf9f3e19fe673ae02554645974a388 -- 2.48.1