fts-backend-solr.c revision 1e60d516e91238b41c951009729f5703eca49211
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (c) 2006-2015 Dovecot authors, see the included COPYING file */
22627da0fb77c1d0d9a8e8bc485ef5540b6f2e69Timo Sirainen#define SOLR_CMDBUF_FLUSH_SIZE (SOLR_CMDBUF_SIZE-128)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen/* If header is larger than this, truncate it. */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen/* If SOLR_HEADER_MAX_SIZE was already reached, write still to individual
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen header fields as long as they're smaller than this */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* Valid characters in XML:
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] |
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen [#x10000-#x10FFFF]
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen This function gets called only for #x80 and higher */
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenstatic unsigned int
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenxml_encode_data_max(string_t *dest, const unsigned char *data, unsigned int len,
892b3cbf0eba9ba455448adcf71864a409345c6dTimo Sirainen unsigned int max_len)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen unsigned int i;
892b3cbf0eba9ba455448adcf71864a409345c6dTimo Sirainen for (i = 0; i < max_len; i++) {
892b3cbf0eba9ba455448adcf71864a409345c6dTimo Sirainen switch (data[i]) {
d16b506f5540e3407d256bda35624b38a5ecf88fTimo Sirainen /* exceptions to the following control char check */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* SOLR doesn't like control characters.
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen replace them with spaces. */
a54fa00087ba926a3d966a8449d8d7579e89911cTimo Sirainen /* make sure the character is valid for XML
a54fa00087ba926a3d966a8449d8d7579e89911cTimo Sirainen so we don't get XML parser errors */
a54fa00087ba926a3d966a8449d8d7579e89911cTimo Sirainen unsigned int char_len =
a54fa00087ba926a3d966a8449d8d7579e89911cTimo Sirainen uni_utf8_get_char_n(data + i, char_len, &chr) == 1 &&
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenxml_encode_data(string_t *dest, const unsigned char *data, unsigned int len)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen (void)xml_encode_data_max(dest, data, len, len);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic void xml_encode(string_t *dest, const char *str)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen xml_encode_data(dest, (const unsigned char *)str, strlen(str));
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic void solr_quote_http(string_t *dest, const char *str)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic struct fts_backend *fts_backend_solr_alloc(void)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenfts_backend_solr_init(struct fts_backend *_backend, const char **error_r)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct solr_fts_backend *backend = (struct solr_fts_backend *)_backend;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct fts_solr_user *fuser = FTS_SOLR_USER_CONTEXT(_backend->ns->user);
d16b506f5540e3407d256bda35624b38a5ecf88fTimo Sirainen /* change our flags so we get proper input */
d16b506f5540e3407d256bda35624b38a5ecf88fTimo Sirainen _backend->flags &= ~FTS_BACKEND_FLAG_FUZZY_SEARCH;
d16b506f5540e3407d256bda35624b38a5ecf88fTimo Sirainen _backend->flags |= FTS_BACKEND_FLAG_TOKENIZED_INPUT;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen return solr_connection_init(fuser->set.url, fuser->set.debug,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic void fts_backend_solr_deinit(struct fts_backend *_backend)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct solr_fts_backend *backend = (struct solr_fts_backend *)_backend;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenget_last_uid_fallback(struct fts_backend *_backend, struct mailbox *box,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct solr_fts_backend *backend = (struct solr_fts_backend *)_backend;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen unsigned int count;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen str_append(str, "fl=uid&rows=1&sort=uid+desc&q=");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen solr_quote_http(str, _backend->ns->owner->username);
944a12ae4f453cc3f8a25f1e9047a5094fdfe828Timo Sirainen pool = pool_alloconly_create("solr last uid lookup", 1024);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (solr_connection_select(backend->solr_conn, str_c(str),
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* no UIDs */
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen uidvals = array_get(&results[0]->uids, &count);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (count == 1 && uidvals[0].seq1 == uidvals[0].seq2) {
d16b506f5540e3407d256bda35624b38a5ecf88fTimo Sirainen i_error("fts_solr: Last UID lookup returned multiple rows");
5fe06fea9fee0f5e4e9cb49f6866877223f78b85Timo Sirainenfts_backend_solr_get_last_uid(struct fts_backend *_backend,
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainen /* either nothing has been indexed, or the index was corrupted.
ccffb125d94adff0ad776de5a96e22f864d6fb0aTimo Sirainen do it the slow way. */
ccffb125d94adff0ad776de5a96e22f864d6fb0aTimo Sirainen if (get_last_uid_fallback(_backend, box, last_uid_r) < 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenfts_backend_solr_update_init(struct fts_backend *_backend)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ctx = i_new(struct solr_fts_backend_update_context, 1);
e958a3c4573058f17999f0083a34080ca35e34d8Timo Sirainen (_backend->flags & FTS_BACKEND_FLAG_TOKENIZED_INPUT) != 0;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic void xml_encode_id(struct solr_fts_backend_update_context *ctx,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen str_printfa(str, "%u/%s", uid, ctx->box_guid);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen xml_encode(str, ctx->ctx.backend->ns->owner->username);
a1aaf11831cab8346d6d0dc702e37b3f1d95eb43Timo Sirainenfts_backend_solr_doc_open(struct solr_fts_backend_update_context *ctx,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen "<field name=\"uid\">%u</field>"
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen "<field name=\"box\">%s</field>",
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen str_append(ctx->cmd, "<field name=\"user\">");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen xml_encode(ctx->cmd, ctx->ctx.backend->ns->owner->username);
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainenfts_solr_field_get(struct solr_fts_backend_update_context *ctx, const char *key)
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen /* there are only a few fields. this lookup is fast enough. */
68f0dfb4b2815ecbc1bd8d8a68adcfd577ec55aeTimo Sirainenfts_backend_solr_doc_close(struct solr_fts_backend_update_context *ctx)
68f0dfb4b2815ecbc1bd8d8a68adcfd577ec55aeTimo Sirainen array_foreach_modifiable(&ctx->fields, field) {
68f0dfb4b2815ecbc1bd8d8a68adcfd577ec55aeTimo Sirainen str_printfa(ctx->cmd, "<field name=\"%s\">", field->key);
68f0dfb4b2815ecbc1bd8d8a68adcfd577ec55aeTimo Sirainen xml_encode_data(ctx->cmd, str_data(field->value), str_len(field->value));
892b3cbf0eba9ba455448adcf71864a409345c6dTimo Sirainenfts_backed_solr_build_commit(struct solr_fts_backend_update_context *ctx)
e958a3c4573058f17999f0083a34080ca35e34d8Timo Sirainen solr_connection_post_more(ctx->post, str_data(ctx->cmd),
68f0dfb4b2815ecbc1bd8d8a68adcfd577ec55aeTimo Sirainenfts_backend_solr_expunge_flush(struct solr_fts_backend_update_context *ctx)
68f0dfb4b2815ecbc1bd8d8a68adcfd577ec55aeTimo Sirainen (void)solr_connection_post(backend->solr_conn, str_c(ctx->cmd_expunge));
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenfts_backend_solr_update_deinit(struct fts_backend_update_context *_ctx)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen (struct solr_fts_backend_update_context *)_ctx;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const char *str;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* commit and wait until the documents we just indexed are
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen visible to the following search */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen str = t_strdup_printf("<commit softCommit=\"true\" waitSearcher=\"%s\"/>",
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (solr_connection_post(backend->solr_conn, str) < 0)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen array_foreach_modifiable(&ctx->fields, field) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenfts_backend_solr_update_set_mailbox(struct fts_backend_update_context *_ctx,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen (struct solr_fts_backend_update_context *)_ctx;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen fts_index_set_last_uid(ctx->cur_box, ctx->prev_uid);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen i_assert(strlen(box_guid) == sizeof(ctx->box_guid)-1);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen memcpy(ctx->box_guid, box_guid, sizeof(ctx->box_guid)-1);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen memset(ctx->box_guid, 0, sizeof(ctx->box_guid));
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenfts_backend_solr_update_expunge(struct fts_backend_update_context *_ctx,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen (struct solr_fts_backend_update_context *)_ctx;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (!fts_index_get_header(ctx->cur_box, &hdr))
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* don't waste time asking Solr to expunge a message that is
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen highly unlikely to be indexed at this time. */
61dca057fe86fd5ae57f5106f8f049b7287d78cdTimo Sirainen ctx->cmd_expunge = str_new(default_pool, 1024);
61dca057fe86fd5ae57f5106f8f049b7287d78cdTimo Sirainen if (str_len(ctx->cmd_expunge) >= SOLR_CMDBUF_FLUSH_SIZE)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenfts_backend_solr_uid_changed(struct solr_fts_backend_update_context *ctx,
1412a091183dc0e5d6ea4f403a5cd4f4cd5c7301Timo Sirainen ctx->cmd = str_new(default_pool, SOLR_CMDBUF_SIZE);
1412a091183dc0e5d6ea4f403a5cd4f4cd5c7301Timo Sirainen ctx->post = solr_connection_post_begin(backend->solr_conn);
1412a091183dc0e5d6ea4f403a5cd4f4cd5c7301Timo Sirainenfts_backend_solr_update_set_build_key(struct fts_backend_update_context *_ctx,
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen (struct solr_fts_backend_update_context *)_ctx;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* fall through */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ctx->cur_value = fts_solr_field_get(ctx, "hdr");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen str_append(ctx->cmd, "<field name=\"body\">");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenfts_backend_solr_update_unset_build_key(struct fts_backend_update_context *_ctx)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen (struct solr_fts_backend_update_context *)_ctx;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* There can be multiple duplicate keys (duplicate header lines,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen multiple MIME body parts). Make sure they are separated by
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen whitespace. */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenfts_backend_solr_update_build_more(struct fts_backend_update_context *_ctx,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen (struct solr_fts_backend_update_context *)_ctx;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen unsigned int len;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (ctx->cur_value2 == NULL && ctx->cur_value == ctx->cmd) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* we're writing to message body. if size is huge,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen flush it once in a while */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (str_len(ctx->cmd) >= SOLR_CMDBUF_FLUSH_SIZE) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen len = xml_encode_data_max(ctx->cmd, data, size,
c9343c25215e98880db8f9e9c5f120f6311bc06dTimo Sirainen str_len(ctx->cur_value2) < SOLR_HEADER_LINE_MAX_TRUNC_SIZE)) {
68f0dfb4b2815ecbc1bd8d8a68adcfd577ec55aeTimo Sirainen if (str_len(ctx->cmd) >= SOLR_CMDBUF_FLUSH_SIZE) {
68f0dfb4b2815ecbc1bd8d8a68adcfd577ec55aeTimo Sirainen solr_connection_post_more(ctx->post, str_data(ctx->cmd),
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen str_len(ctx->cur_value) >= SOLR_HEADER_MAX_SIZE) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* a large header */
68f0dfb4b2815ecbc1bd8d8a68adcfd577ec55aeTimo Sirainen i_warning("fts-solr(%s): Mailbox %s UID=%u header size is huge, truncating",
68f0dfb4b2815ecbc1bd8d8a68adcfd577ec55aeTimo Sirainen mailbox_get_vname(ctx->cur_box), ctx->prev_uid);
68f0dfb4b2815ecbc1bd8d8a68adcfd577ec55aeTimo Sirainenstatic int fts_backend_solr_refresh(struct fts_backend *backend ATTR_UNUSED)
68f0dfb4b2815ecbc1bd8d8a68adcfd577ec55aeTimo Sirainenstatic int fts_backend_solr_rescan(struct fts_backend *backend)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* FIXME: proper rescan needed. for now we'll just reset the
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic int fts_backend_solr_optimize(struct fts_backend *backend ATTR_UNUSED)
68f0dfb4b2815ecbc1bd8d8a68adcfd577ec55aeTimo Sirainenstatic bool solr_need_escaping(const char *str)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const char *solr_escape_chars = "+-&|!(){}[]^\"~*?:\\ ";
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenstatic void solr_add_str_arg(string_t *str, struct mail_search_arg *arg)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen /* currently we'll just disable fuzzy searching if there are any
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen parameters that need escaping. solr doesn't seem to give good
1285518f4f8905f22f5812d022a9f75b51752ed4Timo Sirainen fuzzy results even if we did escape them.. */
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen if (!arg->fuzzy || solr_need_escaping(arg->value.str))
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainensolr_add_definite_query(string_t *str, struct mail_search_arg *arg)
892b3cbf0eba9ba455448adcf71864a409345c6dTimo Sirainen if (!fts_header_want_indexed(arg->hdr_field_name))
840a3701b7a0f7fadd17738998c33790a8dfad2dTimo Sirainen str_append(str, t_str_lcase(arg->hdr_field_name));
5fe06fea9fee0f5e4e9cb49f6866877223f78b85Timo Sirainensolr_add_definite_query_args(string_t *str, struct mail_search_arg *arg,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainensolr_add_maybe_query(string_t *str, struct mail_search_arg *arg)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (fts_header_want_indexed(arg->hdr_field_name))
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* all matches would be definite, but all non-matches
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen would be maybies. too much trouble to optimize. */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* we can check if the search key exists in some header and
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen filter out the messages that have no chance of matching */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* checking potential existence of the header name */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen solr_quote_http(str, t_str_lcase(arg->hdr_field_name));
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainensolr_add_maybe_query_args(string_t *str, struct mail_search_arg *arg,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic int solr_search(struct fts_backend *_backend, string_t *str,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const char *box_guid, ARRAY_TYPE(seq_range) *uids_r,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct solr_fts_backend *backend = (struct solr_fts_backend *)_backend;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen pool_t pool = pool_alloconly_create("fts solr search", 1024);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* use a separate filter query for selecting the mailbox. it shouldn't
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen affect the score and there could be some caching benefits too. */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen str_printfa(str, "&fq=%%2Bbox:%s+%%2Buser:", box_guid);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen solr_quote_http(str, _backend->ns->owner->username);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ret = solr_connection_select(backend->solr_conn, str_c(str),
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen array_append_array(uids_r, &results[0]->uids);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen array_append_array(scores_r, &results[0]->scores);
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainenfts_backend_solr_lookup(struct fts_backend *_backend, struct mailbox *box,
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen bool and_args = (flags & FTS_LOOKUP_FLAG_AND_ARGS) != 0;
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen mailbox_get_open_status(box, STATUS_UIDNEXT, &status);
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen str_printfa(str, "fl=uid,score&rows=%u&sort=uid+asc&q=",
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen if (solr_add_definite_query_args(str, args, and_args)) {
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen (flags & FTS_LOOKUP_FLAG_NO_AUTO_FUZZY) == 0 ?
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (solr_add_maybe_query_args(str, args, and_args)) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainensolr_search_multi(struct fts_backend *_backend, string_t *str,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct mailbox *const boxes[], enum fts_lookup_flags flags,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen struct solr_fts_backend *backend = (struct solr_fts_backend *)_backend;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen HASH_TABLE(char *, struct mailbox *) mailboxes;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen unsigned int i, len;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* use a separate filter query for selecting the mailbox. it shouldn't
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen affect the score and there could be some caching benefits too. */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen solr_quote_http(str, _backend->ns->owner->username);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen hash_table_create(&mailboxes, default_pool, 0, str_hash, strcmp);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (fts_mailbox_get_guid(boxes[i], &box_guid) < 0)
9672bb2a11c37c275d695451accd824da5c9e485Timo Sirainen hash_table_insert(mailboxes, t_strdup_noconst(box_guid),
9672bb2a11c37c275d695451accd824da5c9e485Timo Sirainen if (solr_connection_select(backend->solr_conn, str_c(str),
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen box = hash_table_lookup(mailboxes, solr_results[i]->box_id);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen i_warning("fts_solr: Lookup returned unexpected mailbox "
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen fts_result = array_append_space(&fts_results);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen if ((flags & FTS_LOOKUP_FLAG_NO_AUTO_FUZZY) == 0)
9c2b0eb659540b9db8dd3a8a6a2515921fbe8eebTimo Sirainen fts_result->definite_uids = solr_results[i]->uids;
892b3cbf0eba9ba455448adcf71864a409345c6dTimo Sirainen fts_result->maybe_uids = solr_results[i]->uids;
9c2b0eb659540b9db8dd3a8a6a2515921fbe8eebTimo Sirainen result->box_results = array_idx_modifiable(&fts_results, 0);
9c2b0eb659540b9db8dd3a8a6a2515921fbe8eebTimo Sirainenfts_backend_solr_lookup_multi(struct fts_backend *backend,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen bool and_args = (flags & FTS_LOOKUP_FLAG_AND_ARGS) != 0;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen str_printfa(str, "fl=box,uid,score&rows=%u&sort=box+asc,uid+asc&q=",
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen if (solr_add_definite_query_args(str, args, and_args)) {
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen if (solr_search_multi(backend, str, boxes, flags, result) < 0)
892b3cbf0eba9ba455448adcf71864a409345c6dTimo Sirainen /* FIXME: maybe_uids could be handled also with some more work.. */