2 * contrib/btree_gist/btree_utils_num.c
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"
14 gbt_num_compress(GISTENTRY
*entry
, const gbtree_ninfo
*tinfo
)
33 GBT_NUMKEY
*r
= (GBT_NUMKEY
*) palloc0(tinfo
->indexsize
);
39 v
.i2
= DatumGetInt16(entry
->key
);
43 v
.i4
= DatumGetInt32(entry
->key
);
47 v
.i8
= DatumGetInt64(entry
->key
);
52 v
.i4
= DatumGetObjectId(entry
->key
);
56 v
.f4
= DatumGetFloat4(entry
->key
);
60 v
.f8
= DatumGetFloat8(entry
->key
);
64 v
.dt
= DatumGetDateADT(entry
->key
);
68 v
.tm
= DatumGetTimeADT(entry
->key
);
72 v
.ts
= DatumGetTimestamp(entry
->key
);
76 v
.ch
= DatumGetCash(entry
->key
);
80 leaf
= DatumGetPointer(entry
->key
);
83 Assert(tinfo
->indexsize
>= 2 * tinfo
->size
);
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);
98 * Convert a compressed leaf item back to the original type, for index-only
102 gbt_num_fetch(GISTENTRY
*entry
, const gbtree_ninfo
*tinfo
)
107 Assert(tinfo
->indexsize
>= 2 * tinfo
->size
);
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
117 datum
= Int16GetDatum(*(int16
*) entry
->key
);
120 datum
= Int32GetDatum(*(int32
*) entry
->key
);
123 datum
= Int64GetDatum(*(int64
*) entry
->key
);
127 datum
= ObjectIdGetDatum(*(Oid
*) entry
->key
);
130 datum
= Float4GetDatum(*(float4
*) entry
->key
);
133 datum
= Float8GetDatum(*(float8
*) entry
->key
);
136 datum
= DateADTGetDatum(*(DateADT
*) entry
->key
);
139 datum
= TimeADTGetDatum(*(TimeADT
*) entry
->key
);
142 datum
= TimestampGetDatum(*(Timestamp
*) entry
->key
);
145 datum
= CashGetDatum(*(Cash
*) entry
->key
);
148 datum
= PointerGetDatum(entry
->key
);
151 retval
= palloc(sizeof(GISTENTRY
));
152 gistentryinit(*retval
, datum
, entry
->rel
, entry
->page
, entry
->offset
,
160 ** The GiST union method for numerical values
164 gbt_num_union(GBT_NUMKEY
*out
, const GistEntryVector
*entryvec
, const gbtree_ninfo
*tinfo
, FmgrInfo
*flinfo
)
172 numranges
= entryvec
->n
;
173 cur
= (GBT_NUMKEY
*) DatumGetPointer((entryvec
->vector
[0].key
));
176 o
.lower
= &((GBT_NUMKEY
*) out
)[0];
177 o
.upper
= &((GBT_NUMKEY
*) out
)[tinfo
->size
];
179 memcpy((void *) out
, (void *) cur
, 2 * tinfo
->size
);
181 for (i
= 1; i
< numranges
; i
++)
183 cur
= (GBT_NUMKEY
*) DatumGetPointer((entryvec
->vector
[i
].key
));
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(unconstify(GBT_NUMKEY
*, o
.lower
), 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(unconstify(GBT_NUMKEY
*, o
.upper
), c
.upper
, tinfo
->size
);
200 ** The GiST same method for numerical values
204 gbt_num_same(const GBT_NUMKEY
*a
, const GBT_NUMKEY
*b
, const gbtree_ninfo
*tinfo
, FmgrInfo
*flinfo
)
210 b1
.upper
= &(a
[tinfo
->size
]);
212 b2
.upper
= &(b
[tinfo
->size
]);
214 return (tinfo
->f_eq(b1
.lower
, b2
.lower
, flinfo
) &&
215 tinfo
->f_eq(b1
.upper
, b2
.upper
, flinfo
));
220 gbt_num_bin_union(Datum
*u
, GBT_NUMKEY
*e
, const gbtree_ninfo
*tinfo
, FmgrInfo
*flinfo
)
225 rd
.upper
= &e
[tinfo
->size
];
227 if (!DatumGetPointer(*u
))
229 *u
= PointerGetDatum(palloc0(tinfo
->indexsize
));
230 memcpy(&(((GBT_NUMKEY
*) DatumGetPointer(*u
))[0]), rd
.lower
, tinfo
->size
);
231 memcpy(&(((GBT_NUMKEY
*) DatumGetPointer(*u
))[tinfo
->size
]), rd
.upper
, tinfo
->size
);
237 ur
.lower
= &(((GBT_NUMKEY
*) DatumGetPointer(*u
))[0]);
238 ur
.upper
= &(((GBT_NUMKEY
*) DatumGetPointer(*u
))[tinfo
->size
]);
239 if (tinfo
->f_gt(ur
.lower
, rd
.lower
, flinfo
))
240 memcpy(unconstify(GBT_NUMKEY
*, ur
.lower
), rd
.lower
, tinfo
->size
);
241 if (tinfo
->f_lt(ur
.upper
, rd
.upper
, flinfo
))
242 memcpy(unconstify(GBT_NUMKEY
*, ur
.upper
), rd
.upper
, tinfo
->size
);
249 * The GiST consistent method
251 * Note: we currently assume that no datatypes that use this routine are
252 * collation-aware; so we don't bother passing collation through.
255 gbt_num_consistent(const GBT_NUMKEY_R
*key
,
257 const StrategyNumber
*strategy
,
259 const gbtree_ninfo
*tinfo
,
266 case BTLessEqualStrategyNumber
:
267 retval
= tinfo
->f_ge(query
, key
->lower
, flinfo
);
269 case BTLessStrategyNumber
:
271 retval
= tinfo
->f_gt(query
, key
->lower
, flinfo
);
273 retval
= tinfo
->f_ge(query
, key
->lower
, flinfo
);
275 case BTEqualStrategyNumber
:
277 retval
= tinfo
->f_eq(query
, key
->lower
, flinfo
);
279 retval
= (tinfo
->f_le(key
->lower
, query
, flinfo
) &&
280 tinfo
->f_le(query
, key
->upper
, flinfo
));
282 case BTGreaterStrategyNumber
:
284 retval
= tinfo
->f_lt(query
, key
->upper
, flinfo
);
286 retval
= tinfo
->f_le(query
, key
->upper
, flinfo
);
288 case BTGreaterEqualStrategyNumber
:
289 retval
= tinfo
->f_le(query
, key
->upper
, flinfo
);
291 case BtreeGistNotEqualStrategyNumber
:
292 retval
= (!(tinfo
->f_eq(query
, key
->lower
, flinfo
) &&
293 tinfo
->f_eq(query
, key
->upper
, flinfo
)));
304 ** The GiST distance method (for KNN-Gist)
308 gbt_num_distance(const GBT_NUMKEY_R
*key
,
311 const gbtree_ninfo
*tinfo
,
316 if (tinfo
->f_dist
== NULL
)
317 elog(ERROR
, "KNN search is not supported for btree_gist type %d",
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
);
331 gbt_num_picksplit(const GistEntryVector
*entryvec
, GIST_SPLITVEC
*v
,
332 const gbtree_ninfo
*tinfo
, FmgrInfo
*flinfo
)
335 maxoff
= entryvec
->n
- 1;
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);
350 for (i
= FirstOffsetNumber
; i
<= maxoff
; i
= OffsetNumberNext(i
))
352 arr
[i
].t
= (GBT_NUMKEY
*) DatumGetPointer((entryvec
->vector
[i
].key
));
355 qsort_arg((void *) &arr
[FirstOffsetNumber
], maxoff
- FirstOffsetNumber
+ 1, sizeof(Nsrt
), (qsort_arg_comparator
) tinfo
->f_cmp
, (void *) flinfo
);
357 /* We do simply create two parts */
359 for (i
= FirstOffsetNumber
; i
<= maxoff
; i
= OffsetNumberNext(i
))
361 if (i
<= (maxoff
- FirstOffsetNumber
+ 1) / 2)
363 gbt_num_bin_union(&v
->spl_ldatum
, arr
[i
].t
, tinfo
, flinfo
);
364 v
->spl_left
[v
->spl_nleft
] = arr
[i
].i
;
369 gbt_num_bin_union(&v
->spl_rdatum
, arr
[i
].t
, tinfo
, flinfo
);
370 v
->spl_right
[v
->spl_nright
] = arr
[i
].i
;