1 // Licensed to the Apache Software Foundation (ASF) under one
2 // or more contributor license agreements. See the NOTICE file
3 // distributed with this work for additional information
4 // regarding copyright ownership. The ASF licenses this file
5 // to you under the Apache License, Version 2.0 (the
6 // "License"); you may not use this file except in compliance
7 // with the License. You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing,
12 // software distributed under the License is distributed on an
13 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 // KIND, either express or implied. See the License for the
15 // specific language governing permissions and limitations
16 // under the License.
17
18 #include <memory>
19 #include <string>
20 #include <unordered_set>
21 #include <utility>
22 #include <vector>
23
24 #include <gtest/gtest.h>
25
26 #include "arrow/buffer.h"
27 #include "arrow/memory_pool.h"
28 #include "arrow/scalar.h"
29 #include "arrow/status.h"
30 #include "arrow/testing/gtest_util.h"
31 #include "arrow/type_traits.h"
32
33 namespace arrow {
34
35 using internal::checked_cast;
36
TEST(TestNullScalar,Basics)37 TEST(TestNullScalar, Basics) {
38 NullScalar scalar;
39 ASSERT_FALSE(scalar.is_valid);
40 ASSERT_TRUE(scalar.type->Equals(*null()));
41 }
42
43 template <typename T>
44 class TestNumericScalar : public ::testing::Test {
45 public:
TestNumericScalar()46 TestNumericScalar() {}
47 };
48
49 TYPED_TEST_SUITE(TestNumericScalar, NumericArrowTypes);
50
TYPED_TEST(TestNumericScalar,Basics)51 TYPED_TEST(TestNumericScalar, Basics) {
52 using T = typename TypeParam::c_type;
53 using ScalarType = typename TypeTraits<TypeParam>::ScalarType;
54
55 T value = static_cast<T>(1);
56
57 auto scalar_val = std::make_shared<ScalarType>(value);
58 ASSERT_EQ(value, scalar_val->value);
59 ASSERT_TRUE(scalar_val->is_valid);
60
61 auto expected_type = TypeTraits<TypeParam>::type_singleton();
62 ASSERT_TRUE(scalar_val->type->Equals(*expected_type));
63
64 T other_value = static_cast<T>(2);
65 auto scalar_other = std::make_shared<ScalarType>(other_value);
66 ASSERT_NE(*scalar_other, *scalar_val);
67
68 scalar_val->value = other_value;
69 ASSERT_EQ(other_value, scalar_val->value);
70 ASSERT_EQ(*scalar_other, *scalar_val);
71
72 ScalarType stack_val;
73 ASSERT_FALSE(stack_val.is_valid);
74
75 auto null_value = std::make_shared<ScalarType>();
76 ASSERT_FALSE(null_value->is_valid);
77
78 // Nulls should be equals to itself following Array::Equals
79 ASSERT_EQ(*null_value, stack_val);
80
81 auto dyn_null_value = MakeNullScalar(expected_type);
82 ASSERT_EQ(*null_value, *dyn_null_value);
83 }
84
TYPED_TEST(TestNumericScalar,Hashing)85 TYPED_TEST(TestNumericScalar, Hashing) {
86 using T = typename TypeParam::c_type;
87 using ScalarType = typename TypeTraits<TypeParam>::ScalarType;
88
89 std::unordered_set<std::shared_ptr<Scalar>, Scalar::Hash, Scalar::PtrsEqual> set;
90 for (T i = 0; i < 10; ++i) {
91 set.emplace(std::make_shared<ScalarType>(i));
92 }
93
94 for (T i = 0; i < 10; ++i) {
95 ASSERT_FALSE(set.emplace(std::make_shared<ScalarType>(i)).second);
96 }
97 }
98
TYPED_TEST(TestNumericScalar,MakeScalar)99 TYPED_TEST(TestNumericScalar, MakeScalar) {
100 using T = typename TypeParam::c_type;
101 using ScalarType = typename TypeTraits<TypeParam>::ScalarType;
102 auto type = TypeTraits<TypeParam>::type_singleton();
103
104 std::shared_ptr<Scalar> three = MakeScalar(static_cast<T>(3));
105 ASSERT_EQ(ScalarType(3), *three);
106
107 ASSERT_OK_AND_ASSIGN(three, MakeScalar(type, static_cast<T>(3)));
108 ASSERT_EQ(ScalarType(3), *three);
109
110 ASSERT_OK_AND_ASSIGN(three, Scalar::Parse(type, "3"));
111 ASSERT_EQ(ScalarType(3), *three);
112 }
113
TEST(TestBinaryScalar,Basics)114 TEST(TestBinaryScalar, Basics) {
115 std::string data = "test data";
116 auto buf = std::make_shared<Buffer>(data);
117
118 BinaryScalar value(buf);
119 ASSERT_TRUE(value.value->Equals(*buf));
120 ASSERT_TRUE(value.is_valid);
121 ASSERT_TRUE(value.type->Equals(*binary()));
122
123 auto ref_count = buf.use_count();
124 // Check that destructor doesn't fail to clean up a buffer
125 std::shared_ptr<Scalar> base_ref = std::make_shared<BinaryScalar>(buf);
126 base_ref = nullptr;
127 ASSERT_EQ(ref_count, buf.use_count());
128
129 BinaryScalar null_value;
130 ASSERT_FALSE(null_value.is_valid);
131
132 StringScalar value2(buf);
133 ASSERT_TRUE(value2.value->Equals(*buf));
134 ASSERT_TRUE(value2.is_valid);
135 ASSERT_TRUE(value2.type->Equals(*utf8()));
136
137 // Same buffer, different type.
138 ASSERT_NE(value2, value);
139
140 StringScalar value3(buf);
141 // Same buffer, same type.
142 ASSERT_EQ(value2, value3);
143
144 StringScalar null_value2;
145 ASSERT_FALSE(null_value2.is_valid);
146 }
147
TEST(TestStringScalar,MakeScalar)148 TEST(TestStringScalar, MakeScalar) {
149 auto three = MakeScalar("three");
150 ASSERT_EQ(StringScalar("three"), *three);
151
152 ASSERT_OK_AND_ASSIGN(three, MakeScalar(utf8(), Buffer::FromString("three")));
153 ASSERT_EQ(StringScalar("three"), *three);
154
155 ASSERT_OK_AND_ASSIGN(three, Scalar::Parse(utf8(), "three"));
156 ASSERT_EQ(StringScalar("three"), *three);
157 }
158
TEST(TestFixedSizeBinaryScalar,Basics)159 TEST(TestFixedSizeBinaryScalar, Basics) {
160 std::string data = "test data";
161 auto buf = std::make_shared<Buffer>(data);
162
163 auto ex_type = fixed_size_binary(9);
164
165 FixedSizeBinaryScalar value(buf, ex_type);
166 ASSERT_TRUE(value.value->Equals(*buf));
167 ASSERT_TRUE(value.is_valid);
168 ASSERT_TRUE(value.type->Equals(*ex_type));
169 }
170
TEST(TestFixedSizeBinaryScalar,MakeScalar)171 TEST(TestFixedSizeBinaryScalar, MakeScalar) {
172 std::string data = "test data";
173 auto buf = std::make_shared<Buffer>(data);
174 auto type = fixed_size_binary(9);
175
176 ASSERT_OK_AND_ASSIGN(auto s, MakeScalar(type, buf));
177 ASSERT_EQ(FixedSizeBinaryScalar(buf, type), *s);
178
179 ASSERT_OK_AND_ASSIGN(s, Scalar::Parse(type, util::string_view(data)));
180 ASSERT_EQ(FixedSizeBinaryScalar(buf, type), *s);
181
182 // wrong length:
183 ASSERT_RAISES(Invalid, MakeScalar(type, Buffer::FromString(data.substr(3))).status());
184 ASSERT_RAISES(Invalid, Scalar::Parse(type, util::string_view(data).substr(3)).status());
185 }
186
TEST(TestDateScalars,Basics)187 TEST(TestDateScalars, Basics) {
188 int32_t i32_val = 1;
189 Date32Scalar date32_val(i32_val);
190 Date32Scalar date32_null;
191 ASSERT_TRUE(date32_val.type->Equals(*date32()));
192 ASSERT_TRUE(date32_val.is_valid);
193 ASSERT_FALSE(date32_null.is_valid);
194
195 int64_t i64_val = 2;
196 Date64Scalar date64_val(i64_val);
197 Date64Scalar date64_null;
198 ASSERT_EQ(i64_val, date64_val.value);
199 ASSERT_TRUE(date64_val.type->Equals(*date64()));
200 ASSERT_TRUE(date64_val.is_valid);
201 ASSERT_FALSE(date64_null.is_valid);
202 }
203
TEST(TestDateScalars,MakeScalar)204 TEST(TestDateScalars, MakeScalar) {
205 ASSERT_OK_AND_ASSIGN(auto s, MakeScalar(date32(), int32_t(1)));
206 ASSERT_EQ(Date32Scalar(1), *s);
207
208 ASSERT_OK_AND_ASSIGN(s, MakeScalar(date64(), int64_t(1)));
209 ASSERT_EQ(Date64Scalar(1), *s);
210
211 ASSERT_RAISES(NotImplemented, Scalar::Parse(date64(), ""));
212 }
213
TEST(TestTimeScalars,Basics)214 TEST(TestTimeScalars, Basics) {
215 auto type1 = time32(TimeUnit::MILLI);
216 auto type2 = time32(TimeUnit::SECOND);
217 auto type3 = time64(TimeUnit::MICRO);
218 auto type4 = time64(TimeUnit::NANO);
219
220 int32_t i32_val = 1;
221 Time32Scalar time32_val(i32_val, type1);
222 Time32Scalar time32_null(type2);
223 ASSERT_EQ(i32_val, time32_val.value);
224 ASSERT_TRUE(time32_val.type->Equals(*type1));
225 ASSERT_TRUE(time32_val.is_valid);
226 ASSERT_FALSE(time32_null.is_valid);
227 ASSERT_TRUE(time32_null.type->Equals(*type2));
228
229 int64_t i64_val = 2;
230 Time64Scalar time64_val(i64_val, type3);
231 Time64Scalar time64_null(type4);
232 ASSERT_EQ(i64_val, time64_val.value);
233 ASSERT_TRUE(time64_val.type->Equals(*type3));
234 ASSERT_TRUE(time64_val.is_valid);
235 ASSERT_FALSE(time64_null.is_valid);
236 ASSERT_TRUE(time64_null.type->Equals(*type4));
237 }
238
TEST(TestTimeScalars,MakeScalar)239 TEST(TestTimeScalars, MakeScalar) {
240 auto type1 = time32(TimeUnit::MILLI);
241 auto type2 = time32(TimeUnit::SECOND);
242 auto type3 = time64(TimeUnit::MICRO);
243 auto type4 = time64(TimeUnit::NANO);
244
245 ASSERT_OK_AND_ASSIGN(auto s, MakeScalar(type1, int32_t(1)));
246 ASSERT_EQ(Time32Scalar(1, type1), *s);
247
248 ASSERT_OK_AND_ASSIGN(s, MakeScalar(type2, int32_t(1)));
249 ASSERT_EQ(Time32Scalar(1, type2), *s);
250
251 ASSERT_OK_AND_ASSIGN(s, MakeScalar(type3, int64_t(1)));
252 ASSERT_EQ(Time64Scalar(1, type3), *s);
253
254 ASSERT_OK_AND_ASSIGN(s, MakeScalar(type4, int64_t(1)));
255 ASSERT_EQ(Time64Scalar(1, type4), *s);
256
257 ASSERT_RAISES(NotImplemented, Scalar::Parse(type4, ""));
258 }
259
TEST(TestTimestampScalars,Basics)260 TEST(TestTimestampScalars, Basics) {
261 auto type1 = timestamp(TimeUnit::MILLI);
262 auto type2 = timestamp(TimeUnit::SECOND);
263
264 int64_t val1 = 1;
265 int64_t val2 = 2;
266 TimestampScalar ts_val1(val1, type1);
267 TimestampScalar ts_val2(val2, type2);
268 TimestampScalar ts_null(type1);
269 ASSERT_EQ(val1, ts_val1.value);
270
271 ASSERT_TRUE(ts_val1.type->Equals(*type1));
272 ASSERT_TRUE(ts_val2.type->Equals(*type2));
273 ASSERT_TRUE(ts_val1.is_valid);
274 ASSERT_FALSE(ts_null.is_valid);
275 ASSERT_TRUE(ts_null.type->Equals(*type1));
276
277 ASSERT_NE(ts_val1, ts_val2);
278 ASSERT_NE(ts_val1, ts_null);
279 ASSERT_NE(ts_val2, ts_null);
280 }
281
TEST(TestTimestampScalars,MakeScalar)282 TEST(TestTimestampScalars, MakeScalar) {
283 auto type1 = timestamp(TimeUnit::MILLI);
284 auto type2 = timestamp(TimeUnit::SECOND);
285 auto type3 = timestamp(TimeUnit::MICRO);
286 auto type4 = timestamp(TimeUnit::NANO);
287
288 util::string_view epoch_plus_1s = "1970-01-01 00:00:01";
289
290 ASSERT_OK_AND_ASSIGN(auto s, MakeScalar(type1, int64_t(1)));
291 ASSERT_EQ(TimestampScalar(1, type1), *s);
292 ASSERT_OK_AND_ASSIGN(s, Scalar::Parse(type1, epoch_plus_1s));
293 ASSERT_EQ(TimestampScalar(1000, type1), *s);
294
295 ASSERT_OK_AND_ASSIGN(s, MakeScalar(type2, int64_t(1)));
296 ASSERT_EQ(TimestampScalar(1, type2), *s);
297 ASSERT_OK_AND_ASSIGN(s, Scalar::Parse(type2, epoch_plus_1s));
298 ASSERT_EQ(TimestampScalar(1, type2), *s);
299
300 ASSERT_OK_AND_ASSIGN(s, MakeScalar(type3, int64_t(1)));
301 ASSERT_EQ(TimestampScalar(1, type3), *s);
302 ASSERT_OK_AND_ASSIGN(s, Scalar::Parse(type3, epoch_plus_1s));
303 ASSERT_EQ(TimestampScalar(1000 * 1000, type3), *s);
304
305 ASSERT_OK_AND_ASSIGN(s, MakeScalar(type4, int64_t(1)));
306 ASSERT_EQ(TimestampScalar(1, type4), *s);
307 ASSERT_OK_AND_ASSIGN(s, Scalar::Parse(type4, epoch_plus_1s));
308 ASSERT_EQ(TimestampScalar(1000 * 1000 * 1000, type4), *s);
309 }
310
TEST(TestTimestampScalars,Cast)311 TEST(TestTimestampScalars, Cast) {
312 auto convert = [](TimeUnit::type in, TimeUnit::type out, int64_t value) -> int64_t {
313 auto scalar =
314 TimestampScalar(value, timestamp(in)).CastTo(timestamp(out)).ValueOrDie();
315 return internal::checked_pointer_cast<TimestampScalar>(scalar)->value;
316 };
317
318 EXPECT_EQ(convert(TimeUnit::SECOND, TimeUnit::MILLI, 1), 1000);
319 EXPECT_EQ(convert(TimeUnit::SECOND, TimeUnit::NANO, 1), 1000000000);
320
321 EXPECT_EQ(convert(TimeUnit::NANO, TimeUnit::MICRO, 1234), 1);
322 EXPECT_EQ(convert(TimeUnit::MICRO, TimeUnit::MILLI, 4567), 4);
323
324 ASSERT_OK_AND_ASSIGN(auto str,
325 TimestampScalar(1024, timestamp(TimeUnit::MILLI)).CastTo(utf8()));
326 EXPECT_EQ(*str, StringScalar("1024"));
327 ASSERT_OK_AND_ASSIGN(auto i64,
328 TimestampScalar(1024, timestamp(TimeUnit::MILLI)).CastTo(int64()));
329 EXPECT_EQ(*i64, Int64Scalar(1024));
330
331 constexpr int64_t kMillisecondsInDay = 86400000;
332 ASSERT_OK_AND_ASSIGN(
333 auto d64, TimestampScalar(1024 * kMillisecondsInDay + 3, timestamp(TimeUnit::MILLI))
334 .CastTo(date64()));
335 EXPECT_EQ(*d64, Date64Scalar(1024 * kMillisecondsInDay));
336 }
337
TEST(TestDurationScalars,Basics)338 TEST(TestDurationScalars, Basics) {
339 auto type1 = duration(TimeUnit::MILLI);
340 auto type2 = duration(TimeUnit::SECOND);
341
342 int64_t val1 = 1;
343 int64_t val2 = 2;
344 DurationScalar ts_val1(val1, type1);
345 DurationScalar ts_val2(val2, type2);
346 DurationScalar ts_null(type1);
347 ASSERT_EQ(val1, ts_val1.value);
348
349 ASSERT_TRUE(ts_val1.type->Equals(*type1));
350 ASSERT_TRUE(ts_val2.type->Equals(*type2));
351 ASSERT_TRUE(ts_val1.is_valid);
352 ASSERT_FALSE(ts_null.is_valid);
353 ASSERT_TRUE(ts_null.type->Equals(*type1));
354
355 ASSERT_NE(ts_val1, ts_val2);
356 ASSERT_NE(ts_val1, ts_null);
357 ASSERT_NE(ts_val2, ts_null);
358 }
359
TEST(TestMonthIntervalScalars,Basics)360 TEST(TestMonthIntervalScalars, Basics) {
361 auto type = month_interval();
362
363 int32_t val1 = 1;
364 int32_t val2 = 2;
365 MonthIntervalScalar ts_val1(val1);
366 MonthIntervalScalar ts_val2(val2);
367 MonthIntervalScalar ts_null;
368 ASSERT_EQ(val1, ts_val1.value);
369
370 ASSERT_TRUE(ts_val1.type->Equals(*type));
371 ASSERT_TRUE(ts_val2.type->Equals(*type));
372 ASSERT_TRUE(ts_val1.is_valid);
373 ASSERT_FALSE(ts_null.is_valid);
374 ASSERT_TRUE(ts_null.type->Equals(*type));
375
376 ASSERT_NE(ts_val1, ts_val2);
377 ASSERT_NE(ts_val1, ts_null);
378 ASSERT_NE(ts_val2, ts_null);
379 }
380
TEST(TestDayTimeIntervalScalars,Basics)381 TEST(TestDayTimeIntervalScalars, Basics) {
382 auto type = day_time_interval();
383
384 DayTimeIntervalType::DayMilliseconds val1 = {1, 1};
385 DayTimeIntervalType::DayMilliseconds val2 = {2, 2};
386 DayTimeIntervalScalar ts_val1(val1);
387 DayTimeIntervalScalar ts_val2(val2);
388 DayTimeIntervalScalar ts_null;
389 ASSERT_EQ(val1, ts_val1.value);
390
391 ASSERT_TRUE(ts_val1.type->Equals(*type));
392 ASSERT_TRUE(ts_val2.type->Equals(*type));
393 ASSERT_TRUE(ts_val1.is_valid);
394 ASSERT_FALSE(ts_null.is_valid);
395 ASSERT_TRUE(ts_null.type->Equals(*type));
396
397 ASSERT_NE(ts_val1, ts_val2);
398 ASSERT_NE(ts_val1, ts_null);
399 ASSERT_NE(ts_val2, ts_null);
400 }
401
402 // TODO test HalfFloatScalar
403
TYPED_TEST(TestNumericScalar,Cast)404 TYPED_TEST(TestNumericScalar, Cast) {
405 auto type = TypeTraits<TypeParam>::type_singleton();
406
407 for (util::string_view repr : {"0", "1", "3"}) {
408 std::shared_ptr<Scalar> scalar;
409 ASSERT_OK_AND_ASSIGN(scalar, Scalar::Parse(type, repr));
410
411 // cast to and from other numeric scalars
412 for (auto other_type : {float32(), int8(), int64(), uint32()}) {
413 std::shared_ptr<Scalar> other_scalar;
414 ASSERT_OK_AND_ASSIGN(other_scalar, Scalar::Parse(other_type, repr));
415
416 ASSERT_OK_AND_ASSIGN(auto cast_to_other, scalar->CastTo(other_type))
417 ASSERT_EQ(*cast_to_other, *other_scalar);
418
419 ASSERT_OK_AND_ASSIGN(auto cast_from_other, other_scalar->CastTo(type))
420 ASSERT_EQ(*cast_from_other, *scalar);
421 }
422
423 ASSERT_OK_AND_ASSIGN(auto cast_from_string,
424 StringScalar(repr.to_string()).CastTo(type));
425 ASSERT_EQ(*cast_from_string, *scalar);
426
427 if (is_integer_type<TypeParam>::value) {
428 ASSERT_OK_AND_ASSIGN(auto cast_to_string, scalar->CastTo(utf8()));
429 ASSERT_EQ(
430 util::string_view(*checked_cast<const StringScalar&>(*cast_to_string).value),
431 repr);
432 }
433 }
434 }
435
436 } // namespace arrow
437