| /** |
| * 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 <cstddef> |
| #include <cstdint> |
| #include <cstring> |
| #include <limits> |
| #include <memory> |
| #include <string> |
| |
| #include "gtest/gtest.h" |
| |
| #include "catalog/CatalogAttribute.hpp" |
| #include "catalog/CatalogDatabase.hpp" |
| #include "catalog/CatalogRelation.hpp" |
| #include "expressions/ExpressionFactories.hpp" |
| #include "expressions/scalar/Scalar.hpp" |
| #include "expressions/scalar/ScalarAttribute.hpp" |
| #include "expressions/scalar/ScalarBinaryExpression.hpp" |
| #include "expressions/scalar/ScalarLiteral.hpp" |
| #include "expressions/scalar/ScalarUnaryExpression.hpp" |
| #include "types/DatetimeLit.hpp" |
| #include "types/IntervalLit.hpp" |
| #include "types/Type.hpp" |
| #include "types/TypeFactory.hpp" |
| #include "types/TypeID.hpp" |
| #include "types/TypedValue.hpp" |
| #include "types/operations/binary_operations/BinaryOperation.hpp" |
| #include "types/operations/binary_operations/BinaryOperationFactory.hpp" |
| #include "types/operations/binary_operations/BinaryOperationID.hpp" |
| #include "types/operations/unary_operations/NumericCastOperation.hpp" |
| #include "types/operations/unary_operations/UnaryOperation.hpp" |
| #include "types/operations/unary_operations/UnaryOperationFactory.hpp" |
| #include "types/operations/unary_operations/UnaryOperationID.hpp" |
| #include "utility/Macros.hpp" |
| |
| using std::int64_t; |
| using std::numeric_limits; |
| using std::size_t; |
| using std::string; |
| using std::strlen; |
| using std::unique_ptr; |
| |
| namespace quickstep { |
| |
| namespace { |
| |
| static const char kSampleStringShort[] = "foo"; |
| |
| static const char kSampleStringLong[] = |
| "Space is big. You just won't believe how vastly, hugely, mind-bogglingly " |
| "big it is. I mean, you may think it's a long way down the road to the " |
| "chemist's, but that's just peanuts to space."; |
| |
| } // namespace |
| |
| class ScalarTest : public ::testing::Test { |
| protected: |
| virtual void SetUp() { |
| database_.reset(new CatalogDatabase(NULL, "database_")); |
| |
| rel_numeric_ = createCatalogRelation("rel_numeric_"); |
| attr_int_ = createCatalogAttribute(rel_numeric_, "attr_int", TypeFactory::GetType(kInt)); |
| attr_long_ = createCatalogAttribute(rel_numeric_, "attr_long", TypeFactory::GetType(kLong)); |
| attr_float_ = createCatalogAttribute(rel_numeric_, "attr_float", TypeFactory::GetType(kFloat)); |
| attr_double_ = createCatalogAttribute(rel_numeric_, "attr_double", TypeFactory::GetType(kDouble)); |
| |
| rel_date_ = createCatalogRelation("rel_date_"); |
| attr_datetime_ = createCatalogAttribute(rel_date_, "attr_datetime", TypeFactory::GetType(kDatetime)); |
| attr_datetime_interval_ = |
| createCatalogAttribute(rel_date_, "attr_datetime_interval", TypeFactory::GetType(kDatetimeInterval)); |
| attr_year_month_interval_ = |
| createCatalogAttribute(rel_date_, "attr_year_month_interval", TypeFactory::GetType(kYearMonthInterval)); |
| |
| rel_string_ = createCatalogRelation("rel_string_"); |
| size_t length = 12; |
| attr_char_ = createCatalogAttribute(rel_string_, "attr_char", TypeFactory::GetType(kChar, length)); |
| attr_varchar_ = createCatalogAttribute(rel_string_, "attr_varchar", TypeFactory::GetType(kVarChar, length)); |
| } |
| |
| void checkScalarUnaryExpressionSerialization(const UnaryOperation &operation) { |
| checkScalarSerialization(ScalarUnaryExpression(operation, createScalarInt(numeric_limits<int>::max()))); |
| checkScalarSerialization(ScalarUnaryExpression(operation, createScalarLong(numeric_limits<int64_t>::max()))); |
| checkScalarSerialization(ScalarUnaryExpression(operation, createScalarFloat(numeric_limits<float>::max()))); |
| checkScalarSerialization(ScalarUnaryExpression(operation, createScalarDouble(numeric_limits<double>::max()))); |
| } |
| |
| void checkScalarBinaryExpressionSerialization(const BinaryOperation &operation) { |
| checkScalarSerialization(ScalarBinaryExpression(operation, createScalarInt(9), createScalarInt(-1))); |
| checkScalarSerialization( |
| ScalarBinaryExpression(operation, createScalarInt(0), createScalarLong(static_cast<int64_t>(9)))); |
| checkScalarSerialization( |
| ScalarBinaryExpression(operation, createScalarInt(4), createScalarFloat(static_cast<float>(1.2)))); |
| checkScalarSerialization( |
| ScalarBinaryExpression(operation, createScalarInt(7), createScalarDouble(static_cast<double>(3.14)))); |
| |
| checkScalarSerialization( |
| ScalarBinaryExpression(operation, createScalarLong(static_cast<int64_t>(-10)), createScalarInt(8))); |
| checkScalarSerialization( |
| ScalarBinaryExpression(operation, |
| createScalarLong(static_cast<int64_t>(9)), |
| createScalarLong(static_cast<int64_t>(-9)))); |
| checkScalarSerialization( |
| ScalarBinaryExpression(operation, |
| createScalarLong(static_cast<int64_t>(-9)), |
| createScalarFloat(static_cast<float>(1.2)))); |
| checkScalarSerialization( |
| ScalarBinaryExpression(operation, |
| createScalarLong(static_cast<int64_t>(9)), |
| createScalarDouble(static_cast<double>(3.14)))); |
| |
| checkScalarSerialization( |
| ScalarBinaryExpression(operation, createScalarFloat(static_cast<float>(1.2)), createScalarInt(-1))); |
| checkScalarSerialization( |
| ScalarBinaryExpression(operation, |
| createScalarFloat(static_cast<float>(1.2)), |
| createScalarLong(static_cast<int64_t>(-9)))); |
| checkScalarSerialization( |
| ScalarBinaryExpression(operation, |
| createScalarFloat(static_cast<float>(1.2)), |
| createScalarFloat(static_cast<float>(-3.6)))); |
| checkScalarSerialization( |
| ScalarBinaryExpression(operation, |
| createScalarFloat(static_cast<float>(-1.2)), |
| createScalarDouble(static_cast<double>(3.14)))); |
| |
| checkScalarSerialization( |
| ScalarBinaryExpression(operation, createScalarDouble(static_cast<double>(3.14)), createScalarInt(6))); |
| checkScalarSerialization( |
| ScalarBinaryExpression(operation, |
| createScalarDouble(static_cast<double>(3.14)), |
| createScalarLong(static_cast<int64_t>(-9)))); |
| checkScalarSerialization( |
| ScalarBinaryExpression(operation, |
| createScalarDouble(static_cast<double>(-3.14)), |
| createScalarFloat(static_cast<float>(1.2)))); |
| checkScalarSerialization( |
| ScalarBinaryExpression(operation, |
| createScalarDouble(static_cast<double>(3.14)), |
| createScalarDouble(static_cast<double>(-3.14)))); |
| } |
| |
| CatalogRelation* createCatalogRelation(const std::string &name) { |
| return database_->getRelationByIdMutable(database_->addRelation(new CatalogRelation(NULL, name))); |
| } |
| |
| const CatalogAttribute* createCatalogAttribute(CatalogRelation* rel, const std::string &name, const Type &type) { |
| rel->addAttribute(new CatalogAttribute(NULL, name, type)); |
| return rel->getAttributeByName(name); |
| } |
| |
| // All four pointers created below are owned by a Scalar subclass. |
| static Scalar* createScalarInt(int int_literal) { |
| return new ScalarLiteral(TypedValue(int_literal), TypeFactory::GetType(kInt)); |
| } |
| |
| static Scalar* createScalarLong(int64_t long_literal) { |
| return new ScalarLiteral(TypedValue(long_literal), TypeFactory::GetType(kLong)); |
| } |
| |
| static Scalar* createScalarFloat(float float_literal) { |
| return new ScalarLiteral(TypedValue(float_literal), TypeFactory::GetType(kFloat)); |
| } |
| |
| static Scalar* createScalarDouble(double double_literal) { |
| return new ScalarLiteral(TypedValue(double_literal), TypeFactory::GetType(kDouble)); |
| } |
| |
| void checkScalarSerialization(const Scalar &scalar) { |
| unique_ptr<Scalar> scalar_from_proto(ScalarFactory::ReconstructFromProto(scalar.getProto(), *database_)); |
| compareScalar(scalar, *scalar_from_proto); |
| } |
| |
| static void compareScalar(const Scalar &expected, const Scalar &checked) { |
| ASSERT_EQ(expected.getDataSource(), checked.getDataSource()); |
| ASSERT_TRUE(expected.getType().equals(checked.getType())); |
| |
| switch (expected.getDataSource()) { |
| case Scalar::kLiteral: { |
| compareTypedValue(expected.getType(), expected.getStaticValue(), checked.getStaticValue()); |
| break; |
| } |
| case Scalar::kAttribute: { |
| compareCatalogAttribute(static_cast<const ScalarAttribute&>(expected).getAttribute(), |
| static_cast<const ScalarAttribute&>(checked).getAttribute()); |
| break; |
| } |
| case Scalar::kUnaryExpression: { |
| EXPECT_EQ(expected.hasStaticValue(), checked.hasStaticValue()); |
| if (expected.hasStaticValue()) { |
| compareTypedValue(expected.getType(), expected.getStaticValue(), checked.getStaticValue()); |
| } |
| |
| EXPECT_EQ(static_cast<const ScalarUnaryExpression&>(expected).operation_.getUnaryOperationID(), |
| static_cast<const ScalarUnaryExpression&>(checked).operation_.getUnaryOperationID()); |
| compareScalar(*(static_cast<const ScalarUnaryExpression&>(expected).operand_), |
| *(static_cast<const ScalarUnaryExpression&>(checked).operand_)); |
| break; |
| } |
| case Scalar::kBinaryExpression: { |
| EXPECT_EQ(expected.hasStaticValue(), checked.hasStaticValue()); |
| if (expected.hasStaticValue()) { |
| compareTypedValue(expected.getType(), expected.getStaticValue(), checked.getStaticValue()); |
| } |
| |
| EXPECT_EQ(static_cast<const ScalarBinaryExpression&>(expected).operation_.getBinaryOperationID(), |
| static_cast<const ScalarBinaryExpression&>(checked).operation_.getBinaryOperationID()); |
| compareScalar(*(static_cast<const ScalarBinaryExpression&>(expected).left_operand_), |
| *(static_cast<const ScalarBinaryExpression&>(checked).left_operand_)); |
| compareScalar(*(static_cast<const ScalarBinaryExpression&>(expected).right_operand_), |
| *(static_cast<const ScalarBinaryExpression&>(checked).right_operand_)); |
| break; |
| } |
| default: |
| FATAL_ERROR("checked is not a valid Scalar in compareScalar"); |
| } |
| } |
| |
| static void compareTypedValue(const Type &type, |
| const TypedValue &expected, |
| const TypedValue &checked) { |
| ASSERT_EQ(expected.isNull(), checked.isNull()); |
| |
| if (expected.isNull()) { |
| return; |
| } |
| |
| switch (type.getTypeID()) { |
| case kInt: |
| EXPECT_EQ(expected.getLiteral<int>(), checked.getLiteral<int>()); |
| break; |
| case kLong: |
| EXPECT_EQ(expected.getLiteral<int64_t>(), checked.getLiteral<int64_t>()); |
| break; |
| case kFloat: |
| EXPECT_FLOAT_EQ(expected.getLiteral<float>(), checked.getLiteral<float>()); |
| break; |
| case kDouble: |
| EXPECT_DOUBLE_EQ(expected.getLiteral<double>(), checked.getLiteral<double>()); |
| break; |
| case kDatetime: |
| EXPECT_EQ(expected.getLiteral<DatetimeLit>(), checked.getLiteral<DatetimeLit>()); |
| break; |
| case kDatetimeInterval: |
| EXPECT_EQ(expected.getLiteral<DatetimeIntervalLit>(), checked.getLiteral<DatetimeIntervalLit>()); |
| break; |
| case kYearMonthInterval: |
| EXPECT_EQ(expected.getLiteral<YearMonthIntervalLit>(), checked.getLiteral<YearMonthIntervalLit>()); |
| break; |
| case kChar: // Fall through. |
| case kVarChar: |
| EXPECT_EQ(expected.getDataSize(), checked.getDataSize()); |
| EXPECT_EQ(expected.getAsciiStringLength(), checked.getAsciiStringLength()); |
| EXPECT_STREQ(static_cast<const char*>(expected.getDataPtr()), |
| static_cast<const char*>(checked.getDataPtr())); |
| break; |
| default: |
| FATAL_ERROR("Unrecognized Type in compareTypedValue"); |
| } |
| } |
| |
| static void compareCatalogAttribute(const CatalogAttribute &expected, const CatalogAttribute &checked) { |
| EXPECT_EQ(expected.getID(), checked.getID()); |
| EXPECT_EQ(expected.getName(), checked.getName()); |
| EXPECT_TRUE(expected.getType().equals(checked.getType())); |
| } |
| |
| unique_ptr<CatalogDatabase> database_; |
| // Both pointers below are owned by database_. |
| CatalogRelation *rel_numeric_, *rel_date_, *rel_string_; |
| // All pointers below are owned by relations. |
| const CatalogAttribute *attr_int_, *attr_long_, *attr_float_, *attr_double_, |
| *attr_datetime_, *attr_datetime_interval_, *attr_year_month_interval_, |
| *attr_char_, *attr_varchar_; |
| }; |
| |
| TEST_F(ScalarTest, ScalarLiteralSerializationTest) { |
| checkScalarSerialization(ScalarLiteral(TypedValue(kInt), |
| TypeFactory::GetType(kInt, true /* nullable */))); |
| checkScalarSerialization(ScalarLiteral(TypedValue(4), |
| TypeFactory::GetType(kInt, false /* nullable */))); |
| |
| checkScalarSerialization(ScalarLiteral(TypedValue(kLong), |
| TypeFactory::GetType(kLong, true /* nullable */))); |
| checkScalarSerialization(ScalarLiteral(TypedValue(static_cast<int64_t>(9)), |
| TypeFactory::GetType(kLong, false /* nullable */))); |
| |
| checkScalarSerialization(ScalarLiteral(TypedValue(kFloat), |
| TypeFactory::GetType(kFloat, true /* nullable */))); |
| checkScalarSerialization(ScalarLiteral(TypedValue(static_cast<float>(1.2)), |
| TypeFactory::GetType(kFloat, false /* nullable */))); |
| |
| checkScalarSerialization(ScalarLiteral(TypedValue(kDouble), |
| TypeFactory::GetType(kDouble, true /* nullable */))); |
| checkScalarSerialization(ScalarLiteral(TypedValue(static_cast<double>(1.3)), |
| TypeFactory::GetType(kDouble, false /* nullable */))); |
| |
| checkScalarSerialization(ScalarLiteral(TypedValue(kChar), |
| TypeFactory::GetType(kChar, 0, true /* nullable */))); |
| checkScalarSerialization(ScalarLiteral(TypedValue(kChar, kSampleStringShort, strlen(kSampleStringShort)+5), |
| TypeFactory::GetType(kChar, |
| strlen(kSampleStringShort) + 5, |
| false /* nullable */))); |
| |
| checkScalarSerialization(ScalarLiteral(TypedValue(kVarChar), |
| TypeFactory::GetType(kVarChar, 0, true))); |
| checkScalarSerialization(ScalarLiteral(TypedValue(kVarChar, kSampleStringLong, strlen(kSampleStringLong)+1), |
| TypeFactory::GetType(kVarChar, |
| strlen(kSampleStringLong), |
| false /* nullable */))); |
| |
| checkScalarSerialization(ScalarLiteral(TypedValue(kDatetime), |
| TypeFactory::GetType(kDatetime, true /* nullable */))); |
| DatetimeLit datetime; |
| datetime.ticks = static_cast<int64_t>(0xFFFFF); |
| checkScalarSerialization(ScalarLiteral(TypedValue(datetime), |
| TypeFactory::GetType(kDatetime, false /* nullable */))); |
| |
| checkScalarSerialization(ScalarLiteral(TypedValue(kDatetimeInterval), |
| TypeFactory::GetType(kDatetimeInterval, |
| true /* nullable */))); |
| DatetimeIntervalLit datetime_interval; |
| datetime_interval.interval_ticks = static_cast<int64_t>(0xFF); |
| checkScalarSerialization(ScalarLiteral(TypedValue(datetime_interval), |
| TypeFactory::GetType(kDatetimeInterval, |
| false /* nullable */))); |
| |
| checkScalarSerialization(ScalarLiteral(TypedValue(kYearMonthInterval), |
| TypeFactory::GetType(kYearMonthInterval, |
| true /* nullable */))); |
| YearMonthIntervalLit year_month_interval; |
| year_month_interval.months = static_cast<int64_t>(14); |
| checkScalarSerialization(ScalarLiteral(TypedValue(year_month_interval), |
| TypeFactory::GetType(kYearMonthInterval, |
| false /* nullable */))); |
| } |
| |
| TEST_F(ScalarTest, ScalarAttributeSerializationTest) { |
| checkScalarSerialization(ScalarAttribute(*attr_int_)); |
| checkScalarSerialization(ScalarAttribute(*attr_long_)); |
| checkScalarSerialization(ScalarAttribute(*attr_float_)); |
| checkScalarSerialization(ScalarAttribute(*attr_double_)); |
| |
| checkScalarSerialization(ScalarAttribute(*attr_datetime_)); |
| checkScalarSerialization(ScalarAttribute(*attr_datetime_interval_)); |
| checkScalarSerialization(ScalarAttribute(*attr_year_month_interval_)); |
| |
| checkScalarSerialization(ScalarAttribute(*attr_char_)); |
| checkScalarSerialization(ScalarAttribute(*attr_varchar_)); |
| } |
| |
| TEST_F(ScalarTest, ScalarUnaryExpressionSerializationTest) { |
| checkScalarUnaryExpressionSerialization(UnaryOperationFactory::GetUnaryOperation(UnaryOperationID::kNegate)); |
| checkScalarUnaryExpressionSerialization(NumericCastOperation::Instance(TypeFactory::GetType(kDouble))); |
| } |
| |
| TEST_F(ScalarTest, ScalarBinaryExpressionSerializationTest) { |
| checkScalarBinaryExpressionSerialization(BinaryOperationFactory::GetBinaryOperation(BinaryOperationID::kAdd)); |
| checkScalarBinaryExpressionSerialization(BinaryOperationFactory::GetBinaryOperation(BinaryOperationID::kSubtract)); |
| checkScalarBinaryExpressionSerialization(BinaryOperationFactory::GetBinaryOperation(BinaryOperationID::kMultiply)); |
| checkScalarBinaryExpressionSerialization(BinaryOperationFactory::GetBinaryOperation(BinaryOperationID::kDivide)); |
| checkScalarBinaryExpressionSerialization(BinaryOperationFactory::GetBinaryOperation(BinaryOperationID::kModulo)); |
| } |
| |
| } // namespace quickstep |