improve data type conversion (#236)

* improve data type conversion

* update doc
master
songmeizi 4 years ago committed by GitHub
parent cecd4b1b75
commit 4d53045c6b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -78,8 +78,8 @@ goctl model 为go-zero下的工具模块中的组件之一目前支持识别m
Password string `db:"password"` // 用户密码 Password string `db:"password"` // 用户密码
Mobile string `db:"mobile"` // 手机号 Mobile string `db:"mobile"` // 手机号
Gender string `db:"gender"` // 男|女|未公开 Gender string `db:"gender"` // 男|女|未公开
Nickname string `db:"nickname"` // 用户昵称 Nickname sql.NullString `db:"nickname"` // 用户昵称
CreateTime time.Time `db:"create_time"` CreateTime sql.NullTime `db:"create_time"`
UpdateTime time.Time `db:"update_time"` UpdateTime time.Time `db:"update_time"`
} }
) )
@ -347,3 +347,33 @@ OPTIONS:
目前我认为除了基本的CURD外其他的代码均属于<i>业务型</i>代码,这个我觉得开发人员根据业务需要进行编写更好。 目前我认为除了基本的CURD外其他的代码均属于<i>业务型</i>代码,这个我觉得开发人员根据业务需要进行编写更好。
# 类型转换规则
| mysql dataType | golang dataType | golang dataType(if null&&default null) |
|----------------|-----------------|----------------------------------------|
| bool | int64 | sql.NullInt64 |
| boolean | int64 | sql.NullInt64 |
| tinyint | int64 | sql.NullInt64 |
| smallint | int64 | sql.NullInt64 |
| mediumint | int64 | sql.NullInt64 |
| int | int64 | sql.NullInt64 |
| integer | int64 | sql.NullInt64 |
| bigint | int64 | sql.NullInt64 |
| float | float64 | sql.NullFloat64 |
| double | float64 | sql.NullFloat64 |
| decimal | float64 | sql.NullFloat64 |
| date | time.Time | sql.NullTime |
| datetime | time.Time | sql.NullTime |
| timestamp | time.Time | sql.NullTime |
| time | string | sql.NullString |
| year | time.Time | sql.NullInt64 |
| char | string | sql.NullString |
| varchar | string | sql.NullString |
| binary | string | sql.NullString |
| varbinary | string | sql.NullString |
| tinytext | string | sql.NullString |
| text | string | sql.NullString |
| mediumtext | string | sql.NullString |
| longtext | string | sql.NullString |
| enum | string | sql.NullString |
| set | string | sql.NullString |
| json | string | sql.NullString |

@ -41,12 +41,34 @@ var (
} }
) )
func ConvertDataType(dataBaseType string) (goDataType string, err error) { func ConvertDataType(dataBaseType string, isDefaultNull bool) (string, error) {
tp, ok := commonMysqlDataTypeMap[strings.ToLower(dataBaseType)] tp, ok := commonMysqlDataTypeMap[strings.ToLower(dataBaseType)]
if !ok { if !ok {
err = fmt.Errorf("unexpected database type: %s", dataBaseType) return "", fmt.Errorf("unexpected database type: %s", dataBaseType)
return }
return mayConvertNullType(tp, isDefaultNull), nil
}
func mayConvertNullType(goDataType string, isDefaultNull bool) string {
if !isDefaultNull {
return goDataType
}
switch goDataType {
case "int64":
return "sql.NullInt64"
case "int32":
return "sql.NullInt32"
case "float64":
return "sql.NullFloat64"
case "bool":
return "sql.NullBool"
case "string":
return "sql.NullString"
case "time.Time":
return "sql.NullTime"
default:
return goDataType
} }
goDataType = tp
return
} }

@ -7,14 +7,22 @@ import (
) )
func TestConvertDataType(t *testing.T) { func TestConvertDataType(t *testing.T) {
v, err := ConvertDataType("tinyint") v, err := ConvertDataType("tinyint", false)
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, "int64", v) assert.Equal(t, "int64", v)
v, err = ConvertDataType("timestamp") v, err = ConvertDataType("tinyint", true)
assert.Nil(t, err)
assert.Equal(t, "sql.NullInt64", v)
v, err = ConvertDataType("timestamp", false)
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, "time.Time", v) assert.Equal(t, "time.Time", v)
_, err = ConvertDataType("float32") v, err = ConvertDataType("timestamp", true)
assert.Nil(t, err)
assert.Equal(t, "sql.NullTime", v)
_, err = ConvertDataType("float32", false)
assert.NotNil(t, err) assert.NotNil(t, err)
} }

