Preserve CurrentMemoryContext across notify and sinval interrupts.
[pgsql.git] / contrib / btree_gist / btree_utils_num.c
blob346ee837d75f44e1b4aa00fffb408a53601935e1
1 /*
2 * contrib/btree_gist/btree_utils_num.c
3 */
4 #include "postgres.h"
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"
13 GISTENTRY *
14 gbt_num_compress(GISTENTRY *entry, const gbtree_ninfo *tinfo)
16 GISTENTRY *retval;
18 if (entry->leafkey)
20 union
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;
34 GBT_NUMKEY *r = (GBT_NUMKEY *) palloc0(tinfo->indexsize);
35 void *leaf = NULL;
37 switch (tinfo->t)
39 case gbt_t_bool:
40 v.bo = DatumGetBool(entry->key);
41 leaf = &v.bo;
42 break;
43 case gbt_t_int2:
44 v.i2 = DatumGetInt16(entry->key);
45 leaf = &v.i2;
46 break;
47 case gbt_t_int4:
48 v.i4 = DatumGetInt32(entry->key);
49 leaf = &v.i4;
50 break;
51 case gbt_t_int8:
52 v.i8 = DatumGetInt64(entry->key);
53 leaf = &v.i8;
54 break;
55 case gbt_t_oid:
56 case gbt_t_enum:
57 v.i4 = DatumGetObjectId(entry->key);
58 leaf = &v.i4;
59 break;
60 case gbt_t_float4:
61 v.f4 = DatumGetFloat4(entry->key);
62 leaf = &v.f4;
63 break;
64 case gbt_t_float8:
65 v.f8 = DatumGetFloat8(entry->key);
66 leaf = &v.f8;
67 break;
68 case gbt_t_date:
69 v.dt = DatumGetDateADT(entry->key);
70 leaf = &v.dt;
71 break;
72 case gbt_t_time:
73 v.tm = DatumGetTimeADT(entry->key);
74 leaf = &v.tm;
75 break;
76 case gbt_t_ts:
77 v.ts = DatumGetTimestamp(entry->key);
78 leaf = &v.ts;
79 break;
80 case gbt_t_cash:
81 v.ch = DatumGetCash(entry->key);
82 leaf = &v.ch;
83 break;
84 default:
85 leaf = DatumGetPointer(entry->key);
88 Assert(tinfo->indexsize >= 2 * tinfo->size);
90 memcpy(&r[0], leaf, tinfo->size);
91 memcpy(&r[tinfo->size], leaf, tinfo->size);
92 retval = palloc(sizeof(GISTENTRY));
93 gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page,
94 entry->offset, false);
96 else
97 retval = entry;
99 return retval;
103 * Convert a compressed leaf item back to the original type, for index-only
104 * scans.
106 GISTENTRY *
107 gbt_num_fetch(GISTENTRY *entry, const gbtree_ninfo *tinfo)
109 GISTENTRY *retval;
110 Datum datum;
112 Assert(tinfo->indexsize >= 2 * tinfo->size);
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.
119 switch (tinfo->t)
121 case gbt_t_bool:
122 datum = BoolGetDatum(*(bool *) entry->key);
123 break;
124 case gbt_t_int2:
125 datum = Int16GetDatum(*(int16 *) entry->key);
126 break;
127 case gbt_t_int4:
128 datum = Int32GetDatum(*(int32 *) entry->key);
129 break;
130 case gbt_t_int8:
131 datum = Int64GetDatum(*(int64 *) entry->key);
132 break;
133 case gbt_t_oid:
134 case gbt_t_enum:
135 datum = ObjectIdGetDatum(*(Oid *) entry->key);
136 break;
137 case gbt_t_float4:
138 datum = Float4GetDatum(*(float4 *) entry->key);
139 break;
140 case gbt_t_float8:
141 datum = Float8GetDatum(*(float8 *) entry->key);
142 break;
143 case gbt_t_date:
144 datum = DateADTGetDatum(*(DateADT *) entry->key);
145 break;
146 case gbt_t_time:
147 datum = TimeADTGetDatum(*(TimeADT *) entry->key);
148 break;
149 case gbt_t_ts:
150 datum = TimestampGetDatum(*(Timestamp *) entry->key);
151 break;
152 case gbt_t_cash:
153 datum = CashGetDatum(*(Cash *) entry->key);
154 break;
155 default:
156 datum = entry->key;
159 retval = palloc(sizeof(GISTENTRY));
160 gistentryinit(*retval, datum, entry->rel, entry->page, entry->offset,
161 false);
162 return retval;
168 ** The GiST union method for numerical values
171 void *
172 gbt_num_union(GBT_NUMKEY *out, const GistEntryVector *entryvec, const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
174 int i,
175 numranges;
176 GBT_NUMKEY *cur;
177 GBT_NUMKEY_R o,
180 numranges = entryvec->n;
181 cur = (GBT_NUMKEY *) DatumGetPointer((entryvec->vector[0].key));
184 o.lower = &((GBT_NUMKEY *) out)[0];
185 o.upper = &((GBT_NUMKEY *) out)[tinfo->size];
187 memcpy(out, cur, 2 * tinfo->size);
189 for (i = 1; i < numranges; i++)
191 cur = (GBT_NUMKEY *) DatumGetPointer((entryvec->vector[i].key));
192 c.lower = &cur[0];
193 c.upper = &cur[tinfo->size];
194 /* if out->lower > cur->lower, adopt cur as lower */
195 if (tinfo->f_gt(o.lower, c.lower, flinfo))
196 memcpy(unconstify(GBT_NUMKEY *, o.lower), c.lower, tinfo->size);
197 /* if out->upper < cur->upper, adopt cur as upper */
198 if (tinfo->f_lt(o.upper, c.upper, flinfo))
199 memcpy(unconstify(GBT_NUMKEY *, o.upper), c.upper, tinfo->size);
202 return out;
208 ** The GiST same method for numerical values
211 bool
212 gbt_num_same(const GBT_NUMKEY *a, const GBT_NUMKEY *b, const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
214 GBT_NUMKEY_R b1,
217 b1.lower = &(a[0]);
218 b1.upper = &(a[tinfo->size]);
219 b2.lower = &(b[0]);
220 b2.upper = &(b[tinfo->size]);
222 return (tinfo->f_eq(b1.lower, b2.lower, flinfo) &&
223 tinfo->f_eq(b1.upper, b2.upper, flinfo));
227 void
228 gbt_num_bin_union(Datum *u, GBT_NUMKEY *e, const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
230 GBT_NUMKEY_R rd;
232 rd.lower = &e[0];
233 rd.upper = &e[tinfo->size];
235 if (!DatumGetPointer(*u))
237 *u = PointerGetDatum(palloc0(tinfo->indexsize));
238 memcpy(&(((GBT_NUMKEY *) DatumGetPointer(*u))[0]), rd.lower, tinfo->size);
239 memcpy(&(((GBT_NUMKEY *) DatumGetPointer(*u))[tinfo->size]), rd.upper, tinfo->size);
241 else
243 GBT_NUMKEY_R ur;
245 ur.lower = &(((GBT_NUMKEY *) DatumGetPointer(*u))[0]);
246 ur.upper = &(((GBT_NUMKEY *) DatumGetPointer(*u))[tinfo->size]);
247 if (tinfo->f_gt(ur.lower, rd.lower, flinfo))
248 memcpy(unconstify(GBT_NUMKEY *, ur.lower), rd.lower, tinfo->size);
249 if (tinfo->f_lt(ur.upper, rd.upper, flinfo))
250 memcpy(unconstify(GBT_NUMKEY *, ur.upper), rd.upper, tinfo->size);
257 * The GiST consistent method
259 * Note: we currently assume that no datatypes that use this routine are
260 * collation-aware; so we don't bother passing collation through.
262 bool
263 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)
270 bool retval;
272 switch (*strategy)
274 case BTLessEqualStrategyNumber:
275 retval = tinfo->f_ge(query, key->lower, flinfo);
276 break;
277 case BTLessStrategyNumber:
278 if (is_leaf)
279 retval = tinfo->f_gt(query, key->lower, flinfo);
280 else
281 retval = tinfo->f_ge(query, key->lower, flinfo);
282 break;
283 case BTEqualStrategyNumber:
284 if (is_leaf)
285 retval = tinfo->f_eq(query, key->lower, flinfo);
286 else
287 retval = (tinfo->f_le(key->lower, query, flinfo) &&
288 tinfo->f_le(query, key->upper, flinfo));
289 break;
290 case BTGreaterStrategyNumber:
291 if (is_leaf)
292 retval = tinfo->f_lt(query, key->upper, flinfo);
293 else
294 retval = tinfo->f_le(query, key->upper, flinfo);
295 break;
296 case BTGreaterEqualStrategyNumber:
297 retval = tinfo->f_le(query, key->upper, flinfo);
298 break;
299 case BtreeGistNotEqualStrategyNumber:
300 retval = (!(tinfo->f_eq(query, key->lower, flinfo) &&
301 tinfo->f_eq(query, key->upper, flinfo)));
302 break;
303 default:
304 retval = false;
307 return retval;
312 ** The GiST distance method (for KNN-Gist)
315 float8
316 gbt_num_distance(const GBT_NUMKEY_R *key,
317 const void *query,
318 bool is_leaf,
319 const gbtree_ninfo *tinfo,
320 FmgrInfo *flinfo)
322 float8 retval;
324 if (tinfo->f_dist == NULL)
325 elog(ERROR, "KNN search is not supported for btree_gist type %d",
326 (int) tinfo->t);
327 if (tinfo->f_le(query, key->lower, flinfo))
328 retval = tinfo->f_dist(query, key->lower, flinfo);
329 else if (tinfo->f_ge(query, key->upper, flinfo))
330 retval = tinfo->f_dist(query, key->upper, flinfo);
331 else
332 retval = 0.0;
334 return retval;
338 GIST_SPLITVEC *
339 gbt_num_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v,
340 const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
342 OffsetNumber i,
343 maxoff = entryvec->n - 1;
344 Nsrt *arr;
345 int nbytes;
347 arr = (Nsrt *) palloc((maxoff + 1) * sizeof(Nsrt));
348 nbytes = (maxoff + 2) * sizeof(OffsetNumber);
349 v->spl_left = (OffsetNumber *) palloc(nbytes);
350 v->spl_right = (OffsetNumber *) palloc(nbytes);
351 v->spl_ldatum = PointerGetDatum(0);
352 v->spl_rdatum = PointerGetDatum(0);
353 v->spl_nleft = 0;
354 v->spl_nright = 0;
356 /* Sort entries */
358 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
360 arr[i].t = (GBT_NUMKEY *) DatumGetPointer((entryvec->vector[i].key));
361 arr[i].i = i;
363 qsort_arg(&arr[FirstOffsetNumber], maxoff - FirstOffsetNumber + 1, sizeof(Nsrt), (qsort_arg_comparator) tinfo->f_cmp, flinfo);
365 /* We do simply create two parts */
367 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
369 if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
371 gbt_num_bin_union(&v->spl_ldatum, arr[i].t, tinfo, flinfo);
372 v->spl_left[v->spl_nleft] = arr[i].i;
373 v->spl_nleft++;
375 else
377 gbt_num_bin_union(&v->spl_rdatum, arr[i].t, tinfo, flinfo);
378 v->spl_right[v->spl_nright] = arr[i].i;
379 v->spl_nright++;
383 return v;