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