2 * contrib/btree_gist/btree_interval.c
6 #include "btree_gist.h"
7 #include "btree_utils_num.h"
8 #include "utils/builtins.h"
9 #include "utils/timestamp.h"
21 PG_FUNCTION_INFO_V1(gbt_intv_compress
);
22 PG_FUNCTION_INFO_V1(gbt_intv_fetch
);
23 PG_FUNCTION_INFO_V1(gbt_intv_decompress
);
24 PG_FUNCTION_INFO_V1(gbt_intv_union
);
25 PG_FUNCTION_INFO_V1(gbt_intv_picksplit
);
26 PG_FUNCTION_INFO_V1(gbt_intv_consistent
);
27 PG_FUNCTION_INFO_V1(gbt_intv_distance
);
28 PG_FUNCTION_INFO_V1(gbt_intv_penalty
);
29 PG_FUNCTION_INFO_V1(gbt_intv_same
);
33 gbt_intvgt(const void *a
, const void *b
, FmgrInfo
*flinfo
)
35 return DatumGetBool(DirectFunctionCall2(interval_gt
, IntervalPGetDatum(a
), IntervalPGetDatum(b
)));
39 gbt_intvge(const void *a
, const void *b
, FmgrInfo
*flinfo
)
41 return DatumGetBool(DirectFunctionCall2(interval_ge
, IntervalPGetDatum(a
), IntervalPGetDatum(b
)));
45 gbt_intveq(const void *a
, const void *b
, FmgrInfo
*flinfo
)
47 return DatumGetBool(DirectFunctionCall2(interval_eq
, IntervalPGetDatum(a
), IntervalPGetDatum(b
)));
51 gbt_intvle(const void *a
, const void *b
, FmgrInfo
*flinfo
)
53 return DatumGetBool(DirectFunctionCall2(interval_le
, IntervalPGetDatum(a
), IntervalPGetDatum(b
)));
57 gbt_intvlt(const void *a
, const void *b
, FmgrInfo
*flinfo
)
59 return DatumGetBool(DirectFunctionCall2(interval_lt
, IntervalPGetDatum(a
), IntervalPGetDatum(b
)));
63 gbt_intvkey_cmp(const void *a
, const void *b
, FmgrInfo
*flinfo
)
65 intvKEY
*ia
= (intvKEY
*) (((const Nsrt
*) a
)->t
);
66 intvKEY
*ib
= (intvKEY
*) (((const Nsrt
*) b
)->t
);
69 res
= DatumGetInt32(DirectFunctionCall2(interval_cmp
, IntervalPGetDatum(&ia
->lower
), IntervalPGetDatum(&ib
->lower
)));
71 return DatumGetInt32(DirectFunctionCall2(interval_cmp
, IntervalPGetDatum(&ia
->upper
), IntervalPGetDatum(&ib
->upper
)));
78 intr2num(const Interval
*i
)
80 return INTERVAL_TO_SEC(i
);
84 gbt_intv_dist(const void *a
, const void *b
, FmgrInfo
*flinfo
)
86 return (float8
) Abs(intr2num((const Interval
*) a
) - intr2num((const Interval
*) b
));
90 * INTERVALSIZE should be the actual size-on-disk of an Interval, as shown
91 * in pg_type. This might be less than sizeof(Interval) if the compiler
92 * insists on adding alignment padding at the end of the struct. (Note:
93 * this concern is obsolete with the current definition of Interval, but
94 * was real before a separate "day" field was added to it.)
96 #define INTERVALSIZE 16
98 static const gbtree_ninfo tinfo
=
102 32, /* sizeof(gbtreekey32) */
114 abs_interval(Interval
*a
)
116 static Interval zero
= {0, 0, 0};
118 if (DatumGetBool(DirectFunctionCall2(interval_lt
,
119 IntervalPGetDatum(a
),
120 IntervalPGetDatum(&zero
))))
121 a
= DatumGetIntervalP(DirectFunctionCall1(interval_um
,
122 IntervalPGetDatum(a
)));
127 PG_FUNCTION_INFO_V1(interval_dist
);
129 interval_dist(PG_FUNCTION_ARGS
)
131 Datum diff
= DirectFunctionCall2(interval_mi
,
135 PG_RETURN_INTERVAL_P(abs_interval(DatumGetIntervalP(diff
)));
139 /**************************************************
141 **************************************************/
145 gbt_intv_compress(PG_FUNCTION_ARGS
)
147 GISTENTRY
*entry
= (GISTENTRY
*) PG_GETARG_POINTER(0);
148 GISTENTRY
*retval
= entry
;
150 if (entry
->leafkey
|| INTERVALSIZE
!= sizeof(Interval
))
152 char *r
= (char *) palloc(2 * INTERVALSIZE
);
154 retval
= palloc(sizeof(GISTENTRY
));
158 Interval
*key
= DatumGetIntervalP(entry
->key
);
160 memcpy((void *) r
, (void *) key
, INTERVALSIZE
);
161 memcpy((void *) (r
+ INTERVALSIZE
), (void *) key
, INTERVALSIZE
);
165 intvKEY
*key
= (intvKEY
*) DatumGetPointer(entry
->key
);
167 memcpy(r
, &key
->lower
, INTERVALSIZE
);
168 memcpy(r
+ INTERVALSIZE
, &key
->upper
, INTERVALSIZE
);
170 gistentryinit(*retval
, PointerGetDatum(r
),
171 entry
->rel
, entry
->page
,
172 entry
->offset
, false);
175 PG_RETURN_POINTER(retval
);
180 gbt_intv_fetch(PG_FUNCTION_ARGS
)
182 GISTENTRY
*entry
= (GISTENTRY
*) PG_GETARG_POINTER(0);
184 PG_RETURN_POINTER(gbt_num_fetch(entry
, &tinfo
));
188 gbt_intv_decompress(PG_FUNCTION_ARGS
)
190 GISTENTRY
*entry
= (GISTENTRY
*) PG_GETARG_POINTER(0);
191 GISTENTRY
*retval
= entry
;
193 if (INTERVALSIZE
!= sizeof(Interval
))
195 intvKEY
*r
= palloc(sizeof(intvKEY
));
196 char *key
= DatumGetPointer(entry
->key
);
198 retval
= palloc(sizeof(GISTENTRY
));
199 memcpy(&r
->lower
, key
, INTERVALSIZE
);
200 memcpy(&r
->upper
, key
+ INTERVALSIZE
, INTERVALSIZE
);
202 gistentryinit(*retval
, PointerGetDatum(r
),
203 entry
->rel
, entry
->page
,
204 entry
->offset
, false);
206 PG_RETURN_POINTER(retval
);
211 gbt_intv_consistent(PG_FUNCTION_ARGS
)
213 GISTENTRY
*entry
= (GISTENTRY
*) PG_GETARG_POINTER(0);
214 Interval
*query
= PG_GETARG_INTERVAL_P(1);
215 StrategyNumber strategy
= (StrategyNumber
) PG_GETARG_UINT16(2);
217 /* Oid subtype = PG_GETARG_OID(3); */
218 bool *recheck
= (bool *) PG_GETARG_POINTER(4);
219 intvKEY
*kkk
= (intvKEY
*) DatumGetPointer(entry
->key
);
222 /* All cases served by this function are exact */
225 key
.lower
= (GBT_NUMKEY
*) &kkk
->lower
;
226 key
.upper
= (GBT_NUMKEY
*) &kkk
->upper
;
228 PG_RETURN_BOOL(gbt_num_consistent(&key
, (void *) query
, &strategy
,
229 GIST_LEAF(entry
), &tinfo
, fcinfo
->flinfo
));
234 gbt_intv_distance(PG_FUNCTION_ARGS
)
236 GISTENTRY
*entry
= (GISTENTRY
*) PG_GETARG_POINTER(0);
237 Interval
*query
= PG_GETARG_INTERVAL_P(1);
239 /* Oid subtype = PG_GETARG_OID(3); */
240 intvKEY
*kkk
= (intvKEY
*) DatumGetPointer(entry
->key
);
243 key
.lower
= (GBT_NUMKEY
*) &kkk
->lower
;
244 key
.upper
= (GBT_NUMKEY
*) &kkk
->upper
;
246 PG_RETURN_FLOAT8(gbt_num_distance(&key
, (void *) query
, GIST_LEAF(entry
),
247 &tinfo
, fcinfo
->flinfo
));
252 gbt_intv_union(PG_FUNCTION_ARGS
)
254 GistEntryVector
*entryvec
= (GistEntryVector
*) PG_GETARG_POINTER(0);
255 void *out
= palloc(sizeof(intvKEY
));
257 *(int *) PG_GETARG_POINTER(1) = sizeof(intvKEY
);
258 PG_RETURN_POINTER(gbt_num_union((void *) out
, entryvec
, &tinfo
, fcinfo
->flinfo
));
263 gbt_intv_penalty(PG_FUNCTION_ARGS
)
265 intvKEY
*origentry
= (intvKEY
*) DatumGetPointer(((GISTENTRY
*) PG_GETARG_POINTER(0))->key
);
266 intvKEY
*newentry
= (intvKEY
*) DatumGetPointer(((GISTENTRY
*) PG_GETARG_POINTER(1))->key
);
267 float *result
= (float *) PG_GETARG_POINTER(2);
271 iorg
[0] = intr2num(&origentry
->lower
);
272 iorg
[1] = intr2num(&origentry
->upper
);
273 inew
[0] = intr2num(&newentry
->lower
);
274 inew
[1] = intr2num(&newentry
->upper
);
276 penalty_num(result
, iorg
[0], iorg
[1], inew
[0], inew
[1]);
278 PG_RETURN_POINTER(result
);
283 gbt_intv_picksplit(PG_FUNCTION_ARGS
)
285 PG_RETURN_POINTER(gbt_num_picksplit((GistEntryVector
*) PG_GETARG_POINTER(0),
286 (GIST_SPLITVEC
*) PG_GETARG_POINTER(1),
287 &tinfo
, fcinfo
->flinfo
));
291 gbt_intv_same(PG_FUNCTION_ARGS
)
293 intvKEY
*b1
= (intvKEY
*) PG_GETARG_POINTER(0);
294 intvKEY
*b2
= (intvKEY
*) PG_GETARG_POINTER(1);
295 bool *result
= (bool *) PG_GETARG_POINTER(2);
297 *result
= gbt_num_same((void *) b1
, (void *) b2
, &tinfo
, fcinfo
->flinfo
);
298 PG_RETURN_POINTER(result
);