[PATCH 24/25] lib/parse-sexp: support infix subqueries

Subject: [PATCH 24/25] lib/parse-sexp: support infix subqueries

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

To: notmuch@notmuchmail.org

Cc: David Bremner

From: David Bremner


This is necessary so that programs can take infix syntax queries from
a user and use the sexp query syntax to construct e.g. a refinement of
that query.
---
 lib/parse-sexp.cc         | 32 ++++++++++++++++++++++++++++++++
 test/T081-sexpr-search.sh | 35 +++++++++++++++++++++++++++++++++++
 2 files changed, 67 insertions(+)

diff --git a/lib/parse-sexp.cc b/lib/parse-sexp.cc
index df3629af..502b1be0 100644
--- a/lib/parse-sexp.cc
+++ b/lib/parse-sexp.cc
@@ -56,6 +56,7 @@ static _sexp_field_t fields[] =
     { "from",         Xapian::Query::OP_PHRASE,       SEXP_FLAG_REGEXP },
     { "folder",       Xapian::Query::OP_OR,           SEXP_FLAG_REGEXP },
     { "id",           Xapian::Query::OP_OR,           SEXP_FLAG_REGEXP },
+    { "infix",        Xapian::Query::OP_INVALID,      SEXP_FLAG_NONE },
     { "is",           Xapian::Query::OP_AND,          SEXP_FLAG_WILDCARD | SEXP_FLAG_REGEXP },
     { "mid",          Xapian::Query::OP_OR,           SEXP_FLAG_REGEXP },
     { "mimetype",     Xapian::Query::OP_PHRASE,       SEXP_FLAG_NONE },
@@ -236,6 +237,34 @@ _sexp_parse_keywords (notmuch_database_t *notmuch, const char *prefix, const sex
     return NOTMUCH_STATUS_SUCCESS;
 }
 
+static notmuch_status_t
+_sexp_parse_infix (notmuch_database_t *notmuch, const sexp_t *sx, Xapian::Query &output)
+{
+
+    if (sx->ty != SEXP_VALUE) {
+	_notmuch_database_log (notmuch, "infix argument must be value, not list\n");
+	return NOTMUCH_STATUS_BAD_QUERY_SYNTAX;
+    }
+    try {
+	output = notmuch->query_parser->parse_query (sx->val, NOTMUCH_QUERY_PARSER_FLAGS);
+    } catch (const Xapian::QueryParserError &error) {
+	_notmuch_database_log (notmuch, "Syntax error in infix query: %s\n", sx->val);
+	return NOTMUCH_STATUS_BAD_QUERY_SYNTAX;
+    } catch (const Xapian::Error &error) {
+	if (! notmuch->exception_reported) {
+	    _notmuch_database_log (notmuch,
+				   "A Xapian exception occurred parsing query: %s\n",
+				   error.get_msg ().c_str ());
+	    _notmuch_database_log_append (notmuch,
+					  "Query string was: %s\n",
+					  sx->val);
+	    notmuch->exception_reported = true;
+	    return NOTMUCH_STATUS_XAPIAN_EXCEPTION;
+	}
+    }
+    return NOTMUCH_STATUS_SUCCESS;
+}
+
 /* 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 */
@@ -296,6 +325,9 @@ _notmuch_sexp_to_xapian_query (notmuch_database_t *notmuch, const sexp_t *sx, Xa
 		    return _notmuch_query_name_to_query (notmuch, sx->list->next->val, output);
 		}
 	    }
+	    if (strcasecmp (field->name, "infix") == 0) {
+		return _sexp_parse_infix (notmuch, rest, output);
+	    }
 
 	    term_prefix = _find_prefix (field->name);
 
diff --git a/test/T081-sexpr-search.sh b/test/T081-sexpr-search.sh
index f0a7efb0..45568ba5 100755
--- a/test/T081-sexpr-search.sh
+++ b/test/T081-sexpr-search.sh
@@ -471,4 +471,39 @@ missing subquery
 EOF
 test_expect_equal_file EXPECTED OUTPUT
 
+test_begin_subtest "infix query"
+notmuch search to:searchbyto | notmuch_search_sanitize > EXPECTED
+notmuch search --query-syntax=sexp '(infix "to:searchbyto")' |  notmuch_search_sanitize > OUTPUT
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest "bad infix query 1"
+notmuch search --query-syntax=sexp '(infix "from:/unbalanced")' 2>&1|  notmuch_search_sanitize > OUTPUT
+cat <<EOF > EXPECTED
+notmuch search: Syntax error in query
+Syntax error in infix query: from:/unbalanced
+EOF
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest "bad infix query 2"
+notmuch search --query-syntax=sexp '(infix "thread:{unbalanced")' 2>&1|  notmuch_search_sanitize > OUTPUT
+cat <<EOF > EXPECTED
+notmuch search: Syntax error in query
+Syntax error in infix query: thread:{unbalanced
+EOF
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest "infix query that matches no messages"
+notmuch search --query-syntax=sexp '(and (infix "from:keithp") (infix "to:keithp"))' > OUTPUT
+test_expect_equal_file /dev/null OUTPUT
+
+test_begin_subtest "compound infix query"
+notmuch search date:2009-11-18..2009-11-18 and tag:unread > EXPECTED
+notmuch search --query-syntax=sexp  '(infix "date:2009-11-18..2009-11-18 and tag:unread")' > OUTPUT
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest "compound infix query 2"
+notmuch search date:2009-11-18..2009-11-18 and tag:unread > EXPECTED
+notmuch search --query-syntax=sexp  '(and (infix "date:2009-11-18..2009-11-18") (infix "tag:unread"))' > OUTPUT
+test_expect_equal_file EXPECTED OUTPUT
+
 test_done
-- 
2.30.2
_______________________________________________
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-leave@notmuchmail.org

Thread: