udt_test.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. // +build all integration
  2. package gocql
  3. import (
  4. "fmt"
  5. "testing"
  6. )
  7. type position struct {
  8. Lat int
  9. Lon int
  10. }
  11. // NOTE: due to current implementation details it is not currently possible to use
  12. // a pointer receiver type for the UDTMarshaler interface to handle UDT's
  13. func (p position) MarshalUDT(name string, info TypeInfo) ([]byte, error) {
  14. switch name {
  15. case "lat":
  16. return Marshal(info, p.Lat)
  17. case "lon":
  18. return Marshal(info, p.Lon)
  19. default:
  20. return nil, fmt.Errorf("unknown column for position: %q", name)
  21. }
  22. }
  23. func (p *position) UnmarshalUDT(name string, info TypeInfo, data []byte) error {
  24. switch name {
  25. case "lat":
  26. return Unmarshal(info, data, &p.Lat)
  27. case "lon":
  28. return Unmarshal(info, data, &p.Lon)
  29. default:
  30. return fmt.Errorf("unknown column for position: %q", name)
  31. }
  32. }
  33. func TestUDT_Marshaler(t *testing.T) {
  34. if *flagProto < protoVersion3 {
  35. t.Skip("UDT are only available on protocol >= 3")
  36. }
  37. session := createSession(t)
  38. defer session.Close()
  39. err := createTable(session, `CREATE TYPE position(
  40. lat int,
  41. lon int);`)
  42. if err != nil {
  43. t.Fatal(err)
  44. }
  45. err = createTable(session, `CREATE TABLE houses(
  46. id int,
  47. name text,
  48. loc frozen<position>,
  49. primary key(id)
  50. );`)
  51. if err != nil {
  52. t.Fatal(err)
  53. }
  54. const (
  55. expLat = -1
  56. expLon = 2
  57. )
  58. err = session.Query("INSERT INTO houses(id, name, loc) VALUES(?, ?, ?)", 1, "test", &position{expLat, expLon}).Exec()
  59. if err != nil {
  60. t.Fatal(err)
  61. }
  62. pos := &position{}
  63. err = session.Query("SELECT loc FROM houses WHERE id = ?", 1).Scan(pos)
  64. if err != nil {
  65. t.Fatal(err)
  66. }
  67. if pos.Lat != expLat {
  68. t.Errorf("expeceted lat to be be %d got %d", expLat, pos.Lat)
  69. }
  70. if pos.Lon != expLon {
  71. t.Errorf("expeceted lon to be be %d got %d", expLon, pos.Lon)
  72. }
  73. }
  74. func TestUDT_Reflect(t *testing.T) {
  75. if *flagProto < protoVersion3 {
  76. t.Skip("UDT are only available on protocol >= 3")
  77. }
  78. // Uses reflection instead of implementing the marshaling type
  79. session := createSession(t)
  80. defer session.Close()
  81. err := createTable(session, `CREATE TYPE horse(
  82. name text,
  83. owner text);`)
  84. if err != nil {
  85. t.Fatal(err)
  86. }
  87. err = createTable(session, `CREATE TABLE horse_race(
  88. position int,
  89. horse frozen<horse>,
  90. primary key(position)
  91. );`)
  92. if err != nil {
  93. t.Fatal(err)
  94. }
  95. type horse struct {
  96. Name string `cql:"name"`
  97. Owner string `cql:"owner"`
  98. }
  99. insertedHorse := &horse{
  100. Name: "pony",
  101. Owner: "jim",
  102. }
  103. err = session.Query("INSERT INTO horse_race(position, horse) VALUES(?, ?)", 1, insertedHorse).Exec()
  104. if err != nil {
  105. t.Fatal(err)
  106. }
  107. retrievedHorse := &horse{}
  108. err = session.Query("SELECT horse FROM horse_race WHERE position = ?", 1).Scan(retrievedHorse)
  109. if err != nil {
  110. t.Fatal(err)
  111. }
  112. if *retrievedHorse != *insertedHorse {
  113. t.Fatal("exepcted to get %+v got %+v", insertedHorse, retrievedHorse)
  114. }
  115. }
  116. func TestUDT_Proto2error(t *testing.T) {
  117. if *flagProto < protoVersion3 {
  118. t.Skip("UDT are only available on protocol >= 3")
  119. }
  120. cluster := createCluster()
  121. cluster.ProtoVersion = 2
  122. cluster.Keyspace = "gocql_test"
  123. // Uses reflection instead of implementing the marshaling type
  124. session, err := cluster.CreateSession()
  125. if err != nil {
  126. t.Fatal(err)
  127. }
  128. defer session.Close()
  129. err = createTable(session, `CREATE TYPE fish(
  130. name text,
  131. owner text);`)
  132. if err != nil {
  133. t.Fatal(err)
  134. }
  135. err = createTable(session, `CREATE TABLE fish_race(
  136. position int,
  137. fish frozen<fish>,
  138. primary key(position)
  139. );`)
  140. if err != nil {
  141. t.Fatal(err)
  142. }
  143. type fish struct {
  144. Name string `cql:"name"`
  145. Owner string `cql:"owner"`
  146. }
  147. insertedFish := &fish{
  148. Name: "pony",
  149. Owner: "jim",
  150. }
  151. err = session.Query("INSERT INTO fish_race(position, fish) VALUES(?, ?)", 1, insertedFish).Exec()
  152. if err != ErrorUDTUnavailable {
  153. t.Fatalf("expected to get %v got %v", ErrorUDTUnavailable, err)
  154. }
  155. }