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