PostgreSQL Source Code git master
Loading...
Searching...
No Matches
network_spgist.c File Reference
#include "postgres.h"
#include <sys/socket.h>
#include "access/spgist.h"
#include "catalog/pg_type.h"
#include "utils/fmgrprotos.h"
#include "utils/inet.h"
#include "varatt.h"
Include dependency graph for network_spgist.c:

Go to the source code of this file.

Functions

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_config (PG_FUNCTION_ARGS)
 
Datum inet_spg_choose (PG_FUNCTION_ARGS)
 
Datum inet_spg_picksplit (PG_FUNCTION_ARGS)
 
Datum inet_spg_inner_consistent (PG_FUNCTION_ARGS)
 
Datum inet_spg_leaf_consistent (PG_FUNCTION_ARGS)
 

Function Documentation

◆ inet_spg_choose()

Datum inet_spg_choose ( PG_FUNCTION_ARGS  )

Definition at line 70 of file network_spgist.c.

71{
75 *prefix;
76 int commonbits;
77
78 /*
79 * If we're looking at a tuple that splits by address family, choose the
80 * appropriate subnode.
81 */
82 if (!in->hasPrefix)
83 {
84 /* allTheSame isn't possible for such a tuple */
85 Assert(!in->allTheSame);
86 Assert(in->nNodes == 2);
87
89 out->result.matchNode.nodeN = (ip_family(val) == PGSQL_AF_INET) ? 0 : 1;
91
93 }
94
95 /* Else it must split by prefix */
96 Assert(in->nNodes == 4 || in->allTheSame);
97
98 prefix = DatumGetInetPP(in->prefixDatum);
99 commonbits = ip_bits(prefix);
100
101 /*
102 * We cannot put addresses from different families under the same inner
103 * node, so we have to split if the new value's family is different.
104 */
105 if (ip_family(val) != ip_family(prefix))
106 {
107 /* Set up 2-node tuple */
109 out->result.splitTuple.prefixHasPrefix = false;
112
113 /* Identify which node the existing data goes into */
115 (ip_family(prefix) == PGSQL_AF_INET) ? 0 : 1;
116
119
121 }
122
123 /*
124 * If the new value does not match the existing prefix, we have to split.
125 */
126 if (ip_bits(val) < commonbits ||
127 bitncmp(ip_addr(prefix), ip_addr(val), commonbits) != 0)
128 {
129 /* Determine new prefix length for the split tuple */
130 commonbits = bitncommon(ip_addr(prefix), ip_addr(val),
131 Min(ip_bits(val), commonbits));
132
133 /* Set up 4-node tuple */
140
141 /* Identify which node the existing data goes into */
143 inet_spg_node_number(prefix, commonbits);
144
147
149 }
150
151 /*
152 * All OK, choose the node to descend into. (If this tuple is marked
153 * allTheSame, the core code will ignore our choice of nodeN; but we need
154 * not account for that case explicitly here.)
155 */
157 out->result.matchNode.nodeN = inet_spg_node_number(val, commonbits);
159
161}
#define Min(x, y)
Definition c.h:997
#define Assert(condition)
Definition c.h:873
#define PG_RETURN_VOID()
Definition fmgr.h:350
#define PG_GETARG_POINTER(n)
Definition fmgr.h:277
long val
Definition informix.c:689
int bitncommon(const unsigned char *l, const unsigned char *r, int n)
Definition network.c:1536
inet * cidr_set_masklen_internal(const inet *src, int bits)
Definition network.c:364
int bitncmp(const unsigned char *l, const unsigned char *r, int n)
Definition network.c:1502
static int inet_spg_node_number(const inet *val, int commonbits)
static int fb(int x)
@ spgMatchNode
Definition spgist.h:69
@ spgSplitTuple
Definition spgist.h:71
Definition inet.h:53
bool hasPrefix
Definition spgist.h:61
Datum prefixDatum
Definition spgist.h:62
int nNodes
Definition spgist.h:63
Datum datum
Definition spgist.h:55
bool allTheSame
Definition spgist.h:60
bool postfixHasPrefix
Definition spgist.h:101
int childNodeN
Definition spgist.h:98
spgChooseResultType resultType
Definition spgist.h:76
struct spgChooseOut::@54::@57 splitTuple
Datum * prefixNodeLabels
Definition spgist.h:96
Datum postfixPrefixDatum
Definition spgist.h:102
Datum restDatum
Definition spgist.h:83
int prefixNNodes
Definition spgist.h:95
int nodeN
Definition spgist.h:81
union spgChooseOut::@54 result
Datum prefixPrefixDatum
Definition spgist.h:94
bool prefixHasPrefix
Definition spgist.h:93
struct spgChooseOut::@54::@55 matchNode
static Datum InetPGetDatum(const inet *X)
Definition inet.h:129
static inet * DatumGetInetPP(Datum X)
Definition inet.h:123
#define ip_addr(inetptr)
Definition inet.h:77
#define ip_family(inetptr)
Definition inet.h:71
#define PGSQL_AF_INET
Definition inet.h:39
#define ip_bits(inetptr)
Definition inet.h:74

