session.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  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. Keyspace string
  62. }
  63. func NewQuery(stmt string, args ...interface{}) *Query {
  64. return &Query{Stmt: stmt, Args: args}
  65. }
  66. type QueryBuilder struct {
  67. qry *Query
  68. ctx Node
  69. }
  70. func (b QueryBuilder) Args(args ...interface{}) {
  71. b.qry.Args = args
  72. }
  73. func (b QueryBuilder) Consistency(cons Consistency) QueryBuilder {
  74. b.qry.Cons = cons
  75. return b
  76. }
  77. func (b QueryBuilder) Token(token string) QueryBuilder {
  78. b.qry.Token = token
  79. return b
  80. }
  81. func (b QueryBuilder) Trace(trace bool) QueryBuilder {
  82. b.qry.Trace = trace
  83. return b
  84. }
  85. func (b QueryBuilder) PageSize(size int) QueryBuilder {
  86. b.qry.PageSize = size
  87. return b
  88. }
  89. func (b QueryBuilder) Exec() error {
  90. _, err := b.ctx.ExecuteQuery(b.qry)
  91. return err
  92. }
  93. func (b QueryBuilder) Iter() *Iter {
  94. iter, err := b.ctx.ExecuteQuery(b.qry)
  95. if err != nil {
  96. return &Iter{err: err}
  97. }
  98. return iter
  99. }
  100. func (b QueryBuilder) Scan(values ...interface{}) error {
  101. iter := b.Iter()
  102. iter.Scan(values...)
  103. return iter.Close()
  104. }
  105. type Iter struct {
  106. err error
  107. pos int
  108. values [][]byte
  109. info []ColumnInfo
  110. }
  111. func (iter *Iter) readFrame(frame frame) {
  112. defer func() {
  113. if r := recover(); r != nil {
  114. if e, ok := r.(error); ok && e == ErrProtocol {
  115. iter.err = e
  116. return
  117. }
  118. panic(r)
  119. }
  120. }()
  121. frame.skipHeader()
  122. iter.pos = 0
  123. iter.err = nil
  124. iter.values = nil
  125. if frame.readInt() != resultKindRows {
  126. return
  127. }
  128. iter.info = frame.readMetaData()
  129. numRows := frame.readInt()
  130. iter.values = make([][]byte, numRows*len(iter.info))
  131. for i := 0; i < len(iter.values); i++ {
  132. iter.values[i] = frame.readBytes()
  133. }
  134. }
  135. func (iter *Iter) Columns() []ColumnInfo {
  136. return iter.info
  137. }
  138. func (iter *Iter) Scan(values ...interface{}) bool {
  139. if iter.err != nil || iter.pos >= len(iter.values) {
  140. return false
  141. }
  142. if len(values) != len(iter.info) {
  143. iter.err = errors.New("count mismatch")
  144. return false
  145. }
  146. for i := 0; i < len(values); i++ {
  147. err := Unmarshal(iter.info[i].TypeInfo, iter.values[i+iter.pos], values[i])
  148. if err != nil {
  149. iter.err = err
  150. return false
  151. }
  152. }
  153. iter.pos += len(values)
  154. return true
  155. }
  156. func (iter *Iter) Close() error {
  157. return iter.err
  158. }
  159. type Batch struct {
  160. Type BatchType
  161. Entries []BatchEntry
  162. Cons Consistency
  163. }
  164. func NewBatch(typ BatchType) *Batch {
  165. return &Batch{Type: typ}
  166. }
  167. func (b *Batch) Query(stmt string, args ...interface{}) {
  168. b.Entries = append(b.Entries, BatchEntry{Stmt: stmt, Args: args})
  169. }
  170. type BatchType int
  171. const (
  172. LoggedBatch BatchType = 0
  173. UnloggedBatch BatchType = 1
  174. CounterBatch BatchType = 2
  175. )
  176. type BatchEntry struct {
  177. Stmt string
  178. Args []interface{}
  179. }
  180. type Consistency int
  181. const (
  182. Any Consistency = 1 + iota
  183. One
  184. Two
  185. Three
  186. Quorum
  187. All
  188. LocalQuorum
  189. EachQuorum
  190. Serial
  191. LocalSerial
  192. )
  193. var consinstencyNames = []string{
  194. 0: "default",
  195. Any: "any",
  196. One: "one",
  197. Two: "two",
  198. Three: "three",
  199. Quorum: "quorum",
  200. All: "all",
  201. LocalQuorum: "localquorum",
  202. EachQuorum: "eachquorum",
  203. Serial: "serial",
  204. LocalSerial: "localserial",
  205. }
  206. func (c Consistency) String() string {
  207. return consinstencyNames[c]
  208. }
  209. type ColumnInfo struct {
  210. Keyspace string
  211. Table string
  212. Name string
  213. TypeInfo *TypeInfo
  214. }