From 8ce3aa9b5914d1ac45ed3f9bc484f66b3c4850c7 Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Wed, 25 Dec 2019 10:23:39 +0900 Subject: Rename files and headers related to index AM The following renaming is done so as source files related to index access methods are more consistent with table access methods (the original names used for index AMs ware too generic, and could be confused as including features related to table AMs): - amapi.h -> indexam.h. - amapi.c -> indexamapi.c. Here we have an equivalent with backend/access/table/tableamapi.c. - amvalidate.c -> indexamvalidate.c. - amvalidate.h -> indexamvalidate.h. - genam.c -> indexgenam.c. - genam.h -> indexgenam.h. This has been discussed during the development of v12 when table AM was worked on, but the renaming never happened. Author: Michael Paquier Reviewed-by: Fabien Coelho, Julien Rouhaud Discussion: https://postgr.es/m/20191223053434.GF34339@paquier.xyz --- contrib/bloom/blinsert.c | 2 +- contrib/bloom/bloom.h | 2 +- contrib/bloom/blutils.c | 2 +- contrib/bloom/blvacuum.c | 2 +- contrib/bloom/blvalidate.c | 2 +- contrib/sepgsql/database.c | 2 +- contrib/sepgsql/label.c | 2 +- contrib/sepgsql/proc.c | 2 +- contrib/sepgsql/relation.c | 2 +- contrib/sepgsql/schema.c | 2 +- src/backend/access/brin/brin_inclusion.c | 2 +- src/backend/access/brin/brin_minmax.c | 2 +- src/backend/access/brin/brin_validate.c | 2 +- src/backend/access/common/detoast.c | 2 +- src/backend/access/common/toast_internals.c | 2 +- src/backend/access/gin/ginvalidate.c | 2 +- src/backend/access/gist/gistbuild.c | 2 +- src/backend/access/gist/gistbuildbuffers.c | 2 +- src/backend/access/gist/gistget.c | 2 +- src/backend/access/gist/gistvacuum.c | 2 +- src/backend/access/gist/gistvalidate.c | 2 +- src/backend/access/hash/hashvalidate.c | 2 +- src/backend/access/heap/heapam.c | 2 +- src/backend/access/heap/heapam_handler.c | 2 +- src/backend/access/heap/vacuumlazy.c | 2 +- src/backend/access/index/Makefile | 8 +- src/backend/access/index/amapi.c | 143 ----- src/backend/access/index/amvalidate.c | 246 --------- src/backend/access/index/genam.c | 662 ----------------------- src/backend/access/index/indexam.c | 2 +- src/backend/access/index/indexamapi.c | 143 +++++ src/backend/access/index/indexamvalidate.c | 246 +++++++++ src/backend/access/index/indexgenam.c | 662 +++++++++++++++++++++++ src/backend/access/nbtree/nbtvalidate.c | 2 +- src/backend/access/spgist/spgdoinsert.c | 2 +- src/backend/access/spgist/spginsert.c | 2 +- src/backend/access/spgist/spgscan.c | 2 +- src/backend/access/spgist/spgutils.c | 2 +- src/backend/access/spgist/spgvacuum.c | 2 +- src/backend/access/spgist/spgvalidate.c | 2 +- src/backend/bootstrap/bootstrap.c | 2 +- src/backend/catalog/aclchk.c | 2 +- src/backend/catalog/catalog.c | 2 +- src/backend/catalog/dependency.c | 2 +- src/backend/catalog/heap.c | 2 +- src/backend/catalog/index.c | 2 +- src/backend/catalog/indexing.c | 2 +- src/backend/catalog/objectaddress.c | 2 +- src/backend/catalog/partition.c | 2 +- src/backend/catalog/pg_collation.c | 2 +- src/backend/catalog/pg_constraint.c | 2 +- src/backend/catalog/pg_db_role_setting.c | 2 +- src/backend/catalog/pg_depend.c | 2 +- src/backend/catalog/pg_enum.c | 2 +- src/backend/catalog/pg_inherits.c | 2 +- src/backend/catalog/pg_largeobject.c | 2 +- src/backend/catalog/pg_publication.c | 2 +- src/backend/catalog/pg_range.c | 2 +- src/backend/catalog/pg_shdepend.c | 2 +- src/backend/catalog/pg_subscription.c | 2 +- src/backend/commands/analyze.c | 2 +- src/backend/commands/cluster.c | 2 +- src/backend/commands/comment.c | 2 +- src/backend/commands/constraint.c | 2 +- src/backend/commands/dbcommands.c | 2 +- src/backend/commands/extension.c | 2 +- src/backend/commands/functioncmds.c | 2 +- src/backend/commands/indexcmds.c | 2 +- src/backend/commands/matview.c | 2 +- src/backend/commands/opclasscmds.c | 2 +- src/backend/commands/policy.c | 2 +- src/backend/commands/proclang.c | 2 +- src/backend/commands/publicationcmds.c | 2 +- src/backend/commands/seclabel.c | 2 +- src/backend/commands/tablecmds.c | 2 +- src/backend/commands/trigger.c | 2 +- src/backend/commands/tsearchcmds.c | 2 +- src/backend/commands/typecmds.c | 2 +- src/backend/commands/user.c | 2 +- src/backend/commands/vacuum.c | 2 +- src/backend/executor/execAmi.c | 2 +- src/backend/executor/execCurrent.c | 2 +- src/backend/executor/execIndexing.c | 2 +- src/backend/executor/execReplication.c | 2 +- src/backend/executor/nodeBitmapIndexscan.c | 2 +- src/backend/executor/nodeIndexonlyscan.c | 2 +- src/backend/optimizer/path/costsize.c | 4 +- src/backend/optimizer/plan/planner.c | 2 +- src/backend/optimizer/util/plancat.c | 2 +- src/backend/parser/parse_utilcmd.c | 2 +- src/backend/partitioning/partdesc.c | 2 +- src/backend/replication/logical/origin.c | 2 +- src/backend/rewrite/rewriteRemove.c | 2 +- src/backend/statistics/extended_stats.c | 2 +- src/backend/storage/large_object/inv_api.c | 2 +- src/backend/utils/adt/amutils.c | 2 +- src/backend/utils/adt/enum.c | 2 +- src/backend/utils/adt/ruleutils.c | 2 +- src/backend/utils/cache/catcache.c | 2 +- src/backend/utils/cache/evtcache.c | 2 +- src/backend/utils/cache/relfilenodemap.c | 2 +- src/backend/utils/cache/ts_cache.c | 2 +- src/backend/utils/init/postinit.c | 2 +- src/include/access/amapi.h | 240 -------- src/include/access/amvalidate.h | 36 -- src/include/access/brin_internal.h | 2 +- src/include/access/genam.h | 225 -------- src/include/access/gin_private.h | 2 +- src/include/access/gist_private.h | 4 +- src/include/access/gistscan.h | 2 +- src/include/access/hash.h | 2 +- src/include/access/indexam.h | 240 ++++++++ src/include/access/indexamvalidate.h | 36 ++ src/include/access/indexgenam.h | 225 ++++++++ src/include/access/nbtree.h | 2 +- src/include/access/reloptions.h | 2 +- src/include/access/spgist.h | 2 +- src/include/executor/nodeIndexscan.h | 2 +- src/include/nodes/nodes.h | 2 +- src/include/nodes/pathnodes.h | 2 +- src/include/utils/index_selfuncs.h | 4 +- src/include/utils/rel.h | 2 +- src/test/modules/dummy_index_am/dummy_index_am.c | 2 +- 123 files changed, 1669 insertions(+), 1669 deletions(-) delete mode 100644 src/backend/access/index/amapi.c delete mode 100644 src/backend/access/index/amvalidate.c delete mode 100644 src/backend/access/index/genam.c create mode 100644 src/backend/access/index/indexamapi.c create mode 100644 src/backend/access/index/indexamvalidate.c create mode 100644 src/backend/access/index/indexgenam.c delete mode 100644 src/include/access/amapi.h delete mode 100644 src/include/access/amvalidate.h delete mode 100644 src/include/access/genam.h create mode 100644 src/include/access/indexam.h create mode 100644 src/include/access/indexamvalidate.h create mode 100644 src/include/access/indexgenam.h diff --git a/contrib/bloom/blinsert.c b/contrib/bloom/blinsert.c index adcbd168fb..5df616e96e 100644 --- a/contrib/bloom/blinsert.c +++ b/contrib/bloom/blinsert.c @@ -12,8 +12,8 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/generic_xlog.h" +#include "access/indexgenam.h" #include "access/tableam.h" #include "bloom.h" #include "catalog/index.h" diff --git a/contrib/bloom/bloom.h b/contrib/bloom/bloom.h index a7179981f4..5a6e5e48a1 100644 --- a/contrib/bloom/bloom.h +++ b/contrib/bloom/bloom.h @@ -13,8 +13,8 @@ #ifndef _BLOOM_H_ #define _BLOOM_H_ -#include "access/amapi.h" #include "access/generic_xlog.h" +#include "access/indexam.h" #include "access/itup.h" #include "access/xlog.h" #include "fmgr.h" diff --git a/contrib/bloom/blutils.c b/contrib/bloom/blutils.c index e2063bac62..44b7e74c5c 100644 --- a/contrib/bloom/blutils.c +++ b/contrib/bloom/blutils.c @@ -13,8 +13,8 @@ */ #include "postgres.h" -#include "access/amapi.h" #include "access/generic_xlog.h" +#include "access/indexam.h" #include "access/reloptions.h" #include "bloom.h" #include "catalog/index.h" diff --git a/contrib/bloom/blvacuum.c b/contrib/bloom/blvacuum.c index 0c33d1e195..f0a5d8cc5e 100644 --- a/contrib/bloom/blvacuum.c +++ b/contrib/bloom/blvacuum.c @@ -12,7 +12,7 @@ */ #include "postgres.h" -#include "access/genam.h" +#include "access/indexgenam.h" #include "bloom.h" #include "catalog/storage.h" #include "commands/vacuum.h" diff --git a/contrib/bloom/blvalidate.c b/contrib/bloom/blvalidate.c index b3dfe03022..ca2cb095f0 100644 --- a/contrib/bloom/blvalidate.c +++ b/contrib/bloom/blvalidate.c @@ -12,8 +12,8 @@ */ #include "postgres.h" -#include "access/amvalidate.h" #include "access/htup_details.h" +#include "access/indexamvalidate.h" #include "bloom.h" #include "catalog/pg_amop.h" #include "catalog/pg_amproc.h" diff --git a/contrib/sepgsql/database.c b/contrib/sepgsql/database.c index 5850e076eb..1fe30e34e4 100644 --- a/contrib/sepgsql/database.c +++ b/contrib/sepgsql/database.c @@ -10,8 +10,8 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/sysattr.h" #include "access/table.h" #include "catalog/dependency.h" diff --git a/contrib/sepgsql/label.c b/contrib/sepgsql/label.c index d8a1d129d2..083897aa39 100644 --- a/contrib/sepgsql/label.c +++ b/contrib/sepgsql/label.c @@ -12,8 +12,8 @@ #include -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/table.h" #include "access/xact.h" #include "catalog/catalog.h" diff --git a/contrib/sepgsql/proc.c b/contrib/sepgsql/proc.c index 345a4c253d..47382994e2 100644 --- a/contrib/sepgsql/proc.c +++ b/contrib/sepgsql/proc.c @@ -10,8 +10,8 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/sysattr.h" #include "access/table.h" #include "catalog/dependency.h" diff --git a/contrib/sepgsql/relation.c b/contrib/sepgsql/relation.c index fa34221509..4b1f772fc2 100644 --- a/contrib/sepgsql/relation.c +++ b/contrib/sepgsql/relation.c @@ -10,8 +10,8 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/sysattr.h" #include "access/table.h" #include "catalog/dependency.h" diff --git a/contrib/sepgsql/schema.c b/contrib/sepgsql/schema.c index 00c227d86c..42001bf133 100644 --- a/contrib/sepgsql/schema.c +++ b/contrib/sepgsql/schema.c @@ -10,8 +10,8 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/sysattr.h" #include "access/table.h" #include "catalog/dependency.h" diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c index 86788024ef..152b8b70da 100644 --- a/src/backend/access/brin/brin_inclusion.c +++ b/src/backend/access/brin/brin_inclusion.c @@ -26,7 +26,7 @@ #include "access/brin_internal.h" #include "access/brin_tuple.h" -#include "access/genam.h" +#include "access/indexgenam.h" #include "access/skey.h" #include "catalog/pg_amop.h" #include "catalog/pg_type.h" diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c index 655c0b54b5..d0d4389ea3 100644 --- a/src/backend/access/brin/brin_minmax.c +++ b/src/backend/access/brin/brin_minmax.c @@ -12,7 +12,7 @@ #include "access/brin_internal.h" #include "access/brin_tuple.h" -#include "access/genam.h" +#include "access/indexgenam.h" #include "access/stratnum.h" #include "catalog/pg_amop.h" #include "catalog/pg_type.h" diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c index 02337a767c..9b6f435e56 100644 --- a/src/backend/access/brin/brin_validate.c +++ b/src/backend/access/brin/brin_validate.c @@ -13,9 +13,9 @@ */ #include "postgres.h" -#include "access/amvalidate.h" #include "access/brin_internal.h" #include "access/htup_details.h" +#include "access/indexamvalidate.h" #include "catalog/pg_amop.h" #include "catalog/pg_amproc.h" #include "catalog/pg_opclass.h" diff --git a/src/backend/access/common/detoast.c b/src/backend/access/common/detoast.c index 78fcc876da..d6f45c8463 100644 --- a/src/backend/access/common/detoast.c +++ b/src/backend/access/common/detoast.c @@ -14,7 +14,7 @@ #include "postgres.h" #include "access/detoast.h" -#include "access/genam.h" +#include "access/indexgenam.h" #include "access/heaptoast.h" #include "access/table.h" #include "access/toast_internals.h" diff --git a/src/backend/access/common/toast_internals.c b/src/backend/access/common/toast_internals.c index a971242490..63517132d6 100644 --- a/src/backend/access/common/toast_internals.c +++ b/src/backend/access/common/toast_internals.c @@ -14,9 +14,9 @@ #include "postgres.h" #include "access/detoast.h" -#include "access/genam.h" #include "access/heapam.h" #include "access/heaptoast.h" +#include "access/indexgenam.h" #include "access/table.h" #include "access/toast_internals.h" #include "access/xact.h" diff --git a/src/backend/access/gin/ginvalidate.c b/src/backend/access/gin/ginvalidate.c index 5d96f29cde..5abd746894 100644 --- a/src/backend/access/gin/ginvalidate.c +++ b/src/backend/access/gin/ginvalidate.c @@ -13,9 +13,9 @@ */ #include "postgres.h" -#include "access/amvalidate.h" #include "access/gin_private.h" #include "access/htup_details.h" +#include "access/indexamvalidate.h" #include "catalog/pg_amop.h" #include "catalog/pg_amproc.h" #include "catalog/pg_opclass.h" diff --git a/src/backend/access/gist/gistbuild.c b/src/backend/access/gist/gistbuild.c index 739846a257..b9b31dd63e 100644 --- a/src/backend/access/gist/gistbuild.c +++ b/src/backend/access/gist/gistbuild.c @@ -16,9 +16,9 @@ #include -#include "access/genam.h" #include "access/gist_private.h" #include "access/gistxlog.h" +#include "access/indexgenam.h" #include "access/tableam.h" #include "access/xloginsert.h" #include "catalog/index.h" diff --git a/src/backend/access/gist/gistbuildbuffers.c b/src/backend/access/gist/gistbuildbuffers.c index 38f786848d..39121d5597 100644 --- a/src/backend/access/gist/gistbuildbuffers.c +++ b/src/backend/access/gist/gistbuildbuffers.c @@ -14,8 +14,8 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/gist_private.h" +#include "access/indexgenam.h" #include "catalog/index.h" #include "miscadmin.h" #include "storage/buffile.h" diff --git a/src/backend/access/gist/gistget.c b/src/backend/access/gist/gistget.c index 98b6892013..dd1df12fc8 100644 --- a/src/backend/access/gist/gistget.c +++ b/src/backend/access/gist/gistget.c @@ -14,8 +14,8 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/gist_private.h" +#include "access/indexgenam.h" #include "access/relscan.h" #include "lib/pairingheap.h" #include "miscadmin.h" diff --git a/src/backend/access/gist/gistvacuum.c b/src/backend/access/gist/gistvacuum.c index 710e4015b3..c8bb5f96b0 100644 --- a/src/backend/access/gist/gistvacuum.c +++ b/src/backend/access/gist/gistvacuum.c @@ -14,8 +14,8 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/gist_private.h" +#include "access/indexgenam.h" #include "access/transam.h" #include "commands/vacuum.h" #include "lib/integerset.h" diff --git a/src/backend/access/gist/gistvalidate.c b/src/backend/access/gist/gistvalidate.c index dfc1a87a75..3357689970 100644 --- a/src/backend/access/gist/gistvalidate.c +++ b/src/backend/access/gist/gistvalidate.c @@ -13,9 +13,9 @@ */ #include "postgres.h" -#include "access/amvalidate.h" #include "access/gist_private.h" #include "access/htup_details.h" +#include "access/indexamvalidate.h" #include "catalog/pg_amop.h" #include "catalog/pg_amproc.h" #include "catalog/pg_opclass.h" diff --git a/src/backend/access/hash/hashvalidate.c b/src/backend/access/hash/hashvalidate.c index 9315872751..3ec9fcd036 100644 --- a/src/backend/access/hash/hashvalidate.c +++ b/src/backend/access/hash/hashvalidate.c @@ -13,9 +13,9 @@ */ #include "postgres.h" -#include "access/amvalidate.h" #include "access/hash.h" #include "access/htup_details.h" +#include "access/indexamvalidate.h" #include "catalog/pg_amop.h" #include "catalog/pg_amproc.h" #include "catalog/pg_opclass.h" diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 0128bb34ef..e6d2b5f007 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -33,11 +33,11 @@ #include "postgres.h" #include "access/bufmask.h" -#include "access/genam.h" #include "access/heapam.h" #include "access/heapam_xlog.h" #include "access/heaptoast.h" #include "access/hio.h" +#include "access/indexgenam.h" #include "access/multixact.h" #include "access/parallel.h" #include "access/relscan.h" diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c index 92073fec54..72729f744b 100644 --- a/src/backend/access/heap/heapam_handler.c +++ b/src/backend/access/heap/heapam_handler.c @@ -19,9 +19,9 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/heapam.h" #include "access/heaptoast.h" +#include "access/indexgenam.h" #include "access/multixact.h" #include "access/rewriteheap.h" #include "access/tableam.h" diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index ab09d8408c..253b273366 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -36,10 +36,10 @@ #include -#include "access/genam.h" #include "access/heapam.h" #include "access/heapam_xlog.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/multixact.h" #include "access/transam.h" #include "access/visibilitymap.h" diff --git a/src/backend/access/index/Makefile b/src/backend/access/index/Makefile index 6f2e3061a8..0d8cbbc88c 100644 --- a/src/backend/access/index/Makefile +++ b/src/backend/access/index/Makefile @@ -13,9 +13,9 @@ top_builddir = ../../../.. include $(top_builddir)/src/Makefile.global OBJS = \ - amapi.o \ - amvalidate.o \ - genam.o \ - indexam.o + indexam.o \ + indexamapi.o \ + indexamvalidate.o \ + indexgenam.o include $(top_srcdir)/src/backend/common.mk diff --git a/src/backend/access/index/amapi.c b/src/backend/access/index/amapi.c deleted file mode 100644 index 450a7dce1f..0000000000 --- a/src/backend/access/index/amapi.c +++ /dev/null @@ -1,143 +0,0 @@ -/*------------------------------------------------------------------------- - * - * amapi.c - * Support routines for API for Postgres index access methods. - * - * Copyright (c) 2015-2019, PostgreSQL Global Development Group - * - * - * IDENTIFICATION - * src/backend/access/index/amapi.c - * - *------------------------------------------------------------------------- - */ -#include "postgres.h" - -#include "access/amapi.h" -#include "access/htup_details.h" -#include "catalog/pg_am.h" -#include "catalog/pg_opclass.h" -#include "utils/builtins.h" -#include "utils/syscache.h" - - -/* - * GetIndexAmRoutine - call the specified access method handler routine to get - * its IndexAmRoutine struct, which will be palloc'd in the caller's context. - * - * Note that if the amhandler function is built-in, this will not involve - * any catalog access. It's therefore safe to use this while bootstrapping - * indexes for the system catalogs. relcache.c relies on that. - */ -IndexAmRoutine * -GetIndexAmRoutine(Oid amhandler) -{ - Datum datum; - IndexAmRoutine *routine; - - datum = OidFunctionCall0(amhandler); - routine = (IndexAmRoutine *) DatumGetPointer(datum); - - if (routine == NULL || !IsA(routine, IndexAmRoutine)) - elog(ERROR, "index access method handler function %u did not return an IndexAmRoutine struct", - amhandler); - - return routine; -} - -/* - * GetIndexAmRoutineByAmId - look up the handler of the index access method - * with the given OID, and get its IndexAmRoutine struct. - * - * If the given OID isn't a valid index access method, returns NULL if - * noerror is true, else throws error. - */ -IndexAmRoutine * -GetIndexAmRoutineByAmId(Oid amoid, bool noerror) -{ - HeapTuple tuple; - Form_pg_am amform; - regproc amhandler; - - /* Get handler function OID for the access method */ - tuple = SearchSysCache1(AMOID, ObjectIdGetDatum(amoid)); - if (!HeapTupleIsValid(tuple)) - { - if (noerror) - return NULL; - elog(ERROR, "cache lookup failed for access method %u", - amoid); - } - amform = (Form_pg_am) GETSTRUCT(tuple); - - /* Check if it's an index access method as opposed to some other AM */ - if (amform->amtype != AMTYPE_INDEX) - { - if (noerror) - { - ReleaseSysCache(tuple); - return NULL; - } - ereport(ERROR, - (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), - errmsg("access method \"%s\" is not of type %s", - NameStr(amform->amname), "INDEX"))); - } - - amhandler = amform->amhandler; - - /* Complain if handler OID is invalid */ - if (!RegProcedureIsValid(amhandler)) - { - if (noerror) - { - ReleaseSysCache(tuple); - return NULL; - } - ereport(ERROR, - (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), - errmsg("index access method \"%s\" does not have a handler", - NameStr(amform->amname)))); - } - - ReleaseSysCache(tuple); - - /* And finally, call the handler function to get the API struct. */ - return GetIndexAmRoutine(amhandler); -} - - -/* - * Ask appropriate access method to validate the specified opclass. - */ -Datum -amvalidate(PG_FUNCTION_ARGS) -{ - Oid opclassoid = PG_GETARG_OID(0); - bool result; - HeapTuple classtup; - Form_pg_opclass classform; - Oid amoid; - IndexAmRoutine *amroutine; - - classtup = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclassoid)); - if (!HeapTupleIsValid(classtup)) - elog(ERROR, "cache lookup failed for operator class %u", opclassoid); - classform = (Form_pg_opclass) GETSTRUCT(classtup); - - amoid = classform->opcmethod; - - ReleaseSysCache(classtup); - - amroutine = GetIndexAmRoutineByAmId(amoid, false); - - if (amroutine->amvalidate == NULL) - elog(ERROR, "function amvalidate is not defined for index access method %u", - amoid); - - result = amroutine->amvalidate(opclassoid); - - pfree(amroutine); - - PG_RETURN_BOOL(result); -} diff --git a/src/backend/access/index/amvalidate.c b/src/backend/access/index/amvalidate.c deleted file mode 100644 index 5a2728502c..0000000000 --- a/src/backend/access/index/amvalidate.c +++ /dev/null @@ -1,246 +0,0 @@ -/*------------------------------------------------------------------------- - * - * amvalidate.c - * Support routines for index access methods' amvalidate functions. - * - * Copyright (c) 2016-2019, PostgreSQL Global Development Group - * - * - * IDENTIFICATION - * src/backend/access/index/amvalidate.c - * - *------------------------------------------------------------------------- - */ -#include "postgres.h" - -#include "access/amvalidate.h" -#include "access/htup_details.h" -#include "catalog/pg_am.h" -#include "catalog/pg_amop.h" -#include "catalog/pg_amproc.h" -#include "catalog/pg_opclass.h" -#include "catalog/pg_operator.h" -#include "catalog/pg_proc.h" -#include "parser/parse_coerce.h" -#include "utils/syscache.h" - - -/* - * identify_opfamily_groups() returns a List of OpFamilyOpFuncGroup structs, - * one for each combination of lefttype/righttype present in the family's - * operator and support function lists. If amopstrategy K is present for - * this datatype combination, we set bit 1 << K in operatorset, and similarly - * for the support functions. With uint64 fields we can handle operator and - * function numbers up to 63, which is plenty for the foreseeable future. - * - * The given CatCLists are expected to represent a single opfamily fetched - * from the AMOPSTRATEGY and AMPROCNUM caches, so that they will be in - * order by those caches' second and third cache keys, namely the datatypes. - */ -List * -identify_opfamily_groups(CatCList *oprlist, CatCList *proclist) -{ - List *result = NIL; - OpFamilyOpFuncGroup *thisgroup; - Form_pg_amop oprform; - Form_pg_amproc procform; - int io, - ip; - - /* We need the lists to be ordered; should be true in normal operation */ - if (!oprlist->ordered || !proclist->ordered) - elog(ERROR, "cannot validate operator family without ordered data"); - - /* - * Advance through the lists concurrently. Thanks to the ordering, we - * should see all operators and functions of a given datatype pair - * consecutively. - */ - thisgroup = NULL; - io = ip = 0; - if (io < oprlist->n_members) - { - oprform = (Form_pg_amop) GETSTRUCT(&oprlist->members[io]->tuple); - io++; - } - else - oprform = NULL; - if (ip < proclist->n_members) - { - procform = (Form_pg_amproc) GETSTRUCT(&proclist->members[ip]->tuple); - ip++; - } - else - procform = NULL; - - while (oprform || procform) - { - if (oprform && thisgroup && - oprform->amoplefttype == thisgroup->lefttype && - oprform->amoprighttype == thisgroup->righttype) - { - /* Operator belongs to current group; include it and advance */ - - /* Ignore strategy numbers outside supported range */ - if (oprform->amopstrategy > 0 && oprform->amopstrategy < 64) - thisgroup->operatorset |= ((uint64) 1) << oprform->amopstrategy; - - if (io < oprlist->n_members) - { - oprform = (Form_pg_amop) GETSTRUCT(&oprlist->members[io]->tuple); - io++; - } - else - oprform = NULL; - continue; - } - - if (procform && thisgroup && - procform->amproclefttype == thisgroup->lefttype && - procform->amprocrighttype == thisgroup->righttype) - { - /* Procedure belongs to current group; include it and advance */ - - /* Ignore function numbers outside supported range */ - if (procform->amprocnum > 0 && procform->amprocnum < 64) - thisgroup->functionset |= ((uint64) 1) << procform->amprocnum; - - if (ip < proclist->n_members) - { - procform = (Form_pg_amproc) GETSTRUCT(&proclist->members[ip]->tuple); - ip++; - } - else - procform = NULL; - continue; - } - - /* Time for a new group */ - thisgroup = (OpFamilyOpFuncGroup *) palloc(sizeof(OpFamilyOpFuncGroup)); - if (oprform && - (!procform || - (oprform->amoplefttype < procform->amproclefttype || - (oprform->amoplefttype == procform->amproclefttype && - oprform->amoprighttype < procform->amprocrighttype)))) - { - thisgroup->lefttype = oprform->amoplefttype; - thisgroup->righttype = oprform->amoprighttype; - } - else - { - thisgroup->lefttype = procform->amproclefttype; - thisgroup->righttype = procform->amprocrighttype; - } - thisgroup->operatorset = thisgroup->functionset = 0; - result = lappend(result, thisgroup); - } - - return result; -} - -/* - * Validate the signature (argument and result types) of an opclass support - * function. Return true if OK, false if not. - * - * The "..." represents maxargs argument-type OIDs. If "exact" is true, they - * must match the function arg types exactly, else only binary-coercibly. - * In any case the function result type must match restype exactly. - */ -bool -check_amproc_signature(Oid funcid, Oid restype, bool exact, - int minargs, int maxargs,...) -{ - bool result = true; - HeapTuple tp; - Form_pg_proc procform; - va_list ap; - int i; - - tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid)); - if (!HeapTupleIsValid(tp)) - elog(ERROR, "cache lookup failed for function %u", funcid); - procform = (Form_pg_proc) GETSTRUCT(tp); - - if (procform->prorettype != restype || procform->proretset || - procform->pronargs < minargs || procform->pronargs > maxargs) - result = false; - - va_start(ap, maxargs); - for (i = 0; i < maxargs; i++) - { - Oid argtype = va_arg(ap, Oid); - - if (i >= procform->pronargs) - continue; - if (exact ? (argtype != procform->proargtypes.values[i]) : - !IsBinaryCoercible(argtype, procform->proargtypes.values[i])) - result = false; - } - va_end(ap); - - ReleaseSysCache(tp); - return result; -} - -/* - * Validate the signature (argument and result types) of an opclass operator. - * Return true if OK, false if not. - * - * Currently, we can hard-wire this as accepting only binary operators. Also, - * we can insist on exact type matches, since the given lefttype/righttype - * come from pg_amop and should always match the operator exactly. - */ -bool -check_amop_signature(Oid opno, Oid restype, Oid lefttype, Oid righttype) -{ - bool result = true; - HeapTuple tp; - Form_pg_operator opform; - - tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno)); - if (!HeapTupleIsValid(tp)) /* shouldn't happen */ - elog(ERROR, "cache lookup failed for operator %u", opno); - opform = (Form_pg_operator) GETSTRUCT(tp); - - if (opform->oprresult != restype || opform->oprkind != 'b' || - opform->oprleft != lefttype || opform->oprright != righttype) - result = false; - - ReleaseSysCache(tp); - return result; -} - -/* - * Is the datatype a legitimate input type for the btree opfamily? - */ -bool -opfamily_can_sort_type(Oid opfamilyoid, Oid datatypeoid) -{ - bool result = false; - CatCList *opclist; - int i; - - /* - * We search through all btree opclasses to see if one matches. This is a - * bit inefficient but there is no better index available. It also saves - * making an explicit check that the opfamily belongs to btree. - */ - opclist = SearchSysCacheList1(CLAAMNAMENSP, ObjectIdGetDatum(BTREE_AM_OID)); - - for (i = 0; i < opclist->n_members; i++) - { - HeapTuple classtup = &opclist->members[i]->tuple; - Form_pg_opclass classform = (Form_pg_opclass) GETSTRUCT(classtup); - - if (classform->opcfamily == opfamilyoid && - classform->opcintype == datatypeoid) - { - result = true; - break; - } - } - - ReleaseCatCacheList(opclist); - - return result; -} diff --git a/src/backend/access/index/genam.c b/src/backend/access/index/genam.c deleted file mode 100644 index 2599b5d342..0000000000 --- a/src/backend/access/index/genam.c +++ /dev/null @@ -1,662 +0,0 @@ -/*------------------------------------------------------------------------- - * - * genam.c - * general index access method routines - * - * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * - * IDENTIFICATION - * src/backend/access/index/genam.c - * - * NOTES - * many of the old access method routines have been turned into - * macros and moved to genam.h -cim 4/30/91 - * - *------------------------------------------------------------------------- - */ - -#include "postgres.h" - -#include "access/genam.h" -#include "access/heapam.h" -#include "access/relscan.h" -#include "access/tableam.h" -#include "access/transam.h" -#include "catalog/index.h" -#include "lib/stringinfo.h" -#include "miscadmin.h" -#include "storage/bufmgr.h" -#include "utils/acl.h" -#include "utils/builtins.h" -#include "utils/lsyscache.h" -#include "utils/rel.h" -#include "utils/rls.h" -#include "utils/ruleutils.h" -#include "utils/snapmgr.h" -#include "utils/syscache.h" - - -/* ---------------------------------------------------------------- - * general access method routines - * - * All indexed access methods use an identical scan structure. - * We don't know how the various AMs do locking, however, so we don't - * do anything about that here. - * - * The intent is that an AM implementor will define a beginscan routine - * that calls RelationGetIndexScan, to fill in the scan, and then does - * whatever kind of locking he wants. - * - * At the end of a scan, the AM's endscan routine undoes the locking, - * but does *not* call IndexScanEnd --- the higher-level index_endscan - * routine does that. (We can't do it in the AM because index_endscan - * still needs to touch the IndexScanDesc after calling the AM.) - * - * Because of this, the AM does not have a choice whether to call - * RelationGetIndexScan or not; its beginscan routine must return an - * object made by RelationGetIndexScan. This is kinda ugly but not - * worth cleaning up now. - * ---------------------------------------------------------------- - */ - -/* ---------------- - * RelationGetIndexScan -- Create and fill an IndexScanDesc. - * - * This routine creates an index scan structure and sets up initial - * contents for it. - * - * Parameters: - * indexRelation -- index relation for scan. - * nkeys -- count of scan keys (index qual conditions). - * norderbys -- count of index order-by operators. - * - * Returns: - * An initialized IndexScanDesc. - * ---------------- - */ -IndexScanDesc -RelationGetIndexScan(Relation indexRelation, int nkeys, int norderbys) -{ - IndexScanDesc scan; - - scan = (IndexScanDesc) palloc(sizeof(IndexScanDescData)); - - scan->heapRelation = NULL; /* may be set later */ - scan->xs_heapfetch = NULL; - scan->indexRelation = indexRelation; - scan->xs_snapshot = InvalidSnapshot; /* caller must initialize this */ - scan->numberOfKeys = nkeys; - scan->numberOfOrderBys = norderbys; - - /* - * We allocate key workspace here, but it won't get filled until amrescan. - */ - if (nkeys > 0) - scan->keyData = (ScanKey) palloc(sizeof(ScanKeyData) * nkeys); - else - scan->keyData = NULL; - if (norderbys > 0) - scan->orderByData = (ScanKey) palloc(sizeof(ScanKeyData) * norderbys); - else - scan->orderByData = NULL; - - scan->xs_want_itup = false; /* may be set later */ - - /* - * During recovery we ignore killed tuples and don't bother to kill them - * either. We do this because the xmin on the primary node could easily be - * later than the xmin on the standby node, so that what the primary - * thinks is killed is supposed to be visible on standby. So for correct - * MVCC for queries during recovery we must ignore these hints and check - * all tuples. Do *not* set ignore_killed_tuples to true when running in a - * transaction that was started during recovery. xactStartedInRecovery - * should not be altered by index AMs. - */ - scan->kill_prior_tuple = false; - scan->xactStartedInRecovery = TransactionStartedDuringRecovery(); - scan->ignore_killed_tuples = !scan->xactStartedInRecovery; - - scan->opaque = NULL; - - scan->xs_itup = NULL; - scan->xs_itupdesc = NULL; - scan->xs_hitup = NULL; - scan->xs_hitupdesc = NULL; - - return scan; -} - -/* ---------------- - * IndexScanEnd -- End an index scan. - * - * This routine just releases the storage acquired by - * RelationGetIndexScan(). Any AM-level resources are - * assumed to already have been released by the AM's - * endscan routine. - * - * Returns: - * None. - * ---------------- - */ -void -IndexScanEnd(IndexScanDesc scan) -{ - if (scan->keyData != NULL) - pfree(scan->keyData); - if (scan->orderByData != NULL) - pfree(scan->orderByData); - - pfree(scan); -} - -/* - * BuildIndexValueDescription - * - * Construct a string describing the contents of an index entry, in the - * form "(key_name, ...)=(key_value, ...)". This is currently used - * for building unique-constraint and exclusion-constraint error messages, - * so only key columns of the index are checked and printed. - * - * Note that if the user does not have permissions to view all of the - * columns involved then a NULL is returned. Returning a partial key seems - * unlikely to be useful and we have no way to know which of the columns the - * user provided (unlike in ExecBuildSlotValueDescription). - * - * The passed-in values/nulls arrays are the "raw" input to the index AM, - * e.g. results of FormIndexDatum --- this is not necessarily what is stored - * in the index, but it's what the user perceives to be stored. - * - * Note: if you change anything here, check whether - * ExecBuildSlotPartitionKeyDescription() in execMain.c needs a similar - * change. - */ -char * -BuildIndexValueDescription(Relation indexRelation, - Datum *values, bool *isnull) -{ - StringInfoData buf; - Form_pg_index idxrec; - int indnkeyatts; - int i; - int keyno; - Oid indexrelid = RelationGetRelid(indexRelation); - Oid indrelid; - AclResult aclresult; - - indnkeyatts = IndexRelationGetNumberOfKeyAttributes(indexRelation); - - /* - * Check permissions- if the user does not have access to view all of the - * key columns then return NULL to avoid leaking data. - * - * First check if RLS is enabled for the relation. If so, return NULL to - * avoid leaking data. - * - * Next we need to check table-level SELECT access and then, if there is - * no access there, check column-level permissions. - */ - idxrec = indexRelation->rd_index; - indrelid = idxrec->indrelid; - Assert(indexrelid == idxrec->indexrelid); - - /* RLS check- if RLS is enabled then we don't return anything. */ - if (check_enable_rls(indrelid, InvalidOid, true) == RLS_ENABLED) - return NULL; - - /* Table-level SELECT is enough, if the user has it */ - aclresult = pg_class_aclcheck(indrelid, GetUserId(), ACL_SELECT); - if (aclresult != ACLCHECK_OK) - { - /* - * No table-level access, so step through the columns in the index and - * make sure the user has SELECT rights on all of them. - */ - for (keyno = 0; keyno < indnkeyatts; keyno++) - { - AttrNumber attnum = idxrec->indkey.values[keyno]; - - /* - * Note that if attnum == InvalidAttrNumber, then this is an index - * based on an expression and we return no detail rather than try - * to figure out what column(s) the expression includes and if the - * user has SELECT rights on them. - */ - if (attnum == InvalidAttrNumber || - pg_attribute_aclcheck(indrelid, attnum, GetUserId(), - ACL_SELECT) != ACLCHECK_OK) - { - /* No access, so clean up and return */ - return NULL; - } - } - } - - initStringInfo(&buf); - appendStringInfo(&buf, "(%s)=(", - pg_get_indexdef_columns(indexrelid, true)); - - for (i = 0; i < indnkeyatts; i++) - { - char *val; - - if (isnull[i]) - val = "null"; - else - { - Oid foutoid; - bool typisvarlena; - - /* - * The provided data is not necessarily of the type stored in the - * index; rather it is of the index opclass's input type. So look - * at rd_opcintype not the index tupdesc. - * - * Note: this is a bit shaky for opclasses that have pseudotype - * input types such as ANYARRAY or RECORD. Currently, the - * typoutput functions associated with the pseudotypes will work - * okay, but we might have to try harder in future. - */ - getTypeOutputInfo(indexRelation->rd_opcintype[i], - &foutoid, &typisvarlena); - val = OidOutputFunctionCall(foutoid, values[i]); - } - - if (i > 0) - appendStringInfoString(&buf, ", "); - appendStringInfoString(&buf, val); - } - - appendStringInfoChar(&buf, ')'); - - return buf.data; -} - -/* - * Get the latestRemovedXid from the table entries pointed at by the index - * tuples being deleted. - */ -TransactionId -index_compute_xid_horizon_for_tuples(Relation irel, - Relation hrel, - Buffer ibuf, - OffsetNumber *itemnos, - int nitems) -{ - ItemPointerData *ttids = - (ItemPointerData *) palloc(sizeof(ItemPointerData) * nitems); - TransactionId latestRemovedXid = InvalidTransactionId; - Page ipage = BufferGetPage(ibuf); - IndexTuple itup; - - /* identify what the index tuples about to be deleted point to */ - for (int i = 0; i < nitems; i++) - { - ItemId iitemid; - - iitemid = PageGetItemId(ipage, itemnos[i]); - itup = (IndexTuple) PageGetItem(ipage, iitemid); - - ItemPointerCopy(&itup->t_tid, &ttids[i]); - } - - /* determine the actual xid horizon */ - latestRemovedXid = - table_compute_xid_horizon_for_tuples(hrel, ttids, nitems); - - pfree(ttids); - - return latestRemovedXid; -} - - -/* ---------------------------------------------------------------- - * heap-or-index-scan access to system catalogs - * - * These functions support system catalog accesses that normally use - * an index but need to be capable of being switched to heap scans - * if the system indexes are unavailable. - * - * The specified scan keys must be compatible with the named index. - * Generally this means that they must constrain either all columns - * of the index, or the first K columns of an N-column index. - * - * These routines could work with non-system tables, actually, - * but they're only useful when there is a known index to use with - * the given scan keys; so in practice they're only good for - * predetermined types of scans of system catalogs. - * ---------------------------------------------------------------- - */ - -/* - * systable_beginscan --- set up for heap-or-index scan - * - * rel: catalog to scan, already opened and suitably locked - * indexId: OID of index to conditionally use - * indexOK: if false, forces a heap scan (see notes below) - * snapshot: time qual to use (NULL for a recent catalog snapshot) - * nkeys, key: scan keys - * - * The attribute numbers in the scan key should be set for the heap case. - * If we choose to index, we reset them to 1..n to reference the index - * columns. Note this means there must be one scankey qualification per - * index column! This is checked by the Asserts in the normal, index-using - * case, but won't be checked if the heapscan path is taken. - * - * The routine checks the normal cases for whether an indexscan is safe, - * but caller can make additional checks and pass indexOK=false if needed. - * In standard case indexOK can simply be constant TRUE. - */ -SysScanDesc -systable_beginscan(Relation heapRelation, - Oid indexId, - bool indexOK, - Snapshot snapshot, - int nkeys, ScanKey key) -{ - SysScanDesc sysscan; - Relation irel; - - if (indexOK && - !IgnoreSystemIndexes && - !ReindexIsProcessingIndex(indexId)) - irel = index_open(indexId, AccessShareLock); - else - irel = NULL; - - sysscan = (SysScanDesc) palloc(sizeof(SysScanDescData)); - - sysscan->heap_rel = heapRelation; - sysscan->irel = irel; - sysscan->slot = table_slot_create(heapRelation, NULL); - - if (snapshot == NULL) - { - Oid relid = RelationGetRelid(heapRelation); - - snapshot = RegisterSnapshot(GetCatalogSnapshot(relid)); - sysscan->snapshot = snapshot; - } - else - { - /* Caller is responsible for any snapshot. */ - sysscan->snapshot = NULL; - } - - if (irel) - { - int i; - - /* Change attribute numbers to be index column numbers. */ - for (i = 0; i < nkeys; i++) - { - int j; - - for (j = 0; j < IndexRelationGetNumberOfAttributes(irel); j++) - { - if (key[i].sk_attno == irel->rd_index->indkey.values[j]) - { - key[i].sk_attno = j + 1; - break; - } - } - if (j == IndexRelationGetNumberOfAttributes(irel)) - elog(ERROR, "column is not in index"); - } - - sysscan->iscan = index_beginscan(heapRelation, irel, - snapshot, nkeys, 0); - index_rescan(sysscan->iscan, key, nkeys, NULL, 0); - sysscan->scan = NULL; - } - else - { - /* - * We disallow synchronized scans when forced to use a heapscan on a - * catalog. In most cases the desired rows are near the front, so - * that the unpredictable start point of a syncscan is a serious - * disadvantage; and there are no compensating advantages, because - * it's unlikely that such scans will occur in parallel. - */ - sysscan->scan = table_beginscan_strat(heapRelation, snapshot, - nkeys, key, - true, false); - sysscan->iscan = NULL; - } - - return sysscan; -} - -/* - * systable_getnext --- get next tuple in a heap-or-index scan - * - * Returns NULL if no more tuples available. - * - * Note that returned tuple is a reference to data in a disk buffer; - * it must not be modified, and should be presumed inaccessible after - * next getnext() or endscan() call. - * - * XXX: It'd probably make sense to offer a slot based interface, at least - * optionally. - */ -HeapTuple -systable_getnext(SysScanDesc sysscan) -{ - HeapTuple htup = NULL; - - if (sysscan->irel) - { - if (index_getnext_slot(sysscan->iscan, ForwardScanDirection, sysscan->slot)) - { - bool shouldFree; - - htup = ExecFetchSlotHeapTuple(sysscan->slot, false, &shouldFree); - Assert(!shouldFree); - - /* - * We currently don't need to support lossy index operators for - * any system catalog scan. It could be done here, using the scan - * keys to drive the operator calls, if we arranged to save the - * heap attnums during systable_beginscan(); this is practical - * because we still wouldn't need to support indexes on - * expressions. - */ - if (sysscan->iscan->xs_recheck) - elog(ERROR, "system catalog scans with lossy index conditions are not implemented"); - } - } - else - { - if (table_scan_getnextslot(sysscan->scan, ForwardScanDirection, sysscan->slot)) - { - bool shouldFree; - - htup = ExecFetchSlotHeapTuple(sysscan->slot, false, &shouldFree); - Assert(!shouldFree); - } - } - - return htup; -} - -/* - * systable_recheck_tuple --- recheck visibility of most-recently-fetched tuple - * - * In particular, determine if this tuple would be visible to a catalog scan - * that started now. We don't handle the case of a non-MVCC scan snapshot, - * because no caller needs that yet. - * - * This is useful to test whether an object was deleted while we waited to - * acquire lock on it. - * - * Note: we don't actually *need* the tuple to be passed in, but it's a - * good crosscheck that the caller is interested in the right tuple. - */ -bool -systable_recheck_tuple(SysScanDesc sysscan, HeapTuple tup) -{ - Snapshot freshsnap; - bool result; - - Assert(tup == ExecFetchSlotHeapTuple(sysscan->slot, false, NULL)); - - /* - * Trust that table_tuple_satisfies_snapshot() and its subsidiaries - * (commonly LockBuffer() and HeapTupleSatisfiesMVCC()) do not themselves - * acquire snapshots, so we need not register the snapshot. Those - * facilities are too low-level to have any business scanning tables. - */ - freshsnap = GetCatalogSnapshot(RelationGetRelid(sysscan->heap_rel)); - - result = table_tuple_satisfies_snapshot(sysscan->heap_rel, - sysscan->slot, - freshsnap); - - return result; -} - -/* - * systable_endscan --- close scan, release resources - * - * Note that it's still up to the caller to close the heap relation. - */ -void -systable_endscan(SysScanDesc sysscan) -{ - if (sysscan->slot) - { - ExecDropSingleTupleTableSlot(sysscan->slot); - sysscan->slot = NULL; - } - - if (sysscan->irel) - { - index_endscan(sysscan->iscan); - index_close(sysscan->irel, AccessShareLock); - } - else - table_endscan(sysscan->scan); - - if (sysscan->snapshot) - UnregisterSnapshot(sysscan->snapshot); - - pfree(sysscan); -} - - -/* - * systable_beginscan_ordered --- set up for ordered catalog scan - * - * These routines have essentially the same API as systable_beginscan etc, - * except that they guarantee to return multiple matching tuples in - * index order. Also, for largely historical reasons, the index to use - * is opened and locked by the caller, not here. - * - * Currently we do not support non-index-based scans here. (In principle - * we could do a heapscan and sort, but the uses are in places that - * probably don't need to still work with corrupted catalog indexes.) - * For the moment, therefore, these functions are merely the thinnest of - * wrappers around index_beginscan/index_getnext_slot. The main reason for - * their existence is to centralize possible future support of lossy operators - * in catalog scans. - */ -SysScanDesc -systable_beginscan_ordered(Relation heapRelation, - Relation indexRelation, - Snapshot snapshot, - int nkeys, ScanKey key) -{ - SysScanDesc sysscan; - int i; - - /* REINDEX can probably be a hard error here ... */ - if (ReindexIsProcessingIndex(RelationGetRelid(indexRelation))) - elog(ERROR, "cannot do ordered scan on index \"%s\", because it is being reindexed", - RelationGetRelationName(indexRelation)); - /* ... but we only throw a warning about violating IgnoreSystemIndexes */ - if (IgnoreSystemIndexes) - elog(WARNING, "using index \"%s\" despite IgnoreSystemIndexes", - RelationGetRelationName(indexRelation)); - - sysscan = (SysScanDesc) palloc(sizeof(SysScanDescData)); - - sysscan->heap_rel = heapRelation; - sysscan->irel = indexRelation; - sysscan->slot = table_slot_create(heapRelation, NULL); - - if (snapshot == NULL) - { - Oid relid = RelationGetRelid(heapRelation); - - snapshot = RegisterSnapshot(GetCatalogSnapshot(relid)); - sysscan->snapshot = snapshot; - } - else - { - /* Caller is responsible for any snapshot. */ - sysscan->snapshot = NULL; - } - - /* Change attribute numbers to be index column numbers. */ - for (i = 0; i < nkeys; i++) - { - int j; - - for (j = 0; j < IndexRelationGetNumberOfAttributes(indexRelation); j++) - { - if (key[i].sk_attno == indexRelation->rd_index->indkey.values[j]) - { - key[i].sk_attno = j + 1; - break; - } - } - if (j == IndexRelationGetNumberOfAttributes(indexRelation)) - elog(ERROR, "column is not in index"); - } - - sysscan->iscan = index_beginscan(heapRelation, indexRelation, - snapshot, nkeys, 0); - index_rescan(sysscan->iscan, key, nkeys, NULL, 0); - sysscan->scan = NULL; - - return sysscan; -} - -/* - * systable_getnext_ordered --- get next tuple in an ordered catalog scan - */ -HeapTuple -systable_getnext_ordered(SysScanDesc sysscan, ScanDirection direction) -{ - HeapTuple htup = NULL; - - Assert(sysscan->irel); - if (index_getnext_slot(sysscan->iscan, direction, sysscan->slot)) - htup = ExecFetchSlotHeapTuple(sysscan->slot, false, NULL); - - /* See notes in systable_getnext */ - if (htup && sysscan->iscan->xs_recheck) - elog(ERROR, "system catalog scans with lossy index conditions are not implemented"); - - return htup; -} - -/* - * systable_endscan_ordered --- close scan, release resources - */ -void -systable_endscan_ordered(SysScanDesc sysscan) -{ - if (sysscan->slot) - { - ExecDropSingleTupleTableSlot(sysscan->slot); - sysscan->slot = NULL; - } - - Assert(sysscan->irel); - index_endscan(sysscan->iscan); - if (sysscan->snapshot) - UnregisterSnapshot(sysscan->snapshot); - pfree(sysscan); -} diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c index 4af418287d..d5d6e29e18 100644 --- a/src/backend/access/index/indexam.c +++ b/src/backend/access/index/indexam.c @@ -43,8 +43,8 @@ #include "postgres.h" -#include "access/amapi.h" #include "access/heapam.h" +#include "access/indexam.h" #include "access/relscan.h" #include "access/tableam.h" #include "access/transam.h" diff --git a/src/backend/access/index/indexamapi.c b/src/backend/access/index/indexamapi.c new file mode 100644 index 0000000000..bda667cf93 --- /dev/null +++ b/src/backend/access/index/indexamapi.c @@ -0,0 +1,143 @@ +/*------------------------------------------------------------------------- + * + * indexamapi.c + * Support routines for API for Postgres index access methods. + * + * Copyright (c) 2015-2019, PostgreSQL Global Development Group + * + * + * IDENTIFICATION + * src/backend/access/index/indexamapi.c + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include "access/htup_details.h" +#include "access/indexam.h" +#include "catalog/pg_am.h" +#include "catalog/pg_opclass.h" +#include "utils/builtins.h" +#include "utils/syscache.h" + + +/* + * GetIndexAmRoutine - call the specified access method handler routine to get + * its IndexAmRoutine struct, which will be palloc'd in the caller's context. + * + * Note that if the amhandler function is built-in, this will not involve + * any catalog access. It's therefore safe to use this while bootstrapping + * indexes for the system catalogs. relcache.c relies on that. + */ +IndexAmRoutine * +GetIndexAmRoutine(Oid amhandler) +{ + Datum datum; + IndexAmRoutine *routine; + + datum = OidFunctionCall0(amhandler); + routine = (IndexAmRoutine *) DatumGetPointer(datum); + + if (routine == NULL || !IsA(routine, IndexAmRoutine)) + elog(ERROR, "index access method handler function %u did not return an IndexAmRoutine struct", + amhandler); + + return routine; +} + +/* + * GetIndexAmRoutineByAmId - look up the handler of the index access method + * with the given OID, and get its IndexAmRoutine struct. + * + * If the given OID isn't a valid index access method, returns NULL if + * noerror is true, else throws error. + */ +IndexAmRoutine * +GetIndexAmRoutineByAmId(Oid amoid, bool noerror) +{ + HeapTuple tuple; + Form_pg_am amform; + regproc amhandler; + + /* Get handler function OID for the access method */ + tuple = SearchSysCache1(AMOID, ObjectIdGetDatum(amoid)); + if (!HeapTupleIsValid(tuple)) + { + if (noerror) + return NULL; + elog(ERROR, "cache lookup failed for access method %u", + amoid); + } + amform = (Form_pg_am) GETSTRUCT(tuple); + + /* Check if it's an index access method as opposed to some other AM */ + if (amform->amtype != AMTYPE_INDEX) + { + if (noerror) + { + ReleaseSysCache(tuple); + return NULL; + } + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("access method \"%s\" is not of type %s", + NameStr(amform->amname), "INDEX"))); + } + + amhandler = amform->amhandler; + + /* Complain if handler OID is invalid */ + if (!RegProcedureIsValid(amhandler)) + { + if (noerror) + { + ReleaseSysCache(tuple); + return NULL; + } + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("index access method \"%s\" does not have a handler", + NameStr(amform->amname)))); + } + + ReleaseSysCache(tuple); + + /* And finally, call the handler function to get the API struct. */ + return GetIndexAmRoutine(amhandler); +} + + +/* + * Ask appropriate access method to validate the specified opclass. + */ +Datum +amvalidate(PG_FUNCTION_ARGS) +{ + Oid opclassoid = PG_GETARG_OID(0); + bool result; + HeapTuple classtup; + Form_pg_opclass classform; + Oid amoid; + IndexAmRoutine *amroutine; + + classtup = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclassoid)); + if (!HeapTupleIsValid(classtup)) + elog(ERROR, "cache lookup failed for operator class %u", opclassoid); + classform = (Form_pg_opclass) GETSTRUCT(classtup); + + amoid = classform->opcmethod; + + ReleaseSysCache(classtup); + + amroutine = GetIndexAmRoutineByAmId(amoid, false); + + if (amroutine->amvalidate == NULL) + elog(ERROR, "function amvalidate is not defined for index access method %u", + amoid); + + result = amroutine->amvalidate(opclassoid); + + pfree(amroutine); + + PG_RETURN_BOOL(result); +} diff --git a/src/backend/access/index/indexamvalidate.c b/src/backend/access/index/indexamvalidate.c new file mode 100644 index 0000000000..8f00012d20 --- /dev/null +++ b/src/backend/access/index/indexamvalidate.c @@ -0,0 +1,246 @@ +/*------------------------------------------------------------------------- + * + * indexamvalidate.c + * Support routines for index access methods' amvalidate functions. + * + * Copyright (c) 2016-2019, PostgreSQL Global Development Group + * + * + * IDENTIFICATION + * src/backend/access/index/indexamvalidate.c + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include "access/htup_details.h" +#include "access/indexamvalidate.h" +#include "catalog/pg_am.h" +#include "catalog/pg_amop.h" +#include "catalog/pg_amproc.h" +#include "catalog/pg_opclass.h" +#include "catalog/pg_operator.h" +#include "catalog/pg_proc.h" +#include "parser/parse_coerce.h" +#include "utils/syscache.h" + + +/* + * identify_opfamily_groups() returns a List of OpFamilyOpFuncGroup structs, + * one for each combination of lefttype/righttype present in the family's + * operator and support function lists. If amopstrategy K is present for + * this datatype combination, we set bit 1 << K in operatorset, and similarly + * for the support functions. With uint64 fields we can handle operator and + * function numbers up to 63, which is plenty for the foreseeable future. + * + * The given CatCLists are expected to represent a single opfamily fetched + * from the AMOPSTRATEGY and AMPROCNUM caches, so that they will be in + * order by those caches' second and third cache keys, namely the datatypes. + */ +List * +identify_opfamily_groups(CatCList *oprlist, CatCList *proclist) +{ + List *result = NIL; + OpFamilyOpFuncGroup *thisgroup; + Form_pg_amop oprform; + Form_pg_amproc procform; + int io, + ip; + + /* We need the lists to be ordered; should be true in normal operation */ + if (!oprlist->ordered || !proclist->ordered) + elog(ERROR, "cannot validate operator family without ordered data"); + + /* + * Advance through the lists concurrently. Thanks to the ordering, we + * should see all operators and functions of a given datatype pair + * consecutively. + */ + thisgroup = NULL; + io = ip = 0; + if (io < oprlist->n_members) + { + oprform = (Form_pg_amop) GETSTRUCT(&oprlist->members[io]->tuple); + io++; + } + else + oprform = NULL; + if (ip < proclist->n_members) + { + procform = (Form_pg_amproc) GETSTRUCT(&proclist->members[ip]->tuple); + ip++; + } + else + procform = NULL; + + while (oprform || procform) + { + if (oprform && thisgroup && + oprform->amoplefttype == thisgroup->lefttype && + oprform->amoprighttype == thisgroup->righttype) + { + /* Operator belongs to current group; include it and advance */ + + /* Ignore strategy numbers outside supported range */ + if (oprform->amopstrategy > 0 && oprform->amopstrategy < 64) + thisgroup->operatorset |= ((uint64) 1) << oprform->amopstrategy; + + if (io < oprlist->n_members) + { + oprform = (Form_pg_amop) GETSTRUCT(&oprlist->members[io]->tuple); + io++; + } + else + oprform = NULL; + continue; + } + + if (procform && thisgroup && + procform->amproclefttype == thisgroup->lefttype && + procform->amprocrighttype == thisgroup->righttype) + { + /* Procedure belongs to current group; include it and advance */ + + /* Ignore function numbers outside supported range */ + if (procform->amprocnum > 0 && procform->amprocnum < 64) + thisgroup->functionset |= ((uint64) 1) << procform->amprocnum; + + if (ip < proclist->n_members) + { + procform = (Form_pg_amproc) GETSTRUCT(&proclist->members[ip]->tuple); + ip++; + } + else + procform = NULL; + continue; + } + + /* Time for a new group */ + thisgroup = (OpFamilyOpFuncGroup *) palloc(sizeof(OpFamilyOpFuncGroup)); + if (oprform && + (!procform || + (oprform->amoplefttype < procform->amproclefttype || + (oprform->amoplefttype == procform->amproclefttype && + oprform->amoprighttype < procform->amprocrighttype)))) + { + thisgroup->lefttype = oprform->amoplefttype; + thisgroup->righttype = oprform->amoprighttype; + } + else + { + thisgroup->lefttype = procform->amproclefttype; + thisgroup->righttype = procform->amprocrighttype; + } + thisgroup->operatorset = thisgroup->functionset = 0; + result = lappend(result, thisgroup); + } + + return result; +} + +/* + * Validate the signature (argument and result types) of an opclass support + * function. Return true if OK, false if not. + * + * The "..." represents maxargs argument-type OIDs. If "exact" is true, they + * must match the function arg types exactly, else only binary-coercibly. + * In any case the function result type must match restype exactly. + */ +bool +check_amproc_signature(Oid funcid, Oid restype, bool exact, + int minargs, int maxargs,...) +{ + bool result = true; + HeapTuple tp; + Form_pg_proc procform; + va_list ap; + int i; + + tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid)); + if (!HeapTupleIsValid(tp)) + elog(ERROR, "cache lookup failed for function %u", funcid); + procform = (Form_pg_proc) GETSTRUCT(tp); + + if (procform->prorettype != restype || procform->proretset || + procform->pronargs < minargs || procform->pronargs > maxargs) + result = false; + + va_start(ap, maxargs); + for (i = 0; i < maxargs; i++) + { + Oid argtype = va_arg(ap, Oid); + + if (i >= procform->pronargs) + continue; + if (exact ? (argtype != procform->proargtypes.values[i]) : + !IsBinaryCoercible(argtype, procform->proargtypes.values[i])) + result = false; + } + va_end(ap); + + ReleaseSysCache(tp); + return result; +} + +/* + * Validate the signature (argument and result types) of an opclass operator. + * Return true if OK, false if not. + * + * Currently, we can hard-wire this as accepting only binary operators. Also, + * we can insist on exact type matches, since the given lefttype/righttype + * come from pg_amop and should always match the operator exactly. + */ +bool +check_amop_signature(Oid opno, Oid restype, Oid lefttype, Oid righttype) +{ + bool result = true; + HeapTuple tp; + Form_pg_operator opform; + + tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno)); + if (!HeapTupleIsValid(tp)) /* shouldn't happen */ + elog(ERROR, "cache lookup failed for operator %u", opno); + opform = (Form_pg_operator) GETSTRUCT(tp); + + if (opform->oprresult != restype || opform->oprkind != 'b' || + opform->oprleft != lefttype || opform->oprright != righttype) + result = false; + + ReleaseSysCache(tp); + return result; +} + +/* + * Is the datatype a legitimate input type for the btree opfamily? + */ +bool +opfamily_can_sort_type(Oid opfamilyoid, Oid datatypeoid) +{ + bool result = false; + CatCList *opclist; + int i; + + /* + * We search through all btree opclasses to see if one matches. This is a + * bit inefficient but there is no better index available. It also saves + * making an explicit check that the opfamily belongs to btree. + */ + opclist = SearchSysCacheList1(CLAAMNAMENSP, ObjectIdGetDatum(BTREE_AM_OID)); + + for (i = 0; i < opclist->n_members; i++) + { + HeapTuple classtup = &opclist->members[i]->tuple; + Form_pg_opclass classform = (Form_pg_opclass) GETSTRUCT(classtup); + + if (classform->opcfamily == opfamilyoid && + classform->opcintype == datatypeoid) + { + result = true; + break; + } + } + + ReleaseCatCacheList(opclist); + + return result; +} diff --git a/src/backend/access/index/indexgenam.c b/src/backend/access/index/indexgenam.c new file mode 100644 index 0000000000..6a1ac6cc30 --- /dev/null +++ b/src/backend/access/index/indexgenam.c @@ -0,0 +1,662 @@ +/*------------------------------------------------------------------------- + * + * indexgenam.c + * general index access method routines + * + * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/backend/access/index/indexgenam.c + * + * NOTES + * many of the old access method routines have been turned into + * macros and moved to indexgenam.h -cim 4/30/91 + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "access/heapam.h" +#include "access/indexgenam.h" +#include "access/relscan.h" +#include "access/tableam.h" +#include "access/transam.h" +#include "catalog/index.h" +#include "lib/stringinfo.h" +#include "miscadmin.h" +#include "storage/bufmgr.h" +#include "utils/acl.h" +#include "utils/builtins.h" +#include "utils/lsyscache.h" +#include "utils/rel.h" +#include "utils/rls.h" +#include "utils/ruleutils.h" +#include "utils/snapmgr.h" +#include "utils/syscache.h" + + +/* ---------------------------------------------------------------- + * general access method routines + * + * All indexed access methods use an identical scan structure. + * We don't know how the various AMs do locking, however, so we don't + * do anything about that here. + * + * The intent is that an AM implementor will define a beginscan routine + * that calls RelationGetIndexScan, to fill in the scan, and then does + * whatever kind of locking he wants. + * + * At the end of a scan, the AM's endscan routine undoes the locking, + * but does *not* call IndexScanEnd --- the higher-level index_endscan + * routine does that. (We can't do it in the AM because index_endscan + * still needs to touch the IndexScanDesc after calling the AM.) + * + * Because of this, the AM does not have a choice whether to call + * RelationGetIndexScan or not; its beginscan routine must return an + * object made by RelationGetIndexScan. This is kinda ugly but not + * worth cleaning up now. + * ---------------------------------------------------------------- + */ + +/* ---------------- + * RelationGetIndexScan -- Create and fill an IndexScanDesc. + * + * This routine creates an index scan structure and sets up initial + * contents for it. + * + * Parameters: + * indexRelation -- index relation for scan. + * nkeys -- count of scan keys (index qual conditions). + * norderbys -- count of index order-by operators. + * + * Returns: + * An initialized IndexScanDesc. + * ---------------- + */ +IndexScanDesc +RelationGetIndexScan(Relation indexRelation, int nkeys, int norderbys) +{ + IndexScanDesc scan; + + scan = (IndexScanDesc) palloc(sizeof(IndexScanDescData)); + + scan->heapRelation = NULL; /* may be set later */ + scan->xs_heapfetch = NULL; + scan->indexRelation = indexRelation; + scan->xs_snapshot = InvalidSnapshot; /* caller must initialize this */ + scan->numberOfKeys = nkeys; + scan->numberOfOrderBys = norderbys; + + /* + * We allocate key workspace here, but it won't get filled until amrescan. + */ + if (nkeys > 0) + scan->keyData = (ScanKey) palloc(sizeof(ScanKeyData) * nkeys); + else + scan->keyData = NULL; + if (norderbys > 0) + scan->orderByData = (ScanKey) palloc(sizeof(ScanKeyData) * norderbys); + else + scan->orderByData = NULL; + + scan->xs_want_itup = false; /* may be set later */ + + /* + * During recovery we ignore killed tuples and don't bother to kill them + * either. We do this because the xmin on the primary node could easily be + * later than the xmin on the standby node, so that what the primary + * thinks is killed is supposed to be visible on standby. So for correct + * MVCC for queries during recovery we must ignore these hints and check + * all tuples. Do *not* set ignore_killed_tuples to true when running in a + * transaction that was started during recovery. xactStartedInRecovery + * should not be altered by index AMs. + */ + scan->kill_prior_tuple = false; + scan->xactStartedInRecovery = TransactionStartedDuringRecovery(); + scan->ignore_killed_tuples = !scan->xactStartedInRecovery; + + scan->opaque = NULL; + + scan->xs_itup = NULL; + scan->xs_itupdesc = NULL; + scan->xs_hitup = NULL; + scan->xs_hitupdesc = NULL; + + return scan; +} + +/* ---------------- + * IndexScanEnd -- End an index scan. + * + * This routine just releases the storage acquired by + * RelationGetIndexScan(). Any AM-level resources are + * assumed to already have been released by the AM's + * endscan routine. + * + * Returns: + * None. + * ---------------- + */ +void +IndexScanEnd(IndexScanDesc scan) +{ + if (scan->keyData != NULL) + pfree(scan->keyData); + if (scan->orderByData != NULL) + pfree(scan->orderByData); + + pfree(scan); +} + +/* + * BuildIndexValueDescription + * + * Construct a string describing the contents of an index entry, in the + * form "(key_name, ...)=(key_value, ...)". This is currently used + * for building unique-constraint and exclusion-constraint error messages, + * so only key columns of the index are checked and printed. + * + * Note that if the user does not have permissions to view all of the + * columns involved then a NULL is returned. Returning a partial key seems + * unlikely to be useful and we have no way to know which of the columns the + * user provided (unlike in ExecBuildSlotValueDescription). + * + * The passed-in values/nulls arrays are the "raw" input to the index AM, + * e.g. results of FormIndexDatum --- this is not necessarily what is stored + * in the index, but it's what the user perceives to be stored. + * + * Note: if you change anything here, check whether + * ExecBuildSlotPartitionKeyDescription() in execMain.c needs a similar + * change. + */ +char * +BuildIndexValueDescription(Relation indexRelation, + Datum *values, bool *isnull) +{ + StringInfoData buf; + Form_pg_index idxrec; + int indnkeyatts; + int i; + int keyno; + Oid indexrelid = RelationGetRelid(indexRelation); + Oid indrelid; + AclResult aclresult; + + indnkeyatts = IndexRelationGetNumberOfKeyAttributes(indexRelation); + + /* + * Check permissions- if the user does not have access to view all of the + * key columns then return NULL to avoid leaking data. + * + * First check if RLS is enabled for the relation. If so, return NULL to + * avoid leaking data. + * + * Next we need to check table-level SELECT access and then, if there is + * no access there, check column-level permissions. + */ + idxrec = indexRelation->rd_index; + indrelid = idxrec->indrelid; + Assert(indexrelid == idxrec->indexrelid); + + /* RLS check- if RLS is enabled then we don't return anything. */ + if (check_enable_rls(indrelid, InvalidOid, true) == RLS_ENABLED) + return NULL; + + /* Table-level SELECT is enough, if the user has it */ + aclresult = pg_class_aclcheck(indrelid, GetUserId(), ACL_SELECT); + if (aclresult != ACLCHECK_OK) + { + /* + * No table-level access, so step through the columns in the index and + * make sure the user has SELECT rights on all of them. + */ + for (keyno = 0; keyno < indnkeyatts; keyno++) + { + AttrNumber attnum = idxrec->indkey.values[keyno]; + + /* + * Note that if attnum == InvalidAttrNumber, then this is an index + * based on an expression and we return no detail rather than try + * to figure out what column(s) the expression includes and if the + * user has SELECT rights on them. + */ + if (attnum == InvalidAttrNumber || + pg_attribute_aclcheck(indrelid, attnum, GetUserId(), + ACL_SELECT) != ACLCHECK_OK) + { + /* No access, so clean up and return */ + return NULL; + } + } + } + + initStringInfo(&buf); + appendStringInfo(&buf, "(%s)=(", + pg_get_indexdef_columns(indexrelid, true)); + + for (i = 0; i < indnkeyatts; i++) + { + char *val; + + if (isnull[i]) + val = "null"; + else + { + Oid foutoid; + bool typisvarlena; + + /* + * The provided data is not necessarily of the type stored in the + * index; rather it is of the index opclass's input type. So look + * at rd_opcintype not the index tupdesc. + * + * Note: this is a bit shaky for opclasses that have pseudotype + * input types such as ANYARRAY or RECORD. Currently, the + * typoutput functions associated with the pseudotypes will work + * okay, but we might have to try harder in future. + */ + getTypeOutputInfo(indexRelation->rd_opcintype[i], + &foutoid, &typisvarlena); + val = OidOutputFunctionCall(foutoid, values[i]); + } + + if (i > 0) + appendStringInfoString(&buf, ", "); + appendStringInfoString(&buf, val); + } + + appendStringInfoChar(&buf, ')'); + + return buf.data; +} + +/* + * Get the latestRemovedXid from the table entries pointed at by the index + * tuples being deleted. + */ +TransactionId +index_compute_xid_horizon_for_tuples(Relation irel, + Relation hrel, + Buffer ibuf, + OffsetNumber *itemnos, + int nitems) +{ + ItemPointerData *ttids = + (ItemPointerData *) palloc(sizeof(ItemPointerData) * nitems); + TransactionId latestRemovedXid = InvalidTransactionId; + Page ipage = BufferGetPage(ibuf); + IndexTuple itup; + + /* identify what the index tuples about to be deleted point to */ + for (int i = 0; i < nitems; i++) + { + ItemId iitemid; + + iitemid = PageGetItemId(ipage, itemnos[i]); + itup = (IndexTuple) PageGetItem(ipage, iitemid); + + ItemPointerCopy(&itup->t_tid, &ttids[i]); + } + + /* determine the actual xid horizon */ + latestRemovedXid = + table_compute_xid_horizon_for_tuples(hrel, ttids, nitems); + + pfree(ttids); + + return latestRemovedXid; +} + + +/* ---------------------------------------------------------------- + * heap-or-index-scan access to system catalogs + * + * These functions support system catalog accesses that normally use + * an index but need to be capable of being switched to heap scans + * if the system indexes are unavailable. + * + * The specified scan keys must be compatible with the named index. + * Generally this means that they must constrain either all columns + * of the index, or the first K columns of an N-column index. + * + * These routines could work with non-system tables, actually, + * but they're only useful when there is a known index to use with + * the given scan keys; so in practice they're only good for + * predetermined types of scans of system catalogs. + * ---------------------------------------------------------------- + */ + +/* + * systable_beginscan --- set up for heap-or-index scan + * + * rel: catalog to scan, already opened and suitably locked + * indexId: OID of index to conditionally use + * indexOK: if false, forces a heap scan (see notes below) + * snapshot: time qual to use (NULL for a recent catalog snapshot) + * nkeys, key: scan keys + * + * The attribute numbers in the scan key should be set for the heap case. + * If we choose to index, we reset them to 1..n to reference the index + * columns. Note this means there must be one scankey qualification per + * index column! This is checked by the Asserts in the normal, index-using + * case, but won't be checked if the heapscan path is taken. + * + * The routine checks the normal cases for whether an indexscan is safe, + * but caller can make additional checks and pass indexOK=false if needed. + * In standard case indexOK can simply be constant TRUE. + */ +SysScanDesc +systable_beginscan(Relation heapRelation, + Oid indexId, + bool indexOK, + Snapshot snapshot, + int nkeys, ScanKey key) +{ + SysScanDesc sysscan; + Relation irel; + + if (indexOK && + !IgnoreSystemIndexes && + !ReindexIsProcessingIndex(indexId)) + irel = index_open(indexId, AccessShareLock); + else + irel = NULL; + + sysscan = (SysScanDesc) palloc(sizeof(SysScanDescData)); + + sysscan->heap_rel = heapRelation; + sysscan->irel = irel; + sysscan->slot = table_slot_create(heapRelation, NULL); + + if (snapshot == NULL) + { + Oid relid = RelationGetRelid(heapRelation); + + snapshot = RegisterSnapshot(GetCatalogSnapshot(relid)); + sysscan->snapshot = snapshot; + } + else + { + /* Caller is responsible for any snapshot. */ + sysscan->snapshot = NULL; + } + + if (irel) + { + int i; + + /* Change attribute numbers to be index column numbers. */ + for (i = 0; i < nkeys; i++) + { + int j; + + for (j = 0; j < IndexRelationGetNumberOfAttributes(irel); j++) + { + if (key[i].sk_attno == irel->rd_index->indkey.values[j]) + { + key[i].sk_attno = j + 1; + break; + } + } + if (j == IndexRelationGetNumberOfAttributes(irel)) + elog(ERROR, "column is not in index"); + } + + sysscan->iscan = index_beginscan(heapRelation, irel, + snapshot, nkeys, 0); + index_rescan(sysscan->iscan, key, nkeys, NULL, 0); + sysscan->scan = NULL; + } + else + { + /* + * We disallow synchronized scans when forced to use a heapscan on a + * catalog. In most cases the desired rows are near the front, so + * that the unpredictable start point of a syncscan is a serious + * disadvantage; and there are no compensating advantages, because + * it's unlikely that such scans will occur in parallel. + */ + sysscan->scan = table_beginscan_strat(heapRelation, snapshot, + nkeys, key, + true, false); + sysscan->iscan = NULL; + } + + return sysscan; +} + +/* + * systable_getnext --- get next tuple in a heap-or-index scan + * + * Returns NULL if no more tuples available. + * + * Note that returned tuple is a reference to data in a disk buffer; + * it must not be modified, and should be presumed inaccessible after + * next getnext() or endscan() call. + * + * XXX: It'd probably make sense to offer a slot based interface, at least + * optionally. + */ +HeapTuple +systable_getnext(SysScanDesc sysscan) +{ + HeapTuple htup = NULL; + + if (sysscan->irel) + { + if (index_getnext_slot(sysscan->iscan, ForwardScanDirection, sysscan->slot)) + { + bool shouldFree; + + htup = ExecFetchSlotHeapTuple(sysscan->slot, false, &shouldFree); + Assert(!shouldFree); + + /* + * We currently don't need to support lossy index operators for + * any system catalog scan. It could be done here, using the scan + * keys to drive the operator calls, if we arranged to save the + * heap attnums during systable_beginscan(); this is practical + * because we still wouldn't need to support indexes on + * expressions. + */ + if (sysscan->iscan->xs_recheck) + elog(ERROR, "system catalog scans with lossy index conditions are not implemented"); + } + } + else + { + if (table_scan_getnextslot(sysscan->scan, ForwardScanDirection, sysscan->slot)) + { + bool shouldFree; + + htup = ExecFetchSlotHeapTuple(sysscan->slot, false, &shouldFree); + Assert(!shouldFree); + } + } + + return htup; +} + +/* + * systable_recheck_tuple --- recheck visibility of most-recently-fetched tuple + * + * In particular, determine if this tuple would be visible to a catalog scan + * that started now. We don't handle the case of a non-MVCC scan snapshot, + * because no caller needs that yet. + * + * This is useful to test whether an object was deleted while we waited to + * acquire lock on it. + * + * Note: we don't actually *need* the tuple to be passed in, but it's a + * good crosscheck that the caller is interested in the right tuple. + */ +bool +systable_recheck_tuple(SysScanDesc sysscan, HeapTuple tup) +{ + Snapshot freshsnap; + bool result; + + Assert(tup == ExecFetchSlotHeapTuple(sysscan->slot, false, NULL)); + + /* + * Trust that table_tuple_satisfies_snapshot() and its subsidiaries + * (commonly LockBuffer() and HeapTupleSatisfiesMVCC()) do not themselves + * acquire snapshots, so we need not register the snapshot. Those + * facilities are too low-level to have any business scanning tables. + */ + freshsnap = GetCatalogSnapshot(RelationGetRelid(sysscan->heap_rel)); + + result = table_tuple_satisfies_snapshot(sysscan->heap_rel, + sysscan->slot, + freshsnap); + + return result; +} + +/* + * systable_endscan --- close scan, release resources + * + * Note that it's still up to the caller to close the heap relation. + */ +void +systable_endscan(SysScanDesc sysscan) +{ + if (sysscan->slot) + { + ExecDropSingleTupleTableSlot(sysscan->slot); + sysscan->slot = NULL; + } + + if (sysscan->irel) + { + index_endscan(sysscan->iscan); + index_close(sysscan->irel, AccessShareLock); + } + else + table_endscan(sysscan->scan); + + if (sysscan->snapshot) + UnregisterSnapshot(sysscan->snapshot); + + pfree(sysscan); +} + + +/* + * systable_beginscan_ordered --- set up for ordered catalog scan + * + * These routines have essentially the same API as systable_beginscan etc, + * except that they guarantee to return multiple matching tuples in + * index order. Also, for largely historical reasons, the index to use + * is opened and locked by the caller, not here. + * + * Currently we do not support non-index-based scans here. (In principle + * we could do a heapscan and sort, but the uses are in places that + * probably don't need to still work with corrupted catalog indexes.) + * For the moment, therefore, these functions are merely the thinnest of + * wrappers around index_beginscan/index_getnext_slot. The main reason for + * their existence is to centralize possible future support of lossy operators + * in catalog scans. + */ +SysScanDesc +systable_beginscan_ordered(Relation heapRelation, + Relation indexRelation, + Snapshot snapshot, + int nkeys, ScanKey key) +{ + SysScanDesc sysscan; + int i; + + /* REINDEX can probably be a hard error here ... */ + if (ReindexIsProcessingIndex(RelationGetRelid(indexRelation))) + elog(ERROR, "cannot do ordered scan on index \"%s\", because it is being reindexed", + RelationGetRelationName(indexRelation)); + /* ... but we only throw a warning about violating IgnoreSystemIndexes */ + if (IgnoreSystemIndexes) + elog(WARNING, "using index \"%s\" despite IgnoreSystemIndexes", + RelationGetRelationName(indexRelation)); + + sysscan = (SysScanDesc) palloc(sizeof(SysScanDescData)); + + sysscan->heap_rel = heapRelation; + sysscan->irel = indexRelation; + sysscan->slot = table_slot_create(heapRelation, NULL); + + if (snapshot == NULL) + { + Oid relid = RelationGetRelid(heapRelation); + + snapshot = RegisterSnapshot(GetCatalogSnapshot(relid)); + sysscan->snapshot = snapshot; + } + else + { + /* Caller is responsible for any snapshot. */ + sysscan->snapshot = NULL; + } + + /* Change attribute numbers to be index column numbers. */ + for (i = 0; i < nkeys; i++) + { + int j; + + for (j = 0; j < IndexRelationGetNumberOfAttributes(indexRelation); j++) + { + if (key[i].sk_attno == indexRelation->rd_index->indkey.values[j]) + { + key[i].sk_attno = j + 1; + break; + } + } + if (j == IndexRelationGetNumberOfAttributes(indexRelation)) + elog(ERROR, "column is not in index"); + } + + sysscan->iscan = index_beginscan(heapRelation, indexRelation, + snapshot, nkeys, 0); + index_rescan(sysscan->iscan, key, nkeys, NULL, 0); + sysscan->scan = NULL; + + return sysscan; +} + +/* + * systable_getnext_ordered --- get next tuple in an ordered catalog scan + */ +HeapTuple +systable_getnext_ordered(SysScanDesc sysscan, ScanDirection direction) +{ + HeapTuple htup = NULL; + + Assert(sysscan->irel); + if (index_getnext_slot(sysscan->iscan, direction, sysscan->slot)) + htup = ExecFetchSlotHeapTuple(sysscan->slot, false, NULL); + + /* See notes in systable_getnext */ + if (htup && sysscan->iscan->xs_recheck) + elog(ERROR, "system catalog scans with lossy index conditions are not implemented"); + + return htup; +} + +/* + * systable_endscan_ordered --- close scan, release resources + */ +void +systable_endscan_ordered(SysScanDesc sysscan) +{ + if (sysscan->slot) + { + ExecDropSingleTupleTableSlot(sysscan->slot); + sysscan->slot = NULL; + } + + Assert(sysscan->irel); + index_endscan(sysscan->iscan); + if (sysscan->snapshot) + UnregisterSnapshot(sysscan->snapshot); + pfree(sysscan); +} diff --git a/src/backend/access/nbtree/nbtvalidate.c b/src/backend/access/nbtree/nbtvalidate.c index 0148ea7892..2b40b0e21c 100644 --- a/src/backend/access/nbtree/nbtvalidate.c +++ b/src/backend/access/nbtree/nbtvalidate.c @@ -13,8 +13,8 @@ */ #include "postgres.h" -#include "access/amvalidate.h" #include "access/htup_details.h" +#include "access/indexamvalidate.h" #include "access/nbtree.h" #include "catalog/pg_amop.h" #include "catalog/pg_amproc.h" diff --git a/src/backend/access/spgist/spgdoinsert.c b/src/backend/access/spgist/spgdoinsert.c index c34c44cd8b..42a894cc54 100644 --- a/src/backend/access/spgist/spgdoinsert.c +++ b/src/backend/access/spgist/spgdoinsert.c @@ -15,7 +15,7 @@ #include "postgres.h" -#include "access/genam.h" +#include "access/indexgenam.h" #include "access/spgist_private.h" #include "access/spgxlog.h" #include "access/xloginsert.h" diff --git a/src/backend/access/spgist/spginsert.c b/src/backend/access/spgist/spginsert.c index dd9088741c..043016fe8d 100644 --- a/src/backend/access/spgist/spginsert.c +++ b/src/backend/access/spgist/spginsert.c @@ -16,7 +16,7 @@ #include "postgres.h" -#include "access/genam.h" +#include "access/indexgenam.h" #include "access/spgist_private.h" #include "access/spgxlog.h" #include "access/tableam.h" diff --git a/src/backend/access/spgist/spgscan.c b/src/backend/access/spgist/spgscan.c index 6e940fd3de..8e5f012497 100644 --- a/src/backend/access/spgist/spgscan.c +++ b/src/backend/access/spgist/spgscan.c @@ -15,7 +15,7 @@ #include "postgres.h" -#include "access/genam.h" +#include "access/indexgenam.h" #include "access/relscan.h" #include "access/spgist_private.h" #include "miscadmin.h" diff --git a/src/backend/access/spgist/spgutils.c b/src/backend/access/spgist/spgutils.c index e2d391ee75..d01ea59e14 100644 --- a/src/backend/access/spgist/spgutils.c +++ b/src/backend/access/spgist/spgutils.c @@ -15,8 +15,8 @@ #include "postgres.h" -#include "access/amvalidate.h" #include "access/htup_details.h" +#include "access/indexamvalidate.h" #include "access/reloptions.h" #include "access/spgist_private.h" #include "access/transam.h" diff --git a/src/backend/access/spgist/spgvacuum.c b/src/backend/access/spgist/spgvacuum.c index 478d4c0d61..1b8cb9760f 100644 --- a/src/backend/access/spgist/spgvacuum.c +++ b/src/backend/access/spgist/spgvacuum.c @@ -15,7 +15,7 @@ #include "postgres.h" -#include "access/genam.h" +#include "access/indexgenam.h" #include "access/spgist_private.h" #include "access/spgxlog.h" #include "access/transam.h" diff --git a/src/backend/access/spgist/spgvalidate.c b/src/backend/access/spgist/spgvalidate.c index 4b9fdbd5d7..3a599db86c 100644 --- a/src/backend/access/spgist/spgvalidate.c +++ b/src/backend/access/spgist/spgvalidate.c @@ -13,8 +13,8 @@ */ #include "postgres.h" -#include "access/amvalidate.h" #include "access/htup_details.h" +#include "access/indexamvalidate.h" #include "access/spgist_private.h" #include "catalog/pg_amop.h" #include "catalog/pg_amproc.h" diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index 8ea033610d..9dcb7b66d3 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -17,9 +17,9 @@ #include #include -#include "access/genam.h" #include "access/heapam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/tableam.h" #include "access/xact.h" #include "access/xlog_internal.h" diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c index ea5666ebb8..b6dba91b9a 100644 --- a/src/backend/catalog/aclchk.c +++ b/src/backend/catalog/aclchk.c @@ -17,9 +17,9 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/heapam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/sysattr.h" #include "access/tableam.h" #include "access/xact.h" diff --git a/src/backend/catalog/catalog.c b/src/backend/catalog/catalog.c index 6b104695c0..c4c4d9f6c8 100644 --- a/src/backend/catalog/catalog.c +++ b/src/backend/catalog/catalog.c @@ -20,8 +20,8 @@ #include #include -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/sysattr.h" #include "access/table.h" #include "access/transam.h" diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index d07bb4496e..aea8cdde74 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -14,8 +14,8 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/table.h" #include "access/xact.h" #include "catalog/dependency.h" diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index 452a7f3f95..c9b3e17dc1 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -29,8 +29,8 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/multixact.h" #include "access/relation.h" #include "access/sysattr.h" diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 787aad636e..7529bf39b8 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -23,8 +23,8 @@ #include -#include "access/amapi.h" #include "access/heapam.h" +#include "access/indexam.h" #include "access/multixact.h" #include "access/relscan.h" #include "access/sysattr.h" diff --git a/src/backend/catalog/indexing.c b/src/backend/catalog/indexing.c index f237e62bc9..8f48e0076c 100644 --- a/src/backend/catalog/indexing.c +++ b/src/backend/catalog/indexing.c @@ -15,9 +15,9 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/heapam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "catalog/index.h" #include "catalog/indexing.h" #include "executor/executor.h" diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c index ae3002bb42..00a21c430c 100644 --- a/src/backend/catalog/objectaddress.c +++ b/src/backend/catalog/objectaddress.c @@ -15,7 +15,7 @@ #include "postgres.h" -#include "access/genam.h" +#include "access/indexgenam.h" #include "access/htup_details.h" #include "access/relation.h" #include "access/sysattr.h" diff --git a/src/backend/catalog/partition.c b/src/backend/catalog/partition.c index 7657608dd7..5f85b9b99c 100644 --- a/src/backend/catalog/partition.c +++ b/src/backend/catalog/partition.c @@ -15,8 +15,8 @@ #include "postgres.h" #include "access/attmap.h" -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/sysattr.h" #include "access/table.h" #include "catalog/indexing.h" diff --git a/src/backend/catalog/pg_collation.c b/src/backend/catalog/pg_collation.c index dd99d53547..ec5cea1bab 100644 --- a/src/backend/catalog/pg_collation.c +++ b/src/backend/catalog/pg_collation.c @@ -14,8 +14,8 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/sysattr.h" #include "access/table.h" #include "catalog/catalog.h" diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c index 25c52134f0..b12834a2c0 100644 --- a/src/backend/catalog/pg_constraint.c +++ b/src/backend/catalog/pg_constraint.c @@ -14,8 +14,8 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/sysattr.h" #include "access/table.h" #include "access/xact.h" diff --git a/src/backend/catalog/pg_db_role_setting.c b/src/backend/catalog/pg_db_role_setting.c index 20acac2eea..791fca9dee 100644 --- a/src/backend/catalog/pg_db_role_setting.c +++ b/src/backend/catalog/pg_db_role_setting.c @@ -10,9 +10,9 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/heapam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/tableam.h" #include "catalog/indexing.h" #include "catalog/objectaccess.h" diff --git a/src/backend/catalog/pg_depend.c b/src/backend/catalog/pg_depend.c index a060c25d2e..c9228cc907 100644 --- a/src/backend/catalog/pg_depend.c +++ b/src/backend/catalog/pg_depend.c @@ -14,8 +14,8 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/table.h" #include "catalog/dependency.h" #include "catalog/indexing.h" diff --git a/src/backend/catalog/pg_enum.c b/src/backend/catalog/pg_enum.c index be0f06524d..e43b145170 100644 --- a/src/backend/catalog/pg_enum.c +++ b/src/backend/catalog/pg_enum.c @@ -13,8 +13,8 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/table.h" #include "access/xact.h" #include "catalog/binary_upgrade.h" diff --git a/src/backend/catalog/pg_inherits.c b/src/backend/catalog/pg_inherits.c index 59af16221e..62622cc6f9 100644 --- a/src/backend/catalog/pg_inherits.c +++ b/src/backend/catalog/pg_inherits.c @@ -19,8 +19,8 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/table.h" #include "catalog/indexing.h" #include "catalog/pg_inherits.h" diff --git a/src/backend/catalog/pg_largeobject.c b/src/backend/catalog/pg_largeobject.c index 1a687028fe..2c3e15e6bc 100644 --- a/src/backend/catalog/pg_largeobject.c +++ b/src/backend/catalog/pg_largeobject.c @@ -14,8 +14,8 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/sysattr.h" #include "access/table.h" #include "catalog/catalog.h" diff --git a/src/backend/catalog/pg_publication.c b/src/backend/catalog/pg_publication.c index f6e9a68bf7..80a6a92a82 100644 --- a/src/backend/catalog/pg_publication.c +++ b/src/backend/catalog/pg_publication.c @@ -14,9 +14,9 @@ #include "postgres.h" -#include "access/genam.h" #include "access/heapam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/tableam.h" #include "access/xact.h" #include "catalog/catalog.h" diff --git a/src/backend/catalog/pg_range.c b/src/backend/catalog/pg_range.c index e6e138babd..c8808a78b3 100644 --- a/src/backend/catalog/pg_range.c +++ b/src/backend/catalog/pg_range.c @@ -14,8 +14,8 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/table.h" #include "catalog/dependency.h" #include "catalog/indexing.h" diff --git a/src/backend/catalog/pg_shdepend.c b/src/backend/catalog/pg_shdepend.c index 59f97bf3d0..89ebb849a2 100644 --- a/src/backend/catalog/pg_shdepend.c +++ b/src/backend/catalog/pg_shdepend.c @@ -14,8 +14,8 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/table.h" #include "access/xact.h" #include "catalog/catalog.h" diff --git a/src/backend/catalog/pg_subscription.c b/src/backend/catalog/pg_subscription.c index 68d88ff499..f346ec959f 100644 --- a/src/backend/catalog/pg_subscription.c +++ b/src/backend/catalog/pg_subscription.c @@ -14,9 +14,9 @@ #include "postgres.h" -#include "access/genam.h" #include "access/heapam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/tableam.h" #include "access/xact.h" #include "catalog/indexing.h" diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c index 71372ceb16..70ee89d52f 100644 --- a/src/backend/commands/analyze.c +++ b/src/backend/commands/analyze.c @@ -17,7 +17,7 @@ #include #include "access/detoast.h" -#include "access/genam.h" +#include "access/indexgenam.h" #include "access/multixact.h" #include "access/relation.h" #include "access/sysattr.h" diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c index b8c349f245..cc35811dc8 100644 --- a/src/backend/commands/cluster.c +++ b/src/backend/commands/cluster.c @@ -17,8 +17,8 @@ */ #include "postgres.h" -#include "access/amapi.h" #include "access/heapam.h" +#include "access/indexam.h" #include "access/multixact.h" #include "access/relscan.h" #include "access/tableam.h" diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c index 1859fb628f..7823dace9f 100644 --- a/src/backend/commands/comment.c +++ b/src/backend/commands/comment.c @@ -14,8 +14,8 @@ #include "postgres.h" -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/relation.h" #include "access/table.h" #include "catalog/indexing.h" diff --git a/src/backend/commands/constraint.c b/src/backend/commands/constraint.c index 806962a686..8a57a0ef99 100644 --- a/src/backend/commands/constraint.c +++ b/src/backend/commands/constraint.c @@ -13,8 +13,8 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/heapam.h" +#include "access/indexgenam.h" #include "access/tableam.h" #include "catalog/index.h" #include "commands/trigger.h" diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c index a70e75a219..da0e5d8b94 100644 --- a/src/backend/commands/dbcommands.c +++ b/src/backend/commands/dbcommands.c @@ -23,9 +23,9 @@ #include #include -#include "access/genam.h" #include "access/heapam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/multixact.h" #include "access/tableam.h" #include "access/xact.h" diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c index 6eaa9cc4f3..df04a82fe5 100644 --- a/src/backend/commands/extension.c +++ b/src/backend/commands/extension.c @@ -29,8 +29,8 @@ #include #include -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/relation.h" #include "access/sysattr.h" #include "access/table.h" diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index 94411b5008..4527aa15f7 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -32,8 +32,8 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/sysattr.h" #include "access/table.h" #include "catalog/catalog.h" diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index 8f242aef1e..940aa97323 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -15,9 +15,9 @@ #include "postgres.h" -#include "access/amapi.h" #include "access/heapam.h" #include "access/htup_details.h" +#include "access/indexam.h" #include "access/reloptions.h" #include "access/sysattr.h" #include "access/tableam.h" diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c index 537d0e8cef..907c71dda0 100644 --- a/src/backend/commands/matview.c +++ b/src/backend/commands/matview.c @@ -14,9 +14,9 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/heapam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/multixact.h" #include "access/tableam.h" #include "access/xact.h" diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c index cb7a6bd2d1..cccd95a97a 100644 --- a/src/backend/commands/opclasscmds.c +++ b/src/backend/commands/opclasscmds.c @@ -17,9 +17,9 @@ #include -#include "access/genam.h" #include "access/hash.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/nbtree.h" #include "access/sysattr.h" #include "access/table.h" diff --git a/src/backend/commands/policy.c b/src/backend/commands/policy.c index 36093dcd95..72ba997e4c 100644 --- a/src/backend/commands/policy.c +++ b/src/backend/commands/policy.c @@ -12,9 +12,9 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/htup.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/relation.h" #include "access/sysattr.h" #include "access/table.h" diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c index b51c373b93..0182dc7202 100644 --- a/src/backend/commands/proclang.c +++ b/src/backend/commands/proclang.c @@ -13,8 +13,8 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/table.h" #include "catalog/catalog.h" #include "catalog/dependency.h" diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c index fbf11c86aa..4252db4ec0 100644 --- a/src/backend/commands/publicationcmds.c +++ b/src/backend/commands/publicationcmds.c @@ -14,8 +14,8 @@ #include "postgres.h" -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/table.h" #include "access/xact.h" #include "catalog/catalog.h" diff --git a/src/backend/commands/seclabel.c b/src/backend/commands/seclabel.c index 63219ad589..94d28b24fc 100644 --- a/src/backend/commands/seclabel.c +++ b/src/backend/commands/seclabel.c @@ -10,8 +10,8 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/relation.h" #include "access/table.h" #include "catalog/catalog.h" diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 53a8f1610a..a776e652f4 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -15,9 +15,9 @@ #include "postgres.h" #include "access/attmap.h" -#include "access/genam.h" #include "access/heapam.h" #include "access/heapam_xlog.h" +#include "access/indexgenam.h" #include "access/multixact.h" #include "access/reloptions.h" #include "access/relscan.h" diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 99cb5bf557..7e9bcb317d 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -13,8 +13,8 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/relation.h" #include "access/sysattr.h" #include "access/table.h" diff --git a/src/backend/commands/tsearchcmds.c b/src/backend/commands/tsearchcmds.c index 5d6528f9cf..714dff5304 100644 --- a/src/backend/commands/tsearchcmds.c +++ b/src/backend/commands/tsearchcmds.c @@ -17,8 +17,8 @@ #include -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/table.h" #include "access/xact.h" #include "catalog/catalog.h" diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index 89887b8fd7..d3df657fa0 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -31,9 +31,9 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/heapam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/tableam.h" #include "access/xact.h" #include "catalog/binary_upgrade.h" diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c index aab5aa855d..f3572b1749 100644 --- a/src/backend/commands/user.c +++ b/src/backend/commands/user.c @@ -12,8 +12,8 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/table.h" #include "access/xact.h" #include "catalog/binary_upgrade.h" diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index da1da23400..477b271aa3 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -24,9 +24,9 @@ #include "access/clog.h" #include "access/commit_ts.h" -#include "access/genam.h" #include "access/heapam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/multixact.h" #include "access/tableam.h" #include "access/transam.h" diff --git a/src/backend/executor/execAmi.c b/src/backend/executor/execAmi.c index 779d3dccea..c1e2cedc08 100644 --- a/src/backend/executor/execAmi.c +++ b/src/backend/executor/execAmi.c @@ -12,8 +12,8 @@ */ #include "postgres.h" -#include "access/amapi.h" #include "access/htup_details.h" +#include "access/indexam.h" #include "executor/execdebug.h" #include "executor/nodeAgg.h" #include "executor/nodeAppend.h" diff --git a/src/backend/executor/execCurrent.c b/src/backend/executor/execCurrent.c index c7f909241b..3853d154d8 100644 --- a/src/backend/executor/execCurrent.c +++ b/src/backend/executor/execCurrent.c @@ -12,7 +12,7 @@ */ #include "postgres.h" -#include "access/genam.h" +#include "access/indexgenam.h" #include "access/relscan.h" #include "access/sysattr.h" #include "catalog/pg_type.h" diff --git a/src/backend/executor/execIndexing.c b/src/backend/executor/execIndexing.c index 40bd8049f0..823b670760 100644 --- a/src/backend/executor/execIndexing.c +++ b/src/backend/executor/execIndexing.c @@ -106,7 +106,7 @@ */ #include "postgres.h" -#include "access/genam.h" +#include "access/indexgenam.h" #include "access/relscan.h" #include "access/tableam.h" #include "access/xact.h" diff --git a/src/backend/executor/execReplication.c b/src/backend/executor/execReplication.c index 95e027c970..f311476071 100644 --- a/src/backend/executor/execReplication.c +++ b/src/backend/executor/execReplication.c @@ -14,7 +14,7 @@ #include "postgres.h" -#include "access/genam.h" +#include "access/indexgenam.h" #include "access/relscan.h" #include "access/tableam.h" #include "access/transam.h" diff --git a/src/backend/executor/nodeBitmapIndexscan.c b/src/backend/executor/nodeBitmapIndexscan.c index 604f4f1132..fbe434ce2f 100644 --- a/src/backend/executor/nodeBitmapIndexscan.c +++ b/src/backend/executor/nodeBitmapIndexscan.c @@ -21,7 +21,7 @@ */ #include "postgres.h" -#include "access/genam.h" +#include "access/indexgenam.h" #include "executor/execdebug.h" #include "executor/nodeBitmapIndexscan.h" #include "executor/nodeIndexscan.h" diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c index 784486f0c8..a4ea390d2b 100644 --- a/src/backend/executor/nodeIndexonlyscan.c +++ b/src/backend/executor/nodeIndexonlyscan.c @@ -30,7 +30,7 @@ */ #include "postgres.h" -#include "access/genam.h" +#include "access/indexgenam.h" #include "access/relscan.h" #include "access/tableam.h" #include "access/tupdesc.h" diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index c5f6593485..2911c7a461 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -73,8 +73,8 @@ #include -#include "access/amapi.h" #include "access/htup_details.h" +#include "access/indexam.h" #include "access/tsmapi.h" #include "executor/executor.h" #include "executor/nodeHash.h" @@ -539,7 +539,7 @@ cost_index(IndexPath *path, PlannerInfo *root, double loop_count, * for scanning the index, as well as the selectivity of the index (ie, * the fraction of main-table tuples we will have to retrieve) and its * correlation to the main-table tuple order. We need a cast here because - * pathnodes.h uses a weak function type to avoid including amapi.h. + * pathnodes.h uses a weak function type to avoid including indexam.h. */ amcostestimate = (amcostestimate_function) index->amcostestimate; amcostestimate(root, path, loop_count, diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index cb54b15507..d63ebb7287 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -18,8 +18,8 @@ #include #include -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/parallel.h" #include "access/sysattr.h" #include "access/table.h" diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 5e889d1861..c15654e660 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -17,8 +17,8 @@ #include -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/nbtree.h" #include "access/sysattr.h" #include "access/table.h" diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index 45bb31ecf8..3fafa920f3 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -26,8 +26,8 @@ #include "postgres.h" -#include "access/amapi.h" #include "access/htup_details.h" +#include "access/indexam.h" #include "access/relation.h" #include "access/reloptions.h" #include "access/table.h" diff --git a/src/backend/partitioning/partdesc.c b/src/backend/partitioning/partdesc.c index 6ede084afe..5ca63d02b7 100644 --- a/src/backend/partitioning/partdesc.c +++ b/src/backend/partitioning/partdesc.c @@ -14,8 +14,8 @@ #include "postgres.h" -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/table.h" #include "catalog/indexing.h" #include "catalog/partition.h" diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c index fffc330c94..f965bdb027 100644 --- a/src/backend/replication/logical/origin.c +++ b/src/backend/replication/logical/origin.c @@ -70,8 +70,8 @@ #include #include -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/table.h" #include "access/xact.h" #include "catalog/catalog.h" diff --git a/src/backend/rewrite/rewriteRemove.c b/src/backend/rewrite/rewriteRemove.c index bb98b6936a..6dbe010f6a 100644 --- a/src/backend/rewrite/rewriteRemove.c +++ b/src/backend/rewrite/rewriteRemove.c @@ -14,8 +14,8 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/sysattr.h" #include "access/table.h" #include "catalog/catalog.h" diff --git a/src/backend/statistics/extended_stats.c b/src/backend/statistics/extended_stats.c index 9d339433f6..98b70760ad 100644 --- a/src/backend/statistics/extended_stats.c +++ b/src/backend/statistics/extended_stats.c @@ -17,8 +17,8 @@ #include "postgres.h" #include "access/detoast.h" -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/table.h" #include "catalog/indexing.h" #include "catalog/pg_collation.h" diff --git a/src/backend/storage/large_object/inv_api.c b/src/backend/storage/large_object/inv_api.c index 263d5be12e..cd82362287 100644 --- a/src/backend/storage/large_object/inv_api.c +++ b/src/backend/storage/large_object/inv_api.c @@ -33,8 +33,8 @@ #include #include "access/detoast.h" -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/sysattr.h" #include "access/table.h" #include "access/xact.h" diff --git a/src/backend/utils/adt/amutils.c b/src/backend/utils/adt/amutils.c index e81d6cc056..6de33886db 100644 --- a/src/backend/utils/adt/amutils.c +++ b/src/backend/utils/adt/amutils.c @@ -13,8 +13,8 @@ */ #include "postgres.h" -#include "access/amapi.h" #include "access/htup_details.h" +#include "access/indexam.h" #include "catalog/pg_class.h" #include "catalog/pg_index.h" #include "utils/builtins.h" diff --git a/src/backend/utils/adt/enum.c b/src/backend/utils/adt/enum.c index 3402ff860d..000572c5b3 100644 --- a/src/backend/utils/adt/enum.c +++ b/src/backend/utils/adt/enum.c @@ -13,8 +13,8 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/table.h" #include "catalog/indexing.h" #include "catalog/pg_enum.h" diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 4af1603e7c..bdf78db8c8 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -19,8 +19,8 @@ #include #include -#include "access/amapi.h" #include "access/htup_details.h" +#include "access/indexam.h" #include "access/relation.h" #include "access/sysattr.h" #include "access/table.h" diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c index c3e7d94aa5..9ce04af9a9 100644 --- a/src/backend/utils/cache/catcache.c +++ b/src/backend/utils/cache/catcache.c @@ -14,8 +14,8 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/heaptoast.h" +#include "access/indexgenam.h" #include "access/relscan.h" #include "access/sysattr.h" #include "access/table.h" diff --git a/src/backend/utils/cache/evtcache.c b/src/backend/utils/cache/evtcache.c index 1b0f738321..510160c887 100644 --- a/src/backend/utils/cache/evtcache.c +++ b/src/backend/utils/cache/evtcache.c @@ -13,8 +13,8 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/relation.h" #include "catalog/indexing.h" #include "catalog/pg_event_trigger.h" diff --git a/src/backend/utils/cache/relfilenodemap.c b/src/backend/utils/cache/relfilenodemap.c index d244eaf4d8..693501067a 100644 --- a/src/backend/utils/cache/relfilenodemap.c +++ b/src/backend/utils/cache/relfilenodemap.c @@ -13,8 +13,8 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/table.h" #include "catalog/indexing.h" #include "catalog/pg_class.h" diff --git a/src/backend/utils/cache/ts_cache.c b/src/backend/utils/cache/ts_cache.c index 68c04d87d5..487d3cadee 100644 --- a/src/backend/utils/cache/ts_cache.c +++ b/src/backend/utils/cache/ts_cache.c @@ -26,8 +26,8 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/table.h" #include "access/xact.h" #include "catalog/indexing.h" diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index cc38669a1e..5375653a42 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -19,9 +19,9 @@ #include #include -#include "access/genam.h" #include "access/heapam.h" #include "access/htup_details.h" +#include "access/indexgenam.h" #include "access/session.h" #include "access/sysattr.h" #include "access/tableam.h" diff --git a/src/include/access/amapi.h b/src/include/access/amapi.h deleted file mode 100644 index 6e3db06eed..0000000000 --- a/src/include/access/amapi.h +++ /dev/null @@ -1,240 +0,0 @@ -/*------------------------------------------------------------------------- - * - * amapi.h - * API for Postgres index access methods. - * - * Copyright (c) 2015-2019, PostgreSQL Global Development Group - * - * src/include/access/amapi.h - * - *------------------------------------------------------------------------- - */ -#ifndef AMAPI_H -#define AMAPI_H - -#include "access/genam.h" - -/* - * We don't wish to include planner header files here, since most of an index - * AM's implementation isn't concerned with those data structures. To allow - * declaring amcostestimate_function here, use forward struct references. - */ -struct PlannerInfo; -struct IndexPath; - -/* Likewise, this file shouldn't depend on execnodes.h. */ -struct IndexInfo; - - -/* - * Properties for amproperty API. This list covers properties known to the - * core code, but an index AM can define its own properties, by matching the - * string property name. - */ -typedef enum IndexAMProperty -{ - AMPROP_UNKNOWN = 0, /* anything not known to core code */ - AMPROP_ASC, /* column properties */ - AMPROP_DESC, - AMPROP_NULLS_FIRST, - AMPROP_NULLS_LAST, - AMPROP_ORDERABLE, - AMPROP_DISTANCE_ORDERABLE, - AMPROP_RETURNABLE, - AMPROP_SEARCH_ARRAY, - AMPROP_SEARCH_NULLS, - AMPROP_CLUSTERABLE, /* index properties */ - AMPROP_INDEX_SCAN, - AMPROP_BITMAP_SCAN, - AMPROP_BACKWARD_SCAN, - AMPROP_CAN_ORDER, /* AM properties */ - AMPROP_CAN_UNIQUE, - AMPROP_CAN_MULTI_COL, - AMPROP_CAN_EXCLUDE, - AMPROP_CAN_INCLUDE -} IndexAMProperty; - - -/* - * Callback function signatures --- see indexam.sgml for more info. - */ - -/* build new index */ -typedef IndexBuildResult *(*ambuild_function) (Relation heapRelation, - Relation indexRelation, - struct IndexInfo *indexInfo); - -/* build empty index */ -typedef void (*ambuildempty_function) (Relation indexRelation); - -/* insert this tuple */ -typedef bool (*aminsert_function) (Relation indexRelation, - Datum *values, - bool *isnull, - ItemPointer heap_tid, - Relation heapRelation, - IndexUniqueCheck checkUnique, - struct IndexInfo *indexInfo); - -/* bulk delete */ -typedef IndexBulkDeleteResult *(*ambulkdelete_function) (IndexVacuumInfo *info, - IndexBulkDeleteResult *stats, - IndexBulkDeleteCallback callback, - void *callback_state); - -/* post-VACUUM cleanup */ -typedef IndexBulkDeleteResult *(*amvacuumcleanup_function) (IndexVacuumInfo *info, - IndexBulkDeleteResult *stats); - -/* can indexscan return IndexTuples? */ -typedef bool (*amcanreturn_function) (Relation indexRelation, int attno); - -/* estimate cost of an indexscan */ -typedef void (*amcostestimate_function) (struct PlannerInfo *root, - struct IndexPath *path, - double loop_count, - Cost *indexStartupCost, - Cost *indexTotalCost, - Selectivity *indexSelectivity, - double *indexCorrelation, - double *indexPages); - -/* parse index reloptions */ -typedef bytea *(*amoptions_function) (Datum reloptions, - bool validate); - -/* report AM, index, or index column property */ -typedef bool (*amproperty_function) (Oid index_oid, int attno, - IndexAMProperty prop, const char *propname, - bool *res, bool *isnull); - -/* name of phase as used in progress reporting */ -typedef char *(*ambuildphasename_function) (int64 phasenum); - -/* validate definition of an opclass for this AM */ -typedef bool (*amvalidate_function) (Oid opclassoid); - -/* prepare for index scan */ -typedef IndexScanDesc (*ambeginscan_function) (Relation indexRelation, - int nkeys, - int norderbys); - -/* (re)start index scan */ -typedef void (*amrescan_function) (IndexScanDesc scan, - ScanKey keys, - int nkeys, - ScanKey orderbys, - int norderbys); - -/* next valid tuple */ -typedef bool (*amgettuple_function) (IndexScanDesc scan, - ScanDirection direction); - -/* fetch all valid tuples */ -typedef int64 (*amgetbitmap_function) (IndexScanDesc scan, - TIDBitmap *tbm); - -/* end index scan */ -typedef void (*amendscan_function) (IndexScanDesc scan); - -/* mark current scan position */ -typedef void (*ammarkpos_function) (IndexScanDesc scan); - -/* restore marked scan position */ -typedef void (*amrestrpos_function) (IndexScanDesc scan); - -/* - * Callback function signatures - for parallel index scans. - */ - -/* estimate size of parallel scan descriptor */ -typedef Size (*amestimateparallelscan_function) (void); - -/* prepare for parallel index scan */ -typedef void (*aminitparallelscan_function) (void *target); - -/* (re)start parallel index scan */ -typedef void (*amparallelrescan_function) (IndexScanDesc scan); - -/* - * API struct for an index AM. Note this must be stored in a single palloc'd - * chunk of memory. - */ -typedef struct IndexAmRoutine -{ - NodeTag type; - - /* - * Total number of strategies (operators) by which we can traverse/search - * this AM. Zero if AM does not have a fixed set of strategy assignments. - */ - uint16 amstrategies; - /* total number of support functions that this AM uses */ - uint16 amsupport; - /* does AM support ORDER BY indexed column's value? */ - bool amcanorder; - /* does AM support ORDER BY result of an operator on indexed column? */ - bool amcanorderbyop; - /* does AM support backward scanning? */ - bool amcanbackward; - /* does AM support UNIQUE indexes? */ - bool amcanunique; - /* does AM support multi-column indexes? */ - bool amcanmulticol; - /* does AM require scans to have a constraint on the first index column? */ - bool amoptionalkey; - /* does AM handle ScalarArrayOpExpr quals? */ - bool amsearcharray; - /* does AM handle IS NULL/IS NOT NULL quals? */ - bool amsearchnulls; - /* can index storage data type differ from column data type? */ - bool amstorage; - /* can an index of this type be clustered on? */ - bool amclusterable; - /* does AM handle predicate locks? */ - bool ampredlocks; - /* does AM support parallel scan? */ - bool amcanparallel; - /* does AM support columns included with clause INCLUDE? */ - bool amcaninclude; - /* type of data stored in index, or InvalidOid if variable */ - Oid amkeytype; - - /* - * If you add new properties to either the above or the below lists, then - * they should also (usually) be exposed via the property API (see - * IndexAMProperty at the top of the file, and utils/adt/amutils.c). - */ - - /* interface functions */ - ambuild_function ambuild; - ambuildempty_function ambuildempty; - aminsert_function aminsert; - ambulkdelete_function ambulkdelete; - amvacuumcleanup_function amvacuumcleanup; - amcanreturn_function amcanreturn; /* can be NULL */ - amcostestimate_function amcostestimate; - amoptions_function amoptions; - amproperty_function amproperty; /* can be NULL */ - ambuildphasename_function ambuildphasename; /* can be NULL */ - amvalidate_function amvalidate; - ambeginscan_function ambeginscan; - amrescan_function amrescan; - amgettuple_function amgettuple; /* can be NULL */ - amgetbitmap_function amgetbitmap; /* can be NULL */ - amendscan_function amendscan; - ammarkpos_function ammarkpos; /* can be NULL */ - amrestrpos_function amrestrpos; /* can be NULL */ - - /* interface functions to support parallel index scans */ - amestimateparallelscan_function amestimateparallelscan; /* can be NULL */ - aminitparallelscan_function aminitparallelscan; /* can be NULL */ - amparallelrescan_function amparallelrescan; /* can be NULL */ -} IndexAmRoutine; - - -/* Functions in access/index/amapi.c */ -extern IndexAmRoutine *GetIndexAmRoutine(Oid amhandler); -extern IndexAmRoutine *GetIndexAmRoutineByAmId(Oid amoid, bool noerror); - -#endif /* AMAPI_H */ diff --git a/src/include/access/amvalidate.h b/src/include/access/amvalidate.h deleted file mode 100644 index 317e1e6893..0000000000 --- a/src/include/access/amvalidate.h +++ /dev/null @@ -1,36 +0,0 @@ -/*------------------------------------------------------------------------- - * - * amvalidate.h - * Support routines for index access methods' amvalidate functions. - * - * Copyright (c) 2016-2019, PostgreSQL Global Development Group - * - * src/include/access/amvalidate.h - * - *------------------------------------------------------------------------- - */ -#ifndef AMVALIDATE_H -#define AMVALIDATE_H - -#include "utils/catcache.h" - - -/* Struct returned (in a list) by identify_opfamily_groups() */ -typedef struct OpFamilyOpFuncGroup -{ - Oid lefttype; /* amoplefttype/amproclefttype */ - Oid righttype; /* amoprighttype/amprocrighttype */ - uint64 operatorset; /* bitmask of operators with these types */ - uint64 functionset; /* bitmask of support funcs with these types */ -} OpFamilyOpFuncGroup; - - -/* Functions in access/index/amvalidate.c */ -extern List *identify_opfamily_groups(CatCList *oprlist, CatCList *proclist); -extern bool check_amproc_signature(Oid funcid, Oid restype, bool exact, - int minargs, int maxargs,...); -extern bool check_amop_signature(Oid opno, Oid restype, - Oid lefttype, Oid righttype); -extern bool opfamily_can_sort_type(Oid opfamilyoid, Oid datatypeoid); - -#endif /* AMVALIDATE_H */ diff --git a/src/include/access/brin_internal.h b/src/include/access/brin_internal.h index b1c9199946..f78387d891 100644 --- a/src/include/access/brin_internal.h +++ b/src/include/access/brin_internal.h @@ -11,7 +11,7 @@ #ifndef BRIN_INTERNAL_H #define BRIN_INTERNAL_H -#include "access/amapi.h" +#include "access/indexam.h" #include "storage/bufpage.h" #include "utils/typcache.h" diff --git a/src/include/access/genam.h b/src/include/access/genam.h deleted file mode 100644 index a813b004be..0000000000 --- a/src/include/access/genam.h +++ /dev/null @@ -1,225 +0,0 @@ -/*------------------------------------------------------------------------- - * - * genam.h - * POSTGRES generalized index access method definitions. - * - * - * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * src/include/access/genam.h - * - *------------------------------------------------------------------------- - */ -#ifndef GENAM_H -#define GENAM_H - -#include "access/sdir.h" -#include "access/skey.h" -#include "nodes/tidbitmap.h" -#include "storage/lockdefs.h" -#include "utils/relcache.h" -#include "utils/snapshot.h" - -/* We don't want this file to depend on execnodes.h. */ -struct IndexInfo; - -/* - * Struct for statistics returned by ambuild - */ -typedef struct IndexBuildResult -{ - double heap_tuples; /* # of tuples seen in parent table */ - double index_tuples; /* # of tuples inserted into index */ -} IndexBuildResult; - -/* - * Struct for input arguments passed to ambulkdelete and amvacuumcleanup - * - * num_heap_tuples is accurate only when estimated_count is false; - * otherwise it's just an estimate (currently, the estimate is the - * prior value of the relation's pg_class.reltuples field). It will - * always just be an estimate during ambulkdelete. - */ -typedef struct IndexVacuumInfo -{ - Relation index; /* the index being vacuumed */ - bool analyze_only; /* ANALYZE (without any actual vacuum) */ - bool report_progress; /* emit progress.h status reports */ - bool estimated_count; /* num_heap_tuples is an estimate */ - int message_level; /* ereport level for progress messages */ - double num_heap_tuples; /* tuples remaining in heap */ - BufferAccessStrategy strategy; /* access strategy for reads */ -} IndexVacuumInfo; - -/* - * Struct for statistics returned by ambulkdelete and amvacuumcleanup - * - * This struct is normally allocated by the first ambulkdelete call and then - * passed along through subsequent ones until amvacuumcleanup; however, - * amvacuumcleanup must be prepared to allocate it in the case where no - * ambulkdelete calls were made (because no tuples needed deletion). - * Note that an index AM could choose to return a larger struct - * of which this is just the first field; this provides a way for ambulkdelete - * to communicate additional private data to amvacuumcleanup. - * - * Note: pages_removed is the amount by which the index physically shrank, - * if any (ie the change in its total size on disk). pages_deleted and - * pages_free refer to free space within the index file. Some index AMs - * may compute num_index_tuples by reference to num_heap_tuples, in which - * case they should copy the estimated_count field from IndexVacuumInfo. - */ -typedef struct IndexBulkDeleteResult -{ - BlockNumber num_pages; /* pages remaining in index */ - BlockNumber pages_removed; /* # removed during vacuum operation */ - bool estimated_count; /* num_index_tuples is an estimate */ - double num_index_tuples; /* tuples remaining */ - double tuples_removed; /* # removed during vacuum operation */ - BlockNumber pages_deleted; /* # unused pages in index */ - BlockNumber pages_free; /* # pages available for reuse */ -} IndexBulkDeleteResult; - -/* Typedef for callback function to determine if a tuple is bulk-deletable */ -typedef bool (*IndexBulkDeleteCallback) (ItemPointer itemptr, void *state); - -/* struct definitions appear in relscan.h */ -typedef struct IndexScanDescData *IndexScanDesc; -typedef struct SysScanDescData *SysScanDesc; - -typedef struct ParallelIndexScanDescData *ParallelIndexScanDesc; - -/* - * Enumeration specifying the type of uniqueness check to perform in - * index_insert(). - * - * UNIQUE_CHECK_YES is the traditional Postgres immediate check, possibly - * blocking to see if a conflicting transaction commits. - * - * For deferrable unique constraints, UNIQUE_CHECK_PARTIAL is specified at - * insertion time. The index AM should test if the tuple is unique, but - * should not throw error, block, or prevent the insertion if the tuple - * appears not to be unique. We'll recheck later when it is time for the - * constraint to be enforced. The AM must return true if the tuple is - * known unique, false if it is possibly non-unique. In the "true" case - * it is safe to omit the later recheck. - * - * When it is time to recheck the deferred constraint, a pseudo-insertion - * call is made with UNIQUE_CHECK_EXISTING. The tuple is already in the - * index in this case, so it should not be inserted again. Rather, just - * check for conflicting live tuples (possibly blocking). - */ -typedef enum IndexUniqueCheck -{ - UNIQUE_CHECK_NO, /* Don't do any uniqueness checking */ - UNIQUE_CHECK_YES, /* Enforce uniqueness at insertion time */ - UNIQUE_CHECK_PARTIAL, /* Test uniqueness, but no error */ - UNIQUE_CHECK_EXISTING /* Check if existing tuple is unique */ -} IndexUniqueCheck; - - -/* Nullable "ORDER BY col op const" distance */ -typedef struct IndexOrderByDistance -{ - double value; - bool isnull; -} IndexOrderByDistance; - -/* - * generalized index_ interface routines (in indexam.c) - */ - -/* - * IndexScanIsValid - * True iff the index scan is valid. - */ -#define IndexScanIsValid(scan) PointerIsValid(scan) - -extern Relation index_open(Oid relationId, LOCKMODE lockmode); -extern void index_close(Relation relation, LOCKMODE lockmode); - -extern bool index_insert(Relation indexRelation, - Datum *values, bool *isnull, - ItemPointer heap_t_ctid, - Relation heapRelation, - IndexUniqueCheck checkUnique, - struct IndexInfo *indexInfo); - -extern IndexScanDesc index_beginscan(Relation heapRelation, - Relation indexRelation, - Snapshot snapshot, - int nkeys, int norderbys); -extern IndexScanDesc index_beginscan_bitmap(Relation indexRelation, - Snapshot snapshot, - int nkeys); -extern void index_rescan(IndexScanDesc scan, - ScanKey keys, int nkeys, - ScanKey orderbys, int norderbys); -extern void index_endscan(IndexScanDesc scan); -extern void index_markpos(IndexScanDesc scan); -extern void index_restrpos(IndexScanDesc scan); -extern Size index_parallelscan_estimate(Relation indexrel, Snapshot snapshot); -extern void index_parallelscan_initialize(Relation heaprel, Relation indexrel, - Snapshot snapshot, ParallelIndexScanDesc target); -extern void index_parallelrescan(IndexScanDesc scan); -extern IndexScanDesc index_beginscan_parallel(Relation heaprel, - Relation indexrel, int nkeys, int norderbys, - ParallelIndexScanDesc pscan); -extern ItemPointer index_getnext_tid(IndexScanDesc scan, - ScanDirection direction); -struct TupleTableSlot; -extern bool index_fetch_heap(IndexScanDesc scan, struct TupleTableSlot *slot); -extern bool index_getnext_slot(IndexScanDesc scan, ScanDirection direction, - struct TupleTableSlot *slot); -extern int64 index_getbitmap(IndexScanDesc scan, TIDBitmap *bitmap); - -extern IndexBulkDeleteResult *index_bulk_delete(IndexVacuumInfo *info, - IndexBulkDeleteResult *stats, - IndexBulkDeleteCallback callback, - void *callback_state); -extern IndexBulkDeleteResult *index_vacuum_cleanup(IndexVacuumInfo *info, - IndexBulkDeleteResult *stats); -extern bool index_can_return(Relation indexRelation, int attno); -extern RegProcedure index_getprocid(Relation irel, AttrNumber attnum, - uint16 procnum); -extern FmgrInfo *index_getprocinfo(Relation irel, AttrNumber attnum, - uint16 procnum); -extern void index_store_float8_orderby_distances(IndexScanDesc scan, - Oid *orderByTypes, - IndexOrderByDistance *distances, - bool recheckOrderBy); - -/* - * index access method support routines (in genam.c) - */ -extern IndexScanDesc RelationGetIndexScan(Relation indexRelation, - int nkeys, int norderbys); -extern void IndexScanEnd(IndexScanDesc scan); -extern char *BuildIndexValueDescription(Relation indexRelation, - Datum *values, bool *isnull); -extern TransactionId index_compute_xid_horizon_for_tuples(Relation irel, - Relation hrel, - Buffer ibuf, - OffsetNumber *itemnos, - int nitems); - -/* - * heap-or-index access to system catalogs (in genam.c) - */ -extern SysScanDesc systable_beginscan(Relation heapRelation, - Oid indexId, - bool indexOK, - Snapshot snapshot, - int nkeys, ScanKey key); -extern HeapTuple systable_getnext(SysScanDesc sysscan); -extern bool systable_recheck_tuple(SysScanDesc sysscan, HeapTuple tup); -extern void systable_endscan(SysScanDesc sysscan); -extern SysScanDesc systable_beginscan_ordered(Relation heapRelation, - Relation indexRelation, - Snapshot snapshot, - int nkeys, ScanKey key); -extern HeapTuple systable_getnext_ordered(SysScanDesc sysscan, - ScanDirection direction); -extern void systable_endscan_ordered(SysScanDesc sysscan); - -#endif /* GENAM_H */ diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h index b779cc8c7c..8a8ab3b94e 100644 --- a/src/include/access/gin_private.h +++ b/src/include/access/gin_private.h @@ -10,9 +10,9 @@ #ifndef GIN_PRIVATE_H #define GIN_PRIVATE_H -#include "access/amapi.h" #include "access/gin.h" #include "access/ginblock.h" +#include "access/indexam.h" #include "access/itup.h" #include "catalog/pg_am_d.h" #include "fmgr.h" diff --git a/src/include/access/gist_private.h b/src/include/access/gist_private.h index a409975db1..b89107d09e 100644 --- a/src/include/access/gist_private.h +++ b/src/include/access/gist_private.h @@ -14,14 +14,14 @@ #ifndef GIST_PRIVATE_H #define GIST_PRIVATE_H -#include "access/amapi.h" #include "access/gist.h" +#include "access/indexam.h" +#include "access/indexgenam.h" #include "access/itup.h" #include "lib/pairingheap.h" #include "storage/bufmgr.h" #include "storage/buffile.h" #include "utils/hsearch.h" -#include "access/genam.h" /* * Maximum number of "halves" a page can be split into in one operation. diff --git a/src/include/access/gistscan.h b/src/include/access/gistscan.h index c02445a698..bec23b4604 100644 --- a/src/include/access/gistscan.h +++ b/src/include/access/gistscan.h @@ -14,7 +14,7 @@ #ifndef GISTSCAN_H #define GISTSCAN_H -#include "access/amapi.h" +#include "access/indexam.h" extern IndexScanDesc gistbeginscan(Relation r, int nkeys, int norderbys); extern void gistrescan(IndexScanDesc scan, ScanKey key, int nkeys, diff --git a/src/include/access/hash.h b/src/include/access/hash.h index ba58cb31bb..07db6466ae 100644 --- a/src/include/access/hash.h +++ b/src/include/access/hash.h @@ -17,7 +17,7 @@ #ifndef HASH_H #define HASH_H -#include "access/amapi.h" +#include "access/indexam.h" #include "access/itup.h" #include "access/sdir.h" #include "catalog/pg_am_d.h" diff --git a/src/include/access/indexam.h b/src/include/access/indexam.h new file mode 100644 index 0000000000..9b2eefb531 --- /dev/null +++ b/src/include/access/indexam.h @@ -0,0 +1,240 @@ +/*------------------------------------------------------------------------- + * + * indexam.h + * API for Postgres index access methods. + * + * Copyright (c) 2015-2019, PostgreSQL Global Development Group + * + * src/include/access/indexam.h + * + *------------------------------------------------------------------------- + */ +#ifndef INDEXAM_H +#define INDEXAM_H + +#include "access/indexgenam.h" + +/* + * We don't wish to include planner header files here, since most of an index + * AM's implementation isn't concerned with those data structures. To allow + * declaring amcostestimate_function here, use forward struct references. + */ +struct PlannerInfo; +struct IndexPath; + +/* Likewise, this file shouldn't depend on execnodes.h. */ +struct IndexInfo; + + +/* + * Properties for amproperty API. This list covers properties known to the + * core code, but an index AM can define its own properties, by matching the + * string property name. + */ +typedef enum IndexAMProperty +{ + AMPROP_UNKNOWN = 0, /* anything not known to core code */ + AMPROP_ASC, /* column properties */ + AMPROP_DESC, + AMPROP_NULLS_FIRST, + AMPROP_NULLS_LAST, + AMPROP_ORDERABLE, + AMPROP_DISTANCE_ORDERABLE, + AMPROP_RETURNABLE, + AMPROP_SEARCH_ARRAY, + AMPROP_SEARCH_NULLS, + AMPROP_CLUSTERABLE, /* index properties */ + AMPROP_INDEX_SCAN, + AMPROP_BITMAP_SCAN, + AMPROP_BACKWARD_SCAN, + AMPROP_CAN_ORDER, /* AM properties */ + AMPROP_CAN_UNIQUE, + AMPROP_CAN_MULTI_COL, + AMPROP_CAN_EXCLUDE, + AMPROP_CAN_INCLUDE +} IndexAMProperty; + + +/* + * Callback function signatures --- see indexam.sgml for more info. + */ + +/* build new index */ +typedef IndexBuildResult *(*ambuild_function) (Relation heapRelation, + Relation indexRelation, + struct IndexInfo *indexInfo); + +/* build empty index */ +typedef void (*ambuildempty_function) (Relation indexRelation); + +/* insert this tuple */ +typedef bool (*aminsert_function) (Relation indexRelation, + Datum *values, + bool *isnull, + ItemPointer heap_tid, + Relation heapRelation, + IndexUniqueCheck checkUnique, + struct IndexInfo *indexInfo); + +/* bulk delete */ +typedef IndexBulkDeleteResult *(*ambulkdelete_function) (IndexVacuumInfo *info, + IndexBulkDeleteResult *stats, + IndexBulkDeleteCallback callback, + void *callback_state); + +/* post-VACUUM cleanup */ +typedef IndexBulkDeleteResult *(*amvacuumcleanup_function) (IndexVacuumInfo *info, + IndexBulkDeleteResult *stats); + +/* can indexscan return IndexTuples? */ +typedef bool (*amcanreturn_function) (Relation indexRelation, int attno); + +/* estimate cost of an indexscan */ +typedef void (*amcostestimate_function) (struct PlannerInfo *root, + struct IndexPath *path, + double loop_count, + Cost *indexStartupCost, + Cost *indexTotalCost, + Selectivity *indexSelectivity, + double *indexCorrelation, + double *indexPages); + +/* parse index reloptions */ +typedef bytea *(*amoptions_function) (Datum reloptions, + bool validate); + +/* report AM, index, or index column property */ +typedef bool (*amproperty_function) (Oid index_oid, int attno, + IndexAMProperty prop, const char *propname, + bool *res, bool *isnull); + +/* name of phase as used in progress reporting */ +typedef char *(*ambuildphasename_function) (int64 phasenum); + +/* validate definition of an opclass for this AM */ +typedef bool (*amvalidate_function) (Oid opclassoid); + +/* prepare for index scan */ +typedef IndexScanDesc (*ambeginscan_function) (Relation indexRelation, + int nkeys, + int norderbys); + +/* (re)start index scan */ +typedef void (*amrescan_function) (IndexScanDesc scan, + ScanKey keys, + int nkeys, + ScanKey orderbys, + int norderbys); + +/* next valid tuple */ +typedef bool (*amgettuple_function) (IndexScanDesc scan, + ScanDirection direction); + +/* fetch all valid tuples */ +typedef int64 (*amgetbitmap_function) (IndexScanDesc scan, + TIDBitmap *tbm); + +/* end index scan */ +typedef void (*amendscan_function) (IndexScanDesc scan); + +/* mark current scan position */ +typedef void (*ammarkpos_function) (IndexScanDesc scan); + +/* restore marked scan position */ +typedef void (*amrestrpos_function) (IndexScanDesc scan); + +/* + * Callback function signatures - for parallel index scans. + */ + +/* estimate size of parallel scan descriptor */ +typedef Size (*amestimateparallelscan_function) (void); + +/* prepare for parallel index scan */ +typedef void (*aminitparallelscan_function) (void *target); + +/* (re)start parallel index scan */ +typedef void (*amparallelrescan_function) (IndexScanDesc scan); + +/* + * API struct for an index AM. Note this must be stored in a single palloc'd + * chunk of memory. + */ +typedef struct IndexAmRoutine +{ + NodeTag type; + + /* + * Total number of strategies (operators) by which we can traverse/search + * this AM. Zero if AM does not have a fixed set of strategy assignments. + */ + uint16 amstrategies; + /* total number of support functions that this AM uses */ + uint16 amsupport; + /* does AM support ORDER BY indexed column's value? */ + bool amcanorder; + /* does AM support ORDER BY result of an operator on indexed column? */ + bool amcanorderbyop; + /* does AM support backward scanning? */ + bool amcanbackward; + /* does AM support UNIQUE indexes? */ + bool amcanunique; + /* does AM support multi-column indexes? */ + bool amcanmulticol; + /* does AM require scans to have a constraint on the first index column? */ + bool amoptionalkey; + /* does AM handle ScalarArrayOpExpr quals? */ + bool amsearcharray; + /* does AM handle IS NULL/IS NOT NULL quals? */ + bool amsearchnulls; + /* can index storage data type differ from column data type? */ + bool amstorage; + /* can an index of this type be clustered on? */ + bool amclusterable; + /* does AM handle predicate locks? */ + bool ampredlocks; + /* does AM support parallel scan? */ + bool amcanparallel; + /* does AM support columns included with clause INCLUDE? */ + bool amcaninclude; + /* type of data stored in index, or InvalidOid if variable */ + Oid amkeytype; + + /* + * If you add new properties to either the above or the below lists, then + * they should also (usually) be exposed via the property API (see + * IndexAMProperty at the top of the file, and utils/adt/amutils.c). + */ + + /* interface functions */ + ambuild_function ambuild; + ambuildempty_function ambuildempty; + aminsert_function aminsert; + ambulkdelete_function ambulkdelete; + amvacuumcleanup_function amvacuumcleanup; + amcanreturn_function amcanreturn; /* can be NULL */ + amcostestimate_function amcostestimate; + amoptions_function amoptions; + amproperty_function amproperty; /* can be NULL */ + ambuildphasename_function ambuildphasename; /* can be NULL */ + amvalidate_function amvalidate; + ambeginscan_function ambeginscan; + amrescan_function amrescan; + amgettuple_function amgettuple; /* can be NULL */ + amgetbitmap_function amgetbitmap; /* can be NULL */ + amendscan_function amendscan; + ammarkpos_function ammarkpos; /* can be NULL */ + amrestrpos_function amrestrpos; /* can be NULL */ + + /* interface functions to support parallel index scans */ + amestimateparallelscan_function amestimateparallelscan; /* can be NULL */ + aminitparallelscan_function aminitparallelscan; /* can be NULL */ + amparallelrescan_function amparallelrescan; /* can be NULL */ +} IndexAmRoutine; + + +/* Functions in access/index/indexamapi.c */ +extern IndexAmRoutine *GetIndexAmRoutine(Oid amhandler); +extern IndexAmRoutine *GetIndexAmRoutineByAmId(Oid amoid, bool noerror); + +#endif /* INDEXAM_H */ diff --git a/src/include/access/indexamvalidate.h b/src/include/access/indexamvalidate.h new file mode 100644 index 0000000000..69a0520c0a --- /dev/null +++ b/src/include/access/indexamvalidate.h @@ -0,0 +1,36 @@ +/*------------------------------------------------------------------------- + * + * indexamvalidate.h + * Support routines for index access methods' amvalidate functions. + * + * Copyright (c) 2016-2019, PostgreSQL Global Development Group + * + * src/include/access/indexamvalidate.h + * + *------------------------------------------------------------------------- + */ +#ifndef INDEXAMVALIDATE_H +#define INDEXAMVALIDATE_H + +#include "utils/catcache.h" + + +/* Struct returned (in a list) by identify_opfamily_groups() */ +typedef struct OpFamilyOpFuncGroup +{ + Oid lefttype; /* amoplefttype/amproclefttype */ + Oid righttype; /* amoprighttype/amprocrighttype */ + uint64 operatorset; /* bitmask of operators with these types */ + uint64 functionset; /* bitmask of support funcs with these types */ +} OpFamilyOpFuncGroup; + + +/* Functions in access/index/indexamvalidate.c */ +extern List *identify_opfamily_groups(CatCList *oprlist, CatCList *proclist); +extern bool check_amproc_signature(Oid funcid, Oid restype, bool exact, + int minargs, int maxargs,...); +extern bool check_amop_signature(Oid opno, Oid restype, + Oid lefttype, Oid righttype); +extern bool opfamily_can_sort_type(Oid opfamilyoid, Oid datatypeoid); + +#endif /* INDEXAMVALIDATE_H */ diff --git a/src/include/access/indexgenam.h b/src/include/access/indexgenam.h new file mode 100644 index 0000000000..a25cf110e7 --- /dev/null +++ b/src/include/access/indexgenam.h @@ -0,0 +1,225 @@ +/*------------------------------------------------------------------------- + * + * indexgenam.h + * POSTGRES generalized index access method definitions. + * + * + * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/access/indexgenam.h + * + *------------------------------------------------------------------------- + */ +#ifndef INDEXGENAM_H +#define INDEXGENAM_H + +#include "access/sdir.h" +#include "access/skey.h" +#include "nodes/tidbitmap.h" +#include "storage/lockdefs.h" +#include "utils/relcache.h" +#include "utils/snapshot.h" + +/* We don't want this file to depend on execnodes.h. */ +struct IndexInfo; + +/* + * Struct for statistics returned by ambuild + */ +typedef struct IndexBuildResult +{ + double heap_tuples; /* # of tuples seen in parent table */ + double index_tuples; /* # of tuples inserted into index */ +} IndexBuildResult; + +/* + * Struct for input arguments passed to ambulkdelete and amvacuumcleanup + * + * num_heap_tuples is accurate only when estimated_count is false; + * otherwise it's just an estimate (currently, the estimate is the + * prior value of the relation's pg_class.reltuples field). It will + * always just be an estimate during ambulkdelete. + */ +typedef struct IndexVacuumInfo +{ + Relation index; /* the index being vacuumed */ + bool analyze_only; /* ANALYZE (without any actual vacuum) */ + bool report_progress; /* emit progress.h status reports */ + bool estimated_count; /* num_heap_tuples is an estimate */ + int message_level; /* ereport level for progress messages */ + double num_heap_tuples; /* tuples remaining in heap */ + BufferAccessStrategy strategy; /* access strategy for reads */ +} IndexVacuumInfo; + +/* + * Struct for statistics returned by ambulkdelete and amvacuumcleanup + * + * This struct is normally allocated by the first ambulkdelete call and then + * passed along through subsequent ones until amvacuumcleanup; however, + * amvacuumcleanup must be prepared to allocate it in the case where no + * ambulkdelete calls were made (because no tuples needed deletion). + * Note that an index AM could choose to return a larger struct + * of which this is just the first field; this provides a way for ambulkdelete + * to communicate additional private data to amvacuumcleanup. + * + * Note: pages_removed is the amount by which the index physically shrank, + * if any (ie the change in its total size on disk). pages_deleted and + * pages_free refer to free space within the index file. Some index AMs + * may compute num_index_tuples by reference to num_heap_tuples, in which + * case they should copy the estimated_count field from IndexVacuumInfo. + */ +typedef struct IndexBulkDeleteResult +{ + BlockNumber num_pages; /* pages remaining in index */ + BlockNumber pages_removed; /* # removed during vacuum operation */ + bool estimated_count; /* num_index_tuples is an estimate */ + double num_index_tuples; /* tuples remaining */ + double tuples_removed; /* # removed during vacuum operation */ + BlockNumber pages_deleted; /* # unused pages in index */ + BlockNumber pages_free; /* # pages available for reuse */ +} IndexBulkDeleteResult; + +/* Typedef for callback function to determine if a tuple is bulk-deletable */ +typedef bool (*IndexBulkDeleteCallback) (ItemPointer itemptr, void *state); + +/* struct definitions appear in relscan.h */ +typedef struct IndexScanDescData *IndexScanDesc; +typedef struct SysScanDescData *SysScanDesc; + +typedef struct ParallelIndexScanDescData *ParallelIndexScanDesc; + +/* + * Enumeration specifying the type of uniqueness check to perform in + * index_insert(). + * + * UNIQUE_CHECK_YES is the traditional Postgres immediate check, possibly + * blocking to see if a conflicting transaction commits. + * + * For deferrable unique constraints, UNIQUE_CHECK_PARTIAL is specified at + * insertion time. The index AM should test if the tuple is unique, but + * should not throw error, block, or prevent the insertion if the tuple + * appears not to be unique. We'll recheck later when it is time for the + * constraint to be enforced. The AM must return true if the tuple is + * known unique, false if it is possibly non-unique. In the "true" case + * it is safe to omit the later recheck. + * + * When it is time to recheck the deferred constraint, a pseudo-insertion + * call is made with UNIQUE_CHECK_EXISTING. The tuple is already in the + * index in this case, so it should not be inserted again. Rather, just + * check for conflicting live tuples (possibly blocking). + */ +typedef enum IndexUniqueCheck +{ + UNIQUE_CHECK_NO, /* Don't do any uniqueness checking */ + UNIQUE_CHECK_YES, /* Enforce uniqueness at insertion time */ + UNIQUE_CHECK_PARTIAL, /* Test uniqueness, but no error */ + UNIQUE_CHECK_EXISTING /* Check if existing tuple is unique */ +} IndexUniqueCheck; + + +/* Nullable "ORDER BY col op const" distance */ +typedef struct IndexOrderByDistance +{ + double value; + bool isnull; +} IndexOrderByDistance; + +/* + * generalized index_ interface routines (in indexam.c) + */ + +/* + * IndexScanIsValid + * True iff the index scan is valid. + */ +#define IndexScanIsValid(scan) PointerIsValid(scan) + +extern Relation index_open(Oid relationId, LOCKMODE lockmode); +extern void index_close(Relation relation, LOCKMODE lockmode); + +extern bool index_insert(Relation indexRelation, + Datum *values, bool *isnull, + ItemPointer heap_t_ctid, + Relation heapRelation, + IndexUniqueCheck checkUnique, + struct IndexInfo *indexInfo); + +extern IndexScanDesc index_beginscan(Relation heapRelation, + Relation indexRelation, + Snapshot snapshot, + int nkeys, int norderbys); +extern IndexScanDesc index_beginscan_bitmap(Relation indexRelation, + Snapshot snapshot, + int nkeys); +extern void index_rescan(IndexScanDesc scan, + ScanKey keys, int nkeys, + ScanKey orderbys, int norderbys); +extern void index_endscan(IndexScanDesc scan); +extern void index_markpos(IndexScanDesc scan); +extern void index_restrpos(IndexScanDesc scan); +extern Size index_parallelscan_estimate(Relation indexrel, Snapshot snapshot); +extern void index_parallelscan_initialize(Relation heaprel, Relation indexrel, + Snapshot snapshot, ParallelIndexScanDesc target); +extern void index_parallelrescan(IndexScanDesc scan); +extern IndexScanDesc index_beginscan_parallel(Relation heaprel, + Relation indexrel, int nkeys, int norderbys, + ParallelIndexScanDesc pscan); +extern ItemPointer index_getnext_tid(IndexScanDesc scan, + ScanDirection direction); +struct TupleTableSlot; +extern bool index_fetch_heap(IndexScanDesc scan, struct TupleTableSlot *slot); +extern bool index_getnext_slot(IndexScanDesc scan, ScanDirection direction, + struct TupleTableSlot *slot); +extern int64 index_getbitmap(IndexScanDesc scan, TIDBitmap *bitmap); + +extern IndexBulkDeleteResult *index_bulk_delete(IndexVacuumInfo *info, + IndexBulkDeleteResult *stats, + IndexBulkDeleteCallback callback, + void *callback_state); +extern IndexBulkDeleteResult *index_vacuum_cleanup(IndexVacuumInfo *info, + IndexBulkDeleteResult *stats); +extern bool index_can_return(Relation indexRelation, int attno); +extern RegProcedure index_getprocid(Relation irel, AttrNumber attnum, + uint16 procnum); +extern FmgrInfo *index_getprocinfo(Relation irel, AttrNumber attnum, + uint16 procnum); +extern void index_store_float8_orderby_distances(IndexScanDesc scan, + Oid *orderByTypes, + IndexOrderByDistance *distances, + bool recheckOrderBy); + +/* + * index access method support routines (in indexgenam.c) + */ +extern IndexScanDesc RelationGetIndexScan(Relation indexRelation, + int nkeys, int norderbys); +extern void IndexScanEnd(IndexScanDesc scan); +extern char *BuildIndexValueDescription(Relation indexRelation, + Datum *values, bool *isnull); +extern TransactionId index_compute_xid_horizon_for_tuples(Relation irel, + Relation hrel, + Buffer ibuf, + OffsetNumber *itemnos, + int nitems); + +/* + * heap-or-index access to system catalogs (in indexgenam.c) + */ +extern SysScanDesc systable_beginscan(Relation heapRelation, + Oid indexId, + bool indexOK, + Snapshot snapshot, + int nkeys, ScanKey key); +extern HeapTuple systable_getnext(SysScanDesc sysscan); +extern bool systable_recheck_tuple(SysScanDesc sysscan, HeapTuple tup); +extern void systable_endscan(SysScanDesc sysscan); +extern SysScanDesc systable_beginscan_ordered(Relation heapRelation, + Relation indexRelation, + Snapshot snapshot, + int nkeys, ScanKey key); +extern HeapTuple systable_getnext_ordered(SysScanDesc sysscan, + ScanDirection direction); +extern void systable_endscan_ordered(SysScanDesc sysscan); + +#endif /* INDEXGENAM_H */ diff --git a/src/include/access/nbtree.h b/src/include/access/nbtree.h index 5e56aac63f..0bcb2ec2cd 100644 --- a/src/include/access/nbtree.h +++ b/src/include/access/nbtree.h @@ -14,7 +14,7 @@ #ifndef NBTREE_H #define NBTREE_H -#include "access/amapi.h" +#include "access/indexam.h" #include "access/itup.h" #include "access/sdir.h" #include "access/xlogreader.h" diff --git a/src/include/access/reloptions.h b/src/include/access/reloptions.h index d21c513be4..e7abb41193 100644 --- a/src/include/access/reloptions.h +++ b/src/include/access/reloptions.h @@ -19,8 +19,8 @@ #ifndef RELOPTIONS_H #define RELOPTIONS_H -#include "access/amapi.h" #include "access/htup.h" +#include "access/indexam.h" #include "access/tupdesc.h" #include "nodes/pg_list.h" #include "storage/lock.h" diff --git a/src/include/access/spgist.h b/src/include/access/spgist.h index d5fd7bcc02..1f9b9eb5e1 100644 --- a/src/include/access/spgist.h +++ b/src/include/access/spgist.h @@ -14,7 +14,7 @@ #ifndef SPGIST_H #define SPGIST_H -#include "access/amapi.h" +#include "access/indexam.h" #include "access/xlogreader.h" #include "lib/stringinfo.h" diff --git a/src/include/executor/nodeIndexscan.h b/src/include/executor/nodeIndexscan.h index e895ec5b7b..dd3a323891 100644 --- a/src/include/executor/nodeIndexscan.h +++ b/src/include/executor/nodeIndexscan.h @@ -14,7 +14,7 @@ #ifndef NODEINDEXSCAN_H #define NODEINDEXSCAN_H -#include "access/genam.h" +#include "access/indexgenam.h" #include "access/parallel.h" #include "nodes/execnodes.h" diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index bce2d59b0d..8692a32172 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -504,7 +504,7 @@ typedef enum NodeTag T_TIDBitmap, /* in nodes/tidbitmap.h */ T_InlineCodeBlock, /* in nodes/parsenodes.h */ T_FdwRoutine, /* in foreign/fdwapi.h */ - T_IndexAmRoutine, /* in access/amapi.h */ + T_IndexAmRoutine, /* in access/indexam.h */ T_TableAmRoutine, /* in access/tableam.h */ T_TsmRoutine, /* in access/tsmapi.h */ T_ForeignKeyCacheInfo, /* in utils/rel.h */ diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 31b631cfe0..6fe1ba9a96 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -836,7 +836,7 @@ struct IndexOptInfo bool amhasgettuple; /* does AM have amgettuple interface? */ bool amhasgetbitmap; /* does AM have amgetbitmap interface? */ bool amcanparallel; /* does AM support parallel scan? */ - /* Rather than include amapi.h here, we declare amcostestimate like this */ + /* Rather than include indexam.h here, we declare amcostestimate like this */ void (*amcostestimate) (); /* AM's cost estimator */ }; diff --git a/src/include/utils/index_selfuncs.h b/src/include/utils/index_selfuncs.h index b81556d7a1..2a15f5abf6 100644 --- a/src/include/utils/index_selfuncs.h +++ b/src/include/utils/index_selfuncs.h @@ -6,7 +6,7 @@ * * Note: this is split out of selfuncs.h mainly to avoid importing all of the * planner's data structures into the non-planner parts of the index AMs. - * If you make it depend on anything besides access/amapi.h, that's likely + * If you make it depend on anything besides access/indexam.h, that's likely * a mistake. * * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group @@ -19,7 +19,7 @@ #ifndef INDEX_SELFUNCS_H #define INDEX_SELFUNCS_H -#include "access/amapi.h" +#include "access/indexam.h" /* Functions in selfuncs.c */ extern void brincostestimate(struct PlannerInfo *root, diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h index 31d8a1a10e..2752eacc9f 100644 --- a/src/include/utils/rel.h +++ b/src/include/utils/rel.h @@ -153,7 +153,7 @@ typedef struct RelationData * identifier given that restriction. */ MemoryContext rd_indexcxt; /* private memory cxt for this stuff */ - /* use "struct" here to avoid needing to include amapi.h: */ + /* use "struct" here to avoid needing to include indexam.h: */ struct IndexAmRoutine *rd_indam; /* index AM's API struct */ Oid *rd_opfamily; /* OIDs of op families for each index col */ Oid *rd_opcintype; /* OIDs of opclass declared input data types */ diff --git a/src/test/modules/dummy_index_am/dummy_index_am.c b/src/test/modules/dummy_index_am/dummy_index_am.c index 053636e4b4..bade886866 100644 --- a/src/test/modules/dummy_index_am/dummy_index_am.c +++ b/src/test/modules/dummy_index_am/dummy_index_am.c @@ -13,7 +13,7 @@ */ #include "postgres.h" -#include "access/amapi.h" +#include "access/indexam.h" #include "access/reloptions.h" #include "catalog/index.h" #include "nodes/pathnodes.h" -- cgit v1.2.1