| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| **/ |
| |
| #include <initializer_list> |
| #include <utility> |
| |
| #include "types/Type.hpp" |
| #include "types/TypeFactory.hpp" |
| #include "types/TypeID.hpp" |
| #include "types/operations/binary_operations/AddBinaryOperation.hpp" |
| #include "types/operations/binary_operations/BinaryOperation.hpp" |
| #include "types/operations/binary_operations/tests/BinaryOperationTestUtil.hpp" |
| |
| #include "gtest/gtest.h" |
| |
| namespace quickstep { |
| |
| TEST(AddBinaryOperationTest, ResultTypeForPartialArgumentTypesTest) { |
| // If both argument types are unknown, the result is unknown. |
| EXPECT_EQ(nullptr, |
| AddBinaryOperation::Instance().resultTypeForPartialArgumentTypes(nullptr, nullptr)); |
| |
| // If one of the arguments is a Double, the result is Double (since it has |
| // the highest precedence of the numeric types). |
| const Type *result_type = AddBinaryOperation::Instance().resultTypeForPartialArgumentTypes( |
| nullptr, |
| &TypeFactory::GetType(kDouble, false)); |
| ASSERT_NE(result_type, nullptr); |
| EXPECT_TRUE(TypeFactory::GetType(kDouble, true).equals(*result_type)); |
| |
| result_type = AddBinaryOperation::Instance().resultTypeForPartialArgumentTypes( |
| nullptr, |
| &TypeFactory::GetType(kDouble, true)); |
| ASSERT_NE(result_type, nullptr); |
| EXPECT_TRUE(TypeFactory::GetType(kDouble, true).equals(*result_type)); |
| |
| result_type = AddBinaryOperation::Instance().resultTypeForPartialArgumentTypes( |
| &TypeFactory::GetType(kDouble, false), |
| nullptr); |
| ASSERT_NE(result_type, nullptr); |
| EXPECT_TRUE(TypeFactory::GetType(kDouble, true).equals(*result_type)); |
| |
| result_type = AddBinaryOperation::Instance().resultTypeForPartialArgumentTypes( |
| &TypeFactory::GetType(kDouble, true), |
| nullptr); |
| ASSERT_NE(result_type, nullptr); |
| EXPECT_TRUE(TypeFactory::GetType(kDouble, true).equals(*result_type)); |
| |
| // A Date can be added with only YearMonthIntervalType resulting in a Date. |
| result_type = |
| AddBinaryOperation::Instance().resultTypeForPartialArgumentTypes( |
| &TypeFactory::GetType(kDate, true), nullptr); |
| ASSERT_NE(result_type, nullptr); |
| EXPECT_TRUE(TypeFactory::GetType(kDate, true).equals(*result_type)); |
| |
| // If one of the arguments is a Datetime, then it can be added with either |
| // interval type and will always yield a Datetime. |
| result_type = AddBinaryOperation::Instance().resultTypeForPartialArgumentTypes( |
| nullptr, |
| &TypeFactory::GetType(kDatetime, false)); |
| ASSERT_NE(result_type, nullptr); |
| EXPECT_TRUE(TypeFactory::GetType(kDatetime, true).equals(*result_type)); |
| |
| result_type = AddBinaryOperation::Instance().resultTypeForPartialArgumentTypes( |
| nullptr, |
| &TypeFactory::GetType(kDatetime, true)); |
| ASSERT_NE(result_type, nullptr); |
| EXPECT_TRUE(TypeFactory::GetType(kDatetime, true).equals(*result_type)); |
| |
| result_type = AddBinaryOperation::Instance().resultTypeForPartialArgumentTypes( |
| &TypeFactory::GetType(kDatetime, false), |
| nullptr); |
| ASSERT_NE(result_type, nullptr); |
| EXPECT_TRUE(TypeFactory::GetType(kDatetime, true).equals(*result_type)); |
| |
| result_type = AddBinaryOperation::Instance().resultTypeForPartialArgumentTypes( |
| &TypeFactory::GetType(kDatetime, true), |
| nullptr); |
| ASSERT_NE(result_type, nullptr); |
| EXPECT_TRUE(TypeFactory::GetType(kDatetime, true).equals(*result_type)); |
| |
| // Any other argument type is either inapplicable or yields an ambiguous |
| // result. |
| for (const TypeID type_id |
| : {kInt, kLong, kFloat, kDatetimeInterval, kYearMonthInterval}) { |
| EXPECT_EQ(nullptr, |
| AddBinaryOperation::Instance().resultTypeForPartialArgumentTypes( |
| nullptr, |
| &TypeFactory::GetType(type_id, false))); |
| EXPECT_EQ(nullptr, |
| AddBinaryOperation::Instance().resultTypeForPartialArgumentTypes( |
| nullptr, |
| &TypeFactory::GetType(type_id, true))); |
| EXPECT_EQ(nullptr, |
| AddBinaryOperation::Instance().resultTypeForPartialArgumentTypes( |
| &TypeFactory::GetType(type_id, false), |
| nullptr)); |
| EXPECT_EQ(nullptr, |
| AddBinaryOperation::Instance().resultTypeForPartialArgumentTypes( |
| &TypeFactory::GetType(type_id, true), |
| nullptr)); |
| } |
| |
| for (const TypeID type_id : {kChar, kVarChar}) { |
| EXPECT_EQ(nullptr, |
| AddBinaryOperation::Instance().resultTypeForPartialArgumentTypes( |
| nullptr, |
| &TypeFactory::GetType(type_id, 10, false))); |
| EXPECT_EQ(nullptr, |
| AddBinaryOperation::Instance().resultTypeForPartialArgumentTypes( |
| nullptr, |
| &TypeFactory::GetType(type_id, 10, true))); |
| EXPECT_EQ(nullptr, |
| AddBinaryOperation::Instance().resultTypeForPartialArgumentTypes( |
| &TypeFactory::GetType(type_id, 10, false), |
| nullptr)); |
| EXPECT_EQ(nullptr, |
| AddBinaryOperation::Instance().resultTypeForPartialArgumentTypes( |
| &TypeFactory::GetType(type_id, 10, true), |
| nullptr)); |
| } |
| } |
| |
| TEST(AddBinaryOperationTest, PartialTypeSignatureIsPlausibleTest) { |
| // -------------------------------------------------------------------------- |
| // All 3 Types unknown. |
| EXPECT_TRUE(AddBinaryOperation::Instance().partialTypeSignatureIsPlausible( |
| nullptr, nullptr, nullptr)); |
| |
| // -------------------------------------------------------------------------- |
| // Result type known, both argument types unknown. |
| |
| // When both arguments are unknown, any nullable result type that addition |
| // might possibly return is plausible. |
| BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndUnknownArguments( |
| AddBinaryOperation::Instance(), |
| {kInt, kLong, kFloat, kDouble, kDate, kDatetime, kDatetimeInterval, kYearMonthInterval}); |
| |
| // -------------------------------------------------------------------------- |
| // Result type unknown, one argument type known. |
| BinaryOperationTestUtil::CheckPlausibilityWithUnknownResultAndSingleKnownArgument( |
| AddBinaryOperation::Instance(), |
| {kInt, kLong, kFloat, kDouble, kDate, kDatetime, kDatetimeInterval, kYearMonthInterval}, |
| true, |
| true); |
| |
| // -------------------------------------------------------------------------- |
| // Result type and one argument type known. |
| BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument( |
| AddBinaryOperation::Instance(), kInt, {kInt}, true, true); |
| BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument( |
| AddBinaryOperation::Instance(), kLong, {kInt, kLong}, true, true); |
| BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument( |
| AddBinaryOperation::Instance(), kFloat, {kInt, kFloat}, true, true); |
| BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument( |
| AddBinaryOperation::Instance(), kDouble, {kInt, kLong, kFloat, kDouble}, true, true); |
| BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument( |
| AddBinaryOperation::Instance(), |
| kDate, {kDate}, true, true); |
| BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument( |
| AddBinaryOperation::Instance(), |
| kDatetime, {kDatetime, kDatetimeInterval}, true, true); |
| BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument( |
| AddBinaryOperation::Instance(), kDatetimeInterval, {kDatetimeInterval}, true, true); |
| BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument( |
| AddBinaryOperation::Instance(), kYearMonthInterval, {kYearMonthInterval}, true, true); |
| BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument( |
| AddBinaryOperation::Instance(), kChar, {}, true, true); |
| BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument( |
| AddBinaryOperation::Instance(), kVarChar, {}, true, true); |
| } |
| |
| TEST(AddBinaryOperationTest, PushDownTypeHintTest) { |
| const Type *result_type = nullptr; |
| std::pair<const Type*, const Type*> hints |
| = AddBinaryOperation::Instance().pushDownTypeHint(result_type); |
| EXPECT_EQ(nullptr, hints.first); |
| EXPECT_EQ(nullptr, hints.second); |
| |
| for (const TypeID type_id |
| : {kInt, kLong, kFloat, kDouble, kDatetimeInterval, kYearMonthInterval}) { |
| result_type = &TypeFactory::GetType(type_id, false); |
| hints = AddBinaryOperation::Instance().pushDownTypeHint(result_type); |
| ASSERT_NE(hints.first, nullptr); |
| ASSERT_NE(hints.second, nullptr); |
| EXPECT_TRUE(result_type->equals(*hints.first)); |
| EXPECT_TRUE(result_type->equals(*hints.second)); |
| |
| result_type = &TypeFactory::GetType(type_id, true); |
| hints = AddBinaryOperation::Instance().pushDownTypeHint(result_type); |
| ASSERT_NE(hints.first, nullptr); |
| ASSERT_NE(hints.second, nullptr); |
| EXPECT_TRUE(result_type->equals(*hints.first)); |
| EXPECT_TRUE(result_type->equals(*hints.second)); |
| } |
| |
| // A hint of Date is ambiguous, because one argument should be Date and other |
| // should be YearMonthInterval, but the order does not matter. |
| result_type = &TypeFactory::GetType(kDate, false); |
| hints = AddBinaryOperation::Instance().pushDownTypeHint(result_type); |
| EXPECT_EQ(nullptr, hints.first); |
| EXPECT_EQ(nullptr, hints.second); |
| |
| // A hint of Datetime is ambiguous, because one argument should be Datetime |
| // and the other should be some interval type. |
| result_type = &TypeFactory::GetType(kDatetime, false); |
| hints = AddBinaryOperation::Instance().pushDownTypeHint(result_type); |
| EXPECT_EQ(nullptr, hints.first); |
| EXPECT_EQ(nullptr, hints.second); |
| |
| result_type = &TypeFactory::GetType(kDatetime, true); |
| hints = AddBinaryOperation::Instance().pushDownTypeHint(result_type); |
| EXPECT_EQ(nullptr, hints.first); |
| EXPECT_EQ(nullptr, hints.second); |
| |
| for (const TypeID string_type_id : {kChar, kVarChar}) { |
| result_type = &TypeFactory::GetType(string_type_id, 10, false); |
| hints = AddBinaryOperation::Instance().pushDownTypeHint(result_type); |
| EXPECT_EQ(nullptr, hints.first); |
| EXPECT_EQ(nullptr, hints.second); |
| |
| result_type = &TypeFactory::GetType(string_type_id, 10, true); |
| hints = AddBinaryOperation::Instance().pushDownTypeHint(result_type); |
| EXPECT_EQ(nullptr, hints.first); |
| EXPECT_EQ(nullptr, hints.second); |
| } |
| } |
| |
| } // namespace quickstep |