operator.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. package gormop
  2. import (
  3. "fmt"
  4. "reflect"
  5. "regexp"
  6. "strings"
  7. "github.com/jinzhu/gorm"
  8. "github.com/qor5/admin/presets"
  9. "github.com/qor5/web"
  10. )
  11. var (
  12. wildcardReg = regexp.MustCompile(`[%_]`)
  13. )
  14. func DataOperator(db *gorm.DB) (r *DataOperatorBuilder) {
  15. r = &DataOperatorBuilder{db: db}
  16. return
  17. }
  18. type DataOperatorBuilder struct {
  19. db *gorm.DB
  20. }
  21. func (op *DataOperatorBuilder) Search(obj interface{}, params *presets.SearchParams, ctx *web.EventContext) (r interface{}, totalCount int, err error) {
  22. ilike := "ILIKE"
  23. if op.db.Dialect().GetName() == "sqlite3" {
  24. ilike = "LIKE"
  25. }
  26. wh := op.db.Model(obj)
  27. if len(params.KeywordColumns) > 0 && len(params.Keyword) > 0 {
  28. var segs []string
  29. var args []interface{}
  30. for _, c := range params.KeywordColumns {
  31. segs = append(segs, fmt.Sprintf("%s %s ?", c, ilike))
  32. kw := wildcardReg.ReplaceAllString(params.Keyword, `\$0`)
  33. args = append(args, fmt.Sprintf("%%%s%%", kw))
  34. }
  35. wh = wh.Where(strings.Join(segs, " OR "), args...)
  36. }
  37. for _, cond := range params.SQLConditions {
  38. wh = wh.Where(strings.Replace(cond.Query, " ILIKE ", " "+ilike+" ", -1), cond.Args...)
  39. }
  40. err = wh.Count(&totalCount).Error
  41. if err != nil {
  42. return
  43. }
  44. if params.PerPage > 0 {
  45. wh = wh.Limit(params.PerPage)
  46. page := params.Page
  47. if page == 0 {
  48. page = 1
  49. }
  50. offset := (page - 1) * params.PerPage
  51. wh = wh.Offset(offset)
  52. }
  53. orderBy := params.OrderBy
  54. if len(orderBy) > 0 {
  55. wh = wh.Order(orderBy)
  56. }
  57. err = wh.Find(obj).Error
  58. if err != nil {
  59. return
  60. }
  61. r = reflect.ValueOf(obj).Elem().Interface()
  62. return
  63. }
  64. func (op *DataOperatorBuilder) primarySluggerWhere(obj interface{}, id string) *gorm.DB {
  65. wh := op.db.Model(obj)
  66. if id == "" {
  67. return wh
  68. }
  69. if slugger, ok := obj.(presets.SlugDecoder); ok {
  70. cs := slugger.PrimaryColumnValuesBySlug(id)
  71. for key, value := range cs {
  72. wh = wh.Where(fmt.Sprintf("%s = ?", key), value)
  73. }
  74. } else {
  75. wh = wh.Where("id = ?", id)
  76. }
  77. return wh
  78. }
  79. func (op *DataOperatorBuilder) Fetch(obj interface{}, id string, ctx *web.EventContext) (r interface{}, err error) {
  80. err = op.primarySluggerWhere(obj, id).Find(obj).Error
  81. if err != nil {
  82. if err == gorm.ErrRecordNotFound {
  83. return nil, presets.ErrRecordNotFound
  84. }
  85. return
  86. }
  87. r = obj
  88. return
  89. }
  90. func (op *DataOperatorBuilder) Save(obj interface{}, id string, ctx *web.EventContext) (err error) {
  91. if id == "" {
  92. err = op.db.Create(obj).Error
  93. return
  94. }
  95. err = op.primarySluggerWhere(obj, id).Update(obj).Error
  96. return
  97. }
  98. func (op *DataOperatorBuilder) Delete(obj interface{}, id string, ctx *web.EventContext) (err error) {
  99. err = op.primarySluggerWhere(obj, id).Delete(obj).Error
  100. return
  101. }