sql.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  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. ConvertColumn SqlCondition = "ConvertColumn"
  20. ToDate SqlCondition = "ToDate"
  21. )
  22. var TemplateMap = map[SqlCondition]map[Driver]string{
  23. GroupUnit: {
  24. MySql: `GROUP_CONCAT({{.Distinct}} {{.Column}} {{.Order}} SEPARATOR '{{.Delimiter}}')`,
  25. DM: `LISTAGG({{.Distinct}} {{.Column}},'{{.Delimiter}}') WITHIN GROUP ({{.Order}})`,
  26. },
  27. ConvertColumn: {
  28. MySql: `CONVERT({{.ConvertColumn}} USING gbk )`,
  29. DM: `{{.ConvertColumn}}`,
  30. },
  31. ToDate: {
  32. MySql: `DATE({{.Column}})`,
  33. DM: `TO_DATE({{.Column}})`,
  34. },
  35. }
  36. var supportDriverMap = map[string]Driver{
  37. "mysql": MySql,
  38. "dm": DM,
  39. //"postgres": Postgres,
  40. }
  41. type QueryParam struct {
  42. Driver string
  43. Column string
  44. Order string
  45. Distinct string
  46. Delimiter string
  47. OrderField string
  48. OrderRule string
  49. ConvertColumn string `description:"Convert指令传递的clounm"`
  50. HasDistinct bool
  51. }
  52. type SqlParam interface {
  53. GetParamName() string
  54. GetFormatConditionStr(param *QueryParam) string
  55. }
  56. type DistinctParam struct {
  57. }
  58. func (distinctParam *DistinctParam) GetParamName() string {
  59. return "Distinct"
  60. }
  61. func (distinctParam *DistinctParam) GetFormatConditionStr(param *QueryParam) string {
  62. if param.HasDistinct {
  63. return "DISTINCT"
  64. }
  65. return ""
  66. }
  67. type ToDateParam struct {
  68. }
  69. func (toDateParam *ToDateParam) GetParamName() string {
  70. return "ToDate"
  71. }
  72. func (toDateParam *ToDateParam) GetFormatConditionStr(param *QueryParam) (sql string) {
  73. dbDriver, _ := getDriverInstance(param.Driver)
  74. if param.Column == "" {
  75. FileLog.Error("聚合字段为空,无法生成聚合sql")
  76. return
  77. }
  78. var templateSqlStr string
  79. if _, ok := TemplateMap[ToDate][dbDriver]; !ok {
  80. templateSqlStr = TemplateMap[ToDate][MySql]
  81. } else {
  82. templateSqlStr = TemplateMap[ToDate][dbDriver]
  83. }
  84. if templateSqlStr == "" {
  85. FileLog.Error("聚合sql模板不存在,无法生成聚合sql")
  86. return
  87. }
  88. templateSql, err := template.New("ToDate").Parse(templateSqlStr)
  89. if err != nil {
  90. FileLog.Error("failed to parse template: %v", err)
  91. return
  92. }
  93. //反射获取结构体的值
  94. value := reflect.ValueOf(param)
  95. // 检查是否是指针
  96. if value.Kind() != reflect.Ptr {
  97. fmt.Println("请求参数必须是一个结构体")
  98. return
  99. }
  100. // 获取结构体的元素
  101. elem := value.Elem()
  102. // 检查是否是结构体
  103. if elem.Kind() != reflect.Struct {
  104. fmt.Println("请求参数必须是一个结构体")
  105. return
  106. }
  107. // 获取字段的值
  108. fieldValue := elem.FieldByName("ConvertColumn")
  109. // 检查字段是否存在
  110. if !fieldValue.IsValid() {
  111. fmt.Printf("Error: field %s not found\n", "ConvertColumn")
  112. return
  113. }
  114. // 检查字段是否可导出
  115. if !fieldValue.CanSet() {
  116. fmt.Printf("Error: field %s is not exported and cannot be set\n", "ConvertColumn")
  117. return
  118. }
  119. // 渲染模板
  120. var buf bytes.Buffer
  121. err = templateSql.Execute(&buf, param)
  122. if err != nil {
  123. fmt.Sprintf("执行模板填充失败: %v", err)
  124. return
  125. }
  126. sql = buf.String()
  127. fmt.Printf("生成的转换日期语句为:%s\n", sql)
  128. return sql
  129. }
  130. type ConvertParam struct {
  131. }
  132. func (convertParam *ConvertParam) GetParamName() string {
  133. return "Convert"
  134. }
  135. func (convertParam *ConvertParam) GetFormatConditionStr(param *QueryParam) (sqlStr string) {
  136. dbDriver, _ := getDriverInstance(param.Driver)
  137. if param.ConvertColumn == "" {
  138. FileLog.Error("转换字段为空,无法生成聚合sql")
  139. return
  140. }
  141. var templateSqlStr string
  142. if _, ok := TemplateMap[ConvertColumn][dbDriver]; !ok {
  143. templateSqlStr = TemplateMap[ConvertColumn][MySql]
  144. } else {
  145. templateSqlStr = TemplateMap[ConvertColumn][dbDriver]
  146. }
  147. if templateSqlStr == "" {
  148. FileLog.Error("转换sql模板不存在,无法生成转换sql")
  149. return
  150. }
  151. templateSql, err := template.New("ConvertColumn").Parse(templateSqlStr)
  152. if err != nil {
  153. FileLog.Error("failed to parse template: %v", err)
  154. return
  155. }
  156. //反射获取结构体的值
  157. value := reflect.ValueOf(param)
  158. // 检查是否是指针
  159. if value.Kind() != reflect.Ptr {
  160. fmt.Println("请求参数必须是一个结构体")
  161. return
  162. }
  163. // 获取结构体的元素
  164. elem := value.Elem()
  165. // 检查是否是结构体
  166. if elem.Kind() != reflect.Struct {
  167. fmt.Println("请求参数必须是一个结构体")
  168. return
  169. }
  170. // 获取字段的值
  171. fieldValue := elem.FieldByName("ConvertColumn")
  172. // 检查字段是否存在
  173. if !fieldValue.IsValid() {
  174. fmt.Printf("Error: field %s not found\n", "ConvertColumn")
  175. return
  176. }
  177. // 检查字段是否可导出
  178. if !fieldValue.CanSet() {
  179. fmt.Printf("Error: field %s is not exported and cannot be set\n", "ConvertColumn")
  180. return
  181. }
  182. // 渲染模板
  183. var buf bytes.Buffer
  184. err = templateSql.Execute(&buf, param)
  185. if err != nil {
  186. fmt.Sprintf("执行模板填充失败: %v", err)
  187. return
  188. }
  189. sqlStr = buf.String()
  190. fmt.Printf("生成的准换编码语句为:%s\n", sqlStr)
  191. return sqlStr
  192. }
  193. var sqlGeneratorFactory = map[SqlCondition]SqlParam{
  194. // 添加支持的语法
  195. GroupUnit: &GroupUnitParam{
  196. supportGrams: []SqlCondition{
  197. Distinct,
  198. Order,
  199. Delimiter,
  200. },
  201. },
  202. Order: &OrderParam{},
  203. Delimiter: &DelimiterParam{},
  204. Distinct: &DistinctParam{},
  205. ConvertColumn: &ConvertParam{},
  206. ToDate: &ToDateParam{},
  207. }
  208. type DelimiterParam struct {
  209. }
  210. func (delimiterParam *DelimiterParam) GetParamName() string {
  211. return "Delimiter"
  212. }
  213. func (delimiterParam *DelimiterParam) GetFormatConditionStr(param *QueryParam) string {
  214. if param.Delimiter == "" {
  215. return ","
  216. }
  217. return param.Delimiter
  218. }
  219. type OrderParam struct {
  220. Field string
  221. Rule string
  222. }
  223. func (orderParam *OrderParam) GetParamName() string {
  224. return "Order"
  225. }
  226. func (orderParam *OrderParam) GetFormatConditionStr(param *QueryParam) string {
  227. if param.OrderField == "" {
  228. orderParam.Field = param.Column
  229. } else {
  230. orderParam.Field = param.OrderField
  231. }
  232. if param.OrderRule != "" {
  233. if param.OrderRule == "ASC" || param.OrderRule == "DESC" {
  234. orderParam.Rule = param.OrderRule
  235. }
  236. }
  237. return fmt.Sprintf("ORDER BY %s %s", orderParam.Field, orderParam.Rule)
  238. }
  239. // 高级语法聚合
  240. type GroupUnitParam struct {
  241. supportGrams []SqlCondition
  242. }
  243. func (groupUnitParam *GroupUnitParam) GetParamName() string {
  244. return "GroupUnit"
  245. }
  246. func (groupUnitParam *GroupUnitParam) GetFormatConditionStr(param *QueryParam) (sqlStr string) {
  247. dbDriver, _ := getDriverInstance(param.Driver)
  248. if param.Column == "" {
  249. FileLog.Error("聚合字段为空,无法生成聚合sql")
  250. return
  251. }
  252. var templateSqlStr string
  253. if _, ok := TemplateMap[GroupUnit][dbDriver]; !ok {
  254. templateSqlStr = TemplateMap[GroupUnit][MySql]
  255. } else {
  256. templateSqlStr = TemplateMap[GroupUnit][dbDriver]
  257. }
  258. if templateSqlStr == "" {
  259. FileLog.Error("聚合sql模板不存在,无法生成聚合sql")
  260. return
  261. }
  262. templateSql, err := template.New("GroupUnit").Parse(templateSqlStr)
  263. if err != nil {
  264. FileLog.Error("failed to parse template: %v", err)
  265. return
  266. }
  267. //反射获取结构体的值
  268. value := reflect.ValueOf(param)
  269. // 检查是否是指针
  270. if value.Kind() != reflect.Ptr {
  271. fmt.Println("请求参数必须是一个结构体")
  272. return
  273. }
  274. // 获取结构体的元素
  275. elem := value.Elem()
  276. // 检查是否是结构体
  277. if elem.Kind() != reflect.Struct {
  278. fmt.Println("请求参数必须是一个结构体")
  279. return
  280. }
  281. for _, supportGram := range groupUnitParam.supportGrams {
  282. // 获取字段的值
  283. fieldValue := elem.FieldByName(string(supportGram))
  284. // 检查字段是否存在
  285. if !fieldValue.IsValid() {
  286. fmt.Printf("Error: field %s not found\n", supportGram)
  287. continue
  288. }
  289. // 检查字段是否可导出
  290. if !fieldValue.CanSet() {
  291. fmt.Printf("Error: field %s is not exported and cannot be set\n", supportGram)
  292. continue
  293. }
  294. newValue := sqlGeneratorFactory[supportGram].GetFormatConditionStr(param)
  295. // 检查新值的类型是否匹配
  296. newValueValue := reflect.ValueOf(newValue)
  297. if fieldValue.Type() != newValueValue.Type() {
  298. fmt.Printf("字段%s类型不匹配 : 期望的类型是 %s, 传入的类型为: %s", supportGram, fieldValue.Type(), newValueValue.Type())
  299. return
  300. }
  301. // 设置字段的值
  302. fieldValue.Set(newValueValue)
  303. }
  304. // 渲染模板
  305. var buf bytes.Buffer
  306. err = templateSql.Execute(&buf, param)
  307. if err != nil {
  308. fmt.Sprintf("执行模板填充失败: %v", err)
  309. return
  310. }
  311. sqlStr = buf.String()
  312. fmt.Printf("生成的聚合语句为:%s\n", sqlStr)
  313. return sqlStr
  314. }
  315. func GroupUnitFunc(driver string, column, delimiter string, columnOrder bool, orderField, orderRule string, hasDistinct bool) (sqlStr string) {
  316. dbDriver, _ := getDriverInstance(driver)
  317. if delimiter == "" {
  318. delimiter = ","
  319. }
  320. if column == "" {
  321. column = "[UNKNOWN COLUMN]"
  322. }
  323. //if tableAlia != "" {
  324. // column = fmt.Sprintf("%s.%s", tableAlia, column)
  325. //}
  326. var sqlOrder, strDistinct string
  327. if hasDistinct {
  328. strDistinct = "DISTINCT"
  329. }
  330. if columnOrder && orderField == "" {
  331. orderField = column
  332. }
  333. switch dbDriver {
  334. case DM:
  335. if columnOrder {
  336. sqlOrder = fmt.Sprintf("WITHIN GROUP (ORDER BY %s %s)", orderField, orderRule)
  337. }
  338. sqlStr = fmt.Sprintf("LISTAGG(%s %s, '%s') %s", strDistinct, column, delimiter, sqlOrder)
  339. default:
  340. // 默认使用MySQL的语法
  341. if columnOrder {
  342. sqlOrder = fmt.Sprintf("ORDER BY %s %s", orderField, orderRule)
  343. }
  344. sqlStr = fmt.Sprintf("GROUP_CONCAT(%s %s %s SEPARATOR '%s')", strDistinct, column, sqlOrder, delimiter)
  345. }
  346. return sqlStr
  347. }
  348. func getDriverInstance(driver string) (dbDriver Driver, err error) {
  349. if driver == "" {
  350. dbDriver = supportDriverMap[DbDriverName]
  351. }
  352. if currentDriver, ok := supportDriverMap[driver]; !ok {
  353. err = errors.New("不支持的数据库驱动类型")
  354. return
  355. } else {
  356. dbDriver = currentDriver
  357. }
  358. return
  359. }
  360. func ReplaceDriverKeywords(driver string, sql string) string {
  361. dbDriver, _ := getDriverInstance(driver)
  362. rules := map[Driver]map[string]string{
  363. DM: {
  364. "admin": `"admin"`,
  365. "value": `"value"`,
  366. "exchange": `"exchange"`,
  367. "size": `"size"`,
  368. // 查询的from可能会有个别地方是小写, 所以这里不加而是把字段的from统一改为*.from处理
  369. "a.from": `a."from"`,
  370. "b.from": `b."from"`,
  371. "g.from": `g."from"`,
  372. },
  373. }
  374. replacements, ok := rules[dbDriver]
  375. if !ok {
  376. return sql
  377. }
  378. for keyword, replace := range replacements {
  379. // 仅替换单独的单词,复合单词含关键词不管
  380. pattern := fmt.Sprintf(`\b%s\b`, regexp.QuoteMeta(keyword))
  381. re := regexp.MustCompile(pattern)
  382. sql = re.ReplaceAllString(sql, replace)
  383. }
  384. return sql
  385. }
  386. func GenerateQuerySql(gram SqlCondition, param *QueryParam) (sqlGenerator string) {
  387. if exec, ok := sqlGeneratorFactory[gram]; !ok {
  388. FileLog.Error("不支持的语法:%s", gram)
  389. return
  390. } else {
  391. sqlGenerator = exec.GetFormatConditionStr(param)
  392. }
  393. return
  394. }