monzero/vendor/github.com/jackc/pgx/v5/pgtype/qchar.go
Gibheer 6ea4d2c82d switch from github.com/lib/pq to github.com/jackc/pgx/v5
lib/pq is out of maintenance for some time now, so switch to the newer
more active library. Looks like it finally stabilized after a long time.
2024-09-05 19:38:25 +02:00

142 lines
3.1 KiB
Go

package pgtype
import (
"database/sql/driver"
"fmt"
"math"
)
// QCharCodec is for PostgreSQL's special 8-bit-only "char" type more akin to the C
// language's char type, or Go's byte type. (Note that the name in PostgreSQL
// itself is "char", in double-quotes, and not char.) It gets used a lot in
// PostgreSQL's system tables to hold a single ASCII character value (eg
// pg_class.relkind). It is named Qchar for quoted char to disambiguate from SQL
// standard type char.
type QCharCodec struct{}
func (QCharCodec) FormatSupported(format int16) bool {
return format == TextFormatCode || format == BinaryFormatCode
}
func (QCharCodec) PreferredFormat() int16 {
return BinaryFormatCode
}
func (QCharCodec) PlanEncode(m *Map, oid uint32, format int16, value any) EncodePlan {
switch format {
case TextFormatCode, BinaryFormatCode:
switch value.(type) {
case byte:
return encodePlanQcharCodecByte{}
case rune:
return encodePlanQcharCodecRune{}
}
}
return nil
}
type encodePlanQcharCodecByte struct{}
func (encodePlanQcharCodecByte) Encode(value any, buf []byte) (newBuf []byte, err error) {
b := value.(byte)
buf = append(buf, b)
return buf, nil
}
type encodePlanQcharCodecRune struct{}
func (encodePlanQcharCodecRune) Encode(value any, buf []byte) (newBuf []byte, err error) {
r := value.(rune)
if r > math.MaxUint8 {
return nil, fmt.Errorf(`%v cannot be encoded to "char"`, r)
}
b := byte(r)
buf = append(buf, b)
return buf, nil
}
func (QCharCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
switch format {
case TextFormatCode, BinaryFormatCode:
switch target.(type) {
case *byte:
return scanPlanQcharCodecByte{}
case *rune:
return scanPlanQcharCodecRune{}
}
}
return nil
}
type scanPlanQcharCodecByte struct{}
func (scanPlanQcharCodecByte) Scan(src []byte, dst any) error {
if src == nil {
return fmt.Errorf("cannot scan NULL into %T", dst)
}
if len(src) > 1 {
return fmt.Errorf(`invalid length for "char": %v`, len(src))
}
b := dst.(*byte)
// In the text format the zero value is returned as a zero byte value instead of 0
if len(src) == 0 {
*b = 0
} else {
*b = src[0]
}
return nil
}
type scanPlanQcharCodecRune struct{}
func (scanPlanQcharCodecRune) Scan(src []byte, dst any) error {
if src == nil {
return fmt.Errorf("cannot scan NULL into %T", dst)
}
if len(src) > 1 {
return fmt.Errorf(`invalid length for "char": %v`, len(src))
}
r := dst.(*rune)
// In the text format the zero value is returned as a zero byte value instead of 0
if len(src) == 0 {
*r = 0
} else {
*r = rune(src[0])
}
return nil
}
func (c QCharCodec) DecodeDatabaseSQLValue(m *Map, oid uint32, format int16, src []byte) (driver.Value, error) {
if src == nil {
return nil, nil
}
var r rune
err := codecScan(c, m, oid, format, src, &r)
if err != nil {
return nil, err
}
return string(r), nil
}
func (c QCharCodec) DecodeValue(m *Map, oid uint32, format int16, src []byte) (any, error) {
if src == nil {
return nil, nil
}
var r rune
err := codecScan(c, m, oid, format, src, &r)
if err != nil {
return nil, err
}
return r, nil
}