PostgreSQL Source Code  git master
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  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 
34  GBT_NUMKEY *r = (GBT_NUMKEY *) palloc0(tinfo->indexsize);
35  void *leaf = NULL;
36 
37  switch (tinfo->t)
38  {
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);
86  }
87 
88  Assert(tinfo->indexsize >= 2 * tinfo->size);
89 
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);
95  }
96  else
97  retval = entry;
98 
99  return retval;
100 }
101 
102 /*
103  * Convert a compressed leaf item back to the original type, for index-only
104  * scans.
105  */
106 GISTENTRY *
108 {
109  GISTENTRY *retval;
110  Datum datum;
111 
112  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  switch (tinfo->t)
120  {
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;
157  }
158 
159  retval = palloc(sizeof(GISTENTRY));
160  gistentryinit(*retval, datum, entry->rel, entry->page, entry->offset,
161  false);
162  return retval;
163 }
164 
165 
166 
167 /*
168 ** The GiST union method for numerical values
169 */
170 
171 void *
172 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 
180  numranges = entryvec->n;
181  cur = (GBT_NUMKEY *) DatumGetPointer((entryvec->vector[0].key));
182 
183 
184  o.lower = &((GBT_NUMKEY *) out)[0];
185  o.upper = &((GBT_NUMKEY *) out)[tinfo->size];
186 
187  memcpy(out, cur, 2 * tinfo->size);
188 
189  for (i = 1; i < numranges; i++)
190  {
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);
200  }
201 
202  return out;
203 }
204 
205 
206 
207 /*
208 ** The GiST same method for numerical values
209 */
210 
211 bool
212 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 
217  b1.lower = &(a[0]);
218  b1.upper = &(a[tinfo->size]);
219  b2.lower = &(b[0]);
220  b2.upper = &(b[tinfo->size]);
221 
222  return (tinfo->f_eq(b1.lower, b2.lower, flinfo) &&
223  tinfo->f_eq(b1.upper, b2.upper, flinfo));
224 }
225 
226 
227 void
229 {
230  GBT_NUMKEY_R rd;
231 
232  rd.lower = &e[0];
233  rd.upper = &e[tinfo->size];
234 
235  if (!DatumGetPointer(*u))
236  {
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);
240  }
241  else
242  {
243  GBT_NUMKEY_R ur;
244 
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);
251  }
252 }
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
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 
272  switch (*strategy)
273  {
275  retval = tinfo->f_ge(query, key->lower, flinfo);
276  break;
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;
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;
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;
297  retval = tinfo->f_le(query, key->upper, flinfo);
298  break;
300  retval = (!(tinfo->f_eq(query, key->lower, flinfo) &&
301  tinfo->f_eq(query, key->upper, flinfo)));
302  break;
303  default:
304  retval = false;
305  }
306 
307  return retval;
308 }
309 
310 
311 /*
312 ** The GiST distance method (for KNN-Gist)
313 */
314 
315 float8
317  const void *query,
318  bool is_leaf,
319  const gbtree_ninfo *tinfo,
320  FmgrInfo *flinfo)
321 {
322  float8 retval;
323 
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;
333 
334  return retval;
335 }
336 
337 
340  const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
341 {
342  OffsetNumber i,
343  maxoff = entryvec->n - 1;
344  Nsrt *arr;
345  int nbytes;
346 
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;
355 
356  /* Sort entries */
357 
358  for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
359  {
360  arr[i].t = (GBT_NUMKEY *) DatumGetPointer((entryvec->vector[i].key));
361  arr[i].i = i;
362  }
363  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 
367  for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
368  {
369  if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
370  {
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++;
374  }
375  else
376  {
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++;
380  }
381  }
382 
383  return v;
384 }
static const gbtree_vinfo tinfo
Definition: btree_bit.c:109
#define BtreeGistNotEqualStrategyNumber
Definition: btree_gist.h:10
@ gbt_t_enum
Definition: btree_gist.h:38
@ gbt_t_int4
Definition: btree_gist.h:18
@ gbt_t_cash
Definition: btree_gist.h:24
@ gbt_t_float8
Definition: btree_gist.h:21
@ gbt_t_date
Definition: btree_gist.h:27
@ gbt_t_float4
Definition: btree_gist.h:20
@ gbt_t_oid
Definition: btree_gist.h:25
@ gbt_t_bool
Definition: btree_gist.h:35
@ gbt_t_time
Definition: btree_gist.h:26
@ gbt_t_int8
Definition: btree_gist.h:19
@ gbt_t_int2
Definition: btree_gist.h:17
@ gbt_t_ts
Definition: btree_gist.h:23
void gbt_num_bin_union(Datum *u, GBT_NUMKEY *e, const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
float8 gbt_num_distance(const GBT_NUMKEY_R *key, const void *query, bool is_leaf, const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
GISTENTRY * gbt_num_fetch(GISTENTRY *entry, const gbtree_ninfo *tinfo)
bool gbt_num_consistent(const GBT_NUMKEY_R *key, const void *query, const StrategyNumber *strategy, bool is_leaf, const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
bool gbt_num_same(const GBT_NUMKEY *a, const GBT_NUMKEY *b, const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
GISTENTRY * gbt_num_compress(GISTENTRY *entry, const gbtree_ninfo *tinfo)
void * gbt_num_union(GBT_NUMKEY *out, const GistEntryVector *entryvec, const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
GIST_SPLITVEC * gbt_num_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v, const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
char GBT_NUMKEY
#define unconstify(underlying_type, expr)
Definition: c.h:1245
signed short int16
Definition: c.h:493
signed int int32
Definition: c.h:494
#define Assert(condition)
Definition: c.h:858
double float8
Definition: c.h:630
float float4
Definition: c.h:629
static Cash DatumGetCash(Datum X)
Definition: cash.h:21
static Datum CashGetDatum(Cash X)
Definition: cash.h:27
int64 Cash
Definition: cash.h:17
int64 Timestamp
Definition: timestamp.h:38
static Datum DateADTGetDatum(DateADT X)
Definition: date.h:72
int32 DateADT
Definition: date.h:23
static DateADT DatumGetDateADT(Datum X)
Definition: date.h:54
static TimeADT DatumGetTimeADT(Datum X)
Definition: date.h:60
int64 TimeADT
Definition: date.h:25
static Datum TimeADTGetDatum(TimeADT X)
Definition: date.h:78
struct cursor * cur
Definition: ecpg.c:28
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1807
Datum Float8GetDatum(float8 X)
Definition: fmgr.c:1816
#define gistentryinit(e, k, r, pg, o, l)
Definition: gist.h:244
int b
Definition: isn.c:70
int a
Definition: isn.c:69
int i
Definition: isn.c:73
static struct pg_tm tm
Definition: localtime.c:104
void * palloc0(Size size)
Definition: mcxt.c:1346
void * palloc(Size size)
Definition: mcxt.c:1316
#define OffsetNumberNext(offsetNumber)
Definition: off.h:52
uint16 OffsetNumber
Definition: off.h:24
#define FirstOffsetNumber
Definition: off.h:27
int(* qsort_arg_comparator)(const void *a, const void *b, void *arg)
Definition: port.h:451
void qsort_arg(void *base, size_t nel, size_t elsize, qsort_arg_comparator cmp, void *arg)
static bool DatumGetBool(Datum X)
Definition: postgres.h:90
static int64 DatumGetInt64(Datum X)
Definition: postgres.h:385
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
static Datum Float4GetDatum(float4 X)
Definition: postgres.h:475
uintptr_t Datum
Definition: postgres.h:64
static float4 DatumGetFloat4(Datum X)
Definition: postgres.h:458
static Oid DatumGetObjectId(Datum X)
Definition: postgres.h:242
static Datum Int16GetDatum(int16 X)
Definition: postgres.h:172
static Datum BoolGetDatum(bool X)
Definition: postgres.h:102
static float8 DatumGetFloat8(Datum X)
Definition: postgres.h:494
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212
static int16 DatumGetInt16(Datum X)
Definition: postgres.h:162
static int32 DatumGetInt32(Datum X)
Definition: postgres.h:202
unsigned int Oid
Definition: postgres_ext.h:31
char * c
e
Definition: preproc-init.c:82
uint16 StrategyNumber
Definition: stratnum.h:22
#define BTGreaterStrategyNumber
Definition: stratnum.h:33
#define BTLessStrategyNumber
Definition: stratnum.h:29
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define BTLessEqualStrategyNumber
Definition: stratnum.h:30
#define BTGreaterEqualStrategyNumber
Definition: stratnum.h:32
Definition: fmgr.h:57
const GBT_NUMKEY * upper
const GBT_NUMKEY * lower
OffsetNumber offset
Definition: gist.h:163
Datum key
Definition: gist.h:160
Page page
Definition: gist.h:162
Relation rel
Definition: gist.h:161
bool leafkey
Definition: gist.h:164
int spl_nleft
Definition: gist.h:143
OffsetNumber * spl_right
Definition: gist.h:147
Datum spl_ldatum
Definition: gist.h:144
Datum spl_rdatum
Definition: gist.h:149
int spl_nright
Definition: gist.h:148
OffsetNumber * spl_left
Definition: gist.h:142
GISTENTRY vector[FLEXIBLE_ARRAY_MEMBER]
Definition: gist.h:236
int32 n
Definition: gist.h:235
GBT_NUMKEY * t
int32(* f_cmp)(const void *, const void *, Oid, FmgrInfo *)
enum gbtree_type t
bool(* f_lt)(const void *, const void *, Oid, FmgrInfo *)
bool(* f_eq)(const void *, const void *, Oid, FmgrInfo *)
bool(* f_gt)(const void *, const void *, Oid, FmgrInfo *)
bool(* f_ge)(const void *, const void *, Oid, FmgrInfo *)
bool(* f_le)(const void *, const void *, Oid, FmgrInfo *)
static Datum TimestampGetDatum(Timestamp X)
Definition: timestamp.h:46
static Timestamp DatumGetTimestamp(Datum X)
Definition: timestamp.h:28