/* search_query.h -- search query routines
*
* Copyright (c) 1994-2018 Carnegie Mellon University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "Carnegie Mellon University" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For permission or any legal
* details, please contact
* Carnegie Mellon University
* Center for Technology Transfer and Enterprise Creation
* 4615 Forbes Avenue
* Suite 302
* Pittsburgh, PA 15213
* (412) 268-7393, fax: (412) 268-7395
* innovation@andrew.cmu.edu
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Computing Services
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __CYRUS_SEARCH_RESULT_H__
#define __CYRUS_SEARCH_RESULT_H__
#include "mailbox.h"
#include "message.h"
#include "conversations.h"
#include "util.h"
#include "bitvector.h"
#include "ptrarray.h"
#include "dynarray.h"
#include "search_engines.h"
struct sortcrit; /* imapd.h */
struct searchargs; /* imapd.h */
typedef struct search_subquery search_subquery_t;
typedef struct search_query search_query_t;
typedef struct search_folder search_folder_t;
struct search_folder_partnum {
uint32_t uid;
uint32_t partnum;
};
struct search_folder {
char *mboxname;
uint32_t uidvalidity;
uint64_t highest_modseq; /* of returned messages, not the folder */
uint64_t first_modseq; /* of returned messages, not the folder */
uint64_t last_modseq; /* of returned messages, not the folder */
int id;
bitvector_t uids;
bitvector_t found_uids;
int found_dirty;
dynarray_t partnums; /* list of struct search_folder_partnum */
};
struct search_subquery {
char *mboxname; /* may be NULL */
search_expr_t *indexed; /* may be NULL */
search_expr_t *expr;
};
struct search_saved_msgdata {
/* Used to remember MsgData** arrays returned by
* index_msgdata_load() for later freeing. */
struct msgdata **msgdata;
int n;
};
struct search_query {
/*
* A query may report results from multiple folders, but we need
* this one specific folder to tell us the username to limit the
* search engine scope. Also, for most IMAP search commands we
* start with a selected folder anyway so we need to avoid
* double-opening it.
*/
struct index_state *state;
int (*checkfolder)(const char *mboxname, void *rock);
void *checkfolderrock;
/*
* Input parameters of the query. Set these after
* search_query_new() and before search_query_run().
*/
struct searchargs *searchargs;
const struct sortcrit *sortcrit;
int multiple;
int need_ids;
int want_expunged;
uint32_t want_mbtype;
int verbose;
int ignore_timer;
int attachments_in_any;
int want_partids;
/*
* A query comprises multiple sub-queries logically ORed together.
* The sub-queries are organised by the first of three criteria
* which might apply:
*
* - subs_by_indexed: one or more indexed match nodes (need to scan
* all messages reported by a given search engine lookup)
*
* - subs_by_folder: a single positive folder match node (need to
* scan all messages in a given folder)
*
* - global_sub: neither indexed nor folder (need to scan all
* messages in many folders)
*/
hash_table subs_by_indexed;
unsigned int indexed_count;
hash_table subs_by_folder;
unsigned int folder_count;
search_subquery_t global_sub;
/* Used as a temporary holder for errors, e.g. to pass an error from
* a hashtable enumeration callback back up to the caller */
int error;
/*
* Resulting messages from a search engine query or a folder scan
* need to be organised per-folder both for the secondary scan
* (which needs to proceed per-folder to minimise the number of
* index_open() calls) and for reporting back to the IMAP client.
*/
hash_table folders_by_name;
/*
* Some callers need a unique and contiguous 0-based set of integer
* ids for folders which have any results. Note that the
* folders_by_name hash table may contain folders with no results in
* them, e.g. when the search engine returns hits for a folder which
* all subsequently prove to be deleted.
*/
ptrarray_t folders_by_id;
/*
* Array of search_saved_msgdata objects for later freeing
*/
ptrarray_t saved_msgdata;
/*
* When sorting in requested, this array contains the final merged
* sort results as an array of MsgData*. The MsgData objects might
* be "fake" ones if the results were retrieved from the cache DB,
* but the following fields are guaranteed to be usable: uid, cid,
* folder, guid.
*/
ptrarray_t merged_msgdata;
/* A map from string message part ids to a unique numeric
* identifier. This allows to save good chunk of string mallocs */
hashu64_table partid_by_num;
hash_table partnum_by_id;
uint32_t partnum_seq;
};
extern search_query_t *search_query_new(struct index_state *state,
struct searchargs *);
extern int search_query_run(search_query_t *query);
extern void search_query_free(search_query_t *query);
extern search_folder_t *search_query_find_folder(search_query_t *query,
const char *mboxname);
extern void search_folder_use_msn(search_folder_t *, struct index_state *);
extern seqset_t *search_folder_get_seqset(const search_folder_t *);
extern int search_folder_get_array(const search_folder_t *, unsigned int **);
extern uint32_t search_folder_get_min(const search_folder_t *);
extern uint32_t search_folder_get_max(const search_folder_t *);
extern unsigned int search_folder_get_count(const search_folder_t *);
#define search_folder_foreach(folder, u) \
for ((u) = bv_next_set(&(folder)->uids, 0) ; \
(u) != -1 ; \
(u) = bv_next_set(&(folder)->uids, (u)+1))
extern uint64_t search_folder_get_highest_modseq(const search_folder_t *);
extern uint64_t search_folder_get_first_modseq(const search_folder_t *);
extern uint64_t search_folder_get_last_modseq(const search_folder_t *);
extern void search_build_query(search_builder_t *bx, search_expr_t *e);
extern int search_is_mutable(struct sortcrit *sortcrit, search_expr_t *e);
#endif /* __CYRUS_SEARCH_RESULT_H__ */