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