Eine aufbereitete Darstellung der Quelle

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

Benutzer

Quelle  network_gist.c

  Sprache: C
 

/*-------------------------------------------------------------------------
 *
 * network_gist.c
 *   GiST support for network types.
 *
 * The key thing to understand about this code is the definition of the
 * "union" of a set of INET/CIDR values.  It works like this:
 * 1. If the values are not all of the same IP address family, the "union"
 * is a dummy value with family number zero, minbits zero, commonbits zero,
 * address all zeroes.  Otherwise:
 * 2. The union has the common IP address family number.
 * 3. The union's minbits value is the smallest netmask length ("ip_bits")
 * of all the input values.
 * 4. Let C be the number of leading address bits that are in common among
 * all the input values (C ranges from 0 to ip_maxbits for the family).
 * 5. The union's commonbits value is C.
 * 6. The union's address value is the same as the common prefix for its
 * first C bits, and is zeroes to the right of that.  The physical width
 * of the address value is ip_maxbits for the address family.
 *
 * In a leaf index entry (representing a single key), commonbits is equal to
 * ip_maxbits for the address family, minbits is the same as the represented
 * value's ip_bits, and the address is equal to the represented address.
 * Although it may appear that we're wasting a byte by storing the union
 * format and not just the represented INET/CIDR value in leaf keys, the
 * extra byte is actually "free" because of alignment considerations.
 *
 * Note that this design tracks minbits and commonbits independently; in any
 * given union value, either might be smaller than the other.  This does not
 * help us much when descending the tree, because of the way inet comparison
 * is defined: at non-leaf nodes we can't compare more than minbits bits
 * even if we know them.  However, it greatly improves the quality of split
 * decisions.  Preliminary testing suggests that searches are as much as
 * twice as fast as for a simpler design in which a single field doubles as
 * the common prefix length and the minimum ip_bits value.
 *
 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *   src/backend/utils/adt/network_gist.c
 *
 *-------------------------------------------------------------------------
 */

#include "postgres.h"

#include <sys/socket.h>

#include "access/gist.h"
#include "access/stratnum.h"
#include "utils/fmgrprotos.h"
#include "utils/inet.h"
#include "varatt.h"

/*
 * Operator strategy numbers used in the GiST inet_ops opclass
 */

#define INETSTRAT_OVERLAPS  RTOverlapStrategyNumber
#define INETSTRAT_EQ   RTEqualStrategyNumber
#define INETSTRAT_NE   RTNotEqualStrategyNumber
#define INETSTRAT_LT   RTLessStrategyNumber
#define INETSTRAT_LE   RTLessEqualStrategyNumber
#define INETSTRAT_GT   RTGreaterStrategyNumber
#define INETSTRAT_GE   RTGreaterEqualStrategyNumber
#define INETSTRAT_SUB   RTSubStrategyNumber
#define INETSTRAT_SUBEQ   RTSubEqualStrategyNumber
#define INETSTRAT_SUP   RTSuperStrategyNumber
#define INETSTRAT_SUPEQ   RTSuperEqualStrategyNumber


/*
 * Representation of a GiST INET/CIDR index key.  This is not identical to
 * INET/CIDR because we need to keep track of the length of the common address
 * prefix as well as the minimum netmask length.  However, as long as it
 * follows varlena header rules, the core GiST code won't know the difference.
 * For simplicity we always use 1-byte-header varlena format.
 */

typedef struct GistInetKey
{
 uint8  va_header;  /* varlena header --- don't touch directly */
 unsigned char family;  /* PGSQL_AF_INET, PGSQL_AF_INET6, or zero */
 unsigned char minbits;  /* minimum number of bits in netmask */
 unsigned char commonbits; /* number of common prefix bits in addresses */
 unsigned char ipaddr[16]; /* up to 128 bits of common address */
} GistInetKey;

