1// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
2//
3// Copyright 2017 The Go-MySQL-Driver Authors. All rights reserved.
4//
5// This Source Code Form is subject to the terms of the Mozilla Public
6// License, v. 2.0. If a copy of the MPL was not distributed with this file,
7// You can obtain one at http://mozilla.org/MPL/2.0/.
8
9package mysql
10
11import (
12	"database/sql"
13	"reflect"
14)
15
16func (mf *mysqlField) typeDatabaseName() string {
17	switch mf.fieldType {
18	case fieldTypeBit:
19		return "BIT"
20	case fieldTypeBLOB:
21		if mf.charSet != collations[binaryCollation] {
22			return "TEXT"
23		}
24		return "BLOB"
25	case fieldTypeDate:
26		return "DATE"
27	case fieldTypeDateTime:
28		return "DATETIME"
29	case fieldTypeDecimal:
30		return "DECIMAL"
31	case fieldTypeDouble:
32		return "DOUBLE"
33	case fieldTypeEnum:
34		return "ENUM"
35	case fieldTypeFloat:
36		return "FLOAT"
37	case fieldTypeGeometry:
38		return "GEOMETRY"
39	case fieldTypeInt24:
40		return "MEDIUMINT"
41	case fieldTypeJSON:
42		return "JSON"
43	case fieldTypeLong:
44		return "INT"
45	case fieldTypeLongBLOB:
46		if mf.charSet != collations[binaryCollation] {
47			return "LONGTEXT"
48		}
49		return "LONGBLOB"
50	case fieldTypeLongLong:
51		return "BIGINT"
52	case fieldTypeMediumBLOB:
53		if mf.charSet != collations[binaryCollation] {
54			return "MEDIUMTEXT"
55		}
56		return "MEDIUMBLOB"
57	case fieldTypeNewDate:
58		return "DATE"
59	case fieldTypeNewDecimal:
60		return "DECIMAL"
61	case fieldTypeNULL:
62		return "NULL"
63	case fieldTypeSet:
64		return "SET"
65	case fieldTypeShort:
66		return "SMALLINT"
67	case fieldTypeString:
68		if mf.charSet == collations[binaryCollation] {
69			return "BINARY"
70		}
71		return "CHAR"
72	case fieldTypeTime:
73		return "TIME"
74	case fieldTypeTimestamp:
75		return "TIMESTAMP"
76	case fieldTypeTiny:
77		return "TINYINT"
78	case fieldTypeTinyBLOB:
79		if mf.charSet != collations[binaryCollation] {
80			return "TINYTEXT"
81		}
82		return "TINYBLOB"
83	case fieldTypeVarChar:
84		if mf.charSet == collations[binaryCollation] {
85			return "VARBINARY"
86		}
87		return "VARCHAR"
88	case fieldTypeVarString:
89		if mf.charSet == collations[binaryCollation] {
90			return "VARBINARY"
91		}
92		return "VARCHAR"
93	case fieldTypeYear:
94		return "YEAR"
95	default:
96		return ""
97	}
98}
99
100var (
101	scanTypeFloat32   = reflect.TypeOf(float32(0))
102	scanTypeFloat64   = reflect.TypeOf(float64(0))
103	scanTypeInt8      = reflect.TypeOf(int8(0))
104	scanTypeInt16     = reflect.TypeOf(int16(0))
105	scanTypeInt32     = reflect.TypeOf(int32(0))
106	scanTypeInt64     = reflect.TypeOf(int64(0))
107	scanTypeNullFloat = reflect.TypeOf(sql.NullFloat64{})
108	scanTypeNullInt   = reflect.TypeOf(sql.NullInt64{})
109	scanTypeNullTime  = reflect.TypeOf(NullTime{})
110	scanTypeUint8     = reflect.TypeOf(uint8(0))
111	scanTypeUint16    = reflect.TypeOf(uint16(0))
112	scanTypeUint32    = reflect.TypeOf(uint32(0))
113	scanTypeUint64    = reflect.TypeOf(uint64(0))
114	scanTypeRawBytes  = reflect.TypeOf(sql.RawBytes{})
115	scanTypeUnknown   = reflect.TypeOf(new(interface{}))
116)
117
118type mysqlField struct {
119	tableName string
120	name      string
121	length    uint32
122	flags     fieldFlag
123	fieldType fieldType
124	decimals  byte
125	charSet   uint8
126}
127
128func (mf *mysqlField) scanType() reflect.Type {
129	switch mf.fieldType {
130	case fieldTypeTiny:
131		if mf.flags&flagNotNULL != 0 {
132			if mf.flags&flagUnsigned != 0 {
133				return scanTypeUint8
134			}
135			return scanTypeInt8
136		}
137		return scanTypeNullInt
138
139	case fieldTypeShort, fieldTypeYear:
140		if mf.flags&flagNotNULL != 0 {
141			if mf.flags&flagUnsigned != 0 {
142				return scanTypeUint16
143			}
144			return scanTypeInt16
145		}
146		return scanTypeNullInt
147
148	case fieldTypeInt24, fieldTypeLong:
149		if mf.flags&flagNotNULL != 0 {
150			if mf.flags&flagUnsigned != 0 {
151				return scanTypeUint32
152			}
153			return scanTypeInt32
154		}
155		return scanTypeNullInt
156
157	case fieldTypeLongLong:
158		if mf.flags&flagNotNULL != 0 {
159			if mf.flags&flagUnsigned != 0 {
160				return scanTypeUint64
161			}
162			return scanTypeInt64
163		}
164		return scanTypeNullInt
165
166	case fieldTypeFloat:
167		if mf.flags&flagNotNULL != 0 {
168			return scanTypeFloat32
169		}
170		return scanTypeNullFloat
171
172	case fieldTypeDouble:
173		if mf.flags&flagNotNULL != 0 {
174			return scanTypeFloat64
175		}
176		return scanTypeNullFloat
177
178	case fieldTypeDecimal, fieldTypeNewDecimal, fieldTypeVarChar,
179		fieldTypeBit, fieldTypeEnum, fieldTypeSet, fieldTypeTinyBLOB,
180		fieldTypeMediumBLOB, fieldTypeLongBLOB, fieldTypeBLOB,
181		fieldTypeVarString, fieldTypeString, fieldTypeGeometry, fieldTypeJSON,
182		fieldTypeTime:
183		return scanTypeRawBytes
184
185	case fieldTypeDate, fieldTypeNewDate,
186		fieldTypeTimestamp, fieldTypeDateTime:
187		// NullTime is always returned for more consistent behavior as it can
188		// handle both cases of parseTime regardless if the field is nullable.
189		return scanTypeNullTime
190
191	default:
192		return scanTypeUnknown
193	}
194}
195