From f285a0ff4a054fa54bc377fac972b259f212a0b3 Mon Sep 17 00:00:00 2001 From: Bas Toonk Date: Fri, 22 Jul 2022 08:36:17 +0200 Subject: [PATCH 1/2] fix: return null values properly in proxy mode --- server/resp.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/server/resp.go b/server/resp.go index abe04c774..f7f395d8b 100644 --- a/server/resp.go +++ b/server/resp.go @@ -182,11 +182,16 @@ func (c *Conn) writeFieldList(fs []*Field, data []byte) error { func (c *Conn) writeFieldValues(fv []FieldValue) error { data := make([]byte, 4, 1024) for _, v := range fv { - tv, err := FormatTextValue(v.Value()) - if err != nil { - return err + if v.Value() == nil { + // NULL value is encoded as 0xfb here + data = append(data, []byte{0xfb}...) + } else { + tv, err := FormatTextValue(v.Value()) + if err != nil { + return err + } + data = append(data, PutLengthEncodedString(tv)...) } - data = append(data, PutLengthEncodedString(tv)...) } return c.WritePacket(data) From 3d92d36c3862bf211e6578fc765e2fe412507f6b Mon Sep 17 00:00:00 2001 From: Bas Toonk Date: Wed, 17 Aug 2022 10:50:18 +0200 Subject: [PATCH 2/2] test writeFieldValues with null value --- server/resp_test.go | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/server/resp_test.go b/server/resp_test.go index d64f59df3..9256a41ec 100644 --- a/server/resp_test.go +++ b/server/resp_test.go @@ -189,3 +189,43 @@ func (t *respConnTestSuite) TestConnWriteFieldList(c *check.C) { c.Assert(clientConn.WriteBuffered[:27], check.BytesEquals, []byte{23, 0, 0, 0, 3, 100, 101, 102, 0, 0, 0, 1, 'c', 0, 12, 33, 0, 0, 0, 0, 0, 253, 0, 0, 0, 0, 0}) c.Assert(clientConn.WriteBuffered[27:], check.BytesEquals, []byte{1, 0, 0, 1, mysql.EOF_HEADER}) } + +func (t *respConnTestSuite) TestConnWriteFieldValues(c *check.C) { + clientConn := &mockconn.MockConn{MultiWrite: true} + conn := &Conn{Conn: packet.NewConn(clientConn)} + + r, err := mysql.BuildSimpleTextResultset([]string{"c"}, [][]interface{}{ + []interface{}{"d"}, + []interface{}{nil}, + }) + + c.Assert(err, check.IsNil) + err = conn.writeFieldList(r.Fields, nil) + c.Assert(err, check.IsNil) + + // fields and EOF + c.Assert(clientConn.WriteBuffered[:27], check.BytesEquals, []byte{23, 0, 0, 0, 3, 100, 101, 102, 0, 0, 0, 1, 'c', 0, 12, 33, 0, 0, 0, 0, 0, 253, 0, 0, 0, 0, 0}) + c.Assert(clientConn.WriteBuffered[27:32], check.BytesEquals, []byte{1, 0, 0, 1, mysql.EOF_HEADER}) + + r.Values = make([][]mysql.FieldValue, len(r.RowDatas)) + for i := range r.Values { + r.Values[i], err = r.RowDatas[i].Parse(r.Fields, false, r.Values[i]) + + c.Assert(err, check.IsNil) + + err = conn.writeFieldValues(r.Values[i]) + c.Assert(err, check.IsNil) + } + + err = conn.writeEOF() + c.Assert(err, check.IsNil) + + // first row + c.Assert(clientConn.WriteBuffered[32:38], check.BytesEquals, []byte{2, 0, 0, 2, 1, 'd'}) + + // second row with NULL value + c.Assert(clientConn.WriteBuffered[38:43], check.BytesEquals, []byte{1, 0, 0, 3, 251}) + + // EOF + c.Assert(clientConn.WriteBuffered[43:], check.BytesEquals, []byte{1, 0, 0, 4, mysql.EOF_HEADER}) +}