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

Reply via email to