Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  spgvalidate.c

  Sprache: C
 

/*-------------------------------------------------------------------------
 *
 * spgvalidate.c
 *   Opclass validator for SP-GiST.
 *
 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * IDENTIFICATION
 *   src/backend/access/spgist/spgvalidate.c
 *
 *-------------------------------------------------------------------------
 */

#include "postgres.h"

#include "access/amvalidate.h"
#include "access/htup_details.h"
#include "access/spgist.h"
#include "catalog/pg_amop.h"
#include "catalog/pg_amproc.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_type.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/regproc.h"
#include "utils/syscache.h"


/*
 * Validator for an SP-GiST opclass.
 *
 * Some of the checks done here cover the whole opfamily, and therefore are
 * redundant when checking each opclass in a family.  But they don't run long
 * enough to be much of a problem, so we accept the duplication rather than
 * complicate the amvalidate API.
 */

bool
spgvalidate(Oid opclassoid)
{
 bool  result = true;
 HeapTuple classtup;
 Form_pg_opclass classform;
 Oid   opfamilyoid;
 Oid   opcintype;
 Oid   opckeytype;
 char    *opclassname;
 char    *opfamilyname;
 CatCList   *proclist,
      *oprlist;
 List    *grouplist;
 OpFamilyOpFuncGroup *opclassgroup;
 int   i;
 ListCell   *lc;
 spgConfigIn configIn;
 spgConfigOut configOut;
 Oid   configOutLefttype = InvalidOid;
 Oid   configOutRighttype = InvalidOid;
 Oid   configOutLeafType = InvalidOid;

 /* Fetch opclass information */
 classtup = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclassoid));
 if (!HeapTupleIsValid(classtup))
  elog(ERROR, "cache lookup failed for operator class %u", opclassoid);
 classform = (Form_pg_opclass) GETSTRUCT(classtup);

 opfamilyoid = classform->opcfamily;
 opcintype = classform->opcintype;
 opckeytype = classform->opckeytype;
 opclassname = NameStr(classform->opcname);

 /* Fetch opfamily information */
 opfamilyname = get_opfamily_name(opfamilyoid, false);

 /* Fetch all operators and support functions of the opfamily */
 oprlist = SearchSysCacheList1(AMOPSTRATEGY, ObjectIdGetDatum(opfamilyoid));
 proclist = SearchSysCacheList1(AMPROCNUM, ObjectIdGetDatum(opfamilyoid));
 grouplist = identify_opfamily_groups(oprlist, proclist);

 /* Check individual support functions */
 for (i = 0; i < proclist->n_members; i++)
 {
  HeapTuple proctup = &proclist->members[i]->tuple;
  Form_pg_amproc procform = (Form_pg_amproc) GETSTRUCT(proctup);
  bool  ok;

  /*
   * All SP-GiST support functions should be registered with matching
   * left/right types
 */

  if (procform->amproclefttype != procform->amprocrighttype)
  {
   ereport(INFO,
     (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
      errmsg("operator family \"%s\" of access method %s contains support function %s with different left and right input types",
       opfamilyname, "spgist",
       format_procedure(procform->amproc))));
   result = false;
  }

  /* Check procedure numbers and function signatures */
  switch (procform->amprocnum)
  {
   case SPGIST_CONFIG_PROC:
    ok = check_amproc_signature(procform->amproc, VOIDOID, true,
           22, INTERNALOID, INTERNALOID);
    configIn.attType = procform->amproclefttype;
    memset(&configOut, 0sizeof(configOut));

    OidFunctionCall2(procform->amproc,
         PointerGetDatum(&configIn),
         PointerGetDatum(&configOut));

    configOutLefttype = procform->amproclefttype;
    configOutRighttype = procform->amprocrighttype;

    /* Default leaf type is opckeytype or input type */
    if (OidIsValid(opckeytype))
     configOutLeafType = opckeytype;
    else
     configOutLeafType = procform->amproclefttype;

    /* If some other leaf datum type is specified, warn */
    if (OidIsValid(configOut.leafType) &&
     configOutLeafType != configOut.leafType)
    {
     ereport(INFO,
       (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
        errmsg("SP-GiST leaf data type %s does not match declared type %s",
         format_type_be(configOut.leafType),
         format_type_be(configOutLeafType))));
     result = false;
     configOutLeafType = configOut.leafType;
    }

    /*
     * When leaf and attribute types are the same, compress
     * function is not required and we set corresponding bit in
     * functionset for later group consistency check.
 */

    if (configOutLeafType == configIn.attType)
    {
     foreach(lc, grouplist)
     {
      OpFamilyOpFuncGroup *group = lfirst(lc);

      if (group->lefttype == procform->amproclefttype &&
       group->righttype == procform->amprocrighttype)
      {
       group->functionset |=
        ((uint64) 1) << SPGIST_COMPRESS_PROC;
       break;
      }
     }
    }
    break;
   case SPGIST_CHOOSE_PROC:
   case SPGIST_PICKSPLIT_PROC:
   case SPGIST_INNER_CONSISTENT_PROC:
    ok = check_amproc_signature(procform->amproc, VOIDOID, true,
           22, INTERNALOID, INTERNALOID);
    break;
   case SPGIST_LEAF_CONSISTENT_PROC:
    ok = check_amproc_signature(procform->amproc, BOOLOID, true,
           22, INTERNALOID, INTERNALOID);
    break;
   case SPGIST_COMPRESS_PROC:
    if (configOutLefttype != procform->amproclefttype ||
     configOutRighttype != procform->amprocrighttype)
     ok = false;
    else
     ok = check_amproc_signature(procform->amproc,
            configOutLeafType, true,
            11, procform->amproclefttype);
    break;
   case SPGIST_OPTIONS_PROC:
    ok = check_amoptsproc_signature(procform->amproc);
    break;
   default:
    ereport(INFO,
      (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
       errmsg("operator family \"%s\" of access method %s contains function %s with invalid support number %d",
        opfamilyname, "spgist",
        format_procedure(procform->amproc),
        procform->amprocnum)));
    result = false;
    continue;  /* don't want additional message */
  }

  if (!ok)
  {
   ereport(INFO,
     (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
      errmsg("operator family \"%s\" of access method %s contains function %s with wrong signature for support number %d",
       opfamilyname, "spgist",
       format_procedure(procform->amproc),
       procform->amprocnum)));
   result = false;
  }
 }

 /* Check individual operators */
 for (i = 0; i < oprlist->n_members; i++)
 {
  HeapTuple oprtup = &oprlist->members[i]->tuple;
  Form_pg_amop oprform = (Form_pg_amop) GETSTRUCT(oprtup);
  Oid   op_rettype;

  /* TODO: Check that only allowed strategy numbers exist */
  if (oprform->amopstrategy < 1 || oprform->amopstrategy > 63)
  {
   ereport(INFO,
     (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
      errmsg("operator family \"%s\" of access method %s contains operator %s with invalid strategy number %d",
       opfamilyname, "spgist",
       format_operator(oprform->amopopr),
       oprform->amopstrategy)));
   result = false;
  }

  /* spgist supports ORDER BY operators */
  if (oprform->amoppurpose != AMOP_SEARCH)
  {
   /* ... and operator result must match the claimed btree opfamily */
   op_rettype = get_op_rettype(oprform->amopopr);
   if (!opfamily_can_sort_type(oprform->amopsortfamily, op_rettype))
   {
    ereport(INFO,
      (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
       errmsg("operator family \"%s\" of access method %s contains invalid ORDER BY specification for operator %s",
        opfamilyname, "spgist",
        format_operator(oprform->amopopr))));
    result = false;
   }
  }
  else
   op_rettype = BOOLOID;

  /* Check operator signature --- same for all spgist strategies */
  if (!check_amop_signature(oprform->amopopr, op_rettype,
          oprform->amoplefttype,
          oprform->amoprighttype))
  {
   ereport(INFO,
     (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
      errmsg("operator family \"%s\" of access method %s contains operator %s with wrong signature",
       opfamilyname, "spgist",
       format_operator(oprform->amopopr))));
   result = false;
  }
 }

 /* Now check for inconsistent groups of operators/functions */
 opclassgroup = NULL;
 foreach(lc, grouplist)
 {
  OpFamilyOpFuncGroup *thisgroup = (OpFamilyOpFuncGroup *) lfirst(lc);

  /* Remember the group exactly matching the test opclass */
  if (thisgroup->lefttype == opcintype &&
   thisgroup->righttype == opcintype)
   opclassgroup = thisgroup;

  /*
   * Complain if there are any datatype pairs with functions but no
   * operators.  This is about the best we can do for now to detect
   * missing operators.
 */

  if (thisgroup->operatorset == 0)
  {
   ereport(INFO,
     (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
      errmsg("operator family \"%s\" of access method %s is missing operator(s) for types %s and %s",
       opfamilyname, "spgist",
       format_type_be(thisgroup->lefttype),
       format_type_be(thisgroup->righttype))));
   result = false;
  }

  /*
   * Complain if we're missing functions for any datatype, remembering
   * that SP-GiST doesn't use cross-type support functions.
 */

  if (thisgroup->lefttype != thisgroup->righttype)
   continue;

  for (i = 1; i <= SPGISTNProc; i++)
  {
   if ((thisgroup->functionset & (((uint64) 1) << i)) != 0)
    continue;  /* got it */
   if (i == SPGIST_OPTIONS_PROC)
    continue;  /* optional method */
   ereport(INFO,
     (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
      errmsg("operator family \"%s\" of access method %s is missing support function %d for type %s",
       opfamilyname, "spgist", i,
       format_type_be(thisgroup->lefttype))));
   result = false;
  }
 }

 /* Check that the originally-named opclass is supported */
 /* (if group is there, we already checked it adequately above) */
 if (!opclassgroup)
 {
  ereport(INFO,
    (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
     errmsg("operator class \"%s\" of access method %s is missing operator(s)",
      opclassname, "spgist")));
  result = false;
 }

 ReleaseCatCacheList(proclist);
 ReleaseCatCacheList(oprlist);
 ReleaseSysCache(classtup);

 return result;
}

/*
 * Prechecking function for adding operators/functions to an SP-GiST opfamily.
 */

void
spgadjustmembers(Oid opfamilyoid,
     Oid opclassoid,
     List *operators,
     List *functions)
{
 ListCell   *lc;

 /*
  * Operator members of an SP-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 SP-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 SPGIST_CONFIG_PROC:
   case SPGIST_CHOOSE_PROC:
   case SPGIST_PICKSPLIT_PROC:
   case SPGIST_INNER_CONSISTENT_PROC:
   case SPGIST_LEAF_CONSISTENT_PROC:
    /* Required support function */
    op->ref_is_hard = true;
    break;
   case SPGIST_COMPRESS_PROC:
   case SPGIST_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, "spgist")));
    break;
  }
 }
}

Messung V0.5 in Prozent
C=91 H=97 G=93

¤ Dauer der Verarbeitung: 0.15 Sekunden  (vorverarbeitet am  2026-08-08) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=141584
#Domains=752002