Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Postgres/src/backend/access/brin/   (Postgres Database Version 18.4©)  Datei vom 11.4.2026 mit Größe 9 kB image not shown  

Quelle  brin_minmax.c   Sprache: C

 

/*
 * brin_minmax.c
 *  Implementation of Min/Max opclass for BRIN
 *
 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * IDENTIFICATION
 *   src/backend/access/brin/brin_minmax.c
 */

#include "postgres.h"

#include "access/brin_internal.h"
#include "access/brin_tuple.h"
#include "access/stratnum.h"
#include "catalog/pg_amop.h"
#include "utils/datum.h"
#include "utils/fmgrprotos.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/syscache.h"

typedef struct MinmaxOpaque
{
 Oid   cached_subtype;
 FmgrInfo strategy_procinfos[BTMaxStrategyNumber];
} MinmaxOpaque;

static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
             Oid subtype, uint16 strategynum);


Datum
brin_minmax_opcinfo(PG_FUNCTION_ARGS)
{
 Oid   typoid = PG_GETARG_OID(0);
 BrinOpcInfo *result;

 /*
  * opaque->strategy_procinfos is initialized lazily; here it is set to
  * all-uninitialized by palloc0 which sets fn_oid to InvalidOid.
 */


 result = palloc0(MAXALIGN(SizeofBrinOpcInfo(2)) +
      sizeof(MinmaxOpaque));
 result->oi_nstored = 2;
 result->oi_regular_nulls = true;
 result->oi_opaque = (MinmaxOpaque *)
  MAXALIGN((char *) result + SizeofBrinOpcInfo(2));
 result->oi_typcache[0] = result->oi_typcache[1] =
  lookup_type_cache(typoid, 0);

 PG_RETURN_POINTER(result);
}

/*
 * Examine the given index tuple (which contains partial status of a certain
 * page range) by comparing it to the given value that comes from another heap
 * tuple.  If the new value is outside the min/max range specified by the
 * existing tuple values, update the index tuple and return true.  Otherwise,
 * return false and do not modify in this case.
 */

Datum
brin_minmax_add_value(PG_FUNCTION_ARGS)
{
 BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
 Datum  newval = PG_GETARG_DATUM(2);
 bool  isnull PG_USED_FOR_ASSERTS_ONLY = PG_GETARG_DATUM(3);
 Oid   colloid = PG_GET_COLLATION();
 FmgrInfo   *cmpFn;
 Datum  compar;
 bool  updated = false;
 Form_pg_attribute attr;
 AttrNumber attno;

 Assert(!isnull);

 attno = column->bv_attno;
 attr = TupleDescAttr(bdesc->bd_tupdesc, attno - 1);

 /*
  * If the recorded value is null, store the new value (which we know to be
  * not null) as both minimum and maximum, and we're done.
 */

 if (column->bv_allnulls)
 {
  column->bv_values[0] = datumCopy(newval, attr->attbyval, attr->attlen);
  column->bv_values[1] = datumCopy(newval, attr->attbyval, attr->attlen);
  column->bv_allnulls = false;
  PG_RETURN_BOOL(true);
 }

 /*
  * Otherwise, need to compare the new value with the existing boundaries
  * and update them accordingly.  First check if it's less than the
  * existing minimum.
 */

 cmpFn = minmax_get_strategy_procinfo(bdesc, attno, attr->atttypid,
           BTLessStrategyNumber);
 compar = FunctionCall2Coll(cmpFn, colloid, newval, column->bv_values[0]);
 if (DatumGetBool(compar))
 {
  if (!attr->attbyval)
   pfree(DatumGetPointer(column->bv_values[0]));
  column->bv_values[0] = datumCopy(newval, attr->attbyval, attr->attlen);
  updated = true;
 }

 /*
  * And now compare it to the existing maximum.
 */

 cmpFn = minmax_get_strategy_procinfo(bdesc, attno, attr->atttypid,
           BTGreaterStrategyNumber);
 compar = FunctionCall2Coll(cmpFn, colloid, newval, column->bv_values[1]);
 if (DatumGetBool(compar))
 {
  if (!attr->attbyval)
   pfree(DatumGetPointer(column->bv_values[1]));
  column->bv_values[1] = datumCopy(newval, attr->attbyval, attr->attlen);
  updated = true;
 }

 PG_RETURN_BOOL(updated);
}

/*
 * Given an index tuple corresponding to a certain page range and a scan key,
 * return whether the scan key is consistent with the index tuple's min/max
 * values.  Return true if so, false otherwise.
 *
 * We're no longer dealing with NULL keys in the consistent function, that is
 * now handled by the AM code. That means we should not get any all-NULL ranges
 * either, because those can't be consistent with regular (not [IS] NULL) keys.
 */

Datum
brin_minmax_consistent(PG_FUNCTION_ARGS)
{
 BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
 ScanKey  key = (ScanKey) PG_GETARG_POINTER(2);
 Oid   colloid = PG_GET_COLLATION(),
    subtype;
 AttrNumber attno;
 Datum  value;
 Datum  matches;
 FmgrInfo   *finfo;

 /* This opclass uses the old signature with only three arguments. */
 Assert(PG_NARGS() == 3);

 /* Should not be dealing with all-NULL ranges. */
 Assert(!column->bv_allnulls);

 attno = key->sk_attno;
 subtype = key->sk_subtype;
 value = key->sk_argument;
 switch (key->sk_strategy)
 {
  case BTLessStrategyNumber:
  case BTLessEqualStrategyNumber:
   finfo = minmax_get_strategy_procinfo(bdesc, attno, subtype,
             key->sk_strategy);
   matches = FunctionCall2Coll(finfo, colloid, column->bv_values[0],
          value);
   break;
  case BTEqualStrategyNumber:

   /*
    * In the equality case (WHERE col = someval), we want to return
    * the current page range if the minimum value in the range <=
    * scan key, and the maximum value >= scan key.
 */

   finfo = minmax_get_strategy_procinfo(bdesc, attno, subtype,
             BTLessEqualStrategyNumber);
   matches = FunctionCall2Coll(finfo, colloid, column->bv_values[0],
          value);
   if (!DatumGetBool(matches))
    break;
   /* max() >= scankey */
   finfo = minmax_get_strategy_procinfo(bdesc, attno, subtype,
             BTGreaterEqualStrategyNumber);
   matches = FunctionCall2Coll(finfo, colloid, column->bv_values[1],
          value);
   break;
  case BTGreaterEqualStrategyNumber:
  case BTGreaterStrategyNumber:
   finfo = minmax_get_strategy_procinfo(bdesc, attno, subtype,
             key->sk_strategy);
   matches = FunctionCall2Coll(finfo, colloid, column->bv_values[1],
          value);
   break;
  default:
   /* shouldn't happen */
   elog(ERROR, "invalid strategy number %d", key->sk_strategy);
   matches = 0;
   break;
 }

 PG_RETURN_DATUM(matches);
}

/*
 * Given two BrinValues, update the first of them as a union of the summary
 * values contained in both.  The second one is untouched.
 */

Datum
brin_minmax_union(PG_FUNCTION_ARGS)
{
 BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 BrinValues *col_a = (BrinValues *) PG_GETARG_POINTER(1);
 BrinValues *col_b = (BrinValues *) PG_GETARG_POINTER(2);
 Oid   colloid = PG_GET_COLLATION();
 AttrNumber attno;
 Form_pg_attribute attr;
 FmgrInfo   *finfo;
 bool  needsadj;

 Assert(col_a->bv_attno == col_b->bv_attno);
 Assert(!col_a->bv_allnulls && !col_b->bv_allnulls);

 attno = col_a->bv_attno;
 attr = TupleDescAttr(bdesc->bd_tupdesc, attno - 1);

 /* Adjust minimum, if B's min is less than A's min */
 finfo = minmax_get_strategy_procinfo(bdesc, attno, attr->atttypid,
           BTLessStrategyNumber);
 needsadj = FunctionCall2Coll(finfo, colloid, col_b->bv_values[0],
         col_a->bv_values[0]);
 if (needsadj)
 {
  if (!attr->attbyval)
   pfree(DatumGetPointer(col_a->bv_values[0]));
  col_a->bv_values[0] = datumCopy(col_b->bv_values[0],
          attr->attbyval, attr->attlen);
 }

 /* Adjust maximum, if B's max is greater than A's max */
 finfo = minmax_get_strategy_procinfo(bdesc, attno, attr->atttypid,
           BTGreaterStrategyNumber);
 needsadj = FunctionCall2Coll(finfo, colloid, col_b->bv_values[1],
         col_a->bv_values[1]);
 if (needsadj)
 {
  if (!attr->attbyval)
   pfree(DatumGetPointer(col_a->bv_values[1]));
  col_a->bv_values[1] = datumCopy(col_b->bv_values[1],
          attr->attbyval, attr->attlen);
 }

 PG_RETURN_VOID();
}

/*
 * Cache and return the procedure for the given strategy.
 *
 * Note: this function mirrors inclusion_get_strategy_procinfo; see notes
 * there.  If changes are made here, see that function too.
 */

static FmgrInfo *
minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno, Oid subtype,
        uint16 strategynum)
{
 MinmaxOpaque *opaque;

 Assert(strategynum >= 1 &&
     strategynum <= BTMaxStrategyNumber);

 opaque = (MinmaxOpaque *) bdesc->bd_info[attno - 1]->oi_opaque;

 /*
  * We cache the procedures for the previous subtype in the opaque struct,
  * to avoid repetitive syscache lookups.  If the subtype changed,
  * invalidate all the cached entries.
 */

 if (opaque->cached_subtype != subtype)
 {
  uint16  i;

  for (i = 1; i <= BTMaxStrategyNumber; i++)
   opaque->strategy_procinfos[i - 1].fn_oid = InvalidOid;
  opaque->cached_subtype = subtype;
 }

 if (opaque->strategy_procinfos[strategynum - 1].fn_oid == InvalidOid)
 {
  Form_pg_attribute attr;
  HeapTuple tuple;
  Oid   opfamily,
     oprid;

  opfamily = bdesc->bd_index->rd_opfamily[attno - 1];
  attr = TupleDescAttr(bdesc->bd_tupdesc, attno - 1);
  tuple = SearchSysCache4(AMOPSTRATEGY, ObjectIdGetDatum(opfamily),
        ObjectIdGetDatum(attr->atttypid),
        ObjectIdGetDatum(subtype),
        Int16GetDatum(strategynum));

  if (!HeapTupleIsValid(tuple))
   elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
     strategynum, attr->atttypid, subtype, opfamily);

  oprid = DatumGetObjectId(SysCacheGetAttrNotNull(AMOPSTRATEGY, tuple,
              Anum_pg_amop_amopopr));
  ReleaseSysCache(tuple);
  Assert(RegProcedureIsValid(oprid));

  fmgr_info_cxt(get_opcode(oprid),
       &opaque->strategy_procinfos[strategynum - 1],
       bdesc->bd_context);
 }

 return &opaque->strategy_procinfos[strategynum - 1];
}

Messung V0.5 in Prozent
C=92 H=95 G=93

¤ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet am  2026-09-28) ¤

*© 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.