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