9 Commits

Author SHA1 Message Date
a7480bac13 fix 2024-09-06 15:01:14 +08:00
375aed7160 增加数据创建能力 2024-09-06 14:49:36 +08:00
38f3f763bf update comment 2024-09-05 14:50:28 +08:00
16e6d57d59 update go mod 2024-09-05 14:43:50 +08:00
9de616194b update doc 2024-09-03 12:02:13 +08:00
b89b9b6958 update go sum 2024-09-03 11:55:15 +08:00
6f9a560e59 增加数据详情查询能力 2024-08-30 14:50:51 +08:00
c9d6c4c845 修复json tag生成 2024-08-30 14:16:11 +08:00
aebb943603 update go mod 2024-08-30 14:07:38 +08:00
16 changed files with 988 additions and 616 deletions

View File

@ -17,7 +17,7 @@ import (
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:06 2023/10/14
type IDatabase[DatabaseDataType any, DatabaseTableColumns any] interface {
type IDatabase interface {
// Create 创建数据
Create(dbInstance *gorm.DB, data any, optionList ...define.SetOption) error
// Update 更新数据
@ -25,13 +25,11 @@ type IDatabase[DatabaseDataType any, DatabaseTableColumns any] interface {
// UpdateOne 更新一条数据
UpdateOne(dbInstance *gorm.DB, updateData any, optionFuncList ...define.SetOption) (int64, error)
// List 查询数据列表
List(dbInstance *gorm.DB, result *[]DatabaseDataType, optionFuncList ...define.SetOption) error
// ListAndTotal 查询列表并返回满足条件数据总数
ListAndTotal(dbInstance *gorm.DB, listRes *[]DatabaseDataType, totalRes *int64, disableTotal bool, optionFuncList ...define.SetOption) error
List(dbInstance *gorm.DB, result any, optionFuncList ...define.SetOption) error
// Delete 删除数据
Delete(dbInstance *gorm.DB, dataModel *DatabaseDataType, optionFuncList ...define.SetOption) (int64, error)
Delete(dbInstance *gorm.DB, dataModel any, optionFuncList ...define.SetOption) (int64, error)
// Detail 数据详情
Detail(dbInstance *gorm.DB, result *DatabaseDataType, optionFuncList ...define.SetOption) error
Detail(dbInstance *gorm.DB, result any, optionFuncList ...define.SetOption) error
// IsNotFound 错误是否为数据不存在
IsNotFound(err error) bool
// Count 查询数据数量
@ -45,13 +43,5 @@ type IDatabase[DatabaseDataType any, DatabaseTableColumns any] interface {
// Rollback 回滚事务
Rollback(db *gorm.DB) error
// DetailByPrimaryID 根据主键ID, 查询任意表的数据详情
DetailByPrimaryID(dbInstance *gorm.DB, result *DatabaseDataType, primaryID any, primaryKey ...string) error
// ColumnComment 表字段注释
ColumnComment() map[string]string
// Columns 表字段定义
Columns() DatabaseTableColumns
// DetailForAny 任意数据详情
DetailForAny(tx *gorm.DB, tableName string, result any, optionList ...define.SetOption) error
// ListForAny 任意数据列表
ListForAny(tx *gorm.DB, tableName string, data any, optionList ...define.SetOption) error
DetailByPrimaryID(dbInstance *gorm.DB, result any, primaryID any, primaryKey ...string) error
}

345
api2sql/execute.go Normal file
View File

@ -0,0 +1,345 @@
// Package api2sql ...
//
// Description : api2sql ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2024-08-21 20:45
package api2sql
import (
"context"
"errors"
"fmt"
"git.zhangdeman.cn/zhangdeman/consts"
"git.zhangdeman.cn/zhangdeman/database"
"git.zhangdeman.cn/zhangdeman/database/abstract"
"git.zhangdeman.cn/zhangdeman/database/define"
"git.zhangdeman.cn/zhangdeman/wrapper"
"gorm.io/gorm"
)
var (
Exec = &execute{}
)
type execute struct {
databaseClientManager abstract.IWrapperClient // 全部数据库管理的实例
baseDao database.BaseDao // 基础dao
}
// SetDatabaseClientManager 设置数据库连接管理实例
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 21:06 2024/8/21
func (e *execute) SetDatabaseClientManager(databaseClientManager abstract.IWrapperClient) {
e.databaseClientManager = databaseClientManager
}
// Run 执行
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 20:48 2024/8/21
func (e *execute) Run(ctx context.Context, inputParam *define.Api2SqlParam) (any, error) {
if err := e.formatAndValidateInputParam(inputParam); nil != err {
return nil, err
}
if len(inputParam.InputSql) > 0 {
// 基于表达式执行
return e.Express(ctx, inputParam)
}
switch inputParam.SqlType {
case consts.SqlTypeCount:
return e.Count(ctx, inputParam)
case consts.SqlTypeDetail:
return e.Detail(ctx, inputParam)
case consts.SqlTypeList:
return e.List(ctx, inputParam)
case consts.SqlTypeInsert:
return e.Insert(ctx, inputParam)
case consts.SqlTypeUpdate:
return e.Update(ctx, inputParam)
case consts.SqlTypeDelete:
return e.Delete(ctx, inputParam)
default:
return nil, errors.New(inputParam.SqlType + " : sql type is not support")
}
}
// List 方法用于从数据库中查询数据列表。
//
// 参数:
// - ctx: 上下文对象,用于传递请求的上下文信息。
// - inputParam: 查询参数,包含 SQL 语句、列列表等信息。
//
// 返回值:
// - any: 查询结果,返回一个结构体切片,其中包含查询到的数据。
// - error: 错误信息,如果查询过程中发生错误,将返回相应的错误对象。
//
// 使用示例:
// result, err := e.List(ctx, inputParam)
// if err!= nil {
// // 处理错误
// }
// // 处理查询结果
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 20:52 2024/8/21
func (e *execute) List(ctx context.Context, inputParam *define.Api2SqlParam) ([]map[string]any, error) {
var (
err error
tx *gorm.DB
optionList []define.SetOption
val []map[string]any
)
if tx, err = e.getTx(ctx, inputParam); nil != err {
return nil, err
}
if optionList, err = e.getOptionList(ctx, inputParam); nil != err {
return nil, err
}
if err = e.baseDao.List(tx, &val, optionList...); nil != err {
return nil, err
}
return val, nil
}
// Detail 方法用于获取单个数据的详细信息。
// 它接受一个上下文对象 ctx 和一个指向输入参数结构体 Api2SqlParam 的指针 inputParam。
// 首先,它会将 inputParam 的 Limit 属性设置为 1以限制查询结果为一条记录。
// 然后,它会调用 e.List 方法来执行查询操作,并将结果存储在 res 变量中。
// 如果查询过程中发生错误,它会将错误返回。
// 如果查询成功但结果集为空,它会返回一个错误,表示未找到记录。
// 如果查询成功且结果集不为空,它会返回结果集中的第一条记录。
//
// 参数 :
// - ctx : 上下文对象,用于传递请求的上下文信息。
// - inputParam : 查询参数,包含了查询所需的条件和限制。
//
// 返回值 :
// - 返回查询到的单个数据的详细信息
// - 如果未找到数据则返回错误
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 20:52 2024/8/21
func (e *execute) Detail(ctx context.Context, inputParam *define.Api2SqlParam) (any, error) {
inputParam.Limit = 1 // 限制查询一条
var (
list []map[string]any
err error
)
if list, err = e.List(ctx, inputParam); nil != err {
return nil, err
}
if len(list) == 0 {
return nil, gorm.ErrRecordNotFound
}
return list[0], nil
}
// Insert 插入
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 20:52 2024/8/21
func (e *execute) Insert(ctx context.Context, inputParam *define.Api2SqlParam) (any, error) {
var (
err error
tx *gorm.DB
)
if tx, err = e.getTx(ctx, inputParam); nil != err {
return nil, err
}
// 动态生成结果解析结构体
insertVal := map[string]any{}
for _, itemColumn := range inputParam.ConditionList {
insertVal[itemColumn.Column] = itemColumn.Value
}
if err = e.baseDao.Create(tx, &insertVal, database.WithTable(inputParam.Table)); nil != err {
return nil, err
}
return insertVal, nil
}
// Update 更新
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 20:52 2024/8/21
func (e *execute) Update(ctx context.Context, inputParam *define.Api2SqlParam) (any, error) {
return nil, nil
}
// Count 数量
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 20:52 2024/8/21
func (e *execute) Count(ctx context.Context, inputParam *define.Api2SqlParam) (any, error) {
return nil, nil
}
// Delete 删除
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 20:51 2024/8/21
func (e *execute) Delete(ctx context.Context, inputParam *define.Api2SqlParam) (any, error) {
return nil, nil
}
// Express 基于表达式执行
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 20:51 2024/8/21
func (e *execute) Express(ctx context.Context, inputParam *define.Api2SqlParam) (any, error) {
if nil == e.databaseClientManager {
return nil, errors.New("database client is nil, please use `SetDatabaseClientManager` set instance")
}
// 格式化 inputParam
return nil, nil
}
// formatAndValidateInputParam 格式化并校验输入参数
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 10:38 2024/8/22
func (e *execute) formatAndValidateInputParam(inputParam *define.Api2SqlParam) error {
if nil == inputParam {
return errors.New("inputParam is nil")
}
if len(inputParam.DatabaseFlag) == 0 {
return errors.New("databaseFlag is empty")
}
if len(inputParam.Table) == 0 {
return errors.New("table is empty")
}
if len(inputParam.SqlType) == 0 {
return errors.New("sqlType is empty")
}
databaseClient, err := e.databaseClientManager.GetDBClient(inputParam.DatabaseFlag)
if nil != err {
return errors.New(inputParam.DatabaseFlag + " : database client get fail -> " + err.Error())
}
// 尝试获取表结构, api 转 sql 要求必须开启表结构缓存, 否则无法确定相关数据如何解析
if inputParam.TableColumnConfig, err = databaseClient.GetTableFieldList(inputParam.Table); nil != err {
return errors.New(inputParam.DatabaseFlag + " : get table field list fail -> " + err.Error())
}
if len(inputParam.TableColumnConfig) == 0 {
return errors.New(inputParam.DatabaseFlag + " : table field list is empty, please enable `CacheDataTableStructureConfig` or `SetTableColumnConfig`")
}
// 操作字段列表为空
if err = e.validateColumn(inputParam); nil != err {
return err
}
// 验证 force no limit
if inputParam.ForceNoLimit {
inputParam.Limit = 0
inputParam.WithCount = false
}
return nil
}
// validateColumn 验证表字段相关
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:48 2024/8/22
func (e *execute) validateColumn(inputParam *define.Api2SqlParam) error {
if len(inputParam.ColumnList) == 0 && wrapper.ArrayType[string]([]string{
consts.SqlTypeList, consts.SqlTypeDetail,
}).Has(inputParam.SqlType) >= 0 {
return errors.New("column list is empty")
}
// 验证字段是否都正确
tableColumnTable := make(map[string]bool)
for _, itemColumn := range inputParam.TableColumnConfig {
tableColumnTable[itemColumn.Column] = true
}
for _, columnConfig := range inputParam.ColumnList {
if !tableColumnTable[columnConfig.Column] {
return errors.New(columnConfig.Column + " : input column not found in table column list")
}
if len(columnConfig.Alias) == 0 {
columnConfig.Alias = columnConfig.Column
}
}
return nil
}
// getTx 获取数据库连接
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 12:20 2024/8/23
func (e *execute) getTx(ctx context.Context, inputParam *define.Api2SqlParam) (*gorm.DB, error) {
if nil != inputParam.Tx {
return inputParam.Tx, nil
}
if inputParam.ForceMaster || // 强制操作主库
wrapper.ArrayType[string]([]string{consts.SqlTypeDelete, consts.SqlTypeInsert, consts.SqlTypeUpdate}).Has(inputParam.SqlType) >= 0 { // 写操作
return e.databaseClientManager.GetMasterClient(ctx, inputParam.DatabaseFlag)
}
return e.databaseClientManager.GetSlaveClient(ctx, inputParam.DatabaseFlag)
}
// getOptionList 设置where条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 12:31 2024/8/23
func (e *execute) getOptionList(ctx context.Context, inputParam *define.Api2SqlParam) ([]define.SetOption, error) {
optionList := []define.SetOption{
database.WithTable(inputParam.Table),
}
// 设置 limit offset
if !inputParam.ForceNoLimit && inputParam.Limit > 0 {
optionList = append(optionList, database.WithLimit(inputParam.Limit, inputParam.Offset))
}
for _, item := range inputParam.ConditionList {
optionFunc, err := database.WithAnyCondition(item.Column, item.Operate, item.Value)
if nil != err {
return nil, err
}
optionList = append(optionList, optionFunc)
}
return optionList, nil
}
// dynamicGenerateStruct 生成动态结构体
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 14:19 2024/8/30
func (e *execute) dynamicGenerateStruct(columnList []*define.ColumnConfig) *wrapper.DynamicStruct {
st := wrapper.NewDynamic()
for _, columnConfig := range columnList {
tag := fmt.Sprintf(`%v`, columnConfig.Alias)
column := wrapper.String(columnConfig.Column).SnakeCaseToCamel()
switch columnConfig.Type {
case "int", "int8", "int16", "int32", "int64":
st.AddInt(column, tag, "")
case "uint", "uint8", "uint16", "uint32", "uint64":
st.AddUint(column, tag, "")
case "bool":
st.AddBool(column, tag, "")
case "float":
st.AddBool(column, tag, "")
case "string":
st.AddString(column, tag, "")
case "map":
st.AddMap(column, tag, "")
case "slice":
st.AddSlice(column, tag, "")
}
}
return st
}

163
api2sql/execute_test.go Normal file
View File

@ -0,0 +1,163 @@
// Package api2sql ...
//
// Description : api2sql ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2024-08-23 17:36
package api2sql
import (
"context"
"encoding/json"
"fmt"
"git.zhangdeman.cn/zhangdeman/consts"
"git.zhangdeman.cn/zhangdeman/database"
"git.zhangdeman.cn/zhangdeman/database/define"
"testing"
"time"
)
func startTest() {
clientManager := database.NewWrapperClient()
if err := clientManager.AddWithConfig("TEST_DATABASE", nil, &define.Database{
Master: &define.Driver{
DBType: "sqlite3",
Host: "/tmp/gateway.db",
},
Slave: &define.Driver{
DBType: "sqlite3",
Host: "/tmp/gateway.db",
},
}, []string{}); nil != err {
panic(err.Error())
}
dbClient, _ := clientManager.GetDBClient("TEST_DATABASE")
dbClient.SetTableStructure(map[string][]*define.ColumnConfig{
"project": []*define.ColumnConfig{
&define.ColumnConfig{
Column: "flag",
Alias: "project_flag",
Type: "string",
},
},
})
Exec.SetDatabaseClientManager(clientManager)
}
func Test_execute_List(t *testing.T) {
startTest()
res, err := Exec.List(context.Background(), &define.Api2SqlParam{
DatabaseFlag: "TEST_DATABASE",
Table: "project",
ForceMaster: false,
InputSql: "",
TableSplitConfig: define.TableSplitConfig{},
SqlType: consts.SqlTypeList,
ColumnList: []*define.ColumnConfig{
&define.ColumnConfig{
Column: "flag",
Alias: "project_flag",
Type: "string",
},
&define.ColumnConfig{
Column: "connect_timeout",
Alias: "timeout",
Type: "string",
},
},
Limit: 0,
Offset: 0,
ForceNoLimit: false,
OrderField: "id",
OrderRule: "desc",
WithCount: false,
ConditionList: nil,
TableColumnConfig: nil,
Tx: nil,
})
byteData, _ := json.Marshal(res)
fmt.Println(string(byteData), err)
}
func Test_execute_Detail(t *testing.T) {
startTest()
res, err := Exec.Detail(context.Background(), &define.Api2SqlParam{
DatabaseFlag: "TEST_DATABASE",
Table: "project",
ForceMaster: false,
InputSql: "",
TableSplitConfig: define.TableSplitConfig{},
SqlType: consts.SqlTypeList,
ColumnList: []*define.ColumnConfig{
&define.ColumnConfig{
Column: "flag",
Alias: "project_flag",
Type: "string",
},
&define.ColumnConfig{
Column: "description",
Alias: "desc",
Type: "string",
},
},
Limit: 0,
Offset: 0,
ForceNoLimit: false,
OrderField: "id",
OrderRule: "desc",
WithCount: false,
ConditionList: nil,
TableColumnConfig: nil,
Tx: nil,
})
byteData, _ := json.Marshal(res)
fmt.Println(res, err, string(byteData))
}
func Test_execute_Insert(t *testing.T) {
startTest()
res, err := Exec.Insert(context.Background(), &define.Api2SqlParam{
DatabaseFlag: "TEST_DATABASE",
Table: "project",
ForceMaster: false,
InputSql: "",
TableSplitConfig: define.TableSplitConfig{},
SqlType: consts.SqlTypeList,
ColumnList: []*define.ColumnConfig{
&define.ColumnConfig{
Column: "flag",
Alias: "project_flag",
Type: "string",
},
&define.ColumnConfig{
Column: "description",
Alias: "desc",
Type: "string",
},
},
Limit: 0,
Offset: 0,
ForceNoLimit: false,
OrderField: "id",
OrderRule: "desc",
WithCount: false,
ConditionList: []define.SqlCondition{
define.SqlCondition{
Column: "flag",
Operate: "",
Value: fmt.Sprintf("unit_test_flag_%v", time.Now().Unix()),
},
define.SqlCondition{
Column: "description",
Operate: "",
Value: "单元测试生成项目",
},
},
TableColumnConfig: nil,
Tx: nil,
})
byteData, _ := json.Marshal(res)
fmt.Println(res, err, string(byteData))
}

213
base.go
View File

@ -7,101 +7,95 @@ package database
import (
"errors"
"reflect"
"git.zhangdeman.cn/zhangdeman/database/define"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)
func NewBaseDao[DatabaseDataType any, DatabaseTableColumns any]() *BaseDao[DatabaseDataType, DatabaseTableColumns] {
res := &BaseDao[DatabaseDataType, DatabaseTableColumns]{}
res.tableName = res.TableName()
res.columns = res.Columns()
res.isSetColumns = true
res.columnComment = res.ColumnComment()
return res
}
// BaseDao 基础dao层
type BaseDao[DatabaseDataType any, DatabaseTableColumns any] struct {
tableName string // 继承BaseDao需要指定表名后续调用不用传递表名进来如果分表了使用SetOption设置表名, 这里的优先级更高
isSetColumns bool
columns DatabaseTableColumns
columnComment map[string]string
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 14:13 2023/2/9
type BaseDao struct {
TableName string // 继承BaseDao需要指定表名后续调用不用传递表名进来如果分表了使用SetOption设置表名, 这里的优先级更高
}
// Create 创建新的数据
func (b *BaseDao[DatabaseDataType, DatabaseTableColumns]) Create(dbInstance *gorm.DB, data any, optionList ...define.SetOption) error {
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 8:06 下午 2021/8/8
func (b *BaseDao) Create(dbInstance *gorm.DB, data any, optionList ...define.SetOption) error {
o := &define.Option{}
for _, itemFunc := range optionList {
itemFunc(o)
}
useTableName := b.tableName
tableName := b.TableName
if len(o.Table) > 0 {
useTableName = o.Table
tableName = o.Table
}
return dbInstance.Table(useTableName).Create(data).Error
return dbInstance.Table(tableName).Create(data).Error
}
// Update 更新数据
func (b *BaseDao[DatabaseDataType, DatabaseTableColumns]) Update(dbInstance *gorm.DB, updateData any, optionFuncList ...define.SetOption) (int64, error) {
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 8:12 下午 2021/8/8
func (b *BaseDao) Update(dbInstance *gorm.DB, updateData any, optionFuncList ...define.SetOption) (int64, error) {
dbInstance = b.setTxCondition(dbInstance, optionFuncList...)
r := dbInstance.Updates(updateData)
return r.RowsAffected, r.Error
}
// UpdateOne 更新一条数据
func (b *BaseDao[DatabaseDataType, DatabaseTableColumns]) UpdateOne(dbInstance *gorm.DB, updateData any, optionFuncList ...define.SetOption) (int64, error) {
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:05 2024/1/13
func (b *BaseDao) UpdateOne(dbInstance *gorm.DB, updateData any, optionFuncList ...define.SetOption) (int64, error) {
optionFuncList = append(optionFuncList, WithLimit(1, 0))
return b.Update(dbInstance, updateData, optionFuncList...)
}
// List 查询数据列表
func (b *BaseDao[DatabaseDataType, DatabaseTableColumns]) List(dbInstance *gorm.DB, result *[]DatabaseDataType, optionFuncList ...define.SetOption) error {
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 8:14 下午 2021/8/8
func (b *BaseDao) List(dbInstance *gorm.DB, result any, optionFuncList ...define.SetOption) error {
dbInstance = b.setTxCondition(dbInstance, optionFuncList...)
return dbInstance.Find(result).Error
}
// ListAndTotal 同时查询数据列表和数据总数
func (b *BaseDao[DatabaseDataType, DatabaseTableColumns]) ListAndTotal(dbInstance *gorm.DB, listRes *[]DatabaseDataType, totalRes *int64, disableTotal bool, optionFuncList ...define.SetOption) error {
var (
err error
)
dbInstance = b.setTxCondition(dbInstance, optionFuncList...)
if err = dbInstance.Find(listRes).Error; nil != err {
// 列表查询失败
return err
}
if disableTotal {
// 禁用查询总数
*totalRes = int64(reflect.ValueOf(listRes).Elem().Len())
return nil
}
optionFuncList = append(optionFuncList, WithClearLimit())
dbInstance = b.setTxCondition(dbInstance, optionFuncList...)
if err = dbInstance.Count(totalRes).Error; nil != err {
return err
}
return nil
}
// Delete 删除数据, 硬删除, 对应 delete语句
func (b *BaseDao[DatabaseDataType, DatabaseTableColumns]) Delete(dbInstance *gorm.DB, dataModel *DatabaseDataType, optionFuncList ...define.SetOption) (int64, error) {
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:46 2023/2/9
func (b *BaseDao) Delete(dbInstance *gorm.DB, dataModel any, optionFuncList ...define.SetOption) (int64, error) {
dbInstance = dbInstance.Model(dataModel)
dbInstance = b.setTxCondition(dbInstance, optionFuncList...).Delete(dataModel)
return dbInstance.RowsAffected, dbInstance.Error
}
// Detail 查询详情
func (b *BaseDao[DatabaseDataType, DatabaseTableColumns]) Detail(dbInstance *gorm.DB, result *DatabaseDataType, optionFuncList ...define.SetOption) error {
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 8:25 下午 2021/8/8
func (b *BaseDao) Detail(dbInstance *gorm.DB, result any, optionFuncList ...define.SetOption) error {
dbInstance = b.setTxCondition(dbInstance, optionFuncList...)
return dbInstance.First(result).Error
}
// DetailByPrimaryID ...
func (b *BaseDao[DatabaseDataType, DatabaseTableColumns]) DetailByPrimaryID(dbInstance *gorm.DB, result *DatabaseDataType, primaryID any, primaryKey ...string) error {
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 14:14 2023/10/15
func (b *BaseDao) DetailByPrimaryID(dbInstance *gorm.DB, result any, primaryID any, primaryKey ...string) error {
primaryKeyField := "id"
if len(primaryKey) > 0 {
primaryKeyField = primaryKey[0]
@ -112,20 +106,31 @@ func (b *BaseDao[DatabaseDataType, DatabaseTableColumns]) DetailByPrimaryID(dbIn
}
// IsNotFound 增加结果是否为数据不存在的判断
func (b *BaseDao[DatabaseDataType, DatabaseTableColumns]) IsNotFound(err error) bool {
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:57 2023/2/23
func (b *BaseDao) IsNotFound(err error) bool {
return errors.Is(err, gorm.ErrRecordNotFound)
}
// Count 查询数量
func (b *BaseDao[DatabaseDataType, DatabaseTableColumns]) Count(dbInstance *gorm.DB, optionFuncList ...define.SetOption) (int64, error) {
optionFuncList = append(optionFuncList, WithClearLimit())
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 8:25 下午 2021/8/8
func (b *BaseDao) Count(dbInstance *gorm.DB, optionFuncList ...define.SetOption) (int64, error) {
dbInstance = b.setTxCondition(dbInstance, optionFuncList...)
var cnt int64
return cnt, dbInstance.Count(&cnt).Error
}
// Tx 执行事务
func (b *BaseDao[DatabaseDataType, DatabaseTableColumns]) Tx(dbInstance *gorm.DB, txFunc func(dbInstance *gorm.DB) error) error {
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 20:31 2022/12/24
func (b *BaseDao) Tx(dbInstance *gorm.DB, txFunc func(dbInstance *gorm.DB) error) error {
if nil == dbInstance {
return errors.New("db instance is null")
}
@ -138,38 +143,50 @@ func (b *BaseDao[DatabaseDataType, DatabaseTableColumns]) Tx(dbInstance *gorm.DB
}
// Begin 开启事务
func (b *BaseDao[DatabaseDataType, DatabaseTableColumns]) Begin(dbInstance *gorm.DB) *gorm.DB {
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 3:09 下午 2021/8/9
func (b *BaseDao) Begin(dbInstance *gorm.DB) *gorm.DB {
return dbInstance.Begin()
}
// Commit 提交事务
func (b *BaseDao[DatabaseDataType, DatabaseTableColumns]) Commit(db *gorm.DB) error {
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 3:10 下午 2021/8/9
func (b *BaseDao) Commit(db *gorm.DB) error {
return db.Commit().Error
}
// Rollback 回滚
func (b *BaseDao[DatabaseDataType, DatabaseTableColumns]) Rollback(db *gorm.DB) error {
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 3:12 下午 2021/8/9
func (b *BaseDao) Rollback(db *gorm.DB) error {
return db.Rollback().Error
}
// setTxCondition 设置查询条件
func (b *BaseDao[DatabaseDataType, DatabaseTableColumns]) setTxCondition(inputTx *gorm.DB, optionFuncList ...define.SetOption) *gorm.DB {
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:38 2022/5/15
func (b *BaseDao) setTxCondition(tx *gorm.DB, optionFuncList ...define.SetOption) *gorm.DB {
// 构建查询条件
o := &define.Option{}
for _, fn := range optionFuncList {
fn(o)
}
tx := inputTx.Session(&gorm.Session{
NewDB: true,
Initialized: true,
})
// 指定查询的表
if len(o.Table) > 0 {
tx = tx.Table(o.Table)
} else {
tx = tx.Table(b.tableName)
tx = tx.Table(b.TableName)
}
if nil != o.Model {
@ -223,14 +240,6 @@ func (b *BaseDao[DatabaseDataType, DatabaseTableColumns]) setTxCondition(inputTx
}
}
if len(o.Where) > 0 {
tx = tx.Where(o.Where)
}
if o.ForUpdate {
tx = tx.Clauses(clause.Locking{Strength: "UPDATE"})
}
// between
for field, betweenVal := range o.Between {
tx = tx.Where("`"+field+"` BETWEEN ? AND ?", betweenVal[0], betweenVal[1])
@ -241,8 +250,8 @@ func (b *BaseDao[DatabaseDataType, DatabaseTableColumns]) setTxCondition(inputTx
}
// 排序
if len(o.Order) == 2 {
tx = tx.Order(o.Order[0] + " " + o.Order[1])
for _, orderRule := range o.Order {
tx = tx.Order(orderRule)
}
// or 语句
@ -256,45 +265,19 @@ func (b *BaseDao[DatabaseDataType, DatabaseTableColumns]) setTxCondition(inputTx
tx.Or(orSql, orBindVal)
}
}
/*sqlBlockList := make([]string, 0)
bindValueList := make([]any, 0)
sql, bindVal := optionToSql(o)
tx.Or(sql, bindVal...)
sqlBlockList = append(sqlBlockList, sql)
bindValueList = append(bindValueList, bindVal)
for _, itemOrFuncList := range o.OR {
orOption := &Option{}
for _, fn := range itemOrFuncList {
fn(orOption)
}
orSql, orBindVal := optionToSql(orOption)
tx.Or(orSql, orBindVal...)
}*/
return tx
}
// TableName 获取数据表名
func (b *BaseDao[DatabaseDataType, DatabaseTableColumns]) TableName() string {
val := reflect.ValueOf(*new(DatabaseDataType)).MethodByName("TableName").Call(nil)[0]
return val.Interface().(string)
}
// ColumnComment 表字段注释
func (b *BaseDao[DatabaseDataType, DatabaseTableColumns]) ColumnComment() map[string]string {
if len(b.columnComment) > 0 {
return b.columnComment
}
val := reflect.ValueOf(new(DatabaseDataType)).MethodByName("ColumnComment").Call(nil)[0]
b.columnComment = val.Interface().(map[string]string)
return b.columnComment
}
// Columns 表字段枚举
func (b *BaseDao[DatabaseDataType, DatabaseTableColumns]) Columns() DatabaseTableColumns {
if b.isSetColumns {
return b.columns
}
b.columns = reflect.ValueOf(new(DatabaseDataType)).MethodByName("Columns").Call(nil)[0].Interface().(DatabaseTableColumns)
b.isSetColumns = true
return b.columns
}
// DetailForAny 查询任意表数据详情
func (b *BaseDao[DatabaseDataType, DatabaseTableColumns]) DetailForAny(tx *gorm.DB, tableName string, result any, optionList ...define.SetOption) error {
tx = tx.Table(tableName)
tx = b.setTxCondition(tx, optionList...)
return tx.First(result).Error
}
// ListForAny 查询任意表数据列表
func (b *BaseDao[DatabaseDataType, DatabaseTableColumns]) ListForAny(tx *gorm.DB, tableName string, data any, optionList ...define.SetOption) error {
tx = tx.Table(tableName)
tx = b.setTxCondition(tx, optionList...)
return tx.Find(data).Error
}

View File

@ -44,6 +44,7 @@ type Api2SqlParam struct {
WithCount bool `json:"with_count"` // 是否返回数据总量, 仅 sqlType = list 生效
ConditionList []SqlCondition `json:"value_list"` // 字段列表
TableColumnConfig []*ColumnConfig `json:"table_column_config"` // 表字段配置
UpdateData map[string]any `json:"update_data"` // 要更新的数据, 仅对 update语句有效
Tx *gorm.DB `json:"-"` // 前后已有的数据库连接, 直接复用
}

View File

@ -7,8 +7,6 @@
// Date : 2021-03-01 9:27 下午
package define
import "git.zhangdeman.cn/zhangdeman/consts"
// DBConfig 数据库连接的配置
//
// Author : go_developer@163.com<白茶清欢>
@ -30,10 +28,10 @@ type DBConfig struct {
//
// Date : 14:47 2022/6/9
type CfgFile struct {
Flag string `json:"flag"` // 数据库标识
Path string `json:"path"` // 配置文件路径
Type consts.FileType `json:"type"` // 配置文件类型
Config *Database `json:"config"` // 解析之后的配置文件
Flag string `json:"flag"` // 数据库标识
Path string `json:"path"` // 配置文件路径
Type string `json:"type"` // 配置文件类型
Config *Database `json:"config"` // 解析之后的配置文件
}
// Database 数据库配置
@ -42,8 +40,8 @@ type CfgFile struct {
//
// Date : 15:19 2022/6/9
type Database struct {
Master *Driver `json:"master" yaml:"master" toml:"master" ini:"master"` // 主库配置
Slave *Driver `json:"slave" yaml:"slave" toml:"slave" ini:"slave"` // 从库配置
Master *Driver `json:"master" yaml:"master"` // 主库配置
Slave *Driver `json:"slave" yaml:"slave"` // 从库配置
}
// Driver ...
@ -52,15 +50,15 @@ type Database struct {
//
// Date : 18:44 2022/5/14
type Driver struct {
DBType string `json:"db_type" yaml:"db_type" toml:"db_type" ini:"db_type"` // 数据库驱动类型
Host string `json:"host" yaml:"host" toml:"host" ini:"host"` // 数据库地址
Port int `json:"port" yaml:"port" toml:"port" ini:"port"` // 数据库端口
Username string `json:"username" yaml:"username" toml:"username" ini:"username"` // 用户名
Password string `json:"password" yaml:"password" toml:"password" ini:"password"` // 密码
Database string `json:"database" yaml:"database" toml:"database" ini:"database"` // 数据库
Charset string `json:"charset" yaml:"charset" toml:"charset" ini:"charset"` // 数据库编码
Connection *Connection `json:"connection" yaml:"connection" toml:"connection" ini:"connection"` // 连接配置
Timezone string `json:"timezone" yaml:"timezone" toml:"timezone" ini:"timezone"` // 时区
DBType string `json:"db_type" yaml:"db_type"` // 数据库驱动类型
Host string `json:"host" yaml:"host"` // 数据库地址
Port int `json:"port" yaml:"port"` // 数据库端口
Username string `json:"username" yaml:"username"` // 用户名
Password string `json:"password" yaml:"password"` // 密码
Database string `json:"database" yaml:"database"` // 数据库
Charset string `json:"charset" yaml:"charset"` // 数据库编码
Connection *Connection `json:"connection" yaml:"connection"` // 连接配置
Timezone string `json:"timezone" yaml:"timezone"` // 时区
}
// Connection 连接数配置
@ -69,8 +67,8 @@ type Driver struct {
//
// Date : 15:18 2022/6/9
type Connection struct {
MaxOpen int `json:"max_open" yaml:"max_open" toml:"max_open" ini:"max_open"` // 最大打开连接数
MaxIdle int `json:"max_idle" yaml:"max_idle" toml:"max_idle" ini:"max_idle"` // 最大的处理连接数
MaxOpen int `json:"max_open" yaml:"max_open"` // 最大打开连接数
MaxIdle int `json:"max_idle" yaml:"max_idle"` // 最大的处理连接数
}
// DescTableItem 表结构的描述

View File

@ -34,7 +34,6 @@ type Option struct {
Like map[string]string `json:"like"` // like 语句
NotLike map[string]string `json:"not_like"` // not like 语句
NotEqual map[string]any `json:"not_equal"` // != 语句
ForUpdate bool `json:"for_update"` // 加互斥锁
Order []string `json:"order"` // 排序规则
OR [][]SetOption `json:"or"` // or 语句, or 和其他属性 and 关系, 内部 OR 关系
}

85
go.mod
View File

@ -1,84 +1,77 @@
module git.zhangdeman.cn/zhangdeman/database
go 1.24.1
go 1.21.0
toolchain go1.24.2
toolchain go1.23.0
require (
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250916024308-d378e6c57772
git.zhangdeman.cn/zhangdeman/logger v0.0.0-20251013144549-29cc7ca2481e
git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20251013024601-da007da2fb42
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20251013044511-86c1a4a3a9dd
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20251014035305-c0ec06fa6dff
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240823041145-d4df71cf37e5
git.zhangdeman.cn/zhangdeman/logger v0.0.0-20240725055115-98eb52ae307a
git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20240122104027-4928421213c0
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20240618035451-8d48a6bd39dd
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20240823103024-c38d16dc28d3
github.com/pkg/errors v0.9.1
github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2
go.uber.org/zap v1.27.0
gorm.io/driver/mysql v1.6.0
gorm.io/driver/sqlite v1.6.0
gorm.io/gorm v1.31.0
gorm.io/driver/mysql v1.5.7
gorm.io/driver/sqlite v1.5.6
gorm.io/gorm v1.25.11
)
require (
filippo.io/edwards25519 v1.1.0 // indirect
git.zhangdeman.cn/zhangdeman/easylock v0.0.0-20230731062340-983985c12eda // indirect
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20241101082529-28a6c68e38a4 // indirect
git.zhangdeman.cn/zhangdeman/network v0.0.0-20251013095944-5b89fff39bde // indirect
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20240311030808-e2a2e6a3c211 // indirect
git.zhangdeman.cn/zhangdeman/gin v0.0.0-20240817122134-195e39123512 // indirect
git.zhangdeman.cn/zhangdeman/network v0.0.0-20230925112156-f0eb86dd2442 // indirect
git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e // indirect
git.zhangdeman.cn/zhangdeman/websocket v0.0.0-20251013144324-313024336a6f // indirect
github.com/BurntSushi/toml v1.5.0 // indirect
git.zhangdeman.cn/zhangdeman/websocket v0.0.0-20240723075210-85feada512b2 // indirect
github.com/BurntSushi/toml v1.4.0 // indirect
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 // indirect
github.com/bytedance/gopkg v0.1.3 // indirect
github.com/bytedance/sonic v1.14.1 // indirect
github.com/bytedance/sonic/loader v0.3.0 // indirect
github.com/cloudwego/base64x v0.1.6 // indirect
github.com/bytedance/sonic v1.12.2 // indirect
github.com/bytedance/sonic/loader v0.2.0 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 // indirect
github.com/gabriel-vasile/mimetype v1.4.10 // indirect
github.com/gin-contrib/sse v1.1.0 // indirect
github.com/gin-gonic/gin v1.11.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.5 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/gin-gonic/gin v1.10.0 // indirect
github.com/go-ini/ini v1.67.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.28.0 // indirect
github.com/go-sql-driver/mysql v1.9.3 // indirect
github.com/goccy/go-json v0.10.5 // indirect
github.com/goccy/go-yaml v1.18.0 // indirect
github.com/go-playground/validator/v10 v10.22.0 // indirect
github.com/go-sql-driver/mysql v1.8.1 // indirect
github.com/goccy/go-json v0.10.3 // indirect
github.com/gorilla/websocket v1.5.3 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible // indirect
github.com/lestrrat-go/strftime v1.1.1 // indirect
github.com/lestrrat-go/strftime v1.1.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-sqlite3 v1.14.32 // indirect
github.com/mattn/go-sqlite3 v1.14.23 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mozillazg/go-pinyin v0.21.0 // indirect
github.com/mozillazg/go-pinyin v0.20.0 // indirect
github.com/mssola/user_agent v0.6.0 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/quic-go/qpack v0.5.1 // indirect
github.com/quic-go/quic-go v0.55.0 // indirect
github.com/sbabiv/xml2map v1.2.1 // indirect
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/tidwall/gjson v1.18.0 // indirect
github.com/tidwall/match v1.2.0 // indirect
github.com/tidwall/gjson v1.17.3 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.3.0 // indirect
go.uber.org/mock v0.6.0 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/arch v0.22.0 // indirect
golang.org/x/crypto v0.43.0 // indirect
golang.org/x/mod v0.29.0 // indirect
golang.org/x/net v0.46.0 // indirect
golang.org/x/sync v0.17.0 // indirect
golang.org/x/sys v0.37.0 // indirect
golang.org/x/text v0.30.0 // indirect
golang.org/x/tools v0.38.0 // indirect
golang.org/x/arch v0.10.0 // indirect
golang.org/x/crypto v0.26.0 // indirect
golang.org/x/net v0.28.0 // indirect
golang.org/x/sys v0.25.0 // indirect
golang.org/x/text v0.18.0 // indirect
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
google.golang.org/protobuf v1.36.10 // indirect
google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/olahol/melody.v1 v1.0.0-20170518105555-d52139073376 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

211
go.sum
View File

@ -1,67 +1,51 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250916024308-d378e6c57772 h1:Yo1ur3LnDF5s7F7tpJsNrdUSF8LwYKnN9TdQU32F3eU=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250916024308-d378e6c57772/go.mod h1:5p8CEKGBxi7qPtTXDI3HDmqKAfIm5i/aBWdrbkbdNjc=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240823041145-d4df71cf37e5 h1:pmIHln0gWW+5xAB762h3WDsRkZuYLUDndvJDsGMKoOY=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240823041145-d4df71cf37e5/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
git.zhangdeman.cn/zhangdeman/easylock v0.0.0-20230731062340-983985c12eda h1:bMD6r9gjRy7cO+T4zRQVYAesgIblBdTnhzT1vN5wjvI=
git.zhangdeman.cn/zhangdeman/easylock v0.0.0-20230731062340-983985c12eda/go.mod h1:dT0rmHcJ9Z9IqWeMIt7YzR88nKkNV2V3dfG0j9Q6lK0=
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20241101082529-28a6c68e38a4 h1:s6d4b6yY+NaK1AzoBD1pxqsuygEHQz0Oie86c45geDw=
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20241101082529-28a6c68e38a4/go.mod h1:V4Dfg1v/JVIZGEKCm6/aehs8hK+Xow1dkL1yiQymXlQ=
git.zhangdeman.cn/zhangdeman/logger v0.0.0-20250817142254-a501f79e7894 h1:7nT1CADIAO2lhikqM1lAFlwrJXa7gNaz5bcUB+LgAIE=
git.zhangdeman.cn/zhangdeman/logger v0.0.0-20250817142254-a501f79e7894/go.mod h1:UKGSNWsDmf6pBrC3SuC+jR7/Lj30c6b72hZi8dI+Vp8=
git.zhangdeman.cn/zhangdeman/logger v0.0.0-20251012094811-1afd71fd8627 h1:chAmVCoiWMcrmm+AfvesrhnZH+3+6LZZb+8UDj/E36M=
git.zhangdeman.cn/zhangdeman/logger v0.0.0-20251012094811-1afd71fd8627/go.mod h1:SZsX6q88TdR5JHZenesYhOw1x386ikfs2MkchQmW8D8=
git.zhangdeman.cn/zhangdeman/logger v0.0.0-20251013144549-29cc7ca2481e h1:bfhEntAdt9UrB5A7UC50ts2VoAfEY+524EX9lDC7Q/M=
git.zhangdeman.cn/zhangdeman/logger v0.0.0-20251013144549-29cc7ca2481e/go.mod h1:e9YroNosH0QICXABs59RV0UWx8BcFEJQto61iV6f9lM=
git.zhangdeman.cn/zhangdeman/network v0.0.0-20250726060351-78810e906bfa h1:r3AK2EKbQ82ShC5+AjbE95sqm90CkpbzLpmoV3zok9Q=
git.zhangdeman.cn/zhangdeman/network v0.0.0-20250726060351-78810e906bfa/go.mod h1:v0tMMfXvE4WyUxaRo1r/D20BAbMkT5QPLSW7XtgQOxo=
git.zhangdeman.cn/zhangdeman/network v0.0.0-20251013095944-5b89fff39bde h1:+3zIOditaUwzSpl2ybM1PYN4OYTIKiemMBt+pNv3Yko=
git.zhangdeman.cn/zhangdeman/network v0.0.0-20251013095944-5b89fff39bde/go.mod h1:Ewh0UYOqXxEh0khgHj9bDz1rbnd7cCCsJrcOTFX/8wg=
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20240311030808-e2a2e6a3c211 h1:I/wOsRpCSRkU9vo1u703slQsmK0wnNeZzsWQOGtIAG0=
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20240311030808-e2a2e6a3c211/go.mod h1:SrtvrQRdzt+8KfYzvosH++gWxo2ShPTzR1m3VQ6uX7U=
git.zhangdeman.cn/zhangdeman/gin v0.0.0-20240817122134-195e39123512 h1:j+zH8gl4aEg24GWCutddnH5hw4eAuFJLW6vvJUJiJpM=
git.zhangdeman.cn/zhangdeman/gin v0.0.0-20240817122134-195e39123512/go.mod h1:twDDFXzPJ56qfAG1ZtPhvwXmtZG+aRlk2dnnjufh/hs=
git.zhangdeman.cn/zhangdeman/logger v0.0.0-20240725055115-98eb52ae307a h1:22VkxGmpS58zHA8tf75lPr/3S6hmHKP00w/jUa700Ps=
git.zhangdeman.cn/zhangdeman/logger v0.0.0-20240725055115-98eb52ae307a/go.mod h1:phaF6LMebn7Fpp8J/mOzHRYGniKuCk78k4N53T2m8NI=
git.zhangdeman.cn/zhangdeman/network v0.0.0-20230925112156-f0eb86dd2442 h1:1eBf0C0gdpBQOqjTK3UCw/mwzQ/SCodx3iTQtidx9eE=
git.zhangdeman.cn/zhangdeman/network v0.0.0-20230925112156-f0eb86dd2442/go.mod h1:hFYWiS+ExIuJJJdwHWy4P3pVHbd/0mpv53qlbhDNdTI=
git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20240122104027-4928421213c0 h1:gUDlQMuJ4xNfP2Abl1Msmpa3fASLWYkNlqDFF/6GN0Y=
git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20240122104027-4928421213c0/go.mod h1:VHb9qmhaPDAQDcS6vUiDCamYjZ4R5lD1XtVsh55KsMI=
git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20251013024601-da007da2fb42 h1:VjYrb4adud7FHeiYS9XA0B/tOaJjfRejzQAlwimrrDc=
git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20251013024601-da007da2fb42/go.mod h1:VHb9qmhaPDAQDcS6vUiDCamYjZ4R5lD1XtVsh55KsMI=
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20250504055908-8d68e6106ea9 h1:/GLQaFoLb+ciHOtAS2BIyPNnf4O5ME3AC5PUaJY9kfs=
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20250504055908-8d68e6106ea9/go.mod h1:ABJ655C5QenQNOzf7LjCe4sSB52CXvaWLX2Zg4uwDJY=
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20251013044511-86c1a4a3a9dd h1:kTZOpR8iHx27sUufMWVYhDZx9Q4h80j7RWlaR8GIBiU=
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20251013044511-86c1a4a3a9dd/go.mod h1:pLrQ63JICi81/3w2BrD26QZiu+IpddvEVfMJ6No3Xb4=
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20240618035451-8d48a6bd39dd h1:2Y37waOVCmVvx0Rp8VGEptE2/2JVMImtxB4dKKDk/3w=
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20240618035451-8d48a6bd39dd/go.mod h1:6+7whkCmb4sJDIfH3HxNuXRveaM0gCCNWd2uXZqNtIE=
git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e h1:Q973S6CcWr1ICZhFI1STFOJ+KUImCl2BaIXm6YppBqI=
git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e/go.mod h1:VpPjBlwz8U+OxZuxzHQBv1aEEZ3pStH6bZvT21ADEbI=
git.zhangdeman.cn/zhangdeman/websocket v0.0.0-20241125101541-c5ea194c9c1e h1:YE2Gi+M03UDImIpWa3I7jzSesyfu2RL8x/4ONs5v0oE=
git.zhangdeman.cn/zhangdeman/websocket v0.0.0-20241125101541-c5ea194c9c1e/go.mod h1:L/7JugxKZL3JP9JP/XDvPAPz0FQXG1u181Su1+u/d1c=
git.zhangdeman.cn/zhangdeman/websocket v0.0.0-20251013144324-313024336a6f h1:InxNoLPHBLwCLblW0lsL2P1ZBYoUEzw9Yh+KNLt4Xmg=
git.zhangdeman.cn/zhangdeman/websocket v0.0.0-20251013144324-313024336a6f/go.mod h1:Pbs7tusW6RNcqrNCVcLE2zrM8JfPaO7lBJQuRiAzzLs=
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250321102712-1cbfbe959740 h1:zPUoylfJTbc0EcxW+NEzOTBmoeFZ2I/rLFBnEzxb4Wk=
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250321102712-1cbfbe959740/go.mod h1:1ct92dbVc49pmXusA/iGfcQUJzcYmJ+cjAhgc3sDv1I=
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20251013091053-fa9097dc09fc h1:q+0ZRJ6NxhPHeBqzZPOt27RMuKvGJpwg37W9JdhKpjA=
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20251013091053-fa9097dc09fc/go.mod h1:mBvTwcdqHRF3QIkAh92j/JRhru2LzyJ2LBqolxjzzKE=
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20251013094128-d57d32b103be h1:mlmXacZHRKxmFmFKNFYRjZJ8+z2+QW3CH8L7AzoMTcQ=
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20251013094128-d57d32b103be/go.mod h1:mBvTwcdqHRF3QIkAh92j/JRhru2LzyJ2LBqolxjzzKE=
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20251014035305-c0ec06fa6dff h1:ym1Qs4diJe27CK/0K6vy7RvgH90mXgslWA++L8mXaKE=
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20251014035305-c0ec06fa6dff/go.mod h1:mBvTwcdqHRF3QIkAh92j/JRhru2LzyJ2LBqolxjzzKE=
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
git.zhangdeman.cn/zhangdeman/websocket v0.0.0-20240723075210-85feada512b2 h1:P2kuhU2TFWk9mPbJlZCK6FMDVS7S3NGafWKD4eNqKiI=
git.zhangdeman.cn/zhangdeman/websocket v0.0.0-20240723075210-85feada512b2/go.mod h1:7KaMpQmWgiNLpEkaV7oDtep7geI1f/VoCoPVcyvMjAE=
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20240823103024-c38d16dc28d3 h1:RcWNxrHmhZksZWrP/HLEwAM8uIIHYlPLQ20HnLzC+j0=
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20240823103024-c38d16dc28d3/go.mod h1:KcojKP22mv9/IZrQWlIBfa1EuBxtEOqfWMgN3SYK2N8=
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 h1:OYA+5W64v3OgClL+IrOD63t4i/RW7RqrAVl9LTZ9UqQ=
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394/go.mod h1:Q8n74mJTIgjX4RBBcHnJ05h//6/k6foqmgE45jTQtxg=
github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M=
github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM=
github.com/bytedance/sonic v1.14.1 h1:FBMC0zVz5XUmE4z9wF4Jey0An5FueFvOsTKKKtwIl7w=
github.com/bytedance/sonic v1.14.1/go.mod h1:gi6uhQLMbTdeP0muCnrjHLeCUPyb70ujhnNlhOylAFc=
github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA=
github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M=
github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU=
github.com/bytedance/sonic v1.12.2 h1:oaMFuRTpMHYLpCntGca65YWt5ny+wAceDERTkT2L9lg=
github.com/bytedance/sonic v1.12.2/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk=
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
github.com/bytedance/sonic/loader v0.2.0 h1:zNprn+lsIP06C/IqCHs3gPQIvnvpKbbxyXQP1iU4kWM=
github.com/bytedance/sonic/loader v0.2.0/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 h1:CaO/zOnF8VvUfEbhRatPcwKVWamvbYd8tQGRWacE9kU=
github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1/go.mod h1:+hnT3ywWDTAFrW5aE+u2Sa/wT555ZqwoCS+pk3p6ry4=
github.com/gabriel-vasile/mimetype v1.4.10 h1:zyueNbySn/z8mJZHLt6IPw0KoZsiQNszIpU+bX4+ZK0=
github.com/gabriel-vasile/mimetype v1.4.10/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w=
github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM=
github.com/gin-gonic/gin v1.11.0 h1:OW/6PLjyusp2PPXtyxKHU0RbX6I/l28FTdDlae5ueWk=
github.com/gin-gonic/gin v1.11.0/go.mod h1:+iq/FyxlGzII0KHiBGjuNn4UNENUlKbGlNmc+W50Dls=
github.com/gabriel-vasile/mimetype v1.4.5 h1:J7wGKdGu33ocBOhGy0z653k/lFKLFDPJMG8Gql0kxn4=
github.com/gabriel-vasile/mimetype v1.4.5/go.mod h1:ibHel+/kbxn9x2407k1izTA1S81ku1z/DlgOW2QE0M4=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
@ -70,21 +54,16 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.28.0 h1:Q7ibns33JjyW48gHkuFT91qX48KG0ktULL6FgHdG688=
github.com/go-playground/validator/v10 v10.28.0/go.mod h1:GoI6I1SjPBh9p7ykNE/yj3fFYbyDOpwMn5KXd+m2hUU=
github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw=
github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/go-playground/validator/v10 v10.22.0 h1:k6HsTZ0sTnROkhS//R0O+55JgM8C4Bx7ia+JlgcnOao=
github.com/go-playground/validator/v10 v10.22.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g=
github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
@ -95,119 +74,101 @@ github.com/jonboulle/clockwork v0.3.0 h1:9BSCMi8C+0qdApAp4auwX0RkLGUjs956h0EkuQy
github.com/jonboulle/clockwork v0.3.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8=
github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is=
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible h1:Y6sqxHMyB1D2YSzWkLibYKgg+SwmyFU9dF2hn6MdTj4=
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible/go.mod h1:ZQnN8lSECaebrkQytbHj4xNgtg8CR7RYXnPok8e0EHA=
github.com/lestrrat-go/strftime v1.1.1 h1:zgf8QCsgj27GlKBy3SU9/8MMgegZ8UCzlCyHYrUF0QU=
github.com/lestrrat-go/strftime v1.1.1/go.mod h1:YDrzHJAODYQ+xxvrn5SG01uFIQAeDTzpxNVppCz7Nmw=
github.com/lestrrat-go/strftime v1.1.0 h1:gMESpZy44/4pXLO/m+sL0yBd1W6LjgjrrD4a68Gapyg=
github.com/lestrrat-go/strftime v1.1.0/go.mod h1:uzeIB52CeUJenCo1syghlugshMysrqUT51HlxphXVeI=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.32 h1:JD12Ag3oLy1zQA+BNn74xRgaBbdhbNIDYvQUEuuErjs=
github.com/mattn/go-sqlite3 v1.14.32/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/mattn/go-sqlite3 v1.14.23 h1:gbShiuAP1W5j9UOksQ06aiiqPMxYecovVGwmTxWtuw0=
github.com/mattn/go-sqlite3 v1.14.23/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mozillazg/go-pinyin v0.21.0 h1:Wo8/NT45z7P3er/9YSLHA3/kjZzbLz5hR7i+jGeIGao=
github.com/mozillazg/go-pinyin v0.21.0/go.mod h1:iR4EnMMRXkfpFVV5FMi4FNB6wGq9NV6uDWbUuPhP4Yc=
github.com/mozillazg/go-pinyin v0.20.0 h1:BtR3DsxpApHfKReaPO1fCqF4pThRwH9uwvXzm+GnMFQ=
github.com/mozillazg/go-pinyin v0.20.0/go.mod h1:iR4EnMMRXkfpFVV5FMi4FNB6wGq9NV6uDWbUuPhP4Yc=
github.com/mssola/user_agent v0.6.0 h1:uwPR4rtWlCHRFyyP9u2KOV0u8iQXmS7Z7feTrstQwk4=
github.com/mssola/user_agent v0.6.0/go.mod h1:TTPno8LPY3wAIEKRpAtkdMT0f8SE24pLRGPahjCH4uw=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
github.com/quic-go/quic-go v0.55.0 h1:zccPQIqYCXDt5NmcEabyYvOnomjs8Tlwl7tISjJh9Mk=
github.com/quic-go/quic-go v0.55.0/go.mod h1:DR51ilwU1uE164KuWXhinFcKWGlEjzys2l8zUl5Ss1U=
github.com/sbabiv/xml2map v1.2.1 h1:1lT7t0hhUvXZCkdxqtq4n8/ZCnwLWGq4rDuDv5XOoFE=
github.com/sbabiv/xml2map v1.2.1/go.mod h1:2TPoAfcaM7+Sd4iriPvzyntb2mx7GY+kkQpB/GQa/eo=
github.com/smarty/assertions v1.15.0 h1:cR//PqUBUiQRakZWqBiFFQ9wb8emQGDb0HeGdqGByCY=
github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec=
github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sSznIX1xY=
github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tidwall/gjson v1.17.3 h1:bwWLZU7icoKRG+C+0PNwIKC6FCJO/Q3p2pZvuP0jN94=
github.com/tidwall/gjson v1.17.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/match v1.2.0 h1:0pt8FlkOwjN2fPt4bIl4BoNxb98gGHN2ObFEDkrfZnM=
github.com/tidwall/match v1.2.0/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.3.0 h1:Qd2W2sQawAfG8XSvzwhBeoGq71zXOC/Q1E9y/wUcsUA=
github.com/ugorji/go/codec v1.3.0/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2 h1:zzrxE1FKn5ryBNl9eKOeqQ58Y/Qpo3Q9QNxKHX5uzzQ=
github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2/go.mod h1:hzfGeIUDq/j97IG+FhNqkowIyEcD88LrW6fyU3K3WqY=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/arch v0.22.0 h1:c/Zle32i5ttqRXjdLyyHZESLD/bB90DCU1g9l/0YBDI=
golang.org/x/arch v0.22.0/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A=
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/arch v0.10.0 h1:S3huipmSclq3PJMNe76NGwkBR504WFkQ5dhzWzP8ZW8=
golang.org/x/arch v0.10.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU=
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/olahol/melody.v1 v1.0.0-20170518105555-d52139073376 h1:sY2a+y0j4iDrajJcorb+a0hJIQ6uakU5gybjfLWHlXo=
gopkg.in/olahol/melody.v1 v1.0.0-20170518105555-d52139073376/go.mod h1:BHKOc1m5wm8WwQkMqYBoo4vNxhmF7xg8+xhG8L+Cy3M=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/mysql v1.6.0 h1:eNbLmNTpPpTOVZi8MMxCi2aaIm0ZpInbORNXDwyLGvg=
gorm.io/driver/mysql v1.6.0/go.mod h1:D/oCC2GWK3M/dqoLxnOlaNKmXz8WNTfcS9y5ovaSqKo=
gorm.io/driver/sqlite v1.6.0 h1:WHRRrIiulaPiPFmDcod6prc4l2VGVWHz80KspNsxSfQ=
gorm.io/driver/sqlite v1.6.0/go.mod h1:AO9V1qIQddBESngQUKWL9yoH93HIeA1X6V633rBwyT8=
gorm.io/gorm v1.31.0 h1:0VlycGreVhK7RF/Bwt51Fk8v0xLiiiFdbGDPIZQ7mJY=
gorm.io/gorm v1.31.0/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs=
gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo=
gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
gorm.io/driver/sqlite v1.5.6 h1:fO/X46qn5NUEEOZtnjJRWRzZMe8nqJiQ9E+0hi+hKQE=
gorm.io/driver/sqlite v1.5.6/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDah4=
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
gorm.io/gorm v1.25.11 h1:/Wfyg1B/je1hnDx3sMkX+gAlxrlZpn6X0BXRlwXlvHg=
gorm.io/gorm v1.25.11/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=

View File

@ -11,7 +11,7 @@ import (
"fmt"
"git.zhangdeman.cn/zhangdeman/database/install/define"
"git.zhangdeman.cn/zhangdeman/wrapper/op_string"
"git.zhangdeman.cn/zhangdeman/wrapper"
)
var (
@ -42,7 +42,7 @@ func (h *helper) NewPrimaryID(name string, comment string) *define.Field {
Type: "BIGINT(20)",
Unsigned: true,
NotNull: true,
DefaultValue: op_string.ToBaseValuePtr[string]("0").Value,
DefaultValue: wrapper.String("0").ToStringPtr().Value,
PrimaryKey: true,
IsAutoIncrement: true,
Comment: comment,
@ -60,7 +60,7 @@ func (h *helper) NewBigintField(name string, unsigned bool, defaultVal string, c
Type: "BIGINT(20)",
Unsigned: unsigned,
NotNull: true,
DefaultValue: op_string.ToBaseValuePtr[string](defaultVal).Value,
DefaultValue: wrapper.String(defaultVal).ToStringPtr().Value,
PrimaryKey: false,
IsAutoIncrement: false,
Comment: comment,
@ -78,7 +78,7 @@ func (h *helper) NewIntField(name string, unsigned bool, defaultVal string, comm
Type: "INT(11)",
Unsigned: unsigned,
NotNull: true,
DefaultValue: op_string.ToBaseValuePtr[string](defaultVal).Value,
DefaultValue: wrapper.String(defaultVal).ToStringPtr().Value,
PrimaryKey: false,
IsAutoIncrement: false,
Comment: comment,
@ -96,7 +96,7 @@ func (h *helper) NewVarcharField(name string, length int, defaultVal string, com
Type: fmt.Sprintf("VARCHAR(%v)", length),
Unsigned: false,
NotNull: true,
DefaultValue: op_string.ToBaseValuePtr[string](defaultVal).Value,
DefaultValue: wrapper.String(defaultVal).ToStringPtr().Value,
PrimaryKey: false,
IsAutoIncrement: false,
Comment: comment,
@ -114,7 +114,7 @@ func (h *helper) NewCharField(name string, length int, comment string, defaultVa
Type: fmt.Sprintf("CHAR(%v)", length),
Unsigned: false,
NotNull: true,
DefaultValue: op_string.ToBaseValuePtr[string](defaultVal).Value,
DefaultValue: wrapper.String(defaultVal).ToStringPtr().Value,
PrimaryKey: false,
IsAutoIncrement: false,
Comment: comment,
@ -150,7 +150,7 @@ func (h *helper) NewTimestampField(name string, comment string, defaultVal strin
Type: "TIMESTAMP",
Unsigned: false,
NotNull: true,
DefaultValue: op_string.ToBaseValuePtr[string](defaultVal).Value,
DefaultValue: wrapper.String(defaultVal).ToStringPtr().Value,
PrimaryKey: false,
IsAutoIncrement: false,
Comment: comment,
@ -168,7 +168,7 @@ func (h *helper) NewTimestampFieldWithUpdate(name string, comment string, defaul
Type: "TIMESTAMP",
Unsigned: false,
NotNull: true,
DefaultValue: op_string.ToBaseValuePtr[string](defaultVal).Value,
DefaultValue: wrapper.String(defaultVal).ToStringPtr().Value,
PrimaryKey: false,
IsAutoIncrement: false,
OnUpdate: "current_timestamp()",

View File

@ -1,176 +0,0 @@
// Package logger ...
//
// Description : logger ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2025-10-12 17:23
package logger
import (
"context"
"fmt"
"strings"
"time"
"git.zhangdeman.cn/zhangdeman/consts"
"gorm.io/gorm"
"go.uber.org/zap/zapcore"
"go.uber.org/zap"
loggerPkg "git.zhangdeman.cn/zhangdeman/logger"
"gorm.io/gorm/logger"
)
// NewGormV2 获取日志实例
func NewGormV2(loggerLevel consts.LogLevel, consoleOutput bool, encoder zapcore.Encoder, splitConfig *loggerPkg.RotateLogConfig, traceIDField string, skip int) (logger.Interface, error) {
logConfList := []loggerPkg.SetLoggerOptionFunc{loggerPkg.WithEncoder(encoder), loggerPkg.WithCallerSkip(skip), loggerPkg.WithCaller()}
if consoleOutput {
logConfList = append(logConfList, loggerPkg.WithConsoleOutput())
}
logInstance, err := loggerPkg.NewLogger(loggerLevel, splitConfig, logConfList...)
if nil != err {
return nil, err
}
if len(traceIDField) == 0 {
traceIDField = "trace_id"
}
return &Gorm{
instance: logInstance,
traceIDField: traceIDField,
}, nil
}
// NewGormLoggerWithInstance 获取gorm日志实现
func NewGormLoggerWithInstance(outCtx context.Context, dbClient *gorm.DB, instance *zap.Logger, node string, extraCtxFieldList []string) logger.Interface {
nodeArr := strings.Split(node, "|")
i := &Gorm{
dbClient: dbClient,
instance: instance,
traceIDField: consts.GinTraceIDField,
extraCtxFieldList: extraCtxFieldList,
flag: "",
node: node,
outCtx: outCtx,
}
if len(nodeArr) >= 2 {
i.node = nodeArr[1]
i.flag = nodeArr[0]
}
return i
}
// Gorm v2 版本库日志实现
type Gorm struct {
dbClient *gorm.DB
instance *zap.Logger // 日志实例
traceIDField string // 串联请求上下文的的ID
extraCtxFieldList []string // 从请求上线问提取的字段
flag string // 数据库标识
node string // 数据库节点 master / slave
outCtx context.Context
}
// LogMode ...
func (g *Gorm) LogMode(level logger.LogLevel) logger.Interface {
return g
}
// Info 日志
func (g *Gorm) Info(ctx context.Context, s string, i ...any) {
g.write(ctx, s, consts.LogLevelInfo, map[string]any{
"log_data": i,
})
}
// Warn ...
func (g *Gorm) Warn(ctx context.Context, s string, i ...any) {
g.write(ctx, s, consts.LogLevelWarn, map[string]any{
"log_data": i,
})
}
// Error 日志
func (g *Gorm) Error(ctx context.Context, s string, i ...any) {
g.write(ctx, s, consts.LogLevelError, map[string]any{
"log_data": i,
})
}
// Trace Trace 记录
func (g *Gorm) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) {
start := begin.UnixNano()
end := time.Now().UnixNano()
sql := ""
affectRows := int64(0)
if nil != fc {
sql, affectRows = fc()
}
logData := map[string]any{
"db_flag": g.flag,
"db_node": g.node,
"begin_time": start,
"finish_time": end,
"used_time": (end - start) / 1e6,
"sql": sql,
"affect_rows": affectRows,
"err": "",
}
if nil != err {
logData["err"] = err.Error()
}
g.write(ctx, "SQL执行记录", consts.LogLevelInfo, logData)
}
// write ...
func (g *Gorm) write(ctx context.Context, message string, level consts.LogLevel, data map[string]any) {
if len(message) == 0 {
message = "SQL执行记录"
}
if nil == g.instance {
// 未设置日志实例
return
}
if nil == data {
data = make(map[string]any)
}
if nil != data["sql"] {
sqlStr := strings.TrimSpace(fmt.Sprintf("%v", data["sql"]))
sqlArr := strings.Split(sqlStr, " ")
if len(sqlArr) > 0 {
data["sql_type"] = strings.ToUpper(sqlArr[0])
}
}
if nil == g.outCtx {
g.outCtx = context.Background()
}
dataList := loggerPkg.ZapLogDataList(loggerPkg.NewLogData(g.outCtx, consts.LogTypeDatabase, "", data))
switch level {
case consts.LogLevelDebug:
g.instance.Debug(message, dataList...)
case consts.LogLevelInfo:
g.instance.Info(message, dataList...)
case consts.LogLevelWarn:
g.instance.Warn(message, dataList...)
case consts.LogLevelError:
g.instance.Error(message, dataList...)
case consts.LogLevelPanic:
g.instance.Panic(message, dataList...)
default:
g.instance.Info(message, dataList...)
}
}
// GetGormSQL 获取trace fn
func GetGormSQL(dbClient *gorm.DB) func() (string, int64) {
return func() (string, int64) {
return dbClient.Dialector.Explain(dbClient.Statement.SQL.String(), dbClient.Statement.Vars...), dbClient.RowsAffected
}
}

162
option.go
View File

@ -11,23 +11,19 @@ import (
"encoding/json"
"errors"
"fmt"
"reflect"
"strings"
"git.zhangdeman.cn/zhangdeman/consts"
"git.zhangdeman.cn/zhangdeman/database/define"
"git.zhangdeman.cn/zhangdeman/op_type"
"git.zhangdeman.cn/zhangdeman/serialize"
"reflect"
"strings"
)
// WithForUpdate 查询语句增加互斥锁
func WithForUpdate(forUpdate bool) define.SetOption {
return func(o *define.Option) {
o.ForUpdate = forUpdate
}
}
// WithModel ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:18 2024/1/15
func WithModel(model any) define.SetOption {
return func(o *define.Option) {
o.Model = model
@ -35,6 +31,10 @@ func WithModel(model any) define.SetOption {
}
// WithTable 设置查询的表名
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 20:56 2023/3/22
func WithTable(tableName string) define.SetOption {
return func(o *define.Option) {
o.Table = tableName
@ -42,6 +42,10 @@ func WithTable(tableName string) define.SetOption {
}
// WithWhere 设置where条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 12:17 2022/5/15
func WithWhere[T op_type.BaseType](where map[string]T) define.SetOption {
return func(o *define.Option) {
if nil == o.Where {
@ -54,6 +58,10 @@ func WithWhere[T op_type.BaseType](where map[string]T) define.SetOption {
}
// WithLimit 设置limit条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 12:00 2022/5/15
func WithLimit[T op_type.Int](limit T, offset T) define.SetOption {
return func(o *define.Option) {
o.Limit = int(limit)
@ -61,14 +69,11 @@ func WithLimit[T op_type.Int](limit T, offset T) define.SetOption {
}
}
func WithClearLimit() define.SetOption {
return func(o *define.Option) {
o.Limit = 0
o.Offset = 0
}
}
// WithLimitByPageAndSize 通过page和size构建条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 21:42 2023/10/14
func WithLimitByPageAndSize[T op_type.Int](page T, size T) define.SetOption {
return func(o *define.Option) {
if size > 0 {
@ -82,6 +87,10 @@ func WithLimitByPageAndSize[T op_type.Int](page T, size T) define.SetOption {
}
// WithIn 设置in条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 12:23 2022/5/15
func WithIn[T op_type.Array](field string, value T) define.SetOption {
return func(o *define.Option) {
if nil == value {
@ -97,7 +106,11 @@ func WithIn[T op_type.Array](field string, value T) define.SetOption {
}
}
// WithBatchIn 批量设置IN条件
// WithBatchIn ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 12:24 2022/5/15
func WithBatchIn[T op_type.Array](batchIn map[string]T) define.SetOption {
return func(o *define.Option) {
if nil == o.In {
@ -110,6 +123,10 @@ func WithBatchIn[T op_type.Array](batchIn map[string]T) define.SetOption {
}
// WithNotIn 设置 notin 条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:18 2022/5/15
func WithNotIn[T op_type.Array](field string, value T) define.SetOption {
return func(o *define.Option) {
if nil == o.NotIn {
@ -123,6 +140,10 @@ func WithNotIn[T op_type.Array](field string, value T) define.SetOption {
}
// WithBatchNotIn 批量设置 NOT IN
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:23 2022/5/15
func WithBatchNotIn[T op_type.Array](data map[string]T) define.SetOption {
return func(o *define.Option) {
if nil == o.NotIn {
@ -138,6 +159,10 @@ func WithBatchNotIn[T op_type.Array](data map[string]T) define.SetOption {
}
// WithStart >= 条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:01 2022/5/15
func WithStart(field string, value any) define.SetOption {
return func(o *define.Option) {
if nil == o.Start {
@ -148,6 +173,10 @@ func WithStart(field string, value any) define.SetOption {
}
// WithBatchStart 批量设置起始条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:03 2022/5/15
func WithBatchStart(data map[string]any) define.SetOption {
return func(o *define.Option) {
if nil == o.Start {
@ -160,6 +189,10 @@ func WithBatchStart(data map[string]any) define.SetOption {
}
// WithEnd 设置 < 条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:07 2022/5/15
func WithEnd(field string, value any) define.SetOption {
return func(o *define.Option) {
if nil == o.End {
@ -170,6 +203,10 @@ func WithEnd(field string, value any) define.SetOption {
}
// WithBatchEnd 批量设置 < 条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:10 2022/5/15
func WithBatchEnd(data map[string]any) define.SetOption {
return func(o *define.Option) {
if nil == o.End {
@ -182,6 +219,10 @@ func WithBatchEnd(data map[string]any) define.SetOption {
}
// WithLike 设置 like 查询条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:16 2022/5/15
func WithLike(field string, value string) define.SetOption {
return func(o *define.Option) {
if nil == o.Like {
@ -195,6 +236,10 @@ func WithLike(field string, value string) define.SetOption {
}
// WithBatchLike 批量设置like条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:19 2022/5/15
func WithBatchLike(data map[string]string) define.SetOption {
return func(o *define.Option) {
if nil == o.Like {
@ -210,6 +255,10 @@ func WithBatchLike(data map[string]string) define.SetOption {
}
// WithNotLike NOT LIKE 语句
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:50 2022/5/15
func WithNotLike(field string, value string) define.SetOption {
return func(o *define.Option) {
if nil == o.NotLike {
@ -223,6 +272,10 @@ func WithNotLike(field string, value string) define.SetOption {
}
// WithBatchNotLike ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:52 2022/5/15
func WithBatchNotLike(data map[string]string) define.SetOption {
return func(o *define.Option) {
if nil == o.NotLike {
@ -238,6 +291,10 @@ func WithBatchNotLike(data map[string]string) define.SetOption {
}
// WithNotEqual 设置不等于语句
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:31 2022/5/15
func WithNotEqual[T op_type.BaseType](field string, value T) define.SetOption {
return func(o *define.Option) {
if nil == o.NotEqual {
@ -248,6 +305,10 @@ func WithNotEqual[T op_type.BaseType](field string, value T) define.SetOption {
}
// WithBatchNotEqual 批量设置不等于条件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:33 2022/5/15
func WithBatchNotEqual[T op_type.BaseType](data map[string]T) define.SetOption {
return func(o *define.Option) {
if nil == o.NotEqual {
@ -260,6 +321,10 @@ func WithBatchNotEqual[T op_type.BaseType](data map[string]T) define.SetOption {
}
// WithOR 设置OR语句
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 20:03 2022/7/23
func WithOR(orConditionList ...define.SetOption) define.SetOption {
return func(o *define.Option) {
if nil == o.OR {
@ -270,34 +335,49 @@ func WithOR(orConditionList ...define.SetOption) define.SetOption {
}
// WithOrder 设置排序规则
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 20:15 2022/10/20
func WithOrder(orderRuleList ...string) define.SetOption {
return func(o *define.Option) {
if len(orderRuleList) != 2 {
return
}
if len(orderRuleList[0]) == 0 {
// 未指定排序字段
return
}
if len(orderRuleList[1]) == 0 {
// 未指定排序规则, 默认倒序
orderRuleList[1] = "DESC"
}
o.Order = orderRuleList
}
}
// WithOrderDesc 降序排序
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:09 2023/4/3
func WithOrderDesc(field string) define.SetOption {
return WithOrder(field, "DESC")
return func(o *define.Option) {
if nil == o.Order {
o.Order = make([]string, 0)
}
o.Order = append(o.Order, field+" desc")
}
}
// WithOrderAsc 升序排序
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:09 2023/4/3
func WithOrderAsc(field string) define.SetOption {
return WithOrder(field, "ASC")
return func(o *define.Option) {
if nil == o.Order {
o.Order = make([]string, 0)
}
o.Order = append(o.Order, field+" asc")
}
}
// newOption 生成新的option
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:46 2024/8/9
func newOption(setOptionList ...define.SetOption) *define.Option {
o := &define.Option{}
for _, item := range setOptionList {
@ -307,6 +387,10 @@ func newOption(setOptionList ...define.SetOption) *define.Option {
}
// optionToSql 基于 option 配置生成sql
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:46 2024/8/9
func optionToSql(o *define.Option) (sqlBuildResult string, bindValue []any) {
bindValue = make([]any, 0)
sqlBuildResultBlockList := make([]string, 0)
@ -394,6 +478,10 @@ func optionToSql(o *define.Option) (sqlBuildResult string, bindValue []any) {
}
// parseInSql 解析in语句需要绑定占位符以及数据
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 22:07 2024/8/9
func parseInSql(fieldValue any) (string, []any) {
byteData, _ := json.Marshal(fieldValue)
var dataList []any
@ -409,6 +497,10 @@ func parseInSql(fieldValue any) (string, []any) {
}
// WithBetween between 语句
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:52 2024/8/23
func WithBetween(field string, left any, right any) define.SetOption {
return func(o *define.Option) {
if nil == o.Between {
@ -419,6 +511,10 @@ func WithBetween(field string, left any, right any) define.SetOption {
}
// WithNotBetween not between 语句
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:52 2024/8/23
func WithNotBetween(field string, left any, right any) define.SetOption {
return func(o *define.Option) {
if nil == o.NotBetween {
@ -429,6 +525,10 @@ func WithNotBetween(field string, left any, right any) define.SetOption {
}
// WithAnyCondition 设置任意查询条件, 仅 where 子句 in / not in / like / not like / == / !=
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 14:48 2024/8/23
func WithAnyCondition(column string, operate string, value any) (define.SetOption, error) {
if nil == value {
return nil, errors.New("value is nil")

View File

@ -7,50 +7,47 @@
// Date : 2021-10-25 4:50 下午
package sql2go
import "git.zhangdeman.cn/zhangdeman/consts"
// sqlTypeMap mysql数据类型 => go 数据类型映射
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 4:50 下午 2021/10/25
var sqlTypeMap = map[string]string{
"int": consts.DataTypeInt.String(),
"integer": consts.DataTypeInt.String(),
"tinyint": consts.DataTypeInt8.String(),
"smallint": consts.DataTypeInt16.String(),
"mediumint": consts.DataTypeInt32.String(),
"bigint": consts.DataTypeInt64.String(),
"int unsigned": consts.DataTypeUint.String(),
"integer unsigned": consts.DataTypeUint.String(),
"tinyint unsigned": consts.DataTypeUint8.String(),
"smallint unsigned": consts.DataTypeUint16.String(),
"mediumint unsigned": consts.DataTypeUint32.String(),
"bigint unsigned": consts.DataTypeUint64.String(),
"int": "int",
"integer": "int",
"tinyint": "int8",
"smallint": "int16",
"mediumint": "int32",
"bigint": "int64",
"int unsigned": "uint",
"integer unsigned": "uint",
"tinyint unsigned": "uint8",
"smallint unsigned": "uint16",
"mediumint unsigned": "uint32",
"bigint unsigned": "uint64",
"bit": "byte",
"bool": consts.DataTypeBool.String(),
"enum": consts.DataTypeString.String(),
"set": consts.DataTypeString.String(),
"varchar": consts.DataTypeString.String(),
"char": consts.DataTypeString.String(),
"tinytext": consts.DataTypeString.String(),
"mediumtext": consts.DataTypeString.String(),
"text": consts.DataTypeString.String(),
"longtext": consts.DataTypeString.String(),
"blob": consts.DataTypeString.String(),
"tinyblob": consts.DataTypeString.String(),
"mediumblob": consts.DataTypeString.String(),
"longblob": consts.DataTypeString.String(),
"bool": "bool",
"enum": "string",
"set": "string",
"varchar": "string",
"char": "string",
"tinytext": "string",
"mediumtext": "string",
"text": "string",
"longtext": "string",
"blob": "string",
"tinyblob": "string",
"mediumblob": "string",
"longblob": "string",
"date": "time.Time",
"datetime": "time.Time",
"timestamp": "time.Time",
"time": "time.Time",
"float": consts.DataTypeFloat64.String(),
"double": consts.DataTypeFloat64.String(),
"decimal": consts.DataTypeFloat64.String(),
"binary": consts.DataTypeString.String(),
"varbinary": consts.DataTypeString.String(),
"json": consts.DataTypeString.String(),
"float": "float64",
"double": "float64",
"decimal": "float64",
"binary": "string",
"varbinary": "string",
}
const (

View File

@ -9,16 +9,15 @@ package sql2go
import (
"errors"
wrapperType "git.zhangdeman.cn/zhangdeman/wrapper"
"strings"
"git.zhangdeman.cn/zhangdeman/wrapper/op_string"
"github.com/xwb1989/sqlparser"
)
const (
// CreateSQLColumnTPL 每个字段的模版
CreateSQLColumnTPL = " {FIELD} {TYPE} `json:\"{JSON_TAG}\" gorm:\"column:{COLUMN};default:{DEFAULT_VALUE};{NOT_NULL}\" dc:\"{COMMENT}\"`"
CreateSQLColumnTPL = " {FIELD} {TYPE} `json:\"{JSON_TAG}\" gorm:\"column:{COLUMN};default:{DEFAULT_VALUE};{NOT_NULL}\"` // {COMMENT}"
// TableColumnTpl 每个字段的模版
TableColumnTpl = " {FIELD} string `json:\"{JSON_TAG}\"`"
// TableColumnDescTpl 字段描述
@ -72,7 +71,7 @@ func ParseCreateTableSql(sql string) (*BasicTableInfo, error) {
return nil, errors.New("input sql is not ddl")
}
basic.TableName = sqlparser.String(r.NewName)
basic.ModelStructName = op_string.SnakeCaseToCamel(basic.TableName)
basic.ModelStructName = wrapperType.String(basic.TableName).SnakeCaseToCamel()
// 生成model sql
basic.ModelStruct = generateTable(basic.TableName, basic.ModelStructName, r.TableSpec.Columns)
@ -94,26 +93,19 @@ func generateTable(tableName string, modelStructName string, columnList []*sqlpa
for _, item := range columnList {
comment := ""
if item.Type.Comment == nil || item.Type.Comment.Val == nil {
if item.Type.Comment == nil {
comment = item.Name.String()
} else {
comment = string(item.Type.Comment.Val)
}
if comment == "" {
comment = item.Name.String()
}
data := map[string]string{
"{FIELD}": op_string.SnakeCaseToCamel(item.Name.String()),
"{FIELD}": wrapperType.String(item.Name.String()).SnakeCaseToCamel(),
"{COLUMN}": item.Name.String(),
"{JSON_TAG}": item.Name.String(),
"{DEFAULT_VALUE}": "",
"{COMMENT}": comment,
"{TYPE}": sqlTypeMap[item.Type.Type],
}
if item.Type.Unsigned {
// 无符号
data["{TYPE}"] = sqlTypeMap[item.Type.Type+" unsigned"]
}
/*if data["{FIELD}"] == "ID" {
basic.PrimaryFieldType = data["{TYPE}"]
}*/
@ -158,20 +150,17 @@ return "{{TABLE_NAME}}"
func generateTableColumnDefined(modelStructName string, columnList []*sqlparser.ColumnDefinition) (string, string, string) {
columnDefineName := modelStructName + "Column"
structFieldResult := "type " + columnDefineName + " struct { \n"
structFieldDescInstanceResult := columnDefineName + "{ \n"
structFieldDescInstanceResult := "&" + columnDefineName + "{ \n"
structFieldCommentInstanceResult := "map[string]string{ \n"
for _, column := range columnList {
comment := column.Name.String()
if nil != column.Type.Comment {
comment = string(column.Type.Comment.Val)
}
if comment == "" {
comment = column.Name.String()
}
dataMap := map[string]string{
"{FIELD}": op_string.SnakeCaseToCamel(column.Name.String()),
"{JSON_TAG}": column.Name.String(),
"{FIELD_COMMENT}": comment,
"{FIELD}": wrapperType.String(column.Name.String()).SnakeCaseToCamel(),
"{JSON_TAG}": column.Name.String(),
"{FIELD_COMMENT}": wrapperType.TernaryOperator.String(
column.Type.Comment == nil,
wrapperType.String(column.Name.String()),
wrapperType.String(string(column.Type.Comment.Val)),
).Value(),
}
structFieldDefine := TableColumnTpl
@ -192,7 +181,7 @@ func generateTableColumnDefined(modelStructName string, columnList []*sqlparser.
tableColumnFunction := `
// Columns 获取表字段定义
func ({TABLE_FIRST} {MODEL_STRUCT_NAME}) Columns() {COLUMN_DEFINED} {
func ({TABLE_FIRST} {MODEL_STRUCT_NAME}) Columns() *{COLUMN_DEFINED} {
return {STRUCT_FIELD_DESC_DEFINED_RESULT}
}

View File

@ -11,15 +11,14 @@ import (
"context"
"errors"
"fmt"
"path/filepath"
"strings"
"sync"
"git.zhangdeman.cn/zhangdeman/consts"
"git.zhangdeman.cn/zhangdeman/database/abstract"
"git.zhangdeman.cn/zhangdeman/database/define"
"git.zhangdeman.cn/zhangdeman/serialize"
"go.uber.org/zap"
"path/filepath"
"strings"
"sync"
"gorm.io/gorm"
)
@ -33,7 +32,7 @@ func init() {
WrapperClient = NewWrapperClient()
}
func NewWrapperClient() abstract.IWrapperClient {
func NewWrapperClient() *wrapperClient {
return &wrapperClient{
lock: &sync.RWMutex{},
clientTable: make(map[string]abstract.IWrapperDatabaseClient),
@ -115,7 +114,7 @@ func (c *wrapperClient) getCfg(cfgPath string) (*define.CfgFile, error) {
// 获取不到类型
return nil, errors.New("文件格式必须是JSON或者YAML")
}
fileType := consts.FileType(strings.ToLower(fileArr[len(fileArr)-1]))
fileType := strings.ToLower(fileArr[len(fileArr)-1])
fileFlagArr := strings.Split(fileArr[0], string(filepath.Separator))
result := &define.CfgFile{
Path: cfgPath,

View File

@ -11,21 +11,24 @@ import (
"context"
"errors"
"fmt"
"strings"
"sync"
"time"
"git.zhangdeman.cn/zhangdeman/consts"
"git.zhangdeman.cn/zhangdeman/database/define"
"git.zhangdeman.cn/zhangdeman/database/logger"
"git.zhangdeman.cn/zhangdeman/logger/wrapper"
"go.uber.org/zap"
"gorm.io/driver/mysql"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
gormLogger "gorm.io/gorm/logger"
"strings"
"sync"
"time"
)
// DBClient 包装日志实例
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 3:09 PM 2021/12/24
type DBClient struct {
DbFlag string // 数据库标识
LoggerInstance *zap.Logger // 日志实例
@ -39,6 +42,10 @@ type DBClient struct {
}
// Init 初始化客户端
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:44 2024/8/20
func (dc *DBClient) Init(databaseConfig *define.Database, cacheTableStructureConfig *define.CacheTableStructureConfig) error {
dc.lock = &sync.RWMutex{}
dc.cacheTableStructureConfig = cacheTableStructureConfig
@ -69,6 +76,10 @@ func (dc *DBClient) Init(databaseConfig *define.Database, cacheTableStructureCon
}
// GetMaster 获取主库连接
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 3:28 PM 2021/12/24
func (dc *DBClient) GetMaster(ctx context.Context) *gorm.DB {
session := dc.master.Session(&gorm.Session{})
session.Logger = dc.getLogger(ctx, session, "master")
@ -76,6 +87,10 @@ func (dc *DBClient) GetMaster(ctx context.Context) *gorm.DB {
}
// GetSlave 获取从库链接
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 3:29 PM 2021/12/24
func (dc *DBClient) GetSlave(ctx context.Context) *gorm.DB {
session := dc.slave.Session(&gorm.Session{})
session.Logger = dc.getLogger(ctx, session, "slave")
@ -83,8 +98,12 @@ func (dc *DBClient) GetSlave(ctx context.Context) *gorm.DB {
}
// getLogger 获取日志实例
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 3:45 PM 2021/12/24
func (dc *DBClient) getLogger(ctx context.Context, dbClient *gorm.DB, node string) gormLogger.Interface {
return logger.NewGormLoggerWithInstance(ctx, dbClient, dc.LoggerInstance, dc.DbFlag+"|"+node, dc.ExtraFieldList)
return wrapper.NewGormLoggerWithInstance(ctx, dbClient, dc.LoggerInstance, dc.DbFlag+"|"+node, dc.ExtraFieldList)
}
// GetDatabaseClient 获取数据库连接
@ -114,21 +133,16 @@ func (dc *DBClient) GetDatabaseClient(conf *define.Driver, logInstance *zap.Logg
return nil, fmt.Errorf("%v : db driver is not support", conf.DBType)
}
dbInstance, _ := instance.DB()
if nil == conf.Connection {
conf.Connection = &define.Connection{
MaxOpen: 100,
MaxIdle: 100,
}
}
dbInstance.SetMaxIdleConns(conf.Connection.MaxIdle)
dbInstance.SetMaxOpenConns(conf.Connection.MaxOpen)
instance.Logger = logger.NewGormLoggerWithInstance(nil, instance, logInstance, "", nil)
instance.Logger = wrapper.NewGormLoggerWithInstance(nil, instance, logInstance, "", nil)
return instance, nil
}
// buildConnectionDSN 构建连接信息
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 18:42 2022/6/11
func (dc *DBClient) buildConnectionDSN(conf *define.Driver) string {
if conf.DBType == consts.DatabaseDriverSqlite3 {
// 兼容sqlite3
@ -147,6 +161,10 @@ func (dc *DBClient) buildConnectionDSN(conf *define.Driver) string {
}
// CacheDataTableStructureConfig ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:03 2024/8/21
func (dc *DBClient) CacheDataTableStructureConfig() *define.CacheTableStructureConfig {
if nil == dc.cacheTableStructureConfig {
return &define.CacheTableStructureConfig{Enable: false, SyncTimeInterval: 3600}
@ -158,6 +176,10 @@ func (dc *DBClient) CacheDataTableStructureConfig() *define.CacheTableStructureC
}
// GetTableFieldList 获取表结构配置
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:07 2024/8/21
func (dc *DBClient) GetTableFieldList(tableName string) ([]*define.ColumnConfig, error) {
if !dc.CacheDataTableStructureConfig().Enable {
// 未启用缓存, 返回空list
@ -172,6 +194,10 @@ func (dc *DBClient) GetTableFieldList(tableName string) ([]*define.ColumnConfig,
}
// syncDbTableStructure 缓存表结构
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:17 2024/8/21
func (dc *DBClient) syncDbTableStructure(ignoreErr bool) error {
if !dc.CacheDataTableStructureConfig().Enable {
// 自动同步不可用
@ -221,6 +247,10 @@ func (dc *DBClient) syncDbTableStructure(ignoreErr bool) error {
}
// SetTableStructure 设置表结构, 一旦调用人工设置, 则将终止自动同步
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:06 2024/8/23
func (dc *DBClient) SetTableStructure(tableConfigTable map[string][]*define.ColumnConfig) {
if nil != dc.cacheTableStructureConfig {
// 关闭自动同步