1/*
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 *
6 * Copyright 1997 - July 2008 CWI, August 2008 - 2019 MonetDB B.V.
7 */
8
9/* ! ENSURE THAT THESE LOCAL MACROS ARE UNDEFINED AT THE END OF THIS FILE ! */
10
11/* stringify token */
12#define _STRNG_(s) #s
13#define STRNG(t) _STRNG_(t)
14
15/* concatenate two, three or four tokens */
16#define CONCAT_2(a,b) a##b
17#define CONCAT_3(a,b,c) a##b##c
18#define CONCAT_4(a,b,c,d) a##b##c##d
19
20#define NIL(t) CONCAT_2(t,_nil)
21#define ISNIL(t) CONCAT_3(is_,t,_nil)
22#define TPE(t) CONCAT_2(TYPE_,t)
23#define GDKmin(t) CONCAT_3(GDK_,t,_min)
24#define GDKmax(t) CONCAT_3(GDK_,t,_max)
25#define FUN(a,b,c,d) CONCAT_4(a,b,c,d)
26#define SIZEOF(t) CONCAT_2(SIZEOF_,t)
27
28#define SIZEOF_bte 1
29#define SIZEOF_sht 2
30#define SIZEOF_int 4
31#define SIZEOF_lng 8
32#ifdef HAVE_HGE
33#define SIZEOF_hge 16
34#endif
35
36/* sizeof(scales)/sizeof(scales[0]), see sql_atom.c */
37#ifdef HAVE_HGE
38#define MAXDIG 39
39#else
40#define MAXDIG 19
41#endif
42
43static inline str
44FUN(do_,TP1,_dec2dec_,TP2) (TP2 *restrict res, int s1, TP1 val, int p, int s2)
45{
46 int scale = s2 - s1;
47 if (ISNIL(TP1)(val)) {
48 *res = NIL(TP2);
49 return MAL_SUCCEED;
50 }
51 /* if p == 0, the destination is a "normal" integral type (not
52 * a decimal), so we need to check whether the converted
53 * source value fits in the domain of the type, else we need
54 * to check whether the number of decimal digits does or does
55 * not exceed the precision given in p */
56 assert(p >= 0 && p < MAXDIG);
57 assert(s1 >= 0 && s1 < MAXDIG);
58 assert(s2 >= 0 && s2 <= p);
59 if (p != 0 &&
60 p - scale < MAXDIG && /* note, p-scale >= 0 since p >= s2 and s1 >= 0 */
61 (val <= -scales[p - scale] || val >= scales[p - scale])) {
62 int inlen;
63 if (val < 0)
64 val = -val;
65 for (inlen = 1; inlen < MAXDIG; inlen++)
66 if (scales[inlen] > val)
67 break;
68 throw(SQL, STRNG(FUN(,TP1,_2_,TP2)), SQLSTATE(22003) "Too many digits (%d > %d)", inlen + scale, p);
69 }
70 if (scale >= 0) {
71#if SIZEOF(TP1) > SIZEOF(TP2)
72 if (p == 0 && /* this implies scale<=0, thus scale==0 */
73 (val < GDKmin(TP2) || val > GDKmax(TP2)))
74 throw(SQL, STRNG(FUN(,TP1,_2_,TP2)),
75 SQLSTATE(22003) "value exceeds limits of type " STRNG(TP2));
76#endif
77 *res = (TP2) (val * scales[scale]);
78 } else {
79 scale = -scale; /* i.e. scale > 0 now */
80 if (p == 0 &&
81 (val / scales[scale] < GDKmin(TP2) ||
82 val / scales[scale] > GDKmax(TP2)))
83 throw(SQL, STRNG(FUN(,TP1,_2_,TP2)),
84 SQLSTATE(22003) "value exceeds limits of type " STRNG(TP2));
85 *res = (TP2) ((val
86#ifndef TRUNCATE_NUMBERS
87 + (val < 0 ? -5 : 5) * scales[scale - 1]
88#endif
89 )
90 / scales[scale]);
91 }
92 return MAL_SUCCEED;
93}
94
95str
96FUN(,TP1,_dec2_,TP2) (TP2 *res, const int *s1, const TP1 *v)
97{
98 return FUN(do_,TP1,_dec2dec_,TP2) (res, *s1, *v, 0, 0);
99}
100
101str
102FUN(,TP1,_dec2dec_,TP2) (TP2 *res, const int *S1, const TP1 *v, const int *d2, const int *S2)
103{
104 return FUN(do_,TP1,_dec2dec_,TP2) (res, *S1, *v, *d2, *S2);
105}
106
107str
108FUN(,TP1,_num2dec_,TP2) (TP2 *res, const TP1 *v, const int *d2, const int *s2)
109{
110 return FUN(do_,TP1,_dec2dec_,TP2)(res, 0, *v, *d2, *s2);
111}
112
113str
114FUN(bat,TP1,_dec2_,TP2) (bat *res, const int *s1, const bat *bid)
115{
116 BAT *b, *bn;
117 BUN p, q;
118 char *msg = NULL;
119 int scale = *s1;
120
121 if ((b = BATdescriptor(*bid)) == NULL) {
122 throw(SQL, "batcalc."STRNG(FUN(,TP1,_dec2_,TP2)), SQLSTATE(HY005) "Cannot access descriptor");
123 }
124 bn = COLnew(b->hseqbase, TPE(TP2), BATcount(b), TRANSIENT);
125 if (bn == NULL) {
126 BBPunfix(b->batCacheid);
127 throw(SQL, "sql."STRNG(FUN(dec,TP1,_2_,TP2)), SQLSTATE(HY001) MAL_MALLOC_FAIL);
128 }
129 const TP1 *vals = (const TP1 *) Tloc(b, 0);
130 TP2 *o = (TP2 *) Tloc(bn, 0);
131 BATloop(b, p, q) {
132 msg = FUN(do_,TP1,_dec2dec_,TP2)(o, scale, vals[p], 0, 0);
133 if (msg) {
134 BBPreclaim(bn);
135 BBPunfix(b->batCacheid);
136 return msg;
137 }
138 o++;
139 }
140 BATsetcount(bn, BATcount(b));
141 bn->tnonil = b->tnonil;
142 bn->tnil = b->tnil;
143 bn->tsorted = false;
144 bn->trevsorted = false;
145 BATkey(bn, false);
146
147 BBPkeepref(*res = bn->batCacheid);
148 BBPunfix(b->batCacheid);
149 return MAL_SUCCEED;
150}
151
152str
153FUN(bat,TP1,_dec2dec_,TP2) (bat *res, const int *S1, const bat *bid, const int *d2, const int *S2)
154{
155 BAT *b, *bn;
156 BUN p, q;
157 char *msg = NULL;
158
159 if ((b = BATdescriptor(*bid)) == NULL) {
160 throw(SQL, "batcalc."STRNG(FUN(,TP1,_dec2dec_,TP2)), SQLSTATE(HY005) "Cannot access descriptor");
161 }
162 bn = COLnew(b->hseqbase, TPE(TP2), BATcount(b), TRANSIENT);
163 if (bn == NULL) {
164 BBPunfix(b->batCacheid);
165 throw(SQL, "sql."STRNG(FUN(,TP1,_dec2dec_,TP2)), SQLSTATE(HY001) MAL_MALLOC_FAIL);
166 }
167 const TP1 *vals = (const TP1 *) Tloc(b, 0);
168 TP2 *o = (TP2 *) Tloc(bn, 0);
169 BATloop(b, p, q) {
170 msg = FUN(do_,TP1,_dec2dec_,TP2)(o, *S1, vals[p], *d2, *S2);
171 if (msg) {
172 BBPunfix(bn->batCacheid);
173 BBPunfix(b->batCacheid);
174 return msg;
175 }
176 o++;
177 }
178 BATsetcount(bn, BATcount(b));
179 bn->tnonil = b->tnonil;
180 bn->tnil = b->tnil;
181 bn->tsorted = false;
182 bn->trevsorted = false;
183 BATkey(bn, false);
184
185 BBPkeepref(*res = bn->batCacheid);
186 BBPunfix(b->batCacheid);
187 return msg;
188}
189
190str
191FUN(bat,TP1,_num2dec_,TP2) (bat *res, const bat *bid, const int *d2, const int *s2)
192{
193 BAT *b, *bn;
194 BUN p, q;
195 char *msg = NULL;
196
197 if ((b = BATdescriptor(*bid)) == NULL) {
198 throw(SQL, "batcalc."STRNG(FUN(,TP1,_num2dec_,TP2)), SQLSTATE(HY005) "Cannot access descriptor");
199 }
200 bn = COLnew(b->hseqbase, TPE(TP2), BATcount(b), TRANSIENT);
201 if (bn == NULL) {
202 BBPunfix(b->batCacheid);
203 throw(SQL, "sql."STRNG(FUN(,TP1,_num2dec_,TP2)), SQLSTATE(HY001) MAL_MALLOC_FAIL);
204 }
205 const TP1 *vals = (const TP1 *) Tloc(b, 0);
206 TP2 *o = (TP2 *) Tloc(bn, 0);
207 BATloop(b, p, q) {
208 msg = FUN(do_,TP1,_dec2dec_,TP2)(o, 0, vals[p], *d2, *s2);
209 if (msg) {
210 BBPunfix(bn->batCacheid);
211 BBPunfix(b->batCacheid);
212 return msg;
213 }
214 o++;
215 }
216 BATsetcount(bn, BATcount(b));
217 bn->tnonil = b->tnonil;
218 bn->tnil = b->tnil;
219 bn->tsorted = false;
220 bn->trevsorted = false;
221 BATkey(bn, false);
222
223 BBPkeepref(*res = bn->batCacheid);
224 BBPunfix(b->batCacheid);
225 return msg;
226}
227
228
229/* undo local defines */
230#undef FUN
231#undef NIL
232#undef ISNIL
233#undef TPE
234#undef GDKmin
235#undef GDKmax
236#undef CONCAT_2
237#undef CONCAT_3
238#undef CONCAT_4
239#undef STRNG
240#undef _STRNG_
241
242