This is an automated email from the ASF dual-hosted git repository.
yiguolei pushed a commit to branch branch-4.2
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-4.2 by this push:
new ddecccd2a6c branch-4.2: [fix](be) Preserve hidden VERSION values
during ordered compaction (#70240)
ddecccd2a6c is described below
commit ddecccd2a6ce67c0fdbb84be027daadce0910fe5
Author: Jerry Hu <[email protected]>
AuthorDate: Thu Nov 5 17:21:27 2026 +0800
branch-4.2: [fix](be) Preserve hidden VERSION values during ordered
compaction (#70240)
### What problem does this PR solve?
A non-empty single-version rowset may store a placeholder for the hidden
VERSION column. Its reader synthesizes the published value, but ordered
file-link compaction can combine several such rowsets into a range whose
reader exposes the stored placeholder.
This backport of #69395 to branch-4.2 rejects an ordered link only when
the selected tidy prefix spans multiple versions and contains a
non-empty single-version rowset with a hidden VERSION column. The
existing merge path then materializes the published value.
Already-materialized range rowsets and safe tidy prefixes remain
eligible for linking. The branch-4.2 change is limited to its VERSION
path; it does not import the separate changelog or TSO paths.
### Release note
Prevent ordered file-link compaction from exposing incorrect hidden
VERSION values.
### Validation
- [x] ASAN BE and FE build, including FE Checkstyle.
- [x] `OrderedDataCompactionTest.*`: 6 tests passed.
- [x] Both hidden-VERSION regression suites passed with generated
expected output and a normal verification run.
- [x] `clang-format`, `check-format`, and `git diff --check` passed.
---
be/src/storage/compaction/compaction.cpp | 15 ++
.../compaction/ordered_data_compaction_test.cpp | 157 ++++++++++++++++++++-
...st_ordered_compaction_hidden_version_column.out | 12 ++
...ction_hidden_version_no_light_schema_change.out | 12 ++
...ordered_compaction_hidden_version_column.groovy | 103 ++++++++++++++
...on_hidden_version_no_light_schema_change.groovy | 104 ++++++++++++++
6 files changed, 400 insertions(+), 3 deletions(-)
diff --git a/be/src/storage/compaction/compaction.cpp
b/be/src/storage/compaction/compaction.cpp
index 2fcb22f62db..1c8dff950e9 100644
--- a/be/src/storage/compaction/compaction.cpp
+++ b/be/src/storage/compaction/compaction.cpp
@@ -578,6 +578,18 @@ bool CompactionMixin::handle_ordered_data_compaction() {
}
}
+ // Non-empty singleton rowsets store a placeholder for the publish-time
VERSION column.
+ // A linked range rowset would expose it instead of the version
synthesized on read.
+ // Check only the tidy prefix actually selected for linking.
+ auto links_unmaterialized_version = [this] {
+ return _input_rowsets.front()->start_version() !=
_input_rowsets.back()->end_version() &&
+ std::ranges::any_of(_input_rowsets, [](const RowsetSharedPtr&
rowset) {
+ return rowset->num_rows() > 0 &&
+ rowset->start_version() == rowset->end_version() &&
+ rowset->tablet_schema()->field_index(VERSION_COL) >=
0;
+ });
+ };
+
// check if rowsets are tidy so we can just modify meta and do link
// files to handle compaction
auto input_size = _input_rowsets.size();
@@ -593,6 +605,9 @@ bool CompactionMixin::handle_ordered_data_compaction() {
}
}
}
+ if (links_unmaterialized_version()) {
+ return false;
+ }
// most rowset of current compaction is nonoverlapping
// just handle nonoverlappint rowsets
auto st = do_compact_ordered_rowsets();
diff --git a/be/test/storage/compaction/ordered_data_compaction_test.cpp
b/be/test/storage/compaction/ordered_data_compaction_test.cpp
index 9cc991de654..4c4588336d4 100644
--- a/be/test/storage/compaction/ordered_data_compaction_test.cpp
+++ b/be/test/storage/compaction/ordered_data_compaction_test.cpp
@@ -113,14 +113,15 @@ protected:
ExecEnv::GetInstance()->set_storage_engine(nullptr);
}
- TabletSchemaSPtr create_schema(KeysType keys_type = DUP_KEYS) {
+ TabletSchemaSPtr create_schema(KeysType keys_type = DUP_KEYS, bool
with_version_column = false,
+ bool unset_version_col_idx = false) {
TabletSchemaSPtr tablet_schema = std::make_shared<TabletSchema>();
TabletSchemaPB tablet_schema_pb;
tablet_schema_pb.set_keys_type(keys_type);
tablet_schema_pb.set_num_short_key_columns(1);
tablet_schema_pb.set_num_rows_per_row_block(1024);
tablet_schema_pb.set_compress_kind(COMPRESS_NONE);
- tablet_schema_pb.set_next_column_unique_id(4);
+ tablet_schema_pb.set_next_column_unique_id(4 + with_version_column);
ColumnPB* column_1 = tablet_schema_pb.add_column();
column_1->set_unique_id(1);
@@ -157,6 +158,23 @@ protected:
column_3->set_is_bf_column(false);
}
+ if (with_version_column) {
+ ColumnPB* version_column = tablet_schema_pb.add_column();
+ version_column->set_unique_id(4);
+ version_column->set_name(VERSION_COL);
+ version_column->set_type("BIGINT");
+ version_column->set_is_key(false);
+ version_column->set_is_nullable(false);
+ version_column->set_visible(false);
+ version_column->set_default_value("0");
+ version_column->set_length(8);
+ version_column->set_index_length(8);
+ version_column->set_aggregation("REPLACE");
+ if (!unset_version_col_idx) {
+ tablet_schema_pb.set_version_col_idx(3);
+ }
+ }
+
tablet_schema->init_from_pb(tablet_schema_pb);
return tablet_schema;
}
@@ -284,7 +302,8 @@ protected:
RowsetSharedPtr create_rowset(
TabletSchemaSPtr tablet_schema, TabletSharedPtr tablet,
const SegmentsOverlapPB& overlap,
- std::vector<std::vector<std::tuple<int64_t, int64_t>>>
rowset_data) {
+ std::vector<std::vector<std::tuple<int64_t, int64_t>>> rowset_data,
+ Version version = Version(-1, -1), int64_t stored_version = 0) {
RowsetWriterContext writer_context;
if (overlap == NONOVERLAPPING) {
for (auto i = 1; i < rowset_data.size(); i++) {
@@ -297,6 +316,9 @@ protected:
}
create_rowset_writer_context(tablet_schema, tablet->tablet_path(),
overlap, UINT32_MAX,
&writer_context);
+ if (version.first >= 0) {
+ writer_context.version = version;
+ }
auto res = RowsetFactory::create_rowset_writer(*engine_ref,
writer_context, true);
EXPECT_TRUE(res.has_value()) << res.error();
@@ -316,6 +338,10 @@ protected:
uint8_t num = 0;
columns[2]->insert_data((const char*)&num, sizeof(num));
}
+ if (auto version_idx =
tablet_schema->field_index(VERSION_COL); version_idx >= 0) {
+ columns[version_idx]->insert_data((const
char*)&stored_version,
+ sizeof(stored_version));
+ }
num_rows++;
}
block.set_columns(std::move(columns));
@@ -332,6 +358,31 @@ protected:
return rowset;
}
+ std::vector<int64_t> read_hidden_values(Rowset* rowset, const
TabletSchemaSPtr& tablet_schema,
+ ColumnId hidden_column_id) {
+ std::vector<uint32_t> return_columns
{static_cast<uint32_t>(hidden_column_id)};
+ RowsetReaderContext reader_context;
+ reader_context.tablet_schema = tablet_schema;
+ reader_context.return_columns = &return_columns;
+ RowsetReaderSharedPtr reader;
+ create_and_init_rowset_reader(rowset, reader_context, &reader);
+ std::vector<int64_t> values;
+ Status status = Status::OK();
+ do {
+ Block block = tablet_schema->create_block(return_columns);
+ status = reader->next_batch(&block);
+ for (size_t i = 0; i < block.rows(); ++i) {
+ values.push_back(block.get_by_position(0).column->get_int(i));
+ }
+ } while (status.ok());
+ EXPECT_EQ(status, Status::Error<END_OF_FILE>(""));
+ return values;
+ }
+
+ std::vector<int64_t> read_versions(Rowset* rowset, const TabletSchemaSPtr&
tablet_schema) {
+ return read_hidden_values(rowset, tablet_schema,
tablet_schema->field_index(VERSION_COL));
+ }
+
void init_rs_meta(RowsetMetaSharedPtr& pb1, int64_t start, int64_t end) {
std::string json_rowset_meta = R"({
"rowset_id": 540085,
@@ -558,6 +609,106 @@ TEST_F(OrderedDataCompactionTest, test_01) {
}
}
+TEST_F(OrderedDataCompactionTest,
test_version_col_singleton_rowset_not_linked) {
+ auto tablet_schema = create_schema(UNIQUE_KEYS, true);
+ auto tablet = create_tablet(*tablet_schema, false, 10000, false);
+
ASSERT_TRUE(io::global_local_filesystem()->create_directory(tablet->tablet_path()).ok());
+
+ std::vector<std::vector<std::vector<std::tuple<int64_t, int64_t>>>>
input_data;
+ generate_input_data(2, 1, 2, input_data);
+ std::vector<RowsetSharedPtr> input_rowsets;
+ for (const auto& rowset_data : input_data) {
+ auto rowset = create_rowset(tablet_schema, tablet, NONOVERLAPPING,
rowset_data);
+ ASSERT_EQ(rowset->start_version(), rowset->end_version());
+ ASSERT_EQ(rowset->num_rows(), 2);
+ EXPECT_EQ(read_versions(rowset.get(), tablet_schema),
+ (std::vector<int64_t> {rowset->end_version(),
rowset->end_version()}));
+ input_rowsets.push_back(std::move(rowset));
+ }
+
+ CumulativeCompaction compaction(*engine_ref, tablet);
+ compaction._input_rowsets = std::move(input_rowsets);
+ ASSERT_FALSE(compaction.handle_ordered_data_compaction());
+}
+
+TEST_F(OrderedDataCompactionTest,
test_version_col_with_unset_index_singleton_not_linked) {
+ // A schema created without light schema change has the VERSION column but
no index in PB.
+ auto tablet_schema = create_schema(UNIQUE_KEYS, true, true);
+ ASSERT_EQ(tablet_schema->version_col_idx(), -1);
+ ASSERT_EQ(tablet_schema->field_index(VERSION_COL), 3);
+ auto tablet = create_tablet(*tablet_schema, false, 10000, false);
+
ASSERT_TRUE(io::global_local_filesystem()->create_directory(tablet->tablet_path()).ok());
+
+ std::vector<std::vector<std::vector<std::tuple<int64_t, int64_t>>>>
input_data;
+ generate_input_data(2, 1, 2, input_data);
+ std::vector<RowsetSharedPtr> input_rowsets;
+ for (const auto& rowset_data : input_data) {
+ auto rowset = create_rowset(tablet_schema, tablet, NONOVERLAPPING,
rowset_data);
+ ASSERT_EQ(rowset->start_version(), rowset->end_version());
+ ASSERT_EQ(rowset->num_rows(), 2);
+ EXPECT_EQ(read_versions(rowset.get(), tablet_schema),
+ (std::vector<int64_t> {rowset->end_version(),
rowset->end_version()}));
+ input_rowsets.push_back(std::move(rowset));
+ }
+
+ CumulativeCompaction compaction(*engine_ref, tablet);
+ compaction._input_rowsets = std::move(input_rowsets);
+ ASSERT_FALSE(compaction.handle_ordered_data_compaction());
+}
+
+TEST_F(OrderedDataCompactionTest,
test_version_col_materialized_range_rowsets_can_link) {
+ auto tablet_schema = create_schema(UNIQUE_KEYS, true);
+ auto tablet = create_tablet(*tablet_schema, false, 10000, false);
+
ASSERT_TRUE(io::global_local_filesystem()->create_directory(tablet->tablet_path()).ok());
+
+ std::vector<std::vector<std::vector<std::tuple<int64_t, int64_t>>>>
input_data;
+ generate_input_data(2, 1, 2, input_data);
+ auto first = create_rowset(tablet_schema, tablet, NONOVERLAPPING,
input_data[0],
+ Version(1000, 1001), 1001);
+ auto second = create_rowset(tablet_schema, tablet, NONOVERLAPPING,
input_data[1],
+ Version(1002, 1003), 1003);
+ EXPECT_EQ(read_versions(first.get(), tablet_schema), (std::vector<int64_t>
{1001, 1001}));
+ EXPECT_EQ(read_versions(second.get(), tablet_schema),
(std::vector<int64_t> {1003, 1003}));
+
+ CumulativeCompaction compaction(*engine_ref, tablet);
+ compaction._input_rowsets = {first, second};
+ ASSERT_TRUE(compaction.handle_ordered_data_compaction());
+ EXPECT_EQ(compaction._output_rowset->start_version(), 1000);
+ EXPECT_EQ(compaction._output_rowset->end_version(), 1003);
+ EXPECT_EQ(read_versions(compaction._output_rowset.get(), tablet_schema),
+ (std::vector<int64_t> {1001, 1001, 1003, 1003}));
+}
+
+TEST_F(OrderedDataCompactionTest, test_unsafe_tail_does_not_block_safe_prefix)
{
+ auto tablet_schema = create_schema(UNIQUE_KEYS, true);
+ auto tablet = create_tablet(*tablet_schema, false, 10000, false);
+
ASSERT_TRUE(io::global_local_filesystem()->create_directory(tablet->tablet_path()).ok());
+
+ std::vector<std::vector<std::vector<std::tuple<int64_t, int64_t>>>>
input_data;
+ generate_input_data(5, 1, 2, input_data);
+ std::vector<RowsetSharedPtr> input_rowsets;
+ for (size_t i = 0; i < input_data.size() - 1; ++i) {
+ input_rowsets.push_back(create_rowset(tablet_schema, tablet,
NONOVERLAPPING, input_data[i],
+ Version(1000 + 2 * i, 1001 + 2 *
i), 1001 + 2 * i));
+ }
+ // Mark a two-segment singleton tail untidy; it must not veto the tidy
range prefix.
+ auto tail_data = std::vector<std::vector<std::tuple<int64_t, int64_t>>> {
+ {input_data.back()[0][0]}, {input_data.back()[0][0]}};
+ auto tail = create_rowset(tablet_schema, tablet, OVERLAPPING, tail_data,
Version(1008, 1008));
+ ASSERT_EQ(tail->num_segments(), 2);
+ ASSERT_TRUE(tail->is_segments_overlapping());
+ input_rowsets.push_back(tail);
+
+ CumulativeCompaction compaction(*engine_ref, tablet);
+ compaction._input_rowsets = std::move(input_rowsets);
+ ASSERT_TRUE(compaction.handle_ordered_data_compaction());
+ EXPECT_EQ(compaction._input_rowsets.size(), 4);
+ EXPECT_EQ(compaction._output_rowset->start_version(), 1000);
+ EXPECT_EQ(compaction._output_rowset->end_version(), 1007);
+ EXPECT_EQ(read_versions(compaction._output_rowset.get(), tablet_schema),
+ (std::vector<int64_t> {1001, 1001, 1003, 1003, 1005, 1005, 1007,
1007}));
+}
+
TEST_F(OrderedDataCompactionTest, test_index_disk_size) {
auto num_input_rowset = 3;
auto num_segments = 2;
diff --git
a/regression-test/data/fault_injection_p0/test_ordered_compaction_hidden_version_column.out
b/regression-test/data/fault_injection_p0/test_ordered_compaction_hidden_version_column.out
new file mode 100644
index 00000000000..db1ee8131fa
--- /dev/null
+++
b/regression-test/data/fault_injection_p0/test_ordered_compaction_hidden_version_column.out
@@ -0,0 +1,12 @@
+-- This file is automatically generated. You should know what you did if you
want to edit this
+-- !versions --
+10 true
+11 true
+20 true
+21 true
+
+-- !min_max --
+true true
+
+-- !version_filters --
+2 2
diff --git
a/regression-test/data/fault_injection_p0/test_ordered_compaction_hidden_version_no_light_schema_change.out
b/regression-test/data/fault_injection_p0/test_ordered_compaction_hidden_version_no_light_schema_change.out
new file mode 100644
index 00000000000..db1ee8131fa
--- /dev/null
+++
b/regression-test/data/fault_injection_p0/test_ordered_compaction_hidden_version_no_light_schema_change.out
@@ -0,0 +1,12 @@
+-- This file is automatically generated. You should know what you did if you
want to edit this
+-- !versions --
+10 true
+11 true
+20 true
+21 true
+
+-- !min_max --
+true true
+
+-- !version_filters --
+2 2
diff --git
a/regression-test/suites/fault_injection_p0/test_ordered_compaction_hidden_version_column.groovy
b/regression-test/suites/fault_injection_p0/test_ordered_compaction_hidden_version_column.groovy
new file mode 100644
index 00000000000..8a8e662aa4b
--- /dev/null
+++
b/regression-test/suites/fault_injection_p0/test_ordered_compaction_hidden_version_column.groovy
@@ -0,0 +1,103 @@
+// 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_ordered_compaction_hidden_version_column", "nonConcurrent") {
+ if (isCloudMode()) {
+ return
+ }
+
+ setBeConfigTemporary([
+ enable_ordered_data_compaction: true,
+ ordered_data_compaction_min_segment_size: 1,
+ segments_key_bounds_truncation_threshold: -1
+ ]) {
+ sql "DROP TABLE IF EXISTS
test_ordered_compaction_hidden_version_column"
+ sql """
+ CREATE TABLE test_ordered_compaction_hidden_version_column (
+ k INT NOT NULL,
+ v INT NOT NULL
+ ) UNIQUE KEY(k)
+ DISTRIBUTED BY HASH(k) BUCKETS 1
+ PROPERTIES (
+ "replication_num" = "1",
+ "enable_unique_key_merge_on_write" = "false",
+ "disable_auto_compaction" = "true")
+ """
+
+ sql "INSERT INTO test_ordered_compaction_hidden_version_column VALUES
(10, 10), (11, 11)"
+ sql "INSERT INTO test_ordered_compaction_hidden_version_column VALUES
(20, 20), (21, 21)"
+ sql "SET show_hidden_columns = true"
+ def firstVersions = sql """SELECT __DORIS_VERSION_COL__
+ FROM test_ordered_compaction_hidden_version_column WHERE k < 20
ORDER BY k"""
+ def secondVersions = sql """SELECT __DORIS_VERSION_COL__
+ FROM test_ordered_compaction_hidden_version_column WHERE k >= 20
ORDER BY k"""
+ assert firstVersions.size() == 2 && secondVersions.size() == 2
+ long v1 = firstVersions[0][0].toString().toLong()
+ long v2 = secondVersions[0][0].toString().toLong()
+ assert firstVersions.every { it[0].toString().toLong() == v1 }
+ assert secondVersions.every { it[0].toString().toLong() == v2 }
+ assert v1 > 0 && v2 == v1 + 1
+
+ def tabletInfo = sql_return_maparray(
+ "SHOW TABLETS FROM
test_ordered_compaction_hidden_version_column").get(0)
+ def tabletId = tabletInfo.TabletId
+ def (inputCode, inputBody, inputError) = curl("GET",
tabletInfo.MetaUrl)
+ assert inputCode == 0 : inputError
+ def inputRowsets = parseJson(inputBody.trim()).rs_metas
+ for (def version : [v1, v2]) {
+ assert inputRowsets.count {
+ it.start_version.toString().toLong() == version &&
+ it.end_version.toString().toLong() == version &&
+ it.num_rows.toString().toLong() == 2 &&
+ it.num_segments.toString().toLong() == 1
+ } == 1
+ }
+ try {
+ GetDebugPoint().enableDebugPointForAllBEs(
+
"SizeBasedCumulativeCompactionPolicy::pick_input_rowsets.set_input_rowsets",
+ [tablet_id: "${tabletId}", start_version: "${v1}",
end_version: "${v2}"])
+
trigger_and_wait_compaction("test_ordered_compaction_hidden_version_column",
"cumulative")
+ } finally {
+ GetDebugPoint().disableDebugPointForAllBEs(
+
"SizeBasedCumulativeCompactionPolicy::pick_input_rowsets.set_input_rowsets")
+ }
+
+ def metaUrl = sql_return_maparray(
+ "SHOW TABLETS FROM
test_ordered_compaction_hidden_version_column").get(0).MetaUrl
+ def (code, body, error) = curl("GET", metaUrl)
+ assert code == 0 : error
+ def rowsets = parseJson(body.trim()).rs_metas
+ assert rowsets.count {
+ it.start_version.toString().toLong() == v1 &&
+ it.end_version.toString().toLong() == v2 &&
+ it.num_rows.toString().toLong() == 4
+ } == 1
+
+ order_qt_versions """SELECT k,
+ (__DORIS_VERSION_COL__ = CASE WHEN k < 20 THEN ${v1} ELSE ${v2}
END) AS correct_version
+ FROM test_ordered_compaction_hidden_version_column ORDER BY k"""
+ qt_min_max """SELECT MIN(__DORIS_VERSION_COL__) = ${v1},
+ MAX(__DORIS_VERSION_COL__) = ${v2}
+ FROM test_ordered_compaction_hidden_version_column"""
+ qt_version_filters """SELECT
+ (SELECT COUNT(*) FROM test_ordered_compaction_hidden_version_column
+ WHERE __DORIS_VERSION_COL__ = ${v1}),
+ (SELECT COUNT(*) FROM test_ordered_compaction_hidden_version_column
+ WHERE __DORIS_VERSION_COL__ = ${v2})"""
+
+ }
+}
diff --git
a/regression-test/suites/fault_injection_p0/test_ordered_compaction_hidden_version_no_light_schema_change.groovy
b/regression-test/suites/fault_injection_p0/test_ordered_compaction_hidden_version_no_light_schema_change.groovy
new file mode 100644
index 00000000000..5b245cd885c
--- /dev/null
+++
b/regression-test/suites/fault_injection_p0/test_ordered_compaction_hidden_version_no_light_schema_change.groovy
@@ -0,0 +1,104 @@
+// 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_ordered_compaction_hidden_version_no_light_schema_change",
"nonConcurrent") {
+ if (isCloudMode()) {
+ return
+ }
+
+ setBeConfigTemporary([
+ enable_ordered_data_compaction: true,
+ ordered_data_compaction_min_segment_size: 1,
+ segments_key_bounds_truncation_threshold: -1
+ ]) {
+ sql "DROP TABLE IF EXISTS
test_ordered_compaction_hidden_version_no_light_schema_change"
+ sql """
+ CREATE TABLE
test_ordered_compaction_hidden_version_no_light_schema_change (
+ k INT NOT NULL,
+ v INT NOT NULL
+ ) UNIQUE KEY(k)
+ DISTRIBUTED BY HASH(k) BUCKETS 1
+ PROPERTIES (
+ "replication_num" = "1",
+ "enable_unique_key_merge_on_write" = "false",
+ "light_schema_change" = "false",
+ "disable_auto_compaction" = "true")
+ """
+
+ sql "INSERT INTO
test_ordered_compaction_hidden_version_no_light_schema_change VALUES (10, 10),
(11, 11)"
+ sql "INSERT INTO
test_ordered_compaction_hidden_version_no_light_schema_change VALUES (20, 20),
(21, 21)"
+ sql "SET show_hidden_columns = true"
+ def firstVersions = sql """SELECT __DORIS_VERSION_COL__
+ FROM test_ordered_compaction_hidden_version_no_light_schema_change
WHERE k < 20 ORDER BY k"""
+ def secondVersions = sql """SELECT __DORIS_VERSION_COL__
+ FROM test_ordered_compaction_hidden_version_no_light_schema_change
WHERE k >= 20 ORDER BY k"""
+ assert firstVersions.size() == 2 && secondVersions.size() == 2
+ long v1 = firstVersions[0][0].toString().toLong()
+ long v2 = secondVersions[0][0].toString().toLong()
+ assert firstVersions.every { it[0].toString().toLong() == v1 }
+ assert secondVersions.every { it[0].toString().toLong() == v2 }
+ assert v1 > 0 && v2 == v1 + 1
+
+ def tabletInfo = sql_return_maparray(
+ "SHOW TABLETS FROM
test_ordered_compaction_hidden_version_no_light_schema_change").get(0)
+ def tabletId = tabletInfo.TabletId
+ def (inputCode, inputBody, inputError) = curl("GET",
tabletInfo.MetaUrl)
+ assert inputCode == 0 : inputError
+ def inputRowsets = parseJson(inputBody.trim()).rs_metas
+ for (def version : [v1, v2]) {
+ assert inputRowsets.count {
+ it.start_version.toString().toLong() == version &&
+ it.end_version.toString().toLong() == version &&
+ it.num_rows.toString().toLong() == 2 &&
+ it.num_segments.toString().toLong() == 1
+ } == 1
+ }
+ try {
+ GetDebugPoint().enableDebugPointForAllBEs(
+
"SizeBasedCumulativeCompactionPolicy::pick_input_rowsets.set_input_rowsets",
+ [tablet_id: "${tabletId}", start_version: "${v1}",
end_version: "${v2}"])
+
trigger_and_wait_compaction("test_ordered_compaction_hidden_version_no_light_schema_change",
"cumulative")
+ } finally {
+ GetDebugPoint().disableDebugPointForAllBEs(
+
"SizeBasedCumulativeCompactionPolicy::pick_input_rowsets.set_input_rowsets")
+ }
+
+ def metaUrl = sql_return_maparray(
+ "SHOW TABLETS FROM
test_ordered_compaction_hidden_version_no_light_schema_change").get(0).MetaUrl
+ def (code, body, error) = curl("GET", metaUrl)
+ assert code == 0 : error
+ def rowsets = parseJson(body.trim()).rs_metas
+ assert rowsets.count {
+ it.start_version.toString().toLong() == v1 &&
+ it.end_version.toString().toLong() == v2 &&
+ it.num_rows.toString().toLong() == 4
+ } == 1
+
+ order_qt_versions """SELECT k,
+ (__DORIS_VERSION_COL__ = CASE WHEN k < 20 THEN ${v1} ELSE ${v2}
END) AS correct_version
+ FROM test_ordered_compaction_hidden_version_no_light_schema_change
ORDER BY k"""
+ qt_min_max """SELECT MIN(__DORIS_VERSION_COL__) = ${v1},
+ MAX(__DORIS_VERSION_COL__) = ${v2}
+ FROM
test_ordered_compaction_hidden_version_no_light_schema_change"""
+ qt_version_filters """SELECT
+ (SELECT COUNT(*) FROM
test_ordered_compaction_hidden_version_no_light_schema_change
+ WHERE __DORIS_VERSION_COL__ = ${v1}),
+ (SELECT COUNT(*) FROM
test_ordered_compaction_hidden_version_no_light_schema_change
+ WHERE __DORIS_VERSION_COL__ = ${v2})"""
+
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]