query_test.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583
  1. // Copyright 2011 Google Inc. All Rights Reserved.
  2. // Use of this source code is governed by the Apache 2.0
  3. // license that can be found in the LICENSE file.
  4. package datastore
  5. import (
  6. "errors"
  7. "fmt"
  8. "reflect"
  9. "strings"
  10. "testing"
  11. "github.com/golang/protobuf/proto"
  12. "google.golang.org/appengine/internal"
  13. "google.golang.org/appengine/internal/aetesting"
  14. pb "google.golang.org/appengine/internal/datastore"
  15. )
  16. var (
  17. path1 = &pb.Path{
  18. Element: []*pb.Path_Element{
  19. {
  20. Type: proto.String("Gopher"),
  21. Id: proto.Int64(6),
  22. },
  23. },
  24. }
  25. path2 = &pb.Path{
  26. Element: []*pb.Path_Element{
  27. {
  28. Type: proto.String("Gopher"),
  29. Id: proto.Int64(6),
  30. },
  31. {
  32. Type: proto.String("Gopher"),
  33. Id: proto.Int64(8),
  34. },
  35. },
  36. }
  37. )
  38. func fakeRunQuery(in *pb.Query, out *pb.QueryResult) error {
  39. expectedIn := &pb.Query{
  40. App: proto.String("dev~fake-app"),
  41. Kind: proto.String("Gopher"),
  42. Compile: proto.Bool(true),
  43. }
  44. if !proto.Equal(in, expectedIn) {
  45. return fmt.Errorf("unsupported argument: got %v want %v", in, expectedIn)
  46. }
  47. *out = pb.QueryResult{
  48. Result: []*pb.EntityProto{
  49. {
  50. Key: &pb.Reference{
  51. App: proto.String("s~test-app"),
  52. Path: path1,
  53. },
  54. EntityGroup: path1,
  55. Property: []*pb.Property{
  56. {
  57. Meaning: pb.Property_TEXT.Enum(),
  58. Name: proto.String("Name"),
  59. Value: &pb.PropertyValue{
  60. StringValue: proto.String("George"),
  61. },
  62. },
  63. {
  64. Name: proto.String("Height"),
  65. Value: &pb.PropertyValue{
  66. Int64Value: proto.Int64(32),
  67. },
  68. },
  69. },
  70. },
  71. {
  72. Key: &pb.Reference{
  73. App: proto.String("s~test-app"),
  74. Path: path2,
  75. },
  76. EntityGroup: path1, // ancestor is George
  77. Property: []*pb.Property{
  78. {
  79. Meaning: pb.Property_TEXT.Enum(),
  80. Name: proto.String("Name"),
  81. Value: &pb.PropertyValue{
  82. StringValue: proto.String("Rufus"),
  83. },
  84. },
  85. // No height for Rufus.
  86. },
  87. },
  88. },
  89. MoreResults: proto.Bool(false),
  90. }
  91. return nil
  92. }
  93. type StructThatImplementsPLS struct{}
  94. func (StructThatImplementsPLS) Load(p []Property) error { return nil }
  95. func (StructThatImplementsPLS) Save() ([]Property, error) { return nil, nil }
  96. var _ PropertyLoadSaver = StructThatImplementsPLS{}
  97. type StructPtrThatImplementsPLS struct{}
  98. func (*StructPtrThatImplementsPLS) Load(p []Property) error { return nil }
  99. func (*StructPtrThatImplementsPLS) Save() ([]Property, error) { return nil, nil }
  100. var _ PropertyLoadSaver = &StructPtrThatImplementsPLS{}
  101. type PropertyMap map[string]Property
  102. func (m PropertyMap) Load(props []Property) error {
  103. for _, p := range props {
  104. if p.Multiple {
  105. return errors.New("PropertyMap does not support multiple properties")
  106. }
  107. m[p.Name] = p
  108. }
  109. return nil
  110. }
  111. func (m PropertyMap) Save() ([]Property, error) {
  112. props := make([]Property, 0, len(m))
  113. for _, p := range m {
  114. if p.Multiple {
  115. return nil, errors.New("PropertyMap does not support multiple properties")
  116. }
  117. props = append(props, p)
  118. }
  119. return props, nil
  120. }
  121. var _ PropertyLoadSaver = PropertyMap{}
  122. type Gopher struct {
  123. Name string
  124. Height int
  125. }
  126. // typeOfEmptyInterface is the type of interface{}, but we can't use
  127. // reflect.TypeOf((interface{})(nil)) directly because TypeOf takes an
  128. // interface{}.
  129. var typeOfEmptyInterface = reflect.TypeOf((*interface{})(nil)).Elem()
  130. func TestCheckMultiArg(t *testing.T) {
  131. testCases := []struct {
  132. v interface{}
  133. mat multiArgType
  134. elemType reflect.Type
  135. }{
  136. // Invalid cases.
  137. {nil, multiArgTypeInvalid, nil},
  138. {Gopher{}, multiArgTypeInvalid, nil},
  139. {&Gopher{}, multiArgTypeInvalid, nil},
  140. {PropertyList{}, multiArgTypeInvalid, nil}, // This is a special case.
  141. {PropertyMap{}, multiArgTypeInvalid, nil},
  142. {[]*PropertyList(nil), multiArgTypeInvalid, nil},
  143. {[]*PropertyMap(nil), multiArgTypeInvalid, nil},
  144. {[]**Gopher(nil), multiArgTypeInvalid, nil},
  145. {[]*interface{}(nil), multiArgTypeInvalid, nil},
  146. // Valid cases.
  147. {
  148. []PropertyList(nil),
  149. multiArgTypePropertyLoadSaver,
  150. reflect.TypeOf(PropertyList{}),
  151. },
  152. {
  153. []PropertyMap(nil),
  154. multiArgTypePropertyLoadSaver,
  155. reflect.TypeOf(PropertyMap{}),
  156. },
  157. {
  158. []StructThatImplementsPLS(nil),
  159. multiArgTypePropertyLoadSaver,
  160. reflect.TypeOf(StructThatImplementsPLS{}),
  161. },
  162. {
  163. []StructPtrThatImplementsPLS(nil),
  164. multiArgTypePropertyLoadSaver,
  165. reflect.TypeOf(StructPtrThatImplementsPLS{}),
  166. },
  167. {
  168. []Gopher(nil),
  169. multiArgTypeStruct,
  170. reflect.TypeOf(Gopher{}),
  171. },
  172. {
  173. []*Gopher(nil),
  174. multiArgTypeStructPtr,
  175. reflect.TypeOf(Gopher{}),
  176. },
  177. {
  178. []interface{}(nil),
  179. multiArgTypeInterface,
  180. typeOfEmptyInterface,
  181. },
  182. }
  183. for _, tc := range testCases {
  184. mat, elemType := checkMultiArg(reflect.ValueOf(tc.v))
  185. if mat != tc.mat || elemType != tc.elemType {
  186. t.Errorf("checkMultiArg(%T): got %v, %v want %v, %v",
  187. tc.v, mat, elemType, tc.mat, tc.elemType)
  188. }
  189. }
  190. }
  191. func TestSimpleQuery(t *testing.T) {
  192. struct1 := Gopher{Name: "George", Height: 32}
  193. struct2 := Gopher{Name: "Rufus"}
  194. pList1 := PropertyList{
  195. {
  196. Name: "Name",
  197. Value: "George",
  198. },
  199. {
  200. Name: "Height",
  201. Value: int64(32),
  202. },
  203. }
  204. pList2 := PropertyList{
  205. {
  206. Name: "Name",
  207. Value: "Rufus",
  208. },
  209. }
  210. pMap1 := PropertyMap{
  211. "Name": Property{
  212. Name: "Name",
  213. Value: "George",
  214. },
  215. "Height": Property{
  216. Name: "Height",
  217. Value: int64(32),
  218. },
  219. }
  220. pMap2 := PropertyMap{
  221. "Name": Property{
  222. Name: "Name",
  223. Value: "Rufus",
  224. },
  225. }
  226. testCases := []struct {
  227. dst interface{}
  228. want interface{}
  229. }{
  230. // The destination must have type *[]P, *[]S or *[]*S, for some non-interface
  231. // type P such that *P implements PropertyLoadSaver, or for some struct type S.
  232. {new([]Gopher), &[]Gopher{struct1, struct2}},
  233. {new([]*Gopher), &[]*Gopher{&struct1, &struct2}},
  234. {new([]PropertyList), &[]PropertyList{pList1, pList2}},
  235. {new([]PropertyMap), &[]PropertyMap{pMap1, pMap2}},
  236. // Any other destination type is invalid.
  237. {0, nil},
  238. {Gopher{}, nil},
  239. {PropertyList{}, nil},
  240. {PropertyMap{}, nil},
  241. {[]int{}, nil},
  242. {[]Gopher{}, nil},
  243. {[]PropertyList{}, nil},
  244. {new(int), nil},
  245. {new(Gopher), nil},
  246. {new(PropertyList), nil}, // This is a special case.
  247. {new(PropertyMap), nil},
  248. {new([]int), nil},
  249. {new([]map[int]int), nil},
  250. {new([]map[string]Property), nil},
  251. {new([]map[string]interface{}), nil},
  252. {new([]*int), nil},
  253. {new([]*map[int]int), nil},
  254. {new([]*map[string]Property), nil},
  255. {new([]*map[string]interface{}), nil},
  256. {new([]**Gopher), nil},
  257. {new([]*PropertyList), nil},
  258. {new([]*PropertyMap), nil},
  259. }
  260. for _, tc := range testCases {
  261. nCall := 0
  262. c := aetesting.FakeSingleContext(t, "datastore_v3", "RunQuery", func(in *pb.Query, out *pb.QueryResult) error {
  263. nCall++
  264. return fakeRunQuery(in, out)
  265. })
  266. c = internal.WithAppIDOverride(c, "dev~fake-app")
  267. var (
  268. expectedErr error
  269. expectedNCall int
  270. )
  271. if tc.want == nil {
  272. expectedErr = ErrInvalidEntityType
  273. } else {
  274. expectedNCall = 1
  275. }
  276. keys, err := NewQuery("Gopher").GetAll(c, tc.dst)
  277. if err != expectedErr {
  278. t.Errorf("dst type %T: got error [%v], want [%v]", tc.dst, err, expectedErr)
  279. continue
  280. }
  281. if nCall != expectedNCall {
  282. t.Errorf("dst type %T: Context.Call was called an incorrect number of times: got %d want %d", tc.dst, nCall, expectedNCall)
  283. continue
  284. }
  285. if err != nil {
  286. continue
  287. }
  288. key1 := NewKey(c, "Gopher", "", 6, nil)
  289. expectedKeys := []*Key{
  290. key1,
  291. NewKey(c, "Gopher", "", 8, key1),
  292. }
  293. if l1, l2 := len(keys), len(expectedKeys); l1 != l2 {
  294. t.Errorf("dst type %T: got %d keys, want %d keys", tc.dst, l1, l2)
  295. continue
  296. }
  297. for i, key := range keys {
  298. if key.AppID() != "s~test-app" {
  299. t.Errorf(`dst type %T: Key #%d's AppID = %q, want "s~test-app"`, tc.dst, i, key.AppID())
  300. continue
  301. }
  302. if !keysEqual(key, expectedKeys[i]) {
  303. t.Errorf("dst type %T: got key #%d %v, want %v", tc.dst, i, key, expectedKeys[i])
  304. continue
  305. }
  306. }
  307. if !reflect.DeepEqual(tc.dst, tc.want) {
  308. t.Errorf("dst type %T: Entities got %+v, want %+v", tc.dst, tc.dst, tc.want)
  309. continue
  310. }
  311. }
  312. }
  313. // keysEqual is like (*Key).Equal, but ignores the App ID.
  314. func keysEqual(a, b *Key) bool {
  315. for a != nil && b != nil {
  316. if a.Kind() != b.Kind() || a.StringID() != b.StringID() || a.IntID() != b.IntID() {
  317. return false
  318. }
  319. a, b = a.Parent(), b.Parent()
  320. }
  321. return a == b
  322. }
  323. func TestQueriesAreImmutable(t *testing.T) {
  324. // Test that deriving q2 from q1 does not modify q1.
  325. q0 := NewQuery("foo")
  326. q1 := NewQuery("foo")
  327. q2 := q1.Offset(2)
  328. if !reflect.DeepEqual(q0, q1) {
  329. t.Errorf("q0 and q1 were not equal")
  330. }
  331. if reflect.DeepEqual(q1, q2) {
  332. t.Errorf("q1 and q2 were equal")
  333. }
  334. // Test that deriving from q4 twice does not conflict, even though
  335. // q4 has a long list of order clauses. This tests that the arrays
  336. // backed by a query's slice of orders are not shared.
  337. f := func() *Query {
  338. q := NewQuery("bar")
  339. // 47 is an ugly number that is unlikely to be near a re-allocation
  340. // point in repeated append calls. For example, it's not near a power
  341. // of 2 or a multiple of 10.
  342. for i := 0; i < 47; i++ {
  343. q = q.Order(fmt.Sprintf("x%d", i))
  344. }
  345. return q
  346. }
  347. q3 := f().Order("y")
  348. q4 := f()
  349. q5 := q4.Order("y")
  350. q6 := q4.Order("z")
  351. if !reflect.DeepEqual(q3, q5) {
  352. t.Errorf("q3 and q5 were not equal")
  353. }
  354. if reflect.DeepEqual(q5, q6) {
  355. t.Errorf("q5 and q6 were equal")
  356. }
  357. }
  358. func TestFilterParser(t *testing.T) {
  359. testCases := []struct {
  360. filterStr string
  361. wantOK bool
  362. wantFieldName string
  363. wantOp operator
  364. }{
  365. // Supported ops.
  366. {"x<", true, "x", lessThan},
  367. {"x <", true, "x", lessThan},
  368. {"x <", true, "x", lessThan},
  369. {" x < ", true, "x", lessThan},
  370. {"x <=", true, "x", lessEq},
  371. {"x =", true, "x", equal},
  372. {"x >=", true, "x", greaterEq},
  373. {"x >", true, "x", greaterThan},
  374. {"in >", true, "in", greaterThan},
  375. {"in>", true, "in", greaterThan},
  376. // Valid but (currently) unsupported ops.
  377. {"x!=", false, "", 0},
  378. {"x !=", false, "", 0},
  379. {" x != ", false, "", 0},
  380. {"x IN", false, "", 0},
  381. {"x in", false, "", 0},
  382. // Invalid ops.
  383. {"x EQ", false, "", 0},
  384. {"x lt", false, "", 0},
  385. {"x <>", false, "", 0},
  386. {"x >>", false, "", 0},
  387. {"x ==", false, "", 0},
  388. {"x =<", false, "", 0},
  389. {"x =>", false, "", 0},
  390. {"x !", false, "", 0},
  391. {"x ", false, "", 0},
  392. {"x", false, "", 0},
  393. }
  394. for _, tc := range testCases {
  395. q := NewQuery("foo").Filter(tc.filterStr, 42)
  396. if ok := q.err == nil; ok != tc.wantOK {
  397. t.Errorf("%q: ok=%t, want %t", tc.filterStr, ok, tc.wantOK)
  398. continue
  399. }
  400. if !tc.wantOK {
  401. continue
  402. }
  403. if len(q.filter) != 1 {
  404. t.Errorf("%q: len=%d, want %d", tc.filterStr, len(q.filter), 1)
  405. continue
  406. }
  407. got, want := q.filter[0], filter{tc.wantFieldName, tc.wantOp, 42}
  408. if got != want {
  409. t.Errorf("%q: got %v, want %v", tc.filterStr, got, want)
  410. continue
  411. }
  412. }
  413. }
  414. func TestQueryToProto(t *testing.T) {
  415. // The context is required to make Keys for the test cases.
  416. var got *pb.Query
  417. NoErr := errors.New("No error")
  418. c := aetesting.FakeSingleContext(t, "datastore_v3", "RunQuery", func(in *pb.Query, out *pb.QueryResult) error {
  419. got = in
  420. return NoErr // return a non-nil error so Run doesn't keep going.
  421. })
  422. c = internal.WithAppIDOverride(c, "dev~fake-app")
  423. testCases := []struct {
  424. desc string
  425. query *Query
  426. want *pb.Query
  427. err string
  428. }{
  429. {
  430. desc: "empty",
  431. query: NewQuery(""),
  432. want: &pb.Query{},
  433. },
  434. {
  435. desc: "standard query",
  436. query: NewQuery("kind").Order("-I").Filter("I >", 17).Filter("U =", "Dave").Limit(7).Offset(42),
  437. want: &pb.Query{
  438. Kind: proto.String("kind"),
  439. Filter: []*pb.Query_Filter{
  440. {
  441. Op: pb.Query_Filter_GREATER_THAN.Enum(),
  442. Property: []*pb.Property{
  443. {
  444. Name: proto.String("I"),
  445. Value: &pb.PropertyValue{Int64Value: proto.Int64(17)},
  446. Multiple: proto.Bool(false),
  447. },
  448. },
  449. },
  450. {
  451. Op: pb.Query_Filter_EQUAL.Enum(),
  452. Property: []*pb.Property{
  453. {
  454. Name: proto.String("U"),
  455. Value: &pb.PropertyValue{StringValue: proto.String("Dave")},
  456. Multiple: proto.Bool(false),
  457. },
  458. },
  459. },
  460. },
  461. Order: []*pb.Query_Order{
  462. {
  463. Property: proto.String("I"),
  464. Direction: pb.Query_Order_DESCENDING.Enum(),
  465. },
  466. },
  467. Limit: proto.Int32(7),
  468. Offset: proto.Int32(42),
  469. },
  470. },
  471. {
  472. desc: "ancestor",
  473. query: NewQuery("").Ancestor(NewKey(c, "kind", "Mummy", 0, nil)),
  474. want: &pb.Query{
  475. Ancestor: &pb.Reference{
  476. App: proto.String("dev~fake-app"),
  477. Path: &pb.Path{
  478. Element: []*pb.Path_Element{{Type: proto.String("kind"), Name: proto.String("Mummy")}},
  479. },
  480. },
  481. },
  482. },
  483. {
  484. desc: "projection",
  485. query: NewQuery("").Project("A", "B"),
  486. want: &pb.Query{
  487. PropertyName: []string{"A", "B"},
  488. },
  489. },
  490. {
  491. desc: "projection with distinct",
  492. query: NewQuery("").Project("A", "B").Distinct(),
  493. want: &pb.Query{
  494. PropertyName: []string{"A", "B"},
  495. GroupByPropertyName: []string{"A", "B"},
  496. },
  497. },
  498. {
  499. desc: "keys only",
  500. query: NewQuery("").KeysOnly(),
  501. want: &pb.Query{
  502. KeysOnly: proto.Bool(true),
  503. RequirePerfectPlan: proto.Bool(true),
  504. },
  505. },
  506. {
  507. desc: "empty filter",
  508. query: NewQuery("kind").Filter("=", 17),
  509. err: "empty query filter field nam",
  510. },
  511. {
  512. desc: "bad filter type",
  513. query: NewQuery("kind").Filter("M =", map[string]bool{}),
  514. err: "bad query filter value type",
  515. },
  516. {
  517. desc: "bad filter operator",
  518. query: NewQuery("kind").Filter("I <<=", 17),
  519. err: `invalid operator "<<=" in filter "I <<="`,
  520. },
  521. {
  522. desc: "empty order",
  523. query: NewQuery("kind").Order(""),
  524. err: "empty order",
  525. },
  526. {
  527. desc: "bad order direction",
  528. query: NewQuery("kind").Order("+I"),
  529. err: `invalid order: "+I`,
  530. },
  531. }
  532. for _, tt := range testCases {
  533. got = nil
  534. if _, err := tt.query.Run(c).Next(nil); err != NoErr {
  535. if tt.err == "" || !strings.Contains(err.Error(), tt.err) {
  536. t.Errorf("%s: error %v, want %q", tt.desc, err, tt.err)
  537. }
  538. continue
  539. }
  540. if tt.err != "" {
  541. t.Errorf("%s: no error, want %q", tt.desc, tt.err)
  542. continue
  543. }
  544. // Fields that are common to all protos.
  545. tt.want.App = proto.String("dev~fake-app")
  546. tt.want.Compile = proto.Bool(true)
  547. if !proto.Equal(got, tt.want) {
  548. t.Errorf("%s:\ngot %v\nwant %v", tt.desc, got, tt.want)
  549. }
  550. }
  551. }