]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Search code cleanups and minor optimizations.
authorTimo Sirainen <tss@iki.fi>
Fri, 20 Jun 2008 02:35:05 +0000 (05:35 +0300)
committerTimo Sirainen <tss@iki.fi>
Fri, 20 Jun 2008 02:35:05 +0000 (05:35 +0300)
--HG--
branch : HEAD

src/lib-storage/index/index-search.c
src/lib-storage/mail-search.c
src/lib-storage/mail-search.h
src/lib-storage/mail-storage.c

index c1856322cafafd9db22b42ff0aa2cd3d3f5b471e..416807f4fe463dff9b36539f373e2d6125e590cc 100644 (file)
@@ -688,17 +688,23 @@ static void search_or_parse_msgset_args(const struct mail_index_header *hdr,
        for (; args != NULL; args = args->next) {
                seq1 = 1; seq2 = hdr->messages_count;
 
-               if (args->type == SEARCH_SUB) {
+               switch (args->type) {
+               case SEARCH_SUB:
                        i_assert(!args->not);
                        search_parse_msgset_args(hdr, args->value.subargs,
                                                 &seq1, &seq2);
-               } else if (args->type == SEARCH_OR) {
+                       break;
+               case SEARCH_OR:
                        i_assert(!args->not);
                        search_or_parse_msgset_args(hdr, args->value.subargs,
                                                    &seq1, &seq2);
-               } else if (args->type == SEARCH_SEQSET) {
+                       break;
+               case SEARCH_SEQSET:
                        search_msgset_fix(hdr, &args->value.seqset,
                                          &seq1, &seq2, args->not);
+                       break;
+               default:
+                       break;
                }
 
                if (min_seq1 == 0) {
@@ -724,19 +730,25 @@ static void search_parse_msgset_args(const struct mail_index_header *hdr,
                                     uint32_t *seq1_r, uint32_t *seq2_r)
 {
        for (; args != NULL; args = args->next) {
-               if (args->type == SEARCH_SUB) {
+               switch (args->type) {
+               case SEARCH_SUB:
                        i_assert(!args->not);
                        search_parse_msgset_args(hdr, args->value.subargs,
                                                 seq1_r, seq2_r);
-               } else if (args->type == SEARCH_OR) {
+                       break;
+               case SEARCH_OR:
                        /* go through our children and use the widest seqset
                           range */
                        i_assert(!args->not);
                        search_or_parse_msgset_args(hdr, args->value.subargs,
                                                    seq1_r, seq2_r);
-               } else if (args->type == SEARCH_SEQSET) {
+                       break;
+               case SEARCH_SEQSET:
                        search_msgset_fix(hdr, &args->value.seqset,
                                          seq1_r, seq2_r, args->not);
+                       break;
+               default:
+                       break;
                }
        }
 }
@@ -983,7 +995,9 @@ static bool search_arg_is_static(struct mail_search_arg *arg)
                                return FALSE;
                }
                return TRUE;
-       case SEARCH_SEQSET: /* changes between syncs */
+       case SEARCH_SEQSET:
+               /* changes between syncs, but we can't really handle this
+                  currently. seqsets should be converted to uidsets first. */
        case SEARCH_FLAGS:
        case SEARCH_KEYWORDS:
        case SEARCH_MODSEQ:
index e5ee628ec36b269238c53e444620194d7f9c5a20..532e2078c1ba568b7de9b7a4ac4741f68a0da6a5 100644 (file)
@@ -56,36 +56,38 @@ mailbox_uidset_change(struct mail_search_arg *arg, struct mailbox *box,
 }
 
 static void
-mail_search_args_init_sub(struct mail_search_arg *args,
-                         struct mailbox *box, bool change_uidsets,
+mail_search_args_init_sub(struct mail_search_args *args,
+                         struct mail_search_arg *arg,
+                         bool change_uidsets,
                          const ARRAY_TYPE(seq_range) *search_saved_uidset)
 {
        const char *keywords[2];
 
-       for (; args != NULL; args = args->next) {
-               switch (args->type) {
+       for (; arg != NULL; arg = arg->next) {
+               switch (arg->type) {
                case SEARCH_UIDSET:
                        if (change_uidsets) T_BEGIN {
-                               mailbox_uidset_change(args, box,
+                               mailbox_uidset_change(arg, args->box,
                                                      search_saved_uidset);
                        } T_END;
                        break;
                case SEARCH_MODSEQ:
-                       if (args->value.str == NULL)
+                       if (arg->value.str == NULL)
                                break;
                        /* modseq with keyword */
                case SEARCH_KEYWORDS:
-                       keywords[0] = args->value.str;
+                       keywords[0] = arg->value.str;
                        keywords[1] = NULL;
 
-                       i_assert(args->value.keywords == NULL);
-                       args->value.keywords =
-                               mailbox_keywords_create_valid(box, keywords);
+                       i_assert(arg->value.keywords == NULL);
+                       arg->value.keywords =
+                               mailbox_keywords_create_valid(args->box,
+                                                             keywords);
                        break;
 
                case SEARCH_SUB:
                case SEARCH_OR:
-                       mail_search_args_init_sub(args->value.subargs, box,
+                       mail_search_args_init_sub(args, arg->value.subargs,
                                                  change_uidsets,
                                                  search_saved_uidset);
                        break;
@@ -99,8 +101,15 @@ void mail_search_args_init(struct mail_search_args *args,
                           struct mailbox *box, bool change_uidsets,
                           const ARRAY_TYPE(seq_range) *search_saved_uidset)
 {
+       if (args->initialized) {
+               i_assert(args->box == box);
+               return;
+       }
+
        args->box = box;
-       mail_search_args_init_sub(args->args, box, change_uidsets,
+       if (!args->simplified)
+               mail_search_args_simplify(args);
+       mail_search_args_init_sub(args, args->args, change_uidsets,
                                  search_saved_uidset);
 }
 
@@ -127,10 +136,12 @@ static void mail_search_args_deinit_sub(struct mail_search_args *args,
 
 void mail_search_args_deinit(struct mail_search_args *args)
 {
-       if (args->refcount > 1)
+       if (args->refcount > 1 || !args->initialized)
                return;
 
        mail_search_args_deinit_sub(args, args->args);
+       args->initialized = FALSE;
+       args->box = NULL;
 }
 
 static void mail_search_args_seq2uid_sub(struct mail_search_args *args,
@@ -407,7 +418,7 @@ mail_search_args_simplify_sub(struct mail_search_arg *args, bool parent_and)
 
        prev_flags_arg = prev_not_flags_arg = NULL;
        prev_kw_arg = prev_not_kw_arg = NULL;
-       for (; args != NULL;) {
+       while (args != NULL) {
                if (args->not && (args->type == SEARCH_SUB ||
                                  args->type == SEARCH_OR)) {
                        /* neg(p and q and ..) == neg(p) or neg(q) or ..
@@ -421,9 +432,12 @@ mail_search_args_simplify_sub(struct mail_search_arg *args, bool parent_and)
                }
 
                if ((args->type == SEARCH_SUB && parent_and) ||
-                   (args->type == SEARCH_OR && !parent_and)) {
+                   (args->type == SEARCH_OR && !parent_and) ||
+                   ((args->type == SEARCH_SUB || args->type == SEARCH_OR) &&
+                    args->value.subargs->next == NULL)) {
                        /* p and (q and ..) == p and q and ..
-                          p or (q or ..) == p or q or .. */
+                          p or (q or ..) == p or q or ..
+                          (p) = p */
                        sub = args->value.subargs;
                        for (; sub->next != NULL; sub = sub->next) ;
                        sub->next = args->next;
@@ -493,7 +507,8 @@ mail_search_args_simplify_sub(struct mail_search_arg *args, bool parent_and)
        }
 }
 
-void mail_search_args_simplify(struct mail_search_arg *args)
+void mail_search_args_simplify(struct mail_search_args *args)
 {
-       mail_search_args_simplify_sub(args, TRUE);
+       args->simplified = TRUE;
+       mail_search_args_simplify_sub(args->args, TRUE);
 }
index 639eea97b12fbfcca92bcbae1cc61cc6036c3274..8cccb03308fc8a2f127f244423361add9185e91a 100644 (file)
@@ -91,6 +91,10 @@ struct mail_search_args {
        struct mailbox *box;
        struct mail_search_arg *args;
        const char *charset;
+
+       unsigned int initialized:1;
+       unsigned int simplified:1;
+       unsigned int have_inthreads:1;
 };
 
 #define ARG_SET_RESULT(arg, res) \
@@ -142,8 +146,7 @@ const char *const *
 mail_search_args_analyze(struct mail_search_arg *args,
                         bool *have_headers, bool *have_body);
 
-/* 1) Change args so that SEARCH_SUB and SEARCH_OR will never have "not" set
-   2) Drop unnecessary nested SEARCH_SUB and SEARCH_ORs */
-void mail_search_args_simplify(struct mail_search_arg *args);
+/* Simplify/optimize search arguments */
+void mail_search_args_simplify(struct mail_search_args *args);
 
 #endif
index d5bee42b5246557f4190c5d772bd340689efc21a..d0587927ecefea45f8dc0ed464371997eb9df6db 100644 (file)
@@ -643,7 +643,8 @@ mailbox_search_init(struct mailbox_transaction_context *t,
                    const enum mail_sort_type *sort_program)
 {
        mail_search_args_ref(args);
-       mail_search_args_simplify(args->args);
+       if (!args->simplified)
+               mail_search_args_simplify(args);
        return t->box->v.search_init(t, args, sort_program);
 }