Repository: pingcap/tidb
Pull request #60822: planner: fix wrong TopN's ByItem with expression.ScalarFunction when to PushDownTopN
Author: login: hawkingrei
Labels: name: sig/planner
description: SIG: Planner
name: release-note
description: Denotes a PR that will be considered when it comes time to generate release notes.
name: size/XXL
description: Denotes a PR that changes 1000+ lines, ignoring generated files.
name: approved
name: lgtm
Created: 2025-04-24T16:22:37Z | Merged: 2025-05-07T17:23:50Z

<!--

Thank you for contributing to TiDB!

PR Title Format:
1. pkg [, pkg2, pkg3]: what's changed
2. *: what's changed

-->

### What problem does this PR solve?
<!--

Please create an issue first to describe the problem.

There MUST be one line starting with "Issue Number:  " and
linking the relevant issues via the "close" or "ref".

For more info, check https://pingcap.github.io/tidb-dev-guide/contribute-to-tidb/contribute-code.html#referring-to-an-issue.

-->

Issue Number: close #60655 

Problem Summary:

In the https://github.com/pingcap/tidb/pull/40593, 

There is a column in topN.ByItems is generated by proj, when topN is pushed down below proj, topN cannot obtain the column from datasource, to fix this, we can check whether topN.ByItems contains a column(with ID=0) generated by proj, if so, proj will prevent the optimizer from pushing topN down.

1. A column with ID=0 indicates that the column cannot be resolved by data source.
2. To determine whether a column is generated by projection, we can check whether the child of proj contains the column.



### What changed and how does it work?

If you find that the TopN you can push down cannot actually be pushed down, you should use the original TopN to assemble into a structure of ```TopN -> Projection```, rather than using the processed TopN to assemble.

### Check List

Tests <!-- At least one of them must be included. -->

- [x] Unit test
- [ ] Integration test
- [ ] Manual test (add detailed scripts or steps below)
- [ ] No need to test
  > - [ ] I checked and no code files have been changed.
  > <!-- Or your custom  "No need to test" reasons -->

Side effects

- [ ] Performance regression: Consumes more CPU
- [ ] Performance regression: Consumes more Memory
- [ ] Breaking backward compatibility

Documentation

- [ ] Affects user behaviors
- [ ] Contains syntax changes
- [ ] Contains variable changes
- [ ] Contains experimental features
- [ ] Changes MySQL compatibility

### Release note

<!-- compatibility change, improvement, bugfix, and new feature need a release note -->

Please refer to [Release Notes Language Style Guide](https://pingcap.github.io/tidb-dev-guide/contribute-to-tidb/release-notes-style-guide.html) to write a quality release note.

```release-note
planner: fix wrong TopN's ByItem with expression.ScalarFunction when to PushDownTopN

修复在 TopN 下推过程中错误生成带表达式的TopN排序项 
```


Linked issue #60655: Throw Can't find column xxx in schema Column Error when execute SQL
## Bug Report

Please answer these questions before submitting your issue. Thanks!

### 1. Minimal reproduce step (Required)

<!-- a step by step guide for reproducing the bug. -->
```
create database test;
use test;
CREATE TABLE `table_test` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `apply_id` bigint(20) NOT NULL,
  `form_id` int(11) NOT NULL,
  `ws_id` int(11) DEFAULT NULL,
  `ordinal` int(11) DEFAULT NULL,
  `col1` json DEFAULT NULL,
  `col2` json DEFAULT NULL,
  `col3` json DEFAULT NULL,
  `col4` json DEFAULT NULL,
  `col5` json DEFAULT NULL,
  `col6` json DEFAULT NULL,
  `col7` json DEFAULT NULL,
  `col8` json DEFAULT NULL,
  `col9` json DEFAULT NULL,
  `col10` json DEFAULT NULL,
  `col11` json DEFAULT NULL,
  `col12` json DEFAULT NULL,
  `col13` json DEFAULT NULL,
  `col14` json DEFAULT NULL,
  `col15` json DEFAULT NULL,
  `col16` json DEFAULT NULL,
  `col17` json DEFAULT NULL,
  `col18` json DEFAULT NULL,
  `col19` json DEFAULT NULL,
  `col20` json DEFAULT NULL,
  `col21` json DEFAULT NULL,
  `col22` json DEFAULT NULL,
  `col23` json DEFAULT NULL,
  `col24` json DEFAULT NULL,
  `col25` json DEFAULT NULL,
  `col26` json DEFAULT NULL,
  `col27` json DEFAULT NULL,
  `col28` json DEFAULT NULL,
  `col29` json DEFAULT NULL,
  `col30` json DEFAULT NULL,
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP,
  `last_update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `being_deleted` tinyint(1) DEFAULT '0',
  `apply_status` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`,`form_id`),
  KEY `idx_form_apply_deleted` (`form_id`,`apply_id`,`being_deleted`),
  KEY `idx_form_ordinal_deleted` (`form_id`,`ordinal`,`being_deleted`)
);


SELECT cast(if(s.column5 is null
        OR s.column5 = '', 0, s.column5) AS decimal(23,8)) AS column5,s.column1 AS column1,s.column9 AS column9,s.column16 AS column16,s.column17 AS column17,s.column18 AS column18,s.column10 AS column10,s.column3 AS column3,s.column4 AS column4,s.column6 AS column6,s.column7 AS column7
FROM 
    (SELECT apply_id,
        JSON_UNQUOTE(JSON_EXTRACT(col5, '$[0].value')) AS column5,
         replace(replace(replace(json_unquote(json_extract(col10, '$[*].value')), '["', ''), '"]', ''), '","', ',') AS column10,
         JSON_UNQUOTE(JSON_EXTRACT(col6, '$[0].value')) AS column6,
         JSON_UNQUOTE(JSON_EXTRACT(col7, '$[0].value')) AS column7,
         JSON_UNQUOTE(JSON_EXTRACT(col1, '$[0].value')) AS column1,
         JSON_UNQUOTE(JSON_EXTRACT(col9, '$[0].value')) AS column9, col16 -> '$[*].optUid' AS column16,
         replace(replace(replace(json_unquote(json_extract(col16, '$[*].value')), '["', ''), '"]', ''), '","', ',') AS order_column16,
         JSON_UNQUOTE(JSON_EXTRACT(col17, '$[0].value')) AS column17,
         JSON_UNQUOTE(JSON_EXTRACT(col3, '$[0].value')) AS column3,
         JSON_UNQUOTE(JSON_EXTRACT(col18, '$[0].value')) AS column18,
         JSON_UNQUOTE(JSON_EXTRACT(col4, '$[0].value')) AS column4
    FROM 
        (SELECT table_test.apply_id,
        col5,
        col10,
        col6,
        col7,
        col1,
        col9,
        col16,
        col17,
        col3,
        col18,
        col4,
         table_test.ordinal,
        table_test.being_deleted
        FROM table_test
        WHERE table_test.form_id = 9093606
                AND table_test.being_deleted = 0
                AND table_test.apply_status != 1) ta24e
        WHERE ordinal = -1
                AND being_deleted = 0) AS s where( (s.column1 = '标准'))
    ORDER BY  column5 asc,CONVERT(column1
    USING GBK) asc,CONVERT(column9
    USING GBK) asc,CONVERT(column16
    USING GBK) asc,column17 asc,column18 asc,CONVERT(column10
    USING GBK) asc,column3 asc,CONVERT(column4
    USING GBK) asc,CONVERT(column6
    USING GBK) asc,CONVERT(column7
    USING GBK) ASC limit 0,20;
```

### 2. What did you expect to see? (Required)
Execute query success

### 3. What did you see instead (Required)
```
Error with: Can't find column test.large_data_1.col5 in schema Column: [Column#160,Column#161,Column#162,Column#163,Column#164,Column#165,Column#166,Column#168,Column#169,Column#170,Column#171] Unique key: []
```

### 4. What is your TiDB version? (Required)

<!-- Paste the output of SELECT tidb_version() -->
```
select tidb_version();
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| tidb_version()                                                                                                                                                                                                                               |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Release Version: v8.5.1
Edition: Community
Git Commit Hash: fea86c8e35ad4a86a5e1160701f99493c2ee547c
Git Branch: HEAD
UTC Build Time: 2025-01-16 07:40:13
GoVersion: go1.23.2
Race Enabled: false
Check Table Before Drop: false
Store: tikv |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)
```


Linked issue comments: user: login: hawkingrei
created_at: 2025-04-24T14:32:33Z
body: ```
SELECT 
       s.column16 AS column16,
       s.column17 AS column17
FROM
  (SELECT apply_id,
          col16 -> '$[].optUid' AS column16,
          JSON_UNQUOTE(JSON_EXTRACT(col17, '$[0].value')) AS column17
   FROM
     (SELECT table_test.apply_id,
             col16,
             col17,
             table_test.ordinal,
             table_test.being_deleted
      FROM table_test
      WHERE table_test.form_id = 9093606
        AND table_test.being_deleted = 0
        AND table_test.apply_status != 1) ta24e
   WHERE ordinal = -1
     AND being_deleted = 0) AS s 
ORDER BY CONVERT(column16 USING GBK) ASC,column17 ASC
LIMIT 0,
      20;
```
author_association: MEMBER

Diff:
diff --git a/pkg/executor/infoschema_reader_test.go b/pkg/executor/infoschema_reader_test.go
index c499939133af0..2af48afda10b0 100644
--- a/pkg/executor/infoschema_reader_test.go
+++ b/pkg/executor/infoschema_reader_test.go
@@ -982,10 +982,10 @@ func TestInfoSchemaDDLJobs(t *testing.T) {
 	))
 
 	// Test explain output, since the output may change in future.
-	tk.MustQuery(`EXPLAIN SELECT * FROM information_schema.ddl_jobs where db_name = "test2" limit 10;`).Check(testkit.Rows(
-		`Limit_10 10.00 root  offset:0, count:10`,
-		`└─Selection_11 10.00 root  eq(Column#2, "test2")`,
-		`  └─MemTableScan_12 10000.00 root table:DDL_JOBS db_name:["test2"]`,
+	tk.MustQuery(`EXPLAIN FORMAT='brief' SELECT * FROM information_schema.ddl_jobs where db_name = "test2" limit 10;`).Check(testkit.Rows(
+		`Limit 10.00 root  offset:0, count:10`,
+		`└─Selection 10.00 root  eq(Column#2, "test2")`,
+		`  └─MemTableScan 10000.00 root table:DDL_JOBS db_name:["test2"]`,
 	))
 }
 
diff --git a/pkg/planner/core/casetest/vectorsearch/testdata/ann_index_suite_in.json b/pkg/planner/core/casetest/vectorsearch/testdata/ann_index_suite_in.json
index b682d966a5d9a..1f46b52b2ec2d 100644
--- a/pkg/planner/core/casetest/vectorsearch/testdata/ann_index_suite_in.json
+++ b/pkg/planner/core/casetest/vectorsearch/testdata/ann_index_suite_in.json
@@ -48,65 +48,59 @@
   {
     "name": "TestVectorSearchWithPKAuto",
     "cases": [
-      "explain select id from t1",
-
-      "explain select id from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
-      "explain select id from t1 order by vec_cosine_distance(vec, '[1,1,1]')",
-      "explain select * from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
-      "explain select id, a, b from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
-      "explain select a, id, b from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
-
-      "explain select id, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d limit 10",
-      "explain select id, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d",
-      "explain select *, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d limit 10",
-      "explain select id, vec_cosine_distance(vec, '[1,1,1]') as d, a, b from t1 order by d limit 10",
-      "explain select id, a, b, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d limit 10"
+      "explain format = 'brief' select id from t1",
+      "explain format = 'brief' select id from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
+      "explain format = 'brief' select id from t1 order by vec_cosine_distance(vec, '[1,1,1]')",
+      "explain format = 'brief' select * from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
+      "explain format = 'brief' select id, a, b from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
+      "explain format = 'brief' select a, id, b from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
+      "explain format = 'brief' select id, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d limit 10",
+      "explain format = 'brief' select id, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d",
+      "explain format = 'brief' select *, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d limit 10",
+      "explain format = 'brief' select id, vec_cosine_distance(vec, '[1,1,1]') as d, a, b from t1 order by d limit 10",
+      "explain format = 'brief' select id, a, b, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d limit 10"
     ]
   },
   {
     "name": "TestVectorSearchWithPKForceTiKV",
     "cases": [
-      "explain select id from t1",
-
-      "explain select id from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
-      "explain select id from t1 order by vec_cosine_distance(vec, '[1,1,1]')",
-      "explain select * from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
-      "explain select id, a, b from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
-      "explain select a, id, b from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
-
-      "explain select id, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d limit 10",
-      "explain select id, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d",
-      "explain select *, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d limit 10",
-      "explain select id, vec_cosine_distance(vec, '[1,1,1]') as d, a, b from t1 order by d limit 10",
-      "explain select id, a, b, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d limit 10"
+      "explain format = 'brief' select id from t1",
+      "explain format = 'brief' select id from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
+      "explain format = 'brief' select id from t1 order by vec_cosine_distance(vec, '[1,1,1]')",
+      "explain format = 'brief' select * from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
+      "explain format = 'brief' select id, a, b from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
+      "explain format = 'brief' select a, id, b from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
+      "explain format = 'brief' select id, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d limit 10",
+      "explain format = 'brief' select id, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d",
+      "explain format = 'brief' select *, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d limit 10",
+      "explain format = 'brief' select id, vec_cosine_distance(vec, '[1,1,1]') as d, a, b from t1 order by d limit 10",
+      "explain format = 'brief' select id, a, b, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d limit 10"
     ]
   },
   {
     "name": "TestVectorSearchHeavyFunction",
     "cases": [
-      "explain select id from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
-      "explain select id from t1 order by vec_l1_distance(vec, '[1,1,1]') limit 10",
-      "explain select id from t1 order by vec_l2_distance(vec, '[1,1,1]') limit 10",
-      "explain select id from t1 order by vec_negative_inner_product(vec, '[1,1,1]') limit 10",
-      "explain select id from t1 order by vec_dims(vec) limit 10",
-      "explain select id from t1 order by vec_l2_norm(vec) limit 10",
-      "explain select id from t1 order by MOD(a, 3) limit 10",
-
-      "explain select id, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d limit 10",
-      "explain select id, vec_l1_distance(vec, '[1,1,1]') as d from t1 order by d limit 10",
-      "explain select id, vec_l2_distance(vec, '[1,1,1]') as d from t1 order by d limit 10",
-      "explain select id, vec_negative_inner_product(vec, '[1,1,1]') as d from t1 order by d limit 10",
-      "explain select id, vec_dims(vec) as d from t1 order by d limit 10",
-      "explain select id, vec_l2_norm(vec) as d from t1 order by d limit 10",
-      "explain select id, MOD(a, 3) as d from t1 order by d limit 10",
-
-      "explain select * from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
-      "explain select * from t1 order by vec_l1_distance(vec, '[1,1,1]') limit 10",
-      "explain select * from t1 order by vec_l2_distance(vec, '[1,1,1]') limit 10",
-      "explain select * from t1 order by vec_negative_inner_product(vec, '[1,1,1]') limit 10",
-      "explain select * from t1 order by vec_dims(vec) limit 10",
-      "explain select * from t1 order by vec_l2_norm(vec) limit 10",
-      "explain select * from t1 order by MOD(a, 3) limit 10"
+      "explain format = 'brief' select id from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
+      "explain format = 'brief' select id from t1 order by vec_l1_distance(vec, '[1,1,1]') limit 10",
+      "explain format = 'brief' select id from t1 order by vec_l2_distance(vec, '[1,1,1]') limit 10",
+      "explain format = 'brief' select id from t1 order by vec_negative_inner_product(vec, '[1,1,1]') limit 10",
+      "explain format = 'brief' select id from t1 order by vec_dims(vec) limit 10",
+      "explain format = 'brief' select id from t1 order by vec_l2_norm(vec) limit 10",
+      "explain format = 'brief' select id from t1 order by MOD(a, 3) limit 10",
+      "explain format = 'brief' select id, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d limit 10",
+      "explain format = 'brief' select id, vec_l1_distance(vec, '[1,1,1]') as d from t1 order by d limit 10",
+      "explain format = 'brief' select id, vec_l2_distance(vec, '[1,1,1]') as d from t1 order by d limit 10",
+      "explain format = 'brief' select id, vec_negative_inner_product(vec, '[1,1,1]') as d from t1 order by d limit 10",
+      "explain format = 'brief' select id, vec_dims(vec) as d from t1 order by d limit 10",
+      "explain format = 'brief' select id, vec_l2_norm(vec) as d from t1 order by d limit 10",
+      "explain format = 'brief' select id, MOD(a, 3) as d from t1 order by d limit 10",
+      "explain format = 'brief' select * from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
+      "explain format = 'brief' select * from t1 order by vec_l1_distance(vec, '[1,1,1]') limit 10",
+      "explain format = 'brief' select * from t1 order by vec_l2_distance(vec, '[1,1,1]') limit 10",
+      "explain format = 'brief' select * from t1 order by vec_negative_inner_product(vec, '[1,1,1]') limit 10",
+      "explain format = 'brief' select * from t1 order by vec_dims(vec) limit 10",
+      "explain format = 'brief' select * from t1 order by vec_l2_norm(vec) limit 10",
+      "explain format = 'brief' select * from t1 order by MOD(a, 3) limit 10"
     ]
   }
 ]