#define DatumGetInetKeyP(X) ((GistInetKey *) DatumGetPointer(X))
#define InetKeyPGetDatum(X) PointerGetDatum(X)

/*
 * Access macros; not really exciting, but we use these for notational
 * consistency with access to INET/CIDR values.  Note that family-zero values
 * are stored with 4 bytes of address, not 16.
 */

#define gk_ip_family(gkptr)  ((gkptr)->family)
#define gk_ip_minbits(gkptr) ((gkptr)->minbits)
#define gk_ip_commonbits(gkptr) ((gkptr)->commonbits)
#define gk_ip_addr(gkptr)  ((gkptr)->ipaddr)
#define ip_family_maxbits(fam) ((fam) == PGSQL_AF_INET6 ? 128 : 32)

/* These require that the family field has been set: */
#define gk_ip_addrsize(gkptr) \
 (gk_ip_family(gkptr) == PGSQL_AF_INET6 ? 16 : 4)
#define gk_ip_maxbits(gkptr) \
 ip_family_maxbits(gk_ip_family(gkptr))
#define SET_GK_VARSIZE(dst) \
 SET_VARSIZE_SHORT(dst, offsetof(GistInetKey, ipaddr) + gk_ip_addrsize(dst))


/*
 * The GiST query consistency check
 */

