Files

198 lines
4.9 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
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 xgorm
// @Link https://github.com/xiujiecn/xiu-admin
// @Copyright Copyright (c) 2025 LiXiujie
// @Author Lxj <xxx@example.com>
// @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
package xgorm
import (
"context"
"fmt"
"git.5iot.com/iotlcm-public/iotlcm-openapi/utility"
"slices"
"reflect"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/text/gstr"
)
var (
descTags = []string{"description", "dc", "json"} // 实体描述标签
fieldTags = []string{"json"} // 实体字段名称映射
)
// GetFieldsToSlice 获取dao实例中的所有字段
func GetFieldsToSlice(ctx context.Context, dao daoInstance) ([]string, error) {
fields, err := dao.Ctx(ctx).TableFields(dao.Table())
if err != nil {
return nil, err
}
if len(fields) == 0 {
return nil, gerror.New("field not found")
}
var keys []string
for _, field := range fields {
keys = append(keys, field.Name)
}
return keys, nil
}
// GetPkField 获取dao实例中的主键名称
func GetPkField(ctx context.Context, dao daoInstance) (string, error) {
fields, err := dao.Ctx(ctx).TableFields(dao.Table())
if err != nil {
return "", err
}
if len(fields) == 0 {
return "", gerror.New("field not found")
}
for _, field := range fields {
if field.Key == "PRI" {
return field.Name, nil
}
}
return "", gerror.New("no primary key")
}
// IsUnique 是否唯一
func IsUnique(ctx context.Context, dao daoInstance, where g.Map, message string, pkId ...interface{}) error {
if len(where) == 0 {
return gerror.New("where condition cannot be empty")
}
m := dao.Ctx(ctx).Where(where)
if len(pkId) > 0 {
field, err := GetPkField(ctx, dao)
if err != nil {
return err
}
m = m.WhereNot(field, pkId[0])
}
count, err := m.Count(1)
if err != nil {
return err
}
if count > 0 {
if message == "" {
for k := range where {
message = fmt.Sprintf("in the table:%s, %v not uniqued", dao.Table(), where[k])
break
}
}
return gerror.New(message)
}
return nil
}
func JoinFields(ctx context.Context, entity interface{}, dao daoInstance, as string) (fs string) {
entityFs, err := GetEntityFieldTags(entity)
if err != nil {
g.Log().Errorf(ctx, "JoinFields err: %v", err)
return
}
if len(entityFs) == 0 {
g.Log().Errorf(ctx, "JoinFields entityFs is empty")
return ""
}
fields, err := dao.Ctx(ctx).TableFields(dao.Table())
if err != nil {
g.Log().Errorf(ctx, "JoinFields err: %v", err)
return
}
var columns []string
for _, v := range entityFs {
if !gstr.HasPrefix(v, as) {
g.Log().Infof(ctx, "JoinFields gstr.HasPrefix: %+v, %+v", v, as)
continue
}
g.Log().Infof(ctx, "JoinFields gstr.HasPrefix2: %+v, %+v", v, as)
field := gstr.CaseSnakeFirstUpper(gstr.StrEx(v, as))
if _, ok := fields[field]; ok {
columns = append(columns, fmt.Sprintf("`%s`.`%s` as `%s`", dao.Table(), field, v))
}
g.Log().Infof(ctx, "JoinFields field: %+v fields: %+v", field, fields)
}
if len(columns) > 0 {
g.Log().Infof(ctx, "JoinFields columns: %+v", columns)
return gstr.Implode(",", utility.UniqueSlice(columns))
}
return
}
// GetEntityFieldTags 获取实体中的字段名称
func GetEntityFieldTags(entity interface{}) (tags []string, err error) {
var formRef = reflect.TypeOf(entity)
for i := 0; i < formRef.NumField(); i++ {
field := formRef.Field(i)
if field.Type.Kind() == reflect.Struct {
addTags, err := reflectTag(field.Type, fieldTags, []string{})
if err != nil {
return nil, err
}
tags = append(tags, addTags...)
continue
}
tags = append(tags, reflectTagName(field, fieldTags, true))
}
return
}
// reflectTag 层级递增解析tag
func reflectTag(reflectType reflect.Type, filterTags []string, tags []string) ([]string, error) {
if reflectType.Kind() == reflect.Ptr {
return nil, gerror.Newf("reflect type do not support reflect.Ptr yet, reflectType:%+v", reflectType)
}
if reflectType.Kind() != reflect.Struct {
return nil, nil
}
for i := 0; i < reflectType.NumField(); i++ {
tag := reflectTagName(reflectType.Field(i), filterTags, false)
if tag == "" {
addTags, err := reflectTag(reflectType.Field(i).Type, filterTags, tags)
if err != nil {
return nil, err
}
tags = append(tags, addTags...)
continue
}
tags = append(tags, tag)
}
return tags, nil
}
// reflectTagName 解析实体中的描述标签,优先级:description > dc > json > Name
func reflectTagName(field reflect.StructField, filterTags []string, isDef bool) string {
if slices.Contains(filterTags, "description") {
if description, ok := field.Tag.Lookup("description"); ok && description != "" {
return description
}
}
if slices.Contains(filterTags, "dc") {
if dc, ok := field.Tag.Lookup("dc"); ok && dc != "" {
return dc
}
}
if slices.Contains(filterTags, "json") {
if jsonName, ok := field.Tag.Lookup("json"); ok && jsonName != "" {
return jsonName
}
}
if !isDef {
return ""
}
return field.Name
}