preload.go 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. package rest_gorm
  2. import (
  3. "fmt"
  4. "log"
  5. "reflect"
  6. "strings"
  7. "git.ali33.ru/fcg-xvii/rest"
  8. "gorm.io/gorm"
  9. )
  10. func Preload(obj any, fields rest.FieldList, q *gorm.DB) (*gorm.DB, error) {
  11. return preloadPrefix(obj, fields, q, "")
  12. }
  13. func preloadPrefix(obj any, fields rest.FieldList, q *gorm.DB, prefix string) (*gorm.DB, error) {
  14. val := reflect.ValueOf(obj)
  15. names, err := namesExt(val)
  16. if err != nil {
  17. return nil, err
  18. }
  19. for _, name := range names {
  20. if f, check := fields.Field(name.eName); check {
  21. q = q.Preload(prefix + name.eName)
  22. if f.IsObject() {
  23. log.Println("is_object:" + prefix + name.eName)
  24. if q, err = preloadPrefix(name.eValue, f.Names, q, prefix+name.eName+"."); err != nil {
  25. return nil, err
  26. }
  27. }
  28. }
  29. }
  30. return q, nil
  31. }
  32. type eExtName struct {
  33. eName string
  34. eValue any
  35. }
  36. func fElemType(t reflect.Type) reflect.Type {
  37. switch t.Kind() {
  38. case reflect.Ptr, reflect.Interface, reflect.Slice:
  39. return fElemType(t.Elem())
  40. }
  41. return t
  42. }
  43. func namesExt(val reflect.Value) (res []eExtName, err error) {
  44. k := val.Kind()
  45. switch k {
  46. case reflect.Ptr, reflect.Interface, reflect.Slice:
  47. return namesExt(val.Elem())
  48. }
  49. if k != reflect.Struct {
  50. return nil, fmt.Errorf("type [ %v ] is not a struct", k)
  51. }
  52. t := reflect.TypeOf(val.Interface())
  53. for i := 0; i < t.NumField(); i++ {
  54. fType := t.Field(i)
  55. tag := fType.Tag.Get("rest")
  56. if len(tag) > 0 && strings.Contains(tag, "ext") {
  57. rVal := reflect.New(fElemType(fType.Type))
  58. res = append(
  59. res,
  60. eExtName{
  61. eName: fType.Name,
  62. eValue: rVal.Interface(),
  63. },
  64. )
  65. }
  66. }
  67. return
  68. }