[PATCH 7/8] Implement value range queries.

Austin Clements amdragon at MIT.EDU
Sun Jan 16 00:10:57 PST 2011


Unlike in Xapian, there's no specific syntax that generates value
ranges.  Instead, it's up query transforms to generate them.
---
 lib/notmuch-private.h |    8 ++++++++
 lib/qparser.cc        |   20 +++++++++++++++++---
 2 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h
index 5fc54de..9c16f56 100644
--- a/lib/notmuch-private.h
+++ b/lib/notmuch-private.h
@@ -548,6 +548,8 @@ enum _notmuch_token_type {
      * with no phrase splitting or whitespace removal.  The lexer
      * only generates TOK_TERMS; the parser creates TOK_LIT. */
     TOK_LIT,
+    /* A value range operand. */
+    TOK_RANGE,
     /* An error token.  An error token anywhere in the parse tree will
      * be propagated up by the generator and returned to the caller.
      * The error message should be in the text. */
@@ -577,6 +579,12 @@ typedef struct _notmuch_token {
      * match any terms prefixed with text. */
     notmuch_bool_t wildcard;
 
+    /* For TOK_RANGE, the value number to filter on, and the
+     * (inclusive) range to match lexicographically.  Either endpoint
+     * may be NULL, indicating an open-ended range. */
+    unsigned valueno;
+    const char *rangeBegin, *rangeEnd;
+
     /* Link in the lexer token list. */
     struct _notmuch_token *next;
 
diff --git a/lib/qparser.cc b/lib/qparser.cc
index 0ff240c..2c63062 100644
--- a/lib/qparser.cc
+++ b/lib/qparser.cc
@@ -43,7 +43,6 @@
  * Still missing from this implementation:
  * * Stemming - The stemming should probably be marked on TOK_TERMS
  *   tokens.  Ideally, we can just pass this to the term generator.
- * * Value ranges in the IR
  */
 
 /* XXX notmuch currently registers "tag" as an exclusive boolean
@@ -100,13 +99,13 @@ static const char *token_types[] = {
     "LOVE", "HATE", "BRA", "KET",
     "AND", "OR", "XOR", "ADJ", "NEAR",
     "NOT", "FILTER", "PREFIX",
-    "TERMS", "LIT", "ERROR", "END"
+    "TERMS", "LIT", "ERROR", "RANGE", "END"
 };
 
 /* The distinguished end token.  This simplifies the parser since it
  * never has to worry about dereferencing next. */
 static _notmuch_token_t tok_end = {TOK_END, NULL, -1, FALSE, NULL, FALSE,
-				   &tok_end, NULL, NULL};
+				   0, NULL, NULL, &tok_end, NULL, NULL};
 
 _notmuch_token_t *
 _notmuch_token_create_op (const void *ctx, enum _notmuch_token_type type,
@@ -145,6 +144,9 @@ _notmuch_token_show (const void *ctx, _notmuch_token_t *tok)
     else if (tok->type == TOK_LIT)
 	return talloc_asprintf (ctx, "'%s'%s", tok->text,
 				tok->wildcard ? "*" : "");
+    else if (tok->type == TOK_RANGE)
+	return talloc_asprintf (ctx, "RANGE/%d:%s..%s",
+				tok->valueno, tok->rangeBegin, tok->rangeEnd);
     else if (tok->type == TOK_ERROR)
 	return talloc_asprintf (ctx, "ERROR/\"%s\"", tok->text);
 
@@ -536,6 +538,7 @@ parse_prob (struct _notmuch_parse_state *s, int prec, _notmuch_token_t **tok)
 	    break;
 
 	case TOK_FILTER:
+	case TOK_RANGE:
 	case TOK_ERROR:
 	    INTERNAL_ERROR ("Unexpected token %s",
 			    _notmuch_token_show (s->ctx, *tok));
@@ -902,6 +905,17 @@ generate (struct _notmuch_generate_state *s, _notmuch_token_t *root)
 	    return generate_wildcard (s, term);
 	return Query (term);
 
+    case TOK_RANGE:
+	if (root->rangeBegin && root->rangeEnd)
+	    return Query (Query::OP_VALUE_RANGE, root->valueno,
+			  root->rangeBegin, root->rangeEnd);
+	else if (root->rangeBegin)
+	    return Query (Query::OP_VALUE_GE, root->valueno, root->rangeBegin);
+	else if (root->rangeEnd)
+	    return Query (Query::OP_VALUE_LE, root->valueno, root->rangeEnd);
+	else
+	    INTERNAL_ERROR ("TOK_RANGE must have an endpoint");
+
     case TOK_ERROR:
 	if (!s->error)
 	    s->error = talloc_strdup (s->ctx, root->text);
-- 
1.7.2.3



More information about the notmuch mailing list