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
)
34 GBT_NUMKEY
*r
= (GBT_NUMKEY
*) palloc0(tinfo
->indexsize
);
40 v
.bo
= DatumGetBool(entry
->key
);
44 v
.i2
= DatumGetInt16(entry
->key
);
48 v
.i4
= DatumGetInt32(entry
->key
);
52 v
.i8
= DatumGetInt64(entry
->key
);
57 v
.i4
= DatumGetObjectId(entry
->key
);
61 v
.f4
= DatumGetFloat4(entry
->key
);
65 v
.f8
= DatumGetFloat8(entry
->key
);
69 v
.dt
= DatumGetDateADT(entry
->key
);
73 v
.tm
= DatumGetTimeADT(entry
->key
);
77 v
.ts
= DatumGetTimestamp(entry
->key
);
81 v
.ch
= DatumGetCash(entry
->key
);
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);
103 * Convert a compressed leaf item back to the original type, for index-only
107 gbt_num_fetch(GISTENTRY
*entry
, const gbtree_ninfo
*tinfo
)
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
122 datum
= BoolGetDatum(*(bool *) entry
->key
);
125 datum
= Int16GetDatum(*(int16
*) entry
->key
);
128 datum
= Int32GetDatum(*(int32
*) entry
->key
);
131 datum
= Int64GetDatum(*(int64
*) entry
->key
);
135 datum
= ObjectIdGetDatum(*(Oid
*) entry
->key
);
138 datum
= Float4GetDatum(*(float4
*) entry
->key
);
141 datum
= Float8GetDatum(*(float8
*) entry
->key
);
144 datum
= DateADTGetDatum(*(DateADT
*) entry
->key
);
147 datum
= TimeADTGetDatum(*(TimeADT
*) entry
->key
);
150 datum
= TimestampGetDatum(*(Timestamp
*) entry
->key
);
153 datum
= CashGetDatum(*(Cash
*) entry
->key
);
159 retval
= palloc(sizeof(GISTENTRY
));
160 gistentryinit(*retval
, datum
, entry
->rel
, entry
->page
, entry
->offset
,
168 ** The GiST union method for numerical values
172 gbt_num_union(GBT_NUMKEY
*out
, const GistEntryVector
*entryvec
, const gbtree_ninfo
*tinfo
, FmgrInfo
*flinfo
)
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
));
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
);
208 ** The GiST same method for numerical values
212 gbt_num_same(const GBT_NUMKEY
*a
, const GBT_NUMKEY
*b
, const gbtree_ninfo
*tinfo
, FmgrInfo
*flinfo
)
218 b1
.upper
= &(a
[tinfo
->size
]);
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
));
228 gbt_num_bin_union(Datum
*u
, GBT_NUMKEY
*e
, const gbtree_ninfo
*tinfo
, FmgrInfo
*flinfo
)
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
);
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.
263 gbt_num_consistent(const GBT_NUMKEY_R
*key
,
265 const StrategyNumber
*strategy
,
267 const gbtree_ninfo
*tinfo
,
274 case BTLessEqualStrategyNumber
:
275 retval
= tinfo
->f_ge(query
, key
->lower
, flinfo
);
277 case BTLessStrategyNumber
:
279 retval
= tinfo
->f_gt(query
, key
->lower
, flinfo
);
281 retval
= tinfo
->f_ge(query
, key
->lower
, flinfo
);
283 case BTEqualStrategyNumber
:
285 retval
= tinfo
->f_eq(query
, key
->lower
, flinfo
);
287 retval
= (tinfo
->f_le(key
->lower
, query
, flinfo
) &&
288 tinfo
->f_le(query
, key
->upper
, flinfo
));
290 case BTGreaterStrategyNumber
:
292 retval
= tinfo
->f_lt(query
, key
->upper
, flinfo
);
294 retval
= tinfo
->f_le(query
, key
->upper
, flinfo
);
296 case BTGreaterEqualStrategyNumber
:
297 retval
= tinfo
->f_le(query
, key
->upper
, flinfo
);
299 case BtreeGistNotEqualStrategyNumber
:
300 retval
= (!(tinfo
->f_eq(query
, key
->lower
, flinfo
) &&
301 tinfo
->f_eq(query
, key
->upper
, flinfo
)));
312 ** The GiST distance method (for KNN-Gist)
316 gbt_num_distance(const GBT_NUMKEY_R
*key
,
319 const gbtree_ninfo
*tinfo
,
324 if (tinfo
->f_dist
== NULL
)
325 elog(ERROR
, "KNN search is not supported for btree_gist type %d",
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
);
339 gbt_num_picksplit(const GistEntryVector
*entryvec
, GIST_SPLITVEC
*v
,
340 const gbtree_ninfo
*tinfo
, FmgrInfo
*flinfo
)
343 maxoff
= entryvec
->n
- 1;
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);
358 for (i
= FirstOffsetNumber
; i
<= maxoff
; i
= OffsetNumberNext(i
))
360 arr
[i
].t
= (GBT_NUMKEY
*) DatumGetPointer((entryvec
->vector
[i
].key
));
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
;
377 gbt_num_bin_union(&v
->spl_rdatum
, arr
[i
].t
, tinfo
, flinfo
);
378 v
->spl_right
[v
->spl_nright
] = arr
[i
].i
;