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