github.com/jackc/pgx/v5@v5.5.5/pgtype/text.go (about) 1 package pgtype 2 3 import ( 4 "database/sql/driver" 5 "encoding/json" 6 "fmt" 7 ) 8 9 type TextScanner interface { 10 ScanText(v Text) error 11 } 12 13 type TextValuer interface { 14 TextValue() (Text, error) 15 } 16 17 type Text struct { 18 String string 19 Valid bool 20 } 21 22 func (t *Text) ScanText(v Text) error { 23 *t = v 24 return nil 25 } 26 27 func (t Text) TextValue() (Text, error) { 28 return t, nil 29 } 30 31 // Scan implements the database/sql Scanner interface. 32 func (dst *Text) Scan(src any) error { 33 if src == nil { 34 *dst = Text{} 35 return nil 36 } 37 38 switch src := src.(type) { 39 case string: 40 *dst = Text{String: src, Valid: true} 41 return nil 42 case []byte: 43 *dst = Text{String: string(src), Valid: true} 44 return nil 45 } 46 47 return fmt.Errorf("cannot scan %T", src) 48 } 49 50 // Value implements the database/sql/driver Valuer interface. 51 func (src Text) Value() (driver.Value, error) { 52 if !src.Valid { 53 return nil, nil 54 } 55 return src.String, nil 56 } 57 58 func (src Text) MarshalJSON() ([]byte, error) { 59 if !src.Valid { 60 return []byte("null"), nil 61 } 62 63 return json.Marshal(src.String) 64 } 65 66 func (dst *Text) UnmarshalJSON(b []byte) error { 67 var s *string 68 err := json.Unmarshal(b, &s) 69 if err != nil { 70 return err 71 } 72 73 if s == nil { 74 *dst = Text{} 75 } else { 76 *dst = Text{String: *s, Valid: true} 77 } 78 79 return nil 80 } 81 82 type TextCodec struct{} 83 84 func (TextCodec) FormatSupported(format int16) bool { 85 return format == TextFormatCode || format == BinaryFormatCode 86 } 87 88 func (TextCodec) PreferredFormat() int16 { 89 return TextFormatCode 90 } 91 92 func (TextCodec) PlanEncode(m *Map, oid uint32, format int16, value any) EncodePlan { 93 switch format { 94 case TextFormatCode, BinaryFormatCode: 95 switch value.(type) { 96 case string: 97 return encodePlanTextCodecString{} 98 case []byte: 99 return encodePlanTextCodecByteSlice{} 100 case TextValuer: 101 return encodePlanTextCodecTextValuer{} 102 } 103 } 104 105 return nil 106 } 107 108 type encodePlanTextCodecString struct{} 109 110 func (encodePlanTextCodecString) Encode(value any, buf []byte) (newBuf []byte, err error) { 111 s := value.(string) 112 buf = append(buf, s...) 113 return buf, nil 114 } 115 116 type encodePlanTextCodecByteSlice struct{} 117 118 func (encodePlanTextCodecByteSlice) Encode(value any, buf []byte) (newBuf []byte, err error) { 119 s := value.([]byte) 120 buf = append(buf, s...) 121 return buf, nil 122 } 123 124 type encodePlanTextCodecStringer struct{} 125 126 func (encodePlanTextCodecStringer) Encode(value any, buf []byte) (newBuf []byte, err error) { 127 s := value.(fmt.Stringer) 128 buf = append(buf, s.String()...) 129 return buf, nil 130 } 131 132 type encodePlanTextCodecTextValuer struct{} 133 134 func (encodePlanTextCodecTextValuer) Encode(value any, buf []byte) (newBuf []byte, err error) { 135 text, err := value.(TextValuer).TextValue() 136 if err != nil { 137 return nil, err 138 } 139 140 if !text.Valid { 141 return nil, nil 142 } 143 144 buf = append(buf, text.String...) 145 return buf, nil 146 } 147 148 func (TextCodec) PlanScan(m *Map, oid uint32, format int16, target any) ScanPlan { 149 150 switch format { 151 case TextFormatCode, BinaryFormatCode: 152 switch target.(type) { 153 case *string: 154 return scanPlanTextAnyToString{} 155 case *[]byte: 156 return scanPlanAnyToNewByteSlice{} 157 case BytesScanner: 158 return scanPlanAnyToByteScanner{} 159 case TextScanner: 160 return scanPlanTextAnyToTextScanner{} 161 } 162 } 163 164 return nil 165 } 166 167 func (c TextCodec) DecodeDatabaseSQLValue(m *Map, oid uint32, format int16, src []byte) (driver.Value, error) { 168 return c.DecodeValue(m, oid, format, src) 169 } 170 171 func (c TextCodec) DecodeValue(m *Map, oid uint32, format int16, src []byte) (any, error) { 172 if src == nil { 173 return nil, nil 174 } 175 176 return string(src), nil 177 } 178 179 type scanPlanTextAnyToString struct{} 180 181 func (scanPlanTextAnyToString) Scan(src []byte, dst any) error { 182 if src == nil { 183 return fmt.Errorf("cannot scan NULL into %T", dst) 184 } 185 186 p := (dst).(*string) 187 *p = string(src) 188 189 return nil 190 } 191 192 type scanPlanAnyToNewByteSlice struct{} 193 194 func (scanPlanAnyToNewByteSlice) Scan(src []byte, dst any) error { 195 p := (dst).(*[]byte) 196 if src == nil { 197 *p = nil 198 } else { 199 *p = make([]byte, len(src)) 200 copy(*p, src) 201 } 202 203 return nil 204 } 205 206 type scanPlanAnyToByteScanner struct{} 207 208 func (scanPlanAnyToByteScanner) Scan(src []byte, dst any) error { 209 p := (dst).(BytesScanner) 210 return p.ScanBytes(src) 211 } 212 213 type scanPlanTextAnyToTextScanner struct{} 214 215 func (scanPlanTextAnyToTextScanner) Scan(src []byte, dst any) error { 216 scanner := (dst).(TextScanner) 217 218 if src == nil { 219 return scanner.ScanText(Text{}) 220 } 221 222 return scanner.ScanText(Text{String: string(src), Valid: true}) 223 }