convert.go 5.0 KB

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