Age Owner Branch data TLA Line data Source code
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/fmgrprotos.h"
9 : : #include "utils/date.h"
10 : : #include "utils/rel.h"
11 : : #include "utils/sortsupport.h"
12 : : #include "utils/timestamp.h"
13 : :
14 : : typedef struct
15 : : {
16 : : TimeADT lower;
17 : : TimeADT upper;
18 : : } timeKEY;
19 : :
20 : : /* GiST support functions */
7961 teodor@sigaev.ru 21 :CBC 4 : PG_FUNCTION_INFO_V1(gbt_time_compress);
22 : 4 : PG_FUNCTION_INFO_V1(gbt_timetz_compress);
4006 heikki.linnakangas@i 23 : 4 : PG_FUNCTION_INFO_V1(gbt_time_fetch);
7961 teodor@sigaev.ru 24 : 5 : PG_FUNCTION_INFO_V1(gbt_time_union);
25 : 5 : PG_FUNCTION_INFO_V1(gbt_time_picksplit);
26 : 4 : PG_FUNCTION_INFO_V1(gbt_time_consistent);
5492 tgl@sss.pgh.pa.us 27 : 4 : PG_FUNCTION_INFO_V1(gbt_time_distance);
7961 teodor@sigaev.ru 28 : 4 : PG_FUNCTION_INFO_V1(gbt_timetz_consistent);
29 : 5 : PG_FUNCTION_INFO_V1(gbt_time_penalty);
30 : 5 : PG_FUNCTION_INFO_V1(gbt_time_same);
346 heikki.linnakangas@i 31 : 5 : PG_FUNCTION_INFO_V1(gbt_time_sortsupport);
346 heikki.linnakangas@i 32 :UBC 0 : PG_FUNCTION_INFO_V1(gbt_timetz_sortsupport);
33 : :
34 : :
35 : : static bool
3281 andrew@dunslane.net 36 :CBC 3211 : gbt_timegt(const void *a, const void *b, FmgrInfo *flinfo)
37 : : {
6537 tgl@sss.pgh.pa.us 38 : 3211 : const TimeADT *aa = (const TimeADT *) a;
39 : 3211 : const TimeADT *bb = (const TimeADT *) b;
40 : :
41 : 3211 : return DatumGetBool(DirectFunctionCall2(time_gt,
42 : : TimeADTGetDatum(*aa),
43 : : TimeADTGetDatum(*bb)));
44 : : }
45 : :
46 : : static bool
3281 andrew@dunslane.net 47 : 1335 : gbt_timege(const void *a, const void *b, FmgrInfo *flinfo)
48 : : {
6537 tgl@sss.pgh.pa.us 49 : 1335 : const TimeADT *aa = (const TimeADT *) a;
50 : 1335 : const TimeADT *bb = (const TimeADT *) b;
51 : :
52 : 1335 : return DatumGetBool(DirectFunctionCall2(time_ge,
53 : : TimeADTGetDatum(*aa),
54 : : TimeADTGetDatum(*bb)));
55 : : }
56 : :
57 : : static bool
3281 andrew@dunslane.net 58 : 1067 : gbt_timeeq(const void *a, const void *b, FmgrInfo *flinfo)
59 : : {
6537 tgl@sss.pgh.pa.us 60 : 1067 : const TimeADT *aa = (const TimeADT *) a;
61 : 1067 : const TimeADT *bb = (const TimeADT *) b;
62 : :
63 : 1067 : return DatumGetBool(DirectFunctionCall2(time_eq,
64 : : TimeADTGetDatum(*aa),
65 : : TimeADTGetDatum(*bb)));
66 : : }
67 : :
68 : : static bool
3281 andrew@dunslane.net 69 : 2439 : gbt_timele(const void *a, const void *b, FmgrInfo *flinfo)
70 : : {
6537 tgl@sss.pgh.pa.us 71 : 2439 : const TimeADT *aa = (const TimeADT *) a;
72 : 2439 : const TimeADT *bb = (const TimeADT *) b;
73 : :
74 : 2439 : return DatumGetBool(DirectFunctionCall2(time_le,
75 : : TimeADTGetDatum(*aa),
76 : : TimeADTGetDatum(*bb)));
77 : : }
78 : :
79 : : static bool
3281 andrew@dunslane.net 80 : 4281 : gbt_timelt(const void *a, const void *b, FmgrInfo *flinfo)
81 : : {
6537 tgl@sss.pgh.pa.us 82 : 4281 : const TimeADT *aa = (const TimeADT *) a;
83 : 4281 : const TimeADT *bb = (const TimeADT *) b;
84 : :
85 : 4281 : return DatumGetBool(DirectFunctionCall2(time_lt,
86 : : TimeADTGetDatum(*aa),
87 : : TimeADTGetDatum(*bb)));
88 : : }
89 : :
90 : : static int
3281 andrew@dunslane.net 91 : 1073 : gbt_timekey_cmp(const void *a, const void *b, FmgrInfo *flinfo)
92 : : {
5299 peter_e@gmx.net 93 : 1073 : timeKEY *ia = (timeKEY *) (((const Nsrt *) a)->t);
94 : 1073 : timeKEY *ib = (timeKEY *) (((const Nsrt *) b)->t);
95 : : int res;
96 : :
214 tgl@sss.pgh.pa.us 97 :GNC 1073 : res = DatumGetInt32(DirectFunctionCall2(time_cmp, TimeADTGetDatum(ia->lower), TimeADTGetDatum(ib->lower)));
5947 teodor@sigaev.ru 98 [ + + ]:CBC 1073 : if (res == 0)
214 tgl@sss.pgh.pa.us 99 :GNC 1 : return DatumGetInt32(DirectFunctionCall2(time_cmp, TimeADTGetDatum(ia->upper), TimeADTGetDatum(ib->upper)));
100 : :
5947 teodor@sigaev.ru 101 :CBC 1072 : return res;
102 : : }
103 : :
104 : : static float8
3281 andrew@dunslane.net 105 : 273 : gbt_time_dist(const void *a, const void *b, FmgrInfo *flinfo)
106 : : {
5492 tgl@sss.pgh.pa.us 107 : 273 : const TimeADT *aa = (const TimeADT *) a;
108 : 273 : const TimeADT *bb = (const TimeADT *) b;
109 : : Interval *i;
110 : :
111 : 273 : i = DatumGetIntervalP(DirectFunctionCall2(time_mi_time,
112 : : TimeADTGetDatum(*aa),
113 : : TimeADTGetDatum(*bb)));
1255 peter@eisentraut.org 114 : 273 : return fabs(INTERVAL_TO_SEC(i));
115 : : }
116 : :
117 : :
118 : : static const gbtree_ninfo tinfo =
119 : : {
120 : : gbt_t_time,
121 : : sizeof(TimeADT),
122 : : 16, /* sizeof(gbtreekey16) */
123 : : gbt_timegt,
124 : : gbt_timege,
125 : : gbt_timeeq,
126 : : gbt_timele,
127 : : gbt_timelt,
128 : : gbt_timekey_cmp,
129 : : gbt_time_dist
130 : : };
131 : :
132 : :
5492 tgl@sss.pgh.pa.us 133 : 4 : PG_FUNCTION_INFO_V1(time_dist);
134 : : Datum
135 : 547 : time_dist(PG_FUNCTION_ARGS)
136 : : {
137 : 547 : Datum diff = DirectFunctionCall2(time_mi_time,
138 : : PG_GETARG_DATUM(0),
139 : : PG_GETARG_DATUM(1));
140 : :
141 : 547 : PG_RETURN_INTERVAL_P(abs_interval(DatumGetIntervalP(diff)));
142 : : }
143 : :
144 : :
145 : : /**************************************************
146 : : * GiST support functions
147 : : **************************************************/
148 : :
149 : : Datum
7961 teodor@sigaev.ru 150 : 546 : gbt_time_compress(PG_FUNCTION_ARGS)
151 : : {
7868 bruce@momjian.us 152 : 546 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
153 : :
4007 heikki.linnakangas@i 154 : 546 : PG_RETURN_POINTER(gbt_num_compress(entry, &tinfo));
155 : : }
156 : :
157 : : Datum
7961 teodor@sigaev.ru 158 : 533 : gbt_timetz_compress(PG_FUNCTION_ARGS)
159 : : {
7868 bruce@momjian.us 160 : 533 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
161 : : GISTENTRY *retval;
162 : :
163 [ + + ]: 533 : if (entry->leafkey)
164 : : {
100 michael@paquier.xyz 165 :GNC 531 : timeKEY *r = palloc_object(timeKEY);
7868 bruce@momjian.us 166 :CBC 531 : TimeTzADT *tz = DatumGetTimeTzADTP(entry->key);
167 : : TimeADT tmp;
168 : :
100 michael@paquier.xyz 169 :GNC 531 : retval = palloc_object(GISTENTRY);
170 : :
171 : : /* We are using the time + zone only to compress */
7629 tgl@sss.pgh.pa.us 172 :CBC 531 : tmp = tz->time + (tz->zone * INT64CONST(1000000));
173 : 531 : r->lower = r->upper = tmp;
7868 bruce@momjian.us 174 : 531 : gistentryinit(*retval, PointerGetDatum(r),
175 : : entry->rel, entry->page,
176 : : entry->offset, false);
177 : : }
178 : : else
179 : 2 : retval = entry;
180 : 533 : PG_RETURN_POINTER(retval);
181 : : }
182 : :
183 : : Datum
4006 heikki.linnakangas@i 184 : 272 : gbt_time_fetch(PG_FUNCTION_ARGS)
185 : : {
186 : 272 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
187 : :
188 : 272 : PG_RETURN_POINTER(gbt_num_fetch(entry, &tinfo));
189 : : }
190 : :
191 : : Datum
7961 teodor@sigaev.ru 192 : 1914 : gbt_time_consistent(PG_FUNCTION_ARGS)
193 : : {
7868 bruce@momjian.us 194 : 1914 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
195 : 1914 : TimeADT query = PG_GETARG_TIMEADT(1);
6544 tgl@sss.pgh.pa.us 196 : 1914 : StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
197 : : #ifdef NOT_USED
198 : : Oid subtype = PG_GETARG_OID(3);
199 : : #endif
200 : 1914 : bool *recheck = (bool *) PG_GETARG_POINTER(4);
7868 bruce@momjian.us 201 : 1914 : timeKEY *kkk = (timeKEY *) DatumGetPointer(entry->key);
202 : : GBT_NUMKEY_R key;
203 : :
204 : : /* All cases served by this function are exact */
6544 tgl@sss.pgh.pa.us 205 : 1914 : *recheck = false;
206 : :
6121 bruce@momjian.us 207 : 1914 : key.lower = (GBT_NUMKEY *) &kkk->lower;
208 : 1914 : key.upper = (GBT_NUMKEY *) &kkk->upper;
209 : :
472 peter@eisentraut.org 210 : 1914 : PG_RETURN_BOOL(gbt_num_consistent(&key, &query, &strategy,
211 : : GIST_LEAF(entry), &tinfo, fcinfo->flinfo));
212 : : }
213 : :
214 : : Datum
5492 tgl@sss.pgh.pa.us 215 : 274 : gbt_time_distance(PG_FUNCTION_ARGS)
216 : : {
217 : 274 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
218 : 274 : TimeADT query = PG_GETARG_TIMEADT(1);
219 : : #ifdef NOT_USED
220 : : Oid subtype = PG_GETARG_OID(3);
221 : : #endif
222 : 274 : timeKEY *kkk = (timeKEY *) DatumGetPointer(entry->key);
223 : : GBT_NUMKEY_R key;
224 : :
225 : 274 : key.lower = (GBT_NUMKEY *) &kkk->lower;
226 : 274 : key.upper = (GBT_NUMKEY *) &kkk->upper;
227 : :
472 peter@eisentraut.org 228 : 274 : PG_RETURN_FLOAT8(gbt_num_distance(&key, &query, GIST_LEAF(entry),
229 : : &tinfo, fcinfo->flinfo));
230 : : }
231 : :
232 : : Datum
7961 teodor@sigaev.ru 233 : 5601 : gbt_timetz_consistent(PG_FUNCTION_ARGS)
234 : : {
7868 bruce@momjian.us 235 : 5601 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
236 : 5601 : TimeTzADT *query = PG_GETARG_TIMETZADT_P(1);
7629 tgl@sss.pgh.pa.us 237 : 5601 : StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
238 : : #ifdef NOT_USED
239 : : Oid subtype = PG_GETARG_OID(3);
240 : : #endif
6544 241 : 5601 : bool *recheck = (bool *) PG_GETARG_POINTER(4);
7868 bruce@momjian.us 242 : 5601 : timeKEY *kkk = (timeKEY *) DatumGetPointer(entry->key);
243 : : TimeADT qqq;
244 : : GBT_NUMKEY_R key;
245 : :
246 : : /* All cases served by this function are inexact */
6544 tgl@sss.pgh.pa.us 247 : 5601 : *recheck = true;
248 : :
7629 249 : 5601 : qqq = query->time + (query->zone * INT64CONST(1000000));
250 : :
6121 bruce@momjian.us 251 : 5601 : key.lower = (GBT_NUMKEY *) &kkk->lower;
252 : 5601 : key.upper = (GBT_NUMKEY *) &kkk->upper;
253 : :
472 peter@eisentraut.org 254 : 5601 : PG_RETURN_BOOL(gbt_num_consistent(&key, &qqq, &strategy,
255 : : GIST_LEAF(entry), &tinfo, fcinfo->flinfo));
256 : : }
257 : :
258 : : Datum
7961 teodor@sigaev.ru 259 : 2 : gbt_time_union(PG_FUNCTION_ARGS)
260 : : {
7868 bruce@momjian.us 261 : 2 : GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
262 : 2 : void *out = palloc(sizeof(timeKEY));
263 : :
264 : 2 : *(int *) PG_GETARG_POINTER(1) = sizeof(timeKEY);
472 peter@eisentraut.org 265 : 2 : PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
266 : : }
267 : :
268 : : Datum
7961 teodor@sigaev.ru 269 :UBC 0 : gbt_time_penalty(PG_FUNCTION_ARGS)
270 : : {
7868 bruce@momjian.us 271 : 0 : timeKEY *origentry = (timeKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
272 : 0 : timeKEY *newentry = (timeKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
273 : 0 : float *result = (float *) PG_GETARG_POINTER(2);
274 : : Interval *intr;
275 : : double res;
276 : : double res2;
277 : :
2236 alvherre@alvh.no-ip. 278 : 0 : intr = DatumGetIntervalP(DirectFunctionCall2(time_mi_time,
279 : : TimeADTGetDatum(newentry->upper),
280 : : TimeADTGetDatum(origentry->upper)));
7542 tgl@sss.pgh.pa.us 281 : 0 : res = INTERVAL_TO_SEC(intr);
282 [ # # ]: 0 : res = Max(res, 0);
283 : :
2236 alvherre@alvh.no-ip. 284 : 0 : intr = DatumGetIntervalP(DirectFunctionCall2(time_mi_time,
285 : : TimeADTGetDatum(origentry->lower),
286 : : TimeADTGetDatum(newentry->lower)));
7542 tgl@sss.pgh.pa.us 287 : 0 : res2 = INTERVAL_TO_SEC(intr);
288 [ # # ]: 0 : res2 = Max(res2, 0);
289 : :
290 : 0 : res += res2;
291 : :
7868 bruce@momjian.us 292 : 0 : *result = 0.0;
293 : :
294 [ # # ]: 0 : if (res > 0)
295 : : {
2236 alvherre@alvh.no-ip. 296 : 0 : intr = DatumGetIntervalP(DirectFunctionCall2(time_mi_time,
297 : : TimeADTGetDatum(origentry->upper),
298 : : TimeADTGetDatum(origentry->lower)));
7868 bruce@momjian.us 299 : 0 : *result += FLT_MIN;
7542 tgl@sss.pgh.pa.us 300 : 0 : *result += (float) (res / (res + INTERVAL_TO_SEC(intr)));
7868 bruce@momjian.us 301 : 0 : *result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1));
302 : : }
303 : :
304 : 0 : PG_RETURN_POINTER(result);
305 : : }
306 : :
307 : : Datum
7961 teodor@sigaev.ru 308 :CBC 2 : gbt_time_picksplit(PG_FUNCTION_ARGS)
309 : : {
2236 alvherre@alvh.no-ip. 310 : 2 : PG_RETURN_POINTER(gbt_num_picksplit((GistEntryVector *) PG_GETARG_POINTER(0),
311 : : (GIST_SPLITVEC *) PG_GETARG_POINTER(1),
312 : : &tinfo, fcinfo->flinfo));
313 : : }
314 : :
315 : : Datum
7961 teodor@sigaev.ru 316 :UBC 0 : gbt_time_same(PG_FUNCTION_ARGS)
317 : : {
7868 bruce@momjian.us 318 : 0 : timeKEY *b1 = (timeKEY *) PG_GETARG_POINTER(0);
319 : 0 : timeKEY *b2 = (timeKEY *) PG_GETARG_POINTER(1);
320 : 0 : bool *result = (bool *) PG_GETARG_POINTER(2);
321 : :
3281 andrew@dunslane.net 322 : 0 : *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
7868 bruce@momjian.us 323 : 0 : PG_RETURN_POINTER(result);
324 : : }
325 : :
326 : : static int
346 heikki.linnakangas@i 327 :CBC 10635 : gbt_timekey_ssup_cmp(Datum x, Datum y, SortSupport ssup)
328 : : {
329 : 10635 : timeKEY *arg1 = (timeKEY *) DatumGetPointer(x);
330 : 10635 : timeKEY *arg2 = (timeKEY *) DatumGetPointer(y);
331 : :
332 : : /* for leaf items we expect lower == upper, so only compare lower */
333 : 10635 : return DatumGetInt32(DirectFunctionCall2(time_cmp,
334 : : TimeADTGetDatum(arg1->lower),
335 : : TimeADTGetDatum(arg2->lower)));
336 : : }
337 : :
338 : : Datum
339 : 2 : gbt_time_sortsupport(PG_FUNCTION_ARGS)
340 : : {
341 : 2 : SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
342 : :
343 : 2 : ssup->comparator = gbt_timekey_ssup_cmp;
344 : 2 : ssup->ssup_extra = NULL;
345 : :
346 : 2 : PG_RETURN_VOID();
347 : : }
|