Files
nCovTrack-Backend/models/utils.go
2022-05-04 20:06:21 +08:00

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
}