2
0

Replace Status with Valid to conform to database/sql style

https://github.com/jackc/pgx/issues/1060
This commit is contained in:
Jack Christensen
2021-08-26 22:46:13 -05:00
parent 37044f47f5
commit 11d351dd75
156 changed files with 6909 additions and 7894 deletions
+157 -170
View File
@@ -14,13 +14,13 @@ import (
type NumericArray struct {
Elements []Numeric
Dimensions []ArrayDimension
Status Status
Valid bool
}
func (dst *NumericArray) Set(src interface{}) error {
// untyped nil and typed nil interfaces are different
if src == nil {
*dst = NumericArray{Status: Null}
*dst = NumericArray{}
return nil
}
@@ -36,9 +36,9 @@ func (dst *NumericArray) Set(src interface{}) error {
case []float32:
if value == nil {
*dst = NumericArray{Status: Null}
*dst = NumericArray{}
} else if len(value) == 0 {
*dst = NumericArray{Status: Present}
*dst = NumericArray{Valid: true}
} else {
elements := make([]Numeric, len(value))
for i := range value {
@@ -49,15 +49,15 @@ func (dst *NumericArray) Set(src interface{}) error {
*dst = NumericArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
Valid: true,
}
}
case []*float32:
if value == nil {
*dst = NumericArray{Status: Null}
*dst = NumericArray{}
} else if len(value) == 0 {
*dst = NumericArray{Status: Present}
*dst = NumericArray{Valid: true}
} else {
elements := make([]Numeric, len(value))
for i := range value {
@@ -68,15 +68,15 @@ func (dst *NumericArray) Set(src interface{}) error {
*dst = NumericArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
Valid: true,
}
}
case []float64:
if value == nil {
*dst = NumericArray{Status: Null}
*dst = NumericArray{}
} else if len(value) == 0 {
*dst = NumericArray{Status: Present}
*dst = NumericArray{Valid: true}
} else {
elements := make([]Numeric, len(value))
for i := range value {
@@ -87,15 +87,15 @@ func (dst *NumericArray) Set(src interface{}) error {
*dst = NumericArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
Valid: true,
}
}
case []*float64:
if value == nil {
*dst = NumericArray{Status: Null}
*dst = NumericArray{}
} else if len(value) == 0 {
*dst = NumericArray{Status: Present}
*dst = NumericArray{Valid: true}
} else {
elements := make([]Numeric, len(value))
for i := range value {
@@ -106,15 +106,15 @@ func (dst *NumericArray) Set(src interface{}) error {
*dst = NumericArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
Valid: true,
}
}
case []int64:
if value == nil {
*dst = NumericArray{Status: Null}
*dst = NumericArray{}
} else if len(value) == 0 {
*dst = NumericArray{Status: Present}
*dst = NumericArray{Valid: true}
} else {
elements := make([]Numeric, len(value))
for i := range value {
@@ -125,15 +125,15 @@ func (dst *NumericArray) Set(src interface{}) error {
*dst = NumericArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
Valid: true,
}
}
case []*int64:
if value == nil {
*dst = NumericArray{Status: Null}
*dst = NumericArray{}
} else if len(value) == 0 {
*dst = NumericArray{Status: Present}
*dst = NumericArray{Valid: true}
} else {
elements := make([]Numeric, len(value))
for i := range value {
@@ -144,15 +144,15 @@ func (dst *NumericArray) Set(src interface{}) error {
*dst = NumericArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
Valid: true,
}
}
case []uint64:
if value == nil {
*dst = NumericArray{Status: Null}
*dst = NumericArray{}
} else if len(value) == 0 {
*dst = NumericArray{Status: Present}
*dst = NumericArray{Valid: true}
} else {
elements := make([]Numeric, len(value))
for i := range value {
@@ -163,15 +163,15 @@ func (dst *NumericArray) Set(src interface{}) error {
*dst = NumericArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
Valid: true,
}
}
case []*uint64:
if value == nil {
*dst = NumericArray{Status: Null}
*dst = NumericArray{}
} else if len(value) == 0 {
*dst = NumericArray{Status: Present}
*dst = NumericArray{Valid: true}
} else {
elements := make([]Numeric, len(value))
for i := range value {
@@ -182,20 +182,20 @@ func (dst *NumericArray) Set(src interface{}) error {
*dst = NumericArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
Valid: true,
}
}
case []Numeric:
if value == nil {
*dst = NumericArray{Status: Null}
*dst = NumericArray{}
} else if len(value) == 0 {
*dst = NumericArray{Status: Present}
*dst = NumericArray{Valid: true}
} else {
*dst = NumericArray{
Elements: value,
Dimensions: []ArrayDimension{{Length: int32(len(value)), LowerBound: 1}},
Status: Present,
Valid: true,
}
}
default:
@@ -204,7 +204,7 @@ func (dst *NumericArray) Set(src interface{}) error {
// but it comes with a 20-50% performance penalty for large arrays/slices
reflectedValue := reflect.ValueOf(src)
if !reflectedValue.IsValid() || reflectedValue.IsZero() {
*dst = NumericArray{Status: Null}
*dst = NumericArray{}
return nil
}
@@ -213,7 +213,7 @@ func (dst *NumericArray) Set(src interface{}) error {
return fmt.Errorf("cannot find dimensions of %v for NumericArray", src)
}
if elementsLength == 0 {
*dst = NumericArray{Status: Present}
*dst = NumericArray{Valid: true}
return nil
}
if len(dimensions) == 0 {
@@ -226,7 +226,7 @@ func (dst *NumericArray) Set(src interface{}) error {
*dst = NumericArray{
Elements: make([]Numeric, elementsLength),
Dimensions: dimensions,
Status: Present,
Valid: true,
}
elementCount, err := dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
@@ -293,138 +293,131 @@ func (dst *NumericArray) setRecursive(value reflect.Value, index, dimension int)
}
func (dst NumericArray) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
if !dst.Valid {
return nil
default:
return dst.Status
}
return dst
}
func (src *NumericArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
case *[]float32:
*v = make([]float32, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*float32:
*v = make([]*float32, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]float64:
*v = make([]float64, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*float64:
*v = make([]*float64, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]int64:
*v = make([]int64, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*int64:
*v = make([]*int64, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]uint64:
*v = make([]uint64, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*uint64:
*v = make([]*uint64, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
}
}
// Try to convert to something AssignTo can use directly.
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
value := reflect.ValueOf(dst)
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
switch value.Kind() {
case reflect.Array, reflect.Slice:
default:
return fmt.Errorf("cannot assign %T to %T", src, dst)
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err
}
if elementCount != len(src.Elements) {
return fmt.Errorf("cannot assign %v, needed to assign %d elements, but only assigned %d", dst, len(src.Elements), elementCount)
}
return nil
case Null:
if !src.Valid {
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
case *[]float32:
*v = make([]float32, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*float32:
*v = make([]*float32, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]float64:
*v = make([]float64, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*float64:
*v = make([]*float64, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]int64:
*v = make([]int64, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*int64:
*v = make([]*int64, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]uint64:
*v = make([]uint64, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*uint64:
*v = make([]*uint64, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
}
}
// Try to convert to something AssignTo can use directly.
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
value := reflect.ValueOf(dst)
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
switch value.Kind() {
case reflect.Array, reflect.Slice:
default:
return fmt.Errorf("cannot assign %T to %T", src, dst)
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err
}
if elementCount != len(src.Elements) {
return fmt.Errorf("cannot assign %v, needed to assign %d elements, but only assigned %d", dst, len(src.Elements), elementCount)
}
return nil
}
func (src *NumericArray) assignToRecursive(value reflect.Value, index, dimension int) (int, error) {
@@ -476,7 +469,7 @@ func (src *NumericArray) assignToRecursive(value reflect.Value, index, dimension
func (dst *NumericArray) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = NumericArray{Status: Null}
*dst = NumericArray{}
return nil
}
@@ -505,14 +498,14 @@ func (dst *NumericArray) DecodeText(ci *ConnInfo, src []byte) error {
}
}
*dst = NumericArray{Elements: elements, Dimensions: uta.Dimensions, Status: Present}
*dst = NumericArray{Elements: elements, Dimensions: uta.Dimensions, Valid: true}
return nil
}
func (dst *NumericArray) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = NumericArray{Status: Null}
*dst = NumericArray{}
return nil
}
@@ -523,7 +516,7 @@ func (dst *NumericArray) DecodeBinary(ci *ConnInfo, src []byte) error {
}
if len(arrayHeader.Dimensions) == 0 {
*dst = NumericArray{Dimensions: arrayHeader.Dimensions, Status: Present}
*dst = NumericArray{Dimensions: arrayHeader.Dimensions, Valid: true}
return nil
}
@@ -548,16 +541,13 @@ func (dst *NumericArray) DecodeBinary(ci *ConnInfo, src []byte) error {
}
}
*dst = NumericArray{Elements: elements, Dimensions: arrayHeader.Dimensions, Status: Present}
*dst = NumericArray{Elements: elements, Dimensions: arrayHeader.Dimensions, Valid: true}
return nil
}
func (src NumericArray) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
if !src.Valid {
return nil, nil
case Undefined:
return nil, errUndefined
}
if len(src.Dimensions) == 0 {
@@ -610,11 +600,8 @@ func (src NumericArray) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
}
func (src NumericArray) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
if !src.Valid {
return nil, nil
case Undefined:
return nil, errUndefined
}
arrayHeader := ArrayHeader{
@@ -628,7 +615,7 @@ func (src NumericArray) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
}
for i := range src.Elements {
if src.Elements[i].Status == Null {
if !src.Elements[i].Valid {
arrayHeader.ContainsNull = true
break
}