1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-17 17:02:08 +03:00

Invent "amadjustmembers" AM method for validating opclass members.

This allows AM-specific knowledge to be applied during creation of
pg_amop and pg_amproc entries.  Specifically, the AM knows better than
core code which entries to consider as required or optional.  Giving
the latter entries the appropriate sort of dependency allows them to
be dropped without taking out the whole opclass or opfamily; which
is something we'd like to have to correct obsolescent entries in
extensions.

This callback also opens the door to performing AM-specific validity
checks during opclass creation, rather than hoping than an opclass
developer will remember to test with "amvalidate".  For the most part
I've not actually added any such checks yet; that can happen in a
follow-on patch.  (Note that we shouldn't remove any tests from
"amvalidate", as those are still needed to cross-check manually
constructed entries in the initdb data.  So adding tests to
"amadjustmembers" will be somewhat duplicative, but it seems like
a good idea anyway.)

Patch by me, reviewed by Alexander Korotkov, Hamid Akhtar, and
Anastasia Lubennikova.

Discussion: https://postgr.es/m/4578.1565195302@sss.pgh.pa.us
This commit is contained in:
Tom Lane
2020-08-01 17:12:47 -04:00
parent e2b37d9e7c
commit 9f9682783b
24 changed files with 646 additions and 112 deletions

View File

@ -92,6 +92,7 @@ gisthandler(PG_FUNCTION_ARGS)
amroutine->amproperty = gistproperty;
amroutine->ambuildphasename = NULL;
amroutine->amvalidate = gistvalidate;
amroutine->amadjustmembers = gistadjustmembers;
amroutine->ambeginscan = gistbeginscan;
amroutine->amrescan = gistrescan;
amroutine->amgettuple = gistgettuple;

View File

@ -279,3 +279,72 @@ gistvalidate(Oid opclassoid)
return result;
}
/*
* Prechecking function for adding operators/functions to a GiST opfamily.
*/
void
gistadjustmembers(Oid opfamilyoid,
Oid opclassoid,
List *operators,
List *functions)
{
ListCell *lc;
/*
* Operator members of a GiST opfamily should never have hard
* dependencies, since their connection to the opfamily depends only on
* what the support functions think, and that can be altered. For
* consistency, we make all soft dependencies point to the opfamily,
* though a soft dependency on the opclass would work as well in the
* CREATE OPERATOR CLASS case.
*/
foreach(lc, operators)
{
OpFamilyMember *op = (OpFamilyMember *) lfirst(lc);
op->ref_is_hard = false;
op->ref_is_family = true;
op->refobjid = opfamilyoid;
}
/*
* Required support functions should have hard dependencies. Preferably
* those are just dependencies on the opclass, but if we're in ALTER
* OPERATOR FAMILY, we leave the dependency pointing at the whole
* opfamily. (Given that GiST opclasses generally don't share opfamilies,
* it seems unlikely to be worth working harder.)
*/
foreach(lc, functions)
{
OpFamilyMember *op = (OpFamilyMember *) lfirst(lc);
switch (op->number)
{
case GIST_CONSISTENT_PROC:
case GIST_UNION_PROC:
case GIST_PENALTY_PROC:
case GIST_PICKSPLIT_PROC:
case GIST_EQUAL_PROC:
/* Required support function */
op->ref_is_hard = true;
break;
case GIST_COMPRESS_PROC:
case GIST_DECOMPRESS_PROC:
case GIST_DISTANCE_PROC:
case GIST_FETCH_PROC:
case GIST_OPTIONS_PROC:
/* Optional, so force it to be a soft family dependency */
op->ref_is_hard = false;
op->ref_is_family = true;
op->refobjid = opfamilyoid;
break;
default:
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("support function number %d is invalid for access method %s",
op->number, "gist")));
break;
}
}
}