blob: 7aca09bf2c7fb109d0b8c9639d79068ccf5de3d3 [file] [log] [blame]
/**
* 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/BinaryOperation.hpp"
#include "types/operations/binary_operations/DivideBinaryOperation.hpp"
#include "types/operations/binary_operations/tests/BinaryOperationTestUtil.hpp"
#include "gtest/gtest.h"
namespace quickstep {
TEST(DivideBinaryOperationTest, ResultTypeForPartialArgumentTypesTest) {
// If both argument types are unknown, the result is unknown.
EXPECT_EQ(nullptr,
DivideBinaryOperation::Instance().resultTypeForPartialArgumentTypes(nullptr, nullptr));
// Double has highest precedence of numeric types, and dividing an interval
// type by a numeric type yields the same interval type.
for (const TypeID type_id : {kDouble, kDatetimeInterval, kYearMonthInterval}) {
const Type *result_type = DivideBinaryOperation::Instance().resultTypeForPartialArgumentTypes(
&TypeFactory::GetType(type_id, false),
nullptr);
ASSERT_NE(result_type, nullptr);
EXPECT_TRUE(TypeFactory::GetType(type_id, true).equals(*result_type));
result_type = DivideBinaryOperation::Instance().resultTypeForPartialArgumentTypes(
&TypeFactory::GetType(type_id, true),
nullptr);
ASSERT_NE(result_type, nullptr);
EXPECT_TRUE(TypeFactory::GetType(type_id, true).equals(*result_type));
}
// Other types for left argument are ambiguous or inapplicable.
for (const TypeID type_id : {kInt, kLong, kFloat, kDatetime}) {
EXPECT_EQ(nullptr,
DivideBinaryOperation::Instance().resultTypeForPartialArgumentTypes(
&TypeFactory::GetType(type_id, false),
nullptr));
EXPECT_EQ(nullptr,
DivideBinaryOperation::Instance().resultTypeForPartialArgumentTypes(
&TypeFactory::GetType(type_id, true),
nullptr));
}
for (const TypeID type_id : {kChar, kVarChar}) {
EXPECT_EQ(nullptr,
DivideBinaryOperation::Instance().resultTypeForPartialArgumentTypes(
&TypeFactory::GetType(type_id, 10, false),
nullptr));
EXPECT_EQ(nullptr,
DivideBinaryOperation::Instance().resultTypeForPartialArgumentTypes(
&TypeFactory::GetType(type_id, 10, true),
nullptr));
}
// Can't determine a return type from just the divisor (only numeric types
// are allowed as the divisor, but the result may be a numeric type OR an
// interval type).
for (const TypeID type_id
: {kInt, kLong, kFloat, kDouble, kDatetime, kDatetimeInterval, kYearMonthInterval}) {
EXPECT_EQ(nullptr,
DivideBinaryOperation::Instance().resultTypeForPartialArgumentTypes(
nullptr,
&TypeFactory::GetType(type_id, false)));
EXPECT_EQ(nullptr,
DivideBinaryOperation::Instance().resultTypeForPartialArgumentTypes(
nullptr,
&TypeFactory::GetType(type_id, true)));
}
for (const TypeID type_id : {kChar, kVarChar}) {
EXPECT_EQ(nullptr,
DivideBinaryOperation::Instance().resultTypeForPartialArgumentTypes(
nullptr,
&TypeFactory::GetType(type_id, 10, false)));
EXPECT_EQ(nullptr,
DivideBinaryOperation::Instance().resultTypeForPartialArgumentTypes(
nullptr,
&TypeFactory::GetType(type_id, 10, true)));
}
}
TEST(DivideBinaryOperationTest, PartialTypeSignatureIsPlausibleTest) {
// --------------------------------------------------------------------------
// All 3 Types unknown.
EXPECT_TRUE(DivideBinaryOperation::Instance().partialTypeSignatureIsPlausible(
nullptr, nullptr, nullptr));
// --------------------------------------------------------------------------
// Result type known, both argument types unknown.
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndUnknownArguments(
DivideBinaryOperation::Instance(),
{kInt, kLong, kFloat, kDouble, kDatetimeInterval, kYearMonthInterval});
// --------------------------------------------------------------------------
// Result type unknown, left argument type known.
BinaryOperationTestUtil::CheckPlausibilityWithUnknownResultAndSingleKnownArgument(
DivideBinaryOperation::Instance(),
{kInt, kLong, kFloat, kDouble, kDatetimeInterval, kYearMonthInterval},
true,
false);
// --------------------------------------------------------------------------
// Result type unknown, right argument type known.
BinaryOperationTestUtil::CheckPlausibilityWithUnknownResultAndSingleKnownArgument(
DivideBinaryOperation::Instance(),
{kInt, kLong, kFloat, kDouble},
false,
true);
// --------------------------------------------------------------------------
// Result type and left argument type known.
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
DivideBinaryOperation::Instance(), kInt, {kInt}, true, false);
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
DivideBinaryOperation::Instance(), kLong, {kInt, kLong}, true, false);
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
DivideBinaryOperation::Instance(), kFloat, {kInt, kFloat}, true, false);
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
DivideBinaryOperation::Instance(), kDouble, {kInt, kLong, kFloat, kDouble}, true, false);
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
DivideBinaryOperation::Instance(), kDatetime, {}, true, false);
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
DivideBinaryOperation::Instance(), kDatetimeInterval, {kDatetimeInterval}, true, false);
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
DivideBinaryOperation::Instance(), kYearMonthInterval, {kYearMonthInterval}, true, false);
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
DivideBinaryOperation::Instance(), kChar, {}, true, false);
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
DivideBinaryOperation::Instance(), kVarChar, {}, true, false);
// --------------------------------------------------------------------------
// Result type and right argument type known.
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
DivideBinaryOperation::Instance(), kInt, {kInt}, false, true);
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
DivideBinaryOperation::Instance(), kLong, {kInt, kLong}, false, true);
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
DivideBinaryOperation::Instance(), kFloat, {kInt, kFloat}, false, true);
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
DivideBinaryOperation::Instance(), kDouble, {kInt, kLong, kFloat, kDouble}, false, true);
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
DivideBinaryOperation::Instance(), kDatetime, {}, false, true);
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
DivideBinaryOperation::Instance(),
kDatetimeInterval, {kInt, kLong, kFloat, kDouble}, false, true);
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
DivideBinaryOperation::Instance(),
kYearMonthInterval, {kInt, kLong, kFloat, kDouble}, false, true);
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
DivideBinaryOperation::Instance(), kChar, {}, false, true);
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
DivideBinaryOperation::Instance(), kVarChar, {}, false, true);
}
TEST(DivideBinaryOperationTest, PushDownTypeHintTest) {
const Type *result_type = nullptr;
std::pair<const Type*, const Type*> hints
= DivideBinaryOperation::Instance().pushDownTypeHint(result_type);
EXPECT_EQ(nullptr, hints.first);
EXPECT_EQ(nullptr, hints.second);
// For any numeric result type, hints for arguments should be the same type.
for (const TypeID type_id : {kInt, kLong, kFloat, kDouble}) {
result_type = &TypeFactory::GetType(type_id, false);
hints = DivideBinaryOperation::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 = DivideBinaryOperation::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 result of an interval type means that the left argument should be the
// same interval type and the right could be any numeric type.
for (const TypeID type_id : {kDatetimeInterval, kYearMonthInterval}) {
result_type = &TypeFactory::GetType(type_id, false);
hints = DivideBinaryOperation::Instance().pushDownTypeHint(result_type);
ASSERT_NE(hints.first, nullptr);
EXPECT_TRUE(result_type->equals(*hints.first));
EXPECT_EQ(nullptr, hints.second);
result_type = &TypeFactory::GetType(type_id, true);
hints = DivideBinaryOperation::Instance().pushDownTypeHint(result_type);
ASSERT_NE(hints.first, nullptr);
EXPECT_TRUE(result_type->equals(*hints.first));
EXPECT_EQ(nullptr, hints.second);
}
// Division can't produce a Datetime or a string.
result_type = &TypeFactory::GetType(kDatetime, false);
hints = DivideBinaryOperation::Instance().pushDownTypeHint(result_type);
EXPECT_EQ(nullptr, hints.first);
EXPECT_EQ(nullptr, hints.second);
result_type = &TypeFactory::GetType(kDatetime, true);
hints = DivideBinaryOperation::Instance().pushDownTypeHint(result_type);
EXPECT_EQ(nullptr, hints.first);
EXPECT_EQ(nullptr, hints.second);
for (const TypeID type_id : {kChar, kVarChar}) {
result_type = &TypeFactory::GetType(type_id, 10, false);
hints = DivideBinaryOperation::Instance().pushDownTypeHint(result_type);
EXPECT_EQ(nullptr, hints.first);
EXPECT_EQ(nullptr, hints.second);
result_type = &TypeFactory::GetType(type_id, 10, true);
hints = DivideBinaryOperation::Instance().pushDownTypeHint(result_type);
EXPECT_EQ(nullptr, hints.first);
EXPECT_EQ(nullptr, hints.second);
}
}
} // namespace quickstep