147 lines
3.1 KiB
Go
147 lines
3.1 KiB
Go
package pgtype
|
|
|
|
import (
|
|
"database/sql/driver"
|
|
"fmt"
|
|
"math"
|
|
"strconv"
|
|
|
|
"github.com/jackc/pgio"
|
|
)
|
|
|
|
type Int2Codec struct{}
|
|
|
|
func (Int2Codec) FormatSupported(format int16) bool {
|
|
return format == TextFormatCode || format == BinaryFormatCode
|
|
}
|
|
|
|
func (Int2Codec) PreferredFormat() int16 {
|
|
return BinaryFormatCode
|
|
}
|
|
|
|
func (Int2Codec) Encode(ci *ConnInfo, oid uint32, format int16, value interface{}, buf []byte) (newBuf []byte, err error) {
|
|
n, valid, err := convertToInt64ForEncode(value)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("cannot convert %v to int2: %v", value, err)
|
|
}
|
|
if !valid {
|
|
return nil, nil
|
|
}
|
|
|
|
if n > math.MaxInt16 {
|
|
return nil, fmt.Errorf("%d is greater than maximum value for int2", n)
|
|
}
|
|
if n < math.MinInt16 {
|
|
return nil, fmt.Errorf("%d is less than minimum value for int2", n)
|
|
}
|
|
|
|
switch format {
|
|
case BinaryFormatCode:
|
|
return pgio.AppendInt16(buf, int16(n)), nil
|
|
case TextFormatCode:
|
|
return append(buf, strconv.FormatInt(n, 10)...), nil
|
|
default:
|
|
return nil, fmt.Errorf("unknown format code: %v", format)
|
|
}
|
|
}
|
|
|
|
func (Int2Codec) PlanScan(ci *ConnInfo, oid uint32, format int16, target interface{}, actualTarget bool) ScanPlan {
|
|
switch format {
|
|
case BinaryFormatCode:
|
|
case TextFormatCode:
|
|
switch target.(type) {
|
|
case *int16:
|
|
return scanPlanTextToAnyInt16{}
|
|
case *int32:
|
|
return scanPlanTextToAnyInt32{}
|
|
case *int64:
|
|
return scanPlanTextToAnyInt64{}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (c Int2Codec) DecodeDatabaseSQLValue(ci *ConnInfo, oid uint32, format int16, src []byte) (driver.Value, error) {
|
|
if src == nil {
|
|
return nil, nil
|
|
}
|
|
|
|
var n int64
|
|
err := c.PlanScan(ci, oid, format, &n, true).Scan(ci, oid, format, src, &n)
|
|
return n, err
|
|
}
|
|
|
|
func (c Int2Codec) DecodeValue(ci *ConnInfo, oid uint32, format int16, src []byte) (interface{}, error) {
|
|
if src == nil {
|
|
return nil, nil
|
|
}
|
|
|
|
var n int16
|
|
err := c.PlanScan(ci, oid, format, &n, true).Scan(ci, oid, format, src, &n)
|
|
return n, err
|
|
}
|
|
|
|
type scanPlanTextToAnyInt16 struct{}
|
|
|
|
func (scanPlanTextToAnyInt16) 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).(*int16)
|
|
if !ok {
|
|
return ErrScanTargetTypeChanged
|
|
}
|
|
|
|
n, err := strconv.ParseInt(string(src), 10, 16)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
*p = int16(n)
|
|
return nil
|
|
}
|
|
|
|
type scanPlanTextToAnyInt32 struct{}
|
|
|
|
func (scanPlanTextToAnyInt32) 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).(*int32)
|
|
if !ok {
|
|
return ErrScanTargetTypeChanged
|
|
}
|
|
|
|
n, err := strconv.ParseInt(string(src), 10, 32)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
*p = int32(n)
|
|
return nil
|
|
}
|
|
|
|
type scanPlanTextToAnyInt64 struct{}
|
|
|
|
func (scanPlanTextToAnyInt64) 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).(*int64)
|
|
if !ok {
|
|
return ErrScanTargetTypeChanged
|
|
}
|
|
|
|
n, err := strconv.ParseInt(string(src), 10, 64)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
*p = int64(n)
|
|
return nil
|
|
}
|