mail-search-args-simplify.c revision f5e8a76a128d4e92f0641135183c164fd5c5ce5e
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2002-2015 Dovecot authors, see the included COPYING file */
2b9e49e4e65e3e2dca38f56971029a3051ccdb99Timo Sirainen /* arg mask => prev_arg */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mail_search_simplify_prev_arg *) prev_args;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic int mail_search_arg_cmp(const struct mail_search_arg *arg1,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic unsigned int mail_search_arg_hash(const struct mail_search_arg *arg)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic void mail_search_arg_get_base_mask(const struct mail_search_arg *arg,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mask_r->value.search_flags = arg->value.search_flags;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic struct mail_search_arg **
2b9e49e4e65e3e2dca38f56971029a3051ccdb99Timo Sirainenmail_search_args_simplify_get_prev_argp(struct mail_search_simplify_ctx *ctx,
d22301419109ed4a38351715e6760011421dadecTimo Sirainen struct mail_search_simplify_prev_arg *prev_arg;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen prev_arg = hash_table_lookup(ctx->prev_args, mask);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen prev_arg = p_new(ctx->pool, struct mail_search_simplify_prev_arg, 1);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen hash_table_insert(ctx->prev_args, &prev_arg->mask, prev_arg);
d22301419109ed4a38351715e6760011421dadecTimo Sirainenstatic bool mail_search_args_merge_flags(struct mail_search_simplify_ctx *ctx,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (!((!args->match_not && ctx->parent_and) ||
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen prev_argp = mail_search_args_simplify_get_prev_argp(ctx, &mask);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen (*prev_argp)->value.flags |= args->value.flags;
4b2a4c8c762e3eaddf7fd2abfe7d4cca6e5e3fd8Timo Sirainenstatic bool mail_search_args_merge_set(struct mail_search_simplify_ctx *ctx,
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen if (!((!args->match_not && ctx->parent_and) ||
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen prev_argp = mail_search_args_simplify_get_prev_argp(ctx, &mask);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen seq_range_array_merge(&(*prev_argp)->value.seqset,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic bool mail_search_args_merge_time(struct mail_search_simplify_ctx *ctx,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mail_search_arg **prev_argp, *prev_arg;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen prev_argp = mail_search_args_simplify_get_prev_argp(ctx, &mask);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (prev_arg->value.time < args->value.time) {
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen /* prev_arg < 5 AND arg < 10 */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* prev_arg < 10 AND arg < 5 */
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen if (prev_arg->value.time < args->value.time) {
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen /* prev_arg < 5 OR arg < 10 */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* prev_arg < 10 OR arg < 5 */
46219292a55094fa49aae33eee681ed075d30e17Timo Sirainen if (prev_arg->value.time < args->value.time) {
46219292a55094fa49aae33eee681ed075d30e17Timo Sirainen /* prev_arg >= 5 AND arg >= 10 */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* prev_arg >= 10 AND arg >= 5 */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (prev_arg->value.time < args->value.time) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* prev_arg >= 5 OR arg >= 10 */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* prev_arg >= 10 OR arg >= 5 */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic bool mail_search_args_merge_size(struct mail_search_simplify_ctx *ctx,
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen struct mail_search_arg **prev_argp, *prev_arg;
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen prev_argp = mail_search_args_simplify_get_prev_argp(ctx, &mask);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (prev_arg->value.size < args->value.size) {
888ab4e17f7441b4dcca4a01886d055b57f4586dTimo Sirainen /* prev_arg < 5 AND arg < 10 */
888ab4e17f7441b4dcca4a01886d055b57f4586dTimo Sirainen /* prev_arg < 10 AND arg < 5 */
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (prev_arg->value.size < args->value.size) {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen /* prev_arg < 5 OR arg < 10 */
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen /* prev_arg < 10 OR arg < 5 */
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen if (prev_arg->value.size < args->value.size) {
5b62dea2f88165f3f4d87bba9011343f3ff415ffTimo Sirainen /* prev_arg >= 5 AND arg >= 10 */
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen /* prev_arg >= 10 AND arg >= 5 */
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen if (prev_arg->value.size < args->value.size) {
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen /* prev_arg >= 5 OR arg >= 10 */
5b62dea2f88165f3f4d87bba9011343f3ff415ffTimo Sirainen /* prev_arg >= 10 OR arg >= 5 */
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenmail_search_args_simplify_sub(struct mailbox *box,
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen struct mail_search_arg *args, bool parent_and)
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen struct mail_search_arg *sub, *prev_arg = NULL;
e22ac7474fb36e3e3dcfeb70ea5f54ea812aa2d0Timo Sirainen ctx.pool = pool_alloconly_create("mail search args simplify", 1024);
e22ac7474fb36e3e3dcfeb70ea5f54ea812aa2d0Timo Sirainen hash_table_create(&ctx.prev_args, ctx.pool, 0, mail_search_arg_hash,
e22ac7474fb36e3e3dcfeb70ea5f54ea812aa2d0Timo Sirainen if (args->match_not && (args->type == SEARCH_SUB ||
e22ac7474fb36e3e3dcfeb70ea5f54ea812aa2d0Timo Sirainen /* neg(p and q and ..) == neg(p) or neg(q) or ..
e22ac7474fb36e3e3dcfeb70ea5f54ea812aa2d0Timo Sirainen neg(p or q or ..) == neg(p) and neg(q) and .. */
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if ((args->type == SEARCH_SUB && parent_and) ||
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen ((args->type == SEARCH_SUB || args->type == SEARCH_OR) &&
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen /* p and (q and ..) == p and q and ..
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen p or (q or ..) == p or q or ..
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (mail_search_args_simplify_sub(box, args->value.subargs,
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen /* try to merge arguments */
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen merged = mail_search_args_merge_flags(&ctx, args);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen merged = mail_search_args_merge_set(&ctx, args);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen merged = mail_search_args_merge_time(&ctx, args);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen merged = mail_search_args_merge_size(&ctx, args);
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainenmail_search_args_unnest_inthreads(struct mail_search_args *args,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mail_search_arg *arg, *thread_arg, *or_arg;
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen bool child_inthreads = FALSE, non_inthreads = FALSE;
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen for (arg = *argp; arg != NULL; arg = arg->next) {
2b9e49e4e65e3e2dca38f56971029a3051ccdb99Timo Sirainen /* children converted to SEARCH_INTHREADs */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (!parent_inthreads || !child_inthreads || !non_inthreads)
2b9e49e4e65e3e2dca38f56971029a3051ccdb99Timo Sirainen /* put all non-INTHREADs under a single INTHREAD */
2b9e49e4e65e3e2dca38f56971029a3051ccdb99Timo Sirainen thread_arg = p_new(args->pool, struct mail_search_arg, 1);
2b9e49e4e65e3e2dca38f56971029a3051ccdb99Timo Sirainen /* not an INTHREAD or a SUB/OR with only INTHREADs */
2b9e49e4e65e3e2dca38f56971029a3051ccdb99Timo Sirainen /* We want to OR the args */
2b9e49e4e65e3e2dca38f56971029a3051ccdb99Timo Sirainen or_arg = p_new(args->pool, struct mail_search_arg, 1);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen or_arg->value.subargs = thread_arg->value.subargs;
438f12d7a776da695019114884b48188d94613efTimo Sirainenvoid mail_search_args_simplify(struct mail_search_args *args)
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen removals = mail_search_args_simplify_sub(args->box, args->args, TRUE);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (mail_search_args_unnest_inthreads(args, &args->args,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* we may have added some extra SUBs that could be dropped */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mail_search_args_simplify_sub(args->box, args->args, TRUE);