[PATCH 12/25] lib/parse-sexp: parse date fields

Subject: [PATCH 12/25] lib/parse-sexp: parse date fields

Date: Sat, 17 Jul 2021 23:40:08 -0300

To: notmuch@notmuchmail.org

Cc: David Bremner

From: David Bremner


This is mainly just marshalling the arguments and calling the existing
query generator. It's not obvious why date is in the field table now,
but we will later use this to track what flags (options) are permitted
per field.
---
 lib/parse-sexp.cc         | 42 ++++++++++++++++++++++++++++++++++++++-
 test/T081-sexpr-search.sh | 15 +++++++++++++-
 2 files changed, 55 insertions(+), 2 deletions(-)

diff --git a/lib/parse-sexp.cc b/lib/parse-sexp.cc
index c8bc3432..29c5cd31 100644
--- a/lib/parse-sexp.cc
+++ b/lib/parse-sexp.cc
@@ -1,6 +1,7 @@
 #include <xapian.h>
 #include "notmuch-private.h"
 #include "sexp.h"
+#include "parse-time-vrp.h"
 
 typedef struct  {
     const char *name;
@@ -25,6 +26,7 @@ static _sexp_field_t fields[] =
 {
     { "attachment",     Xapian::Query::OP_PHRASE },
     { "body",           Xapian::Query::OP_PHRASE },
+    { "date",           Xapian::Query::OP_INVALID },
     { "from",           Xapian::Query::OP_PHRASE },
     { "folder",         Xapian::Query::OP_OR },
     { "id",             Xapian::Query::OP_OR },
@@ -134,6 +136,36 @@ _sexp_combine_field (const char *prefix,
     return NOTMUCH_STATUS_SUCCESS;
 }
 
+static notmuch_status_t
+_sexp_parse_date (notmuch_database_t *notmuch, const sexp_t *sx, Xapian::Query &output)
+{
+    std::string begin, end, msg;
+    notmuch_status_t status;
+    const sexp_t *cur = sx->list->next;
+
+    if (cur) {
+	begin = cur->val;
+	cur = cur->next;
+	if (cur) {
+	    end = cur->val;
+	    cur = cur->next;
+	    if (cur) {
+		_notmuch_database_log_append (notmuch, "extra argument(s) to date");
+		return NOTMUCH_STATUS_BAD_QUERY_SYNTAX;
+	    }
+	    status = _notmuch_time_range_to_query (NOTMUCH_VALUE_TIMESTAMP, begin, end, msg, output);
+	} else {
+	    status = _notmuch_time_string_to_query (NOTMUCH_VALUE_TIMESTAMP, begin, msg, output);
+	}
+	if (status)
+	    _notmuch_database_log_append (notmuch, "%s", msg.c_str ());
+	return status;
+    } else {
+	_notmuch_database_log_append (notmuch, "missing argument(s) to date");
+	return NOTMUCH_STATUS_BAD_QUERY_SYNTAX;
+    }
+}
+
 /* Here we expect the s-expression to be a proper list, with first
  * element defining and operation, or as a special case the empty
  * list */
@@ -148,6 +180,8 @@ _sexp_to_xapian_query (notmuch_database_t *notmuch, const sexp_t *sx, Xapian::Qu
 	Xapian::Query accumulator;
 	for (const _sexp_field_t *field = fields; field && field->name; field++) {
 	    std::vector<std::string> terms;
+	    if (field->xapian_op == Xapian::Query::OP_INVALID)
+		continue;
 	    _sexp_find_words (sx->val, _find_prefix (field->name), terms);
 	    accumulator = Xapian::Query (Xapian::Query::OP_OR, accumulator,
 					 Xapian::Query (Xapian::Query::OP_PHRASE,
@@ -169,9 +203,15 @@ _sexp_to_xapian_query (notmuch_database_t *notmuch, const sexp_t *sx, Xapian::Qu
     }
 
     for (const _sexp_field_t *field = fields; field && field->name; field++) {
-	if (strcasecmp (field->name, hd_sexp (sx)->val) == 0)
+	if (strcasecmp (field->name, hd_sexp (sx)->val) == 0) {
+	    /* some fields need to be handled specially */
+	    if (strcasecmp (field->name, "date") == 0) {
+		return _sexp_parse_date (notmuch, sx, output);
+	    }
+
 	    return _sexp_combine_field (_find_prefix (field->name), field->xapian_op, sx->list->next,
 					output);
+	}
     }
 
     _notmuch_database_log_append (notmuch, "unimplemented prefix %s\n", sx->list->val);
diff --git a/test/T081-sexpr-search.sh b/test/T081-sexpr-search.sh
index 80e3daf3..c9dd8f39 100755
--- a/test/T081-sexpr-search.sh
+++ b/test/T081-sexpr-search.sh
@@ -67,6 +67,20 @@ notmuch search body:kryptonite > EXPECTED
 notmuch search --query-syntax=sexp '(body kryptonite)' > OUTPUT
 test_expect_equal_file EXPECTED OUTPUT
 
+test_begin_subtest "date 0 arguments"
+test_expect_code 1 "notmuch search --query-syntax=sexp '(date)'"
+
+test_begin_subtest "date 1 argument"
+output=$(notmuch search --query-syntax=sexp '(date 2010-12-16)' | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX   2010-12-16 [1/1] Olivier Berger; Essai accentué (inbox unread)"
+
+test_begin_subtest "date 2 arguments"
+output=$(notmuch search --query-syntax=sexp '(date 2010-12-16 12/16/2010)' | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX   2010-12-16 [1/1] Olivier Berger; Essai accentué (inbox unread)"
+
+test_begin_subtest "date 3 arguments"
+test_expect_code 1 "notmuch search --query-syntax=sexp '(date 2010-12-16 12/16/2010 trailing-garbage)'"
+
 test_begin_subtest "Search by 'from'"
 add_message '[subject]="search by from"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' [from]=searchbyfrom
 output=$(notmuch search --query-syntax=sexp '(from searchbyfrom)' | notmuch_search_sanitize)
@@ -205,7 +219,6 @@ test_begin_subtest "Search by 'to' (name and address)"
 output=$(notmuch search --query-syntax=sexp '(to "Search By To Name <test@example.com>")' | notmuch_search_sanitize)
 test_expect_equal "$output" "thread:XXX   2000-01-01 [1/1] Notmuch Test Suite; search by to (name) (inbox unread)"
 
-
 test_begin_subtest "Unbalanced parens"
 # A code 1 indicates the error was handled (a crash will return e.g. 139).
 test_expect_code 1 "notmuch search --query-syntax=sexp '('"
-- 
2.30.2
_______________________________________________
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-leave@notmuchmail.org

Thread: