Skip to content

Commit d1daaf0

Browse files
committed
Use FilterEntity instead of Filter
The datastore library has marked Filter as deprecated. By moving to FilterEntity, we can use more advanced queries as well. This commit introduces a new EntityFilter type. That type just wraps datastore.EntityFilter because there are no exposed methods on datastore.EntityFilter for us to manually declare. In order to create an EntityFilter, another type called FilterBuilder is created which will allow consumers to make a particular Filter that reteurns an EntityFilter. More about the deprecation here: https://pkg.go.dev/cloud.google.com/go/datastore#Query.Filter
1 parent ac382a9 commit d1daaf0

File tree

9 files changed

+78
-31
lines changed

9 files changed

+78
-31
lines changed

api/checks/api.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ func (s checksAPIImpl) ScheduleResultsProcessing(sha string, product shared.Prod
7676
func (s checksAPIImpl) GetSuitesForSHA(sha string) ([]shared.CheckSuite, error) {
7777
var suites []shared.CheckSuite
7878
store := shared.NewAppEngineDatastore(s.Context(), false)
79-
_, err := store.GetAll(store.NewQuery("CheckSuite").Filter("SHA =", sha), &suites)
79+
q := store.NewQuery("CheckSuite")
80+
_, err := store.GetAll(q.FilterEntity(q.FilterBuilder().PropertyFilter("SHA", "=", sha)), &suites)
8081

8182
return suites, err
8283
}

api/checks/suites.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,14 @@ func getOrCreateCheckSuite(
2020
prNumbers ...int,
2121
) (*shared.CheckSuite, error) {
2222
ds := shared.NewAppEngineDatastore(ctx, false)
23-
query := ds.NewQuery("CheckSuite").
24-
Filter("SHA =", sha).
25-
Filter("AppID =", appID).
26-
Filter("InstallationID =", installationID).
27-
Filter("Owner =", owner).
28-
Filter("Repo =", repo).
23+
query := ds.NewQuery("CheckSuite")
24+
filterBuilder := query.FilterBuilder()
25+
query = query.
26+
FilterEntity(filterBuilder.PropertyFilter("SHA", "=", sha)).
27+
FilterEntity(filterBuilder.PropertyFilter("AppID", "=", appID)).
28+
FilterEntity(filterBuilder.PropertyFilter("InstallationID", "=", installationID)).
29+
FilterEntity(filterBuilder.PropertyFilter("Owner", "=", owner)).
30+
FilterEntity(filterBuilder.PropertyFilter("Repo", "=", repo)).
2931
KeysOnly()
3032
var suite shared.CheckSuite
3133
if keys, err := ds.GetAll(query, nil); err != nil {

api/pending_test_runs.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,16 @@ func apiPendingTestRunsHandler(w http.ResponseWriter, r *http.Request) {
2323

2424
filter := strings.ToLower(mux.Vars(r)["filter"])
2525
q := store.NewQuery("PendingTestRun")
26+
filterBuilder := q.FilterBuilder()
2627
switch filter {
2728
case "pending":
28-
q = q.Order("-Stage").Filter("Stage < ", int(shared.StageValid))
29+
q = q.Order("-Stage").FilterEntity(filterBuilder.PropertyFilter("Stage", "<", int(shared.StageValid)))
2930
case "invalid":
30-
q = q.Filter("Stage = ", int(shared.StageInvalid))
31+
q = q.FilterEntity(filterBuilder.PropertyFilter("Stage", "=", int(shared.StageInvalid)))
3132
case "empty":
32-
q = q.Filter("Stage = ", int(shared.StageEmpty))
33+
q = q.FilterEntity(filterBuilder.PropertyFilter("Stage", "=", int(shared.StageEmpty)))
3334
case "duplicate":
34-
q = q.Filter("Stage = ", int(shared.StageDuplicate))
35+
q = q.FilterEntity(filterBuilder.PropertyFilter("Stage", "= ", int(shared.StageDuplicate)))
3536
case "":
3637
// No-op
3738
default:

api/screenshot/model.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ func RecentScreenshotHashes(
140140
for all.Cardinality() < totalLimit {
141141
query := ds.NewQuery("Screenshot")
142142
for _, l := range labels {
143-
query = query.Filter("Labels =", l)
143+
query = query.FilterEntity(query.FilterBuilder().PropertyFilter("Labels", "=", l))
144144
}
145145
query = query.Order("-LastUsed").Limit(totalLimit)
146146

api/test_history.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ func testHistoryHandler(w http.ResponseWriter, r *http.Request) {
5454
}
5555

5656
store := shared.NewAppEngineDatastore(ctx, false)
57-
q := store.NewQuery("TestHistoryEntry").Filter("TestName =", reqBody.TestName)
57+
q := store.NewQuery("TestHistoryEntry")
58+
q = q.FilterEntity(q.FilterBuilder().PropertyFilter("TestName", "=", reqBody.TestName))
5859

5960
var runs []shared.TestHistoryEntry
6061
_, err = store.GetAll(q, &runs)

api/versions.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,12 @@ func (h VersionsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
4949

5050
ctx := h.ctx
5151
store := shared.NewAppEngineDatastore(ctx, false)
52-
query := store.NewQuery("TestRun").Filter("BrowserName =", product.BrowserName)
52+
query := store.NewQuery("TestRun")
53+
filterBuilder := query.FilterBuilder()
54+
query = query.FilterEntity(filterBuilder.PropertyFilter("BrowserName", "=", product.BrowserName))
5355
if product.Labels != nil {
5456
for label := range product.Labels.Iter() {
55-
query = query.Filter("Labels =", label)
57+
query = query.FilterEntity(filterBuilder.PropertyFilter("Labels", "=", label))
5658
}
5759
}
5860
distinctQuery := query.Project("BrowserVersion").Distinct()
@@ -61,7 +63,7 @@ func (h VersionsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
6163
queries = []shared.Query{distinctQuery}
6264
} else {
6365
queries = []shared.Query{
64-
query.Filter("BrowserVersion =", product.BrowserVersion).Limit(1),
66+
query.FilterEntity(filterBuilder.PropertyFilter("BrowserVersion", "=", product.BrowserVersion)).Limit(1),
6567
shared.VersionPrefix(distinctQuery, "BrowserVersion", product.BrowserVersion, false /*desc*/),
6668
}
6769
}

shared/datastore.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,26 @@ type Iterator interface {
3636

3737
// Query abstracts a datastore.Query
3838
type Query interface {
39-
Filter(filterStr string, value interface{}) Query
39+
FilterEntity(EntityFilter) Query
4040
Project(fields ...string) Query
4141
Limit(limit int) Query
4242
Offset(offset int) Query
4343
Order(order string) Query
4444
KeysOnly() Query
4545
Distinct() Query
4646
Run(Datastore) Iterator
47+
48+
FilterBuilder() FilterBuilder
49+
}
50+
51+
// PropertyFilter is a particular filter that filters based on property value.
52+
type PropertyFilter interface {
53+
EntityFilter
54+
}
55+
56+
// FilterBuilder contains the logic to create different types of filters
57+
type FilterBuilder interface {
58+
PropertyFilter(FieldName string, Operator string, Value interface{}) EntityFilter
4759
}
4860

4961
// Datastore abstracts a datastore, hiding the distinctions between cloud and

shared/datastore_cloud.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,14 @@ type cloudQuery struct {
197197
query *datastore.Query
198198
}
199199

200+
func (q cloudQuery) FilterBuilder() FilterBuilder {
201+
return cloudFilterBuilder{}
202+
}
203+
204+
func (q cloudQuery) FilterEntity(entityFilter EntityFilter) Query {
205+
return cloudQuery{q.query.FilterEntity(entityFilter)}
206+
}
207+
200208
func (q cloudQuery) Filter(filterStr string, value interface{}) Query {
201209
return cloudQuery{q.query.Filter(filterStr, value)}
202210
}
@@ -240,3 +248,16 @@ func (i cloudIterator) Next(dst interface{}) (Key, error) {
240248
key, err := i.iter.Next(dst)
241249
return cloudKey{key}, err
242250
}
251+
252+
// EntityFilter wraps datastore.EntityFilter.
253+
// datastore.EntityFilter does not expose any methods. But using this type
254+
// allows us to be strict on the filters returned by the FilterBuilder.
255+
type EntityFilter interface {
256+
datastore.EntityFilter
257+
}
258+
259+
type cloudFilterBuilder struct{}
260+
261+
func (b cloudFilterBuilder) PropertyFilter(FieldName string, Operator string, Value interface{}) EntityFilter {
262+
return datastore.PropertyFilter{FieldName: FieldName, Operator: Operator, Value: Value}
263+
}

shared/test_run_query.go

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -119,13 +119,14 @@ func (t testRunQueryImpl) LoadTestRunKeys(
119119
log := GetLogger(t.store.Context())
120120
result = make(KeysByProduct, len(products))
121121
baseQuery := t.store.NewQuery("TestRun")
122+
filterBuilder := baseQuery.FilterBuilder()
122123
if offset != nil {
123124
baseQuery = baseQuery.Offset(*offset)
124125
}
125126
if labels != nil {
126127
labels.Remove("") // Ensure the empty string isn't present.
127128
for i := range labels.Iter() {
128-
baseQuery = baseQuery.Filter("Labels =", i.(string))
129+
baseQuery = baseQuery.FilterEntity(filterBuilder.PropertyFilter("Labels", "=", i.(string)))
129130
}
130131
}
131132
var globalIDFilter mapset.Set
@@ -143,10 +144,10 @@ func (t testRunQueryImpl) LoadTestRunKeys(
143144

144145
for i, product := range products {
145146
var productIDFilter = merge(globalIDFilter, nil)
146-
query := baseQuery.Filter("BrowserName =", product.BrowserName)
147+
query := baseQuery.FilterEntity(filterBuilder.PropertyFilter("BrowserName", "=", product.BrowserName))
147148
if product.Labels != nil {
148149
for i := range product.Labels.Iter() {
149-
query = query.Filter("Labels =", i.(string))
150+
query = query.FilterEntity(filterBuilder.PropertyFilter("Labels", "=", i.(string)))
150151
}
151152
}
152153
if !IsLatest(product.Revision) {
@@ -180,10 +181,10 @@ func (t testRunQueryImpl) LoadTestRunKeys(
180181
// TODO(lukebjerring): Indexes + filtering for OS + version.
181182
query = query.Order("-TimeStart")
182183
if from != nil {
183-
query = query.Filter("TimeStart >=", *from)
184+
query = query.FilterEntity(filterBuilder.PropertyFilter("TimeStart", ">=", *from))
184185
}
185186
if to != nil {
186-
query = query.Filter("TimeStart <", *to)
187+
query = query.FilterEntity(filterBuilder.PropertyFilter("TimeStart", "<", *to))
187188
}
188189
max := MaxCountMaxValue
189190
if limit != nil && *limit < MaxCountMaxValue {
@@ -267,17 +268,18 @@ func (t testRunQueryImpl) GetAlignedRunSHAs(
267268
query := t.store.
268269
NewQuery("TestRun").
269270
Order("-TimeStart")
271+
filterBuilder := query.FilterBuilder()
270272

271273
if labels != nil {
272274
for i := range labels.Iter() {
273-
query = query.Filter("Labels =", i.(string))
275+
query = query.FilterEntity(filterBuilder.PropertyFilter("Labels", "=", i.(string)))
274276
}
275277
}
276278
if from != nil {
277-
query = query.Filter("TimeStart >=", *from)
279+
query = query.FilterEntity(filterBuilder.PropertyFilter("TimeStart", ">=", *from))
278280
}
279281
if to != nil {
280-
query = query.Filter("TimeStart <", *to)
282+
query = query.FilterEntity(filterBuilder.PropertyFilter("TimeStart", "<", *to))
281283
}
282284

283285
productsBySHA := make(map[string]mapset.Set)
@@ -356,16 +358,17 @@ func contains(s []string, x string) bool {
356358
func loadIDsForRevision(store Datastore, query Query, sha string) (result mapset.Set, err error) {
357359
log := GetLogger(store.Context())
358360
var revQuery Query
361+
filterBuilder := query.FilterBuilder()
359362
if len(sha) < 40 {
360363
log.Debugf("Finding revisions %s <= SHA < %s", sha, sha+"g")
361364
revQuery = query.
362365
Order("FullRevisionHash").
363366
Limit(MaxCountMaxValue).
364-
Filter("FullRevisionHash >=", sha).
365-
Filter("FullRevisionHash <", sha+"g") // g > f
367+
FilterEntity(filterBuilder.PropertyFilter("FullRevisionHash", ">=", sha)).
368+
FilterEntity(filterBuilder.PropertyFilter("FullRevisionHash", "<", sha+"g")) // g > f
366369
} else {
367370
log.Debugf("Finding exact revision %s", sha)
368-
revQuery = query.Filter("FullRevisionHash =", sha[:40])
371+
revQuery = query.FilterEntity(filterBuilder.PropertyFilter("FullRevisionHash", "=", sha[:40]))
369372
}
370373

371374
var keys []Key
@@ -393,7 +396,8 @@ func loadIDsForBrowserVersion(store Datastore, query Query, version string) (res
393396
result.Add(id)
394397
}
395398
// By exact match
396-
if keys, err = store.GetAll(query.Filter("BrowserVersion =", version).KeysOnly(), nil); err != nil {
399+
if keys, err = store.GetAll(query.FilterEntity(
400+
query.FilterBuilder().PropertyFilter("BrowserVersion", "=", version)).KeysOnly(), nil); err != nil {
397401
return nil, err
398402
}
399403
for _, id := range GetTestRunIDs(keys) {
@@ -409,11 +413,14 @@ func VersionPrefix(query Query, fieldName, versionPrefix string, desc bool) Quer
409413
if desc {
410414
order = "-" + order
411415
}
416+
filterBuilder := query.FilterBuilder()
412417
return query.
413418
Limit(MaxCountMaxValue).
414419
Order(order).
415-
Filter(fieldName+" >=", fmt.Sprintf("%s.", versionPrefix)).
416-
Filter(fieldName+" <=", fmt.Sprintf("%s.%c", versionPrefix, '9'+1))
420+
FilterEntity(
421+
filterBuilder.PropertyFilter(fieldName, ">=", fmt.Sprintf("%s.", versionPrefix))).
422+
FilterEntity(
423+
filterBuilder.PropertyFilter(fieldName, "<=", fmt.Sprintf("%s.%c", versionPrefix, '9'+1)))
417424
}
418425

419426
func getTestRunRedisKey(id int64) string {

0 commit comments

Comments
 (0)