From: Timo Sirainen Date: Thu, 23 Apr 2015 17:16:54 +0000 (+0300) Subject: lib-storage: mail_search_args_simplify() merges now seqsets and uidsets. X-Git-Tag: 2.2.17.rc1~159 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7000810786f2959f02cd6d2f4151a9eb61ff5db8;p=thirdparty%2Fdovecot%2Fcore.git lib-storage: mail_search_args_simplify() merges now seqsets and uidsets. --- diff --git a/src/lib-storage/mail-search-args-simplify.c b/src/lib-storage/mail-search-args-simplify.c index dda0901e81..76781195ae 100644 --- a/src/lib-storage/mail-search-args-simplify.c +++ b/src/lib-storage/mail-search-args-simplify.c @@ -3,15 +3,58 @@ #include "lib.h" #include "mail-search.h" +struct mail_search_simplify_ctx { + struct mail_search_arg *prev_flags, *prev_not_flags; + struct mail_search_arg *prev_seqset, *prev_not_seqset; + struct mail_search_arg *prev_uidset, *prev_not_uidset; + bool removals; +}; + +static bool mail_search_args_merge_flags(struct mail_search_simplify_ctx *ctx, + struct mail_search_arg *args) +{ + struct mail_search_arg **prev_argp; + + prev_argp = !args->match_not ? &ctx->prev_flags : &ctx->prev_not_flags; + if (*prev_argp == NULL) { + *prev_argp = args; + return FALSE; + } else { + (*prev_argp)->value.flags |= args->value.flags; + return TRUE; + } +} + +static bool mail_search_args_merge_set(struct mail_search_simplify_ctx *ctx, + struct mail_search_arg *args) +{ + struct mail_search_arg **prev_argp; + + if (args->type == SEARCH_SEQSET) { + prev_argp = !args->match_not ? &ctx->prev_seqset : + &ctx->prev_not_seqset; + } else { + prev_argp = !args->match_not ? &ctx->prev_uidset : + &ctx->prev_not_uidset; + } + if (*prev_argp == NULL) { + *prev_argp = args; + return FALSE; + } else { + seq_range_array_merge(&(*prev_argp)->value.seqset, + &args->value.seqset); + return TRUE; + } +} + static bool mail_search_args_simplify_sub(struct mailbox *box, struct mail_search_arg *args, bool parent_and) { - struct mail_search_arg *sub, *prev = NULL; - struct mail_search_arg *prev_flags_arg, *prev_not_flags_arg; - bool removals; + struct mail_search_simplify_ctx ctx; + struct mail_search_arg *sub, *prev_arg = NULL; - prev_flags_arg = prev_not_flags_arg = NULL; + memset(&ctx, 0, sizeof(ctx)); while (args != NULL) { if (args->match_not && (args->type == SEARCH_SUB || args->type == SEARCH_OR)) { @@ -46,40 +89,39 @@ mail_search_args_simplify_sub(struct mailbox *box, args->type == SEARCH_INTHREAD) { if (mail_search_args_simplify_sub(box, args->value.subargs, args->type != SEARCH_OR)) - removals = TRUE; + ctx.removals = TRUE; } - /* merge all flags arguments */ - if (args->type == SEARCH_FLAGS && - !args->match_not && parent_and) { - if (prev_flags_arg == NULL) - prev_flags_arg = args; - else { - prev_flags_arg->value.flags |= - args->value.flags; - prev->next = args->next; - args = args->next; - removals = TRUE; - continue; + if ((!args->match_not && parent_and) || + (args->match_not && !parent_and)) { + /* try to merge arguments */ + bool merged; + + switch (args->type) { + case SEARCH_FLAGS: + merged = mail_search_args_merge_flags(&ctx, args); + break; + case SEARCH_SEQSET: + case SEARCH_UIDSET: + merged = mail_search_args_merge_set(&ctx, args); + break; + case SEARCH_BEFORE: + default: + merged = FALSE; + break; } - } else if (args->type == SEARCH_FLAGS && args->match_not && - !parent_and) { - if (prev_not_flags_arg == NULL) - prev_not_flags_arg = args; - else { - prev_not_flags_arg->value.flags |= - args->value.flags; - prev->next = args->next; + if (merged) { + prev_arg->next = args->next; args = args->next; - removals = TRUE; + ctx.removals = TRUE; continue; } } - prev = args; + prev_arg = args; args = args->next; } - return removals; + return ctx.removals; } static bool diff --git a/src/lib-storage/test-mail-search-args-simplify.c b/src/lib-storage/test-mail-search-args-simplify.c index 0d03152158..fd7d77c36c 100644 --- a/src/lib-storage/test-mail-search-args-simplify.c +++ b/src/lib-storage/test-mail-search-args-simplify.c @@ -32,7 +32,24 @@ struct { { "OR ( ANSWERED FLAGGED SEEN ) DRAFT", "(OR (ANSWERED FLAGGED SEEN) (DRAFT))" }, { "ANSWERED TEXT foo FLAGGED SEEN", "(ANSWERED FLAGGED SEEN) TEXT foo" }, { "NOT ( ANSWERED FLAGGED SEEN )", "NOT (ANSWERED FLAGGED SEEN)" }, - { "OR NOT ANSWERED OR NOT FLAGGED NOT SEEN", "NOT (ANSWERED FLAGGED SEEN)" } + { "OR NOT ANSWERED OR NOT FLAGGED NOT SEEN", "NOT (ANSWERED FLAGGED SEEN)" }, + { "ANSWERED NOT FLAGGED SEEN NOT DRAFT", "(ANSWERED SEEN) NOT (FLAGGED) NOT (DRAFT)" }, + { "OR NOT ANSWERED NOT SEEN", "NOT (ANSWERED SEEN)" }, + + { "1:5 10:20", "1:5,10:20" }, + { "1:5 NOT 10:20", "1:5 NOT 10:20" }, + { "1:5 NOT 10:20 NOT 30:40", "1:5 NOT 10:20 NOT 30:40" }, + { "OR 1:5 NOT 10:20", "(OR 1:5 NOT 10:20)" }, + { "OR 1:5 OR NOT 10:20 NOT 30:40", "(OR 1:5 NOT 10:20,30:40)" }, + + { "UID 1:5 UID 10:20", "UID 1:5,10:20" }, + { "UID 1:5 NOT UID 10:20", "UID 1:5 NOT UID 10:20" }, + { "UID 1:5 NOT UID 10:20 NOT UID 30:40", "UID 1:5 NOT UID 10:20 NOT UID 30:40" }, + { "OR UID 1:5 NOT UID 10:20", "(OR UID 1:5 NOT UID 10:20)" }, + { "OR UID 1:5 OR NOT UID 10:20 NOT UID 30:40", "(OR UID 1:5 NOT UID 10:20,30:40)" }, + + { "1:5 UID 10:20", "1:5 UID 10:20" }, + { "1:5 NOT UID 10:20", "1:5 NOT UID 10:20" } }; static struct mail_search_args *