@ -15,3 +15,12 @@ CREATE TABLE `user` (
UNIQUE KEY `mobile_index` (`mobile`) UNIQUE KEY `mobile_index` (`mobile`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
CREATE TABLE `student` (
`id` bigint NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8mb4_bin NOT NULL DEFAULT '',
`age` tinyint DEFAULT NULL,
`score` float(10,0) DEFAULT NULL,
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

@ -1,15 +0,0 @@
-- 用户表 --
CREATE TABLE `user1` (
`id` bigint(10) NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户名称',
`password` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户密码',
`mobile` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '手机号',
`gender` char(5) COLLATE utf8mb4_general_ci NOT NULL COMMENT '男|女|未公开',
`nickname` varchar(255) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '用户昵称',
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `name_index` (`name`),
UNIQUE KEY `mobile_index` (`mobile`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

@ -9,11 +9,13 @@ type (
conn sqlx.SqlConn conn sqlx.SqlConn
} }
Column struct { Column struct {
Name string `db:"COLUMN_NAME"` Name string `db:"COLUMN_NAME"`
DataType string `db:"DATA_TYPE"` DataType string `db:"DATA_TYPE"`
Key string `db:"COLUMN_KEY"` Key string `db:"COLUMN_KEY"`
Extra string `db:"EXTRA"` Extra string `db:"EXTRA"`
Comment string `db:"COLUMN_COMMENT"` Comment string `db:"COLUMN_COMMENT"`
ColumnDefault interface{} `db:"COLUMN_DEFAULT"`
IsNullAble string `db:"IS_NULLABLE"`
} }
) )
@ -33,7 +35,7 @@ func (m *InformationSchemaModel) GetAllTables(database string) ([]string, error)
} }
func (m *InformationSchemaModel) FindByTableName(db, table string) ([]*Column, error) { func (m *InformationSchemaModel) FindByTableName(db, table string) ([]*Column, error) {
querySql := `select COLUMN_NAME,DATA_TYPE,COLUMN_KEY,EXTRA,COLUMN_COMMENT from COLUMNS where TABLE_SCHEMA = ? and TABLE_NAME = ?` querySql := `select COLUMN_NAME,COLUMN_DEFAULT,IS_NULLABLE,DATA_TYPE,COLUMN_KEY,EXTRA,COLUMN_COMMENT from COLUMNS where TABLE_SCHEMA = ? and TABLE_NAME = ?`
var reply []*Column var reply []*Column
err := m.conn.QueryRows(&reply, querySql, db, table) err := m.conn.QueryRows(&reply, querySql, db, table)
return reply, err return reply, err

@ -112,7 +112,17 @@ func Parse(ddl string) (*Table, error) {
if column.Type.Comment != nil { if column.Type.Comment != nil {
comment = string(column.Type.Comment.Val) comment = string(column.Type.Comment.Val)
} }
dataType, err := converter.ConvertDataType(column.Type.Type) var isDefaultNull = true
if column.Type.NotNull {
isDefaultNull = false
} else {
if column.Type.Default == nil {
isDefaultNull = false
} else if string(column.Type.Default.Val) != "null" {
isDefaultNull = false
}
}
dataType, err := converter.ConvertDataType(column.Type.Type, isDefaultNull)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -170,7 +180,8 @@ func ConvertColumn(db, table string, in []*model.Column) (*Table, error) {
} }
primaryColumn := primaryColumns[0] primaryColumn := primaryColumns[0]
primaryFt, err := converter.ConvertDataType(primaryColumn.DataType) isDefaultNull := primaryColumn.ColumnDefault == nil && primaryColumn.IsNullAble == "YES"
primaryFt, err := converter.ConvertDataType(primaryColumn.DataType, isDefaultNull)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -189,7 +200,8 @@ func ConvertColumn(db, table string, in []*model.Column) (*Table, error) {
} }
for key, columns := range keyMap { for key, columns := range keyMap {
for _, item := range columns { for _, item := range columns {
dt, err := converter.ConvertDataType(item.DataType) isColumnDefaultNull := item.ColumnDefault == nil && item.IsNullAble == "YES"
dt, err := converter.ConvertDataType(item.DataType, isColumnDefaultNull)
if err != nil { if err != nil {
return nil, err return nil, err
} }

@ -79,6 +79,7 @@ func TestConvertColumn(t *testing.T) {
for _, item := range table.Fields { for _, item := range table.Fields {
if item.Name.Source() == "mobile" { if item.Name.Source() == "mobile" {
assert.True(t, item.IsUniqueKey) assert.True(t, item.IsUniqueKey)
break
} }
} }
} }

Loading…
Cancel
Save