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: &Line{}, Name: "line", OID: LineOID}) 297 ci.RegisterDataType(DataType{Value: &Lseg{}, Name: "lseg", OID: LsegOID}) 298 ci.RegisterDataType(DataType{Value: &Macaddr{}, Name: "macaddr", OID: MacaddrOID}) 299 ci.RegisterDataType(DataType{Value: &Name{}, Name: "name", OID: NameOID}) 300 ci.RegisterDataType(DataType{Value: &Numeric{}, Name: "numeric", OID: NumericOID}) 301 ci.RegisterDataType(DataType{Value: &Numrange{}, Name: "numrange", OID: NumrangeOID}) 302 ci.RegisterDataType(DataType{Value: &OIDValue{}, Name: "oid", OID: OIDOID}) 303 ci.RegisterDataType(DataType{Value: &Path{}, Name: "path", OID: PathOID}) 304 ci.RegisterDataType(DataType{Value: &Point{}, Name: "point", OID: PointOID}) 305 ci.RegisterDataType(DataType{Value: &Polygon{}, Name: "polygon", OID: PolygonOID}) 306 ci.RegisterDataType(DataType{Value: &Record{}, Name: "record", OID: RecordOID}) 307 ci.RegisterDataType(DataType{Value: &Text{}, Name: "text", OID: TextOID}) 308 ci.RegisterDataType(DataType{Value: &TID{}, Name: "tid", OID: TIDOID}) 309 ci.RegisterDataType(DataType{Value: &Time{}, Name: "time", OID: TimeOID}) 310 ci.RegisterDataType(DataType{Value: &Timestamp{}, Name: "timestamp", OID: TimestampOID}) 311 ci.RegisterDataType(DataType{Value: &Timestamptz{}, Name: "timestamptz", OID: TimestamptzOID}) 312 ci.RegisterDataType(DataType{Value: &Tsrange{}, Name: "tsrange", OID: TsrangeOID}) 313 ci.RegisterDataType(DataType{Value: &TsrangeArray{}, Name: "_tsrange", OID: TsrangeArrayOID}) 314 ci.RegisterDataType(DataType{Value: &Tstzrange{}, Name: "tstzrange", OID: TstzrangeOID}) 315 ci.RegisterDataType(DataType{Value: &TstzrangeArray{}, Name: "_tstzrange", OID: TstzrangeArrayOID}) 316 ci.RegisterDataType(DataType{Value: &Unknown{}, Name: "unknown", OID: UnknownOID}) 317 ci.RegisterDataType(DataType{Value: &UUID{}, Name: "uuid", OID: UUIDOID}) 318 ci.RegisterDataType(DataType{Value: &Varbit{}, Name: "varbit", OID: VarbitOID}) 319 ci.RegisterDataType(DataType{Value: &Varchar{}, Name: "varchar", OID: VarcharOID}) 320 ci.RegisterDataType(DataType{Value: &XID{}, Name: "xid", OID: XIDOID}) 321 322 registerDefaultPgTypeVariants := func(name, arrayName string, value interface{}) { 323 ci.RegisterDefaultPgType(value, name) 324 valueType := reflect.TypeOf(value) 325 326 ci.RegisterDefaultPgType(reflect.New(valueType).Interface(), name) 327 328 sliceType := reflect.SliceOf(valueType) 329 ci.RegisterDefaultPgType(reflect.MakeSlice(sliceType, 0, 0).Interface(), arrayName) 330 331 ci.RegisterDefaultPgType(reflect.New(sliceType).Interface(), arrayName) 332 } 333 334 // Integer types that directly map to a PostgreSQL type 335 registerDefaultPgTypeVariants("int2", "_int2", int16(0)) 336 registerDefaultPgTypeVariants("int4", "_int4", int32(0)) 337 registerDefaultPgTypeVariants("int8", "_int8", int64(0)) 338 339 // Integer types that do not have a direct match to a PostgreSQL type 340 registerDefaultPgTypeVariants("int8", "_int8", uint16(0)) 341 registerDefaultPgTypeVariants("int8", "_int8", uint32(0)) 342 registerDefaultPgTypeVariants("int8", "_int8", uint64(0)) 343 registerDefaultPgTypeVariants("int8", "_int8", int(0)) 344 registerDefaultPgTypeVariants("int8", "_int8", uint(0)) 345 346 registerDefaultPgTypeVariants("float4", "_float4", float32(0)) 347 registerDefaultPgTypeVariants("float8", "_float8", float64(0)) 348 349 registerDefaultPgTypeVariants("bool", "_bool", false) 350 registerDefaultPgTypeVariants("timestamptz", "_timestamptz", time.Time{}) 351 registerDefaultPgTypeVariants("text", "_text", "") 352 registerDefaultPgTypeVariants("bytea", "_bytea", []byte(nil)) 353 354 registerDefaultPgTypeVariants("inet", "_inet", net.IP{}) 355 ci.RegisterDefaultPgType((*net.IPNet)(nil), "cidr") 356 ci.RegisterDefaultPgType([]*net.IPNet(nil), "_cidr") 357 358 return ci 359} 360 361func (ci *ConnInfo) InitializeDataTypes(nameOIDs map[string]uint32) { 362 for name, oid := range nameOIDs { 363 var value Value 364 if t, ok := nameValues[name]; ok { 365 value = reflect.New(reflect.ValueOf(t).Elem().Type()).Interface().(Value) 366 } else { 367 value = &GenericText{} 368 } 369 ci.RegisterDataType(DataType{Value: value, Name: name, OID: oid}) 370 } 371} 372 373func (ci *ConnInfo) RegisterDataType(t DataType) { 374 t.Value = NewValue(t.Value) 375 376 ci.oidToDataType[t.OID] = &t 377 ci.nameToDataType[t.Name] = &t 378 379 { 380 var formatCode int16 381 if pfp, ok := t.Value.(ParamFormatPreferrer); ok { 382 formatCode = pfp.PreferredParamFormat() 383 } else if _, ok := t.Value.(BinaryEncoder); ok { 384 formatCode = BinaryFormatCode 385 } 386 ci.oidToParamFormatCode[t.OID] = formatCode 387 } 388 389 { 390 var formatCode int16 391 if rfp, ok := t.Value.(ResultFormatPreferrer); ok { 392 formatCode = rfp.PreferredResultFormat() 393 } else if _, ok := t.Value.(BinaryDecoder); ok { 394 formatCode = BinaryFormatCode 395 } 396 ci.oidToResultFormatCode[t.OID] = formatCode 397 } 398 399 if d, ok := t.Value.(TextDecoder); ok { 400 t.textDecoder = d 401 } 402 403 if d, ok := t.Value.(BinaryDecoder); ok { 404 t.binaryDecoder = d 405 } 406 407 ci.reflectTypeToDataType = nil // Invalidated by type registration 408} 409 410// RegisterDefaultPgType registers a mapping of a Go type to a PostgreSQL type name. Typically the data type to be 411// encoded or decoded is determined by the PostgreSQL OID. But if the OID of a value to be encoded or decoded is 412// unknown, this additional mapping will be used by DataTypeForValue to determine a suitable data type. 413func (ci *ConnInfo) RegisterDefaultPgType(value interface{}, name string) { 414 ci.reflectTypeToName[reflect.TypeOf(value)] = name 415 ci.reflectTypeToDataType = nil // Invalidated by registering a default type 416} 417 418func (ci *ConnInfo) DataTypeForOID(oid uint32) (*DataType, bool) { 419 dt, ok := ci.oidToDataType[oid] 420 return dt, ok 421} 422 423func (ci *ConnInfo) DataTypeForName(name string) (*DataType, bool) { 424 dt, ok := ci.nameToDataType[name] 425 return dt, ok 426} 427 428func (ci *ConnInfo) buildReflectTypeToDataType() { 429 ci.reflectTypeToDataType = make(map[reflect.Type]*DataType) 430 431 for _, dt := range ci.oidToDataType { 432 if _, is := dt.Value.(TypeValue); !is { 433 ci.reflectTypeToDataType[reflect.ValueOf(dt.Value).Type()] = dt 434 } 435 } 436 437 for reflectType, name := range ci.reflectTypeToName { 438 if dt, ok := ci.nameToDataType[name]; ok { 439 ci.reflectTypeToDataType[reflectType] = dt 440 } 441 } 442} 443 444// DataTypeForValue finds a data type suitable for v. Use RegisterDataType to register types that can encode and decode 445// themselves. Use RegisterDefaultPgType to register that can be handled by a registered data type. 446func (ci *ConnInfo) DataTypeForValue(v interface{}) (*DataType, bool) { 447 if ci.reflectTypeToDataType == nil { 448 ci.buildReflectTypeToDataType() 449 } 450 451 if tv, ok := v.(TypeValue); ok { 452 dt, ok := ci.nameToDataType[tv.TypeName()] 453 return dt, ok 454 } 455 456 dt, ok := ci.reflectTypeToDataType[reflect.TypeOf(v)] 457 return dt, ok 458} 459 460func (ci *ConnInfo) ParamFormatCodeForOID(oid uint32) int16 { 461 fc, ok := ci.oidToParamFormatCode[oid] 462 if ok { 463 return fc 464 } 465 return TextFormatCode 466} 467 468func (ci *ConnInfo) ResultFormatCodeForOID(oid uint32) int16 { 469 fc, ok := ci.oidToResultFormatCode[oid] 470 if ok { 471 return fc 472 } 473 return TextFormatCode 474} 475 476// DeepCopy makes a deep copy of the ConnInfo. 477func (ci *ConnInfo) DeepCopy() *ConnInfo { 478 ci2 := newConnInfo() 479 480 for _, dt := range ci.oidToDataType { 481 ci2.RegisterDataType(DataType{ 482 Value: NewValue(dt.Value), 483 Name: dt.Name, 484 OID: dt.OID, 485 }) 486 } 487 488 for t, n := range ci.reflectTypeToName { 489 ci2.reflectTypeToName[t] = n 490 } 491 492 return ci2 493} 494 495// ScanPlan is a precompiled plan to scan into a type of destination. 496type ScanPlan interface { 497 // Scan scans src into dst. If the dst type has changed in an incompatible way a ScanPlan should automatically 498 // replan and scan. 499 Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error 500} 501 502type scanPlanDstBinaryDecoder struct{} 503 504func (scanPlanDstBinaryDecoder) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error { 505 if d, ok := (dst).(BinaryDecoder); ok { 506 return d.DecodeBinary(ci, src) 507 } 508 509 newPlan := ci.PlanScan(oid, formatCode, dst) 510 return newPlan.Scan(ci, oid, formatCode, src, dst) 511} 512 513type scanPlanDstTextDecoder struct{} 514 515func (plan scanPlanDstTextDecoder) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error { 516 if d, ok := (dst).(TextDecoder); ok { 517 return d.DecodeText(ci, src) 518 } 519 520 newPlan := ci.PlanScan(oid, formatCode, dst) 521 return newPlan.Scan(ci, oid, formatCode, src, dst) 522} 523 524type scanPlanDataTypeSQLScanner DataType 525 526func (plan *scanPlanDataTypeSQLScanner) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error { 527 scanner, ok := dst.(sql.Scanner) 528 if !ok { 529 newPlan := ci.PlanScan(oid, formatCode, dst) 530 return newPlan.Scan(ci, oid, formatCode, src, dst) 531 } 532 533 dt := (*DataType)(plan) 534 var err error 535 switch formatCode { 536 case BinaryFormatCode: 537 err = dt.binaryDecoder.DecodeBinary(ci, src) 538 case TextFormatCode: 539 err = dt.textDecoder.DecodeText(ci, src) 540 } 541 if err != nil { 542 return err 543 } 544 545 sqlSrc, err := DatabaseSQLValue(ci, dt.Value) 546 if err != nil { 547 return err 548 } 549 return scanner.Scan(sqlSrc) 550} 551 552type scanPlanDataTypeAssignTo DataType 553 554func (plan *scanPlanDataTypeAssignTo) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error { 555 dt := (*DataType)(plan) 556 var err error 557 switch formatCode { 558 case BinaryFormatCode: 559 err = dt.binaryDecoder.DecodeBinary(ci, src) 560 case TextFormatCode: 561 err = dt.textDecoder.DecodeText(ci, src) 562 } 563 if err != nil { 564 return err 565 } 566 567 assignToErr := dt.Value.AssignTo(dst) 568 if assignToErr == nil { 569 return nil 570 } 571 572 if dstPtr, ok := dst.(*interface{}); ok { 573 *dstPtr = dt.Value.Get() 574 return nil 575 } 576 577 // assignToErr might have failed because the type of destination has changed 578 newPlan := ci.PlanScan(oid, formatCode, dst) 579 if newPlan, sameType := newPlan.(*scanPlanDataTypeAssignTo); !sameType { 580 return newPlan.Scan(ci, oid, formatCode, src, dst) 581 } 582 583 return assignToErr 584} 585 586type scanPlanSQLScanner struct{} 587 588func (scanPlanSQLScanner) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error { 589 scanner := dst.(sql.Scanner) 590 if formatCode == BinaryFormatCode { 591 return scanner.Scan(src) 592 } else { 593 return scanner.Scan(string(src)) 594 } 595} 596 597type scanPlanReflection struct{} 598 599func (scanPlanReflection) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error { 600 // We might be given a pointer to something that implements the decoder interface(s), 601 // even though the pointer itself doesn't. 602 refVal := reflect.ValueOf(dst) 603 if refVal.Kind() == reflect.Ptr && refVal.Type().Elem().Kind() == reflect.Ptr { 604 // If the database returned NULL, then we set dest as nil to indicate that. 605 if src == nil { 606 nilPtr := reflect.Zero(refVal.Type().Elem()) 607 refVal.Elem().Set(nilPtr) 608 return nil 609 } 610 611 // We need to allocate an element, and set the destination to it 612 // Then we can retry as that element. 613 elemPtr := reflect.New(refVal.Type().Elem().Elem()) 614 refVal.Elem().Set(elemPtr) 615 616 plan := ci.PlanScan(oid, formatCode, elemPtr.Interface()) 617 return plan.Scan(ci, oid, formatCode, src, elemPtr.Interface()) 618 } 619 620 return scanUnknownType(oid, formatCode, src, dst) 621} 622 623type scanPlanBinaryInt16 struct{} 624 625func (scanPlanBinaryInt16) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error { 626 if src == nil { 627 return fmt.Errorf("cannot scan null into %T", dst) 628 } 629 630 if len(src) != 2 { 631 return fmt.Errorf("invalid length for int2: %v", len(src)) 632 } 633 634 if p, ok := (dst).(*int16); ok { 635 *p = int16(binary.BigEndian.Uint16(src)) 636 return nil 637 } 638 639 newPlan := ci.PlanScan(oid, formatCode, dst) 640 return newPlan.Scan(ci, oid, formatCode, src, dst) 641} 642 643type scanPlanBinaryInt32 struct{} 644 645func (scanPlanBinaryInt32) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error { 646 if src == nil { 647 return fmt.Errorf("cannot scan null into %T", dst) 648 } 649 650 if len(src) != 4 { 651 return fmt.Errorf("invalid length for int4: %v", len(src)) 652 } 653 654 if p, ok := (dst).(*int32); ok { 655 *p = int32(binary.BigEndian.Uint32(src)) 656 return nil 657 } 658 659 newPlan := ci.PlanScan(oid, formatCode, dst) 660 return newPlan.Scan(ci, oid, formatCode, src, dst) 661} 662 663type scanPlanBinaryInt64 struct{} 664 665func (scanPlanBinaryInt64) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error { 666 if src == nil { 667 return fmt.Errorf("cannot scan null into %T", dst) 668 } 669 670 if len(src) != 8 { 671 return fmt.Errorf("invalid length for int8: %v", len(src)) 672 } 673 674 if p, ok := (dst).(*int64); ok { 675 *p = int64(binary.BigEndian.Uint64(src)) 676 return nil 677 } 678 679 newPlan := ci.PlanScan(oid, formatCode, dst) 680 return newPlan.Scan(ci, oid, formatCode, src, dst) 681} 682 683type scanPlanBinaryFloat32 struct{} 684 685func (scanPlanBinaryFloat32) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error { 686 if src == nil { 687 return fmt.Errorf("cannot scan null into %T", dst) 688 } 689 690 if len(src) != 4 { 691 return fmt.Errorf("invalid length for int4: %v", len(src)) 692 } 693 694 if p, ok := (dst).(*float32); ok { 695 n := int32(binary.BigEndian.Uint32(src)) 696 *p = float32(math.Float32frombits(uint32(n))) 697 return nil 698 } 699 700 newPlan := ci.PlanScan(oid, formatCode, dst) 701 return newPlan.Scan(ci, oid, formatCode, src, dst) 702} 703 704type scanPlanBinaryFloat64 struct{} 705 706func (scanPlanBinaryFloat64) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error { 707 if src == nil { 708 return fmt.Errorf("cannot scan null into %T", dst) 709 } 710 711 if len(src) != 8 { 712 return fmt.Errorf("invalid length for int8: %v", len(src)) 713 } 714 715 if p, ok := (dst).(*float64); ok { 716 n := int64(binary.BigEndian.Uint64(src)) 717 *p = float64(math.Float64frombits(uint64(n))) 718 return nil 719 } 720 721 newPlan := ci.PlanScan(oid, formatCode, dst) 722 return newPlan.Scan(ci, oid, formatCode, src, dst) 723} 724 725type scanPlanBinaryBytes struct{} 726 727func (scanPlanBinaryBytes) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error { 728 if p, ok := (dst).(*[]byte); ok { 729 *p = src 730 return nil 731 } 732 733 newPlan := ci.PlanScan(oid, formatCode, dst) 734 return newPlan.Scan(ci, oid, formatCode, src, dst) 735} 736 737type scanPlanString struct{} 738 739func (scanPlanString) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error { 740 if src == nil { 741 return fmt.Errorf("cannot scan null into %T", dst) 742 } 743 744 if p, ok := (dst).(*string); ok { 745 *p = string(src) 746 return nil 747 } 748 749 newPlan := ci.PlanScan(oid, formatCode, dst) 750 return newPlan.Scan(ci, oid, formatCode, src, dst) 751} 752 753// PlanScan prepares a plan to scan a value into dst. 754func (ci *ConnInfo) PlanScan(oid uint32, formatCode int16, dst interface{}) ScanPlan { 755 switch formatCode { 756 case BinaryFormatCode: 757 switch dst.(type) { 758 case *string: 759 switch oid { 760 case TextOID, VarcharOID: 761 return scanPlanString{} 762 } 763 case *int16: 764 if oid == Int2OID { 765 return scanPlanBinaryInt16{} 766 } 767 case *int32: 768 if oid == Int4OID { 769 return scanPlanBinaryInt32{} 770 } 771 case *int64: 772 if oid == Int8OID { 773 return scanPlanBinaryInt64{} 774 } 775 case *float32: 776 if oid == Float4OID { 777 return scanPlanBinaryFloat32{} 778 } 779 case *float64: 780 if oid == Float8OID { 781 return scanPlanBinaryFloat64{} 782 } 783 case *[]byte: 784 switch oid { 785 case ByteaOID, TextOID, VarcharOID, JSONOID: 786 return scanPlanBinaryBytes{} 787 } 788 case BinaryDecoder: 789 return scanPlanDstBinaryDecoder{} 790 } 791 case TextFormatCode: 792 switch dst.(type) { 793 case *string: 794 return scanPlanString{} 795 case *[]byte: 796 if oid != ByteaOID { 797 return scanPlanBinaryBytes{} 798 } 799 case TextDecoder: 800 return scanPlanDstTextDecoder{} 801 } 802 } 803 804 var dt *DataType 805 806 if oid == 0 { 807 if dataType, ok := ci.DataTypeForValue(dst); ok { 808 dt = dataType 809 } 810 } else { 811 if dataType, ok := ci.DataTypeForOID(oid); ok { 812 dt = dataType 813 } 814 } 815 816 if dt != nil { 817 if _, ok := dst.(sql.Scanner); ok { 818 return (*scanPlanDataTypeSQLScanner)(dt) 819 } 820 return (*scanPlanDataTypeAssignTo)(dt) 821 } 822 823 if _, ok := dst.(sql.Scanner); ok { 824 return scanPlanSQLScanner{} 825 } 826 827 return scanPlanReflection{} 828} 829 830func (ci *ConnInfo) Scan(oid uint32, formatCode int16, src []byte, dst interface{}) error { 831 if dst == nil { 832 return nil 833 } 834 835 plan := ci.PlanScan(oid, formatCode, dst) 836 return plan.Scan(ci, oid, formatCode, src, dst) 837} 838 839func scanUnknownType(oid uint32, formatCode int16, buf []byte, dest interface{}) error { 840 switch dest := dest.(type) { 841 case *string: 842 if formatCode == BinaryFormatCode { 843 return fmt.Errorf("unknown oid %d in binary format cannot be scanned into %T", oid, dest) 844 } 845 *dest = string(buf) 846 return nil 847 case *[]byte: 848 *dest = buf 849 return nil 850 default: 851 if nextDst, retry := GetAssignToDstType(dest); retry { 852 return scanUnknownType(oid, formatCode, buf, nextDst) 853 } 854 return fmt.Errorf("unknown oid %d cannot be scanned into %T", oid, dest) 855 } 856} 857 858// NewValue returns a new instance of the same type as v. 859func NewValue(v Value) Value { 860 if tv, ok := v.(TypeValue); ok { 861 return tv.NewTypeValue() 862 } else { 863 return reflect.New(reflect.ValueOf(v).Elem().Type()).Interface().(Value) 864 } 865} 866 867var nameValues map[string]Value 868 869func init() { 870 nameValues = map[string]Value{ 871 "_aclitem": &ACLItemArray{}, 872 "_bool": &BoolArray{}, 873 "_bpchar": &BPCharArray{}, 874 "_bytea": &ByteaArray{}, 875 "_cidr": &CIDRArray{}, 876 "_date": &DateArray{}, 877 "_float4": &Float4Array{}, 878 "_float8": &Float8Array{}, 879 "_inet": &InetArray{}, 880 "_int2": &Int2Array{}, 881 "_int4": &Int4Array{}, 882 "_int8": &Int8Array{}, 883 "_numeric": &NumericArray{}, 884 "_text": &TextArray{}, 885 "_timestamp": &TimestampArray{}, 886 "_timestamptz": &TimestamptzArray{}, 887 "_uuid": &UUIDArray{}, 888 "_varchar": &VarcharArray{}, 889 "_jsonb": &JSONBArray{}, 890 "aclitem": &ACLItem{}, 891 "bit": &Bit{}, 892 "bool": &Bool{}, 893 "box": &Box{}, 894 "bpchar": &BPChar{}, 895 "bytea": &Bytea{}, 896 "char": &QChar{}, 897 "cid": &CID{}, 898 "cidr": &CIDR{}, 899 "circle": &Circle{}, 900 "date": &Date{}, 901 "daterange": &Daterange{}, 902 "float4": &Float4{}, 903 "float8": &Float8{}, 904 "hstore": &Hstore{}, 905 "inet": &Inet{}, 906 "int2": &Int2{}, 907 "int4": &Int4{}, 908 "int4range": &Int4range{}, 909 "int8": &Int8{}, 910 "int8range": &Int8range{}, 911 "interval": &Interval{}, 912 "json": &JSON{}, 913 "jsonb": &JSONB{}, 914 "line": &Line{}, 915 "lseg": &Lseg{}, 916 "macaddr": &Macaddr{}, 917 "name": &Name{}, 918 "numeric": &Numeric{}, 919 "numrange": &Numrange{}, 920 "oid": &OIDValue{}, 921 "path": &Path{}, 922 "point": &Point{}, 923 "polygon": &Polygon{}, 924 "record": &Record{}, 925 "text": &Text{}, 926 "tid": &TID{}, 927 "timestamp": &Timestamp{}, 928 "timestamptz": &Timestamptz{}, 929 "tsrange": &Tsrange{}, 930 "_tsrange": &TsrangeArray{}, 931 "tstzrange": &Tstzrange{}, 932 "_tstzrange": &TstzrangeArray{}, 933 "unknown": &Unknown{}, 934 "uuid": &UUID{}, 935 "varbit": &Varbit{}, 936 "varchar": &Varchar{}, 937 "xid": &XID{}, 938 } 939} 940