This is an automated email from the ASF dual-hosted git repository.

yiguolei pushed a commit to branch branch-2.1
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/branch-2.1 by this push:
     new 75cd3712f32 branch-2.1: [Fix](mow) Should use rowset's schema when 
calculate delete bitmaps between segments #54351 (#54370)
75cd3712f32 is described below

commit 75cd3712f32cb4d1fa1c4bc066c4f3378c4a5d7b
Author: bobhan1 <[email protected]>
AuthorDate: Thu Aug 7 16:14:29 2025 +0800

    branch-2.1: [Fix](mow) Should use rowset's schema when calculate delete 
bitmaps between segments #54351 (#54370)
    
    pick https://github.com/apache/doris/pull/54351
---
 be/src/olap/rowset_builder.cpp                     |   4 +-
 be/src/olap/tablet.cpp                             |  16 ++--
 be/src/olap/tablet.h                               |   3 +-
 be/src/olap/txn_manager.cpp                        |   2 +-
 be/src/service/backend_service.cpp                 |   4 +-
 .../test_mow_alter_seq_multi_segments.out          | Bin 0 -> 154 bytes
 .../test_mow_alter_seq_multi_segments.groovy       |  94 +++++++++++++++++++++
 7 files changed, 109 insertions(+), 14 deletions(-)

