| // Go MySQL Driver - A MySQL-Driver for Go's database/sql package |
| // |
| // Copyright 2017 The Go-MySQL-Driver Authors. All rights reserved. |
| // |
| // This Source Code Form is subject to the terms of the Mozilla Public |
| // License, v. 2.0. If a copy of the MPL was not distributed with this file, |
| // You can obtain one at http://mozilla.org/MPL/2.0/. |
| |
| package mysql |
| |
| import ( |
| "database/sql" |
| "reflect" |
| ) |
| |
| func (mf *mysqlField) typeDatabaseName() string { |
| switch mf.fieldType { |
| case fieldTypeBit: |
| return "BIT" |
| case fieldTypeBLOB: |
| if mf.charSet != binaryCollationID { |
| return "TEXT" |
| } |
| return "BLOB" |
| case fieldTypeDate: |
| return "DATE" |
| case fieldTypeDateTime: |
| return "DATETIME" |
| case fieldTypeDecimal: |
| return "DECIMAL" |
| case fieldTypeDouble: |
| return "DOUBLE" |
| case fieldTypeEnum: |
| return "ENUM" |
| case fieldTypeFloat: |
| return "FLOAT" |
| case fieldTypeGeometry: |
| return "GEOMETRY" |
| case fieldTypeInt24: |
| if mf.flags&flagUnsigned != 0 { |
| return "UNSIGNED MEDIUMINT" |
| } |
| return "MEDIUMINT" |
| case fieldTypeJSON: |
| return "JSON" |
| case fieldTypeLong: |
| if mf.flags&flagUnsigned != 0 { |
| return "UNSIGNED INT" |
| } |
| return "INT" |
| case fieldTypeLongBLOB: |
| if mf.charSet != binaryCollationID { |
| return "LONGTEXT" |
| } |
| return "LONGBLOB" |
| case fieldTypeLongLong: |
| if mf.flags&flagUnsigned != 0 { |
| return "UNSIGNED BIGINT" |
| } |
| return "BIGINT" |
| case fieldTypeMediumBLOB: |
| if mf.charSet != binaryCollationID { |
| return "MEDIUMTEXT" |
| } |
| return "MEDIUMBLOB" |
| case fieldTypeNewDate: |
| return "DATE" |
| case fieldTypeNewDecimal: |
| return "DECIMAL" |
| case fieldTypeNULL: |
| return "NULL" |
| case fieldTypeSet: |
| return "SET" |
| case fieldTypeShort: |
| if mf.flags&flagUnsigned != 0 { |
| return "UNSIGNED SMALLINT" |
| } |
| return "SMALLINT" |
| case fieldTypeString: |
| if mf.flags&flagEnum != 0 { |
| return "ENUM" |
| } else if mf.flags&flagSet != 0 { |
| return "SET" |
| } |
| if mf.charSet == binaryCollationID { |
| return "BINARY" |
| } |
| return "CHAR" |
| case fieldTypeTime: |
| return "TIME" |
| case fieldTypeTimestamp: |
| return "TIMESTAMP" |
| case fieldTypeTiny: |
| if mf.flags&flagUnsigned != 0 { |
| return "UNSIGNED TINYINT" |
| } |
| return "TINYINT" |
| case fieldTypeTinyBLOB: |
| if mf.charSet != binaryCollationID { |
| return "TINYTEXT" |
| } |
| return "TINYBLOB" |
| case fieldTypeVarChar: |
| if mf.charSet == binaryCollationID { |
| return "VARBINARY" |
| } |
| return "VARCHAR" |
| case fieldTypeVarString: |
| if mf.charSet == binaryCollationID { |
| return "VARBINARY" |
| } |
| return "VARCHAR" |
| case fieldTypeYear: |
| return "YEAR" |
| default: |
| return "" |
| } |
| } |
| |
| var ( |
| scanTypeFloat32 = reflect.TypeOf(float32(0)) |
| scanTypeFloat64 = reflect.TypeOf(float64(0)) |
| scanTypeInt8 = reflect.TypeOf(int8(0)) |
| scanTypeInt16 = reflect.TypeOf(int16(0)) |
| scanTypeInt32 = reflect.TypeOf(int32(0)) |
| scanTypeInt64 = reflect.TypeOf(int64(0)) |
| scanTypeNullFloat = reflect.TypeOf(sql.NullFloat64{}) |
| scanTypeNullInt = reflect.TypeOf(sql.NullInt64{}) |
| scanTypeNullTime = reflect.TypeOf(sql.NullTime{}) |
| scanTypeUint8 = reflect.TypeOf(uint8(0)) |
| scanTypeUint16 = reflect.TypeOf(uint16(0)) |
| scanTypeUint32 = reflect.TypeOf(uint32(0)) |
| scanTypeUint64 = reflect.TypeOf(uint64(0)) |
| scanTypeString = reflect.TypeOf("") |
| scanTypeNullString = reflect.TypeOf(sql.NullString{}) |
| scanTypeBytes = reflect.TypeOf([]byte{}) |
| scanTypeUnknown = reflect.TypeOf(new(any)) |
| ) |
| |
| type mysqlField struct { |
| tableName string |
| name string |
| length uint32 |
| flags fieldFlag |
| fieldType fieldType |
| decimals byte |
| charSet uint8 |
| } |
| |
| func (mf *mysqlField) scanType() reflect.Type { |
| switch mf.fieldType { |
| case fieldTypeTiny: |
| if mf.flags&flagNotNULL != 0 { |
| if mf.flags&flagUnsigned != 0 { |
| return scanTypeUint8 |
| } |
| return scanTypeInt8 |
| } |
| return scanTypeNullInt |
| |
| case fieldTypeShort, fieldTypeYear: |
| if mf.flags&flagNotNULL != 0 { |
| if mf.flags&flagUnsigned != 0 { |
| return scanTypeUint16 |
| } |
| return scanTypeInt16 |
| } |
| return scanTypeNullInt |
| |
| case fieldTypeInt24, fieldTypeLong: |
| if mf.flags&flagNotNULL != 0 { |
| if mf.flags&flagUnsigned != 0 { |
| return scanTypeUint32 |
| } |
| return scanTypeInt32 |
| } |
| return scanTypeNullInt |
| |
| case fieldTypeLongLong: |
| if mf.flags&flagNotNULL != 0 { |
| if mf.flags&flagUnsigned != 0 { |
| return scanTypeUint64 |
| } |
| return scanTypeInt64 |
| } |
| return scanTypeNullInt |
| |
| case fieldTypeFloat: |
| if mf.flags&flagNotNULL != 0 { |
| return scanTypeFloat32 |
| } |
| return scanTypeNullFloat |
| |
| case fieldTypeDouble: |
| if mf.flags&flagNotNULL != 0 { |
| return scanTypeFloat64 |
| } |
| return scanTypeNullFloat |
| |
| case fieldTypeBit, fieldTypeTinyBLOB, fieldTypeMediumBLOB, fieldTypeLongBLOB, |
| fieldTypeBLOB, fieldTypeVarString, fieldTypeString, fieldTypeGeometry: |
| if mf.charSet == binaryCollationID { |
| return scanTypeBytes |
| } |
| fallthrough |
| case fieldTypeDecimal, fieldTypeNewDecimal, fieldTypeVarChar, |
| fieldTypeEnum, fieldTypeSet, fieldTypeJSON, fieldTypeTime: |
| if mf.flags&flagNotNULL != 0 { |
| return scanTypeString |
| } |
| return scanTypeNullString |
| |
| case fieldTypeDate, fieldTypeNewDate, |
| fieldTypeTimestamp, fieldTypeDateTime: |
| // NullTime is always returned for more consistent behavior as it can |
| // handle both cases of parseTime regardless if the field is nullable. |
| return scanTypeNullTime |
| |
| default: |
| return scanTypeUnknown |
| } |
| } |