Line data Source code
1 : /*
2 : * contrib/btree_gist/btree_date.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 :
13 : typedef struct
14 : {
15 : DateADT lower;
16 : DateADT upper;
17 : } dateKEY;
18 :
19 : /* GiST support functions */
20 0 : PG_FUNCTION_INFO_V1(gbt_date_compress);
21 0 : PG_FUNCTION_INFO_V1(gbt_date_fetch);
22 0 : PG_FUNCTION_INFO_V1(gbt_date_union);
23 0 : PG_FUNCTION_INFO_V1(gbt_date_picksplit);
24 0 : PG_FUNCTION_INFO_V1(gbt_date_consistent);
25 0 : PG_FUNCTION_INFO_V1(gbt_date_distance);
26 0 : PG_FUNCTION_INFO_V1(gbt_date_penalty);
27 0 : PG_FUNCTION_INFO_V1(gbt_date_same);
28 0 : PG_FUNCTION_INFO_V1(gbt_date_sortsupport);
29 :
30 : static bool
31 0 : gbt_dategt(const void *a, const void *b, FmgrInfo *flinfo)
32 : {
33 0 : return DatumGetBool(DirectFunctionCall2(date_gt,
34 : DateADTGetDatum(*((const DateADT *) a)),
35 : DateADTGetDatum(*((const DateADT *) b))));
36 : }
37 :
38 : static bool
39 0 : gbt_datege(const void *a, const void *b, FmgrInfo *flinfo)
40 : {
41 0 : return DatumGetBool(DirectFunctionCall2(date_ge,
42 : DateADTGetDatum(*((const DateADT *) a)),
43 : DateADTGetDatum(*((const DateADT *) b))));
44 : }
45 :
46 : static bool
47 0 : gbt_dateeq(const void *a, const void *b, FmgrInfo *flinfo)
48 : {
49 0 : return DatumGetBool(DirectFunctionCall2(date_eq,
50 : DateADTGetDatum(*((const DateADT *) a)),
51 : DateADTGetDatum(*((const DateADT *) b)))
52 : );
53 : }
54 :
55 : static bool
56 0 : gbt_datele(const void *a, const void *b, FmgrInfo *flinfo)
57 : {
58 0 : return DatumGetBool(DirectFunctionCall2(date_le,
59 : DateADTGetDatum(*((const DateADT *) a)),
60 : DateADTGetDatum(*((const DateADT *) b))));
61 : }
62 :
63 : static bool
64 0 : gbt_datelt(const void *a, const void *b, FmgrInfo *flinfo)
65 : {
66 0 : return DatumGetBool(DirectFunctionCall2(date_lt,
67 : DateADTGetDatum(*((const DateADT *) a)),
68 : DateADTGetDatum(*((const DateADT *) b))));
69 : }
70 :
71 :
72 :
73 : static int
74 0 : gbt_datekey_cmp(const void *a, const void *b, FmgrInfo *flinfo)
75 : {
76 0 : dateKEY *ia = (dateKEY *) (((const Nsrt *) a)->t);
77 0 : dateKEY *ib = (dateKEY *) (((const Nsrt *) b)->t);
78 0 : int res;
79 :
80 0 : res = DatumGetInt32(DirectFunctionCall2(date_cmp,
81 : DateADTGetDatum(ia->lower),
82 : DateADTGetDatum(ib->lower)));
83 0 : if (res == 0)
84 0 : return DatumGetInt32(DirectFunctionCall2(date_cmp,
85 : DateADTGetDatum(ia->upper),
86 : DateADTGetDatum(ib->upper)));
87 :
88 0 : return res;
89 0 : }
90 :
91 : static float8
92 0 : gdb_date_dist(const void *a, const void *b, FmgrInfo *flinfo)
93 : {
94 : /* we assume the difference can't overflow */
95 0 : Datum diff = DirectFunctionCall2(date_mi,
96 : DateADTGetDatum(*((const DateADT *) a)),
97 : DateADTGetDatum(*((const DateADT *) b)));
98 :
99 0 : return (float8) abs(DatumGetInt32(diff));
100 0 : }
101 :
102 :
103 : static const gbtree_ninfo tinfo =
104 : {
105 : gbt_t_date,
106 : sizeof(DateADT),
107 : 8, /* sizeof(gbtreekey8) */
108 : gbt_dategt,
109 : gbt_datege,
110 : gbt_dateeq,
111 : gbt_datele,
112 : gbt_datelt,
113 : gbt_datekey_cmp,
114 : gdb_date_dist
115 : };
116 :
117 :
118 0 : PG_FUNCTION_INFO_V1(date_dist);
119 : Datum
120 0 : date_dist(PG_FUNCTION_ARGS)
121 : {
122 : /* we assume the difference can't overflow */
123 0 : Datum diff = DirectFunctionCall2(date_mi,
124 : PG_GETARG_DATUM(0),
125 : PG_GETARG_DATUM(1));
126 :
127 0 : PG_RETURN_INT32(abs(DatumGetInt32(diff)));
128 0 : }
129 :
130 :
131 : /**************************************************
132 : * GiST support functions
133 : **************************************************/
134 :
135 : Datum
136 0 : gbt_date_compress(PG_FUNCTION_ARGS)
137 : {
138 0 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
139 :
140 0 : PG_RETURN_POINTER(gbt_num_compress(entry, &tinfo));
141 0 : }
142 :
143 : Datum
144 0 : gbt_date_fetch(PG_FUNCTION_ARGS)
145 : {
146 0 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
147 :
148 0 : PG_RETURN_POINTER(gbt_num_fetch(entry, &tinfo));
149 0 : }
150 :
151 : Datum
152 0 : gbt_date_consistent(PG_FUNCTION_ARGS)
153 : {
154 0 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
155 0 : DateADT query = PG_GETARG_DATEADT(1);
156 0 : StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
157 : #ifdef NOT_USED
158 : Oid subtype = PG_GETARG_OID(3);
159 : #endif
160 0 : bool *recheck = (bool *) PG_GETARG_POINTER(4);
161 0 : dateKEY *kkk = (dateKEY *) DatumGetPointer(entry->key);
162 0 : GBT_NUMKEY_R key;
163 :
164 : /* All cases served by this function are exact */
165 0 : *recheck = false;
166 :
167 0 : key.lower = (GBT_NUMKEY *) &kkk->lower;
168 0 : key.upper = (GBT_NUMKEY *) &kkk->upper;
169 :
170 0 : PG_RETURN_BOOL(gbt_num_consistent(&key, &query, &strategy,
171 : GIST_LEAF(entry), &tinfo,
172 : fcinfo->flinfo));
173 0 : }
174 :
175 : Datum
176 0 : gbt_date_distance(PG_FUNCTION_ARGS)
177 : {
178 0 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
179 0 : DateADT query = PG_GETARG_DATEADT(1);
180 : #ifdef NOT_USED
181 : Oid subtype = PG_GETARG_OID(3);
182 : #endif
183 0 : dateKEY *kkk = (dateKEY *) DatumGetPointer(entry->key);
184 0 : GBT_NUMKEY_R key;
185 :
186 0 : key.lower = (GBT_NUMKEY *) &kkk->lower;
187 0 : key.upper = (GBT_NUMKEY *) &kkk->upper;
188 :
189 0 : PG_RETURN_FLOAT8(gbt_num_distance(&key, &query, GIST_LEAF(entry),
190 : &tinfo, fcinfo->flinfo));
191 0 : }
192 :
193 : Datum
194 0 : gbt_date_union(PG_FUNCTION_ARGS)
195 : {
196 0 : GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
197 0 : void *out = palloc(sizeof(dateKEY));
198 :
199 0 : *(int *) PG_GETARG_POINTER(1) = sizeof(dateKEY);
200 0 : PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
201 0 : }
202 :
203 : Datum
204 0 : gbt_date_penalty(PG_FUNCTION_ARGS)
205 : {
206 0 : dateKEY *origentry = (dateKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
207 0 : dateKEY *newentry = (dateKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
208 0 : float *result = (float *) PG_GETARG_POINTER(2);
209 0 : int32 diff,
210 : res;
211 :
212 0 : diff = DatumGetInt32(DirectFunctionCall2(date_mi,
213 : DateADTGetDatum(newentry->upper),
214 : DateADTGetDatum(origentry->upper)));
215 :
216 0 : res = Max(diff, 0);
217 :
218 0 : diff = DatumGetInt32(DirectFunctionCall2(date_mi,
219 : DateADTGetDatum(origentry->lower),
220 : DateADTGetDatum(newentry->lower)));
221 :
222 0 : res += Max(diff, 0);
223 :
224 0 : *result = 0.0;
225 :
226 0 : if (res > 0)
227 : {
228 0 : diff = DatumGetInt32(DirectFunctionCall2(date_mi,
229 : DateADTGetDatum(origentry->upper),
230 : DateADTGetDatum(origentry->lower)));
231 0 : *result += FLT_MIN;
232 0 : *result += (float) (res / ((double) (res + diff)));
233 0 : *result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1));
234 0 : }
235 :
236 0 : PG_RETURN_POINTER(result);
237 0 : }
238 :
239 : Datum
240 0 : gbt_date_picksplit(PG_FUNCTION_ARGS)
241 : {
242 0 : PG_RETURN_POINTER(gbt_num_picksplit((GistEntryVector *) PG_GETARG_POINTER(0),
243 : (GIST_SPLITVEC *) PG_GETARG_POINTER(1),
244 : &tinfo, fcinfo->flinfo));
245 : }
246 :
247 : Datum
248 0 : gbt_date_same(PG_FUNCTION_ARGS)
249 : {
250 0 : dateKEY *b1 = (dateKEY *) PG_GETARG_POINTER(0);
251 0 : dateKEY *b2 = (dateKEY *) PG_GETARG_POINTER(1);
252 0 : bool *result = (bool *) PG_GETARG_POINTER(2);
253 :
254 0 : *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
255 0 : PG_RETURN_POINTER(result);
256 0 : }
257 :
258 : static int
259 0 : gbt_date_ssup_cmp(Datum x, Datum y, SortSupport ssup)
260 : {
261 0 : dateKEY *akey = (dateKEY *) DatumGetPointer(x);
262 0 : dateKEY *bkey = (dateKEY *) DatumGetPointer(y);
263 :
264 : /* for leaf items we expect lower == upper, so only compare lower */
265 0 : return DatumGetInt32(DirectFunctionCall2(date_cmp,
266 : DateADTGetDatum(akey->lower),
267 : DateADTGetDatum(bkey->lower)));
268 0 : }
269 :
270 : Datum
271 0 : gbt_date_sortsupport(PG_FUNCTION_ARGS)
272 : {
273 0 : SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
274 :
275 0 : ssup->comparator = gbt_date_ssup_cmp;
276 0 : ssup->ssup_extra = NULL;
277 :
278 0 : PG_RETURN_VOID();
279 0 : }
|