unofficial mirror of notmuch@notmuchmail.org
 help / color / mirror / code / Atom feed
From: David Bremner <david@tethera.net>
To: notmuch@notmuchmail.org
Cc: David Bremner <david@tethera.net>
Subject: [PATCH 12/25] lib/parse-sexp: parse date fields
Date: Sat, 17 Jul 2021 23:40:08 -0300	[thread overview]
Message-ID: <20210718024021.3850340-13-david@tethera.net> (raw)
In-Reply-To: <20210718024021.3850340-1-david@tethera.net>

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\r

  parent reply	other threads:[~2021-07-18  2:41 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-18  2:39 v2 sexpr parser David Bremner
2021-07-18  2:39 ` [PATCH 01/25] configure: optional library sfsexp David Bremner
2021-07-18  2:39 ` [PATCH 02/25] lib: split notmuch_query_create David Bremner
2021-07-18  2:39 ` [PATCH 03/25] lib: define notmuch_query_create_sexpr David Bremner
2021-07-18  2:40 ` [PATCH 04/25] CLI/search+address: support sexpr queries David Bremner
2021-07-18  2:40 ` [PATCH 05/25] lib: add new status code for query syntax errors David Bremner
2021-07-18  2:40 ` [PATCH 06/25] lib/parse-sexp: parse 'and', 'not', 'or' David Bremner
2021-07-18  2:40 ` [PATCH 07/25] lib/parse-sexp: parse 'subject' David Bremner
2021-07-18  2:40 ` [PATCH 08/25] lib/parse-sexp: split terms in phrase mode David Bremner
2021-07-18  2:40 ` [PATCH 09/25] lib/parse-sexp: handle most fields David Bremner
2021-07-18  2:40 ` [PATCH 10/25] lib/parse-sexp: handle unprefixed terms David Bremner
2021-07-18  2:40 ` [PATCH 11/25] lib: factor out date to query conversion David Bremner
2021-07-18  2:40 ` David Bremner [this message]
2021-07-18  2:40 ` [PATCH 13/25] lib: factor out expansion of saved queries David Bremner
2021-07-18  2:40 ` [PATCH 14/25] lib/parse-sexp: handle " David Bremner
2021-07-18  2:40 ` [PATCH 15/25] lib/parse-sexp: add keyword arguments for fields David Bremner
2021-07-18  2:40 ` [PATCH 16/25] lib/parse-sexp: initial support for wildcard queries David Bremner
2021-07-18  2:40 ` [PATCH 17/25] lib/query: generalize exclude handling to s-expression queries David Bremner
2021-07-18  2:40 ` [PATCH 18/25] lib: factor out query construction from regexp David Bremner
2021-07-18  2:40 ` [PATCH 19/25] lib/parse-sexp: add support for regexp fields David Bremner
2021-07-18  2:40 ` [PATCH 20/25] lib/thread-fp: factor out query expansion David Bremner
2021-07-18  2:40 ` [PATCH 21/25] lib: define _notmuch_query_from_sexp David Bremner
2021-07-18  2:40 ` [PATCH 22/25] lib: generate actual Xapian query for "*" and "" David Bremner
2021-07-18  2:40 ` [PATCH 23/25] lib/parse-sexp: support thread subqueries David Bremner
2021-07-18  2:40 ` [PATCH 24/25] lib/parse-sexp: support infix subqueries David Bremner
2021-07-18  2:40 ` [PATCH 25/25] lib/parse-sexp: parse user headers David Bremner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://notmuchmail.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210718024021.3850340-13-david@tethera.net \
    --to=david@tethera.net \
    --cc=notmuch@notmuchmail.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://yhetil.org/notmuch.git/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).