Age Owner Branch data TLA 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 */
8093 teodor@sigaev.ru 18 :CBC 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);
478 heikki.linnakangas@i 24 : 5 : PG_FUNCTION_INFO_V1(gbt_numeric_sortsupport);
25 : :
26 : :
27 : : /* define for comparison */
28 : :
29 : : static bool
3413 andrew@dunslane.net 30 : 1695 : gbt_numeric_gt(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
31 : : {
5573 tgl@sss.pgh.pa.us 32 : 1695 : return DatumGetBool(DirectFunctionCall2(numeric_gt,
33 : : PointerGetDatum(a),
34 : : PointerGetDatum(b)));
35 : : }
36 : :
37 : : static bool
3413 andrew@dunslane.net 38 : 1965 : gbt_numeric_ge(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
39 : : {
5573 tgl@sss.pgh.pa.us 40 : 1965 : return DatumGetBool(DirectFunctionCall2(numeric_ge,
41 : : PointerGetDatum(a),
42 : : PointerGetDatum(b)));
43 : : }
44 : :
45 : : static bool
3413 andrew@dunslane.net 46 : 567 : gbt_numeric_eq(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
47 : : {
5573 tgl@sss.pgh.pa.us 48 : 567 : return DatumGetBool(DirectFunctionCall2(numeric_eq,
49 : : PointerGetDatum(a),
50 : : PointerGetDatum(b)));
51 : : }
52 : :
53 : : static bool
3413 andrew@dunslane.net 54 : 2198 : gbt_numeric_le(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
55 : : {
5573 tgl@sss.pgh.pa.us 56 : 2198 : return DatumGetBool(DirectFunctionCall2(numeric_le,
57 : : PointerGetDatum(a),
58 : : PointerGetDatum(b)));
59 : : }
60 : :
61 : : static bool
3413 andrew@dunslane.net 62 : 2185 : gbt_numeric_lt(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
63 : : {
5573 tgl@sss.pgh.pa.us 64 : 2185 : return DatumGetBool(DirectFunctionCall2(numeric_lt,
65 : : PointerGetDatum(a),
66 : : PointerGetDatum(b)));
67 : : }
68 : :
69 : : static int32
3413 andrew@dunslane.net 70 : 43504 : gbt_numeric_cmp(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
71 : : {
5573 tgl@sss.pgh.pa.us 72 : 43504 : 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
8000 bruce@momjian.us 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
8093 teodor@sigaev.ru 110 : 8729 : gbt_numeric_consistent(PG_FUNCTION_ARGS)
111 : : {
8000 bruce@momjian.us 112 : 8729 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
604 peter@eisentraut.org 113 : 8729 : void *query = DatumGetNumeric(PG_GETARG_DATUM(1));
8000 bruce@momjian.us 114 : 8729 : StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
115 : : #ifdef NOT_USED
116 : : Oid subtype = PG_GETARG_OID(3);
117 : : #endif
6676 tgl@sss.pgh.pa.us 118 : 8729 : bool *recheck = (bool *) PG_GETARG_POINTER(4);
119 : : bool retval;
120 : 8729 : GBT_VARKEY *key = (GBT_VARKEY *) DatumGetPointer(entry->key);
8000 bruce@momjian.us 121 : 8729 : GBT_VARKEY_R r = gbt_var_key_readable(key);
122 : :
123 : : /* All cases served by this function are exact */
6676 tgl@sss.pgh.pa.us 124 : 8729 : *recheck = false;
125 : :
5573 126 : 17458 : retval = gbt_var_consistent(&r, query, strategy, PG_GET_COLLATION(),
3413 andrew@dunslane.net 127 : 8729 : GIST_LEAF(entry), &tinfo, fcinfo->flinfo);
8000 bruce@momjian.us 128 : 8729 : PG_RETURN_BOOL(retval);
129 : : }
130 : :
131 : : Datum
8093 teodor@sigaev.ru 132 : 1859 : gbt_numeric_union(PG_FUNCTION_ARGS)
133 : : {
8000 bruce@momjian.us 134 : 1859 : GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
135 : 1859 : int32 *size = (int *) PG_GETARG_POINTER(1);
136 : :
5573 tgl@sss.pgh.pa.us 137 : 1859 : PG_RETURN_POINTER(gbt_var_union(entryvec, size, PG_GET_COLLATION(),
138 : : &tinfo, fcinfo->flinfo));
139 : : }
140 : :
141 : : Datum
8093 teodor@sigaev.ru 142 : 1814 : gbt_numeric_same(PG_FUNCTION_ARGS)
143 : : {
8000 bruce@momjian.us 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 : :
3413 andrew@dunslane.net 148 : 1814 : *result = gbt_var_same(d1, d2, PG_GET_COLLATION(), &tinfo, fcinfo->flinfo);
5573 tgl@sss.pgh.pa.us 149 : 1814 : PG_RETURN_POINTER(result);
150 : : }
151 : :
152 : : Datum
8000 bruce@momjian.us 153 : 3474 : gbt_numeric_penalty(PG_FUNCTION_ARGS)
154 : : {
155 : 3474 : GISTENTRY *o = (GISTENTRY *) PG_GETARG_POINTER(0);
156 : 3474 : GISTENTRY *n = (GISTENTRY *) PG_GETARG_POINTER(1);
157 : 3474 : float *result = (float *) PG_GETARG_POINTER(2);
158 : :
159 : : Numeric us,
160 : : os,
161 : : ds;
162 : :
163 : 3474 : GBT_VARKEY *org = (GBT_VARKEY *) DatumGetPointer(o->key);
164 : 3474 : GBT_VARKEY *newe = (GBT_VARKEY *) DatumGetPointer(n->key);
165 : : Datum uni;
166 : : GBT_VARKEY_R rk,
167 : : ok,
168 : : uk;
169 : :
170 : 3474 : rk = gbt_var_key_readable(org);
4139 heikki.linnakangas@i 171 : 3474 : uni = PointerGetDatum(gbt_var_key_copy(&rk));
3413 andrew@dunslane.net 172 : 3474 : gbt_var_bin_union(&uni, newe, PG_GET_COLLATION(), &tinfo, fcinfo->flinfo);
8000 bruce@momjian.us 173 : 3474 : ok = gbt_var_key_readable(org);
174 : 3474 : uk = gbt_var_key_readable((GBT_VARKEY *) DatumGetPointer(uni));
175 : :
2368 alvherre@alvh.no-ip. 176 : 3474 : us = DatumGetNumeric(DirectFunctionCall2(numeric_sub,
177 : : PointerGetDatum(uk.upper),
178 : : PointerGetDatum(uk.lower)));
179 : :
180 : 3474 : os = DatumGetNumeric(DirectFunctionCall2(numeric_sub,
181 : : PointerGetDatum(ok.upper),
182 : : PointerGetDatum(ok.lower)));
183 : :
184 : 3474 : ds = DatumGetNumeric(DirectFunctionCall2(numeric_sub,
185 : : NumericGetDatum(us),
186 : : NumericGetDatum(os)));
187 : :
5839 rhaas@postgresql.org 188 [ - + ]: 3474 : if (numeric_is_nan(us))
189 : : {
5839 rhaas@postgresql.org 190 [ # # ]:UBC 0 : if (numeric_is_nan(os))
8000 bruce@momjian.us 191 : 0 : *result = 0.0;
192 : : else
193 : 0 : *result = 1.0;
194 : : }
195 : : else
196 : : {
2145 peter@eisentraut.org 197 :CBC 3474 : Numeric nul = int64_to_numeric(0);
198 : :
8000 bruce@momjian.us 199 : 3474 : *result = 0.0;
200 : :
351 peter@eisentraut.org 201 [ + + ]: 3474 : if (DatumGetBool(DirectFunctionCall2(numeric_gt, NumericGetDatum(ds), NumericGetDatum(nul))))
202 : : {
8000 bruce@momjian.us 203 : 14 : *result += FLT_MIN;
2368 alvherre@alvh.no-ip. 204 : 14 : os = DatumGetNumeric(DirectFunctionCall2(numeric_div,
205 : : NumericGetDatum(ds),
206 : : NumericGetDatum(us)));
8000 bruce@momjian.us 207 : 14 : *result += (float4) DatumGetFloat8(DirectFunctionCall1(numeric_float8_no_overflow, NumericGetDatum(os)));
208 : : }
209 : : }
210 : :
211 [ + + ]: 3474 : if (*result > 0)
212 : 14 : *result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1));
213 : :
214 : 3474 : PG_RETURN_POINTER(result);
215 : : }
216 : :
217 : : Datum
8093 teodor@sigaev.ru 218 : 24 : gbt_numeric_picksplit(PG_FUNCTION_ARGS)
219 : : {
8000 bruce@momjian.us 220 : 24 : GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
221 : 24 : GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
222 : :
5573 tgl@sss.pgh.pa.us 223 : 24 : gbt_var_picksplit(entryvec, v, PG_GET_COLLATION(),
224 : : &tinfo, fcinfo->flinfo);
8000 bruce@momjian.us 225 : 24 : PG_RETURN_POINTER(v);
226 : : }
227 : :
228 : : static int
478 heikki.linnakangas@i 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 : : }
|