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