dovecot-2.2: lib-storage: mail_search_args_simplify() handles no...

dovecot at dovecot.org dovecot at dovecot.org
Sun Dec 6 16:14:26 UTC 2015


details:   http://hg.dovecot.org/dovecot-2.2/rev/836a0c2bc48a
changeset: 19473:836a0c2bc48a
user:      Timo Sirainen <tss at iki.fi>
date:      Sun Dec 06 18:14:08 2015 +0200
description:
lib-storage: mail_search_args_simplify() handles now "(a AND b) OR (a AND c)" -> "a AND (b OR c)"

diffstat:

 src/lib-storage/mail-search-args-simplify.c      |  102 +++++++++++++++++++++-
 src/lib-storage/test-mail-search-args-simplify.c |   14 +++
 2 files changed, 111 insertions(+), 5 deletions(-)

diffs (161 lines):

diff -r 8749308aad53 -r 836a0c2bc48a src/lib-storage/mail-search-args-simplify.c
--- a/src/lib-storage/mail-search-args-simplify.c	Sun Dec 06 18:12:24 2015 +0200
+++ b/src/lib-storage/mail-search-args-simplify.c	Sun Dec 06 18:14:08 2015 +0200
@@ -278,6 +278,37 @@
 }
 
 static bool
+mail_search_args_remove_equal(struct mail_search_arg *parent_arg,
+			      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; ) {
+		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)) {
+				/* we already verified that this should have
+				   existed. */
+				i_unreached();
+			}
+			if ((*argp)->value.subargs == NULL)
+				*argp = (*argp)->next;
+			else
+				argp = &(*argp)->next;
+			found = TRUE;
+		} else {
+			argp = &(*argp)->next;
+		}
+	}
+	return found;
+}
+
+static bool
 mail_search_args_have_all_equal(struct mail_search_arg *parent_arg,
 				const struct mail_search_arg *wanted_args)
 {
@@ -341,7 +372,66 @@
 }
 
 static bool
