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