References spgChooseIn::allTheSame, Assert, bitncmp(), bitncommon(), spgChooseOut::childNodeN, cidr_set_masklen_internal(), spgChooseIn::datum, DatumGetInetPP(), fb(), spgChooseIn::hasPrefix, inet_spg_node_number(), InetPGetDatum(), ip_addr, ip_bits, ip_family, spgChooseOut::matchNode, Min, spgChooseIn::nNodes, spgChooseOut::nodeN, PG_GETARG_POINTER, PG_RETURN_VOID, PGSQL_AF_INET, spgChooseOut::postfixHasPrefix, spgChooseOut::postfixPrefixDatum, spgChooseIn::prefixDatum, spgChooseOut::prefixHasPrefix, spgChooseOut::prefixNNodes, spgChooseOut::prefixNodeLabels, spgChooseOut::prefixPrefixDatum, spgChooseOut::restDatum, spgChooseOut::result, spgChooseOut::resultType, spgMatchNode, spgSplitTuple, spgChooseOut::splitTuple, and val.

◆ inet_spg_config()

Datum inet_spg_config ( PG_FUNCTION_ARGS  )

Definition at line 51 of file network_spgist.c.

52{
53#ifdef NOT_USED
55#endif
57
58 cfg->prefixType = CIDROID;
59 cfg->labelType = VOIDOID;
60 cfg->canReturnData = true;
61 cfg->longValuesOK = false;
62
64}
bool longValuesOK
Definition spgist.h:47
bool canReturnData
Definition spgist.h:46
Oid labelType
Definition spgist.h:44
Oid prefixType
Definition spgist.h:43

References spgConfigOut::canReturnData, fb(), spgConfigOut::labelType, spgConfigOut::longValuesOK, PG_GETARG_POINTER, PG_RETURN_VOID, and spgConfigOut::prefixType.

◆ inet_spg_consistent_bitmap()

static int inet_spg_consistent_bitmap ( const inet prefix,
int  nkeys,
ScanKey  scankeys,
bool  leaf 
)
static

Definition at line 376 of file network_spgist.c.