Datum
inet_gist_consistent(PG_FUNCTION_ARGS)
{
 GISTENTRY  *ent = (GISTENTRY *) PG_GETARG_POINTER(0);
 inet    *query = PG_GETARG_INET_PP(1);
 StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);

 /* Oid subtype = PG_GETARG_OID(3); */
 bool    *recheck = (bool *) PG_GETARG_POINTER(4);
 GistInetKey *key = DatumGetInetKeyP(ent->key);
 int   minbits,
    order;

 /* All operators served by this function are exact. */
 *recheck = false;

 /*
  * Check 0: different families
  *
  * If key represents multiple address families, its children could match
  * anything.  This can only happen on an inner index page.
 */

 if (gk_ip_family(key) == 0)
 {
  Assert(!GIST_LEAF(ent));
  PG_RETURN_BOOL(true);
 }

 /*
  * Check 1: different families
  *
  * Matching families do not help any of the strategies.
 */

 if (gk_ip_family(key) != ip_family(query))
 {
  switch (strategy)
  {
   case INETSTRAT_LT:
   case INETSTRAT_LE:
    if (gk_ip_family(key) < ip_family(query))
     PG_RETURN_BOOL(true);
    break;

   case INETSTRAT_GE:
   case INETSTRAT_GT:
    if (gk_ip_family(key) > ip_family(query))
     PG_RETURN_BOOL(true);
    break;

   case INETSTRAT_NE:
    PG_RETURN_BOOL(true);
  }
  /* For all other cases, we can be sure there is no match */
  PG_RETURN_BOOL(false);
 }

 /*
  * Check 2: network bit count
  *
  * Network bit count (ip_bits) helps to check leaves for sub network and
  * sup network operators.  At non-leaf nodes, we know every child value
  * has ip_bits >= gk_ip_minbits(key), so we can avoid descending in some
  * cases too.
 */

 switch (strategy)
 {
  case INETSTRAT_SUB:
   if (GIST_LEAF(ent) && gk_ip_minbits(key) <= ip_bits(query))
    PG_RETURN_BOOL(false);
   break;

  case INETSTRAT_SUBEQ:
   if (GIST_LEAF(ent) && gk_ip_minbits(key) < ip_bits(query))
    PG_RETURN_BOOL(false);
   break;

  case INETSTRAT_SUPEQ:
  case INETSTRAT_EQ:
   if (gk_ip_minbits(key) > ip_bits(query))
    PG_RETURN_BOOL(false);
   break;

  case INETSTRAT_SUP:
   if (gk_ip_minbits(key) >= ip_bits(query))
    PG_RETURN_BOOL(false);
   break;
 }

 /*
  * Check 3: common network bits
  *
  * Compare available common prefix bits to the query, but not beyond
  * either the query's netmask or the minimum netmask among the represented
  * values.  If these bits don't match the query, we have our answer (and
  * may or may not need to descend, depending on the operator).  If they do
  * match, and we are not at a leaf, we descend in all cases.
  *
  * Note this is the final check for operators that only consider the
  * network part of the address.
 */

 minbits = Min(gk_ip_commonbits(key), gk_ip_minbits(key));
 minbits = Min(minbits, ip_bits(query));

 order = bitncmp(gk_ip_addr(key), ip_addr(query), minbits);

 switch (strategy)
 {
  case INETSTRAT_SUB:
  case INETSTRAT_SUBEQ:
  case INETSTRAT_OVERLAPS:
  case INETSTRAT_SUPEQ:
  case INETSTRAT_SUP:
   PG_RETURN_BOOL(order == 0);

  case INETSTRAT_LT:
  case INETSTRAT_LE:
   if (order > 0)
    PG_RETURN_BOOL(false);
   if (order < 0 || !GIST_LEAF(ent))
    PG_RETURN_BOOL(true);
   break;

  case INETSTRAT_EQ:
   if (order != 0)
    PG_RETURN_BOOL(false);
   if (!GIST_LEAF(ent))
    PG_RETURN_BOOL(true);
   break;

  case INETSTRAT_GE:
  case INETSTRAT_GT:
   if (order < 0)
    PG_RETURN_BOOL(false);
   if (order > 0 || !GIST_LEAF(ent))
    PG_RETURN_BOOL(true);
   break;

  case INETSTRAT_NE:
   if (order != 0 || !GIST_LEAF(ent))
    PG_RETURN_BOOL(true);
   break;
 }

 /*
  * Remaining checks are only for leaves and basic comparison strategies.
  * See network_cmp_internal() in network.c for the implementation we need
  * to match.  Note that in a leaf key, commonbits should equal the address
  * length, so we compared the whole network parts above.
 */

 Assert(GIST_LEAF(ent));

 /*
  * Check 4: network bit count
  *
  * Next step is to compare netmask widths.
 */

 switch (strategy)
 {
  case INETSTRAT_LT:
  case INETSTRAT_LE:
   if (gk_ip_minbits(key) < ip_bits(query))
    PG_RETURN_BOOL(true);
   if (gk_ip_minbits(key) > ip_bits(query))
    PG_RETURN_BOOL(false);
   break;

  case INETSTRAT_EQ:
   if (gk_ip_minbits(key) != ip_bits(query))
    PG_RETURN_BOOL(false);
   break;

  case INETSTRAT_GE:
  case INETSTRAT_GT:
   if (gk_ip_minbits(key) > ip_bits(query))
    PG_RETURN_BOOL(true);
   if (gk_ip_minbits(key) < ip_bits(query))
    PG_RETURN_BOOL(false);
   break;

  case INETSTRAT_NE:
   if (gk_ip_minbits(key) != ip_bits(query))
    PG_RETURN_BOOL(true);
   break;
 }

 /*
  * Check 5: whole address
  *
  * Netmask bit counts are the same, so check all the address bits.
 */

 order = bitncmp(gk_ip_addr(key), ip_addr(query), gk_ip_maxbits(key));

 switch (strategy)
 {
  case INETSTRAT_LT:
   PG_RETURN_BOOL(order < 0);

  case INETSTRAT_LE:
   PG_RETURN_BOOL(order <= 0);

  case INETSTRAT_EQ:
   PG_RETURN_BOOL(order == 0);

  case INETSTRAT_GE:
   PG_RETURN_BOOL(order >= 0);

  case INETSTRAT_GT:
   PG_RETURN_BOOL(order > 0);

  case INETSTRAT_NE:
   PG_RETURN_BOOL(order != 0);
 }

 elog(ERROR, "unknown strategy for inet GiST");
 PG_RETURN_BOOL(false);  /* keep compiler quiet */
}

