| /* |
| * 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 "paimon/predicate/literal.h" |
| |
| #include <utility> |
| |
| #include "gtest/gtest.h" |
| #include "paimon/common/utils/decimal_utils.h" |
| #include "paimon/data/decimal.h" |
| #include "paimon/data/timestamp.h" |
| #include "paimon/status.h" |
| #include "paimon/testing/utils/testharness.h" |
| |
| namespace paimon::test { |
| |
| class LiteralTest : public ::testing::Test { |
| public: |
| void SetUp() override {} |
| void TearDown() override {} |
| |
| void CheckResult(const Literal& literal1, const Literal& literal2, FieldType type) { |
| ASSERT_FALSE(literal1.IsNull()); |
| ASSERT_EQ(literal1.GetType(), type); |
| ASSERT_FALSE(literal2.IsNull()); |
| ASSERT_EQ(literal2.GetType(), type); |
| |
| // literal1 < literal2 |
| ASSERT_OK_AND_ASSIGN(auto compare_result, literal1.CompareTo(literal2)); |
| ASSERT_EQ(compare_result, -1); |
| ASSERT_OK_AND_ASSIGN(compare_result, literal2.CompareTo(literal1)); |
| ASSERT_EQ(compare_result, 1); |
| ASSERT_FALSE(literal1 == literal2); |
| ASSERT_TRUE(literal1 != literal2); |
| |
| // literal1 == literal1 |
| ASSERT_OK_AND_ASSIGN(compare_result, literal1.CompareTo(literal1)); |
| ASSERT_EQ(compare_result, 0); |
| ASSERT_TRUE(literal1 == literal1); |
| ASSERT_FALSE(literal1 != literal1); |
| |
| // literal1 == copy_literal1 |
| Literal copy_literal1 = literal1; |
| ASSERT_OK_AND_ASSIGN(compare_result, copy_literal1.CompareTo(literal1)); |
| ASSERT_EQ(compare_result, 0); |
| ASSERT_TRUE(literal1 == copy_literal1); |
| ASSERT_FALSE(literal1 != copy_literal1); |
| } |
| }; |
| |
| TEST_F(LiteralTest, TestSimple) { |
| { |
| Literal literal1(false); |
| Literal literal2(true); |
| CheckResult(literal1, literal2, FieldType::BOOLEAN); |
| ASSERT_EQ(literal1.ToString(), "false"); |
| ASSERT_EQ(literal2.ToString(), "true"); |
| } |
| { |
| Literal literal1(static_cast<int8_t>(10)); |
| Literal literal2(static_cast<int8_t>(20)); |
| CheckResult(literal1, literal2, FieldType::TINYINT); |
| ASSERT_EQ(literal1.ToString(), std::string(1, 10)); |
| ASSERT_EQ(literal2.ToString(), std::string(1, 20)); |
| } |
| { |
| Literal literal1(static_cast<int16_t>(100)); |
| Literal literal2(static_cast<int16_t>(200)); |
| CheckResult(literal1, literal2, FieldType::SMALLINT); |
| ASSERT_EQ(literal1.ToString(), "100"); |
| ASSERT_EQ(literal2.ToString(), "200"); |
| } |
| { |
| Literal literal1(static_cast<int32_t>(10000)); |
| Literal literal2(static_cast<int32_t>(20000)); |
| CheckResult(literal1, literal2, FieldType::INT); |
| ASSERT_EQ(literal1.ToString(), "10000"); |
| ASSERT_EQ(literal2.ToString(), "20000"); |
| } |
| { |
| Literal literal1(static_cast<int64_t>(1000000)); |
| Literal literal2(static_cast<int64_t>(2000000)); |
| CheckResult(literal1, literal2, FieldType::BIGINT); |
| ASSERT_EQ(literal1.ToString(), "1000000"); |
| ASSERT_EQ(literal2.ToString(), "2000000"); |
| } |
| { |
| Literal literal1(static_cast<float>(1000.5)); |
| Literal literal2(static_cast<float>(2000.6)); |
| CheckResult(literal1, literal2, FieldType::FLOAT); |
| ASSERT_EQ(literal1.ToString(), "1000.5"); |
| ASSERT_EQ(literal2.ToString(), "2000.6"); |
| } |
| { |
| Literal literal1(1000.5555); |
| Literal literal2(2000.6666); |
| CheckResult(literal1, literal2, FieldType::DOUBLE); |
| ASSERT_EQ(literal1.ToString(), "1000.56"); |
| ASSERT_EQ(literal2.ToString(), "2000.67"); |
| } |
| { |
| std::string str1("abandon"); |
| std::string str2("abandon1"); |
| Literal literal1(FieldType::STRING, str1.data(), str1.size()); |
| Literal literal2(FieldType::STRING, str2.data(), str2.size()); |
| CheckResult(literal1, literal2, FieldType::STRING); |
| ASSERT_EQ(literal1.ToString(), "abandon"); |
| ASSERT_EQ(literal2.ToString(), "abandon1"); |
| } |
| { |
| std::string str1("快乐每一天"); |
| std::string str2("快乐每一天!"); |
| Literal literal1(FieldType::BINARY, str1.data(), str1.size()); |
| Literal literal2(FieldType::BINARY, str2.data(), str2.size()); |
| CheckResult(literal1, literal2, FieldType::BINARY); |
| ASSERT_EQ(literal1.ToString(), "快乐每一天"); |
| ASSERT_EQ(literal2.ToString(), "快乐每一天!"); |
| } |
| { |
| Literal literal1(FieldType::DATE, 10000); |
| Literal literal2(FieldType::DATE, 20000); |
| CheckResult(literal1, literal2, FieldType::DATE); |
| ASSERT_EQ(literal1.ToString(), "10000"); |
| ASSERT_EQ(literal2.ToString(), "20000"); |
| } |
| { |
| Literal literal1(Timestamp(1725875365442l, 120000)); |
| Literal literal2(Timestamp(1725875365442l, 120001)); |
| CheckResult(literal1, literal2, FieldType::TIMESTAMP); |
| ASSERT_EQ(literal1.ToString(), "2024-09-09 09:49:25.442120000"); |
| ASSERT_EQ(literal2.ToString(), "2024-09-09 09:49:25.442120001"); |
| } |
| { |
| Literal literal1(Timestamp(1725875365442l, 120000)); |
| Literal literal2(Timestamp(1725875365443l, 110000)); |
| CheckResult(literal1, literal2, FieldType::TIMESTAMP); |
| ASSERT_EQ(literal1.ToString(), "2024-09-09 09:49:25.442120000"); |
| ASSERT_EQ(literal2.ToString(), "2024-09-09 09:49:25.443110000"); |
| } |
| { |
| // 1234.56 vs. 1235.56 |
| Literal literal1(Decimal(6, 2, 123456)); |
| Literal literal2(Decimal(6, 2, 123556)); |
| CheckResult(literal1, literal2, FieldType::DECIMAL); |
| ASSERT_EQ(literal1.ToString(), "1234.56"); |
| ASSERT_EQ(literal2.ToString(), "1235.56"); |
| } |
| { |
| // 1234.56 vs. 1234.567 |
| Literal literal1(Decimal(6, 2, 123456)); |
| Literal literal2(Decimal(7, 3, 1234567)); |
| CheckResult(literal1, literal2, FieldType::DECIMAL); |
| ASSERT_EQ(literal1.ToString(), "1234.56"); |
| ASSERT_EQ(literal2.ToString(), "1234.567"); |
| } |
| { |
| // 1234.56 vs. 123456789987654321.45678 |
| Literal literal1(Decimal(6, 2, 123456)); |
| Literal literal2( |
| Decimal(23, 5, DecimalUtils::StrToInt128("12345678998765432145678").value())); |
| CheckResult(literal1, literal2, FieldType::DECIMAL); |
| ASSERT_EQ(literal1.ToString(), "1234.56"); |
| ASSERT_EQ(literal2.ToString(), "123456789987654321.45678"); |
| } |
| } |
| |
| TEST_F(LiteralTest, TestWithNull) { |
| { |
| Literal literal1(FieldType::BIGINT); |
| Literal literal2(FieldType::BIGINT); |
| ASSERT_TRUE(literal1.IsNull()); |
| ASSERT_EQ(literal1.GetType(), FieldType::BIGINT); |
| ASSERT_TRUE(literal2.IsNull()); |
| ASSERT_EQ(literal2.GetType(), FieldType::BIGINT); |
| ASSERT_OK_AND_ASSIGN(auto compare_result, literal1.CompareTo(literal2)); |
| ASSERT_EQ(compare_result, 0); |
| } |
| { |
| Literal literal1(FieldType::BIGINT); |
| Literal literal2(FieldType::STRING); |
| ASSERT_TRUE(literal1.IsNull()); |
| ASSERT_EQ(literal1.GetType(), FieldType::BIGINT); |
| ASSERT_TRUE(literal2.IsNull()); |
| ASSERT_EQ(literal2.GetType(), FieldType::STRING); |
| ASSERT_NOK(literal1.CompareTo(literal2)); |
| } |
| { |
| Literal literal1(FieldType::INT); |
| Literal literal2(static_cast<int32_t>(10000)); |
| ASSERT_NOK(literal1.CompareTo(literal2)); |
| } |
| { |
| Literal literal1(FieldType::BIGINT); |
| Literal literal2(10000.5); |
| ASSERT_NOK(literal1.CompareTo(literal2)); |
| } |
| { |
| // type mismatch |
| Literal literal1(static_cast<int64_t>(10000)); |
| Literal literal2(10000.5); |
| ASSERT_NOK(literal1.CompareTo(literal2)); |
| } |
| } |
| |
| TEST_F(LiteralTest, TestOwnData) { |
| { |
| std::string data = "hello world"; |
| // literal points to data |
| Literal literal(FieldType::STRING, data.data(), data.size(), /*own data*/ false); |
| ASSERT_EQ(data, literal.GetValue<std::string>()); |
| // literal and literal2 point to data |
| Literal literal2 = literal; |
| ASSERT_EQ(data, literal2.GetValue<std::string>()); |
| ASSERT_EQ(data, literal.GetValue<std::string>()); |
| |
| std::string data3 = "copy hello world"; |
| Literal literal3(FieldType::STRING, data3.data(), data3.size(), /*own data*/ true); |
| ASSERT_EQ(data3, literal3.GetValue<std::string>()); |
| // literal3 point to data |
| literal3 = literal2; |
| ASSERT_EQ(data, literal3.GetValue<std::string>()); |
| ASSERT_EQ(data, literal2.GetValue<std::string>()); |
| } |
| { |
| std::string data = "hello world"; |
| // literal points to data |
| Literal literal(FieldType::BINARY, data.data(), data.size(), /*own data*/ false); |
| ASSERT_EQ(data, literal.GetValue<std::string>()); |
| // literal and literal2 point to data |
| Literal literal2 = literal; |
| ASSERT_EQ(data, literal2.GetValue<std::string>()); |
| ASSERT_EQ(data, literal.GetValue<std::string>()); |
| |
| std::string data3 = "copy hello world"; |
| Literal literal3(FieldType::BINARY, data3.data(), data3.size(), /*own data*/ true); |
| ASSERT_EQ(data3, literal3.GetValue<std::string>()); |
| // literal3 point to data |
| literal3 = literal2; |
| ASSERT_EQ(data, literal3.GetValue<std::string>()); |
| ASSERT_EQ(data, literal2.GetValue<std::string>()); |
| } |
| { |
| std::string data = "hello world"; |
| // literal points to data |
| Literal literal(FieldType::STRING, data.data(), data.size(), /*own data*/ false); |
| ASSERT_EQ(data, literal.GetValue<std::string>()); |
| Literal literal2 = std::move(literal); |
| // literal2 point to data, literal point to null |
| ASSERT_EQ(data, literal2.GetValue<std::string>()); |
| |
| std::string data3 = "copy hello world"; |
| Literal literal3(FieldType::STRING, data3.data(), data3.size(), /*own data*/ true); |
| ASSERT_EQ(data3, literal3.GetValue<std::string>()); |
| // literal3 point to data, literal2 point to null |
| literal3 = std::move(literal2); |
| ASSERT_EQ(data, literal3.GetValue<std::string>()); |
| } |
| { |
| // test empty string |
| std::string data = ""; |
| Literal literal(FieldType::STRING, data.data(), data.size(), /*own data*/ false); |
| ASSERT_EQ(data, literal.GetValue<std::string>()); |
| Literal literal2 = literal; |
| ASSERT_EQ(data, literal.GetValue<std::string>()); |
| |
| std::string data3 = "copy hello world"; |
| Literal literal3(FieldType::STRING, data3.data(), data3.size(), /*own data*/ true); |
| ASSERT_EQ(data3, literal3.GetValue<std::string>()); |
| literal3 = std::move(literal2); |
| ASSERT_EQ(data, literal3.GetValue<std::string>()); |
| |
| Literal literal4(FieldType::STRING, data.data(), data.size(), /*own data*/ true); |
| ASSERT_EQ(data, literal4.GetValue<std::string>()); |
| literal4 = literal3; |
| ASSERT_EQ(data, literal4.GetValue<std::string>()); |
| } |
| } |
| } // namespace paimon::test |