// Copyright 2023 PingCAP, Inc. // // Licensed 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 #include #include #include #include #include #include #include #include #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wsign-compare" #include #pragma GCC diagnostic pop namespace DB { namespace tests { class StringPad : public DB::tests::FunctionTest { }; TEST_F(StringPad, string_pad_string_unit_Test) { const auto context = TiFlashTestEnv::getContext(); auto & factory = FunctionFactory::instance(); std::vector strs{"hello", "hello, world", "It's TiFlash", " ", ""}; MutableColumnPtr csp = ColumnString::create(); for (const auto & str : strs) { csp->insert(Field(str.c_str(), str.size())); } auto cp2 = ColumnInt64::create(); ColumnInt64::Container & vec = cp2->getData(); vec.resize(1); vec[0] = 12; ColumnPtr csp2 = ColumnConst::create(cp2->getPtr(), 5); MutableColumnPtr cp3 = ColumnString::create(); cp3->insert(Field("abc", 3)); ColumnPtr csp3 = ColumnConst::create(cp3->getPtr(), 5); Block testBlock; ColumnWithTypeAndName ctn = ColumnWithTypeAndName(std::move(csp), std::make_shared(), "test_pad_1"); ColumnWithTypeAndName ctn2 = ColumnWithTypeAndName(csp2, std::make_shared(), "test_pad_2"); ColumnWithTypeAndName ctn3 = ColumnWithTypeAndName(csp3, std::make_shared(), "test_pad_3"); ColumnsWithTypeAndName ctns{ctn, ctn2, ctn3}; testBlock.insert(ctn); testBlock.insert(ctn2); testBlock.insert(ctn3); testBlock.insert({}); ColumnNumbers cns{0, 1, 2}; // test lpad auto bp = factory.tryGet("lpadUTF8", *context); ASSERT_TRUE(bp != nullptr); bp->build(ctns)->execute(testBlock, cns, 3); const IColumn * res = testBlock.getByPosition(3).column.get(); const ColumnNullable * c0_nullable = checkAndGetColumn(res); Field resField; std::vector results{"abcabcahello", "hello, world", "It's TiFlash", "abcabca ", "abcabcabcabc"}; for (size_t t = 0; t < results.size(); t++) { c0_nullable->get(t, resField); String s = resField.get(); EXPECT_EQ(results[t], s); } // test rpad bp = factory.tryGet("rpadUTF8", *context); ASSERT_TRUE(bp != nullptr); bp->build(ctns)->execute(testBlock, cns, 3); res = testBlock.getByPosition(3).column.get(); c0_nullable = checkAndGetColumn(res); results = {"helloabcabca", "hello, world", "It's TiFlash", " abcabca", "abcabcabcabc"}; for (size_t t = 0; t < results.size(); t++) { c0_nullable->get(t, resField); String s = resField.get(); EXPECT_EQ(results[t], s); } } TEST_F(StringPad, string_pad_const_string_unit_Test) { const auto context = TiFlashTestEnv::getContext(); auto & factory = FunctionFactory::instance(); MutableColumnPtr cp = ColumnString::create(); cp->insert(Field("hello", 5)); ColumnPtr csp = ColumnConst::create(cp->getPtr(), 5); auto cp2 = ColumnInt64::create(); ColumnInt64::Container & vec = cp2->getData(); vec.resize(1); vec[0] = 10; ColumnPtr csp2 = ColumnConst::create(cp2->getPtr(), 5); MutableColumnPtr cp3 = ColumnString::create(); cp3->insert(Field("abc", 3)); ColumnPtr csp3 = ColumnConst::create(cp3->getPtr(), 5); Block testBlock; ColumnWithTypeAndName ctn = ColumnWithTypeAndName(csp, std::make_shared(), "test_pad_1"); ColumnWithTypeAndName ctn2 = ColumnWithTypeAndName(csp2, std::make_shared(), "test_pad_2"); ColumnWithTypeAndName ctn3 = ColumnWithTypeAndName(csp3, std::make_shared(), "test_pad_3"); ColumnsWithTypeAndName ctns{ctn, ctn2, ctn3}; testBlock.insert(ctn); testBlock.insert(ctn2); testBlock.insert(ctn3); testBlock.insert({}); ColumnNumbers cns{0, 1, 2}; // test lpad auto bp = factory.tryGet("lpadUTF8", *context); ASSERT_TRUE(bp != nullptr); bp->build(ctns)->execute(testBlock, cns, 3); const IColumn * res = testBlock.getByPosition(3).column.get(); const ColumnConst * c0_const = checkAndGetColumn(res); Field resField; c0_const->get(0, resField); String s = resField.get(); EXPECT_STREQ("abcabhello", s.c_str()); // test rpad bp = factory.tryGet("rpadUTF8", *context); ASSERT_TRUE(bp != nullptr); bp->build(ctns)->execute(testBlock, cns, 3); res = testBlock.getByPosition(3).column.get(); c0_const = checkAndGetColumn(res); c0_const->get(0, resField); s = resField.get(); EXPECT_STREQ("helloabcab", s.c_str()); } TEST_F(StringPad, string_pad_empty_padding_unit_Test) { const auto context = TiFlashTestEnv::getContext(); auto & factory = FunctionFactory::instance(); std::vector strs{"hello", "hello, world", "It's TiFlash", " ", ""}; MutableColumnPtr csp = ColumnString::create(); for (const auto & str : strs) { csp->insert(Field(str.c_str(), str.size())); } auto cp2 = ColumnInt64::create(); ColumnInt64::Container & vec = cp2->getData(); vec.resize(1); vec[0] = 12; ColumnPtr csp2 = ColumnConst::create(cp2->getPtr(), 5); MutableColumnPtr cp3 = ColumnString::create(); cp3->insert(Field("", 0)); ColumnPtr csp3 = ColumnConst::create(cp3->getPtr(), 5); Block testBlock; ColumnWithTypeAndName ctn = ColumnWithTypeAndName(std::move(csp), std::make_shared(), "test_pad_1"); ColumnWithTypeAndName ctn2 = ColumnWithTypeAndName(csp2, std::make_shared(), "test_pad_2"); ColumnWithTypeAndName ctn3 = ColumnWithTypeAndName(csp3, std::make_shared(), "test_pad_3"); ColumnsWithTypeAndName ctns{ctn, ctn2, ctn3}; testBlock.insert(ctn); testBlock.insert(ctn2); testBlock.insert(ctn3); testBlock.insert({}); ColumnNumbers cns{0, 1, 2}; // test lpad auto bp = factory.tryGet("lpadUTF8", *context); ASSERT_TRUE(bp != nullptr); bp->build(ctns)->execute(testBlock, cns, 3); const IColumn * res = testBlock.getByPosition(3).column.get(); const ColumnNullable * c0_nullable = checkAndGetColumn(res); Field resField; std::vector null_bit_map{1, 0, 0, 1, 1}; std::vector results{"", "hello, world", "It's TiFlash", " ", ""}; for (size_t t = 0; t < results.size(); t++) { if (null_bit_map[t]) { EXPECT_TRUE(c0_nullable->isNullAt(t)); } else { c0_nullable->get(t, resField); String s = resField.get(); EXPECT_EQ(results[t], s); } } // test rpad bp = factory.tryGet("rpadUTF8", *context); ASSERT_TRUE(bp != nullptr); bp->build(ctns)->execute(testBlock, cns, 3); res = testBlock.getByPosition(3).column.get(); c0_nullable = checkAndGetColumn(res); null_bit_map = {1, 0, 0, 1, 1}; results = {"hello", "hello, world", "It's TiFlash", " ", ""}; for (size_t t = 0; t < results.size(); t++) { if (null_bit_map[t]) { EXPECT_TRUE(c0_nullable->isNullAt(t)); } else { c0_nullable->get(t, resField); String s = resField.get(); EXPECT_EQ(results[t], s); } } } TEST_F(StringPad, string_pad_utf8_padding_unit_Test) { const auto context = TiFlashTestEnv::getContext(); auto & factory = FunctionFactory::instance(); std::vector strs{"你好,", "你好, 世界", "这是 TiFlash", " ", ""}; MutableColumnPtr csp = ColumnString::create(); for (const auto & str : strs) { csp->insert(Field(str.c_str(), str.size())); } auto cp2 = ColumnInt64::create(); ColumnInt64::Container & vec = cp2->getData(); vec.resize(1); vec[0] = 4; ColumnPtr csp2 = ColumnConst::create(cp2->getPtr(), 5); MutableColumnPtr cp3 = ColumnString::create(); String padding = "上海"; cp3->insert(Field(padding.c_str(), padding.size())); ColumnPtr csp3 = ColumnConst::create(cp3->getPtr(), 5); Block testBlock; ColumnWithTypeAndName ctn = ColumnWithTypeAndName(std::move(csp), std::make_shared(), "test_pad_1"); ColumnWithTypeAndName ctn2 = ColumnWithTypeAndName(csp2, std::make_shared(), "test_pad_2"); ColumnWithTypeAndName ctn3 = ColumnWithTypeAndName(csp3, std::make_shared(), "test_pad_3"); ColumnsWithTypeAndName ctns{ctn, ctn2, ctn3}; testBlock.insert(ctn); testBlock.insert(ctn2); testBlock.insert(ctn3); testBlock.insert({}); ColumnNumbers cns{0, 1, 2}; // test lpad auto bp = factory.tryGet("lpadUTF8", *context); ASSERT_TRUE(bp != nullptr); bp->build(ctns)->execute(testBlock, cns, 3); const IColumn * res = testBlock.getByPosition(3).column.get(); const ColumnNullable * c0_nullable = checkAndGetColumn(res); Field resField; std::vector results{"上你好,", "你好, ", "这是 T", " ", "上海上海"}; for (size_t t = 0; t < results.size(); t++) { String s; c0_nullable->get(t, resField); s = resField.get(); EXPECT_EQ(results[t], s); } // test rpad bp = factory.tryGet("rpadUTF8", *context); ASSERT_TRUE(bp != nullptr); bp->build(ctns)->execute(testBlock, cns, 3); res = testBlock.getByPosition(3).column.get(); c0_nullable = checkAndGetColumn(res); results = {"你好,上", "你好, ", "这是 T", " ", "上海上海"}; for (size_t t = 0; t < results.size(); t++) { c0_nullable->get(t, resField); String s = resField.get(); EXPECT_EQ(results[t], s); } } TEST_F(StringPad, string_pad_const_utf8_padding_unit_Test) { const auto context = TiFlashTestEnv::getContext(); auto & factory = FunctionFactory::instance(); MutableColumnPtr cp = ColumnString::create(); String word = "你好,"; cp->insert(Field(word.c_str(), word.size())); ColumnPtr csp = ColumnConst::create(cp->getPtr(), 5); auto cp2 = ColumnInt64::create(); ColumnInt64::Container & vec = cp2->getData(); vec.resize(1); vec[0] = 4; ColumnPtr csp2 = ColumnConst::create(cp2->getPtr(), 5); MutableColumnPtr cp3 = ColumnString::create(); String padding = "上海"; cp3->insert(Field(padding.c_str(), padding.size())); ColumnPtr csp3 = ColumnConst::create(cp3->getPtr(), 5); Block testBlock; ColumnWithTypeAndName ctn = ColumnWithTypeAndName(csp, std::make_shared(), "test_pad_1"); ColumnWithTypeAndName ctn2 = ColumnWithTypeAndName(csp2, std::make_shared(), "test_pad_2"); ColumnWithTypeAndName ctn3 = ColumnWithTypeAndName(csp3, std::make_shared(), "test_pad_3"); ColumnsWithTypeAndName ctns{ctn, ctn2, ctn3}; testBlock.insert(ctn); testBlock.insert(ctn2); testBlock.insert(ctn3); testBlock.insert({}); ColumnNumbers cns{0, 1, 2}; // test lpad auto bp = factory.tryGet("lpadUTF8", *context); ASSERT_TRUE(bp != nullptr); bp->build(ctns)->execute(testBlock, cns, 3); const IColumn * res = testBlock.getByPosition(3).column.get(); const ColumnConst * c0_const = checkAndGetColumn(res); ASSERT_TRUE(c0_const != nullptr); Field resField; String s; c0_const->get(0, resField); s = resField.get(); EXPECT_EQ("上你好,", s); // test rpad bp = factory.tryGet("rpadUTF8", *context); ASSERT_TRUE(bp != nullptr); bp->build(ctns)->execute(testBlock, cns, 3); res = testBlock.getByPosition(3).column.get(); c0_const = checkAndGetColumn(res); c0_const->get(0, resField); s = resField.get(); EXPECT_EQ("你好,上", s); } TEST_F(StringPad, string_pad_empty_utf8_padding_unit_Test) { const auto context = TiFlashTestEnv::getContext(); auto & factory = FunctionFactory::instance(); std::vector strs{"你好,", "你好, 世界", "这是 TiFlash", " ", ""}; MutableColumnPtr csp = ColumnString::create(); for (const auto & str : strs) { csp->insert(Field(str.c_str(), str.size())); } auto cp2 = ColumnInt64::create(); ColumnInt64::Container & vec = cp2->getData(); vec.resize(1); vec[0] = 4; ColumnPtr csp2 = ColumnConst::create(cp2->getPtr(), 5); MutableColumnPtr cp3 = ColumnString::create(); String padding = ""; cp3->insert(Field(padding.c_str(), padding.size())); ColumnPtr csp3 = ColumnConst::create(cp3->getPtr(), 5); Block testBlock; ColumnWithTypeAndName ctn = ColumnWithTypeAndName(std::move(csp), std::make_shared(), "test_pad_1"); ColumnWithTypeAndName ctn2 = ColumnWithTypeAndName(csp2, std::make_shared(), "test_pad_2"); ColumnWithTypeAndName ctn3 = ColumnWithTypeAndName(csp3, std::make_shared(), "test_pad_3"); ColumnsWithTypeAndName ctns{ctn, ctn2, ctn3}; testBlock.insert(ctn); testBlock.insert(ctn2); testBlock.insert(ctn3); testBlock.insert({}); ColumnNumbers cns{0, 1, 2}; // test lpad auto bp = factory.tryGet("lpadUTF8", *context); ASSERT_TRUE(bp != nullptr); bp->build(ctns)->execute(testBlock, cns, 3); const IColumn * res = testBlock.getByPosition(3).column.get(); const ColumnNullable * c0_nullable = checkAndGetColumn(res); Field resField; std::vector null_bit_map{1, 0, 0, 0, 1}; std::vector results{"你好,", "你好, ", "这是 T", " ", ""}; for (size_t t = 0; t < results.size(); t++) { if (null_bit_map[t]) { EXPECT_TRUE(c0_nullable->isNullAt(t)); } else { c0_nullable->get(t, resField); String s = resField.get(); EXPECT_EQ(results[t], s); } } // test rpad bp = factory.tryGet("rpadUTF8", *context); ASSERT_TRUE(bp != nullptr); bp->build(ctns)->execute(testBlock, cns, 3); res = testBlock.getByPosition(3).column.get(); c0_nullable = checkAndGetColumn(res); null_bit_map = {1, 0, 0, 0, 1}; results = {"你好,", "你好, ", "这是 T", " ", ""}; for (size_t t = 0; t < results.size(); t++) { if (null_bit_map[t]) { EXPECT_TRUE(c0_nullable->isNullAt(t)); } else { c0_nullable->get(t, resField); String s = resField.get(); EXPECT_EQ(results[t], s); } } } TEST_F(StringPad, lpad_mixed_col_const_test) try { // pad(const, const, const) ASSERT_COLUMN_EQ( createConstColumn>(5, "xxxxxxxxxabc"), executeFunction( "lpadUTF8", createConstColumn>(5, "abc"), createConstColumn>(5, 12), createConstColumn>(5, "xxx"))); ASSERT_COLUMN_EQ( createConstColumn>(5, "abcxxxxxxxxx"), executeFunction( "rpadUTF8", createConstColumn>(5, "abc"), createConstColumn>(5, 12), createConstColumn>(5, "xxx"))); ASSERT_COLUMN_EQ( createConstColumn>(5, {}), executeFunction( "lpadUTF8", createConstColumn>(5, {}), createConstColumn>(5, 12), createConstColumn>(5, "xxx"))); ASSERT_COLUMN_EQ( createConstColumn>(5, {}), executeFunction( "rpadUTF8", createConstColumn>(5, {}), createConstColumn>(5, 12), createConstColumn>(5, "xxx"))); // pad(const, const, column) ASSERT_COLUMN_EQ( createColumn>( {"xxxxxxxxxabc", "yyyyyyyyyabc", "zzzzzzzzzabc", "eeeeeeeeeabc", "fffffffffabc"}), executeFunction( "lpadUTF8", createConstColumn>(5, "abc"), createConstColumn>(5, 12), createColumn>({"xxx", "yyy", "zzz", "eee", "fff"}))); ASSERT_COLUMN_EQ( createColumn>( {"abcxxxxxxxxx", "abcyyyyyyyyy", "abczzzzzzzzz", "abceeeeeeeee", "abcfffffffff"}), executeFunction( "rpadUTF8", createConstColumn>(5, "abc"), createConstColumn>(5, 12), createColumn>({"xxx", "yyy", "zzz", "eee", "fff"}))); // pad(const, column, const) ASSERT_COLUMN_EQ( createColumn>({"a", "ab", "abc", "xabc", "xxabc"}), executeFunction( "lpadUTF8", createConstColumn>(5, "abc"), createColumn>({1, 2, 3, 4, 5}), createConstColumn>(5, "xxx"))); ASSERT_COLUMN_EQ( createColumn>({"a", "ab", "abc", "abcx", "abcxx"}), executeFunction( "rpadUTF8", createConstColumn>(5, "abc"), createColumn>({1, 2, 3, 4, 5}), createConstColumn>(5, "xxx"))); // pad(const, column, column) ASSERT_COLUMN_EQ( createColumn>({"a", "ab", "abc", "eabc", "ffabc"}), executeFunction( "lpadUTF8", createConstColumn>(5, "abc"), createColumn>({1, 2, 3, 4, 5}), createColumn>({"xxx", "yyy", "zzz", "eee", "fff"}))); ASSERT_COLUMN_EQ( createColumn>({"a", "ab", "abc", "abce", "abcff"}), executeFunction( "rpadUTF8", createConstColumn>(5, "abc"), createColumn>({1, 2, 3, 4, 5}), createColumn>({"xxx", "yyy", "zzz", "eee", "fff"}))); // pad(column, const, const) ASSERT_COLUMN_EQ( createColumn>({"1231231a", "123123ab", "12312abc", "1231abcd", "123abcde"}), executeFunction( "lpadUTF8", createColumn>({"a", "ab", "abc", "abcd", "abcde"}), createConstColumn>(5, 8), createConstColumn>(5, "123"))); ASSERT_COLUMN_EQ( createColumn>({"a1231231", "ab123123", "abc12312", "abcd1231", "abcde123"}), executeFunction( "rpadUTF8", createColumn>({"a", "ab", "abc", "abcd", "abcde"}), createConstColumn>(5, 8), createConstColumn>(5, "123"))); // pad(column, const, column) ASSERT_COLUMN_EQ( createColumn>({"1212121a", "343434ab", "56565abc", "7878abcd", "999abcde"}), executeFunction( "lpadUTF8", createColumn>({"a", "ab", "abc", "abcd", "abcde"}), createConstColumn>(5, 8), createColumn>({"12", "34", "56", "78", "99"}))); ASSERT_COLUMN_EQ( createColumn>({"a1212121", "ab343434", "abc56565", "abcd7878", "abcde999"}), executeFunction( "rpadUTF8", createColumn>({"a", "ab", "abc", "abcd", "abcde"}), createConstColumn>(5, 8), createColumn>({"12", "34", "56", "78", "99"}))); // pad(column, column, const) ASSERT_COLUMN_EQ( createColumn>({"1231231a", "123123ab", "12312abc", "1231abcd", "123abcde"}), executeFunction( "lpadUTF8", createColumn>({"a", "ab", "abc", "abcd", "abcde"}), createColumn>({8, 8, 8, 8, 8}), createConstColumn>(5, "123"))); ASSERT_COLUMN_EQ( createColumn>({"a1231231", "ab123123", "abc12312", "abcd1231", "abcde123"}), executeFunction( "rpadUTF8", createColumn>({"a", "ab", "abc", "abcd", "abcde"}), createColumn>({8, 8, 8, 8, 8}), createConstColumn>(5, "123"))); // pad(column, column, column) ASSERT_COLUMN_EQ( createColumn>({"123a", "123ab", "123abc", "121abcd", "111abcde"}), executeFunction( "lpadUTF8", createColumn>({"a", "ab", "abc", "abcd", "abcde"}), createColumn>({4, 5, 6, 7, 8}), createColumn>({"12345", "1234", "123", "12", "1"}))); ASSERT_COLUMN_EQ( createColumn>({"a123", "ab123", "abc123", "abcd121", "abcde111"}), executeFunction( "rpadUTF8", createColumn>({"a", "ab", "abc", "abcd", "abcde"}), createColumn>({4, 5, 6, 7, 8}), createColumn>({"12345", "1234", "123", "12", "1"}))); } CATCH TEST_F(StringPad, special_argument) try { // Empty str. ASSERT_COLUMN_EQ( createColumn>({"123 ", "12312", "ab", " def"}), executeFunction( "lpadUTF8", createColumn>({" ", "", "abc", "def"}), createColumn>({4, 5, 2, 7}), createColumn>({"123", "123", "", " "}))); ASSERT_COLUMN_EQ( createColumn>({" 123", "12312", "ab", "def "}), executeFunction( "rpadUTF8", createColumn>({" ", "", "abc", "def"}), createColumn>({4, 5, 2, 7}), createColumn>({"123", "123", "", " "}))); // Chinese. ASSERT_COLUMN_EQ( createColumn>({"你 好 ", "杭州 西湖", "¿¿¿¿!!"}), executeFunction( "lpadUTF8", createColumn>({" ", "西湖", "!!"}), createColumn>({4, 5, 6}), createColumn>({"你 好", "杭州 ll", "¿¿¿¿¿¿"}))); ASSERT_COLUMN_EQ( createColumn>({" 你 好", "西湖杭州 ", "!!¿¿¿¿"}), executeFunction( "rpadUTF8", createColumn>({" ", "西湖", "!!"}), createColumn>({4, 5, 6}), createColumn>({"你 好", "杭州 ll", "¿¿¿¿¿¿"}))); ASSERT_COLUMN_EQ( createColumn>({"𝌃𝌃𝌃𝌃 ", "杭州 西湖", "¿¿¿¿!!"}), executeFunction( "lpadUTF8", createColumn>({" ", "西湖", "!!"}), createColumn>({5, 5, 6}), createColumn>({"𝌃𝌃𝌃𝌃", "杭州 ll", "¿¿¿¿¿¿"}))); // Length value is zero. ASSERT_COLUMN_EQ( createColumn>({"", "", "", "", ""}), executeFunction( "lpadUTF8", createColumn>({" ", "西湖", "!!", "test", "test1"}), createConstColumn>(5, 0), createColumn>({"你 好", "杭州 ll", "¿¿¿¿¿¿", "123", " "}))); ASSERT_COLUMN_EQ( createColumn>({"", "", "", "", ""}), executeFunction( "rpadUTF8", createColumn>({" ", "西湖", "!!", "test", "test1"}), createConstColumn>(5, 0), createColumn>({"你 好", "杭州 ll", "¿¿¿¿¿¿", "123", " "}))); // Length value is less than zero. Expect Null. ASSERT_COLUMN_EQ( createColumn>({{}, "a"}), executeFunction( "lpadUTF8", createColumn>({"abc", "abc"}), createColumn>({-1, 1}), createColumn>({"123", "123"}))); ASSERT_COLUMN_EQ( createColumn>({{}, "a"}), executeFunction( "rpadUTF8", createColumn>({"abc", "abc"}), createColumn>({-1, 1}), createColumn>({"123", "123"}))); ASSERT_COLUMN_EQ( createColumn>({{}, "a"}), executeFunction( "lpadUTF8", createColumn>({"abc", "abc"}), createColumn>({-1, 1}), createColumn>({"123", "123"}))); ASSERT_COLUMN_EQ( createColumn>({{}, "a"}), executeFunction( "rpadUTF8", createColumn>({"abc", "abc"}), createColumn>({-1, 1}), createColumn>({"123", "123"}))); // Test padding_str is empty. // lpad("abc", 10, "") -> NULL ASSERT_COLUMN_EQ( createColumn>({{}, {}, "xy"}), executeFunction( "lpadUTF8", createColumn>({"abc", "def", "xyz"}), createColumn>({10, 100, 2}), createColumn>({"", "", ""}))); ASSERT_COLUMN_EQ( createColumn>({{}, {}, "xy"}), executeFunction( "rpadUTF8", createColumn>({"abc", "def", "xyz"}), createColumn>({10, 100, 2}), createColumn>({"", "", ""}))); // Null test // Result is Null if any column is all null. ASSERT_COLUMN_EQ( createColumn>({{}, {}, {}}), executeFunction( "lpadUTF8", createColumn>({{}, "abc", "def"}), createColumn>({10, {}, 11}), createColumn>({"123", "456", {}}))); ASSERT_COLUMN_EQ( createColumn>({{}, {}, {}}), executeFunction( "rpadUTF8", createColumn>({{}, "abc", "def"}), createColumn>({10, {}, 11}), createColumn>({"123", "456", {}}))); // Test non-Nullable column. // Result is nullable even if arguments are all non-nullable. ASSERT_COLUMN_EQ( createConstColumn>(5, "xxxxxxxxxabc"), executeFunction( "lpadUTF8", createConstColumn(5, "abc"), createConstColumn(5, 12), createConstColumn(5, "xxx"))); ASSERT_COLUMN_EQ( createConstColumn>(5, "abcxxxxxxxxx"), executeFunction( "rpadUTF8", createConstColumn(5, "abc"), createConstColumn(5, 12), createConstColumn(5, "xxx"))); } CATCH TEST_F(StringPad, different_col_type) try { // Different type of length column. ASSERT_COLUMN_EQ( createConstColumn>(5, "xxxxxxxxxabc"), executeFunction( "lpadUTF8", createConstColumn>(5, "abc"), createConstColumn>(5, 12), createConstColumn>(5, "xxx"))); ASSERT_COLUMN_EQ( createConstColumn>(5, "xxxxxxxxxabc"), executeFunction( "lpadUTF8", createConstColumn>(5, "abc"), createConstColumn>(5, 12), createConstColumn>(5, "xxx"))); ASSERT_COLUMN_EQ( createConstColumn>(5, "xxxxxxxxxabc"), executeFunction( "lpadUTF8", createConstColumn>(5, "abc"), createConstColumn>(5, 12), createConstColumn>(5, "xxx"))); ASSERT_COLUMN_EQ( createConstColumn>(5, "xxxxxxxxxabc"), executeFunction( "lpadUTF8", createConstColumn>(5, "abc"), createConstColumn>(5, 12), createConstColumn>(5, "xxx"))); ASSERT_COLUMN_EQ( createConstColumn>(5, "xxxxxxxxxabc"), executeFunction( "lpadUTF8", createConstColumn>(5, "abc"), createConstColumn>(5, 12), createConstColumn>(5, "xxx"))); ASSERT_COLUMN_EQ( createConstColumn>(5, "xxxxxxxxxabc"), executeFunction( "lpadUTF8", createConstColumn>(5, "abc"), createConstColumn>(5, 12), createConstColumn>(5, "xxx"))); ASSERT_COLUMN_EQ( createConstColumn>(5, "xxxxxxxxxabc"), executeFunction( "lpadUTF8", createConstColumn>(5, "abc"), createConstColumn>(5, 12), createConstColumn>(5, "xxx"))); ASSERT_COLUMN_EQ( createConstColumn>(5, "xxxxxxxxxabc"), executeFunction( "lpadUTF8", createConstColumn>(5, "abc"), createConstColumn>(5, 12), createConstColumn>(5, "xxx"))); // rpad ASSERT_COLUMN_EQ( createConstColumn>(5, "abcxxxxxxxxx"), executeFunction( "rpadUTF8", createConstColumn>(5, "abc"), createConstColumn>(5, 12), createConstColumn>(5, "xxx"))); ASSERT_COLUMN_EQ( createConstColumn>(5, "abcxxxxxxxxx"), executeFunction( "rpadUTF8", createConstColumn>(5, "abc"), createConstColumn>(5, 12), createConstColumn>(5, "xxx"))); ASSERT_COLUMN_EQ( createConstColumn>(5, "abcxxxxxxxxx"), executeFunction( "rpadUTF8", createConstColumn>(5, "abc"), createConstColumn>(5, 12), createConstColumn>(5, "xxx"))); ASSERT_COLUMN_EQ( createConstColumn>(5, "abcxxxxxxxxx"), executeFunction( "rpadUTF8", createConstColumn>(5, "abc"), createConstColumn>(5, 12), createConstColumn>(5, "xxx"))); ASSERT_COLUMN_EQ( createConstColumn>(5, "abcxxxxxxxxx"), executeFunction( "rpadUTF8", createConstColumn>(5, "abc"), createConstColumn>(5, 12), createConstColumn>(5, "xxx"))); ASSERT_COLUMN_EQ( createConstColumn>(5, "abcxxxxxxxxx"), executeFunction( "rpadUTF8", createConstColumn>(5, "abc"), createConstColumn>(5, 12), createConstColumn>(5, "xxx"))); ASSERT_COLUMN_EQ( createConstColumn>(5, "abcxxxxxxxxx"), executeFunction( "rpadUTF8", createConstColumn>(5, "abc"), createConstColumn>(5, 12), createConstColumn>(5, "xxx"))); ASSERT_COLUMN_EQ( createConstColumn>(5, "abcxxxxxxxxx"), executeFunction( "rpadUTF8", createConstColumn>(5, "abc"), createConstColumn>(5, 12), createConstColumn>(5, "xxx"))); } CATCH TEST_F(StringPad, test_pad_binary) try { // Basic test. ASSERT_COLUMN_EQ( createConstColumn>(5, "xxxxxxxxxabc"), executeFunction( "lpad", createConstColumn>(5, "abc"), createConstColumn>(5, 12), createConstColumn>(5, "xxx"))); ASSERT_COLUMN_EQ( createConstColumn>(5, "abcxxxxxxxxx"), executeFunction( "rpad", createConstColumn>(5, "abc"), createConstColumn>(5, 12), createConstColumn>(5, "xxx"))); // Empty str. ASSERT_COLUMN_EQ( createColumn>({"123 ", "12312", "ab", " def", "111abc", "12", {}}), executeFunction( "lpad", createColumn>({" ", "", "abc", "def", "abc", "123456789", "abc"}), createColumn>({4, 5, 2, 7, 6, 2, -1}), createColumn>({"123", "123", "", " ", "1", "", "1"}))); ASSERT_COLUMN_EQ( createColumn>({" 123", "12312", "ab", "def ", "abc111", "12", {}}), executeFunction( "rpad", createColumn>({" ", "", "abc", "def", "abc", "123456789", "abc"}), createColumn>({4, 5, 2, 7, 6, 2, -1}), createColumn>({"123", "123", "", " ", "1", "", "1"}))); // Chinese. ASSERT_COLUMN_EQ( createColumn>({"\xE4\xBD\xA0\x20", "\xe8\xa5\xbf\xe6\xb9", "\xc2\xbf\xc2\xbf\x21\x21"}), executeFunction( "lpad", createColumn>({" ", "西湖", "!!"}), createColumn>({4, 5, 6}), createColumn>({"你 好", "杭州 ll", "¿¿¿¿¿¿"}))); ASSERT_COLUMN_EQ( createColumn>({"\x20\xE4\xBD\xA0", "\xe8\xa5\xbf\xe6\xb9", "\x21\x21\xc2\xbf\xc2\xbf"}), executeFunction( "rpad", createColumn>({" ", "西湖", "!!"}), createColumn>({4, 5, 6}), createColumn>({"你 好", "杭州 ll", "¿¿¿¿¿¿"}))); } CATCH // pad(str, len, padding) return NULL if len(str) < len and len(padding) == 0 // So the result of lpad is always Nullable. TEST_F(StringPad, test_pad_not_nullable) try { // Basic test. ASSERT_COLUMN_EQ( createConstColumn>(5, "xxxxxxxxxabc"), executeFunction( "lpad", createConstColumn(5, "abc"), createConstColumn(5, 12), createConstColumn(5, "xxx"))); ASSERT_COLUMN_EQ( createConstColumn>(5, "abcxxxxxxxxx"), executeFunction( "rpad", createConstColumn(5, "abc"), createConstColumn(5, 12), createConstColumn(5, "xxx"))); // Empty str. ASSERT_COLUMN_EQ( createColumn>({"123 ", "12312", "ab", " def", "111abc", "12"}), executeFunction( "lpad", createColumn({" ", "", "abc", "def", "abc", "123456789"}), createColumn({4, 5, 2, 7, 6, 2}), createColumn({"123", "123", "", " ", "1", ""}))); ASSERT_COLUMN_EQ( createColumn>({" 123", "12312", "ab", "def ", "abc111", "12"}), executeFunction( "rpad", createColumn({" ", "", "abc", "def", "abc", "123456789"}), createColumn({4, 5, 2, 7, 6, 2}), createColumn({"123", "123", "", " ", "1", ""}))); // Chinese. ASSERT_COLUMN_EQ( createColumn>({"\xE4\xBD\xA0\x20", "\xe8\xa5\xbf\xe6\xb9", "\xc2\xbf\xc2\xbf\x21\x21"}), executeFunction( "lpad", createColumn({" ", "西湖", "!!"}), createColumn({4, 5, 6}), createColumn({"你 好", "杭州 ll", "¿¿¿¿¿¿"}))); ASSERT_COLUMN_EQ( createColumn>({"\x20\xE4\xBD\xA0", "\xe8\xa5\xbf\xe6\xb9", "\x21\x21\xc2\xbf\xc2\xbf"}), executeFunction( "rpad", createColumn({" ", "西湖", "!!"}), createColumn({4, 5, 6}), createColumn({"你 好", "杭州 ll", "¿¿¿¿¿¿"}))); // utf8 test ASSERT_COLUMN_EQ( createColumn>({"你 好 ", "杭州 西湖", "¿¿¿¿!!"}), executeFunction( "lpadUTF8", createColumn({" ", "西湖", "!!"}), createColumn({4, 5, 6}), createColumn({"你 好", "杭州 ll", "¿¿¿¿¿¿"}))); ASSERT_COLUMN_EQ( createColumn>({" 你 好", "西湖杭州 ", "!!¿¿¿¿"}), executeFunction( "rpadUTF8", createColumn({" ", "西湖", "!!"}), createColumn({4, 5, 6}), createColumn({"你 好", "杭州 ll", "¿¿¿¿¿¿"}))); } CATCH } // namespace tests } // namespace DB