/*
 * Calculate parameters of the union of some GistInetKeys.
 *
 * Examine the keys in elements m..n inclusive of the GISTENTRY array,
 * and compute these output parameters:
 * *minfamily_p = minimum IP address family number
 * *maxfamily_p = maximum IP address family number
 * *minbits_p = minimum netmask width
 * *commonbits_p = number of leading bits in common among the addresses
 *
 * minbits and commonbits are forced to zero if there's more than one
 * address family.
 */

static void
calc_inet_union_params(GISTENTRY *ent,
        int m, int n,
        int *minfamily_p,
        int *maxfamily_p,
        int *minbits_p,
        int *commonbits_p)
{
 int   minfamily,
    maxfamily,
    minbits,
    commonbits;
 unsigned char *addr;
 GistInetKey *tmp;
 int   i;

 /* Must be at least one key. */
 Assert(m <= n);

 /* Initialize variables using the first key. */
 tmp = DatumGetInetKeyP(ent[m].key);
 minfamily = maxfamily = gk_ip_family(tmp);
 minbits = gk_ip_minbits(tmp);
 commonbits = gk_ip_commonbits(tmp);
 addr = gk_ip_addr(tmp);

 /* Scan remaining keys. */
 for (i = m + 1; i <= n; i++)
 {
  tmp = DatumGetInetKeyP(ent[i].key);

  /* Determine range of family numbers */
  if (minfamily > gk_ip_family(tmp))
   minfamily = gk_ip_family(tmp);
  if (maxfamily < gk_ip_family(tmp))
   maxfamily = gk_ip_family(tmp);

  /* Find minimum minbits */
  if (minbits > gk_ip_minbits(tmp))
   minbits = gk_ip_minbits(tmp);

  /* Find minimum number of bits in common */
  if (commonbits > gk_ip_commonbits(tmp))
   commonbits = gk_ip_commonbits(tmp);
  if (commonbits > 0)
   commonbits = bitncommon(addr, gk_ip_addr(tmp), commonbits);
 }

 /* Force minbits/commonbits to zero if more than one family. */
 if (minfamily != maxfamily)
  minbits = commonbits = 0;

 *minfamily_p = minfamily;
 *maxfamily_p = maxfamily;
 *minbits_p = minbits;
 *commonbits_p = commonbits;
}

/*
 * Same as above, but the GISTENTRY elements to examine are those with
 * indices listed in the offsets[] array.
 */

static void
calc_inet_union_params_indexed(GISTENTRY *ent,
          OffsetNumber *offsets, int noffsets,
          int *minfamily_p,
          int *maxfamily_p,
          int *minbits_p,
          int *commonbits_p)
{
 int   minfamily,
    maxfamily,
    minbits,
    commonbits;
 unsigned char *addr;
 GistInetKey *tmp;
 int   i;

 /* Must be at least one key. */
 Assert(noffsets > 0);

 /* Initialize variables using the first key. */
 tmp = DatumGetInetKeyP(ent[offsets[0]].key);
 minfamily = maxfamily = gk_ip_family(tmp);
 minbits = gk_ip_minbits(tmp);
 commonbits = gk_ip_commonbits(tmp);
 addr = gk_ip_addr(tmp);

 /* Scan remaining keys. */
 for (i = 1; i < noffsets; i++)
 {
  tmp = DatumGetInetKeyP(ent[offsets[i]].key);

  /* Determine range of family numbers */
  if (minfamily > gk_ip_family(tmp))
   minfamily = gk_ip_family(tmp);
  if (maxfamily < gk_ip_family(tmp))
   maxfamily = gk_ip_family(tmp);

  /* Find minimum minbits */
  if (minbits > gk_ip_minbits(tmp))
   minbits = gk_ip_minbits(tmp);

  /* Find minimum number of bits in common */
  if (commonbits > gk_ip_commonbits(tmp))
   commonbits = gk_ip_commonbits(tmp);
  if (commonbits > 0)
   commonbits = bitncommon(addr, gk_ip_addr(tmp), commonbits);
 }

 /* Force minbits/commonbits to zero if more than one family. */
 if (minfamily != maxfamily)
  minbits = commonbits = 0;

 *minfamily_p = minfamily;
 *maxfamily_p = maxfamily;
 *minbits_p = minbits;
 *commonbits_p = commonbits;
}

