blob: a561ccdfd74cf7b9ceb5f1f49a450d30a8d7c80c [file]
/*
* 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