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 | /* This file is included multiple times (from sql_cast.c). |
10 | * We expect the tokens TP1 & TP2 to be defined by the including file. |
11 | */ |
12 | |
13 | /* ! ENSURE THAT THESE LOCAL MACROS ARE UNDEFINED AT THE END OF THIS FILE ! */ |
14 | |
15 | /* stringify token */ |
16 | #define _STRNG_(s) #s |
17 | #define STRNG(t) _STRNG_(t) |
18 | |
19 | /* concatenate two or four tokens */ |
20 | #define CONCAT_2(a,b) a##b |
21 | #define CONCAT_3(a,b,c) a##b##c |
22 | #define CONCAT_4(a,b,c,d) a##b##c##d |
23 | |
24 | #define NIL(t) CONCAT_2(t,_nil) |
25 | #define ISNIL(t) CONCAT_3(is_,t,_nil) |
26 | #define TPE(t) CONCAT_2(TYPE_,t) |
27 | #define FUN(a,b,c,d) CONCAT_4(a,b,c,d) |
28 | |
29 | |
30 | str |
31 | FUN(,TP1,_dec2_,TP2) (TP2 *res, const int *s1, const TP1 *v) |
32 | { |
33 | int scale = *s1; |
34 | TP2 r; |
35 | |
36 | /* shortcut nil */ |
37 | if (ISNIL(TP1)(*v)) { |
38 | *res = NIL(TP2); |
39 | return (MAL_SUCCEED); |
40 | } |
41 | |
42 | /* since the TP2 type is bigger than or equal to the TP1 type, it will |
43 | always fit */ |
44 | r = (TP2) *v; |
45 | if (scale) |
46 | r /= scales[scale]; |
47 | *res = r; |
48 | return MAL_SUCCEED; |
49 | } |
50 | |
51 | str |
52 | FUN(,TP1,_dec2dec_,TP2) (TP2 *res, const int *S1, const TP1 *v, const int *d2, const int *S2) |
53 | { |
54 | int p = *d2, inlen = 1; |
55 | TP1 cpyval = *v; |
56 | int s1 = *S1, s2 = *S2; |
57 | TP2 r; |
58 | |
59 | /* shortcut nil */ |
60 | if (ISNIL(TP1)(*v)) { |
61 | *res = NIL(TP2); |
62 | return (MAL_SUCCEED); |
63 | } |
64 | |
65 | /* count the number of digits in the input */ |
66 | while (cpyval /= 10) |
67 | inlen++; |
68 | /* rounding is allowed */ |
69 | inlen += (s2 - s1); |
70 | if (p && inlen > p) { |
71 | throw(SQL, "convert" , SQLSTATE(22003) "too many digits (%d > %d)" , inlen, p); |
72 | } |
73 | |
74 | /* since the TP2 type is bigger than or equal to the TP1 type, it will |
75 | always fit */ |
76 | r = (TP2) *v; |
77 | if (s2 > s1) |
78 | r *= scales[s2 - s1]; |
79 | else if (s2 != s1) |
80 | r /= scales[s1 - s2]; |
81 | *res = r; |
82 | return MAL_SUCCEED; |
83 | } |
84 | |
85 | str |
86 | FUN(,TP1,_num2dec_,TP2) (TP2 *res, const TP1 *v, const int *d2, const int *s2) |
87 | { |
88 | int zero = 0; |
89 | return FUN(,TP1,_dec2dec_,TP2)(res, &zero, v, d2, s2); |
90 | } |
91 | |
92 | str |
93 | FUN(bat,TP1,_dec2_,TP2) (bat *res, const int *s1, const bat *bid) |
94 | { |
95 | BAT *b, *bn; |
96 | TP1 *p, *q; |
97 | char *msg = NULL; |
98 | int scale = *s1; |
99 | TP2 *o; |
100 | |
101 | if ((b = BATdescriptor(*bid)) == NULL) { |
102 | throw(SQL, "batcalc." STRNG(FUN(,TP1,_dec2_,TP2)), SQLSTATE(HY005) "Cannot access column descriptor" ); |
103 | } |
104 | bn = COLnew(b->hseqbase, TPE(TP2), BATcount(b), TRANSIENT); |
105 | if (bn == NULL) { |
106 | BBPunfix(b->batCacheid); |
107 | throw(SQL, "sql." STRNG(FUN(,TP1,_dec2_,TP2)), SQLSTATE(HY001) MAL_MALLOC_FAIL); |
108 | } |
109 | o = (TP2 *) Tloc(bn, 0); |
110 | p = (TP1 *) Tloc(b, 0); |
111 | q = (TP1 *) Tloc(b, BUNlast(b)); |
112 | bn->tnonil = true; |
113 | if (b->tnonil) { |
114 | for (; p < q; p++, o++) |
115 | *o = (((TP2) *p) / scales[scale]); |
116 | } else { |
117 | for (; p < q; p++, o++) { |
118 | if (ISNIL(TP1)(*p)) { |
119 | *o = NIL(TP2); |
120 | bn->tnonil = false; |
121 | } else |
122 | *o = (((TP2) *p) / scales[scale]); |
123 | } |
124 | } |
125 | BATsetcount(bn, BATcount(b)); |
126 | bn->tsorted = false; |
127 | bn->trevsorted = false; |
128 | BATkey(bn, false); |
129 | |
130 | BBPkeepref(*res = bn->batCacheid); |
131 | BBPunfix(b->batCacheid); |
132 | return msg; |
133 | } |
134 | |
135 | str |
136 | FUN(bat,TP1,_dec2dec_,TP2) (bat *res, const int *S1, const bat *bid, const int *d2, const int *S2) |
137 | { |
138 | BAT *b, *dst; |
139 | BUN p, q; |
140 | char *msg = NULL; |
141 | |
142 | if ((b = BATdescriptor(*bid)) == NULL) { |
143 | throw(SQL, "batcalc." STRNG(FUN(,TP1,_dec2dec_,TP2)), SQLSTATE(HY005) "Cannot access column descriptor" ); |
144 | } |
145 | dst = COLnew(b->hseqbase, TPE(TP2), BATcount(b), TRANSIENT); |
146 | if (dst == NULL) { |
147 | BBPunfix(b->batCacheid); |
148 | throw(SQL, "sql." STRNG(FUN(,TP1,_dec2dec_,TP2)), SQLSTATE(HY001) MAL_MALLOC_FAIL); |
149 | } |
150 | const TP1 *v = (const TP1 *) Tloc(b, 0); |
151 | BATloop(b, p, q) { |
152 | TP2 r; |
153 | msg = FUN(,TP1,_dec2dec_,TP2)(&r, S1, v, d2, S2); |
154 | if (msg) { |
155 | BBPunfix(dst->batCacheid); |
156 | BBPunfix(b->batCacheid); |
157 | return msg; |
158 | } |
159 | if (BUNappend(dst, &r, false) != GDK_SUCCEED) { |
160 | BBPunfix(dst->batCacheid); |
161 | BBPunfix(b->batCacheid); |
162 | throw(SQL, "sql." STRNG(FUN(,TP1,_dec2dec_,TP2)), SQLSTATE(HY001) MAL_MALLOC_FAIL); |
163 | } |
164 | v++; |
165 | } |
166 | BBPkeepref(*res = dst->batCacheid); |
167 | BBPunfix(b->batCacheid); |
168 | return msg; |
169 | } |
170 | |
171 | str |
172 | FUN(bat,TP1,_num2dec_,TP2) (bat *res, const bat *bid, const int *d2, const int *s2) |
173 | { |
174 | BAT *b, *dst; |
175 | BUN p, q; |
176 | char *msg = NULL; |
177 | |
178 | if ((b = BATdescriptor(*bid)) == NULL) { |
179 | throw(SQL, "batcalc." STRNG(FUN(,TP1,_num2dec_,TP2)), SQLSTATE(HY005) "Cannot access column descriptor" ); |
180 | } |
181 | dst = COLnew(b->hseqbase, TPE(TP2), BATcount(b), TRANSIENT); |
182 | if (dst == NULL) { |
183 | BBPunfix(b->batCacheid); |
184 | throw(SQL, "sql." STRNG(FUN(,TP1,_num2dec_,TP2)), SQLSTATE(HY001) MAL_MALLOC_FAIL); |
185 | } |
186 | const TP1 *v = (const TP1 *) Tloc(b, 0); |
187 | BATloop(b, p, q) { |
188 | TP2 r; |
189 | msg = FUN(,TP1,_num2dec_,TP2)(&r, v, d2, s2); |
190 | if (msg) { |
191 | BBPunfix(dst->batCacheid); |
192 | BBPunfix(b->batCacheid); |
193 | return msg; |
194 | } |
195 | if (BUNappend(dst, &r, false) != GDK_SUCCEED) { |
196 | BBPunfix(dst->batCacheid); |
197 | BBPunfix(b->batCacheid); |
198 | throw(SQL, "sql." STRNG(FUN(,TP1,_num2dec_,TP2)), SQLSTATE(HY001) MAL_MALLOC_FAIL); |
199 | } |
200 | v++; |
201 | } |
202 | BBPkeepref(*res = dst->batCacheid); |
203 | BBPunfix(b->batCacheid); |
204 | return msg; |
205 | } |
206 | |
207 | |
208 | /* undo local defines */ |
209 | #undef FUN |
210 | #undef ISNIL |
211 | #undef NIL |
212 | #undef TPE |
213 | #undef CONCAT_2 |
214 | #undef CONCAT_3 |
215 | #undef CONCAT_4 |
216 | #undef STRNG |
217 | #undef _STRNG_ |
218 | |
219 | |