PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
btree_utils_num.c
Go to the documentation of this file.
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 *
15 {
16  GISTENTRY *retval;
17 
18  if (entry->leafkey)
19  {
20  union
21  {
22  int16 i2;
23  int32 i4;
24  int64 i8;
25  float4 f4;
26  float8 f8;
27  DateADT dt;
28  TimeADT tm;
29  Timestamp ts;
30  Cash ch;
31  } v;
32 
33  GBT_NUMKEY *r = (GBT_NUMKEY *) palloc0(tinfo->indexsize);
34  void *leaf = NULL;
35 
36  switch (tinfo->t)
37  {
38  case gbt_t_int2:
39  v.i2 = DatumGetInt16(entry->key);
40  leaf = &v.i2;
41  break;
42  case gbt_t_int4:
43  v.i4 = DatumGetInt32(entry->key);
44  leaf = &v.i4;
45  break;
46  case gbt_t_int8:
47  v.i8 = DatumGetInt64(entry->key);
48  leaf = &v.i8;
49  break;
50  case gbt_t_oid:
51  case gbt_t_enum:
52  v.i4 = DatumGetObjectId(entry->key);
53  leaf = &v.i4;
54  break;
55  case gbt_t_float4:
56  v.f4 = DatumGetFloat4(entry->key);
57  leaf = &v.f4;
58  break;
59  case gbt_t_float8:
60  v.f8 = DatumGetFloat8(entry->key);
61  leaf = &v.f8;
62  break;
63  case gbt_t_date:
64  v.dt = DatumGetDateADT(entry->key);
65  leaf = &v.dt;
66  break;
67  case gbt_t_time:
68  v.tm = DatumGetTimeADT(entry->key);
69  leaf = &v.tm;
70  break;
71  case gbt_t_ts:
72  v.ts = DatumGetTimestamp(entry->key);
73  leaf = &v.ts;
74  break;
75  case gbt_t_cash:
76  v.ch = DatumGetCash(entry->key);
77  leaf = &v.ch;
78  break;
79  default:
80  leaf = DatumGetPointer(entry->key);
81  }
82 
83  Assert(tinfo->indexsize >= 2 * tinfo->size);
84 
85  memcpy((void *) &r[0], leaf, tinfo->size);
86  memcpy((void *) &r[tinfo->size], leaf, tinfo->size);
87  retval = palloc(sizeof(GISTENTRY));
88  gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page,
89  entry->offset, FALSE);
90  }
91  else
92  retval = entry;
93 
94  return retval;
95 }
96 
97 /*
98  * Convert a compressed leaf item back to the original type, for index-only
99  * scans.
100  */
101 GISTENTRY *
103 {
104  GISTENTRY *retval;
105  Datum datum;
106 
107  Assert(tinfo->indexsize >= 2 * tinfo->size);
108 
109  /*
110  * Get the original Datum from the stored datum. On leaf entries, the
111  * lower and upper bound are the same. We just grab the lower bound and
112  * return it.
113  */
114  switch (tinfo->t)
115  {
116  case gbt_t_int2:
117  datum = Int16GetDatum(*(int16 *) entry->key);
118  break;
119  case gbt_t_int4:
120  datum = Int32GetDatum(*(int32 *) entry->key);
121  break;
122  case gbt_t_int8:
123  datum = Int64GetDatum(*(int64 *) entry->key);
124  break;
125  case gbt_t_oid:
126  case gbt_t_enum:
127  datum = ObjectIdGetDatum(*(Oid *) entry->key);
128  break;
129  case gbt_t_float4:
130  datum = Float4GetDatum(*(float4 *) entry->key);
131  break;
132  case gbt_t_float8:
133  datum = Float8GetDatum(*(float8 *) entry->key);
134  break;
135  case gbt_t_date:
136  datum = DateADTGetDatum(*(DateADT *) entry->key);
137  break;
138  case gbt_t_time:
139  datum = TimeADTGetDatum(*(TimeADT *) entry->key);
140  break;
141  case gbt_t_ts:
142  datum = TimestampGetDatum(*(Timestamp *) entry->key);
143  break;
144  case gbt_t_cash:
145  datum = CashGetDatum(*(Cash *) entry->key);
146  break;
147  default:
148  datum = PointerGetDatum(entry->key);
149  }
150 
151  retval = palloc(sizeof(GISTENTRY));
152  gistentryinit(*retval, datum, entry->rel, entry->page, entry->offset,
153  FALSE);
154  return retval;
155 }
156 
157 
158 
159 /*
160 ** The GiST union method for numerical values
161 */
162 
163 void *
164 gbt_num_union(GBT_NUMKEY *out, const GistEntryVector *entryvec, const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
165 {
166  int i,
167  numranges;
168  GBT_NUMKEY *cur;
169  GBT_NUMKEY_R o,
170  c;
171 
172  numranges = entryvec->n;
173  cur = (GBT_NUMKEY *) DatumGetPointer((entryvec->vector[0].key));
174 
175 
176  o.lower = &((GBT_NUMKEY *) out)[0];
177  o.upper = &((GBT_NUMKEY *) out)[tinfo->size];
178 
179  memcpy((void *) out, (void *) cur, 2 * tinfo->size);
180 
181  for (i = 1; i < numranges; i++)
182  {
183  cur = (GBT_NUMKEY *) DatumGetPointer((entryvec->vector[i].key));
184  c.lower = &cur[0];
185  c.upper = &cur[tinfo->size];
186  /* if out->lower > cur->lower, adopt cur as lower */
187  if (tinfo->f_gt(o.lower, c.lower, flinfo))
188  memcpy((void *) o.lower, (void *) c.lower, tinfo->size);
189  /* if out->upper < cur->upper, adopt cur as upper */
190  if (tinfo->f_lt(o.upper, c.upper, flinfo))
191  memcpy((void *) o.upper, (void *) c.upper, tinfo->size);
192  }
193 
194  return out;
195 }
196 
197 
198 
199 /*
200 ** The GiST same method for numerical values
201 */
202 
203 bool
204 gbt_num_same(const GBT_NUMKEY *a, const GBT_NUMKEY *b, const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
205 {
206  GBT_NUMKEY_R b1,
207  b2;
208 
209  b1.lower = &(((GBT_NUMKEY *) a)[0]);
210  b1.upper = &(((GBT_NUMKEY *) a)[tinfo->size]);
211  b2.lower = &(((GBT_NUMKEY *) b)[0]);
212  b2.upper = &(((GBT_NUMKEY *) b)[tinfo->size]);
213 
214  return (tinfo->f_eq(b1.lower, b2.lower, flinfo) &&
215  tinfo->f_eq(b1.upper, b2.upper, flinfo));
216 }
217 
218 
219 void
221 {
222  GBT_NUMKEY_R rd;
223 
224  rd.lower = &e[0];
225  rd.upper = &e[tinfo->size];
226 
227  if (!DatumGetPointer(*u))
228  {
229  *u = PointerGetDatum(palloc0(tinfo->indexsize));
230  memcpy((void *) &(((GBT_NUMKEY *) DatumGetPointer(*u))[0]), (void *) rd.lower, tinfo->size);
231  memcpy((void *) &(((GBT_NUMKEY *) DatumGetPointer(*u))[tinfo->size]), (void *) rd.upper, tinfo->size);
232  }
233  else
234  {
235  GBT_NUMKEY_R ur;
236 
237  ur.lower = &(((GBT_NUMKEY *) DatumGetPointer(*u))[0]);
238  ur.upper = &(((GBT_NUMKEY *) DatumGetPointer(*u))[tinfo->size]);
239  if (tinfo->f_gt((void *) ur.lower, (void *) rd.lower, flinfo))
240  memcpy((void *) ur.lower, (void *) rd.lower, tinfo->size);
241  if (tinfo->f_lt((void *) ur.upper, (void *) rd.upper, flinfo))
242  memcpy((void *) ur.upper, (void *) rd.upper, tinfo->size);
243  }
244 }
245 
246 
247 
248 /*
249  * The GiST consistent method
250  *
251  * Note: we currently assume that no datatypes that use this routine are
252  * collation-aware; so we don't bother passing collation through.
253  */
254 bool
256  const void *query,
257  const StrategyNumber *strategy,
258  bool is_leaf,
259  const gbtree_ninfo *tinfo,
260  FmgrInfo *flinfo)
261 {
262  bool retval;
263 
264  switch (*strategy)
265  {
267  retval = tinfo->f_ge(query, key->lower, flinfo);
268  break;
270  if (is_leaf)
271  retval = tinfo->f_gt(query, key->lower, flinfo);
272  else
273  retval = tinfo->f_ge(query, key->lower, flinfo);
274  break;
276  if (is_leaf)
277  retval = tinfo->f_eq(query, key->lower, flinfo);
278  else
279  retval = (tinfo->f_le(key->lower, query, flinfo) &&
280  tinfo->f_le(query, key->upper, flinfo));
281  break;
283  if (is_leaf)
284  retval = tinfo->f_lt(query, key->upper, flinfo);
285  else
286  retval = tinfo->f_le(query, key->upper, flinfo);
287  break;
289  retval = tinfo->f_le(query, key->upper, flinfo);
290  break;
292  retval = (!(tinfo->f_eq(query, key->lower, flinfo) &&
293  tinfo->f_eq(query, key->upper, flinfo)));
294  break;
295  default:
296  retval = false;
297  }
298 
299  return retval;
300 }
301 
302 
303 /*
304 ** The GiST distance method (for KNN-Gist)
305 */
306 
307 float8
309  const void *query,
310  bool is_leaf,
311  const gbtree_ninfo *tinfo,
312  FmgrInfo *flinfo)
313 {
314  float8 retval;
315 
316  if (tinfo->f_dist == NULL)
317  elog(ERROR, "KNN search is not supported for btree_gist type %d",
318  (int) tinfo->t);
319  if (tinfo->f_le(query, key->lower, flinfo))
320  retval = tinfo->f_dist(query, key->lower, flinfo);
321  else if (tinfo->f_ge(query, key->upper, flinfo))
322  retval = tinfo->f_dist(query, key->upper, flinfo);
323  else
324  retval = 0.0;
325 
326  return retval;
327 }
328 
329 
332  const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
333 {
334  OffsetNumber i,
335  maxoff = entryvec->n - 1;
336  Nsrt *arr;
337  int nbytes;
338 
339  arr = (Nsrt *) palloc((maxoff + 1) * sizeof(Nsrt));
340  nbytes = (maxoff + 2) * sizeof(OffsetNumber);
341  v->spl_left = (OffsetNumber *) palloc(nbytes);
342  v->spl_right = (OffsetNumber *) palloc(nbytes);
343  v->spl_ldatum = PointerGetDatum(0);
344  v->spl_rdatum = PointerGetDatum(0);
345  v->spl_nleft = 0;
346  v->spl_nright = 0;
347 
348  /* Sort entries */
349 
350  for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
351  {
352  arr[i].t = (GBT_NUMKEY *) DatumGetPointer((entryvec->vector[i].key));
353  arr[i].i = i;
354  }
355  qsort_arg((void *) &arr[FirstOffsetNumber], maxoff - FirstOffsetNumber + 1, sizeof(Nsrt), (qsort_arg_comparator) tinfo->f_cmp, (void *) flinfo);
356 
357  /* We do simply create two parts */
358 
359  for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
360  {
361  if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
362  {
363  gbt_num_bin_union(&v->spl_ldatum, arr[i].t, tinfo, flinfo);
364  v->spl_left[v->spl_nleft] = arr[i].i;
365  v->spl_nleft++;
366  }
367  else
368  {
369  gbt_num_bin_union(&v->spl_rdatum, arr[i].t, tinfo, flinfo);
370  v->spl_right[v->spl_nright] = arr[i].i;
371  v->spl_nright++;
372  }
373  }
374 
375  return v;
376 }
Relation rel
Definition: gist.h:124
signed short int16
Definition: c.h:245
bool gbt_num_same(const GBT_NUMKEY *a, const GBT_NUMKEY *b, const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
Definition: fmgr.h:56
GBT_NUMKEY * t
#define DatumGetDateADT(X)
Definition: date.h:52
#define BTGreaterStrategyNumber
Definition: stratnum.h:33
const GBT_NUMKEY * lower
float8 gbt_num_distance(const GBT_NUMKEY_R *key, const void *query, bool is_leaf, const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
#define DatumGetInt32(X)
Definition: postgres.h:478
float8(* f_dist)(const void *, const void *, FmgrInfo *)
int32 DateADT
Definition: date.h:22
GISTENTRY * gbt_num_fetch(GISTENTRY *entry, const gbtree_ninfo *tinfo)
#define PointerGetDatum(X)
Definition: postgres.h:562
#define DatumGetObjectId(X)
Definition: postgres.h:506
OffsetNumber * spl_left
Definition: gist.h:105
Datum spl_rdatum
Definition: gist.h:112
#define Int16GetDatum(X)
Definition: postgres.h:457
int32 n
Definition: gist.h:160
struct cursor * cur
Definition: ecpg.c:28
uint16 StrategyNumber
Definition: stratnum.h:22
#define DateADTGetDatum(X)
Definition: date.h:56
bool(* f_ge)(const void *, const void *, FmgrInfo *)
const GBT_NUMKEY * upper
bool gbt_num_consistent(const GBT_NUMKEY_R *key, const void *query, const StrategyNumber *strategy, bool is_leaf, const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
int spl_nleft
Definition: gist.h:106
unsigned int Oid
Definition: postgres_ext.h:31
enum gbtree_type t
signed int int32
Definition: c.h:246
Datum Float8GetDatum(float8 X)
Definition: fmgr.c:1815
#define BTLessEqualStrategyNumber
Definition: stratnum.h:30
static struct pg_tm tm
Definition: localtime.c:111
uint16 OffsetNumber
Definition: off.h:24
Page page
Definition: gist.h:125
bool(* f_gt)(const void *, const void *, FmgrInfo *)
GISTENTRY * gbt_num_compress(GISTENTRY *entry, const gbtree_ninfo *tinfo)
GISTENTRY vector[FLEXIBLE_ARRAY_MEMBER]
Definition: gist.h:161
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
double float8
Definition: c.h:375
bool(* f_le)(const void *, const void *, FmgrInfo *)
#define FALSE
Definition: c.h:219
bool(* f_lt)(const void *, const void *, FmgrInfo *)
int spl_nright
Definition: gist.h:111
Datum Float4GetDatum(float4 X)
Definition: fmgr.c:1803
#define DatumGetInt64(X)
Definition: postgres.h:613
Datum key
Definition: gist.h:123
char * c
char GBT_NUMKEY
#define FirstOffsetNumber
Definition: off.h:27
#define DatumGetInt16(X)
Definition: postgres.h:450
int64 TimeADT
Definition: date.h:24
int(* f_cmp)(const void *, const void *, FmgrInfo *)
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1791
#define TimestampGetDatum(X)
Definition: timestamp.h:31
bool leafkey
Definition: gist.h:127
int64 Timestamp
Definition: timestamp.h:38
void qsort_arg(void *base, size_t nel, size_t elsize, qsort_arg_comparator cmp, void *arg)
Definition: qsort_arg.c:113
#define DatumGetTimeADT(X)
Definition: date.h:53
float float4
Definition: c.h:374
#define DatumGetCash(X)
Definition: cash.h:20
void * palloc0(Size size)
Definition: mcxt.c:877
#define DatumGetFloat8(X)
Definition: postgres.h:734
uintptr_t Datum
Definition: postgres.h:372
#define TimeADTGetDatum(X)
Definition: date.h:57
bool(* f_eq)(const void *, const void *, FmgrInfo *)
void gbt_num_bin_union(Datum *u, GBT_NUMKEY *e, const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
Datum spl_ldatum
Definition: gist.h:107
static const gbtree_vinfo tinfo
Definition: btree_bit.c:110
#define Assert(condition)
Definition: c.h:664
#define gistentryinit(e, k, r, pg, o, l)
Definition: gist.h:169
#define DatumGetFloat4(X)
Definition: postgres.h:686
#define OffsetNumberNext(offsetNumber)
Definition: off.h:53
#define BtreeGistNotEqualStrategyNumber
Definition: btree_gist.h:10
OffsetNumber * spl_right
Definition: gist.h:110
GIST_SPLITVEC * gbt_num_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v, const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
#define DatumGetPointer(X)
Definition: postgres.h:555
int64 Cash
Definition: cash.h:17
#define Int32GetDatum(X)
Definition: postgres.h:485
e
Definition: preproc-init.c:82
void * palloc(Size size)
Definition: mcxt.c:848
int i
int(* qsort_arg_comparator)(const void *a, const void *b, void *arg)
Definition: port.h:445
#define elog
Definition: elog.h:219
#define CashGetDatum(X)
Definition: cash.h:21
#define BTLessStrategyNumber
Definition: stratnum.h:29
OffsetNumber offset
Definition: gist.h:126
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define BTGreaterEqualStrategyNumber
Definition: stratnum.h:32
void * gbt_num_union(GBT_NUMKEY *out, const GistEntryVector *entryvec, const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
#define DatumGetTimestamp(X)
Definition: timestamp.h:27