From 44f45c6c62198949596eceb23990eddeb9581b6b Mon Sep 17 00:00:00 2001 From: tserakhau Date: Sun, 21 Jun 2020 14:21:16 +0300 Subject: [PATCH] Use erb for jsonb array generation --- jsonb_array.go | 48 ++++++++++++++++++++++++++++++++-------------- typed_array_gen.sh | 1 + 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/jsonb_array.go b/jsonb_array.go index 7abc8193..fd78fc80 100644 --- a/jsonb_array.go +++ b/jsonb_array.go @@ -4,12 +4,12 @@ import ( "database/sql/driver" "encoding/binary" - "github.com/jackc/pgx/pgio" - "github.com/pkg/errors" + "github.com/jackc/pgio" + errors "golang.org/x/xerrors" ) type JSONBArray struct { - Elements []JSONB + Elements []Text Dimensions []ArrayDimension Status Status } @@ -21,6 +21,13 @@ func (dst *JSONBArray) Set(src interface{}) error { return nil } + if value, ok := src.(interface{ Get() interface{} }); ok { + value2 := value.Get() + if value2 != value { + return dst.Set(value2) + } + } + switch value := src.(type) { case []string: @@ -29,7 +36,7 @@ func (dst *JSONBArray) Set(src interface{}) error { } else if len(value) == 0 { *dst = JSONBArray{Status: Present} } else { - elements := make([]JSONB, len(value)) + elements := make([]Text, len(value)) for i := range value { if err := elements[i].Set(value[i]); err != nil { return err @@ -42,6 +49,18 @@ func (dst *JSONBArray) Set(src interface{}) error { } } + case []Text: + if value == nil { + *dst = JSONBArray{Status: Null} + } else if len(value) == 0 { + *dst = JSONBArray{Status: Present} + } else { + *dst = JSONBArray{ + Elements: value, + Dimensions: []ArrayDimension{{Length: int32(len(value)), LowerBound: 1}}, + Status: Present, + } + } default: if originalSrc, ok := underlyingSliceType(src); ok { return dst.Set(originalSrc) @@ -52,7 +71,7 @@ func (dst *JSONBArray) Set(src interface{}) error { return nil } -func (dst *JSONBArray) Get() interface{} { +func (dst JSONBArray) Get() interface{} { switch dst.Status { case Present: return dst @@ -81,6 +100,7 @@ func (src *JSONBArray) AssignTo(dst interface{}) error { if nextDst, retry := GetAssignToDstType(dst); retry { return src.AssignTo(nextDst) } + return errors.Errorf("unable to assign to %T", dst) } case Null: return NullAssignTo(dst) @@ -100,13 +120,13 @@ func (dst *JSONBArray) DecodeText(ci *ConnInfo, src []byte) error { return err } - var elements []JSONB + var elements []Text if len(uta.Elements) > 0 { - elements = make([]JSONB, len(uta.Elements)) + elements = make([]Text, len(uta.Elements)) for i, s := range uta.Elements { - var elem JSONB + var elem Text var elemSrc []byte if s != "NULL" { elemSrc = []byte(s) @@ -147,7 +167,7 @@ func (dst *JSONBArray) DecodeBinary(ci *ConnInfo, src []byte) error { elementCount *= d.Length } - elements := make([]JSONB, elementCount) + elements := make([]Text, elementCount) for i := range elements { elemLen := int(int32(binary.BigEndian.Uint32(src[rp:]))) @@ -167,7 +187,7 @@ func (dst *JSONBArray) DecodeBinary(ci *ConnInfo, src []byte) error { return nil } -func (src *JSONBArray) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) { +func (src JSONBArray) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) { switch src.Status { case Null: return nil, nil @@ -209,7 +229,7 @@ func (src *JSONBArray) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) { return nil, err } if elemBuf == nil { - buf = append(buf, `"NULL"`...) + buf = append(buf, `NULL`...) } else { buf = append(buf, QuoteArrayElementIfNeeded(string(elemBuf))...) } @@ -224,7 +244,7 @@ func (src *JSONBArray) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) { return buf, nil } -func (src *JSONBArray) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) { +func (src JSONBArray) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) { switch src.Status { case Null: return nil, nil @@ -236,7 +256,7 @@ func (src *JSONBArray) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) { Dimensions: src.Dimensions, } - if dt, ok := ci.DataTypeForName("jsonb"); ok { + if dt, ok := ci.DataTypeForName("text"); ok { arrayHeader.ElementOID = int32(dt.OID) } else { return nil, errors.Errorf("unable to find oid for type name %v", "text") @@ -287,7 +307,7 @@ func (dst *JSONBArray) Scan(src interface{}) error { } // Value implements the database/sql/driver Valuer interface. -func (src *JSONBArray) Value() (driver.Value, error) { +func (src JSONBArray) Value() (driver.Value, error) { buf, err := src.EncodeText(nil, nil) if err != nil { return nil, err diff --git a/typed_array_gen.sh b/typed_array_gen.sh index 6fd49264..523b2600 100755 --- a/typed_array_gen.sh +++ b/typed_array_gen.sh @@ -19,6 +19,7 @@ erb pgtype_array_type=ACLItemArray pgtype_element_type=ACLItem go_array_types=[] erb pgtype_array_type=HstoreArray pgtype_element_type=Hstore go_array_types=[]map[string]string element_type_name=hstore text_null=NULL binary_format=true typed_array.go.erb > hstore_array.go erb pgtype_array_type=NumericArray pgtype_element_type=Numeric go_array_types=[]float32,[]float64,[]int64,[]uint64 element_type_name=numeric text_null=NULL binary_format=true typed_array.go.erb > numeric_array.go erb pgtype_array_type=UUIDArray pgtype_element_type=UUID go_array_types=[][16]byte,[][]byte,[]string element_type_name=uuid text_null=NULL binary_format=true typed_array.go.erb > uuid_array.go +erb pgtype_array_type=JSONBArray pgtype_element_type=Text go_array_types=[]string element_type_name=text text_null=NULL binary_format=true typed_array.go.erb > jsonb_array.go # While the binary format is theoretically possible it is only practical to use the text format. erb pgtype_array_type=EnumArray pgtype_element_type=GenericText go_array_types=[]string text_null=NULL binary_format=false typed_array.go.erb > enum_array.go