OSDN Git Service

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