-mail_search_args_simplify_sub(struct mailbox *box,
+mail_search_args_simplify_extract_common_and(struct mail_search_arg *parent_arg,
+					     pool_t pool)
+{
+	struct mail_search_arg *arg, *sub_arg, *sub_next;
+	struct mail_search_arg *or_arg, *common_args = NULL;
+
+	i_assert(parent_arg->type == SEARCH_OR);
+	i_assert(!parent_arg->match_not);
+
+	/* find the first SEARCH_SUB */
+	for (arg = parent_arg->value.subargs; arg != NULL; arg = arg->next) {
+		if (arg->type == SEARCH_SUB)
+			break;
+	}
+	if (arg == NULL)
+		return FALSE;
+
+	for (sub_arg = arg->value.subargs; sub_arg != NULL; sub_arg = sub_next) {
+		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) {
+			if (mail_search_arg_one_equals(arg, sub_arg)) {
+				/* the whole arg matches */
+			} else if (arg->type == SEARCH_SUB &&
+				   mail_search_args_have_equal(arg->value.subargs, sub_arg)) {
+				/* exists as subarg */
+			} else {
+				break;
+			}
+		}
+		if (arg != NULL)
+			continue;
+
+		/* extract the arg and put it to common_args */
+		mail_search_args_remove_equal(parent_arg, sub_arg, TRUE);
+		sub_arg->next = common_args;
+		common_args = sub_arg;
+	}
+	if (common_args == NULL)
+		return FALSE;
+
+	if (parent_arg->value.subargs == NULL) {
+		/* there are only common args */
+		parent_arg->type = SEARCH_SUB;
+		parent_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;
+	}
+	return TRUE;
+}
+
+static bool
+mail_search_args_simplify_sub(struct mailbox *box, pool_t pool,
 			      struct mail_search_arg *args, bool parent_and)
 {
 	struct mail_search_simplify_ctx ctx;
@@ -390,8 +480,10 @@
 			if (args->type == SEARCH_OR) {
 				if (mail_search_args_simplify_or_drop_redundent_args(args))
 					ctx.removals = TRUE;
+				if (mail_search_args_simplify_extract_common_and(args, pool))
+					ctx.removals = TRUE;
 			}
-			if (mail_search_args_simplify_sub(box, args->value.subargs,
+			if (mail_search_args_simplify_sub(box, pool, args->value.subargs,
 							  args->type != SEARCH_OR))
 				ctx.removals = TRUE;
 		}
@@ -513,12 +605,12 @@
 
 	args->simplified = TRUE;
 
-	removals = mail_search_args_simplify_sub(args->box, args->args, TRUE);
+	removals = mail_search_args_simplify_sub(args->box, args->pool, args->args, TRUE);
 	if (mail_search_args_unnest_inthreads(args, &args->args,
 					      FALSE, TRUE)) {
 		/* we may have added some extra SUBs that could be dropped */
-		mail_search_args_simplify_sub(args->box, args->args, TRUE);
+		mail_search_args_simplify_sub(args->box, args->pool, args->args, TRUE);
 	}
 	while (removals)
-		removals = mail_search_args_simplify_sub(args->box, args->args, TRUE);
+		removals = mail_search_args_simplify_sub(args->box, args->pool, args->args, TRUE);
 }
diff -r 8749308aad53 -r 836a0c2bc48a src/lib-storage/test-mail-search-args-simplify.c
--- a/src/lib-storage/test-mail-search-args-simplify.c	Sun Dec 06 18:12:24 2015 +0200
+++ b/src/lib-storage/test-mail-search-args-simplify.c	Sun Dec 06 18:14:08 2015 +0200
@@ -102,6 +102,20 @@
 	{ "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" },
+
+	{ "OR ( TEXT common1 TEXT unique1 ) ( TEXT common1 TEXT unique2 )", "(OR TEXT unique1 TEXT unique2) TEXT common1" },
+	{ "OR ( TEXT unique1 TEXT common1 ) ( TEXT unique2 TEXT common1 )", "(OR TEXT unique1 TEXT unique2) TEXT common1" },
+	{ "OR ( TEXT common1 TEXT unique1 ) ( TEXT unique2 TEXT common1 )", "(OR TEXT unique1 TEXT unique2) TEXT common1" },
+	{ "OR ( TEXT unique1 TEXT common1 ) ( TEXT common1 TEXT unique2 )", "(OR TEXT unique1 TEXT unique2) TEXT common1" },
+
+	{ "OR ( TEXT unique1 TEXT common1 ) ( TEXT common1 TEXT unique2 TEXT unique3 )", "(OR TEXT unique1 (TEXT unique2 TEXT unique3)) TEXT common1" },
+	{ "OR ( TEXT common1 TEXT common2 TEXT unique1 ) ( TEXT common1 TEXT common2 TEXT unique2 )", "(OR TEXT unique1 TEXT unique2) TEXT common2 TEXT common1" },
+	{ "OR ( TEXT common1 TEXT common2 TEXT unique1 TEXT unique2 ) ( TEXT common1 TEXT common2 TEXT unique3 TEXT unique4 )", "(OR (TEXT unique1 TEXT unique2) (TEXT unique3 TEXT unique4)) TEXT common2 TEXT common1" },
+
+	{ "OR ( TEXT unique1 TEXT unique2 ) TEXT unique3", "(OR (TEXT unique1 TEXT unique2) TEXT unique3)" },
+	{ "OR ( TEXT unique1 TEXT unique2 ) ( TEXT unique3 TEXT unique4 )", "(OR (TEXT unique1 TEXT unique2) (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 ) ( TEXT common2 TEXT unique2 )", "(OR (TEXT common1 TEXT unique1) OR (TEXT common1 TEXT common2) (TEXT common2 TEXT unique2))" },
 };
 
 static struct mail_search_args *


More information about the dovecot-cvs mailing list