...

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

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

     1  package pgtype
     2  
     3  import (
     4  	"database/sql/driver"
     5  	"encoding/hex"
     6  	"fmt"
     7  )
     8  
     9  type BytesScanner interface {
    10  	// ScanBytes receives a byte slice of driver memory that is only valid until the next database method call.
    11  	ScanBytes(v []byte) error
    12  }
    13  
    14  type BytesValuer interface {
    15  	// BytesValue returns a byte slice of the byte data. The caller must not change the returned slice.
    16  	BytesValue() ([]byte, error)
    17  }
    18  
    19  // DriverBytes is a byte slice that holds a reference to memory owned by the driver. It is only valid from the time it
    20  // is scanned until Rows.Next or Rows.Close is called. It is never safe to use DriverBytes with QueryRow as Row.Scan
    21  // internally calls Rows.Close before returning.
    22  type DriverBytes []byte
    23  
    24  func (b *DriverBytes) ScanBytes(v []byte) error {
    25  	*b = v
    26  	return nil
    27  }
    28  
    29  // PreallocBytes is a byte slice of preallocated memory that scanned bytes will be copied to. If it is too small a new
    30  // slice will be allocated.
    31  type PreallocBytes []byte
    32  
    33  func (b *PreallocBytes) ScanBytes(v []byte) error {
    34  	if v == nil {
    35  		*b = nil
    36  		return nil
    37  	}
    38  
    39  	if len(v) <= len(*b) {
    40  		*b = (*b)[:len(v)]
    41  	} else {
    42  		*b = make(PreallocBytes, len(v))
    43  	}
    44  	copy(*b, v)
    45  	return nil
    46  }
    47  
    48  // UndecodedBytes can be used as a scan target to get the raw bytes from PostgreSQL without any decoding.
    49  type UndecodedBytes []byte
    50  
    51  type scanPlanAnyToUndecodedBytes struct{}
    52  
    53  func (scanPlanAnyToUndecodedBytes) Scan(src []byte, dst any) error {
    54  	dstBuf := dst.(*UndecodedBytes)
    55  	if src == nil {
    56  		*dstBuf = nil
    57  		return nil
    58  	}
    59  
    60  	*dstBuf = make([]byte, len(src))
    61  	copy(*dstBuf, src)
    62  	return nil
    63  }
    64  
    65  type ByteaCodec struct{}
    66  
    67  func (ByteaCodec) FormatSupported(format int16) bool {
    68  	return format == TextFormatCode || format == BinaryFormatCode
    69  }
    70  
    71  func (ByteaCodec) PreferredFormat() int16 {
    72  	return BinaryFormatCode
    73  }
    74  
    75  func (ByteaCodec) PlanEncode(m *Map, oid uint32, format int16, value any) EncodePlan {
    76  	switch format {
    77  	case BinaryFormatCode:
    78  		switch value.(type) {
    79  		case []byte:
    80  			return encodePlanBytesCodecBinaryBytes{}
    81  		case BytesValuer:
    82  			return encodePlanBytesCodecBinaryBytesValuer{}
    83  		}
    84  	case TextFormatCode:
    85  		switch value.(type) {
    86  		case []byte:
    87  			return encodePlanBytesCodecTextBytes{}
    88  		case BytesValuer:
    89  			return encodePlanBytesCodecTextBytesValuer{}
    90  		}
    91  	}
    92  
    93  	return nil
    94  }
    95  
    96  type encodePlanBytesCodecBinaryBytes struct{}
    97  
    98  func (encodePlanBytesCodecBinaryBytes) Encode(value any, buf []byte) (newBuf []byte, err error) {
    99  	b := value.([]byte)
   100  	if b == nil {
   101  		return nil, nil
   102  	}
   103  
   104  	return append(buf, b...), nil
   105  }
   106  
   107  type encodePlanBytesCodecBinaryBytesValuer struct{}
   108  
   109  func (encodePlanBytesCodecBinaryBytesValuer) Encode(value any, buf []byte) (newBuf []byte, err error) {
   110  	b, err := value.(BytesValuer).BytesValue()
   111  	if err != nil {
   112  		return nil, err
   113  	}
   114  	if b == nil {
   115  		return nil, nil
   116  	}
   117  
   118  	return append(buf, b...), nil
   119  }
   120  
   121  type encodePlanBytesCodecTextBytes struct{}
   122  
   123  func (encodePlanBytesCodecTextBytes) Encode(value any, buf []byte) (newBuf []byte, err error) {
   124  	b := value.([]byte)
   125  	if b == nil {
   126  		return nil, nil
   127  	}
   128  
   129  	buf = append(buf, `\x`...)
   130  	buf = append(buf, hex.EncodeToString(b)...)
   131  	return buf, nil
   132  }
   133  
   134  type encodePlanBytesCodecTextBytesValuer struct{}
   135  
   136  func (encodePlanBytesCodecTextBytesValuer) Encode(value any, buf []byte) (newBuf []byte, err error) {
   137  	b, err := value.(BytesValuer).BytesValue()
   138  	if err != nil {
   139  		return nil, err
   140  	}
   141  	if b == nil {
   142  		return nil, nil
   143  	}
   144  
   145  	buf = append(buf, `\x`...)
   146  	buf = append(buf, hex.EncodeToString(b)...)
   147  	return buf, nil
   148  }
   149  
   150  func (ByteaCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
   151  
   152  	switch format {
   153  	case BinaryFormatCode:
   154  		switch target.(type) {
   155  		case *[]byte:
   156  			return scanPlanBinaryBytesToBytes{}
   157  		case BytesScanner:
   158  			return scanPlanBinaryBytesToBytesScanner{}
   159  		}
   160  	case TextFormatCode:
   161  		switch target.(type) {
   162  		case *[]byte:
   163  			return scanPlanTextByteaToBytes{}
   164  		case BytesScanner:
   165  			return scanPlanTextByteaToBytesScanner{}
   166  		}
   167  	}
   168  
   169  	return nil
   170  }
   171  
   172  type scanPlanBinaryBytesToBytes struct{}
   173  
   174  func (scanPlanBinaryBytesToBytes) Scan(src []byte, dst any) error {
   175  	dstBuf := dst.(*[]byte)
   176  	if src == nil {
   177  		*dstBuf = nil
   178  		return nil
   179  	}
   180  
   181  	*dstBuf = make([]byte, len(src))
   182  	copy(*dstBuf, src)
   183  	return nil
   184  }
   185  
   186  type scanPlanBinaryBytesToBytesScanner struct{}
   187  
   188  func (scanPlanBinaryBytesToBytesScanner) Scan(src []byte, dst any) error {
   189  	scanner := (dst).(BytesScanner)
   190  	return scanner.ScanBytes(src)
   191  }
   192  
   193  type scanPlanTextByteaToBytes struct{}
   194  
   195  func (scanPlanTextByteaToBytes) Scan(src []byte, dst any) error {
   196  	dstBuf := dst.(*[]byte)
   197  	if src == nil {
   198  		*dstBuf = nil
   199  		return nil
   200  	}
   201  
   202  	buf, err := decodeHexBytea(src)
   203  	if err != nil {
   204  		return err
   205  	}
   206  	*dstBuf = buf
   207  
   208  	return nil
   209  }
   210  
   211  type scanPlanTextByteaToBytesScanner struct{}
   212  
   213  func (scanPlanTextByteaToBytesScanner) Scan(src []byte, dst any) error {
   214  	scanner := (dst).(BytesScanner)
   215  	buf, err := decodeHexBytea(src)
   216  	if err != nil {
   217  		return err
   218  	}
   219  	return scanner.ScanBytes(buf)
   220  }
   221  
   222  func decodeHexBytea(src []byte) ([]byte, error) {
   223  	if src == nil {
   224  		return nil, nil
   225  	}
   226  
   227  	if len(src) < 2 || src[0] != '\\' || src[1] != 'x' {
   228  		return nil, fmt.Errorf("invalid hex format")
   229  	}
   230  
   231  	buf := make([]byte, (len(src)-2)/2)
   232  	_, err := hex.Decode(buf, src[2:])
   233  	if err != nil {
   234  		return nil, err
   235  	}
   236  
   237  	return buf, nil
   238  }
   239  
   240  func (c ByteaCodec) DecodeDatabaseSQLValue(m *Map, oid uint32, format int16, src []byte) (driver.Value, error) {
   241  	return c.DecodeValue(m, oid, format, src)
   242  }
   243  
   244  func (c ByteaCodec) DecodeValue(m *Map, oid uint32, format int16, src []byte) (any, error) {
   245  	if src == nil {
   246  		return nil, nil
   247  	}
   248  
   249  	var buf []byte
   250  	err := codecScan(c, m, oid, format, src, &buf)
   251  	if err != nil {
   252  		return nil, err
   253  	}
   254  	return buf, nil
   255  }
   256  

View as plain text