github.com/jackc/pgx/v5@v5.5.5/pgtype/ltree.go (about) 1 package pgtype 2 3 import ( 4 "database/sql/driver" 5 "fmt" 6 ) 7 8 type LtreeCodec struct{} 9 10 func (l LtreeCodec) FormatSupported(format int16) bool { 11 return format == TextFormatCode || format == BinaryFormatCode 12 } 13 14 // PreferredFormat returns the preferred format. 15 func (l LtreeCodec) PreferredFormat() int16 { 16 return TextFormatCode 17 } 18 19 // PlanEncode returns an EncodePlan for encoding value into PostgreSQL format for oid and format. If no plan can be 20 // found then nil is returned. 21 func (l LtreeCodec) PlanEncode(m *Map, oid uint32, format int16, value any) EncodePlan { 22 switch format { 23 case TextFormatCode: 24 return (TextCodec)(l).PlanEncode(m, oid, format, value) 25 case BinaryFormatCode: 26 switch value.(type) { 27 case string: 28 return encodeLtreeCodecBinaryString{} 29 case []byte: 30 return encodeLtreeCodecBinaryByteSlice{} 31 case TextValuer: 32 return encodeLtreeCodecBinaryTextValuer{} 33 } 34 } 35 36 return nil 37 } 38 39 type encodeLtreeCodecBinaryString struct{} 40 41 func (encodeLtreeCodecBinaryString) Encode(value any, buf []byte) (newBuf []byte, err error) { 42 ltree := value.(string) 43 buf = append(buf, 1) 44 return append(buf, ltree...), nil 45 } 46 47 type encodeLtreeCodecBinaryByteSlice struct{} 48 49 func (encodeLtreeCodecBinaryByteSlice) Encode(value any, buf []byte) (newBuf []byte, err error) { 50 ltree := value.([]byte) 51 buf = append(buf, 1) 52 return append(buf, ltree...), nil 53 } 54 55 type encodeLtreeCodecBinaryTextValuer struct{} 56 57 func (encodeLtreeCodecBinaryTextValuer) Encode(value any, buf []byte) (newBuf []byte, err error) { 58 t, err := value.(TextValuer).TextValue() 59 if err != nil { 60 return nil, err 61 } 62 if !t.Valid { 63 return nil, nil 64 } 65 66 buf = append(buf, 1) 67 return append(buf, t.String...), nil 68 } 69 70 // PlanScan returns a ScanPlan for scanning a PostgreSQL value into a destination with the same type as target. If 71 // no plan can be found then nil is returned. 72 func (l LtreeCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan { 73 switch format { 74 case TextFormatCode: 75 return (TextCodec)(l).PlanScan(m, oid, format, target) 76 case BinaryFormatCode: 77 switch target.(type) { 78 case *string: 79 return scanPlanBinaryLtreeToString{} 80 case TextScanner: 81 return scanPlanBinaryLtreeToTextScanner{} 82 } 83 } 84 85 return nil 86 } 87 88 type scanPlanBinaryLtreeToString struct{} 89 90 func (scanPlanBinaryLtreeToString) Scan(src []byte, target any) error { 91 version := src[0] 92 if version != 1 { 93 return fmt.Errorf("unsupported ltree version %d", version) 94 } 95 96 p := (target).(*string) 97 *p = string(src[1:]) 98 99 return nil 100 } 101 102 type scanPlanBinaryLtreeToTextScanner struct{} 103 104 func (scanPlanBinaryLtreeToTextScanner) Scan(src []byte, target any) error { 105 version := src[0] 106 if version != 1 { 107 return fmt.Errorf("unsupported ltree version %d", version) 108 } 109 110 scanner := (target).(TextScanner) 111 return scanner.ScanText(Text{String: string(src[1:]), Valid: true}) 112 } 113 114 // DecodeDatabaseSQLValue returns src decoded into a value compatible with the sql.Scanner interface. 115 func (l LtreeCodec) DecodeDatabaseSQLValue(m *Map, oid uint32, format int16, src []byte) (driver.Value, error) { 116 return (TextCodec)(l).DecodeDatabaseSQLValue(m, oid, format, src) 117 } 118 119 // DecodeValue returns src decoded into its default format. 120 func (l LtreeCodec) DecodeValue(m *Map, oid uint32, format int16, src []byte) (any, error) { 121 return (TextCodec)(l).DecodeValue(m, oid, format, src) 122 }