dovecot: Handle NOT in search without returning wrong results.

dovecot at dovecot.org dovecot at dovecot.org
Sat Nov 10 19:18:54 EET 2007


details:   http://hg.dovecot.org/dovecot/rev/8e0d9821c0d7
changeset: 6759:8e0d9821c0d7
user:      Timo Sirainen <tss at iki.fi>
date:      Sat Nov 10 19:18:51 2007 +0200
description:
Handle NOT in search without returning wrong results.

diffstat:

5 files changed, 44 insertions(+), 4 deletions(-)
src/plugins/fts-lucene/fts-backend-lucene.c |    2 ++
src/plugins/fts-squat/fts-backend-squat.c   |    7 +++++--
src/plugins/fts/fts-api.c                   |   14 +++++++++++++-
src/plugins/fts/fts-api.h                   |    3 ++-
src/plugins/fts/fts-storage.c               |   22 ++++++++++++++++++++++

diffs (147 lines):

diff -r 3896c75bfaa8 -r 8e0d9821c0d7 src/plugins/fts-lucene/fts-backend-lucene.c
--- a/src/plugins/fts-lucene/fts-backend-lucene.c	Sat Nov 10 19:16:01 2007 +0200
+++ b/src/plugins/fts-lucene/fts-backend-lucene.c	Sat Nov 10 19:18:51 2007 +0200
@@ -187,6 +187,8 @@ fts_backend_lucene_lookup(struct fts_bac
 {
 	struct lucene_fts_backend *backend =
 		(struct lucene_fts_backend *)_backend;
+
+	i_assert((flags & FTS_LOOKUP_FLAG_INVERT) == 0);
 
 	fts_backend_select(backend);
 	return lucene_index_lookup(backend->lstorage->index,
diff -r 3896c75bfaa8 -r 8e0d9821c0d7 src/plugins/fts-squat/fts-backend-squat.c
--- a/src/plugins/fts-squat/fts-backend-squat.c	Sat Nov 10 19:16:01 2007 +0200
+++ b/src/plugins/fts-squat/fts-backend-squat.c	Sat Nov 10 19:18:51 2007 +0200
@@ -178,22 +178,25 @@ static void fts_backend_squat_unlock(str
 
 static int
 fts_backend_squat_lookup(struct fts_backend *_backend,
-			 enum fts_lookup_flags flags ATTR_UNUSED,
+			 enum fts_lookup_flags flags,
 			 const char *key, ARRAY_TYPE(seq_range) *result)
 {
 	struct squat_fts_backend *backend =
 		(struct squat_fts_backend *)_backend;
 
+	i_assert((flags & FTS_LOOKUP_FLAG_INVERT) == 0);
 	return squat_trie_lookup(backend->trie, result, key);
 }
 
 static int
 fts_backend_squat_filter(struct fts_backend *_backend,
-			 enum fts_lookup_flags flags ATTR_UNUSED,
+			 enum fts_lookup_flags flags,
 			 const char *key, ARRAY_TYPE(seq_range) *result)
 {
 	struct squat_fts_backend *backend =
 		(struct squat_fts_backend *)_backend;
+
+	i_assert((flags & FTS_LOOKUP_FLAG_INVERT) == 0);
 
 	return squat_trie_filter(backend->trie, result, key);
 }
diff -r 3896c75bfaa8 -r 8e0d9821c0d7 src/plugins/fts/fts-api.c
--- a/src/plugins/fts/fts-api.c	Sat Nov 10 19:16:01 2007 +0200
+++ b/src/plugins/fts/fts-api.c	Sat Nov 10 19:18:51 2007 +0200
@@ -111,7 +111,12 @@ int fts_backend_lookup(struct fts_backen
 int fts_backend_lookup(struct fts_backend *backend, enum fts_lookup_flags flags,
 		       const char *key, ARRAY_TYPE(seq_range) *result)
 {
-	return backend->v.lookup(backend, flags, key, result);
+	if (backend->v.lookup(backend, flags & ~FTS_LOOKUP_FLAG_INVERT,
+			      key, result) < 0)
+		return -1;
+	if ((flags & FTS_LOOKUP_FLAG_INVERT) != 0)
+		seq_range_array_invert(result, 1, (uint32_t)-1);
+	return 0;
 }
 
 int fts_backend_filter(struct fts_backend *backend, enum fts_lookup_flags flags,
@@ -131,6 +136,13 @@ int fts_backend_filter(struct fts_backen
 		unsigned int i, count;
 		uint32_t next_seq = 1;
 
+		if ((flags & FTS_LOOKUP_FLAG_INVERT) != 0) {
+			/* if the lookups aren't definite, we can't just
+			   invert the result. */
+			i_assert((backend->flags &
+				  FTS_BACKEND_FLAG_DEFINITE_LOOKUPS) != 0);
+			seq_range_array_invert(&tmp_result, 1, (uint32_t)-1);
+		}
 		range = array_get(&tmp_result, &count);
 		for (i = 0; i < count; i++) {
 			if (next_seq != range[i].seq1) {
diff -r 3896c75bfaa8 -r 8e0d9821c0d7 src/plugins/fts/fts-api.h
--- a/src/plugins/fts/fts-api.h	Sat Nov 10 19:16:01 2007 +0200
+++ b/src/plugins/fts/fts-api.h	Sat Nov 10 19:18:51 2007 +0200
@@ -8,7 +8,8 @@ struct mailbox;
 
 enum fts_lookup_flags {
 	FTS_LOOKUP_FLAG_HEADERS	= 0x01,
-	FTS_LOOKUP_FLAG_BODY	= 0x02
+	FTS_LOOKUP_FLAG_BODY	= 0x02,
+	FTS_LOOKUP_FLAG_INVERT	= 0x04
 };
 
 struct fts_backend *
diff -r 3896c75bfaa8 -r 8e0d9821c0d7 src/plugins/fts/fts-storage.c
--- a/src/plugins/fts/fts-storage.c	Sat Nov 10 19:16:01 2007 +0200
+++ b/src/plugins/fts/fts-storage.c	Sat Nov 10 19:18:51 2007 +0200
@@ -378,6 +378,12 @@ static void fts_search_filter_args(struc
 				/* already handled this one */
 				break;
 			}
+			if (args->not &&
+			    (fctx->backend->flags &
+			     FTS_BACKEND_FLAG_DEFINITE_LOOKUPS) == 0) {
+				/* can't optimize this */
+				break;
+			}
 
 			key = args->value.str;
 			if (*key == '\0') {
@@ -392,6 +398,8 @@ static void fts_search_filter_args(struc
 			if (args->type == SEARCH_TEXT_FAST ||
 			    args->type == SEARCH_TEXT)
 				flags |= FTS_LOOKUP_FLAG_HEADERS;
+			if (args->not)
+				flags |= FTS_LOOKUP_FLAG_INVERT;
 			if (fts_backend_filter(fctx->backend, flags, key,
 					       uid_result) < 0) {
 				/* failed, but we already have limited
@@ -442,6 +450,8 @@ static void fts_search_init(struct mailb
 		    fctx->best_arg->type == SEARCH_TEXT)
 			flags |= FTS_LOOKUP_FLAG_HEADERS;
 	}
+	if (fctx->best_arg->not)
+		flags |= FTS_LOOKUP_FLAG_INVERT;
 
 	i_array_init(&uid_result, 64);
 	if (fts_backend_lookup(backend, flags, key, &uid_result) < 0) {
@@ -467,6 +477,11 @@ static bool arg_is_better(const struct m
 	if (old_arg == NULL)
 		return TRUE;
 	if (new_arg == NULL)
+		return FALSE;
+
+	if (old_arg->not && !new_arg->not)
+		return TRUE;
+	if (!old_arg->not && new_arg->not)
 		return FALSE;
 
 	/* prefer not to use headers. they have a larger possibility of
@@ -581,6 +596,13 @@ fts_mailbox_search_init(struct mailbox_t
 			best_exact_arg : best_fast_arg;
 	}
 
+	if (fctx->best_arg != NULL && fctx->best_arg->not &&
+	    (fctx->backend->flags & FTS_BACKEND_FLAG_DEFINITE_LOOKUPS) == 0) {
+		/* NOTs can't be handled without definite lookups */
+		fctx->backend = NULL;
+		fctx->best_arg = NULL;
+	}
+
 	fts_try_build_init(fctx);
 	return ctx;
 }


More information about the dovecot-cvs mailing list