From 699a534632fc649d581d03bf7610f471202b2341 Mon Sep 17 00:00:00 2001 From: Ralph Slooten Date: Fri, 14 Oct 2022 17:25:07 +1300 Subject: [PATCH] API: Add limit and start parameters to search Requested in #15 --- server/apiv1/api.go | 4 +++- server/server_test.go | 4 +++- storage/database.go | 12 +++++------- storage/database_test.go | 4 ++-- storage/search.go | 13 +++++++++++-- 5 files changed, 24 insertions(+), 13 deletions(-) diff --git a/server/apiv1/api.go b/server/apiv1/api.go index fc0fe4a..d65da77 100644 --- a/server/apiv1/api.go +++ b/server/apiv1/api.go @@ -55,7 +55,9 @@ func Search(w http.ResponseWriter, r *http.Request) { return } - messages, err := storage.Search(search) + start, limit := getStartLimit(r) + + messages, err := storage.Search(search, start, limit) if err != nil { httpError(w, err.Error()) return diff --git a/server/server_test.go b/server/server_test.go index ecf4b70..e920b03 100644 --- a/server/server_test.go +++ b/server/server_test.go @@ -181,7 +181,9 @@ func assertSearchEqual(t *testing.T, uri, query string, count int) { t.Logf("Test search: %s", query) m := apiv1.MessagesResult{} - data, err := clientGet(uri + "?query=" + url.QueryEscape(query)) + limit := fmt.Sprintf("%d", count) + + data, err := clientGet(uri + "?query=" + url.QueryEscape(query) + "&limit=" + limit) if err != nil { t.Errorf(err.Error()) return diff --git a/storage/database.go b/storage/database.go index 0d7e452..37915a6 100644 --- a/storage/database.go +++ b/storage/database.go @@ -1,3 +1,4 @@ +// Package storage handles all database actions package storage import ( @@ -290,9 +291,9 @@ func List(start, limit int) ([]Summary, error) { // The search is broken up by segments (exact phrases can be quoted), and interprits specific terms such as: // is:read, is:unread, has:attachment, to:, from: & subject: // Negative searches also also included by prefixing the search term with a `-` or `!` -func Search(search string) ([]Summary, error) { +func Search(search string, start, limit int) ([]Summary, error) { results := []Summary{} - start := time.Now() + tsStart := time.Now() s := strings.ToLower(search) // add another quote if missing closing quote @@ -308,7 +309,7 @@ func Search(search string) ([]Summary, error) { } // generate the SQL based on arguments - q := searchParser(args) + q := searchParser(args, start, limit) if err := q.QueryAndClose(nil, db, func(row *sql.Rows) { var id string @@ -336,7 +337,7 @@ func Search(search string) ([]Summary, error) { return results, err } - elapsed := time.Since(start) + elapsed := time.Since(tsStart) logger.Log().Debugf("[db] search for \"%s\" in %s", search, elapsed) @@ -648,13 +649,10 @@ func DeleteAllMessages() error { // StatsGet returns the total/unread statistics for a mailbox func StatsGet() MailboxStats { var ( - start = time.Now() total = CountTotal() unread = CountUnread() ) - logger.Log().Debugf("[db] statistics calculated in %s", time.Since(start)) - dbLastAction = time.Now() return MailboxStats{ diff --git a/storage/database_test.go b/storage/database_test.go index 7c2c4db..07fd35f 100644 --- a/storage/database_test.go +++ b/storage/database_test.go @@ -180,7 +180,7 @@ func TestSearch(t *testing.T) { search = fmt.Sprintf("\"the email body %d jdsauk dwqmdqw\"", i) } - summaries, err := Search(search) + summaries, err := Search(search, 0, 100) if err != nil { t.Log("error ", err) t.Fail() @@ -196,7 +196,7 @@ func TestSearch(t *testing.T) { } // search something that will return 200 rsults - summaries, err := Search("This is the email body") + summaries, err := Search("This is the email body", 0, testRuns) if err != nil { t.Log("error ", err) t.Fail() diff --git a/storage/search.go b/storage/search.go index 91fbfa9..42c2eaa 100644 --- a/storage/search.go +++ b/storage/search.go @@ -8,7 +8,11 @@ import ( ) // SearchParser returns the SQL syntax for the database search based on the search arguments -func searchParser(args []string) *sqlf.Stmt { +func searchParser(args []string, start, limit int) *sqlf.Stmt { + if limit == 0 { + limit = 50 + } + q := sqlf.From("mailbox"). Select(`ID, Data, read, json_extract(Data, '$.To') as ToJSON, @@ -17,7 +21,12 @@ func searchParser(args []string) *sqlf.Stmt { json_extract(Data, '$.Attachments') as Attachments `). OrderBy("Sort DESC"). - Limit(200) + Limit(limit). + Offset(start) + + if limit > 0 { + q = q.Limit(limit) + } for _, w := range args { if cleanString(w) == "" {