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
30str
31FUN(,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
51str
52FUN(,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
85str
86FUN(,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
92str
93FUN(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
135str
136FUN(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
171str
172FUN(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