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 ((*tinfo->f_gt) (o.lower, c.lower, flinfo)) /* out->lower > cur->lower */
187  memcpy((void *) o.lower, (void *) c.lower, tinfo->size);
188  if ((*tinfo->f_lt) (o.upper, c.upper, flinfo)) /* out->upper < cur->upper */
189  memcpy((void *) o.upper, (void *) c.upper, tinfo->size);
190  }
191 
192  return out;
193 }
194 
195 
196 
197 /*
198 ** The GiST same method for numerical values
199 */
200 
201 bool
202 gbt_num_same(const GBT_NUMKEY *a, const GBT_NUMKEY *b, const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
203 {
204  GBT_NUMKEY_R b1,
205  b2;
206 
207  b1.lower = &(((GBT_NUMKEY *) a)[0]);
208  b1.upper = &(((GBT_NUMKEY *) a)[tinfo->size]);
209  b2.lower = &(((GBT_NUMKEY *) b)[0]);
210  b2.upper = &(((GBT_NUMKEY *) b)[tinfo->size]);
211 
212  return ((*tinfo->f_eq) (b1.lower, b2.lower, flinfo) &&
213  (*tinfo->f_eq) (b1.upper, b2.upper, flinfo));
214 }
215 
216 
217 void
219 {
220  GBT_NUMKEY_R rd;
221 
222  rd.lower = &e[0];
223  rd.upper = &e[tinfo->size];
224 
225  if (!DatumGetPointer(*u))
226  {
227  *u = PointerGetDatum(palloc0(tinfo->indexsize));
228  memcpy((void *) &(((GBT_NUMKEY *) DatumGetPointer(*u))[0]), (void *) rd.lower, tinfo->size);
229  memcpy((void *) &(((GBT_NUMKEY *) DatumGetPointer(*u))[tinfo->size]), (void *) rd.upper, tinfo->size);
230  }
231  else
232  {
233  GBT_NUMKEY_R ur;
234 
235  ur.lower = &(((GBT_NUMKEY *) DatumGetPointer(*u))[0]);
236  ur.upper = &(((GBT_NUMKEY *) DatumGetPointer(*u))[tinfo->size]);
237  if ((*tinfo->f_gt) ((void *) ur.lower, (void *) rd.lower, flinfo))
238  memcpy((void *) ur.lower, (void *) rd.lower, tinfo->size);
239  if ((*tinfo->f_lt) ((void *) ur.upper, (void *) rd.upper, flinfo))
240  memcpy((void *) ur.upper, (void *) rd.upper, tinfo->size);
241  }
242 }
243 
244 
245 
246 /*
247  * The GiST consistent method
248  *
249  * Note: we currently assume that no datatypes that use this routine are
250  * collation-aware; so we don't bother passing collation through.
251  */
252 bool
254  const void *query,
255  const StrategyNumber *strategy,
256  bool is_leaf,
257  const gbtree_ninfo *tinfo,
258  FmgrInfo *flinfo)
259 {
260  bool retval;
261 
262  switch (*strategy)
263  {
265  retval = (*tinfo->f_ge) (query, key->lower, flinfo);
266  break;
268  if (is_leaf)
269  retval = (*tinfo->f_gt) (query, key->lower, flinfo);
270  else
271  retval = (*tinfo->f_ge) (query, key->lower, flinfo);
272  break;
274  if (is_leaf)
275  retval = (*tinfo->f_eq) (query, key->lower, flinfo);
276  else
277  retval = ((*tinfo->f_le) (key->lower, query, flinfo) && (*tinfo->f_le) (query, key->upper, flinfo)) ? true : false;
278  break;
280  if (is_leaf)
281  retval = (*tinfo->f_lt) (query, key->upper, flinfo);
282  else
283  retval = (*tinfo->f_le) (query, key->upper, flinfo);
284  break;
286  retval = (*tinfo->f_le) (query, key->upper, flinfo);
287  break;
289  retval = (!((*tinfo->f_eq) (query, key->lower, flinfo) &&
290  (*tinfo->f_eq) (query, key->upper, flinfo))) ? true : false;
291  break;
292  default:
293  retval = false;
294  }
295 
296  return (retval);
297 }
298 
299 
300 /*
301 ** The GiST distance method (for KNN-Gist)
302 */
303 
304 float8
306  const void *query,
307  bool is_leaf,
308  const gbtree_ninfo *tinfo,
309  FmgrInfo *flinfo)
310 {
311  float8 retval;
312 
313  if (tinfo->f_dist == NULL)
314  elog(ERROR, "KNN search is not supported for btree_gist type %d",
315  (int) tinfo->t);
316  if (tinfo->f_le(query, key->lower, flinfo))
317  retval = tinfo->f_dist(query, key->lower, flinfo);
318  else if (tinfo->f_ge(query, key->upper, flinfo))
319  retval = tinfo->f_dist(query, key->upper, flinfo);
320  else
321  retval = 0.0;
322 
323  return retval;
324 }
325 
326 
329  const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
330 {
331  OffsetNumber i,
332  maxoff = entryvec->n - 1;
333  Nsrt *arr;
334  int nbytes;
335 
336  arr = (Nsrt *) palloc((maxoff + 1) * sizeof(Nsrt));
337  nbytes = (maxoff + 2) * sizeof(OffsetNumber);
338  v->spl_left = (OffsetNumber *) palloc(nbytes);
339  v->spl_right = (OffsetNumber *) palloc(nbytes);
340  v->spl_ldatum = PointerGetDatum(0);
341  v->spl_rdatum = PointerGetDatum(0);
342  v->spl_nleft = 0;
343  v->spl_nright = 0;
344 
345  /* Sort entries */
346 
347  for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
348  {
349  arr[i].t = (GBT_NUMKEY *) DatumGetPointer((entryvec->vector[i].key));
350  arr[i].i = i;
351  }
352  qsort_arg((void *) &arr[FirstOffsetNumber], maxoff - FirstOffsetNumber + 1, sizeof(Nsrt), (qsort_arg_comparator) tinfo->f_cmp, (void *) flinfo);
353 
354  /* We do simply create two parts */
355 
356  for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
357  {
358  if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
359  {
360  gbt_num_bin_union(&v->spl_ldatum, arr[i].t, tinfo, flinfo);
361  v->spl_left[v->spl_nleft] = arr[i].i;
362  v->spl_nleft++;
363  }
364  else
365  {
366  gbt_num_bin_union(&v->spl_rdatum, arr[i].t, tinfo, flinfo);
367  v->spl_right[v->spl_nright] = arr[i].i;
368  v->spl_nright++;
369  }
370  }
371 
372  return v;
373 }
Relation rel
Definition: gist.h:124
signed short int16
Definition: c.h:255
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:256
Datum Float8GetDatum(float8 X)
Definition: fmgr.c:1815
#define BTLessEqualStrategyNumber
Definition: stratnum.h:30
static struct pg_tm tm
Definition: localtime.c:103
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:381
bool(* f_le)(const void *, const void *, FmgrInfo *)
#define FALSE
Definition: c.h:221
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:380
#define DatumGetCash(X)
Definition: cash.h:20
void * palloc0(Size size)
Definition: mcxt.c:878
#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
#define NULL
Definition: c.h:229
static const gbtree_vinfo tinfo
Definition: btree_bit.c:110
#define Assert(condition)
Definition: c.h:675
#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:849
int i
int(* qsort_arg_comparator)(const void *a, const void *b, void *arg)
Definition: port.h:442
#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