mirror of
https://github.com/gohouse/gorose.git
synced 2025-09-27 04:06:06 +08:00
189 lines
4.7 KiB
Go
189 lines
4.7 KiB
Go
package parser
|
|
|
|
import (
|
|
"database/sql/driver"
|
|
"reflect"
|
|
"slices"
|
|
"strings"
|
|
)
|
|
|
|
func StructsToTableName(rft reflect.Type) (tab string) {
|
|
if field, ok := rft.FieldByName("TableName"); ok {
|
|
if field.Tag.Get("db") != "" {
|
|
tab = field.Tag.Get("db")
|
|
}
|
|
}
|
|
if tab == "" {
|
|
if tn := reflect.New(rft).Elem().MethodByName("TableName"); tn.IsValid() {
|
|
tab = tn.Call(nil)[0].String()
|
|
}
|
|
}
|
|
if tab == "" {
|
|
tab = rft.Name()
|
|
}
|
|
return
|
|
}
|
|
|
|
func StructsParse(obj any) (FieldTag []string, FieldStruct []string, pkField string) {
|
|
rfv := reflect.Indirect(reflect.ValueOf(obj))
|
|
switch rfv.Kind() {
|
|
case reflect.Struct:
|
|
return StructsTypeParse(rfv.Type())
|
|
case reflect.Slice:
|
|
return StructsTypeParse(rfv.Type())
|
|
default:
|
|
return
|
|
}
|
|
}
|
|
|
|
func StructsTypeParse(rft reflect.Type) (fieldTag []string, fieldStruct []string, pkField string) {
|
|
//rfv := reflect.Indirect(reflect.ValueOf(obj))
|
|
if rft.Kind() == reflect.Slice {
|
|
rft2 := rft.Elem()
|
|
if rft2.Kind() == reflect.Struct {
|
|
return StructsTypeParse(rft2)
|
|
}
|
|
} else {
|
|
for i := 0; i < rft.NumField(); i++ {
|
|
field := rft.Field(i)
|
|
if field.Anonymous {
|
|
continue
|
|
}
|
|
tag := field.Tag.Get("db")
|
|
if tag == "-" || field.Name == "TableName" {
|
|
continue
|
|
}
|
|
if tag == "" {
|
|
//field.Tag = reflect.StructTag("db:" + field.Name)
|
|
fieldStruct = append(fieldStruct, field.Name)
|
|
tag = field.Name
|
|
} else {
|
|
if strings.Contains(tag, ",") {
|
|
tags := strings.Split(tag, ",")
|
|
if slices.Contains(tags, "pk") {
|
|
pkField = field.Name
|
|
tag = tags[0]
|
|
}
|
|
}
|
|
fieldStruct = append(fieldStruct, field.Name)
|
|
}
|
|
//else {
|
|
// fieldStruct = append(fieldStruct, field.Tag.Get("db"))
|
|
//}
|
|
//if field.Tag.Get("pkField") == "true" {
|
|
// pkField = field.Name
|
|
// pkValue = rfv.FieldByName(field.Name)
|
|
//}
|
|
fieldTag = append(fieldTag, tag)
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
//func StructsToSelects(obj any) []string {
|
|
// tag, fieldStruct, _ := StructsParse(obj)
|
|
// if len(tag) > 0 {
|
|
// return tag
|
|
// } else {
|
|
// return fieldStruct
|
|
// }
|
|
//}
|
|
|
|
func StructDataToMap(rfv reflect.Value, tags, fieldStruct []string, mustColumn ...string) (data map[string]any, err error) {
|
|
data = make(map[string]any)
|
|
for i, fieldName := range fieldStruct {
|
|
field := rfv.FieldByName(fieldName)
|
|
if (field.Kind() == reflect.Ptr && field.IsNil()) || (field.IsZero() && !slices.Contains(mustColumn, tags[i])) {
|
|
continue
|
|
}
|
|
var rfvVal = field.Interface()
|
|
if v, ok := rfvVal.(driver.Valuer); ok {
|
|
var value driver.Value
|
|
value, err = v.Value()
|
|
if err != nil {
|
|
return
|
|
}
|
|
data[tags[i]] = value
|
|
} else {
|
|
data[tags[i]] = rfvVal
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func structUpdateDataToMap(rfv reflect.Value, tags, fieldStruct []string, pkField string, mustColumn ...string) (data map[string]any, err error) {
|
|
data = make(map[string]any)
|
|
for i, fieldName := range fieldStruct {
|
|
field := rfv.FieldByName(fieldName)
|
|
if (field.Kind() == reflect.Ptr && field.IsNil()) || (field.IsZero() && !slices.Contains(mustColumn, tags[i])) || fieldName == pkField {
|
|
continue
|
|
}
|
|
var rfvVal = field.Interface()
|
|
if v, ok := rfvVal.(driver.Valuer); ok {
|
|
var value driver.Value
|
|
value, err = v.Value()
|
|
if err != nil {
|
|
return
|
|
}
|
|
data[tags[i]] = value
|
|
} else {
|
|
data[tags[i]] = rfvVal
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func StructToDelete(obj any, mustColumn ...string) (data map[string]any, err error) {
|
|
rfv := reflect.Indirect(reflect.ValueOf(obj))
|
|
if rfv.Kind() == reflect.Struct {
|
|
tag, fieldStruct, _ := StructsTypeParse(rfv.Type())
|
|
data, err = StructDataToMap(rfv, tag, fieldStruct, mustColumn...)
|
|
}
|
|
return
|
|
}
|
|
|
|
func StructsToInsert(obj any, mustColumn ...string) (datas []map[string]any, err error) {
|
|
rfv := reflect.Indirect(reflect.ValueOf(obj))
|
|
switch rfv.Kind() {
|
|
case reflect.Struct:
|
|
fieldTag, fieldStruct, _ := StructsTypeParse(rfv.Type())
|
|
var data = make(map[string]any)
|
|
data, err = StructDataToMap(rfv, fieldTag, fieldStruct, mustColumn...)
|
|
if err != nil {
|
|
return
|
|
}
|
|
datas = append(datas, data)
|
|
case reflect.Slice:
|
|
tag, fieldStruct, _ := StructsTypeParse(rfv.Type())
|
|
for i := 0; i < rfv.Len(); i++ {
|
|
var data = make(map[string]any)
|
|
data, err = StructDataToMap(rfv.Index(i), tag, fieldStruct, mustColumn...)
|
|
if err != nil {
|
|
return
|
|
}
|
|
datas = append(datas, data)
|
|
}
|
|
default:
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
func StructToUpdate(obj any, mustColumn ...string) (data map[string]any, pkTag string, pkValue any, err error) {
|
|
tag, fieldStruct, pkField := StructsParse(obj)
|
|
if len(tag) > 0 {
|
|
data = make(map[string]any)
|
|
rfv := reflect.Indirect(reflect.ValueOf(obj))
|
|
data, err = structUpdateDataToMap(rfv, tag, fieldStruct, pkField, mustColumn...)
|
|
if err != nil {
|
|
return
|
|
}
|
|
if pkField != "" {
|
|
pkTag = tag[slices.Index(fieldStruct, pkField)]
|
|
pkValue = rfv.FieldByName(pkField).Interface()
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|