callback_query.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. package gorm
  2. import (
  3. "errors"
  4. "fmt"
  5. "reflect"
  6. )
  7. // Define callbacks for querying
  8. func init() {
  9. DefaultCallback.Query().Register("gorm:query", queryCallback)
  10. DefaultCallback.Query().Register("gorm:preload", preloadCallback)
  11. DefaultCallback.Query().Register("gorm:after_query", afterQueryCallback)
  12. }
  13. // queryCallback used to query data from database
  14. func queryCallback(scope *Scope) {
  15. if _, skip := scope.InstanceGet("gorm:skip_query_callback"); skip {
  16. return
  17. }
  18. defer scope.trace(NowFunc())
  19. var (
  20. isSlice, isPtr bool
  21. resultType reflect.Type
  22. results = scope.IndirectValue()
  23. )
  24. if orderBy, ok := scope.Get("gorm:order_by_primary_key"); ok {
  25. if primaryField := scope.PrimaryField(); primaryField != nil {
  26. scope.Search.Order(fmt.Sprintf("%v.%v %v", scope.QuotedTableName(), scope.Quote(primaryField.DBName), orderBy))
  27. }
  28. }
  29. if value, ok := scope.Get("gorm:query_destination"); ok {
  30. results = indirect(reflect.ValueOf(value))
  31. }
  32. if kind := results.Kind(); kind == reflect.Slice {
  33. isSlice = true
  34. resultType = results.Type().Elem()
  35. results.Set(reflect.MakeSlice(results.Type(), 0, 0))
  36. if resultType.Kind() == reflect.Ptr {
  37. isPtr = true
  38. resultType = resultType.Elem()
  39. }
  40. } else if kind != reflect.Struct {
  41. scope.Err(errors.New("unsupported destination, should be slice or struct"))
  42. return
  43. }
  44. scope.prepareQuerySQL()
  45. if !scope.HasError() {
  46. scope.db.RowsAffected = 0
  47. if str, ok := scope.Get("gorm:query_option"); ok {
  48. scope.SQL += addExtraSpaceIfExist(fmt.Sprint(str))
  49. }
  50. if rows, err := scope.SQLDB().Query(scope.SQL, scope.SQLVars...); scope.Err(err) == nil {
  51. defer rows.Close()
  52. columns, _ := rows.Columns()
  53. for rows.Next() {
  54. scope.db.RowsAffected++
  55. elem := results
  56. if isSlice {
  57. elem = reflect.New(resultType).Elem()
  58. }
  59. scope.scan(rows, columns, scope.New(elem.Addr().Interface()).Fields())
  60. if isSlice {
  61. if isPtr {
  62. results.Set(reflect.Append(results, elem.Addr()))
  63. } else {
  64. results.Set(reflect.Append(results, elem))
  65. }
  66. }
  67. }
  68. if err := rows.Err(); err != nil {
  69. scope.Err(err)
  70. } else if scope.db.RowsAffected == 0 && !isSlice {
  71. scope.Err(ErrRecordNotFound)
  72. }
  73. }
  74. }
  75. }
  76. // afterQueryCallback will invoke `AfterFind` method after querying
  77. func afterQueryCallback(scope *Scope) {
  78. if !scope.HasError() {
  79. scope.CallMethod("AfterFind")
  80. }
  81. }