378{
379 int bitmap;
380 int commonbits,
381 i;
382
383 /* Initialize result to allow visiting all children */
384 if (leaf)
385 bitmap = 1;
386 else
387 bitmap = 1 | (1 << 1) | (1 << 2) | (1 << 3);
388
389 commonbits = ip_bits(prefix);
390
391 for (i = 0; i < nkeys; i++)
392 {
393 inet *argument = DatumGetInetPP(scankeys[i].sk_argument);
394 StrategyNumber strategy = scankeys[i].sk_strategy;
395 int order;
396
397 /*
398 * Check 0: different families
399 *
400 * Matching families do not help any of the strategies.
401 */
402 if (ip_family(argument) != ip_family(prefix))
403 {
404 switch (strategy)
405 {
408 if (ip_family(argument) < ip_family(prefix))
409 bitmap = 0;
410 break;
411
414 if (ip_family(argument) > ip_family(prefix))
415 bitmap = 0;
416 break;
417
419 break;
420
421 default:
422 /* For all other cases, we can be sure there is no match */
423 bitmap = 0;
424 break;
425 }
426
427 if (!bitmap)
428 break;
429
430 /* Other checks make no sense with different families. */
431 continue;
432 }
433
434 /*
435 * Check 1: network bit count
436 *
437 * Network bit count (ip_bits) helps to check leaves for sub network
438 * and sup network operators. At non-leaf nodes, we know every child
439 * value has greater ip_bits, so we can avoid descending in some cases
440 * too.
441 *
442 * This check is less expensive than checking the address bits, so we
443 * are doing this before, but it has to be done after for the basic
444 * comparison strategies, because ip_bits only affect their results
445 * when the common network bits are the same.
446 */
447 switch (strategy)
448 {
450 if (commonbits <= ip_bits(argument))
451 bitmap &= (1 << 2) | (1 << 3);
452 break;
453
455 if (commonbits < ip_bits(argument))
456 bitmap &= (1 << 2) | (1 << 3);
457 break;
458
460 if (commonbits == ip_bits(argument) - 1)
461 bitmap &= 1 | (1 << 1);
462 else if (commonbits >= ip_bits(argument))
463 bitmap = 0;
464 break;
465
467 if (commonbits == ip_bits(argument))
468 bitmap &= 1 | (1 << 1);
469 else if (commonbits > ip_bits(argument))
470 bitmap = 0;
471 break;
472
474 if (commonbits < ip_bits(argument))
475 bitmap &= (1 << 2) | (1 << 3);
476 else if (commonbits == ip_bits(argument))
477 bitmap &= 1 | (1 << 1);
478 else
479 bitmap = 0;
480 break;
481 }
482
483 if (!bitmap)
484 break;
485
486 /*
487 * Check 2: common network bits
488 *
489 * Compare available common prefix bits to the query, but not beyond
490 * either the query's netmask or the minimum netmask among the
491 * represented values. If these bits don't match the query, we can
492 * eliminate some cases.
493 */
494 order = bitncmp(ip_addr(prefix), ip_addr(argument),
495 Min(commonbits, ip_bits(argument)));
496
497 if (order != 0)
498 {
499 switch (strategy)
500 {
503 if (order > 0)
504 bitmap = 0;
505 break;
506
509 if (order < 0)
510 bitmap = 0;
511 break;
512
514 break;
515
516 default:
517 /* For all other cases, we can be sure there is no match */
518 bitmap = 0;
519 break;
520 }
521
522 if (!bitmap)
523 break;
524
525 /*
526 * Remaining checks make no sense when common bits don't match.
527 */
528 continue;
529 }
530
531 /*
532 * Check 3: next network bit
533 *
534 * We can filter out branch 2 or 3 using the next network bit of the
535 * argument, if it is available.
536 *
537 * This check matters for the performance of the search. The results
538 * would be correct without it.
539 */
540 if (bitmap & ((1 << 2) | (1 << 3)) &&
541 commonbits < ip_bits(argument))
542 {
543 int nextbit;
544
545 nextbit = ip_addr(argument)[commonbits / 8] &
546 (1 << (7 - commonbits % 8));
547
548 switch (strategy)
549 {
552 if (!nextbit)
553 bitmap &= 1 | (1 << 1) | (1 << 2);
554 break;
555
558 if (nextbit)
559 bitmap &= 1 | (1 << 1) | (1 << 3);
560 break;
561
563 break;
564
565 default:
566 if (!nextbit)
567 bitmap &= 1 | (1 << 1) | (1 << 2);
568 else
569 bitmap &= 1 | (1 << 1) | (1 << 3);
570 break;
571 }
572
573 if (!bitmap)
574 break;
575 }
576
577 /*
578 * Remaining checks are only for the basic comparison strategies. This
579 * test relies on the strategy number ordering defined in stratnum.h.
580 */
581 if (strategy < RTEqualStrategyNumber ||
583 continue;
584
585 /*
586 * Check 4: network bit count
587 *
588 * At this point, we know that the common network bits of the prefix
589 * and the argument are the same, so we can go forward and check the
590 * ip_bits.
591 */
592 switch (strategy)
593 {
596 if (commonbits == ip_bits(argument))
597 bitmap &= 1 | (1 << 1);
598 else if (commonbits > ip_bits(argument))
599 bitmap = 0;
600 break;
601
604 if (commonbits < ip_bits(argument))
605 bitmap &= (1 << 2) | (1 << 3);
606 break;
607 }
608
609 if (!bitmap)
610 break;
611
612 /* Remaining checks don't make sense with different ip_bits. */
613 if (commonbits != ip_bits(argument))
614 continue;
615
616 /*
617 * Check 5: next host bit
618 *
619 * We can filter out branch 0 or 1 using the next host bit of the
620 * argument, if it is available.
621 *
622 * This check matters for the performance of the search. The results
623 * would be correct without it. There is no point in running it for
624 * leafs as we have to check the whole address on the next step.
625 */
626 if (!leaf && bitmap & (1 | (1 << 1)) &&
627 commonbits < ip_maxbits(argument))
628 {
629 int nextbit;
630
631 nextbit = ip_addr(argument)[commonbits / 8] &
632 (1 << (7 - commonbits % 8));
633
634 switch (strategy)
635 {
638 if (!nextbit)
639 bitmap &= 1 | (1 << 2) | (1 << 3);
640 break;
641
644 if (nextbit)
645 bitmap &= (1 << 1) | (1 << 2) | (1 << 3);
646 break;
647
649 break;
650
651 default:
652 if (!nextbit)
653 bitmap &= 1 | (1 << 2) | (1 << 3);
654 else
655 bitmap &= (1 << 1) | (1 << 2) | (1 << 3);
656 break;
657 }
658
659 if (!bitmap)
660 break;
661 }
662
663 /*
664 * Check 6: whole address
665 *
666 * This is the last check for correctness of the basic comparison
667 * strategies. It's only appropriate at leaf entries.
668 */
669 if (leaf)
670 {
671 /* Redo ordering comparison using all address bits */
672 order = bitncmp(ip_addr(prefix), ip_addr(argument),
673 ip_maxbits(prefix));
674
675 switch (strategy)
676 {
678 if (order >= 0)
679 bitmap = 0;
680 break;
681
683 if (order > 0)
684 bitmap = 0;
685 break;
686
688 if (order != 0)
689 bitmap = 0;
690 break;
691
693 if (order < 0)
694 bitmap = 0;
695 break;
696
698 if (order <= 0)
699 bitmap = 0;
700 break;
701
703 if (order == 0)
704 bitmap = 0;
705 break;
706 }
707
708 if (!bitmap)
709 break;
710 }
711 }
712
713 return bitmap;
714}
int i
Definition isn.c:77
#define RTNotEqualStrategyNumber
Definition stratnum.h:69
#define RTSubStrategyNumber
Definition stratnum.h:74
uint16 StrategyNumber
Definition stratnum.h:22
#define RTSubEqualStrategyNumber
Definition stratnum.h:75
#define RTSuperEqualStrategyNumber
Definition stratnum.h:77
#define RTEqualStrategyNumber
Definition stratnum.h:68
#define RTLessEqualStrategyNumber
Definition stratnum.h:71
#define RTGreaterEqualStrategyNumber
Definition stratnum.h:73
#define RTGreaterStrategyNumber
Definition stratnum.h:72
#define RTSuperStrategyNumber
Definition stratnum.h:76
#define RTLessStrategyNumber
Definition stratnum.h:70
StrategyNumber sk_strategy
Definition skey.h:68
#define ip_maxbits(inetptr)
Definition inet.h:83

References bitncmp(), DatumGetInetPP(), fb(), i, ip_addr, ip_bits, ip_family, ip_maxbits, Min, RTEqualStrategyNumber, RTGreaterEqualStrategyNumber, RTGreaterStrategyNumber, RTLessEqualStrategyNumber, RTLessStrategyNumber, RTNotEqualStrategyNumber, RTSubEqualStrategyNumber, RTSubStrategyNumber, RTSuperEqualStrategyNumber, RTSuperStrategyNumber, and ScanKeyData::sk_strategy.

Referenced by inet_spg_inner_consistent(), and inet_spg_leaf_consistent().

◆ inet_spg_inner_consistent()

Datum inet_spg_inner_consistent ( PG_FUNCTION_ARGS  )

Definition at line 241 of file network_spgist.c.

242{
245 int i;
246 int which;
247
248 if (!in->hasPrefix)
249 {
250 Assert(!in->allTheSame);
251 Assert(in->nNodes == 2);
252
253 /* Identify which child nodes need to be visited */
254 which = 1 | (1 << 1);
255
256 for (i = 0; i < in->nkeys; i++)
257 {
258 StrategyNumber strategy = in->scankeys[i].sk_strategy;
260
261 switch (strategy)
262 {
266 which &= 1;
267 break;
268
272 which &= (1 << 1);
273 break;
274
276 break;
277
278 default:
279 /* all other ops can only match addrs of same family */
281 which &= 1;
282 else
283 which &= (1 << 1);
284 break;
285 }
286 }
287 }
288 else if (!in->allTheSame)
289 {
290 Assert(in->nNodes == 4);
291
292 /* Identify which child nodes need to be visited */
294 in->nkeys, in->scankeys, false);
295 }
296 else
297 {
298 /* Must visit all nodes; we assume there are less than 32 of 'em */
299 which = ~0;
300 }
301
302 out->nNodes = 0;
303
304 if (which)
305 {
306 out->nodeNumbers = palloc_array(int, in->nNodes);
307
308 for (i = 0; i < in->nNodes; i++)
309 {
310 if (which & (1 << i))
311 {
312 out->nodeNumbers[out->nNodes] = i;
313 out->nNodes++;
314 }
315 }
316 }
317
319}
#define palloc_array(type, count)
Definition fe_memutils.h:76
static int inet_spg_consistent_bitmap(const inet *prefix, int nkeys, ScanKey scankeys, bool leaf)
Datum sk_argument
Definition skey.h:72
#define PGSQL_AF_INET6
Definition inet.h:40

