A fork of Gitea (see branch `mj`) adding Majority Judgment Polls 𐄷 over Issues and Merge Requests. https://git.mieuxvoter.fr
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

157 lines
4.1 KiB

  1. // Copyright 2017 The Xorm Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package statements
  5. import (
  6. "database/sql"
  7. "database/sql/driver"
  8. "fmt"
  9. "reflect"
  10. "time"
  11. "xorm.io/xorm/convert"
  12. "xorm.io/xorm/dialects"
  13. "xorm.io/xorm/internal/json"
  14. "xorm.io/xorm/schemas"
  15. )
  16. var (
  17. nullFloatType = reflect.TypeOf(sql.NullFloat64{})
  18. )
  19. // Value2Interface convert a field value of a struct to interface for puting into database
  20. func (statement *Statement) Value2Interface(col *schemas.Column, fieldValue reflect.Value) (interface{}, error) {
  21. if fieldValue.CanAddr() {
  22. if fieldConvert, ok := fieldValue.Addr().Interface().(convert.Conversion); ok {
  23. data, err := fieldConvert.ToDB()
  24. if err != nil {
  25. return nil, err
  26. }
  27. if col.SQLType.IsBlob() {
  28. return data, nil
  29. }
  30. return string(data), nil
  31. }
  32. }
  33. isNil := fieldValue.Kind() == reflect.Ptr && fieldValue.IsNil()
  34. if !isNil {
  35. if fieldConvert, ok := fieldValue.Interface().(convert.Conversion); ok {
  36. data, err := fieldConvert.ToDB()
  37. if err != nil {
  38. return nil, err
  39. }
  40. if col.SQLType.IsBlob() {
  41. return data, nil
  42. }
  43. if nil == data {
  44. return nil, nil
  45. }
  46. return string(data), nil
  47. }
  48. }
  49. fieldType := fieldValue.Type()
  50. k := fieldType.Kind()
  51. if k == reflect.Ptr {
  52. if fieldValue.IsNil() {
  53. return nil, nil
  54. } else if !fieldValue.IsValid() {
  55. return nil, nil
  56. } else {
  57. // !nashtsai! deference pointer type to instance type
  58. fieldValue = fieldValue.Elem()
  59. fieldType = fieldValue.Type()
  60. k = fieldType.Kind()
  61. }
  62. }
  63. switch k {
  64. case reflect.Bool:
  65. return fieldValue.Bool(), nil
  66. case reflect.String:
  67. return fieldValue.String(), nil
  68. case reflect.Struct:
  69. if fieldType.ConvertibleTo(schemas.TimeType) {
  70. t := fieldValue.Convert(schemas.TimeType).Interface().(time.Time)
  71. tf := dialects.FormatColumnTime(statement.dialect, statement.defaultTimeZone, col, t)
  72. return tf, nil
  73. } else if fieldType.ConvertibleTo(nullFloatType) {
  74. t := fieldValue.Convert(nullFloatType).Interface().(sql.NullFloat64)
  75. if !t.Valid {
  76. return nil, nil
  77. }
  78. return t.Float64, nil
  79. }
  80. if !col.SQLType.IsJson() {
  81. // !<winxxp>! 增加支持driver.Valuer接口的结构,如sql.NullString
  82. if v, ok := fieldValue.Interface().(driver.Valuer); ok {
  83. return v.Value()
  84. }
  85. fieldTable, err := statement.tagParser.ParseWithCache(fieldValue)
  86. if err != nil {
  87. return nil, err
  88. }
  89. if len(fieldTable.PrimaryKeys) == 1 {
  90. pkField := reflect.Indirect(fieldValue).FieldByName(fieldTable.PKColumns()[0].FieldName)
  91. return pkField.Interface(), nil
  92. }
  93. return nil, fmt.Errorf("no primary key for col %v", col.Name)
  94. }
  95. if col.SQLType.IsText() {
  96. bytes, err := json.DefaultJSONHandler.Marshal(fieldValue.Interface())
  97. if err != nil {
  98. return nil, err
  99. }
  100. return string(bytes), nil
  101. } else if col.SQLType.IsBlob() {
  102. bytes, err := json.DefaultJSONHandler.Marshal(fieldValue.Interface())
  103. if err != nil {
  104. return nil, err
  105. }
  106. return bytes, nil
  107. }
  108. return nil, fmt.Errorf("Unsupported type %v", fieldValue.Type())
  109. case reflect.Complex64, reflect.Complex128:
  110. bytes, err := json.DefaultJSONHandler.Marshal(fieldValue.Interface())
  111. if err != nil {
  112. return nil, err
  113. }
  114. return string(bytes), nil
  115. case reflect.Array, reflect.Slice, reflect.Map:
  116. if !fieldValue.IsValid() {
  117. return fieldValue.Interface(), nil
  118. }
  119. if col.SQLType.IsText() {
  120. bytes, err := json.DefaultJSONHandler.Marshal(fieldValue.Interface())
  121. if err != nil {
  122. return nil, err
  123. }
  124. return string(bytes), nil
  125. } else if col.SQLType.IsBlob() {
  126. var bytes []byte
  127. var err error
  128. if (k == reflect.Slice) &&
  129. (fieldValue.Type().Elem().Kind() == reflect.Uint8) {
  130. bytes = fieldValue.Bytes()
  131. } else {
  132. bytes, err = json.DefaultJSONHandler.Marshal(fieldValue.Interface())
  133. if err != nil {
  134. return nil, err
  135. }
  136. }
  137. return bytes, nil
  138. }
  139. return nil, ErrUnSupportedType
  140. case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
  141. return fieldValue.Uint(), nil
  142. default:
  143. return fieldValue.Interface(), nil
  144. }
  145. }