// Package api2sql ... // // Description : api2sql ... // // Author : go_developer@163.com<白茶清欢> // // Date : 2024-08-21 20:45 package api2sql import ( "context" "errors" "git.zhangdeman.cn/zhangdeman/consts" "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 // 全部数据库管理的实例 } // 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 列表 // // Author : go_developer@163.com<白茶清欢> // // Date : 20:52 2024/8/21 func (e *execute) List(ctx context.Context, inputParam *define.Api2SqlParam) (any, error) { return nil, nil } // Detail 详情 // // Author : go_developer@163.com<白茶清欢> // // Date : 20:52 2024/8/21 func (e *execute) Detail(ctx context.Context, inputParam *define.Api2SqlParam) (any, error) { return nil, 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) { return nil, 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.ColumnTable) == 0 && wrapper.ArrayType[string]([]string{ consts.SqlTypeList, consts.SqlTypeDetail, }).Has(inputParam.SqlType) >= 0 { for _, itemParam := range inputParam.TableColumnConfig { inputParam.ColumnTable[itemParam.ColumnName] = itemParam.ColumnName } } // 验证字段是否都正确 tableColumnTable := make(map[string]bool) for _, itemColumn := range inputParam.TableColumnConfig { tableColumnTable[itemColumn.ColumnName] = true } for columnName, _ := range inputParam.ColumnTable { if !tableColumnTable[columnName] { return errors.New(columnName + " : input column not found in table column list") } } for _, item := range inputParam.ValueList { if !tableColumnTable[item.Column] { return errors.New(item.Column + " : input column in `ValueList` is not found in table column list") } } 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) }