mirror of https://github.com/djcb/mu.git
* use GError to convey error info in MuQuery; update users
This commit is contained in:
parent
21c01f156d
commit
b87b5d25fd
|
@ -36,6 +36,7 @@
|
||||||
#include "mu-util.h"
|
#include "mu-util.h"
|
||||||
#include "mu-util-db.h"
|
#include "mu-util-db.h"
|
||||||
#include "mu-str.h"
|
#include "mu-str.h"
|
||||||
|
#include "mu-result.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* custom parser for date ranges
|
* custom parser for date ranges
|
||||||
|
@ -179,23 +180,26 @@ uninit_mu_query (MuQuery *mqx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static Xapian::Query
|
static bool
|
||||||
get_query (MuQuery * mqx, const char* searchexpr, int *err = 0) {
|
set_query (MuQuery *mqx, Xapian::Query& q, const char* searchexpr,
|
||||||
|
GError **err) {
|
||||||
try {
|
try {
|
||||||
return mqx->_qparser->parse_query
|
q = mqx->_qparser->parse_query
|
||||||
(searchexpr,
|
(searchexpr,
|
||||||
Xapian::QueryParser::FLAG_BOOLEAN |
|
Xapian::QueryParser::FLAG_BOOLEAN |
|
||||||
Xapian::QueryParser::FLAG_PURE_NOT |
|
Xapian::QueryParser::FLAG_PURE_NOT |
|
||||||
Xapian::QueryParser::FLAG_AUTO_SYNONYMS |
|
Xapian::QueryParser::FLAG_AUTO_SYNONYMS |
|
||||||
Xapian::QueryParser::FLAG_BOOLEAN_ANY_CASE);
|
Xapian::QueryParser::FLAG_BOOLEAN_ANY_CASE);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
} MU_XAPIAN_CATCH_BLOCK;
|
} MU_XAPIAN_CATCH_BLOCK;
|
||||||
|
|
||||||
if (err)
|
/* some error occured */
|
||||||
*err = 1;
|
g_set_error (err, 0, MU_ERROR_QUERY, "parse error in query '%s'",
|
||||||
|
searchexpr);
|
||||||
|
|
||||||
return Xapian::Query();
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -231,32 +235,34 @@ add_prefix (MuMsgFieldId mfid, Xapian::QueryParser* qparser)
|
||||||
}
|
}
|
||||||
|
|
||||||
MuQuery*
|
MuQuery*
|
||||||
mu_query_new (const char* xpath)
|
mu_query_new (const char* xpath, GError **err)
|
||||||
{
|
{
|
||||||
MuQuery *mqx;
|
MuQuery *mqx;
|
||||||
|
|
||||||
g_return_val_if_fail (xpath, NULL);
|
g_return_val_if_fail (xpath, NULL);
|
||||||
|
|
||||||
if (!mu_util_check_dir (xpath, TRUE, FALSE)) {
|
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;
|
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)) {
|
if (!mu_util_db_version_up_to_date (xpath)) {
|
||||||
g_warning ("%s is not up-to-date, needs a full update",
|
g_set_error (err, 0, MU_ERROR_XAPIAN_NOT_UPTODATE,
|
||||||
xpath);
|
"%s is not up-to-date, needs a full update",
|
||||||
|
xpath);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mu_util_db_is_empty (xpath))
|
||||||
|
g_warning ("database %s is empty; nothing to do", xpath);
|
||||||
|
|
||||||
mqx = g_new (MuQuery, 1);
|
mqx = g_new (MuQuery, 1);
|
||||||
|
|
||||||
if (!init_mu_query (mqx, xpath)) {
|
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);
|
g_free (mqx);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -373,7 +379,7 @@ mu_query_preprocess (const char *query)
|
||||||
MuMsgIter*
|
MuMsgIter*
|
||||||
mu_query_run (MuQuery *self, const char* searchexpr,
|
mu_query_run (MuQuery *self, const char* searchexpr,
|
||||||
MuMsgFieldId sortfieldid, gboolean ascending,
|
MuMsgFieldId sortfieldid, gboolean ascending,
|
||||||
size_t batchsize)
|
size_t batchsize, 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);
|
||||||
|
@ -381,14 +387,12 @@ mu_query_run (MuQuery *self, const char* searchexpr,
|
||||||
sortfieldid == MU_MSG_FIELD_ID_NONE,
|
sortfieldid == MU_MSG_FIELD_ID_NONE,
|
||||||
NULL);
|
NULL);
|
||||||
try {
|
try {
|
||||||
|
Xapian::Query query;
|
||||||
char *preprocessed;
|
char *preprocessed;
|
||||||
int err (0);
|
|
||||||
|
|
||||||
preprocessed = mu_query_preprocess (searchexpr);
|
preprocessed = mu_query_preprocess (searchexpr);
|
||||||
|
|
||||||
Xapian::Query q(get_query(self, preprocessed, &err));
|
if (!set_query(self, query, preprocessed, err)) {
|
||||||
if (err) {
|
|
||||||
g_warning ("Error in query '%s'", preprocessed);
|
|
||||||
g_free (preprocessed);
|
g_free (preprocessed);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -402,9 +406,8 @@ mu_query_run (MuQuery *self, const char* searchexpr,
|
||||||
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 ((Xapian::valueno)sortfieldid,
|
||||||
ascending ? true : false);
|
ascending ? true : false);
|
||||||
enq.set_query(q);
|
enq.set_query(query);
|
||||||
enq.set_cutoff(0,0);
|
enq.set_cutoff(0,0);
|
||||||
|
|
||||||
|
|
||||||
return mu_msg_iter_new (enq, batchsize);
|
return mu_msg_iter_new (enq, batchsize);
|
||||||
|
|
||||||
|
@ -412,24 +415,24 @@ mu_query_run (MuQuery *self, const char* searchexpr,
|
||||||
}
|
}
|
||||||
|
|
||||||
char*
|
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 (self, NULL);
|
||||||
g_return_val_if_fail (searchexpr, NULL);
|
g_return_val_if_fail (searchexpr, NULL);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
Xapian::Query query;
|
||||||
char *preprocessed;
|
char *preprocessed;
|
||||||
int err (0);
|
|
||||||
|
|
||||||
preprocessed = mu_query_preprocess (searchexpr);
|
preprocessed = mu_query_preprocess (searchexpr);
|
||||||
|
|
||||||
Xapian::Query q(get_query(self, preprocessed, &err));
|
if (!set_query(self, query, preprocessed, err)) {
|
||||||
if (err)
|
g_free (preprocessed);
|
||||||
g_warning ("Error in query '%s'", preprocessed);
|
return NULL;
|
||||||
|
}
|
||||||
g_free (preprocessed);
|
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);
|
} MU_XAPIAN_CATCH_BLOCK_RETURN(NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,14 +31,15 @@ typedef struct _MuQuery MuQuery;
|
||||||
/**
|
/**
|
||||||
* create a new MuQuery instance.
|
* create a new MuQuery instance.
|
||||||
*
|
*
|
||||||
* @param path path to the xapian db to search
|
* @param path path to the xapian db to search
|
||||||
* @param err receives error information (if there is any)
|
* @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.
|
* @return a new MuQuery instance, or NULL in case of error.
|
||||||
* when the instance is no longer needed, use mu_query_destroy
|
* when the instance is no longer needed, use mu_query_destroy
|
||||||
* to free it
|
* 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
|
* 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.
|
* 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
|
* If you pass '0' as the batchsize, mu will use the maximum size (the count
|
||||||
* of documents in the database)
|
* 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
|
* @return a MuMsgIter instance you can iterate over, or NULL in
|
||||||
* case of error
|
* case of error
|
||||||
|
@ -79,19 +82,22 @@ MuMsgIter* mu_query_run (MuQuery *self,
|
||||||
const char* expr,
|
const char* expr,
|
||||||
MuMsgFieldId sortfieldid,
|
MuMsgFieldId sortfieldid,
|
||||||
gboolean ascending,
|
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
|
* get a string representation of the Xapian search query
|
||||||
*
|
*
|
||||||
* @param self a MuQuery instance
|
* @param self a MuQuery instance
|
||||||
* @param searchexpr a xapian search expression
|
* @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
|
* @return the string representation of the xapian query, or NULL in case of
|
||||||
* error; free the returned value with g_free
|
* error; free the returned value with g_free
|
||||||
*/
|
*/
|
||||||
char* mu_query_as_string (MuQuery *self,
|
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
|
* pre-process the query; this function is useful mainly for debugging mu
|
||||||
|
|
|
@ -23,7 +23,16 @@
|
||||||
enum _MuResult {
|
enum _MuResult {
|
||||||
MU_OK, /* all went ok */
|
MU_OK, /* all went ok */
|
||||||
MU_STOP, /* user wants to stop */
|
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 */
|
MU_ERROR /* some error occured */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
typedef enum _MuResult MuResult;
|
typedef enum _MuResult MuResult;
|
||||||
|
|
||||||
|
|
|
@ -64,11 +64,11 @@ run_and_count_matches (const char *xpath, const char *query)
|
||||||
MuMsgIter *iter;
|
MuMsgIter *iter;
|
||||||
guint count;
|
guint count;
|
||||||
|
|
||||||
mquery = mu_query_new (xpath);
|
mquery = mu_query_new (xpath, NULL);
|
||||||
g_assert (query);
|
g_assert (query);
|
||||||
|
|
||||||
iter = mu_query_run (mquery, query, MU_MSG_FIELD_ID_NONE,
|
iter = mu_query_run (mquery, query, MU_MSG_FIELD_ID_NONE,
|
||||||
FALSE, 1);
|
FALSE, 1, NULL);
|
||||||
mu_query_destroy (mquery);
|
mu_query_destroy (mquery);
|
||||||
g_assert (iter);
|
g_assert (iter);
|
||||||
|
|
||||||
|
@ -213,11 +213,11 @@ test_mu_query_05 (void)
|
||||||
xpath = fill_database ();
|
xpath = fill_database ();
|
||||||
g_assert (xpath != NULL);
|
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,
|
iter = mu_query_run (query, "fünkÿ", MU_MSG_FIELD_ID_NONE,
|
||||||
FALSE, 1);
|
FALSE, 1, NULL);
|
||||||
msg = mu_msg_iter_get_msg (iter);
|
msg = mu_msg_iter_get_msg (iter);
|
||||||
|
|
||||||
g_assert_cmpstr (mu_msg_get_subject(msg),==,
|
g_assert_cmpstr (mu_msg_get_subject(msg),==,
|
||||||
"Greetings from Lothlórien");
|
"Greetings from Lothlórien");
|
||||||
g_assert_cmpstr (mu_msg_get_summary(msg,5),==,
|
g_assert_cmpstr (mu_msg_get_summary(msg,5),==,
|
||||||
|
|
|
@ -311,21 +311,25 @@ empty_or_display_contact (const gchar* str)
|
||||||
static MuMsgIter *
|
static MuMsgIter *
|
||||||
run_query (const char *xpath, const char *query)
|
run_query (const char *xpath, const char *query)
|
||||||
{
|
{
|
||||||
|
GError *err;
|
||||||
MuQuery *xapian;
|
MuQuery *xapian;
|
||||||
MuMsgIter *iter;
|
MuMsgIter *iter;
|
||||||
|
|
||||||
xapian = mu_query_new (xpath);
|
err = NULL;
|
||||||
|
xapian = mu_query_new (xpath, &err);
|
||||||
if (!xapian) {
|
if (!xapian) {
|
||||||
g_printerr ("Failed to create a Xapian query\n");
|
g_warning ("Error: %s", err->message);
|
||||||
|
g_error_free (err);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
iter = mu_query_run (xapian, query,
|
iter = mu_query_run (xapian, query,
|
||||||
MU_MSG_FIELD_ID_DATE,
|
MU_MSG_FIELD_ID_DATE,
|
||||||
TRUE, 0);
|
TRUE, 0, &err);
|
||||||
mu_query_destroy (xapian);
|
mu_query_destroy (xapian);
|
||||||
if (!iter) {
|
if (!iter) {
|
||||||
g_warning ("error: running query failed\n");
|
g_warning ("Error: %s", err->message);
|
||||||
|
g_error_free (err);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue