1 | package pq
|
---|
2 |
|
---|
3 | import (
|
---|
4 | "math"
|
---|
5 | "reflect"
|
---|
6 | "time"
|
---|
7 |
|
---|
8 | "github.com/lib/pq/oid"
|
---|
9 | )
|
---|
10 |
|
---|
11 | const headerSize = 4
|
---|
12 |
|
---|
13 | type 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 |
|
---|
24 | func (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 |
|
---|
45 | func (fd fieldDesc) Name() string {
|
---|
46 | return oid.TypeName[fd.OID]
|
---|
47 | }
|
---|
48 |
|
---|
49 | func (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 |
|
---|
60 | func (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.
|
---|
73 | func (rs *rows) ColumnTypeScanType(index int) reflect.Type {
|
---|
74 | return rs.colTyps[index].Type()
|
---|
75 | }
|
---|
76 |
|
---|
77 | // ColumnTypeDatabaseTypeName return the database system type name.
|
---|
78 | func (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.
|
---|
85 | func (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.
|
---|
91 | func (rs *rows) ColumnTypePrecisionScale(index int) (precision, scale int64, ok bool) {
|
---|
92 | return rs.colTyps[index].PrecisionScale()
|
---|
93 | }
|
---|