improve data type conversion (#236)
* improve data type conversion * update doc
This commit is contained in:
@@ -78,8 +78,8 @@ goctl model 为go-zero下的工具模块中的组件之一,目前支持识别m
|
||||
Password string `db:"password"` // 用户密码
|
||||
Mobile string `db:"mobile"` // 手机号
|
||||
Gender string `db:"gender"` // 男|女|未公开
|
||||
Nickname string `db:"nickname"` // 用户昵称
|
||||
CreateTime time.Time `db:"create_time"`
|
||||
Nickname sql.NullString `db:"nickname"` // 用户昵称
|
||||
CreateTime sql.NullTime `db:"create_time"`
|
||||
UpdateTime time.Time `db:"update_time"`
|
||||
}
|
||||
)
|
||||
@@ -347,3 +347,33 @@ OPTIONS:
|
||||
|
||||
目前,我认为除了基本的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)]
|
||||
if !ok {
|
||||
err = fmt.Errorf("unexpected database type: %s", dataBaseType)
|
||||
return
|
||||
return "", fmt.Errorf("unexpected database type: %s", dataBaseType)
|
||||
}
|
||||
|
||||
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) {
|
||||
v, err := ConvertDataType("tinyint")
|
||||
v, err := ConvertDataType("tinyint", false)
|
||||
assert.Nil(t, err)
|
||||
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.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)
|
||||
}
|
||||
|
||||
@@ -15,3 +15,12 @@ CREATE TABLE `user` (
|
||||
UNIQUE KEY `mobile_index` (`mobile`)
|
||||
) 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
|
||||
}
|
||||
Column struct {
|
||||
Name string `db:"COLUMN_NAME"`
|
||||
DataType string `db:"DATA_TYPE"`
|
||||
Key string `db:"COLUMN_KEY"`
|
||||
Extra string `db:"EXTRA"`
|
||||
Comment string `db:"COLUMN_COMMENT"`
|
||||
Name string `db:"COLUMN_NAME"`
|
||||
DataType string `db:"DATA_TYPE"`
|
||||
Key string `db:"COLUMN_KEY"`
|
||||
Extra string `db:"EXTRA"`
|
||||
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) {
|
||||
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
|
||||
err := m.conn.QueryRows(&reply, querySql, db, table)
|
||||
return reply, err
|
||||
|
||||
@@ -112,7 +112,17 @@ func Parse(ddl string) (*Table, error) {
|
||||
if column.Type.Comment != nil {
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
@@ -170,7 +180,8 @@ func ConvertColumn(db, table string, in []*model.Column) (*Table, error) {
|
||||
}
|
||||
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
@@ -189,7 +200,8 @@ func ConvertColumn(db, table string, in []*model.Column) (*Table, error) {
|
||||
}
|
||||
for key, columns := range keyMap {
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -79,6 +79,7 @@ func TestConvertColumn(t *testing.T) {
|
||||
for _, item := range table.Fields {
|
||||
if item.Name.Source() == "mobile" {
|
||||
assert.True(t, item.IsUniqueKey)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user