Skip to content

Commit 18bdf5f

Browse files
vitessdriver: send string for binary result values (#19542)
Signed-off-by: Derek Perkins <derek@nozzle.io>
1 parent 0a8836e commit 18bdf5f

5 files changed

Lines changed: 235 additions & 392 deletions

File tree

go/vt/vitessdriver/convert.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,6 @@ func (cv *converter) ToNative(v sqltypes.Value) (any, error) {
4545
return v.ToFloat64()
4646
case v.Type() == sqltypes.Datetime, v.Type() == sqltypes.Timestamp, v.Type() == sqltypes.Date:
4747
return v.ToTime(cv.location)
48-
case v.IsBinary():
49-
// sending through string values matches the behavior in go-sql-driver and
50-
// is necessary for json values to be handled without erroring in vttablet.
51-
out = v.ToString()
5248
case v.IsQuoted() || v.Type() == sqltypes.Bit || v.Type() == sqltypes.Decimal:
5349
out, err = v.ToBytes()
5450
case v.Type() == sqltypes.Expression:
@@ -58,10 +54,19 @@ func (cv *converter) ToNative(v sqltypes.Value) (any, error) {
5854
}
5955

6056
func (cv *converter) BuildBindVariable(v any) (*querypb.BindVariable, error) {
61-
if t, ok := v.(time.Time); ok {
57+
switch t := v.(type) {
58+
case time.Time:
6259
return sqltypes.ValueBindVariable(NewDatetime(t, cv.location)), nil
60+
case []byte:
61+
if t == nil {
62+
return sqltypes.NullBindVariable, nil
63+
}
64+
// sending through string values matches the behavior in go-sql-driver and
65+
// is necessary for json values to be handled without erroring in vttablet.
66+
return sqltypes.StringBindVariable(string(t)), nil
67+
default:
68+
return sqltypes.BuildBindVariable(v)
6369
}
64-
return sqltypes.BuildBindVariable(v)
6570
}
6671

6772
// populateRow populates a row of data using the table's field descriptions.

go/vt/vitessdriver/convert_test.go

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,13 @@ limitations under the License.
1717
package vitessdriver
1818

1919
import (
20-
"reflect"
2120
"testing"
2221
"time"
2322

23+
"github.com/stretchr/testify/require"
24+
2425
"vitess.io/vitess/go/sqltypes"
26+
querypb "vitess.io/vitess/go/vt/proto/query"
2527
)
2628

2729
func TestToNative(t *testing.T) {
@@ -147,7 +149,7 @@ func TestToNative(t *testing.T) {
147149
{
148150
convert: &converter{},
149151
in: sqltypes.TestValue(sqltypes.Blob, "a"),
150-
out: "a",
152+
out: []byte("a"),
151153
},
152154
{
153155
convert: &converter{},
@@ -157,7 +159,7 @@ func TestToNative(t *testing.T) {
157159
{
158160
convert: &converter{},
159161
in: sqltypes.TestValue(sqltypes.VarBinary, "a"),
160-
out: "a",
162+
out: []byte("a"),
161163
},
162164
{
163165
convert: &converter{},
@@ -167,7 +169,7 @@ func TestToNative(t *testing.T) {
167169
{
168170
convert: &converter{},
169171
in: sqltypes.TestValue(sqltypes.Binary, "a"),
170-
out: "a",
172+
out: []byte("a"),
171173
},
172174
{
173175
convert: &converter{},
@@ -193,11 +195,53 @@ func TestToNative(t *testing.T) {
193195

194196
for _, tcase := range testcases {
195197
v, err := tcase.convert.ToNative(tcase.in)
196-
if err != nil {
197-
t.Error(err)
198-
}
199-
if !reflect.DeepEqual(v, tcase.out) {
200-
t.Errorf("%v.ToNativeEx = %#v, want %#v", tcase.in, v, tcase.out)
201-
}
198+
require.NoError(t, err)
199+
require.Equal(t, tcase.out, v)
200+
}
201+
}
202+
203+
func TestBuildBindVariable(t *testing.T) {
204+
testcases := []struct {
205+
name string
206+
in any
207+
out *querypb.BindVariable
208+
}{
209+
{
210+
name: "json bytes become varchar",
211+
in: []byte("[]"),
212+
out: sqltypes.StringBindVariable("[]"),
213+
},
214+
{
215+
name: "binary bytes become varchar",
216+
in: []byte{0x00, 0xff},
217+
out: &querypb.BindVariable{
218+
Type: querypb.Type_VARCHAR,
219+
Value: []byte{0x00, 0xff},
220+
},
221+
},
222+
{
223+
name: "nil bytes become null",
224+
in: []byte(nil),
225+
out: sqltypes.NullBindVariable,
226+
},
227+
{
228+
name: "empty bytes become empty varchar",
229+
in: []byte{},
230+
out: sqltypes.StringBindVariable(""),
231+
},
232+
{
233+
name: "time becomes datetime",
234+
in: time.Date(2012, 0o2, 24, 23, 19, 43, 0, time.UTC),
235+
out: sqltypes.ValueBindVariable(sqltypes.TestValue(sqltypes.Datetime, "2012-02-24 23:19:43")),
236+
},
237+
}
238+
239+
convert := &converter{location: time.UTC}
240+
for _, tcase := range testcases {
241+
t.Run(tcase.name, func(t *testing.T) {
242+
bv, err := convert.BuildBindVariable(tcase.in)
243+
require.NoError(t, err)
244+
require.Equal(t, tcase.out, bv)
245+
})
202246
}
203247
}

0 commit comments

Comments
 (0)