bkmgit commented on a change in pull request #11882:
URL: https://github.com/apache/arrow/pull/11882#discussion_r793735145



##########
File path: cpp/src/arrow/compute/kernels/scalar_compare_test.cc
##########
@@ -1865,5 +1928,654 @@ TEST(TestMaxElementWiseMinElementWise, CommonTemporal) {
               ResultWith(ScalarFromJSON(date64(), "86400000")));
 }
 
+static void ValidateBetween(BetweenOptions options, const Datum& val, const 
Datum& lhs,
+                            const Datum& rhs, const Datum& expected) {
+  ASSERT_OK_AND_ASSIGN(Datum result, Between(val, lhs, rhs, options, nullptr));
+  if ((val.is_scalar()) && (lhs.is_scalar()) && (rhs.is_scalar())) {
+    AssertScalarsEqual(*expected.scalar(), *result.scalar(), /*verbose=*/true);
+  } else {
+    AssertArraysEqual(*expected.make_array(), *result.make_array(),
+                      /*verbose=*/true);
+  }
+}
+
+void ValidateBetween(const Datum& val, const Datum& lhs, const Datum& rhs) {
+  CompareOperator lhs_val;
+  CompareOperator val_rhs;
+  for (auto inclusive :
+       {BetweenOptions::Inclusive::BOTH, BetweenOptions::Inclusive::LEFT,
+        BetweenOptions::Inclusive::RIGHT, BetweenOptions::Inclusive::NEITHER}) 
{
+    auto options = BetweenOptions(inclusive);
+    if (inclusive == BetweenOptions::Inclusive::NEITHER) {
+      lhs_val = LESS;
+      val_rhs = LESS;
+    } else if (inclusive == BetweenOptions::Inclusive::LEFT) {
+      lhs_val = LESS_EQUAL;
+      val_rhs = LESS;
+    } else if (inclusive == BetweenOptions::Inclusive::RIGHT) {
+      lhs_val = LESS;
+      val_rhs = LESS_EQUAL;
+    } else {
+      lhs_val = LESS_EQUAL;
+      val_rhs = LESS_EQUAL;
+    }
+
+    ASSERT_OK_AND_ASSIGN(
+        Datum resultl, CallFunction(CompareOperatorToFunctionName(lhs_val), 
{lhs, val}));
+    ASSERT_OK_AND_ASSIGN(
+        Datum resultr, CallFunction(CompareOperatorToFunctionName(val_rhs), 
{val, rhs}));
+    ASSERT_OK_AND_ASSIGN(Datum expected, CallFunction("and", {resultl, 
resultr}));
+
+    ValidateBetween(options, val, lhs, rhs, expected);
+  }
+}
+
+class TestNumericBetweenKernel : public ::testing::Test {};
+
+std::shared_ptr<DataType> GetType(std::shared_ptr<DataType> type) {
+  auto type_string = type->ToString();
+  if (type_string == "duration[s]") {
+    return int64();
+  } else if (type_string == "duration[ms]") {
+    return int64();
+  } else if (type_string == "duration[ns]") {
+    return int64();
+  } else if (type_string == "uint8") {
+    return uint8();
+  } else if (type_string == "uint16") {
+    return uint16();
+  } else if (type_string == "uint32") {
+    return uint32();
+  } else if (type_string == "uint64") {
+    return uint64();
+  } else if (type_string == "int8") {
+    return int8();
+  } else if (type_string == "int16") {
+    return int16();
+  } else if (type_string == "int32") {
+    return int32();
+  } else if (type_string == "int64") {
+    return int64();
+  } else if (type_string == "float") {
+    return float32();
+  } else if (type_string == "double") {
+    return float64();
+  } else {
+    return int64();
+  }
+}
+
+TEST(TestNumericBetweenKernel, 3Scalars) {
+  for (const auto& types : {DurationTypes(), NumericTypes()}) {
+    for (const std::shared_ptr<DataType>& ty : types) {
+      ARROW_SCOPED_TRACE("type = ", ty->ToString());
+      auto tt = GetType(ty);
+      auto zero = Datum(ScalarFromJSON(tt, "0"));
+      auto two = Datum(ScalarFromJSON(tt, "2"));
+      auto four = Datum(ScalarFromJSON(tt, "4"));
+      auto null = Datum(ScalarFromJSON(tt, "null"));
+      ValidateBetween(zero, two, four);
+      ValidateBetween(two, zero, four);
+      ValidateBetween(two, two, four);
+      ValidateBetween(four, two, four);
+      ValidateBetween(null, two, four);
+      ValidateBetween(two, null, four);
+      ValidateBetween(two, zero, null);
+    }
+  }
+}
+
+TEST(TestNumericBetweenKernel, 1Array2Scalars) {
+  for (const auto& types : {DurationTypes(), NumericTypes()}) {
+    for (const std::shared_ptr<DataType>& ty : types) {
+      ARROW_SCOPED_TRACE("type = ", ty->ToString());
+      auto tt = GetType(ty);
+      auto zero = Datum(ScalarFromJSON(tt, "0"));
+      auto four = Datum(ScalarFromJSON(tt, "4"));
+      auto null = Datum(ScalarFromJSON(tt, "null"));
+      ValidateBetween(Datum(ArrayFromJSON(tt, "[]")), zero, four);
+      ValidateBetween(Datum(ArrayFromJSON(tt, "[null]")), zero, four);
+      ValidateBetween(Datum(ArrayFromJSON(tt, "[0,1,2,3,4,5]")), zero, four);
+      ValidateBetween(Datum(ArrayFromJSON(tt, "[null,0,1,1]")), zero, four);
+      ValidateBetween(Datum(ArrayFromJSON(tt, "[5,4,3,2,1,0]")), null, four);
+      ValidateBetween(Datum(ArrayFromJSON(tt, "[5,4,3,2,1,0]")), zero, null);
+      ValidateBetween(zero, Datum(ArrayFromJSON(tt, "[]")), four);
+      ValidateBetween(zero, Datum(ArrayFromJSON(tt, "[null]")), four);
+      ValidateBetween(zero, Datum(ArrayFromJSON(tt, "[0,1,2,3,4,5]")), four);
+      ValidateBetween(zero, Datum(ArrayFromJSON(tt, "[null,0,1,1]")), four);
+      ValidateBetween(null, Datum(ArrayFromJSON(tt, "[5,4,3,2,1,0]")), four);
+      ValidateBetween(zero, Datum(ArrayFromJSON(tt, "[5,4,3,2,1,0]")), null);
+      ValidateBetween(zero, four, Datum(ArrayFromJSON(tt, "[]")));
+      ValidateBetween(zero, four, Datum(ArrayFromJSON(tt, "[null]")));
+      ValidateBetween(zero, four, Datum(ArrayFromJSON(tt, "[0,1,2,3,4,5]")));
+      ValidateBetween(zero, four, Datum(ArrayFromJSON(tt, "[null,0,1,1]")));
+      ValidateBetween(null, four, Datum(ArrayFromJSON(tt, "[5,4,3,2,1,0]")));
+      ValidateBetween(zero, null, Datum(ArrayFromJSON(tt, "[5,4,3,2,1,0]")));
+    }
+  }
+}
+
+TEST(TestNumericBetweenKernel, 2Arrays1Scalar) {
+  for (const auto& types : {DurationTypes(), NumericTypes()}) {
+    for (const std::shared_ptr<DataType>& ty : types) {
+      ARROW_SCOPED_TRACE("type = ", ty->ToString());
+      auto tt = GetType(ty);
+      auto one = Datum(ScalarFromJSON(tt, "1"));
+      ValidateBetween(one, Datum(ArrayFromJSON(tt, "[]")),
+                      Datum(ArrayFromJSON(tt, "[]")));
+      ValidateBetween(one, Datum(ArrayFromJSON(tt, "[null]")),
+                      Datum(ArrayFromJSON(tt, "[null]")));
+      ValidateBetween(one, Datum(ArrayFromJSON(tt, "[0,0,1,3,3]")),
+                      Datum(ArrayFromJSON(tt, "[10,10,2,5,5]")));
+      ValidateBetween(one, Datum(ArrayFromJSON(tt, "[0,0,1,null,3,3]")),
+                      Datum(ArrayFromJSON(tt, "[0,10,2,2,5,5]")));
+      ValidateBetween(Datum(ArrayFromJSON(tt, "[]")), one,
+                      Datum(ArrayFromJSON(tt, "[]")));
+      ValidateBetween(Datum(ArrayFromJSON(tt, "[null]")), one,
+                      Datum(ArrayFromJSON(tt, "[null]")));
+      ValidateBetween(Datum(ArrayFromJSON(tt, "[0,0,1,3,3]")), one,
+                      Datum(ArrayFromJSON(tt, "[10,10,2,5,5]")));
+      ValidateBetween(Datum(ArrayFromJSON(tt, "[0,0,1,null,3,3]")), one,
+                      Datum(ArrayFromJSON(tt, "[0,10,2,2,5,5]")));
+      ValidateBetween(Datum(ArrayFromJSON(tt, "[]")), Datum(ArrayFromJSON(tt, 
"[]")),
+                      one);
+      ValidateBetween(Datum(ArrayFromJSON(tt, "[null]")),
+                      Datum(ArrayFromJSON(tt, "[null]")), one);
+      ValidateBetween(Datum(ArrayFromJSON(tt, "[0,0,1,3,3]")),
+                      Datum(ArrayFromJSON(tt, "[10,10,2,5,5]")), one);
+      ValidateBetween(Datum(ArrayFromJSON(tt, "[0,0,1,null,3,3]")),
+                      Datum(ArrayFromJSON(tt, "[0,10,2,2,5,5]")), one);
+    }
+  }
+}
+
+TEST(TestNumericBetweenKernel, 3Arrays) {
+  for (const auto& types : {DurationTypes(), NumericTypes()}) {
+    for (const std::shared_ptr<DataType>& ty : types) {
+      ARROW_SCOPED_TRACE("type = ", ty->ToString());
+      ValidateBetween(Datum(ArrayFromJSON(ty, "[]")), Datum(ArrayFromJSON(ty, 
"[]")),
+                      Datum(ArrayFromJSON(ty, "[]")));
+      ValidateBetween(Datum(ArrayFromJSON(ty, "[null]")),
+                      Datum(ArrayFromJSON(ty, "[null]")),
+                      Datum(ArrayFromJSON(ty, "[null]")));
+      ValidateBetween(Datum(ArrayFromJSON(ty, "[1,1,2,2,2]")),
+                      Datum(ArrayFromJSON(ty, "[0,0,1,3,3]")),
+                      Datum(ArrayFromJSON(ty, "[10,10,2,5,5]")));
+      ValidateBetween(Datum(ArrayFromJSON(ty, "[0,1,2,2,2,2]")),
+                      Datum(ArrayFromJSON(ty, "[0,0,1,null,3,3]")),
+                      Datum(ArrayFromJSON(ty, "[0,10,2,2,5,5]")));
+    }
+  }
+}
+
+TEST(TestNumericBetweenKernel, Random) {
+  for (const auto& types : {DurationTypes(), NumericTypes()}) {
+    for (const std::shared_ptr<DataType>& ty : types) {
+      auto rand = random::RandomArrayGenerator(0x5416447);
+      const int64_t length = 100;
+      for (auto null_probability : {0.0, 0.01, 0.1, 0.25, 0.5, 1.0}) {
+        ARROW_SCOPED_TRACE("type = ", ty->ToString());
+        auto tt = GetType(ty);
+        auto metadata =
+            key_value_metadata({"null_probability"}, 
{std::to_string(null_probability)});
+        auto field = ::arrow::field("[0,100]", std::move(ty), 
std::move(metadata));
+        auto data1 = rand.ArrayOf(*field, length);
+        auto data2 = rand.ArrayOf(*field, length);
+        auto data3 = rand.ArrayOf(*field, length);
+
+        // Create view of data as the type (e.g. float64)
+        auto array1 = Datum(*data1->View(tt));
+        auto array2 = Datum(*data2->View(tt));
+        auto array3 = Datum(*data3->View(tt));
+        auto scalar1 = Datum(ScalarFromJSON(tt, "10"));
+        auto scalar2 = Datum(ScalarFromJSON(tt, "30"));
+        auto scalar3 = Datum(ScalarFromJSON(tt, "50"));
+        ValidateBetween(scalar1, scalar2, scalar3);
+       ValidateBetween(array1, scalar2, scalar3);
+        ValidateBetween(array1, array2, scalar3);
+        ValidateBetween(array1, array2, array3);
+        ValidateBetween(array1, scalar2, scalar3);
+        ValidateBetween(scalar1, array2, array3);
+        ValidateBetween(scalar1, array2, scalar3);
+        ValidateBetween(scalar1, scalar2, array3);
+        ValidateBetween(array1, scalar2, array3);
+      }
+    }
+  }
+}
+
+class TestStringBetweenKernel : public ::testing::Test {};
+
+TEST(TestStringBetweenKernel, Random) {
+  using ScalarType = typename TypeTraits<StringType>::ScalarType;
+
+  auto rand = random::RandomArrayGenerator(0x5416447);
+  for (size_t i = 3; i < 10; i++) {
+    for (auto null_probability : {0.0, 0.01, 0.1, 0.25, 0.5, 1.0}) {
+      const int64_t length = static_cast<int64_t>(1ULL << i);
+      auto array1 = Datum(rand.String(length, 0, 16, null_probability));
+      auto array2 = Datum(rand.String(length, 0, 16, null_probability));
+      auto array3 = Datum(rand.String(length, 0, 16, null_probability));
+      auto scalar1 = Datum(std::make_shared<ScalarType>("fupi"));
+      auto scalar2 = Datum(std::make_shared<ScalarType>("tupu"));
+      auto scalar3 = Datum(std::make_shared<ScalarType>("zito"));
+      ValidateBetween(scalar1, scalar2, scalar3);
+      ValidateBetween(array1, scalar2, scalar3);
+      ValidateBetween(scalar1, array2, scalar3);
+      ValidateBetween(scalar1, scalar2, array3);
+      ValidateBetween(scalar1, array2, array3);
+      ValidateBetween(array1, scalar2, array3);
+      ValidateBetween(array1, array2, scalar3);
+      ValidateBetween(array1, array2, array3);
+    }
+  }
+}
+
+TEST(TestStringBetweenKernel, 1Array2Scalars) {
+  using ScalarType = typename TypeTraits<StringType>::ScalarType;
+  auto l = Datum(std::make_shared<ScalarType>("abc"));
+  auto r = Datum(std::make_shared<ScalarType>("zzz"));
+  
ValidateBetween(Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(), 
"[]")), l,
+                  r);
+  ValidateBetween(
+      Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(), 
"[null]")), l, r);
+  ValidateBetween(Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(),
+                                      R"(["aaa", "aaaa", "ccc", "z"])")),
+                  l, r);
+  ValidateBetween(Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(),
+                                      R"(["abc", "baa", "fff", "zzz"])")),
+                  l, r);
+  ValidateBetween(Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(),
+                                      R"(["abd", null, null, "zzx"])")),
+                  l, r);
+  ValidateBetween(l, 
Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(), "[]")),
+                  r);
+  ValidateBetween(l,
+      Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(), 
"[null]")), r);
+  ValidateBetween(l, 
Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(),
+                                      R"(["aaa", "aaaa", "ccc", "z"])")),
+                  r);
+  ValidateBetween(l, 
Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(),
+                                      R"(["abc", "baa", "fff", "zzz"])")),
+                  r);
+  ValidateBetween(l, 
Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(),
+                                      R"(["abd", null, null, "zzx"])")),
+                  r);
+  ValidateBetween(l, r,
+                  
Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(), "[]")));
+  ValidateBetween(l, r,
+      Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(), 
"[null]")));
+  ValidateBetween(l, r, 
Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(),
+                                       R"(["aaa", "aaaa", "ccc", "z"])")));
+  ValidateBetween(l, r, 
Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(),
+                                      R"(["abc", "baa", "fff", "zzz"])")));
+  ValidateBetween(l, r, 
Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(),
+                                      R"(["abd", null, null, "zzx"])")));
+}
+
+TEST(TestStringBetweenKernel, 2Arrays1Scalar) {
+  using ScalarType = typename TypeTraits<StringType>::ScalarType;
+  auto r = Datum(std::make_shared<ScalarType>("zzz"));
+  ValidateBetween(r, 
Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(), "[]")),
+                  
Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(), "[]")));
+  ValidateBetween(r, 
Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(),
+                                   R"(["aaa", "aaaa", "ccc", "z"])")),
+                  Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(),
+                                R"(["abc", "baa", "fff", "zzz"])")));
+  ValidateBetween(r, 
Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(),
+                                   R"(["abc", "baa", "fff", "zzz"])")),
+                  Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(),
+                                R"(["abd", null, null, "zzx"])")));
+  
ValidateBetween(Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(), 
"[]")), r,
+                  
Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(), "[]")));
+  ValidateBetween(Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(),
+                                R"(["aaa", "aaaa", "ccc", "z"])")), r,
+                  Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(),
+                                R"(["abc", "baa", "fff", "zzz"])")));
+  ValidateBetween(Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(),
+                                R"(["abc", "baa", "fff", "zzz"])")), r,
+                  Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(),
+                                R"(["abd", null, null, "zzx"])")));
+  
ValidateBetween(Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(), 
"[]")),
+                  
Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(), "[]")),
+                 r);
+  ValidateBetween(Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(),
+                                R"(["aaa", "aaaa", "ccc", "z"])")),
+                 Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(),
+                                R"(["abc", "baa", "fff", "zzz"])")),
+                 r);
+  ValidateBetween(Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(),
+                                R"(["abc", "baa", "fff", "zzz"])")),
+                  Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(),
+                                R"(["abd", null, null, "zzx"])")),
+                 r);
+}
+
+TEST(TestStringBetweenKernel, 3Arrays) {
+  ValidateBetween(Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(),
+                                      R"(["david","hello","world"])")),
+                  Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(),
+                                      R"(["adam","hi","whirl"])")),
+                  Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(),
+                                      
R"(["robert","goeiemoreen","whirlwind"])")));
+  ValidateBetween(
+      Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(), 
R"(["x","a","f"])")),
+      Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(), 
R"(["w","a","e"])")),
+      Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(), 
R"(["z","a","g"])")));
+  ValidateBetween(Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(),
+                                      R"(["block","bit","binary"])")),
+                  Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(),
+                                      R"(["bit","nibble","ternary"])")),
+                  Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(),
+                                      R"(["word","d","xyz"])")));
+  ValidateBetween(Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(),
+                                      R"(["よしもと","の","ち"])")),
+                  Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(),
+                                      R"(["は","へ","あ"])")),
+                  Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(),
+                                      R"(["な","を","ち"])")));
+  ValidateBetween(Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(),
+                                      R"(["A","ア","王"])")),
+                  Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(),
+                                      R"(["た","あ","歩"])")),
+                  Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(),
+                                      R"(["李","田",null])")));
+  ValidateBetween(
+      Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(), 
R"(["Б",null,"Я"])")),
+      Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(), 
R"(["А","Ж","Щ"])")),
+      Datum(ArrayFromJSON(TypeTraits<StringType>::type_singleton(), 
R"(["Д","Л","Ф"])")));
+}
+
+TEST(TestTimestampsBetweenKernel, 1Array2Scalars) {
+  const std::string scalar1_json = R"("1980-02-02")";
+  const std::string scalar2_json = R"("1970-01-01")";
+  const std::string array_json = R"(["1970-01-02","1980-02-02","1970-02-28"])";
+  // Same units should be fine
+  ValidateBetween(Datum(ArrayFromJSON(timestamp(TimeUnit::SECOND), 
array_json)),
+                  Datum(ScalarFromJSON(timestamp(TimeUnit::SECOND), 
scalar1_json)),
+                  Datum(ScalarFromJSON(timestamp(TimeUnit::SECOND), 
scalar2_json)));
+  ValidateBetween(Datum(ScalarFromJSON(timestamp(TimeUnit::SECOND), 
scalar1_json)),
+                  Datum(ArrayFromJSON(timestamp(TimeUnit::SECOND), 
array_json)),
+                  Datum(ScalarFromJSON(timestamp(TimeUnit::SECOND), 
scalar2_json)));
+  ValidateBetween(Datum(ScalarFromJSON(timestamp(TimeUnit::SECOND), 
scalar1_json)),
+                  Datum(ScalarFromJSON(timestamp(TimeUnit::SECOND), 
scalar2_json)),
+                  Datum(ArrayFromJSON(timestamp(TimeUnit::SECOND), 
array_json)));
+  // Different timezones should be fine
+  ValidateBetween(
+      Datum(ArrayFromJSON(timestamp(TimeUnit::SECOND, "Africa/Cairo"), 
array_json)),
+      Datum(ScalarFromJSON(timestamp(TimeUnit::SECOND, "America/Chicago"), 
scalar1_json)),
+      Datum(ScalarFromJSON(timestamp(TimeUnit::SECOND, "Asia/Beijing"), 
scalar2_json)));
+  ValidateBetween(
+      Datum(ScalarFromJSON(timestamp(TimeUnit::NANO, "Europe/Berlin"), 
scalar1_json)),
+      Datum(ArrayFromJSON(timestamp(TimeUnit::NANO, "America/Phoenix"), 
array_json)),
+      Datum(ScalarFromJSON(timestamp(TimeUnit::NANO, "Africa/Nairobi"), 
scalar2_json)));
+  ValidateBetween(
+      Datum(ScalarFromJSON(timestamp(TimeUnit::NANO, "Europe/Berlin"), 
scalar1_json)),
+      Datum(ScalarFromJSON(timestamp(TimeUnit::NANO, "Asia/Tokyo"), 
scalar2_json)),
+      Datum(ArrayFromJSON(timestamp(TimeUnit::NANO, "Africa/Nairobi"), 
array_json)));
+  // Different units should be fine
+  ValidateBetween(Datum(ArrayFromJSON(timestamp(TimeUnit::SECOND), 
array_json)),
+                  Datum(ScalarFromJSON(timestamp(TimeUnit::MILLI), 
scalar1_json)),
+                  Datum(ScalarFromJSON(timestamp(TimeUnit::SECOND), 
scalar2_json)));
+  ValidateBetween(Datum(ScalarFromJSON(timestamp(TimeUnit::SECOND), 
scalar1_json)),
+                  Datum(ArrayFromJSON(timestamp(TimeUnit::NANO), array_json)),
+                  Datum(ScalarFromJSON(timestamp(TimeUnit::SECOND), 
scalar2_json)));
+  ValidateBetween(Datum(ScalarFromJSON(timestamp(TimeUnit::SECOND), 
scalar1_json)),
+                  Datum(ScalarFromJSON(timestamp(TimeUnit::NANO), 
scalar2_json)),
+                  Datum(ArrayFromJSON(timestamp(TimeUnit::SECOND), 
array_json)));
+  // But comparing naive to zoned is not OK
+  for (auto inclusive :
+       {BetweenOptions::Inclusive::BOTH, BetweenOptions::Inclusive::LEFT,
+        BetweenOptions::Inclusive::RIGHT, BetweenOptions::Inclusive::NEITHER}) 
{
+    auto options = BetweenOptions(inclusive);
+    EXPECT_RAISES_WITH_MESSAGE_THAT(
+        TypeError,
+        ::testing::HasSubstr(
+            "Cannot compare timestamp with timezone to timestamp without 
timezone"),
+        Between(ArrayFromJSON(timestamp(TimeUnit::SECOND), array_json),
+                ScalarFromJSON(timestamp(TimeUnit::SECOND), scalar1_json),
+                ScalarFromJSON(timestamp(TimeUnit::SECOND, "Asia/Tokyo"), 
scalar2_json),
+                options, nullptr));
+    EXPECT_RAISES_WITH_MESSAGE_THAT(
+        TypeError,
+        ::testing::HasSubstr(
+            "Cannot compare timestamp with timezone to timestamp without 
timezone"),
+        Between(ScalarFromJSON(timestamp(TimeUnit::SECOND), scalar1_json),
+                ArrayFromJSON(timestamp(TimeUnit::SECOND, "America/New_York"), 
array_json),
+                ScalarFromJSON(timestamp(TimeUnit::SECOND, "Europe/Berlin"), 
scalar2_json),
+                options, nullptr));
+    EXPECT_RAISES_WITH_MESSAGE_THAT(
+        TypeError,
+        ::testing::HasSubstr(
+            "Cannot compare timestamp with timezone to timestamp without 
timezone"),
+        Between(ScalarFromJSON(timestamp(TimeUnit::SECOND, "Africa/Nairobi"), 
scalar1_json),
+                ArrayFromJSON(timestamp(TimeUnit::SECOND), array_json),
+                ScalarFromJSON(timestamp(TimeUnit::SECOND), scalar2_json), 
options, nullptr));
+  }
+}
+
+TEST(TestTimestampsBetweenKernel, 2Arrays1Scalar) {
+  const std::string scalar_json = R"("1980-02-02")";
+  const std::string array1_json = 
R"(["1970-01-01","1980-02-01","1970-02-28"])";
+  const std::string array2_json = 
R"(["1970-01-02","1980-02-02","1970-02-28"])";
+  // Same units should be fine
+  ValidateBetween(Datum(ScalarFromJSON(timestamp(TimeUnit::SECOND), 
scalar_json)),
+                  Datum(ArrayFromJSON(timestamp(TimeUnit::SECOND), 
array1_json)),
+                  Datum(ArrayFromJSON(timestamp(TimeUnit::SECOND), 
array2_json)));
+  ValidateBetween(Datum(ArrayFromJSON(timestamp(TimeUnit::SECOND), 
array1_json)),
+                  Datum(ScalarFromJSON(timestamp(TimeUnit::SECOND), 
scalar_json)),
+                  Datum(ArrayFromJSON(timestamp(TimeUnit::SECOND), 
array2_json)));
+  ValidateBetween(Datum(ArrayFromJSON(timestamp(TimeUnit::SECOND), 
array1_json)),
+                  Datum(ArrayFromJSON(timestamp(TimeUnit::SECOND), 
array2_json)),
+                  Datum(ScalarFromJSON(timestamp(TimeUnit::SECOND), 
scalar_json)));
+  // Different timezones should be fine
+  ValidateBetween(
+      Datum(ScalarFromJSON(timestamp(TimeUnit::SECOND, "Africa/Cairo"), 
scalar_json)),
+      Datum(ArrayFromJSON(timestamp(TimeUnit::SECOND, "America/Chicago"), 
array1_json)),
+      Datum(ArrayFromJSON(timestamp(TimeUnit::SECOND, "Asia/Beijing"), 
array2_json)));
+  ValidateBetween(
+      Datum(ArrayFromJSON(timestamp(TimeUnit::NANO, "Europe/Berlin"), 
array1_json)),
+      Datum(ScalarFromJSON(timestamp(TimeUnit::NANO, "America/Phoenix"), 
scalar_json)),
+      Datum(ArrayFromJSON(timestamp(TimeUnit::NANO, "Africa/Nairobi"), 
array2_json)));
+  ValidateBetween(
+      Datum(ArrayFromJSON(timestamp(TimeUnit::NANO, "Europe/Berlin"), 
array1_json)),
+      Datum(ArrayFromJSON(timestamp(TimeUnit::NANO, "Asia/Tokyo"), 
array2_json)),
+      Datum(ScalarFromJSON(timestamp(TimeUnit::NANO, "Africa/Nairobi"), 
scalar_json)));
+  // Different units should be fine
+  ValidateBetween(Datum(ScalarFromJSON(timestamp(TimeUnit::SECOND), 
scalar_json)),
+                  Datum(ArrayFromJSON(timestamp(TimeUnit::MILLI), 
array1_json)),
+                  Datum(ArrayFromJSON(timestamp(TimeUnit::SECOND), 
array2_json)));
+  ValidateBetween(Datum(ArrayFromJSON(timestamp(TimeUnit::SECOND), 
array1_json)),
+                  Datum(ScalarFromJSON(timestamp(TimeUnit::NANO), 
scalar_json)),
+                  Datum(ArrayFromJSON(timestamp(TimeUnit::SECOND), 
array2_json)));
+  ValidateBetween(Datum(ArrayFromJSON(timestamp(TimeUnit::SECOND), 
array1_json)),
+                  Datum(ArrayFromJSON(timestamp(TimeUnit::NANO), array2_json)),
+                  Datum(ScalarFromJSON(timestamp(TimeUnit::SECOND), 
scalar_json)));
+  // But comparing naive to zoned is not OK
+  for (auto inclusive :
+       {BetweenOptions::Inclusive::BOTH, BetweenOptions::Inclusive::LEFT,
+        BetweenOptions::Inclusive::RIGHT, BetweenOptions::Inclusive::NEITHER}) 
{
+    auto options = BetweenOptions(inclusive);
+    EXPECT_RAISES_WITH_MESSAGE_THAT(
+        TypeError,
+        ::testing::HasSubstr(
+            "Cannot compare timestamp with timezone to timestamp without 
timezone"),
+        Between(ScalarFromJSON(timestamp(TimeUnit::SECOND), scalar_json),
+                ArrayFromJSON(timestamp(TimeUnit::SECOND), array1_json),
+                ArrayFromJSON(timestamp(TimeUnit::SECOND, "Asia/Tokyo"), 
array2_json),
+                options, nullptr));
+    EXPECT_RAISES_WITH_MESSAGE_THAT(
+        TypeError,
+        ::testing::HasSubstr(
+            "Cannot compare timestamp with timezone to timestamp without 
timezone"),
+        Between(ArrayFromJSON(timestamp(TimeUnit::SECOND), array1_json),
+                ScalarFromJSON(timestamp(TimeUnit::SECOND, 
"America/New_York"), scalar_json),
+                ArrayFromJSON(timestamp(TimeUnit::SECOND, "Europe/Berlin"), 
array2_json),
+                options, nullptr));
+    EXPECT_RAISES_WITH_MESSAGE_THAT(
+        TypeError,
+        ::testing::HasSubstr(
+            "Cannot compare timestamp with timezone to timestamp without 
timezone"),
+        Between(ArrayFromJSON(timestamp(TimeUnit::SECOND, "Africa/Nairobi"), 
array1_json),
+                ScalarFromJSON(timestamp(TimeUnit::SECOND), scalar_json),
+                ArrayFromJSON(timestamp(TimeUnit::SECOND), array2_json), 
options, nullptr));
+  }
+}
+
+TEST(TestTimestampsBetweenKernel, 3Arrays) {
+  const std::string arr_json = R"(["1970-01-01","1980-02-02","1970-02-28"])";
+  const std::string lhs_json = R"(["1970-01-01","1980-02-01","1970-02-28"])";
+  const std::string rhs_json = R"(["1970-01-02","1980-02-02","1970-02-28"])";
+  // Same units should be fine
+  ValidateBetween(Datum(ArrayFromJSON(timestamp(TimeUnit::SECOND), arr_json)),
+                  Datum(ArrayFromJSON(timestamp(TimeUnit::SECOND), lhs_json)),
+                  Datum(ArrayFromJSON(timestamp(TimeUnit::SECOND), rhs_json)));
+  // Different timezones should be fine
+  ValidateBetween(
+      Datum(ArrayFromJSON(timestamp(TimeUnit::SECOND, "Africa/Cairo"), 
arr_json)),
+      Datum(ArrayFromJSON(timestamp(TimeUnit::SECOND, "America/Chicago"), 
lhs_json)),
+      Datum(ArrayFromJSON(timestamp(TimeUnit::SECOND, "Asia/Beijing"), 
rhs_json)));
+  ValidateBetween(
+      Datum(ArrayFromJSON(timestamp(TimeUnit::NANO, "Europe/Berlin"), 
arr_json)),
+      Datum(ArrayFromJSON(timestamp(TimeUnit::NANO, "America/Phoenix"), 
lhs_json)),
+      Datum(ArrayFromJSON(timestamp(TimeUnit::NANO, "Africa/Nairobi"), 
rhs_json)));
+  // Different units should be fine
+  ValidateBetween(Datum(ArrayFromJSON(timestamp(TimeUnit::SECOND), arr_json)),
+                  Datum(ArrayFromJSON(timestamp(TimeUnit::MILLI), lhs_json)),
+                  Datum(ArrayFromJSON(timestamp(TimeUnit::SECOND), rhs_json)));
+  ValidateBetween(Datum(ArrayFromJSON(timestamp(TimeUnit::SECOND), arr_json)),
+                  Datum(ArrayFromJSON(timestamp(TimeUnit::NANO), lhs_json)),
+                  Datum(ArrayFromJSON(timestamp(TimeUnit::SECOND), rhs_json)));
+  // But comparing naive to zoned is not OK
+  for (auto inclusive :
+       {BetweenOptions::Inclusive::BOTH, BetweenOptions::Inclusive::LEFT,
+        BetweenOptions::Inclusive::RIGHT, BetweenOptions::Inclusive::NEITHER}) 
{
+    auto options = BetweenOptions(inclusive);
+    EXPECT_RAISES_WITH_MESSAGE_THAT(
+        TypeError,
+        ::testing::HasSubstr(
+            "Cannot compare timestamp with timezone to timestamp without 
timezone"),
+        Between(ArrayFromJSON(timestamp(TimeUnit::SECOND), arr_json),
+                ArrayFromJSON(timestamp(TimeUnit::SECOND), lhs_json),
+                ArrayFromJSON(timestamp(TimeUnit::SECOND, "Asia/Tokyo"), 
rhs_json),
+                options, nullptr));
+    EXPECT_RAISES_WITH_MESSAGE_THAT(
+        TypeError,
+        ::testing::HasSubstr(
+            "Cannot compare timestamp with timezone to timestamp without 
timezone"),
+        Between(ArrayFromJSON(timestamp(TimeUnit::SECOND), arr_json),
+                ArrayFromJSON(timestamp(TimeUnit::SECOND, "America/New_York"), 
lhs_json),
+                ArrayFromJSON(timestamp(TimeUnit::SECOND, "Europe/Berlin"), 
rhs_json),
+                options, nullptr));
+    EXPECT_RAISES_WITH_MESSAGE_THAT(
+        TypeError,
+        ::testing::HasSubstr(
+            "Cannot compare timestamp with timezone to timestamp without 
timezone"),
+        Between(ArrayFromJSON(timestamp(TimeUnit::SECOND, "Africa/Nairobi"), 
arr_json),
+                ArrayFromJSON(timestamp(TimeUnit::SECOND), lhs_json),
+                ArrayFromJSON(timestamp(TimeUnit::SECOND), rhs_json), options, 
nullptr));
+  }
+}
+
+template <typename ArrowType>
+class TestBetweenDecimal : public ::testing::Test {};
+TYPED_TEST_SUITE(TestBetweenDecimal, DecimalArrowTypes);
+
+TYPED_TEST(TestBetweenDecimal, 3Arrays) {
+  auto ty = std::make_shared<TypeParam>(3, 2);

Review comment:
       Thanks for the suggestion. Was not sure how to get the decimal types in 
ty.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to