]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-storage: mail_search_args_simplify() refactoring
authorTimo Sirainen <tss@iki.fi>
Sun, 6 Dec 2015 18:46:52 +0000 (20:46 +0200)
committerTimo Sirainen <tss@iki.fi>
Sun, 6 Dec 2015 18:46:52 +0000 (20:46 +0200)
Removed parent_arg from mail_search_args_simplify_extract_common_and() in
preperation for the next changeset.

src/lib-storage/mail-search-args-simplify.c
src/lib-storage/test-mail-search-args-simplify.c

index cefadfb7708d2058f41ed7e56196ec5d5b6be3fe..b9825fa678f24fdc33cdcd04e9ea4fd74cbedba3 100644 (file)
@@ -278,20 +278,20 @@ mail_search_args_have_equal(const struct mail_search_arg *args,
 }
 
 static bool
-mail_search_args_remove_equal(struct mail_search_arg *parent_arg,
+mail_search_args_remove_equal(struct mail_search_arg **argsp,
                              const struct mail_search_arg *wanted_arg,
                              bool check_subs)
 {
        struct mail_search_arg **argp;
        bool found = FALSE;
 
-       for (argp = &parent_arg->value.subargs; (*argp) != NULL; ) {
+       for (argp = argsp; (*argp) != NULL; ) {
                if (mail_search_arg_one_equals(*argp, wanted_arg)) {
                        *argp = (*argp)->next;
                        found = TRUE;
                } else if (check_subs) {
                        i_assert((*argp)->type == SEARCH_SUB);
-                       if (!mail_search_args_remove_equal(*argp, wanted_arg, FALSE)) {
+                       if (!mail_search_args_remove_equal(&(*argp)->value.subargs, wanted_arg, FALSE)) {
                                /* we already verified that this should have
                                   existed. */
                                i_unreached();
@@ -377,17 +377,26 @@ mail_search_args_simplify_drop_redundent_args(struct mail_search_arg **argsp,
 }
 
 static bool
-mail_search_args_simplify_extract_common_and(struct mail_search_arg *parent_arg,
+mail_search_args_simplify_extract_common_and(struct mail_search_arg **argsp,
                                             pool_t pool)
 {
+       /* Simple SUB example:
+          (a AND b) OR (a AND c) -> a AND (b OR c)
+
+          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))
+       */
        struct mail_search_arg *arg, *sub_arg, *sub_next;
-       struct mail_search_arg *or_arg, *common_args = NULL;
+       struct mail_search_arg *new_arg, *child_arg, *common_args = NULL;
 
-       i_assert(parent_arg->type == SEARCH_OR);
-       i_assert(!parent_arg->match_not);
+       if ((*argsp)->next == NULL) {
+               /* single arg, nothing to extract */
+               return FALSE;
+       }
 
        /* find the first SEARCH_SUB */
-       for (arg = parent_arg->value.subargs; arg != NULL; arg = arg->next) {
+       for (arg = *argsp; arg != NULL; arg = arg->next) {
                if (arg->type == SEARCH_SUB)
                        break;
        }
@@ -398,7 +407,7 @@ mail_search_args_simplify_extract_common_and(struct mail_search_arg *parent_arg,
                sub_next = sub_arg->next;
 
                /* check if sub_arg is found from all the args */
-               for (arg = parent_arg->value.subargs; arg != NULL; arg = arg->next) {
+               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 &&
@@ -412,26 +421,28 @@ mail_search_args_simplify_extract_common_and(struct mail_search_arg *parent_arg,
                        continue;
 
                /* extract the arg and put it to common_args */
-               mail_search_args_remove_equal(parent_arg, sub_arg, TRUE);
+               mail_search_args_remove_equal(argsp, sub_arg, TRUE);
                sub_arg->next = common_args;
                common_args = sub_arg;
        }
        if (common_args == NULL)
                return FALSE;
 
-       if (parent_arg->value.subargs == NULL) {
+       /* 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;
+       if (*argsp == NULL) {
                /* there are only common args */
-               parent_arg->type = SEARCH_SUB;
-               parent_arg->value.subargs = common_args;
+               new_arg->value.subargs = common_args;
        } else {
                /* replace OR arg with AND(common_args, OR(non_common_args)) */
-               or_arg = p_new(pool, struct mail_search_arg, 1);
-               *or_arg = *parent_arg;
-               or_arg->next = common_args;
-
-               parent_arg->type = SEARCH_SUB;
-               parent_arg->value.subargs = or_arg;
+               child_arg = p_new(pool, struct mail_search_arg, 1);
+               child_arg->type = SEARCH_OR;
+               child_arg->value.subargs = *argsp;
+               child_arg->next = common_args;
+               new_arg->value.subargs = child_arg;
        }
+       *argsp = new_arg;
        return TRUE;
 }
 
@@ -483,11 +494,13 @@ mail_search_args_simplify_sub(struct mailbox *box, pool_t pool,
                if (args->type == SEARCH_SUB ||
                    args->type == SEARCH_OR ||
                    args->type == SEARCH_INTHREAD) {
+                       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))
                                        ctx.removals = TRUE;
                                if (args->type == SEARCH_OR &&
-                                   mail_search_args_simplify_extract_common_and(args, pool))
+                                   mail_search_args_simplify_extract_common_and(&args->value.subargs, pool))
                                        ctx.removals = TRUE;
                        }
                        if (mail_search_args_simplify_sub(box, pool, args->value.subargs,
index 5d99071b0add59965d8659407cb287d27099b9a5..6cd3d4e1f998b9e4197cc60b29d9bcf760eeb1b6 100644 (file)
@@ -102,7 +102,7 @@ struct {
        { "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 TEXT common2 ) ( TEXT common1 TEXT common2 TEXT unique1 )", "TEXT common2 TEXT common1" },
+       { "OR ( TEXT common1 TEXT common2 ) ( TEXT common1 TEXT common2 TEXT unique1 )", "TEXT common1 TEXT common2" },
        { "OR TEXT common1 OR ( TEXT unique1 TEXT common1 ) ( TEXT unique3 TEXT common1 )", "TEXT common1" },
 
        /* OR: extract common AND */