Files
common/sql/sql.go
2026-03-12 08:51:59 +08:00

460 lines
10 KiB
Go
Raw 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.
// =============================================================================
// SQL 业务操作封装
// 提供向后兼容的CRUD操作方法支持 PostgreSQL
// =============================================================================
package sql
import (
"context"
"gitea.com/red-future/common/beans"
"gitea.com/red-future/common/utils"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/util/gconv"
)
const (
PageSize = 20
)
type sqlDB struct {
noTenantId bool
}
func DB(cache ...bool) *sqlDB {
return &sqlDB{
noTenantId: false,
}
}
// NoTenantId 不使用租户过滤
func (s *sqlDB) NoTenantId() *sqlDB {
s.noTenantId = true
return s
}
// Count 查询总数
func (s *sqlDB) Count(ctx context.Context, model *gdb.Model) (int64, error) {
user, err := utils.GetUserInfo(ctx)
if err != nil {
return 0, err
}
// 如果没有调用 noTenantId则添加 tenantId 过滤
if !s.noTenantId && !g.IsEmpty(user.TenantId) {
model = model.Where("tenant_id", user.TenantId)
}
model = model.Where("is_deleted", false)
// 执行查询
count, _ := model.Count(ctx)
return int64(count), nil
}
// Insert 插入记录(集合版本)
func (s *sqlDB) Insert(ctx context.Context, data interface{}, collection string) ([]any, error) {
user, err := utils.GetUserInfo(ctx)
if err != nil {
return nil, err
}
model := g.DB().Model(collection)
// 处理切片类型数据
var resultSlice []any
if slice, ok := data.([]interface{}); ok {
for _, item := range slice {
// 转换为map
dataMap := gconv.Map(item)
delete(dataMap, "id")
// 设置租户ID
if !g.IsEmpty(user.TenantId) && g.IsEmpty(dataMap["tenant_id"]) {
dataMap["tenant_id"] = user.TenantId
}
// 设置创建人
if !g.IsEmpty(user.UserName) && g.IsEmpty(dataMap["creator"]) {
dataMap["creator"] = user.UserName
}
// 设置更新人
if !g.IsEmpty(user.UserName) && g.IsEmpty(dataMap["updater"]) {
dataMap["updater"] = user.UserName
}
// 设置时间
now := gtime.Now().Time
if g.IsEmpty(dataMap["created_at"]) {
dataMap["created_at"] = now
}
if g.IsEmpty(dataMap["updated_at"]) {
dataMap["updated_at"] = now
}
// 设置删除标记
if g.IsEmpty(dataMap["is_deleted"]) {
dataMap["is_deleted"] = false
}
resultSlice = append(resultSlice, dataMap)
}
// 批量插入
result, err := model.Data(resultSlice).Insert(ctx)
if err != nil {
return nil, err
}
id, err := result.LastInsertId()
if err != nil {
return nil, err
}
return []any{id}, nil
}
// 单条数据插入
dataMap := gconv.Map(data)
delete(dataMap, "id")
// 设置租户ID
if !g.IsEmpty(user.TenantId) && g.IsEmpty(dataMap["tenant_id"]) {
dataMap["tenant_id"] = user.TenantId
}
// 设置创建人
if !g.IsEmpty(user.UserName) && g.IsEmpty(dataMap["creator"]) {
dataMap["creator"] = user.UserName
}
// 设置更新人
if !g.IsEmpty(user.UserName) && g.IsEmpty(dataMap["updater"]) {
dataMap["updater"] = user.UserName
}
// 设置时间
now := gtime.Now().Time
if g.IsEmpty(dataMap["created_at"]) {
dataMap["created_at"] = now
}
if g.IsEmpty(dataMap["updated_at"]) {
dataMap["updated_at"] = now
}
// 设置删除标记
if g.IsEmpty(dataMap["is_deleted"]) {
dataMap["is_deleted"] = false
}
// 执行插入
result, err := model.Data(dataMap).Insert(ctx)
if err != nil {
return nil, err
}
id, err := result.LastInsertId()
if err != nil {
return nil, err
}
return []any{id}, nil
}
// FindOne 根据ID查询单条记录
func (s *sqlDB) FindOne(ctx context.Context, id string, collection string, result interface{}) error {
user, err := utils.GetUserInfo(ctx)
if err != nil {
return err
}
model := g.DB().Model(collection).Where("id", id)
// 如果没有调用 noTenantId则添加 tenantId 过滤
if !s.noTenantId && !g.IsEmpty(user.TenantId) {
model = model.Where("tenant_id", user.TenantId)
}
model = model.Where("is_deleted", false)
// 执行查询
return model.Scan(ctx, result)
}
// FindOneWithResult 根据ID查询单条记录并返回结果
func (s *sqlDB) FindOneWithResult(ctx context.Context, id string, collection string, result interface{}) (interface{}, error) {
user, err := utils.GetUserInfo(ctx)
if err != nil {
return nil, err
}
model := g.DB().Model(collection).Where("id", id)
// 如果没有调用 noTenantId则添加 tenantId 过滤
if !s.noTenantId && !g.IsEmpty(user.TenantId) {
model = model.Where("tenant_id", user.TenantId)
}
model = model.Where("is_deleted", false)
// 执行查询
err = model.Scan(ctx, result)
return result, err
}
// FindOneByModel 根据Model查询单条记录
func (s *sqlDB) FindOneByModel(ctx context.Context, model *gdb.Model, result interface{}) error {
user, err := utils.GetUserInfo(ctx)
if err != nil {
return err
}
// 如果没有调用 noTenantId则添加 tenantId 过滤
if !s.noTenantId && !g.IsEmpty(user.TenantId) {
model = model.Where("tenant_id", user.TenantId)
}
model = model.Where("is_deleted", false)
// 执行查询
return model.Scan(ctx, result)
}
// Find 查询多条记录(集合版本)
func (s *sqlDB) Find(ctx context.Context, model *gdb.Model, collection string, result interface{}, page *beans.Page, orderBy []beans.OrderBy) (int64, error) {
if model == nil {
model = g.DB().Model(collection)
}
user, err := utils.GetUserInfo(ctx)
if err != nil {
return 0, err
}
// 如果没有调用 noTenantId则添加 tenantId 过滤
if !s.noTenantId && !g.IsEmpty(user.TenantId) {
model = model.Where("tenant_id", user.TenantId)
}
model = model.Where("is_deleted", false)
// 分页处理
limit := int64(PageSize)
offset := int64(0)
if page != nil && !g.IsEmpty(page.PageNum) && !g.IsEmpty(page.PageSize) {
limit = page.PageSize
if limit != -1 {
offset = (page.PageNum - 1) * limit
}
}
// 排序处理
if orderBy != nil && len(orderBy) > 0 {
for _, o := range orderBy {
orderStr := string(o.Order)
if orderStr == "asc" || orderStr == "ASC" {
model = model.OrderAsc(o.Field)
} else {
model = model.OrderDesc(o.Field)
}
}
} else {
model = model.OrderDesc("created_at")
}
// 执行查询
if limit != -1 {
total, err := s.Count(ctx, model)
if err != nil {
return 0, err
}
if total == 0 {
return 0, nil
}
err = model.Offset(int(offset)).Limit(int(limit)).Scan(ctx, result)
if err != nil {
return 0, err
}
return total, nil
}
// 不分页,查询全部
err = model.Scan(ctx, result)
if err != nil {
return 0, err
}
// 获取结果集长度
return 0, nil
}
// Update 更新记录ID版本
func (s *sqlDB) Update(ctx context.Context, id string, collection string, data interface{}) (int64, error) {
user, err := utils.GetUserInfo(ctx)
if err != nil {
return 0, err
}
model := g.DB().Model(collection).Where("id", id)
// 如果没有调用 noTenantId则添加 tenantId 过滤
if !s.noTenantId && !g.IsEmpty(user.TenantId) {
model = model.Where("tenant_id", user.TenantId)
}
model = model.Where("is_deleted", false)
// 转换为map
dataMap := gconv.Map(data)
delete(dataMap, "id")
// 设置更新人
if !g.IsEmpty(user.UserName) && g.IsEmpty(dataMap["updater"]) {
dataMap["updater"] = user.UserName
}
// 设置更新时间
dataMap["updated_at"] = gtime.Now().Time
// 执行更新
result, err := model.Data(dataMap).Update(ctx)
if err != nil {
return 0, err
}
affected, err := result.RowsAffected()
if err != nil {
return 0, err
}
return affected, err
}
// Delete 软删除ID版本
func (s *sqlDB) Delete(ctx context.Context, id string, collection string) (int64, error) {
user, err := utils.GetUserInfo(ctx)
if err != nil {
return 0, err
}
model := g.DB().Model(collection).Where("id", id)
// 如果没有调用 noTenantId则添加 tenantId 过滤
if !s.noTenantId && !g.IsEmpty(user.TenantId) {
model = model.Where("tenant_id", user.TenantId)
}
model = model.Where("is_deleted", false)
// 软删除
data := map[string]interface{}{
"is_deleted": true,
"updater": user.UserName,
"updated_at": gtime.Now().Time,
}
result, err := model.Data(data).Update(ctx)
if err != nil {
return 0, err
}
affected, err := result.RowsAffected()
if err != nil {
return 0, err
}
return affected, err
}
// DeleteByModel 软删除Model版本
func (s *sqlDB) DeleteSoftByModel(ctx context.Context, model *gdb.Model) (int64, error) {
user, err := utils.GetUserInfo(ctx)
if err != nil {
return 0, err
}
// 如果没有调用 noTenantId则添加 tenantId 过滤
if !s.noTenantId && !g.IsEmpty(user.TenantId) {
model = model.Where("tenant_id", user.TenantId)
}
model = model.Where("is_deleted", false)
// 软删除
data := map[string]interface{}{
"is_deleted": true,
"updater": user.UserName,
"updated_at": gtime.Now().Time,
}
result, err := model.Data(data).Update(ctx)
if err != nil {
return 0, err
}
affected, err := result.RowsAffected()
if err != nil {
return 0, err
}
return affected, err
}
// Increment 字段自增
func (s *sqlDB) Increment(ctx context.Context, id string, collection string, field string, value int64) (int64, error) {
user, err := utils.GetUserInfo(ctx)
if err != nil {
return 0, err
}
model := g.DB().Model(collection).Where("id", id)
// 如果没有调用 noTenantId则添加 tenantId 过滤
if !s.noTenantId && !g.IsEmpty(user.TenantId) {
model = model.Where("tenant_id", user.TenantId)
}
model = model.Where("is_deleted", false)
// 设置更新人和时间
data := map[string]interface{}{
"updater": user.UserName,
"updated_at": gtime.Now().Time,
}
// 使用原生SQL实现自增
data[field] = gdb.Raw(field + " + " + gconv.String(value) + "::bigint")
// 执行更新
result, err := model.Data(data).Update(ctx)
if err != nil {
return 0, err
}
affected, err := result.RowsAffected()
if err != nil {
return 0, err
}
return affected, err
}
// DeleteSoft 软删除ID版本
func (s *sqlDB) DeleteSoft(ctx context.Context, id string, collection string) (int64, error) {
return s.Delete(ctx, id, collection)
}
// Model 获取Model
func (s *sqlDB) Model(collection string) *gdb.Model {
return g.DB().Model(collection)
}
// BuildUpdateData 构建更新数据
func BuildUpdateData(ctx context.Context, req interface{}) (map[string]interface{}, error) {
return gconv.Map(req), nil
}