2 * contrib/btree_gist/btree_interval.c
6 #include "btree_gist.h"
7 #include "btree_utils_num.h"
8 #include "utils/fmgrprotos.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 fabs(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 const 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(r
, key
, INTERVALSIZE
);
161 memcpy(r
+ INTERVALSIZE
, 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
);
179 gbt_intv_fetch(PG_FUNCTION_ARGS
)
181 GISTENTRY
*entry
= (GISTENTRY
*) PG_GETARG_POINTER(0);
183 PG_RETURN_POINTER(gbt_num_fetch(entry
, &tinfo
));
187 gbt_intv_decompress(PG_FUNCTION_ARGS
)
189 GISTENTRY
*entry
= (GISTENTRY
*) PG_GETARG_POINTER(0);
190 GISTENTRY
*retval
= entry
;
192 if (INTERVALSIZE
!= sizeof(Interval
))
194 intvKEY
*r
= palloc(sizeof(intvKEY
));
195 char *key
= DatumGetPointer(entry
->key
);
197 retval
= palloc(sizeof(GISTENTRY
));
198 memcpy(&r
->lower
, key
, INTERVALSIZE
);
199 memcpy(&r
->upper
, key
+ INTERVALSIZE
, INTERVALSIZE
);
201 gistentryinit(*retval
, PointerGetDatum(r
),
202 entry
->rel
, entry
->page
,
203 entry
->offset
, false);
205 PG_RETURN_POINTER(retval
);
210 gbt_intv_consistent(PG_FUNCTION_ARGS
)
212 GISTENTRY
*entry
= (GISTENTRY
*) PG_GETARG_POINTER(0);
213 Interval
*query
= PG_GETARG_INTERVAL_P(1);
214 StrategyNumber strategy
= (StrategyNumber
) PG_GETARG_UINT16(2);
216 /* Oid subtype = PG_GETARG_OID(3); */
217 bool *recheck
= (bool *) PG_GETARG_POINTER(4);
218 intvKEY
*kkk
= (intvKEY
*) DatumGetPointer(entry
->key
);
221 /* All cases served by this function are exact */
224 key
.lower
= (GBT_NUMKEY
*) &kkk
->lower
;
225 key
.upper
= (GBT_NUMKEY
*) &kkk
->upper
;
227 PG_RETURN_BOOL(gbt_num_consistent(&key
, query
, &strategy
,
228 GIST_LEAF(entry
), &tinfo
, fcinfo
->flinfo
));
233 gbt_intv_distance(PG_FUNCTION_ARGS
)
235 GISTENTRY
*entry
= (GISTENTRY
*) PG_GETARG_POINTER(0);
236 Interval
*query
= PG_GETARG_INTERVAL_P(1);
238 /* Oid subtype = PG_GETARG_OID(3); */
239 intvKEY
*kkk
= (intvKEY
*) DatumGetPointer(entry
->key
);
242 key
.lower
= (GBT_NUMKEY
*) &kkk
->lower
;
243 key
.upper
= (GBT_NUMKEY
*) &kkk
->upper
;
245 PG_RETURN_FLOAT8(gbt_num_distance(&key
, query
, GIST_LEAF(entry
),
246 &tinfo
, fcinfo
->flinfo
));
251 gbt_intv_union(PG_FUNCTION_ARGS
)
253 GistEntryVector
*entryvec
= (GistEntryVector
*) PG_GETARG_POINTER(0);
254 void *out
= palloc(sizeof(intvKEY
));
256 *(int *) PG_GETARG_POINTER(1) = sizeof(intvKEY
);
257 PG_RETURN_POINTER(gbt_num_union(out
, entryvec
, &tinfo
, fcinfo
->flinfo
));
262 gbt_intv_penalty(PG_FUNCTION_ARGS
)
264 intvKEY
*origentry
= (intvKEY
*) DatumGetPointer(((GISTENTRY
*) PG_GETARG_POINTER(0))->key
);
265 intvKEY
*newentry
= (intvKEY
*) DatumGetPointer(((GISTENTRY
*) PG_GETARG_POINTER(1))->key
);
266 float *result
= (float *) PG_GETARG_POINTER(2);
270 iorg
[0] = intr2num(&origentry
->lower
);
271 iorg
[1] = intr2num(&origentry
->upper
);
272 inew
[0] = intr2num(&newentry
->lower
);
273 inew
[1] = intr2num(&newentry
->upper
);
275 penalty_num(result
, iorg
[0], iorg
[1], inew
[0], inew
[1]);
277 PG_RETURN_POINTER(result
);
281 gbt_intv_picksplit(PG_FUNCTION_ARGS
)
283 PG_RETURN_POINTER(gbt_num_picksplit((GistEntryVector
*) PG_GETARG_POINTER(0),
284 (GIST_SPLITVEC
*) PG_GETARG_POINTER(1),
285 &tinfo
, fcinfo
->flinfo
));
289 gbt_intv_same(PG_FUNCTION_ARGS
)
291 intvKEY
*b1
= (intvKEY
*) PG_GETARG_POINTER(0);
292 intvKEY
*b2
= (intvKEY
*) PG_GETARG_POINTER(1);
293 bool *result
= (bool *) PG_GETARG_POINTER(2);
295 *result
= gbt_num_same((void *) b1
, (void *) b2
, &tinfo
, fcinfo
->flinfo
);
296 PG_RETURN_POINTER(result
);