mirror of https://github.com/jackc/pgx.git
Special case the underlying type of []byte
Underlying types were already tried. But []byte is not a normal underlying type. It is a slice. But since is can be treated as a scalar instead of an array / slice we need to special case it. https://github.com/jackc/pgx/issues/1763pull/1769/head
parent
8a09979417
commit
45f807fdb4
|
@ -1358,6 +1358,8 @@ var kindToTypes map[reflect.Kind]reflect.Type = map[reflect.Kind]reflect.Type{
|
||||||
reflect.Bool: reflect.TypeOf(false),
|
reflect.Bool: reflect.TypeOf(false),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var byteSliceType = reflect.TypeOf([]byte{})
|
||||||
|
|
||||||
type underlyingTypeEncodePlan struct {
|
type underlyingTypeEncodePlan struct {
|
||||||
nextValueType reflect.Type
|
nextValueType reflect.Type
|
||||||
next EncodePlan
|
next EncodePlan
|
||||||
|
@ -1372,6 +1374,10 @@ func (plan *underlyingTypeEncodePlan) Encode(value any, buf []byte) (newBuf []by
|
||||||
// TryWrapFindUnderlyingTypeEncodePlan tries to convert to a Go builtin type. e.g. If value was of type MyString and
|
// TryWrapFindUnderlyingTypeEncodePlan tries to convert to a Go builtin type. e.g. If value was of type MyString and
|
||||||
// MyString was defined as a string then a wrapper plan would be returned that converts MyString to string.
|
// MyString was defined as a string then a wrapper plan would be returned that converts MyString to string.
|
||||||
func TryWrapFindUnderlyingTypeEncodePlan(value any) (plan WrappedEncodePlanNextSetter, nextValue any, ok bool) {
|
func TryWrapFindUnderlyingTypeEncodePlan(value any) (plan WrappedEncodePlanNextSetter, nextValue any, ok bool) {
|
||||||
|
if value == nil {
|
||||||
|
return nil, nil, false
|
||||||
|
}
|
||||||
|
|
||||||
if _, ok := value.(driver.Valuer); ok {
|
if _, ok := value.(driver.Valuer); ok {
|
||||||
return nil, nil, false
|
return nil, nil, false
|
||||||
}
|
}
|
||||||
|
@ -1387,6 +1393,15 @@ func TryWrapFindUnderlyingTypeEncodePlan(value any) (plan WrappedEncodePlanNextS
|
||||||
return &underlyingTypeEncodePlan{nextValueType: nextValueType}, refValue.Convert(nextValueType).Interface(), true
|
return &underlyingTypeEncodePlan{nextValueType: nextValueType}, refValue.Convert(nextValueType).Interface(), true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// []byte is a special case. It is a slice but we treat it as a scalar type. In the case of a named type like
|
||||||
|
// json.RawMessage which is defined as []byte the underlying type should be considered as []byte. But any other slice
|
||||||
|
// does not have a special underlying type.
|
||||||
|
//
|
||||||
|
// https://github.com/jackc/pgx/issues/1763
|
||||||
|
if refValue.Type() != byteSliceType && refValue.Type().AssignableTo(byteSliceType) {
|
||||||
|
return &underlyingTypeEncodePlan{nextValueType: byteSliceType}, refValue.Convert(byteSliceType).Interface(), true
|
||||||
|
}
|
||||||
|
|
||||||
return nil, nil, false
|
return nil, nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"database/sql/driver"
|
"database/sql/driver"
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
@ -417,6 +418,14 @@ func TestMapEncodeByteSliceIntoUnregisteredTypeTextFormat(t *testing.T) {
|
||||||
require.Equal(t, []byte(`\x00010203`), buf)
|
require.Equal(t, []byte(`\x00010203`), buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://github.com/jackc/pgx/issues/1763
|
||||||
|
func TestMapEncodeNamedTypeOfByteSliceIntoTextTextFormat(t *testing.T) {
|
||||||
|
m := pgtype.NewMap()
|
||||||
|
buf, err := m.Encode(pgtype.TextOID, pgtype.TextFormatCode, json.RawMessage(`{"foo": "bar"}`), nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, []byte(`{"foo": "bar"}`), buf)
|
||||||
|
}
|
||||||
|
|
||||||
// https://github.com/jackc/pgx/issues/1326
|
// https://github.com/jackc/pgx/issues/1326
|
||||||
func TestMapScanPointerToRenamedType(t *testing.T) {
|
func TestMapScanPointerToRenamedType(t *testing.T) {
|
||||||
srcBuf := []byte("foo")
|
srcBuf := []byte("foo")
|
||||||
|
|
Loading…
Reference in New Issue