fts-search-args.c revision f784d5bb8edbec88829524135cfa100129f5384d
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny/* Copyright (c) 2015-2017 Dovecot authors, see the included COPYING file */
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny#include "lib.h"
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny#include "array.h"
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny#include "mail-namespace.h"
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny#include "mail-search.h"
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny#include "fts-api-private.h"
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny#include "fts-tokenizer.h"
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny#include "fts-filter.h"
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny#include "fts-user.h"
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny#include "fts-search-args.h"
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny
f26c954658dfd7461f290f0b5d924951a6db219aJan Zelenystatic void strings_deduplicate(ARRAY_TYPE(const_string) *arr)
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny{
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny const char *const *strings;
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny unsigned int i, count;
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny strings = array_get(arr, &count);
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny for (i = 1; i < count; ) {
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny if (strcmp(strings[i-1], strings[i]) == 0) {
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny array_delete(arr, i, 1);
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny strings = array_get(arr, &count);
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny } else {
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny i++;
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny }
3ee411625aee19afda7477bb10b52c3da378b6fbPetr Čech }
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny}
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny
58d02e0d3d6d48c97fccdb2ad7212e065671ad6dStephen Gallagherstatic struct mail_search_arg *
fae99bfe4bfc8b4a12e9c2a0ad01b3684c22f934Simo Sorcefts_search_arg_create_or(const struct mail_search_arg *orig_arg, pool_t pool,
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny const ARRAY_TYPE(const_string) *tokens)
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny{
d81d8d3dc151ebc95cd0e3f3b14c1cdaa48980f1Sumit Bose struct mail_search_arg *arg, *or_arg, **argp;
d81d8d3dc151ebc95cd0e3f3b14c1cdaa48980f1Sumit Bose const char *const *tokenp;
d81d8d3dc151ebc95cd0e3f3b14c1cdaa48980f1Sumit Bose
c03214d427ea43e7bf8255ccc79faa905c89f7f6Jakub Hrozek /* create the OR arg first as the parent */
d81d8d3dc151ebc95cd0e3f3b14c1cdaa48980f1Sumit Bose or_arg = p_new(pool, struct mail_search_arg, 1);
d81d8d3dc151ebc95cd0e3f3b14c1cdaa48980f1Sumit Bose or_arg->type = SEARCH_OR;
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny /* now create all the child args for the OR */
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny argp = &or_arg->value.subargs;
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny array_foreach(tokens, tokenp) {
bfd59d1a2d0d45125e5164ef12c425690d519f61Jakub Hrozek arg = p_new(pool, struct mail_search_arg, 1);
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny *arg = *orig_arg;
108db0e3b9e06e530364ef8228634f5e3f6bd3b5Jakub Hrozek arg->match_not = FALSE; /* we copied this to the root OR */
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny arg->next = NULL;
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny arg->value.str = p_strdup(pool, *tokenp);
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny
21d485184df986e1a123f70c689517386e51a5ceMichal Zidek *argp = arg;
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny argp = &arg->next;
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny }
684d1b48b5582a1bf7812b8c3c663592dc6dfed9Pavel Březina return or_arg;
75dd4b05e1dacc76dc9d5f16be31978f84a71dc5Sumit Bose}
b56b06e199f15a8a840b36bc7cb8010e39ae761dSumit Bose
b9fbeb75e7a4f50f98d979a70a710f9221892483Lukas Slebodnikstatic int
f26c954658dfd7461f290f0b5d924951a6db219aJan Zelenyfts_backend_dovecot_expand_tokens(struct fts_filter *filter,
4a9c1047354dbe5a4ed41e5951ae623e3772e113René Genz pool_t pool,
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny struct mail_search_arg *parent_arg,
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny const struct mail_search_arg *orig_arg,
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny const char *orig_token, const char *token,
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny const char **error_r)
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny{
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny struct mail_search_arg *arg;
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny ARRAY_TYPE(const_string) tokens;
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny const char *token2, *error;
21d485184df986e1a123f70c689517386e51a5ceMichal Zidek int ret;
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny t_array_init(&tokens, 4);
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny /* first add the word exactly as it without any tokenization */
c03214d427ea43e7bf8255ccc79faa905c89f7f6Jakub Hrozek array_append(&tokens, &orig_token, 1);
c03214d427ea43e7bf8255ccc79faa905c89f7f6Jakub Hrozek /* then add it tokenized, but without filtering */
4c08db0fb0dda3d27b1184248ca5c800d7ce23f0Michal Zidek array_append(&tokens, &token, 1);
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny /* add the word filtered */
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny if (filter != NULL) {
c03214d427ea43e7bf8255ccc79faa905c89f7f6Jakub Hrozek token2 = t_strdup(token);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov ret = fts_filter_filter(filter, &token2, &error);
15b5d885e28afcd6c3c19f900eea2a8e00c3e6d3Sumit Bose if (ret > 0) {
c03214d427ea43e7bf8255ccc79faa905c89f7f6Jakub Hrozek token2 = t_strdup(token2);
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny array_append(&tokens, &token2, 1);
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny } else if (ret < 0) {
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny *error_r = t_strdup_printf("Couldn't filter search token: %s", error);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov return -1;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov } else {
21d485184df986e1a123f70c689517386e51a5ceMichal Zidek /* The filter dropped the token, which means it was
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny never even indexed. Ignore this word entirely in the
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny search query. */
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny return 0;
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny }
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny }
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny array_sort(&tokens, i_strcmp_p);
326f4fc3125e155ee2d484fe921aafddd6b5a49dPavel Březina strings_deduplicate(&tokens);
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny arg = fts_search_arg_create_or(orig_arg, pool, &tokens);
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny arg->next = parent_arg->value.subargs;
b56b06e199f15a8a840b36bc7cb8010e39ae761dSumit Bose parent_arg->value.subargs = arg;
fdda4b659fa3be3027df91a2b053835186ec2c59Sumit Bose return 0;
b56b06e199f15a8a840b36bc7cb8010e39ae761dSumit Bose}
b56b06e199f15a8a840b36bc7cb8010e39ae761dSumit Bose
21d485184df986e1a123f70c689517386e51a5ceMichal Zidekstatic int
21d485184df986e1a123f70c689517386e51a5ceMichal Zidekfts_backend_dovecot_tokenize_lang(struct fts_user_language *user_lang,
21d485184df986e1a123f70c689517386e51a5ceMichal Zidek pool_t pool, struct mail_search_arg *or_arg,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov struct mail_search_arg *orig_arg,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov const char *orig_token, const char **error_r)
21d485184df986e1a123f70c689517386e51a5ceMichal Zidek{
21d485184df986e1a123f70c689517386e51a5ceMichal Zidek size_t orig_token_len = strlen(orig_token);
21d485184df986e1a123f70c689517386e51a5ceMichal Zidek struct mail_search_arg *and_arg;
21d485184df986e1a123f70c689517386e51a5ceMichal Zidek const char *token, *error;
21d485184df986e1a123f70c689517386e51a5ceMichal Zidek int ret;
684d1b48b5582a1bf7812b8c3c663592dc6dfed9Pavel Březina
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny /* we want all the tokens found from the string to be found, so create
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny a parent AND and place all the filtered token alternatives under
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny it */
bfd59d1a2d0d45125e5164ef12c425690d519f61Jakub Hrozek and_arg = p_new(pool, struct mail_search_arg, 1);
bfd59d1a2d0d45125e5164ef12c425690d519f61Jakub Hrozek and_arg->type = SEARCH_SUB;
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny and_arg->next = or_arg->value.subargs;
bfd59d1a2d0d45125e5164ef12c425690d519f61Jakub Hrozek or_arg->value.subargs = and_arg;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov
21d485184df986e1a123f70c689517386e51a5ceMichal Zidek /* reset tokenizer between search args in case there's any state left
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny from some previous failure */
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny fts_tokenizer_reset(user_lang->search_tokenizer);
bfd59d1a2d0d45125e5164ef12c425690d519f61Jakub Hrozek while ((ret = fts_tokenizer_next(user_lang->search_tokenizer,
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny (const void *)orig_token,
58d02e0d3d6d48c97fccdb2ad7212e065671ad6dStephen Gallagher orig_token_len, &token, &error)) > 0) {
75dd4b05e1dacc76dc9d5f16be31978f84a71dc5Sumit Bose if (fts_backend_dovecot_expand_tokens(user_lang->filter, pool,
75dd4b05e1dacc76dc9d5f16be31978f84a71dc5Sumit Bose and_arg, orig_arg, orig_token,
75dd4b05e1dacc76dc9d5f16be31978f84a71dc5Sumit Bose token, error_r) < 0)
75dd4b05e1dacc76dc9d5f16be31978f84a71dc5Sumit Bose return -1;
75dd4b05e1dacc76dc9d5f16be31978f84a71dc5Sumit Bose }
75dd4b05e1dacc76dc9d5f16be31978f84a71dc5Sumit Bose while (ret >= 0 &&
58d02e0d3d6d48c97fccdb2ad7212e065671ad6dStephen Gallagher (ret = fts_tokenizer_final(user_lang->search_tokenizer, &token, &error)) > 0) {
75dd4b05e1dacc76dc9d5f16be31978f84a71dc5Sumit Bose if (fts_backend_dovecot_expand_tokens(user_lang->filter, pool,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov and_arg, orig_arg, orig_token,
75dd4b05e1dacc76dc9d5f16be31978f84a71dc5Sumit Bose token, error_r) < 0)
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov return -1;
75dd4b05e1dacc76dc9d5f16be31978f84a71dc5Sumit Bose }
75dd4b05e1dacc76dc9d5f16be31978f84a71dc5Sumit Bose if (ret < 0) {
75dd4b05e1dacc76dc9d5f16be31978f84a71dc5Sumit Bose *error_r = t_strdup_printf("Couldn't tokenize search args: %s", error);
75dd4b05e1dacc76dc9d5f16be31978f84a71dc5Sumit Bose return -1;
58d02e0d3d6d48c97fccdb2ad7212e065671ad6dStephen Gallagher }
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov if (and_arg->value.subargs == NULL) {
58d02e0d3d6d48c97fccdb2ad7212e065671ad6dStephen Gallagher /* nothing was actually expanded, remove the empty and_arg */
58d02e0d3d6d48c97fccdb2ad7212e065671ad6dStephen Gallagher or_arg->value.subargs = NULL;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov }
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov return 0;
58d02e0d3d6d48c97fccdb2ad7212e065671ad6dStephen Gallagher}
58d02e0d3d6d48c97fccdb2ad7212e065671ad6dStephen Gallagher
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagherstatic int fts_search_arg_expand(struct fts_backend *backend, pool_t pool,
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher struct mail_search_arg **argp)
c20a339d54b39120b4051f690ca759e6d079f177Stephen Gallagher{
c20a339d54b39120b4051f690ca759e6d079f177Stephen Gallagher const ARRAY_TYPE(fts_user_language) *languages;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov struct fts_user_language *const *langp;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov struct mail_search_arg *or_arg, *orig_arg = *argp;
c20a339d54b39120b4051f690ca759e6d079f177Stephen Gallagher const char *error, *orig_token = orig_arg->value.str;
c20a339d54b39120b4051f690ca759e6d079f177Stephen Gallagher
c20a339d54b39120b4051f690ca759e6d079f177Stephen Gallagher if ((*argp)->type == SEARCH_HEADER &&
c20a339d54b39120b4051f690ca759e6d079f177Stephen Gallagher !fts_header_has_language((*argp)->hdr_field_name)) {
c20a339d54b39120b4051f690ca759e6d079f177Stephen Gallagher /* use only the data-language */
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov languages = fts_user_get_data_languages(backend->ns->user);
c20a339d54b39120b4051f690ca759e6d079f177Stephen Gallagher } else {
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov languages = fts_user_get_all_languages(backend->ns->user);
58d02e0d3d6d48c97fccdb2ad7212e065671ad6dStephen Gallagher }
58d02e0d3d6d48c97fccdb2ad7212e065671ad6dStephen Gallagher
58d02e0d3d6d48c97fccdb2ad7212e065671ad6dStephen Gallagher /* OR together all the different expansions for different languages.
58d02e0d3d6d48c97fccdb2ad7212e065671ad6dStephen Gallagher it's enough for one of them to match. */
58d02e0d3d6d48c97fccdb2ad7212e065671ad6dStephen Gallagher or_arg = p_new(pool, struct mail_search_arg, 1);
58d02e0d3d6d48c97fccdb2ad7212e065671ad6dStephen Gallagher or_arg->type = SEARCH_OR;
58d02e0d3d6d48c97fccdb2ad7212e065671ad6dStephen Gallagher or_arg->match_not = orig_arg->match_not;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov or_arg->next = orig_arg->next;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov
bfd59d1a2d0d45125e5164ef12c425690d519f61Jakub Hrozek array_foreach(languages, langp) {
4a9c1047354dbe5a4ed41e5951ae623e3772e113René Genz if (fts_backend_dovecot_tokenize_lang(*langp, pool, or_arg,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov orig_arg, orig_token, &error) < 0) {
58d02e0d3d6d48c97fccdb2ad7212e065671ad6dStephen Gallagher i_error("fts: %s", error);
58d02e0d3d6d48c97fccdb2ad7212e065671ad6dStephen Gallagher return -1;
58d02e0d3d6d48c97fccdb2ad7212e065671ad6dStephen Gallagher }
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov }
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov
21d485184df986e1a123f70c689517386e51a5ceMichal Zidek if (or_arg->value.subargs == NULL) {
58d02e0d3d6d48c97fccdb2ad7212e065671ad6dStephen Gallagher /* we couldn't parse any tokens from the input */
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny or_arg->type = SEARCH_ALL;
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny or_arg->match_not = !or_arg->match_not;
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny }
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny *argp = or_arg;
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny return 0;
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny}
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov
108db0e3b9e06e530364ef8228634f5e3f6bd3b5Jakub Hrozekstatic int
f26c954658dfd7461f290f0b5d924951a6db219aJan Zelenyfts_search_args_expand_tree(struct fts_backend *backend, pool_t pool,
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny struct mail_search_arg **argp)
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny{
1d93029624d708119bbf803e6647a2cbb271f001Sumit Bose int ret;
1d93029624d708119bbf803e6647a2cbb271f001Sumit Bose
1d93029624d708119bbf803e6647a2cbb271f001Sumit Bose for (; *argp != NULL; argp = &(*argp)->next) {
1d93029624d708119bbf803e6647a2cbb271f001Sumit Bose switch ((*argp)->type) {
1d93029624d708119bbf803e6647a2cbb271f001Sumit Bose case SEARCH_OR:
56e88cd5f3501566778b138e4934ee8e7f3fa674Lukas Slebodnik case SEARCH_SUB:
56e88cd5f3501566778b138e4934ee8e7f3fa674Lukas Slebodnik case SEARCH_INTHREAD:
56e88cd5f3501566778b138e4934ee8e7f3fa674Lukas Slebodnik if (fts_search_args_expand_tree(backend, pool,
56e88cd5f3501566778b138e4934ee8e7f3fa674Lukas Slebodnik &(*argp)->value.subargs) < 0)
56e88cd5f3501566778b138e4934ee8e7f3fa674Lukas Slebodnik return -1;
56e88cd5f3501566778b138e4934ee8e7f3fa674Lukas Slebodnik break;
108db0e3b9e06e530364ef8228634f5e3f6bd3b5Jakub Hrozek case SEARCH_HEADER:
1d93029624d708119bbf803e6647a2cbb271f001Sumit Bose case SEARCH_HEADER_ADDRESS:
108db0e3b9e06e530364ef8228634f5e3f6bd3b5Jakub Hrozek case SEARCH_HEADER_COMPRESS_LWSP:
108db0e3b9e06e530364ef8228634f5e3f6bd3b5Jakub Hrozek if ((*argp)->value.str[0] == '\0') {
108db0e3b9e06e530364ef8228634f5e3f6bd3b5Jakub Hrozek /* we're testing for the existence of
108db0e3b9e06e530364ef8228634f5e3f6bd3b5Jakub Hrozek the header */
108db0e3b9e06e530364ef8228634f5e3f6bd3b5Jakub Hrozek break;
108db0e3b9e06e530364ef8228634f5e3f6bd3b5Jakub Hrozek }
108db0e3b9e06e530364ef8228634f5e3f6bd3b5Jakub Hrozek /* fall through */
b9fbeb75e7a4f50f98d979a70a710f9221892483Lukas Slebodnik case SEARCH_BODY:
b9fbeb75e7a4f50f98d979a70a710f9221892483Lukas Slebodnik case SEARCH_TEXT:
b9fbeb75e7a4f50f98d979a70a710f9221892483Lukas Slebodnik T_BEGIN {
b9fbeb75e7a4f50f98d979a70a710f9221892483Lukas Slebodnik ret = fts_search_arg_expand(backend, pool, argp);
b9fbeb75e7a4f50f98d979a70a710f9221892483Lukas Slebodnik } T_END;
b9fbeb75e7a4f50f98d979a70a710f9221892483Lukas Slebodnik if (ret < 0)
b9fbeb75e7a4f50f98d979a70a710f9221892483Lukas Slebodnik return -1;
b9fbeb75e7a4f50f98d979a70a710f9221892483Lukas Slebodnik break;
b9fbeb75e7a4f50f98d979a70a710f9221892483Lukas Slebodnik default:
b9fbeb75e7a4f50f98d979a70a710f9221892483Lukas Slebodnik break;
b9fbeb75e7a4f50f98d979a70a710f9221892483Lukas Slebodnik }
bfd59d1a2d0d45125e5164ef12c425690d519f61Jakub Hrozek }
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov return 0;
d115f40c7a3999e3cbe705a2ff9cf0fd493f80fbMichal Zidek}
108db0e3b9e06e530364ef8228634f5e3f6bd3b5Jakub Hrozek
108db0e3b9e06e530364ef8228634f5e3f6bd3b5Jakub Hrozekint fts_search_args_expand(struct fts_backend *backend,
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny struct mail_search_args *args)
21d485184df986e1a123f70c689517386e51a5ceMichal Zidek{
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny struct mail_search_arg *args_dup, *orig_args = args->args;
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny /* don't keep re-expanding every time the search args are used.
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny this is especially important to avoid an assert-crash in
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny index_search_result_update_flags(). */
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny if (args->fts_expanded)
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov return 0;
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov args->fts_expanded = TRUE;
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny
21d485184df986e1a123f70c689517386e51a5ceMichal Zidek /* duplicate the args, so if expansion fails we haven't changed
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny anything */
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny args_dup = mail_search_arg_dup(args->pool, args->args);
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny if (fts_search_args_expand_tree(backend, args->pool, &args_dup) < 0)
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny return -1;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov
21d485184df986e1a123f70c689517386e51a5ceMichal Zidek /* we'll need to re-simplify the args if we changed anything */
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny args->simplified = FALSE;
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny args->args = args_dup;
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny mail_search_args_simplify(args);
21d485184df986e1a123f70c689517386e51a5ceMichal Zidek
21d485184df986e1a123f70c689517386e51a5ceMichal Zidek /* duplicated args aren't initialized */
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny i_assert(args->init_refcount > 0);
21d485184df986e1a123f70c689517386e51a5ceMichal Zidek mail_search_arg_init(args, args_dup, FALSE, NULL);
21d485184df986e1a123f70c689517386e51a5ceMichal Zidek mail_search_arg_deinit(orig_args);
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov return 0;
21d485184df986e1a123f70c689517386e51a5ceMichal Zidek}
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny