1package pq
2
3import (
4	"math"
5	"reflect"
6	"time"
7
8	"github.com/lib/pq/oid"
9)
10
11const headerSize = 4
12
13type fieldDesc struct {
14	// The object ID of the data type.
15	OID oid.Oid
16	// The data type size (see pg_type.typlen).
17	// Note that negative values denote variable-width types.
18	Len int
19	// The type modifier (see pg_attribute.atttypmod).
20	// The meaning of the modifier is type-specific.
21	Mod int
22}
23
24func (fd fieldDesc) Type() reflect.Type {
25	switch fd.OID {
26	case oid.T_int8:
27		return reflect.TypeOf(int64(0))
28	case oid.T_int4:
29		return reflect.TypeOf(int32(0))
30	case oid.T_int2:
31		return reflect.TypeOf(int16(0))
32	case oid.T_varchar, oid.T_text:
33		return reflect.TypeOf("")
34	case oid.T_bool:
35		return reflect.TypeOf(false)
36	case oid.T_date, oid.T_time, oid.T_timetz, oid.T_timestamp, oid.T_timestamptz:
37		return reflect.TypeOf(time.Time{})
38	case oid.T_bytea:
39		return reflect.TypeOf([]byte(nil))
40	default:
41		return reflect.TypeOf(new(interface{})).Elem()
42	}
43}
44
45func (fd fieldDesc) Name() string {
46	return oid.TypeName[fd.OID]
47}
48
49func (fd fieldDesc) Length() (length int64, ok bool) {
50	switch fd.OID {
51	case oid.T_text, oid.T_bytea:
52		return math.MaxInt64, true
53	case oid.T_varchar, oid.T_bpchar:
54		return int64(fd.Mod - headerSize), true
55	default:
56		return 0, false
57	}
58}
59
60func (fd fieldDesc) PrecisionScale() (precision, scale int64, ok bool) {
61	switch fd.OID {
62	case oid.T_numeric, oid.T__numeric:
63		mod := fd.Mod - headerSize
64		precision = int64((mod >> 16) & 0xffff)
65		scale = int64(mod & 0xffff)
66		return precision, scale, true
67	default:
68		return 0, 0, false
69	}
70}
71
72// ColumnTypeScanType returns the value type that can be used to scan types into.
73func (rs *rows) ColumnTypeScanType(index int) reflect.Type {
74	return rs.colTyps[index].Type()
75}
76
77// ColumnTypeDatabaseTypeName return the database system type name.
78func (rs *rows) ColumnTypeDatabaseTypeName(index int) string {
79	return rs.colTyps[index].Name()
80}
81
82// ColumnTypeLength returns the length of the column type if the column is a
83// variable length type. If the column is not a variable length type ok
84// should return false.
85func (rs *rows) ColumnTypeLength(index int) (length int64, ok bool) {
86	return rs.colTyps[index].Length()
87}
88
89// ColumnTypePrecisionScale should return the precision and scale for decimal
90// types. If not applicable, ok should be false.
91func (rs *rows) ColumnTypePrecisionScale(index int) (precision, scale int64, ok bool) {
92	return rs.colTyps[index].PrecisionScale()
93}
94