Skip to content

[test](catalog) Add unit tests for SHOW TABLES name listing on external catalogs - #1

Merged
Baymine merged 3 commits into
Baymine:improvement/show-tables-external-perffrom
u70b3:test-show-tables-external-ut
Aug 5, 2026
Merged

Baymine merged 3 commits into
Baymine:improvement/show-tables-external-perffrom
u70b3:test-show-tables-external-ut

Conversation

@u70b3

@u70b3 u70b3 commented Aug 4, 2026

Copy link
Copy Markdown

Hi @Baymine — as mentioned in apache#66080, here are unit tests for the SHOW TABLES fast path, adapted to your implementation (getTableNamesWithLock() and the InternalCatalog check).

7 cases:

  • plain SHOW TABLES on an external catalog lists names only — verifies getTables() is never called
  • LIKE pattern filter on the fast path
  • SHOW privilege filter on the fast path
  • name-listing failure (case-insensitive conflict) propagates instead of returning an empty result
  • SHOW FULL TABLES / SHOW VIEWS / internal catalog keep the getTables() path (temporary tables still hidden)

Verified: mvn -pl fe-core -am test -Dtest=ShowTableCommandExternalTest → 7/7 pass; fe-core checkstyle clean.

If you merge this into your branch, the tests become part of apache#66080. Happy to adjust anything.

…al catalogs

Cover the SHOW TABLES fast path added in apache#66080:
- plain SHOW TABLES on an external catalog lists names via
  getTableNamesWithLock() and never initializes table objects
- LIKE pattern and SHOW privilege filters still apply on the fast path
- name-listing failures (case-insensitive name conflicts) propagate
  instead of being swallowed into an empty result
- SHOW FULL TABLES / SHOW VIEWS / internal catalog keep iterating
  table objects (temporary tables still hidden)
@u70b3

u70b3 commented Aug 4, 2026

Copy link
Copy Markdown
Author

Note on the two red checks — both are fork-side CI infrastructure issues, unrelated to this change (which adds a single Java test file):

  • ShellCheck: GitHub refuses to check out fork-PR code in a pull_request_target workflow (cross-fork anti-pwn-request protection). Expected for any fork-to-fork PR.
  • Clang Tidy Preparation: the fork's workflow files pin the deprecated actions/upload-artifact: v3, which GitHub now hard-fails. These workflows no longer exist in current apache/doris master — syncing the fork with upstream would clear them, but it's not required.

Neither check processes Java files, and the real CI gate runs on apache#66080 after merge. Safe to merge despite the red X's here.

@Baymine

Baymine commented Aug 5, 2026

Copy link
Copy Markdown
Owner

Thanks for the tests, @u70b3 — the failure-propagation case in particular is a good catch.

One thing before we merge: I'd like to keep this aligned with the Google Java Style Guide on test-class naming:

A test class has a name that ends with Test, for example, HashIntegrationTest. If it covers a single class, its name is the name of that class plus Test, for example HashImplTest.

Both this new ShowTableCommandExternalTest and the existing ShowTableCommandTest cover the same single class, ShowTableCommand — so per the guide the "external" cases should live in ShowTableCommandTest rather than in a separate class. Splitting one class's tests across
two files also makes coverage harder to see at a glance.

ShowTableCommandTest already added fast-path coverage in cad2f74, so most of the 7 cases here overlap with what's there:

  • listsNamesOnly / privilege filter → already covered
  • SHOW FULL TABLES / SHOW VIEWS / internal-catalog still-loads → already covered

The two that add genuinely new coverage are:

  • LIKE-pattern filter on the fast path
  • name-listing failure propagates (guards the getTableNamesWithLock() contract from 6f15009, which currently has no FE unit test)

Could you fold just those two cases into ShowTableCommandTest (reusing its existing ShowTableCommandMocks helper) and drop the new class? That keeps one test file per class and avoids the duplicate cases.

u70b3 added 2 commits August 5, 2026 16:39
…dTest

