convert.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. // Copyright (c) 2012 The gocql 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 gocql
  5. import (
  6. "database/sql/driver"
  7. "encoding/binary"
  8. "fmt"
  9. "github.com/tux21b/gocql/uuid"
  10. "math"
  11. "reflect"
  12. "strconv"
  13. "time"
  14. )
  15. const (
  16. typeCustom uint16 = 0x0000
  17. typeAscii uint16 = 0x0001
  18. typeBigInt uint16 = 0x0002
  19. typeBlob uint16 = 0x0003
  20. typeBool uint16 = 0x0004
  21. typeCounter uint16 = 0x0005
  22. typeDecimal uint16 = 0x0006
  23. typeDouble uint16 = 0x0007
  24. typeFloat uint16 = 0x0008
  25. typeInt uint16 = 0x0009
  26. typeText uint16 = 0x000A
  27. typeTimestamp uint16 = 0x000B
  28. typeUUID uint16 = 0x000C
  29. typeVarchar uint16 = 0x000D
  30. typeVarint uint16 = 0x000E
  31. typeTimeUUID uint16 = 0x000F
  32. typeList uint16 = 0x0020
  33. typeMap uint16 = 0x0021
  34. typeSet uint16 = 0x0022
  35. )
  36. func decode(b []byte, t uint16) driver.Value {
  37. switch t {
  38. case typeBool:
  39. if len(b) >= 1 && b[0] != 0 {
  40. return true
  41. }
  42. return false
  43. case typeBlob:
  44. return b
  45. case typeVarchar, typeText, typeAscii:
  46. return b
  47. case typeInt:
  48. return int64(int32(binary.BigEndian.Uint32(b)))
  49. case typeBigInt:
  50. return int64(binary.BigEndian.Uint64(b))
  51. case typeFloat:
  52. return float64(math.Float32frombits(binary.BigEndian.Uint32(b)))
  53. case typeDouble:
  54. return math.Float64frombits(binary.BigEndian.Uint64(b))
  55. case typeTimestamp:
  56. t := int64(binary.BigEndian.Uint64(b))
  57. sec := t / 1000
  58. nsec := (t - sec*1000) * 1000000
  59. return time.Unix(sec, nsec)
  60. case typeUUID, typeTimeUUID:
  61. return uuid.FromBytes(b)
  62. default:
  63. panic("unsupported type")
  64. }
  65. return b
  66. }
  67. type columnEncoder struct {
  68. columnTypes []uint16
  69. }
  70. func (e *columnEncoder) ColumnConverter(idx int) ValueConverter {
  71. switch e.columnTypes[idx] {
  72. case typeInt:
  73. return ValueConverter(encInt)
  74. case typeBigInt:
  75. return ValueConverter(encBigInt)
  76. case typeFloat:
  77. return ValueConverter(encFloat)
  78. case typeDouble:
  79. return ValueConverter(encDouble)
  80. case typeBool:
  81. return ValueConverter(encBool)
  82. case typeVarchar, typeText, typeAscii:
  83. return ValueConverter(encVarchar)
  84. case typeBlob:
  85. return ValueConverter(encBlob)
  86. case typeTimestamp:
  87. return ValueConverter(encTimestamp)
  88. case typeUUID, typeTimeUUID:
  89. return ValueConverter(encUUID)
  90. }
  91. panic("not implemented")
  92. }
  93. type ValueConverter func(v interface{}) (driver.Value, error)
  94. func (vc ValueConverter) ConvertValue(v interface{}) (driver.Value, error) {
  95. return vc(v)
  96. }
  97. func encBool(v interface{}) (driver.Value, error) {
  98. b, err := driver.Bool.ConvertValue(v)
  99. if err != nil {
  100. return nil, err
  101. }
  102. if b.(bool) {
  103. return []byte{1}, nil
  104. }
  105. return []byte{0}, nil
  106. }
  107. func encInt(v interface{}) (driver.Value, error) {
  108. x, err := driver.Int32.ConvertValue(v)
  109. if err != nil {
  110. return nil, err
  111. }
  112. b := make([]byte, 4)
  113. binary.BigEndian.PutUint32(b, uint32(x.(int64)))
  114. return b, nil
  115. }
  116. func encBigInt(v interface{}) (driver.Value, error) {
  117. x := reflect.Indirect(reflect.ValueOf(v)).Interface()
  118. b := make([]byte, 8)
  119. binary.BigEndian.PutUint64(b, uint64(x.(int64)))
  120. return b, nil
  121. }
  122. func encVarchar(v interface{}) (driver.Value, error) {
  123. x, err := driver.String.ConvertValue(v)
  124. if err != nil {
  125. return nil, err
  126. }
  127. return []byte(x.(string)), nil
  128. }
  129. func encFloat(v interface{}) (driver.Value, error) {
  130. x, err := driver.DefaultParameterConverter.ConvertValue(v)
  131. if err != nil {
  132. return nil, err
  133. }
  134. var f float64
  135. switch x := x.(type) {
  136. case float64:
  137. f = x
  138. case int64:
  139. f = float64(x)
  140. case []byte:
  141. if f, err = strconv.ParseFloat(string(x), 64); err != nil {
  142. return nil, err
  143. }
  144. default:
  145. return nil, fmt.Errorf("can not convert %T to float64", x)
  146. }
  147. b := make([]byte, 4)
  148. binary.BigEndian.PutUint32(b, math.Float32bits(float32(f)))
  149. return b, nil
  150. }
  151. func encDouble(v interface{}) (driver.Value, error) {
  152. x, err := driver.DefaultParameterConverter.ConvertValue(v)
  153. if err != nil {
  154. return nil, err
  155. }
  156. var f float64
  157. switch x := x.(type) {
  158. case float64:
  159. f = x
  160. case int64:
  161. f = float64(x)
  162. case []byte:
  163. if f, err = strconv.ParseFloat(string(x), 64); err != nil {
  164. return nil, err
  165. }
  166. default:
  167. return nil, fmt.Errorf("can not convert %T to float64", x)
  168. }
  169. b := make([]byte, 8)
  170. binary.BigEndian.PutUint64(b, math.Float64bits(f))
  171. return b, nil
  172. }
  173. func encTimestamp(v interface{}) (driver.Value, error) {
  174. x, err := driver.DefaultParameterConverter.ConvertValue(v)
  175. if err != nil {
  176. return nil, err
  177. }
  178. var millis int64
  179. switch x := x.(type) {
  180. case time.Time:
  181. x = x.In(time.UTC)
  182. millis = x.UnixNano() / 1000000
  183. default:
  184. return nil, fmt.Errorf("can not convert %T to a timestamp", x)
  185. }
  186. b := make([]byte, 8)
  187. binary.BigEndian.PutUint64(b, uint64(millis))
  188. return b, nil
  189. }
  190. func encBlob(v interface{}) (driver.Value, error) {
  191. x, err := driver.DefaultParameterConverter.ConvertValue(v)
  192. if err != nil {
  193. return nil, err
  194. }
  195. var b []byte
  196. switch x := x.(type) {
  197. case string:
  198. b = []byte(x)
  199. case []byte:
  200. b = x
  201. default:
  202. return nil, fmt.Errorf("can not convert %T to a []byte", x)
  203. }
  204. return b, nil
  205. }
  206. func encUUID(v interface{}) (driver.Value, error) {
  207. var u uuid.UUID
  208. switch v := v.(type) {
  209. case string:
  210. var err error
  211. u, err = uuid.ParseUUID(v)
  212. if err != nil {
  213. return nil, err
  214. }
  215. case []byte:
  216. u = uuid.FromBytes(v)
  217. case uuid.UUID:
  218. u = v
  219. default:
  220. return nil, fmt.Errorf("can not convert %T to a UUID", v)
  221. }
  222. return u.Bytes(), nil
  223. }