callback_query.go 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  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. defer scope.trace(NowFunc())
  16. var (
  17. isSlice, isPtr bool
  18. resultType reflect.Type
  19. results = scope.IndirectValue()
  20. )
  21. if orderBy, ok := scope.Get("gorm:order_by_primary_key"); ok {
  22. if primaryField := scope.PrimaryField(); primaryField != nil {
  23. scope.Search.Order(fmt.Sprintf("%v.%v %v", scope.QuotedTableName(), scope.Quote(primaryField.DBName), orderBy))
  24. }
  25. }
  26. if value, ok := scope.Get("gorm:query_destination"); ok {
  27. results = indirect(reflect.ValueOf(value))
  28. }
  29. if kind := results.Kind(); kind == reflect.Slice {
  30. isSlice = true
  31. resultType = results.Type().Elem()
  32. results.Set(reflect.MakeSlice(results.Type(), 0, 0))
  33. if resultType.Kind() == reflect.Ptr {
  34. isPtr = true
  35. resultType = resultType.Elem()
  36. }
  37. } else if kind != reflect.Struct {
  38. scope.Err(errors.New("unsupported destination, should be slice or struct"))
  39. return
  40. }
  41. scope.prepareQuerySQL()
  42. if !scope.HasError() {
  43. scope.db.RowsAffected = 0
  44. if str, ok := scope.Get("gorm:query_option"); ok {
  45. scope.SQL += addExtraSpaceIfExist(fmt.Sprint(str))
  46. }
  47. if rows, err := scope.SQLDB().Query(scope.SQL, scope.SQLVars...); scope.Err(err) == nil {
  48. defer rows.Close()
  49. columns, _ := rows.Columns()
  50. for rows.Next() {
  51. scope.db.RowsAffected++
  52. elem := results
  53. if isSlice {
  54. elem = reflect.New(resultType).Elem()
  55. }
  56. scope.scan(rows, columns, scope.New(elem.Addr().Interface()).Fields())
  57. if isSlice {
  58. if isPtr {
  59. results.Set(reflect.Append(results, elem.Addr()))
  60. } else {
  61. results.Set(reflect.Append(results, elem))
  62. }
  63. }
  64. }
  65. if err := rows.Err(); err != nil {
  66. scope.Err(err)
  67. } else if scope.db.RowsAffected == 0 && !isSlice {
  68. scope.Err(ErrRecordNotFound)
  69. }
  70. }
  71. }
  72. }
  73. // afterQueryCallback will invoke `AfterFind` method after querying
  74. func afterQueryCallback(scope *Scope) {
  75. if !scope.HasError() {
  76. scope.CallMethod("AfterFind")
  77. }
  78. }