Files
mayfly-go/server/internal/db/dbm/mysql/metadata.go
2024-11-01 17:27:22 +08:00

215 lines
5.9 KiB
Go
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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")
}