mirror of https://github.com/jackc/pgx.git
123 lines
3.3 KiB
Go
123 lines
3.3 KiB
Go
package pgtype
|
|
|
|
import (
|
|
"database/sql/driver"
|
|
"fmt"
|
|
)
|
|
|
|
type LtreeCodec struct{}
|
|
|
|
func (l LtreeCodec) FormatSupported(format int16) bool {
|
|
return format == TextFormatCode || format == BinaryFormatCode
|
|
}
|
|
|
|
// PreferredFormat returns the preferred format.
|
|
func (l LtreeCodec) PreferredFormat() int16 {
|
|
return TextFormatCode
|
|
}
|
|
|
|
// PlanEncode returns an EncodePlan for encoding value into PostgreSQL format for oid and format. If no plan can be
|
|
// found then nil is returned.
|
|
func (l LtreeCodec) PlanEncode(m *Map, oid uint32, format int16, value any) EncodePlan {
|
|
switch format {
|
|
case TextFormatCode:
|
|
return (TextCodec)(l).PlanEncode(m, oid, format, value)
|
|
case BinaryFormatCode:
|
|
switch value.(type) {
|
|
case string:
|
|
return encodeLtreeCodecBinaryString{}
|
|
case []byte:
|
|
return encodeLtreeCodecBinaryByteSlice{}
|
|
case TextValuer:
|
|
return encodeLtreeCodecBinaryTextValuer{}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
type encodeLtreeCodecBinaryString struct{}
|
|
|
|
func (encodeLtreeCodecBinaryString) Encode(value any, buf []byte) (newBuf []byte, err error) {
|
|
ltree := value.(string)
|
|
buf = append(buf, 1)
|
|
return append(buf, ltree...), nil
|
|
}
|
|
|
|
type encodeLtreeCodecBinaryByteSlice struct{}
|
|
|
|
func (encodeLtreeCodecBinaryByteSlice) Encode(value any, buf []byte) (newBuf []byte, err error) {
|
|
ltree := value.([]byte)
|
|
buf = append(buf, 1)
|
|
return append(buf, ltree...), nil
|
|
}
|
|
|
|
type encodeLtreeCodecBinaryTextValuer struct{}
|
|
|
|
func (encodeLtreeCodecBinaryTextValuer) Encode(value any, buf []byte) (newBuf []byte, err error) {
|
|
t, err := value.(TextValuer).TextValue()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if !t.Valid {
|
|
return nil, nil
|
|
}
|
|
|
|
buf = append(buf, 1)
|
|
return append(buf, t.String...), nil
|
|
}
|
|
|
|
// PlanScan returns a ScanPlan for scanning a PostgreSQL value into a destination with the same type as target. If
|
|
// no plan can be found then nil is returned.
|
|
func (l LtreeCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan {
|
|
switch format {
|
|
case TextFormatCode:
|
|
return (TextCodec)(l).PlanScan(m, oid, format, target)
|
|
case BinaryFormatCode:
|
|
switch target.(type) {
|
|
case *string:
|
|
return scanPlanBinaryLtreeToString{}
|
|
case TextScanner:
|
|
return scanPlanBinaryLtreeToTextScanner{}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
type scanPlanBinaryLtreeToString struct{}
|
|
|
|
func (scanPlanBinaryLtreeToString) Scan(src []byte, target any) error {
|
|
version := src[0]
|
|
if version != 1 {
|
|
return fmt.Errorf("unsupported ltree version %d", version)
|
|
}
|
|
|
|
p := (target).(*string)
|
|
*p = string(src[1:])
|
|
|
|
return nil
|
|
}
|
|
|
|
type scanPlanBinaryLtreeToTextScanner struct{}
|
|
|
|
func (scanPlanBinaryLtreeToTextScanner) Scan(src []byte, target any) error {
|
|
version := src[0]
|
|
if version != 1 {
|
|
return fmt.Errorf("unsupported ltree version %d", version)
|
|
}
|
|
|
|
scanner := (target).(TextScanner)
|
|
return scanner.ScanText(Text{String: string(src[1:]), Valid: true})
|
|
}
|
|
|
|
// DecodeDatabaseSQLValue returns src decoded into a value compatible with the sql.Scanner interface.
|
|
func (l LtreeCodec) DecodeDatabaseSQLValue(m *Map, oid uint32, format int16, src []byte) (driver.Value, error) {
|
|
return (TextCodec)(l).DecodeDatabaseSQLValue(m, oid, format, src)
|
|
}
|
|
|
|
// DecodeValue returns src decoded into its default format.
|
|
func (l LtreeCodec) DecodeValue(m *Map, oid uint32, format int16, src []byte) (any, error) {
|
|
return (TextCodec)(l).DecodeValue(m, oid, format, src)
|
|
}
|