Browse Source

change gorm

Roc 1 month ago
parent
commit
e788561a70
4 changed files with 414 additions and 22 deletions
  1. 21 21
      controllers/chart_common.go
  2. 31 0
      global/initDb.go
  3. 4 1
      models/chart.go
  4. 358 0
      utils/sql.go

+ 21 - 21
controllers/chart_common.go

@@ -71,27 +71,27 @@ func (this *ChartController) CommonChartInfoDetailFromUniqueCode() {
 		isCollect = tmpIsCollect
 	}
 	//判断是否有缓存
-	if utils.Re == nil {
-		if utils.Re == nil && utils.Rc.IsExist(key) {
-			if data, err1 := utils.Rc.RedisBytes(key); err1 == nil {
-				err := json.Unmarshal(data, &resp)
-				if err == nil && resp != nil {
-					if conf[models.BusinessConfWatermarkChart] == "true" && conf[models.BusinessConfCompanyWatermark] != "" {
-						resp.WaterMark = conf[models.BusinessConfCompanyWatermark]
-					}
-					if isCollect {
-						resp.IsCollect = isCollect
-					}
-					br.Ret = 200
-					br.Success = true
-					br.Msg = "获取成功"
-					br.Data = resp
-					fmt.Println("source redis")
-					return
-				}
-			}
-		}
-	}
+	//if utils.Re == nil {
+	//	if utils.Re == nil && utils.Rc.IsExist(key) {
+	//		if data, err1 := utils.Rc.RedisBytes(key); err1 == nil {
+	//			err := json.Unmarshal(data, &resp)
+	//			if err == nil && resp != nil {
+	//				if conf[models.BusinessConfWatermarkChart] == "true" && conf[models.BusinessConfCompanyWatermark] != "" {
+	//					resp.WaterMark = conf[models.BusinessConfCompanyWatermark]
+	//				}
+	//				if isCollect {
+	//					resp.IsCollect = isCollect
+	//				}
+	//				br.Ret = 200
+	//				br.Success = true
+	//				br.Msg = "获取成功"
+	//				br.Data = resp
+	//				fmt.Println("source redis")
+	//				return
+	//			}
+	//		}
+	//	}
+	//}
 
 	chartInfo, err := models.GetChartInfoByUniqueCode(uniqueCode)
 	if err != nil {

+ 31 - 0
global/initDb.go

@@ -17,6 +17,14 @@ import (
 	"time"
 )
 
+var (
+	//需要钩子函数执行的数据库表
+	tableMap = map[string]int{
+		"base_from_mysteel_chemical_data": 1,
+		"future_good_edb_info":            1,
+	}
+)
+
 type LocalTime time.Time
 
 // InitDb
@@ -44,6 +52,29 @@ func InitDb() {
 	// 指标库
 	connectDb(utils.MYSQL_URL_DATA, utils.DbNameIndex, newLogger, dbMap, false)
 
+	// gorm前置处理
+	for _, db := range dbMap {
+		_ = db.Callback().Query().Before("gorm:query").Register("before_query", func(tx *gorm.DB) {
+			orgSql := tx.Statement.SQL.String()
+			if _, ok := tableMap[tx.Statement.Table]; ok && strings.Contains(strings.ToLower(orgSql), "select") {
+				newSql := utils.ReplaceDriverKeywords(utils.DbDriverName, orgSql)
+				tx.Statement.SQL.Reset()
+				tx.Statement.SQL.WriteString(newSql)
+			}
+		})
+		_ = db.Callback().Raw().Before("gorm:raw").Register("before_raw", func(tx *gorm.DB) {
+			orgSql := tx.Statement.SQL.String()
+			if _, ok := tableMap[tx.Statement.Table]; ok &&
+				(strings.Contains(strings.ToLower(orgSql), "delete") ||
+					strings.Contains(strings.ToLower(orgSql), "update") ||
+					strings.Contains(strings.ToLower(orgSql), "insert")) {
+				newSql := utils.ReplaceDriverKeywords(utils.DbDriverName, orgSql)
+				tx.Statement.SQL.Reset()
+				tx.Statement.SQL.WriteString(newSql)
+			}
+		})
+	}
+
 	//全局赋值数据库链接
 	DbMap = dbMap
 

+ 4 - 1
models/chart.go

@@ -178,7 +178,7 @@ type EdbDataList struct {
 	EdbInfoId     int     `json:"-" description:"指标ID"`
 	DataTime      string  `description:"数据日期"`
 	DataTimestamp int64   `description:"数据日期"`
-	Value         float64 `description:"数据值"`
+	Value         float64 `description:"数据值" gorm:"column:value"`
 }
 
 func (m *EdbDataList) AfterFind(db *gorm.DB) (err error) {
@@ -238,7 +238,10 @@ func getEdbDataListByMysql(source, subSource, edbInfoId int, startDate, endDate
 	//_, err = o.Raw(sql, edbInfoId, pars).QueryRows(&list)
 	newPars := utils.ForwardPars(pars, edbInfoId)
 	pars = append(pars, edbInfoId)
+	sql = utils.ReplaceDriverKeywords("", sql)
+
 	err = global.DbMap[utils.DbNameIndex].Raw(sql, newPars...).Find(&list).Error
+
 	return
 }
 

+ 358 - 0
utils/sql.go

@@ -0,0 +1,358 @@
+package utils
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"reflect"
+	"regexp"
+	"text/template"
+)
+
+type Driver string
+type SqlCondition string
+
+const (
+	DM            Driver       = "dm"
+	MySql         Driver       = "mysql"
+	GroupUnit     SqlCondition = "GroupUnit"
+	Distinct      SqlCondition = "Distinct"
+	Order         SqlCondition = "Order"
+	Delimiter     SqlCondition = "Delimiter"
+	ConvertColumn SqlCondition = "ConvertColumn"
+)
+
+var TemplateMap = map[SqlCondition]map[Driver]string{
+	GroupUnit: {
+		MySql: `GROUP_CONCAT({{.Distinct}} {{.Column}} {{.Order}} SEPARATOR '{{.Delimiter}}')`,
+		DM:    `LISTAGG({{.Distinct}} {{.Column}},'{{.Delimiter}}') WITHIN GROUP ({{.Order}})`,
+	},
+	ConvertColumn: {
+		MySql: `CONVERT({{.ConvertColumn}} USING gbk )`,
+		DM:    `{{.ConvertColumn}}`,
+	},
+}
+
+var supportDriverMap = map[string]Driver{
+	"mysql": MySql,
+	"dm":    DM,
+	//"postgres": Postgres,
+}
+
+type QueryParam struct {
+	Driver        string
+	Column        string
+	Order         string
+	Distinct      string
+	Delimiter     string
+	OrderField    string
+	OrderRule     string
+	ConvertColumn string `description:"Convert指令传递的clounm"`
+	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 ""
+}
+
+type ConvertParam struct {
+}
+
+func (convertParam *ConvertParam) GetParamName() string {
+	return "Convert"
+}
+func (convertParam *ConvertParam) GetFormatConditionStr(param *QueryParam) (sqlStr string) {
+	dbDriver, _ := getDriverInstance(param.Driver)
+	if param.ConvertColumn == "" {
+		FileLog.Error("转换字段为空,无法生成聚合sql")
+		return
+	}
+	var templateSqlStr string
+	if _, ok := TemplateMap[ConvertColumn][dbDriver]; !ok {
+		templateSqlStr = TemplateMap[ConvertColumn][MySql]
+	} else {
+		templateSqlStr = TemplateMap[ConvertColumn][dbDriver]
+	}
+	if templateSqlStr == "" {
+		FileLog.Error("转换sql模板不存在,无法生成转换sql")
+		return
+	}
+	templateSql, err := template.New("ConvertColumn").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
+	}
+	// 获取字段的值
+	fieldValue := elem.FieldByName("ConvertColumn")
+	// 检查字段是否存在
+	if !fieldValue.IsValid() {
+		fmt.Printf("Error: field %s not found\n", "ConvertColumn")
+		return
+	}
+	// 检查字段是否可导出
+	if !fieldValue.CanSet() {
+		fmt.Printf("Error: field %s is not exported and cannot be set\n", "ConvertColumn")
+		return
+	}
+	// 渲染模板
+	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
+}
+
+var sqlGeneratorFactory = map[SqlCondition]SqlParam{
+	// 添加支持的语法
+	GroupUnit: &GroupUnitParam{
+		supportGrams: []SqlCondition{
+			Distinct,
+			Order,
+			Delimiter,
+		},
+	},
+	Order:         &OrderParam{},
+	Delimiter:     &DelimiterParam{},
+	Distinct:      &DistinctParam{},
+	ConvertColumn: &ConvertParam{},
+}
+
+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) {
+	dbDriver, _ := getDriverInstance(driver)
+	if delimiter == "" {
+		delimiter = ","
+	}
+	if column == "" {
+		column = "[UNKNOWN COLUMN]"
+	}
+	//if tableAlia != "" {
+	//	column = fmt.Sprintf("%s.%s", tableAlia, column)
+	//}
+	var sqlOrder, strDistinct string
+	if hasDistinct {
+		strDistinct = "DISTINCT"
+	}
+	if columnOrder && orderField == "" {
+		orderField = column
+	}
+	switch dbDriver {
+	case DM:
+		if columnOrder {
+			sqlOrder = fmt.Sprintf("WITHIN GROUP (ORDER BY %s %s)", orderField, orderRule)
+		}
+		sqlStr = fmt.Sprintf("LISTAGG(%s %s, '%s') %s", strDistinct, column, delimiter, sqlOrder)
+	default:
+		// 默认使用MySQL的语法
+		if columnOrder {
+			sqlOrder = fmt.Sprintf("ORDER BY %s %s", orderField, orderRule)
+		}
+		sqlStr = fmt.Sprintf("GROUP_CONCAT(%s %s %s SEPARATOR '%s')", strDistinct, column, sqlOrder, delimiter)
+	}
+	return sqlStr
+}
+
+func getDriverInstance(driver string) (dbDriver Driver, err error) {
+	if driver == "" {
+		dbDriver = supportDriverMap[DbDriverName]
+	}
+	if currentDriver, ok := supportDriverMap[driver]; !ok {
+		err = errors.New("不支持的数据库驱动类型")
+		return
+	} else {
+		dbDriver = currentDriver
+	}
+	return
+}
+
+func NeedDateOrTimeFormat(driver string) bool {
+	var dbDriver Driver
+	if driver == "" {
+		dbDriver = supportDriverMap[DbDriverName]
+	} else {
+		dbDriver, _ = getDriverInstance(driver)
+	}
+	if dbDriver == DM {
+		return true
+	}
+	return false
+}
+
+func ReplaceDriverKeywords(driver string, sql string) string {
+	dbDriver, _ := getDriverInstance(driver)
+	rules := map[Driver]map[string]string{
+		DM: {
+			"admin":    `"admin"`,
+			"value":    `"value"`,
+			"exchange": `"exchange"`,
+			"size":     `"size"`,
+			"a.from":   `a."from"`,
+			"b.from":   `b."from"`,
+		},
+	}
+	replacements, ok := rules[dbDriver]
+	if !ok {
+		return sql
+	}
+	for keyword, replace := range replacements {
+		// 仅替换单独的单词,复合单词含关键词不管
+		pattern := fmt.Sprintf(`\b%s\b`, regexp.QuoteMeta(keyword))
+		re := regexp.MustCompile(pattern)
+		sql = re.ReplaceAllString(sql, replace)
+	}
+	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
+}