fetch.go 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package sqlchemy
  15. import (
  16. "reflect"
  17. "yunion.io/x/log"
  18. "yunion.io/x/pkg/errors"
  19. "yunion.io/x/pkg/gotypes"
  20. "yunion.io/x/pkg/util/reflectutils"
  21. )
  22. // Fetch method fetches the values of a struct whose primary key values have been set
  23. // input is a pointer to the model to be populated
  24. func (ts *STableSpec) Fetch(dt interface{}) error {
  25. q := ts.Query()
  26. dataValue := reflect.ValueOf(dt).Elem()
  27. fields := reflectutils.FetchStructFieldValueSet(dataValue)
  28. for _, c := range ts.Columns() {
  29. priVal, _ := fields.GetInterface(c.Name())
  30. if c.IsPrimary() && !gotypes.IsNil(priVal) { // skip update primary key
  31. q = q.Equals(c.Name(), priVal)
  32. }
  33. }
  34. return q.First(dt)
  35. }
  36. // FetchAll method fetches the values of an array of structs whose primary key values have been set
  37. // input is a pointer to the array of models to be populated
  38. func (ts *STableSpec) FetchAll(dest interface{}) error {
  39. arrayType := reflect.TypeOf(dest).Elem()
  40. if arrayType.Kind() != reflect.Array && arrayType.Kind() != reflect.Slice {
  41. return errors.Wrap(ErrNeedsArray, "dest is not an array or slice")
  42. }
  43. arrayValue := reflect.ValueOf(dest).Elem()
  44. primaryCols := ts.PrimaryColumns()
  45. if len(primaryCols) != 1 {
  46. return errors.Wrap(ErrNotSupported, "support 1 primary key only")
  47. }
  48. primaryCol := primaryCols[0]
  49. keyValues := make([]interface{}, arrayValue.Len())
  50. for i := 0; i < arrayValue.Len(); i++ {
  51. eleValue := arrayValue.Index(i)
  52. fields := reflectutils.FetchStructFieldValueSet(eleValue)
  53. keyValues[i], _ = fields.GetInterface(primaryCol.Name())
  54. }
  55. q := ts.Query().In(primaryCol.Name(), keyValues)
  56. tmpDestMaps, err := q.AllStringMap()
  57. if err != nil {
  58. return errors.Wrap(err, "q.AllStringMap")
  59. }
  60. tmpDestMapMap := make(map[string]map[string]string)
  61. for i := 0; i < len(tmpDestMaps); i++ {
  62. tmpDestMapMap[tmpDestMaps[i][primaryCol.Name()]] = tmpDestMaps[i]
  63. }
  64. for i := 0; i < arrayValue.Len(); i++ {
  65. keyValueStr := GetStringValue(keyValues[i])
  66. if tmpMap, ok := tmpDestMapMap[keyValueStr]; ok {
  67. err = mapString2Struct(tmpMap, arrayValue.Index(i))
  68. if err != nil {
  69. return errors.Wrapf(err, "mapString2Struct %d:%s", i, keyValueStr)
  70. }
  71. } else {
  72. log.Warningf("element %d:%s not found in fetch result", i, keyValueStr)
  73. }
  74. }
  75. return nil
  76. }