github.com/jackc/pgx/v5@v5.5.5/pgtype/int.go.erb (about)

     1  package pgtype
     2  
     3  import (
     4  	"database/sql/driver"
     5  	"encoding/binary"
     6  	"encoding/json"
     7  	"fmt"
     8  	"math"
     9  	"strconv"
    10  
    11  	"github.com/jackc/pgx/v5/internal/pgio"
    12  )
    13  
    14  type Int64Scanner interface {
    15  	ScanInt64(Int8) error
    16  }
    17  
    18  type Int64Valuer interface {
    19  	Int64Value() (Int8, error)
    20  }
    21  
    22  
    23  <% [2, 4, 8].each do |pg_byte_size| %>
    24  <% pg_bit_size = pg_byte_size * 8 %>
    25  type Int<%= pg_byte_size %> struct {
    26  	Int<%= pg_bit_size %>   int<%= pg_bit_size %>
    27  	Valid bool
    28  }
    29  
    30  // ScanInt64 implements the Int64Scanner interface.
    31  func (dst *Int<%= pg_byte_size %>) ScanInt64(n Int8) error {
    32  	if !n.Valid {
    33  		*dst = Int<%= pg_byte_size %>{}
    34  		return nil
    35  	}
    36  
    37  	if n.Int64 < math.MinInt<%= pg_bit_size %> {
    38  		return fmt.Errorf("%d is less than minimum value for Int<%= pg_byte_size %>", n.Int64)
    39  	}
    40  	if n.Int64 > math.MaxInt<%= pg_bit_size %> {
    41  		return fmt.Errorf("%d is greater than maximum value for Int<%= pg_byte_size %>", n.Int64)
    42  	}
    43  	*dst = Int<%= pg_byte_size %>{Int<%= pg_bit_size %>: int<%= pg_bit_size %>(n.Int64), Valid: true}
    44  
    45  	return nil
    46  }
    47  
    48  func (n Int<%= pg_byte_size %>) Int64Value() (Int8, error) {
    49  	return Int8{Int64: int64(n.Int<%= pg_bit_size %>), Valid: n.Valid}, nil
    50  }
    51  
    52  // Scan implements the database/sql Scanner interface.
    53  func (dst *Int<%= pg_byte_size %>) Scan(src any) error {
    54  	if src == nil {
    55  		*dst = Int<%= pg_byte_size %>{}
    56  		return nil
    57  	}
    58  
    59  	var n int64
    60  
    61  	switch src := src.(type) {
    62  	case int64:
    63  		n = src
    64  	case string:
    65  		var err error
    66  		n, err = strconv.ParseInt(src, 10, <%= pg_bit_size %>)
    67  		if err != nil {
    68  			return err
    69  		}
    70  	case []byte:
    71  		var err error
    72  		n, err = strconv.ParseInt(string(src), 10, <%= pg_bit_size %>)
    73  		if err != nil {
    74  			return err
    75  		}
    76  	default:
    77  		return fmt.Errorf("cannot scan %T", src)
    78  	}
    79  
    80  	if n < math.MinInt<%= pg_bit_size %> {
    81  		return fmt.Errorf("%d is greater than maximum value for Int<%= pg_byte_size %>", n)
    82  	}
    83  	if n > math.MaxInt<%= pg_bit_size %> {
    84  		return fmt.Errorf("%d is greater than maximum value for Int<%= pg_byte_size %>", n)
    85  	}
    86  	*dst = Int<%= pg_byte_size %>{Int<%= pg_bit_size %>: int<%= pg_bit_size %>(n), Valid: true}
    87  
    88  	return nil
    89  }
    90  
    91  // Value implements the database/sql/driver Valuer interface.
    92  func (src Int<%= pg_byte_size %>) Value() (driver.Value, error) {
    93  	if !src.Valid {
    94  		return nil, nil
    95  	}
    96  	return int64(src.Int<%= pg_bit_size %>), nil
    97  }
    98  
    99  func (src Int<%= pg_byte_size %>) MarshalJSON() ([]byte, error) {
   100  	if !src.Valid {
   101  		return []byte("null"), nil
   102  	}
   103  	return []byte(strconv.FormatInt(int64(src.Int<%= pg_bit_size %>), 10)), nil
   104  }
   105  
   106  func (dst *Int<%= pg_byte_size %>) UnmarshalJSON(b []byte) error {
   107  	var n *int<%= pg_bit_size %>
   108  	err := json.Unmarshal(b, &n)
   109  	if err != nil {
   110  		return err
   111  	}
   112  
   113  	if n == nil {
   114  		*dst = Int<%= pg_byte_size %>{}
   115  	} else {
   116  		*dst = Int<%= pg_byte_size %>{Int<%= pg_bit_size %>: *n, Valid: true}
   117  	}
   118  
   119  	return nil
   120  }
   121  
   122  type Int<%= pg_byte_size %>Codec struct{}
   123  
   124  func (Int<%= pg_byte_size %>Codec) FormatSupported(format int16) bool {
   125  	return format == TextFormatCode || format == BinaryFormatCode
   126  }
   127  
   128  func (Int<%= pg_byte_size %>Codec) PreferredFormat() int16 {
   129  	return BinaryFormatCode
   130  }
   131  
   132  func (Int<%= pg_byte_size %>Codec) PlanEncode(m *Map, oid uint32, format int16, value any) EncodePlan {
   133  	switch format {
   134  	case BinaryFormatCode:
   135  		switch value.(type) {
   136  		case int<%= pg_bit_size %>:
   137  			return encodePlanInt<%= pg_byte_size %>CodecBinaryInt<%= pg_bit_size %>{}
   138  		case Int64Valuer:
   139  			return encodePlanInt<%= pg_byte_size %>CodecBinaryInt64Valuer{}
   140  		}
   141  	case TextFormatCode:
   142  		switch value.(type) {
   143  		case int<%= pg_bit_size %>:
   144  			return encodePlanInt<%= pg_byte_size %>CodecTextInt<%= pg_bit_size %>{}
   145  		case Int64Valuer:
   146  			return encodePlanInt<%= pg_byte_size %>CodecTextInt64Valuer{}
   147  		}
   148  	}
   149  
   150  	return nil
   151  }
   152  
   153  type encodePlanInt<%= pg_byte_size %>CodecBinaryInt<%= pg_bit_size %> struct{}
   154  
   155  func (encodePlanInt<%= pg_byte_size %>CodecBinaryInt<%= pg_bit_size %>) Encode(value any, buf []byte) (newBuf []byte, err error) {
   156    n := value.(int<%= pg_bit_size %>)
   157    return pgio.AppendInt<%= pg_bit_size %>(buf, int<%= pg_bit_size %>(n)), nil
   158  }
   159  
   160  type encodePlanInt<%= pg_byte_size %>CodecTextInt<%= pg_bit_size %> struct{}
   161  
   162  func (encodePlanInt<%= pg_byte_size %>CodecTextInt<%= pg_bit_size %>) Encode(value any, buf []byte) (newBuf []byte, err error) {
   163    n := value.(int<%= pg_bit_size %>)
   164    return append(buf, strconv.FormatInt(int64(n), 10)...), nil
   165  }
   166  
   167  type encodePlanInt<%= pg_byte_size %>CodecBinaryInt64Valuer struct{}
   168  
   169  func (encodePlanInt<%= pg_byte_size %>CodecBinaryInt64Valuer) Encode(value any, buf []byte) (newBuf []byte, err error) {
   170    n, err := value.(Int64Valuer).Int64Value()
   171  	if err != nil {
   172  		return nil, err
   173  	}
   174  
   175  	if !n.Valid {
   176  		return nil, nil
   177  	}
   178  
   179  	if n.Int64 > math.MaxInt<%= pg_bit_size %> {
   180  		return nil, fmt.Errorf("%d is greater than maximum value for int<%= pg_byte_size %>", n.Int64)
   181  	}
   182  	if n.Int64 < math.MinInt<%= pg_bit_size %> {
   183  		return nil, fmt.Errorf("%d is less than minimum value for int<%= pg_byte_size %>", n.Int64)
   184  	}
   185  
   186    return pgio.AppendInt<%= pg_bit_size %>(buf, int<%= pg_bit_size %>(n.Int64)), nil
   187  }
   188  
   189  type encodePlanInt<%= pg_byte_size %>CodecTextInt64Valuer struct{}
   190  
   191  func (encodePlanInt<%= pg_byte_size %>CodecTextInt64Valuer) Encode(value any, buf []byte) (newBuf []byte, err error) {
   192    n, err := value.(Int64Valuer).Int64Value()
   193  	if err != nil {
   194  		return nil, err
   195  	}
   196  
   197  	if !n.Valid {
   198  		return nil, nil
   199  	}
   200  
   201  	if n.Int64 > math.MaxInt<%= pg_bit_size %> {
   202  		return nil, fmt.Errorf("%d is greater than maximum value for int<%= pg_byte_size %>", n.Int64)
   203  	}
   204  	if n.Int64 < math.MinInt<%= pg_bit_size %> {
   205  		return nil, fmt.Errorf("%d is less than minimum value for int<%= pg_byte_size %>", n.Int64)
   206  	}
   207  
   208    return append(buf, strconv.FormatInt(n.Int64, 10)...), nil
   209  }
   210  
   211  func (Int<%= pg_byte_size %>Codec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
   212  
   213  	switch format {
   214  	case BinaryFormatCode:
   215  		switch target.(type) {
   216  		case *int8:
   217  			return scanPlanBinaryInt<%= pg_byte_size %>ToInt8{}
   218  		case *int16:
   219  			return scanPlanBinaryInt<%= pg_byte_size %>ToInt16{}
   220  		case *int32:
   221  			return scanPlanBinaryInt<%= pg_byte_size %>ToInt32{}
   222  		case *int64:
   223  			return scanPlanBinaryInt<%= pg_byte_size %>ToInt64{}
   224  		case *int:
   225  			return scanPlanBinaryInt<%= pg_byte_size %>ToInt{}
   226  		case *uint8:
   227  			return scanPlanBinaryInt<%= pg_byte_size %>ToUint8{}
   228  		case *uint16:
   229  			return scanPlanBinaryInt<%= pg_byte_size %>ToUint16{}
   230  		case *uint32:
   231  			return scanPlanBinaryInt<%= pg_byte_size %>ToUint32{}
   232  		case *uint64:
   233  			return scanPlanBinaryInt<%= pg_byte_size %>ToUint64{}
   234  		case *uint:
   235  			return scanPlanBinaryInt<%= pg_byte_size %>ToUint{}
   236  		case Int64Scanner:
   237  			return scanPlanBinaryInt<%= pg_byte_size %>ToInt64Scanner{}
   238  		case TextScanner:
   239  			return scanPlanBinaryInt<%= pg_byte_size %>ToTextScanner{}
   240  		}
   241  	case TextFormatCode:
   242  		switch target.(type) {
   243  		case *int8:
   244  			return scanPlanTextAnyToInt8{}
   245  		case *int16:
   246  			return scanPlanTextAnyToInt16{}
   247  		case *int32:
   248  			return scanPlanTextAnyToInt32{}
   249  		case *int64:
   250  			return scanPlanTextAnyToInt64{}
   251  		case *int:
   252  			return scanPlanTextAnyToInt{}
   253  		case *uint8:
   254  			return scanPlanTextAnyToUint8{}
   255  		case *uint16:
   256  			return scanPlanTextAnyToUint16{}
   257  		case *uint32:
   258  			return scanPlanTextAnyToUint32{}
   259  		case *uint64:
   260  			return scanPlanTextAnyToUint64{}
   261  		case *uint:
   262  			return scanPlanTextAnyToUint{}
   263  		case Int64Scanner:
   264  			return scanPlanTextAnyToInt64Scanner{}
   265  		}
   266  	}
   267  
   268  	return nil
   269  }
   270  
   271  func (c Int<%= pg_byte_size %>Codec) DecodeDatabaseSQLValue(m *Map, oid uint32, format int16, src []byte) (driver.Value, error) {
   272  	if src == nil {
   273  		return nil, nil
   274  	}
   275  
   276  	var n int64
   277  	err := codecScan(c, m, oid, format, src, &n)
   278  	if err != nil {
   279  		return nil, err
   280  	}
   281  	return n, nil
   282  }
   283  
   284  func (c Int<%= pg_byte_size %>Codec) DecodeValue(m *Map, oid uint32, format int16, src []byte) (any, error) {
   285  	if src == nil {
   286  		return nil, nil
   287  	}
   288  
   289  	var n int<%= pg_bit_size %>
   290  	err := codecScan(c, m, oid, format, src, &n)
   291  	if err != nil {
   292  		return nil, err
   293  	}
   294  	return n, nil
   295  }
   296  
   297  <%# PostgreSQL binary format integer to fixed size Go integers %>
   298  <% [8, 16, 32, 64].each do |dst_bit_size| %>
   299  type scanPlanBinaryInt<%= pg_byte_size %>ToInt<%= dst_bit_size %> struct{}
   300  
   301  func (scanPlanBinaryInt<%= pg_byte_size %>ToInt<%= dst_bit_size %>) Scan(src []byte, dst any) error {
   302  	if src == nil {
   303  		return fmt.Errorf("cannot scan NULL into %T", dst)
   304  	}
   305  
   306  	if len(src) != <%= pg_byte_size %> {
   307  		return fmt.Errorf("invalid length for int<%= pg_byte_size %>: %v", len(src))
   308  	}
   309  
   310  	p, ok := (dst).(*int<%= dst_bit_size %>)
   311  	if !ok {
   312  		return ErrScanTargetTypeChanged
   313  	}
   314  
   315    <% if dst_bit_size < pg_bit_size %>
   316  	n := int<%= pg_bit_size %>(binary.BigEndian.Uint<%= pg_bit_size %>(src))
   317  	if n < math.MinInt<%= dst_bit_size %> {
   318  		return fmt.Errorf("%d is less than minimum value for int<%= dst_bit_size %>", n)
   319  	} else if n > math.MaxInt<%= dst_bit_size %> {
   320  		return fmt.Errorf("%d is greater than maximum value for int<%= dst_bit_size %>", n)
   321  	}
   322  
   323  	*p = int<%= dst_bit_size %>(n)
   324    <% elsif dst_bit_size == pg_bit_size %>
   325  	*p = int<%= dst_bit_size %>(binary.BigEndian.Uint<%= pg_bit_size %>(src))
   326    <% else %>
   327  	*p = int<%= dst_bit_size %>(int<%= pg_bit_size %>(binary.BigEndian.Uint<%= pg_bit_size %>(src)))
   328    <% end %>
   329  
   330  	return nil
   331  }
   332  
   333  type scanPlanBinaryInt<%= pg_byte_size %>ToUint<%= dst_bit_size %> struct{}
   334  
   335  func (scanPlanBinaryInt<%= pg_byte_size %>ToUint<%= dst_bit_size %>) Scan(src []byte, dst any) error {
   336  	if src == nil {
   337  		return fmt.Errorf("cannot scan NULL into %T", dst)
   338  	}
   339  
   340  	if len(src) != <%= pg_byte_size %> {
   341  		return fmt.Errorf("invalid length for uint<%= pg_byte_size %>: %v", len(src))
   342  	}
   343  
   344  	p, ok := (dst).(*uint<%= dst_bit_size %>)
   345  	if !ok {
   346  		return ErrScanTargetTypeChanged
   347  	}
   348  
   349  	n := int<%= pg_bit_size %>(binary.BigEndian.Uint<%= pg_bit_size %>(src))
   350  	if n < 0 {
   351  		return fmt.Errorf("%d is less than minimum value for uint<%= dst_bit_size %>", n)
   352  	}
   353    <% if dst_bit_size < pg_bit_size %>
   354  	if n > math.MaxUint<%= dst_bit_size %> {
   355  		return fmt.Errorf("%d is greater than maximum value for uint<%= dst_bit_size %>", n)
   356  	}
   357    <% end %>
   358  	*p = uint<%= dst_bit_size %>(n)
   359  
   360  	return nil
   361  }
   362  <% end %>
   363  
   364  <%# PostgreSQL binary format integer to Go machine integers %>
   365  type scanPlanBinaryInt<%= pg_byte_size %>ToInt struct{}
   366  
   367  func (scanPlanBinaryInt<%= pg_byte_size %>ToInt) Scan(src []byte, dst any) error {
   368  	if src == nil {
   369  		return fmt.Errorf("cannot scan NULL into %T", dst)
   370  	}
   371  
   372  	if len(src) != <%= pg_byte_size %> {
   373  		return fmt.Errorf("invalid length for int<%= pg_byte_size %>: %v", len(src))
   374  	}
   375  
   376  	p, ok := (dst).(*int)
   377  	if !ok {
   378  		return ErrScanTargetTypeChanged
   379  	}
   380  
   381    <% if 32 < pg_bit_size %>
   382  	n := int64(binary.BigEndian.Uint<%= pg_bit_size %>(src))
   383  	if n < math.MinInt {
   384  		return fmt.Errorf("%d is less than minimum value for int", n)
   385  	} else if n > math.MaxInt {
   386  		return fmt.Errorf("%d is greater than maximum value for int", n)
   387  	}
   388  
   389  	*p = int(n)
   390    <% else %>
   391  	*p = int(int<%= pg_bit_size %>(binary.BigEndian.Uint<%= pg_bit_size %>(src)))
   392    <% end %>
   393  
   394  	return nil
   395  }
   396  
   397  type scanPlanBinaryInt<%= pg_byte_size %>ToUint struct{}
   398  
   399  func (scanPlanBinaryInt<%= pg_byte_size %>ToUint) Scan(src []byte, dst any) error {
   400  	if src == nil {
   401  		return fmt.Errorf("cannot scan NULL into %T", dst)
   402  	}
   403  
   404  	if len(src) != <%= pg_byte_size %> {
   405  		return fmt.Errorf("invalid length for uint<%= pg_byte_size %>: %v", len(src))
   406  	}
   407  
   408  	p, ok := (dst).(*uint)
   409  	if !ok {
   410  		return ErrScanTargetTypeChanged
   411  	}
   412  
   413  	n := int64(int<%= pg_bit_size %>(binary.BigEndian.Uint<%= pg_bit_size %>(src)))
   414  	if n < 0 {
   415  		return fmt.Errorf("%d is less than minimum value for uint", n)
   416  	}
   417    <% if 32 < pg_bit_size %>
   418  	if uint64(n) > math.MaxUint {
   419  		return fmt.Errorf("%d is greater than maximum value for uint", n)
   420  	}
   421    <% end %>
   422  	*p = uint(n)
   423  
   424  	return nil
   425  }
   426  
   427  <%# PostgreSQL binary format integer to Go Int64Scanner %>
   428  type scanPlanBinaryInt<%= pg_byte_size %>ToInt64Scanner struct{}
   429  
   430  func (scanPlanBinaryInt<%= pg_byte_size %>ToInt64Scanner) Scan(src []byte, dst any) error {
   431  	s, ok := (dst).(Int64Scanner)
   432  	if !ok {
   433  		return ErrScanTargetTypeChanged
   434  	}
   435  
   436  	if src == nil {
   437      return s.ScanInt64(Int8{})
   438  	}
   439  
   440  	if len(src) != <%= pg_byte_size %> {
   441  		return fmt.Errorf("invalid length for int<%= pg_byte_size %>: %v", len(src))
   442  	}
   443  
   444  
   445  	n := int64(int<%= pg_bit_size %>(binary.BigEndian.Uint<%= pg_bit_size %>(src)))
   446  
   447    return s.ScanInt64(Int8{Int64: n, Valid: true})
   448  }
   449  
   450  <%# PostgreSQL binary format integer to Go TextScanner %>
   451  type scanPlanBinaryInt<%= pg_byte_size %>ToTextScanner struct{}
   452  
   453  func (scanPlanBinaryInt<%= pg_byte_size %>ToTextScanner) Scan(src []byte, dst any) error {
   454  	s, ok := (dst).(TextScanner)
   455  	if !ok {
   456  		return ErrScanTargetTypeChanged
   457  	}
   458  
   459  	if src == nil {
   460      return s.ScanText(Text{})
   461  	}
   462  
   463  	if len(src) != <%= pg_byte_size %> {
   464  		return fmt.Errorf("invalid length for int<%= pg_byte_size %>: %v", len(src))
   465  	}
   466  
   467  
   468  	n := int64(int<%= pg_bit_size %>(binary.BigEndian.Uint<%= pg_bit_size %>(src)))
   469  
   470    return s.ScanText(Text{String: strconv.FormatInt(n, 10), Valid: true})
   471  }
   472  <% end %>
   473  
   474  <%# Any text to all integer types %>
   475  <% [
   476    ["8", 8],
   477    ["16", 16],
   478    ["32", 32],
   479    ["64", 64],
   480    ["", 0]
   481  ].each do |type_suffix, bit_size| %>
   482  type scanPlanTextAnyToInt<%= type_suffix %> struct{}
   483  
   484  func (scanPlanTextAnyToInt<%= type_suffix %>) Scan(src []byte, dst any) error {
   485  	if src == nil {
   486  		return fmt.Errorf("cannot scan NULL into %T", dst)
   487  	}
   488  
   489  	p, ok := (dst).(*int<%= type_suffix %>)
   490  	if !ok {
   491  		return ErrScanTargetTypeChanged
   492  	}
   493  
   494  	n, err := strconv.ParseInt(string(src), 10, <%= bit_size %>)
   495  	if err != nil {
   496  		return err
   497  	}
   498  
   499  	*p = int<%= type_suffix %>(n)
   500  	return nil
   501  }
   502  
   503  type scanPlanTextAnyToUint<%= type_suffix %> struct{}
   504  
   505  func (scanPlanTextAnyToUint<%= type_suffix %>) Scan(src []byte, dst any) error {
   506  	if src == nil {
   507  		return fmt.Errorf("cannot scan NULL into %T", dst)
   508  	}
   509  
   510  	p, ok := (dst).(*uint<%= type_suffix %>)
   511  	if !ok {
   512  		return ErrScanTargetTypeChanged
   513  	}
   514  
   515  	n, err := strconv.ParseUint(string(src), 10, <%= bit_size %>)
   516  	if err != nil {
   517  		return err
   518  	}
   519  
   520  	*p = uint<%= type_suffix %>(n)
   521  	return nil
   522  }
   523  <% end %>
   524  
   525  type scanPlanTextAnyToInt64Scanner struct{}
   526  
   527  func (scanPlanTextAnyToInt64Scanner) Scan(src []byte, dst any) error {
   528  	s, ok := (dst).(Int64Scanner)
   529  	if !ok {
   530  		return ErrScanTargetTypeChanged
   531  	}
   532  
   533  	if src == nil {
   534      return s.ScanInt64(Int8{})
   535  	}
   536  
   537  	n, err := strconv.ParseInt(string(src), 10, 64)
   538  	if err != nil {
   539  		return err
   540  	}
   541  
   542    err = s.ScanInt64(Int8{Int64: n, Valid: true})
   543  	if err != nil {
   544  		return err
   545  	}
   546  
   547  	return nil
   548  }