Mercurial > dovecot > core-2.2
changeset 21964:ffeadb7ead57
lib-storage: mail_search_args_simplify() - simplify "x AND NOT x"
Implemented for SEARCH_KEYWORD, SEARCH_TEXT, SEARCH_BODY and SEARCH_HEADER*.
Dates and sizes would need special code, which gets a bit complicated.
author | Timo Sirainen <timo.sirainen@dovecot.fi> |
---|---|
date | Thu, 13 Apr 2017 15:09:19 +0300 |
parents | a73fb37621df |
children | 8ec0f067fab1 |
files | src/lib-storage/mail-search-args-simplify.c src/lib-storage/test-mail-search-args-simplify.c |
diffstat | 2 files changed, 39 insertions(+), 20 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-storage/mail-search-args-simplify.c Thu Apr 13 14:05:55 2017 +0300 +++ b/src/lib-storage/mail-search-args-simplify.c Thu Apr 13 15:09:19 2017 +0300 @@ -60,7 +60,6 @@ { i_zero(mask_r); mask_r->bin_mask.type = arg->type; - mask_r->bin_mask.match_not = arg->match_not; mask_r->bin_mask.fuzzy = arg->fuzzy; mask_r->bin_mask.search_flags = arg->value.search_flags; } @@ -84,6 +83,27 @@ return &prev_arg->prev_arg; } +static bool +mail_search_args_merge_mask(struct mail_search_simplify_ctx *ctx, + struct mail_search_arg *args, + const struct mail_search_simplify_prev_arg *mask) +{ + struct mail_search_arg **prev_argp; + + prev_argp = mail_search_args_simplify_get_prev_argp(ctx, mask); + if (*prev_argp == NULL) { + *prev_argp = args; + return FALSE; + } + if ((*prev_argp)->match_not != args->match_not) { + /* a && !a = 0 */ + (*prev_argp)->type = SEARCH_ALL; + (*prev_argp)->match_not = ctx->parent_and; + } + /* duplicate keyword. */ + return TRUE; +} + static bool mail_search_args_merge_flags(struct mail_search_simplify_ctx *ctx, struct mail_search_arg *args) { @@ -95,6 +115,7 @@ return FALSE; mail_search_arg_get_base_mask(args, &mask); + mask.bin_mask.match_not = args->match_not; prev_argp = mail_search_args_simplify_get_prev_argp(ctx, &mask); if (*prev_argp == NULL) { @@ -111,18 +132,10 @@ struct mail_search_arg *args) { struct mail_search_simplify_prev_arg mask; - struct mail_search_arg **prev_argp; mail_search_arg_get_base_mask(args, &mask); mask.str_mask = args->value.str; - prev_argp = mail_search_args_simplify_get_prev_argp(ctx, &mask); - - if (*prev_argp == NULL) { - *prev_argp = args; - return FALSE; - } - /* duplicate keyword. */ - return TRUE; + return mail_search_args_merge_mask(ctx, args, &mask); } static void mail_search_args_simplify_set(struct mail_search_arg *args) @@ -164,6 +177,7 @@ } mail_search_arg_get_base_mask(args, &mask); + mask.bin_mask.match_not = args->match_not; prev_argp = mail_search_args_simplify_get_prev_argp(ctx, &mask); if (*prev_argp == NULL) { @@ -187,6 +201,7 @@ struct mail_search_arg **prev_argp, *prev_arg; mail_search_arg_get_base_mask(args, &mask); + mask.bin_mask.match_not = args->match_not; mask.bin_mask.date_type = args->value.date_type; prev_argp = mail_search_args_simplify_get_prev_argp(ctx, &mask); @@ -248,6 +263,7 @@ struct mail_search_arg **prev_argp, *prev_arg; mail_search_arg_get_base_mask(args, &mask); + mask.bin_mask.match_not = args->match_not; prev_argp = mail_search_args_simplify_get_prev_argp(ctx, &mask); if (*prev_argp == NULL) { @@ -301,19 +317,11 @@ struct mail_search_arg *args) { struct mail_search_simplify_prev_arg mask; - struct mail_search_arg **prev_argp; mail_search_arg_get_base_mask(args, &mask); mask.hdr_field_name_mask = args->hdr_field_name; mask.str_mask = args->value.str; - prev_argp = mail_search_args_simplify_get_prev_argp(ctx, &mask); - - if (*prev_argp == NULL) { - *prev_argp = args; - return FALSE; - } - /* duplicate search word. */ - return TRUE; + return mail_search_args_merge_mask(ctx, args, &mask); } static bool
--- a/src/lib-storage/test-mail-search-args-simplify.c Thu Apr 13 14:05:55 2017 +0300 +++ b/src/lib-storage/test-mail-search-args-simplify.c Thu Apr 13 15:09:19 2017 +0300 @@ -59,6 +59,8 @@ { "OR NOT KEYWORD foo NOT KEYWORD bar", "(OR NOT KEYWORD foo NOT KEYWORD bar)" }, { "KEYWORD foo KEYWORD foo", "KEYWORD foo" }, + { "KEYWORD foo NOT KEYWORD foo", "NOT ALL" }, + { "OR KEYWORD foo NOT KEYWORD foo", "ALL" }, { "OR KEYWORD foo KEYWORD foo", "KEYWORD foo" }, { "NOT KEYWORD foo NOT KEYWORD foo", "NOT KEYWORD foo" }, @@ -125,17 +127,26 @@ { "LARGER 3 NOT LARGER 1 LARGER 2", "LARGER 3 NOT LARGER 1" }, { "SUBJECT foo SUBJECT foo", "SUBJECT foo" }, + { "SUBJECT foo NOT SUBJECT foo", "NOT ALL" }, + { "OR SUBJECT foo NOT SUBJECT foo", "ALL" }, { "SUBJECT foo SUBJECT foob", "SUBJECT foo SUBJECT foob" }, { "OR SUBJECT foo SUBJECT foo", "SUBJECT foo" }, { "FROM foo FROM foo", "FROM foo" }, + { "FROM foo NOT FROM foo", "NOT ALL" }, + { "OR FROM foo NOT FROM foo", "ALL" }, { "FROM foo FROM bar", "FROM foo FROM bar" }, { "FROM foo TO foo", "FROM foo TO foo" }, { "TEXT foo TEXT foo", "TEXT foo" }, { "TEXT foo TEXT foob", "TEXT foo TEXT foob" }, { "OR TEXT foo TEXT foo", "TEXT foo" }, - { "TEXT foo NOT TEXT foo TEXT foo NOT TEXT foo", "TEXT foo NOT TEXT foo" }, + { "OR NOT TEXT foo TEXT foo", "ALL" }, + { "OR TEXT foo NOT TEXT foo", "ALL" }, + { "TEXT foo NOT TEXT foo", "NOT ALL" }, + { "NOT TEXT foo TEXT foo", "NOT ALL" }, { "BODY foo BODY foo", "BODY foo" }, + { "BODY foo NOT BODY foo", "NOT ALL" }, + { "OR BODY foo NOT BODY foo", "ALL" }, { "OR BODY foo BODY foo", "BODY foo" }, { "TEXT foo BODY foo", "TEXT foo BODY foo" }, { "OR ( TEXT foo OR TEXT foo TEXT foo ) ( TEXT foo ( TEXT foo ) )", "TEXT foo" },