Address review feedback: keep one test class per tested class (Google
Java Style) and reuse the existing ShowTableCommandMocks helper instead
of a separate ShowTableCommandExternalTest. The listsNamesOnly,
privilege-filter, SHOW FULL TABLES, SHOW VIEWS and internal-catalog
cases duplicate the call-count coverage added in cad2f74 and are
dropped.

Retained new coverage:
- LIKE pattern filter applies on the names-only fast path and
  getTables() is never called
- name-listing failures (case-insensitive name conflicts) raised by
  getTableNamesWithLock() propagate instead of being swallowed into
  an empty result

Verified: mvn -pl fe-core -am test -Dtest=ShowTableCommandTest, 8/8 pass.
@Baymine
Baymine merged commit 52dc351 into Baymine:improvement/show-tables-external-perf Aug 5, 2026
4 of 7 checks passed
@u70b3

u70b3 commented Aug 5, 2026

Copy link
Copy Markdown
Author

@Baymine Done — folded the LIKE-pattern and name-conflict propagation cases into ShowTableCommandTest (reusing ShowTableCommandMocks), dropped ShowTableCommandExternalTest and the 5 overlapping cases. Also merged your cad2f74d into the branch to pick up the mocks helper. Verified: mvn -pl fe-core -am test -Dtest=ShowTableCommandTest → 8/8 pass.

