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
commit b30e0c95c58e9032384fcfa817b816688abd1bf2 Author: deardeng <[email protected]> AuthorDate: Tue Oct 13 10:18:50 2026 +0800 [fix](cloud) Fix SHOW TABLETS visible version (#68467) (#68949) pick from https://github.com/apache/doris/pull/68467 Problem Summary: Cloud replicas keep placeholder version fields in FE metadata. SHOW TABLETS constructed TabletsProcDir without the partition visible version, so it displayed -1 and filtered on the stale replica version. Batch-read partition visible versions outside the table metadata lock, pass each version through the existing TabletsProcDir constructor, and filter on the same displayed version returned to users. Enable the existing partitioned and non-partitioned regression case in cloud mode and add a focused unit test for version filtering. Fix SHOW TABLETS to display and filter by the current partition visible version in cloud mode. - Test: Unit Test - ./run-fe-ut.sh --run org.apache.doris.common.proc.CloudProcVersionDisplayTest - ./run-fe-ut.sh --run org.apache.doris.nereids.trees.plans.commands.TruncateTableCommandTest#testTruncateTable - Cloud regression case enabled but not run because this worktree has no running cloud cluster - Behavior changed: Yes, cloud SHOW TABLETS now reports and filters by partition visible version - Does this need documentation: No (cherry picked from commit e75325840cb928030f3212a3380dc6b8969b994f) ### What problem does this PR solve? Issue Number: close #xxx Related PR: #xxx Problem Summary: ### Release note None ### Check List (For Author) - Test <!-- At least one of them must be included. --> - [ ] Regression test - [ ] Unit Test - [ ] Manual test (add detailed scripts or steps below) - [ ] No need to test or manual test. Explain why: - [ ] This is a refactor/code format and no logic has been changed. - [ ] Previous test can cover this change. - [ ] No code files have been changed. - [ ] Other reason <!-- Add your reason? --> - Behavior changed: - [ ] No. - [ ] Yes. <!-- Explain the behavior change --> - Does this need documentation? - [ ] No. - [ ] Yes. <!-- Add document PR link here. eg: https://github.com/apache/doris-website/pull/1214 --> ### Check List (For Reviewer who merge this PR) - [ ] Confirm the release note - [ ] Confirm test cases - [ ] Confirm document - [ ] Add branch pick label <!-- Add branch pick label that this PR should merge into --> --- .../apache/doris/common/proc/TabletsProcDir.java | 6 ++-- .../commands/ShowTabletsFromTableCommand.java | 40 +++++++++++++--------- .../common/proc/CloudProcVersionDisplayTest.java | 16 +++++++++ .../select_tablets/select_with_tablets.groovy | 3 -- 4 files changed, 43 insertions(+), 22 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/common/proc/TabletsProcDir.java b/fe/fe-core/src/main/java/org/apache/doris/common/proc/TabletsProcDir.java index 2e47a8f707a..19bdc78aa16 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/common/proc/TabletsProcDir.java +++ b/fe/fe-core/src/main/java/org/apache/doris/common/proc/TabletsProcDir.java @@ -175,13 +175,13 @@ public class TabletsProcDir implements ProcDirInterface { } for (Replica replica : tablet.getReplicas()) { long beId = replica.getBackendIdWithoutException(); - if ((version > -1 && replica.getVersion() != version) + long displayVersion = ProcReplicaVersionDisplay.getDisplayReplicaVersion( + replica, partitionVisibleVersion); + if ((version > -1 && displayVersion != version) || (backendId > -1 && beId != backendId) || (state != null && replica.getState() != state)) { continue; } - long displayVersion = ProcReplicaVersionDisplay.getDisplayReplicaVersion( - replica, partitionVisibleVersion); long displayLastSuccessVersion = ProcReplicaVersionDisplay.getDisplayReplicaLastSuccessVersion( replica, partitionVisibleVersion); List<Comparable> tabletInfo = new ArrayList<Comparable>(); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowTabletsFromTableCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowTabletsFromTableCommand.java index 491bc93b60c..bf52ddf5f13 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowTabletsFromTableCommand.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowTabletsFromTableCommand.java @@ -57,7 +57,6 @@ import org.apache.doris.qe.StmtExecutor; import com.google.common.collect.Lists; import java.util.ArrayList; -import java.util.Collection; import java.util.List; import java.util.Locale; import java.util.Optional; @@ -200,19 +199,20 @@ public class ShowTabletsFromTableCommand extends ShowCommand { Env env = Env.getCurrentEnv(); Database db = env.getInternalCatalog().getDbOrAnalysisException(dbTableName.getDb()); OlapTable olapTable = db.getOlapTableOrAnalysisException(dbTableName.getTbl()); + + // The parser passes limit = 0 when the statement carries no LIMIT clause + // (see LogicalPlanBuilder#visitShowTabletsFromTable), so only a positive limit + // bounds the result. sizeLimit is how many sorted rows have to be kept: the LIMIT + // rows plus the OFFSET rows that are skipped afterwards. + Optional<Integer> sizeLimit = Optional.empty(); + if (limit > 0) { + long capped = limit + Math.max(offset, 0); + sizeLimit = Optional.of((int) Math.min(capped, Integer.MAX_VALUE)); + } + + List<Partition> partitions = new ArrayList<>(); olapTable.readLock(); try { - // The parser passes limit = 0 when the statement carries no LIMIT clause - // (see LogicalPlanBuilder#visitShowTabletsFromTable), so only a positive limit - // bounds the result. sizeLimit is how many sorted rows have to be kept: the LIMIT - // rows plus the OFFSET rows that are skipped afterwards. - Optional<Integer> sizeLimit = Optional.empty(); - if (limit > 0) { - long capped = limit + Math.max(offset, 0); - sizeLimit = Optional.of((int) Math.min(capped, Integer.MAX_VALUE)); - } - - Collection<Partition> partitions = new ArrayList<Partition>(); if (partitionNames != null) { List<String> paNames = partitionNames.getPartitionNames(); if (!paNames.isEmpty()) { @@ -225,21 +225,29 @@ public class ShowTabletsFromTableCommand extends ShowCommand { } } } else { - partitions = olapTable.getPartitions(); + partitions.addAll(olapTable.getPartitions()); } + } finally { + olapTable.readUnlock(); + } + + List<Long> visibleVersions = Partition.getVisibleVersions(partitions); + List<List<Comparable>> tabletInfos = new ArrayList<>(); + olapTable.readLock(); + try { // With an explicit ORDER BY every tablet has to be collected before the result can be // truncated, otherwise the sort only sees an arbitrary prefix of the scan and returns // the wrong rows -- the bug reported in #65871. Without ORDER BY the scan still stops // as soon as enough rows are gathered, as it did before: LIMIT then returns a prefix // of the scan, ordered by (tabletId, replicaId) among itself. boolean stop = false; - List<List<Comparable>> tabletInfos = new ArrayList<>(); - for (Partition partition : partitions) { + for (int i = 0; i < partitions.size(); i++) { if (stop) { break; } + Partition partition = partitions.get(i); for (MaterializedIndex index : partition.getMaterializedIndices(IndexExtState.ALL)) { - TabletsProcDir procDir = new TabletsProcDir(olapTable, index); + TabletsProcDir procDir = new TabletsProcDir(olapTable, index, visibleVersions.get(i)); tabletInfos.addAll(procDir.fetchComparableResult( version, backendId, replicaState)); if (orderByPairs == null && sizeLimit.isPresent() && tabletInfos.size() >= sizeLimit.get()) { diff --git a/fe/fe-core/src/test/java/org/apache/doris/common/proc/CloudProcVersionDisplayTest.java b/fe/fe-core/src/test/java/org/apache/doris/common/proc/CloudProcVersionDisplayTest.java index 1957e565787..bde328500ff 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/common/proc/CloudProcVersionDisplayTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/common/proc/CloudProcVersionDisplayTest.java @@ -53,6 +53,8 @@ import org.junit.Test; import org.mockito.MockedStatic; import org.mockito.Mockito; +import java.util.List; + public class CloudProcVersionDisplayTest { private static final long DB_ID = 10001L; private static final long TABLE_ID = 20001L; @@ -120,6 +122,20 @@ public class CloudProcVersionDisplayTest { assertVersionColumns(result, PARTITION_VISIBLE_VERSION); } + @Test + public void testTabletsProcDirFiltersByDisplayedCloudVersion() throws AnalysisException { + ProcTestContext context = createProcTestContext(); + TabletsProcDir procDir = new TabletsProcDir( + context.table, context.partition.getBaseIndex(), PARTITION_VISIBLE_VERSION); + + List<List<Comparable>> result = procDir.fetchComparableResult(PARTITION_VISIBLE_VERSION, -1, null); + + Assert.assertEquals(1, result.size()); + Assert.assertEquals( + PARTITION_VISIBLE_VERSION, result.get(0).get(TabletsProcDir.TITLE_NAMES.indexOf("Version"))); + Assert.assertTrue(procDir.fetchComparableResult(STALE_REPLICA_VERSION, -1, null).isEmpty()); + } + @Test public void testReplicasProcNodeShowsPartitionCachedVersionInCloudMode() throws AnalysisException { ProcTestContext context = createProcTestContext(); diff --git a/regression-test/suites/nereids_p0/select_tablets/select_with_tablets.groovy b/regression-test/suites/nereids_p0/select_tablets/select_with_tablets.groovy index a76750712a1..6cb6b2436e2 100644 --- a/regression-test/suites/nereids_p0/select_tablets/select_with_tablets.groovy +++ b/regression-test/suites/nereids_p0/select_tablets/select_with_tablets.groovy @@ -16,9 +16,6 @@ // under the License. suite("select_with_tablets") { - if (isCloudMode()) { - return - } sql 'set enable_nereids_planner=true;' sql 'set enable_fallback_to_original_planner=false;' --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
