...

Source file src/github.com/jackc/pgx/v5/pgtype/qchar.go

Documentation: github.com/jackc/pgx/v5/pgtype

     1  package pgtype
     2  
     3  import (
     4  	"database/sql/driver"
     5  	"fmt"
     6  	"math"
     7  )
     8  
     9  // QCharCodec is for PostgreSQL's special 8-bit-only "char" type more akin to the C
    10  // language's char type, or Go's byte type. (Note that the name in PostgreSQL
    11  // itself is "char", in double-quotes, and not char.) It gets used a lot in
    12  // PostgreSQL's system tables to hold a single ASCII character value (eg
    13  // pg_class.relkind). It is named Qchar for quoted char to disambiguate from SQL
    14  // standard type char.
    15  type QCharCodec struct{}
    16  
    17  func (QCharCodec) FormatSupported(format int16) bool {
    18  	return format == TextFormatCode || format == BinaryFormatCode
    19  }
    20  
    21  func (QCharCodec) PreferredFormat() int16 {
    22  	return BinaryFormatCode
    23  }
    24  
    25  func (QCharCodec) PlanEncode(m *Map, oid uint32, format int16, value any) EncodePlan {
    26  	switch format {
    27  	case TextFormatCode, BinaryFormatCode:
    28  		switch value.(type) {
    29  		case byte:
    30  			return encodePlanQcharCodecByte{}
    31  		case rune:
    32  			return encodePlanQcharCodecRune{}
    33  		}
    34  	}
    35  
    36  	return nil
    37  }
    38  
    39  type encodePlanQcharCodecByte struct{}
    40  
    41  func (encodePlanQcharCodecByte) Encode(value any, buf []byte) (newBuf []byte, err error) {
    42  	b := value.(byte)
    43  	buf = append(buf, b)
    44  	return buf, nil
    45  }
    46  
    47  type encodePlanQcharCodecRune struct{}
    48  
    49  func (encodePlanQcharCodecRune) Encode(value any, buf []byte) (newBuf []byte, err error) {
    50  	r := value.(rune)
    51  	if r > math.MaxUint8 {
    52  		return nil, fmt.Errorf(`%v cannot be encoded to "char"`, r)
    53  	}
    54  	b := byte(r)
    55  	buf = append(buf, b)
    56  	return buf, nil
    57  }
    58  
    59  func (QCharCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
    60  	switch format {
    61  	case TextFormatCode, BinaryFormatCode:
    62  		switch target.(type) {
    63  		case *byte:
    64  			return scanPlanQcharCodecByte{}
    65  		case *rune:
    66  			return scanPlanQcharCodecRune{}
    67  		}
    68  	}
    69  
    70  	return nil
    71  }
    72  
    73  type scanPlanQcharCodecByte struct{}
    74  
    75  func (scanPlanQcharCodecByte) Scan(src []byte, dst any) error {
    76  	if src == nil {
    77  		return fmt.Errorf("cannot scan NULL into %T", dst)
    78  	}
    79  
    80  	if len(src) > 1 {
    81  		return fmt.Errorf(`invalid length for "char": %v`, len(src))
    82  	}
    83  
    84  	b := dst.(*byte)
    85  	// In the text format the zero value is returned as a zero byte value instead of 0
    86  	if len(src) == 0 {
    87  		*b = 0
    88  	} else {
    89  		*b = src[0]
    90  	}
    91  
    92  	return nil
    93  }
    94  
    95  type scanPlanQcharCodecRune struct{}
    96  
    97  func (scanPlanQcharCodecRune) Scan(src []byte, dst any) error {
    98  	if src == nil {
    99  		return fmt.Errorf("cannot scan NULL into %T", dst)
   100  	}
   101  
   102  	if len(src) > 1 {
   103  		return fmt.Errorf(`invalid length for "char": %v`, len(src))
   104  	}
   105  
   106  	r := dst.(*rune)
   107  	// In the text format the zero value is returned as a zero byte value instead of 0
   108  	if len(src) == 0 {
   109  		*r = 0
   110  	} else {
   111  		*r = rune(src[0])
   112  	}
   113  
   114  	return nil
   115  }
   116  
   117  func (c QCharCodec) DecodeDatabaseSQLValue(m *Map, oid uint32, format int16, src []byte) (driver.Value, error) {
   118  	if src == nil {
   119  		return nil, nil
   120  	}
   121  
   122  	var r rune
   123  	err := codecScan(c, m, oid, format, src, &r)
   124  	if err != nil {
   125  		return nil, err
   126  	}
   127  	return string(r), nil
   128  }
   129  
   130  func (c QCharCodec) DecodeValue(m *Map, oid uint32, format int16, src []byte) (any, error) {
   131  	if src == nil {
   132  		return nil, nil
   133  	}
   134  
   135  	var r rune
   136  	err := codecScan(c, m, oid, format, src, &r)
   137  	if err != nil {
   138  		return nil, err
   139  	}
   140  	return r, nil
   141  }
   142  

View as plain text