Add text to pgtype
This commit is contained in:
@@ -40,6 +40,13 @@ func TestParseUntypedTextArray(t *testing.T) {
|
|||||||
Dimensions: []pgtype.ArrayDimension{{Length: 1, LowerBound: 1}},
|
Dimensions: []pgtype.ArrayDimension{{Length: 1, LowerBound: 1}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
source: `{""}`,
|
||||||
|
result: pgtype.UntypedTextArray{
|
||||||
|
Elements: []string{""},
|
||||||
|
Dimensions: []pgtype.ArrayDimension{{Length: 1, LowerBound: 1}},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
source: `{"He said, \"Hello.\""}`,
|
source: `{"He said, \"Hello.\""}`,
|
||||||
result: pgtype.UntypedTextArray{
|
result: pgtype.UntypedTextArray{
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ func (src *Bool) AssignTo(dst interface{}) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fmt.Errorf("cannot put decode %v into %T", src, dst)
|
return fmt.Errorf("cannot decode %v into %T", src, dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
+5
-5
@@ -18,7 +18,7 @@ func (dst *BoolArray) ConvertFrom(src interface{}) error {
|
|||||||
switch value := src.(type) {
|
switch value := src.(type) {
|
||||||
case BoolArray:
|
case BoolArray:
|
||||||
*dst = value
|
*dst = value
|
||||||
|
|
||||||
case []bool:
|
case []bool:
|
||||||
if value == nil {
|
if value == nil {
|
||||||
*dst = BoolArray{Status: Null}
|
*dst = BoolArray{Status: Null}
|
||||||
@@ -37,7 +37,7 @@ func (dst *BoolArray) ConvertFrom(src interface{}) error {
|
|||||||
Status: Present,
|
Status: Present,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if originalSrc, ok := underlyingSliceType(src); ok {
|
if originalSrc, ok := underlyingSliceType(src); ok {
|
||||||
return dst.ConvertFrom(originalSrc)
|
return dst.ConvertFrom(originalSrc)
|
||||||
@@ -50,7 +50,7 @@ func (dst *BoolArray) ConvertFrom(src interface{}) error {
|
|||||||
|
|
||||||
func (src *BoolArray) AssignTo(dst interface{}) error {
|
func (src *BoolArray) AssignTo(dst interface{}) error {
|
||||||
switch v := dst.(type) {
|
switch v := dst.(type) {
|
||||||
|
|
||||||
case *[]bool:
|
case *[]bool:
|
||||||
if src.Status == Present {
|
if src.Status == Present {
|
||||||
*v = make([]bool, len(src.Elements))
|
*v = make([]bool, len(src.Elements))
|
||||||
@@ -62,12 +62,12 @@ func (src *BoolArray) AssignTo(dst interface{}) error {
|
|||||||
} else {
|
} else {
|
||||||
*v = nil
|
*v = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if originalDst, ok := underlyingPtrSliceType(dst); ok {
|
if originalDst, ok := underlyingPtrSliceType(dst); ok {
|
||||||
return src.AssignTo(originalDst)
|
return src.AssignTo(originalDst)
|
||||||
}
|
}
|
||||||
return fmt.Errorf("cannot put decode %v into %T", src, dst)
|
return fmt.Errorf("cannot decode %v into %T", src, dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
+19
@@ -85,6 +85,25 @@ func underlyingBoolType(val interface{}) (interface{}, bool) {
|
|||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// underlyingStringType gets the underlying type that can be converted to String
|
||||||
|
func underlyingStringType(val interface{}) (interface{}, bool) {
|
||||||
|
refVal := reflect.ValueOf(val)
|
||||||
|
|
||||||
|
switch refVal.Kind() {
|
||||||
|
case reflect.Ptr:
|
||||||
|
if refVal.IsNil() {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
convVal := refVal.Elem().Interface()
|
||||||
|
return convVal, true
|
||||||
|
case reflect.String:
|
||||||
|
convVal := refVal.String()
|
||||||
|
return convVal, reflect.TypeOf(convVal) != refVal.Type()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
// underlyingPtrType dereferences a pointer
|
// underlyingPtrType dereferences a pointer
|
||||||
func underlyingPtrType(val interface{}) (interface{}, bool) {
|
func underlyingPtrType(val interface{}) (interface{}, bool) {
|
||||||
refVal := reflect.ValueOf(val)
|
refVal := reflect.ValueOf(val)
|
||||||
|
|||||||
+1
-1
@@ -68,7 +68,7 @@ func (src *DateArray) AssignTo(dst interface{}) error {
|
|||||||
if originalDst, ok := underlyingPtrSliceType(dst); ok {
|
if originalDst, ok := underlyingPtrSliceType(dst); ok {
|
||||||
return src.AssignTo(originalDst)
|
return src.AssignTo(originalDst)
|
||||||
}
|
}
|
||||||
return fmt.Errorf("cannot put decode %v into %T", src, dst)
|
return fmt.Errorf("cannot decode %v into %T", src, dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
+5
-5
@@ -18,7 +18,7 @@ func (dst *Float4Array) ConvertFrom(src interface{}) error {
|
|||||||
switch value := src.(type) {
|
switch value := src.(type) {
|
||||||
case Float4Array:
|
case Float4Array:
|
||||||
*dst = value
|
*dst = value
|
||||||
|
|
||||||
case []float32:
|
case []float32:
|
||||||
if value == nil {
|
if value == nil {
|
||||||
*dst = Float4Array{Status: Null}
|
*dst = Float4Array{Status: Null}
|
||||||
@@ -37,7 +37,7 @@ func (dst *Float4Array) ConvertFrom(src interface{}) error {
|
|||||||
Status: Present,
|
Status: Present,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if originalSrc, ok := underlyingSliceType(src); ok {
|
if originalSrc, ok := underlyingSliceType(src); ok {
|
||||||
return dst.ConvertFrom(originalSrc)
|
return dst.ConvertFrom(originalSrc)
|
||||||
@@ -50,7 +50,7 @@ func (dst *Float4Array) ConvertFrom(src interface{}) error {
|
|||||||
|
|
||||||
func (src *Float4Array) AssignTo(dst interface{}) error {
|
func (src *Float4Array) AssignTo(dst interface{}) error {
|
||||||
switch v := dst.(type) {
|
switch v := dst.(type) {
|
||||||
|
|
||||||
case *[]float32:
|
case *[]float32:
|
||||||
if src.Status == Present {
|
if src.Status == Present {
|
||||||
*v = make([]float32, len(src.Elements))
|
*v = make([]float32, len(src.Elements))
|
||||||
@@ -62,12 +62,12 @@ func (src *Float4Array) AssignTo(dst interface{}) error {
|
|||||||
} else {
|
} else {
|
||||||
*v = nil
|
*v = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if originalDst, ok := underlyingPtrSliceType(dst); ok {
|
if originalDst, ok := underlyingPtrSliceType(dst); ok {
|
||||||
return src.AssignTo(originalDst)
|
return src.AssignTo(originalDst)
|
||||||
}
|
}
|
||||||
return fmt.Errorf("cannot put decode %v into %T", src, dst)
|
return fmt.Errorf("cannot decode %v into %T", src, dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
+5
-5
@@ -18,7 +18,7 @@ func (dst *Float8Array) ConvertFrom(src interface{}) error {
|
|||||||
switch value := src.(type) {
|
switch value := src.(type) {
|
||||||
case Float8Array:
|
case Float8Array:
|
||||||
*dst = value
|
*dst = value
|
||||||
|
|
||||||
case []float64:
|
case []float64:
|
||||||
if value == nil {
|
if value == nil {
|
||||||
*dst = Float8Array{Status: Null}
|
*dst = Float8Array{Status: Null}
|
||||||
@@ -37,7 +37,7 @@ func (dst *Float8Array) ConvertFrom(src interface{}) error {
|
|||||||
Status: Present,
|
Status: Present,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if originalSrc, ok := underlyingSliceType(src); ok {
|
if originalSrc, ok := underlyingSliceType(src); ok {
|
||||||
return dst.ConvertFrom(originalSrc)
|
return dst.ConvertFrom(originalSrc)
|
||||||
@@ -50,7 +50,7 @@ func (dst *Float8Array) ConvertFrom(src interface{}) error {
|
|||||||
|
|
||||||
func (src *Float8Array) AssignTo(dst interface{}) error {
|
func (src *Float8Array) AssignTo(dst interface{}) error {
|
||||||
switch v := dst.(type) {
|
switch v := dst.(type) {
|
||||||
|
|
||||||
case *[]float64:
|
case *[]float64:
|
||||||
if src.Status == Present {
|
if src.Status == Present {
|
||||||
*v = make([]float64, len(src.Elements))
|
*v = make([]float64, len(src.Elements))
|
||||||
@@ -62,12 +62,12 @@ func (src *Float8Array) AssignTo(dst interface{}) error {
|
|||||||
} else {
|
} else {
|
||||||
*v = nil
|
*v = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if originalDst, ok := underlyingPtrSliceType(dst); ok {
|
if originalDst, ok := underlyingPtrSliceType(dst); ok {
|
||||||
return src.AssignTo(originalDst)
|
return src.AssignTo(originalDst)
|
||||||
}
|
}
|
||||||
return fmt.Errorf("cannot put decode %v into %T", src, dst)
|
return fmt.Errorf("cannot decode %v into %T", src, dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
+1
-1
@@ -97,7 +97,7 @@ func (src *InetArray) AssignTo(dst interface{}) error {
|
|||||||
if originalDst, ok := underlyingPtrSliceType(dst); ok {
|
if originalDst, ok := underlyingPtrSliceType(dst); ok {
|
||||||
return src.AssignTo(originalDst)
|
return src.AssignTo(originalDst)
|
||||||
}
|
}
|
||||||
return fmt.Errorf("cannot put decode %v into %T", src, dst)
|
return fmt.Errorf("cannot decode %v into %T", src, dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
+7
-7
@@ -18,7 +18,7 @@ func (dst *Int2Array) ConvertFrom(src interface{}) error {
|
|||||||
switch value := src.(type) {
|
switch value := src.(type) {
|
||||||
case Int2Array:
|
case Int2Array:
|
||||||
*dst = value
|
*dst = value
|
||||||
|
|
||||||
case []int16:
|
case []int16:
|
||||||
if value == nil {
|
if value == nil {
|
||||||
*dst = Int2Array{Status: Null}
|
*dst = Int2Array{Status: Null}
|
||||||
@@ -37,7 +37,7 @@ func (dst *Int2Array) ConvertFrom(src interface{}) error {
|
|||||||
Status: Present,
|
Status: Present,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case []uint16:
|
case []uint16:
|
||||||
if value == nil {
|
if value == nil {
|
||||||
*dst = Int2Array{Status: Null}
|
*dst = Int2Array{Status: Null}
|
||||||
@@ -56,7 +56,7 @@ func (dst *Int2Array) ConvertFrom(src interface{}) error {
|
|||||||
Status: Present,
|
Status: Present,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if originalSrc, ok := underlyingSliceType(src); ok {
|
if originalSrc, ok := underlyingSliceType(src); ok {
|
||||||
return dst.ConvertFrom(originalSrc)
|
return dst.ConvertFrom(originalSrc)
|
||||||
@@ -69,7 +69,7 @@ func (dst *Int2Array) ConvertFrom(src interface{}) error {
|
|||||||
|
|
||||||
func (src *Int2Array) AssignTo(dst interface{}) error {
|
func (src *Int2Array) AssignTo(dst interface{}) error {
|
||||||
switch v := dst.(type) {
|
switch v := dst.(type) {
|
||||||
|
|
||||||
case *[]int16:
|
case *[]int16:
|
||||||
if src.Status == Present {
|
if src.Status == Present {
|
||||||
*v = make([]int16, len(src.Elements))
|
*v = make([]int16, len(src.Elements))
|
||||||
@@ -81,7 +81,7 @@ func (src *Int2Array) AssignTo(dst interface{}) error {
|
|||||||
} else {
|
} else {
|
||||||
*v = nil
|
*v = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
case *[]uint16:
|
case *[]uint16:
|
||||||
if src.Status == Present {
|
if src.Status == Present {
|
||||||
*v = make([]uint16, len(src.Elements))
|
*v = make([]uint16, len(src.Elements))
|
||||||
@@ -93,12 +93,12 @@ func (src *Int2Array) AssignTo(dst interface{}) error {
|
|||||||
} else {
|
} else {
|
||||||
*v = nil
|
*v = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if originalDst, ok := underlyingPtrSliceType(dst); ok {
|
if originalDst, ok := underlyingPtrSliceType(dst); ok {
|
||||||
return src.AssignTo(originalDst)
|
return src.AssignTo(originalDst)
|
||||||
}
|
}
|
||||||
return fmt.Errorf("cannot put decode %v into %T", src, dst)
|
return fmt.Errorf("cannot decode %v into %T", src, dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
+7
-7
@@ -18,7 +18,7 @@ func (dst *Int4Array) ConvertFrom(src interface{}) error {
|
|||||||
switch value := src.(type) {
|
switch value := src.(type) {
|
||||||
case Int4Array:
|
case Int4Array:
|
||||||
*dst = value
|
*dst = value
|
||||||
|
|
||||||
case []int32:
|
case []int32:
|
||||||
if value == nil {
|
if value == nil {
|
||||||
*dst = Int4Array{Status: Null}
|
*dst = Int4Array{Status: Null}
|
||||||
@@ -37,7 +37,7 @@ func (dst *Int4Array) ConvertFrom(src interface{}) error {
|
|||||||
Status: Present,
|
Status: Present,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case []uint32:
|
case []uint32:
|
||||||
if value == nil {
|
if value == nil {
|
||||||
*dst = Int4Array{Status: Null}
|
*dst = Int4Array{Status: Null}
|
||||||
@@ -56,7 +56,7 @@ func (dst *Int4Array) ConvertFrom(src interface{}) error {
|
|||||||
Status: Present,
|
Status: Present,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if originalSrc, ok := underlyingSliceType(src); ok {
|
if originalSrc, ok := underlyingSliceType(src); ok {
|
||||||
return dst.ConvertFrom(originalSrc)
|
return dst.ConvertFrom(originalSrc)
|
||||||
@@ -69,7 +69,7 @@ func (dst *Int4Array) ConvertFrom(src interface{}) error {
|
|||||||
|
|
||||||
func (src *Int4Array) AssignTo(dst interface{}) error {
|
func (src *Int4Array) AssignTo(dst interface{}) error {
|
||||||
switch v := dst.(type) {
|
switch v := dst.(type) {
|
||||||
|
|
||||||
case *[]int32:
|
case *[]int32:
|
||||||
if src.Status == Present {
|
if src.Status == Present {
|
||||||
*v = make([]int32, len(src.Elements))
|
*v = make([]int32, len(src.Elements))
|
||||||
@@ -81,7 +81,7 @@ func (src *Int4Array) AssignTo(dst interface{}) error {
|
|||||||
} else {
|
} else {
|
||||||
*v = nil
|
*v = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
case *[]uint32:
|
case *[]uint32:
|
||||||
if src.Status == Present {
|
if src.Status == Present {
|
||||||
*v = make([]uint32, len(src.Elements))
|
*v = make([]uint32, len(src.Elements))
|
||||||
@@ -93,12 +93,12 @@ func (src *Int4Array) AssignTo(dst interface{}) error {
|
|||||||
} else {
|
} else {
|
||||||
*v = nil
|
*v = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if originalDst, ok := underlyingPtrSliceType(dst); ok {
|
if originalDst, ok := underlyingPtrSliceType(dst); ok {
|
||||||
return src.AssignTo(originalDst)
|
return src.AssignTo(originalDst)
|
||||||
}
|
}
|
||||||
return fmt.Errorf("cannot put decode %v into %T", src, dst)
|
return fmt.Errorf("cannot decode %v into %T", src, dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
+7
-7
@@ -18,7 +18,7 @@ func (dst *Int8Array) ConvertFrom(src interface{}) error {
|
|||||||
switch value := src.(type) {
|
switch value := src.(type) {
|
||||||
case Int8Array:
|
case Int8Array:
|
||||||
*dst = value
|
*dst = value
|
||||||
|
|
||||||
case []int64:
|
case []int64:
|
||||||
if value == nil {
|
if value == nil {
|
||||||
*dst = Int8Array{Status: Null}
|
*dst = Int8Array{Status: Null}
|
||||||
@@ -37,7 +37,7 @@ func (dst *Int8Array) ConvertFrom(src interface{}) error {
|
|||||||
Status: Present,
|
Status: Present,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case []uint64:
|
case []uint64:
|
||||||
if value == nil {
|
if value == nil {
|
||||||
*dst = Int8Array{Status: Null}
|
*dst = Int8Array{Status: Null}
|
||||||
@@ -56,7 +56,7 @@ func (dst *Int8Array) ConvertFrom(src interface{}) error {
|
|||||||
Status: Present,
|
Status: Present,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if originalSrc, ok := underlyingSliceType(src); ok {
|
if originalSrc, ok := underlyingSliceType(src); ok {
|
||||||
return dst.ConvertFrom(originalSrc)
|
return dst.ConvertFrom(originalSrc)
|
||||||
@@ -69,7 +69,7 @@ func (dst *Int8Array) ConvertFrom(src interface{}) error {
|
|||||||
|
|
||||||
func (src *Int8Array) AssignTo(dst interface{}) error {
|
func (src *Int8Array) AssignTo(dst interface{}) error {
|
||||||
switch v := dst.(type) {
|
switch v := dst.(type) {
|
||||||
|
|
||||||
case *[]int64:
|
case *[]int64:
|
||||||
if src.Status == Present {
|
if src.Status == Present {
|
||||||
*v = make([]int64, len(src.Elements))
|
*v = make([]int64, len(src.Elements))
|
||||||
@@ -81,7 +81,7 @@ func (src *Int8Array) AssignTo(dst interface{}) error {
|
|||||||
} else {
|
} else {
|
||||||
*v = nil
|
*v = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
case *[]uint64:
|
case *[]uint64:
|
||||||
if src.Status == Present {
|
if src.Status == Present {
|
||||||
*v = make([]uint64, len(src.Elements))
|
*v = make([]uint64, len(src.Elements))
|
||||||
@@ -93,12 +93,12 @@ func (src *Int8Array) AssignTo(dst interface{}) error {
|
|||||||
} else {
|
} else {
|
||||||
*v = nil
|
*v = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if originalDst, ok := underlyingPtrSliceType(dst); ok {
|
if originalDst, ok := underlyingPtrSliceType(dst); ok {
|
||||||
return src.AssignTo(originalDst)
|
return src.AssignTo(originalDst)
|
||||||
}
|
}
|
||||||
return fmt.Errorf("cannot put decode %v into %T", src, dst)
|
return fmt.Errorf("cannot decode %v into %T", src, dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Test for renamed types
|
// Test for renamed types
|
||||||
|
type _string string
|
||||||
type _bool bool
|
type _bool bool
|
||||||
type _int8 int8
|
type _int8 int8
|
||||||
type _int16 int16
|
type _int16 int16
|
||||||
|
|||||||
@@ -0,0 +1,115 @@
|
|||||||
|
package pgtype
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/jackc/pgx/pgio"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Text struct {
|
||||||
|
String string
|
||||||
|
Status Status
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dst *Text) ConvertFrom(src interface{}) error {
|
||||||
|
switch value := src.(type) {
|
||||||
|
case Text:
|
||||||
|
*dst = value
|
||||||
|
case string:
|
||||||
|
*dst = Text{String: value, Status: Present}
|
||||||
|
case *string:
|
||||||
|
if value == nil {
|
||||||
|
*dst = Text{Status: Null}
|
||||||
|
} else {
|
||||||
|
*dst = Text{String: *value, Status: Present}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
if originalSrc, ok := underlyingStringType(src); ok {
|
||||||
|
return dst.ConvertFrom(originalSrc)
|
||||||
|
}
|
||||||
|
return fmt.Errorf("cannot convert %v to Text", value)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (src *Text) AssignTo(dst interface{}) error {
|
||||||
|
switch v := dst.(type) {
|
||||||
|
case *string:
|
||||||
|
if src.Status != Present {
|
||||||
|
return fmt.Errorf("cannot assign %v to %T", src, dst)
|
||||||
|
}
|
||||||
|
*v = src.String
|
||||||
|
default:
|
||||||
|
if v := reflect.ValueOf(dst); v.Kind() == reflect.Ptr {
|
||||||
|
el := v.Elem()
|
||||||
|
switch el.Kind() {
|
||||||
|
// if dst is a pointer to pointer, strip the pointer and try again
|
||||||
|
case reflect.Ptr:
|
||||||
|
if src.Status == Null {
|
||||||
|
el.Set(reflect.Zero(el.Type()))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if el.IsNil() {
|
||||||
|
// allocate destination
|
||||||
|
el.Set(reflect.New(el.Type().Elem()))
|
||||||
|
}
|
||||||
|
return src.AssignTo(el.Interface())
|
||||||
|
case reflect.String:
|
||||||
|
if src.Status != Present {
|
||||||
|
return fmt.Errorf("cannot assign %v to %T", src, dst)
|
||||||
|
}
|
||||||
|
el.SetString(src.String)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fmt.Errorf("cannot decode %v into %T", src, dst)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dst *Text) DecodeText(r io.Reader) error {
|
||||||
|
size, err := pgio.ReadInt32(r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if size == -1 {
|
||||||
|
*dst = Text{Status: Null}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := make([]byte, int(size))
|
||||||
|
_, err = r.Read(buf)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
*dst = Text{String: string(buf), Status: Present}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dst *Text) DecodeBinary(r io.Reader) error {
|
||||||
|
return dst.DecodeText(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (src Text) EncodeText(w io.Writer) error {
|
||||||
|
if done, err := encodeNotPresent(w, src.Status); done {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := pgio.WriteInt32(w, int32(len(src.String)))
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = io.WriteString(w, src.String)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (src Text) EncodeBinary(w io.Writer) error {
|
||||||
|
return src.EncodeText(w)
|
||||||
|
}
|
||||||
+100
@@ -0,0 +1,100 @@
|
|||||||
|
package pgtype_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/jackc/pgx/pgtype"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestTextTranscode(t *testing.T) {
|
||||||
|
for _, pgTypeName := range []string{"text", "varchar"} {
|
||||||
|
testSuccessfulTranscode(t, pgTypeName, []interface{}{
|
||||||
|
pgtype.Text{String: "", Status: pgtype.Present},
|
||||||
|
pgtype.Text{String: "foo", Status: pgtype.Present},
|
||||||
|
pgtype.Text{Status: pgtype.Null},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTextConvertFrom(t *testing.T) {
|
||||||
|
successfulTests := []struct {
|
||||||
|
source interface{}
|
||||||
|
result pgtype.Text
|
||||||
|
}{
|
||||||
|
{source: pgtype.Text{String: "foo", Status: pgtype.Present}, result: pgtype.Text{String: "foo", Status: pgtype.Present}},
|
||||||
|
{source: "foo", result: pgtype.Text{String: "foo", Status: pgtype.Present}},
|
||||||
|
{source: _string("bar"), result: pgtype.Text{String: "bar", Status: pgtype.Present}},
|
||||||
|
{source: (*string)(nil), result: pgtype.Text{Status: pgtype.Null}},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tt := range successfulTests {
|
||||||
|
var d pgtype.Text
|
||||||
|
err := d.ConvertFrom(tt.source)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("%d: %v", i, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if d != tt.result {
|
||||||
|
t.Errorf("%d: expected %v to convert to %v, but it was %v", i, tt.source, tt.result, d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTextAssignTo(t *testing.T) {
|
||||||
|
var s string
|
||||||
|
var ps *string
|
||||||
|
|
||||||
|
simpleTests := []struct {
|
||||||
|
src pgtype.Text
|
||||||
|
dst interface{}
|
||||||
|
expected interface{}
|
||||||
|
}{
|
||||||
|
{src: pgtype.Text{String: "foo", Status: pgtype.Present}, dst: &s, expected: "foo"},
|
||||||
|
{src: pgtype.Text{Status: pgtype.Null}, dst: &ps, expected: ((*string)(nil))},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tt := range simpleTests {
|
||||||
|
err := tt.src.AssignTo(tt.dst)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("%d: %v", i, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if dst := reflect.ValueOf(tt.dst).Elem().Interface(); dst != tt.expected {
|
||||||
|
t.Errorf("%d: expected %v to assign %v, but result was %v", i, tt.src, tt.expected, dst)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pointerAllocTests := []struct {
|
||||||
|
src pgtype.Text
|
||||||
|
dst interface{}
|
||||||
|
expected interface{}
|
||||||
|
}{
|
||||||
|
{src: pgtype.Text{String: "foo", Status: pgtype.Present}, dst: &ps, expected: "foo"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tt := range pointerAllocTests {
|
||||||
|
err := tt.src.AssignTo(tt.dst)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("%d: %v", i, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if dst := reflect.ValueOf(tt.dst).Elem().Elem().Interface(); dst != tt.expected {
|
||||||
|
t.Errorf("%d: expected %v to assign %v, but result was %v", i, tt.src, tt.expected, dst)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
errorTests := []struct {
|
||||||
|
src pgtype.Text
|
||||||
|
dst interface{}
|
||||||
|
}{
|
||||||
|
{src: pgtype.Text{Status: pgtype.Null}, dst: &s},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tt := range errorTests {
|
||||||
|
err := tt.src.AssignTo(tt.dst)
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("%d: expected error but none was returned (%v -> %v)", i, tt.src, tt.dst)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+297
@@ -0,0 +1,297 @@
|
|||||||
|
package pgtype
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/jackc/pgx/pgio"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TextArray struct {
|
||||||
|
Elements []Text
|
||||||
|
Dimensions []ArrayDimension
|
||||||
|
Status Status
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dst *TextArray) ConvertFrom(src interface{}) error {
|
||||||
|
switch value := src.(type) {
|
||||||
|
case TextArray:
|
||||||
|
*dst = value
|
||||||
|
|
||||||
|
case []string:
|
||||||
|
if value == nil {
|
||||||
|
*dst = TextArray{Status: Null}
|
||||||
|
} else if len(value) == 0 {
|
||||||
|
*dst = TextArray{Status: Present}
|
||||||
|
} else {
|
||||||
|
elements := make([]Text, len(value))
|
||||||
|
for i := range value {
|
||||||
|
if err := elements[i].ConvertFrom(value[i]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*dst = TextArray{
|
||||||
|
Elements: elements,
|
||||||
|
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
|
||||||
|
Status: Present,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
if originalSrc, ok := underlyingSliceType(src); ok {
|
||||||
|
return dst.ConvertFrom(originalSrc)
|
||||||
|
}
|
||||||
|
return fmt.Errorf("cannot convert %v to Text", value)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (src *TextArray) AssignTo(dst interface{}) error {
|
||||||
|
switch v := dst.(type) {
|
||||||
|
|
||||||
|
case *[]string:
|
||||||
|
if src.Status == Present {
|
||||||
|
*v = make([]string, len(src.Elements))
|
||||||
|
for i := range src.Elements {
|
||||||
|
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*v = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
if originalDst, ok := underlyingPtrSliceType(dst); ok {
|
||||||
|
return src.AssignTo(originalDst)
|
||||||
|
}
|
||||||
|
return fmt.Errorf("cannot decode %v into %T", src, dst)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dst *TextArray) DecodeText(r io.Reader) error {
|
||||||
|
size, err := pgio.ReadInt32(r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if size == -1 {
|
||||||
|
*dst = TextArray{Status: Null}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := make([]byte, int(size))
|
||||||
|
_, err = io.ReadFull(r, buf)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
uta, err := ParseUntypedTextArray(string(buf))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
textElementReader := NewTextElementReader(r)
|
||||||
|
var elements []Text
|
||||||
|
|
||||||
|
if len(uta.Elements) > 0 {
|
||||||
|
elements = make([]Text, len(uta.Elements))
|
||||||
|
|
||||||
|
for i, s := range uta.Elements {
|
||||||
|
var elem Text
|
||||||
|
textElementReader.Reset(s)
|
||||||
|
err = elem.DecodeText(textElementReader)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
elements[i] = elem
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*dst = TextArray{Elements: elements, Dimensions: uta.Dimensions, Status: Present}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dst *TextArray) DecodeBinary(r io.Reader) error {
|
||||||
|
size, err := pgio.ReadInt32(r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if size == -1 {
|
||||||
|
*dst = TextArray{Status: Null}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var arrayHeader ArrayHeader
|
||||||
|
err = arrayHeader.DecodeBinary(r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(arrayHeader.Dimensions) == 0 {
|
||||||
|
*dst = TextArray{Dimensions: arrayHeader.Dimensions, Status: Present}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
elementCount := arrayHeader.Dimensions[0].Length
|
||||||
|
for _, d := range arrayHeader.Dimensions[1:] {
|
||||||
|
elementCount *= d.Length
|
||||||
|
}
|
||||||
|
|
||||||
|
elements := make([]Text, elementCount)
|
||||||
|
|
||||||
|
for i := range elements {
|
||||||
|
err = elements[i].DecodeBinary(r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*dst = TextArray{Elements: elements, Dimensions: arrayHeader.Dimensions, Status: Present}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (src *TextArray) EncodeText(w io.Writer) error {
|
||||||
|
if done, err := encodeNotPresent(w, src.Status); done {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(src.Dimensions) == 0 {
|
||||||
|
_, err := pgio.WriteInt32(w, 2)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = w.Write([]byte("{}"))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
|
||||||
|
err := EncodeTextArrayDimensions(buf, src.Dimensions)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// dimElemCounts is the multiples of elements that each array lies on. For
|
||||||
|
// example, a single dimension array of length 4 would have a dimElemCounts of
|
||||||
|
// [4]. A multi-dimensional array of lengths [3,5,2] would have a
|
||||||
|
// dimElemCounts of [30,10,2]. This is used to simplify when to render a '{'
|
||||||
|
// or '}'.
|
||||||
|
dimElemCounts := make([]int, len(src.Dimensions))
|
||||||
|
dimElemCounts[len(src.Dimensions)-1] = int(src.Dimensions[len(src.Dimensions)-1].Length)
|
||||||
|
for i := len(src.Dimensions) - 2; i > -1; i-- {
|
||||||
|
dimElemCounts[i] = int(src.Dimensions[i].Length) * dimElemCounts[i+1]
|
||||||
|
}
|
||||||
|
|
||||||
|
textElementWriter := NewTextElementWriter(buf)
|
||||||
|
|
||||||
|
for i, elem := range src.Elements {
|
||||||
|
if i > 0 {
|
||||||
|
err = pgio.WriteByte(buf, ',')
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, dec := range dimElemCounts {
|
||||||
|
if i%dec == 0 {
|
||||||
|
err = pgio.WriteByte(buf, '{')
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
textElementWriter.Reset()
|
||||||
|
if elem.String == "" && elem.Status == Present {
|
||||||
|
_, err := io.WriteString(buf, `""`)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = elem.EncodeText(textElementWriter)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, dec := range dimElemCounts {
|
||||||
|
if (i+1)%dec == 0 {
|
||||||
|
err = pgio.WriteByte(buf, '}')
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = pgio.WriteInt32(w, int32(buf.Len()))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = buf.WriteTo(w)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (src *TextArray) EncodeBinary(w io.Writer) error {
|
||||||
|
return src.encodeBinary(w, TextOID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (src *TextArray) encodeBinary(w io.Writer, elementOID int32) error {
|
||||||
|
if done, err := encodeNotPresent(w, src.Status); done {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var arrayHeader ArrayHeader
|
||||||
|
|
||||||
|
// TODO - consider how to avoid having to buffer array before writing length -
|
||||||
|
// or how not pay allocations for the byte order conversions.
|
||||||
|
elemBuf := &bytes.Buffer{}
|
||||||
|
|
||||||
|
for i := range src.Elements {
|
||||||
|
err := src.Elements[i].EncodeBinary(elemBuf)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if src.Elements[i].Status == Null {
|
||||||
|
arrayHeader.ContainsNull = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
arrayHeader.ElementOID = elementOID
|
||||||
|
arrayHeader.Dimensions = src.Dimensions
|
||||||
|
|
||||||
|
// TODO - consider how to avoid having to buffer array before writing length -
|
||||||
|
// or how not pay allocations for the byte order conversions.
|
||||||
|
headerBuf := &bytes.Buffer{}
|
||||||
|
err := arrayHeader.EncodeBinary(headerBuf)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = pgio.WriteInt32(w, int32(headerBuf.Len()+elemBuf.Len()))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = headerBuf.WriteTo(w)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = elemBuf.WriteTo(w)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
package pgtype_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/jackc/pgx/pgtype"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestTextArrayTranscode(t *testing.T) {
|
||||||
|
testSuccessfulTranscode(t, "text[]", []interface{}{
|
||||||
|
&pgtype.TextArray{
|
||||||
|
Elements: nil,
|
||||||
|
Dimensions: nil,
|
||||||
|
Status: pgtype.Present,
|
||||||
|
},
|
||||||
|
&pgtype.TextArray{
|
||||||
|
Elements: []pgtype.Text{
|
||||||
|
pgtype.Text{String: "foo", Status: pgtype.Present},
|
||||||
|
pgtype.Text{Status: pgtype.Null},
|
||||||
|
},
|
||||||
|
Dimensions: []pgtype.ArrayDimension{{Length: 2, LowerBound: 1}},
|
||||||
|
Status: pgtype.Present,
|
||||||
|
},
|
||||||
|
&pgtype.TextArray{Status: pgtype.Null},
|
||||||
|
&pgtype.TextArray{
|
||||||
|
Elements: []pgtype.Text{
|
||||||
|
pgtype.Text{String: "bar", Status: pgtype.Present},
|
||||||
|
pgtype.Text{String: "baz", Status: pgtype.Present},
|
||||||
|
pgtype.Text{String: "quz", Status: pgtype.Present},
|
||||||
|
pgtype.Text{String: "", Status: pgtype.Present},
|
||||||
|
pgtype.Text{Status: pgtype.Null},
|
||||||
|
pgtype.Text{String: "foo", Status: pgtype.Present},
|
||||||
|
},
|
||||||
|
Dimensions: []pgtype.ArrayDimension{{Length: 3, LowerBound: 1}, {Length: 2, LowerBound: 1}},
|
||||||
|
Status: pgtype.Present,
|
||||||
|
},
|
||||||
|
&pgtype.TextArray{
|
||||||
|
Elements: []pgtype.Text{
|
||||||
|
pgtype.Text{String: "bar", Status: pgtype.Present},
|
||||||
|
pgtype.Text{String: "baz", Status: pgtype.Present},
|
||||||
|
pgtype.Text{String: "quz", Status: pgtype.Present},
|
||||||
|
pgtype.Text{String: "foo", Status: pgtype.Present},
|
||||||
|
},
|
||||||
|
Dimensions: []pgtype.ArrayDimension{
|
||||||
|
{Length: 2, LowerBound: 4},
|
||||||
|
{Length: 2, LowerBound: 2},
|
||||||
|
},
|
||||||
|
Status: pgtype.Present,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTextArrayConvertFrom(t *testing.T) {
|
||||||
|
successfulTests := []struct {
|
||||||
|
source interface{}
|
||||||
|
result pgtype.TextArray
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
source: []string{"foo"},
|
||||||
|
result: pgtype.TextArray{
|
||||||
|
Elements: []pgtype.Text{{String: "foo", Status: pgtype.Present}},
|
||||||
|
Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 1}},
|
||||||
|
Status: pgtype.Present},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
source: (([]string)(nil)),
|
||||||
|
result: pgtype.TextArray{Status: pgtype.Null},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tt := range successfulTests {
|
||||||
|
var r pgtype.TextArray
|
||||||
|
err := r.ConvertFrom(tt.source)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("%d: %v", i, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(r, tt.result) {
|
||||||
|
t.Errorf("%d: expected %v to convert to %v, but it was %v", i, tt.source, tt.result, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTextArrayAssignTo(t *testing.T) {
|
||||||
|
var stringSlice []string
|
||||||
|
type _stringSlice []string
|
||||||
|
var namedStringSlice _stringSlice
|
||||||
|
|
||||||
|
simpleTests := []struct {
|
||||||
|
src pgtype.TextArray
|
||||||
|
dst interface{}
|
||||||
|
expected interface{}
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
src: pgtype.TextArray{
|
||||||
|
Elements: []pgtype.Text{{String: "foo", Status: pgtype.Present}},
|
||||||
|
Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 1}},
|
||||||
|
Status: pgtype.Present,
|
||||||
|
},
|
||||||
|
dst: &stringSlice,
|
||||||
|
expected: []string{"foo"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: pgtype.TextArray{
|
||||||
|
Elements: []pgtype.Text{{String: "bar", Status: pgtype.Present}},
|
||||||
|
Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 1}},
|
||||||
|
Status: pgtype.Present,
|
||||||
|
},
|
||||||
|
dst: &namedStringSlice,
|
||||||
|
expected: _stringSlice{"bar"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: pgtype.TextArray{Status: pgtype.Null},
|
||||||
|
dst: &stringSlice,
|
||||||
|
expected: (([]string)(nil)),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tt := range simpleTests {
|
||||||
|
err := tt.src.AssignTo(tt.dst)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("%d: %v", i, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if dst := reflect.ValueOf(tt.dst).Elem().Interface(); !reflect.DeepEqual(dst, tt.expected) {
|
||||||
|
t.Errorf("%d: expected %v to assign %v, but result was %v", i, tt.src, tt.expected, dst)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
errorTests := []struct {
|
||||||
|
src pgtype.TextArray
|
||||||
|
dst interface{}
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
src: pgtype.TextArray{
|
||||||
|
Elements: []pgtype.Text{{Status: pgtype.Null}},
|
||||||
|
Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 1}},
|
||||||
|
Status: pgtype.Present,
|
||||||
|
},
|
||||||
|
dst: &stringSlice,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tt := range errorTests {
|
||||||
|
err := tt.src.AssignTo(tt.dst)
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("%d: expected error but none was returned (%v -> %v)", i, tt.src, tt.dst)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -68,7 +68,7 @@ func (src *TimestampArray) AssignTo(dst interface{}) error {
|
|||||||
if originalDst, ok := underlyingPtrSliceType(dst); ok {
|
if originalDst, ok := underlyingPtrSliceType(dst); ok {
|
||||||
return src.AssignTo(originalDst)
|
return src.AssignTo(originalDst)
|
||||||
}
|
}
|
||||||
return fmt.Errorf("cannot put decode %v into %T", src, dst)
|
return fmt.Errorf("cannot decode %v into %T", src, dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
+1
-1
@@ -68,7 +68,7 @@ func (src *TimestamptzArray) AssignTo(dst interface{}) error {
|
|||||||
if originalDst, ok := underlyingPtrSliceType(dst); ok {
|
if originalDst, ok := underlyingPtrSliceType(dst); ok {
|
||||||
return src.AssignTo(originalDst)
|
return src.AssignTo(originalDst)
|
||||||
}
|
}
|
||||||
return fmt.Errorf("cannot put decode %v into %T", src, dst)
|
return fmt.Errorf("cannot decode %v into %T", src, dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
+1
-1
@@ -67,7 +67,7 @@ func (src *<%= pgtype_array_type %>) AssignTo(dst interface{}) error {
|
|||||||
if originalDst, ok := underlyingPtrSliceType(dst); ok {
|
if originalDst, ok := underlyingPtrSliceType(dst); ok {
|
||||||
return src.AssignTo(originalDst)
|
return src.AssignTo(originalDst)
|
||||||
}
|
}
|
||||||
return fmt.Errorf("cannot put decode %v into %T", src, dst)
|
return fmt.Errorf("cannot decode %v into %T", src, dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -8,3 +8,4 @@ erb pgtype_array_type=TimestampArray pgtype_element_type=Timestamp go_array_type
|
|||||||
erb pgtype_array_type=Float4Array pgtype_element_type=Float4 go_array_types=[]float32 element_oid=Float4OID typed_array.go.erb > float4array.go
|
erb pgtype_array_type=Float4Array pgtype_element_type=Float4 go_array_types=[]float32 element_oid=Float4OID typed_array.go.erb > float4array.go
|
||||||
erb pgtype_array_type=Float8Array pgtype_element_type=Float8 go_array_types=[]float64 element_oid=Float8OID typed_array.go.erb > float8array.go
|
erb pgtype_array_type=Float8Array pgtype_element_type=Float8 go_array_types=[]float64 element_oid=Float8OID typed_array.go.erb > float8array.go
|
||||||
erb pgtype_array_type=InetArray pgtype_element_type=Inet go_array_types=[]*net.IPNet,[]net.IP element_oid=InetOID typed_array.go.erb > inetarray.go
|
erb pgtype_array_type=InetArray pgtype_element_type=Inet go_array_types=[]*net.IPNet,[]net.IP element_oid=InetOID typed_array.go.erb > inetarray.go
|
||||||
|
erb pgtype_array_type=TextArray pgtype_element_type=Text go_array_types=[]string element_oid=TextOID typed_array.go.erb > textarray.go
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package pgtype
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
type VarcharArray TextArray
|
||||||
|
|
||||||
|
func (dst *VarcharArray) ConvertFrom(src interface{}) error {
|
||||||
|
return (*TextArray)(dst).ConvertFrom(src)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (src *VarcharArray) AssignTo(dst interface{}) error {
|
||||||
|
return (*TextArray)(src).AssignTo(dst)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dst *VarcharArray) DecodeText(r io.Reader) error {
|
||||||
|
return (*TextArray)(dst).DecodeText(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dst *VarcharArray) DecodeBinary(r io.Reader) error {
|
||||||
|
return (*TextArray)(dst).DecodeBinary(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (src *VarcharArray) EncodeText(w io.Writer) error {
|
||||||
|
return (*TextArray)(src).EncodeText(w)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (src *VarcharArray) EncodeBinary(w io.Writer) error {
|
||||||
|
return (*TextArray)(src).encodeBinary(w, VarcharOID)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user