@u70b3
u70b3 deleted the test-show-tables-external-ut branch August 11, 2026 03:40
Baymine pushed a commit that referenced this pull request Sep 7, 2026
…ExprId (apache#67047)

### What problem does this PR solve?

Related PR: apache#57204

Problem Summary:

#### 1. Captured arguments from outer Lambdas could not be resolved

Lambda arguments were associated with their bound arrays by argument
name, and `visitArrayItemSlot` only searched the innermost Lambda scope.

For example:

```sql
SELECT array_map(
           m -> array_map(
               x -> element_at(map_values(m)[1], 'a') + x,
               [1]),
           maps)
FROM t;
```
The inner Lambda captures m from the outer Lambda. The collector should
produce:`s.data.*.VALUES.a`

#### 2. `element_at` did not collect payload access for Lambda index/key
arguments
For example:
```sql
SELECT id,
       array_map(
           (nested, i) -> element_at(nested, i),
           nested_arrays,
           indexes
       ) AS result
FROM repro_lambda_access_path
WHERE indexes IS NOT NULL
ORDER BY id;
-- ERROR 1105 (HY000): errCode = 2, detailMessage = (127.0.0.1)[INVALID_ARGUMENT]in array map function, the input column size are not equal completely, nested column data rows 1st size is 5, 2th size is 0.
```

In `EXPLAIN VERBOSE`:
```text
|   0:VOlapScanNode(20)                                                                                                                                      |
|      TABLE: repro_lambda_access_path.repro_lambda_access_path(repro_lambda_access_path), PREAGGREGATION: ON                                                |
|      PREDICATES: indexes[apache#2] IS NOT NULL                                                                                                                   |
|      partitions=1/1 (repro_lambda_access_path)                                                                                                             |
|      tablets=1/1, tabletList=1787714324292                                                                                                                 |
|      cardinality=1, avgRowSize=0.0, numNodes=1                                                                                                             |
|      pushAggOp=NONE                                                                                                                                        |
|      nested columns:                                                                                                                                       |
|        nested_arrays:                                                                                                                                      |
|          origin type: array<array<int>>                                                                                                                    |
|          all access paths: [nested_arrays.*.*]                                                                                                             |
|        indexes:                                                                                                                                            |
|          origin type: array<bigint>                                                                                                                        |
|          all access paths: [indexes.NULL]                                                                                                                  |
|          predicate access paths: [indexes.NULL]                                                                                                            |
|      final projections: array_map((nested,i) -> element_at(nested, i), nested_arrays[#1], indexes[apache#2])                                                     |
|      final project output tuple id: 1                                                                                                                      |
|      tuple ids: 0
```

The old visitElementAt handled secondary arguments through a direct
generic visitor call:`visit(arguments.get(i), context);`

When `i` is an `ArrayItemSlot` leaf, this call does not dispatch to
`visitArrayItemSlot`. The collector therefore did not register payload
access for the array bound to `i`.

#### 3. Comparator-form array_sort did not preserve its returned payload
```sql
 SELECT id,
        array_sort(
            (x, y) ->
                IF(
                    cardinality(x) < cardinality(y),
                    -1,
                    IF(cardinality(x) = cardinality(y), 0, 1)
                ),
            nested_arrays
        ) AS result
 FROM repro_lambda_access_path
 ORDER BY id;
+------+--------------------------------------------------------------+
| id   | result                                                       |
+------+--------------------------------------------------------------+
|    1 | [[null, null], [null, null, null], [null, null, null, null]] |
|    2 | [[null], [null, null]]                                       |
|    3 | []                                                           |
|    4 | NULL                                                         |
+------+--------------------------------------------------------------+
```

In `EXPLAIN VERBOSE`:
```text
|   0:VOlapScanNode(15)                                                                                                                                           |
|      TABLE: repro_lambda_access_path.repro_lambda_access_path(repro_lambda_access_path), PREAGGREGATION: ON                                                     |
|      partitions=1/1 (repro_lambda_access_path)                                                                                                                  |
|      tablets=1/1, tabletList=1787714324292                                                                                                                      |
|      cardinality=4, avgRowSize=1592.5, numNodes=1                                                                                                               |
|      pushAggOp=NONE                                                                                                                                             |
|      nested columns:                                                                                                                                            |
|        nested_arrays:                                                                                                                                           |
|          origin type: array<array<int>>                                                                                                                         |
|          all access paths: [nested_arrays.*.OFFSET]                                                                                                             |
|      final projections: array_sort((x,y) -> if((cardinality(x) < cardinality(x)), -1, if((cardinality(x) = cardinality(x)), 0, 1)), nested_arrays[#1])          |
|      final project output tuple id: 1                                                                                                                           |
|      tuple ids: 0
```


For arr `ARRAY<ARRAY<INT>>`, the comparator only needs the inner-array
offsets: `arr.*.OFFSET`.

However, `array_sort` also returns the original inner arrays after
reordering them. The old collector returned immediately after collecting
the comparator paths and did not propagate the consumer's result path to
`arr`.

#### What is changed

1. Resolve Lambda bindings by `ExprId`
- Associate each `ArrayItemReference` with its bound array by `ExprId`.
- When visiting an `ArrayItemSlot`, search Lambda scopes from the
innermost scope to the outermost scope.

2. Dynamically dispatch `element_at` index/key expressions
3. Preserve comparator paths and result paths for `array_sort`

#### After fix: 
```text
Doris> SELECT id,
    ->        array_map(
    ->            (nested, i) -> element_at(nested, i),
    ->            nested_arrays,
    ->            indexes
    ->        ) AS result
    -> FROM repro_lambda_access_path
    -> WHERE indexes IS NOT NULL
    -> ORDER BY id;
+------+-----------+
| id   | result    |
+------+-----------+
|    1 | [3, 4, 2] |
|    2 | [9, 7]    |
|    3 | []        |
+------+-----------+

Doris> SELECT id,
    ->        array_sort(
    ->            (x, y) ->
    ->                IF(
    ->                    cardinality(x) < cardinality(y),
    ->                    -1,
    ->                    IF(cardinality(x) = cardinality(y), 0, 1)
    ->                ),
    ->            nested_arrays
    ->        ) AS result
    -> FROM repro_lambda_access_path
    -> ORDER BY id;
+------+-----------------------------------+
| id   | result                            |
+------+-----------------------------------+
|    1 | [[1, 2], [2, 3, 1], [4, 2, 1, 4]] |
|    2 | [[9], [8, 7]]                     |
|    3 | []                                |
|    4 | NULL                              |
+------+-----------------------------------+
```
Baymine pushed a commit that referenced this pull request Sep 7, 2026
Problem Summary: Streaming `ROWS` window aggregates retain state across
frame evaluations. The eviction path previously considered only whether
buffered blocks had been emitted, so it could erase either the outgoing
row needed by a bounded sliding frame or the next unread row needed by
an `UNBOUNDED PRECEDING ... N PRECEDING` frame. After rebasing, negative
partition and outgoing positions could allow a nullable aggregate to
access its null map out of bounds. Evicting either kind of required row
could also produce incorrect aggregate results.

Root cause: `_remove_unused_rows()` did not account for the earliest row
required by the next ROWS frame evaluation, and
`BoundaryPose::remove_unused_rows()` allowed retained-column coordinates
to become negative.

This change defers block-aligned eviction when the candidate prefix
contains either `frame_start - 1`, the outgoing row required by a
bounded sliding update, or the next unread row required by an `UNBOUNDED
PRECEDING ... N PRECEDING` frame. It also rebases partition and order
boundaries to nonnegative physical-column coordinates. The BE unit
coverage exercises both ROWS executors across eviction boundaries and
verifies boundary rebasing.

Observed ASAN failure before this change (`output/be/log/be.out`):

```text
ERROR: AddressSanitizer: heap-buffer-overflow
READ of size 1
    #0 doris::AggregateFunctionNullUnaryInlineV2<...>::execute_function_with_incremental(...)
       be/src/exprs/aggregate/aggregate_function_null_v2.h:595
    #1 doris::AggFnEvaluator::execute_function_with_incremental(...)
       be/src/exprs/vectorized_agg_fn.cpp:334
    apache#2 doris::AnalyticSinkLocalState::_execute_for_function<true>(...)
       be/src/exec/operator/analytic_sink_operator.cpp:385
    apache#3 doris::AnalyticSinkLocalState::_get_next_for_sliding_rows(...)
       be/src/exec/operator/analytic_sink_operator.cpp:203
    apache#4 doris::AnalyticSinkLocalState::_execute_impl(...)
       be/src/exec/operator/analytic_sink_operator.cpp:358
    apache#5 doris::AnalyticSinkOperatorX::sink_impl(...)
       be/src/exec/operator/analytic_sink_operator.cpp:757
SUMMARY: AddressSanitizer: heap-buffer-overflow in
doris::AggregateFunctionNullUnaryInlineV2<...>::execute_function_with_incremental(...)
```


### 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:
apache/doris-website#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 -->
Baymine pushed a commit that referenced this pull request Oct 19, 2026
…pache#68880)

Issue Number: N/A

Related PR: N/A

Problem Summary: EXCEPT DISTINCT can introduce a streaming distinct
aggregation whose grouping expressions repeat an input column, for
example (s, d, d). When preaggregation switches to pass-through, both
output construction and column reuse call assert_mutable() even though
they only transfer column references. Retaining output references can
make a repeated key shared, so a subsequent assertion fails with
COW::assert_mutable: use_count() > 1:

```
W 2026-10-09 06:31:59,596 13803 exception.cpp:34] meet exception, error code: 6, message: COW::assert_mutable: use_count() > 1
0#  doris::Exception::Exception(int, std::basic_string_view<char, std::char_traits<char> > const&) at /usr/local/ldb-toolchain-v0.26/bin/../lib/gcc/x86_64-pc-linux-gnu/15/include/g++-v15/bits/basic_string.h:239
1#  doris::DistinctStreamingAggLocalState::_distinct_pre_agg_with_serialized_key(doris::Block*, doris::Block*) at ../src/core/cow.h:325
2#  doris::DistinctStreamingAggOperatorX::push(doris::RuntimeState*, doris::Block*, bool) const at ../src/common/status.h:519
3#  doris::StatefulOperatorX<doris::DistinctStreamingAggLocalState>::get_block_impl(doris::RuntimeState*, doris::Block*, bool*) at ../src/common/status.h:519
4#  doris::OperatorXBase::get_block(doris::RuntimeState*, doris::Block*, bool*) at ../src/common/status.h:519
5#  doris::OperatorXBase::get_block_after_projects(doris::RuntimeState*, doris::Block*, bool*) at ./be/build_RELEASE/../src/exec/operator/operator.cpp:0
6#  doris::PipelineTask::execute(bool*) at ./be/src/exec/pipeline/pipeline_task.cpp:0
7#  doris::TaskScheduler::_do_work(int) at ./be/src/exec/pipeline/task_scheduler.cpp:155
```

Use immutable get_ptr() references in both pass-through paths. The
evaluated key pointers preserve the original column when a repeated
input position has already been replaced during column reuse, and
downstream mutations continue to use copy-on-write. No column data is
copied during pass-through. Add unit coverage with three references to
one input slot for fresh and reused output blocks, transition from
deduplication, retained output ownership, and nullable output. Add
regression coverage for repeated keys in EXCEPT DISTINCT, nullable
EXCEPT output, INTERSECT DISTINCT, and UNION DISTINCT.

Fix queries with repeated projected columns failing with a COW assertion
during distinct streaming aggregation.

根因是:**Distinct Streaming Aggregation 在透传列时调用了要求“列对象独占”的
`assert_mutable()`,而重复分组键会让多个输出位置共享同一个列对象,导致后续调用违反这个要求。**

下面结合修复前的代码,分别说明两条透传路径。

**1\. `assert_mutable()` 检查的是列对象的引用计数**

COW::assert\_mutable() (be/src/core/cow.h:323) 的实现是:

```
MutablePtr assert_mutable() const {
    if (this->use_count() > 1) {
        throw Exception(ErrorCode::INTERNAL_ERROR,
                        "COW::assert_mutable: use_count() > 1");
    }
    return const_cast<COW*>(this)->get_ptr();
}
```

它要求调用时 `use_count() <= 1`,直接返回可变指针,**不会自动复制共享的列对象**。

如果确实需要修改可能共享的列,应使用 IColumn::mutate()
(be/src/core/column/column.h:618):它通过 `shallow_mutate()` 在引用计数大于 1
时复制列,使修改发生在独立对象上。

这里的引用计数统计的是持有列对象的智能指针数量。例如:

```
in_block.column[1] ─┐
                   ├── 同一个日期列对象 C
output.column[2] ───┘

C.use_count() = 2
```

**2\. 重复投影如何变成重复输入列引用**

例如:

```
SELECT s, d, d FROM t1
EXCEPT DISTINCT
SELECT s, d, d FROM t2;
```

当优化器为集合操作的输入推导局部去重时,InferSetOperatorDistinct
(fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/InferSetOperatorDistinct.java:60)
使用子节点输出构造分组键:

```
new LogicalAggregate<>(
        ImmutableList.copyOf(child.getOutput()), true, child)
```

因此,生成的局部聚合可能保留重复槽位,例如:

```
group by: s[#1], d[apache#2], d[apache#2]
```

BE 在准备分组列
(be/src/exec/operator/distinct\_streaming\_aggregation\_operator.cpp:177)时,记录表达式执行结果:

```
RETURN_IF_ERROR(_probe_expr_ctxs[i]->execute(in_block, &result_column_id));
// 准备列……
key_columns[i] = in_block->get_by_position(result_column_id).column.get();
result_idxs[i] = result_column_id;
```

假设输入 Block 只有 `s`、`d` 两列,最终得到:

```
in_block:    [Cs, Cd]
result_idxs: [ 0,  1,  1]
key_columns: [Cs*, Cd*, Cd*]
```

两个日期键指向同一个列对象。`key_columns` 保存的是裸指针,本身不增加引用计数。

当预聚合因内存限制或去重收益不足设置 `_stop_emplace_flag = true` 后,算子开始透传输入,进入下面的问题路径。

**3\. 首次构造输出:两个重复引用即可报错**

修复前,不复用输出列的透传代码是:

```
for (int i = 0; i < key_size; ++i) {
    if (_stop_emplace_flag) {
        columns_with_schema.emplace_back(
                key_columns[i]->assert_mutable(),
                /* type, name */);
    }
}
```

对应当前代码的输出构造位置
(be/src/exec/operator/distinct\_streaming\_aggregation\_operator.cpp:267)。

以 `[s, d, d]` 为例,假设日期列 `Cd` 开始只有输入 Block 持有:

| 时刻 | 持有 `Cd` 的位置 | 稳定引用计数 |
|---|---|---:|
| 处理第一个 `d` 前 | 输入列 | 1 |
| 第一个 `d` 加入输出后 | 输入列、第一个日期输出列 | 2 |
| 处理第二个 `d` 时 | 再次调用 `Cd->assert_mutable()` | 2,抛异常 |

第一个 `d` 输出时增加了一个列引用,输入引用仍然存在。第二个 `d` 再要求独占,就会失败。

后面的 `in_block->clear()` 原本可以释放输入引用,但异常已经在循环内发生,执行不到那里。

**4\. 复用输出 Block:三个重复引用能展示同样的问题**

修复前,复用输出列的透传位置
(be/src/exec/operator/distinct\_streaming\_aggregation\_operator.cpp:235)
是:

```
for (int i = 0; i < key_size; ++i) {
    auto output_column = out_block->get_by_position(i).column;
    out_block->replace_by_position(i, key_columns[i]->assert_mutable());
    in_block->replace_by_position(result_idxs[i], output_column);
}
```

这个分支将旧输出列放回输入 Block,释放输入对原数据列的引用。

以 `[s, d, d, d]` 为例:

```
result_idxs = [0, 1, 1, 1]
```

假设输出列最初为空,且没有其他所有者:

| 时刻 | 原日期列 `Cd` 的所有者 | 稳定引用计数 |
|---|---|---:|
| 第一个 `d` 处理结束 | 第一个日期输出列;输入位置已换成旧输出空列 | 1 |
| 第二个 `d` 处理结束 | 第一个、第二个日期输出列 | 2 |
| 第三个 `d` 开始处理 | 调用 `Cd->assert_mutable()` | 2,抛异常 |

第二次替换的输入位置已经是空列,无法再释放原日期列的引用。于是两个输出列共同持有 `Cd`,第三次独占断言失败。

因此,**复用分支中只有两个相同槽位不一定立即报错**;已有单测使用 `[0, 1, 0, 0]`,让同一输入槽位出现三次,覆盖这一过程。

**5\. 为什么改为 `get_ptr()` 能解决**

两条透传路径现在都使用:

```
key_columns[i]->get_ptr()
```

`key_columns` 的类型是 `std::vector<const IColumn*>`,因此这里调用的是 const 版本的
`get_ptr()` (be/src/core/cow.h:304),返回不可变列指针。

透传只需要让输出引用已有列数据,允许多个输出位置共享该列。后续需要修改数据时,仍通过 `IColumn::mutate()` 执行 COW。

复用分支继续从预先记录的 `key_columns` 取指针也很关键:第一次替换后,`in_block[result_idxs[i]]`
已经变成旧输出列,而 `key_columns[i]` 仍指向原数据列,并由前面的输出位置保持其生命周期。

关于 GROUP BY,直接的 `GROUP BY s, d, d` 会在 NormalizeAggregate
(fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/NormalizeAggregate.java:167)
中去重。静态分析发现,`GROUP BY + LIMIT` 下推到 `UNION ALL` 分支时,槽位映射可能重新引入重复键;已在回归用例
(regression-test/suites/query\_p0/set\_operations/distinct\_streaming\_repeated\_keys.groovy:101)中补充直接分组对照和该候选场景,并检查计划中同一槽位是否出现三次。提交为
`c8c1f67d3e9`,按你的要求未执行新增用例,因此尚未实测确认该 GROUP BY 场景。

- Test: Unit Test / Regression test / Manual test
    - ASAN build with ./build.sh --be -j 12
    - 11 BE unit tests covering distinct streaming aggregation
- Four regression queries; results also match non-streaming execution
    - Original reproducing SQL on the supplied table data
- clang-format 16, format check, build hygiene, and clang-tidy on
changed lines
- Behavior changed: Yes; repeated grouping keys pass through without an
incorrect ownership assertion
- Does this need documentation: No

### 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:
apache/doris-website#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 -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants