Line data Source code
1 : /*
2 : * contrib/btree_gist/btree_numeric.c
3 : */
4 : #include "postgres.h"
5 :
6 : #include <float.h>
7 :
8 : #include "btree_gist.h"
9 : #include "btree_utils_var.h"
10 : #include "utils/builtins.h"
11 : #include "utils/numeric.h"
12 : #include "utils/rel.h"
13 : #include "utils/sortsupport.h"
14 :
15 : /* GiST support functions */
16 0 : PG_FUNCTION_INFO_V1(gbt_numeric_compress);
17 0 : PG_FUNCTION_INFO_V1(gbt_numeric_union);
18 0 : PG_FUNCTION_INFO_V1(gbt_numeric_picksplit);
19 0 : PG_FUNCTION_INFO_V1(gbt_numeric_consistent);
20 0 : PG_FUNCTION_INFO_V1(gbt_numeric_penalty);
21 0 : PG_FUNCTION_INFO_V1(gbt_numeric_same);
22 0 : PG_FUNCTION_INFO_V1(gbt_numeric_sortsupport);
23 :
24 :
25 : /* define for comparison */
26 :
27 : static bool
28 0 : gbt_numeric_gt(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
29 : {
30 0 : return DatumGetBool(DirectFunctionCall2(numeric_gt,
31 : PointerGetDatum(a),
32 : PointerGetDatum(b)));
33 : }
34 :
35 : static bool
36 0 : gbt_numeric_ge(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
37 : {
38 0 : return DatumGetBool(DirectFunctionCall2(numeric_ge,
39 : PointerGetDatum(a),
40 : PointerGetDatum(b)));
41 : }
42 :
43 : static bool
44 0 : gbt_numeric_eq(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
45 : {
46 0 : return DatumGetBool(DirectFunctionCall2(numeric_eq,
47 : PointerGetDatum(a),
48 : PointerGetDatum(b)));
49 : }
50 :
51 : static bool
52 0 : gbt_numeric_le(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
53 : {
54 0 : return DatumGetBool(DirectFunctionCall2(numeric_le,
55 : PointerGetDatum(a),
56 : PointerGetDatum(b)));
57 : }
58 :
59 : static bool
60 0 : gbt_numeric_lt(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
61 : {
62 0 : return DatumGetBool(DirectFunctionCall2(numeric_lt,
63 : PointerGetDatum(a),
64 : PointerGetDatum(b)));
65 : }
66 :
67 : static int32
68 0 : gbt_numeric_cmp(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
69 : {
70 0 : return DatumGetInt32(DirectFunctionCall2(numeric_cmp,
71 : PointerGetDatum(a),
72 : PointerGetDatum(b)));
73 : }
74 :
75 :
76 : static const gbtree_vinfo tinfo =
77 : {
78 : gbt_t_numeric,
79 : 0,
80 : false,
81 : gbt_numeric_gt,
82 : gbt_numeric_ge,
83 : gbt_numeric_eq,
84 : gbt_numeric_le,
85 : gbt_numeric_lt,
86 : gbt_numeric_cmp,
87 : NULL
88 : };
89 :
90 :
91 : /**************************************************
92 : * GiST support functions
93 : **************************************************/
94 :
95 : Datum
96 0 : gbt_numeric_compress(PG_FUNCTION_ARGS)
97 : {
98 0 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
99 :
100 0 : PG_RETURN_POINTER(gbt_var_compress(entry, &tinfo));
101 0 : }
102 :
103 : Datum
104 0 : gbt_numeric_consistent(PG_FUNCTION_ARGS)
105 : {
106 0 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
107 0 : void *query = DatumGetNumeric(PG_GETARG_DATUM(1));
108 0 : StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
109 : #ifdef NOT_USED
110 : Oid subtype = PG_GETARG_OID(3);
111 : #endif
112 0 : bool *recheck = (bool *) PG_GETARG_POINTER(4);
113 0 : bool retval;
114 0 : GBT_VARKEY *key = (GBT_VARKEY *) DatumGetPointer(entry->key);
115 0 : GBT_VARKEY_R r = gbt_var_key_readable(key);
116 :
117 : /* All cases served by this function are exact */
118 0 : *recheck = false;
119 :
120 0 : retval = gbt_var_consistent(&r, query, strategy, PG_GET_COLLATION(),
121 0 : GIST_LEAF(entry), &tinfo, fcinfo->flinfo);
122 0 : PG_RETURN_BOOL(retval);
123 0 : }
124 :
125 : Datum
126 0 : gbt_numeric_union(PG_FUNCTION_ARGS)
127 : {
128 0 : GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
129 0 : int32 *size = (int *) PG_GETARG_POINTER(1);
130 :
131 0 : PG_RETURN_POINTER(gbt_var_union(entryvec, size, PG_GET_COLLATION(),
132 : &tinfo, fcinfo->flinfo));
133 0 : }
134 :
135 : Datum
136 0 : gbt_numeric_same(PG_FUNCTION_ARGS)
137 : {
138 0 : Datum d1 = PG_GETARG_DATUM(0);
139 0 : Datum d2 = PG_GETARG_DATUM(1);
140 0 : bool *result = (bool *) PG_GETARG_POINTER(2);
141 :
142 0 : *result = gbt_var_same(d1, d2, PG_GET_COLLATION(), &tinfo, fcinfo->flinfo);
143 0 : PG_RETURN_POINTER(result);
144 0 : }
145 :
146 : Datum
147 0 : gbt_numeric_penalty(PG_FUNCTION_ARGS)
148 : {
149 0 : GISTENTRY *o = (GISTENTRY *) PG_GETARG_POINTER(0);
150 0 : GISTENTRY *n = (GISTENTRY *) PG_GETARG_POINTER(1);
151 0 : float *result = (float *) PG_GETARG_POINTER(2);
152 :
153 0 : Numeric us,
154 : os,
155 : ds;
156 :
157 0 : GBT_VARKEY *org = (GBT_VARKEY *) DatumGetPointer(o->key);
158 0 : GBT_VARKEY *newe = (GBT_VARKEY *) DatumGetPointer(n->key);
159 0 : Datum uni;
160 0 : GBT_VARKEY_R rk,
161 : ok,
162 : uk;
163 :
164 0 : rk = gbt_var_key_readable(org);
165 0 : uni = PointerGetDatum(gbt_var_key_copy(&rk));
166 0 : gbt_var_bin_union(&uni, newe, PG_GET_COLLATION(), &tinfo, fcinfo->flinfo);
167 0 : ok = gbt_var_key_readable(org);
168 0 : uk = gbt_var_key_readable((GBT_VARKEY *) DatumGetPointer(uni));
169 :
170 0 : us = DatumGetNumeric(DirectFunctionCall2(numeric_sub,
171 : PointerGetDatum(uk.upper),
172 : PointerGetDatum(uk.lower)));
173 :
174 0 : os = DatumGetNumeric(DirectFunctionCall2(numeric_sub,
175 : PointerGetDatum(ok.upper),
176 : PointerGetDatum(ok.lower)));
177 :
178 0 : ds = DatumGetNumeric(DirectFunctionCall2(numeric_sub,
179 : NumericGetDatum(us),
180 : NumericGetDatum(os)));
181 :
182 0 : if (numeric_is_nan(us))
183 : {
184 0 : if (numeric_is_nan(os))
185 0 : *result = 0.0;
186 : else
187 0 : *result = 1.0;
188 0 : }
189 : else
190 : {
191 0 : Numeric nul = int64_to_numeric(0);
192 :
193 0 : *result = 0.0;
194 :
195 0 : if (DatumGetBool(DirectFunctionCall2(numeric_gt, NumericGetDatum(ds), NumericGetDatum(nul))))
196 : {
197 0 : *result += FLT_MIN;
198 0 : os = DatumGetNumeric(DirectFunctionCall2(numeric_div,
199 : NumericGetDatum(ds),
200 : NumericGetDatum(us)));
201 0 : *result += (float4) DatumGetFloat8(DirectFunctionCall1(numeric_float8_no_overflow, NumericGetDatum(os)));
202 0 : }
203 0 : }
204 :
205 0 : if (*result > 0)
206 0 : *result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1));
207 :
208 0 : PG_RETURN_POINTER(result);
209 0 : }
210 :
211 : Datum
212 0 : gbt_numeric_picksplit(PG_FUNCTION_ARGS)
213 : {
214 0 : GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
215 0 : GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
216 :
217 0 : gbt_var_picksplit(entryvec, v, PG_GET_COLLATION(),
218 0 : &tinfo, fcinfo->flinfo);
219 0 : PG_RETURN_POINTER(v);
220 0 : }
221 :
222 : static int
223 0 : gbt_numeric_ssup_cmp(Datum x, Datum y, SortSupport ssup)
224 : {
225 0 : GBT_VARKEY *key1 = PG_DETOAST_DATUM(x);
226 0 : GBT_VARKEY *key2 = PG_DETOAST_DATUM(y);
227 :
228 0 : GBT_VARKEY_R arg1 = gbt_var_key_readable(key1);
229 0 : GBT_VARKEY_R arg2 = gbt_var_key_readable(key2);
230 0 : Datum result;
231 :
232 : /* for leaf items we expect lower == upper, so only compare lower */
233 0 : result = DirectFunctionCall2(numeric_cmp,
234 : PointerGetDatum(arg1.lower),
235 : PointerGetDatum(arg2.lower));
236 :
237 0 : GBT_FREE_IF_COPY(key1, x);
238 0 : GBT_FREE_IF_COPY(key2, y);
239 :
240 0 : return DatumGetInt32(result);
241 0 : }
242 :
243 : Datum
244 0 : gbt_numeric_sortsupport(PG_FUNCTION_ARGS)
245 : {
246 0 : SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
247 :
248 0 : ssup->comparator = gbt_numeric_ssup_cmp;
249 0 : ssup->ssup_extra = NULL;
250 :
251 0 : PG_RETURN_VOID();
252 0 : }
|