bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen /* arg mask => prev_arg */
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen HASH_TABLE(struct mail_search_simplify_prev_arg *,
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen struct mail_search_simplify_prev_arg *) prev_args;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainenmail_search_simplify_prev_arg_cmp(const struct mail_search_simplify_prev_arg *arg1,
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen const struct mail_search_simplify_prev_arg *arg2)
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen ret = memcmp(&arg1->bin_mask, &arg2->bin_mask, sizeof(arg1->bin_mask));
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen ret = null_strcmp(arg1->hdr_field_name_mask, arg2->hdr_field_name_mask);
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen ret = null_strcmp(arg1->str_mask, arg2->str_mask);
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainenstatic unsigned int
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainenmail_search_simplify_prev_arg_hash(const struct mail_search_simplify_prev_arg *arg)
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen hash = mem_hash(&arg->bin_mask, sizeof(arg->bin_mask));
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainenstatic void mail_search_arg_get_base_mask(const struct mail_search_arg *arg,
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen mask_r->bin_mask.search_flags = arg->value.search_flags;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainenstatic struct mail_search_arg **
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainenmail_search_args_simplify_get_prev_argp(struct mail_search_simplify_ctx *ctx,
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen const struct mail_search_simplify_prev_arg *mask)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen struct mail_search_simplify_prev_arg *prev_arg;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen prev_arg = hash_table_lookup(ctx->prev_args, mask);
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen prev_arg = p_new(ctx->pool, struct mail_search_simplify_prev_arg, 1);
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen p_strdup(ctx->pool, mask->hdr_field_name_mask);
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen hash_table_insert(ctx->prev_args, prev_arg, prev_arg);
92f9871ac981201fe0a47f6c909f790cce14b240Timo Sirainenmail_search_args_merge_mask(struct mail_search_simplify_ctx *ctx,
92f9871ac981201fe0a47f6c909f790cce14b240Timo Sirainen const struct mail_search_simplify_prev_arg *mask)
92f9871ac981201fe0a47f6c909f790cce14b240Timo Sirainen prev_argp = mail_search_args_simplify_get_prev_argp(ctx, mask);
92f9871ac981201fe0a47f6c909f790cce14b240Timo Sirainen if ((*prev_argp)->match_not != args->match_not) {
92f9871ac981201fe0a47f6c909f790cce14b240Timo Sirainen /* a && !a = 0 */
92f9871ac981201fe0a47f6c909f790cce14b240Timo Sirainen /* duplicate keyword. */
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainenstatic bool mail_search_args_merge_flags(struct mail_search_simplify_ctx *ctx,
cc23ad7b8ab96d93d5ab5139c431fcdd8d9e1d72Timo Sirainen return mail_search_args_merge_mask(ctx, args, &mask);
1c0020171b04d14adc4966ed963361abc9a86787Timo Sirainenmail_search_args_merge_keywords(struct mail_search_simplify_ctx *ctx,
92f9871ac981201fe0a47f6c909f790cce14b240Timo Sirainen return mail_search_args_merge_mask(ctx, args, &mask);
df8046c9a4f6bc2a478ad1e74504d50f3110c906Timo Sirainenstatic void mail_search_args_simplify_set(struct mail_search_arg *args)
abb5d20d3155db02a1afec4066d52707ba9d4e52Timo Sirainen /* invert the set to drop the NOT. Note that (uint32_t)-1
abb5d20d3155db02a1afec4066d52707ba9d4e52Timo Sirainen matches the last existing mail, which we don't know at this
abb5d20d3155db02a1afec4066d52707ba9d4e52Timo Sirainen point. lib-imap/imap-seqset.c has similar code that
abb5d20d3155db02a1afec4066d52707ba9d4e52Timo Sirainen disallows using (uint32_t)-1 as a real UID. */
abb5d20d3155db02a1afec4066d52707ba9d4e52Timo Sirainen if (seq_range_exists(&args->value.seqset, (uint32_t)-1))
abb5d20d3155db02a1afec4066d52707ba9d4e52Timo Sirainen seq_range_array_invert(&args->value.seqset, 1, (uint32_t)-2);
df8046c9a4f6bc2a478ad1e74504d50f3110c906Timo Sirainen seqset = array_get(&args->value.seqset, &count);
abb5d20d3155db02a1afec4066d52707ba9d4e52Timo Sirainen if (count == 1 && seqset->seq1 == 1 && seqset->seq2 >= (uint32_t)-2) {
df8046c9a4f6bc2a478ad1e74504d50f3110c906Timo Sirainen /* 1:* is the same as ALL. */
df8046c9a4f6bc2a478ad1e74504d50f3110c906Timo Sirainen } else if (count == 0) {
df8046c9a4f6bc2a478ad1e74504d50f3110c906Timo Sirainen /* empty set is the same as NOT ALL. this is mainly coming
df8046c9a4f6bc2a478ad1e74504d50f3110c906Timo Sirainen from mail_search_args_merge_set() intersection. */
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainenstatic bool mail_search_args_merge_set(struct mail_search_simplify_ctx *ctx,
abb5d20d3155db02a1afec4066d52707ba9d4e52Timo Sirainen /* "*" used - can't simplify it */
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen prev_argp = mail_search_args_simplify_get_prev_argp(ctx, &mask);
df8046c9a4f6bc2a478ad1e74504d50f3110c906Timo Sirainen seq_range_array_intersect(&(*prev_argp)->value.seqset,
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen seq_range_array_merge(&(*prev_argp)->value.seqset,
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainenstatic bool mail_search_args_merge_time(struct mail_search_simplify_ctx *ctx,
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen struct mail_search_arg **prev_argp, *prev_arg;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen mask.bin_mask.date_type = args->value.date_type;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen prev_argp = mail_search_args_simplify_get_prev_argp(ctx, &mask);
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if (prev_arg->value.time < args->value.time) {
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen /* prev_arg < 5 AND arg < 10 */
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen /* prev_arg < 10 AND arg < 5 */
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if (prev_arg->value.time < args->value.time) {
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen /* prev_arg < 5 OR arg < 10 */
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen /* prev_arg < 10 OR arg < 5 */
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if (prev_arg->value.time < args->value.time) {
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen /* prev_arg >= 5 AND arg >= 10 */
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen /* prev_arg >= 10 AND arg >= 5 */
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if (prev_arg->value.time < args->value.time) {
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen /* prev_arg >= 5 OR arg >= 10 */
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen /* prev_arg >= 10 OR arg >= 5 */
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainenstatic bool mail_search_args_merge_size(struct mail_search_simplify_ctx *ctx,
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen struct mail_search_arg **prev_argp, *prev_arg;
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen prev_argp = mail_search_args_simplify_get_prev_argp(ctx, &mask);
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen if (prev_arg->value.size < args->value.size) {
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen /* prev_arg < 5 AND arg < 10 */
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen /* prev_arg < 10 AND arg < 5 */
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen if (prev_arg->value.size < args->value.size) {
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen /* prev_arg < 5 OR arg < 10 */
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen /* prev_arg < 10 OR arg < 5 */
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen if (prev_arg->value.size < args->value.size) {
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen /* prev_arg >= 5 AND arg >= 10 */
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen /* prev_arg >= 10 AND arg >= 5 */
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen if (prev_arg->value.size < args->value.size) {
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen /* prev_arg >= 5 OR arg >= 10 */
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen /* prev_arg >= 10 OR arg >= 5 */
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainenstatic bool mail_search_args_merge_text(struct mail_search_simplify_ctx *ctx,
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen mask.hdr_field_name_mask = args->hdr_field_name;
92f9871ac981201fe0a47f6c909f790cce14b240Timo Sirainen return mail_search_args_merge_mask(ctx, args, &mask);
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainenmail_search_args_have_equal(const struct mail_search_arg *args,
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen for (arg = args; arg != NULL; arg = arg->next) {
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen if (mail_search_arg_one_equals(arg, wanted_arg))
fccd110b494a7e31f23d31d9e3bc3e986c9bb1a8Timo Sirainenmail_search_args_remove_equal(struct mail_search_args *all_args,
632018810af689442569cbb0139c55868923ccfeTimo Sirainen if (mail_search_arg_one_equals(*argp, wanted_arg)) {
fccd110b494a7e31f23d31d9e3bc3e986c9bb1a8Timo Sirainen if (!mail_search_args_remove_equal(all_args, &(*argp)->value.subargs, wanted_arg, FALSE)) {
632018810af689442569cbb0139c55868923ccfeTimo Sirainen /* we already verified that this should have
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainenmail_search_args_have_all_equal(struct mail_search_arg *parent_arg,
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen for (arg = wanted_args; arg != NULL; arg = arg->next) {
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen if (!mail_search_args_have_equal(parent_arg->value.subargs, arg))
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainenstatic unsigned int
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainenmail_search_args_count(const struct mail_search_arg *args)
fccd110b494a7e31f23d31d9e3bc3e986c9bb1a8Timo Sirainenmail_search_args_simplify_drop_redundant_args(struct mail_search_args *all_args,
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen struct mail_search_arg *arg, **argp, one_arg, *lowest_arg = NULL;
8d3af185ae454653fad60e41c5f36edb1d45c868Timo Sirainen child_subargs_type = and_arg ? SEARCH_OR : SEARCH_SUB;
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen /* find the arg which has the lowest number of child args */
8d3af185ae454653fad60e41c5f36edb1d45c868Timo Sirainen for (arg = *argsp; arg != NULL; arg = arg->next) {
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen count = mail_search_args_count(arg->value.subargs);
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen /* if there are any args that include lowest_arg, drop the arg since
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen it's redundant. (non-SUB duplicates are dropped elsewhere.) */
8d3af185ae454653fad60e41c5f36edb1d45c868Timo Sirainen if (*argp != lowest_arg && (*argp)->type == child_subargs_type &&
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen mail_search_args_have_all_equal(*argp, lowest_arg)) {
fccd110b494a7e31f23d31d9e3bc3e986c9bb1a8Timo Sirainenmail_search_args_simplify_extract_common(struct mail_search_args *all_args,
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen /* Simple SUB example:
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen (a AND b) OR (a AND c) -> a AND (b OR c)
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen More complicated example:
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen (c1 AND c2 AND u1 AND u2) OR (c1 AND c2 AND u3 AND u4) ->
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen c1 AND c2 AND ((u1 AND u2) OR (u3 AND u4))
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen Similarly for ORs:
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen (a OR b) AND (a OR c) -> a OR (b AND c)
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen (c1 OR c2 OR u1 OR u2) AND (c1 OR c2 OR u3 OR u4) ->
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen c1 OR c2 OR ((u1 OR u2) AND (u3 OR u4))
632018810af689442569cbb0139c55868923ccfeTimo Sirainen struct mail_search_arg *arg, *sub_arg, *sub_next;
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen struct mail_search_arg *new_arg, *child_arg, *common_args = NULL;
6de0cbb4a498ce0519b0f28e221164ce8d39736aTimo Sirainen if (*argsp == NULL || (*argsp)->next == NULL) {
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen /* single arg, nothing to extract */
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen child_subargs_type = and_arg ? SEARCH_OR : SEARCH_SUB;
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen /* find the first arg with child_subargs_type */
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen for (arg = *argsp; arg != NULL; arg = arg->next) {
632018810af689442569cbb0139c55868923ccfeTimo Sirainen for (sub_arg = arg->value.subargs; sub_arg != NULL; sub_arg = sub_next) {
632018810af689442569cbb0139c55868923ccfeTimo Sirainen /* check if sub_arg is found from all the args */
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen for (arg = *argsp; arg != NULL; arg = arg->next) {
632018810af689442569cbb0139c55868923ccfeTimo Sirainen if (mail_search_arg_one_equals(arg, sub_arg)) {
632018810af689442569cbb0139c55868923ccfeTimo Sirainen /* the whole arg matches */
632018810af689442569cbb0139c55868923ccfeTimo Sirainen mail_search_args_have_equal(arg->value.subargs, sub_arg)) {
632018810af689442569cbb0139c55868923ccfeTimo Sirainen /* exists as subarg */
632018810af689442569cbb0139c55868923ccfeTimo Sirainen /* extract the arg and put it to common_args */
fccd110b494a7e31f23d31d9e3bc3e986c9bb1a8Timo Sirainen mail_search_args_remove_equal(all_args, argsp, sub_arg, TRUE);
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen /* replace all the original args with a single new SUB/OR arg */
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen new_arg = p_new(pool, struct mail_search_arg, 1);
632018810af689442569cbb0139c55868923ccfeTimo Sirainen /* there are only common args */
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen /* replace OR arg with AND(OR(non_common_args), common_args)
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen replace AND arg with OR(AND(non_common_args), common_args) */
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen child_arg = p_new(pool, struct mail_search_arg, 1);
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen child_arg->type = and_arg ? SEARCH_SUB : SEARCH_OR;
fccd110b494a7e31f23d31d9e3bc3e986c9bb1a8Timo Sirainenmail_search_args_simplify_sub(struct mail_search_args *all_args, pool_t pool,
37ce8d49a351f073958624b78c702af75362c1cbTimo Sirainen struct mail_search_arg **argsp, bool parent_and)
c9099b08b3cae8a849098ca776b4363c6d5f5f36Timo Sirainen struct mail_search_arg *sub, **all_argsp = argsp;
fccd110b494a7e31f23d31d9e3bc3e986c9bb1a8Timo Sirainen ctx.initialized = all_args->init_refcount > 0;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen ctx.pool = pool_alloconly_create("mail search args simplify", 1024);
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen hash_table_create(&ctx.prev_args, ctx.pool, 0,
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen if (args->match_not && (args->type == SEARCH_SUB ||
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen /* neg(p and q and ..) == neg(p) or neg(q) or ..
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen neg(p or q or ..) == neg(p) and neg(q) and .. */
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen if ((args->type == SEARCH_SUB && parent_and) ||
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen ((args->type == SEARCH_SUB || args->type == SEARCH_OR) &&
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen /* p and (q and ..) == p and q and ..
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen p or (q or ..) == p or q or ..
fccd110b494a7e31f23d31d9e3bc3e986c9bb1a8Timo Sirainen if (mail_search_args_simplify_drop_redundant_args(all_args, &args->value.subargs, and_arg))
fccd110b494a7e31f23d31d9e3bc3e986c9bb1a8Timo Sirainen if (mail_search_args_simplify_extract_common(all_args, &args->value.subargs, pool, and_arg))
fccd110b494a7e31f23d31d9e3bc3e986c9bb1a8Timo Sirainen if (mail_search_args_simplify_sub(all_args, pool, &args->value.subargs,
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen /* try to merge arguments */
c9099b08b3cae8a849098ca776b4363c6d5f5f36Timo Sirainen if (*all_argsp == args && args->next == NULL) {
c9099b08b3cae8a849098ca776b4363c6d5f5f36Timo Sirainen /* this arg has no siblings - no merging */
c9099b08b3cae8a849098ca776b4363c6d5f5f36Timo Sirainen /* .. AND ALL ..
c9099b08b3cae8a849098ca776b4363c6d5f5f36Timo Sirainen .. OR NOT ALL ..
c9099b08b3cae8a849098ca776b4363c6d5f5f36Timo Sirainen This arg is irrelevant -> drop */
c9099b08b3cae8a849098ca776b4363c6d5f5f36Timo Sirainen /* .. AND NOT ALL ..
c9099b08b3cae8a849098ca776b4363c6d5f5f36Timo Sirainen The other args are irrelevant -> drop them */
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen merged = mail_search_args_merge_flags(&ctx, args);
1c0020171b04d14adc4966ed963361abc9a86787Timo Sirainen merged = mail_search_args_merge_keywords(&ctx, args);
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen merged = mail_search_args_merge_set(&ctx, args);
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen merged = mail_search_args_merge_time(&ctx, args);
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen merged = mail_search_args_merge_size(&ctx, args);
279c6b6d0b0a159c8533102e7e914db21dadcb03Timo Sirainen /* BODY "" and TEXT "" matches everything */
279c6b6d0b0a159c8533102e7e914db21dadcb03Timo Sirainen /* fall through */
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen merged = mail_search_args_merge_text(&ctx, args);
cc23ad7b8ab96d93d5ab5139c431fcdd8d9e1d72Timo Sirainenmail_search_args_simplify_merge_flags(struct mail_search_arg **argsp,
cc23ad7b8ab96d93d5ab5139c431fcdd8d9e1d72Timo Sirainen if (mail_search_args_simplify_merge_flags(&args->value.subargs,
cc23ad7b8ab96d93d5ab5139c431fcdd8d9e1d72Timo Sirainen /* ignore non-flags */
cc23ad7b8ab96d93d5ab5139c431fcdd8d9e1d72Timo Sirainen } else if (!((!args->match_not && parent_and) ||
cc23ad7b8ab96d93d5ab5139c431fcdd8d9e1d72Timo Sirainen /* can't merge these flags args */
cc23ad7b8ab96d93d5ab5139c431fcdd8d9e1d72Timo Sirainen /* first flags arg */
cc23ad7b8ab96d93d5ab5139c431fcdd8d9e1d72Timo Sirainen /* merge to previous arg */
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainenmail_search_args_unnest_inthreads(struct mail_search_args *args,
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen struct mail_search_arg *arg, *thread_arg, *or_arg;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen bool child_inthreads = FALSE, non_inthreads = FALSE;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen for (arg = *argp; arg != NULL; arg = arg->next) {
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen /* children converted to SEARCH_INTHREADs */
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen if (!parent_inthreads || !child_inthreads || !non_inthreads)
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen /* put all non-INTHREADs under a single INTHREAD */
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen thread_arg = p_new(args->pool, struct mail_search_arg, 1);
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen /* not an INTHREAD or a SUB/OR with only INTHREADs */
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen /* We want to OR the args */
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen or_arg = p_new(args->pool, struct mail_search_arg, 1);
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen or_arg->value.subargs = thread_arg->value.subargs;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainenvoid mail_search_args_simplify(struct mail_search_args *args)
fccd110b494a7e31f23d31d9e3bc3e986c9bb1a8Timo Sirainen removals = mail_search_args_simplify_sub(args, args->pool, &args->args, TRUE);
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen if (mail_search_args_unnest_inthreads(args, &args->args,
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen /* we may have added some extra SUBs that could be dropped */
fccd110b494a7e31f23d31d9e3bc3e986c9bb1a8Timo Sirainen if (mail_search_args_simplify_sub(args, args->pool, &args->args, TRUE))
fccd110b494a7e31f23d31d9e3bc3e986c9bb1a8Timo Sirainen if (mail_search_args_simplify_drop_redundant_args(args, &args->args, TRUE))
fccd110b494a7e31f23d31d9e3bc3e986c9bb1a8Timo Sirainen if (mail_search_args_simplify_extract_common(args, &args->args, args->pool, TRUE))
fccd110b494a7e31f23d31d9e3bc3e986c9bb1a8Timo Sirainen removals = mail_search_args_simplify_sub(args, args->pool, &args->args, TRUE);
cc23ad7b8ab96d93d5ab5139c431fcdd8d9e1d72Timo Sirainen /* do the flag merging into a single arg only at the end.
cc23ad7b8ab96d93d5ab5139c431fcdd8d9e1d72Timo Sirainen up until then they're treated as any other search args,
cc23ad7b8ab96d93d5ab5139c431fcdd8d9e1d72Timo Sirainen which simplifies their handling. after the flags merging is
cc23ad7b8ab96d93d5ab5139c431fcdd8d9e1d72Timo Sirainen done, further simplifications are still possible. */