Skip to content
This repository was archived by the owner on Sep 2, 2024. It is now read-only.

Commit 4e398c0

Browse files
committed
implemented in and not in for PG query fix #41
1 parent 39caa4b commit 4e398c0

File tree

3 files changed

+76
-3
lines changed

3 files changed

+76
-3
lines changed

database/postgresql/base_test.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ type Task struct {
1717
Done bool `json:"done"`
1818
Likes int64 `json:"likes"`
1919
Todos []Todo `json:"todos"`
20+
Tags []string `json:"tags"`
2021
Created time.Time `json:"created"`
2122
}
2223

@@ -57,6 +58,7 @@ func newTask(title string, done bool) map[string]interface{} {
5758
Title: title,
5859
Done: done,
5960
Todos: []Todo{Todo{Title: "sub", Done: done}, Todo{Title: "sub2", Done: done}},
61+
Tags: []string{title, "unittest", "tag"},
6062
Created: time.Now(),
6163
})
6264
}
@@ -370,3 +372,66 @@ func TestQueryDocumentsWithNonExistingDB(t *testing.T) {
370372
t.Fatalf("expected empty result but got %v", result)
371373
}
372374
}
375+
376+
func TestQueryWithInOperator(t *testing.T) {
377+
redTask := newTask("red", false)
378+
redTask, err := datastore.CreateDocument(adminAuth, confDBName, colName, redTask)
379+
if err != nil {
380+
t.Fatal(err)
381+
}
382+
383+
blueTask := newTask("blue", false)
384+
blueTask, err = datastore.CreateDocument(adminAuth, confDBName, colName, blueTask)
385+
if err != nil {
386+
t.Fatal(err)
387+
}
388+
389+
// test the "in" operator
390+
var clauses [][]interface{}
391+
clauses = append(clauses, []interface{}{"tags", "in", "red"})
392+
clauses = append(clauses, []interface{}{"done", "=", false})
393+
394+
lp := model.ListParams{Page: 1, Size: 5}
395+
396+
filters, err := datastore.ParseQuery(clauses)
397+
if err != nil {
398+
t.Fatal(err)
399+
}
400+
401+
result, err := datastore.QueryDocuments(adminAuth, confDBName, colName, filters, lp)
402+
if err != nil {
403+
t.Fatal(err)
404+
} else if result.Total != 1 {
405+
t.Fatalf("expected total to be 1 got %d", result.Total)
406+
} else if id := result.Results[0]["ID"]; id != redTask["ID"] {
407+
t.Fatalf("expected result item id to be %s got %s", redTask["ID"], id)
408+
}
409+
410+
clauses = nil
411+
clauses = append(clauses, []interface{}{"tags", "!in", "red"})
412+
clauses = append(clauses, []interface{}{"done", "=", false})
413+
414+
filters, err = datastore.ParseQuery(clauses)
415+
if err != nil {
416+
t.Fatal(err)
417+
}
418+
419+
result, err = datastore.QueryDocuments(adminAuth, confDBName, colName, filters, lp)
420+
if err != nil {
421+
t.Fatal(err)
422+
} else if result.Total <= 1 {
423+
t.Fatalf("expected total to be > 1 got %d", result.Total)
424+
}
425+
426+
found := false
427+
for _, task := range result.Results {
428+
if task["ID"] == blueTask["ID"] {
429+
found = true
430+
break
431+
}
432+
}
433+
434+
if !found {
435+
t.Errorf("expected to find blueTask ID in result set")
436+
}
437+
}

database/postgresql/count_test.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,10 @@ func TestCountWithNoFilter(t *testing.T) {
4848
}
4949

5050
// Here we expect this count because after running all tests total count of documents will be 16 + 3
51-
if count != 19 {
51+
//TODO: Use a dedicated collection for testing the count, only this function
52+
// will append row to the collection so this hardcoded value isn't dependent of
53+
// previous test
54+
if count != 21 {
5255
t.Fatalf("expected 19 got %v", count)
5356
}
5457
}

database/postgresql/query.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ func (mg *PostgreSQL) ParseQuery(clauses [][]interface{}) (map[string]interface{
2121
return filter, fmt.Errorf("The %d query clause's field parameter must be a string: %v", i+1, clause[0])
2222
}
2323

24+
origField := field
25+
2426
field = fmt.Sprintf(`data->>'%s'`, field)
2527

2628
op, ok := clause[1].(string)
@@ -36,8 +38,11 @@ func (mg *PostgreSQL) ParseQuery(clauses [][]interface{}) (map[string]interface{
3638
case ">", "<", ">=", "<=":
3739
filter[field+" "+op+" "] = clause[2]
3840
case "in", "!in":
39-
//TODO: Implement the value in array or value not in array
40-
return filter, fmt.Errorf("array lookup is not implemented yet for PostgreSQL at %d op: %s.", i+1, op)
41+
field = fmt.Sprintf("data->'%s' ? ", origField)
42+
if strings.HasPrefix(op, "!") {
43+
field = " NOT " + field
44+
}
45+
filter[field] = clause[2]
4146
default:
4247
return filter, fmt.Errorf("The %d query clause's operator: %s is not supported at the moment.", i+1, op)
4348
}

0 commit comments

Comments
 (0)