diff --git a/src/mu-query.cc b/src/mu-query.cc index 2f65d702..242dbc79 100644 --- a/src/mu-query.cc +++ b/src/mu-query.cc @@ -36,6 +36,7 @@ #include "mu-util.h" #include "mu-util-db.h" #include "mu-str.h" +#include "mu-result.h" /* * custom parser for date ranges @@ -179,23 +180,26 @@ uninit_mu_query (MuQuery *mqx) } -static Xapian::Query -get_query (MuQuery * mqx, const char* searchexpr, int *err = 0) { - +static bool +set_query (MuQuery *mqx, Xapian::Query& q, const char* searchexpr, + GError **err) { try { - return mqx->_qparser->parse_query + q = mqx->_qparser->parse_query (searchexpr, Xapian::QueryParser::FLAG_BOOLEAN | Xapian::QueryParser::FLAG_PURE_NOT | Xapian::QueryParser::FLAG_AUTO_SYNONYMS | Xapian::QueryParser::FLAG_BOOLEAN_ANY_CASE); + + return true; } MU_XAPIAN_CATCH_BLOCK; - if (err) - *err = 1; + /* some error occured */ + g_set_error (err, 0, MU_ERROR_QUERY, "parse error in query '%s'", + searchexpr); - return Xapian::Query(); + return false; } static void @@ -231,32 +235,34 @@ add_prefix (MuMsgFieldId mfid, Xapian::QueryParser* qparser) } MuQuery* -mu_query_new (const char* xpath) +mu_query_new (const char* xpath, GError **err) { MuQuery *mqx; g_return_val_if_fail (xpath, NULL); if (!mu_util_check_dir (xpath, TRUE, FALSE)) { - g_warning ("'%s' is not a readable xapian dir", xpath); + g_set_error (err, 0, MU_ERROR_XAPIAN_DIR, + "'%s' is not a readable xapian dir", xpath); return NULL; } - if (mu_util_db_is_empty (xpath)) { - g_warning ("database %s is empty; nothing to do", xpath); - return NULL; - } - + if (!mu_util_db_version_up_to_date (xpath)) { - g_warning ("%s is not up-to-date, needs a full update", - xpath); + g_set_error (err, 0, MU_ERROR_XAPIAN_NOT_UPTODATE, + "%s is not up-to-date, needs a full update", + xpath); return NULL; } + + if (mu_util_db_is_empty (xpath)) + g_warning ("database %s is empty; nothing to do", xpath); mqx = g_new (MuQuery, 1); if (!init_mu_query (mqx, xpath)) { - g_critical ("failed to initialize the Xapian query object"); + g_set_error (err, 0, MU_ERROR_INTERNAL, + "failed to initialize the Xapian query object"); g_free (mqx); return NULL; } @@ -373,7 +379,7 @@ mu_query_preprocess (const char *query) MuMsgIter* mu_query_run (MuQuery *self, const char* searchexpr, MuMsgFieldId sortfieldid, gboolean ascending, - size_t batchsize) + size_t batchsize, GError **err) { g_return_val_if_fail (self, NULL); g_return_val_if_fail (searchexpr, NULL); @@ -381,14 +387,12 @@ mu_query_run (MuQuery *self, const char* searchexpr, sortfieldid == MU_MSG_FIELD_ID_NONE, NULL); try { + Xapian::Query query; char *preprocessed; - int err (0); - + preprocessed = mu_query_preprocess (searchexpr); - Xapian::Query q(get_query(self, preprocessed, &err)); - if (err) { - g_warning ("Error in query '%s'", preprocessed); + if (!set_query(self, query, preprocessed, err)) { g_free (preprocessed); return NULL; } @@ -402,9 +406,8 @@ mu_query_run (MuQuery *self, const char* searchexpr, if (sortfieldid != MU_MSG_FIELD_ID_NONE) enq.set_sort_by_value ((Xapian::valueno)sortfieldid, ascending ? true : false); - enq.set_query(q); + enq.set_query(query); enq.set_cutoff(0,0); - return mu_msg_iter_new (enq, batchsize); @@ -412,24 +415,24 @@ mu_query_run (MuQuery *self, const char* searchexpr, } char* -mu_query_as_string (MuQuery *self, const char *searchexpr) +mu_query_as_string (MuQuery *self, const char *searchexpr, GError **err) { g_return_val_if_fail (self, NULL); g_return_val_if_fail (searchexpr, NULL); try { + Xapian::Query query; char *preprocessed; - int err (0); preprocessed = mu_query_preprocess (searchexpr); - Xapian::Query q(get_query(self, preprocessed, &err)); - if (err) - g_warning ("Error in query '%s'", preprocessed); - + if (!set_query(self, query, preprocessed, err)) { + g_free (preprocessed); + return NULL; + } g_free (preprocessed); - return err ? NULL : g_strdup(q.get_description().c_str()); + return g_strdup(query.get_description().c_str()); } MU_XAPIAN_CATCH_BLOCK_RETURN(NULL); } diff --git a/src/mu-query.h b/src/mu-query.h index 4f853304..925c618a 100644 --- a/src/mu-query.h +++ b/src/mu-query.h @@ -31,14 +31,15 @@ typedef struct _MuQuery MuQuery; /** * create a new MuQuery instance. * - * @param path path to the xapian db to search - * @param err receives error information (if there is any) - * + * @param path path to the xapian db to search + * @param err receives error information (if there is any); if + * function returns non-NULL, err will _not_be set. err can be NULL + * * @return a new MuQuery instance, or NULL in case of error. * when the instance is no longer needed, use mu_query_destroy * to free it */ -MuQuery *mu_query_new (const char* path) G_GNUC_WARN_UNUSED_RESULT; +MuQuery *mu_query_new (const char* path, GError **err) G_GNUC_WARN_UNUSED_RESULT; /** * destroy the MuQuery instance @@ -71,6 +72,8 @@ char* mu_query_version (MuQuery *store) G_GNUC_WARN_UNUSED_RESULT; * reasons - it's best to get the size one wants to show the user at once. * If you pass '0' as the batchsize, mu will use the maximum size (the count * of documents in the database) + * @param err receives error information (if there is any); if + * function returns non-NULL, err will _not_be set. err can be NULL * * @return a MuMsgIter instance you can iterate over, or NULL in * case of error @@ -79,19 +82,22 @@ MuMsgIter* mu_query_run (MuQuery *self, const char* expr, MuMsgFieldId sortfieldid, gboolean ascending, - size_t batchsize) G_GNUC_WARN_UNUSED_RESULT; + size_t batchsize, + GError **err) G_GNUC_WARN_UNUSED_RESULT; /** * get a string representation of the Xapian search query * * @param self a MuQuery instance * @param searchexpr a xapian search expression + * @param err receives error information (if there is any); if + * function returns non-NULL, err will _not_be set. err can be NULL * * @return the string representation of the xapian query, or NULL in case of * error; free the returned value with g_free */ char* mu_query_as_string (MuQuery *self, - const char* searchexpr) G_GNUC_WARN_UNUSED_RESULT; + const char* searchexpr, GError **err) G_GNUC_WARN_UNUSED_RESULT; /** * pre-process the query; this function is useful mainly for debugging mu diff --git a/src/mu-result.h b/src/mu-result.h index 51ffa3d1..a9b88a58 100644 --- a/src/mu-result.h +++ b/src/mu-result.h @@ -23,7 +23,16 @@ enum _MuResult { MU_OK, /* all went ok */ MU_STOP, /* user wants to stop */ + + MU_ERROR_XAPIAN_DIR, + MU_ERROR_XAPIAN_NOT_UPTODATE, + MU_ERROR_QUERY, + MU_ERROR_INTERNAL, + MU_ERROR /* some error occured */ + + + }; typedef enum _MuResult MuResult; diff --git a/src/tests/test-mu-query.c b/src/tests/test-mu-query.c index 1cebc052..bdbd35ba 100644 --- a/src/tests/test-mu-query.c +++ b/src/tests/test-mu-query.c @@ -64,11 +64,11 @@ run_and_count_matches (const char *xpath, const char *query) MuMsgIter *iter; guint count; - mquery = mu_query_new (xpath); + mquery = mu_query_new (xpath, NULL); g_assert (query); iter = mu_query_run (mquery, query, MU_MSG_FIELD_ID_NONE, - FALSE, 1); + FALSE, 1, NULL); mu_query_destroy (mquery); g_assert (iter); @@ -213,11 +213,11 @@ test_mu_query_05 (void) xpath = fill_database (); g_assert (xpath != NULL); - query = mu_query_new (xpath); + query = mu_query_new (xpath, NULL); iter = mu_query_run (query, "fünkÿ", MU_MSG_FIELD_ID_NONE, - FALSE, 1); + FALSE, 1, NULL); msg = mu_msg_iter_get_msg (iter); - + g_assert_cmpstr (mu_msg_get_subject(msg),==, "Greetings from Lothlórien"); g_assert_cmpstr (mu_msg_get_summary(msg,5),==, diff --git a/toys/mug/mug-msg-list-view.c b/toys/mug/mug-msg-list-view.c index b8823f9f..798eab2c 100644 --- a/toys/mug/mug-msg-list-view.c +++ b/toys/mug/mug-msg-list-view.c @@ -311,21 +311,25 @@ empty_or_display_contact (const gchar* str) static MuMsgIter * run_query (const char *xpath, const char *query) { + GError *err; MuQuery *xapian; MuMsgIter *iter; - xapian = mu_query_new (xpath); + err = NULL; + xapian = mu_query_new (xpath, &err); if (!xapian) { - g_printerr ("Failed to create a Xapian query\n"); + g_warning ("Error: %s", err->message); + g_error_free (err); return NULL; } iter = mu_query_run (xapian, query, MU_MSG_FIELD_ID_DATE, - TRUE, 0); + TRUE, 0, &err); mu_query_destroy (xapian); if (!iter) { - g_warning ("error: running query failed\n"); + g_warning ("Error: %s", err->message); + g_error_free (err); return NULL; }