main.go 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  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 main
  5. import (
  6. "fmt"
  7. "log"
  8. "os"
  9. "reflect"
  10. "sort"
  11. "time"
  12. "tux21b.org/v1/gocql"
  13. "tux21b.org/v1/gocql/uuid"
  14. )
  15. var cluster *gocql.ClusterConfig
  16. var session *gocql.Session
  17. func init() {
  18. cluster = gocql.NewCluster("127.0.0.1")
  19. // uncomment the following two lines if you want to use Cassandra 1.2
  20. // cluster.ProtoVersion = 1
  21. // cluster.CQLVersion = "3.0.0"
  22. session, _ = cluster.CreateSession()
  23. }
  24. type Page struct {
  25. Title string
  26. RevId uuid.UUID
  27. Body string
  28. Views int64
  29. Protected bool
  30. Modified time.Time
  31. Tags []string
  32. Attachments map[string]Attachment
  33. }
  34. type Attachment []byte
  35. func initSchema() error {
  36. if err := session.Query("DROP KEYSPACE gocql_test").Exec(); err != nil {
  37. log.Println("drop keyspace", err)
  38. }
  39. if err := session.Query(`CREATE KEYSPACE gocql_test
  40. WITH replication = {
  41. 'class' : 'SimpleStrategy',
  42. 'replication_factor' : 1
  43. }`).Exec(); err != nil {
  44. return err
  45. }
  46. log.Println("Testing that the connections do not reconnect in an infinite loop.")
  47. session.Close()
  48. time.Sleep(15 * time.Second)
  49. log.Println("If there were error messages that an address cannot be assigned then the test failed.")
  50. cluster.Keyspace = "gocql_test"
  51. session, _ = cluster.CreateSession()
  52. if err := session.Query(`CREATE TABLE page (
  53. title varchar,
  54. revid timeuuid,
  55. body varchar,
  56. views bigint,
  57. protected boolean,
  58. modified timestamp,
  59. tags set<varchar>,
  60. attachments map<varchar, text>,
  61. PRIMARY KEY (title, revid)
  62. )`).Exec(); err != nil {
  63. return err
  64. }
  65. if err := session.Query(`CREATE TABLE page_stats (
  66. title varchar,
  67. views counter,
  68. PRIMARY KEY (title)
  69. )`).Exec(); err != nil {
  70. return err
  71. }
  72. if err := session.Query(`CREATE TABLE cas_table (
  73. title varchar,
  74. revid timeuuid,
  75. PRIMARY KEY (title, revid)
  76. )`).Exec(); err != nil {
  77. return err
  78. }
  79. return nil
  80. }
  81. var pageTestData = []*Page{
  82. &Page{
  83. Title: "Frontpage",
  84. RevId: uuid.TimeUUID(),
  85. Body: "Welcome to this wiki page!",
  86. Modified: time.Date(2013, time.August, 13, 9, 52, 3, 0, time.UTC),
  87. Tags: []string{"start", "important", "test"},
  88. Attachments: map[string]Attachment{
  89. "logo": Attachment("\x00company logo\x00"),
  90. "favicon": Attachment("favicon.ico"),
  91. },
  92. },
  93. &Page{
  94. Title: "Foobar",
  95. RevId: uuid.TimeUUID(),
  96. Body: "foo::Foo f = new foo::Foo(foo::Foo::INIT);",
  97. Modified: time.Date(2013, time.August, 13, 9, 52, 3, 0, time.UTC),
  98. },
  99. }
  100. func insertTestData() error {
  101. for _, page := range pageTestData {
  102. if err := session.Query(`INSERT INTO page
  103. (title, revid, body, views, protected, modified, tags, attachments)
  104. VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
  105. page.Title, page.RevId, page.Body, page.Views, page.Protected,
  106. page.Modified, page.Tags, page.Attachments).Exec(); err != nil {
  107. return err
  108. }
  109. }
  110. return nil
  111. }
  112. func insertBatch() error {
  113. batch := gocql.NewBatch(gocql.LoggedBatch)
  114. for _, page := range pageTestData {
  115. batch.Query(`INSERT INTO page
  116. (title, revid, body, views, protected, modified, tags, attachments)
  117. VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
  118. page.Title, page.RevId, page.Body, page.Views, page.Protected,
  119. page.Modified, page.Tags, page.Attachments)
  120. }
  121. if err := session.ExecuteBatch(batch); err != nil {
  122. return err
  123. }
  124. return nil
  125. }
  126. func insertCAS() error {
  127. title := "baz"
  128. revid := uuid.TimeUUID()
  129. var titleCAS string
  130. var revidCAS uuid.UUID
  131. applied, err := session.Query(
  132. `INSERT INTO cas_table (title, revid)
  133. VALUES (?,?) IF NOT EXISTS`,
  134. title, revid).ScanCAS(&titleCAS, &revidCAS)
  135. if err != nil {
  136. return err
  137. }
  138. if !applied {
  139. return fmt.Errorf("Should have applied update for new random title %s", title)
  140. }
  141. applied, err = session.Query(
  142. `INSERT INTO cas_table (title, revid)
  143. VALUES (?,?) IF NOT EXISTS`,
  144. title, revid).ScanCAS(&titleCAS, &revidCAS)
  145. if err != nil {
  146. return err
  147. }
  148. if applied {
  149. return fmt.Errorf("Should NOT have applied update for existing random title %s", title)
  150. }
  151. if title != titleCAS || revid != revidCAS {
  152. return fmt.Errorf("Expected %s/%v but got %s/%v", title, revid, titleCAS, revidCAS)
  153. }
  154. return nil
  155. }
  156. func getPage(title string, revid uuid.UUID) (*Page, error) {
  157. p := new(Page)
  158. err := session.Query(`SELECT title, revid, body, views, protected, modified,
  159. tags, attachments
  160. FROM page WHERE title = ? AND revid = ? LIMIT 1`, title, revid).Scan(
  161. &p.Title, &p.RevId, &p.Body, &p.Views, &p.Protected, &p.Modified,
  162. &p.Tags, &p.Attachments)
  163. return p, err
  164. }
  165. //This test checks to make sure a valid error and a nil reference to
  166. //a session are returned when an empty array of hosts are provided
  167. //to the cluster configuration
  168. func TestEmptyHosts() error {
  169. empty := make([]string, 0)
  170. cfg := gocql.NewCluster(empty...)
  171. _, err := cfg.CreateSession()
  172. return err
  173. }
  174. func main() {
  175. if err := TestEmptyHosts(); err == nil {
  176. log.Fatal("Failed to error when empty host list is provided.")
  177. }
  178. if err := initSchema(); err != nil {
  179. log.Fatal("initSchema: ", err)
  180. }
  181. if err := insertTestData(); err != nil {
  182. log.Fatal("insertTestData: ", err)
  183. }
  184. var count int
  185. if err := session.Query("SELECT COUNT(*) FROM page").Scan(&count); err != nil {
  186. log.Fatal("getCount: ", err)
  187. }
  188. if count != len(pageTestData) {
  189. log.Printf("count: expected %d, got %d", len(pageTestData), count)
  190. }
  191. for _, original := range pageTestData {
  192. page, err := getPage(original.Title, original.RevId)
  193. if err != nil {
  194. log.Print("getPage: ", err)
  195. continue
  196. }
  197. sort.Sort(sort.StringSlice(page.Tags))
  198. sort.Sort(sort.StringSlice(original.Tags))
  199. if !reflect.DeepEqual(page, original) {
  200. log.Printf("page: expected %#v, got %#v\n", original, page)
  201. }
  202. }
  203. // Query Tracing
  204. trace := gocql.NewTraceWriter(session, os.Stdout)
  205. if err := session.Query("SELECT COUNT(*) FROM page").Trace(trace).Scan(&count); err != nil {
  206. log.Fatal("trace: ", err)
  207. }
  208. if err := session.Query("CREATE TABLE large (id int primary key)").Exec(); err != nil {
  209. log.Fatal("create table: ", err)
  210. }
  211. for i := 0; i < 100; i++ {
  212. if err := session.Query("INSERT INTO large (id) VALUES (?)", i).Exec(); err != nil {
  213. log.Fatal("insert: ", err)
  214. }
  215. }
  216. if cluster.ProtoVersion >= 2 {
  217. // Result Paging
  218. iter := session.Query("SELECT id FROM large").PageSize(10).Iter()
  219. var id int
  220. count = 0
  221. for iter.Scan(&id) {
  222. count++
  223. }
  224. if err := iter.Close(); err != nil {
  225. log.Fatal("large iter:", err)
  226. }
  227. if count != 100 {
  228. log.Fatalf("expected %d, got %d", 100, count)
  229. }
  230. // Atomic Batches
  231. for _, original := range pageTestData {
  232. if err := session.Query("DELETE FROM page WHERE title = ? AND revid = ?",
  233. original.Title, original.RevId).Exec(); err != nil {
  234. log.Println("delete:", err)
  235. }
  236. }
  237. if err := session.Query("SELECT COUNT(*) FROM page").Scan(&count); err != nil {
  238. log.Fatal("getCount: ", err)
  239. }
  240. if count != 0 {
  241. log.Printf("count: expected %d, got %d", len(pageTestData), count)
  242. }
  243. if err := insertBatch(); err != nil {
  244. log.Fatal("insertBatch: ", err)
  245. }
  246. // CAS
  247. if err := insertCAS(); err != nil {
  248. log.Fatal("insertCAS: ", err)
  249. }
  250. }
  251. }