pgx/pgtype/int.go.erb

489 lines
12 KiB
Plaintext

package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"math"
"strconv"
"github.com/jackc/pgio"
)
type Int64Scanner interface {
ScanInt64(v int64, valid bool) error
}
<% [2, 4, 8].each do |pg_byte_size| %>
<% pg_bit_size = pg_byte_size * 8 %>
type Int<%= pg_byte_size %> struct {
Int int<%= pg_bit_size %>
Valid bool
}
// ScanInt64 implements the Int64Scanner interface.
func (dst *Int<%= pg_byte_size %>) ScanInt64(n int64, valid bool) error {
if !valid {
*dst = Int<%= pg_byte_size %>{}
return nil
}
if n < math.MinInt<%= pg_bit_size %> {
return fmt.Errorf("%d is greater than maximum value for Int<%= pg_byte_size %>", n)
}
if n > math.MaxInt<%= pg_bit_size %> {
return fmt.Errorf("%d is greater than maximum value for Int<%= pg_byte_size %>", n)
}
*dst = Int<%= pg_byte_size %>{Int: int<%= pg_bit_size %>(n), Valid: true}
return nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Int<%= pg_byte_size %>) Scan(src interface{}) error {
if src == nil {
*dst = Int<%= pg_byte_size %>{}
return nil
}
var n int64
switch src := src.(type) {
case int64:
n = src
case string:
var err error
n, err = strconv.ParseInt(src, 10, <%= pg_bit_size %>)
if err != nil {
return err
}
case []byte:
var err error
n, err = strconv.ParseInt(string(src), 10, <%= pg_bit_size %>)
if err != nil {
return err
}
default:
return fmt.Errorf("cannot scan %T", src)
}
if n < math.MinInt<%= pg_bit_size %> {
return fmt.Errorf("%d is greater than maximum value for Int<%= pg_byte_size %>", n)
}
if n > math.MaxInt<%= pg_bit_size %> {
return fmt.Errorf("%d is greater than maximum value for Int<%= pg_byte_size %>", n)
}
*dst = Int<%= pg_byte_size %>{Int: int<%= pg_bit_size %>(n), Valid: true}
return nil
}
// Value implements the database/sql/driver Valuer interface.
func (src Int<%= pg_byte_size %>) Value() (driver.Value, error) {
if !src.Valid {
return nil, nil
}
return int64(src.Int), nil
}
func (src Int<%= pg_byte_size %>) MarshalJSON() ([]byte, error) {
if !src.Valid {
return []byte("null"), nil
}
return []byte(strconv.FormatInt(int64(src.Int), 10)), nil
}
func (dst *Int<%= pg_byte_size %>) UnmarshalJSON(b []byte) error {
var n *int<%= pg_bit_size %>
err := json.Unmarshal(b, &n)
if err != nil {
return err
}
if n == nil {
*dst = Int<%= pg_byte_size %>{}
} else {
*dst = Int<%= pg_byte_size %>{Int: *n, Valid: true}
}
return nil
}
type Int<%= pg_byte_size %>Codec struct{}
func (Int<%= pg_byte_size %>Codec) FormatSupported(format int16) bool {
return format == TextFormatCode || format == BinaryFormatCode
}
func (Int<%= pg_byte_size %>Codec) PreferredFormat() int16 {
return BinaryFormatCode
}
func (Int<%= pg_byte_size %>Codec) PlanEncode(ci *ConnInfo, oid uint32, format int16, value interface{}) EncodePlan {
switch format {
case BinaryFormatCode:
return &encodePlanInt<%= pg_byte_size %>CodecBinary{}
case TextFormatCode:
return &encodePlanInt<%= pg_byte_size %>CodecText{}
}
return nil
}
type encodePlanInt<%= pg_byte_size %>CodecBinary struct{}
func (p *encodePlanInt<%= pg_byte_size %>CodecBinary) Encode(value interface{}, buf []byte) (newBuf []byte, err error) {
n, valid, err := convertToInt64ForEncode(value)
if err != nil {
return nil, fmt.Errorf("cannot convert %v to int<%= pg_byte_size %>: %v", value, err)
}
if !valid {
return nil, nil
}
if n > math.MaxInt<%= pg_bit_size %> {
return nil, fmt.Errorf("%d is greater than maximum value for int<%= pg_byte_size %>", n)
}
if n < math.MinInt<%= pg_bit_size %> {
return nil, fmt.Errorf("%d is less than minimum value for int<%= pg_byte_size %>", n)
}
return pgio.AppendInt<%= pg_bit_size %>(buf, int<%= pg_bit_size %>(n)), nil
}
type encodePlanInt<%= pg_byte_size %>CodecText struct{}
func (p *encodePlanInt<%= pg_byte_size %>CodecText) Encode(value interface{}, buf []byte) (newBuf []byte, err error) {
n, valid, err := convertToInt64ForEncode(value)
if err != nil {
return nil, fmt.Errorf("cannot convert %v to int<%= pg_byte_size %>: %v", value, err)
}
if !valid {
return nil, nil
}
if n > math.MaxInt<%= pg_bit_size %> {
return nil, fmt.Errorf("%d is greater than maximum value for int<%= pg_byte_size %>", n)
}
if n < math.MinInt<%= pg_bit_size %> {
return nil, fmt.Errorf("%d is less than minimum value for int<%= pg_byte_size %>", n)
}
return append(buf, strconv.FormatInt(n, 10)...), nil
}
func (Int<%= pg_byte_size %>Codec) PlanScan(ci *ConnInfo, oid uint32, format int16, target interface{}, actualTarget bool) ScanPlan {
switch format {
case BinaryFormatCode:
switch target.(type) {
case *int8:
return scanPlanBinaryInt<%= pg_byte_size %>ToInt8{}
case *int16:
return scanPlanBinaryInt<%= pg_byte_size %>ToInt16{}
case *int32:
return scanPlanBinaryInt<%= pg_byte_size %>ToInt32{}
case *int64:
return scanPlanBinaryInt<%= pg_byte_size %>ToInt64{}
case *int:
return scanPlanBinaryInt<%= pg_byte_size %>ToInt{}
case *uint8:
return scanPlanBinaryInt<%= pg_byte_size %>ToUint8{}
case *uint16:
return scanPlanBinaryInt<%= pg_byte_size %>ToUint16{}
case *uint32:
return scanPlanBinaryInt<%= pg_byte_size %>ToUint32{}
case *uint64:
return scanPlanBinaryInt<%= pg_byte_size %>ToUint64{}
case *uint:
return scanPlanBinaryInt<%= pg_byte_size %>ToUint{}
case Int64Scanner:
return scanPlanBinaryInt<%= pg_byte_size %>ToInt64Scanner{}
}
case TextFormatCode:
switch target.(type) {
case *int8:
return scanPlanTextAnyToInt8{}
case *int16:
return scanPlanTextAnyToInt16{}
case *int32:
return scanPlanTextAnyToInt32{}
case *int64:
return scanPlanTextAnyToInt64{}
case *int:
return scanPlanTextAnyToInt{}
case *uint8:
return scanPlanTextAnyToUint8{}
case *uint16:
return scanPlanTextAnyToUint16{}
case *uint32:
return scanPlanTextAnyToUint32{}
case *uint64:
return scanPlanTextAnyToUint64{}
case *uint:
return scanPlanTextAnyToUint{}
case Int64Scanner:
return scanPlanTextAnyToInt64Scanner{}
}
}
return nil
}
func (c Int<%= pg_byte_size %>Codec) DecodeDatabaseSQLValue(ci *ConnInfo, oid uint32, format int16, src []byte) (driver.Value, error) {
if src == nil {
return nil, nil
}
var n int64
err := codecScan(c, ci, oid, format, src, &n)
if err != nil {
return nil, err
}
return n, nil
}
func (c Int<%= pg_byte_size %>Codec) DecodeValue(ci *ConnInfo, oid uint32, format int16, src []byte) (interface{}, error) {
if src == nil {
return nil, nil
}
var n int<%= pg_bit_size %>
err := codecScan(c, ci, oid, format, src, &n)
if err != nil {
return nil, err
}
return n, nil
}
<%# PostgreSQL binary format integer to fixed size Go integers %>
<% [8, 16, 32, 64].each do |dst_bit_size| %>
type scanPlanBinaryInt<%= pg_byte_size %>ToInt<%= dst_bit_size %> struct{}
func (scanPlanBinaryInt<%= pg_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) != <%= pg_byte_size %> {
return fmt.Errorf("invalid length for int<%= pg_byte_size %>: %v", len(src))
}
p, ok := (dst).(*int<%= dst_bit_size %>)
if !ok {
return ErrScanTargetTypeChanged
}
<% if dst_bit_size < pg_bit_size %>
n := int<%= pg_bit_size %>(binary.BigEndian.Uint<%= pg_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)
<% elsif dst_bit_size == pg_bit_size %>
*p = int<%= dst_bit_size %>(binary.BigEndian.Uint<%= pg_bit_size %>(src))
<% else %>
*p = int<%= dst_bit_size %>(int<%= pg_bit_size %>(binary.BigEndian.Uint<%= pg_bit_size %>(src)))
<% end %>
return nil
}
type scanPlanBinaryInt<%= pg_byte_size %>ToUint<%= dst_bit_size %> struct{}
func (scanPlanBinaryInt<%= pg_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) != <%= pg_byte_size %> {
return fmt.Errorf("invalid length for uint<%= pg_byte_size %>: %v", len(src))
}
p, ok := (dst).(*uint<%= dst_bit_size %>)
if !ok {
return ErrScanTargetTypeChanged
}
n := int<%= pg_bit_size %>(binary.BigEndian.Uint<%= pg_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 < pg_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 %>
<%# PostgreSQL binary format integer to Go machine integers %>
type scanPlanBinaryInt<%= pg_byte_size %>ToInt struct{}
func (scanPlanBinaryInt<%= pg_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) != <%= pg_byte_size %> {
return fmt.Errorf("invalid length for int<%= pg_byte_size %>: %v", len(src))
}
p, ok := (dst).(*int)
if !ok {
return ErrScanTargetTypeChanged
}
<% if 32 < pg_bit_size %>
n := int64(binary.BigEndian.Uint<%= pg_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(int<%= pg_bit_size %>(binary.BigEndian.Uint<%= pg_bit_size %>(src)))
<% end %>
return nil
}
type scanPlanBinaryInt<%= pg_byte_size %>ToUint struct{}
func (scanPlanBinaryInt<%= pg_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) != <%= pg_byte_size %> {
return fmt.Errorf("invalid length for uint<%= pg_byte_size %>: %v", len(src))
}
p, ok := (dst).(*uint)
if !ok {
return ErrScanTargetTypeChanged
}
n := int64(int<%= pg_bit_size %>(binary.BigEndian.Uint<%= pg_bit_size %>(src)))
if n < 0 {
return fmt.Errorf("%d is less than minimum value for uint", n)
}
<% if 32 < pg_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
}
<%# PostgreSQL binary format integer to Go Int64Scanner %>
type scanPlanBinaryInt<%= pg_byte_size %>ToInt64Scanner struct{}
func (scanPlanBinaryInt<%= pg_byte_size %>ToInt64Scanner) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error {
s, ok := (dst).(Int64Scanner)
if !ok {
return ErrScanTargetTypeChanged
}
if src == nil {
return s.ScanInt64(0, false)
}
if len(src) != <%= pg_byte_size %> {
return fmt.Errorf("invalid length for int<%= pg_byte_size %>: %v", len(src))
}
n := int64(binary.BigEndian.Uint<%= pg_bit_size %>(src))
return s.ScanInt64(n, true)
}
<% end %>
<%# Any text to all integer types %>
<% [
["8", 8],
["16", 16],
["32", 32],
["64", 64],
["", 0]
].each do |type_suffix, bit_size| %>
type scanPlanTextAnyToInt<%= type_suffix %> struct{}
func (scanPlanTextAnyToInt<%= type_suffix %>) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error {
if src == nil {
return fmt.Errorf("cannot scan null into %T", dst)
}
p, ok := (dst).(*int<%= type_suffix %>)
if !ok {
return ErrScanTargetTypeChanged
}
n, err := strconv.ParseInt(string(src), 10, <%= bit_size %>)
if err != nil {
return err
}
*p = int<%= type_suffix %>(n)
return nil
}
type scanPlanTextAnyToUint<%= type_suffix %> struct{}
func (scanPlanTextAnyToUint<%= type_suffix %>) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error {
if src == nil {
return fmt.Errorf("cannot scan null into %T", dst)
}
p, ok := (dst).(*uint<%= type_suffix %>)
if !ok {
return ErrScanTargetTypeChanged
}
n, err := strconv.ParseUint(string(src), 10, <%= bit_size %>)
if err != nil {
return err
}
*p = uint<%= type_suffix %>(n)
return nil
}
<% end %>
type scanPlanTextAnyToInt64Scanner struct{}
func (scanPlanTextAnyToInt64Scanner) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error {
s, ok := (dst).(Int64Scanner)
if !ok {
return ErrScanTargetTypeChanged
}
if src == nil {
return s.ScanInt64(0, false)
}
n, err := strconv.ParseInt(string(src), 10, 64)
if err != nil {
return err
}
err = s.ScanInt64(n, true)
if err != nil {
return err
}
return nil
}