convert.go 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. // Extracted from Go database/sql source code
  2. // Copyright 2011 The Go Authors. All rights reserved.
  3. // Use of this source code is governed by a BSD-style
  4. // license that can be found in the LICENSE file.
  5. // Type conversions for Scan.
  6. package sqlite3
  7. import (
  8. "database/sql"
  9. "database/sql/driver"
  10. "errors"
  11. "fmt"
  12. "reflect"
  13. "strconv"
  14. "time"
  15. )
  16. var errNilPtr = errors.New("destination pointer is nil") // embedded in descriptive error
  17. // convertAssign copies to dest the value in src, converting it if possible.
  18. // An error is returned if the copy would result in loss of information.
  19. // dest should be a pointer type.
  20. func convertAssign(dest, src any) error {
  21. // Common cases, without reflect.
  22. switch s := src.(type) {
  23. case string:
  24. switch d := dest.(type) {
  25. case *string:
  26. if d == nil {
  27. return errNilPtr
  28. }
  29. *d = s
  30. return nil
  31. case *[]byte:
  32. if d == nil {
  33. return errNilPtr
  34. }
  35. *d = []byte(s)
  36. return nil
  37. case *sql.RawBytes:
  38. if d == nil {
  39. return errNilPtr
  40. }
  41. *d = append((*d)[:0], s...)
  42. return nil
  43. }
  44. case []byte:
  45. switch d := dest.(type) {
  46. case *string:
  47. if d == nil {
  48. return errNilPtr
  49. }
  50. *d = string(s)
  51. return nil
  52. case *any:
  53. if d == nil {
  54. return errNilPtr
  55. }
  56. *d = cloneBytes(s)
  57. return nil
  58. case *[]byte:
  59. if d == nil {
  60. return errNilPtr
  61. }
  62. *d = cloneBytes(s)
  63. return nil
  64. case *sql.RawBytes:
  65. if d == nil {
  66. return errNilPtr
  67. }
  68. *d = s
  69. return nil
  70. }
  71. case time.Time:
  72. switch d := dest.(type) {
  73. case *time.Time:
  74. *d = s
  75. return nil
  76. case *string:
  77. *d = s.Format(time.RFC3339Nano)
  78. return nil
  79. case *[]byte:
  80. if d == nil {
  81. return errNilPtr
  82. }
  83. *d = []byte(s.Format(time.RFC3339Nano))
  84. return nil
  85. case *sql.RawBytes:
  86. if d == nil {
  87. return errNilPtr
  88. }
  89. *d = s.AppendFormat((*d)[:0], time.RFC3339Nano)
  90. return nil
  91. }
  92. case nil:
  93. switch d := dest.(type) {
  94. case *any:
  95. if d == nil {
  96. return errNilPtr
  97. }
  98. *d = nil
  99. return nil
  100. case *[]byte:
  101. if d == nil {
  102. return errNilPtr
  103. }
  104. *d = nil
  105. return nil
  106. case *sql.RawBytes:
  107. if d == nil {
  108. return errNilPtr
  109. }
  110. *d = nil
  111. return nil
  112. }
  113. }
  114. var sv reflect.Value
  115. switch d := dest.(type) {
  116. case *string:
  117. sv = reflect.ValueOf(src)
  118. switch sv.Kind() {
  119. case reflect.Bool,
  120. reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
  121. reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
  122. reflect.Float32, reflect.Float64:
  123. *d = asString(src)
  124. return nil
  125. }
  126. case *[]byte:
  127. sv = reflect.ValueOf(src)
  128. if b, ok := asBytes(nil, sv); ok {
  129. *d = b
  130. return nil
  131. }
  132. case *sql.RawBytes:
  133. sv = reflect.ValueOf(src)
  134. if b, ok := asBytes([]byte(*d)[:0], sv); ok {
  135. *d = sql.RawBytes(b)
  136. return nil
  137. }
  138. case *bool:
  139. bv, err := driver.Bool.ConvertValue(src)
  140. if err == nil {
  141. *d = bv.(bool)
  142. }
  143. return err
  144. case *any:
  145. *d = src
  146. return nil
  147. }
  148. if scanner, ok := dest.(sql.Scanner); ok {
  149. return scanner.Scan(src)
  150. }
  151. dpv := reflect.ValueOf(dest)
  152. if dpv.Kind() != reflect.Ptr {
  153. return errors.New("destination not a pointer")
  154. }
  155. if dpv.IsNil() {
  156. return errNilPtr
  157. }
  158. if !sv.IsValid() {
  159. sv = reflect.ValueOf(src)
  160. }
  161. dv := reflect.Indirect(dpv)
  162. if sv.IsValid() && sv.Type().AssignableTo(dv.Type()) {
  163. switch b := src.(type) {
  164. case []byte:
  165. dv.Set(reflect.ValueOf(cloneBytes(b)))
  166. default:
  167. dv.Set(sv)
  168. }
  169. return nil
  170. }
  171. if dv.Kind() == sv.Kind() && sv.Type().ConvertibleTo(dv.Type()) {
  172. dv.Set(sv.Convert(dv.Type()))
  173. return nil
  174. }
  175. // The following conversions use a string value as an intermediate representation
  176. // to convert between various numeric types.
  177. //
  178. // This also allows scanning into user defined types such as "type Int int64".
  179. // For symmetry, also check for string destination types.
  180. switch dv.Kind() {
  181. case reflect.Ptr:
  182. if src == nil {
  183. dv.Set(reflect.Zero(dv.Type()))
  184. return nil
  185. }
  186. dv.Set(reflect.New(dv.Type().Elem()))
  187. return convertAssign(dv.Interface(), src)
  188. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  189. s := asString(src)
  190. i64, err := strconv.ParseInt(s, 10, dv.Type().Bits())
  191. if err != nil {
  192. err = strconvErr(err)
  193. return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err)
  194. }
  195. dv.SetInt(i64)
  196. return nil
  197. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  198. s := asString(src)
  199. u64, err := strconv.ParseUint(s, 10, dv.Type().Bits())
  200. if err != nil {
  201. err = strconvErr(err)
  202. return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err)
  203. }
  204. dv.SetUint(u64)
  205. return nil
  206. case reflect.Float32, reflect.Float64:
  207. s := asString(src)
  208. f64, err := strconv.ParseFloat(s, dv.Type().Bits())
  209. if err != nil {
  210. err = strconvErr(err)
  211. return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err)
  212. }
  213. dv.SetFloat(f64)
  214. return nil
  215. case reflect.String:
  216. switch v := src.(type) {
  217. case string:
  218. dv.SetString(v)
  219. return nil
  220. case []byte:
  221. dv.SetString(string(v))
  222. return nil
  223. }
  224. }
  225. return fmt.Errorf("unsupported Scan, storing driver.Value type %T into type %T", src, dest)
  226. }
  227. func strconvErr(err error) error {
  228. if ne, ok := err.(*strconv.NumError); ok {
  229. return ne.Err
  230. }
  231. return err
  232. }
  233. func cloneBytes(b []byte) []byte {
  234. if b == nil {
  235. return nil
  236. }
  237. c := make([]byte, len(b))
  238. copy(c, b)
  239. return c
  240. }
  241. func asString(src any) string {
  242. switch v := src.(type) {
  243. case string:
  244. return v
  245. case []byte:
  246. return string(v)
  247. }
  248. rv := reflect.ValueOf(src)
  249. switch rv.Kind() {
  250. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  251. return strconv.FormatInt(rv.Int(), 10)
  252. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  253. return strconv.FormatUint(rv.Uint(), 10)
  254. case reflect.Float64:
  255. return strconv.FormatFloat(rv.Float(), 'g', -1, 64)
  256. case reflect.Float32:
  257. return strconv.FormatFloat(rv.Float(), 'g', -1, 32)
  258. case reflect.Bool:
  259. return strconv.FormatBool(rv.Bool())
  260. }
  261. return fmt.Sprintf("%v", src)
  262. }
  263. func asBytes(buf []byte, rv reflect.Value) (b []byte, ok bool) {
  264. switch rv.Kind() {
  265. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  266. return strconv.AppendInt(buf, rv.Int(), 10), true
  267. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  268. return strconv.AppendUint(buf, rv.Uint(), 10), true
  269. case reflect.Float32:
  270. return strconv.AppendFloat(buf, rv.Float(), 'g', -1, 32), true
  271. case reflect.Float64:
  272. return strconv.AppendFloat(buf, rv.Float(), 'g', -1, 64), true
  273. case reflect.Bool:
  274. return strconv.AppendBool(buf, rv.Bool()), true
  275. case reflect.String:
  276. s := rv.String()
  277. return append(buf, s...), true
  278. }
  279. return
  280. }