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

dovecot at dovecot.org dovecot at dovecot.org
Sun Dec 6 18:49:16 UTC 2015


details:   http://hg.dovecot.org/dovecot-2.2/rev/33465d1d595c
changeset: 19478:33465d1d595c
user:      Timo Sirainen <tss at iki.fi>
date:      Sun Dec 06 20:48:55 2015 +0200
description:
lib-storage: mail_search_args_simplify() handles now "(a OR b) AND (a OR c)" -> "a OR (b AND c)"

diffstat:

 src/lib-storage/mail-search-args-simplify.c      |  40 ++++++++++++++++-------
 src/lib-storage/test-mail-search-args-simplify.c |  16 +++++++++
 2 files changed, 44 insertions(+), 12 deletions(-)

diffs (134 lines):

diff -r 91b9510237fd -r 33465d1d595c src/lib-storage/mail-search-args-simplify.c
--- 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);
diff -r 91b9510237fd -r 33465d1d595c src/lib-storage/test-mail-search-args-simplify.c
--- 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 *


More information about the dovecot-cvs mailing list