udt_test.go 4.0 KB

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