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