session.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  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. "errors"
  7. )
  8. // Session is the interface used by users to interact with the database.
  9. //
  10. // It extends the Node interface by adding a convinient query builder and
  11. // automatically sets a default consinstency level on all operations
  12. // that do not have a consistency level set.
  13. type Session struct {
  14. Node Node
  15. Cons Consistency
  16. }
  17. // NewSession wraps an existing Node.
  18. func NewSession(node Node) *Session {
  19. if s, ok := node.(*Session); ok {
  20. return &Session{Node: s.Node}
  21. }
  22. return &Session{Node: node, Cons: Quorum}
  23. }
  24. // Query can be used to build new queries that should be executed on this
  25. // session.
  26. func (s *Session) Query(stmt string, args ...interface{}) QueryBuilder {
  27. return QueryBuilder{NewQuery(stmt, args...), s}
  28. }
  29. // Do can be used to modify a copy of an existing query before it is
  30. // executed on this session.
  31. func (s *Session) Do(qry *Query) QueryBuilder {
  32. q := *qry
  33. return QueryBuilder{&q, s}
  34. }
  35. // Close closes all connections. The session is unuseable after this
  36. // operation.
  37. func (s *Session) Close() {
  38. s.Node.Close()
  39. }
  40. // ExecuteBatch executes a Batch on the underlying Node.
  41. func (s *Session) ExecuteBatch(batch *Batch) error {
  42. if batch.Cons == 0 {
  43. batch.Cons = s.Cons
  44. }
  45. return s.Node.ExecuteBatch(batch)
  46. }
  47. // ExecuteQuery executes a Query on the underlying Node.
  48. func (s *Session) ExecuteQuery(qry *Query) (*Iter, error) {
  49. if qry.Cons == 0 {
  50. qry.Cons = s.Cons
  51. }
  52. return s.Node.ExecuteQuery(qry)
  53. }
  54. type Query struct {
  55. Stmt string
  56. Args []interface{}
  57. Cons Consistency
  58. Token string
  59. PageSize int
  60. Trace bool
  61. }
  62. func NewQuery(stmt string, args ...interface{}) *Query {
  63. return &Query{Stmt: stmt, Args: args}
  64. }
  65. type QueryBuilder struct {
  66. qry *Query
  67. ctx Node
  68. }
  69. func (b QueryBuilder) Args(args ...interface{}) {
  70. b.qry.Args = args
  71. }
  72. func (b QueryBuilder) Consistency(cons Consistency) QueryBuilder {
  73. b.qry.Cons = cons
  74. return b
  75. }
  76. func (b QueryBuilder) Token(token string) QueryBuilder {
  77. b.qry.Token = token
  78. return b
  79. }
  80. func (b QueryBuilder) Trace(trace bool) QueryBuilder {
  81. b.qry.Trace = trace
  82. return b
  83. }
  84. func (b QueryBuilder) PageSize(size int) QueryBuilder {
  85. b.qry.PageSize = size
  86. return b
  87. }
  88. func (b QueryBuilder) Exec() error {
  89. _, err := b.ctx.ExecuteQuery(b.qry)
  90. return err
  91. }
  92. func (b QueryBuilder) Iter() *Iter {
  93. iter, err := b.ctx.ExecuteQuery(b.qry)
  94. if err != nil {
  95. return &Iter{err: err}
  96. }
  97. return iter
  98. }
  99. func (b QueryBuilder) Scan(values ...interface{}) error {
  100. iter := b.Iter()
  101. iter.Scan(values...)
  102. return iter.Close()
  103. }
  104. type Iter struct {
  105. err error
  106. pos int
  107. values [][]byte
  108. info []ColumnInfo
  109. }
  110. func (iter *Iter) readFrame(frame frame) {
  111. defer func() {
  112. if r := recover(); r != nil {
  113. if e, ok := r.(error); ok && e == ErrProtocol {
  114. iter.err = e
  115. return
  116. }
  117. panic(r)
  118. }
  119. }()
  120. frame.skipHeader()
  121. iter.pos = 0
  122. iter.err = nil
  123. iter.values = nil
  124. if frame.readInt() != resultKindRows {
  125. return
  126. }
  127. iter.info = frame.readMetaData()
  128. numRows := frame.readInt()
  129. iter.values = make([][]byte, numRows*len(iter.info))
  130. for i := 0; i < len(iter.values); i++ {
  131. iter.values[i] = frame.readBytes()
  132. }
  133. }
  134. func (iter *Iter) Columns() []ColumnInfo {
  135. return iter.info
  136. }
  137. func (iter *Iter) Scan(values ...interface{}) bool {
  138. if iter.err != nil || iter.pos >= len(iter.values) {
  139. return false
  140. }
  141. if len(values) != len(iter.info) {
  142. iter.err = errors.New("count mismatch")
  143. return false
  144. }
  145. for i := 0; i < len(values); i++ {
  146. err := Unmarshal(iter.info[i].TypeInfo, iter.values[i+iter.pos], values[i])
  147. if err != nil {
  148. iter.err = err
  149. return false
  150. }
  151. }
  152. iter.pos += len(values)
  153. return true
  154. }
  155. func (iter *Iter) Close() error {
  156. return iter.err
  157. }
  158. type Batch struct {
  159. Type BatchType
  160. Entries []BatchEntry
  161. Cons Consistency
  162. }
  163. func NewBatch(typ BatchType) *Batch {
  164. return &Batch{Type: typ}
  165. }
  166. func (b *Batch) Query(stmt string, args ...interface{}) {
  167. b.Entries = append(b.Entries, BatchEntry{Stmt: stmt, Args: args})
  168. }
  169. type BatchType int
  170. const (
  171. LoggedBatch BatchType = 0
  172. UnloggedBatch BatchType = 1
  173. CounterBatch BatchType = 2
  174. )
  175. type BatchEntry struct {
  176. Stmt string
  177. Args []interface{}
  178. }
  179. type Consistency int
  180. const (
  181. Any Consistency = 1 + iota
  182. One
  183. Two
  184. Three
  185. Quorum
  186. All
  187. LocalQuorum
  188. EachQuorum
  189. Serial
  190. LocalSerial
  191. )
  192. var consinstencyNames = []string{
  193. 0: "default",
  194. Any: "any",
  195. One: "one",
  196. Two: "two",
  197. Three: "three",
  198. Quorum: "quorum",
  199. All: "all",
  200. LocalQuorum: "localquorum",
  201. EachQuorum: "eachquorum",
  202. Serial: "serial",
  203. LocalSerial: "localserial",
  204. }
  205. func (c Consistency) String() string {
  206. return consinstencyNames[c]
  207. }
  208. type ColumnInfo struct {
  209. Keyspace string
  210. Table string
  211. Name string
  212. TypeInfo *TypeInfo
  213. }