Line data Source code
1 : /*
2 : * contrib/btree_gist/btree_inet.c
3 : */
4 : #include "postgres.h"
5 :
6 : #include "btree_gist.h"
7 : #include "btree_utils_num.h"
8 : #include "catalog/pg_type.h"
9 : #include "utils/builtins.h"
10 : #include "utils/sortsupport.h"
11 :
12 : typedef struct inetkey
13 : {
14 : double lower;
15 : double upper;
16 : } inetKEY;
17 :
18 : /* GiST support functions */
19 6 : PG_FUNCTION_INFO_V1(gbt_inet_compress);
20 6 : PG_FUNCTION_INFO_V1(gbt_inet_union);
21 6 : PG_FUNCTION_INFO_V1(gbt_inet_picksplit);
22 6 : PG_FUNCTION_INFO_V1(gbt_inet_consistent);
23 6 : PG_FUNCTION_INFO_V1(gbt_inet_penalty);
24 6 : PG_FUNCTION_INFO_V1(gbt_inet_same);
25 6 : PG_FUNCTION_INFO_V1(gbt_inet_sortsupport);
26 :
27 :
28 : static bool
29 11994 : gbt_inetgt(const void *a, const void *b, FmgrInfo *flinfo)
30 : {
31 11994 : return (*((const double *) a) > *((const double *) b));
32 : }
33 : static bool
34 1232 : gbt_inetge(const void *a, const void *b, FmgrInfo *flinfo)
35 : {
36 1232 : return (*((const double *) a) >= *((const double *) b));
37 : }
38 : static bool
39 2844 : gbt_ineteq(const void *a, const void *b, FmgrInfo *flinfo)
40 : {
41 2844 : return (*((const double *) a) == *((const double *) b));
42 : }
43 : static bool
44 1880 : gbt_inetle(const void *a, const void *b, FmgrInfo *flinfo)
45 : {
46 1880 : return (*((const double *) a) <= *((const double *) b));
47 : }
48 : static bool
49 12594 : gbt_inetlt(const void *a, const void *b, FmgrInfo *flinfo)
50 : {
51 12594 : return (*((const double *) a) < *((const double *) b));
52 : }
53 :
54 : static int
55 14816 : gbt_inetkey_cmp(const void *a, const void *b, FmgrInfo *flinfo)
56 : {
57 14816 : inetKEY *ia = (inetKEY *) (((const Nsrt *) a)->t);
58 14816 : inetKEY *ib = (inetKEY *) (((const Nsrt *) b)->t);
59 :
60 14816 : if (ia->lower == ib->lower)
61 : {
62 0 : if (ia->upper == ib->upper)
63 0 : return 0;
64 :
65 0 : return (ia->upper > ib->upper) ? 1 : -1;
66 : }
67 :
68 14816 : return (ia->lower > ib->lower) ? 1 : -1;
69 : }
70 :
71 :
72 : static const gbtree_ninfo tinfo =
73 : {
74 : gbt_t_inet,
75 : sizeof(double),
76 : 16, /* sizeof(gbtreekey16) */
77 : gbt_inetgt,
78 : gbt_inetge,
79 : gbt_ineteq,
80 : gbt_inetle,
81 : gbt_inetlt,
82 : gbt_inetkey_cmp,
83 : NULL
84 : };
85 :
86 :
87 : /**************************************************
88 : * GiST support functions
89 : **************************************************/
90 :
91 : Datum
92 3638 : gbt_inet_compress(PG_FUNCTION_ARGS)
93 : {
94 3638 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
95 : GISTENTRY *retval;
96 :
97 3638 : if (entry->leafkey)
98 : {
99 3600 : inetKEY *r = (inetKEY *) palloc(sizeof(inetKEY));
100 3600 : bool failure = false;
101 :
102 3600 : retval = palloc(sizeof(GISTENTRY));
103 3600 : r->lower = convert_network_to_scalar(entry->key, INETOID, &failure);
104 : Assert(!failure);
105 3600 : r->upper = r->lower;
106 3600 : gistentryinit(*retval, PointerGetDatum(r),
107 : entry->rel, entry->page,
108 : entry->offset, false);
109 : }
110 : else
111 38 : retval = entry;
112 :
113 3638 : PG_RETURN_POINTER(retval);
114 : }
115 :
116 : Datum
117 7308 : gbt_inet_consistent(PG_FUNCTION_ARGS)
118 : {
119 7308 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
120 7308 : Datum dquery = PG_GETARG_DATUM(1);
121 7308 : StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
122 :
123 : /* Oid subtype = PG_GETARG_OID(3); */
124 7308 : bool *recheck = (bool *) PG_GETARG_POINTER(4);
125 7308 : inetKEY *kkk = (inetKEY *) DatumGetPointer(entry->key);
126 : GBT_NUMKEY_R key;
127 : double query;
128 7308 : bool failure = false;
129 :
130 7308 : query = convert_network_to_scalar(dquery, INETOID, &failure);
131 : Assert(!failure);
132 :
133 : /* All cases served by this function are inexact */
134 7308 : *recheck = true;
135 :
136 7308 : key.lower = (GBT_NUMKEY *) &kkk->lower;
137 7308 : key.upper = (GBT_NUMKEY *) &kkk->upper;
138 :
139 7308 : PG_RETURN_BOOL(gbt_num_consistent(&key, &query,
140 : &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo));
141 : }
142 :
143 : Datum
144 834 : gbt_inet_union(PG_FUNCTION_ARGS)
145 : {
146 834 : GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
147 834 : void *out = palloc(sizeof(inetKEY));
148 :
149 834 : *(int *) PG_GETARG_POINTER(1) = sizeof(inetKEY);
150 834 : PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
151 : }
152 :
153 : Datum
154 3548 : gbt_inet_penalty(PG_FUNCTION_ARGS)
155 : {
156 3548 : inetKEY *origentry = (inetKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
157 3548 : inetKEY *newentry = (inetKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
158 3548 : float *result = (float *) PG_GETARG_POINTER(2);
159 :
160 3548 : penalty_num(result, origentry->lower, origentry->upper, newentry->lower, newentry->upper);
161 :
162 3548 : PG_RETURN_POINTER(result);
163 : }
164 :
165 : Datum
166 18 : gbt_inet_picksplit(PG_FUNCTION_ARGS)
167 : {
168 18 : PG_RETURN_POINTER(gbt_num_picksplit((GistEntryVector *) PG_GETARG_POINTER(0),
169 : (GIST_SPLITVEC *) PG_GETARG_POINTER(1),
170 : &tinfo, fcinfo->flinfo));
171 : }
172 :
173 : Datum
174 822 : gbt_inet_same(PG_FUNCTION_ARGS)
175 : {
176 822 : inetKEY *b1 = (inetKEY *) PG_GETARG_POINTER(0);
177 822 : inetKEY *b2 = (inetKEY *) PG_GETARG_POINTER(1);
178 822 : bool *result = (bool *) PG_GETARG_POINTER(2);
179 :
180 822 : *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
181 822 : PG_RETURN_POINTER(result);
182 : }
183 :
184 : static int
185 24108 : gbt_inet_ssup_cmp(Datum x, Datum y, SortSupport ssup)
186 : {
187 24108 : inetKEY *arg1 = (inetKEY *) DatumGetPointer(x);
188 24108 : inetKEY *arg2 = (inetKEY *) DatumGetPointer(y);
189 :
190 : /* for leaf items we expect lower == upper, so only compare lower */
191 24108 : if (arg1->lower < arg2->lower)
192 13168 : return -1;
193 10940 : else if (arg1->lower > arg2->lower)
194 10940 : return 1;
195 : else
196 0 : return 0;
197 : }
198 :
199 : Datum
200 4 : gbt_inet_sortsupport(PG_FUNCTION_ARGS)
201 : {
202 4 : SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
203 :
204 4 : ssup->comparator = gbt_inet_ssup_cmp;
205 4 : ssup->ssup_extra = NULL;
206 :
207 4 : PG_RETURN_VOID();
208 : }
|