diff --git a/be/src/olap/rowset_builder.cpp b/be/src/olap/rowset_builder.cpp
index ca746f8aac7..f9353a0b644 100644
--- a/be/src/olap/rowset_builder.cpp
+++ b/be/src/olap/rowset_builder.cpp
@@ -262,8 +262,8 @@ Status RowsetBuilder::submit_calc_delete_bitmap_task() {
     RETURN_IF_ERROR(beta_rowset->load_segments(&segments));
     if (segments.size() > 1) {
         // calculate delete bitmap between segments
-        RETURN_IF_ERROR(
-                tablet()->calc_delete_bitmap_between_segments(_rowset, 
segments, _delete_bitmap));
+        
RETURN_IF_ERROR(tablet()->calc_delete_bitmap_between_segments(_tablet_schema, 
_rowset,
+                                                                      
segments, _delete_bitmap));
     }
 
     // tablet is under alter process. The delete bitmap will be calculated 
after conversion.
diff --git a/be/src/olap/tablet.cpp b/be/src/olap/tablet.cpp
index 4661f5eae8d..2ad8d43bcb9 100644
--- a/be/src/olap/tablet.cpp
+++ b/be/src/olap/tablet.cpp
@@ -3503,7 +3503,8 @@ Status Tablet::update_delete_bitmap_without_lock(
 
     // calculate delete bitmap between segments if necessary.
     DeleteBitmapPtr delete_bitmap = 
std::make_shared<DeleteBitmap>(tablet_id());
-    RETURN_IF_ERROR(calc_delete_bitmap_between_segments(rowset, segments, 
delete_bitmap));
+    
RETURN_IF_ERROR(calc_delete_bitmap_between_segments(rowset->tablet_schema(), 
rowset, segments,
+                                                        delete_bitmap));
 
     // get all base rowsets to calculate on
     std::vector<RowsetSharedPtr> specified_rowsets;
@@ -4089,22 +4090,21 @@ void Tablet::clear_cache() {
 }
 
 Status Tablet::calc_delete_bitmap_between_segments(
-        RowsetSharedPtr rowset, const 
std::vector<segment_v2::SegmentSharedPtr>& segments,
-        DeleteBitmapPtr delete_bitmap) {
+        TabletSchemaSPtr schema, RowsetSharedPtr rowset,
+        const std::vector<segment_v2::SegmentSharedPtr>& segments, 
DeleteBitmapPtr delete_bitmap) {
     size_t const num_segments = segments.size();
     if (num_segments < 2) {
         return Status::OK();
     }
-
     OlapStopWatch watch;
     auto const rowset_id = rowset->rowset_id();
     size_t seq_col_length = 0;
-    if (_tablet_meta->tablet_schema()->has_sequence_col()) {
-        auto seq_col_idx = _tablet_meta->tablet_schema()->sequence_col_idx();
-        seq_col_length = 
_tablet_meta->tablet_schema()->column(seq_col_idx).length() + 1;
+    if (schema->has_sequence_col()) {
+        auto seq_col_idx = schema->sequence_col_idx();
+        seq_col_length = schema->column(seq_col_idx).length() + 1;
     }
     size_t rowid_length = 0;
-    if (!_tablet_meta->tablet_schema()->cluster_key_idxes().empty()) {
+    if (!schema->cluster_key_idxes().empty()) {
         rowid_length = PrimaryKeyIndexReader::ROW_ID_LENGTH;
     }
 
diff --git a/be/src/olap/tablet.h b/be/src/olap/tablet.h
index a3f2c40a612..ee70008279e 100644
--- a/be/src/olap/tablet.h
+++ b/be/src/olap/tablet.h
@@ -485,7 +485,8 @@ public:
                                       RowsetWriter* rowset_writer);
 
     Status calc_delete_bitmap_between_segments(
-            RowsetSharedPtr rowset, const 
std::vector<segment_v2::SegmentSharedPtr>& segments,
+            TabletSchemaSPtr schema, RowsetSharedPtr rowset,
+            const std::vector<segment_v2::SegmentSharedPtr>& segments,
             DeleteBitmapPtr delete_bitmap);
     Status read_columns_by_plan(TabletSchemaSPtr tablet_schema, 
std::vector<uint32_t> cids_to_read,
                                 const PartialUpdateReadPlan& read_plan,
diff --git a/be/src/olap/txn_manager.cpp b/be/src/olap/txn_manager.cpp
index 851718f49c6..a9f3bf3aa2a 100644
--- a/be/src/olap/txn_manager.cpp
+++ b/be/src/olap/txn_manager.cpp
@@ -549,7 +549,7 @@ Status TxnManager::publish_txn(OlapMeta* meta, TPartitionId 
partition_id,
             std::vector<segment_v2::SegmentSharedPtr> segments;
             
RETURN_IF_ERROR(std::static_pointer_cast<BetaRowset>(rowset)->load_segments(&segments));
             RETURN_IF_ERROR(tablet->calc_delete_bitmap_between_segments(
-                    rowset, segments, tablet_txn_info->delete_bitmap));
+                    rowset->tablet_schema(), rowset, segments, 
tablet_txn_info->delete_bitmap));
         }
 
         RETURN_IF_ERROR(tablet->update_delete_bitmap(tablet_txn_info.get(), 
transaction_id));
diff --git a/be/src/service/backend_service.cpp 
b/be/src/service/backend_service.cpp
index 07e5ef41041..7aa8da0e0b8 100644
--- a/be/src/service/backend_service.cpp
+++ b/be/src/service/backend_service.cpp
@@ -580,8 +580,8 @@ void _ingest_binlog(IngestBinlogArg* arg) {
         }
         if (segments.size() > 1) {
             // calculate delete bitmap between segments
-            status = local_tablet->calc_delete_bitmap_between_segments(rowset, 
segments,
-                                                                       
delete_bitmap);
+            status = local_tablet->calc_delete_bitmap_between_segments(
+                    rowset->tablet_schema(), rowset, segments, delete_bitmap);
             if (!status) {
                 LOG(WARNING) << "failed to calculate delete bitmap"
                              << ". tablet_id: " << local_tablet->tablet_id()
diff --git 
a/regression-test/data/fault_injection_p0/test_mow_alter_seq_multi_segments.out 
b/regression-test/data/fault_injection_p0/test_mow_alter_seq_multi_segments.out
new file mode 100644
index 00000000000..aa44268bf31
Binary files /dev/null and 
b/regression-test/data/fault_injection_p0/test_mow_alter_seq_multi_segments.out 
differ
diff --git 
a/regression-test/suites/fault_injection_p0/test_mow_alter_seq_multi_segments.groovy
 
b/regression-test/suites/fault_injection_p0/test_mow_alter_seq_multi_segments.groovy
new file mode 100644
index 00000000000..d6b17bd5c73
--- /dev/null
+++ 
b/regression-test/suites/fault_injection_p0/test_mow_alter_seq_multi_segments.groovy
@@ -0,0 +1,94 @@
+// 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.
+
+suite("test_mow_alter_seq_multi_segments", "nonConcurrent") {
+    def table1 = "test_mow_alter_seq_multi_segments"
+    sql "DROP TABLE IF EXISTS ${table1} FORCE;"
+    sql """ CREATE TABLE IF NOT EXISTS ${table1} (
+            `k1` int NOT NULL,
+            `c1` int,
+            `c2` int
+            )UNIQUE KEY(k1)
+        DISTRIBUTED BY HASH(k1) BUCKETS 1
+        PROPERTIES (
+            "enable_unique_key_merge_on_write" = "true",
+            "disable_auto_compaction" = "true",
+            "replication_num" = "1"); """
+
+    sql """insert into ${table1} values(1,1,1);"""
+    qt_sql "select * from ${table1} order by k1;"
+    sql """alter table ${table1} ENABLE FEATURE "SEQUENCE_LOAD" WITH 
PROPERTIES ("function_column.sequence_type"="int");"""
+
+    // to cause multi segments and segment compaction
+    def customBeConfig = [
+        doris_scanner_row_bytes : 1
+    ]
+
+    setBeConfigTemporary(customBeConfig) {
+        try {
+            GetDebugPoint().clearDebugPointsForAllBEs()
+            GetDebugPoint().clearDebugPointsForAllFEs()
+            // batch_size is 4164 in csv_reader.cpp
+            // _batch_size is 8192 in vtablet_writer.cpp
+            // to cause multi segments
+            GetDebugPoint().enableDebugPointForAllBEs("MemTable.need_flush")
+            
+            Thread.sleep(1000)
+
+            int rows = 4064
+            // load data that will have multi segments and there are duplicate 
keys between segments
+            String content = ""
+            (1..rows).each {
+                int x = it
+                content += "${x},${x},${x},1\n"
+            }
+            (1..rows).each {
+                int x = it
+                content += "${x},${x},${x},2\n"
+            }
+            def t1 = Thread.start {
+                streamLoad {
+                    table "${table1}"
+                    set 'column_separator', ','
+                    set 'columns', 'k1,c1,c2,seq'
+                    set 'function_column.sequence_col', 'seq'
+                    inputStream new ByteArrayInputStream(content.getBytes())
+                    time 30000
+
+                    check { result, exception, startTime, endTime ->
+                        if (exception != null) {
+                            throw exception
+                        }
+                        def json = parseJson(result)
+                        assert "success" == json.Status.toLowerCase()
+                    }
+                }
+            }
+            t1.join()
+            qt_sql "select count() from ${table1};"
+            // qt_sql "select *,__DORIS_VERSION_COL__ as ver, 
__DORIS_DELETE_SIGN__ as del,__DORIS_SEQUENCE_COL__ as seq from ${table1} where 
k1<=10 order by k1,__DORIS_VERSION_COL__;"
+            sql "set disable_nereids_rules='ELIMINATE_GROUP_BY';"
+            qt_dup_key_count "select count() from (select k1,count() as cnt 
from ${table1} group by k1 having cnt > 1) A;"
+        } catch(Exception e) {
+            logger.info(e.getMessage())
+            throw e
+        } finally {
+            GetDebugPoint().clearDebugPointsForAllBEs()
+            GetDebugPoint().clearDebugPointsForAllFEs()
+        }
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to