blob: 15436d84fb3dc6a3b353945f60cbaae6b2ccaaf7 [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/SubtractBinaryOperation.hpp"
#include "types/operations/binary_operations/tests/BinaryOperationTestUtil.hpp"
#include "gtest/gtest.h"
namespace quickstep {
TEST(SubtractBinaryOperationTest, ResultTypeForPartialArgumentTypesTest) {
// If both argument types are unknown, the result is unknown.
EXPECT_EQ(nullptr,
SubtractBinaryOperation::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 = SubtractBinaryOperation::Instance().resultTypeForPartialArgumentTypes(
nullptr,
&TypeFactory::GetType(kDouble, false));
ASSERT_NE(result_type, nullptr);
EXPECT_TRUE(TypeFactory::GetType(kDouble, true).equals(*result_type));
result_type = SubtractBinaryOperation::Instance().resultTypeForPartialArgumentTypes(
nullptr,
&TypeFactory::GetType(kDouble, true));
ASSERT_NE(result_type, nullptr);
EXPECT_TRUE(TypeFactory::GetType(kDouble, true).equals(*result_type));
result_type = SubtractBinaryOperation::Instance().resultTypeForPartialArgumentTypes(
&TypeFactory::GetType(kDouble, false),
nullptr);
ASSERT_NE(result_type, nullptr);
EXPECT_TRUE(TypeFactory::GetType(kDouble, true).equals(*result_type));
result_type = SubtractBinaryOperation::Instance().resultTypeForPartialArgumentTypes(
&TypeFactory::GetType(kDouble, true),
nullptr);
ASSERT_NE(result_type, nullptr);
EXPECT_TRUE(TypeFactory::GetType(kDouble, true).equals(*result_type));
// If the left argument is a Date, then the result should be a Date.
result_type =
SubtractBinaryOperation::Instance().resultTypeForPartialArgumentTypes(
&TypeFactory::GetType(kDate, false), nullptr);
ASSERT_NE(result_type, nullptr);
EXPECT_TRUE(TypeFactory::GetType(kDate, true).equals(*result_type));
// If the left argument (the minuend) is an interval, then the subtrahend and
// the result must also be the same kind of interval.
result_type = SubtractBinaryOperation::Instance().resultTypeForPartialArgumentTypes(
&TypeFactory::GetType(kDatetimeInterval, false),
nullptr);
ASSERT_NE(result_type, nullptr);
EXPECT_TRUE(TypeFactory::GetType(kDatetimeInterval, true).equals(*result_type));
result_type = SubtractBinaryOperation::Instance().resultTypeForPartialArgumentTypes(
&TypeFactory::GetType(kDatetimeInterval, true),
nullptr);
ASSERT_NE(result_type, nullptr);
EXPECT_TRUE(TypeFactory::GetType(kDatetimeInterval, true).equals(*result_type));
result_type = SubtractBinaryOperation::Instance().resultTypeForPartialArgumentTypes(
&TypeFactory::GetType(kYearMonthInterval, false),
nullptr);
ASSERT_NE(result_type, nullptr);
EXPECT_TRUE(TypeFactory::GetType(kYearMonthInterval, true).equals(*result_type));
result_type = SubtractBinaryOperation::Instance().resultTypeForPartialArgumentTypes(
&TypeFactory::GetType(kYearMonthInterval, true),
nullptr);
ASSERT_NE(result_type, nullptr);
EXPECT_TRUE(TypeFactory::GetType(kYearMonthInterval, true).equals(*result_type));
// If the right argument (the subtrahend) is a Datetime, then the minuend
// must also be a Datetime and the result is an interval.
result_type = SubtractBinaryOperation::Instance().resultTypeForPartialArgumentTypes(
nullptr,
&TypeFactory::GetType(kDatetime, false));
ASSERT_NE(result_type, nullptr);
EXPECT_TRUE(TypeFactory::GetType(kDatetimeInterval, true).equals(*result_type));
result_type = SubtractBinaryOperation::Instance().resultTypeForPartialArgumentTypes(
nullptr,
&TypeFactory::GetType(kDatetime, true));
ASSERT_NE(result_type, nullptr);
EXPECT_TRUE(TypeFactory::GetType(kDatetimeInterval, true).equals(*result_type));
// Other argument types give ambiguous or inapplicable results.
for (const TypeID left_type_id : {kInt, kLong, kFloat, kDatetime, kChar, kVarChar}) {
const Type *left_type = TypeFactory::TypeRequiresLengthParameter(left_type_id)
? &TypeFactory::GetType(left_type_id, 10, false)
: &TypeFactory::GetType(left_type_id, false);
EXPECT_EQ(nullptr,
SubtractBinaryOperation::Instance().resultTypeForPartialArgumentTypes(
left_type,
nullptr));
EXPECT_EQ(nullptr,
SubtractBinaryOperation::Instance().resultTypeForPartialArgumentTypes(
&left_type->getNullableVersion(),
nullptr));
}
for (const TypeID right_type_id
: {kInt, kLong, kFloat, kDatetimeInterval, kYearMonthInterval, kChar, kVarChar}) {
const Type *right_type = TypeFactory::TypeRequiresLengthParameter(right_type_id)
? &TypeFactory::GetType(right_type_id, 10, false)
: &TypeFactory::GetType(right_type_id, false);
EXPECT_EQ(nullptr,
SubtractBinaryOperation::Instance().resultTypeForPartialArgumentTypes(
nullptr,
right_type));
EXPECT_EQ(nullptr,
SubtractBinaryOperation::Instance().resultTypeForPartialArgumentTypes(
nullptr,
&right_type->getNullableVersion()));
}
}
TEST(SubtractBinaryOperationTest, PartialTypeSignatureIsPlausibleTest) {
// --------------------------------------------------------------------------
// All 3 Types unknown.
EXPECT_TRUE(SubtractBinaryOperation::Instance().partialTypeSignatureIsPlausible(
nullptr, nullptr, nullptr));
// --------------------------------------------------------------------------
// Result type known, both argument types unknown.
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndUnknownArguments(
SubtractBinaryOperation::Instance(),
{kInt, kLong, kFloat, kDouble, kDatetime, kDatetimeInterval, kYearMonthInterval});
// --------------------------------------------------------------------------
// Result type unknown, one argument type known.
BinaryOperationTestUtil::CheckPlausibilityWithUnknownResultAndSingleKnownArgument(
SubtractBinaryOperation::Instance(),
{kInt, kLong, kFloat, kDouble, kDate, kDatetime, kDatetimeInterval, kYearMonthInterval},
true,
false);
BinaryOperationTestUtil::CheckPlausibilityWithUnknownResultAndSingleKnownArgument(
SubtractBinaryOperation::Instance(),
{kInt, kLong, kFloat, kDouble, kDatetime, kDatetimeInterval, kYearMonthInterval},
false,
true);
// --------------------------------------------------------------------------
// Result type and left argument type known.
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
SubtractBinaryOperation::Instance(), kInt, {kInt}, true, false);
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
SubtractBinaryOperation::Instance(), kLong, {kInt, kLong}, true, false);
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
SubtractBinaryOperation::Instance(), kFloat, {kInt, kFloat}, true, false);
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
SubtractBinaryOperation::Instance(), kDouble, {kInt, kLong, kFloat, kDouble}, true, false);
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
SubtractBinaryOperation::Instance(), kDate, {kDate}, true, false);
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
SubtractBinaryOperation::Instance(), kDatetime, {kDatetime}, true, false);
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
SubtractBinaryOperation::Instance(),
kDatetimeInterval, {kDatetime, kDatetimeInterval}, true, false);
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
SubtractBinaryOperation::Instance(), kYearMonthInterval, {kYearMonthInterval}, true, false);
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
SubtractBinaryOperation::Instance(), kChar, {}, true, false);
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
SubtractBinaryOperation::Instance(), kVarChar, {}, true, false);
// --------------------------------------------------------------------------
// Result type and right argument type known.
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
SubtractBinaryOperation::Instance(), kInt, {kInt}, false, true);
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
SubtractBinaryOperation::Instance(), kLong, {kInt, kLong}, false, true);
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
SubtractBinaryOperation::Instance(), kFloat, {kInt, kFloat}, false, true);
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
SubtractBinaryOperation::Instance(), kDouble, {kInt, kLong, kFloat, kDouble}, false, true);
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
SubtractBinaryOperation::Instance(),
kDatetime, {kDatetimeInterval, kYearMonthInterval}, false, true);
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
SubtractBinaryOperation::Instance(),
kDatetimeInterval, {kDatetime, kDatetimeInterval}, false, true);
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
SubtractBinaryOperation::Instance(), kYearMonthInterval, {kYearMonthInterval}, false, true);
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
SubtractBinaryOperation::Instance(), kChar, {}, false, true);
BinaryOperationTestUtil::CheckPlausibilityWithKnownResultAndSingleArgument(
SubtractBinaryOperation::Instance(), kVarChar, {}, false, true);
}
TEST(SubtractBinaryOperationTest, PushDownTypeHintTest) {
const Type *result_type = nullptr;
std::pair<const Type*, const Type*> hints
= SubtractBinaryOperation::Instance().pushDownTypeHint(result_type);
EXPECT_EQ(nullptr, hints.first);
EXPECT_EQ(nullptr, hints.second);
for (const TypeID type_id
: {kInt, kLong, kFloat, kDouble, kYearMonthInterval}) {
result_type = &TypeFactory::GetType(type_id, false);
hints = SubtractBinaryOperation::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 = SubtractBinaryOperation::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(kDate, false);
hints = SubtractBinaryOperation::Instance().pushDownTypeHint(result_type);
ASSERT_NE(hints.first, nullptr);
EXPECT_TRUE(result_type->equals(*hints.first));
EXPECT_EQ(&TypeFactory::GetType(kYearMonthInterval, true), hints.second);
// A hint of Datetime means the left argument should be Datetime and the
// right could be either interval type.
result_type = &TypeFactory::GetType(kDatetime, false);
hints = SubtractBinaryOperation::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(kDatetime, true);
hints = SubtractBinaryOperation::Instance().pushDownTypeHint(result_type);
ASSERT_NE(hints.first, nullptr);
EXPECT_TRUE(result_type->equals(*hints.first));
EXPECT_EQ(nullptr, hints.second);
// A hint of DatetimeInterval is ambiguous, because the arguments could be
// a pair of DateTimes or a pair of DatetimeIntervals.
result_type = &TypeFactory::GetType(kDatetimeInterval, false);
hints = SubtractBinaryOperation::Instance().pushDownTypeHint(result_type);
EXPECT_EQ(nullptr, hints.first);
EXPECT_EQ(nullptr, hints.second);
result_type = &TypeFactory::GetType(kDatetimeInterval, true);
hints = SubtractBinaryOperation::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 = SubtractBinaryOperation::Instance().pushDownTypeHint(result_type);
EXPECT_EQ(nullptr, hints.first);
EXPECT_EQ(nullptr, hints.second);
result_type = &TypeFactory::GetType(string_type_id, 10, true);
hints = SubtractBinaryOperation::Instance().pushDownTypeHint(result_type);
EXPECT_EQ(nullptr, hints.first);
EXPECT_EQ(nullptr, hints.second);
}
}
} // namespace quickstep