/*
 * Construct a GistInetKey representing a union value.
 *
 * Inputs are the family/minbits/commonbits values to use, plus a pointer to
 * the address field of one of the union inputs.  (Since we're going to copy
 * just the bits-in-common, it doesn't matter which one.)
 */

static GistInetKey *
build_inet_union_key(int family, int minbits, int commonbits,
      unsigned char *addr)
{
 GistInetKey *result;

 /* Make sure any unused bits are zeroed. */
 result = (GistInetKey *) palloc0(sizeof(GistInetKey));

 gk_ip_family(result) = family;
 gk_ip_minbits(result) = minbits;
 gk_ip_commonbits(result) = commonbits;

 /* Clone appropriate bytes of the address. */
 if (commonbits > 0)
  memcpy(gk_ip_addr(result), addr, (commonbits + 7) / 8);

 /* Clean any unwanted bits in the last partial byte. */
 if (commonbits % 8 != 0)
  gk_ip_addr(result)[commonbits / 8] &= ~(0xFF >> (commonbits % 8));

 /* Set varlena header correctly. */
 SET_GK_VARSIZE(result);

 return result;
}


/*
 * The GiST union function
 *
 * See comments at head of file for the definition of the union.
 */

Datum
inet_gist_union(PG_FUNCTION_ARGS)
{
 GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
 GISTENTRY  *ent = entryvec->vector;
 int   minfamily,
    maxfamily,
    minbits,
    commonbits;
 unsigned char *addr;
 GistInetKey *tmp,
      *result;

 /* Determine parameters of the union. */
 calc_inet_union_params(ent, 0, entryvec->n - 1,
         &minfamily, &maxfamily,
         &minbits, &commonbits);

 /* If more than one family, emit family number zero. */
 if (minfamily != maxfamily)
  minfamily = 0;

 /* Initialize address using the first key. */
 tmp = DatumGetInetKeyP(ent[0].key);
 addr = gk_ip_addr(tmp);

 /* Construct the union value. */
 result = build_inet_union_key(minfamily, minbits, commonbits, addr);

 PG_RETURN_POINTER(result);
}

/*
 * The GiST compress function
 *
 * Convert an inet value to GistInetKey.
 */

Datum
inet_gist_compress(PG_FUNCTION_ARGS)
{
 GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
 GISTENTRY  *retval;

 if (entry->leafkey)
 {
  retval = palloc(sizeof(GISTENTRY));
  if (DatumGetPointer(entry->key) != NULL)
  {
   inet    *in = DatumGetInetPP(entry->key);
   GistInetKey *r;

   r = (GistInetKey *) palloc0(sizeof(GistInetKey));

   gk_ip_family(r) = ip_family(in);
   gk_ip_minbits(r) = ip_bits(in);
   gk_ip_commonbits(r) = gk_ip_maxbits(r);
   memcpy(gk_ip_addr(r), ip_addr(in), gk_ip_addrsize(r));
   SET_GK_VARSIZE(r);

   gistentryinit(*retval, PointerGetDatum(r),
        entry->rel, entry->page,
        entry->offset, false);
  }
  else
  {
   gistentryinit(*retval, (Datum) 0,
        entry->rel, entry->page,
        entry->offset, false);
  }
 }
 else
  retval = entry;
 PG_RETURN_POINTER(retval);
}

/*
 * We do not need a decompress function, because the other GiST inet
 * support functions work with the GistInetKey representation.
 */


