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