* add query flags (which match msgiterflags) to mu_query_run, update callers

This commit is contained in:
djcb 2012-12-16 15:08:34 +02:00
parent 8fdd82d549
commit 2f9dd78bb0
10 changed files with 100 additions and 63 deletions

View File

@ -432,8 +432,8 @@ get_query_iter (MuQuery *query, const char* expr, int maxnum)
GError *err; GError *err;
err = NULL; err = NULL;
iter = mu_query_run (query, expr, iter = mu_query_run (query, expr, MU_MSG_FIELD_ID_NONE, maxnum,
FALSE, MU_MSG_FIELD_ID_NONE, TRUE, maxnum, &err); MU_QUERY_FLAG_NONE, &err);
if (!iter) { if (!iter) {
mu_guile_g_error ("<internal error>", err); mu_guile_g_error ("<internal error>", err);
g_clear_error (&err); g_clear_error (&err);

View File

@ -312,7 +312,7 @@ mu_container_from_list (GSList *lst)
struct _SortFuncData { struct _SortFuncData {
MuMsgFieldId mfid; MuMsgFieldId mfid;
gboolean revert; gboolean descending;
gpointer user_data; gpointer user_data;
}; };
typedef struct _SortFuncData SortFuncData; typedef struct _SortFuncData SortFuncData;
@ -335,7 +335,7 @@ sort_func_wrapper (MuContainer *a, MuContainer *b, SortFuncData *data)
else if (!b1->msg) else if (!b1->msg)
return -1; return -1;
if (data->revert) if (data->descending)
return mu_msg_cmp (b1->msg, a1->msg, data->mfid); return mu_msg_cmp (b1->msg, a1->msg, data->mfid);
else else
return mu_msg_cmp (a1->msg, b1->msg, data->mfid); return mu_msg_cmp (a1->msg, b1->msg, data->mfid);
@ -367,14 +367,14 @@ container_sort_real (MuContainer *c, SortFuncData *sfdata)
MuContainer* MuContainer*
mu_container_sort (MuContainer *c, MuMsgFieldId mfid, gboolean revert, mu_container_sort (MuContainer *c, MuMsgFieldId mfid, gboolean descending,
gpointer user_data) gpointer user_data)
{ {
SortFuncData sfdata; SortFuncData sfdata;
sfdata.mfid = mfid; sfdata.mfid = mfid;
sfdata.revert = revert; sfdata.descending = descending;
sfdata.user_data = user_data; sfdata.user_data = user_data;
g_return_val_if_fail (c, NULL); g_return_val_if_fail (c, NULL);
g_return_val_if_fail (mu_msg_field_id_is_valid(mfid), NULL); g_return_val_if_fail (mu_msg_field_id_is_valid(mfid), NULL);

View File

@ -342,38 +342,38 @@ mu_query_preprocess (const char *query, GError **err)
* exception is raised. We try to reopen the database, and run the * exception is raised. We try to reopen the database, and run the
* query again. */ * query again. */
static MuMsgIter * static MuMsgIter *
try_requery (MuQuery *self, const char* searchexpr, gboolean threads, try_requery (MuQuery *self, const char* searchexpr, MuMsgFieldId sortfieldid,
MuMsgFieldId sortfieldid, gboolean revert, int maxnum, int maxnum, MuQueryFlags flags, GError **err)
GError **err)
{ {
try { try {
/* let's assume that infinite regression is /* let's assume that infinite regression is
* impossible */ * impossible */
self->db().reopen(); self->db().reopen();
MU_WRITE_LOG ("reopening db after modification"); MU_WRITE_LOG ("reopening db after modification");
return mu_query_run (self, searchexpr, threads, sortfieldid, return mu_query_run (self, searchexpr, sortfieldid,
revert, maxnum, err); maxnum, flags, err);
} MU_XAPIAN_CATCH_BLOCK_G_ERROR_RETURN (err, MU_ERROR_XAPIAN, 0); } MU_XAPIAN_CATCH_BLOCK_G_ERROR_RETURN (err, MU_ERROR_XAPIAN, 0);
} }
static Xapian::Enquire static Xapian::Enquire
get_enquire (MuQuery *self, const char *searchexpr, gboolean threads, get_enquire (MuQuery *self, const char *searchexpr, MuMsgFieldId sortfieldid,
MuMsgFieldId sortfieldid, gboolean revert, GError **err) MuQueryFlags flags, GError **err)
{ {
Xapian::Enquire enq (self->db()); Xapian::Enquire enq (self->db());
if (sortfieldid != MU_MSG_FIELD_ID_NONE) if (sortfieldid != MU_MSG_FIELD_ID_NONE)
enq.set_sort_by_value ((Xapian::valueno)sortfieldid, enq.set_sort_by_value
revert ? true : false); ((Xapian::valueno)sortfieldid,
(flags & MU_QUERY_FLAG_DESCENDING) ? true : false);
/* empty or "" means "matchall" */ /* empty or "" means "matchall" */
if (!mu_str_is_empty(searchexpr) && if (!mu_str_is_empty(searchexpr) &&
g_strcmp0 (searchexpr, "\"\"") != 0) /* NULL or "" or """" */ g_strcmp0 (searchexpr, "\"\"") != 0) /* NULL or "" or """" */
enq.set_query(get_query (self, searchexpr, err)); enq.set_query(get_query (self, searchexpr, err));
else else
enq.set_query(Xapian::Query::MatchAll); enq.set_query(Xapian::Query::MatchAll);
enq.set_cutoff(0,0); enq.set_cutoff(0,0);
@ -381,10 +381,29 @@ get_enquire (MuQuery *self, const char *searchexpr, gboolean threads,
} }
static MuMsgIterFlags
msg_iter_flags (MuQueryFlags flags)
{
MuMsgIterFlags iflags;
iflags = MU_MSG_ITER_FLAG_NONE;
if (flags & MU_QUERY_FLAG_THREADS)
iflags |= MU_MSG_ITER_FLAG_THREADS;
if (flags & MU_QUERY_FLAG_DESCENDING)
iflags |= MU_MSG_ITER_FLAG_DESCENDING;
if (flags & MU_QUERY_FLAG_SKIP_UNREADABLE)
iflags |= MU_MSG_ITER_FLAG_SKIP_UNREADABLE;
if (flags & MU_QUERY_FLAG_SKIP_MSGID_DUPS)
iflags |= MU_MSG_ITER_FLAG_SKIP_MSGID_DUPS;
return iflags;
}
MuMsgIter* MuMsgIter*
mu_query_run (MuQuery *self, const char* searchexpr, gboolean threads, mu_query_run (MuQuery *self, const char* searchexpr, MuMsgFieldId sortfieldid,
MuMsgFieldId sortfieldid, gboolean revert, int maxnum, int maxnum, MuQueryFlags flags, GError **err)
GError **err)
{ {
g_return_val_if_fail (self, NULL); g_return_val_if_fail (self, NULL);
g_return_val_if_fail (searchexpr, NULL); g_return_val_if_fail (searchexpr, NULL);
@ -393,16 +412,8 @@ mu_query_run (MuQuery *self, const char* searchexpr, gboolean threads,
NULL); NULL);
try { try {
MuMsgIter *iter; MuMsgIter *iter;
Xapian::Enquire enq (get_enquire(self, searchexpr, threads, Xapian::Enquire enq (get_enquire(self, searchexpr, sortfieldid, flags,
sortfieldid, revert, err)); err));
MuMsgIterFlags flags;
flags = MU_MSG_ITER_FLAG_NONE;
if (threads)
flags |= MU_MSG_ITER_FLAG_THREADS;
if (revert)
flags |= MU_MSG_ITER_FLAG_REVERT;
/* get the 'real' maxnum if it was specified as < 0 */ /* get the 'real' maxnum if it was specified as < 0 */
maxnum <= 0 ? self->db().get_doccount() : maxnum; maxnum <= 0 ? self->db().get_doccount() : maxnum;
@ -412,15 +423,14 @@ mu_query_run (MuQuery *self, const char* searchexpr, gboolean threads,
maxnum, maxnum,
/* in we were *not* using threads, no further sorting /* in we were *not* using threads, no further sorting
* is needed since Xapian already sorted */ * is needed since Xapian already sorted */
threads ? sortfieldid : MU_MSG_FIELD_ID_NONE, (flags & MU_QUERY_FLAG_THREADS) ? sortfieldid : MU_MSG_FIELD_ID_NONE,
flags, msg_iter_flags (flags),
err); err);
if (err && *err && (*err)->code == MU_ERROR_XAPIAN_MODIFIED) { if (err && *err && (*err)->code == MU_ERROR_XAPIAN_MODIFIED) {
g_clear_error (err); g_clear_error (err);
return try_requery (self, searchexpr, threads, return try_requery (self, searchexpr, sortfieldid,
sortfieldid, maxnum, flags, err);
revert, maxnum, err);
} else } else
return iter; return iter;

View File

@ -64,19 +64,28 @@ void mu_query_destroy (MuQuery *self);
char* mu_query_version (MuQuery *store) char* mu_query_version (MuQuery *store)
G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
enum _MuQueryFlags {
MU_QUERY_FLAG_NONE = 0,
MU_QUERY_FLAG_THREADS = 1 << 0, /* <** add threading info */
MU_QUERY_FLAG_DESCENDING = 1 << 1, /* <** sort z->a */
MU_QUERY_FLAG_SKIP_UNREADABLE = 1 << 2, /* <** skip unreadable msgs */
MU_QUERY_FLAG_SKIP_MSGID_DUPS = 1 << 3 /* <** skip msgid dups */
};
typedef enum _MuQueryFlags MuQueryFlags;
/** /**
* run a Xapian query; for the syntax, please refer to the mu-find * run a Xapian query; for the syntax, please refer to the mu-find
* manpage, or http://xapian.org/docs/queryparser.html * manpage, or http://xapian.org/docs/queryparser.html
* *
* @param self a valid MuQuery instance * @param self a valid MuQuery instance
* @param expr the search expression; use "" to match all messages * @param expr the search expression; use "" to match all messages
* @param threads calculate message-threads
* @param sortfield the field id to sort by or MU_MSG_FIELD_ID_NONE if * @param sortfield the field id to sort by or MU_MSG_FIELD_ID_NONE if
* sorting is not desired * sorting is not desired
* @param reverse if TRUE, sort in descending (Z-A) order, otherwise,
* sort in descending (A-Z) order
* @param maxnum maximum number of search results to return, or <= 0 for * @param maxnum maximum number of search results to return, or <= 0 for
* unlimited * unlimited
* @param flags bitwise OR'd flags to influence the query (see MuQueryFlags)
* @param err receives error information (if there is any); if * @param err receives error information (if there is any); if
* function returns non-NULL, err will _not_be set. err can be NULL * function returns non-NULL, err will _not_be set. err can be NULL
* possible error (err->code) is MU_ERROR_QUERY, * possible error (err->code) is MU_ERROR_QUERY,
@ -84,9 +93,8 @@ char* mu_query_version (MuQuery *store)
* @return a MuMsgIter instance you can iterate over, or NULL in * @return a MuMsgIter instance you can iterate over, or NULL in
* case of error * case of error
*/ */
MuMsgIter* mu_query_run (MuQuery *self, const char* expr, gboolean threads, MuMsgIter* mu_query_run (MuQuery *self, const char* expr, MuMsgFieldId sortfieldid, int maxnum,
MuMsgFieldId sortfieldid, gboolean ascending, int maxnum, MuQueryFlags flags, GError **err)
GError **err)
G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;

View File

@ -59,7 +59,7 @@ GHashTable* create_doc_id_thread_path_hash (MuContainer *root,
* http://www.jwz.org/doc/threading.html */ * http://www.jwz.org/doc/threading.html */
GHashTable* GHashTable*
mu_threader_calculate (MuMsgIter *iter, size_t matchnum, mu_threader_calculate (MuMsgIter *iter, size_t matchnum,
MuMsgFieldId sortfield, gboolean revert) MuMsgFieldId sortfield, gboolean descending)
{ {
GHashTable *id_table, *thread_ids; GHashTable *id_table, *thread_ids;
MuContainer *root_set; MuContainer *root_set;
@ -82,7 +82,7 @@ mu_threader_calculate (MuMsgIter *iter, size_t matchnum,
/* sort root set */ /* sort root set */
if (sortfield != MU_MSG_FIELD_ID_NONE) if (sortfield != MU_MSG_FIELD_ID_NONE)
root_set = mu_container_sort (root_set, sortfield, revert, root_set = mu_container_sort (root_set, sortfield, descending,
NULL); NULL);
/* step 5: group root set by subject */ /* step 5: group root set by subject */

View File

@ -113,6 +113,7 @@ run_query (MuQuery *xapian, const gchar *query, MuConfig *opts, GError **err)
{ {
MuMsgIter *iter; MuMsgIter *iter;
MuMsgFieldId sortid; MuMsgFieldId sortid;
MuQueryFlags qflags;
sortid = MU_MSG_FIELD_ID_NONE; sortid = MU_MSG_FIELD_ID_NONE;
if (opts->sortfield) { if (opts->sortfield) {
@ -121,8 +122,13 @@ run_query (MuQuery *xapian, const gchar *query, MuConfig *opts, GError **err)
return FALSE; return FALSE;
} }
iter = mu_query_run (xapian, query, opts->threads, sortid, qflags = MU_QUERY_FLAG_NONE;
opts->reverse, -1, err); if (opts->threads)
qflags |= MU_QUERY_FLAG_THREADS;
if (opts->reverse)
qflags |= MU_QUERY_FLAG_DESCENDING;
iter = mu_query_run (xapian, query, sortid, -1, qflags, err);
return iter; return iter;
} }

View File

@ -266,8 +266,9 @@ get_docid_from_msgid (MuQuery *query, const char *str, GError **err)
MuMsgIter *iter; MuMsgIter *iter;
querystr = g_strdup_printf ("msgid:%s", str); querystr = g_strdup_printf ("msgid:%s", str);
iter = mu_query_run (query, querystr, FALSE, iter = mu_query_run (query, querystr,
MU_MSG_FIELD_ID_NONE, FALSE, 1, err); MU_MSG_FIELD_ID_NONE,
1, MU_QUERY_FLAG_NONE, err);
g_free (querystr); g_free (querystr);
docid = MU_STORE_INVALID_DOCID; docid = MU_STORE_INVALID_DOCID;
@ -300,8 +301,8 @@ get_docids_from_msgids (MuQuery *query, const char *str, GError **err)
GSList *lst; GSList *lst;
querystr = g_strdup_printf ("msgid:%s", str); querystr = g_strdup_printf ("msgid:%s", str);
iter = mu_query_run (query, querystr, FALSE, iter = mu_query_run (query, querystr, MU_MSG_FIELD_ID_NONE,
MU_MSG_FIELD_ID_NONE, FALSE,-1 /*unlimited*/, -1 /*unlimited*/, MU_QUERY_FLAG_NONE,
err); err);
g_free (querystr); g_free (querystr);
@ -889,6 +890,7 @@ cmd_find (ServerContext *ctx, GSList *args, GError **err)
gboolean threads, reverse; gboolean threads, reverse;
MuMsgFieldId sortfield; MuMsgFieldId sortfield;
const char *querystr; const char *querystr;
MuQueryFlags qflags;
GET_STRING_OR_ERROR_RETURN (args, "query", &querystr, err); GET_STRING_OR_ERROR_RETURN (args, "query", &querystr, err);
if (get_find_params (args, &threads, &sortfield, if (get_find_params (args, &threads, &sortfield,
@ -900,9 +902,14 @@ cmd_find (ServerContext *ctx, GSList *args, GError **err)
/* note: when we're threading, we get *all* matching messages, /* note: when we're threading, we get *all* matching messages,
* and then only return maxnum; this is so that we maximimize * and then only return maxnum; this is so that we maximimize
* the change of all messages in a thread showing up */ * the change of all messages in a thread showing up */
iter = mu_query_run (ctx->query, querystr, threads, qflags = MU_QUERY_FLAG_NONE;
sortfield, reverse, if (threads)
threads ? -1 : maxnum, err); qflags |= MU_QUERY_FLAG_THREADS;
if (reverse)
qflags |= MU_QUERY_FLAG_DESCENDING;
iter = mu_query_run (ctx->query, querystr, sortfield,
threads ? -1 : maxnum, qflags, err);
if (!iter) { if (!iter) {
print_and_clear_g_error (err); print_and_clear_g_error (err);
return MU_OK; return MU_OK;

View File

@ -130,8 +130,8 @@ run_and_count_matches (const char *xpath, const char *query)
} }
iter = mu_query_run (mquery, query, FALSE, MU_MSG_FIELD_ID_NONE, iter = mu_query_run (mquery, query, MU_MSG_FIELD_ID_NONE, -1,
FALSE, -1, NULL); MU_QUERY_FLAG_NONE, NULL);
mu_query_destroy (mquery); mu_query_destroy (mquery);
g_assert (iter); g_assert (iter);
@ -295,8 +295,8 @@ test_mu_query_accented_chars_01 (void)
query = mu_query_new (store, NULL); query = mu_query_new (store, NULL);
mu_store_unref (store); mu_store_unref (store);
iter = mu_query_run (query, "fünkÿ", FALSE, MU_MSG_FIELD_ID_NONE, iter = mu_query_run (query, "fünkÿ", MU_MSG_FIELD_ID_NONE,
FALSE, -1, NULL); -1, MU_QUERY_FLAG_NONE, NULL);
err = NULL; err = NULL;
msg = mu_msg_iter_get_msg_floating (iter); /* don't unref */ msg = mu_msg_iter_get_msg_floating (iter); /* don't unref */
if (!msg) { if (!msg) {

View File

@ -70,8 +70,8 @@ run_and_get_iter (const char *xpath, const char *query)
mu_store_unref (store); mu_store_unref (store);
g_assert (query); g_assert (query);
iter = mu_query_run (mquery, query, TRUE, MU_MSG_FIELD_ID_DATE, iter = mu_query_run (mquery, query, MU_MSG_FIELD_ID_DATE,
FALSE, -1, NULL); -1, MU_QUERY_FLAG_THREADS, NULL);
mu_query_destroy (mquery); mu_query_destroy (mquery);
g_assert (iter); g_assert (iter);

View File

@ -327,6 +327,7 @@ run_query (const char *xpath, const char *query, MugMsgListView * self)
MuQuery *xapian; MuQuery *xapian;
MuMsgIter *iter; MuMsgIter *iter;
MuStore *store; MuStore *store;
MuQueryFlags qflags;
err = NULL; err = NULL;
if (! (store = mu_store_new_read_only (xpath, &err)) || if (! (store = mu_store_new_read_only (xpath, &err)) ||
@ -342,8 +343,13 @@ run_query (const char *xpath, const char *query, MugMsgListView * self)
} }
mu_store_unref (store); mu_store_unref (store);
iter = mu_query_run (xapian, query, TRUE, MU_MSG_FIELD_ID_DATE, qflags = MU_QUERY_FLAG_THREADS |
TRUE, -1, &err); MU_QUERY_FLAG_DESCENDING |
MU_QUERY_FLAG_SKIP_UNREADABLE |
MU_QUERY_FLAG_SKIP_MSGID_DUPS;
iter = mu_query_run (xapian, query, MU_MSG_FIELD_ID_DATE,
-1, qflags, &err);
mu_query_destroy (xapian); mu_query_destroy (xapian);
if (!iter) { if (!iter) {
g_warning ("Error: %s", err->message); g_warning ("Error: %s", err->message);