|
@@ -1,21 +1,193 @@
|
|
package utils
|
|
package utils
|
|
|
|
|
|
import (
|
|
import (
|
|
|
|
+ "bytes"
|
|
"errors"
|
|
"errors"
|
|
"fmt"
|
|
"fmt"
|
|
|
|
+ "reflect"
|
|
"regexp"
|
|
"regexp"
|
|
|
|
+ "text/template"
|
|
)
|
|
)
|
|
|
|
|
|
type Driver string
|
|
type Driver string
|
|
|
|
+type SqlCondition string
|
|
|
|
|
|
const (
|
|
const (
|
|
- DM Driver = "dm"
|
|
|
|
- MySql Driver = "mysql"
|
|
|
|
|
|
+ DM Driver = "dm"
|
|
|
|
+ MySql Driver = "mysql"
|
|
|
|
+ GroupUnit SqlCondition = "GroupUnit"
|
|
|
|
+ Distinct SqlCondition = "Distinct"
|
|
|
|
+ Order SqlCondition = "Order"
|
|
|
|
+ Delimiter SqlCondition = "Delimiter"
|
|
)
|
|
)
|
|
|
|
|
|
|
|
+var TemplateMap = map[SqlCondition]map[Driver]string{
|
|
|
|
+ GroupUnit: {
|
|
|
|
+ MySql: `GROUP_CONCAT({{.Distinct}} {{.Column}} {{.Order}} SEPARATOR '{{.Delimiter}}')`,
|
|
|
|
+ DM: `LISTAGG({{.Distinct}} {{.Column}},'{{.Delimiter}}') WITHIN GROUP ({{.Order}})`,
|
|
|
|
+ },
|
|
|
|
+}
|
|
|
|
+
|
|
var supportDriverMap = map[string]Driver{
|
|
var supportDriverMap = map[string]Driver{
|
|
"mysql": MySql,
|
|
"mysql": MySql,
|
|
"dm": DM,
|
|
"dm": DM,
|
|
|
|
+ //"postgres": Postgres,
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+type QueryParam struct {
|
|
|
|
+ Driver string
|
|
|
|
+ Column string
|
|
|
|
+ Order string
|
|
|
|
+ Distinct string
|
|
|
|
+ Delimiter string
|
|
|
|
+ OrderField string
|
|
|
|
+ OrderRule string
|
|
|
|
+ HasDistinct bool
|
|
|
|
+}
|
|
|
|
+type SqlParam interface {
|
|
|
|
+ GetParamName() string
|
|
|
|
+ GetFormatConditionStr(param *QueryParam) string
|
|
|
|
+}
|
|
|
|
+type DistinctParam struct {
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (distinctParam *DistinctParam) GetParamName() string {
|
|
|
|
+ return "Distinct"
|
|
|
|
+}
|
|
|
|
+func (distinctParam *DistinctParam) GetFormatConditionStr(param *QueryParam) string {
|
|
|
|
+ if param.HasDistinct {
|
|
|
|
+ return "DISTINCT"
|
|
|
|
+ }
|
|
|
|
+ return ""
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+var sqlGeneratorFactory = map[SqlCondition]SqlParam{
|
|
|
|
+ // 添加支持的语法
|
|
|
|
+ GroupUnit: &GroupUnitParam{
|
|
|
|
+ supportGrams: []SqlCondition{
|
|
|
|
+ Distinct,
|
|
|
|
+ Order,
|
|
|
|
+ Delimiter,
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+ Order: &OrderParam{},
|
|
|
|
+ Delimiter: &DelimiterParam{},
|
|
|
|
+ Distinct: &DistinctParam{},
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+type DelimiterParam struct {
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (delimiterParam *DelimiterParam) GetParamName() string {
|
|
|
|
+ return "Delimiter"
|
|
|
|
+}
|
|
|
|
+func (delimiterParam *DelimiterParam) GetFormatConditionStr(param *QueryParam) string {
|
|
|
|
+ if param.Delimiter == "" {
|
|
|
|
+ return ","
|
|
|
|
+ }
|
|
|
|
+ return param.Delimiter
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+type OrderParam struct {
|
|
|
|
+ Field string
|
|
|
|
+ Rule string
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (orderParam *OrderParam) GetParamName() string {
|
|
|
|
+ return "Order"
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (orderParam *OrderParam) GetFormatConditionStr(param *QueryParam) string {
|
|
|
|
+ if param.OrderField == "" {
|
|
|
|
+ orderParam.Field = param.Column
|
|
|
|
+ } else {
|
|
|
|
+ orderParam.Field = param.OrderField
|
|
|
|
+ }
|
|
|
|
+ if param.OrderRule != "" {
|
|
|
|
+ if param.OrderRule == "ASC" || param.OrderRule == "DESC" {
|
|
|
|
+ orderParam.Rule = param.OrderRule
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return fmt.Sprintf("ORDER BY %s %s", orderParam.Field, orderParam.Rule)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// 高级语法聚合
|
|
|
|
+type GroupUnitParam struct {
|
|
|
|
+ supportGrams []SqlCondition
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (groupUnitParam *GroupUnitParam) GetParamName() string {
|
|
|
|
+ return "GroupUnit"
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (groupUnitParam *GroupUnitParam) GetFormatConditionStr(param *QueryParam) (sqlStr string) {
|
|
|
|
+ dbDriver, _ := getDriverInstance(param.Driver)
|
|
|
|
+ if param.Column == "" {
|
|
|
|
+ FileLog.Error("聚合字段为空,无法生成聚合sql")
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ var templateSqlStr string
|
|
|
|
+ if _, ok := TemplateMap[GroupUnit][dbDriver]; !ok {
|
|
|
|
+ templateSqlStr = TemplateMap[GroupUnit][MySql]
|
|
|
|
+ } else {
|
|
|
|
+ templateSqlStr = TemplateMap[GroupUnit][dbDriver]
|
|
|
|
+ }
|
|
|
|
+ if templateSqlStr == "" {
|
|
|
|
+ FileLog.Error("聚合sql模板不存在,无法生成聚合sql")
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ templateSql, err := template.New("GroupUnit").Parse(templateSqlStr)
|
|
|
|
+ if err != nil {
|
|
|
|
+ FileLog.Error("failed to parse template: %v", err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ //反射获取结构体的值
|
|
|
|
+ value := reflect.ValueOf(param)
|
|
|
|
+ // 检查是否是指针
|
|
|
|
+ if value.Kind() != reflect.Ptr {
|
|
|
|
+ fmt.Println("请求参数必须是一个结构体")
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ // 获取结构体的元素
|
|
|
|
+ elem := value.Elem()
|
|
|
|
+ // 检查是否是结构体
|
|
|
|
+ if elem.Kind() != reflect.Struct {
|
|
|
|
+ fmt.Println("请求参数必须是一个结构体")
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ for _, supportGram := range groupUnitParam.supportGrams {
|
|
|
|
+ // 获取字段的值
|
|
|
|
+ fieldValue := elem.FieldByName(string(supportGram))
|
|
|
|
+ // 检查字段是否存在
|
|
|
|
+ if !fieldValue.IsValid() {
|
|
|
|
+ fmt.Printf("Error: field %s not found\n", supportGram)
|
|
|
|
+ continue
|
|
|
|
+ }
|
|
|
|
+ // 检查字段是否可导出
|
|
|
|
+ if !fieldValue.CanSet() {
|
|
|
|
+ fmt.Printf("Error: field %s is not exported and cannot be set\n", supportGram)
|
|
|
|
+ continue
|
|
|
|
+ }
|
|
|
|
+ newValue := sqlGeneratorFactory[supportGram].GetFormatConditionStr(param)
|
|
|
|
+ // 检查新值的类型是否匹配
|
|
|
|
+ newValueValue := reflect.ValueOf(newValue)
|
|
|
|
+ if fieldValue.Type() != newValueValue.Type() {
|
|
|
|
+ fmt.Printf("字段%s类型不匹配 : 期望的类型是 %s, 传入的类型为: %s", supportGram, fieldValue.Type(), newValueValue.Type())
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ // 设置字段的值
|
|
|
|
+ fieldValue.Set(newValueValue)
|
|
|
|
+ }
|
|
|
|
+ // 渲染模板
|
|
|
|
+ var buf bytes.Buffer
|
|
|
|
+ err = templateSql.Execute(&buf, param)
|
|
|
|
+ if err != nil {
|
|
|
|
+ fmt.Sprintf("执行模板填充失败: %v", err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ sqlStr = buf.String()
|
|
|
|
+ fmt.Printf("生成的聚合语句为:%s\n", sqlStr)
|
|
|
|
+ return sqlStr
|
|
}
|
|
}
|
|
|
|
|
|
func GroupUnitFunc(driver string, column, delimiter string, columnOrder bool, orderField, orderRule string, hasDistinct bool) (sqlStr string) {
|
|
func GroupUnitFunc(driver string, column, delimiter string, columnOrder bool, orderField, orderRule string, hasDistinct bool) (sqlStr string) {
|
|
@@ -52,27 +224,6 @@ func GroupUnitFunc(driver string, column, delimiter string, columnOrder bool, or
|
|
return sqlStr
|
|
return sqlStr
|
|
}
|
|
}
|
|
|
|
|
|
-func GroupUnitDistinctFunc(driver string, column, delimiter string) (sqlStr string) {
|
|
|
|
- dbDriver, _ := getDriverInstance(driver)
|
|
|
|
- if delimiter == "" {
|
|
|
|
- delimiter = ","
|
|
|
|
- }
|
|
|
|
- if column == "" {
|
|
|
|
- column = "[UNKNOWN COLUMN]"
|
|
|
|
- }
|
|
|
|
- //if tableAlia != "" {
|
|
|
|
- // column = fmt.Sprintf("%s.%s", tableAlia, column)
|
|
|
|
- //}
|
|
|
|
- switch dbDriver {
|
|
|
|
- case MySql:
|
|
|
|
- sqlStr = fmt.Sprintf("GROUP_CONCAT(DISTINCT %s SEPARATOR '%s')", column, delimiter)
|
|
|
|
- case DM:
|
|
|
|
- sqlStr = fmt.Sprintf("LISTAGG(DISTINCT %s, '%s') WITHIN GROUP (ORDER BY %s)", column, delimiter, column)
|
|
|
|
- default:
|
|
|
|
- sqlStr = fmt.Sprintf("GROUP_CONCAT(DISTINCT %s SEPARATOR '%s')", column, delimiter) // 默认使用 MySQL 的语法
|
|
|
|
- }
|
|
|
|
- return sqlStr
|
|
|
|
-}
|
|
|
|
func getDriverInstance(driver string) (dbDriver Driver, err error) {
|
|
func getDriverInstance(driver string) (dbDriver Driver, err error) {
|
|
if driver == "" {
|
|
if driver == "" {
|
|
dbDriver = supportDriverMap[DbDriverName]
|
|
dbDriver = supportDriverMap[DbDriverName]
|
|
@@ -120,3 +271,13 @@ func ReplaceDriverKeywords(driver string, sql string) string {
|
|
}
|
|
}
|
|
return sql
|
|
return sql
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+func GenerateQuerySql(gram SqlCondition, param *QueryParam) (sqlGenerator string) {
|
|
|
|
+ if exec, ok := sqlGeneratorFactory[gram]; !ok {
|
|
|
|
+ FileLog.Error("不支持的语法:%s", gram)
|
|
|
|
+ return
|
|
|
|
+ } else {
|
|
|
|
+ sqlGenerator = exec.GetFormatConditionStr(param)
|
|
|
|
+ }
|
|
|
|
+ return
|
|
|
|
+}
|