This is an automated email from the ASF dual-hosted git repository. zhangstar333 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push: new 2dfa817a905 [util](column) add check_and_get_column_ptr to cast ColumnPtr (#48306) 2dfa817a905 is described below commit 2dfa817a90536a500f2e4da4fa6870ab68288fcb Author: Mryange <yanxuech...@selectdb.com> AuthorDate: Tue Mar 4 11:49:40 2025 +0800 [util](column) add check_and_get_column_ptr to cast ColumnPtr (#48306) ### What problem does this PR solve? In the past, our casting method only allowed casting ColumnPtr to a raw pointer. Now we introduce a new casting method that can cast to a specific ColumnPtr. For example, casting ColumnPtr to ColumnInt32::Ptr. This is similar to std::dynamic_pointer_cast. --- be/src/vec/columns/column.h | 11 ++ .../vec/columns/check_and_get_column_ptr_test.cpp | 143 +++++++++++++++++++++ 2 files changed, 154 insertions(+) diff --git a/be/src/vec/columns/column.h b/be/src/vec/columns/column.h index a73b43b265d..50a780e4355 100644 --- a/be/src/vec/columns/column.h +++ b/be/src/vec/columns/column.h @@ -756,6 +756,17 @@ bool is_column(const IColumn* column) { return check_and_get_column<Type>(column); } +// check_and_get_column_ptr is used to return a ColumnPtr of a specific column type, +// which will hold ownership. This prevents the occurrence of dangling pointers due to certain situations. +template <typename ColumnType> +ColumnType::Ptr check_and_get_column_ptr(const ColumnPtr& column) { + const ColumnType* raw_type_ptr = check_and_get_column<ColumnType>(column.get()); + if (raw_type_ptr == nullptr) { + return nullptr; + } + return typename ColumnType::Ptr(const_cast<ColumnType*>(raw_type_ptr)); +} + /// True if column's an ColumnConst instance. It's just a syntax sugar for type check. bool is_column_const(const IColumn& column); diff --git a/be/test/vec/columns/check_and_get_column_ptr_test.cpp b/be/test/vec/columns/check_and_get_column_ptr_test.cpp new file mode 100644 index 00000000000..82b4373bdd8 --- /dev/null +++ b/be/test/vec/columns/check_and_get_column_ptr_test.cpp @@ -0,0 +1,143 @@ +// 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 <gtest/gtest.h> + +#include "testutil/column_helper.h" +#include "vec/columns/column.h" +#include "vec/columns/column_nullable.h" +#include "vec/columns/columns_number.h" +#include "vec/data_types/data_type_number.h" + +namespace doris::vectorized { + +TEST(CheckAndGetColumnPtrTest, stdtest) { + { + std::shared_ptr<IColumn> column_ptr = std::make_shared<ColumnInt32>(42); + + EXPECT_EQ(column_ptr.use_count(), 1); + auto column_i32 = std::dynamic_pointer_cast<ColumnInt32>(column_ptr); + + EXPECT_TRUE(column_i32); + + EXPECT_EQ(column_ptr.use_count(), 2); + + EXPECT_EQ(column_i32.use_count(), 2); + } + + { + std::shared_ptr<IColumn> column_ptr = std::make_shared<ColumnInt32>(42); + + EXPECT_EQ(column_ptr.use_count(), 1); + auto column_i64 = std::dynamic_pointer_cast<ColumnInt64>(column_ptr); + + EXPECT_FALSE(column_i64); + + EXPECT_EQ(column_ptr.use_count(), 1); + } +} + +TEST(CheckAndGetColumnPtrTest, checktest) { + { + ColumnPtr column_ptr = ColumnHelper::create_column<DataTypeInt32>({1, 2, 3}); + + EXPECT_EQ(column_ptr->use_count(), 1); + auto column_i32 = check_and_get_column_ptr<ColumnInt32>(column_ptr); + + EXPECT_TRUE(column_i32); + + EXPECT_EQ(column_ptr->use_count(), 2); + + EXPECT_EQ(column_i32->use_count(), 2); + } + + { + ColumnPtr column_ptr = ColumnHelper::create_column<DataTypeInt32>({1, 2, 3}); + + EXPECT_EQ(column_ptr->use_count(), 1); + auto column_i64 = check_and_get_column_ptr<ColumnInt64>(column_ptr); + + EXPECT_FALSE(column_i64); + + EXPECT_EQ(column_ptr->use_count(), 1); + } +} + +TEST(CheckAndGetColumnPtrTest, errorTest) { + { + ColumnPtr column = ColumnConst::create( + ColumnNullable::create(ColumnHelper::create_column<DataTypeInt32>({1}), + ColumnHelper::create_column<DataTypeUInt8>({true})), + 3); + + ColumnPtr nested_column = column; + + nested_column = nested_column->convert_to_full_column_if_const(); + const auto* source_column = check_and_get_column<ColumnNullable>(nested_column.get()); + nested_column = source_column->get_nested_column_ptr(); + // The source_column is now a dangling pointer. + // std::cout<<source_column->use_count()<<std::endl; + } + + { + ColumnPtr column = ColumnConst::create( + ColumnNullable::create(ColumnHelper::create_column<DataTypeInt32>({1}), + ColumnHelper::create_column<DataTypeUInt8>({true})), + 3); + + ColumnPtr nested_column = column; + + nested_column = nested_column->convert_to_full_column_if_const(); + const auto& source_column = assert_cast<const ColumnNullable&>(*nested_column); + nested_column = source_column.get_nested_column_ptr(); + // The source_column is now a dangling pointer. + // std::cout<<source_column.use_count()<<std::endl; + } + + { + ColumnPtr column = ColumnConst::create( + ColumnNullable::create(ColumnHelper::create_column<DataTypeInt32>({1}), + ColumnHelper::create_column<DataTypeUInt8>({true})), + 3); + + ColumnPtr nested_column = column; + + nested_column = nested_column->convert_to_full_column_if_const(); + const auto source_column = check_and_get_column_ptr<ColumnNullable>(nested_column); + nested_column = source_column->get_nested_column_ptr(); + EXPECT_EQ(source_column->use_count(), 1); + } +} + +TEST(CheckAndGetColumnPtrTest, destructstest) { + ColumnPtr column_ptr = ColumnHelper::create_column<DataTypeInt32>({1, 2, 3}); + + EXPECT_EQ(column_ptr->use_count(), 1); + + { + auto column_i32 = check_and_get_column_ptr<ColumnInt32>(column_ptr); + + EXPECT_TRUE(column_i32); + + EXPECT_EQ(column_ptr->use_count(), 2); + + EXPECT_EQ(column_i32->use_count(), 2); + } + + EXPECT_EQ(column_ptr->use_count(), 1); +} +} // namespace doris::vectorized \ No newline at end of file --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org