1#include "catch.hpp"
2#include "duckdb/common/operator/cast_operators.hpp"
3#include "duckdb/common/string_util.hpp"
4#include "duckdb/common/limits.hpp"
5#include "duckdb/common/types.hpp"
6#include "duckdb/common/types/vector.hpp"
7#include <vector>
8
9using namespace duckdb;
10using namespace std;
11
12template <class SRC, class DST> static void TestNumericCast(vector<SRC> &working_values, vector<SRC> &broken_values) {
13 DST result;
14 for (auto value : working_values) {
15 REQUIRE_NOTHROW(Cast::Operation<SRC, DST>(value) == (DST)value);
16 REQUIRE(TryCast::Operation<SRC, DST>(value, result));
17 REQUIRE(result == (DST)value);
18 }
19 for (auto value : broken_values) {
20 REQUIRE_THROWS(Cast::Operation<SRC, DST>(value));
21 REQUIRE(!TryCast::Operation<SRC, DST>(value, result));
22 }
23}
24
25template <class DST>
26static void TestStringCast(vector<string> &working_values, vector<DST> &expected_values,
27 vector<string> &broken_values) {
28 DST result;
29 for (idx_t i = 0; i < working_values.size(); i++) {
30 auto &value = working_values[i];
31 auto expected_value = expected_values[i];
32 REQUIRE_NOTHROW(Cast::Operation<string_t, DST>(string_t(value)) == expected_value);
33 REQUIRE(TryCast::Operation<string_t, DST>(string_t(value), result));
34 REQUIRE(result == expected_value);
35
36 StringUtil::Trim(value);
37 vector<string> splits;
38 splits = StringUtil::Split(value, 'e');
39 if (splits.size() > 1) {
40 continue;
41 }
42 splits = StringUtil::Split(value, '.');
43 REQUIRE(Cast::Operation<DST, string>(result) == splits[0]);
44 }
45 for (auto &value : broken_values) {
46 REQUIRE_THROWS(Cast::Operation<string_t, DST>(string_t(value)));
47 REQUIRE(!TryCast::Operation<string_t, DST>(string_t(value), result));
48 }
49}
50
51template <class T> static void TestExponent() {
52 T parse_result;
53 string str;
54 double value = 1;
55 T expected_value = 1;
56 for (idx_t exponent = 0; exponent < 100; exponent++) {
57 if (value < MaximumValue<T>()) {
58 // expect success
59 str = "1e" + to_string(exponent);
60 REQUIRE(TryCast::Operation<string_t, T>(string_t(str), parse_result));
61 REQUIRE(parse_result == expected_value);
62 str = "-1e" + to_string(exponent);
63 REQUIRE(TryCast::Operation<string_t, T>(string_t(str), parse_result));
64 REQUIRE(parse_result == -expected_value);
65 value *= 10;
66 expected_value *= 10;
67 } else {
68 // expect failure
69 str = "1e" + to_string(exponent);
70 REQUIRE(!TryCast::Operation<string_t, T>(string_t(str), parse_result));
71 str = "-1e" + to_string(exponent);
72 REQUIRE(!TryCast::Operation<string_t, T>(string_t(str), parse_result));
73 }
74 }
75}
76
77TEST_CASE("Test casting to boolean", "[cast]") {
78 vector<string> working_values = {"true", "false", "TRUE", "FALSE", "T", "F"};
79 vector<bool> expected_values = {true, false, true, false, true, false};
80 vector<string> broken_values = {"1", "blabla", "", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaa"};
81
82 bool result;
83 for (idx_t i = 0; i < working_values.size(); i++) {
84 auto &value = working_values[i];
85 auto expected_value = expected_values[i];
86 REQUIRE_NOTHROW(Cast::Operation<string_t, bool>(value) == expected_value);
87 REQUIRE(TryCast::Operation<string_t, bool>(value, result));
88 REQUIRE(result == expected_value);
89 }
90 for (auto &value : broken_values) {
91 REQUIRE_THROWS(Cast::Operation<string_t, bool>(value));
92 REQUIRE(!TryCast::Operation<string_t, bool>(value, result));
93 }
94}
95
96TEST_CASE("Test casting to int8_t", "[cast]") {
97 // int16_t -> int8_t
98 vector<int16_t> working_values_int16 = {10, -10, 127, -127};
99 vector<int16_t> broken_values_int16 = {128, -128, 1000, -1000};
100 TestNumericCast<int16_t, int8_t>(working_values_int16, broken_values_int16);
101 // int32_t -> int8_t
102 vector<int32_t> working_values_int32 = {10, -10, 127, -127};
103 vector<int32_t> broken_values_int32 = {128, -128, 1000000, -1000000};
104 TestNumericCast<int32_t, int8_t>(working_values_int32, broken_values_int32);
105 // int64_t -> int8_t
106 vector<int64_t> working_values_int64 = {10, -10, 127, -127};
107 vector<int64_t> broken_values_int64 = {128, -128, 10000000000, -10000000000};
108 TestNumericCast<int64_t, int8_t>(working_values_int64, broken_values_int64);
109 // float -> int8_t
110 vector<float> working_values_float = {10, -10, 127, -127, 1.3f, -2.7f};
111 vector<float> broken_values_float = {128, -128, 10000000000, -10000000000, 1e30f, -1e30f};
112 TestNumericCast<float, int8_t>(working_values_float, broken_values_float);
113 // double -> int8_t
114 vector<double> working_values_double = {10, -10, 127, -127, 1.3, -2.7};
115 vector<double> broken_values_double = {128, -128, 10000000000, -10000000000, 1e100, -1e100};
116 TestNumericCast<double, int8_t>(working_values_double, broken_values_double);
117 // string -> int8_t
118 vector<string> working_values_str = {"10", "-10", "127", "-127", "1.3", "1e2", "2e1",
119 "2e0", "20e-1", "1.", " 3", " 3 ", "\t3 \t \n"};
120 vector<int8_t> expected_values_str = {10, -10, 127, -127, 1, 100, 20, 2, 2, 1, 3, 3, 3};
121 vector<string> broken_values_str = {
122 "128", "-128", "10000000000000000000000000000000000000000000000000000000000000",
123 "aaaa", "19A", "",
124 "1e3", "1e", "1e-",
125 "1e100", "1e100000000", "1000e-1",
126 " 3 2"};
127 TestStringCast<int8_t>(working_values_str, expected_values_str, broken_values_str);
128 TestExponent<int8_t>();
129}
130
131TEST_CASE("Test casting to int16_t", "[cast]") {
132 // int32_t -> int16_t
133 vector<int32_t> working_values_int32 = {10, -10, 127, -127, 32767, -32767};
134 vector<int32_t> broken_values_int32 = {32768, -32768, 1000000, -1000000};
135 TestNumericCast<int32_t, int16_t>(working_values_int32, broken_values_int32);
136 // int64_t -> int16_t
137 vector<int64_t> working_values_int64 = {10, -10, 127, -127, 32767, -32767};
138 vector<int64_t> broken_values_int64 = {32768, -32768, 10000000000, -10000000000};
139 TestNumericCast<int64_t, int16_t>(working_values_int64, broken_values_int64);
140 // float -> int16_t
141 vector<float> working_values_float = {10.0f, -10.0f, 32767.0f, -32767.0f, 1.3f, -2.7f};
142 vector<float> broken_values_float = {32768.0f, -32768.0f, 10000000000.0f, -10000000000.0f, 1e30f, -1e30f};
143 TestNumericCast<float, int16_t>(working_values_float, broken_values_float);
144 // double -> int16_t
145 vector<double> working_values_double = {10, -10, 32767, -32767, 1.3, -2.7};
146 vector<double> broken_values_double = {32768, -32768, 10000000000, -10000000000, 1e100, -1e100};
147 TestNumericCast<double, int16_t>(working_values_double, broken_values_double);
148 // string -> int16_t
149 vector<string> working_values_str = {"10", "-10", "32767", "-32767", "1.3", "3e4", "250e2"};
150 vector<int16_t> expected_values_str = {10, -10, 32767, -32767, 1, 30000, 25000};
151 vector<string> broken_values_str = {
152 "32768", "-32768", "10000000000000000000000000000000000000000000000000000000000000",
153 "aaaa", "19A", "",
154 "1.A", "1e", "1e-",
155 "1e100", "1e100000000"};
156 TestStringCast<int16_t>(working_values_str, expected_values_str, broken_values_str);
157 TestExponent<int16_t>();
158}
159
160TEST_CASE("Test casting to int32_t", "[cast]") {
161 // int64_t -> int32_t
162 vector<int64_t> working_values_int64 = {10, -10, 127, -127, 32767, -32767, 2147483647, -2147483647};
163 vector<int64_t> broken_values_int64 = {2147483648LL, -2147483648LL, 10000000000LL, -10000000000LL};
164 TestNumericCast<int64_t, int32_t>(working_values_int64, broken_values_int64);
165 // float -> int32_t
166 vector<float> working_values_float = {10.0f, -10.0f, 2000000000.0f, -2000000000.0f, 1.3f, -2.7f};
167 vector<float> broken_values_float = {3000000000.0f, -3000000000.0f, 10000000000.0f, -10000000000.0f, 1e30f, -1e30f};
168 TestNumericCast<float, int32_t>(working_values_float, broken_values_float);
169 // double -> int32_t
170 vector<double> working_values_double = {10, -10, 32767.0, -32767.0, 1.3, -2.7, 2147483647.0, -2147483647.0};
171 vector<double> broken_values_double = {2147483648.0, -2147483648.0, 10000000000.0, -10000000000.0, 1e100, -1e100};
172 TestNumericCast<double, int32_t>(working_values_double, broken_values_double);
173 // string -> int32_t
174 vector<string> working_values_str = {"10", "-10", "2147483647", "-2147483647", "1.3", "-1.3", "1e6"};
175 vector<int32_t> expected_values_str = {10, -10, 2147483647, -2147483647, 1, -1, 1000000};
176 vector<string> broken_values_str = {
177 "2147483648", "-2147483648", "10000000000000000000000000000000000000000000000000000000000000",
178 "aaaa", "19A", "",
179 "1.A", "1e1e1e1"};
180 TestStringCast<int32_t>(working_values_str, expected_values_str, broken_values_str);
181 TestExponent<int32_t>();
182}
183
184TEST_CASE("Test casting to int64_t", "[cast]") {
185 // float -> int64_t
186 vector<float> working_values_float = {10.0f,
187 -10.0f,
188 32767.0f,
189 -32767.0f,
190 1.3f,
191 -2.7f,
192 2000000000.0f,
193 -2000000000.0f,
194 4000000000000000000.0f,
195 -4000000000000000000.0f};
196 vector<float> broken_values_float = {20000000000000000000.0f, -20000000000000000000.0f, 1e30f, -1e30f};
197 TestNumericCast<float, int64_t>(working_values_float, broken_values_float);
198 // double -> int64_t
199 vector<double> working_values_double = {
200 10, -10, 32767, -32767, 1.3, -2.7, 2147483647, -2147483647.0, 4611686018427387904.0, -4611686018427387904.0};
201 vector<double> broken_values_double = {18446744073709551616.0, -18446744073709551616.0, 1e100, -1e100};
202 TestNumericCast<double, int64_t>(working_values_double, broken_values_double);
203 // string -> int64_t
204 vector<string> working_values_str = {
205 "10", "-10", "9223372036854775807", "-9223372036854775807", "1.3", "-9223372036854775807.1293813",
206 "1e18", "1."};
207 vector<int64_t> expected_values_str = {
208 10, -10, 9223372036854775807LL, -9223372036854775807LL, 1, -9223372036854775807LL, 1000000000000000000LL, 1};
209 vector<string> broken_values_str = {"9223372036854775808",
210 "-9223372036854775808",
211 "10000000000000000000000000000000000000000000000000000000000000",
212 "aaaa",
213 "19A",
214 "",
215 "1.A",
216 "1.2382398723A"};
217 TestStringCast<int64_t>(working_values_str, expected_values_str, broken_values_str);
218 TestExponent<int64_t>();
219}
220
221template <class DST>
222static void TestStringCastDouble(vector<string> &working_values, vector<DST> &expected_values,
223 vector<string> &broken_values) {
224 DST result;
225 for (idx_t i = 0; i < working_values.size(); i++) {
226 auto &value = working_values[i];
227 auto expected_value = expected_values[i];
228 REQUIRE_NOTHROW(Cast::Operation<string_t, DST>(string_t(value)) == expected_value);
229 REQUIRE(TryCast::Operation<string_t, DST>(string_t(value), result));
230 REQUIRE(ApproxEqual(result, expected_value));
231
232 auto to_str_and_back = Cast::Operation<string_t, DST>(string_t(Cast::Operation<DST, string>(expected_value)));
233 REQUIRE(ApproxEqual(to_str_and_back, expected_value));
234 }
235 for (auto &value : broken_values) {
236 REQUIRE_THROWS(Cast::Operation<string_t, DST>(string_t(value)));
237 REQUIRE(!TryCast::Operation<string_t, DST>(string_t(value), result));
238 }
239}
240
241TEST_CASE("Test casting to float", "[cast]") {
242 // string -> float
243 vector<string> working_values = {"1.3",
244 "1.34514",
245 "1e10",
246 "1e-2",
247 "-1e-1",
248 "1.2e12.3",
249 "1.1781237378938173987123987123981723981723981723987123",
250 "1.123456789",
251 "1."};
252 vector<float> expected_values = {
253 1.3f, 1.34514f, 1e10f, 1e-2f, -1e-1f, 1.2e12f, 1.1781237378938173987123987123981723981723981723987123f,
254 1.123456789f, 1.0f};
255 vector<string> broken_values = {
256 "-", "", "aaa",
257 "12aaa", "1e10e10", "1e",
258 "1e-", "1e10a", "1.1781237378938173987123987123981723981723981723934834583490587123w",
259 "1.2.3"};
260 TestStringCastDouble<float>(working_values, expected_values, broken_values);
261}
262
263TEST_CASE("Test casting to double", "[cast]") {
264 // string -> double
265 vector<string> working_values = {"1.3",
266 "1.34514",
267 "1e10",
268 "1e-2",
269 "-1e-1",
270 "1.2e12.3",
271 "1.1781237378938173987123987123981723981723981723987123",
272 "1.123456789",
273 "1.",
274 "-1.2",
275 "-1.2e1",
276 " 1.2 ",
277 " 1.2e2 ",
278 " \t 1.2e2 \t",
279 "1.2e 2"};
280 vector<double> expected_values = {
281 1.3, 1.34514, 1e10, 1e-2, -1e-1, 1.2e12, 1.1781237378938173987123987123981723981723981723987123,
282 1.123456789, 1.0, -1.2, -12, 1.2, 120, 120,
283 120};
284 vector<string> broken_values = {
285 "-", "", "aaa",
286 "12aaa", "1e10e10", "1e",
287 "1e-", "1e10a", "1.1781237378938173987123987123981723981723981723934834583490587123w",
288 "1.2.3", "1.222.", "1..",
289 "1 . 2", "1. 2", "1.2 e20"};
290 TestStringCastDouble<double>(working_values, expected_values, broken_values);
291}
292