References spgInnerConsistentIn::allTheSame, Assert, DatumGetInetPP(), fb(), spgInnerConsistentIn::hasPrefix, i, inet_spg_consistent_bitmap(), ip_family, spgInnerConsistentIn::nkeys, spgInnerConsistentIn::nNodes, spgInnerConsistentOut::nNodes, spgInnerConsistentOut::nodeNumbers, palloc_array, PG_GETARG_POINTER, PG_RETURN_VOID, PGSQL_AF_INET, PGSQL_AF_INET6, spgInnerConsistentIn::prefixDatum, RTGreaterEqualStrategyNumber, RTGreaterStrategyNumber, RTLessEqualStrategyNumber, RTLessStrategyNumber, RTNotEqualStrategyNumber, spgInnerConsistentIn::scankeys, ScanKeyData::sk_argument, and ScanKeyData::sk_strategy.

◆ inet_spg_leaf_consistent()

Datum inet_spg_leaf_consistent ( PG_FUNCTION_ARGS  )

◆ inet_spg_node_number()

static int inet_spg_node_number ( const inet val,
int  commonbits 
)
static

Definition at line 352 of file network_spgist.c.

353{
354 int nodeN = 0;
355
356 if (commonbits < ip_maxbits(val) &&
357 ip_addr(val)[commonbits / 8] & (1 << (7 - commonbits % 8)))
358 nodeN |= 1;
359 if (commonbits < ip_bits(val))
360 nodeN |= 2;
361
362 return nodeN;
363}

