From f7ba29f4ee8fd6d2af78d671afef3154859d239a Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Tue, 23 Apr 2019 13:00:47 +0200 Subject: [PATCH] connection: interpolate uint64 parameters PR #838 introduced a fix for the driver's custom Value Converter that stopped emitting large uint64 `driver.Value`s as a string. Instead, now _all_ uint{8,16,32,64} values passed to the driver are returned as uint64, and `packets.c` now explicitly handles `driver.Value` instances that are uint64. However, the update in `packets.c` only applies when sending `driver.Value` arguments to the server. When a connection is set up using `InterpolateParams = true` and query interpolation happens inside of the driver, the `(*mysqlConn) interpolateParams` does **not** handle uint64 values (which, again, are now passed by `database/sql` because we've updated our value converter to generate them). Because of this, any `DB.Query` operations which have an uint argument (regardless of its size!!) will force the driver to return `driver.ErrSkip`, disabling client interpolation for such queries. We can fix this by updating `interpolateParams` like we previously updated `writeExecutePacket`. --- connection.go | 3 +++ connection_test.go | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/connection.go b/connection.go index 265fd4e47..565a5480a 100644 --- a/connection.go +++ b/connection.go @@ -213,6 +213,9 @@ func (mc *mysqlConn) interpolateParams(query string, args []driver.Value) (strin switch v := arg.(type) { case int64: buf = strconv.AppendInt(buf, v, 10) + case uint64: + // Handle uint64 explicitly because our custom ConvertValue emits unsigned values + buf = strconv.AppendUint(buf, v, 10) case float64: buf = strconv.AppendFloat(buf, v, 'g', -1, 64) case bool: diff --git a/connection_test.go b/connection_test.go index 8e78f36c6..19c17ff8b 100644 --- a/connection_test.go +++ b/connection_test.go @@ -69,6 +69,24 @@ func TestInterpolateParamsPlaceholderInString(t *testing.T) { } } +func TestInterpolateParamsUint64(t *testing.T) { + mc := &mysqlConn{ + buf: newBuffer(nil), + maxAllowedPacket: maxPacketSize, + cfg: &Config{ + InterpolateParams: true, + }, + } + + q, err := mc.interpolateParams("SELECT ?", []driver.Value{uint64(42)}) + if err != nil { + t.Errorf("Expected err=nil, got err=%#v, q=%#v", err, q) + } + if q != "SELECT 42" { + t.Errorf("Expected uint64 interpolation to work, got q=%#v", q) + } +} + func TestCheckNamedValue(t *testing.T) { value := driver.NamedValue{Value: ^uint64(0)} x := &mysqlConn{}