PolarDB-for-PostgreSQL
342 строки · 8.3 Кб
1/*
2* contrib/btree_gist/btree_time.c
3*/
4#include "postgres.h"5
6#include "btree_gist.h"7#include "btree_utils_num.h"8#include "utils/builtins.h"9#include "utils/date.h"10#include "utils/timestamp.h"11
12typedef struct13{
14TimeADT lower;15TimeADT upper;16} timeKEY;17
18/*
19** time ops
20*/
21PG_FUNCTION_INFO_V1(gbt_time_compress);22PG_FUNCTION_INFO_V1(gbt_timetz_compress);23PG_FUNCTION_INFO_V1(gbt_time_fetch);24PG_FUNCTION_INFO_V1(gbt_time_union);25PG_FUNCTION_INFO_V1(gbt_time_picksplit);26PG_FUNCTION_INFO_V1(gbt_time_consistent);27PG_FUNCTION_INFO_V1(gbt_time_distance);28PG_FUNCTION_INFO_V1(gbt_timetz_consistent);29PG_FUNCTION_INFO_V1(gbt_time_penalty);30PG_FUNCTION_INFO_V1(gbt_time_same);31
32
33#ifdef USE_FLOAT8_BYVAL34#define TimeADTGetDatumFast(X) TimeADTGetDatum(X)35#else36#define TimeADTGetDatumFast(X) PointerGetDatum(&(X))37#endif38
39
40static bool41gbt_timegt(const void *a, const void *b, FmgrInfo *flinfo)42{
43const TimeADT *aa = (const TimeADT *) a;44const TimeADT *bb = (const TimeADT *) b;45
46return DatumGetBool(DirectFunctionCall2(time_gt,47TimeADTGetDatumFast(*aa),48TimeADTGetDatumFast(*bb)));49}
50
51static bool52gbt_timege(const void *a, const void *b, FmgrInfo *flinfo)53{
54const TimeADT *aa = (const TimeADT *) a;55const TimeADT *bb = (const TimeADT *) b;56
57return DatumGetBool(DirectFunctionCall2(time_ge,58TimeADTGetDatumFast(*aa),59TimeADTGetDatumFast(*bb)));60}
61
62static bool63gbt_timeeq(const void *a, const void *b, FmgrInfo *flinfo)64{
65const TimeADT *aa = (const TimeADT *) a;66const TimeADT *bb = (const TimeADT *) b;67
68return DatumGetBool(DirectFunctionCall2(time_eq,69TimeADTGetDatumFast(*aa),70TimeADTGetDatumFast(*bb)));71}
72
73static bool74gbt_timele(const void *a, const void *b, FmgrInfo *flinfo)75{
76const TimeADT *aa = (const TimeADT *) a;77const TimeADT *bb = (const TimeADT *) b;78
79return DatumGetBool(DirectFunctionCall2(time_le,80TimeADTGetDatumFast(*aa),81TimeADTGetDatumFast(*bb)));82}
83
84static bool85gbt_timelt(const void *a, const void *b, FmgrInfo *flinfo)86{
87const TimeADT *aa = (const TimeADT *) a;88const TimeADT *bb = (const TimeADT *) b;89
90return DatumGetBool(DirectFunctionCall2(time_lt,91TimeADTGetDatumFast(*aa),92TimeADTGetDatumFast(*bb)));93}
94
95
96
97static int98gbt_timekey_cmp(const void *a, const void *b, FmgrInfo *flinfo)99{
100timeKEY *ia = (timeKEY *) (((const Nsrt *) a)->t);101timeKEY *ib = (timeKEY *) (((const Nsrt *) b)->t);102int res;103
104res = DatumGetInt32(DirectFunctionCall2(time_cmp, TimeADTGetDatumFast(ia->lower), TimeADTGetDatumFast(ib->lower)));105if (res == 0)106return DatumGetInt32(DirectFunctionCall2(time_cmp, TimeADTGetDatumFast(ia->upper), TimeADTGetDatumFast(ib->upper)));107
108return res;109}
110
111static float8112gbt_time_dist(const void *a, const void *b, FmgrInfo *flinfo)113{
114const TimeADT *aa = (const TimeADT *) a;115const TimeADT *bb = (const TimeADT *) b;116Interval *i;117
118i = DatumGetIntervalP(DirectFunctionCall2(time_mi_time,119TimeADTGetDatumFast(*aa),120TimeADTGetDatumFast(*bb)));121return (float8) Abs(INTERVAL_TO_SEC(i));122}
123
124
125static const gbtree_ninfo tinfo =126{
127gbt_t_time,128sizeof(TimeADT),12916, /* sizeof(gbtreekey16) */130gbt_timegt,131gbt_timege,132gbt_timeeq,133gbt_timele,134gbt_timelt,135gbt_timekey_cmp,136gbt_time_dist
137};138
139
140PG_FUNCTION_INFO_V1(time_dist);141Datum
142time_dist(PG_FUNCTION_ARGS)143{
144Datum diff = DirectFunctionCall2(time_mi_time,145PG_GETARG_DATUM(0),146PG_GETARG_DATUM(1));147
148PG_RETURN_INTERVAL_P(abs_interval(DatumGetIntervalP(diff)));149}
150
151
152/**************************************************
153* time ops
154**************************************************/
155
156
157
158Datum
159gbt_time_compress(PG_FUNCTION_ARGS)160{
161GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);162
163PG_RETURN_POINTER(gbt_num_compress(entry, &tinfo));164}
165
166
167Datum
168gbt_timetz_compress(PG_FUNCTION_ARGS)169{
170GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);171GISTENTRY *retval;172
173if (entry->leafkey)174{175timeKEY *r = (timeKEY *) palloc(sizeof(timeKEY));176TimeTzADT *tz = DatumGetTimeTzADTP(entry->key);177TimeADT tmp;178
179retval = palloc(sizeof(GISTENTRY));180
181/* We are using the time + zone only to compress */182tmp = tz->time + (tz->zone * INT64CONST(1000000));183r->lower = r->upper = tmp;184gistentryinit(*retval, PointerGetDatum(r),185entry->rel, entry->page,186entry->offset, false);187}188else189retval = entry;190PG_RETURN_POINTER(retval);191}
192
193Datum
194gbt_time_fetch(PG_FUNCTION_ARGS)195{
196GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);197
198PG_RETURN_POINTER(gbt_num_fetch(entry, &tinfo));199}
200
201Datum
202gbt_time_consistent(PG_FUNCTION_ARGS)203{
204GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);205TimeADT query = PG_GETARG_TIMEADT(1);206StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);207
208/* Oid subtype = PG_GETARG_OID(3); */209bool *recheck = (bool *) PG_GETARG_POINTER(4);210timeKEY *kkk = (timeKEY *) DatumGetPointer(entry->key);211GBT_NUMKEY_R key;212
213/* All cases served by this function are exact */214*recheck = false;215
216key.lower = (GBT_NUMKEY *) &kkk->lower;217key.upper = (GBT_NUMKEY *) &kkk->upper;218
219PG_RETURN_BOOL(220gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)221);222}
223
224Datum
225gbt_time_distance(PG_FUNCTION_ARGS)226{
227GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);228TimeADT query = PG_GETARG_TIMEADT(1);229
230/* Oid subtype = PG_GETARG_OID(3); */231timeKEY *kkk = (timeKEY *) DatumGetPointer(entry->key);232GBT_NUMKEY_R key;233
234key.lower = (GBT_NUMKEY *) &kkk->lower;235key.upper = (GBT_NUMKEY *) &kkk->upper;236
237PG_RETURN_FLOAT8(238gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)239);240}
241
242Datum
243gbt_timetz_consistent(PG_FUNCTION_ARGS)244{
245GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);246TimeTzADT *query = PG_GETARG_TIMETZADT_P(1);247StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);248
249/* Oid subtype = PG_GETARG_OID(3); */250bool *recheck = (bool *) PG_GETARG_POINTER(4);251timeKEY *kkk = (timeKEY *) DatumGetPointer(entry->key);252TimeADT qqq;253GBT_NUMKEY_R key;254
255/* All cases served by this function are inexact */256*recheck = true;257
258qqq = query->time + (query->zone * INT64CONST(1000000));259
260key.lower = (GBT_NUMKEY *) &kkk->lower;261key.upper = (GBT_NUMKEY *) &kkk->upper;262
263PG_RETURN_BOOL(264gbt_num_consistent(&key, (void *) &qqq, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)265);266}
267
268
269Datum
270gbt_time_union(PG_FUNCTION_ARGS)271{
272GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);273void *out = palloc(sizeof(timeKEY));274
275*(int *) PG_GETARG_POINTER(1) = sizeof(timeKEY);276PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo));277}
278
279
280Datum
281gbt_time_penalty(PG_FUNCTION_ARGS)282{
283timeKEY *origentry = (timeKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);284timeKEY *newentry = (timeKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);285float *result = (float *) PG_GETARG_POINTER(2);286Interval *intr;287double res;288double res2;289
290intr = DatumGetIntervalP(DirectFunctionCall2(291time_mi_time,292TimeADTGetDatumFast(newentry->upper),293TimeADTGetDatumFast(origentry->upper)));294res = INTERVAL_TO_SEC(intr);295res = Max(res, 0);296
297intr = DatumGetIntervalP(DirectFunctionCall2(298time_mi_time,299TimeADTGetDatumFast(origentry->lower),300TimeADTGetDatumFast(newentry->lower)));301res2 = INTERVAL_TO_SEC(intr);302res2 = Max(res2, 0);303
304res += res2;305
306*result = 0.0;307
308if (res > 0)309{310intr = DatumGetIntervalP(DirectFunctionCall2(311time_mi_time,312TimeADTGetDatumFast(origentry->upper),313TimeADTGetDatumFast(origentry->lower)));314*result += FLT_MIN;315*result += (float) (res / (res + INTERVAL_TO_SEC(intr)));316*result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1));317}318
319PG_RETURN_POINTER(result);320}
321
322
323Datum
324gbt_time_picksplit(PG_FUNCTION_ARGS)325{
326PG_RETURN_POINTER(gbt_num_picksplit(327(GistEntryVector *) PG_GETARG_POINTER(0),328(GIST_SPLITVEC *) PG_GETARG_POINTER(1),329&tinfo, fcinfo->flinfo330));331}
332
333Datum
334gbt_time_same(PG_FUNCTION_ARGS)335{
336timeKEY *b1 = (timeKEY *) PG_GETARG_POINTER(0);337timeKEY *b2 = (timeKEY *) PG_GETARG_POINTER(1);338bool *result = (bool *) PG_GETARG_POINTER(2);339
340*result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);341PG_RETURN_POINTER(result);342}
343