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 <[email protected]>
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: [email protected]
For additional commands, e-mail: [email protected]