]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Change IndexAmRoutines to be statically-allocated structs.
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 30 Dec 2025 23:26:23 +0000 (18:26 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 30 Dec 2025 23:26:23 +0000 (18:26 -0500)
Up to now, index amhandlers were expected to produce a new, palloc'd
struct on each call.  That requires palloc/pfree overhead, and creates
a risk of memory leaks if the caller fails to pfree, and the time
taken to fill such a large structure isn't nil.  Moreover, we were
storing these things in the relcache, eating several hundred bytes for
each cached index.  There is not anything in these structs that needs
to vary at runtime, so let's change the definition so that an
amhandler can return a pointer to a "static const" struct of which
there's only one copy per index AM.  Mark all the core code's
IndexAmRoutine pointers const so that we catch anyplace that might
still try to change or pfree one.

(This is similar to the way we were already handling TableAmRoutine
structs.  This commit does fix one comment that was infelicitously
copied-and-pasted into tableamapi.c.)

This commit needs to be called out in the v19 release notes as an API
change for extension index AMs.  An un-updated AM will still work
(as of now, anyway) but it risks memory leaks and will be slower than
necessary.

Author: Matthias van de Meent <boekewurm+postgres@gmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/CAEoWx2=vApYk2LRu8R0DdahsPNEhWUxGBZ=rbZo1EXE=uA+opQ@mail.gmail.com

22 files changed:
contrib/bloom/blutils.c
doc/src/sgml/indexam.sgml
src/backend/access/brin/brin.c
src/backend/access/gin/ginutil.c
src/backend/access/gist/gist.c
src/backend/access/hash/hash.c
src/backend/access/index/amapi.c
src/backend/access/nbtree/nbtree.c
src/backend/access/spgist/spgutils.c
src/backend/access/table/tableamapi.c
src/backend/catalog/index.c
src/backend/commands/indexcmds.c
src/backend/commands/opclasscmds.c
src/backend/executor/execAmi.c
src/backend/optimizer/util/plancat.c
src/backend/utils/adt/amutils.c
src/backend/utils/adt/ruleutils.c
src/backend/utils/cache/lsyscache.c
src/backend/utils/cache/relcache.c
src/include/access/amapi.h
src/include/utils/rel.h
src/test/modules/dummy_index_am/dummy_index_am.c

index 7a468b4a173baad8ce6dcac7f43017c961dd5e8a..50f461fa540c7121be7a5a8a3cd0b055e9efddb4 100644 (file)
@@ -102,61 +102,62 @@ makeDefaultBloomOptions(void)
 Datum
 blhandler(PG_FUNCTION_ARGS)
 {
-       IndexAmRoutine *amroutine = makeNode(IndexAmRoutine);
-
-       amroutine->amstrategies = BLOOM_NSTRATEGIES;
-       amroutine->amsupport = BLOOM_NPROC;
-       amroutine->amoptsprocnum = BLOOM_OPTIONS_PROC;
-       amroutine->amcanorder = false;
-       amroutine->amcanorderbyop = false;
-       amroutine->amcanhash = false;
-       amroutine->amconsistentequality = false;
-       amroutine->amconsistentordering = false;
-       amroutine->amcanbackward = false;
-       amroutine->amcanunique = false;
-       amroutine->amcanmulticol = true;
-       amroutine->amoptionalkey = true;
-       amroutine->amsearcharray = false;
-       amroutine->amsearchnulls = false;
-       amroutine->amstorage = false;
-       amroutine->amclusterable = false;
-       amroutine->ampredlocks = false;
-       amroutine->amcanparallel = false;
-       amroutine->amcanbuildparallel = false;
-       amroutine->amcaninclude = false;
-       amroutine->amusemaintenanceworkmem = false;
-       amroutine->amparallelvacuumoptions =
-               VACUUM_OPTION_PARALLEL_BULKDEL | VACUUM_OPTION_PARALLEL_CLEANUP;
-       amroutine->amkeytype = InvalidOid;
-
-       amroutine->ambuild = blbuild;
-       amroutine->ambuildempty = blbuildempty;
-       amroutine->aminsert = blinsert;
-       amroutine->aminsertcleanup = NULL;
-       amroutine->ambulkdelete = blbulkdelete;
-       amroutine->amvacuumcleanup = blvacuumcleanup;
-       amroutine->amcanreturn = NULL;
-       amroutine->amcostestimate = blcostestimate;
-       amroutine->amgettreeheight = NULL;
-       amroutine->amoptions = bloptions;
-       amroutine->amproperty = NULL;
-       amroutine->ambuildphasename = NULL;
-       amroutine->amvalidate = blvalidate;
-       amroutine->amadjustmembers = NULL;
-       amroutine->ambeginscan = blbeginscan;
-       amroutine->amrescan = blrescan;
-       amroutine->amgettuple = NULL;
-       amroutine->amgetbitmap = blgetbitmap;
-       amroutine->amendscan = blendscan;
-       amroutine->ammarkpos = NULL;
-       amroutine->amrestrpos = NULL;
-       amroutine->amestimateparallelscan = NULL;
-       amroutine->aminitparallelscan = NULL;
-       amroutine->amparallelrescan = NULL;
-       amroutine->amtranslatestrategy = NULL;
-       amroutine->amtranslatecmptype = NULL;
-
-       PG_RETURN_POINTER(amroutine);
+       static const IndexAmRoutine amroutine = {
+               .type = T_IndexAmRoutine,
+               .amstrategies = BLOOM_NSTRATEGIES,
+               .amsupport = BLOOM_NPROC,
+               .amoptsprocnum = BLOOM_OPTIONS_PROC,
+               .amcanorder = false,
+               .amcanorderbyop = false,
+               .amcanhash = false,
+               .amconsistentequality = false,
+               .amconsistentordering = false,
+               .amcanbackward = false,
+               .amcanunique = false,
+               .amcanmulticol = true,
+               .amoptionalkey = true,
+               .amsearcharray = false,
+               .amsearchnulls = false,
+               .amstorage = false,
+               .amclusterable = false,
+               .ampredlocks = false,
+               .amcanparallel = false,
+               .amcanbuildparallel = false,
+               .amcaninclude = false,
+               .amusemaintenanceworkmem = false,
+               .amparallelvacuumoptions =
+               VACUUM_OPTION_PARALLEL_BULKDEL | VACUUM_OPTION_PARALLEL_CLEANUP,
+               .amkeytype = InvalidOid,
+
+               .ambuild = blbuild,
+               .ambuildempty = blbuildempty,
+               .aminsert = blinsert,
+               .aminsertcleanup = NULL,
+               .ambulkdelete = blbulkdelete,
+               .amvacuumcleanup = blvacuumcleanup,
+               .amcanreturn = NULL,
+               .amcostestimate = blcostestimate,
+               .amgettreeheight = NULL,
+               .amoptions = bloptions,
+               .amproperty = NULL,
+               .ambuildphasename = NULL,
+               .amvalidate = blvalidate,
+               .amadjustmembers = NULL,
+               .ambeginscan = blbeginscan,
+               .amrescan = blrescan,
+               .amgettuple = NULL,
+               .amgetbitmap = blgetbitmap,
+               .amendscan = blendscan,
+               .ammarkpos = NULL,
+               .amrestrpos = NULL,
+               .amestimateparallelscan = NULL,
+               .aminitparallelscan = NULL,
+               .amparallelrescan = NULL,
+               .amtranslatestrategy = NULL,
+               .amtranslatecmptype = NULL,
+       };
+
+       PG_RETURN_POINTER(&amroutine);
 }
 
 /*
index 63d7e376f195e4d3a644c082df1703a43d68ccb1..f48da3185307c253900199ce52d2fd621a534ceb 100644 (file)
    single argument of type <type>internal</type> and to return the
    pseudo-type <type>index_am_handler</type>.  The argument is a dummy value that
    simply serves to prevent handler functions from being called directly from
-   SQL commands.  The result of the function must be a palloc'd struct of
-   type <structname>IndexAmRoutine</structname>, which contains everything
-   that the core code needs to know to make use of the index access method.
+   SQL commands.
+   The result of the handler function must be a pointer to a permanently
+   allocated struct of type <structname>IndexAmRoutine</structname>, which
+   contains everything that the core code needs to know to make use of the
+   index access method.  (Typically this struct can be pre-initialized and
+   marked <literal>static const</literal>; but if that is inconvenient,
+   build it in some long-lived context.  In any case, repeat calls within
+   a process should return the same pointer.  The core code will treat the
+   struct as <literal>const</literal>, and will never free it.)
    The <structname>IndexAmRoutine</structname> struct, also called the access
    method's <firstterm>API struct</firstterm>, includes fields specifying assorted
    fixed properties of the access method, such as whether it can support
index 45d306037a4bb9401dd7f739b5cc9551e2d5e008..ec5086a9521fd9ecd7a76b19d4e841ecc1c2db8d 100644 (file)
@@ -249,62 +249,63 @@ static void _brin_parallel_scan_and_build(BrinBuildState *state,
 Datum
 brinhandler(PG_FUNCTION_ARGS)
 {
-       IndexAmRoutine *amroutine = makeNode(IndexAmRoutine);
-
-       amroutine->amstrategies = 0;
-       amroutine->amsupport = BRIN_LAST_OPTIONAL_PROCNUM;
-       amroutine->amoptsprocnum = BRIN_PROCNUM_OPTIONS;
-       amroutine->amcanorder = false;
-       amroutine->amcanorderbyop = false;
-       amroutine->amcanhash = false;
-       amroutine->amconsistentequality = false;
-       amroutine->amconsistentordering = false;
-       amroutine->amcanbackward = false;
-       amroutine->amcanunique = false;
-       amroutine->amcanmulticol = true;
-       amroutine->amoptionalkey = true;
-       amroutine->amsearcharray = false;
-       amroutine->amsearchnulls = true;
-       amroutine->amstorage = true;
-       amroutine->amclusterable = false;
-       amroutine->ampredlocks = false;
-       amroutine->amcanparallel = false;
-       amroutine->amcanbuildparallel = true;
-       amroutine->amcaninclude = false;
-       amroutine->amusemaintenanceworkmem = false;
-       amroutine->amsummarizing = true;
-       amroutine->amparallelvacuumoptions =
-               VACUUM_OPTION_PARALLEL_CLEANUP;
-       amroutine->amkeytype = InvalidOid;
-
-       amroutine->ambuild = brinbuild;
-       amroutine->ambuildempty = brinbuildempty;
-       amroutine->aminsert = brininsert;
-       amroutine->aminsertcleanup = brininsertcleanup;
-       amroutine->ambulkdelete = brinbulkdelete;
-       amroutine->amvacuumcleanup = brinvacuumcleanup;
-       amroutine->amcanreturn = NULL;
-       amroutine->amcostestimate = brincostestimate;
-       amroutine->amgettreeheight = NULL;
-       amroutine->amoptions = brinoptions;
-       amroutine->amproperty = NULL;
-       amroutine->ambuildphasename = NULL;
-       amroutine->amvalidate = brinvalidate;
-       amroutine->amadjustmembers = NULL;
-       amroutine->ambeginscan = brinbeginscan;
-       amroutine->amrescan = brinrescan;
-       amroutine->amgettuple = NULL;
-       amroutine->amgetbitmap = bringetbitmap;
-       amroutine->amendscan = brinendscan;
-       amroutine->ammarkpos = NULL;
-       amroutine->amrestrpos = NULL;
-       amroutine->amestimateparallelscan = NULL;
-       amroutine->aminitparallelscan = NULL;
-       amroutine->amparallelrescan = NULL;
-       amroutine->amtranslatestrategy = NULL;
-       amroutine->amtranslatecmptype = NULL;
-
-       PG_RETURN_POINTER(amroutine);
+       static const IndexAmRoutine amroutine = {
+               .type = T_IndexAmRoutine,
+               .amstrategies = 0,
+               .amsupport = BRIN_LAST_OPTIONAL_PROCNUM,
+               .amoptsprocnum = BRIN_PROCNUM_OPTIONS,
+               .amcanorder = false,
+               .amcanorderbyop = false,
+               .amcanhash = false,
+               .amconsistentequality = false,
+               .amconsistentordering = false,
+               .amcanbackward = false,
+               .amcanunique = false,
+               .amcanmulticol = true,
+               .amoptionalkey = true,
+               .amsearcharray = false,
+               .amsearchnulls = true,
+               .amstorage = true,
+               .amclusterable = false,
+               .ampredlocks = false,
+               .amcanparallel = false,
+               .amcanbuildparallel = true,
+               .amcaninclude = false,
+               .amusemaintenanceworkmem = false,
+               .amsummarizing = true,
+               .amparallelvacuumoptions =
+               VACUUM_OPTION_PARALLEL_CLEANUP,
+               .amkeytype = InvalidOid,
+
+               .ambuild = brinbuild,
+               .ambuildempty = brinbuildempty,
+               .aminsert = brininsert,
+               .aminsertcleanup = brininsertcleanup,
+               .ambulkdelete = brinbulkdelete,
+               .amvacuumcleanup = brinvacuumcleanup,
+               .amcanreturn = NULL,
+               .amcostestimate = brincostestimate,
+               .amgettreeheight = NULL,
+               .amoptions = brinoptions,
+               .amproperty = NULL,
+               .ambuildphasename = NULL,
+               .amvalidate = brinvalidate,
+               .amadjustmembers = NULL,
+               .ambeginscan = brinbeginscan,
+               .amrescan = brinrescan,
+               .amgettuple = NULL,
+               .amgetbitmap = bringetbitmap,
+               .amendscan = brinendscan,
+               .ammarkpos = NULL,
+               .amrestrpos = NULL,
+               .amestimateparallelscan = NULL,
+               .aminitparallelscan = NULL,
+               .amparallelrescan = NULL,
+               .amtranslatestrategy = NULL,
+               .amtranslatecmptype = NULL,
+       };
+
+       PG_RETURN_POINTER(&amroutine);
 }
 
 /*
index 605f80aad39182dcc72d2b9728165d3242988ec2..e4589de2aab544fd5312bd0420e51693608e12b7 100644 (file)
 Datum
 ginhandler(PG_FUNCTION_ARGS)
 {
-       IndexAmRoutine *amroutine = makeNode(IndexAmRoutine);
-
-       amroutine->amstrategies = 0;
-       amroutine->amsupport = GINNProcs;
-       amroutine->amoptsprocnum = GIN_OPTIONS_PROC;
-       amroutine->amcanorder = false;
-       amroutine->amcanorderbyop = false;
-       amroutine->amcanhash = false;
-       amroutine->amconsistentequality = false;
-       amroutine->amconsistentordering = false;
-       amroutine->amcanbackward = false;
-       amroutine->amcanunique = false;
-       amroutine->amcanmulticol = true;
-       amroutine->amoptionalkey = true;
-       amroutine->amsearcharray = false;
-       amroutine->amsearchnulls = false;
-       amroutine->amstorage = true;
-       amroutine->amclusterable = false;
-       amroutine->ampredlocks = true;
-       amroutine->amcanparallel = false;
-       amroutine->amcanbuildparallel = true;
-       amroutine->amcaninclude = false;
-       amroutine->amusemaintenanceworkmem = true;
-       amroutine->amsummarizing = false;
-       amroutine->amparallelvacuumoptions =
-               VACUUM_OPTION_PARALLEL_BULKDEL | VACUUM_OPTION_PARALLEL_CLEANUP;
-       amroutine->amkeytype = InvalidOid;
-
-       amroutine->ambuild = ginbuild;
-       amroutine->ambuildempty = ginbuildempty;
-       amroutine->aminsert = gininsert;
-       amroutine->aminsertcleanup = NULL;
-       amroutine->ambulkdelete = ginbulkdelete;
-       amroutine->amvacuumcleanup = ginvacuumcleanup;
-       amroutine->amcanreturn = NULL;
-       amroutine->amcostestimate = gincostestimate;
-       amroutine->amgettreeheight = NULL;
-       amroutine->amoptions = ginoptions;
-       amroutine->amproperty = NULL;
-       amroutine->ambuildphasename = ginbuildphasename;
-       amroutine->amvalidate = ginvalidate;
-       amroutine->amadjustmembers = ginadjustmembers;
-       amroutine->ambeginscan = ginbeginscan;
-       amroutine->amrescan = ginrescan;
-       amroutine->amgettuple = NULL;
-       amroutine->amgetbitmap = gingetbitmap;
-       amroutine->amendscan = ginendscan;
-       amroutine->ammarkpos = NULL;
-       amroutine->amrestrpos = NULL;
-       amroutine->amestimateparallelscan = NULL;
-       amroutine->aminitparallelscan = NULL;
-       amroutine->amparallelrescan = NULL;
-
-       PG_RETURN_POINTER(amroutine);
+       static const IndexAmRoutine amroutine = {
+               .type = T_IndexAmRoutine,
+               .amstrategies = 0,
+               .amsupport = GINNProcs,
+               .amoptsprocnum = GIN_OPTIONS_PROC,
+               .amcanorder = false,
+               .amcanorderbyop = false,
+               .amcanhash = false,
+               .amconsistentequality = false,
+               .amconsistentordering = false,
+               .amcanbackward = false,
+               .amcanunique = false,
+               .amcanmulticol = true,
+               .amoptionalkey = true,
+               .amsearcharray = false,
+               .amsearchnulls = false,
+               .amstorage = true,
+               .amclusterable = false,
+               .ampredlocks = true,
+               .amcanparallel = false,
+               .amcanbuildparallel = true,
+               .amcaninclude = false,
+               .amusemaintenanceworkmem = true,
+               .amsummarizing = false,
+               .amparallelvacuumoptions =
+               VACUUM_OPTION_PARALLEL_BULKDEL | VACUUM_OPTION_PARALLEL_CLEANUP,
+               .amkeytype = InvalidOid,
+
+               .ambuild = ginbuild,
+               .ambuildempty = ginbuildempty,
+               .aminsert = gininsert,
+               .aminsertcleanup = NULL,
+               .ambulkdelete = ginbulkdelete,
+               .amvacuumcleanup = ginvacuumcleanup,
+               .amcanreturn = NULL,
+               .amcostestimate = gincostestimate,
+               .amgettreeheight = NULL,
+               .amoptions = ginoptions,
+               .amproperty = NULL,
+               .ambuildphasename = ginbuildphasename,
+               .amvalidate = ginvalidate,
+               .amadjustmembers = ginadjustmembers,
+               .ambeginscan = ginbeginscan,
+               .amrescan = ginrescan,
+               .amgettuple = NULL,
+               .amgetbitmap = gingetbitmap,
+               .amendscan = ginendscan,
+               .ammarkpos = NULL,
+               .amrestrpos = NULL,
+               .amestimateparallelscan = NULL,
+               .aminitparallelscan = NULL,
+               .amparallelrescan = NULL,
+       };
+
+       PG_RETURN_POINTER(&amroutine);
 }
 
 /*
index c26d8538f05395a030f5c9c7b901821924f48db9..4b943b7f43ee47dd394338e04d1dc83efe0a602e 100644 (file)
@@ -58,62 +58,63 @@ static void gistprunepage(Relation rel, Page page, Buffer buffer,
 Datum
 gisthandler(PG_FUNCTION_ARGS)
 {
-       IndexAmRoutine *amroutine = makeNode(IndexAmRoutine);
-
-       amroutine->amstrategies = 0;
-       amroutine->amsupport = GISTNProcs;
-       amroutine->amoptsprocnum = GIST_OPTIONS_PROC;
-       amroutine->amcanorder = false;
-       amroutine->amcanorderbyop = true;
-       amroutine->amcanhash = false;
-       amroutine->amconsistentequality = false;
-       amroutine->amconsistentordering = false;
-       amroutine->amcanbackward = false;
-       amroutine->amcanunique = false;
-       amroutine->amcanmulticol = true;
-       amroutine->amoptionalkey = true;
-       amroutine->amsearcharray = false;
-       amroutine->amsearchnulls = true;
-       amroutine->amstorage = true;
-       amroutine->amclusterable = true;
-       amroutine->ampredlocks = true;
-       amroutine->amcanparallel = false;
-       amroutine->amcanbuildparallel = false;
-       amroutine->amcaninclude = true;
-       amroutine->amusemaintenanceworkmem = false;
-       amroutine->amsummarizing = false;
-       amroutine->amparallelvacuumoptions =
-               VACUUM_OPTION_PARALLEL_BULKDEL | VACUUM_OPTION_PARALLEL_COND_CLEANUP;
-       amroutine->amkeytype = InvalidOid;
-
-       amroutine->ambuild = gistbuild;
-       amroutine->ambuildempty = gistbuildempty;
-       amroutine->aminsert = gistinsert;
-       amroutine->aminsertcleanup = NULL;
-       amroutine->ambulkdelete = gistbulkdelete;
-       amroutine->amvacuumcleanup = gistvacuumcleanup;
-       amroutine->amcanreturn = gistcanreturn;
-       amroutine->amcostestimate = gistcostestimate;
-       amroutine->amgettreeheight = NULL;
-       amroutine->amoptions = gistoptions;
-       amroutine->amproperty = gistproperty;
-       amroutine->ambuildphasename = NULL;
-       amroutine->amvalidate = gistvalidate;
-       amroutine->amadjustmembers = gistadjustmembers;
-       amroutine->ambeginscan = gistbeginscan;
-       amroutine->amrescan = gistrescan;
-       amroutine->amgettuple = gistgettuple;
-       amroutine->amgetbitmap = gistgetbitmap;
-       amroutine->amendscan = gistendscan;
-       amroutine->ammarkpos = NULL;
-       amroutine->amrestrpos = NULL;
-       amroutine->amestimateparallelscan = NULL;
-       amroutine->aminitparallelscan = NULL;
-       amroutine->amparallelrescan = NULL;
-       amroutine->amtranslatestrategy = NULL;
-       amroutine->amtranslatecmptype = gisttranslatecmptype;
-
-       PG_RETURN_POINTER(amroutine);
+       static const IndexAmRoutine amroutine = {
+               .type = T_IndexAmRoutine,
+               .amstrategies = 0,
+               .amsupport = GISTNProcs,
+               .amoptsprocnum = GIST_OPTIONS_PROC,
+               .amcanorder = false,
+               .amcanorderbyop = true,
+               .amcanhash = false,
+               .amconsistentequality = false,
+               .amconsistentordering = false,
+               .amcanbackward = false,
+               .amcanunique = false,
+               .amcanmulticol = true,
+               .amoptionalkey = true,
+               .amsearcharray = false,
+               .amsearchnulls = true,
+               .amstorage = true,
+               .amclusterable = true,
+               .ampredlocks = true,
+               .amcanparallel = false,
+               .amcanbuildparallel = false,
+               .amcaninclude = true,
+               .amusemaintenanceworkmem = false,
+               .amsummarizing = false,
+               .amparallelvacuumoptions =
+               VACUUM_OPTION_PARALLEL_BULKDEL | VACUUM_OPTION_PARALLEL_COND_CLEANUP,
+               .amkeytype = InvalidOid,
+
+               .ambuild = gistbuild,
+               .ambuildempty = gistbuildempty,
+               .aminsert = gistinsert,
+               .aminsertcleanup = NULL,
+               .ambulkdelete = gistbulkdelete,
+               .amvacuumcleanup = gistvacuumcleanup,
+               .amcanreturn = gistcanreturn,
+               .amcostestimate = gistcostestimate,
+               .amgettreeheight = NULL,
+               .amoptions = gistoptions,
+               .amproperty = gistproperty,
+               .ambuildphasename = NULL,
+               .amvalidate = gistvalidate,
+               .amadjustmembers = gistadjustmembers,
+               .ambeginscan = gistbeginscan,
+               .amrescan = gistrescan,
+               .amgettuple = gistgettuple,
+               .amgetbitmap = gistgetbitmap,
+               .amendscan = gistendscan,
+               .ammarkpos = NULL,
+               .amrestrpos = NULL,
+               .amestimateparallelscan = NULL,
+               .aminitparallelscan = NULL,
+               .amparallelrescan = NULL,
+               .amtranslatestrategy = NULL,
+               .amtranslatecmptype = gisttranslatecmptype,
+       };
+
+       PG_RETURN_POINTER(&amroutine);
 }
 
 /*
index e388252afdcc8402bff783c0ed366351764623e5..a2172d1063fee967a27c73dea63ec81bdb6bf17b 100644 (file)
@@ -57,62 +57,63 @@ static void hashbuildCallback(Relation index,
 Datum
 hashhandler(PG_FUNCTION_ARGS)
 {
-       IndexAmRoutine *amroutine = makeNode(IndexAmRoutine);
-
-       amroutine->amstrategies = HTMaxStrategyNumber;
-       amroutine->amsupport = HASHNProcs;
-       amroutine->amoptsprocnum = HASHOPTIONS_PROC;
-       amroutine->amcanorder = false;
-       amroutine->amcanorderbyop = false;
-       amroutine->amcanhash = true;
-       amroutine->amconsistentequality = true;
-       amroutine->amconsistentordering = false;
-       amroutine->amcanbackward = true;
-       amroutine->amcanunique = false;
-       amroutine->amcanmulticol = false;
-       amroutine->amoptionalkey = false;
-       amroutine->amsearcharray = false;
-       amroutine->amsearchnulls = false;
-       amroutine->amstorage = false;
-       amroutine->amclusterable = false;
-       amroutine->ampredlocks = true;
-       amroutine->amcanparallel = false;
-       amroutine->amcanbuildparallel = false;
-       amroutine->amcaninclude = false;
-       amroutine->amusemaintenanceworkmem = false;
-       amroutine->amsummarizing = false;
-       amroutine->amparallelvacuumoptions =
-               VACUUM_OPTION_PARALLEL_BULKDEL;
-       amroutine->amkeytype = INT4OID;
-
-       amroutine->ambuild = hashbuild;
-       amroutine->ambuildempty = hashbuildempty;
-       amroutine->aminsert = hashinsert;
-       amroutine->aminsertcleanup = NULL;
-       amroutine->ambulkdelete = hashbulkdelete;
-       amroutine->amvacuumcleanup = hashvacuumcleanup;
-       amroutine->amcanreturn = NULL;
-       amroutine->amcostestimate = hashcostestimate;
-       amroutine->amgettreeheight = NULL;
-       amroutine->amoptions = hashoptions;
-       amroutine->amproperty = NULL;
-       amroutine->ambuildphasename = NULL;
-       amroutine->amvalidate = hashvalidate;
-       amroutine->amadjustmembers = hashadjustmembers;
-       amroutine->ambeginscan = hashbeginscan;
-       amroutine->amrescan = hashrescan;
-       amroutine->amgettuple = hashgettuple;
-       amroutine->amgetbitmap = hashgetbitmap;
-       amroutine->amendscan = hashendscan;
-       amroutine->ammarkpos = NULL;
-       amroutine->amrestrpos = NULL;
-       amroutine->amestimateparallelscan = NULL;
-       amroutine->aminitparallelscan = NULL;
-       amroutine->amparallelrescan = NULL;
-       amroutine->amtranslatestrategy = hashtranslatestrategy;
-       amroutine->amtranslatecmptype = hashtranslatecmptype;
-
-       PG_RETURN_POINTER(amroutine);
+       static const IndexAmRoutine amroutine = {
+               .type = T_IndexAmRoutine,
+               .amstrategies = HTMaxStrategyNumber,
+               .amsupport = HASHNProcs,
+               .amoptsprocnum = HASHOPTIONS_PROC,
+               .amcanorder = false,
+               .amcanorderbyop = false,
+               .amcanhash = true,
+               .amconsistentequality = true,
+               .amconsistentordering = false,
+               .amcanbackward = true,
+               .amcanunique = false,
+               .amcanmulticol = false,
+               .amoptionalkey = false,
+               .amsearcharray = false,
+               .amsearchnulls = false,
+               .amstorage = false,
+               .amclusterable = false,
+               .ampredlocks = true,
+               .amcanparallel = false,
+               .amcanbuildparallel = false,
+               .amcaninclude = false,
+               .amusemaintenanceworkmem = false,
+               .amsummarizing = false,
+               .amparallelvacuumoptions =
+               VACUUM_OPTION_PARALLEL_BULKDEL,
+               .amkeytype = INT4OID,
+
+               .ambuild = hashbuild,
+               .ambuildempty = hashbuildempty,
+               .aminsert = hashinsert,
+               .aminsertcleanup = NULL,
+               .ambulkdelete = hashbulkdelete,
+               .amvacuumcleanup = hashvacuumcleanup,
+               .amcanreturn = NULL,
+               .amcostestimate = hashcostestimate,
+               .amgettreeheight = NULL,
+               .amoptions = hashoptions,
+               .amproperty = NULL,
+               .ambuildphasename = NULL,
+               .amvalidate = hashvalidate,
+               .amadjustmembers = hashadjustmembers,
+               .ambeginscan = hashbeginscan,
+               .amrescan = hashrescan,
+               .amgettuple = hashgettuple,
+               .amgetbitmap = hashgetbitmap,
+               .amendscan = hashendscan,
+               .ammarkpos = NULL,
+               .amrestrpos = NULL,
+               .amestimateparallelscan = NULL,
+               .aminitparallelscan = NULL,
+               .amparallelrescan = NULL,
+               .amtranslatestrategy = hashtranslatestrategy,
+               .amtranslatecmptype = hashtranslatecmptype,
+       };
+
+       PG_RETURN_POINTER(&amroutine);
 }
 
 /*
index 60684c53422794ad288871f225d2945c1cb2ecd2..453fd2a1dcf75cd8dd2059ba821b6bf6528b5eaa 100644 (file)
 
 /*
  * GetIndexAmRoutine - call the specified access method handler routine to get
- * its IndexAmRoutine struct, which will be palloc'd in the caller's context.
+ * its IndexAmRoutine struct, which we expect to be statically allocated.
  *
  * 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 *
+const IndexAmRoutine *
 GetIndexAmRoutine(Oid amhandler)
 {
        Datum           datum;
-       IndexAmRoutine *routine;
+       const IndexAmRoutine *routine;
 
        datum = OidFunctionCall0(amhandler);
-       routine = (IndexAmRoutine *) DatumGetPointer(datum);
+       routine = (const IndexAmRoutine *) DatumGetPointer(datum);
 
        if (routine == NULL || !IsA(routine, IndexAmRoutine))
                elog(ERROR, "index access method handler function %u did not return an IndexAmRoutine struct",
@@ -65,7 +65,7 @@ GetIndexAmRoutine(Oid amhandler)
  * If the given OID isn't a valid index access method, returns NULL if
  * noerror is true, else throws error.
  */
-IndexAmRoutine *
+const IndexAmRoutine *
 GetIndexAmRoutineByAmId(Oid amoid, bool noerror)
 {
        HeapTuple       tuple;
@@ -131,7 +131,7 @@ CompareType
 IndexAmTranslateStrategy(StrategyNumber strategy, Oid amoid, Oid opfamily, bool missing_ok)
 {
        CompareType result;
-       IndexAmRoutine *amroutine;
+       const IndexAmRoutine *amroutine;
 
        /* shortcut for common case */
        if (amoid == BTREE_AM_OID &&
@@ -161,7 +161,7 @@ StrategyNumber
 IndexAmTranslateCompareType(CompareType cmptype, Oid amoid, Oid opfamily, bool missing_ok)
 {
        StrategyNumber result;
-       IndexAmRoutine *amroutine;
+       const IndexAmRoutine *amroutine;
 
        /* shortcut for common case */
        if (amoid == BTREE_AM_OID &&
@@ -191,7 +191,7 @@ amvalidate(PG_FUNCTION_ARGS)
        HeapTuple       classtup;
        Form_pg_opclass classform;
        Oid                     amoid;
-       IndexAmRoutine *amroutine;
+       const IndexAmRoutine *amroutine;
 
        classtup = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclassoid));
        if (!HeapTupleIsValid(classtup))
@@ -210,7 +210,5 @@ amvalidate(PG_FUNCTION_ARGS)
 
        result = amroutine->amvalidate(opclassoid);
 
-       pfree(amroutine);
-
        PG_RETURN_BOOL(result);
 }
index b44252319357e20ed51f94a2c9611da9ae019f07..4a421f0b8f7136faff787abde8372192c9ee0dfd 100644 (file)
@@ -115,62 +115,63 @@ static BTVacuumPosting btreevacuumposting(BTVacState *vstate,
 Datum
 bthandler(PG_FUNCTION_ARGS)
 {
-       IndexAmRoutine *amroutine = makeNode(IndexAmRoutine);
-
-       amroutine->amstrategies = BTMaxStrategyNumber;
-       amroutine->amsupport = BTNProcs;
-       amroutine->amoptsprocnum = BTOPTIONS_PROC;
-       amroutine->amcanorder = true;
-       amroutine->amcanorderbyop = false;
-       amroutine->amcanhash = false;
-       amroutine->amconsistentequality = true;
-       amroutine->amconsistentordering = true;
-       amroutine->amcanbackward = true;
-       amroutine->amcanunique = true;
-       amroutine->amcanmulticol = true;
-       amroutine->amoptionalkey = true;
-       amroutine->amsearcharray = true;
-       amroutine->amsearchnulls = true;
-       amroutine->amstorage = false;
-       amroutine->amclusterable = true;
-       amroutine->ampredlocks = true;
-       amroutine->amcanparallel = true;
-       amroutine->amcanbuildparallel = true;
-       amroutine->amcaninclude = true;
-       amroutine->amusemaintenanceworkmem = false;
-       amroutine->amsummarizing = false;
-       amroutine->amparallelvacuumoptions =
-               VACUUM_OPTION_PARALLEL_BULKDEL | VACUUM_OPTION_PARALLEL_COND_CLEANUP;
-       amroutine->amkeytype = InvalidOid;
-
-       amroutine->ambuild = btbuild;
-       amroutine->ambuildempty = btbuildempty;
-       amroutine->aminsert = btinsert;
-       amroutine->aminsertcleanup = NULL;
-       amroutine->ambulkdelete = btbulkdelete;
-       amroutine->amvacuumcleanup = btvacuumcleanup;
-       amroutine->amcanreturn = btcanreturn;
-       amroutine->amcostestimate = btcostestimate;
-       amroutine->amgettreeheight = btgettreeheight;
-       amroutine->amoptions = btoptions;
-       amroutine->amproperty = btproperty;
-       amroutine->ambuildphasename = btbuildphasename;
-       amroutine->amvalidate = btvalidate;
-       amroutine->amadjustmembers = btadjustmembers;
-       amroutine->ambeginscan = btbeginscan;
-       amroutine->amrescan = btrescan;
-       amroutine->amgettuple = btgettuple;
-       amroutine->amgetbitmap = btgetbitmap;
-       amroutine->amendscan = btendscan;
-       amroutine->ammarkpos = btmarkpos;
-       amroutine->amrestrpos = btrestrpos;
-       amroutine->amestimateparallelscan = btestimateparallelscan;
-       amroutine->aminitparallelscan = btinitparallelscan;
-       amroutine->amparallelrescan = btparallelrescan;
-       amroutine->amtranslatestrategy = bttranslatestrategy;
-       amroutine->amtranslatecmptype = bttranslatecmptype;
-
-       PG_RETURN_POINTER(amroutine);
+       static const IndexAmRoutine amroutine = {
+               .type = T_IndexAmRoutine,
+               .amstrategies = BTMaxStrategyNumber,
+               .amsupport = BTNProcs,
+               .amoptsprocnum = BTOPTIONS_PROC,
+               .amcanorder = true,
+               .amcanorderbyop = false,
+               .amcanhash = false,
+               .amconsistentequality = true,
+               .amconsistentordering = true,
+               .amcanbackward = true,
+               .amcanunique = true,
+               .amcanmulticol = true,
+               .amoptionalkey = true,
+               .amsearcharray = true,
+               .amsearchnulls = true,
+               .amstorage = false,
+               .amclusterable = true,
+               .ampredlocks = true,
+               .amcanparallel = true,
+               .amcanbuildparallel = true,
+               .amcaninclude = true,
+               .amusemaintenanceworkmem = false,
+               .amsummarizing = false,
+               .amparallelvacuumoptions =
+               VACUUM_OPTION_PARALLEL_BULKDEL | VACUUM_OPTION_PARALLEL_COND_CLEANUP,
+               .amkeytype = InvalidOid,
+
+               .ambuild = btbuild,
+               .ambuildempty = btbuildempty,
+               .aminsert = btinsert,
+               .aminsertcleanup = NULL,
+               .ambulkdelete = btbulkdelete,
+               .amvacuumcleanup = btvacuumcleanup,
+               .amcanreturn = btcanreturn,
+               .amcostestimate = btcostestimate,
+               .amgettreeheight = btgettreeheight,
+               .amoptions = btoptions,
+               .amproperty = btproperty,
+               .ambuildphasename = btbuildphasename,
+               .amvalidate = btvalidate,
+               .amadjustmembers = btadjustmembers,
+               .ambeginscan = btbeginscan,
+               .amrescan = btrescan,
+               .amgettuple = btgettuple,
+               .amgetbitmap = btgetbitmap,
+               .amendscan = btendscan,
+               .ammarkpos = btmarkpos,
+               .amrestrpos = btrestrpos,
+               .amestimateparallelscan = btestimateparallelscan,
+               .aminitparallelscan = btinitparallelscan,
+               .amparallelrescan = btparallelrescan,
+               .amtranslatestrategy = bttranslatestrategy,
+               .amtranslatecmptype = bttranslatecmptype,
+       };
+
+       PG_RETURN_POINTER(&amroutine);
 }
 
 /*
index a60ec85e8bedc6f7131605a515b3ef1eb507655d..a6866bd3520bc1ab3f3a10d8b078872c472526b4 100644 (file)
 Datum
 spghandler(PG_FUNCTION_ARGS)
 {
-       IndexAmRoutine *amroutine = makeNode(IndexAmRoutine);
-
-       amroutine->amstrategies = 0;
-       amroutine->amsupport = SPGISTNProc;
-       amroutine->amoptsprocnum = SPGIST_OPTIONS_PROC;
-       amroutine->amcanorder = false;
-       amroutine->amcanorderbyop = true;
-       amroutine->amcanhash = false;
-       amroutine->amconsistentequality = false;
-       amroutine->amconsistentordering = false;
-       amroutine->amcanbackward = false;
-       amroutine->amcanunique = false;
-       amroutine->amcanmulticol = false;
-       amroutine->amoptionalkey = true;
-       amroutine->amsearcharray = false;
-       amroutine->amsearchnulls = true;
-       amroutine->amstorage = true;
-       amroutine->amclusterable = false;
-       amroutine->ampredlocks = false;
-       amroutine->amcanparallel = false;
-       amroutine->amcanbuildparallel = false;
-       amroutine->amcaninclude = true;
-       amroutine->amusemaintenanceworkmem = false;
-       amroutine->amsummarizing = false;
-       amroutine->amparallelvacuumoptions =
-               VACUUM_OPTION_PARALLEL_BULKDEL | VACUUM_OPTION_PARALLEL_COND_CLEANUP;
-       amroutine->amkeytype = InvalidOid;
-
-       amroutine->ambuild = spgbuild;
-       amroutine->ambuildempty = spgbuildempty;
-       amroutine->aminsert = spginsert;
-       amroutine->aminsertcleanup = NULL;
-       amroutine->ambulkdelete = spgbulkdelete;
-       amroutine->amvacuumcleanup = spgvacuumcleanup;
-       amroutine->amcanreturn = spgcanreturn;
-       amroutine->amcostestimate = spgcostestimate;
-       amroutine->amgettreeheight = NULL;
-       amroutine->amoptions = spgoptions;
-       amroutine->amproperty = spgproperty;
-       amroutine->ambuildphasename = NULL;
-       amroutine->amvalidate = spgvalidate;
-       amroutine->amadjustmembers = spgadjustmembers;
-       amroutine->ambeginscan = spgbeginscan;
-       amroutine->amrescan = spgrescan;
-       amroutine->amgettuple = spggettuple;
-       amroutine->amgetbitmap = spggetbitmap;
-       amroutine->amendscan = spgendscan;
-       amroutine->ammarkpos = NULL;
-       amroutine->amrestrpos = NULL;
-       amroutine->amestimateparallelscan = NULL;
-       amroutine->aminitparallelscan = NULL;
-       amroutine->amparallelrescan = NULL;
-       amroutine->amtranslatestrategy = NULL;
-       amroutine->amtranslatecmptype = NULL;
-
-       PG_RETURN_POINTER(amroutine);
+       static const IndexAmRoutine amroutine = {
+               .type = T_IndexAmRoutine,
+               .amstrategies = 0,
+               .amsupport = SPGISTNProc,
+               .amoptsprocnum = SPGIST_OPTIONS_PROC,
+               .amcanorder = false,
+               .amcanorderbyop = true,
+               .amcanhash = false,
+               .amconsistentequality = false,
+               .amconsistentordering = false,
+               .amcanbackward = false,
+               .amcanunique = false,
+               .amcanmulticol = false,
+               .amoptionalkey = true,
+               .amsearcharray = false,
+               .amsearchnulls = true,
+               .amstorage = true,
+               .amclusterable = false,
+               .ampredlocks = false,
+               .amcanparallel = false,
+               .amcanbuildparallel = false,
+               .amcaninclude = true,
+               .amusemaintenanceworkmem = false,
+               .amsummarizing = false,
+               .amparallelvacuumoptions =
+               VACUUM_OPTION_PARALLEL_BULKDEL | VACUUM_OPTION_PARALLEL_COND_CLEANUP,
+               .amkeytype = InvalidOid,
+
+               .ambuild = spgbuild,
+               .ambuildempty = spgbuildempty,
+               .aminsert = spginsert,
+               .aminsertcleanup = NULL,
+               .ambulkdelete = spgbulkdelete,
+               .amvacuumcleanup = spgvacuumcleanup,
+               .amcanreturn = spgcanreturn,
+               .amcostestimate = spgcostestimate,
+               .amgettreeheight = NULL,
+               .amoptions = spgoptions,
+               .amproperty = spgproperty,
+               .ambuildphasename = NULL,
+               .amvalidate = spgvalidate,
+               .amadjustmembers = spgadjustmembers,
+               .ambeginscan = spgbeginscan,
+               .amrescan = spgrescan,
+               .amgettuple = spggettuple,
+               .amgetbitmap = spggetbitmap,
+               .amendscan = spgendscan,
+               .ammarkpos = NULL,
+               .amrestrpos = NULL,
+               .amestimateparallelscan = NULL,
+               .aminitparallelscan = NULL,
+               .amparallelrescan = NULL,
+               .amtranslatestrategy = NULL,
+               .amtranslatecmptype = NULL,
+       };
+
+       PG_RETURN_POINTER(&amroutine);
 }
 
 /*
index 476663b66aada345bc08259a8a719bec7e585adb..6745d608f934a92934a23efcbd4d00269fa91c10 100644 (file)
@@ -21,8 +21,7 @@
 /*
  * GetTableAmRoutine
  *             Call the specified access method handler routine to get its
- *             TableAmRoutine struct, which will be palloc'd in the caller's
- *             memory context.
+ *             TableAmRoutine struct, which we expect to be statically allocated.
  */
 const TableAmRoutine *
 GetTableAmRoutine(Oid amhandler)
@@ -31,7 +30,7 @@ GetTableAmRoutine(Oid amhandler)
        const TableAmRoutine *routine;
 
        datum = OidFunctionCall0(amhandler);
-       routine = (TableAmRoutine *) DatumGetPointer(datum);
+       routine = (const TableAmRoutine *) DatumGetPointer(datum);
 
        if (routine == NULL || !IsA(routine, TableAmRoutine))
                elog(ERROR, "table access method handler %u did not return a TableAmRoutine struct",
index 8dea58ad96bf0b8e4f0888651bc2a1dca3094a78..86db0541f290d489cc80d51113be1fbfa9069775 100644 (file)
@@ -289,7 +289,7 @@ ConstructTupleDescriptor(Relation heapRelation,
        int                     numkeyatts = indexInfo->ii_NumIndexKeyAttrs;
        ListCell   *colnames_item = list_head(indexColNames);
        ListCell   *indexpr_item = list_head(indexInfo->ii_Expressions);
-       IndexAmRoutine *amroutine;
+       const IndexAmRoutine *amroutine;
        TupleDesc       heapTupDesc;
        TupleDesc       indexTupDesc;
        int                     natts;                  /* #atts in heap rel --- for error checks */
@@ -481,8 +481,6 @@ ConstructTupleDescriptor(Relation heapRelation,
                populate_compact_attribute(indexTupDesc, i);
        }
 
-       pfree(amroutine);
-
        return indexTupDesc;
 }
 
index d9cccb6ac1885b102386577aa107727116ec90f6..67a451463ed63a0ea51c323d70f97f1173e1f0c9 100644 (file)
@@ -190,7 +190,7 @@ CheckIndexCompatible(Oid oldId,
        HeapTuple       tuple;
        Form_pg_index indexForm;
        Form_pg_am      accessMethodForm;
-       IndexAmRoutine *amRoutine;
+       const IndexAmRoutine *amRoutine;
        bool            amcanorder;
        bool            amsummarizing;
        int16      *coloptions;
@@ -566,7 +566,7 @@ DefineIndex(Oid tableId,
        Relation        rel;
        HeapTuple       tuple;
        Form_pg_am      accessMethodForm;
-       IndexAmRoutine *amRoutine;
+       const IndexAmRoutine *amRoutine;
        bool            amcanorder;
        bool            amissummarizing;
        amoptions_function amoptions;
@@ -895,7 +895,6 @@ DefineIndex(Oid tableId,
        amoptions = amRoutine->amoptions;
        amissummarizing = amRoutine->amsummarizing;
 
-       pfree(amRoutine);
        ReleaseSysCache(tuple);
 
        /*
index 992ae789b00620f54eba6411b0ac712ebc982664..20c54a523c5829f275253e77a1d417e3e2119361 100644 (file)
@@ -349,7 +349,7 @@ DefineOpClass(CreateOpClassStmt *stmt)
        Relation        rel;
        HeapTuple       tup;
        Form_pg_am      amform;
-       IndexAmRoutine *amroutine;
+       const IndexAmRoutine *amroutine;
        Datum           values[Natts_pg_opclass];
        bool            nulls[Natts_pg_opclass];
        AclResult       aclresult;
@@ -823,7 +823,7 @@ AlterOpFamily(AlterOpFamilyStmt *stmt)
                                maxProcNumber;  /* amsupport value */
        HeapTuple       tup;
        Form_pg_am      amform;
-       IndexAmRoutine *amroutine;
+       const IndexAmRoutine *amroutine;
 
        /* Get necessary info about access method */
        tup = SearchSysCache1(AMNAME, CStringGetDatum(stmt->amname));
@@ -882,7 +882,7 @@ AlterOpFamilyAdd(AlterOpFamilyStmt *stmt, Oid amoid, Oid opfamilyoid,
                                 int maxOpNumber, int maxProcNumber, int optsProcNumber,
                                 List *items)
 {
-       IndexAmRoutine *amroutine = GetIndexAmRoutineByAmId(amoid, false);
+       const IndexAmRoutine *amroutine = GetIndexAmRoutineByAmId(amoid, false);
        List       *operators;          /* OpFamilyMember list for operators */
        List       *procedures;         /* OpFamilyMember list for support procs */
        ListCell   *l;
@@ -1165,9 +1165,7 @@ assignOperTypes(OpFamilyMember *member, Oid amoid, Oid typeoid)
                 * the family has been created but not yet populated with the required
                 * operators.)
                 */
-               IndexAmRoutine *amroutine = GetIndexAmRoutineByAmId(amoid, false);
-
-               if (!amroutine->amcanorderbyop)
+               if (!GetIndexAmRoutineByAmId(amoid, false)->amcanorderbyop)
                        ereport(ERROR,
                                        (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                                         errmsg("access method \"%s\" does not support ordering operators",
index 1d0e8ad57b4a0954d8a3754ededb2bce12794c46..4893ea3ce91aa04dba431264230fda8dcac4d876 100644 (file)
@@ -605,7 +605,7 @@ IndexSupportsBackwardScan(Oid indexid)
        bool            result;
        HeapTuple       ht_idxrel;
        Form_pg_class idxrelrec;
-       IndexAmRoutine *amroutine;
+       const IndexAmRoutine *amroutine;
 
        /* Fetch the pg_class tuple of the index relation */
        ht_idxrel = SearchSysCache1(RELOID, ObjectIdGetDatum(indexid));
@@ -618,7 +618,6 @@ IndexSupportsBackwardScan(Oid indexid)
 
        result = amroutine->amcanbackward;
 
-       pfree(amroutine);
        ReleaseSysCache(ht_idxrel);
 
        return result;
index bf45c355b77fc855c65fd6ec81e351ddecb0e78a..43ca5fd02134b9352cdb8572094d24639ec00b92 100644 (file)
@@ -231,7 +231,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
                        Oid                     indexoid = lfirst_oid(l);
                        Relation        indexRelation;
                        Form_pg_index index;
-                       IndexAmRoutine *amroutine = NULL;
+                       const IndexAmRoutine *amroutine = NULL;
                        IndexOptInfo *info;
                        int                     ncolumns,
                                                nkeycolumns;
index 0af26d6acfab8472731e774a6f78166c0b637557..59c0112c6967d5be1253d2ae18ed156c71b75b9f 100644 (file)
@@ -156,7 +156,7 @@ indexam_property(FunctionCallInfo fcinfo,
        bool            isnull = false;
        int                     natts = 0;
        IndexAMProperty prop;
-       IndexAmRoutine *routine;
+       const IndexAmRoutine *routine;
 
        /* Try to convert property name to enum (no error if not known) */
        prop = lookup_prop_name(propname);
@@ -452,7 +452,7 @@ pg_indexam_progress_phasename(PG_FUNCTION_ARGS)
 {
        Oid                     amoid = PG_GETARG_OID(0);
        int32           phasenum = PG_GETARG_INT32(1);
-       IndexAmRoutine *routine;
+       const IndexAmRoutine *routine;
        char       *name;
 
        routine = GetIndexAmRoutineByAmId(amoid, true);
index 9f85eb86da1cbe5906f9b29af7895d4a1271e462..ef6978111e8114b8041b2868b31e2a4b9e74c7cf 100644 (file)
@@ -1281,7 +1281,7 @@ pg_get_indexdef_worker(Oid indexrelid, int colno,
        Form_pg_index idxrec;
        Form_pg_class idxrelrec;
        Form_pg_am      amrec;
-       IndexAmRoutine *amroutine;
+       const IndexAmRoutine *amroutine;
        List       *indexprs;
        ListCell   *indexpr_item;
        List       *context;
index 9be36583835d07ba3af2a6b7c23a82354bf5d423..bbe634f0f3218376592b73b140e121b99abf6fbd 100644 (file)
@@ -231,14 +231,7 @@ get_opmethod_canorder(Oid amoid)
                case BRIN_AM_OID:
                        return false;
                default:
-                       {
-                               bool            result;
-                               IndexAmRoutine *amroutine = GetIndexAmRoutineByAmId(amoid, false);
-
-                               result = amroutine->amcanorder;
-                               pfree(amroutine);
-                               return result;
-                       }
+                       return GetIndexAmRoutineByAmId(amoid, false)->amcanorder;
        }
 }
 
@@ -729,7 +722,7 @@ get_op_index_interpretation(Oid opno)
                        {
                                HeapTuple       op_tuple = &catlist->members[i]->tuple;
                                Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
-                               IndexAmRoutine *amroutine = GetIndexAmRoutineByAmId(op_form->amopmethod, false);
+                               const IndexAmRoutine *amroutine = GetIndexAmRoutineByAmId(op_form->amopmethod, false);
                                CompareType cmptype;
 
                                /* must be ordering index */
@@ -800,15 +793,11 @@ equality_ops_are_compatible(Oid opno1, Oid opno2)
                 * op_in_opfamily() is cheaper than GetIndexAmRoutineByAmId(), so
                 * check it first
                 */
-               if (op_in_opfamily(opno2, op_form->amopfamily))
+               if (op_in_opfamily(opno2, op_form->amopfamily) &&
+                       GetIndexAmRoutineByAmId(op_form->amopmethod, false)->amconsistentequality)
                {
-                       IndexAmRoutine *amroutine = GetIndexAmRoutineByAmId(op_form->amopmethod, false);
-
-                       if (amroutine->amconsistentequality)
-                       {
-                               result = true;
-                               break;
-                       }
+                       result = true;
+                       break;
                }
        }
 
@@ -856,15 +845,11 @@ comparison_ops_are_compatible(Oid opno1, Oid opno2)
                 * op_in_opfamily() is cheaper than GetIndexAmRoutineByAmId(), so
                 * check it first
                 */
-               if (op_in_opfamily(opno2, op_form->amopfamily))
+               if (op_in_opfamily(opno2, op_form->amopfamily) &&
+                       GetIndexAmRoutineByAmId(op_form->amopmethod, false)->amconsistentordering)
                {
-                       IndexAmRoutine *amroutine = GetIndexAmRoutineByAmId(op_form->amopmethod, false);
-
-                       if (amroutine->amconsistentordering)
-                       {
-                               result = true;
-                               break;
-                       }
+                       result = true;
+                       break;
                }
        }
 
index 2d0cb7bcfd4a63f3c9bdd7127337e24b77f9c99e..88259f7c2288d1e9638a536b05b25e53a30586f4 100644 (file)
@@ -1420,22 +1420,17 @@ RelationInitPhysicalAddr(Relation relation)
 static void
 InitIndexAmRoutine(Relation relation)
 {
-       IndexAmRoutine *cached,
-                          *tmp;
+       MemoryContext oldctx;
 
        /*
-        * Call the amhandler in current, short-lived memory context, just in case
-        * it leaks anything (it probably won't, but let's be paranoid).
+        * We formerly specified that the amhandler should return a palloc'd
+        * struct.  That's now deprecated in favor of returning a pointer to a
+        * static struct, but to avoid completely breaking old external AMs, run
+        * the amhandler in the relation's rd_indexcxt.
         */
-       tmp = GetIndexAmRoutine(relation->rd_amhandler);
-
-       /* OK, now transfer the data into relation's rd_indexcxt. */
-       cached = (IndexAmRoutine *) MemoryContextAlloc(relation->rd_indexcxt,
-                                                                                                  sizeof(IndexAmRoutine));
-       memcpy(cached, tmp, sizeof(IndexAmRoutine));
-       relation->rd_indam = cached;
-
-       pfree(tmp);
+       oldctx = MemoryContextSwitchTo(relation->rd_indexcxt);
+       relation->rd_indam = GetIndexAmRoutine(relation->rd_amhandler);
+       MemoryContextSwitchTo(oldctx);
 }
 
 /*
index 63dd41c1f21bf38d56a6cc3965d053734f8f7c4c..278da36bc081e3f8a28f188b01865446e279307a 100644 (file)
@@ -226,8 +226,8 @@ typedef void (*aminitparallelscan_function) (void *target);
 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.
+ * API struct for an index AM.  Note we expect index AMs to allocate these
+ * structs statically; the core code never copies nor frees them.
  */
 typedef struct IndexAmRoutine
 {
@@ -326,8 +326,8 @@ typedef struct IndexAmRoutine
 
 
 /* Functions in access/index/amapi.c */
-extern IndexAmRoutine *GetIndexAmRoutine(Oid amhandler);
-extern IndexAmRoutine *GetIndexAmRoutineByAmId(Oid amoid, bool noerror);
+extern const IndexAmRoutine *GetIndexAmRoutine(Oid amhandler);
+extern const IndexAmRoutine *GetIndexAmRoutineByAmId(Oid amoid, bool noerror);
 extern CompareType IndexAmTranslateStrategy(StrategyNumber strategy, Oid amoid, Oid opfamily, bool missing_ok);
 extern StrategyNumber IndexAmTranslateCompareType(CompareType cmptype, Oid amoid, Oid opfamily, bool missing_ok);
 
index 80286076a111a4f195a6721f15427ba48147630b..82d0e419e4b62c6e1205c7503a159b3da6dd9f3b 100644 (file)
@@ -203,7 +203,7 @@ typedef struct RelationData
         */
        MemoryContext rd_indexcxt;      /* private memory cxt for this stuff */
        /* use "struct" here to avoid needing to include amapi.h: */
-       struct IndexAmRoutine *rd_indam;        /* index AM's API struct */
+       const 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 */
        RegProcedure *rd_support;       /* OIDs of support procedures */
index a34382a5f7909011a642406ce493a8ffb60be598..d18b18106afc3f03bb29003ae3f044f491c6a5c8 100644 (file)
@@ -276,56 +276,57 @@ diendscan(IndexScanDesc scan)
 Datum
 dihandler(PG_FUNCTION_ARGS)
 {
-       IndexAmRoutine *amroutine = makeNode(IndexAmRoutine);
-
-       amroutine->amstrategies = 0;
-       amroutine->amsupport = 1;
-       amroutine->amcanorder = false;
-       amroutine->amcanorderbyop = false;
-       amroutine->amcanhash = false;
-       amroutine->amconsistentequality = false;
-       amroutine->amconsistentordering = false;
-       amroutine->amcanbackward = false;
-       amroutine->amcanunique = false;
-       amroutine->amcanmulticol = false;
-       amroutine->amoptionalkey = false;
-       amroutine->amsearcharray = false;
-       amroutine->amsearchnulls = false;
-       amroutine->amstorage = false;
-       amroutine->amclusterable = false;
-       amroutine->ampredlocks = false;
-       amroutine->amcanparallel = false;
-       amroutine->amcanbuildparallel = false;
-       amroutine->amcaninclude = false;
-       amroutine->amusemaintenanceworkmem = false;
-       amroutine->amsummarizing = false;
-       amroutine->amparallelvacuumoptions = VACUUM_OPTION_NO_PARALLEL;
-       amroutine->amkeytype = InvalidOid;
-
-       amroutine->ambuild = dibuild;
-       amroutine->ambuildempty = dibuildempty;
-       amroutine->aminsert = diinsert;
-       amroutine->ambulkdelete = dibulkdelete;
-       amroutine->amvacuumcleanup = divacuumcleanup;
-       amroutine->amcanreturn = NULL;
-       amroutine->amcostestimate = dicostestimate;
-       amroutine->amgettreeheight = NULL;
-       amroutine->amoptions = dioptions;
-       amroutine->amproperty = NULL;
-       amroutine->ambuildphasename = NULL;
-       amroutine->amvalidate = divalidate;
-       amroutine->ambeginscan = dibeginscan;
-       amroutine->amrescan = direscan;
-       amroutine->amgettuple = NULL;
-       amroutine->amgetbitmap = NULL;
-       amroutine->amendscan = diendscan;
-       amroutine->ammarkpos = NULL;
-       amroutine->amrestrpos = NULL;
-       amroutine->amestimateparallelscan = NULL;
-       amroutine->aminitparallelscan = NULL;
-       amroutine->amparallelrescan = NULL;
-
-       PG_RETURN_POINTER(amroutine);
+       static const IndexAmRoutine amroutine = {
+               .type = T_IndexAmRoutine,
+               .amstrategies = 0,
+               .amsupport = 1,
+               .amcanorder = false,
+               .amcanorderbyop = false,
+               .amcanhash = false,
+               .amconsistentequality = false,
+               .amconsistentordering = false,
+               .amcanbackward = false,
+               .amcanunique = false,
+               .amcanmulticol = false,
+               .amoptionalkey = false,
+               .amsearcharray = false,
+               .amsearchnulls = false,
+               .amstorage = false,
+               .amclusterable = false,
+               .ampredlocks = false,
+               .amcanparallel = false,
+               .amcanbuildparallel = false,
+               .amcaninclude = false,
+               .amusemaintenanceworkmem = false,
+               .amsummarizing = false,
+               .amparallelvacuumoptions = VACUUM_OPTION_NO_PARALLEL,
+               .amkeytype = InvalidOid,
+
+               .ambuild = dibuild,
+               .ambuildempty = dibuildempty,
+               .aminsert = diinsert,
+               .ambulkdelete = dibulkdelete,
+               .amvacuumcleanup = divacuumcleanup,
+               .amcanreturn = NULL,
+               .amcostestimate = dicostestimate,
+               .amgettreeheight = NULL,
+               .amoptions = dioptions,
+               .amproperty = NULL,
+               .ambuildphasename = NULL,
+               .amvalidate = divalidate,
+               .ambeginscan = dibeginscan,
+               .amrescan = direscan,
+               .amgettuple = NULL,
+               .amgetbitmap = NULL,
+               .amendscan = diendscan,
+               .ammarkpos = NULL,
+               .amrestrpos = NULL,
+               .amestimateparallelscan = NULL,
+               .aminitparallelscan = NULL,
+               .amparallelrescan = NULL,
+       };
+
+       PG_RETURN_POINTER(&amroutine);
 }
 
 void