Skip to content

Commit

Permalink
server: Implement column defaults for mysql.ComFieldList (#40765)
Browse files Browse the repository at this point in the history
close #40764
  • Loading branch information
dveeden committed Feb 6, 2023
1 parent 3b66b54 commit 262ebd5
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 72 deletions.
45 changes: 30 additions & 15 deletions server/column.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
package server

import (
"fmt"

"github.com/pingcap/tidb/parser/charset"
"github.com/pingcap/tidb/parser/mysql"
)
Expand All @@ -23,22 +25,30 @@ const maxColumnNameSize = 256

// ColumnInfo contains information of a column
type ColumnInfo struct {
Schema string
Table string
OrgTable string
Name string
OrgName string
ColumnLength uint32
Charset uint16
Flag uint16
Decimal uint8
Type uint8
DefaultValueLength uint64
DefaultValue []byte
Schema string
Table string
OrgTable string
Name string
OrgName string
ColumnLength uint32
Charset uint16
Flag uint16
Decimal uint8
Type uint8
DefaultValue any
}

// Dump dumps ColumnInfo to bytes.
func (column *ColumnInfo) Dump(buffer []byte, d *resultEncoder) []byte {
return column.dump(buffer, d, false)
}

// DumpWithDefault dumps ColumnInfo to bytes, including column defaults. This is used for ComFieldList responses.
func (column *ColumnInfo) DumpWithDefault(buffer []byte, d *resultEncoder) []byte {
return column.dump(buffer, d, true)
}

func (column *ColumnInfo) dump(buffer []byte, d *resultEncoder, withDefault bool) []byte {
if d == nil {
d = newResultEncoder(charset.CharsetUTF8MB4)
}
Expand All @@ -64,9 +74,14 @@ func (column *ColumnInfo) Dump(buffer []byte, d *resultEncoder) []byte {
buffer = append(buffer, column.Decimal)
buffer = append(buffer, 0, 0)

if column.DefaultValue != nil {
buffer = dumpUint64(buffer, uint64(len(column.DefaultValue)))
buffer = append(buffer, column.DefaultValue...)
if withDefault {
switch column.DefaultValue {
case "CURRENT_TIMESTAMP", "CURRENT_DATE", nil:
buffer = append(buffer, 251) // NULL
default:
defaultValStr := fmt.Sprintf("%v", column.DefaultValue)
buffer = dumpLengthEncodedString(buffer, []byte(defaultValStr))
}
}

return buffer
Expand Down
77 changes: 51 additions & 26 deletions server/column_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,47 @@ import (

func TestDumpColumn(t *testing.T) {
info := ColumnInfo{
Schema: "testSchema",
Table: "testTable",
OrgTable: "testOrgTable",
Name: "testName",
OrgName: "testOrgName",
ColumnLength: 1,
Charset: 106,
Flag: 0,
Decimal: 1,
Type: 14,
DefaultValueLength: 2,
DefaultValue: []byte{5, 2},
Schema: "testSchema",
Table: "testTable",
OrgTable: "testOrgTable",
Name: "testName",
OrgName: "testOrgName",
ColumnLength: 1,
Charset: 106,
Flag: 0,
Decimal: 1,
Type: 14,
DefaultValue: []byte{5, 2},
}
r := info.Dump(nil, nil)
exp := []byte{0x3, 0x64, 0x65, 0x66, 0xa, 0x74, 0x65, 0x73, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x9, 0x74, 0x65, 0x73, 0x74, 0x54, 0x61, 0x62, 0x6c, 0x65, 0xc, 0x74, 0x65, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x8, 0x74, 0x65, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0xb, 0x74, 0x65, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x4e, 0x61, 0x6d, 0x65, 0xc, 0x6a, 0x0, 0x1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x1, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0x2}
exp := []byte{0x3, 0x64, 0x65, 0x66, 0xa, 0x74, 0x65, 0x73, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x9, 0x74, 0x65, 0x73, 0x74, 0x54, 0x61, 0x62, 0x6c, 0x65, 0xc, 0x74, 0x65, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x8, 0x74, 0x65, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0xb, 0x74, 0x65, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x4e, 0x61, 0x6d, 0x65, 0xc, 0x6a, 0x0, 0x1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x1, 0x0, 0x0}
require.Equal(t, exp, r)

require.Equal(t, uint16(mysql.SetFlag), dumpFlag(mysql.TypeSet, 0))
require.Equal(t, uint16(mysql.EnumFlag), dumpFlag(mysql.TypeEnum, 0))
require.Equal(t, uint16(0), dumpFlag(mysql.TypeString, 0))

require.Equal(t, mysql.TypeString, dumpType(mysql.TypeSet))
require.Equal(t, mysql.TypeString, dumpType(mysql.TypeEnum))
require.Equal(t, mysql.TypeBit, dumpType(mysql.TypeBit))
}

func TestDumpColumnWithDefault(t *testing.T) {
info := ColumnInfo{
Schema: "testSchema",
Table: "testTable",
OrgTable: "testOrgTable",
Name: "testName",
OrgName: "testOrgName",
ColumnLength: 1,
Charset: 106,
Flag: 0,
Decimal: 1,
Type: 14,
DefaultValue: "test",
}
r := info.DumpWithDefault(nil, nil)
exp := []byte{0x3, 0x64, 0x65, 0x66, 0xa, 0x74, 0x65, 0x73, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x9, 0x74, 0x65, 0x73, 0x74, 0x54, 0x61, 0x62, 0x6c, 0x65, 0xc, 0x74, 0x65, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x8, 0x74, 0x65, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0xb, 0x74, 0x65, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x4e, 0x61, 0x6d, 0x65, 0xc, 0x6a, 0x0, 0x1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x1, 0x0, 0x0, 0x4, 0x74, 0x65, 0x73, 0x74}
require.Equal(t, exp, r)

require.Equal(t, uint16(mysql.SetFlag), dumpFlag(mysql.TypeSet, 0))
Expand All @@ -55,20 +81,19 @@ func TestColumnNameLimit(t *testing.T) {
aLongName = append(aLongName, 'a')
}
info := ColumnInfo{
Schema: "testSchema",
Table: "testTable",
OrgTable: "testOrgTable",
Name: string(aLongName),
OrgName: "testOrgName",
ColumnLength: 1,
Charset: 106,
Flag: 0,
Decimal: 1,
Type: 14,
DefaultValueLength: 2,
DefaultValue: []byte{5, 2},
Schema: "testSchema",
Table: "testTable",
OrgTable: "testOrgTable",
Name: string(aLongName),
OrgName: "testOrgName",
ColumnLength: 1,
Charset: 106,
Flag: 0,
Decimal: 1,
Type: 14,
DefaultValue: []byte{5, 2},
}
r := info.Dump(nil, nil)
exp := []byte{0x3, 0x64, 0x65, 0x66, 0xa, 0x74, 0x65, 0x73, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x9, 0x74, 0x65, 0x73, 0x74, 0x54, 0x61, 0x62, 0x6c, 0x65, 0xc, 0x74, 0x65, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x54, 0x61, 0x62, 0x6c, 0x65, 0xfc, 0x0, 0x1, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0xb, 0x74, 0x65, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x4e, 0x61, 0x6d, 0x65, 0xc, 0x6a, 0x0, 0x1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x1, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0x2}
exp := []byte{0x3, 0x64, 0x65, 0x66, 0xa, 0x74, 0x65, 0x73, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x9, 0x74, 0x65, 0x73, 0x74, 0x54, 0x61, 0x62, 0x6c, 0x65, 0xc, 0x74, 0x65, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x54, 0x61, 0x62, 0x6c, 0x65, 0xfc, 0x0, 0x1, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0xb, 0x74, 0x65, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x4e, 0x61, 0x6d, 0x65, 0xc, 0x6a, 0x0, 0x1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x1, 0x0, 0x0}
require.Equal(t, exp, r)
}
8 changes: 1 addition & 7 deletions server/conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -2104,14 +2104,8 @@ func (cc *clientConn) handleFieldList(ctx context.Context, sql string) (err erro
cc.initResultEncoder(ctx)
defer cc.rsEncoder.clean()
for _, column := range columns {
// Current we doesn't output defaultValue but reserve defaultValue length byte to make mariadb client happy.
// https://dev.mysql.com/doc/internals/en/com-query-response.html#column-definition
// TODO: fill the right DefaultValues.
column.DefaultValueLength = 0
column.DefaultValue = []byte{}

data = data[0:4]
data = column.Dump(data, cc.rsEncoder)
data = column.DumpWithDefault(data, cc.rsEncoder)
if err := cc.writePacket(data); err != nil {
return err
}
Expand Down
9 changes: 4 additions & 5 deletions server/conn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -429,9 +429,9 @@ func TestDispatch(t *testing.T) {
in: []byte("t"),
err: nil,
out: []byte{
0x26, 0x0, 0x0, 0xc, 0x3, 0x64, 0x65, 0x66, 0x4, 0x74, 0x65, 0x73, 0x74, 0x1, 0x74,
0x1f, 0x0, 0x0, 0xc, 0x3, 0x64, 0x65, 0x66, 0x4, 0x74, 0x65, 0x73, 0x74, 0x1, 0x74,
0x1, 0x74, 0x1, 0x61, 0x1, 0x61, 0xc, 0x3f, 0x0, 0xb, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0xd, 0xfe,
0x0, 0x0, 0x0, 0xfb, 0x1, 0x0, 0x0, 0xd, 0xfe,
},
},
{
Expand Down Expand Up @@ -549,10 +549,9 @@ func TestDispatchClientProtocol41(t *testing.T) {
in: []byte("t"),
err: nil,
out: []byte{
0x26, 0x0, 0x0, 0xc, 0x3, 0x64, 0x65, 0x66, 0x4, 0x74, 0x65, 0x73, 0x74, 0x1, 0x74,
0x1f, 0x0, 0x0, 0xc, 0x3, 0x64, 0x65, 0x66, 0x4, 0x74, 0x65, 0x73, 0x74, 0x1, 0x74,
0x1, 0x74, 0x1, 0x61, 0x1, 0x61, 0xc, 0x3f, 0x0, 0xb, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0xd, 0xfe,
0x0, 0x0, 0x2, 0x0,
0x0, 0x0, 0x0, 0xfb, 0x5, 0x0, 0x0, 0x0d, 0xfe, 0x0, 0x0, 0x2, 0x0,
},
},
{
Expand Down
15 changes: 8 additions & 7 deletions server/driver_tidb.go
Original file line number Diff line number Diff line change
Expand Up @@ -522,13 +522,14 @@ func unwrapResultSet(rs ResultSet) ResultSet {

func convertColumnInfo(fld *ast.ResultField) (ci *ColumnInfo) {
ci = &ColumnInfo{
Name: fld.ColumnAsName.O,
OrgName: fld.Column.Name.O,
Table: fld.TableAsName.O,
Schema: fld.DBName.O,
Flag: uint16(fld.Column.GetFlag()),
Charset: uint16(mysql.CharsetNameToID(fld.Column.GetCharset())),
Type: fld.Column.GetType(),
Name: fld.ColumnAsName.O,
OrgName: fld.Column.Name.O,
Table: fld.TableAsName.O,
Schema: fld.DBName.O,
Flag: uint16(fld.Column.GetFlag()),
Charset: uint16(mysql.CharsetNameToID(fld.Column.GetCharset())),
Type: fld.Column.GetType(),
DefaultValue: fld.Column.GetDefaultValue(),
}

if fld.Table != nil {
Expand Down
23 changes: 11 additions & 12 deletions server/driver_tidb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,17 @@ import (

func createColumnByTypeAndLen(tp byte, cl uint32) *ColumnInfo {
return &ColumnInfo{
Schema: "test",
Table: "dual",
OrgTable: "",
Name: "a",
OrgName: "a",
ColumnLength: cl,
Charset: uint16(mysql.CharsetNameToID(charset.CharsetUTF8)),
Flag: uint16(mysql.UnsignedFlag),
Decimal: uint8(0),
Type: tp,
DefaultValueLength: uint64(0),
DefaultValue: nil,
Schema: "test",
Table: "dual",
OrgTable: "",
Name: "a",
OrgName: "a",
ColumnLength: cl,
Charset: uint16(mysql.CharsetNameToID(charset.CharsetUTF8)),
Flag: uint16(mysql.UnsignedFlag),
Decimal: uint8(0),
Type: tp,
DefaultValue: nil,
}
}
func TestConvertColumnInfo(t *testing.T) {
Expand Down

0 comments on commit 262ebd5

Please sign in to comment.