References ip_addr, ip_bits, ip_maxbits, and val.

Referenced by inet_spg_choose(), and inet_spg_picksplit().

◆ inet_spg_picksplit()

Datum inet_spg_picksplit ( PG_FUNCTION_ARGS  )

Definition at line 167 of file network_spgist.c.

168{
171 inet *prefix,
172 *tmp;
173 int i,
174 commonbits;
175 bool differentFamilies = false;
176
177 /* Initialize the prefix with the first item */
178 prefix = DatumGetInetPP(in->datums[0]);
179 commonbits = ip_bits(prefix);
180
181 /* Examine remaining items to discover minimum common prefix length */
182 for (i = 1; i < in->nTuples; i++)
183 {
184 tmp = DatumGetInetPP(in->datums[i]);
185
186 if (ip_family(tmp) != ip_family(prefix))
187 {
188 differentFamilies = true;
189 break;
190 }
191
192 if (ip_bits(tmp) < commonbits)
193 commonbits = ip_bits(tmp);
194 commonbits = bitncommon(ip_addr(prefix), ip_addr(tmp), commonbits);
195 if (commonbits == 0)
196 break;
197 }
198
199 /* Don't need labels; allocate output arrays */
200 out->nodeLabels = NULL;
201 out->mapTuplesToNodes = palloc_array(int, in->nTuples);
203
205 {
206 /* Set up 2-node tuple */
207 out->hasPrefix = false;
208 out->nNodes = 2;
209
210 for (i = 0; i < in->nTuples; i++)
211 {
212 tmp = DatumGetInetPP(in->datums[i]);
213 out->mapTuplesToNodes[i] =
214 (ip_family(tmp) == PGSQL_AF_INET) ? 0 : 1;
215 out->leafTupleDatums[i] = InetPGetDatum(tmp);
216 }
217 }
218 else
219 {
220 /* Set up 4-node tuple */
221 out->hasPrefix = true;
222 out->prefixDatum =
223 InetPGetDatum(cidr_set_masklen_internal(prefix, commonbits));
224 out->nNodes = 4;
225
226 for (i = 0; i < in->nTuples; i++)
227 {
228 tmp = DatumGetInetPP(in->datums[i]);
229 out->mapTuplesToNodes[i] = inet_spg_node_number(tmp, commonbits);
230 out->leafTupleDatums[i] = InetPGetDatum(tmp);
231 }
232 }
233
235}
uint64_t Datum
Definition postgres.h:70
Datum * datums
Definition spgist.h:113
int * mapTuplesToNodes
Definition spgist.h:125
Datum * nodeLabels
Definition spgist.h:123
Datum * leafTupleDatums
Definition spgist.h:126
Datum prefixDatum
Definition spgist.h:120

References bitncommon(), cidr_set_masklen_internal(), DatumGetInetPP(), spgPickSplitIn::datums, fb(), spgPickSplitOut::hasPrefix, i, inet_spg_node_number(), InetPGetDatum(), ip_addr, ip_bits, ip_family, spgPickSplitOut::leafTupleDatums, spgPickSplitOut::mapTuplesToNodes, spgPickSplitOut::nNodes, spgPickSplitOut::nodeLabels, spgPickSplitIn::nTuples, palloc_array, PG_GETARG_POINTER, PG_RETURN_VOID, PGSQL_AF_INET, and spgPickSplitOut::prefixDatum.