Add binary scan plans for int2

query-exec-mode
Jack Christensen 2021-12-31 17:03:31 -06:00
parent 77b9b59622
commit 19ae359e9e
3 changed files with 405 additions and 21 deletions

View File

@ -2,7 +2,6 @@ package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"math"
"strconv"
@ -50,6 +49,28 @@ func (Int2Codec) PlanScan(ci *ConnInfo, oid uint32, format int16, target interfa
switch format {
case BinaryFormatCode:
switch target.(type) {
case *int8:
return scanPlanBinaryInt2ToInt8{}
case *int16:
return scanPlanBinaryInt2ToInt16{}
case *int32:
return scanPlanBinaryInt2ToInt32{}
case *int64:
return scanPlanBinaryInt2ToInt64{}
case *int:
return scanPlanBinaryInt2ToInt{}
case *uint8:
return scanPlanBinaryInt2ToUint8{}
case *uint16:
return scanPlanBinaryInt2ToUint16{}
case *uint32:
return scanPlanBinaryInt2ToUint32{}
case *uint64:
return scanPlanBinaryInt2ToUint64{}
case *uint:
return scanPlanBinaryInt2ToUint{}
}
case TextFormatCode:
switch target.(type) {
case *int8:
@ -111,23 +132,3 @@ func (c Int2Codec) DecodeValue(ci *ConnInfo, oid uint32, format int16, src []byt
}
return n, nil
}
type scanPlanBinaryInt2ToInt16 struct{}
func (scanPlanBinaryInt2ToInt16) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error {
if src == nil {
return fmt.Errorf("cannot scan null into %T", dst)
}
if len(src) != 2 {
return fmt.Errorf("invalid length for int2: %v", len(src))
}
p, ok := (dst).(*int16)
if !ok {
return ErrScanTargetTypeChanged
}
*p = int16(binary.BigEndian.Uint16(src))
return nil
}

View File

@ -1,7 +1,9 @@
package pgtype
import (
"encoding/binary"
"fmt"
"math"
"strconv"
)
@ -214,3 +216,249 @@ func (scanPlanTextAnyToUint) Scan(ci *ConnInfo, oid uint32, formatCode int16, sr
*p = uint(n)
return nil
}
type scanPlanBinaryInt2ToInt8 struct{}
func (scanPlanBinaryInt2ToInt8) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error {
if src == nil {
return fmt.Errorf("cannot scan null into %T", dst)
}
if len(src) != 2 {
return fmt.Errorf("invalid length for int2: %v", len(src))
}
p, ok := (dst).(*int8)
if !ok {
return ErrScanTargetTypeChanged
}
n := int16(binary.BigEndian.Uint16(src))
if n < math.MinInt8 {
return fmt.Errorf("%d is less than minimum value for int8", n)
} else if n > math.MaxInt8 {
return fmt.Errorf("%d is greater than maximum value for int8", n)
}
*p = int8(n)
return nil
}
type scanPlanBinaryInt2ToUint8 struct{}
func (scanPlanBinaryInt2ToUint8) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error {
if src == nil {
return fmt.Errorf("cannot scan null into %T", dst)
}
if len(src) != 2 {
return fmt.Errorf("invalid length for uint2: %v", len(src))
}
p, ok := (dst).(*uint8)
if !ok {
return ErrScanTargetTypeChanged
}
n := int16(binary.BigEndian.Uint16(src))
if n < 0 {
return fmt.Errorf("%d is less than minimum value for uint8", n)
}
if n > math.MaxUint8 {
return fmt.Errorf("%d is greater than maximum value for uint8", n)
}
*p = uint8(n)
return nil
}
type scanPlanBinaryInt2ToInt16 struct{}
func (scanPlanBinaryInt2ToInt16) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error {
if src == nil {
return fmt.Errorf("cannot scan null into %T", dst)
}
if len(src) != 2 {
return fmt.Errorf("invalid length for int2: %v", len(src))
}
p, ok := (dst).(*int16)
if !ok {
return ErrScanTargetTypeChanged
}
*p = int16(binary.BigEndian.Uint16(src))
return nil
}
type scanPlanBinaryInt2ToUint16 struct{}
func (scanPlanBinaryInt2ToUint16) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error {
if src == nil {
return fmt.Errorf("cannot scan null into %T", dst)
}
if len(src) != 2 {
return fmt.Errorf("invalid length for uint2: %v", len(src))
}
p, ok := (dst).(*uint16)
if !ok {
return ErrScanTargetTypeChanged
}
n := int16(binary.BigEndian.Uint16(src))
if n < 0 {
return fmt.Errorf("%d is less than minimum value for uint16", n)
}
*p = uint16(n)
return nil
}
type scanPlanBinaryInt2ToInt32 struct{}
func (scanPlanBinaryInt2ToInt32) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error {
if src == nil {
return fmt.Errorf("cannot scan null into %T", dst)
}
if len(src) != 2 {
return fmt.Errorf("invalid length for int2: %v", len(src))
}
p, ok := (dst).(*int32)
if !ok {
return ErrScanTargetTypeChanged
}
*p = int32(binary.BigEndian.Uint16(src))
return nil
}
type scanPlanBinaryInt2ToUint32 struct{}
func (scanPlanBinaryInt2ToUint32) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error {
if src == nil {
return fmt.Errorf("cannot scan null into %T", dst)
}
if len(src) != 2 {
return fmt.Errorf("invalid length for uint2: %v", len(src))
}
p, ok := (dst).(*uint32)
if !ok {
return ErrScanTargetTypeChanged
}
n := int16(binary.BigEndian.Uint16(src))
if n < 0 {
return fmt.Errorf("%d is less than minimum value for uint32", n)
}
*p = uint32(n)
return nil
}
type scanPlanBinaryInt2ToInt64 struct{}
func (scanPlanBinaryInt2ToInt64) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error {
if src == nil {
return fmt.Errorf("cannot scan null into %T", dst)
}
if len(src) != 2 {
return fmt.Errorf("invalid length for int2: %v", len(src))
}
p, ok := (dst).(*int64)
if !ok {
return ErrScanTargetTypeChanged
}
*p = int64(binary.BigEndian.Uint16(src))
return nil
}
type scanPlanBinaryInt2ToUint64 struct{}
func (scanPlanBinaryInt2ToUint64) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error {
if src == nil {
return fmt.Errorf("cannot scan null into %T", dst)
}
if len(src) != 2 {
return fmt.Errorf("invalid length for uint2: %v", len(src))
}
p, ok := (dst).(*uint64)
if !ok {
return ErrScanTargetTypeChanged
}
n := int16(binary.BigEndian.Uint16(src))
if n < 0 {
return fmt.Errorf("%d is less than minimum value for uint64", n)
}
*p = uint64(n)
return nil
}
type scanPlanBinaryInt2ToInt struct{}
func (scanPlanBinaryInt2ToInt) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error {
if src == nil {
return fmt.Errorf("cannot scan null into %T", dst)
}
if len(src) != 2 {
return fmt.Errorf("invalid length for int2: %v", len(src))
}
p, ok := (dst).(*int)
if !ok {
return ErrScanTargetTypeChanged
}
*p = int(binary.BigEndian.Uint16(src))
return nil
}
type scanPlanBinaryInt2ToUint struct{}
func (scanPlanBinaryInt2ToUint) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error {
if src == nil {
return fmt.Errorf("cannot scan null into %T", dst)
}
if len(src) != 2 {
return fmt.Errorf("invalid length for uint2: %v", len(src))
}
p, ok := (dst).(*uint)
if !ok {
return ErrScanTargetTypeChanged
}
n := int64(binary.BigEndian.Uint16(src))
if n < 0 {
return fmt.Errorf("%d is less than minimum value for uint", n)
}
*p = uint(n)
return nil
}

View File

@ -54,3 +54,138 @@ func (scanPlanTextAnyToUint<%= type_suffix %>) Scan(ci *ConnInfo, oid uint32, fo
return nil
}
<% end %>
<% [
[16, 8],
[16, 16],
[16, 32],
[16, 64],
].each do |src_bit_size, dst_bit_size| %>
<% src_byte_size = src_bit_size / 8 %>
type scanPlanBinaryInt<%= src_byte_size %>ToInt<%= dst_bit_size %> struct{}
func (scanPlanBinaryInt<%= src_byte_size %>ToInt<%= dst_bit_size %>) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error {
if src == nil {
return fmt.Errorf("cannot scan null into %T", dst)
}
if len(src) != <%= src_byte_size %> {
return fmt.Errorf("invalid length for int<%= src_byte_size %>: %v", len(src))
}
p, ok := (dst).(*int<%= dst_bit_size %>)
if !ok {
return ErrScanTargetTypeChanged
}
<% if dst_bit_size < src_bit_size %>
n := int<%= src_bit_size %>(binary.BigEndian.Uint<%= src_bit_size %>(src))
if n < math.MinInt<%= dst_bit_size %> {
return fmt.Errorf("%d is less than minimum value for int<%= dst_bit_size %>", n)
} else if n > math.MaxInt<%= dst_bit_size %> {
return fmt.Errorf("%d is greater than maximum value for int<%= dst_bit_size %>", n)
}
*p = int<%= dst_bit_size %>(n)
<% else %>
*p = int<%= dst_bit_size %>(binary.BigEndian.Uint<%= src_bit_size %>(src))
<% end %>
return nil
}
type scanPlanBinaryInt<%= src_byte_size %>ToUint<%= dst_bit_size %> struct{}
func (scanPlanBinaryInt<%= src_byte_size %>ToUint<%= dst_bit_size %>) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error {
if src == nil {
return fmt.Errorf("cannot scan null into %T", dst)
}
if len(src) != <%= src_byte_size %> {
return fmt.Errorf("invalid length for uint<%= src_byte_size %>: %v", len(src))
}
p, ok := (dst).(*uint<%= dst_bit_size %>)
if !ok {
return ErrScanTargetTypeChanged
}
n := int<%= src_bit_size %>(binary.BigEndian.Uint<%= src_bit_size %>(src))
if n < 0 {
return fmt.Errorf("%d is less than minimum value for uint<%= dst_bit_size %>", n)
}
<% if dst_bit_size < src_bit_size %>
if n > math.MaxUint<%= dst_bit_size %> {
return fmt.Errorf("%d is greater than maximum value for uint<%= dst_bit_size %>", n)
}
<% end %>
*p = uint<%= dst_bit_size %>(n)
return nil
}
<% end %>
<% [16].each do |src_bit_size| %>
<% src_byte_size = src_bit_size / 8 %>
type scanPlanBinaryInt<%= src_byte_size %>ToInt struct{}
func (scanPlanBinaryInt<%= src_byte_size %>ToInt) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error {
if src == nil {
return fmt.Errorf("cannot scan null into %T", dst)
}
if len(src) != <%= src_byte_size %> {
return fmt.Errorf("invalid length for int<%= src_byte_size %>: %v", len(src))
}
p, ok := (dst).(*int)
if !ok {
return ErrScanTargetTypeChanged
}
<% if 32 < src_bit_size %>
n := int64(binary.BigEndian.Uint<%= src_bit_size %>(src))
if n < math.MinInt {
return fmt.Errorf("%d is less than minimum value for int", n)
} else if n > math.MaxInt {
return fmt.Errorf("%d is greater than maximum value for int", n)
}
*p = int(n)
<% else %>
*p = int(binary.BigEndian.Uint<%= src_bit_size %>(src))
<% end %>
return nil
}
type scanPlanBinaryInt<%= src_byte_size %>ToUint struct{}
func (scanPlanBinaryInt<%= src_byte_size %>ToUint) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error {
if src == nil {
return fmt.Errorf("cannot scan null into %T", dst)
}
if len(src) != <%= src_byte_size %> {
return fmt.Errorf("invalid length for uint<%= src_byte_size %>: %v", len(src))
}
p, ok := (dst).(*uint)
if !ok {
return ErrScanTargetTypeChanged
}
n := int64(binary.BigEndian.Uint<%= src_bit_size %>(src))
if n < 0 {
return fmt.Errorf("%d is less than minimum value for uint", n)
}
<% if 32 < src_bit_size %>
if uint64(n) > math.MaxUint {
return fmt.Errorf("%d is greater than maximum value for uint", n)
}
<% end %>
*p = uint(n)
return nil
}
<% end %>