Mercurial > dovecot > core-2.2
changeset 19478:33465d1d595c
lib-storage: mail_search_args_simplify() handles now "(a OR b) AND (a OR c)" -> "a OR (b AND c)"
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 06 Dec 2015 20:48:55 +0200 |
parents | 91b9510237fd |
children | 1f1fc5eb4a8e |
files | src/lib-storage/mail-search-args-simplify.c src/lib-storage/test-mail-search-args-simplify.c |
diffstat | 2 files changed, 44 insertions(+), 12 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-storage/mail-search-args-simplify.c Sun Dec 06 20:46:52 2015 +0200 +++ b/src/lib-storage/mail-search-args-simplify.c Sun Dec 06 20:48:55 2015 +0200 @@ -290,7 +290,8 @@ *argp = (*argp)->next; found = TRUE; } else if (check_subs) { - i_assert((*argp)->type == SEARCH_SUB); + i_assert((*argp)->type == SEARCH_SUB || + (*argp)->type == SEARCH_OR); if (!mail_search_args_remove_equal(&(*argp)->value.subargs, wanted_arg, FALSE)) { /* we already verified that this should have existed. */ @@ -377,8 +378,8 @@ } static bool -mail_search_args_simplify_extract_common_and(struct mail_search_arg **argsp, - pool_t pool) +mail_search_args_simplify_extract_common(struct mail_search_arg **argsp, + pool_t pool, bool and_arg) { /* Simple SUB example: (a AND b) OR (a AND c) -> a AND (b OR c) @@ -386,18 +387,28 @@ More complicated example: (c1 AND c2 AND u1 AND u2) OR (c1 AND c2 AND u3 AND u4) -> c1 AND c2 AND ((u1 AND u2) OR (u3 AND u4)) + + Similarly for ORs: + (a OR b) AND (a OR c) -> a OR (b AND c) + + (c1 OR c2 OR u1 OR u2) AND (c1 OR c2 OR u3 OR u4) -> + c1 OR c2 OR ((u1 OR u2) AND (u3 OR u4)) + */ struct mail_search_arg *arg, *sub_arg, *sub_next; struct mail_search_arg *new_arg, *child_arg, *common_args = NULL; + enum mail_search_arg_type child_subargs_type; if ((*argsp)->next == NULL) { /* single arg, nothing to extract */ return FALSE; } - /* find the first SEARCH_SUB */ + child_subargs_type = and_arg ? SEARCH_OR : SEARCH_SUB; + + /* find the first arg with child_subargs_type */ for (arg = *argsp; arg != NULL; arg = arg->next) { - if (arg->type == SEARCH_SUB) + if (arg->type == child_subargs_type) break; } if (arg == NULL) @@ -410,7 +421,7 @@ for (arg = *argsp; arg != NULL; arg = arg->next) { if (mail_search_arg_one_equals(arg, sub_arg)) { /* the whole arg matches */ - } else if (arg->type == SEARCH_SUB && + } else if (arg->type == child_subargs_type && mail_search_args_have_equal(arg->value.subargs, sub_arg)) { /* exists as subarg */ } else { @@ -430,14 +441,16 @@ /* replace all the original args with a single new SUB/OR arg */ new_arg = p_new(pool, struct mail_search_arg, 1); - new_arg->type = SEARCH_SUB; + new_arg->type = child_subargs_type; if (*argsp == NULL) { /* there are only common args */ new_arg->value.subargs = common_args; } else { - /* replace OR arg with AND(common_args, OR(non_common_args)) */ + /* replace OR arg with AND(OR(non_common_args), common_args) + or + replace AND arg with OR(AND(non_common_args), common_args) */ child_arg = p_new(pool, struct mail_search_arg, 1); - child_arg->type = SEARCH_OR; + child_arg->type = and_arg ? SEARCH_SUB : SEARCH_OR; child_arg->value.subargs = *argsp; child_arg->next = common_args; new_arg->value.subargs = child_arg; @@ -497,10 +510,11 @@ i_assert(!args->match_not); if (args->type != SEARCH_INTHREAD) { - if (mail_search_args_simplify_drop_redundent_args(&args->value.subargs, args->type == SEARCH_SUB)) + bool and_arg = args->type == SEARCH_SUB; + + if (mail_search_args_simplify_drop_redundent_args(&args->value.subargs, and_arg)) ctx.removals = TRUE; - if (args->type == SEARCH_OR && - mail_search_args_simplify_extract_common_and(&args->value.subargs, pool)) + if (mail_search_args_simplify_extract_common(&args->value.subargs, pool, and_arg)) ctx.removals = TRUE; } if (mail_search_args_simplify_sub(box, pool, args->value.subargs, @@ -635,6 +649,8 @@ for (;;) { if (mail_search_args_simplify_drop_redundent_args(&args->args, TRUE)) removals = TRUE; + if (mail_search_args_simplify_extract_common(&args->args, args->pool, TRUE)) + removals = TRUE; if (!removals) break; removals = mail_search_args_simplify_sub(args->box, args->pool, args->args, TRUE);
--- a/src/lib-storage/test-mail-search-args-simplify.c Sun Dec 06 20:46:52 2015 +0200 +++ b/src/lib-storage/test-mail-search-args-simplify.c Sun Dec 06 20:48:55 2015 +0200 @@ -129,6 +129,22 @@ { "( OR TEXT common1 TEXT common2 ) ( OR TEXT common1 OR TEXT common2 TEXT unique1 )", "(OR TEXT common1 TEXT common2)" }, { "TEXT common1 ( OR TEXT unique1 TEXT common1 ) ( OR TEXT unique3 TEXT common1 )", "TEXT common1" }, { "OR ( TEXT common1 ( OR TEXT unique1 TEXT common1 ) ) TEXT unique1", "(OR TEXT common1 TEXT unique1)" }, + + /* SUB: extract common OR */ + { "( OR TEXT common1 TEXT unique1 ) ( OR TEXT common1 TEXT unique2 )", "(OR (TEXT unique1 TEXT unique2) TEXT common1)" }, + { "( OR TEXT unique1 TEXT common1 ) ( OR TEXT unique2 TEXT common1 )", "(OR (TEXT unique1 TEXT unique2) TEXT common1)" }, + { "( OR TEXT common1 TEXT unique1 ) ( OR TEXT unique2 TEXT common1 )", "(OR (TEXT unique1 TEXT unique2) TEXT common1)" }, + { "( OR TEXT unique1 TEXT common1 ) ( OR TEXT common1 TEXT unique2 )", "(OR (TEXT unique1 TEXT unique2) TEXT common1)" }, + + { "( OR TEXT unique1 TEXT common1 ) ( OR TEXT common1 OR TEXT unique2 TEXT unique3 )", "(OR (TEXT unique1 (OR TEXT unique2 TEXT unique3)) TEXT common1)" }, + { "( OR TEXT common1 OR TEXT common2 TEXT unique1 ) ( OR TEXT common1 OR TEXT common2 TEXT unique2 )", "(OR (TEXT unique1 TEXT unique2) OR TEXT common2 TEXT common1)" }, + { "( OR TEXT common1 OR TEXT common2 OR TEXT unique1 TEXT unique2 ) ( OR TEXT common1 OR TEXT common2 OR TEXT unique3 TEXT unique4 )", "(OR ((OR TEXT unique1 TEXT unique2) (OR TEXT unique3 TEXT unique4)) OR TEXT common2 TEXT common1)" }, + + /* non-matching cases */ + { "( OR TEXT unique1 TEXT unique2 ) TEXT unique3", "(OR TEXT unique1 TEXT unique2) TEXT unique3" }, + { "( OR TEXT unique1 TEXT unique2 ) ( OR TEXT unique3 TEXT unique4 )", "(OR TEXT unique1 TEXT unique2) (OR TEXT unique3 TEXT unique4)" }, + { "( OR TEXT common1 TEXT unique1 ) ( OR TEXT common1 TEXT unique2 ) TEXT unique3", "(OR TEXT common1 TEXT unique1) (OR TEXT common1 TEXT unique2) TEXT unique3" }, + { "( OR TEXT common1 TEXT unique1 ) ( OR TEXT common1 TEXT common2 ) ( OR TEXT common2 TEXT unique2 )", "(OR TEXT common1 TEXT unique1) (OR TEXT common1 TEXT common2) (OR TEXT common2 TEXT unique2)" }, }; static struct mail_search_args *