Mercurial > dovecot > core-2.2
changeset 19472:8749308aad53
lib-storage: mail_search_args_simplify() handles now "a OR (a AND b)" -> "a"
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 06 Dec 2015 18:12:24 +0200 |
parents | 91509e171e4b |
children | 836a0c2bc48a |
files | src/lib-storage/mail-search-args-simplify.c src/lib-storage/test-mail-search-args-simplify.c |
diffstat | 2 files changed, 86 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-storage/mail-search-args-simplify.c Sun Dec 06 18:09:17 2015 +0200 +++ b/src/lib-storage/mail-search-args-simplify.c Sun Dec 06 18:12:24 2015 +0200 @@ -265,6 +265,82 @@ } static bool +mail_search_args_have_equal(const struct mail_search_arg *args, + const struct mail_search_arg *wanted_arg) +{ + const struct mail_search_arg *arg; + + for (arg = args; arg != NULL; arg = arg->next) { + if (mail_search_arg_one_equals(arg, wanted_arg)) + return TRUE; + } + return FALSE; +} + +static bool +mail_search_args_have_all_equal(struct mail_search_arg *parent_arg, + const struct mail_search_arg *wanted_args) +{ + const struct mail_search_arg *arg; + + i_assert(parent_arg->type == SEARCH_SUB); + + for (arg = wanted_args; arg != NULL; arg = arg->next) { + if (!mail_search_args_have_equal(parent_arg->value.subargs, arg)) + return FALSE; + } + return TRUE; +} + +static unsigned int +mail_search_args_count(const struct mail_search_arg *args) +{ + unsigned int count; + + for (count = 0; args != NULL; count++) + args = args->next; + return count; +} + +static bool +mail_search_args_simplify_or_drop_redundent_args(struct mail_search_arg *parent_arg) +{ + struct mail_search_arg *arg, **argp, one_arg, *lowest_arg = NULL; + unsigned int count, lowest_count = UINT_MAX; + bool ret = FALSE; + + /* find the arg which has the lowest number of child args */ + for (arg = parent_arg->value.subargs; arg != NULL; arg = arg->next) { + if (arg->type != SEARCH_SUB) { + one_arg = *arg; + one_arg.next = NULL; + lowest_arg = &one_arg; + break; + } + count = mail_search_args_count(arg->value.subargs); + if (count < lowest_count) { + lowest_arg = arg->value.subargs; + lowest_count = count; + } + } + i_assert(lowest_arg != NULL); + + /* if there are any args that include lowest_arg, drop the arg since + it's redundant. (non-SUB duplicates are dropped elsewhere.) */ + for (argp = &parent_arg->value.subargs; *argp != NULL; ) { + if (*argp != lowest_arg && (*argp)->type == SEARCH_SUB && + (*argp)->value.subargs != lowest_arg && + mail_search_args_have_all_equal(*argp, lowest_arg)) { + *argp = (*argp)->next; + ret = TRUE; + } else { + argp = &(*argp)->next; + } + } + return ret; +} + +static bool mail_search_args_simplify_sub(struct mailbox *box, struct mail_search_arg *args, bool parent_and) { @@ -311,6 +387,10 @@ if (args->type == SEARCH_SUB || args->type == SEARCH_OR || args->type == SEARCH_INTHREAD) { + if (args->type == SEARCH_OR) { + if (mail_search_args_simplify_or_drop_redundent_args(args)) + ctx.removals = TRUE; + } if (mail_search_args_simplify_sub(box, args->value.subargs, args->type != SEARCH_OR)) ctx.removals = TRUE;
--- a/src/lib-storage/test-mail-search-args-simplify.c Sun Dec 06 18:09:17 2015 +0200 +++ b/src/lib-storage/test-mail-search-args-simplify.c Sun Dec 06 18:12:24 2015 +0200 @@ -96,6 +96,12 @@ { "OR BODY foo BODY foo", "BODY foo" }, { "TEXT foo BODY foo", "TEXT foo BODY foo" }, { "OR ( TEXT foo OR TEXT foo TEXT foo ) ( TEXT foo ( TEXT foo ) )", "TEXT foo" }, + + { "OR ( TEXT common1 TEXT unique1 ) TEXT common1", "TEXT common1" }, + { "OR ( TEXT unique1 TEXT common1 ) TEXT common1", "TEXT common1" }, + { "OR TEXT common1 ( TEXT common1 TEXT unique1 )", "TEXT common1" }, + { "OR TEXT common1 ( TEXT unique1 TEXT common1 )", "TEXT common1" }, + { "OR TEXT common1 OR ( TEXT unique1 TEXT common1 ) ( TEXT unique3 TEXT common1 )", "TEXT common1" }, }; static struct mail_search_args *