本站源代码
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.

307 line
7.0KB

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