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) {
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;
}
}
}
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:
}
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;
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);
}
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,
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 ..
}
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;
}
}
-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);
}
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) \
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