PageRenderTime 20ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/gopkg.in/src-d/go-kallax.v1/operators_test.go

https://bitbucket.org/asardak/atm-store
Go | 231 lines | 204 code | 27 blank | 0 comment | 7 complexity | a878b524db1f7afd93e509654d59a713 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, MIT, Apache-2.0, MPL-2.0, BSD-3-Clause, BSD-2-Clause
  1. package kallax
  2. import (
  3. "database/sql"
  4. "testing"
  5. "github.com/stretchr/testify/suite"
  6. "gopkg.in/src-d/go-kallax.v1/types"
  7. )
  8. type OpsSuite struct {
  9. suite.Suite
  10. db *sql.DB
  11. store *Store
  12. }
  13. func (s *OpsSuite) SetupTest() {
  14. var err error
  15. s.db, err = openTestDB()
  16. s.Nil(err)
  17. s.store = NewStore(s.db)
  18. }
  19. func (s *OpsSuite) create(sql string) {
  20. _, err := s.db.Exec(sql)
  21. s.NoError(err)
  22. }
  23. func (s *OpsSuite) remove(table string) {
  24. _, err := s.db.Exec("DROP TABLE IF EXISTS " + table)
  25. s.NoError(err)
  26. }
  27. func (s *OpsSuite) TestOperators() {
  28. s.create(`CREATE TABLE model (
  29. id serial PRIMARY KEY,
  30. name varchar(255) not null,
  31. email varchar(255) not null,
  32. age int not null
  33. )`)
  34. defer s.remove("model")
  35. customGt := NewOperator(":col: > :arg:")
  36. customIn := NewMultiOperator(":col: IN :arg:")
  37. cases := []struct {
  38. name string
  39. cond Condition
  40. count int64
  41. }{
  42. {"Eq", Eq(f("name"), "Joe"), 1},
  43. {"Gt", Gt(f("age"), 1), 2},
  44. {"customGt", customGt(f("age"), 1), 2},
  45. {"Lt", Lt(f("age"), 2), 1},
  46. {"Neq", Neq(f("name"), "Joe"), 2},
  47. {"Like upper", Like(f("name"), "J%"), 2},
  48. {"Like lower", Like(f("name"), "j%"), 0},
  49. {"Ilike upper", Ilike(f("name"), "J%"), 2},
  50. {"Ilike lower", Ilike(f("name"), "j%"), 2},
  51. {"SimilarTo", SimilarTo(f("name"), "An{2}a"), 1},
  52. {"NotSimilarTo", NotSimilarTo(f("name"), "An{2}a"), 2},
  53. {"GtOrEq", GtOrEq(f("age"), 2), 2},
  54. {"LtOrEq", LtOrEq(f("age"), 3), 3},
  55. {"Not", Not(Eq(f("name"), "Joe")), 2},
  56. {"And", And(Neq(f("name"), "Joe"), Gt(f("age"), 1)), 2},
  57. {"Or", Or(Neq(f("name"), "Joe"), Eq(f("age"), 1)), 3},
  58. {"In", In(f("name"), "Joe", "Jane"), 2},
  59. {"customIn", customIn(f("name"), "Joe", "Jane"), 2},
  60. {"NotIn", NotIn(f("name"), "Joe", "Jane"), 1},
  61. {"MatchRegexCase upper", MatchRegexCase(f("name"), "J.*"), 2},
  62. {"MatchRegexCase lower", MatchRegexCase(f("name"), "j.*"), 0},
  63. {"MatchRegex upper", MatchRegex(f("name"), "J.*"), 2},
  64. {"MatchRegex lower", MatchRegex(f("name"), "j.*"), 2},
  65. {"NotMatchRegexCase upper", NotMatchRegexCase(f("name"), "J.*"), 1},
  66. {"NotMatchRegexCase lower", NotMatchRegexCase(f("name"), "j.*"), 3},
  67. {"NotMatchRegex upper", NotMatchRegex(f("name"), "J.*"), 1},
  68. {"NotMatchRegex lower", NotMatchRegex(f("name"), "j.*"), 1},
  69. }
  70. s.Nil(s.store.Insert(ModelSchema, newModel("Joe", "", 1)))
  71. s.Nil(s.store.Insert(ModelSchema, newModel("Jane", "", 2)))
  72. s.Nil(s.store.Insert(ModelSchema, newModel("Anna", "", 2)))
  73. for _, c := range cases {
  74. q := NewBaseQuery(ModelSchema)
  75. q.Where(c.cond)
  76. s.Equal(c.count, s.store.Debug().MustCount(q), c.name)
  77. }
  78. }
  79. func (s *OpsSuite) TestArrayOperators() {
  80. s.create(`CREATE TABLE slices (
  81. id uuid PRIMARY KEY,
  82. elems bigint[]
  83. )`)
  84. defer s.remove("slices")
  85. f := f("elems")
  86. cases := []struct {
  87. name string
  88. cond Condition
  89. ok bool
  90. }{
  91. {"ArrayEq", ArrayEq(f, 1, 2, 3), true},
  92. {"ArrayEq fail", ArrayEq(f, 1, 2, 2), false},
  93. {"ArrayNotEq", ArrayNotEq(f, 1, 2, 2), true},
  94. {"ArrayNotEq fail", ArrayNotEq(f, 1, 2, 3), false},
  95. {"ArrayGt", ArrayGt(f, 1, 2, 2), true},
  96. {"ArrayGt all eq", ArrayGt(f, 1, 2, 3), false},
  97. {"ArrayGt some lt", ArrayGt(f, 1, 3, 1), false},
  98. {"ArrayLt", ArrayLt(f, 1, 2, 4), true},
  99. {"ArrayLt all eq", ArrayLt(f, 1, 2, 3), false},
  100. {"ArrayLt some gt", ArrayLt(f, 1, 1, 4), false},
  101. {"ArrayGtOrEq", ArrayGtOrEq(f, 1, 2, 2), true},
  102. {"ArrayGtOrEq all eq", ArrayGtOrEq(f, 1, 2, 3), true},
  103. {"ArrayGtOrEq some lt", ArrayGtOrEq(f, 1, 3, 1), false},
  104. {"ArrayLtOrEq", ArrayLtOrEq(f, 1, 2, 4), true},
  105. {"ArrayLtOrEq all eq", ArrayLtOrEq(f, 1, 2, 3), true},
  106. {"ArrayLtOrEq some gt", ArrayLtOrEq(f, 1, 1, 4), false},
  107. {"ArrayContains", ArrayContains(f, 1, 2), true},
  108. {"ArrayContains fail", ArrayContains(f, 5, 6), false},
  109. {"ArrayContainedBy", ArrayContainedBy(f, 1, 2, 3, 5, 6), true},
  110. {"ArrayContainedBy fail", ArrayContainedBy(f, 1, 2, 5, 6), false},
  111. {"ArrayOverlap", ArrayOverlap(f, 5, 1, 7), true},
  112. {"ArrayOverlap fail", ArrayOverlap(f, 6, 7, 8, 9), false},
  113. }
  114. _, err := s.db.Exec("INSERT INTO slices (id,elems) VALUES ($1, $2)", NewULID(), types.Slice([]int64{1, 2, 3}))
  115. s.NoError(err)
  116. for _, c := range cases {
  117. q := NewBaseQuery(SlicesSchema)
  118. q.Where(c.cond)
  119. cnt, err := s.store.Count(q)
  120. s.NoError(err, c.name)
  121. s.Equal(c.ok, cnt > 0, "success: %s", c.name)
  122. }
  123. }
  124. type object map[string]interface{}
  125. type array []interface{}
  126. func (s *OpsSuite) TestJSONOperators() {
  127. s.create(`CREATE TABLE jsons (
  128. id uuid primary key,
  129. elem jsonb
  130. )`)
  131. defer s.remove("jsons")
  132. f := f("elem")
  133. cases := []struct {
  134. name string
  135. cond Condition
  136. n int64
  137. }{
  138. {"JSONIsObject", JSONIsObject(f), 2},
  139. {"JSONIsArray", JSONIsArray(f), 3},
  140. {"JSONContains", JSONContains(f, object{"a": 1}), 1},
  141. {"JSONContainedBy", JSONContainedBy(f, object{
  142. "a": 1,
  143. "b": 2,
  144. "c": 3,
  145. "d": 1,
  146. }), 1},
  147. {"JSONContainsAnyKey with array match", JSONContainsAnyKey(f, "a", "c"), 3},
  148. {"JSONContainsAnyKey", JSONContainsAnyKey(f, "b", "e"), 2},
  149. {"JSONContainsAllKeys with array match", JSONContainsAllKeys(f, "a", "c"), 3},
  150. {"JSONContainsAllKeys", JSONContainsAllKeys(f, "b", "e"), 0},
  151. {"JSONContainsAllKeys only objects", JSONContainsAllKeys(f, "a", "b", "c"), 2},
  152. {"JSONContainsAny", JSONContainsAny(f,
  153. object{"a": 1},
  154. object{"a": true},
  155. ), 2},
  156. }
  157. var records = []interface{}{
  158. array{"a", "c", "d"},
  159. object{
  160. "a": true,
  161. "b": array{1, 2, 3},
  162. "c": object{"d": "foo"},
  163. },
  164. object{
  165. "a": 1,
  166. "b": 2,
  167. "c": 3,
  168. },
  169. array{.5, 1., 1.5},
  170. array{1, 2, 3},
  171. }
  172. for _, r := range records {
  173. _, err := s.db.Exec("INSERT INTO jsons (id,elem) VALUES ($1, $2)", NewULID(), types.JSON(r))
  174. s.NoError(err)
  175. }
  176. for _, c := range cases {
  177. q := NewBaseQuery(JsonsSchema)
  178. q.Where(c.cond)
  179. cnt, err := s.store.Count(q)
  180. s.NoError(err, c.name)
  181. s.Equal(c.n, cnt, "should retrieve %d records: %s", c.n, c.name)
  182. }
  183. }
  184. func TestOperators(t *testing.T) {
  185. suite.Run(t, new(OpsSuite))
  186. }
  187. var SlicesSchema = &BaseSchema{
  188. alias: "_sl",
  189. table: "slices",
  190. id: f("id"),
  191. columns: []SchemaField{
  192. f("id"),
  193. f("elems"),
  194. },
  195. }
  196. var JsonsSchema = &BaseSchema{
  197. alias: "_js",
  198. table: "jsons",
  199. id: f("id"),
  200. columns: []SchemaField{
  201. f("id"),
  202. f("elem"),
  203. },
  204. }