query.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. package search
  2. import (
  3. "fmt"
  4. "reflect"
  5. "strings"
  6. )
  7. const (
  8. // FromQueryTag tag标记
  9. FromQueryTag = "search"
  10. // Mysql 数据库标识
  11. Mysql = "mysql"
  12. // Postgres 数据库标识
  13. Postgres = "postgres"
  14. )
  15. // ResolveSearchQuery 解析
  16. /**
  17. * exact / iexact 等于
  18. * contains / icontains 包含
  19. * gt / gte 大于 / 大于等于
  20. * lt / lte 小于 / 小于等于
  21. * startswith / istartswith 以…起始
  22. * endswith / iendswith 以…结束
  23. * in
  24. * isnull
  25. * order 排序 e.g. order[key]=desc order[key]=asc
  26. */
  27. func ResolveSearchQuery(driver string, q interface{}, condition Condition) {
  28. qType := reflect.TypeOf(q)
  29. qValue := reflect.ValueOf(q)
  30. var tag string
  31. var ok bool
  32. var t *resolveSearchTag
  33. //var sep = "`"
  34. //if driver == Postgres {
  35. // sep = "\""
  36. //}
  37. for i := 0; i < qType.NumField(); i++ {
  38. tag, ok = "", false
  39. tag, ok = qType.Field(i).Tag.Lookup(FromQueryTag)
  40. if !ok {
  41. //递归调用
  42. ResolveSearchQuery(driver, qValue.Field(i).Interface(), condition)
  43. continue
  44. }
  45. switch tag {
  46. case "-":
  47. continue
  48. }
  49. t = makeTag(tag)
  50. if qValue.Field(i).IsZero() {
  51. continue
  52. }
  53. //解析 Postgres `语法不支持,单独适配
  54. if driver == Postgres {
  55. pgSql(driver, t, condition, qValue, i)
  56. } else {
  57. otherSql(driver, t, condition, qValue, i)
  58. }
  59. }
  60. }
  61. func pgSql(driver string, t *resolveSearchTag, condition Condition, qValue reflect.Value, i int) {
  62. switch t.Type {
  63. case "left":
  64. //左关联
  65. join := condition.SetJoinOn(t.Type, fmt.Sprintf(
  66. "left join %s on %s.%s = %s.%s", t.Join, t.Join, t.On[0], t.Table, t.On[1],
  67. ))
  68. ResolveSearchQuery(driver, qValue.Field(i).Interface(), join)
  69. case "exact", "iexact":
  70. condition.SetWhere(fmt.Sprintf("%s.%s = ?", t.Table, t.Column), []interface{}{qValue.Field(i).Interface()})
  71. case "icontains":
  72. condition.SetWhere(fmt.Sprintf("%s.%s ilike ?", t.Table, t.Column), []interface{}{"%" + qValue.Field(i).String() + "%"})
  73. case "contains":
  74. condition.SetWhere(fmt.Sprintf("%s.%s like ?", t.Table, t.Column), []interface{}{"%" + qValue.Field(i).String() + "%"})
  75. case "gt":
  76. condition.SetWhere(fmt.Sprintf("%s.%s > ?", t.Table, t.Column), []interface{}{qValue.Field(i).Interface()})
  77. case "gte":
  78. condition.SetWhere(fmt.Sprintf("%s.%s >= ?", t.Table, t.Column), []interface{}{qValue.Field(i).Interface()})
  79. case "lt":
  80. condition.SetWhere(fmt.Sprintf("%s.%s < ?", t.Table, t.Column), []interface{}{qValue.Field(i).Interface()})
  81. case "lte":
  82. condition.SetWhere(fmt.Sprintf("%s.%s <= ?", t.Table, t.Column), []interface{}{qValue.Field(i).Interface()})
  83. case "istartswith":
  84. condition.SetWhere(fmt.Sprintf("%s.%s ilike ?", t.Table, t.Column), []interface{}{qValue.Field(i).String() + "%"})
  85. case "startswith":
  86. condition.SetWhere(fmt.Sprintf("%s.%s like ?", t.Table, t.Column), []interface{}{qValue.Field(i).String() + "%"})
  87. case "iendswith":
  88. condition.SetWhere(fmt.Sprintf("%s.%s ilike ?", t.Table, t.Column), []interface{}{"%" + qValue.Field(i).String()})
  89. case "endswith":
  90. condition.SetWhere(fmt.Sprintf("%s.%s like ?", t.Table, t.Column), []interface{}{"%" + qValue.Field(i).String()})
  91. case "in":
  92. condition.SetWhere(fmt.Sprintf("%s.%s in (?)", t.Table, t.Column), []interface{}{qValue.Field(i).Interface()})
  93. case "isnull":
  94. if !(qValue.Field(i).IsZero() && qValue.Field(i).IsNil()) {
  95. condition.SetWhere(fmt.Sprintf("%s.%s isnull", t.Table, t.Column), make([]interface{}, 0))
  96. }
  97. case "order":
  98. switch strings.ToLower(qValue.Field(i).String()) {
  99. case "desc", "asc":
  100. condition.SetOrder(fmt.Sprintf("%s.%s %s", t.Table, t.Column, qValue.Field(i).String()))
  101. }
  102. }
  103. }
  104. func otherSql(driver string, t *resolveSearchTag, condition Condition, qValue reflect.Value, i int) {
  105. switch t.Type {
  106. case "left":
  107. //左关联
  108. join := condition.SetJoinOn(t.Type, fmt.Sprintf(
  109. "left join `%s` on `%s`.`%s` = `%s`.`%s`",
  110. t.Join,
  111. t.Join,
  112. t.On[0],
  113. t.Table,
  114. t.On[1],
  115. ))
  116. ResolveSearchQuery(driver, qValue.Field(i).Interface(), join)
  117. case "exact", "iexact":
  118. condition.SetWhere(fmt.Sprintf("`%s`.`%s` = ?", t.Table, t.Column), []interface{}{qValue.Field(i).Interface()})
  119. case "contains", "icontains":
  120. condition.SetWhere(fmt.Sprintf("`%s`.`%s` like ?", t.Table, t.Column), []interface{}{"%" + qValue.Field(i).String() + "%"})
  121. case "gt":
  122. condition.SetWhere(fmt.Sprintf("`%s`.`%s` > ?", t.Table, t.Column), []interface{}{qValue.Field(i).Interface()})
  123. case "gte":
  124. condition.SetWhere(fmt.Sprintf("`%s`.`%s` >= ?", t.Table, t.Column), []interface{}{qValue.Field(i).Interface()})
  125. case "lt":
  126. condition.SetWhere(fmt.Sprintf("`%s`.`%s` < ?", t.Table, t.Column), []interface{}{qValue.Field(i).Interface()})
  127. case "lte":
  128. condition.SetWhere(fmt.Sprintf("`%s`.`%s` <= ?", t.Table, t.Column), []interface{}{qValue.Field(i).Interface()})
  129. case "startswith", "istartswith":
  130. condition.SetWhere(fmt.Sprintf("`%s`.`%s` like ?", t.Table, t.Column), []interface{}{qValue.Field(i).String() + "%"})
  131. case "endswith", "iendswith":
  132. condition.SetWhere(fmt.Sprintf("`%s`.`%s` like ?", t.Table, t.Column), []interface{}{"%" + qValue.Field(i).String()})
  133. case "in":
  134. condition.SetWhere(fmt.Sprintf("`%s`.`%s` in (?)", t.Table, t.Column), []interface{}{qValue.Field(i).Interface()})
  135. case "isnull":
  136. if !(qValue.Field(i).IsZero() && qValue.Field(i).IsNil()) {
  137. condition.SetWhere(fmt.Sprintf("`%s`.`%s` isnull", t.Table, t.Column), make([]interface{}, 0))
  138. }
  139. case "order":
  140. switch strings.ToLower(qValue.Field(i).String()) {
  141. case "desc", "asc":
  142. condition.SetOrder(fmt.Sprintf("`%s`.`%s` %s", t.Table, t.Column, qValue.Field(i).String()))
  143. }
  144. }
  145. }