Skip to content

Commit

Permalink
lib-storage: mail_search_args_simplify() - simplify "x AND NOT x"
Browse files Browse the repository at this point in the history
Implemented for SEARCH_KEYWORD, SEARCH_TEXT, SEARCH_BODY and SEARCH_HEADER*.
Dates and sizes would need special code, which gets a bit complicated.
  • Loading branch information
sirainen committed Apr 20, 2017
1 parent 9af86df commit 52a4634
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 20 deletions.
46 changes: 27 additions & 19 deletions src/lib-storage/mail-search-args-simplify.c
Expand Up @@ -60,7 +60,6 @@ static void mail_search_arg_get_base_mask(const struct mail_search_arg *arg,
{
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;
}
Expand All @@ -84,6 +83,27 @@ mail_search_args_simplify_get_prev_argp(struct mail_search_simplify_ctx *ctx,
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)
{
Expand All @@ -95,6 +115,7 @@ static bool mail_search_args_merge_flags(struct mail_search_simplify_ctx *ctx,
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) {
Expand All @@ -111,18 +132,10 @@ mail_search_args_merge_keywords(struct mail_search_simplify_ctx *ctx,
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)
Expand Down Expand Up @@ -164,6 +177,7 @@ static bool mail_search_args_merge_set(struct mail_search_simplify_ctx *ctx,
}

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) {
Expand All @@ -187,6 +201,7 @@ static bool mail_search_args_merge_time(struct mail_search_simplify_ctx *ctx,
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);

Expand Down Expand Up @@ -248,6 +263,7 @@ static bool mail_search_args_merge_size(struct mail_search_simplify_ctx *ctx,
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) {
Expand Down Expand Up @@ -301,19 +317,11 @@ static bool mail_search_args_merge_text(struct mail_search_simplify_ctx *ctx,
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
Expand Down
13 changes: 12 additions & 1 deletion src/lib-storage/test-mail-search-args-simplify.c
Expand Up @@ -59,6 +59,8 @@ struct {
{ "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" },

Expand Down Expand Up @@ -125,17 +127,26 @@ struct {
{ "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" },
Expand Down

0 comments on commit 52a4634

Please sign in to comment.