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.

convert.go 7.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  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 xorm
  5. import (
  6. "database/sql/driver"
  7. "errors"
  8. "fmt"
  9. "reflect"
  10. "strconv"
  11. "time"
  12. )
  13. var errNilPtr = errors.New("destination pointer is nil") // embedded in descriptive error
  14. func strconvErr(err error) error {
  15. if ne, ok := err.(*strconv.NumError); ok {
  16. return ne.Err
  17. }
  18. return err
  19. }
  20. func cloneBytes(b []byte) []byte {
  21. if b == nil {
  22. return nil
  23. } else {
  24. c := make([]byte, len(b))
  25. copy(c, b)
  26. return c
  27. }
  28. }
  29. func asString(src interface{}) string {
  30. switch v := src.(type) {
  31. case string:
  32. return v
  33. case []byte:
  34. return string(v)
  35. }
  36. rv := reflect.ValueOf(src)
  37. switch rv.Kind() {
  38. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  39. return strconv.FormatInt(rv.Int(), 10)
  40. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  41. return strconv.FormatUint(rv.Uint(), 10)
  42. case reflect.Float64:
  43. return strconv.FormatFloat(rv.Float(), 'g', -1, 64)
  44. case reflect.Float32:
  45. return strconv.FormatFloat(rv.Float(), 'g', -1, 32)
  46. case reflect.Bool:
  47. return strconv.FormatBool(rv.Bool())
  48. }
  49. return fmt.Sprintf("%v", src)
  50. }
  51. func asBytes(buf []byte, rv reflect.Value) (b []byte, ok bool) {
  52. switch rv.Kind() {
  53. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  54. return strconv.AppendInt(buf, rv.Int(), 10), true
  55. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  56. return strconv.AppendUint(buf, rv.Uint(), 10), true
  57. case reflect.Float32:
  58. return strconv.AppendFloat(buf, rv.Float(), 'g', -1, 32), true
  59. case reflect.Float64:
  60. return strconv.AppendFloat(buf, rv.Float(), 'g', -1, 64), true
  61. case reflect.Bool:
  62. return strconv.AppendBool(buf, rv.Bool()), true
  63. case reflect.String:
  64. s := rv.String()
  65. return append(buf, s...), true
  66. }
  67. return
  68. }
  69. // convertAssign copies to dest the value in src, converting it if possible.
  70. // An error is returned if the copy would result in loss of information.
  71. // dest should be a pointer type.
  72. func convertAssign(dest, src interface{}) error {
  73. // Common cases, without reflect.
  74. switch s := src.(type) {
  75. case string:
  76. switch d := dest.(type) {
  77. case *string:
  78. if d == nil {
  79. return errNilPtr
  80. }
  81. *d = s
  82. return nil
  83. case *[]byte:
  84. if d == nil {
  85. return errNilPtr
  86. }
  87. *d = []byte(s)
  88. return nil
  89. }
  90. case []byte:
  91. switch d := dest.(type) {
  92. case *string:
  93. if d == nil {
  94. return errNilPtr
  95. }
  96. *d = string(s)
  97. return nil
  98. case *interface{}:
  99. if d == nil {
  100. return errNilPtr
  101. }
  102. *d = cloneBytes(s)
  103. return nil
  104. case *[]byte:
  105. if d == nil {
  106. return errNilPtr
  107. }
  108. *d = cloneBytes(s)
  109. return nil
  110. }
  111. case time.Time:
  112. switch d := dest.(type) {
  113. case *string:
  114. *d = s.Format(time.RFC3339Nano)
  115. return nil
  116. case *[]byte:
  117. if d == nil {
  118. return errNilPtr
  119. }
  120. *d = []byte(s.Format(time.RFC3339Nano))
  121. return nil
  122. }
  123. case nil:
  124. switch d := dest.(type) {
  125. case *interface{}:
  126. if d == nil {
  127. return errNilPtr
  128. }
  129. *d = nil
  130. return nil
  131. case *[]byte:
  132. if d == nil {
  133. return errNilPtr
  134. }
  135. *d = nil
  136. return nil
  137. }
  138. }
  139. var sv reflect.Value
  140. switch d := dest.(type) {
  141. case *string:
  142. sv = reflect.ValueOf(src)
  143. switch sv.Kind() {
  144. case reflect.Bool,
  145. reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
  146. reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
  147. reflect.Float32, reflect.Float64:
  148. *d = asString(src)
  149. return nil
  150. }
  151. case *[]byte:
  152. sv = reflect.ValueOf(src)
  153. if b, ok := asBytes(nil, sv); ok {
  154. *d = b
  155. return nil
  156. }
  157. case *bool:
  158. bv, err := driver.Bool.ConvertValue(src)
  159. if err == nil {
  160. *d = bv.(bool)
  161. }
  162. return err
  163. case *interface{}:
  164. *d = src
  165. return nil
  166. }
  167. dpv := reflect.ValueOf(dest)
  168. if dpv.Kind() != reflect.Ptr {
  169. return errors.New("destination not a pointer")
  170. }
  171. if dpv.IsNil() {
  172. return errNilPtr
  173. }
  174. if !sv.IsValid() {
  175. sv = reflect.ValueOf(src)
  176. }
  177. dv := reflect.Indirect(dpv)
  178. if sv.IsValid() && sv.Type().AssignableTo(dv.Type()) {
  179. switch b := src.(type) {
  180. case []byte:
  181. dv.Set(reflect.ValueOf(cloneBytes(b)))
  182. default:
  183. dv.Set(sv)
  184. }
  185. return nil
  186. }
  187. if dv.Kind() == sv.Kind() && sv.Type().ConvertibleTo(dv.Type()) {
  188. dv.Set(sv.Convert(dv.Type()))
  189. return nil
  190. }
  191. switch dv.Kind() {
  192. case reflect.Ptr:
  193. if src == nil {
  194. dv.Set(reflect.Zero(dv.Type()))
  195. return nil
  196. }
  197. dv.Set(reflect.New(dv.Type().Elem()))
  198. return convertAssign(dv.Interface(), src)
  199. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  200. s := asString(src)
  201. i64, err := strconv.ParseInt(s, 10, dv.Type().Bits())
  202. if err != nil {
  203. err = strconvErr(err)
  204. return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err)
  205. }
  206. dv.SetInt(i64)
  207. return nil
  208. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  209. s := asString(src)
  210. u64, err := strconv.ParseUint(s, 10, dv.Type().Bits())
  211. if err != nil {
  212. err = strconvErr(err)
  213. return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err)
  214. }
  215. dv.SetUint(u64)
  216. return nil
  217. case reflect.Float32, reflect.Float64:
  218. s := asString(src)
  219. f64, err := strconv.ParseFloat(s, dv.Type().Bits())
  220. if err != nil {
  221. err = strconvErr(err)
  222. return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err)
  223. }
  224. dv.SetFloat(f64)
  225. return nil
  226. case reflect.String:
  227. dv.SetString(asString(src))
  228. return nil
  229. }
  230. return fmt.Errorf("unsupported Scan, storing driver.Value type %T into type %T", src, dest)
  231. }
  232. func asKind(vv reflect.Value, tp reflect.Type) (interface{}, error) {
  233. switch tp.Kind() {
  234. case reflect.Int64:
  235. return vv.Int(), nil
  236. case reflect.Int:
  237. return int(vv.Int()), nil
  238. case reflect.Int32:
  239. return int32(vv.Int()), nil
  240. case reflect.Int16:
  241. return int16(vv.Int()), nil
  242. case reflect.Int8:
  243. return int8(vv.Int()), nil
  244. case reflect.Uint64:
  245. return vv.Uint(), nil
  246. case reflect.Uint:
  247. return uint(vv.Uint()), nil
  248. case reflect.Uint32:
  249. return uint32(vv.Uint()), nil
  250. case reflect.Uint16:
  251. return uint16(vv.Uint()), nil
  252. case reflect.Uint8:
  253. return uint8(vv.Uint()), nil
  254. case reflect.String:
  255. return vv.String(), nil
  256. case reflect.Slice:
  257. if tp.Elem().Kind() == reflect.Uint8 {
  258. v, err := strconv.ParseInt(string(vv.Interface().([]byte)), 10, 64)
  259. if err != nil {
  260. return nil, err
  261. }
  262. return v, nil
  263. }
  264. }
  265. return nil, fmt.Errorf("unsupported primary key type: %v, %v", tp, vv)
  266. }
  267. func convertFloat(v interface{}) (float64, error) {
  268. switch v.(type) {
  269. case float32:
  270. return float64(v.(float32)), nil
  271. case float64:
  272. return v.(float64), nil
  273. case string:
  274. i, err := strconv.ParseFloat(v.(string), 64)
  275. if err != nil {
  276. return 0, err
  277. }
  278. return i, nil
  279. case []byte:
  280. i, err := strconv.ParseFloat(string(v.([]byte)), 64)
  281. if err != nil {
  282. return 0, err
  283. }
  284. return i, nil
  285. }
  286. return 0, fmt.Errorf("unsupported type: %v", v)
  287. }
  288. func convertInt(v interface{}) (int64, error) {
  289. switch v.(type) {
  290. case int:
  291. return int64(v.(int)), nil
  292. case int8:
  293. return int64(v.(int8)), nil
  294. case int16:
  295. return int64(v.(int16)), nil
  296. case int32:
  297. return int64(v.(int32)), nil
  298. case int64:
  299. return v.(int64), nil
  300. case []byte:
  301. i, err := strconv.ParseInt(string(v.([]byte)), 10, 64)
  302. if err != nil {
  303. return 0, err
  304. }
  305. return i, nil
  306. case string:
  307. i, err := strconv.ParseInt(v.(string), 10, 64)
  308. if err != nil {
  309. return 0, err
  310. }
  311. return i, nil
  312. }
  313. return 0, fmt.Errorf("unsupported type: %v", v)
  314. }
  315. func asBool(bs []byte) (bool, error) {
  316. if len(bs) == 0 {
  317. return false, nil
  318. }
  319. if bs[0] == 0x00 {
  320. return false, nil
  321. } else if bs[0] == 0x01 {
  322. return true, nil
  323. }
  324. return strconv.ParseBool(string(bs))
  325. }