Age Owner Branch data TLA Line data Source code
1 : : /*
2 : : * contrib/btree_gist/btree_utils_num.c
3 : : */
4 : : #include "postgres.h"
5 : :
6 : : #include "btree_gist.h"
7 : : #include "btree_utils_num.h"
8 : : #include "utils/cash.h"
9 : : #include "utils/date.h"
10 : : #include "utils/timestamp.h"
11 : :
12 : :
13 : : GISTENTRY *
3817 heikki.linnakangas@i 14 :CBC 10271 : gbt_num_compress(GISTENTRY *entry, const gbtree_ninfo *tinfo)
15 : : {
16 : : GISTENTRY *retval;
17 : :
7678 bruce@momjian.us 18 [ + + ]: 10271 : if (entry->leafkey)
19 : : {
20 : : union
21 : : {
22 : : bool bo;
23 : : int16 i2;
24 : : int32 i4;
25 : : int64 i8;
26 : : float4 f4;
27 : : float8 f8;
28 : : DateADT dt;
29 : : TimeADT tm;
30 : : Timestamp ts;
31 : : Cash ch;
32 : : } v;
33 : :
4131 tgl@sss.pgh.pa.us 34 : 10197 : GBT_NUMKEY *r = (GBT_NUMKEY *) palloc0(tinfo->indexsize);
7678 bruce@momjian.us 35 : 10197 : void *leaf = NULL;
36 : :
37 [ + + + + : 10197 : switch (tinfo->t)
+ + + + +
+ + + ]
38 : : {
1400 tomas.vondra@postgre 39 : 2 : case gbt_t_bool:
40 : 2 : v.bo = DatumGetBool(entry->key);
41 : 2 : leaf = &v.bo;
42 : 2 : break;
7678 bruce@momjian.us 43 : 546 : case gbt_t_int2:
44 : 546 : v.i2 = DatumGetInt16(entry->key);
45 : 546 : leaf = &v.i2;
46 : 546 : break;
47 : 1078 : case gbt_t_int4:
48 : 1078 : v.i4 = DatumGetInt32(entry->key);
49 : 1078 : leaf = &v.i4;
50 : 1078 : break;
6347 tgl@sss.pgh.pa.us 51 : 547 : case gbt_t_int8:
52 : 547 : v.i8 = DatumGetInt64(entry->key);
53 : 547 : leaf = &v.i8;
54 : 547 : break;
7678 bruce@momjian.us 55 : 1532 : case gbt_t_oid:
56 : : case gbt_t_enum:
57 : 1532 : v.i4 = DatumGetObjectId(entry->key);
58 : 1532 : leaf = &v.i4;
59 : 1532 : break;
6347 tgl@sss.pgh.pa.us 60 : 547 : case gbt_t_float4:
61 : 547 : v.f4 = DatumGetFloat4(entry->key);
62 : 547 : leaf = &v.f4;
63 : 547 : break;
64 : 544 : case gbt_t_float8:
65 : 544 : v.f8 = DatumGetFloat8(entry->key);
66 : 544 : leaf = &v.f8;
67 : 544 : break;
7678 bruce@momjian.us 68 : 544 : case gbt_t_date:
69 : 544 : v.dt = DatumGetDateADT(entry->key);
70 : 544 : leaf = &v.dt;
71 : 544 : break;
6347 tgl@sss.pgh.pa.us 72 : 544 : case gbt_t_time:
73 : 544 : v.tm = DatumGetTimeADT(entry->key);
74 : 544 : leaf = &v.tm;
75 : 544 : break;
76 : 2570 : case gbt_t_ts:
77 : 2570 : v.ts = DatumGetTimestamp(entry->key);
78 : 2570 : leaf = &v.ts;
79 : 2570 : break;
80 : 543 : case gbt_t_cash:
81 : 543 : v.ch = DatumGetCash(entry->key);
82 : 543 : leaf = &v.ch;
6350 alvherre@alvh.no-ip. 83 : 543 : break;
7678 bruce@momjian.us 84 : 1200 : default:
85 : 1200 : leaf = DatumGetPointer(entry->key);
86 : : }
87 : :
4131 tgl@sss.pgh.pa.us 88 [ - + ]: 10197 : Assert(tinfo->indexsize >= 2 * tinfo->size);
89 : :
942 peter@eisentraut.org 90 : 10197 : memcpy(&r[0], leaf, tinfo->size);
91 : 10197 : memcpy(&r[tinfo->size], leaf, tinfo->size);
7678 bruce@momjian.us 92 : 10197 : retval = palloc(sizeof(GISTENTRY));
93 : 10197 : gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page,
94 : : entry->offset, false);
95 : : }
96 : : else
97 : 74 : retval = entry;
98 : :
99 : 10271 : return retval;
100 : : }
101 : :
102 : : /*
103 : : * Convert a compressed leaf item back to the original type, for index-only
104 : : * scans.
105 : : */
106 : : GISTENTRY *
3816 heikki.linnakangas@i 107 : 2913 : gbt_num_fetch(GISTENTRY *entry, const gbtree_ninfo *tinfo)
108 : : {
109 : : GISTENTRY *retval;
110 : : Datum datum;
111 : :
112 [ - + ]: 2913 : Assert(tinfo->indexsize >= 2 * tinfo->size);
113 : :
114 : : /*
115 : : * Get the original Datum from the stored datum. On leaf entries, the
116 : : * lower and upper bound are the same. We just grab the lower bound and
117 : : * return it.
118 : : */
119 [ + + + + : 2913 : switch (tinfo->t)
- + + + +
+ + + ]
120 : : {
1400 tomas.vondra@postgre 121 : 7 : case gbt_t_bool:
29 peter@eisentraut.org 122 :GNC 7 : datum = BoolGetDatum(*(bool *) DatumGetPointer(entry->key));
1400 tomas.vondra@postgre 123 :CBC 7 : break;
3816 heikki.linnakangas@i 124 : 273 : case gbt_t_int2:
29 peter@eisentraut.org 125 :GNC 273 : datum = Int16GetDatum(*(int16 *) DatumGetPointer(entry->key));
3816 heikki.linnakangas@i 126 :CBC 273 : break;
127 : 273 : case gbt_t_int4:
29 peter@eisentraut.org 128 :GNC 273 : datum = Int32GetDatum(*(int32 *) DatumGetPointer(entry->key));
3816 heikki.linnakangas@i 129 :CBC 273 : break;
130 : 274 : case gbt_t_int8:
29 peter@eisentraut.org 131 :GNC 274 : datum = Int64GetDatum(*(int64 *) DatumGetPointer(entry->key));
3816 heikki.linnakangas@i 132 :CBC 274 : break;
3816 heikki.linnakangas@i 133 :UBC 0 : case gbt_t_oid:
134 : : case gbt_t_enum:
29 peter@eisentraut.org 135 :UNC 0 : datum = ObjectIdGetDatum(*(Oid *) DatumGetPointer(entry->key));
3816 heikki.linnakangas@i 136 :UBC 0 : break;
3816 heikki.linnakangas@i 137 :CBC 273 : case gbt_t_float4:
29 peter@eisentraut.org 138 :GNC 273 : datum = Float4GetDatum(*(float4 *) DatumGetPointer(entry->key));
3816 heikki.linnakangas@i 139 :CBC 273 : break;
140 : 272 : case gbt_t_float8:
29 peter@eisentraut.org 141 :GNC 272 : datum = Float8GetDatum(*(float8 *) DatumGetPointer(entry->key));
3816 heikki.linnakangas@i 142 :CBC 272 : break;
143 : 272 : case gbt_t_date:
29 peter@eisentraut.org 144 :GNC 272 : datum = DateADTGetDatum(*(DateADT *) DatumGetPointer(entry->key));
3816 heikki.linnakangas@i 145 :CBC 272 : break;
146 : 272 : case gbt_t_time:
29 peter@eisentraut.org 147 :GNC 272 : datum = TimeADTGetDatum(*(TimeADT *) DatumGetPointer(entry->key));
3816 heikki.linnakangas@i 148 :CBC 272 : break;
149 : 559 : case gbt_t_ts:
29 peter@eisentraut.org 150 :GNC 559 : datum = TimestampGetDatum(*(Timestamp *) DatumGetPointer(entry->key));
3816 heikki.linnakangas@i 151 :CBC 559 : break;
152 : 272 : case gbt_t_cash:
29 peter@eisentraut.org 153 :GNC 272 : datum = CashGetDatum(*(Cash *) DatumGetPointer(entry->key));
3816 heikki.linnakangas@i 154 :CBC 272 : break;
155 : 166 : default:
1105 peter@eisentraut.org 156 : 166 : datum = entry->key;
157 : : }
158 : :
3816 heikki.linnakangas@i 159 : 2913 : retval = palloc(sizeof(GISTENTRY));
160 : 2913 : gistentryinit(*retval, datum, entry->rel, entry->page, entry->offset,
161 : : false);
162 : 2913 : return retval;
163 : : }
164 : :
165 : :
166 : :
167 : : /*
168 : : ** The GiST union method for numerical values
169 : : */
170 : :
171 : : void *
3091 andrew@dunslane.net 172 : 2289 : gbt_num_union(GBT_NUMKEY *out, const GistEntryVector *entryvec, const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
173 : : {
174 : : int i,
175 : : numranges;
176 : : GBT_NUMKEY *cur;
177 : : GBT_NUMKEY_R o,
178 : : c;
179 : :
7678 bruce@momjian.us 180 : 2289 : numranges = entryvec->n;
181 : 2289 : cur = (GBT_NUMKEY *) DatumGetPointer((entryvec->vector[0].key));
182 : :
183 : :
184 : 2289 : o.lower = &((GBT_NUMKEY *) out)[0];
185 : 2289 : o.upper = &((GBT_NUMKEY *) out)[tinfo->size];
186 : :
942 peter@eisentraut.org 187 : 2289 : memcpy(out, cur, 2 * tinfo->size);
188 : :
7678 bruce@momjian.us 189 [ + + ]: 18934 : for (i = 1; i < numranges; i++)
190 : : {
191 : 16645 : cur = (GBT_NUMKEY *) DatumGetPointer((entryvec->vector[i].key));
192 : 16645 : c.lower = &cur[0];
193 : 16645 : c.upper = &cur[tinfo->size];
194 : : /* if out->lower > cur->lower, adopt cur as lower */
2921 peter_e@gmx.net 195 [ + + ]: 16645 : if (tinfo->f_gt(o.lower, c.lower, flinfo))
2412 peter@eisentraut.org 196 : 12 : memcpy(unconstify(GBT_NUMKEY *, o.lower), c.lower, tinfo->size);
197 : : /* if out->upper < cur->upper, adopt cur as upper */
2921 peter_e@gmx.net 198 [ + + ]: 16645 : if (tinfo->f_lt(o.upper, c.upper, flinfo))
2412 peter@eisentraut.org 199 : 9243 : memcpy(unconstify(GBT_NUMKEY *, o.upper), c.upper, tinfo->size);
200 : : }
201 : :
7678 bruce@momjian.us 202 : 2289 : return out;
203 : : }
204 : :
205 : :
206 : :
207 : : /*
208 : : ** The GiST same method for numerical values
209 : : */
210 : :
211 : : bool
3091 andrew@dunslane.net 212 : 2246 : gbt_num_same(const GBT_NUMKEY *a, const GBT_NUMKEY *b, const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
213 : : {
214 : : GBT_NUMKEY_R b1,
215 : : b2;
216 : :
2412 peter@eisentraut.org 217 : 2246 : b1.lower = &(a[0]);
218 : 2246 : b1.upper = &(a[tinfo->size]);
219 : 2246 : b2.lower = &(b[0]);
220 : 2246 : b2.upper = &(b[tinfo->size]);
221 : :
2921 peter_e@gmx.net 222 [ + + + + ]: 4483 : return (tinfo->f_eq(b1.lower, b2.lower, flinfo) &&
223 : 2237 : tinfo->f_eq(b1.upper, b2.upper, flinfo));
224 : : }
225 : :
226 : :
227 : : void
3091 andrew@dunslane.net 228 : 20393 : gbt_num_bin_union(Datum *u, GBT_NUMKEY *e, const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
229 : : {
230 : : GBT_NUMKEY_R rd;
231 : :
7678 bruce@momjian.us 232 : 20393 : rd.lower = &e[0];
233 : 20393 : rd.upper = &e[tinfo->size];
234 : :
235 [ + + ]: 20393 : if (!DatumGetPointer(*u))
236 : : {
4131 tgl@sss.pgh.pa.us 237 : 112 : *u = PointerGetDatum(palloc0(tinfo->indexsize));
2412 peter@eisentraut.org 238 : 112 : memcpy(&(((GBT_NUMKEY *) DatumGetPointer(*u))[0]), rd.lower, tinfo->size);
239 : 112 : memcpy(&(((GBT_NUMKEY *) DatumGetPointer(*u))[tinfo->size]), rd.upper, tinfo->size);
240 : : }
241 : : else
242 : : {
243 : : GBT_NUMKEY_R ur;
244 : :
7678 bruce@momjian.us 245 : 20281 : ur.lower = &(((GBT_NUMKEY *) DatumGetPointer(*u))[0]);
246 : 20281 : ur.upper = &(((GBT_NUMKEY *) DatumGetPointer(*u))[tinfo->size]);
2412 peter@eisentraut.org 247 [ - + ]: 20281 : if (tinfo->f_gt(ur.lower, rd.lower, flinfo))
2412 peter@eisentraut.org 248 :UBC 0 : memcpy(unconstify(GBT_NUMKEY *, ur.lower), rd.lower, tinfo->size);
2412 peter@eisentraut.org 249 [ + + ]:CBC 20281 : if (tinfo->f_lt(ur.upper, rd.upper, flinfo))
250 : 14397 : memcpy(unconstify(GBT_NUMKEY *, ur.upper), rd.upper, tinfo->size);
251 : : }
7771 teodor@sigaev.ru 252 : 20393 : }
253 : :
254 : :
255 : :
256 : : /*
257 : : * The GiST consistent method
258 : : *
259 : : * Note: we currently assume that no datatypes that use this routine are
260 : : * collation-aware; so we don't bother passing collation through.
261 : : */
262 : : bool
5302 tgl@sss.pgh.pa.us 263 : 46186 : gbt_num_consistent(const GBT_NUMKEY_R *key,
264 : : const void *query,
265 : : const StrategyNumber *strategy,
266 : : bool is_leaf,
267 : : const gbtree_ninfo *tinfo,
268 : : FmgrInfo *flinfo)
269 : : {
270 : : bool retval;
271 : :
7678 bruce@momjian.us 272 [ + + + + : 46186 : switch (*strategy)
+ + - ]
273 : : {
274 : 8492 : case BTLessEqualStrategyNumber:
2921 peter_e@gmx.net 275 : 8492 : retval = tinfo->f_ge(query, key->lower, flinfo);
7678 bruce@momjian.us 276 : 8492 : break;
277 : 8800 : case BTLessStrategyNumber:
278 [ + + ]: 8800 : if (is_leaf)
2921 peter_e@gmx.net 279 : 8732 : retval = tinfo->f_gt(query, key->lower, flinfo);
280 : : else
281 : 68 : retval = tinfo->f_ge(query, key->lower, flinfo);
7678 bruce@momjian.us 282 : 8800 : break;
283 : 7280 : case BTEqualStrategyNumber:
284 [ + + ]: 7280 : if (is_leaf)
2921 peter_e@gmx.net 285 : 7204 : retval = tinfo->f_eq(query, key->lower, flinfo);
286 : : else
287 [ + + + + ]: 120 : retval = (tinfo->f_le(key->lower, query, flinfo) &&
288 : 44 : tinfo->f_le(query, key->upper, flinfo));
7678 bruce@momjian.us 289 : 7280 : break;
290 : 10704 : case BTGreaterStrategyNumber:
291 [ + + ]: 10704 : if (is_leaf)
2921 peter_e@gmx.net 292 : 10644 : retval = tinfo->f_lt(query, key->upper, flinfo);
293 : : else
294 : 60 : retval = tinfo->f_le(query, key->upper, flinfo);
7678 bruce@momjian.us 295 : 10704 : break;
296 : 10704 : case BTGreaterEqualStrategyNumber:
2921 peter_e@gmx.net 297 : 10704 : retval = tinfo->f_le(query, key->upper, flinfo);
7678 bruce@momjian.us 298 : 10704 : break;
5514 rhaas@postgresql.org 299 : 206 : case BtreeGistNotEqualStrategyNumber:
2921 peter_e@gmx.net 300 [ + + + + ]: 409 : retval = (!(tinfo->f_eq(query, key->lower, flinfo) &&
301 : 203 : tinfo->f_eq(query, key->upper, flinfo)));
5514 rhaas@postgresql.org 302 : 206 : break;
7678 bruce@momjian.us 303 :UBC 0 : default:
5302 tgl@sss.pgh.pa.us 304 : 0 : retval = false;
305 : : }
306 : :
2942 peter_e@gmx.net 307 :CBC 46186 : return retval;
308 : : }
309 : :
310 : :
311 : : /*
312 : : ** The GiST distance method (for KNN-Gist)
313 : : */
314 : :
315 : : float8
5302 tgl@sss.pgh.pa.us 316 : 3068 : gbt_num_distance(const GBT_NUMKEY_R *key,
317 : : const void *query,
318 : : bool is_leaf,
319 : : const gbtree_ninfo *tinfo,
320 : : FmgrInfo *flinfo)
321 : : {
322 : : float8 retval;
323 : :
324 [ - + ]: 3068 : if (tinfo->f_dist == NULL)
5302 tgl@sss.pgh.pa.us 325 [ # # ]:UBC 0 : elog(ERROR, "KNN search is not supported for btree_gist type %d",
326 : : (int) tinfo->t);
3091 andrew@dunslane.net 327 [ + + ]:CBC 3068 : if (tinfo->f_le(query, key->lower, flinfo))
328 : 1565 : retval = tinfo->f_dist(query, key->lower, flinfo);
329 [ + + ]: 1503 : else if (tinfo->f_ge(query, key->upper, flinfo))
330 : 1491 : retval = tinfo->f_dist(query, key->upper, flinfo);
331 : : else
5302 tgl@sss.pgh.pa.us 332 : 12 : retval = 0.0;
333 : :
334 : 3068 : return retval;
335 : : }
336 : :
337 : :
338 : : GIST_SPLITVEC *
7678 bruce@momjian.us 339 : 56 : gbt_num_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v,
340 : : const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
341 : : {
342 : : OffsetNumber i,
343 : 56 : maxoff = entryvec->n - 1;
344 : : Nsrt *arr;
345 : : int nbytes;
346 : :
347 : 56 : arr = (Nsrt *) palloc((maxoff + 1) * sizeof(Nsrt));
348 : 56 : nbytes = (maxoff + 2) * sizeof(OffsetNumber);
349 : 56 : v->spl_left = (OffsetNumber *) palloc(nbytes);
350 : 56 : v->spl_right = (OffsetNumber *) palloc(nbytes);
351 : 56 : v->spl_ldatum = PointerGetDatum(0);
352 : 56 : v->spl_rdatum = PointerGetDatum(0);
353 : 56 : v->spl_nleft = 0;
354 : 56 : v->spl_nright = 0;
355 : :
356 : : /* Sort entries */
357 : :
358 [ + + ]: 20449 : for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
359 : : {
360 : 20393 : arr[i].t = (GBT_NUMKEY *) DatumGetPointer((entryvec->vector[i].key));
361 : 20393 : arr[i].i = i;
362 : : }
942 peter@eisentraut.org 363 : 56 : qsort_arg(&arr[FirstOffsetNumber], maxoff - FirstOffsetNumber + 1, sizeof(Nsrt), (qsort_arg_comparator) tinfo->f_cmp, flinfo);
364 : :
365 : : /* We do simply create two parts */
366 : :
7678 bruce@momjian.us 367 [ + + ]: 20449 : for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
368 : : {
369 [ + + ]: 20393 : if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
370 : : {
3091 andrew@dunslane.net 371 : 10193 : gbt_num_bin_union(&v->spl_ldatum, arr[i].t, tinfo, flinfo);
7678 bruce@momjian.us 372 : 10193 : v->spl_left[v->spl_nleft] = arr[i].i;
373 : 10193 : v->spl_nleft++;
374 : : }
375 : : else
376 : : {
3091 andrew@dunslane.net 377 : 10200 : gbt_num_bin_union(&v->spl_rdatum, arr[i].t, tinfo, flinfo);
7678 bruce@momjian.us 378 : 10200 : v->spl_right[v->spl_nright] = arr[i].i;
379 : 10200 : v->spl_nright++;
380 : : }
381 : : }
382 : :
383 : 56 : return v;
384 : : }
|