sql.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. package utils
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. "reflect"
  7. "regexp"
  8. "text/template"
  9. )
  10. type Driver string
  11. type SqlCondition string
  12. const (
  13. DM Driver = "dm"
  14. MySql Driver = "mysql"
  15. GroupUnit SqlCondition = "GroupUnit"
  16. Distinct SqlCondition = "Distinct"
  17. Order SqlCondition = "Order"
  18. Delimiter SqlCondition = "Delimiter"
  19. )
  20. var TemplateMap = map[SqlCondition]map[Driver]string{
  21. GroupUnit: {
  22. MySql: `GROUP_CONCAT({{.Distinct}} {{.Column}} {{.Order}} SEPARATOR '{{.Delimiter}}')`,
  23. DM: `LISTAGG({{.Distinct}} {{.Column}},'{{.Delimiter}}') WITHIN GROUP ({{.Order}})`,
  24. },
  25. }
  26. var supportDriverMap = map[string]Driver{
  27. "mysql": MySql,
  28. "dm": DM,
  29. //"postgres": Postgres,
  30. }
  31. type QueryParam struct {
  32. Driver string
  33. Column string
  34. Order string
  35. Distinct string
  36. Delimiter string
  37. OrderField string
  38. OrderRule string
  39. HasDistinct bool
  40. }
  41. type SqlParam interface {
  42. GetParamName() string
  43. GetFormatConditionStr(param *QueryParam) string
  44. }
  45. type DistinctParam struct {
  46. }
  47. func (distinctParam *DistinctParam) GetParamName() string {
  48. return "Distinct"
  49. }
  50. func (distinctParam *DistinctParam) GetFormatConditionStr(param *QueryParam) string {
  51. if param.HasDistinct {
  52. return "DISTINCT"
  53. }
  54. return ""
  55. }
  56. var sqlGeneratorFactory = map[SqlCondition]SqlParam{
  57. // 添加支持的语法
  58. GroupUnit: &GroupUnitParam{
  59. supportGrams: []SqlCondition{
  60. Distinct,
  61. Order,
  62. Delimiter,
  63. },
  64. },
  65. Order: &OrderParam{},
  66. Delimiter: &DelimiterParam{},
  67. Distinct: &DistinctParam{},
  68. }
  69. type DelimiterParam struct {
  70. }
  71. func (delimiterParam *DelimiterParam) GetParamName() string {
  72. return "Delimiter"
  73. }
  74. func (delimiterParam *DelimiterParam) GetFormatConditionStr(param *QueryParam) string {
  75. if param.Delimiter == "" {
  76. return ","
  77. }
  78. return param.Delimiter
  79. }
  80. type OrderParam struct {
  81. Field string
  82. Rule string
  83. }
  84. func (orderParam *OrderParam) GetParamName() string {
  85. return "Order"
  86. }
  87. func (orderParam *OrderParam) GetFormatConditionStr(param *QueryParam) string {
  88. if param.OrderField == "" {
  89. orderParam.Field = param.Column
  90. } else {
  91. orderParam.Field = param.OrderField
  92. }
  93. if param.OrderRule != "" {
  94. if param.OrderRule == "ASC" || param.OrderRule == "DESC" {
  95. orderParam.Rule = param.OrderRule
  96. }
  97. }
  98. return fmt.Sprintf("ORDER BY %s %s", orderParam.Field, orderParam.Rule)
  99. }
  100. // 高级语法聚合
  101. type GroupUnitParam struct {
  102. supportGrams []SqlCondition
  103. }
  104. func (groupUnitParam *GroupUnitParam) GetParamName() string {
  105. return "GroupUnit"
  106. }
  107. func (groupUnitParam *GroupUnitParam) GetFormatConditionStr(param *QueryParam) (sqlStr string) {
  108. dbDriver, _ := getDriverInstance(param.Driver)
  109. if param.Column == "" {
  110. FileLog.Error("聚合字段为空,无法生成聚合sql")
  111. return
  112. }
  113. var templateSqlStr string
  114. if _, ok := TemplateMap[GroupUnit][dbDriver]; !ok {
  115. templateSqlStr = TemplateMap[GroupUnit][MySql]
  116. } else {
  117. templateSqlStr = TemplateMap[GroupUnit][dbDriver]
  118. }
  119. if templateSqlStr == "" {
  120. FileLog.Error("聚合sql模板不存在,无法生成聚合sql")
  121. return
  122. }
  123. templateSql, err := template.New("GroupUnit").Parse(templateSqlStr)
  124. if err != nil {
  125. FileLog.Error("failed to parse template: %v", err)
  126. return
  127. }
  128. //反射获取结构体的值
  129. value := reflect.ValueOf(param)
  130. // 检查是否是指针
  131. if value.Kind() != reflect.Ptr {
  132. fmt.Println("请求参数必须是一个结构体")
  133. return
  134. }
  135. // 获取结构体的元素
  136. elem := value.Elem()
  137. // 检查是否是结构体
  138. if elem.Kind() != reflect.Struct {
  139. fmt.Println("请求参数必须是一个结构体")
  140. return
  141. }
  142. for _, supportGram := range groupUnitParam.supportGrams {
  143. // 获取字段的值
  144. fieldValue := elem.FieldByName(string(supportGram))
  145. // 检查字段是否存在
  146. if !fieldValue.IsValid() {
  147. fmt.Printf("Error: field %s not found\n", supportGram)
  148. continue
  149. }
  150. // 检查字段是否可导出
  151. if !fieldValue.CanSet() {
  152. fmt.Printf("Error: field %s is not exported and cannot be set\n", supportGram)
  153. continue
  154. }
  155. newValue := sqlGeneratorFactory[supportGram].GetFormatConditionStr(param)
  156. // 检查新值的类型是否匹配
  157. newValueValue := reflect.ValueOf(newValue)
  158. if fieldValue.Type() != newValueValue.Type() {
  159. fmt.Printf("字段%s类型不匹配 : 期望的类型是 %s, 传入的类型为: %s", supportGram, fieldValue.Type(), newValueValue.Type())
  160. return
  161. }
  162. // 设置字段的值
  163. fieldValue.Set(newValueValue)
  164. }
  165. // 渲染模板
  166. var buf bytes.Buffer
  167. err = templateSql.Execute(&buf, param)
  168. if err != nil {
  169. fmt.Sprintf("执行模板填充失败: %v", err)
  170. return
  171. }
  172. sqlStr = buf.String()
  173. fmt.Printf("生成的聚合语句为:%s\n", sqlStr)
  174. return sqlStr
  175. }
  176. func GroupUnitFunc(driver string, column, delimiter string, columnOrder bool, orderField, orderRule string, hasDistinct bool) (sqlStr string) {
  177. dbDriver, _ := getDriverInstance(driver)
  178. if delimiter == "" {
  179. delimiter = ","
  180. }
  181. if column == "" {
  182. column = "[UNKNOWN COLUMN]"
  183. }
  184. //if tableAlia != "" {
  185. // column = fmt.Sprintf("%s.%s", tableAlia, column)
  186. //}
  187. var sqlOrder, strDistinct string
  188. if hasDistinct {
  189. strDistinct = "DISTINCT"
  190. }
  191. if columnOrder && orderField == "" {
  192. orderField = column
  193. }
  194. switch dbDriver {
  195. case DM:
  196. if columnOrder {
  197. sqlOrder = fmt.Sprintf("WITHIN GROUP (ORDER BY %s %s)", orderField, orderRule)
  198. }
  199. sqlStr = fmt.Sprintf("LISTAGG(%s %s, '%s') %s", strDistinct, column, delimiter, sqlOrder)
  200. default:
  201. // 默认使用MySQL的语法
  202. if columnOrder {
  203. sqlOrder = fmt.Sprintf("ORDER BY %s %s", orderField, orderRule)
  204. }
  205. sqlStr = fmt.Sprintf("GROUP_CONCAT(%s %s %s SEPARATOR '%s')", strDistinct, column, sqlOrder, delimiter)
  206. }
  207. return sqlStr
  208. }
  209. func getDriverInstance(driver string) (dbDriver Driver, err error) {
  210. if driver == "" {
  211. dbDriver = supportDriverMap[DbDriverName]
  212. }
  213. if currentDriver, ok := supportDriverMap[driver]; !ok {
  214. err = errors.New("不支持的数据库驱动类型")
  215. return
  216. } else {
  217. dbDriver = currentDriver
  218. }
  219. return
  220. }
  221. func NeedDateOrTimeFormat(driver string) bool {
  222. var dbDriver Driver
  223. if driver == "" {
  224. dbDriver = supportDriverMap[DbDriverName]
  225. } else {
  226. dbDriver, _ = getDriverInstance(driver)
  227. }
  228. if dbDriver == DM {
  229. return true
  230. }
  231. return false
  232. }
  233. func ReplaceDriverKeywords(driver string, sql string) string {
  234. dbDriver, _ := getDriverInstance(driver)
  235. rules := map[Driver]map[string]string{
  236. DM: {
  237. "admin": `"admin"`,
  238. "value": `"value"`,
  239. "exchange": `"exchange"`,
  240. "b.from": `b."from"`,
  241. "size": `"size"`,
  242. },
  243. }
  244. replacements, ok := rules[dbDriver]
  245. if !ok {
  246. return sql
  247. }
  248. for keyword, replace := range replacements {
  249. // 仅替换单独的单词,复合单词含关键词不管
  250. pattern := fmt.Sprintf(`\b%s\b`, regexp.QuoteMeta(keyword))
  251. re := regexp.MustCompile(pattern)
  252. sql = re.ReplaceAllString(sql, replace)
  253. }
  254. return sql
  255. }
  256. func GenerateQuerySql(gram SqlCondition, param *QueryParam) (sqlGenerator string) {
  257. if exec, ok := sqlGeneratorFactory[gram]; !ok {
  258. FileLog.Error("不支持的语法:%s", gram)
  259. return
  260. } else {
  261. sqlGenerator = exec.GetFormatConditionStr(param)
  262. }
  263. return
  264. }