1/*-------------------------------------------------------------------------
4 * SP-GiST support for network types.
6 * We split inet index entries first by address family (IPv4 or IPv6).
7 * If the entries below a given inner tuple are all of the same family,
8 * we identify their common prefix and split by the next bit of the address,
9 * and by whether their masklens exceed the length of the common prefix.
11 * An inner tuple that has both IPv4 and IPv6 children has a null prefix
12 * and exactly two nodes, the first being for IPv4 and the second for IPv6.
14 * Otherwise, the prefix is a CIDR value representing the common prefix,
15 * and there are exactly four nodes. Node numbers 0 and 1 are for addresses
16 * with the same masklen as the prefix, while node numbers 2 and 3 are for
17 * addresses with larger masklen. (We do not allow a tuple to contain
18 * entries with masklen smaller than its prefix's.) Node numbers 0 and 1
19 * are distinguished by the next bit of the address after the common prefix,
20 * and likewise for node numbers 2 and 3. If there are no more bits in
21 * the address family, everything goes into node 0 (which will probably
22 * lead to creating an allTheSame tuple).
24 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
25 * Portions Copyright (c) 1994, Regents of the University of California
28 * src/backend/utils/adt/network_spgist.c
30 *-------------------------------------------------------------------------
38#include "utils/fmgrprotos.h"
48 * The SP-GiST configuration function
53 /* spgConfigIn *cfgin = (spgConfigIn *) PG_GETARG_POINTER(0); */
65 * The SP-GiST choose function
77 * If we're looking at a tuple that splits by address family, choose the
78 * appropriate subnode.
82 /* allTheSame isn't possible for such a tuple */
93 /* Else it must split by prefix */
100 * We cannot put addresses from different families under the same inner
101 * node, so we have to split if the new value's family is different.
105 /* Set up 2-node tuple */
111 /* Identify which node the existing data goes into */
122 * If the new value does not match the existing prefix, we have to split.
127 /* Determine new prefix length for the split tuple */
131 /* Set up 4-node tuple */
139 /* Identify which node the existing data goes into */
150 * All OK, choose the node to descend into. (If this tuple is marked
151 * allTheSame, the core code will ignore our choice of nodeN; but we need
152 * not account for that case explicitly here.)
162 * The GiST PickSplit method
173 bool differentFamilies =
false;
175 /* Initialize the prefix with the first item */
179 /* Examine remaining items to discover minimum common prefix length */
186 differentFamilies =
true;
197 /* Don't need labels; allocate output arrays */
202 if (differentFamilies)
204 /* Set up 2-node tuple */
218 /* Set up 4-node tuple */
236 * The SP-GiST query consistency check for inner tuples
251 /* Identify which child nodes need to be visited */
252 which = 1 | (1 << 1);
277 /* all other ops can only match addrs of same family */
290 /* Identify which child nodes need to be visited */
296 /* Must visit all nodes; we assume there are less than 32 of 'em */
308 if (which & (1 <<
i))
320 * The SP-GiST query consistency check for leaf tuples
329 /* All tests are exact. */
332 /* Leaf is what it is... */
335 /* Use common code to apply the tests. */
341 * Calculate node number (within a 4-node, single-family inner index tuple)
343 * The value must have the same family as the node's prefix, and
344 * commonbits is the mask length of the prefix. We use even or odd
345 * nodes according to the next address bit after the commonbits,
346 * and low or high nodes according to whether the value's mask length
347 * is larger than commonbits.
355 ip_addr(
val)[commonbits / 8] & (1 << (7 - commonbits % 8)))
364 * Calculate bitmap of node numbers that are consistent with the query
366 * This can be used either at a 4-way inner tuple, or at a leaf tuple.
367 * In the latter case, we should return a boolean result (0 or 1)
370 * This definition is pretty odd, but the inner and leaf consistency checks
371 * are mostly common and it seems best to keep them in one function.
381 /* Initialize result to allow visiting all children */
385 bitmap = 1 | (1 << 1) | (1 << 2) | (1 << 3);
389 for (
i = 0;
i < nkeys;
i++)
396 * Check 0: different families
398 * Matching families do not help any of the strategies.
420 /* For all other cases, we can be sure there is no match */
428 /* Other checks make no sense with different families. */
433 * Check 1: network bit count
435 * Network bit count (ip_bits) helps to check leaves for sub network
436 * and sup network operators. At non-leaf nodes, we know every child
437 * value has greater ip_bits, so we can avoid descending in some cases
440 * This check is less expensive than checking the address bits, so we
441 * are doing this before, but it has to be done after for the basic
442 * comparison strategies, because ip_bits only affect their results
443 * when the common network bits are the same.
448 if (commonbits <=
ip_bits(argument))
449 bitmap &= (1 << 2) | (1 << 3);
453 if (commonbits <
ip_bits(argument))
454 bitmap &= (1 << 2) | (1 << 3);
458 if (commonbits ==
ip_bits(argument) - 1)
459 bitmap &= 1 | (1 << 1);
460 else if (commonbits >=
ip_bits(argument))
465 if (commonbits ==
ip_bits(argument))
466 bitmap &= 1 | (1 << 1);
467 else if (commonbits >
ip_bits(argument))
472 if (commonbits <
ip_bits(argument))
473 bitmap &= (1 << 2) | (1 << 3);
474 else if (commonbits ==
ip_bits(argument))
475 bitmap &= 1 | (1 << 1);
485 * Check 2: common network bits
487 * Compare available common prefix bits to the query, but not beyond
488 * either the query's netmask or the minimum netmask among the
489 * represented values. If these bits don't match the query, we can
490 * eliminate some cases.
515 /* For all other cases, we can be sure there is no match */
524 * Remaining checks make no sense when common bits don't match.
530 * Check 3: next network bit
532 * We can filter out branch 2 or 3 using the next network bit of the
533 * argument, if it is available.
535 * This check matters for the performance of the search. The results
536 * would be correct without it.
538 if (bitmap & ((1 << 2) | (1 << 3)) &&
539 commonbits <
ip_bits(argument))
543 nextbit =
ip_addr(argument)[commonbits / 8] &
544 (1 << (7 - commonbits % 8));
551 bitmap &= 1 | (1 << 1) | (1 << 2);
557 bitmap &= 1 | (1 << 1) | (1 << 3);
565 bitmap &= 1 | (1 << 1) | (1 << 2);
567 bitmap &= 1 | (1 << 1) | (1 << 3);
576 * Remaining checks are only for the basic comparison strategies. This
577 * test relies on the strategy number ordering defined in stratnum.h.
584 * Check 4: network bit count
586 * At this point, we know that the common network bits of the prefix
587 * and the argument are the same, so we can go forward and check the
594 if (commonbits ==
ip_bits(argument))
595 bitmap &= 1 | (1 << 1);
596 else if (commonbits >
ip_bits(argument))
602 if (commonbits <
ip_bits(argument))
603 bitmap &= (1 << 2) | (1 << 3);
610 /* Remaining checks don't make sense with different ip_bits. */
611 if (commonbits !=
ip_bits(argument))
615 * Check 5: next host bit
617 * We can filter out branch 0 or 1 using the next host bit of the
618 * argument, if it is available.
620 * This check matters for the performance of the search. The results
621 * would be correct without it. There is no point in running it for
622 * leafs as we have to check the whole address on the next step.
624 if (!leaf && bitmap & (1 | (1 << 1)) &&
629 nextbit =
ip_addr(argument)[commonbits / 8] &
630 (1 << (7 - commonbits % 8));
637 bitmap &= 1 | (1 << 2) | (1 << 3);
643 bitmap &= (1 << 1) | (1 << 2) | (1 << 3);
651 bitmap &= 1 | (1 << 2) | (1 << 3);
653 bitmap &= (1 << 1) | (1 << 2) | (1 << 3);
662 * Check 6: whole address
664 * This is the last check for correctness of the basic comparison
665 * strategies. It's only appropriate at leaf entries.
669 /* Redo ordering comparison using all address bits */
#define PG_GETARG_POINTER(n)
#define PG_RETURN_BOOL(x)
Assert(PointerIsAligned(start, uint64))
int bitncommon(const unsigned char *l, const unsigned char *r, int n)
inet * cidr_set_masklen_internal(const inet *src, int bits)
int bitncmp(const unsigned char *l, const unsigned char *r, int n)
Datum inet_spg_config(PG_FUNCTION_ARGS)
Datum inet_spg_choose(PG_FUNCTION_ARGS)
Datum inet_spg_leaf_consistent(PG_FUNCTION_ARGS)
Datum inet_spg_inner_consistent(PG_FUNCTION_ARGS)
static int inet_spg_node_number(const inet *val, int commonbits)
static int inet_spg_consistent_bitmap(const inet *prefix, int nkeys, ScanKey scankeys, bool leaf)
Datum inet_spg_picksplit(PG_FUNCTION_ARGS)
#define RTNotEqualStrategyNumber
#define RTSubStrategyNumber
#define RTSubEqualStrategyNumber
#define RTSuperEqualStrategyNumber
#define RTEqualStrategyNumber
#define RTLessEqualStrategyNumber
#define RTGreaterEqualStrategyNumber
#define RTGreaterStrategyNumber
#define RTSuperStrategyNumber
#define RTLessStrategyNumber
StrategyNumber sk_strategy
spgChooseResultType resultType
struct spgChooseOut::@53::@54 matchNode
struct spgChooseOut::@53::@56 splitTuple
union spgChooseOut::@53 result
static Datum InetPGetDatum(const inet *X)
static inet * DatumGetInetPP(Datum X)
#define ip_family(inetptr)
#define ip_maxbits(inetptr)