[822] | 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 | }
|
---|