/*
 * The GiST fetch function
 *
 * Reconstruct the original inet datum from a GistInetKey.
 */

Datum
inet_gist_fetch(PG_FUNCTION_ARGS)
{
 GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
 GistInetKey *key = DatumGetInetKeyP(entry->key);
 GISTENTRY  *retval;
 inet    *dst;

 dst = (inet *) palloc0(sizeof(inet));

 ip_family(dst) = gk_ip_family(key);
 ip_bits(dst) = gk_ip_minbits(key);
 memcpy(ip_addr(dst), gk_ip_addr(key), ip_addrsize(dst));
 SET_INET_VARSIZE(dst);

 retval = palloc(sizeof(GISTENTRY));
 gistentryinit(*retval, InetPGetDatum(dst), entry->rel, entry->page,
      entry->offset, false);

 PG_RETURN_POINTER(retval);
}

/*
 * The GiST page split penalty function
 *
 * Charge a large penalty if address family doesn't match, or a somewhat
 * smaller one if the new value would degrade the union's minbits
 * (minimum netmask width).  Otherwise, penalty is inverse of the
 * new number of common address bits.
 */

Datum
inet_gist_penalty(PG_FUNCTION_ARGS)
{
 GISTENTRY  *origent = (GISTENTRY *) PG_GETARG_POINTER(0);
 GISTENTRY  *newent = (GISTENTRY *) PG_GETARG_POINTER(1);
 float    *penalty = (float *) PG_GETARG_POINTER(2);
 GistInetKey *orig = DatumGetInetKeyP(origent->key),
      *new = DatumGetInetKeyP(newent->key);
 int   commonbits;

 if (gk_ip_family(orig) == gk_ip_family(new))
 {
  if (gk_ip_minbits(orig) <= gk_ip_minbits(new))
  {
   commonbits = bitncommon(gk_ip_addr(orig), gk_ip_addr(new),
         Min(gk_ip_commonbits(orig),
          gk_ip_commonbits(new)));
   if (commonbits > 0)
    *penalty = 1.0f / commonbits;
   else
    *penalty = 2;
  }
  else
   *penalty = 3;
 }
 else
  *penalty = 4;

 PG_RETURN_POINTER(penalty);
}

/*
 * The GiST PickSplit method
 *
 * There are two ways to split. First one is to split by address families,
 * if there are multiple families appearing in the input.
 *
 * The second and more common way is to split by addresses. To achieve this,
 * determine the number of leading bits shared by all the keys, then split on
 * the next bit.  (We don't currently consider the netmask widths while doing
 * this; should we?)  If we fail to get a nontrivial split that way, split
 * 50-50.
 */

Datum
inet_gist_picksplit(PG_FUNCTION_ARGS)
{
 GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
 GIST_SPLITVEC *splitvec = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
 GISTENTRY  *ent = entryvec->vector;
 int   minfamily,
    maxfamily,
    minbits,
    commonbits;
 unsigned char *addr;
 GistInetKey *tmp,
      *left_union,
      *right_union;
 int   maxoff,
    nbytes;
 OffsetNumber i,
      *left,
      *right;

 maxoff = entryvec->n - 1;
 nbytes = (maxoff + 1) * sizeof(OffsetNumber);

 left = (OffsetNumber *) palloc(nbytes);
 right = (OffsetNumber *) palloc(nbytes);

 splitvec->spl_left = left;
 splitvec->spl_right = right;

 splitvec->spl_nleft = 0;
 splitvec->spl_nright = 0;

 /* Determine parameters of the union of all the inputs. */
 calc_inet_union_params(ent, FirstOffsetNumber, maxoff,
         &minfamily, &maxfamily,
         &minbits, &commonbits);

 if (minfamily != maxfamily)
 {
  /* Multiple families, so split by family. */
  for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
  {
   /*
    * If there's more than 2 families, all but maxfamily go into the
    * left union.  This could only happen if the inputs include some
    * IPv4, some IPv6, and some already-multiple-family unions.
 */

   tmp = DatumGetInetKeyP(ent[i].key);
   if (gk_ip_family(tmp) != maxfamily)
    left[splitvec->spl_nleft++] = i;
   else
    right[splitvec->spl_nright++] = i;
  }
 }
 else
 {
  /*
   * Split on the next bit after the common bits.  If that yields a
   * trivial split, try the next bit position to the right.  Repeat till
   * success; or if we run out of bits, do an arbitrary 50-50 split.
 */

  int   maxbits = ip_family_maxbits(minfamily);

  while (commonbits < maxbits)
  {
   /* Split using the commonbits'th bit position. */
   int   bitbyte = commonbits / 8;
   int   bitmask = 0x80 >> (commonbits % 8);

   splitvec->spl_nleft = splitvec->spl_nright = 0;

   for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
   {
    tmp = DatumGetInetKeyP(ent[i].key);
    addr = gk_ip_addr(tmp);
    if ((addr[bitbyte] & bitmask) == 0)
     left[splitvec->spl_nleft++] = i;
    else
     right[splitvec->spl_nright++] = i;
   }

   if (splitvec->spl_nleft > 0 && splitvec->spl_nright > 0)
    break;   /* success */
   commonbits++;
  }

  if (commonbits >= maxbits)
  {
   /* Failed ... do a 50-50 split. */
   splitvec->spl_nleft = splitvec->spl_nright = 0;

   for (i = FirstOffsetNumber; i <= maxoff / 2; i = OffsetNumberNext(i))
   {
    left[splitvec->spl_nleft++] = i;
   }
   for (; i <= maxoff; i = OffsetNumberNext(i))
   {
    right[splitvec->spl_nright++] = i;
   }
  }
 }

 /*
  * Compute the union value for each side from scratch.  In most cases we
  * could approximate the union values with what we already know, but this
  * ensures that each side has minbits and commonbits set as high as
  * possible.
 */

 calc_inet_union_params_indexed(ent, left, splitvec->spl_nleft,
           &minfamily, &maxfamily,
           &minbits, &commonbits);
 if (minfamily != maxfamily)
  minfamily = 0;
 tmp = DatumGetInetKeyP(ent[left[0]].key);
 addr = gk_ip_addr(tmp);
 left_union = build_inet_union_key(minfamily, minbits, commonbits, addr);
 splitvec->spl_ldatum = PointerGetDatum(left_union);

 calc_inet_union_params_indexed(ent, right, splitvec->spl_nright,
           &minfamily, &maxfamily,
           &minbits, &commonbits);
 if (minfamily != maxfamily)
  minfamily = 0;
 tmp = DatumGetInetKeyP(ent[right[0]].key);
 addr = gk_ip_addr(tmp);
 right_union = build_inet_union_key(minfamily, minbits, commonbits, addr);
 splitvec->spl_rdatum = PointerGetDatum(right_union);

 PG_RETURN_POINTER(splitvec);
}

/*
 * The GiST equality function
 */

Datum
inet_gist_same(PG_FUNCTION_ARGS)
{
 GistInetKey *left = DatumGetInetKeyP(PG_GETARG_DATUM(0));
 GistInetKey *right = DatumGetInetKeyP(PG_GETARG_DATUM(1));
 bool    *result = (bool *) PG_GETARG_POINTER(2);

 *result = (gk_ip_family(left) == gk_ip_family(right) &&
      gk_ip_minbits(left) == gk_ip_minbits(right) &&
      gk_ip_commonbits(left) == gk_ip_commonbits(right) &&
      memcmp(gk_ip_addr(left), gk_ip_addr(right),
       gk_ip_addrsize(left)) == 0);

 PG_RETURN_POINTER(result);
}

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

¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.19Angebot  (Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-08-08) ¤

*Eine klare Vorstellung vom Zielzustand






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