diff --git a/pkg/planner/core/casetest/vectorsearch/testdata/ann_index_suite_out.json b/pkg/planner/core/casetest/vectorsearch/testdata/ann_index_suite_out.json
index 95023baaff8fe..b003cd040331a 100644
--- a/pkg/planner/core/casetest/vectorsearch/testdata/ann_index_suite_out.json
+++ b/pkg/planner/core/casetest/vectorsearch/testdata/ann_index_suite_out.json
@@ -436,133 +436,133 @@
     "Name": "TestVectorSearchWithPKAuto",
     "Cases": [
       {
-        "SQL": "explain select id from t1",
+        "SQL": "explain format = 'brief' select id from t1",
         "Plan": [
-          "TableReader_14 6000.00 root  MppVersion: 3, data:ExchangeSender_13",
-          "└─ExchangeSender_13 6000.00 mpp[tiflash]  ExchangeType: PassThrough",
-          "  └─TableFullScan_11 6000.00 mpp[tiflash] table:t1 keep order:false"
+          "TableReader 6000.00 root  MppVersion: 3, data:ExchangeSender",
+          "└─ExchangeSender 6000.00 mpp[tiflash]  ExchangeType: PassThrough",
+          "  └─TableFullScan 6000.00 mpp[tiflash] table:t1 keep order:false"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select id from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
+        "SQL": "explain format = 'brief' select id from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
         "Plan": [
-          "TopN_11 10.00 root  Column#11, offset:0, count:10",
-          "└─TableReader_29 10.00 root  MppVersion: 3, data:ExchangeSender_28",
-          "  └─ExchangeSender_28 10.00 mpp[tiflash]  ExchangeType: PassThrough",
-          "    └─TopN_27 10.00 mpp[tiflash]  Column#11, offset:0, count:10",
-          "      └─TableFullScan_25 10.00 mpp[tiflash] table:t1, index:idx_embedding(vec) keep order:false, annIndex:COSINE(vec..[1,1,1], limit:10)->Column#11"
+          "TopN 10.00 root  Column#11, offset:0, count:10",
+          "└─TableReader 10.00 root  MppVersion: 3, data:ExchangeSender",
+          "  └─ExchangeSender 10.00 mpp[tiflash]  ExchangeType: PassThrough",
+          "    └─TopN 10.00 mpp[tiflash]  Column#11, offset:0, count:10",
+          "      └─TableFullScan 10.00 mpp[tiflash] table:t1, index:idx_embedding(vec) keep order:false, annIndex:COSINE(vec..[1,1,1], limit:10)->Column#11"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select id from t1 order by vec_cosine_distance(vec, '[1,1,1]')",
+        "SQL": "explain format = 'brief' select id from t1 order by vec_cosine_distance(vec, '[1,1,1]')",
         "Plan": [
-          "Projection_5 6000.00 root  test.t1.id",
-          "└─Projection_14 6000.00 root  test.t1.id, test.t1.vec",
-          "  └─Sort_7 6000.00 root  Column#8",
-          "    └─Projection_15 6000.00 root  test.t1.id, test.t1.vec, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#8",
-          "      └─TableReader_12 6000.00 root  MppVersion: 3, data:ExchangeSender_11",
-          "        └─ExchangeSender_11 6000.00 mpp[tiflash]  ExchangeType: PassThrough",
-          "          └─TableFullScan_10 6000.00 mpp[tiflash] table:t1 keep order:false"
+          "Projection 6000.00 root  test.t1.id",
+          "└─Projection 6000.00 root  test.t1.id, test.t1.vec",
+          "  └─Sort 6000.00 root  Column#8",
+          "    └─Projection 6000.00 root  test.t1.id, test.t1.vec, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#8",
+          "      └─TableReader 6000.00 root  MppVersion: 3, data:ExchangeSender",
+          "        └─ExchangeSender 6000.00 mpp[tiflash]  ExchangeType: PassThrough",
+          "          └─TableFullScan 6000.00 mpp[tiflash] table:t1 keep order:false"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select * from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
+        "SQL": "explain format = 'brief' select * from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
         "Plan": [
-          "TopN_10 10.00 root  Column#9, offset:0, count:10",
-          "└─TableReader_28 10.00 root  MppVersion: 3, data:ExchangeSender_27",
-          "  └─ExchangeSender_27 10.00 mpp[tiflash]  ExchangeType: PassThrough",
-          "    └─TopN_26 10.00 mpp[tiflash]  Column#9, offset:0, count:10",
-          "      └─Projection_25 10.00 mpp[tiflash]  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, test.t1.c, test.t1.d, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#9",
-          "        └─TableFullScan_24 10.00 mpp[tiflash] table:t1, index:idx_embedding(vec) keep order:false, annIndex:COSINE(vec..[1,1,1], limit:10)"
+          "TopN 10.00 root  Column#9, offset:0, count:10",
+          "└─TableReader 10.00 root  MppVersion: 3, data:ExchangeSender",
+          "  └─ExchangeSender 10.00 mpp[tiflash]  ExchangeType: PassThrough",
+          "    └─TopN 10.00 mpp[tiflash]  Column#9, offset:0, count:10",
+          "      └─Projection 10.00 mpp[tiflash]  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, test.t1.c, test.t1.d, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#9",
+          "        └─TableFullScan 10.00 mpp[tiflash] table:t1, index:idx_embedding(vec) keep order:false, annIndex:COSINE(vec..[1,1,1], limit:10)"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select id, a, b from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
+        "SQL": "explain format = 'brief' select id, a, b from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
         "Plan": [
-          "TopN_11 10.00 root  Column#13, offset:0, count:10",
-          "└─TableReader_29 10.00 root  MppVersion: 3, data:ExchangeSender_28",
-          "  └─ExchangeSender_28 10.00 mpp[tiflash]  ExchangeType: PassThrough",
-          "    └─TopN_27 10.00 mpp[tiflash]  Column#13, offset:0, count:10",
-          "      └─TableFullScan_25 10.00 mpp[tiflash] table:t1, index:idx_embedding(vec) keep order:false, annIndex:COSINE(vec..[1,1,1], limit:10)->Column#13"
+          "TopN 10.00 root  Column#13, offset:0, count:10",
+          "└─TableReader 10.00 root  MppVersion: 3, data:ExchangeSender",
+          "  └─ExchangeSender 10.00 mpp[tiflash]  ExchangeType: PassThrough",
+          "    └─TopN 10.00 mpp[tiflash]  Column#13, offset:0, count:10",
+          "      └─TableFullScan 10.00 mpp[tiflash] table:t1, index:idx_embedding(vec) keep order:false, annIndex:COSINE(vec..[1,1,1], limit:10)->Column#13"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select a, id, b from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
+        "SQL": "explain format = 'brief' select a, id, b from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
         "Plan": [
-          "Projection_7 10.00 root  test.t1.a, test.t1.id, test.t1.b",
-          "└─TopN_11 10.00 root  Column#13, offset:0, count:10",
-          "  └─TableReader_29 10.00 root  MppVersion: 3, data:ExchangeSender_28",
-          "    └─ExchangeSender_28 10.00 mpp[tiflash]  ExchangeType: PassThrough",
-          "      └─TopN_27 10.00 mpp[tiflash]  Column#13, offset:0, count:10",
-          "        └─TableFullScan_25 10.00 mpp[tiflash] table:t1, index:idx_embedding(vec) keep order:false, annIndex:COSINE(vec..[1,1,1], limit:10)->Column#13"
+          "Projection 10.00 root  test.t1.a, test.t1.id, test.t1.b",
+          "└─TopN 10.00 root  Column#13, offset:0, count:10",
+          "  └─TableReader 10.00 root  MppVersion: 3, data:ExchangeSender",
+          "    └─ExchangeSender 10.00 mpp[tiflash]  ExchangeType: PassThrough",
+          "      └─TopN 10.00 mpp[tiflash]  Column#13, offset:0, count:10",
+          "        └─TableFullScan 10.00 mpp[tiflash] table:t1, index:idx_embedding(vec) keep order:false, annIndex:COSINE(vec..[1,1,1], limit:10)->Column#13"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select id, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d limit 10",
+        "SQL": "explain format = 'brief' select id, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d limit 10",
         "Plan": [
-          "Projection_6 10.00 root  test.t1.id, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#7",
-          "└─TopN_10 10.00 root  Column#10, offset:0, count:10",
-          "  └─TableReader_28 10.00 root  MppVersion: 3, data:ExchangeSender_27",
-          "    └─ExchangeSender_27 10.00 mpp[tiflash]  ExchangeType: PassThrough",
-          "      └─TopN_26 10.00 mpp[tiflash]  Column#10, offset:0, count:10",
-          "        └─Projection_25 10.00 mpp[tiflash]  test.t1.id, test.t1.vec, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#10",
-          "          └─TableFullScan_24 10.00 mpp[tiflash] table:t1, index:idx_embedding(vec) keep order:false, annIndex:COSINE(vec..[1,1,1], limit:10)"
+          "Projection 10.00 root  test.t1.id, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#7",
+          "└─TopN 10.00 root  Column#10, offset:0, count:10",
+          "  └─TableReader 10.00 root  MppVersion: 3, data:ExchangeSender",
+          "    └─ExchangeSender 10.00 mpp[tiflash]  ExchangeType: PassThrough",
+          "      └─TopN 10.00 mpp[tiflash]  Column#10, offset:0, count:10",
+          "        └─Projection 10.00 mpp[tiflash]  test.t1.id, test.t1.vec, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#10",
+          "          └─TableFullScan 10.00 mpp[tiflash] table:t1, index:idx_embedding(vec) keep order:false, annIndex:COSINE(vec..[1,1,1], limit:10)"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select id, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d",
+        "SQL": "explain format = 'brief' select id, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d",
         "Plan": [
-          "Sort_4 6000.00 root  Column#7",
-          "└─TableReader_17 6000.00 root  MppVersion: 3, data:ExchangeSender_16",
-          "  └─ExchangeSender_16 6000.00 mpp[tiflash]  ExchangeType: PassThrough",
-          "    └─Projection_7 6000.00 mpp[tiflash]  test.t1.id, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#7",
-          "      └─TableFullScan_14 6000.00 mpp[tiflash] table:t1 keep order:false"
+          "Sort 6000.00 root  Column#7",
+          "└─TableReader 6000.00 root  MppVersion: 3, data:ExchangeSender",
+          "  └─ExchangeSender 6000.00 mpp[tiflash]  ExchangeType: PassThrough",
+          "    └─Projection 6000.00 mpp[tiflash]  test.t1.id, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#7",
+          "      └─TableFullScan 6000.00 mpp[tiflash] table:t1 keep order:false"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select *, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d limit 10",
+        "SQL": "explain format = 'brief' select *, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d limit 10",
         "Plan": [
-          "Projection_6 10.00 root  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, test.t1.c, test.t1.d, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#7",
-          "└─TopN_10 10.00 root  Column#10, offset:0, count:10",
-          "  └─TableReader_28 10.00 root  MppVersion: 3, data:ExchangeSender_27",
-          "    └─ExchangeSender_27 10.00 mpp[tiflash]  ExchangeType: PassThrough",
-          "      └─TopN_26 10.00 mpp[tiflash]  Column#10, offset:0, count:10",
-          "        └─Projection_25 10.00 mpp[tiflash]  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, test.t1.c, test.t1.d, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#10",
-          "          └─TableFullScan_24 10.00 mpp[tiflash] table:t1, index:idx_embedding(vec) keep order:false, annIndex:COSINE(vec..[1,1,1], limit:10)"
+          "Projection 10.00 root  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, test.t1.c, test.t1.d, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#7",
+          "└─TopN 10.00 root  Column#10, offset:0, count:10",
+          "  └─TableReader 10.00 root  MppVersion: 3, data:ExchangeSender",
+          "    └─ExchangeSender 10.00 mpp[tiflash]  ExchangeType: PassThrough",
+          "      └─TopN 10.00 mpp[tiflash]  Column#10, offset:0, count:10",
+          "        └─Projection 10.00 mpp[tiflash]  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, test.t1.c, test.t1.d, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#10",
+          "          └─TableFullScan 10.00 mpp[tiflash] table:t1, index:idx_embedding(vec) keep order:false, annIndex:COSINE(vec..[1,1,1], limit:10)"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select id, vec_cosine_distance(vec, '[1,1,1]') as d, a, b from t1 order by d limit 10",
+        "SQL": "explain format = 'brief' select id, vec_cosine_distance(vec, '[1,1,1]') as d, a, b from t1 order by d limit 10",
         "Plan": [
-          "Projection_6 10.00 root  test.t1.id, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#7, test.t1.a, test.t1.b",
-          "└─TopN_10 10.00 root  Column#10, offset:0, count:10",
-          "  └─TableReader_28 10.00 root  MppVersion: 3, data:ExchangeSender_27",
-          "    └─ExchangeSender_27 10.00 mpp[tiflash]  ExchangeType: PassThrough",
-          "      └─TopN_26 10.00 mpp[tiflash]  Column#10, offset:0, count:10",
-          "        └─Projection_25 10.00 mpp[tiflash]  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#10",
-          "          └─TableFullScan_24 10.00 mpp[tiflash] table:t1, index:idx_embedding(vec) keep order:false, annIndex:COSINE(vec..[1,1,1], limit:10)"
+          "Projection 10.00 root  test.t1.id, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#7, test.t1.a, test.t1.b",
+          "└─TopN 10.00 root  Column#10, offset:0, count:10",
+          "  └─TableReader 10.00 root  MppVersion: 3, data:ExchangeSender",
+          "    └─ExchangeSender 10.00 mpp[tiflash]  ExchangeType: PassThrough",
+          "      └─TopN 10.00 mpp[tiflash]  Column#10, offset:0, count:10",
+          "        └─Projection 10.00 mpp[tiflash]  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#10",
+          "          └─TableFullScan 10.00 mpp[tiflash] table:t1, index:idx_embedding(vec) keep order:false, annIndex:COSINE(vec..[1,1,1], limit:10)"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select id, a, b, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d limit 10",
+        "SQL": "explain format = 'brief' select id, a, b, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d limit 10",
         "Plan": [
-          "Projection_6 10.00 root  test.t1.id, test.t1.a, test.t1.b, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#7",
-          "└─TopN_10 10.00 root  Column#10, offset:0, count:10",
-          "  └─TableReader_28 10.00 root  MppVersion: 3, data:ExchangeSender_27",
-          "    └─ExchangeSender_27 10.00 mpp[tiflash]  ExchangeType: PassThrough",
-          "      └─TopN_26 10.00 mpp[tiflash]  Column#10, offset:0, count:10",
-          "        └─Projection_25 10.00 mpp[tiflash]  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#10",
-          "          └─TableFullScan_24 10.00 mpp[tiflash] table:t1, index:idx_embedding(vec) keep order:false, annIndex:COSINE(vec..[1,1,1], limit:10)"
+          "Projection 10.00 root  test.t1.id, test.t1.a, test.t1.b, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#7",
+          "└─TopN 10.00 root  Column#10, offset:0, count:10",
+          "  └─TableReader 10.00 root  MppVersion: 3, data:ExchangeSender",
+          "    └─ExchangeSender 10.00 mpp[tiflash]  ExchangeType: PassThrough",
+          "      └─TopN 10.00 mpp[tiflash]  Column#10, offset:0, count:10",
+          "        └─Projection 10.00 mpp[tiflash]  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#10",
+          "          └─TableFullScan 10.00 mpp[tiflash] table:t1, index:idx_embedding(vec) keep order:false, annIndex:COSINE(vec..[1,1,1], limit:10)"
         ],
         "Warn": null
       }
@@ -572,125 +572,125 @@
     "Name": "TestVectorSearchWithPKForceTiKV",
     "Cases": [
       {
-        "SQL": "explain select id from t1",
+        "SQL": "explain format = 'brief' select id from t1",
         "Plan": [
-          "TableReader_5 6000.00 root  data:TableFullScan_4",
-          "└─TableFullScan_4 6000.00 cop[tikv] table:t1 keep order:false"
+          "TableReader 6000.00 root  data:TableFullScan",
+          "└─TableFullScan 6000.00 cop[tikv] table:t1 keep order:false"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select id from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
+        "SQL": "explain format = 'brief' select id from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
         "Plan": [
-          "TopN_8 10.00 root  Column#8, offset:0, count:10",
-          "└─TableReader_15 10.00 root  data:TopN_14",
-          "  └─TopN_14 10.00 cop[tikv]  Column#8, offset:0, count:10",
-          "    └─Projection_13 10.00 cop[tikv]  test.t1.id, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#8",
-          "      └─TableFullScan_12 6000.00 cop[tikv] table:t1 keep order:false"
+          "TopN 10.00 root  Column#8, offset:0, count:10",
+          "└─TableReader 10.00 root  data:TopN",
+          "  └─TopN 10.00 cop[tikv]  Column#8, offset:0, count:10",
+          "    └─Projection 10.00 cop[tikv]  test.t1.id, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#8",
+          "      └─TableFullScan 6000.00 cop[tikv] table:t1 keep order:false"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select id from t1 order by vec_cosine_distance(vec, '[1,1,1]')",
+        "SQL": "explain format = 'brief' select id from t1 order by vec_cosine_distance(vec, '[1,1,1]')",
         "Plan": [
-          "Projection_5 6000.00 root  test.t1.id",
-          "└─Projection_9 6000.00 root  test.t1.id, test.t1.vec",
-          "  └─Sort_6 6000.00 root  Column#8",
-          "    └─Projection_10 6000.00 root  test.t1.id, test.t1.vec, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#8",
-          "      └─TableReader_8 6000.00 root  data:TableFullScan_7",
-          "        └─TableFullScan_7 6000.00 cop[tikv] table:t1 keep order:false"
+          "Projection 6000.00 root  test.t1.id",
+          "└─Projection 6000.00 root  test.t1.id, test.t1.vec",
+          "  └─Sort 6000.00 root  Column#8",
+          "    └─Projection 6000.00 root  test.t1.id, test.t1.vec, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#8",
+          "      └─TableReader 6000.00 root  data:TableFullScan",
+          "        └─TableFullScan 6000.00 cop[tikv] table:t1 keep order:false"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select * from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
+        "SQL": "explain format = 'brief' select * from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
         "Plan": [
-          "TopN_7 10.00 root  Column#7, offset:0, count:10",
-          "└─TableReader_14 10.00 root  data:TopN_13",
-          "  └─TopN_13 10.00 cop[tikv]  Column#7, offset:0, count:10",
-          "    └─Projection_12 10.00 cop[tikv]  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, test.t1.c, test.t1.d, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#7",
-          "      └─TableFullScan_11 6000.00 cop[tikv] table:t1 keep order:false"
+          "TopN 10.00 root  Column#7, offset:0, count:10",
+          "└─TableReader 10.00 root  data:TopN",
+          "  └─TopN 10.00 cop[tikv]  Column#7, offset:0, count:10",
+          "    └─Projection 10.00 cop[tikv]  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, test.t1.c, test.t1.d, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#7",
+          "      └─TableFullScan 6000.00 cop[tikv] table:t1 keep order:false"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select id, a, b from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
+        "SQL": "explain format = 'brief' select id, a, b from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
         "Plan": [
-          "TopN_8 10.00 root  Column#10, offset:0, count:10",
-          "└─TableReader_15 10.00 root  data:TopN_14",
-          "  └─TopN_14 10.00 cop[tikv]  Column#10, offset:0, count:10",
-          "    └─Projection_13 10.00 cop[tikv]  test.t1.id, test.t1.a, test.t1.b, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#10",
-          "      └─TableFullScan_12 6000.00 cop[tikv] table:t1 keep order:false"
+          "TopN 10.00 root  Column#10, offset:0, count:10",
+          "└─TableReader 10.00 root  data:TopN",
+          "  └─TopN 10.00 cop[tikv]  Column#10, offset:0, count:10",
+          "    └─Projection 10.00 cop[tikv]  test.t1.id, test.t1.a, test.t1.b, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#10",
+          "      └─TableFullScan 6000.00 cop[tikv] table:t1 keep order:false"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select a, id, b from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
+        "SQL": "explain format = 'brief' select a, id, b from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
         "Plan": [
-          "Projection_7 10.00 root  test.t1.a, test.t1.id, test.t1.b",
-          "└─TopN_8 10.00 root  Column#10, offset:0, count:10",
-          "  └─TableReader_15 10.00 root  data:TopN_14",
-          "    └─TopN_14 10.00 cop[tikv]  Column#10, offset:0, count:10",
-          "      └─Projection_13 10.00 cop[tikv]  test.t1.id, test.t1.a, test.t1.b, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#10",
-          "        └─TableFullScan_12 6000.00 cop[tikv] table:t1 keep order:false"
+          "Projection 10.00 root  test.t1.a, test.t1.id, test.t1.b",
+          "└─TopN 10.00 root  Column#10, offset:0, count:10",
+          "  └─TableReader 10.00 root  data:TopN",
+          "    └─TopN 10.00 cop[tikv]  Column#10, offset:0, count:10",
+          "      └─Projection 10.00 cop[tikv]  test.t1.id, test.t1.a, test.t1.b, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#10",
+          "        └─TableFullScan 6000.00 cop[tikv] table:t1 keep order:false"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select id, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d limit 10",
+        "SQL": "explain format = 'brief' select id, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d limit 10",
         "Plan": [
-          "Projection_6 10.00 root  test.t1.id, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#7",
-          "└─TopN_7 10.00 root  Column#8, offset:0, count:10",
-          "  └─TableReader_14 10.00 root  data:TopN_13",
-          "    └─TopN_13 10.00 cop[tikv]  Column#8, offset:0, count:10",
-          "      └─Projection_12 10.00 cop[tikv]  test.t1.id, test.t1.vec, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#8",
-          "        └─TableFullScan_11 6000.00 cop[tikv] table:t1 keep order:false"
+          "Projection 10.00 root  test.t1.id, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#7",
+          "└─TopN 10.00 root  Column#8, offset:0, count:10",
+          "  └─TableReader 10.00 root  data:TopN",
+          "    └─TopN 10.00 cop[tikv]  Column#8, offset:0, count:10",
+          "      └─Projection 10.00 cop[tikv]  test.t1.id, test.t1.vec, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#8",
+          "        └─TableFullScan 6000.00 cop[tikv] table:t1 keep order:false"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select id, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d",
+        "SQL": "explain format = 'brief' select id, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d",
         "Plan": [
-          "Sort_4 6000.00 root  Column#7",
-          "└─Projection_6 6000.00 root  test.t1.id, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#7",
-          "  └─TableReader_8 6000.00 root  data:TableFullScan_7",
-          "    └─TableFullScan_7 6000.00 cop[tikv] table:t1 keep order:false"
+          "Sort 6000.00 root  Column#7",
+          "└─Projection 6000.00 root  test.t1.id, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#7",
+          "  └─TableReader 6000.00 root  data:TableFullScan",
+          "    └─TableFullScan 6000.00 cop[tikv] table:t1 keep order:false"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select *, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d limit 10",
+        "SQL": "explain format = 'brief' select *, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d limit 10",
         "Plan": [
-          "Projection_6 10.00 root  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, test.t1.c, test.t1.d, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#7",
-          "└─TopN_7 10.00 root  Column#8, offset:0, count:10",
-          "  └─TableReader_14 10.00 root  data:TopN_13",
-          "    └─TopN_13 10.00 cop[tikv]  Column#8, offset:0, count:10",
-          "      └─Projection_12 10.00 cop[tikv]  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, test.t1.c, test.t1.d, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#8",
-          "        └─TableFullScan_11 6000.00 cop[tikv] table:t1 keep order:false"
+          "Projection 10.00 root  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, test.t1.c, test.t1.d, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#7",
+          "└─TopN 10.00 root  Column#8, offset:0, count:10",
+          "  └─TableReader 10.00 root  data:TopN",
+          "    └─TopN 10.00 cop[tikv]  Column#8, offset:0, count:10",
+          "      └─Projection 10.00 cop[tikv]  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, test.t1.c, test.t1.d, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#8",
+          "        └─TableFullScan 6000.00 cop[tikv] table:t1 keep order:false"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select id, vec_cosine_distance(vec, '[1,1,1]') as d, a, b from t1 order by d limit 10",
+        "SQL": "explain format = 'brief' select id, vec_cosine_distance(vec, '[1,1,1]') as d, a, b from t1 order by d limit 10",
         "Plan": [
-          "Projection_6 10.00 root  test.t1.id, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#7, test.t1.a, test.t1.b",
-          "└─TopN_7 10.00 root  Column#8, offset:0, count:10",
-          "  └─TableReader_14 10.00 root  data:TopN_13",
-          "    └─TopN_13 10.00 cop[tikv]  Column#8, offset:0, count:10",
-          "      └─Projection_12 10.00 cop[tikv]  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#8",
-          "        └─TableFullScan_11 6000.00 cop[tikv] table:t1 keep order:false"
+          "Projection 10.00 root  test.t1.id, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#7, test.t1.a, test.t1.b",
+          "└─TopN 10.00 root  Column#8, offset:0, count:10",
+          "  └─TableReader 10.00 root  data:TopN",
+          "    └─TopN 10.00 cop[tikv]  Column#8, offset:0, count:10",
+          "      └─Projection 10.00 cop[tikv]  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#8",
+          "        └─TableFullScan 6000.00 cop[tikv] table:t1 keep order:false"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select id, a, b, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d limit 10",
+        "SQL": "explain format = 'brief' select id, a, b, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d limit 10",
         "Plan": [
-          "Projection_6 10.00 root  test.t1.id, test.t1.a, test.t1.b, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#7",
-          "└─TopN_7 10.00 root  Column#8, offset:0, count:10",
-          "  └─TableReader_14 10.00 root  data:TopN_13",
-          "    └─TopN_13 10.00 cop[tikv]  Column#8, offset:0, count:10",
-          "      └─Projection_12 10.00 cop[tikv]  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#8",
-          "        └─TableFullScan_11 6000.00 cop[tikv] table:t1 keep order:false"
+          "Projection 10.00 root  test.t1.id, test.t1.a, test.t1.b, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#7",
+          "└─TopN 10.00 root  Column#8, offset:0, count:10",
+          "  └─TableReader 10.00 root  data:TopN",
+          "    └─TopN 10.00 cop[tikv]  Column#8, offset:0, count:10",
+          "      └─Projection 10.00 cop[tikv]  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#8",
+          "        └─TableFullScan 6000.00 cop[tikv] table:t1 keep order:false"
         ],
         "Warn": null
       }
@@ -700,272 +700,272 @@
     "Name": "TestVectorSearchHeavyFunction",
     "Cases": [
       {
-        "SQL": "explain select id from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
+        "SQL": "explain format = 'brief' select id from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
         "Plan": [
-          "TopN_11 10.00 root  Column#11, offset:0, count:10",
-          "└─TableReader_29 10.00 root  MppVersion: 3, data:ExchangeSender_28",
-          "  └─ExchangeSender_28 10.00 mpp[tiflash]  ExchangeType: PassThrough",
-          "    └─TopN_27 10.00 mpp[tiflash]  Column#11, offset:0, count:10",
-          "      └─TableFullScan_25 10.00 mpp[tiflash] table:t1, index:idx_embedding(vec) keep order:false, annIndex:COSINE(vec..[1,1,1], limit:10)->Column#11"
+          "TopN 10.00 root  Column#11, offset:0, count:10",
+          "└─TableReader 10.00 root  MppVersion: 3, data:ExchangeSender",
+          "  └─ExchangeSender 10.00 mpp[tiflash]  ExchangeType: PassThrough",
+          "    └─TopN 10.00 mpp[tiflash]  Column#11, offset:0, count:10",
+          "      └─TableFullScan 10.00 mpp[tiflash] table:t1, index:idx_embedding(vec) keep order:false, annIndex:COSINE(vec..[1,1,1], limit:10)->Column#11"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select id from t1 order by vec_l1_distance(vec, '[1,1,1]') limit 10",
+        "SQL": "explain format = 'brief' select id from t1 order by vec_l1_distance(vec, '[1,1,1]') limit 10",
         "Plan": [
-          "TopN_10 10.00 root  Column#9, offset:0, count:10",
-          "└─TableReader_23 10.00 root  MppVersion: 3, data:ExchangeSender_22",
-          "  └─ExchangeSender_22 10.00 mpp[tiflash]  ExchangeType: PassThrough",
-          "    └─TopN_21 10.00 mpp[tiflash]  Column#9, offset:0, count:10",
-          "      └─Projection_20 10.00 mpp[tiflash]  test.t1.id, vec_l1_distance(test.t1.vec, [1,1,1])->Column#9",
-          "        └─TableFullScan_18 6000.00 mpp[tiflash] table:t1 keep order:false"
+          "TopN 10.00 root  Column#9, offset:0, count:10",
+          "└─TableReader 10.00 root  MppVersion: 3, data:ExchangeSender",
+          "  └─ExchangeSender 10.00 mpp[tiflash]  ExchangeType: PassThrough",
+          "    └─TopN 10.00 mpp[tiflash]  Column#9, offset:0, count:10",
+          "      └─Projection 10.00 mpp[tiflash]  test.t1.id, vec_l1_distance(test.t1.vec, [1,1,1])->Column#9",
+          "        └─TableFullScan 6000.00 mpp[tiflash] table:t1 keep order:false"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select id from t1 order by vec_l2_distance(vec, '[1,1,1]') limit 10",
+        "SQL": "explain format = 'brief' select id from t1 order by vec_l2_distance(vec, '[1,1,1]') limit 10",
         "Plan": [
-          "TopN_10 10.00 root  Column#9, offset:0, count:10",
-          "└─TableReader_23 10.00 root  MppVersion: 3, data:ExchangeSender_22",
-          "  └─ExchangeSender_22 10.00 mpp[tiflash]  ExchangeType: PassThrough",
-          "    └─TopN_21 10.00 mpp[tiflash]  Column#9, offset:0, count:10",
-          "      └─Projection_20 10.00 mpp[tiflash]  test.t1.id, vec_l2_distance(test.t1.vec, [1,1,1])->Column#9",
-          "        └─TableFullScan_18 6000.00 mpp[tiflash] table:t1 keep order:false"
+          "TopN 10.00 root  Column#9, offset:0, count:10",
+          "└─TableReader 10.00 root  MppVersion: 3, data:ExchangeSender",
+          "  └─ExchangeSender 10.00 mpp[tiflash]  ExchangeType: PassThrough",
+          "    └─TopN 10.00 mpp[tiflash]  Column#9, offset:0, count:10",
+          "      └─Projection 10.00 mpp[tiflash]  test.t1.id, vec_l2_distance(test.t1.vec, [1,1,1])->Column#9",
+          "        └─TableFullScan 6000.00 mpp[tiflash] table:t1 keep order:false"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select id from t1 order by vec_negative_inner_product(vec, '[1,1,1]') limit 10",
+        "SQL": "explain format = 'brief' select id from t1 order by vec_negative_inner_product(vec, '[1,1,1]') limit 10",
         "Plan": [
-          "TopN_10 10.00 root  Column#9, offset:0, count:10",
-          "└─TableReader_23 10.00 root  MppVersion: 3, data:ExchangeSender_22",
-          "  └─ExchangeSender_22 10.00 mpp[tiflash]  ExchangeType: PassThrough",
-          "    └─TopN_21 10.00 mpp[tiflash]  Column#9, offset:0, count:10",
-          "      └─Projection_20 10.00 mpp[tiflash]  test.t1.id, vec_negative_inner_product(test.t1.vec, [1,1,1])->Column#9",
-          "        └─TableFullScan_18 6000.00 mpp[tiflash] table:t1 keep order:false"
+          "TopN 10.00 root  Column#9, offset:0, count:10",
+          "└─TableReader 10.00 root  MppVersion: 3, data:ExchangeSender",
+          "  └─ExchangeSender 10.00 mpp[tiflash]  ExchangeType: PassThrough",
+          "    └─TopN 10.00 mpp[tiflash]  Column#9, offset:0, count:10",
+          "      └─Projection 10.00 mpp[tiflash]  test.t1.id, vec_negative_inner_product(test.t1.vec, [1,1,1])->Column#9",
+          "        └─TableFullScan 6000.00 mpp[tiflash] table:t1 keep order:false"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select id from t1 order by vec_dims(vec) limit 10",
+        "SQL": "explain format = 'brief' select id from t1 order by vec_dims(vec) limit 10",
         "Plan": [
-          "TopN_10 10.00 root  Column#9, offset:0, count:10",
-          "└─TableReader_22 10.00 root  MppVersion: 3, data:ExchangeSender_21",
-          "  └─ExchangeSender_21 10.00 mpp[tiflash]  ExchangeType: PassThrough",
-          "    └─TopN_20 10.00 mpp[tiflash]  Column#9, offset:0, count:10",
-          "      └─Projection_19 10.00 mpp[tiflash]  test.t1.id, vec_dims(test.t1.vec)->Column#9",
-          "        └─TableFullScan_17 6000.00 mpp[tiflash] table:t1 keep order:false"
+          "TopN 10.00 root  Column#9, offset:0, count:10",
+          "└─TableReader 10.00 root  MppVersion: 3, data:ExchangeSender",
+          "  └─ExchangeSender 10.00 mpp[tiflash]  ExchangeType: PassThrough",
+          "    └─TopN 10.00 mpp[tiflash]  Column#9, offset:0, count:10",
+          "      └─Projection 10.00 mpp[tiflash]  test.t1.id, vec_dims(test.t1.vec)->Column#9",
+          "        └─TableFullScan 6000.00 mpp[tiflash] table:t1 keep order:false"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select id from t1 order by vec_l2_norm(vec) limit 10",
+        "SQL": "explain format = 'brief' select id from t1 order by vec_l2_norm(vec) limit 10",
         "Plan": [
-          "TopN_10 10.00 root  Column#9, offset:0, count:10",
-          "└─TableReader_22 10.00 root  MppVersion: 3, data:ExchangeSender_21",
-          "  └─ExchangeSender_21 10.00 mpp[tiflash]  ExchangeType: PassThrough",
-          "    └─TopN_20 10.00 mpp[tiflash]  Column#9, offset:0, count:10",
-          "      └─Projection_19 10.00 mpp[tiflash]  test.t1.id, vec_l2_norm(test.t1.vec)->Column#9",
-          "        └─TableFullScan_17 6000.00 mpp[tiflash] table:t1 keep order:false"
+          "TopN 10.00 root  Column#9, offset:0, count:10",
+          "└─TableReader 10.00 root  MppVersion: 3, data:ExchangeSender",
+          "  └─ExchangeSender 10.00 mpp[tiflash]  ExchangeType: PassThrough",
+          "    └─TopN 10.00 mpp[tiflash]  Column#9, offset:0, count:10",
+          "      └─Projection 10.00 mpp[tiflash]  test.t1.id, vec_l2_norm(test.t1.vec)->Column#9",
+          "        └─TableFullScan 6000.00 mpp[tiflash] table:t1 keep order:false"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select id from t1 order by MOD(a, 3) limit 10",
+        "SQL": "explain format = 'brief' select id from t1 order by MOD(a, 3) limit 10",
         "Plan": [
-          "Projection_23 10.00 root  test.t1.id",
-          "└─TopN_10 10.00 root  Column#9, offset:0, count:10",
-          "  └─Projection_24 10.00 root  test.t1.id, test.t1.a, mod(test.t1.a, 3)->Column#9",
-          "    └─TableReader_20 10.00 root  MppVersion: 3, data:ExchangeSender_19",
-          "      └─ExchangeSender_19 10.00 mpp[tiflash]  ExchangeType: PassThrough",
-          "        └─Projection_21 10.00 mpp[tiflash]  test.t1.id, test.t1.a",
-          "          └─TopN_18 10.00 mpp[tiflash]  Column#8, offset:0, count:10",
-          "            └─Projection_22 6000.00 mpp[tiflash]  test.t1.id, test.t1.a, mod(test.t1.a, 3)->Column#8",
-          "              └─TableFullScan_16 6000.00 mpp[tiflash] table:t1 keep order:false"
+          "Projection 10.00 root  test.t1.id",
+          "└─TopN 10.00 root  Column#9, offset:0, count:10",
+          "  └─Projection 10.00 root  test.t1.id, test.t1.a, mod(test.t1.a, 3)->Column#9",
+          "    └─TableReader 10.00 root  MppVersion: 3, data:ExchangeSender",
+          "      └─ExchangeSender 10.00 mpp[tiflash]  ExchangeType: PassThrough",
+          "        └─Projection 10.00 mpp[tiflash]  test.t1.id, test.t1.a",
+          "          └─TopN 10.00 mpp[tiflash]  Column#8, offset:0, count:10",
+          "            └─Projection 6000.00 mpp[tiflash]  test.t1.id, test.t1.a, mod(test.t1.a, 3)->Column#8",
+          "              └─TableFullScan 6000.00 mpp[tiflash] table:t1 keep order:false"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select id, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d limit 10",
+        "SQL": "explain format = 'brief' select id, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d limit 10",
         "Plan": [
-          "Projection_6 10.00 root  test.t1.id, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#7",
-          "└─TopN_10 10.00 root  Column#10, offset:0, count:10",
-          "  └─TableReader_28 10.00 root  MppVersion: 3, data:ExchangeSender_27",
-          "    └─ExchangeSender_27 10.00 mpp[tiflash]  ExchangeType: PassThrough",
-          "      └─TopN_26 10.00 mpp[tiflash]  Column#10, offset:0, count:10",
-          "        └─Projection_25 10.00 mpp[tiflash]  test.t1.id, test.t1.vec, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#10",
-          "          └─TableFullScan_24 10.00 mpp[tiflash] table:t1, index:idx_embedding(vec) keep order:false, annIndex:COSINE(vec..[1,1,1], limit:10)"
+          "Projection 10.00 root  test.t1.id, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#7",
+          "└─TopN 10.00 root  Column#10, offset:0, count:10",
+          "  └─TableReader 10.00 root  MppVersion: 3, data:ExchangeSender",
+          "    └─ExchangeSender 10.00 mpp[tiflash]  ExchangeType: PassThrough",
+          "      └─TopN 10.00 mpp[tiflash]  Column#10, offset:0, count:10",
+          "        └─Projection 10.00 mpp[tiflash]  test.t1.id, test.t1.vec, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#10",
+          "          └─TableFullScan 10.00 mpp[tiflash] table:t1, index:idx_embedding(vec) keep order:false, annIndex:COSINE(vec..[1,1,1], limit:10)"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select id, vec_l1_distance(vec, '[1,1,1]') as d from t1 order by d limit 10",
+        "SQL": "explain format = 'brief' select id, vec_l1_distance(vec, '[1,1,1]') as d from t1 order by d limit 10",
         "Plan": [
-          "Projection_6 10.00 root  test.t1.id, vec_l1_distance(test.t1.vec, [1,1,1])->Column#7",
-          "└─TopN_9 10.00 root  Column#9, offset:0, count:10",
-          "  └─TableReader_22 10.00 root  MppVersion: 3, data:ExchangeSender_21",
-          "    └─ExchangeSender_21 10.00 mpp[tiflash]  ExchangeType: PassThrough",
-          "      └─TopN_20 10.00 mpp[tiflash]  Column#9, offset:0, count:10",
-          "        └─Projection_19 10.00 mpp[tiflash]  test.t1.id, test.t1.vec, vec_l1_distance(test.t1.vec, [1,1,1])->Column#9",
-          "          └─TableFullScan_17 6000.00 mpp[tiflash] table:t1 keep order:false"
+          "Projection 10.00 root  test.t1.id, vec_l1_distance(test.t1.vec, [1,1,1])->Column#7",
+          "└─TopN 10.00 root  Column#9, offset:0, count:10",
+          "  └─TableReader 10.00 root  MppVersion: 3, data:ExchangeSender",
+          "    └─ExchangeSender 10.00 mpp[tiflash]  ExchangeType: PassThrough",
+          "      └─TopN 10.00 mpp[tiflash]  Column#9, offset:0, count:10",
+          "        └─Projection 10.00 mpp[tiflash]  test.t1.id, test.t1.vec, vec_l1_distance(test.t1.vec, [1,1,1])->Column#9",
+          "          └─TableFullScan 6000.00 mpp[tiflash] table:t1 keep order:false"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select id, vec_l2_distance(vec, '[1,1,1]') as d from t1 order by d limit 10",
+        "SQL": "explain format = 'brief' select id, vec_l2_distance(vec, '[1,1,1]') as d from t1 order by d limit 10",
         "Plan": [
-          "Projection_6 10.00 root  test.t1.id, vec_l2_distance(test.t1.vec, [1,1,1])->Column#7",
-          "└─TopN_9 10.00 root  Column#9, offset:0, count:10",
-          "  └─TableReader_22 10.00 root  MppVersion: 3, data:ExchangeSender_21",
-          "    └─ExchangeSender_21 10.00 mpp[tiflash]  ExchangeType: PassThrough",
-          "      └─TopN_20 10.00 mpp[tiflash]  Column#9, offset:0, count:10",
-          "        └─Projection_19 10.00 mpp[tiflash]  test.t1.id, test.t1.vec, vec_l2_distance(test.t1.vec, [1,1,1])->Column#9",
-          "          └─TableFullScan_17 6000.00 mpp[tiflash] table:t1 keep order:false"
+          "Projection 10.00 root  test.t1.id, vec_l2_distance(test.t1.vec, [1,1,1])->Column#7",
+          "└─TopN 10.00 root  Column#9, offset:0, count:10",
+          "  └─TableReader 10.00 root  MppVersion: 3, data:ExchangeSender",
+          "    └─ExchangeSender 10.00 mpp[tiflash]  ExchangeType: PassThrough",
+          "      └─TopN 10.00 mpp[tiflash]  Column#9, offset:0, count:10",
+          "        └─Projection 10.00 mpp[tiflash]  test.t1.id, test.t1.vec, vec_l2_distance(test.t1.vec, [1,1,1])->Column#9",
+          "          └─TableFullScan 6000.00 mpp[tiflash] table:t1 keep order:false"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select id, vec_negative_inner_product(vec, '[1,1,1]') as d from t1 order by d limit 10",
+        "SQL": "explain format = 'brief' select id, vec_negative_inner_product(vec, '[1,1,1]') as d from t1 order by d limit 10",
         "Plan": [
-          "Projection_6 10.00 root  test.t1.id, vec_negative_inner_product(test.t1.vec, [1,1,1])->Column#7",
-          "└─TopN_9 10.00 root  Column#9, offset:0, count:10",
-          "  └─TableReader_22 10.00 root  MppVersion: 3, data:ExchangeSender_21",
-          "    └─ExchangeSender_21 10.00 mpp[tiflash]  ExchangeType: PassThrough",
-          "      └─TopN_20 10.00 mpp[tiflash]  Column#9, offset:0, count:10",
-          "        └─Projection_19 10.00 mpp[tiflash]  test.t1.id, test.t1.vec, vec_negative_inner_product(test.t1.vec, [1,1,1])->Column#9",
-          "          └─TableFullScan_17 6000.00 mpp[tiflash] table:t1 keep order:false"
+          "Projection 10.00 root  test.t1.id, vec_negative_inner_product(test.t1.vec, [1,1,1])->Column#7",
+          "└─TopN 10.00 root  Column#9, offset:0, count:10",
+          "  └─TableReader 10.00 root  MppVersion: 3, data:ExchangeSender",
+          "    └─ExchangeSender 10.00 mpp[tiflash]  ExchangeType: PassThrough",
+          "      └─TopN 10.00 mpp[tiflash]  Column#9, offset:0, count:10",
+          "        └─Projection 10.00 mpp[tiflash]  test.t1.id, test.t1.vec, vec_negative_inner_product(test.t1.vec, [1,1,1])->Column#9",
+          "          └─TableFullScan 6000.00 mpp[tiflash] table:t1 keep order:false"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select id, vec_dims(vec) as d from t1 order by d limit 10",
+        "SQL": "explain format = 'brief' select id, vec_dims(vec) as d from t1 order by d limit 10",
         "Plan": [
-          "Projection_6 10.00 root  test.t1.id, vec_dims(test.t1.vec)->Column#7",
-          "└─TopN_9 10.00 root  Column#9, offset:0, count:10",
-          "  └─TableReader_21 10.00 root  MppVersion: 3, data:ExchangeSender_20",
-          "    └─ExchangeSender_20 10.00 mpp[tiflash]  ExchangeType: PassThrough",
-          "      └─TopN_19 10.00 mpp[tiflash]  Column#9, offset:0, count:10",
-          "        └─Projection_18 10.00 mpp[tiflash]  test.t1.id, test.t1.vec, vec_dims(test.t1.vec)->Column#9",
-          "          └─TableFullScan_16 6000.00 mpp[tiflash] table:t1 keep order:false"
+          "Projection 10.00 root  test.t1.id, vec_dims(test.t1.vec)->Column#7",
+          "└─TopN 10.00 root  Column#9, offset:0, count:10",
+          "  └─TableReader 10.00 root  MppVersion: 3, data:ExchangeSender",
+          "    └─ExchangeSender 10.00 mpp[tiflash]  ExchangeType: PassThrough",
+          "      └─TopN 10.00 mpp[tiflash]  Column#9, offset:0, count:10",
+          "        └─Projection 10.00 mpp[tiflash]  test.t1.id, test.t1.vec, vec_dims(test.t1.vec)->Column#9",
+          "          └─TableFullScan 6000.00 mpp[tiflash] table:t1 keep order:false"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select id, vec_l2_norm(vec) as d from t1 order by d limit 10",
+        "SQL": "explain format = 'brief' select id, vec_l2_norm(vec) as d from t1 order by d limit 10",
         "Plan": [
-          "Projection_6 10.00 root  test.t1.id, vec_l2_norm(test.t1.vec)->Column#7",
-          "└─TopN_9 10.00 root  Column#9, offset:0, count:10",
-          "  └─TableReader_21 10.00 root  MppVersion: 3, data:ExchangeSender_20",
-          "    └─ExchangeSender_20 10.00 mpp[tiflash]  ExchangeType: PassThrough",
-          "      └─TopN_19 10.00 mpp[tiflash]  Column#9, offset:0, count:10",
-          "        └─Projection_18 10.00 mpp[tiflash]  test.t1.id, test.t1.vec, vec_l2_norm(test.t1.vec)->Column#9",
-          "          └─TableFullScan_16 6000.00 mpp[tiflash] table:t1 keep order:false"
+          "Projection 10.00 root  test.t1.id, vec_l2_norm(test.t1.vec)->Column#7",
+          "└─TopN 10.00 root  Column#9, offset:0, count:10",
+          "  └─TableReader 10.00 root  MppVersion: 3, data:ExchangeSender",
+          "    └─ExchangeSender 10.00 mpp[tiflash]  ExchangeType: PassThrough",
+          "      └─TopN 10.00 mpp[tiflash]  Column#9, offset:0, count:10",
+          "        └─Projection 10.00 mpp[tiflash]  test.t1.id, test.t1.vec, vec_l2_norm(test.t1.vec)->Column#9",
+          "          └─TableFullScan 6000.00 mpp[tiflash] table:t1 keep order:false"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select id, MOD(a, 3) as d from t1 order by d limit 10",
+        "SQL": "explain format = 'brief' select id, MOD(a, 3) as d from t1 order by d limit 10",
         "Plan": [
-          "Projection_6 10.00 root  test.t1.id, mod(test.t1.a, 3)->Column#7",
-          "└─Projection_22 10.00 root  test.t1.id, test.t1.a",
-          "  └─TopN_9 10.00 root  Column#9, offset:0, count:10",
-          "    └─Projection_23 10.00 root  test.t1.id, test.t1.a, mod(test.t1.a, 3)->Column#9",
-          "      └─TableReader_19 10.00 root  MppVersion: 3, data:ExchangeSender_18",
-          "        └─ExchangeSender_18 10.00 mpp[tiflash]  ExchangeType: PassThrough",
-          "          └─Projection_20 10.00 mpp[tiflash]  test.t1.id, test.t1.a",
-          "            └─TopN_17 10.00 mpp[tiflash]  Column#8, offset:0, count:10",
-          "              └─Projection_21 6000.00 mpp[tiflash]  test.t1.id, test.t1.a, mod(test.t1.a, 3)->Column#8",
-          "                └─TableFullScan_15 6000.00 mpp[tiflash] table:t1 keep order:false"
+          "Projection 10.00 root  test.t1.id, mod(test.t1.a, 3)->Column#7",
+          "└─Projection 10.00 root  test.t1.id, test.t1.a",
+          "  └─TopN 10.00 root  Column#9, offset:0, count:10",
+          "    └─Projection 10.00 root  test.t1.id, test.t1.a, mod(test.t1.a, 3)->Column#9",
+          "      └─TableReader 10.00 root  MppVersion: 3, data:ExchangeSender",
+          "        └─ExchangeSender 10.00 mpp[tiflash]  ExchangeType: PassThrough",
+          "          └─Projection 10.00 mpp[tiflash]  test.t1.id, test.t1.a",
+          "            └─TopN 10.00 mpp[tiflash]  Column#8, offset:0, count:10",
+          "              └─Projection 6000.00 mpp[tiflash]  test.t1.id, test.t1.a, mod(test.t1.a, 3)->Column#8",
+          "                └─TableFullScan 6000.00 mpp[tiflash] table:t1 keep order:false"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select * from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
+        "SQL": "explain format = 'brief' select * from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
         "Plan": [
-          "TopN_10 10.00 root  Column#9, offset:0, count:10",
-          "└─TableReader_28 10.00 root  MppVersion: 3, data:ExchangeSender_27",
-          "  └─ExchangeSender_27 10.00 mpp[tiflash]  ExchangeType: PassThrough",
-          "    └─TopN_26 10.00 mpp[tiflash]  Column#9, offset:0, count:10",
-          "      └─Projection_25 10.00 mpp[tiflash]  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, test.t1.c, test.t1.d, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#9",
-          "        └─TableFullScan_24 10.00 mpp[tiflash] table:t1, index:idx_embedding(vec) keep order:false, annIndex:COSINE(vec..[1,1,1], limit:10)"
+          "TopN 10.00 root  Column#9, offset:0, count:10",
+          "└─TableReader 10.00 root  MppVersion: 3, data:ExchangeSender",
+          "  └─ExchangeSender 10.00 mpp[tiflash]  ExchangeType: PassThrough",
+          "    └─TopN 10.00 mpp[tiflash]  Column#9, offset:0, count:10",
+          "      └─Projection 10.00 mpp[tiflash]  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, test.t1.c, test.t1.d, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#9",
+          "        └─TableFullScan 10.00 mpp[tiflash] table:t1, index:idx_embedding(vec) keep order:false, annIndex:COSINE(vec..[1,1,1], limit:10)"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select * from t1 order by vec_l1_distance(vec, '[1,1,1]') limit 10",
+        "SQL": "explain format = 'brief' select * from t1 order by vec_l1_distance(vec, '[1,1,1]') limit 10",
         "Plan": [
-          "TopN_9 10.00 root  Column#8, offset:0, count:10",
-          "└─TableReader_22 10.00 root  MppVersion: 3, data:ExchangeSender_21",
-          "  └─ExchangeSender_21 10.00 mpp[tiflash]  ExchangeType: PassThrough",
-          "    └─TopN_20 10.00 mpp[tiflash]  Column#8, offset:0, count:10",
-          "      └─Projection_19 10.00 mpp[tiflash]  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, test.t1.c, test.t1.d, vec_l1_distance(test.t1.vec, [1,1,1])->Column#8",
-          "        └─TableFullScan_17 6000.00 mpp[tiflash] table:t1 keep order:false"
+          "TopN 10.00 root  Column#8, offset:0, count:10",
+          "└─TableReader 10.00 root  MppVersion: 3, data:ExchangeSender",
+          "  └─ExchangeSender 10.00 mpp[tiflash]  ExchangeType: PassThrough",
+          "    └─TopN 10.00 mpp[tiflash]  Column#8, offset:0, count:10",
+          "      └─Projection 10.00 mpp[tiflash]  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, test.t1.c, test.t1.d, vec_l1_distance(test.t1.vec, [1,1,1])->Column#8",
+          "        └─TableFullScan 6000.00 mpp[tiflash] table:t1 keep order:false"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select * from t1 order by vec_l2_distance(vec, '[1,1,1]') limit 10",
+        "SQL": "explain format = 'brief' select * from t1 order by vec_l2_distance(vec, '[1,1,1]') limit 10",
         "Plan": [
-          "TopN_9 10.00 root  Column#8, offset:0, count:10",
-          "└─TableReader_22 10.00 root  MppVersion: 3, data:ExchangeSender_21",
-          "  └─ExchangeSender_21 10.00 mpp[tiflash]  ExchangeType: PassThrough",
-          "    └─TopN_20 10.00 mpp[tiflash]  Column#8, offset:0, count:10",
-          "      └─Projection_19 10.00 mpp[tiflash]  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, test.t1.c, test.t1.d, vec_l2_distance(test.t1.vec, [1,1,1])->Column#8",
-          "        └─TableFullScan_17 6000.00 mpp[tiflash] table:t1 keep order:false"
+          "TopN 10.00 root  Column#8, offset:0, count:10",
+          "└─TableReader 10.00 root  MppVersion: 3, data:ExchangeSender",
+          "  └─ExchangeSender 10.00 mpp[tiflash]  ExchangeType: PassThrough",
+          "    └─TopN 10.00 mpp[tiflash]  Column#8, offset:0, count:10",
+          "      └─Projection 10.00 mpp[tiflash]  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, test.t1.c, test.t1.d, vec_l2_distance(test.t1.vec, [1,1,1])->Column#8",
+          "        └─TableFullScan 6000.00 mpp[tiflash] table:t1 keep order:false"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select * from t1 order by vec_negative_inner_product(vec, '[1,1,1]') limit 10",
+        "SQL": "explain format = 'brief' select * from t1 order by vec_negative_inner_product(vec, '[1,1,1]') limit 10",
         "Plan": [
-          "TopN_9 10.00 root  Column#8, offset:0, count:10",
-          "└─TableReader_22 10.00 root  MppVersion: 3, data:ExchangeSender_21",
-          "  └─ExchangeSender_21 10.00 mpp[tiflash]  ExchangeType: PassThrough",
-          "    └─TopN_20 10.00 mpp[tiflash]  Column#8, offset:0, count:10",
-          "      └─Projection_19 10.00 mpp[tiflash]  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, test.t1.c, test.t1.d, vec_negative_inner_product(test.t1.vec, [1,1,1])->Column#8",
-          "        └─TableFullScan_17 6000.00 mpp[tiflash] table:t1 keep order:false"
+          "TopN 10.00 root  Column#8, offset:0, count:10",
+          "└─TableReader 10.00 root  MppVersion: 3, data:ExchangeSender",
+          "  └─ExchangeSender 10.00 mpp[tiflash]  ExchangeType: PassThrough",
+          "    └─TopN 10.00 mpp[tiflash]  Column#8, offset:0, count:10",
+          "      └─Projection 10.00 mpp[tiflash]  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, test.t1.c, test.t1.d, vec_negative_inner_product(test.t1.vec, [1,1,1])->Column#8",
+          "        └─TableFullScan 6000.00 mpp[tiflash] table:t1 keep order:false"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select * from t1 order by vec_dims(vec) limit 10",
+        "SQL": "explain format = 'brief' select * from t1 order by vec_dims(vec) limit 10",
         "Plan": [
-          "TopN_9 10.00 root  Column#8, offset:0, count:10",
-          "└─TableReader_21 10.00 root  MppVersion: 3, data:ExchangeSender_20",
-          "  └─ExchangeSender_20 10.00 mpp[tiflash]  ExchangeType: PassThrough",
-          "    └─TopN_19 10.00 mpp[tiflash]  Column#8, offset:0, count:10",
-          "      └─Projection_18 10.00 mpp[tiflash]  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, test.t1.c, test.t1.d, vec_dims(test.t1.vec)->Column#8",
-          "        └─TableFullScan_16 6000.00 mpp[tiflash] table:t1 keep order:false"
+          "TopN 10.00 root  Column#8, offset:0, count:10",
+          "└─TableReader 10.00 root  MppVersion: 3, data:ExchangeSender",
+          "  └─ExchangeSender 10.00 mpp[tiflash]  ExchangeType: PassThrough",
+          "    └─TopN 10.00 mpp[tiflash]  Column#8, offset:0, count:10",
+          "      └─Projection 10.00 mpp[tiflash]  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, test.t1.c, test.t1.d, vec_dims(test.t1.vec)->Column#8",
+          "        └─TableFullScan 6000.00 mpp[tiflash] table:t1 keep order:false"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select * from t1 order by vec_l2_norm(vec) limit 10",
+        "SQL": "explain format = 'brief' select * from t1 order by vec_l2_norm(vec) limit 10",
         "Plan": [
-          "TopN_9 10.00 root  Column#8, offset:0, count:10",
-          "└─TableReader_21 10.00 root  MppVersion: 3, data:ExchangeSender_20",
-          "  └─ExchangeSender_20 10.00 mpp[tiflash]  ExchangeType: PassThrough",
-          "    └─TopN_19 10.00 mpp[tiflash]  Column#8, offset:0, count:10",
-          "      └─Projection_18 10.00 mpp[tiflash]  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, test.t1.c, test.t1.d, vec_l2_norm(test.t1.vec)->Column#8",
-          "        └─TableFullScan_16 6000.00 mpp[tiflash] table:t1 keep order:false"
+          "TopN 10.00 root  Column#8, offset:0, count:10",
+          "└─TableReader 10.00 root  MppVersion: 3, data:ExchangeSender",
+          "  └─ExchangeSender 10.00 mpp[tiflash]  ExchangeType: PassThrough",
+          "    └─TopN 10.00 mpp[tiflash]  Column#8, offset:0, count:10",
+          "      └─Projection 10.00 mpp[tiflash]  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, test.t1.c, test.t1.d, vec_l2_norm(test.t1.vec)->Column#8",
+          "        └─TableFullScan 6000.00 mpp[tiflash] table:t1 keep order:false"
         ],
         "Warn": null
       },
       {
-        "SQL": "explain select * from t1 order by MOD(a, 3) limit 10",
+        "SQL": "explain format = 'brief' select * from t1 order by MOD(a, 3) limit 10",
         "Plan": [
-          "Projection_22 10.00 root  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, test.t1.c, test.t1.d",
-          "└─TopN_9 10.00 root  Column#8, offset:0, count:10",
-          "  └─Projection_23 10.00 root  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, test.t1.c, test.t1.d, mod(test.t1.a, 3)->Column#8",
-          "    └─TableReader_19 10.00 root  MppVersion: 3, data:ExchangeSender_18",
-          "      └─ExchangeSender_18 10.00 mpp[tiflash]  ExchangeType: PassThrough",
-          "        └─Projection_20 10.00 mpp[tiflash]  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, test.t1.c, test.t1.d",
-          "          └─TopN_17 10.00 mpp[tiflash]  Column#7, offset:0, count:10",
-          "            └─Projection_21 6000.00 mpp[tiflash]  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, test.t1.c, test.t1.d, mod(test.t1.a, 3)->Column#7",
-          "              └─TableFullScan_15 6000.00 mpp[tiflash] table:t1 keep order:false"
+          "Projection 10.00 root  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, test.t1.c, test.t1.d",
+          "└─TopN 10.00 root  Column#8, offset:0, count:10",
+          "  └─Projection 10.00 root  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, test.t1.c, test.t1.d, mod(test.t1.a, 3)->Column#8",
+          "    └─TableReader 10.00 root  MppVersion: 3, data:ExchangeSender",
+          "      └─ExchangeSender 10.00 mpp[tiflash]  ExchangeType: PassThrough",
+          "        └─Projection 10.00 mpp[tiflash]  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, test.t1.c, test.t1.d",
+          "          └─TopN 10.00 mpp[tiflash]  Column#7, offset:0, count:10",
+          "            └─Projection 6000.00 mpp[tiflash]  test.t1.id, test.t1.vec, test.t1.a, test.t1.b, test.t1.c, test.t1.d, mod(test.t1.a, 3)->Column#7",
+          "              └─TableFullScan 6000.00 mpp[tiflash] table:t1 keep order:false"
         ],
         "Warn": null
       }
     ]
   }
-]
\ No newline at end of file
+]
diff --git a/pkg/planner/core/integration_test.go b/pkg/planner/core/integration_test.go
index 41a8071868e16..91750c6346ef2 100644
--- a/pkg/planner/core/integration_test.go
+++ b/pkg/planner/core/integration_test.go
@@ -2181,11 +2181,11 @@ func TestVirtualExprPushDown(t *testing.T) {
 
 	// TopN to tikv.
 	rows := [][]any{
-		{"TopN_7", "root", "test.t.c2, offset:0, count:2"},
-		{"└─TableReader_13", "root", "data:TableFullScan_12"},
-		{"  └─TableFullScan_12", "cop[tikv]", "keep order:false, stats:pseudo"},
+		{"TopN", "root", "test.t.c2, offset:0, count:2"},
+		{"└─TableReader", "root", "data:TableFullScan"},
+		{"  └─TableFullScan", "cop[tikv]", "keep order:false, stats:pseudo"},
 	}
-	tk.MustQuery("explain select * from t order by c2 limit 2;").CheckAt([]int{0, 2, 4}, rows)
+	tk.MustQuery("explain format='brief' select * from t order by c2 limit 2;").CheckAt([]int{0, 2, 4}, rows)
 
 	// Projection to tikv.
 	rows = [][]any{
@@ -2217,11 +2217,11 @@ func TestVirtualExprPushDown(t *testing.T) {
 
 	// TopN to tiflash.
 	rows = [][]any{
-		{"TopN_7", "root", "test.t.c2, offset:0, count:2"},
-		{"└─TableReader_15", "root", "data:TableFullScan_14"},
-		{"  └─TableFullScan_14", "cop[tiflash]", "keep order:false, stats:pseudo"},
+		{"TopN", "root", "test.t.c2, offset:0, count:2"},
+		{"└─TableReader", "root", "data:TableFullScan"},
+		{"  └─TableFullScan", "cop[tiflash]", "keep order:false, stats:pseudo"},
 	}
-	tk.MustQuery("explain select * from t order by c2 limit 2;").CheckAt([]int{0, 2, 4}, rows)
+	tk.MustQuery("explain format='brief' select * from t order by c2 limit 2;").CheckAt([]int{0, 2, 4}, rows)
 
 	// Projection to tiflash.
 	rows = [][]any{
diff --git a/pkg/planner/core/operator/logicalop/logical_projection.go b/pkg/planner/core/operator/logicalop/logical_projection.go
index 69d3d93a58417..8e6acd75e42b8 100644
--- a/pkg/planner/core/operator/logicalop/logical_projection.go
+++ b/pkg/planner/core/operator/logicalop/logical_projection.go
@@ -193,6 +193,7 @@ func (p *LogicalProjection) PushDownTopN(topNLogicalPlan base.LogicalPlan, opt *
 	if slices.ContainsFunc(p.Exprs, expression.HasAssignSetVarFunc) {
 		return p.BaseLogicalPlan.PushDownTopN(topN, opt)
 	}
+
 	if topN != nil {
 		exprCtx := p.SCtx().GetExprCtx()
 		substitutedExprs := make([]expression.Expression, 0, len(topN.ByItems))
@@ -202,12 +203,23 @@ func (p *LogicalProjection) PushDownTopN(topNLogicalPlan base.LogicalPlan, opt *
 				// after substituting, if the order-by expression is un-deterministic like 'order by rand()', stop pushing down.
 				return p.BaseLogicalPlan.PushDownTopN(topN, opt)
 			}
+			// if topN.ByItems contains a column(with ID=0) generated by projection,
+			// projection will prevent the optimizer from pushing topN down.
+			cols := expression.ExtractColumns(substituted)
+			for _, col := range cols {
+				if col.ID == 0 && p.Schema().Contains(col) {
+					// check whether the column is generated by projection
+					if !p.Children()[0].Schema().Contains(col) {
+						p.Children()[0] = p.Children()[0].PushDownTopN(nil, opt)
+						return topN.AttachChild(p, opt)
+					}
+				}
+			}
 			substitutedExprs = append(substitutedExprs, substituted)
 		}
 		for i, by := range topN.ByItems {
 			by.Expr = substitutedExprs[i]
 		}
-
 		// remove meaningless constant sort items.
 		for i := len(topN.ByItems) - 1; i >= 0; i-- {
 			switch topN.ByItems[i].Expr.(type) {
@@ -215,22 +227,11 @@ func (p *LogicalProjection) PushDownTopN(topNLogicalPlan base.LogicalPlan, opt *
 				topN.ByItems = slices.Delete(topN.ByItems, i, i+1)
 			}
 		}
-
-		// if topN.ByItems contains a column(with ID=0) generated by projection, projection will prevent the optimizer from pushing topN down.
-		for _, by := range topN.ByItems {
-			cols := expression.ExtractColumns(by.Expr)
-			for _, col := range cols {
-				if col.ID == 0 && p.Schema().Contains(col) {
-					// check whether the column is generated by projection
-					if !p.Children()[0].Schema().Contains(col) {
-						p.Children()[0] = p.Children()[0].PushDownTopN(nil, opt)
-						return topN.AttachChild(p, opt)
-					}
-				}
-			}
-		}
+		p.Children()[0] = p.Children()[0].PushDownTopN(topN, opt)
+		return p
 	}
-	p.Children()[0] = p.Children()[0].PushDownTopN(topN, opt)
+
+	p.Children()[0] = p.Children()[0].PushDownTopN(nil, opt)
 	return p
 }
 
diff --git a/pkg/planner/core/operator/logicalop/logicalop_test/BUILD.bazel b/pkg/planner/core/operator/logicalop/logicalop_test/BUILD.bazel
index 05f836890faf9..a4e44563b0c01 100644
--- a/pkg/planner/core/operator/logicalop/logicalop_test/BUILD.bazel
+++ b/pkg/planner/core/operator/logicalop/logicalop_test/BUILD.bazel
@@ -10,7 +10,7 @@ go_test(
         "plan_execute_test.go",
     ],
     flaky = True,
-    shard_count = 36,
+    shard_count = 37,
     deps = [
         "//pkg/domain",
         "//pkg/expression",
diff --git a/pkg/planner/core/operator/logicalop/logicalop_test/logical_operator_test.go b/pkg/planner/core/operator/logicalop/logicalop_test/logical_operator_test.go
index 9cc74589e353e..6e40cdeaa30ff 100644
--- a/pkg/planner/core/operator/logicalop/logicalop_test/logical_operator_test.go
+++ b/pkg/planner/core/operator/logicalop/logicalop_test/logical_operator_test.go
@@ -20,6 +20,7 @@ import (
 	"github.com/pingcap/tidb/pkg/expression"
 	"github.com/pingcap/tidb/pkg/parser/ast"
 	"github.com/pingcap/tidb/pkg/planner/core/operator/logicalop"
+	"github.com/pingcap/tidb/pkg/testkit"
 	"github.com/pingcap/tidb/pkg/types"
 	"github.com/pingcap/tidb/pkg/util/mock"
 	"github.com/stretchr/testify/require"
@@ -103,3 +104,46 @@ func TestLogicalApplyClone(t *testing.T) {
 	require.True(t, clonedApply.EqualConditions[0].FuncName.L == "f2")
 	require.True(t, apply.EqualConditions[0].FuncName.L == "f2")
 }
+
+func TestLogicalProjectionPushDownTopN(t *testing.T) {
+	store := testkit.CreateMockStore(t)
+	tk := testkit.NewTestKit(t, store)
+	tk.MustExec("use test;")
+	tk.MustExec(`CREATE TABLE table_test (
+col16 json DEFAULT NULL,
+col17 json DEFAULT NULL
+);`)
+	sql := `explain format='brief' SELECT 
+       s.column16 AS column16,
+       s.column17 AS column17
+FROM
+  (SELECT 
+          col16 -> '$[].optUid' AS column16,
+          JSON_UNQUOTE(JSON_EXTRACT(col17, '$[0].value')) AS column17
+   FROM
+     (SELECT 
+             col16,
+             col17
+      FROM table_test) ta24e
+   ) AS s 
+ORDER BY CONVERT(column16 USING GBK) ASC,column17 ASC
+LIMIT 0,
+      20;`
+	tk.MustQuery(sql).Check(testkit.Rows(
+		"Projection 20.00 root  Column#4, Column#5",
+		"└─TopN 20.00 root  Column#6, Column#5, offset:0, count:20",
+		"  └─Projection 10000.00 root  Column#4, Column#5, convert(cast(Column#4, var_string(16777216)), gbk)->Column#6",
+		"    └─TableReader 10000.00 root  data:Projection",
+		"      └─Projection 10000.00 cop[tikv]  json_extract(test.table_test.col16, $[].optUid)->Column#4, json_unquote(cast(json_extract(test.table_test.col17, $[0].value), var_string(16777216)))->Column#5",
+		"        └─TableFullScan 10000.00 cop[tikv] table:table_test keep order:false, stats:pseudo"))
+	tk.MustExec(`INSERT INTO mysql.opt_rule_blacklist VALUES("topn_push_down");`)
+	tk.MustExec(`admin reload opt_rule_blacklist;`)
+	tk.MustQuery(sql).Check(testkit.Rows(
+		"Limit 20.00 root  offset:0, count:20",
+		"└─Projection 20.00 root  Column#4, Column#5",
+		"  └─Sort 20.00 root  Column#6, Column#5",
+		"    └─Projection 10000.00 root  Column#4, Column#5, convert(cast(Column#4, var_string(16777216)), gbk)->Column#6",
+		"      └─TableReader 10000.00 root  data:Projection",
+		"        └─Projection 10000.00 cop[tikv]  json_extract(test.table_test.col16, $[].optUid)->Column#4, json_unquote(cast(json_extract(test.table_test.col17, $[0].value), var_string(16777216)))->Column#5",
+		"          └─TableFullScan 10000.00 cop[tikv] table:table_test keep order:false, stats:pseudo"))
+}
diff --git a/tests/integrationtest/r/planner/core/plan.result b/tests/integrationtest/r/planner/core/plan.result
index 165c09f59d8ad..2f82c6622fcd1 100644
--- a/tests/integrationtest/r/planner/core/plan.result
+++ b/tests/integrationtest/r/planner/core/plan.result
@@ -418,6 +418,24 @@ CREATE TABLE `t2`(`c1` set('kn8pu','7et','vekx6','v3','liwrh','q14','1met','nnd5
 r0	r1
 affected rows: 0
 info: 
+explain format='brief' (select /*+ agg_to_cop()*/ locate(t1.c3, t1.c3) as r0, t1.c3 as r1 from t1 where not( IsNull(t1.c1)) order by r0,r1) union all (select concat_ws(',', t2.c2, t2.c1) as r0, t2.c1 as r1 from t2 order by r0, r1) order by 1 limit 273;
+id	estRows	task	access object	operator info
+TopN	273.00	root		Column#9, offset:0, count:273
+└─Union	546.00	root		
+  ├─Projection	273.00	root		cast(Column#4, longblob BINARY)->Column#9, planner__core__plan.t1.c3->Column#10
+  │ └─Projection	273.00	root		locate(planner__core__plan.t1.c3, planner__core__plan.t1.c3)->Column#4, planner__core__plan.t1.c3
+  │   └─Projection	273.00	root		planner__core__plan.t1.c3
+  │     └─TopN	273.00	root		Column#11, offset:0, count:273
+  │       └─Projection	10000.00	root		planner__core__plan.t1.c3, cast(locate(planner__core__plan.t1.c3, planner__core__plan.t1.c3), longblob BINARY)->Column#11
+  │         └─TableReader	10000.00	root		data:TableFullScan
+  │           └─TableFullScan	10000.00	cop[tikv]	table:t1	keep order:false, stats:pseudo
+  └─Projection	273.00	root		cast(to_binary(Column#8), longblob BINARY)->Column#9, cast(planner__core__plan.t2.c1, tinyblob BINARY)->Column#10
+    └─Projection	273.00	root		concat_ws(,, cast(planner__core__plan.t2.c2, var_string(5)), planner__core__plan.t2.c1)->Column#8, planner__core__plan.t2.c1
+      └─Projection	273.00	root		planner__core__plan.t2.c1, planner__core__plan.t2.c2
+        └─TopN	273.00	root		Column#12, offset:0, count:273
+          └─Projection	10000.00	root		planner__core__plan.t2.c1, planner__core__plan.t2.c2, cast(to_binary(concat_ws(,, cast(planner__core__plan.t2.c2, var_string(5)), planner__core__plan.t2.c1)), longblob BINARY)->Column#12
+            └─IndexReader	10000.00	root		index:IndexFullScan
+              └─IndexFullScan	10000.00	cop[tikv]	table:t2, index:k1(c2, c1)	keep order:false, stats:pseudo
 drop table if exists golang1, golang2;
 CREATE TABLE golang1 ( `fcbpdt` CHAR (8) COLLATE utf8_general_ci NOT NULL, `fcbpsq` VARCHAR (20) COLLATE utf8_general_ci NOT NULL, `procst` char (4) COLLATE utf8_general_ci DEFAULT NULL,`cipstx` VARCHAR (105) COLLATE utf8_general_ci DEFAULT NULL, `cipsst` CHAR (4) COLLATE utf8_general_ci DEFAULT NULL, `dyngtg` VARCHAR(4) COLLATE utf8_general_ci DEFAULT NULL, `blncdt` VARCHAR (8) COLLATE utf8_general_ci DEFAULT NULL, PRIMARY KEY ( fcbpdt, fcbpsq ));
 insert into golang1 values('20230925','12023092502158016','abc','','','','');
diff --git a/tests/integrationtest/t/planner/core/plan.test b/tests/integrationtest/t/planner/core/plan.test
index 4b18143dcc46b..8f35075a3cb65 100644
--- a/tests/integrationtest/t/planner/core/plan.test
+++ b/tests/integrationtest/t/planner/core/plan.test
@@ -179,6 +179,7 @@ CREATE TABLE `t2`(`c1` set('kn8pu','7et','vekx6','v3','liwrh','q14','1met','nnd5
 --enable_info
 (select /*+ agg_to_cop()*/ locate(t1.c3, t1.c3) as r0, t1.c3 as r1 from t1 where not( IsNull(t1.c1)) order by r0,r1) union all (select concat_ws(',', t2.c2, t2.c1) as r0, t2.c1 as r1 from t2 order by r0, r1) order by 1 limit 273;
 --disable_info
+explain format='brief' (select /*+ agg_to_cop()*/ locate(t1.c3, t1.c3) as r0, t1.c3 as r1 from t1 where not( IsNull(t1.c1)) order by r0,r1) union all (select concat_ws(',', t2.c2, t2.c1) as r0, t2.c1 as r1 from t2 order by r0, r1) order by 1 limit 273;
 
 
 # TestIssue47445


Reviews:
user: login: copilot-pull-request-reviewer[bot]
body: ## Pull Request Overview

This PR addresses a bug that causes the wrong schema to be used when pushing down TopN into a projection. Key changes include:
- Removing an extra blank line in optimizer.go.
- Adding a new unit test to verify the TopN push down behavior in projection.
- Updating the push down logic in logical_projection.go with an additional check using a new helper method (isSetTopNChild).

### Reviewed Changes

Copilot reviewed 3 out of 6 changed files in this pull request and generated no comments.

| File | Description |
| ---- | ----------- |
| pkg/planner/core/optimizer.go | Removed an unnecessary blank line to improve code clarity. |
| pkg/planner/core/operator/logicalop/logicalop_test/logical_operator_test.go | Added unit tests that verify the correct behavior for projection push down TopN. |
| pkg/planner/core/operator/logicalop/logical_projection.go | Updated TopN push down logic and added the helper method isSetTopNChild to better determine if the TopN child is set appropriately. |

<details>
<summary>Files not reviewed (3)</summary>

* **pkg/planner/core/operator/logicalop/logicalop_test/BUILD.bazel**: Language not supported
* **tests/integrationtest/r/planner/core/plan.result**: Language not supported
* **tests/integrationtest/t/planner/core/plan.test**: Language not supported
</details>

<details>
<summary>Comments suppressed due to low confidence (1)</summary>

**pkg/planner/core/operator/logicalop/logical_projection.go:228**
* [nitpick] The helper function name 'isSetTopNChild' is ambiguous. Consider renaming it to something like 'areTopNByItemsInChildSchema' so that its purpose is clearer.
```
if !p.Children()[0].Schema().Contains(col) {
```
</details>


state: COMMENTED
author_association: NONE
submitted_at: 2025-04-29T07:59:01Z
user: login: copilot-pull-request-reviewer[bot]
body: ## Pull Request Overview

This PR fixes an issue with the TopN push down logic in the planner when dealing with projections that generate columns with ID=0. The changes update the push-down behavior in LogicalProjection and add new unit tests to verify the correct operator tree under different configuration scenarios.
- Update LogicalProjection.PushDownTopN to create a TopN operator without by-items when a projection-generated column is detected.
- Add unit tests in logical_operator_test to ensure the correct handling of TopN push down.

### Reviewed Changes

Copilot reviewed 2 out of 5 changed files in this pull request and generated no comments.

| File | Description |
| ---- | ----------- |
| pkg/planner/core/operator/logicalop/logicalop_test/logical_operator_test.go | Adds tests validating the TopN push down logic with projections. |
| pkg/planner/core/operator/logicalop/logical_projection.go | Adjusts the push-down logic to generate a new TopN operator when the child schema is missing a projection-generated column. |

<details>
<summary>Files not reviewed (3)</summary>

* **pkg/planner/core/operator/logicalop/logicalop_test/BUILD.bazel**: Language not supported
* **tests/integrationtest/r/planner/core/plan.result**: Language not supported
* **tests/integrationtest/t/planner/core/plan.test**: Language not supported
</details>

<details>
<summary>Comments suppressed due to low confidence (2)</summary>

**pkg/planner/core/operator/logicalop/logical_projection.go:228**
* The condition checking for a projection-generated column (col.ID == 0) may inadvertently trigger the creation and push down of a TopN operator without by-items even for cases that are not truly projection-related. Consider refining this condition with additional checks to ensure that only columns generated by projection result in this behavior.
```
if !p.Children()[0].Schema().Contains(col) {
```
**pkg/planner/core/operator/logicalop/logicalop_test/logical_operator_test.go:128**
* [nitpick] Consider adding more granular assertions on the plan structure rather than relying on exact string matching, to reduce brittleness if plan formatting changes.
```
AS s 
```
</details>


state: COMMENTED
author_association: NONE
submitted_at: 2025-04-29T08:18:41Z
user: login: copilot-pull-request-reviewer[bot]
body: ## Pull Request Overview

This PR fixes an issue where the TopN operator is pushed down with an incorrect schema when a projection generates columns that cannot be resolved by the data source.  
- Added a new test (TestLogicalProjectionPushDownTopN) to validate the TopN pushdown behavior under different configurations.  
- Modified the LogicalProjection's PushDownTopN function to rebuild the TopN operator with a new ByItems array based on the projection's schema.

### Reviewed Changes

Copilot reviewed 2 out of 5 changed files in this pull request and generated 1 comment.

| File | Description |
| ---- | ----------- |
| pkg/planner/core/operator/logicalop/logicalop_test/logical_operator_test.go | Added test for verifying TopN pushdown behavior post projection changes |
| pkg/planner/core/operator/logicalop/logical_projection.go | Updated logic to recreate the TopN operator with a reconstructed ByItems array |

<details>
<summary>Files not reviewed (3)</summary>

* **pkg/planner/core/operator/logicalop/logicalop_test/BUILD.bazel**: Language not supported
* **tests/integrationtest/r/planner/core/plan.result**: Language not supported
* **tests/integrationtest/t/planner/core/plan.test**: Language not supported
</details>



state: COMMENTED
author_association: NONE
submitted_at: 2025-04-29T12:28:53Z
user: login: copilot-pull-request-reviewer[bot]
body: ## Pull Request Overview

This PR fixes an issue where the TopN operator is incorrectly pushed below the Projection when a TopN.ByItems expression references a column generated by the Projection (identified by ID 0).  
- Updated the PushDownTopN logic in LogicalProjection to detect and handle columns generated by projection, creating a new TopN plan when required.  
- Added a unit test to verify the correct execution plan before and after applying an optimizer rule blacklist.

### Reviewed Changes

Copilot reviewed 2 out of 5 changed files in this pull request and generated no comments.

| File | Description |
| ---- | ----------- |
| pkg/planner/core/operator/logicalop/logicalop_test/logical_operator_test.go | Adds a unit test for validating the push down and execution plan transformation regarding Projection and TopN. |
| pkg/planner/core/operator/logicalop/logical_projection.go | Modifies the PushDownTopN method to conditionally recreate TopN when a projection‐generated column is encountered. |

<details>
<summary>Files not reviewed (3)</summary>

* **pkg/planner/core/operator/logicalop/logicalop_test/BUILD.bazel**: Language not supported
* **tests/integrationtest/r/planner/core/plan.result**: Language not supported
* **tests/integrationtest/t/planner/core/plan.test**: Language not supported
</details>

<details>
<summary>Comments suppressed due to low confidence (2)</summary>

**pkg/planner/core/operator/logicalop/logical_projection.go:218**
* [nitpick] Consider renaming 'newCreateTopN' to a more descriptive name (e.g. 'shouldCreateNewTopN') to clarify its purpose.
```
newCreateTopN := false
```
**pkg/planner/core/operator/logicalop/logical_projection.go:241**
* Ensure that 'p.Exprs' is a one-to-one mapping with 'p.Schema'. If duplicate expressions are possible, this index lookup may yield an unintended column mapping.
```
if idx := slices.IndexFunc(p.Exprs, func(e expression.Expression) bool { return e.Equal(evalCtx, byItem.Expr) }); idx >= 0 {
```
</details>


state: COMMENTED
author_association: NONE
submitted_at: 2025-04-29T14:55:31Z
user: login: copilot-pull-request-reviewer[bot]
body: ## Pull Request Overview

This PR fixes an issue where TopN’s ByItems generated by projection and containing expression.ScalarFunction cause errors when pushed down. The changes include modifying the projection's PushDownTopN method to detect projection-generated columns and creating a new TopN plan when necessary, along with adding tests to verify the behavior.

### Reviewed Changes

Copilot reviewed 2 out of 5 changed files in this pull request and generated 1 comment.

| File | Description |
| ---- | ----------- |
| pkg/planner/core/operator/logicalop/logicalop_test/logical_operator_test.go | Added unit test to validate the behavior of projection push down with TopN. |
| pkg/planner/core/operator/logicalop/logical_projection.go | Updated PushDownTopN to create a new TopN plan when encountering projection-generated columns. |

<details>
<summary>Files not reviewed (3)</summary>

* **pkg/planner/core/operator/logicalop/logicalop_test/BUILD.bazel**: Language not supported
* **tests/integrationtest/r/planner/core/plan.result**: Language not supported
* **tests/integrationtest/t/planner/core/plan.test**: Language not supported
</details>



state: COMMENTED
author_association: NONE
submitted_at: 2025-04-30T09:54:31Z
user: login: copilot-pull-request-reviewer[bot]
body: ## Pull Request Overview

This PR fixes an issue where TopN’s ByItems produced by a Projection were incorrectly pushed down, causing the wrong ordering behavior when the expression is a ScalarFunction. Key changes include:
- Adding tests to verify the correct execution plan before and after the fix.
- Modifying LogicalProjection's PushDownTopN logic to construct a new TopN plan with substituted ByItems.
- Updating the expected plan strings in trace and integration tests to match the new pushdown behavior.

### Reviewed Changes

Copilot reviewed 7 out of 23 changed files in this pull request and generated 1 comment.

| File | Description |
| ---- | ----------- |
| pkg/planner/core/operator/logicalop/logicalop_test/logical_operator_test.go | Added tests for TopN push down behavior with projection. |
| pkg/planner/core/operator/logicalop/logical_projection.go | Refactored TopN push down logic to construct new ByItems and prevent push down when a generated column is detected. |
| pkg/planner/core/logical_plan_trace_test.go | Updated expected plan labels to reflect new TopN identifiers. |
| pkg/planner/core/integration_test.go | Updated expected plan output to match changed TopN push down behavior. |

<details>
<summary>Files not reviewed (16)</summary>

* **pkg/planner/core/casetest/testdata/integration_suite_out.json**: Language not supported
* **pkg/planner/core/casetest/vectorsearch/testdata/ann_index_suite_out.json**: Language not supported
* **pkg/planner/core/operator/logicalop/logicalop_test/BUILD.bazel**: Language not supported
* **tests/integrationtest/r/executor/explain.result**: Language not supported
* **tests/integrationtest/r/executor/index_merge_reader.result**: Language not supported
* **tests/integrationtest/r/executor/issues.result**: Language not supported
* **tests/integrationtest/r/globalindex/mem_index_merge.result**: Language not supported
* **tests/integrationtest/r/index_merge.result**: Language not supported
* **tests/integrationtest/r/infoschema/cluster_tables.result**: Language not supported
* **tests/integrationtest/r/planner/core/casetest/integration.result**: Language not supported
* **tests/integrationtest/r/planner/core/casetest/physicalplantest/physical_plan.result**: Language not supported
* **tests/integrationtest/r/planner/core/issuetest/planner_issue.result**: Language not supported
* **tests/integrationtest/r/planner/core/plan.result**: Language not supported
* **tests/integrationtest/r/planner/core/plan_cache.result**: Language not supported
* **tests/integrationtest/r/planner/core/plan_cost_ver2.result**: Language not supported
* **tests/integrationtest/r/planner/core/rule_result_reorder.result**: Language not supported
</details>



state: COMMENTED
author_association: NONE
submitted_at: 2025-05-06T11:07:51Z
user: login: AilinKid
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-07T07:20:55Z
user: login: winoros
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-07T11:21:52Z
user: login: winoros
state: APPROVED
author_association: MEMBER
submitted_at: 2025-05-07T16:40:23Z

Review comments:
diff_hunk: @@ -224,7 +224,21 @@ func (p *LogicalProjection) PushDownTopN(topNLogicalPlan base.LogicalPlan, opt *
 					// check whether the column is generated by projection
 					if !p.Children()[0].Schema().Contains(col) {
 						p.Children()[0] = p.Children()[0].PushDownTopN(nil, opt)
-						return topN.AttachChild(p, opt)
+						newTopN := LogicalTopN{
+							Count:            topN.Count,
+							Offset:           topN.Offset,
+							ByItems:          make([]*util.ByItems, 0, len(p.Schema().Columns)),
+							PreferLimitToCop: topN.PreferLimitToCop,
+							PartitionBy:      topN.GetPartitionBy(),
+						}.Init(topN.SCtx(), topN.QueryBlockOffset())
+						for idx, byitem := range p.Schema().Columns {
+							by := &util.ByItems{
+								Expr: byitem,
+								Desc: topN.ByItems[idx].Desc,
+							}
+							newTopN.ByItems = append(newTopN.ByItems, by)
path: pkg/planner/core/operator/logicalop/logical_projection.go
user: login: Copilot
body: Looping over p.Schema().Columns and indexing topN.ByItems assumes both slices have matching lengths, which could lead to an index out-of-range error if they differ. Consider iterating directly over topN.ByItems or validating the lengths of these slices before indexing.
```suggestion
						for idx, by := range topN.ByItems {
							if idx >= len(p.Schema().Columns) {
								break // Prevent out-of-range access
							}
							byItem := &util.ByItems{
								Expr: p.Schema().Columns[idx],
								Desc: by.Desc,
							}
							newTopN.ByItems = append(newTopN.ByItems, byItem)
```
created_at: 2025-04-29T12:28:52Z
author_association: NONE
diff_hunk: @@ -215,21 +215,48 @@ func (p *LogicalProjection) PushDownTopN(topNLogicalPlan base.LogicalPlan, opt *
 				topN.ByItems = slices.Delete(topN.ByItems, i, i+1)
 			}
 		}
-
+		newCreateTopN := false
path: pkg/planner/core/operator/logicalop/logical_projection.go
user: login: Copilot
body: [nitpick] The nested loops and conditional logic for handling TopN.ByItems is complex; consider extracting this logic into a helper function to improve readability and maintainability.
created_at: 2025-04-30T09:54:31Z
author_association: NONE
diff_hunk: @@ -229,8 +240,11 @@ func (p *LogicalProjection) PushDownTopN(topNLogicalPlan base.LogicalPlan, opt *
 				}
 			}
 		}
+		p.Children()[0] = p.Children()[0].PushDownTopN(pushDownTopN, opt)
+		return p
 	}
-	p.Children()[0] = p.Children()[0].PushDownTopN(topN, opt)
+
path: pkg/planner/core/operator/logicalop/logical_projection.go
user: login: Copilot
body: [nitpick] Consider adding a comment to clarify why PushDownTopN is called with nil here, explaining that it prevents further TopN push down after handling the current projection.
```suggestion

	// Passing `nil` here prevents further TopN pushdown after handling the current projection.
```
created_at: 2025-05-06T11:07:50Z
author_association: NONE
diff_hunk: @@ -48,65 +48,65 @@
   {
     "name": "TestVectorSearchWithPKAuto",
     "cases": [
-      "explain select id from t1",
+      "explain format = 'brief' select id from t1",
 
-      "explain select id from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
-      "explain select id from t1 order by vec_cosine_distance(vec, '[1,1,1]')",
-      "explain select * from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
-      "explain select id, a, b from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
-      "explain select a, id, b from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
+      "explain format = 'brief' select id from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
+      "explain format = 'brief' select id from t1 order by vec_cosine_distance(vec, '[1,1,1]')",
+      "explain format = 'brief' select * from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
+      "explain format = 'brief' select id, a, b from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
+      "explain format = 'brief' select a, id, b from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10",
 
-      "explain select id, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d limit 10",
-      "explain select id, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d",
-      "explain select *, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d limit 10",
-      "explain select id, vec_cosine_distance(vec, '[1,1,1]') as d, a, b from t1 order by d limit 10",
-      "explain select id, a, b, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d limit 10"
+      "explain format = 'brief' select id, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d limit 10",
+      "explain format = 'brief' select id, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d",
+      "explain format = 'brief' select *, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d limit 10",
+      "explain format = 'brief' select id, vec_cosine_distance(vec, '[1,1,1]') as d, a, b from t1 order by d limit 10",
+      "explain format = 'brief' select id, a, b, vec_cosine_distance(vec, '[1,1,1]') as d from t1 order by d limit 10"
     ]
   },
   {
     "name": "TestVectorSearchWithPKForceTiKV",
     "cases": [
-      "explain select id from t1",
+       "explain format = 'brief' select id from t1",
path: pkg/planner/core/casetest/vectorsearch/testdata/ann_index_suite_in.json
user: login: winoros
body: one extra space is added
rest part lgtm
created_at: 2025-05-07T11:21:47Z
author_association: MEMBER

PR comments:
user: login: hawkingrei
created_at: 2025-04-24T16:24:56Z
body: /check-issue-triage-complete
author_association: MEMBER
user: login: hawkingrei
created_at: 2025-04-28T09:28:34Z
body: /test fast_tiprow_test
author_association: MEMBER
user: login: tiprow[bot]
created_at: 2025-04-28T09:29:33Z
body: @ti-chi-bot[bot]: The specified target(s) for `/test` were not found.
The following commands are available to trigger required jobs:
* `/test fast_test_tiprow`
* `/test tidb_parser_test`

Use `/test all` to run the following jobs that were automatically triggered:
* `tidb_parser_test`



<details>

In response to [this](https://github.com/pingcap/tidb/pull/60822#issuecomment-2834594965):

>@hawkingrei: The specified target(s) for `/test` were not found.
>The following commands are available to trigger required jobs:
>```
>/test build
>```
>```
>/test check-dev
>```
>```
>/test check-dev2
>```
>```
>/test mysql-test
>```
>```
>/test pull-br-integration-test
>```
>```
>/test pull-integration-ddl-test
>```
>```
>/test pull-integration-e2e-test
>```
>```
>/test pull-lightning-integration-test
>```
>```
>/test pull-mysql-client-test
>```
>```
>/test pull-unit-test-ddlv1
>```
>```
>/test unit-test
>```
>
>The following commands are available to trigger optional jobs:
>```
>/test pingcap/tidb/canary_ghpr_unit_test
>```
>```
>/test pull-common-test
>```
>```
>/test pull-e2e-test
>```
>```
>/test pull-integration-common-test
>```
>```
>/test pull-integration-copr-test
>```
>```
>/test pull-integration-jdbc-test
>```
>```
>/test pull-integration-mysql-test
>```
>```
>/test pull-integration-nodejs-test
>```
>```
>/test pull-integration-python-orm-test
>```
>```
>/test pull-next-gen-real-tikv-test
>```
>```
>/test pull-sqllogic-test
>```
>```
>/test pull-tiflash-test
>```
>
>Use `/test all` to run the following jobs that were automatically triggered:
>```
>pingcap/tidb/ghpr_build
>```
>```
>pingcap/tidb/ghpr_check
>```
>```
>pingcap/tidb/ghpr_check2
>```
>```
>pingcap/tidb/ghpr_mysql_test
>```
>```
>pingcap/tidb/ghpr_unit_test
>```
>```
>pingcap/tidb/pull_integration_ddl_test
>```
>```
>pingcap/tidb/pull_integration_e2e_test
>```
>```
>pingcap/tidb/pull_mysql_client_test
>```
>
>
>
><details>
>
>In response to [this](https://github.com/pingcap/tidb/pull/60822#issuecomment-2834594834):
>
>>/test fast_test_tiprow
>
>
>Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository.
></details>


Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository.
</details>
author_association: NONE
user: login: codecov[bot]
created_at: 2025-04-29T07:08:02Z
body: ## [Codecov](https://app.codecov.io/gh/pingcap/tidb/pull/60822?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pingcap) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 73.5929%. Comparing base [(`a0293bf`)](https://app.codecov.io/gh/pingcap/tidb/commit/a0293bff9b65e0bfcb0db6b785d525b69a8c0b6f?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pingcap) to head [(`ecb5e20`)](https://app.codecov.io/gh/pingcap/tidb/commit/ecb5e202a6405b41a616bdaf6d1e6acc31fc8381?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pingcap).
> Report is 11 commits behind head on master.

<details><summary>Additional details and impacted files</summary>


```diff
@@               Coverage Diff                @@
##             master     #60822        +/-   ##
================================================
+ Coverage   73.1429%   73.5929%   +0.4499%     
================================================
  Files          1722       1722                
  Lines        476948     481220      +4272     
================================================
+ Hits         348854     354144      +5290     
+ Misses       106703     105535      -1168     
- Partials      21391      21541       +150     
```

| [Flag](https://app.codecov.io/gh/pingcap/tidb/pull/60822/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pingcap) | Coverage Δ | |
|---|---|---|
| [integration](https://app.codecov.io/gh/pingcap/tidb/pull/60822/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pingcap) | `42.6384% <63.6363%> (?)` | |
| [unit](https://app.codecov.io/gh/pingcap/tidb/pull/60822/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pingcap) | `72.3697% <100.0000%> (+0.0125%)` | :arrow_up: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pingcap#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Components](https://app.codecov.io/gh/pingcap/tidb/pull/60822/components?src=pr&el=components&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pingcap) | Coverage Δ | |
|---|---|---|
| [dumpling](https://app.codecov.io/gh/pingcap/tidb/pull/60822/components?src=pr&el=component&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pingcap) | `52.7804% <ø> (ø)` | |
| [parser](https://app.codecov.io/gh/pingcap/tidb/pull/60822/components?src=pr&el=component&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pingcap) | `∅ <ø> (∅)` | |
| [br](https://app.codecov.io/gh/pingcap/tidb/pull/60822/components?src=pr&el=component&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pingcap) | `46.4900% <ø> (-0.9561%)` | :arrow_down: |

</details>
<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
- :package: [JS Bundle Analysis](https://docs.codecov.com/docs/javascript-bundle-analysis): Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
</details>
author_association: NONE
user: login: hawkingrei
created_at: 2025-04-29T07:40:44Z
body: /retest
author_association: MEMBER
user: login: hawkingrei
created_at: 2025-04-29T08:39:35Z
body: /retest
author_association: MEMBER
user: login: hawkingrei
created_at: 2025-04-29T08:46:40Z
body: /retest

author_association: MEMBER
user: login: hawkingrei
created_at: 2025-04-29T10:05:53Z
body: /retest
author_association: MEMBER
user: login: hawkingrei
created_at: 2025-04-29T12:02:50Z
body: /retest
author_association: MEMBER
user: login: hawkingrei
created_at: 2025-04-29T12:40:14Z
body: /hold 

have a problem at the setting of topN's ByItem.
author_association: MEMBER
user: login: hawkingrei
created_at: 2025-04-29T14:53:47Z
body: /unhold
author_association: MEMBER
user: login: hawkingrei
created_at: 2025-04-30T09:53:32Z
body: /retest
author_association: MEMBER
user: login: hawkingrei
created_at: 2025-05-01T02:39:59Z
body: /hold
author_association: MEMBER
user: login: hawkingrei
created_at: 2025-05-06T11:12:30Z
body: /retest
author_association: MEMBER
user: login: hawkingrei
created_at: 2025-05-07T03:07:17Z
body: /unhold
author_association: MEMBER
user: login: hawkingrei
created_at: 2025-05-07T09:51:20Z
body: /retest
author_association: MEMBER
user: login: ti-chi-bot[bot]
created_at: 2025-05-07T16:40:29Z
body: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/pingcap/tidb/pull/60822#pullrequestreview-2820641454" title="Approved">AilinKid</a>*, *<a href="https://github.com/pingcap/tidb/pull/60822#pullrequestreview-2822483393" title="Approved">winoros</a>*

The full list of commands accepted by this bot can be found [here](https://prow.tidb.net/command-help?repo=pingcap%2Ftidb).

The pull request process is described [here](https://book.prow.tidb.net/#/workflows/pr)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/pingcap/tidb/blob/master/OWNERS)~~ [AilinKid,winoros]
- ~~[pkg/planner/OWNERS](https://github.com/pingcap/tidb/blob/master/pkg/planner/OWNERS)~~ [AilinKid,winoros]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
author_association: NONE
user: login: ti-chi-bot[bot]
created_at: 2025-05-07T16:40:32Z
body: [LGTM Timeline notifier]
---
Timeline:

- `2025-05-07 07:21:07.397709417 +0000 UTC m=+426114.580612676`: :ballot_box_with_check: agreed by [AilinKid](https://github.com/AilinKid).
- `2025-05-07 16:40:32.145241422 +0000 UTC m=+459679.328144678`: :ballot_box_with_check: agreed by [winoros](https://github.com/winoros).
author_association: NONE
user: login: hawkingrei
created_at: 2025-05-08T02:20:08Z
body: /cherrypick release-8.5
/cherrypick release-8.1
/cherrypick release-7.5
author_association: MEMBER
user: login: ti-chi-bot
created_at: 2025-05-08T02:20:52Z
body: @hawkingrei: new pull request created to branch `release-7.5`: #61004.
But this PR has conflicts, please resolve them!

<details>

In response to [this](https://github.com/pingcap/tidb/pull/60822#issuecomment-2861294790):

>/cherrypick release-8.5
>/cherrypick release-8.1
>/cherrypick release-7.5


Instructions for interacting with me using PR comments are available [here](https://prow.tidb.net/command-help).  If you have questions or suggestions related to my behavior, please file an issue against the [ti-community-infra/tichi](https://github.com/ti-community-infra/tichi/issues/new?title=Prow%20issue:) repository.
</details>
author_association: MEMBER
user: login: ti-chi-bot
created_at: 2025-05-08T02:21:36Z
body: @hawkingrei: new pull request created to branch `release-8.1`: #61005.
But this PR has conflicts, please resolve them!

<details>

In response to [this](https://github.com/pingcap/tidb/pull/60822#issuecomment-2861294790):

>/cherrypick release-8.5
>/cherrypick release-8.1
>/cherrypick release-7.5


Instructions for interacting with me using PR comments are available [here](https://prow.tidb.net/command-help).  If you have questions or suggestions related to my behavior, please file an issue against the [ti-community-infra/tichi](https://github.com/ti-community-infra/tichi/issues/new?title=Prow%20issue:) repository.
</details>
author_association: MEMBER
user: login: ti-chi-bot
created_at: 2025-05-08T02:22:20Z
body: @hawkingrei: new pull request created to branch `release-8.5`: #61006.
But this PR has conflicts, please resolve them!

<details>

In response to [this](https://github.com/pingcap/tidb/pull/60822#issuecomment-2861294790):

>/cherrypick release-8.5
>/cherrypick release-8.1
>/cherrypick release-7.5


Instructions for interacting with me using PR comments are available [here](https://prow.tidb.net/command-help).  If you have questions or suggestions related to my behavior, please file an issue against the [ti-community-infra/tichi](https://github.com/ti-community-infra/tichi/issues/new?title=Prow%20issue:) repository.
</details>
author_association: MEMBER