Skip to content

TiDB ignores ast.SetOprStmt when calculating number of fields of prepared statement #30971

@ichn-hu

Description

@ichn-hu

Bug Report

Please answer these questions before submitting your issue. Thanks!

When prepare statement, the mysql protocol requires that the number of fields of the output of the statement should be returned, however, TiDB only calculates it for ast.SelectStmt, i.e. simple select statement, however for statement with union, the ast.SetOprStmt is not handled, therefore the returning fields number will always be 0

> github.com/pingcap/tidb/executor.(*PrepareExec).Next() /home/ichn/Projects/pingcap/tidb/executor/prepared.go:224 (PC: 0x31fc2d8)
Warning: debugging optimized function                                                                                 
   219:                 return err
   220:         }                                                                                                 
   221:         if _, ok := stmt.(*ast.SelectStmt); ok {                                                              
   222:                 e.Fields = colNames2ResultFields(p.Schema(), p.OutputNames(), vars.CurrentDB)                 
   223:         }
=> 224:         if e.ID == 0 {
   225:                 e.ID = vars.GetNextPreparedStmtID()                                                           
   226:         }
   227:         if e.name != "" {
   228:                 vars.PreparedStmtNameToID[e.name] = e.ID                                                      
   229:         }                                                                                                     
(dlv) p stmt
github.com/pingcap/tidb/parser/ast.StmtNode(*github.com/pingcap/tidb/parser/ast.SetOprStmt) *{                        
        dmlNode: github.com/pingcap/tidb/parser/ast.dmlNode {                                                         
                stmtNode: (*"github.com/pingcap/tidb/parser/ast.stmtNode")(0xc010acc1c0),},
        IsInBraces: false,
        SelectList: *github.com/pingcap/tidb/parser/ast.SetOprSelectList {                                            
                node: (*"github.com/pingcap/tidb/parser/ast.node")(0xc010acc240),
                With: *github.com/pingcap/tidb/parser/ast.WithClause nil,                                             
                AfterSetOperator: *github.com/pingcap/tidb/parser/ast.SetOprType nil,
                Selects: []github.com/pingcap/tidb/parser/ast.Node len: 2, cap: 2, [                                  
                        ...,
                        ...,
                ],},
        OrderBy: *github.com/pingcap/tidb/parser/ast.OrderByClause nil,                                               
        Limit: *github.com/pingcap/tidb/parser/ast.Limit nil,
        With: *github.com/pingcap/tidb/parser/ast.WithClause nil,}

1. Minimal reproduce step (Required)

create table t(a int);

reproducing this issue requires using prepare API instead of the mysql client query interface.

see https://dev.mysql.com/doc/c-api/5.7/en/mysql-stmt-field-count.html for more information

prepare statement

select * from t union select 1 form t;

2. What did you expect to see? (Required)

the mysql_stmt_field_count function returns 1

3. What did you see instead (Required)

it returns 0

4. What is your TiDB version? (Required)

v5.3.0

Metadata

Metadata

Assignees

Labels

affects-4.0This bug affects 4.0.x versions.affects-5.0This bug affects 5.0.x versions.affects-5.1This bug affects 5.1.x versions.affects-5.2This bug affects 5.2.x versions.affects-5.3This bug affects 5.3.x versions.fixes-5.4.0severity/majorsig/sql-infraSIG: SQL Infratype/bugThe issue is confirmed as a bug.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions