256 lines
6.5 KiB
Go
256 lines
6.5 KiB
Go
package models
|
|
|
|
import (
|
|
"fmt"
|
|
"gorm.io/gorm"
|
|
"nCovTrack-Backend/global"
|
|
"reflect"
|
|
"regexp"
|
|
"time"
|
|
)
|
|
|
|
var colNameReg, _ = regexp.Compile(".*column:(.*);?")
|
|
var j2cMap = make(map[string]map[string]string)
|
|
var c2jMap = make(map[string]map[string]string)
|
|
|
|
const IS_DELETE = "is_delete"
|
|
|
|
// initJcMap the gorm models need to call this function in init function
|
|
func initJcMap[T any]() {
|
|
t := reflect.TypeOf(new(T)).Elem()
|
|
tJ2cMap, tC2jMap := make(map[string]string), make(map[string]string)
|
|
for i := 0; i < t.NumField(); i++ {
|
|
colName := columnName(t.Field(i).Tag.Get("gorm"))
|
|
// TODO: Deal with (-)
|
|
jsonName := t.Field(i).Tag.Get("json")
|
|
if colName == "" || jsonName == "" {
|
|
continue
|
|
}
|
|
tJ2cMap[jsonName] = colName
|
|
tC2jMap[colName] = jsonName
|
|
}
|
|
j2cMap[t.Name()] = tJ2cMap
|
|
c2jMap[t.Name()] = tC2jMap
|
|
}
|
|
|
|
// columnName get the mysql column name of the tag
|
|
func columnName(gormTag string) string {
|
|
colNames := colNameReg.FindSubmatch([]byte(gormTag))
|
|
if len(colNames) != 2 {
|
|
panic("Model tag regex error")
|
|
}
|
|
return string(colNames[1])
|
|
}
|
|
|
|
// MapJ2c convert jsonMap to colMap, which will used by gorm
|
|
func MapJ2c[T any](jsonMap map[string]interface{}, ignoreNil bool) (colMap map[string]interface{}) {
|
|
tName := reflect.TypeOf(new(T)).Elem().Name()
|
|
tJ2cMap := j2cMap[tName]
|
|
if tJ2cMap == nil {
|
|
panic(tName + " is not init registered int j2cMap")
|
|
}
|
|
|
|
colMap = make(map[string]interface{})
|
|
for k, v := range jsonMap {
|
|
//TODO 无法转换
|
|
if colName := tJ2cMap[k]; colName != "" && (!ignoreNil || v != nil) {
|
|
colMap[colName] = v
|
|
}
|
|
}
|
|
return colMap
|
|
}
|
|
|
|
func MapsJ2c[T any](jsonMaps []map[string]interface{}, ignoreNil bool) (colMaps []map[string]interface{}) {
|
|
for _, jsonMap := range jsonMaps {
|
|
colMap := MapJ2c[T](jsonMap, ignoreNil)
|
|
colMaps = append(colMaps, colMap)
|
|
}
|
|
return colMaps
|
|
}
|
|
|
|
func MapC2j[T any](colMap map[string]interface{}, ignoreNil bool) (jsonMap map[string]interface{}) {
|
|
tName := reflect.TypeOf(new(T)).Elem().Name()
|
|
tC2jMap := c2jMap[tName]
|
|
if tC2jMap == nil {
|
|
panic(tName + " is not init registered int j2cMap")
|
|
}
|
|
|
|
jsonMap = make(map[string]interface{})
|
|
for k, v := range colMap {
|
|
//TODO 无法转换
|
|
if jsonKey := tC2jMap[k]; jsonKey != "" && (!ignoreNil || v != nil) {
|
|
jsonMap[jsonKey] = v
|
|
}
|
|
}
|
|
return jsonMap
|
|
}
|
|
|
|
func MapsC2j[T any](jsonMaps []map[string]interface{}, ignoreNil bool) (colMaps []map[string]interface{}) {
|
|
for _, jsonMap := range jsonMaps {
|
|
colMap := MapC2j[T](jsonMap, ignoreNil)
|
|
colMaps = append(colMaps, colMap)
|
|
}
|
|
return colMaps
|
|
}
|
|
|
|
// BeforeSave need to set some field while insert or update
|
|
func BeforeSave(colMap map[string]interface{}, user int) {
|
|
if colMap["id"] == nil || int(colMap["id"].(float64)) == 0 {
|
|
colMap["create_time"] = time.Now()
|
|
if user != -1 {
|
|
colMap["create_user"] = user
|
|
} else {
|
|
colMap["create_user"] = 0
|
|
}
|
|
}
|
|
colMap["modify_time"] = time.Now()
|
|
if user != -1 {
|
|
colMap["modify_user"] = user
|
|
} else {
|
|
colMap["modify_user"] = 0
|
|
}
|
|
}
|
|
|
|
func BeforeBatchSave(colMaps *[]map[string]interface{}, user int) {
|
|
for _, colMap := range *colMaps {
|
|
BeforeSave(colMap, user)
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------<Gorm functions>-----------------------------------------------------------*/
|
|
// Due to gorm can't deal with the zero value, so we use gorm with map.
|
|
// The generic will make the function is generally used to gorm models
|
|
// TODO: add uniqueKey map, which can be used when Upsert
|
|
|
|
func Upsert[T any](colMap map[string]interface{}) (ok bool, rowsAffected int64) {
|
|
var tx *gorm.DB
|
|
if colMap["id"] == nil || int(colMap["id"].(float64)) == 0 {
|
|
tx = global.Db.Model(new(T)).Create(colMap)
|
|
} else {
|
|
tx = global.Db.Model(new(T)).Where("id = ?", colMap["id"]).Updates(colMap)
|
|
}
|
|
if tx.Error != nil {
|
|
fmt.Println(tx.Error)
|
|
return false, 0
|
|
}
|
|
return true, tx.RowsAffected
|
|
}
|
|
|
|
func BatchInsert[T any](colMaps []map[string]interface{}) (ok bool, rowsAffected int64) {
|
|
tx := global.Db.Model(new(T)).Create(&colMaps)
|
|
if tx.Error != nil {
|
|
fmt.Println(tx.Error)
|
|
return false, 0
|
|
}
|
|
return true, tx.RowsAffected
|
|
}
|
|
|
|
func Update[T any](queryMap []map[string]interface{}, updateMap map[string]interface{}) (ok bool, rowsAffected int64) {
|
|
tx := global.Db.Model(new(T))
|
|
for _, e := range queryMap {
|
|
e[IS_DELETE] = 0
|
|
tx = tx.Or(e)
|
|
}
|
|
return UpdateByOrm(tx, updateMap)
|
|
}
|
|
|
|
func UpdateByOrm(tx *gorm.DB, updateMap map[string]interface{}) (ok bool, rowsAffected int64) {
|
|
tx.Updates(updateMap)
|
|
if tx.Error != nil {
|
|
fmt.Println(tx.Error)
|
|
return false, 0
|
|
}
|
|
return true, tx.RowsAffected
|
|
}
|
|
|
|
// DeleteById will delete by id, not delete the record from database, only set the field "is_delete" as 1
|
|
func DeleteById[T any](id int) (ok bool, rowsAffected int64) {
|
|
tx := global.Db.Model(new(T)).Where("id = ?", id).Update("is_delete", 1)
|
|
if tx.Error != nil {
|
|
return false, 0
|
|
}
|
|
return true, rowsAffected
|
|
}
|
|
|
|
func DropById[T any](id int) {
|
|
global.Db.Model(new(T)).Delete("id = ?", id)
|
|
}
|
|
|
|
func List[T any](queryMap []map[string]interface{}) *[]map[string]interface{} {
|
|
tx := global.Db.Model(new(T))
|
|
for _, e := range queryMap {
|
|
e[IS_DELETE] = 0
|
|
tx = tx.Or(e)
|
|
}
|
|
return ListByOrm(tx)
|
|
}
|
|
|
|
func ListField[T any](queryMap []map[string]interface{}, isOmit bool, queryField ...string) *[]map[string]interface{} {
|
|
tx := global.Db.Model(new(T))
|
|
for _, e := range queryMap {
|
|
e[IS_DELETE] = 0
|
|
tx = tx.Or(e)
|
|
}
|
|
if len(queryMap) == 0 {
|
|
return ListByOrm(tx)
|
|
}
|
|
if isOmit {
|
|
tx = tx.Omit(queryField...)
|
|
} else {
|
|
tx = tx.Select(queryField[0], queryField[1:])
|
|
}
|
|
return ListByOrm(tx)
|
|
}
|
|
|
|
func ListByOrm(tx *gorm.DB) *[]map[string]interface{} {
|
|
var res []map[string]interface{}
|
|
tx.Find(&res)
|
|
return &res
|
|
}
|
|
func Get[T any](queryMap []map[string]interface{}) map[string]interface{} {
|
|
tx := global.Db.Model(new(T))
|
|
for _, e := range queryMap {
|
|
e[IS_DELETE] = 0
|
|
tx = tx.Or(e)
|
|
}
|
|
return GetByOrm(tx)
|
|
}
|
|
|
|
func GetField[T any](queryMap []map[string]interface{}, isOmit bool, queryField ...string) map[string]interface{} {
|
|
tx := global.Db.Model(new(T))
|
|
for _, e := range queryMap {
|
|
e[IS_DELETE] = 0
|
|
tx = tx.Or(e)
|
|
}
|
|
if len(queryMap) == 0 {
|
|
return GetByOrm(tx)
|
|
}
|
|
if isOmit {
|
|
tx = tx.Omit(queryField...)
|
|
} else {
|
|
tx = tx.Select(queryField[0], queryField[1:])
|
|
}
|
|
return GetByOrm(tx)
|
|
}
|
|
|
|
func GetByOrm(tx *gorm.DB) map[string]interface{} {
|
|
var res map[string]interface{}
|
|
tx.Limit(1).Find(&res)
|
|
return res
|
|
}
|
|
|
|
func Count[T any](queryMap []map[string]interface{}) int64 {
|
|
tx := global.Db.Model(new(T))
|
|
for _, e := range queryMap {
|
|
e[IS_DELETE] = 0
|
|
tx = tx.Or(e)
|
|
}
|
|
return CountByOrm(tx)
|
|
}
|
|
|
|
func CountByOrm(tx *gorm.DB) int64 {
|
|
var count int64
|
|
tx.Count(&count)
|
|
return count
|
|
}
|