mirror of
https://gitee.com/dromara/mayfly-go
synced 2025-11-14 13:20:25 +08:00
215 lines
5.9 KiB
Go
215 lines
5.9 KiB
Go
package mysql
|
||
|
||
import (
|
||
"errors"
|
||
"fmt"
|
||
"mayfly-go/internal/db/dbm/dbi"
|
||
"mayfly-go/pkg/errorx"
|
||
"mayfly-go/pkg/logx"
|
||
"mayfly-go/pkg/utils/collx"
|
||
"mayfly-go/pkg/utils/stringx"
|
||
"strings"
|
||
|
||
"github.com/may-fly/cast"
|
||
)
|
||
|
||
const (
|
||
MYSQL_META_FILE = "metasql/mysql_meta.sql"
|
||
MYSQL_DBS = "MYSQL_DBS"
|
||
MYSQL_TABLE_INFO_KEY = "MYSQL_TABLE_INFO"
|
||
MYSQL_INDEX_INFO_KEY = "MYSQL_INDEX_INFO"
|
||
MYSQL_COLUMN_MA_KEY = "MYSQL_COLUMN_MA"
|
||
)
|
||
|
||
type MysqlMetadata struct {
|
||
dbi.DefaultMetadata
|
||
|
||
dc *dbi.DbConn
|
||
}
|
||
|
||
func (md *MysqlMetadata) GetDbServer() (*dbi.DbServer, error) {
|
||
_, res, err := md.dc.Query("SELECT VERSION() version")
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
ds := &dbi.DbServer{
|
||
Version: cast.ToString(res[0]["version"]),
|
||
}
|
||
return ds, nil
|
||
}
|
||
|
||
func (md *MysqlMetadata) GetDbNames() ([]string, error) {
|
||
_, res, err := md.dc.Query(dbi.GetLocalSql(MYSQL_META_FILE, MYSQL_DBS))
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
databases := make([]string, 0)
|
||
for _, re := range res {
|
||
databases = append(databases, cast.ToString(re["dbname"]))
|
||
}
|
||
return databases, nil
|
||
}
|
||
|
||
func (md *MysqlMetadata) GetTables(tableNames ...string) ([]dbi.Table, error) {
|
||
dialect := md.dc.GetDialect()
|
||
names := strings.Join(collx.ArrayMap[string, string](tableNames, func(val string) string {
|
||
return fmt.Sprintf("'%s'", dialect.RemoveQuote(val))
|
||
}), ",")
|
||
|
||
var res []map[string]any
|
||
var err error
|
||
|
||
sql, err := stringx.TemplateParse(dbi.GetLocalSql(MYSQL_META_FILE, MYSQL_TABLE_INFO_KEY), collx.M{"tableNames": names})
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
_, res, err = md.dc.Query(sql)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
tables := make([]dbi.Table, 0)
|
||
for _, re := range res {
|
||
tables = append(tables, dbi.Table{
|
||
TableName: cast.ToString(re["tableName"]),
|
||
TableComment: cast.ToString(re["tableComment"]),
|
||
CreateTime: cast.ToString(re["createTime"]),
|
||
TableRows: cast.ToInt(re["tableRows"]),
|
||
DataLength: cast.ToInt64(re["dataLength"]),
|
||
IndexLength: cast.ToInt64(re["indexLength"]),
|
||
})
|
||
}
|
||
return tables, nil
|
||
}
|
||
|
||
// 获å<C2B7>–列元信æ<C2A1>¯, 如列å<E28094><C3A5>ç‰
|
||
func (md *MysqlMetadata) GetColumns(tableNames ...string) ([]dbi.Column, error) {
|
||
dialect := md.dc.GetDialect()
|
||
columnHelper := dialect.GetColumnHelper()
|
||
tableName := strings.Join(collx.ArrayMap[string, string](tableNames, func(val string) string {
|
||
return fmt.Sprintf("'%s'", dialect.RemoveQuote(val))
|
||
}), ",")
|
||
|
||
_, res, err := md.dc.Query(fmt.Sprintf(dbi.GetLocalSql(MYSQL_META_FILE, MYSQL_COLUMN_MA_KEY), tableName))
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
columns := make([]dbi.Column, 0)
|
||
for _, re := range res {
|
||
|
||
column := dbi.Column{
|
||
TableName: cast.ToString(re["tableName"]),
|
||
ColumnName: cast.ToString(re["columnName"]),
|
||
DataType: dbi.ColumnDataType(cast.ToString(re["dataType"])),
|
||
ColumnComment: cast.ToString(re["columnComment"]),
|
||
Nullable: cast.ToString(re["nullable"]) == "YES",
|
||
IsPrimaryKey: cast.ToInt(re["isPrimaryKey"]) == 1,
|
||
IsIdentity: cast.ToInt(re["isIdentity"]) == 1,
|
||
ColumnDefault: cast.ToString(re["columnDefault"]),
|
||
CharMaxLength: cast.ToInt(re["charMaxLength"]),
|
||
NumPrecision: cast.ToInt(re["numPrecision"]),
|
||
NumScale: cast.ToInt(re["numScale"]),
|
||
}
|
||
|
||
columnHelper.FixColumn(&column)
|
||
columns = append(columns, column)
|
||
}
|
||
return columns, nil
|
||
}
|
||
|
||
// 获å<C2B7>–è¡¨ä¸»é”®å—æ®µå<C2B5><C3A5>,ä¸<C3A4>å˜åœ¨ä¸»é”®æ ‡è¯†åˆ™é»˜è®¤ç¬¬ä¸€ä¸ªå—段
|
||
func (md *MysqlMetadata) GetPrimaryKey(tablename string) (string, error) {
|
||
columns, err := md.GetColumns(tablename)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
if len(columns) == 0 {
|
||
return "", errorx.NewBiz("[%s] 表ä¸<C3A4>å˜åœ¨", tablename)
|
||
}
|
||
|
||
for _, v := range columns {
|
||
if v.IsPrimaryKey {
|
||
return v.ColumnName, nil
|
||
}
|
||
}
|
||
|
||
return columns[0].ColumnName, nil
|
||
}
|
||
|
||
// 获å<C2B7>–表索引信æ<C2A1>¯
|
||
func (md *MysqlMetadata) GetTableIndex(tableName string) ([]dbi.Index, error) {
|
||
_, res, err := md.dc.Query(dbi.GetLocalSql(MYSQL_META_FILE, MYSQL_INDEX_INFO_KEY), tableName)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
indexs := make([]dbi.Index, 0)
|
||
for _, re := range res {
|
||
indexs = append(indexs, dbi.Index{
|
||
IndexName: cast.ToString(re["indexName"]),
|
||
ColumnName: cast.ToString(re["columnName"]),
|
||
IndexType: cast.ToString(re["indexType"]),
|
||
IndexComment: cast.ToString(re["indexComment"]),
|
||
IsUnique: cast.ToInt(re["isUnique"]) == 1,
|
||
SeqInIndex: cast.ToInt(re["seqInIndex"]),
|
||
IsPrimaryKey: cast.ToInt(re["isPrimaryKey"]) == 1,
|
||
})
|
||
}
|
||
// 把查询结果以索引å<E280A2><C3A5>åˆ†ç»„ï¼Œç´¢å¼•å—æ®µä»¥é€—å<E28094>·è¿žæŽ¥
|
||
result := make([]dbi.Index, 0)
|
||
key := ""
|
||
for _, v := range indexs {
|
||
// 当å‰<C3A5>的索引å<E280A2><C3A5>
|
||
in := v.IndexName
|
||
if key == in {
|
||
// ç´¢å¼•å—æ®µå·²æ ¹æ<C2B9>®å<C2AE><C3A5>称和顺åº<C3A5>排åº<C3A5>,故å<E280A6>–最å<E282AC>Žä¸€ä¸ªå<C2AA>³å<C2B3>¯
|
||
i := len(result) - 1
|
||
// å<>Œç´¢å¼•å—æ®µä»¥é€—å<E28094>·è¿žæŽ¥
|
||
result[i].ColumnName = result[i].ColumnName + "," + v.ColumnName
|
||
} else {
|
||
key = in
|
||
result = append(result, v)
|
||
}
|
||
}
|
||
return result, nil
|
||
}
|
||
|
||
// 获å<C2B7>–建表ddl
|
||
func (md *MysqlMetadata) GetTableDDL(tableName string, dropBeforeCreate bool) (string, error) {
|
||
// 1.获å<C2B7>–表信æ<C2A1>¯
|
||
tbs, err := md.GetTables(tableName)
|
||
tableInfo := &dbi.Table{}
|
||
if err != nil || tbs == nil || len(tbs) <= 0 {
|
||
logx.Errorf("获å<C2B7>–表信æ<C2A1>¯å¤±è´¥, %s", tableName)
|
||
return "", err
|
||
}
|
||
tableInfo.TableName = tbs[0].TableName
|
||
tableInfo.TableComment = tbs[0].TableComment
|
||
|
||
// 2.获å<C2B7>–列信æ<C2A1>¯
|
||
columns, err := md.GetColumns(tableName)
|
||
if err != nil {
|
||
logx.Errorf("获å<C2B7>–列信æ<C2A1>¯å¤±è´¥, %s", tableName)
|
||
return "", err
|
||
}
|
||
|
||
dialect := md.dc.GetDialect()
|
||
tableDDLArr := dialect.GenerateTableDDL(columns, *tableInfo, dropBeforeCreate)
|
||
// 3.获å<C2B7>–索引信æ<C2A1>¯
|
||
indexs, err := md.GetTableIndex(tableName)
|
||
if err != nil {
|
||
logx.Errorf("获å<C2B7>–索引信æ<C2A1>¯å¤±è´¥, %s", tableName)
|
||
return "", err
|
||
}
|
||
// 组装返回
|
||
tableDDLArr = append(tableDDLArr, dialect.GenerateIndexDDL(indexs, *tableInfo)...)
|
||
return strings.Join(tableDDLArr, ";\n"), nil
|
||
}
|
||
|
||
func (md *MysqlMetadata) GetSchemas() ([]string, error) {
|
||
return nil, errors.New("ä¸<C3A4>支æŒ<C3A6>schema")
|
||
}
|