Browse Source

connection: interpolate uint64 parameters (#955)

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`.
Vicent Martí 6 years ago
parent
commit
d0a5481819
2 changed files with 21 additions and 0 deletions
  1. 3 0
      connection.go
  2. 18 0
      connection_test.go

+ 3 - 0
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:

+ 18 - 0
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{}