Files
mayfly-go/server/internal/db/dbm/dbi/metadata.go

216 lines
7.0 KiB
Go
Raw Normal View History

2024-03-11 20:04:20 +08:00
package dbi
import (
"embed"
2024-03-18 12:25:40 +08:00
"fmt"
2024-03-11 20:04:20 +08:00
"mayfly-go/pkg/biz"
"mayfly-go/pkg/utils/collx"
"mayfly-go/pkg/utils/stringx"
"strings"
)
// 元数据接口(表、列、等元信息)
type MetaData interface {
2024-03-15 13:31:53 +08:00
BaseMetaData
2024-03-11 20:04:20 +08:00
// 获取数据库服务实例信息
GetDbServer() (*DbServer, error)
// 获取数据库名称列表
GetDbNames() ([]string, error)
// 获取表信息
GetTables(tableNames ...string) ([]Table, error)
2024-03-11 20:04:20 +08:00
// 获取指定表名的所有列元信息
GetColumns(tableNames ...string) ([]Column, error)
// 根据数据库类型修复字段长度、精度等
2024-03-26 21:46:03 +08:00
// FixColumn(column *Column)
2024-03-11 20:04:20 +08:00
// 获取表主键字段名,没有主键标识则默认第一个字段
GetPrimaryKey(tableName string) (string, error)
// 获取表索引信息
GetTableIndex(tableName string) ([]Index, error)
// 获取建表ddl
GetTableDDL(tableName string, dropBeforeCreate bool) (string, error)
2024-03-11 20:04:20 +08:00
GenerateTableDDL(columns []Column, tableInfo Table, dropBeforeCreate bool) []string
GenerateIndexDDL(indexs []Index, tableInfo Table) []string
2024-03-11 20:04:20 +08:00
GetSchemas() ([]string, error)
2024-03-15 13:31:53 +08:00
2024-03-26 21:46:03 +08:00
// 获取数据处理助手 用于解析格式化列数据等
GetDataHelper() DataHelper
2024-03-11 20:04:20 +08:00
}
// GenerateSQLStepFunc 生成insert sql的step函数用于生成insert sql时每生成100条sql时调用
type GenerateSQLStepFunc func(sqlArr []string)
2024-03-11 20:04:20 +08:00
// 数据库服务实例信息
type DbServer struct {
Version string `json:"version"` // 版本信息
Extra collx.M `json:"extra"` // 其他额外信息
}
// 表信息
type Table struct {
TableName string `json:"tableName"` // 表名
TableComment string `json:"tableComment"` // 表备注
CreateTime string `json:"createTime"` // 创建时间
TableRows int `json:"tableRows"`
DataLength int64 `json:"dataLength"`
IndexLength int64 `json:"indexLength"`
}
// 表的列信息
type Column struct {
2024-03-18 12:25:40 +08:00
TableName string `json:"tableName"` // 表名
ColumnName string `json:"columnName"` // 列名
DataType ColumnDataType `json:"dataType"` // 数据类型
ColumnComment string `json:"columnComment"` // 列备注
IsPrimaryKey bool `json:"isPrimaryKey"` // 是否为主键
IsIdentity bool `json:"isIdentity"` // 是否自增
ColumnDefault string `json:"columnDefault"` // 默认值
2024-03-21 20:28:24 +08:00
Nullable bool `json:"nullable"` // 是否可为null
2024-03-18 12:25:40 +08:00
CharMaxLength int `json:"charMaxLength"` // 字符最大长度
NumPrecision int `json:"numPrecision"` // 精度(总数字位数)
NumScale int `json:"numScale"` // 小数点位数
Extra collx.M `json:"extra"` // 其他额外信息
}
2024-03-21 17:15:52 +08:00
// 拼接数据类型与长度等。如varchar(2000)decimal(20,2)
func (c *Column) GetColumnType() string {
2024-05-31 21:02:31 +08:00
// 哪些mysql数据类型不需要添加字段长度
if collx.ArrayAnyMatches([]string{"int", "blob", "float", "double", "date", "year", "json"}, string(c.DataType)) {
return string(c.DataType)
}
if c.DataType == "timestamp" {
return "timestamp(6)"
}
2024-03-18 12:25:40 +08:00
if c.CharMaxLength > 0 {
2024-03-21 17:15:52 +08:00
return fmt.Sprintf("%s(%d)", c.DataType, c.CharMaxLength)
2024-03-18 12:25:40 +08:00
}
if c.NumPrecision > 0 {
if c.NumScale > 0 {
2024-03-21 17:15:52 +08:00
return fmt.Sprintf("%s(%d,%d)", c.DataType, c.NumPrecision, c.NumScale)
} else {
2024-03-21 17:15:52 +08:00
return fmt.Sprintf("%s(%d)", c.DataType, c.NumPrecision)
}
2024-03-18 12:25:40 +08:00
}
2024-03-21 17:15:52 +08:00
return string(c.DataType)
2024-03-11 20:04:20 +08:00
}
// 表索引信息
type Index struct {
IndexName string `json:"indexName"` // 索引名
ColumnName string `json:"columnName"` // 列名
IndexType string `json:"indexType"` // 索引类型
IndexComment string `json:"indexComment"` // 备注
SeqInIndex int `json:"seqInIndex"`
IsUnique bool `json:"isUnique"`
IsPrimaryKey bool `json:"isPrimaryKey"` // 是否是主键索引,某些情况需要判断并过滤掉主键索引
2024-03-11 20:04:20 +08:00
}
2024-03-18 12:25:40 +08:00
type ColumnDataType string
const (
CommonTypeVarchar ColumnDataType = "varchar"
CommonTypeChar ColumnDataType = "char"
CommonTypeText ColumnDataType = "text"
CommonTypeBlob ColumnDataType = "blob"
CommonTypeLongblob ColumnDataType = "longblob"
CommonTypeLongtext ColumnDataType = "longtext"
CommonTypeBinary ColumnDataType = "binary"
CommonTypeMediumblob ColumnDataType = "mediumblob"
CommonTypeMediumtext ColumnDataType = "mediumtext"
CommonTypeVarbinary ColumnDataType = "varbinary"
CommonTypeInt ColumnDataType = "int"
2024-05-31 21:02:31 +08:00
CommonTypeBit ColumnDataType = "bit"
2024-03-18 12:25:40 +08:00
CommonTypeSmallint ColumnDataType = "smallint"
CommonTypeTinyint ColumnDataType = "tinyint"
CommonTypeNumber ColumnDataType = "number"
CommonTypeBigint ColumnDataType = "bigint"
CommonTypeDatetime ColumnDataType = "datetime"
CommonTypeDate ColumnDataType = "date"
CommonTypeTime ColumnDataType = "time"
CommonTypeTimestamp ColumnDataType = "timestamp"
CommonTypeEnum ColumnDataType = "enum"
CommonTypeJSON ColumnDataType = "json"
)
2024-03-15 13:31:53 +08:00
type DataType string
const (
DataTypeString DataType = "string"
DataTypeNumber DataType = "number"
DataTypeDate DataType = "date"
DataTypeTime DataType = "time"
DataTypeDateTime DataType = "datetime"
2024-05-31 21:02:31 +08:00
DataTypeBlob DataType = "blob"
2024-03-15 13:31:53 +08:00
)
2024-03-26 21:46:03 +08:00
// 列数据处理帮助方法
type DataHelper interface {
2024-03-15 13:31:53 +08:00
// 获取数据对应的类型
// @param dbColumnType 数据库原始列类型如varchar等
GetDataType(dbColumnType string) DataType
// 根据数据类型格式化指定数据
FormatData(dbColumnValue any, dataType DataType) string
// 根据数据类型解析数据为符合要求的指定类型等
ParseData(dbColumnValue any, dataType DataType) any
// WrapValue 根据数据类型包装value
// 1.数字型:不需要引号,
// 2.文本型:需要用引号包裹,单引号需要转义,换行符转义,
// 3.date型需要格式化成对应的字符串timehh:mm:ss.SSS date: yyyy-mm-dd datetime:
// 4.特殊oracle date型需要用函数包裹to_timestamp('%s', 'yyyy-mm-dd hh24:mi:ss')
WrapValue(dbColumnValue any, dataType DataType) string
2024-03-15 13:31:53 +08:00
}
2024-03-11 20:04:20 +08:00
// ------------------------- 元数据sql操作 -------------------------
//
//go:embed metasql/*
var metasql embed.FS
// sql缓存 key: sql备注的key 如MYSQL_TABLE_MA value: sql内容
var sqlCache = make(map[string]string, 20)
// 获取本地文件的sql内容并进行解析获取对应key的sql内容
func GetLocalSql(file, key string) string {
sql := sqlCache[key]
if sql != "" {
return sql
}
bytes, err := metasql.ReadFile(file)
biz.ErrIsNilAppendErr(err, "获取sql meta文件内容失败: %s")
allSql := string(bytes)
sqls := strings.Split(allSql, "---------------------------------------")
var resSql string
for _, sql := range sqls {
sql = stringx.TrimSpaceAndBr(sql)
// 获取sql第一行的sql备注信息如--MYSQL_TABLE_MA 表信息元数据
info := strings.SplitN(sql, "\n", 2)
// 原始sql即去除第一行的key与备注信息
rowSql := info[1]
// 获取sql keyMYSQL_TABLE_MA
sqlKey := strings.Split(strings.Split(info[0], " ")[0], "--")[1]
if key == sqlKey {
resSql = rowSql
}
sqlCache[sqlKey] = rowSql
}
return resSql
}