1package pgtype 2 3import ( 4 "database/sql" 5 "encoding/binary" 6 "errors" 7 "fmt" 8 "math" 9 "net" 10 "reflect" 11 "time" 12) 13 14// PostgreSQL oids for common types 15const ( 16 BoolOID = 16 17 ByteaOID = 17 18 QCharOID = 18 19 NameOID = 19 20 Int8OID = 20 21 Int2OID = 21 22 Int4OID = 23 23 TextOID = 25 24 OIDOID = 26 25 TIDOID = 27 26 XIDOID = 28 27 CIDOID = 29 28 JSONOID = 114 29 PointOID = 600 30 LsegOID = 601 31 PathOID = 602 32 BoxOID = 603 33 PolygonOID = 604 34 LineOID = 628 35 CIDROID = 650 36 CIDRArrayOID = 651 37 Float4OID = 700 38 Float8OID = 701 39 CircleOID = 718 40 UnknownOID = 705 41 MacaddrOID = 829 42 InetOID = 869 43 BoolArrayOID = 1000 44 Int2ArrayOID = 1005 45 Int4ArrayOID = 1007 46 TextArrayOID = 1009 47 ByteaArrayOID = 1001 48 BPCharArrayOID = 1014 49 VarcharArrayOID = 1015 50 Int8ArrayOID = 1016 51 Float4ArrayOID = 1021 52 Float8ArrayOID = 1022 53 ACLItemOID = 1033 54 ACLItemArrayOID = 1034 55 InetArrayOID = 1041 56 BPCharOID = 1042 57 VarcharOID = 1043 58 DateOID = 1082 59 TimeOID = 1083 60 TimestampOID = 1114 61 TimestampArrayOID = 1115 62 DateArrayOID = 1182 63 TimestamptzOID = 1184 64 TimestamptzArrayOID = 1185 65 IntervalOID = 1186 66 NumericArrayOID = 1231 67 BitOID = 1560 68 VarbitOID = 1562 69 NumericOID = 1700 70 RecordOID = 2249 71 UUIDOID = 2950 72 UUIDArrayOID = 2951 73 JSONBOID = 3802 74 JSONBArrayOID = 3807 75 DaterangeOID = 3912 76 Int4rangeOID = 3904 77 NumrangeOID = 3906 78 TsrangeOID = 3908 79 TsrangeArrayOID = 3909 80 TstzrangeOID = 3910 81 TstzrangeArrayOID = 3911 82 Int8rangeOID = 3926 83) 84 85type Status byte 86 87const ( 88 Undefined Status = iota 89 Null 90 Present 91) 92 93type InfinityModifier int8 94 95const ( 96 Infinity InfinityModifier = 1 97 None InfinityModifier = 0 98 NegativeInfinity InfinityModifier = -Infinity 99) 100 101func (im InfinityModifier) String() string { 102 switch im { 103 case None: 104 return "none" 105 case Infinity: 106 return "infinity" 107 case NegativeInfinity: 108 return "-infinity" 109 default: 110 return "invalid" 111 } 112} 113 114// PostgreSQL format codes 115const ( 116 TextFormatCode = 0 117 BinaryFormatCode = 1 118) 119 120// Value translates values to and from an internal canonical representation for the type. To actually be usable a type 121// that implements Value should also implement some combination of BinaryDecoder, BinaryEncoder, TextDecoder, 122// and TextEncoder. 123// 124// Operations that update a Value (e.g. Set, DecodeText, DecodeBinary) should entirely replace the value. e.g. Internal 125// slices should be replaced not resized and reused. This allows Get and AssignTo to return a slice directly rather 126// than incur a usually unnecessary copy. 127type Value interface { 128 // Set converts and assigns src to itself. Value takes ownership of src. 129 Set(src interface{}) error 130 131 // Get returns the simplest representation of Value. Get may return a pointer to an internal value but it must never 132 // mutate that value. e.g. If Get returns a []byte Value must never change the contents of the []byte. 133 Get() interface{} 134 135 // AssignTo converts and assigns the Value to dst. AssignTo may a pointer to an internal value but it must never 136 // mutate that value. e.g. If Get returns a []byte Value must never change the contents of the []byte. 137 AssignTo(dst interface{}) error 138} 139 140// TypeValue is a Value where instances can represent different PostgreSQL types. This can be useful for 141// representing types such as enums, composites, and arrays. 142// 143// In general, instances of TypeValue should not be used to directly represent a value. It should only be used as an 144// encoder and decoder internal to ConnInfo. 145type TypeValue interface { 146 Value 147 148 // NewTypeValue creates a TypeValue including references to internal type information. e.g. the list of members 149 // in an EnumType. 150 NewTypeValue() Value 151 152 // TypeName returns the PostgreSQL name of this type. 153 TypeName() string 154} 155 156// ValueTranscoder is a value that implements the text and binary encoding and decoding interfaces. 157type ValueTranscoder interface { 158 Value 159 TextEncoder 160 BinaryEncoder 161 TextDecoder 162 BinaryDecoder 163} 164 165// ResultFormatPreferrer allows a type to specify its preferred result format instead of it being inferred from 166// whether it is also a BinaryDecoder. 167type ResultFormatPreferrer interface { 168 PreferredResultFormat() int16 169} 170 171// ParamFormatPreferrer allows a type to specify its preferred param format instead of it being inferred from 172// whether it is also a BinaryEncoder. 173type ParamFormatPreferrer interface { 174 PreferredParamFormat() int16 175} 176 177type BinaryDecoder interface { 178 // DecodeBinary decodes src into BinaryDecoder. If src is nil then the 179 // original SQL value is NULL. BinaryDecoder takes ownership of src. The 180 // caller MUST not use it again. 181 DecodeBinary(ci *ConnInfo, src []byte) error 182} 183 184type TextDecoder interface { 185 // DecodeText decodes src into TextDecoder. If src is nil then the original 186 // SQL value is NULL. TextDecoder takes ownership of src. The caller MUST not 187 // use it again. 188 DecodeText(ci *ConnInfo, src []byte) error 189} 190 191// BinaryEncoder is implemented by types that can encode themselves into the 192// PostgreSQL binary wire format. 193type BinaryEncoder interface { 194 // EncodeBinary should append the binary format of self to buf. If self is the 195 // SQL value NULL then append nothing and return (nil, nil). The caller of 196 // EncodeBinary is responsible for writing the correct NULL value or the 197 // length of the data written. 198 EncodeBinary(ci *ConnInfo, buf []byte) (newBuf []byte, err error) 199} 200 201// TextEncoder is implemented by types that can encode themselves into the 202// PostgreSQL text wire format. 203type TextEncoder interface { 204 // EncodeText should append the text format of self to buf. If self is the 205 // SQL value NULL then append nothing and return (nil, nil). The caller of 206 // EncodeText is responsible for writing the correct NULL value or the 207 // length of the data written. 208 EncodeText(ci *ConnInfo, buf []byte) (newBuf []byte, err error) 209} 210 211var errUndefined = errors.New("cannot encode status undefined") 212var errBadStatus = errors.New("invalid status") 213 214type nullAssignmentError struct { 215 dst interface{} 216} 217 218func (e *nullAssignmentError) Error() string { 219 return fmt.Sprintf("cannot assign NULL to %T", e.dst) 220} 221 222type DataType struct { 223 Value Value 224 225 textDecoder TextDecoder 226 binaryDecoder BinaryDecoder 227 228 Name string 229 OID uint32 230} 231 232type ConnInfo struct { 233 oidToDataType map[uint32]*DataType 234 nameToDataType map[string]*DataType 235 reflectTypeToName map[reflect.Type]string 236 oidToParamFormatCode map[uint32]int16 237 oidToResultFormatCode map[uint32]int16 238 239 reflectTypeToDataType map[reflect.Type]*DataType 240} 241 242func newConnInfo() *ConnInfo { 243 return &ConnInfo{ 244 oidToDataType: make(map[uint32]*DataType), 245 nameToDataType: make(map[string]*DataType), 246 reflectTypeToName: make(map[reflect.Type]string), 247 oidToParamFormatCode: make(map[uint32]int16), 248 oidToResultFormatCode: make(map[uint32]int16), 249 } 250} 251 252func NewConnInfo() *ConnInfo { 253 ci := newConnInfo() 254 255 ci.RegisterDataType(DataType{Value: &ACLItemArray{}, Name: "_aclitem", OID: ACLItemArrayOID}) 256 ci.RegisterDataType(DataType{Value: &BoolArray{}, Name: "_bool", OID: BoolArrayOID}) 257 ci.RegisterDataType(DataType{Value: &BPCharArray{}, Name: "_bpchar", OID: BPCharArrayOID}) 258 ci.RegisterDataType(DataType{Value: &ByteaArray{}, Name: "_bytea", OID: ByteaArrayOID}) 259 ci.RegisterDataType(DataType{Value: &CIDRArray{}, Name: "_cidr", OID: CIDRArrayOID}) 260 ci.RegisterDataType(DataType{Value: &DateArray{}, Name: "_date", OID: DateArrayOID}) 261 ci.RegisterDataType(DataType{Value: &Float4Array{}, Name: "_float4", OID: Float4ArrayOID}) 262 ci.RegisterDataType(DataType{Value: &Float8Array{}, Name: "_float8", OID: Float8ArrayOID}) 263 ci.RegisterDataType(DataType{Value: &InetArray{}, Name: "_inet", OID: InetArrayOID}) 264 ci.RegisterDataType(DataType{Value: &Int2Array{}, Name: "_int2", OID: Int2ArrayOID}) 265 ci.RegisterDataType(DataType{Value: &Int4Array{}, Name: "_int4", OID: Int4ArrayOID}) 266 ci.RegisterDataType(DataType{Value: &Int8Array{}, Name: "_int8", OID: Int8ArrayOID}) 267 ci.RegisterDataType(DataType{Value: &NumericArray{}, Name: "_numeric", OID: NumericArrayOID}) 268 ci.RegisterDataType(DataType{Value: &TextArray{}, Name: "_text", OID: TextArrayOID}) 269 ci.RegisterDataType(DataType{Value: &TimestampArray{}, Name: "_timestamp", OID: TimestampArrayOID}) 270 ci.RegisterDataType(DataType{Value: &TimestamptzArray{}, Name: "_timestamptz", OID: TimestamptzArrayOID}) 271 ci.RegisterDataType(DataType{Value: &UUIDArray{}, Name: "_uuid", OID: UUIDArrayOID}) 272 ci.RegisterDataType(DataType{Value: &VarcharArray{}, Name: "_varchar", OID: VarcharArrayOID}) 273 ci.RegisterDataType(DataType{Value: &ACLItem{}, Name: "aclitem", OID: ACLItemOID}) 274 ci.RegisterDataType(DataType{Value: &Bit{}, Name: "bit", OID: BitOID}) 275 ci.RegisterDataType(DataType{Value: &Bool{}, Name: "bool", OID: BoolOID}) 276 ci.RegisterDataType(DataType{Value: &Box{}, Name: "box", OID: BoxOID}) 277 ci.RegisterDataType(DataType{Value: &BPChar{}, Name: "bpchar", OID: BPCharOID}) 278 ci.RegisterDataType(DataType{Value: &Bytea{}, Name: "bytea", OID: ByteaOID}) 279 ci.RegisterDataType(DataType{Value: &QChar{}, Name: "char", OID: QCharOID}) 280 ci.RegisterDataType(DataType{Value: &CID{}, Name: "cid", OID: CIDOID}) 281 ci.RegisterDataType(DataType{Value: &CIDR{}, Name: "cidr", OID: CIDROID}) 282 ci.RegisterDataType(DataType{Value: &Circle{}, Name: "circle", OID: CircleOID}) 283 ci.RegisterDataType(DataType{Value: &Date{}, Name: "date", OID: DateOID}) 284 ci.RegisterDataType(DataType{Value: &Daterange{}, Name: "daterange", OID: DaterangeOID}) 285 ci.RegisterDataType(DataType{Value: &Float4{}, Name: "float4", OID: Float4OID}) 286 ci.RegisterDataType(DataType{Value: &Float8{}, Name: "float8", OID: Float8OID}) 287 ci.RegisterDataType(DataType{Value: &Inet{}, Name: "inet", OID: InetOID}) 288 ci.RegisterDataType(DataType{Value: &Int2{}, Name: "int2", OID: Int2OID}) 289 ci.RegisterDataType(DataType{Value: &Int4{}, Name: "int4", OID: Int4OID}) 290 ci.RegisterDataType(DataType{Value: &Int4range{}, Name: "int4range", OID: Int4rangeOID}) 291 ci.RegisterDataType(DataType{Value: &Int8{}, Name: "int8", OID: Int8OID}) 292 ci.RegisterDataType(DataType{Value: &Int8range{}, Name: "int8range", OID: Int8rangeOID}) 293 ci.RegisterDataType(DataType{Value: &Interval{}, Name: "interval", OID: IntervalOID}) 294 ci.RegisterDataType(DataType{Value: &JSON{}, Name: "json", OID: JSONOID}) 295 ci.RegisterDataType(DataType{Value: &JSONB{}, Name: "jsonb", OID: JSONBOID}) 296 ci.RegisterDataType(DataType{Value: &JSONBArray{}, Name: "_jsonb", OID: JSONBArrayOID}) 297 ci.RegisterDataType(DataType{Value: &Line{}, Name: "line", OID: LineOID}) 298 ci.RegisterDataType(DataType{Value: &Lseg{}, Name: "lseg", OID: LsegOID}) 299 ci.RegisterDataType(DataType{Value: &Macaddr{}, Name: "macaddr", OID: MacaddrOID}) 300 ci.RegisterDataType(DataType{Value: &Name{}, Name: "name", OID: NameOID}) 301 ci.RegisterDataType(DataType{Value: &Numeric{}, Name: "numeric", OID: NumericOID}) 302 ci.RegisterDataType(DataType{Value: &Numrange{}, Name: "numrange", OID: NumrangeOID}) 303 ci.RegisterDataType(DataType{Value: &OIDValue{}, Name: "oid", OID: OIDOID}) 304 ci.RegisterDataType(DataType{Value: &Path{}, Name: "path", OID: PathOID}) 305 ci.RegisterDataType(DataType{Value: &Point{}, Name: "point", OID: PointOID}) 306 ci.RegisterDataType(DataType{Value: &Polygon{}, Name: "polygon", OID: PolygonOID}) 307 ci.RegisterDataType(DataType{Value: &Record{}, Name: "record", OID: RecordOID}) 308 ci.RegisterDataType(DataType{Value: &Text{}, Name: "text", OID: TextOID}) 309 ci.RegisterDataType(DataType{Value: &TID{}, Name: "tid", OID: TIDOID}) 310 ci.RegisterDataType(DataType{Value: &Time{}, Name: "time", OID: TimeOID}) 311 ci.RegisterDataType(DataType{Value: &Timestamp{}, Name: "timestamp", OID: TimestampOID}) 312 ci.RegisterDataType(DataType{Value: &Timestamptz{}, Name: "timestamptz", OID: TimestamptzOID}) 313 ci.RegisterDataType(DataType{Value: &Tsrange{}, Name: "tsrange", OID: TsrangeOID}) 314 ci.RegisterDataType(DataType{Value: &TsrangeArray{}, Name: "_tsrange", OID: TsrangeArrayOID}) 315 ci.RegisterDataType(DataType{Value: &Tstzrange{}, Name: "tstzrange", OID: TstzrangeOID}) 316 ci.RegisterDataType(DataType{Value: &TstzrangeArray{}, Name: "_tstzrange", OID: TstzrangeArrayOID}) 317 ci.RegisterDataType(DataType{Value: &Unknown{}, Name: "unknown", OID: UnknownOID}) 318 ci.RegisterDataType(DataType{Value: &UUID{}, Name: "uuid", OID: UUIDOID}) 319 ci.RegisterDataType(DataType{Value: &Varbit{}, Name: "varbit", OID: VarbitOID}) 320 ci.RegisterDataType(DataType{Value: &Varchar{}, Name: "varchar", OID: VarcharOID}) 321 ci.RegisterDataType(DataType{Value: &XID{}, Name: "xid", OID: XIDOID}) 322 323 registerDefaultPgTypeVariants := func(name, arrayName string, value interface{}) { 324 ci.RegisterDefaultPgType(value, name) 325 valueType := reflect.TypeOf(value) 326 327 ci.RegisterDefaultPgType(reflect.New(valueType).Interface(), name) 328 329 sliceType := reflect.SliceOf(valueType) 330 ci.RegisterDefaultPgType(reflect.MakeSlice(sliceType, 0, 0).Interface(), arrayName) 331 332 ci.RegisterDefaultPgType(reflect.New(sliceType).Interface(), arrayName) 333 } 334 335 // Integer types that directly map to a PostgreSQL type 336 registerDefaultPgTypeVariants("int2", "_int2", int16(0)) 337 registerDefaultPgTypeVariants("int4", "_int4", int32(0)) 338 registerDefaultPgTypeVariants("int8", "_int8", int64(0)) 339 340 // Integer types that do not have a direct match to a PostgreSQL type 341 registerDefaultPgTypeVariants("int8", "_int8", uint16(0)) 342 registerDefaultPgTypeVariants("int8", "_int8", uint32(0)) 343 registerDefaultPgTypeVariants("int8", "_int8", uint64(0)) 344 registerDefaultPgTypeVariants("int8", "_int8", int(0)) 345 registerDefaultPgTypeVariants("int8", "_int8", uint(0)) 346 347 registerDefaultPgTypeVariants("float4", "_float4", float32(0)) 348 registerDefaultPgTypeVariants("float8", "_float8", float64(0)) 349 350 registerDefaultPgTypeVariants("bool", "_bool", false) 351 registerDefaultPgTypeVariants("timestamptz", "_timestamptz", time.Time{}) 352 registerDefaultPgTypeVariants("text", "_text", "") 353 registerDefaultPgTypeVariants("bytea", "_bytea", []byte(nil)) 354 355 registerDefaultPgTypeVariants("inet", "_inet", net.IP{}) 356 ci.RegisterDefaultPgType((*net.IPNet)(nil), "cidr") 357 ci.RegisterDefaultPgType([]*net.IPNet(nil), "_cidr") 358 359 return ci 360} 361 362func (ci *ConnInfo) InitializeDataTypes(nameOIDs map[string]uint32) { 363 for name, oid := range nameOIDs { 364 var value Value 365 if t, ok := nameValues[name]; ok { 366 value = reflect.New(reflect.ValueOf(t).Elem().Type()).Interface().(Value) 367 } else { 368 value = &GenericText{} 369 } 370 ci.RegisterDataType(DataType{Value: value, Name: name, OID: oid}) 371 } 372} 373 374func (ci *ConnInfo) RegisterDataType(t DataType) { 375 t.Value = NewValue(t.Value) 376 377 ci.oidToDataType[t.OID] = &t 378 ci.nameToDataType[t.Name] = &t 379 380 { 381 var formatCode int16 382 if pfp, ok := t.Value.(ParamFormatPreferrer); ok { 383 formatCode = pfp.PreferredParamFormat() 384 } else if _, ok := t.Value.(BinaryEncoder); ok { 385 formatCode = BinaryFormatCode 386 } 387 ci.oidToParamFormatCode[t.OID] = formatCode 388 } 389 390 { 391 var formatCode int16 392 if rfp, ok := t.Value.(ResultFormatPreferrer); ok { 393 formatCode = rfp.PreferredResultFormat() 394 } else if _, ok := t.Value.(BinaryDecoder); ok { 395 formatCode = BinaryFormatCode 396 } 397 ci.oidToResultFormatCode[t.OID] = formatCode 398 } 399 400 if d, ok := t.Value.(TextDecoder); ok { 401 t.textDecoder = d 402 } 403 404 if d, ok := t.Value.(BinaryDecoder); ok { 405 t.binaryDecoder = d 406 } 407 408 ci.reflectTypeToDataType = nil // Invalidated by type registration 409} 410 411// RegisterDefaultPgType registers a mapping of a Go type to a PostgreSQL type name. Typically the data type to be 412// encoded or decoded is determined by the PostgreSQL OID. But if the OID of a value to be encoded or decoded is 413// unknown, this additional mapping will be used by DataTypeForValue to determine a suitable data type. 414func (ci *ConnInfo) RegisterDefaultPgType(value interface{}, name string) { 415 ci.reflectTypeToName[reflect.TypeOf(value)] = name 416 ci.reflectTypeToDataType = nil // Invalidated by registering a default type 417} 418 419func (ci *ConnInfo) DataTypeForOID(oid uint32) (*DataType, bool) { 420 dt, ok := ci.oidToDataType[oid] 421 return dt, ok 422} 423 424func (ci *ConnInfo) DataTypeForName(name string) (*DataType, bool) { 425 dt, ok := ci.nameToDataType[name] 426 return dt, ok 427} 428 429func (ci *ConnInfo) buildReflectTypeToDataType() { 430 ci.reflectTypeToDataType = make(map[reflect.Type]*DataType) 431 432 for _, dt := range ci.oidToDataType { 433 if _, is := dt.Value.(TypeValue); !is { 434 ci.reflectTypeToDataType[reflect.ValueOf(dt.Value).Type()] = dt 435 } 436 } 437 438 for reflectType, name := range ci.reflectTypeToName { 439 if dt, ok := ci.nameToDataType[name]; ok { 440 ci.reflectTypeToDataType[reflectType] = dt 441 } 442 } 443} 444 445// DataTypeForValue finds a data type suitable for v. Use RegisterDataType to register types that can encode and decode 446// themselves. Use RegisterDefaultPgType to register that can be handled by a registered data type. 447func (ci *ConnInfo) DataTypeForValue(v interface{}) (*DataType, bool) { 448 if ci.reflectTypeToDataType == nil { 449 ci.buildReflectTypeToDataType() 450 } 451 452 if tv, ok := v.(TypeValue); ok { 453 dt, ok := ci.nameToDataType[tv.TypeName()] 454 return dt, ok 455 } 456 457 dt, ok := ci.reflectTypeToDataType[reflect.TypeOf(v)] 458 return dt, ok 459} 460 461func (ci *ConnInfo) ParamFormatCodeForOID(oid uint32) int16 { 462 fc, ok := ci.oidToParamFormatCode[oid] 463 if ok { 464 return fc 465 } 466 return TextFormatCode 467} 468 469func (ci *ConnInfo) ResultFormatCodeForOID(oid uint32) int16 { 470 fc, ok := ci.oidToResultFormatCode[oid] 471 if ok { 472 return fc 473 } 474 return TextFormatCode 475} 476 477// DeepCopy makes a deep copy of the ConnInfo. 478func (ci *ConnInfo) DeepCopy() *ConnInfo { 479 ci2 := newConnInfo() 480 481 for _, dt := range ci.oidToDataType { 482 ci2.RegisterDataType(DataType{ 483 Value: NewValue(dt.Value), 484 Name: dt.Name, 485 OID: dt.OID, 486 }) 487 } 488 489 for t, n := range ci.reflectTypeToName { 490 ci2.reflectTypeToName[t] = n 491 } 492 493 return ci2 494} 495 496// ScanPlan is a precompiled plan to scan into a type of destination. 497type ScanPlan interface { 498 // Scan scans src into dst. If the dst type has changed in an incompatible way a ScanPlan should automatically 499 // replan and scan. 500 Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error 501} 502 503type scanPlanDstBinaryDecoder struct{} 504 505func (scanPlanDstBinaryDecoder) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error { 506 if d, ok := (dst).(BinaryDecoder); ok { 507 return d.DecodeBinary(ci, src) 508 } 509 510 newPlan := ci.PlanScan(oid, formatCode, dst) 511 return newPlan.Scan(ci, oid, formatCode, src, dst) 512} 513 514type scanPlanDstTextDecoder struct{} 515 516func (plan scanPlanDstTextDecoder) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error { 517 if d, ok := (dst).(TextDecoder); ok { 518 return d.DecodeText(ci, src) 519 } 520 521 newPlan := ci.PlanScan(oid, formatCode, dst) 522 return newPlan.Scan(ci, oid, formatCode, src, dst) 523} 524 525type scanPlanDataTypeSQLScanner DataType 526 527func (plan *scanPlanDataTypeSQLScanner) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error { 528 scanner, ok := dst.(sql.Scanner) 529 if !ok { 530 newPlan := ci.PlanScan(oid, formatCode, dst) 531 return newPlan.Scan(ci, oid, formatCode, src, dst) 532 } 533 534 dt := (*DataType)(plan) 535 var err error 536 switch formatCode { 537 case BinaryFormatCode: 538 err = dt.binaryDecoder.DecodeBinary(ci, src) 539 case TextFormatCode: 540 err = dt.textDecoder.DecodeText(ci, src) 541 } 542 if err != nil { 543 return err 544 } 545 546 sqlSrc, err := DatabaseSQLValue(ci, dt.Value) 547 if err != nil { 548 return err 549 } 550 return scanner.Scan(sqlSrc) 551} 552 553type scanPlanDataTypeAssignTo DataType 554 555func (plan *scanPlanDataTypeAssignTo) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error { 556 dt := (*DataType)(plan) 557 var err error 558 switch formatCode { 559 case BinaryFormatCode: 560 err = dt.binaryDecoder.DecodeBinary(ci, src) 561 case TextFormatCode: 562 err = dt.textDecoder.DecodeText(ci, src) 563 } 564 if err != nil { 565 return err 566 } 567 568 assignToErr := dt.Value.AssignTo(dst) 569 if assignToErr == nil { 570 return nil 571 } 572 573 if dstPtr, ok := dst.(*interface{}); ok { 574 *dstPtr = dt.Value.Get() 575 return nil 576 } 577 578 // assignToErr might have failed because the type of destination has changed 579 newPlan := ci.PlanScan(oid, formatCode, dst) 580 if newPlan, sameType := newPlan.(*scanPlanDataTypeAssignTo); !sameType { 581 return newPlan.Scan(ci, oid, formatCode, src, dst) 582 } 583 584 return assignToErr 585} 586 587type scanPlanSQLScanner struct{} 588 589func (scanPlanSQLScanner) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error { 590 scanner := dst.(sql.Scanner) 591 if formatCode == BinaryFormatCode { 592 return scanner.Scan(src) 593 } else { 594 return scanner.Scan(string(src)) 595 } 596} 597 598type scanPlanReflection struct{} 599 600func (scanPlanReflection) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error { 601 // We might be given a pointer to something that implements the decoder interface(s), 602 // even though the pointer itself doesn't. 603 refVal := reflect.ValueOf(dst) 604 if refVal.Kind() == reflect.Ptr && refVal.Type().Elem().Kind() == reflect.Ptr { 605 // If the database returned NULL, then we set dest as nil to indicate that. 606 if src == nil { 607 nilPtr := reflect.Zero(refVal.Type().Elem()) 608 refVal.Elem().Set(nilPtr) 609 return nil 610 } 611 612 // We need to allocate an element, and set the destination to it 613 // Then we can retry as that element. 614 elemPtr := reflect.New(refVal.Type().Elem().Elem()) 615 refVal.Elem().Set(elemPtr) 616 617 plan := ci.PlanScan(oid, formatCode, elemPtr.Interface()) 618 return plan.Scan(ci, oid, formatCode, src, elemPtr.Interface()) 619 } 620 621 return scanUnknownType(oid, formatCode, src, dst) 622} 623 624type scanPlanBinaryInt16 struct{} 625 626func (scanPlanBinaryInt16) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error { 627 if src == nil { 628 return fmt.Errorf("cannot scan null into %T", dst) 629 } 630 631 if len(src) != 2 { 632 return fmt.Errorf("invalid length for int2: %v", len(src)) 633 } 634 635 if p, ok := (dst).(*int16); ok { 636 *p = int16(binary.BigEndian.Uint16(src)) 637 return nil 638 } 639 640 newPlan := ci.PlanScan(oid, formatCode, dst) 641 return newPlan.Scan(ci, oid, formatCode, src, dst) 642} 643 644type scanPlanBinaryInt32 struct{} 645 646func (scanPlanBinaryInt32) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error { 647 if src == nil { 648 return fmt.Errorf("cannot scan null into %T", dst) 649 } 650 651 if len(src) != 4 { 652 return fmt.Errorf("invalid length for int4: %v", len(src)) 653 } 654 655 if p, ok := (dst).(*int32); ok { 656 *p = int32(binary.BigEndian.Uint32(src)) 657 return nil 658 } 659 660 newPlan := ci.PlanScan(oid, formatCode, dst) 661 return newPlan.Scan(ci, oid, formatCode, src, dst) 662} 663 664type scanPlanBinaryInt64 struct{} 665 666func (scanPlanBinaryInt64) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error { 667 if src == nil { 668 return fmt.Errorf("cannot scan null into %T", dst) 669 } 670 671 if len(src) != 8 { 672 return fmt.Errorf("invalid length for int8: %v", len(src)) 673 } 674 675 if p, ok := (dst).(*int64); ok { 676 *p = int64(binary.BigEndian.Uint64(src)) 677 return nil 678 } 679 680 newPlan := ci.PlanScan(oid, formatCode, dst) 681 return newPlan.Scan(ci, oid, formatCode, src, dst) 682} 683 684type scanPlanBinaryFloat32 struct{} 685 686func (scanPlanBinaryFloat32) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error { 687 if src == nil { 688 return fmt.Errorf("cannot scan null into %T", dst) 689 } 690 691 if len(src) != 4 { 692 return fmt.Errorf("invalid length for int4: %v", len(src)) 693 } 694 695 if p, ok := (dst).(*float32); ok { 696 n := int32(binary.BigEndian.Uint32(src)) 697 *p = float32(math.Float32frombits(uint32(n))) 698 return nil 699 } 700 701 newPlan := ci.PlanScan(oid, formatCode, dst) 702 return newPlan.Scan(ci, oid, formatCode, src, dst) 703} 704 705type scanPlanBinaryFloat64 struct{} 706 707func (scanPlanBinaryFloat64) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error { 708 if src == nil { 709 return fmt.Errorf("cannot scan null into %T", dst) 710 } 711 712 if len(src) != 8 { 713 return fmt.Errorf("invalid length for int8: %v", len(src)) 714 } 715 716 if p, ok := (dst).(*float64); ok { 717 n := int64(binary.BigEndian.Uint64(src)) 718 *p = float64(math.Float64frombits(uint64(n))) 719 return nil 720 } 721 722 newPlan := ci.PlanScan(oid, formatCode, dst) 723 return newPlan.Scan(ci, oid, formatCode, src, dst) 724} 725 726type scanPlanBinaryBytes struct{} 727 728func (scanPlanBinaryBytes) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error { 729 if p, ok := (dst).(*[]byte); ok { 730 *p = src 731 return nil 732 } 733 734 newPlan := ci.PlanScan(oid, formatCode, dst) 735 return newPlan.Scan(ci, oid, formatCode, src, dst) 736} 737 738type scanPlanString struct{} 739 740func (scanPlanString) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error { 741 if src == nil { 742 return fmt.Errorf("cannot scan null into %T", dst) 743 } 744 745 if p, ok := (dst).(*string); ok { 746 *p = string(src) 747 return nil 748 } 749 750 newPlan := ci.PlanScan(oid, formatCode, dst) 751 return newPlan.Scan(ci, oid, formatCode, src, dst) 752} 753 754// PlanScan prepares a plan to scan a value into dst. 755func (ci *ConnInfo) PlanScan(oid uint32, formatCode int16, dst interface{}) ScanPlan { 756 switch formatCode { 757 case BinaryFormatCode: 758 switch dst.(type) { 759 case *string: 760 switch oid { 761 case TextOID, VarcharOID: 762 return scanPlanString{} 763 } 764 case *int16: 765 if oid == Int2OID { 766 return scanPlanBinaryInt16{} 767 } 768 case *int32: 769 if oid == Int4OID { 770 return scanPlanBinaryInt32{} 771 } 772 case *int64: 773 if oid == Int8OID { 774 return scanPlanBinaryInt64{} 775 } 776 case *float32: 777 if oid == Float4OID { 778 return scanPlanBinaryFloat32{} 779 } 780 case *float64: 781 if oid == Float8OID { 782 return scanPlanBinaryFloat64{} 783 } 784 case *[]byte: 785 switch oid { 786 case ByteaOID, TextOID, VarcharOID, JSONOID: 787 return scanPlanBinaryBytes{} 788 } 789 case BinaryDecoder: 790 return scanPlanDstBinaryDecoder{} 791 } 792 case TextFormatCode: 793 switch dst.(type) { 794 case *string: 795 return scanPlanString{} 796 case *[]byte: 797 if oid != ByteaOID { 798 return scanPlanBinaryBytes{} 799 } 800 case TextDecoder: 801 return scanPlanDstTextDecoder{} 802 } 803 } 804 805 var dt *DataType 806 807 if oid == 0 { 808 if dataType, ok := ci.DataTypeForValue(dst); ok { 809 dt = dataType 810 } 811 } else { 812 if dataType, ok := ci.DataTypeForOID(oid); ok { 813 dt = dataType 814 } 815 } 816 817 if dt != nil { 818 if _, ok := dst.(sql.Scanner); ok { 819 return (*scanPlanDataTypeSQLScanner)(dt) 820 } 821 return (*scanPlanDataTypeAssignTo)(dt) 822 } 823 824 if _, ok := dst.(sql.Scanner); ok { 825 return scanPlanSQLScanner{} 826 } 827 828 return scanPlanReflection{} 829} 830 831func (ci *ConnInfo) Scan(oid uint32, formatCode int16, src []byte, dst interface{}) error { 832 if dst == nil { 833 return nil 834 } 835 836 plan := ci.PlanScan(oid, formatCode, dst) 837 return plan.Scan(ci, oid, formatCode, src, dst) 838} 839 840func scanUnknownType(oid uint32, formatCode int16, buf []byte, dest interface{}) error { 841 switch dest := dest.(type) { 842 case *string: 843 if formatCode == BinaryFormatCode { 844 return fmt.Errorf("unknown oid %d in binary format cannot be scanned into %T", oid, dest) 845 } 846 *dest = string(buf) 847 return nil 848 case *[]byte: 849 *dest = buf 850 return nil 851 default: 852 if nextDst, retry := GetAssignToDstType(dest); retry { 853 return scanUnknownType(oid, formatCode, buf, nextDst) 854 } 855 return fmt.Errorf("unknown oid %d cannot be scanned into %T", oid, dest) 856 } 857} 858 859// NewValue returns a new instance of the same type as v. 860func NewValue(v Value) Value { 861 if tv, ok := v.(TypeValue); ok { 862 return tv.NewTypeValue() 863 } else { 864 return reflect.New(reflect.ValueOf(v).Elem().Type()).Interface().(Value) 865 } 866} 867 868var nameValues map[string]Value 869 870func init() { 871 nameValues = map[string]Value{ 872 "_aclitem": &ACLItemArray{}, 873 "_bool": &BoolArray{}, 874 "_bpchar": &BPCharArray{}, 875 "_bytea": &ByteaArray{}, 876 "_cidr": &CIDRArray{}, 877 "_date": &DateArray{}, 878 "_float4": &Float4Array{}, 879 "_float8": &Float8Array{}, 880 "_inet": &InetArray{}, 881 "_int2": &Int2Array{}, 882 "_int4": &Int4Array{}, 883 "_int8": &Int8Array{}, 884 "_numeric": &NumericArray{}, 885 "_text": &TextArray{}, 886 "_timestamp": &TimestampArray{}, 887 "_timestamptz": &TimestamptzArray{}, 888 "_uuid": &UUIDArray{}, 889 "_varchar": &VarcharArray{}, 890 "_jsonb": &JSONBArray{}, 891 "aclitem": &ACLItem{}, 892 "bit": &Bit{}, 893 "bool": &Bool{}, 894 "box": &Box{}, 895 "bpchar": &BPChar{}, 896 "bytea": &Bytea{}, 897 "char": &QChar{}, 898 "cid": &CID{}, 899 "cidr": &CIDR{}, 900 "circle": &Circle{}, 901 "date": &Date{}, 902 "daterange": &Daterange{}, 903 "float4": &Float4{}, 904 "float8": &Float8{}, 905 "hstore": &Hstore{}, 906 "inet": &Inet{}, 907 "int2": &Int2{}, 908 "int4": &Int4{}, 909 "int4range": &Int4range{}, 910 "int8": &Int8{}, 911 "int8range": &Int8range{}, 912 "interval": &Interval{}, 913 "json": &JSON{}, 914 "jsonb": &JSONB{}, 915 "line": &Line{}, 916 "lseg": &Lseg{}, 917 "macaddr": &Macaddr{}, 918 "name": &Name{}, 919 "numeric": &Numeric{}, 920 "numrange": &Numrange{}, 921 "oid": &OIDValue{}, 922 "path": &Path{}, 923 "point": &Point{}, 924 "polygon": &Polygon{}, 925 "record": &Record{}, 926 "text": &Text{}, 927 "tid": &TID{}, 928 "timestamp": &Timestamp{}, 929 "timestamptz": &Timestamptz{}, 930 "tsrange": &Tsrange{}, 931 "_tsrange": &TsrangeArray{}, 932 "tstzrange": &Tstzrange{}, 933 "_tstzrange": &TstzrangeArray{}, 934 "unknown": &Unknown{}, 935 "uuid": &UUID{}, 936 "varbit": &Varbit{}, 937 "varchar": &Varchar{}, 938 "xid": &XID{}, 939 } 940} 941