row.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. package mysql
  2. import (
  3. "bytes"
  4. "fmt"
  5. "math"
  6. "os"
  7. "reflect"
  8. "strconv"
  9. "time"
  10. )
  11. // Row is a type for result row. It contains values for any column of received row.
  12. //
  13. // If row is a result of ordinary text query, its element can be
  14. // []byte slice, contained result text or nil if NULL is returned.
  15. //
  16. // If it is a result of prepared statement execution, its element field can be:
  17. // intX, uintX, floatX, []byte, Date, Time, time.Time (in Local location) or nil.
  18. type Row []interface{}
  19. // Bin gets the nn-th value and returns it as []byte ([]byte{} if NULL).
  20. func (tr Row) Bin(nn int) (bin []byte) {
  21. switch data := tr[nn].(type) {
  22. case nil:
  23. // bin = []byte{}
  24. case []byte:
  25. bin = data
  26. default:
  27. buf := new(bytes.Buffer)
  28. fmt.Fprint(buf, data)
  29. bin = buf.Bytes()
  30. }
  31. return
  32. }
  33. // Str gets the nn-th value and returns it as string ("" if NULL).
  34. func (tr Row) Str(nn int) (str string) {
  35. switch data := tr[nn].(type) {
  36. case nil:
  37. // str = ""
  38. case []byte:
  39. str = string(data)
  40. case time.Time:
  41. str = TimeString(data)
  42. case time.Duration:
  43. str = DurationString(data)
  44. default:
  45. str = fmt.Sprint(data)
  46. }
  47. return
  48. }
  49. const _MAX_INT = int64(int(^uint(0) >> 1))
  50. const _MIN_INT = -_MAX_INT - 1
  51. // IntErr gets the nn-th value and returns it as int (0 if NULL). Returns error if
  52. // conversion is impossible.
  53. func (tr Row) IntErr(nn int) (val int, err error) {
  54. switch data := tr[nn].(type) {
  55. case nil:
  56. // nop
  57. case int32:
  58. val = int(data)
  59. case int16:
  60. val = int(data)
  61. case uint16:
  62. val = int(data)
  63. case int8:
  64. val = int(data)
  65. case uint8:
  66. val = int(data)
  67. case []byte:
  68. val, err = strconv.Atoi(string(data))
  69. case int64:
  70. if data >= _MIN_INT && data <= _MAX_INT {
  71. val = int(data)
  72. } else {
  73. err = strconv.ErrRange
  74. }
  75. case uint32:
  76. if int64(data) <= _MAX_INT {
  77. val = int(data)
  78. } else {
  79. err = strconv.ErrRange
  80. }
  81. case uint64:
  82. if data <= uint64(_MAX_INT) {
  83. val = int(data)
  84. } else {
  85. err = strconv.ErrRange
  86. }
  87. default:
  88. err = os.ErrInvalid
  89. }
  90. return
  91. }
  92. // Int gets the nn-th value and returns it as int (0 if NULL). Panics if conversion is
  93. // impossible.
  94. func (tr Row) Int(nn int) (val int) {
  95. val, err := tr.IntErr(nn)
  96. if err != nil {
  97. panic(err)
  98. }
  99. return
  100. }
  101. // ForceInt gets the nn-th value and returns it as int. Returns 0 if value is NULL or
  102. // conversion is impossible.
  103. func (tr Row) ForceInt(nn int) (val int) {
  104. val, _ = tr.IntErr(nn)
  105. return
  106. }
  107. const _MAX_UINT = uint64(^uint(0))
  108. // UintErr gets the nn-th value and return it as uint (0 if NULL). Returns error if
  109. // conversion is impossible.
  110. func (tr Row) UintErr(nn int) (val uint, err error) {
  111. switch data := tr[nn].(type) {
  112. case nil:
  113. // nop
  114. case uint32:
  115. val = uint(data)
  116. case uint16:
  117. val = uint(data)
  118. case uint8:
  119. val = uint(data)
  120. case []byte:
  121. var v uint64
  122. v, err = strconv.ParseUint(string(data), 0, 0)
  123. val = uint(v)
  124. case uint64:
  125. if data <= _MAX_UINT {
  126. val = uint(data)
  127. } else {
  128. err = strconv.ErrRange
  129. }
  130. case int8, int16, int32, int64:
  131. v := reflect.ValueOf(data).Int()
  132. if v >= 0 && uint64(v) <= _MAX_UINT {
  133. val = uint(v)
  134. } else {
  135. err = strconv.ErrRange
  136. }
  137. default:
  138. err = os.ErrInvalid
  139. }
  140. return
  141. }
  142. // Uint gets the nn-th value and returns it as uint (0 if NULL). Panics if conversion is
  143. // impossible.
  144. func (tr Row) Uint(nn int) (val uint) {
  145. val, err := tr.UintErr(nn)
  146. if err != nil {
  147. panic(err)
  148. }
  149. return
  150. }
  151. // ForceUint gets the nn-th value and returns it as uint. Returns 0 if value is NULL or
  152. // conversion is impossible.
  153. func (tr Row) ForceUint(nn int) (val uint) {
  154. val, _ = tr.UintErr(nn)
  155. return
  156. }
  157. // DateErr gets the nn-th value and returns it as Date (0000-00-00 if NULL). Returns error
  158. // if conversion is impossible.
  159. func (tr Row) DateErr(nn int) (val Date, err error) {
  160. switch data := tr[nn].(type) {
  161. case nil:
  162. // nop
  163. case Date:
  164. val = data
  165. case []byte:
  166. val, err = ParseDate(string(data))
  167. }
  168. return
  169. }
  170. // Date is like DateErr but panics if conversion is impossible.
  171. func (tr Row) Date(nn int) (val Date) {
  172. val, err := tr.DateErr(nn)
  173. if err != nil {
  174. panic(err)
  175. }
  176. return
  177. }
  178. // ForceDate is like DateErr but returns 0000-00-00 if conversion is impossible.
  179. func (tr Row) ForceDate(nn int) (val Date) {
  180. val, _ = tr.DateErr(nn)
  181. return
  182. }
  183. // TimeErr gets the nn-th value and returns it as time.Time in loc location (zero if NULL)
  184. // Returns error if conversion is impossible. It can convert Date to time.Time.
  185. func (tr Row) TimeErr(nn int, loc *time.Location) (t time.Time, err error) {
  186. switch data := tr[nn].(type) {
  187. case nil:
  188. // nop
  189. case time.Time:
  190. if loc == time.Local {
  191. t = data
  192. } else {
  193. y, mon, d := data.Date()
  194. h, m, s := data.Clock()
  195. t = time.Date(y, mon, d, h, m, s, t.Nanosecond(), loc)
  196. }
  197. case Date:
  198. t = data.Time(loc)
  199. case []byte:
  200. t, err = ParseTime(string(data), loc)
  201. }
  202. return
  203. }
  204. // Time is like TimeErr but panics if conversion is impossible.
  205. func (tr Row) Time(nn int, loc *time.Location) (val time.Time) {
  206. val, err := tr.TimeErr(nn, loc)
  207. if err != nil {
  208. panic(err)
  209. }
  210. return
  211. }
  212. // ForceTime is like TimeErr but returns 0000-00-00 00:00:00 if conversion is
  213. // impossible.
  214. func (tr Row) ForceTime(nn int, loc *time.Location) (val time.Time) {
  215. val, _ = tr.TimeErr(nn, loc)
  216. return
  217. }
  218. // LocaltimeErr gets the nn-th value and returns it as time.Time in Local location
  219. // (zero if NULL). Returns error if conversion is impossible.
  220. // It can convert Date to time.Time.
  221. func (tr Row) LocaltimeErr(nn int) (t time.Time, err error) {
  222. switch data := tr[nn].(type) {
  223. case nil:
  224. // nop
  225. case time.Time:
  226. t = data
  227. case Date:
  228. t = data.Time(time.Local)
  229. case []byte:
  230. t, err = ParseTime(string(data), time.Local)
  231. }
  232. return
  233. }
  234. // Localtime is like LocaltimeErr but panics if conversion is impossible.
  235. func (tr Row) Localtime(nn int) (val time.Time) {
  236. val, err := tr.LocaltimeErr(nn)
  237. if err != nil {
  238. panic(err)
  239. }
  240. return
  241. }
  242. // ForceLocaltime is like LocaltimeErr but returns 0000-00-00 00:00:00 if conversion is
  243. // impossible.
  244. func (tr Row) ForceLocaltime(nn int) (val time.Time) {
  245. val, _ = tr.LocaltimeErr(nn)
  246. return
  247. }
  248. // DurationErr gets the nn-th value and returns it as time.Duration (0 if NULL). Returns error
  249. // if conversion is impossible.
  250. func (tr Row) DurationErr(nn int) (val time.Duration, err error) {
  251. switch data := tr[nn].(type) {
  252. case nil:
  253. case time.Duration:
  254. val = data
  255. case []byte:
  256. val, err = ParseDuration(string(data))
  257. default:
  258. err = fmt.Errorf("Can't convert `%v` to time.Duration", data)
  259. }
  260. return
  261. }
  262. // Duration is like DurationErr but panics if conversion is impossible.
  263. func (tr Row) Duration(nn int) (val time.Duration) {
  264. val, err := tr.DurationErr(nn)
  265. if err != nil {
  266. panic(err)
  267. }
  268. return
  269. }
  270. // ForceDuration is like DurationErr but returns 0 if conversion is impossible.
  271. func (tr Row) ForceDuration(nn int) (val time.Duration) {
  272. val, _ = tr.DurationErr(nn)
  273. return
  274. }
  275. // BoolErr gets the nn-th value and returns it as bool. Returns error
  276. // if conversion is impossible.
  277. func (tr Row) BoolErr(nn int) (val bool, err error) {
  278. switch data := tr[nn].(type) {
  279. case nil:
  280. // nop
  281. case int8:
  282. val = (data != 0)
  283. case int32:
  284. val = (data != 0)
  285. case int16:
  286. val = (data != 0)
  287. case int64:
  288. val = (data != 0)
  289. case uint8:
  290. val = (data != 0)
  291. case uint32:
  292. val = (data != 0)
  293. case uint16:
  294. val = (data != 0)
  295. case uint64:
  296. val = (data != 0)
  297. case []byte:
  298. var v int64
  299. v, err = strconv.ParseInt(string(data), 0, 64)
  300. val = (v != 0)
  301. default:
  302. err = os.ErrInvalid
  303. }
  304. return
  305. }
  306. // Bool is like BoolErr but panics if conversion is impossible.
  307. func (tr Row) Bool(nn int) (val bool) {
  308. val, err := tr.BoolErr(nn)
  309. if err != nil {
  310. panic(err)
  311. }
  312. return
  313. }
  314. // ForceBool is like BoolErr but returns false if conversion is impossible.
  315. func (tr Row) ForceBool(nn int) (val bool) {
  316. val, _ = tr.BoolErr(nn)
  317. return
  318. }
  319. // Int64Err gets the nn-th value and returns it as int64 (0 if NULL). Returns error if
  320. // conversion is impossible.
  321. func (tr Row) Int64Err(nn int) (val int64, err error) {
  322. switch data := tr[nn].(type) {
  323. case nil:
  324. // nop
  325. case int64, int32, int16, int8:
  326. val = reflect.ValueOf(data).Int()
  327. case uint64, uint32, uint16, uint8:
  328. u := reflect.ValueOf(data).Uint()
  329. if u > math.MaxInt64 {
  330. err = strconv.ErrRange
  331. } else {
  332. val = int64(u)
  333. }
  334. case []byte:
  335. val, err = strconv.ParseInt(string(data), 10, 64)
  336. default:
  337. err = os.ErrInvalid
  338. }
  339. return
  340. }
  341. // Int64 gets the nn-th value and returns it as int64 (0 if NULL).
  342. // Panics if conversion is impossible.
  343. func (tr Row) Int64(nn int) (val int64) {
  344. val, err := tr.Int64Err(nn)
  345. if err != nil {
  346. panic(err)
  347. }
  348. return
  349. }
  350. // ForceInt64 gets the nn-th value and returns it as int64. Returns 0 if value is NULL or
  351. // conversion is impossible.
  352. func (tr Row) ForceInt64(nn int) (val int64) {
  353. val, _ = tr.Int64Err(nn)
  354. return
  355. }
  356. // Uint64Err gets the nn-th value and returns it as uint64 (0 if NULL). Returns error if
  357. // conversion is impossible.
  358. func (tr Row) Uint64Err(nn int) (val uint64, err error) {
  359. switch data := tr[nn].(type) {
  360. case nil:
  361. // nop
  362. case uint64, uint32, uint16, uint8:
  363. val = reflect.ValueOf(data).Uint()
  364. case int64, int32, int16, int8:
  365. i := reflect.ValueOf(data).Int()
  366. if i < 0 {
  367. err = strconv.ErrRange
  368. } else {
  369. val = uint64(i)
  370. }
  371. case []byte:
  372. val, err = strconv.ParseUint(string(data), 10, 64)
  373. default:
  374. err = os.ErrInvalid
  375. }
  376. return
  377. }
  378. // Uint64 gets the nn-th value and returns it as uint64 (0 if NULL).
  379. // Panic if conversion is impossible.
  380. func (tr Row) Uint64(nn int) (val uint64) {
  381. val, err := tr.Uint64Err(nn)
  382. if err != nil {
  383. panic(err)
  384. }
  385. return
  386. }
  387. // ForceUint64 gets the nn-th value and returns it as uint64. Returns 0 if value is NULL or
  388. // conversion is impossible.
  389. func (tr Row) ForceUint64(nn int) (val uint64) {
  390. val, _ = tr.Uint64Err(nn)
  391. return
  392. }
  393. // FloatErr gets the nn-th value and returns it as float64 (0 if NULL). Returns error if
  394. // conversion is impossible.
  395. func (tr Row) FloatErr(nn int) (val float64, err error) {
  396. switch data := tr[nn].(type) {
  397. case nil:
  398. // nop
  399. case float64, float32:
  400. val = reflect.ValueOf(data).Float()
  401. case int64, int32, int16, int8:
  402. i := reflect.ValueOf(data).Int()
  403. if i >= 2<<53 || i <= -(2<<53) {
  404. err = strconv.ErrRange
  405. } else {
  406. val = float64(i)
  407. }
  408. case uint64, uint32, uint16, uint8:
  409. u := reflect.ValueOf(data).Uint()
  410. if u >= 2<<53 {
  411. err = strconv.ErrRange
  412. } else {
  413. val = float64(u)
  414. }
  415. case []byte:
  416. val, err = strconv.ParseFloat(string(data), 64)
  417. default:
  418. err = os.ErrInvalid
  419. }
  420. return
  421. }
  422. // Float gets the nn-th value and returns it as float64 (0 if NULL).
  423. // Panics if conversion is impossible.
  424. func (tr Row) Float(nn int) (val float64) {
  425. val, err := tr.FloatErr(nn)
  426. if err != nil {
  427. panic(err)
  428. }
  429. return
  430. }
  431. // ForceFloat gets the nn-th value and returns it as float64. Returns 0 if value is NULL or
  432. // if conversion is impossible.
  433. func (tr Row) ForceFloat(nn int) (val float64) {
  434. val, _ = tr.FloatErr(nn)
  435. return
  436. }