From b69cf8f5898d88d2de4c5827ccada7a94f578b42 Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Sat, 20 Nov 2010 14:43:04 +0200 Subject: [PATCH] * : update for mu-msg-field change --- src/mu-cmd-find.c | 39 +++--- src/mu-msg-iter.cc | 70 +++++------ src/mu-msg-iter.h | 4 +- src/mu-msg.c | 18 +-- src/mu-msg.h | 7 +- src/mu-output-link.c | 9 +- src/mu-output-plain.c | 38 +++--- src/mu-query.cc | 99 ++++++++++----- src/mu-query.h | 5 +- src/mu-store.cc | 228 ++++++++++++++++++++++------------- src/mu-store.h | 10 +- toys/mug/mug-msg-list-view.c | 3 +- 12 files changed, 306 insertions(+), 224 deletions(-) diff --git a/src/mu-cmd-find.c b/src/mu-cmd-find.c index 5beb8a22..48d5ddad 100644 --- a/src/mu-cmd-find.c +++ b/src/mu-cmd-find.c @@ -70,20 +70,23 @@ print_xapian_query (MuQuery *xapian, const gchar *query) } /* returns NULL if there is an error */ -const MuMsgField* +static MuMsgFieldId sort_field_from_string (const char* fieldstr) { - const MuMsgField *field; + MuMsgFieldId mfid; - field = mu_msg_field_from_name (fieldstr); + mfid = mu_msg_field_id_from_name (fieldstr, FALSE); - if (!field && strlen(fieldstr) == 1) - field = mu_msg_field_from_shortcut(fieldstr[0]); - - if (!field) - g_printerr ("not a valid sort field: '%s'\n", - fieldstr); - return field; + /* not found? try a shortcut */ + if (mfid == MU_MSG_FIELD_ID_NONE && + strlen(fieldstr) == 1) + mfid = mu_msg_field_id_from_shortcut(fieldstr[0], + FALSE); + + if (mfid == MU_MSG_FIELD_ID_NONE) + g_warning ("Not a valid sort field: '%s'\n", + fieldstr); + return mfid; } @@ -133,26 +136,28 @@ static gboolean run_query (MuQuery *xapian, const gchar *query, MuConfigOptions *opts) { MuMsgIter *iter; - const MuMsgField *sortfield; + MuMsgFieldId sortid; size_t matches; - sortfield = NULL; + sortid = MU_MSG_FIELD_ID_NONE; if (opts->sortfield) { - sortfield = sort_field_from_string (opts->sortfield); - if (!sortfield) /* error occured? */ + sortid = sort_field_from_string (opts->sortfield); + if (sortid == MU_MSG_FIELD_ID_NONE) /* error occured? */ return FALSE; } - iter = mu_query_run (xapian, query, sortfield, !opts->descending, 0); + iter = mu_query_run (xapian, query, sortid, !opts->descending, 0); if (!iter) { g_printerr ("error: running query failed\n"); return FALSE; } if (opts->linksdir) - matches = make_links (iter, opts->linksdir, opts->clearlinks); + matches = make_links (iter, opts->linksdir, + opts->clearlinks); else - matches = print_rows (iter, opts->fields, opts->summary_len); + matches = print_rows (iter, opts->fields, + opts->summary_len); if (matches == 0) g_printerr ("No matches found\n"); diff --git a/src/mu-msg-iter.cc b/src/mu-msg-iter.cc index ffa9d1db..cfab58e6 100644 --- a/src/mu-msg-iter.cc +++ b/src/mu-msg-iter.cc @@ -181,54 +181,50 @@ mu_msg_iter_is_done (MuMsgIter *iter) const gchar* -mu_msg_iter_get_field (MuMsgIter *iter, const MuMsgField *field) +mu_msg_iter_get_field (MuMsgIter *iter, MuMsgFieldId mfid) { - g_return_val_if_fail (field, NULL); g_return_val_if_fail (!mu_msg_iter_is_done(iter), NULL); - + g_return_val_if_fail (mu_msg_field_id_is_valid(mfid), NULL); + try { - MuMsgFieldId id; - - id = mu_msg_field_id (field); - if (!iter->_str[id]) { /* cache the value */ + if (!iter->_str[mfid]) { /* cache the value */ Xapian::Document doc (iter->_cursor.get_document()); - iter->_str[id] = g_strdup (doc.get_value(id).c_str()); + iter->_str[mfid] = + g_strdup (doc.get_value(mfid).c_str()); } - return iter->_str[id]; + return iter->_str[mfid]; } MU_XAPIAN_CATCH_BLOCK_RETURN(NULL); } gint64 -mu_msg_iter_get_field_numeric (MuMsgIter *iter, - const MuMsgField *field) +mu_msg_iter_get_field_numeric (MuMsgIter *iter, MuMsgFieldId mfid) { - g_return_val_if_fail (field, -1); g_return_val_if_fail (!mu_msg_iter_is_done(iter), -1); - g_return_val_if_fail (mu_msg_field_is_numeric(field), -1); + g_return_val_if_fail (mu_msg_field_is_numeric(mfid), -1); try { return static_cast( Xapian::sortable_unserialise( - mu_msg_iter_get_field(iter, field))); + mu_msg_iter_get_field(iter, mfid))); } MU_XAPIAN_CATCH_BLOCK_RETURN(static_cast(-1)); } -static const gchar* -get_field (MuMsgIter *iter, MuMsgFieldId id) -{ - return mu_msg_iter_get_field(iter, mu_msg_field_from_id (id)); -} +// static const gchar* +// get_field (MuMsgIter *iter, MuMsgFieldId mfid) +// { +// return mu_msg_iter_get_field(iter, mfid); +// } static long -get_field_number (MuMsgIter *iter, MuMsgFieldId id) +get_field_number (MuMsgIter *iter, MuMsgFieldId mfid) { - const char* str = get_field (iter, id); + const char* str = mu_msg_iter_get_field(iter, mfid); return str ? atol (str) : 0; } @@ -250,14 +246,14 @@ const char* mu_msg_iter_get_path (MuMsgIter *iter) { g_return_val_if_fail (!mu_msg_iter_is_done(iter), NULL); - return get_field (iter, MU_MSG_FIELD_ID_PATH); + return mu_msg_iter_get_field (iter, MU_MSG_FIELD_ID_PATH); } const char* mu_msg_iter_get_maildir (MuMsgIter *iter) { g_return_val_if_fail (!mu_msg_iter_is_done(iter), NULL); - return get_field (iter, MU_MSG_FIELD_ID_MAILDIR); + return mu_msg_iter_get_field (iter, MU_MSG_FIELD_ID_MAILDIR); } @@ -266,14 +262,14 @@ const char* mu_msg_iter_get_from (MuMsgIter *iter) { g_return_val_if_fail (!mu_msg_iter_is_done(iter), NULL); - return get_field (iter, MU_MSG_FIELD_ID_FROM); + return mu_msg_iter_get_field (iter, MU_MSG_FIELD_ID_FROM); } const char* mu_msg_iter_get_to (MuMsgIter *iter) { g_return_val_if_fail (!mu_msg_iter_is_done(iter), NULL); - return get_field (iter, MU_MSG_FIELD_ID_TO); + return mu_msg_iter_get_field (iter, MU_MSG_FIELD_ID_TO); } @@ -281,7 +277,7 @@ const char* mu_msg_iter_get_cc (MuMsgIter *iter) { g_return_val_if_fail (!mu_msg_iter_is_done(iter), NULL); - return get_field (iter, MU_MSG_FIELD_ID_CC); + return mu_msg_iter_get_field (iter, MU_MSG_FIELD_ID_CC); } @@ -289,7 +285,7 @@ const char* mu_msg_iter_get_subject (MuMsgIter *iter) { g_return_val_if_fail (!mu_msg_iter_is_done(iter), NULL); - return get_field (iter, MU_MSG_FIELD_ID_SUBJECT); + return mu_msg_iter_get_field (iter, MU_MSG_FIELD_ID_SUBJECT); } @@ -297,45 +293,39 @@ size_t mu_msg_iter_get_size (MuMsgIter *iter) { g_return_val_if_fail (!mu_msg_iter_is_done(iter), 0); - return static_cast(get_field_number (iter, MU_MSG_FIELD_ID_SIZE)); + return static_cast(get_field_number + (iter, MU_MSG_FIELD_ID_SIZE)); } time_t mu_msg_iter_get_date (MuMsgIter *iter) { - static const MuMsgField *date_field = - mu_msg_field_from_id (MU_MSG_FIELD_ID_DATE); - g_return_val_if_fail (!mu_msg_iter_is_done(iter), 0); try { return static_cast( Xapian::sortable_unserialise( - mu_msg_iter_get_field(iter, date_field))); + mu_msg_iter_get_field + (iter,MU_MSG_FIELD_ID_DATE))); + } MU_XAPIAN_CATCH_BLOCK_RETURN(0); } MuMsgFlags mu_msg_iter_get_flags (MuMsgIter *iter) { - static const MuMsgField *flags_field = - mu_msg_field_from_id (MU_MSG_FIELD_ID_FLAGS); - g_return_val_if_fail (!mu_msg_iter_is_done(iter), MU_MSG_FLAG_NONE); return static_cast(mu_msg_iter_get_field_numeric - (iter, flags_field)); + (iter, MU_MSG_FIELD_ID_FLAGS)); } MuMsgPrio mu_msg_iter_get_prio (MuMsgIter *iter) { - static const MuMsgField *prio_field = - mu_msg_field_from_id (MU_MSG_FIELD_ID_PRIO); - g_return_val_if_fail (!mu_msg_iter_is_done(iter), MU_MSG_PRIO_NONE); return static_cast(mu_msg_iter_get_field_numeric - (iter, prio_field)); + (iter, MU_MSG_FIELD_ID_PRIO)); } diff --git a/src/mu-msg-iter.h b/src/mu-msg-iter.h index cd324316..dee8fd94 100644 --- a/src/mu-msg-iter.h +++ b/src/mu-msg-iter.h @@ -198,7 +198,7 @@ MuMsgPrio mu_msg_iter_get_prio (MuMsgIter *iter); * @return the field value, or NULL */ const gchar* mu_msg_iter_get_field (MuMsgIter *iter, - const MuMsgField *field); + MuMsgFieldId mfid); /** * get some numeric message field @@ -209,7 +209,7 @@ const gchar* mu_msg_iter_get_field (MuMsgIter *iter, * @return the field value, or -1 in case of error */ gint64 mu_msg_iter_get_field_numeric (MuMsgIter *iter, - const MuMsgField *field); + MuMsgFieldId mfid); G_END_DECLS #endif /*__MU_MSG_ITER_H__*/ diff --git a/src/mu-msg.c b/src/mu-msg.c index b39da789..df548602 100644 --- a/src/mu-msg.c +++ b/src/mu-msg.c @@ -751,15 +751,11 @@ mu_msg_get_summary (MuMsg *msg, size_t max_lines) const char* -mu_msg_get_field_string (MuMsg *msg, const MuMsgField* field) +mu_msg_get_field_string (MuMsg *msg, MuMsgFieldId mfid) { - MuMsgFieldId id; - g_return_val_if_fail (msg, NULL); - id = mu_msg_field_id (field); - g_return_val_if_fail (id != MU_MSG_FIELD_ID_NONE, NULL); - switch (id) { + switch (mfid) { case MU_MSG_FIELD_ID_BODY_TEXT: return mu_msg_get_body_text (msg); case MU_MSG_FIELD_ID_BODY_HTML: return mu_msg_get_body_html (msg); case MU_MSG_FIELD_ID_CC: return mu_msg_get_cc (msg); @@ -775,15 +771,11 @@ mu_msg_get_field_string (MuMsg *msg, const MuMsgField* field) } gint64 -mu_msg_get_field_numeric (MuMsg *msg, const MuMsgField* field) +mu_msg_get_field_numeric (MuMsg *msg, const MuMsgFieldId mfid) { - MuMsgFieldId id; - g_return_val_if_fail (msg, 0); - id = mu_msg_field_id (field); - g_return_val_if_fail (id != MU_MSG_FIELD_ID_NONE, 0); - switch (id) { + switch (mfid) { case MU_MSG_FIELD_ID_DATE: return mu_msg_get_date(msg); case MU_MSG_FIELD_ID_FLAGS: @@ -793,7 +785,7 @@ mu_msg_get_field_numeric (MuMsg *msg, const MuMsgField* field) case MU_MSG_FIELD_ID_SIZE: return mu_msg_get_size(msg); default: - g_warning ("%s: %u", __FUNCTION__, (guint)id); + g_warning ("%s: %u", __FUNCTION__, mfid); g_return_val_if_reached (0); } } diff --git a/src/mu-msg.h b/src/mu-msg.h index 1eaf110f..478bc45e 100644 --- a/src/mu-msg.h +++ b/src/mu-msg.h @@ -238,8 +238,8 @@ size_t mu_msg_get_size (MuMsg *msg); * * @return a string that should not be freed */ -const char* mu_msg_get_field_string (MuMsg *msg, - const MuMsgField* field); +const char* mu_msg_get_field_string (MuMsg *msg, MuMsgFieldId mfid); + /** * get some field value as string @@ -249,8 +249,7 @@ const char* mu_msg_get_field_string (MuMsg *msg, * * @return a string that should not be freed */ -gint64 mu_msg_get_field_numeric (MuMsg *msg, - const MuMsgField* field); +gint64 mu_msg_get_field_numeric (MuMsg *msg, MuMsgFieldId mfid); /** * get the message priority for this message (MU_MSG_PRIO_LOW, diff --git a/src/mu-output-link.c b/src/mu-output-link.c index 7eb8d9be..f144a9d5 100644 --- a/src/mu-output-link.c +++ b/src/mu-output-link.c @@ -57,15 +57,12 @@ gboolean mu_output_link_row (MuMsgIter *iter, const char* linksdir) { const char *path; - const MuMsgField *pathfield; - + g_return_val_if_fail (iter, FALSE); g_return_val_if_fail (linksdir, FALSE); g_return_val_if_fail (!mu_msg_iter_is_done (iter), FALSE); - - pathfield = mu_msg_field_from_id (MU_MSG_FIELD_ID_PATH); - - path = mu_msg_iter_get_field (iter, pathfield); + + path = mu_msg_iter_get_field (iter, MU_MSG_FIELD_ID_PATH); if (!path) return FALSE; diff --git a/src/mu-output-plain.c b/src/mu-output-plain.c index 258d806c..383322f2 100644 --- a/src/mu-output-plain.c +++ b/src/mu-output-plain.c @@ -40,34 +40,31 @@ static const gchar* -display_field (MuMsgIter *iter, const MuMsgField* field) +display_field (MuMsgIter *iter, MuMsgFieldId mfid) { gint64 val; - switch (mu_msg_field_type(field)) { + switch (mu_msg_field_type(mfid)) { case MU_MSG_FIELD_TYPE_STRING: - return mu_msg_iter_get_field (iter, field); + return mu_msg_iter_get_field (iter, mfid); case MU_MSG_FIELD_TYPE_INT: - if (mu_msg_field_id(field) == MU_MSG_FIELD_ID_PRIO) { - val = mu_msg_iter_get_field_numeric (iter, field); + if (mfid == MU_MSG_FIELD_ID_PRIO) { + val = mu_msg_iter_get_field_numeric (iter, mfid); return mu_msg_str_prio ((MuMsgPrio)val); - } - - if (mu_msg_field_id(field) == MU_MSG_FIELD_ID_FLAGS) { - val = mu_msg_iter_get_field_numeric (iter, field); - return mu_msg_str_flags_s ((MuMsgPrio)val); - } - - return mu_msg_iter_get_field (iter, field); /* as string */ + } else if (mfid == MU_MSG_FIELD_ID_FLAGS) { + val = mu_msg_iter_get_field_numeric (iter, mfid); + return mu_msg_str_flags_s ((MuMsgFlags)val); + } else /* as string */ + return mu_msg_iter_get_field (iter, mfid); case MU_MSG_FIELD_TYPE_TIME_T: - val = mu_msg_iter_get_field_numeric (iter, field); + val = mu_msg_iter_get_field_numeric (iter, mfid); return mu_msg_str_date_s ("%c", (time_t)val); case MU_MSG_FIELD_TYPE_BYTESIZE: - val = mu_msg_iter_get_field_numeric (iter, field); + val = mu_msg_iter_get_field_numeric (iter, mfid); return mu_msg_str_size_s ((unsigned)val); default: g_return_val_if_reached (NULL); @@ -107,14 +104,15 @@ mu_output_plain_row (MuMsgIter *iter, const char *fields, size_t summary_len) myfields = fields; while (*myfields) { - const MuMsgField* field; - field = mu_msg_field_from_shortcut (*myfields); - if (!field || ( !mu_msg_field_xapian_value (field) && - !mu_msg_field_xapian_contact (field))) + MuMsgFieldId mfid; + mfid = mu_msg_field_id_from_shortcut (*myfields, FALSE); + if (mfid == MU_MSG_FIELD_ID_NONE || + ( !mu_msg_field_xapian_value (mfid) && + !mu_msg_field_xapian_contact (mfid))) len += printf ("%c", *myfields); else len += printf ("%s", - display_field(iter, field)); + display_field(iter, mfid)); ++myfields; } diff --git a/src/mu-query.cc b/src/mu-query.cc index 8aad6929..7a80806b 100644 --- a/src/mu-query.cc +++ b/src/mu-query.cc @@ -32,8 +32,7 @@ #include "mu-util-db.h" #include "mu-msg-str.h" -static void add_prefix (const MuMsgField* field, - Xapian::QueryParser* qparser); +static void add_prefix (MuMsgFieldId field, Xapian::QueryParser* qparser); struct _MuQuery { Xapian::Database* _db; @@ -51,14 +50,23 @@ init_mu_query (MuQuery *mqx, const char* dbpath) mqx->_db = new Xapian::Database(dbpath); mqx->_qparser = new Xapian::QueryParser; - mqx->_qparser->set_database(*mqx->_db); - mqx->_qparser->set_default_op(Xapian::Query::OP_AND); - mqx->_qparser->set_stemming_strategy - (Xapian::QueryParser::STEM_ALL); + mqx->_qparser->set_database (*mqx->_db); + mqx->_qparser->set_default_op (Xapian::Query::OP_AND); + //mqx->_qparser->set_stemming_strategy (Xapian::QueryParser::STEM_NONE); memset (mqx->_sorters, 0, sizeof(mqx->_sorters)); mu_msg_field_foreach ((MuMsgFieldForEachFunc)add_prefix, (gpointer)mqx->_qparser); +////// FIXME + // g_print ("synonyms:"); + // for (Xapian::TermIterator iter = mqx->_db->synonym_keys_begin(); + // iter != mqx->_db->synonym_keys_end(); ++iter) { + // for (Xapian::TermIterator jter = mqx->_db->synonyms_begin(*iter); + // jter != mqx->_db->synonyms_end(*iter); ++jter) { + // g_print ("%s => %s\n", (*iter).c_str(), (*jter).c_str()); + // } + // } + return TRUE; } MU_XAPIAN_CATCH_BLOCK; @@ -95,8 +103,9 @@ get_query (MuQuery * mqx, const char* searchexpr, int *err = 0) { (searchexpr, Xapian::QueryParser::FLAG_BOOLEAN | Xapian::QueryParser::FLAG_PHRASE | + Xapian::QueryParser::FLAG_AUTO_SYNONYMS | Xapian::QueryParser::FLAG_BOOLEAN_ANY_CASE); - + } MU_XAPIAN_CATCH_BLOCK; if (err) @@ -106,22 +115,43 @@ get_query (MuQuery * mqx, const char* searchexpr, int *err = 0) { } static void -add_prefix (const MuMsgField* field, Xapian::QueryParser* qparser) +add_prefix (MuMsgFieldId mfid, Xapian::QueryParser* qparser) { - if (!mu_msg_field_xapian_index(field) && - !mu_msg_field_xapian_term(field) && - !mu_msg_field_xapian_contact(field)) + static char pfx[] = "\0\0"; + static char shortcut[] = "\0\0"; + + if (!mu_msg_field_xapian_index(mfid) && + !mu_msg_field_xapian_term(mfid) && + !mu_msg_field_xapian_contact(mfid)) return; - const std::string prefix (mu_msg_field_xapian_prefix(field)); + pfx[0] = mu_msg_field_xapian_prefix (mfid); + shortcut[0] = mu_msg_field_shortcut (mfid); - qparser->add_boolean_prefix - (std::string(mu_msg_field_name(field)), prefix); - qparser->add_boolean_prefix - (std::string(mu_msg_field_shortcut(field)), prefix); + try { - /* make the empty string match this field too*/ - qparser->add_prefix ("", prefix); + if (mfid == MU_MSG_FIELD_ID_MSGID || + mfid == MU_MSG_FIELD_ID_MAILDIR || + mu_msg_field_type (mfid) != MU_MSG_FIELD_TYPE_STRING || + mu_msg_field_xapian_contact(mfid)) { + qparser->add_boolean_prefix + (mu_msg_field_name(mfid), pfx); + qparser->add_boolean_prefix (shortcut, pfx); + + /* make the empty string match this field too*/ + qparser->add_prefix ("", pfx); + + } else { + + qparser->add_boolean_prefix + (mu_msg_field_name(mfid), pfx); + qparser->add_prefix (shortcut, pfx); + + /* make the empty string match this field too*/ + qparser->add_prefix ("", pfx); + } + + } MU_XAPIAN_CATCH_BLOCK; } MuQuery* @@ -162,10 +192,11 @@ mu_query_new (const char* xpath) void mu_query_destroy (MuQuery *self) { - if (self) { - uninit_mu_query (self); - g_free (self); - } + if (!self) + return; + + uninit_mu_query (self); + g_free (self); } struct _CheckPrefix { @@ -176,21 +207,21 @@ struct _CheckPrefix { typedef struct _CheckPrefix CheckPrefix; static void -each_check_prefix (const MuMsgField *field, CheckPrefix *cpfx) +each_check_prefix (MuMsgFieldId mfid, CheckPrefix *cpfx) { - const char *field_name, *field_shortcut; + const char *field_name; + char field_shortcut; - if (cpfx->match) + if (!cpfx || cpfx->match) return; - field_shortcut = mu_msg_field_shortcut (field); - if (field_shortcut && - strncmp (cpfx->pfx, field_shortcut, cpfx->len) == 0) { + field_shortcut = mu_msg_field_shortcut (mfid); + if (field_shortcut == cpfx->pfx[0]) { cpfx->match = TRUE; return; } - field_name = mu_msg_field_name (field); + field_name = mu_msg_field_name (mfid); if (field_name && strncmp (cpfx->pfx, field_name, cpfx->len) == 0) { cpfx->match = TRUE; @@ -265,11 +296,13 @@ mu_query_preprocess (const char *query) MuMsgIter* mu_query_run (MuQuery *self, const char* searchexpr, - const MuMsgField* sortfield, gboolean ascending, + MuMsgFieldId sortfieldid, gboolean ascending, size_t batchsize) { g_return_val_if_fail (self, NULL); g_return_val_if_fail (searchexpr, NULL); + g_return_val_if_fail (mu_msg_field_id_is_valid (sortfieldid) || + sortfieldid == MU_MSG_FIELD_ID_NONE, NULL); try { char *preprocessed; @@ -290,9 +323,9 @@ mu_query_run (MuQuery *self, const char* searchexpr, if (batchsize == 0) batchsize = self->_db->get_doccount(); - if (sortfield) + if (sortfieldid != MU_MSG_FIELD_ID_NONE) enq.set_sort_by_value ( - (Xapian::valueno)mu_msg_field_id(sortfield), + (Xapian::valueno)sortfieldid, ascending); enq.set_query(q); @@ -312,7 +345,7 @@ mu_query_as_string (MuQuery *self, const char *searchexpr) try { char *preprocessed; int err (0); - + preprocessed = mu_query_preprocess (searchexpr); Xapian::Query q(get_query(self, preprocessed, &err)); diff --git a/src/mu-query.h b/src/mu-query.h index 2c2eb584..4f853304 100644 --- a/src/mu-query.h +++ b/src/mu-query.h @@ -63,7 +63,8 @@ char* mu_query_version (MuQuery *store) G_GNUC_WARN_UNUSED_RESULT; * * @param self a valid MuQuery instance * @param expr the search expression - * @param sortfield the field to sort by or NULL + * @param sortfield the field id to sort by or MU_MSG_FIELD_ID_NONE if + * sorting is not desired * @param ascending if TRUE sort in ascending (A-Z) order, otherwise, * sort in descending (Z-A) order * @param batchsize the size of batches to receive; this is mainly for @@ -76,7 +77,7 @@ char* mu_query_version (MuQuery *store) G_GNUC_WARN_UNUSED_RESULT; */ MuMsgIter* mu_query_run (MuQuery *self, const char* expr, - const MuMsgField* sortfield, + MuMsgFieldId sortfieldid, gboolean ascending, size_t batchsize) G_GNUC_WARN_UNUSED_RESULT; diff --git a/src/mu-store.cc b/src/mu-store.cc index ab7dcaf8..42a4108b 100644 --- a/src/mu-store.cc +++ b/src/mu-store.cc @@ -40,12 +40,60 @@ struct _MuStore { Xapian::WritableDatabase *_db; + char *_version; + /* transaction handling */ bool _in_transaction; int _processed; size_t _trx_size; }; + +static void +add_synonyms (MuStore *store) +{ + std::string pfx (1, mu_msg_field_xapian_prefix + (MU_MSG_FIELD_ID_FLAGS)); + + store->_db->add_synonym (pfx + "n", pfx + "new"); + store->_db->add_synonym (pfx + "unread", pfx + "n"); + + store->_db->add_synonym (pfx + "attach", pfx + "a"); + store->_db->add_synonym (pfx + "attachment", pfx + "a"); + + store->_db->add_synonym ("Bfoo", "Bbar"); + store->_db->add_synonym ("Gnew", "Gn"); +} + +static gboolean +check_version (MuStore *store) +{ + /* FIXME clear up versioning semantics */ + const gchar *version; + + version = mu_store_version (store); + + /* no version yet? it must be a new db then; we'll set the version */ + if (!version) { + if (!mu_store_set_version (store, MU_XAPIAN_DB_VERSION)) { + g_warning ("failed to set database version"); + return FALSE; + } + return TRUE; /* ok, done. */ + } + + /* we have a version, but is it the right one? */ + if (std::strcmp (version, MU_XAPIAN_DB_VERSION) != 0) { + g_warning ("expected db version %s, but got %s", + MU_XAPIAN_DB_VERSION, version); + return FALSE; + } + + return TRUE; +} + + + MuStore* mu_store_new (const char* xpath) { @@ -55,15 +103,22 @@ mu_store_new (const char* xpath) try { store = g_new0(MuStore,1); - store->_db = new Xapian::WritableDatabase - (xpath, Xapian::DB_CREATE_OR_OPEN); + store->_db = new Xapian::WritableDatabase (xpath, + Xapian::DB_CREATE_OR_OPEN); + if (!check_version (store)) { + mu_store_destroy (store); + return NULL; + } /* keep count of processed docs */ store->_trx_size = MU_STORE_TRX_SIZE; store->_in_transaction = false; store->_processed = 0; + + add_synonyms (store); MU_WRITE_LOG ("%s: opened %s", __FUNCTION__, xpath); + return store; } MU_XAPIAN_CATCH_BLOCK; @@ -75,6 +130,26 @@ mu_store_new (const char* xpath) } +void +mu_store_destroy (MuStore *store) +{ + if (!store) + return; + + try { + mu_store_flush (store); + + MU_WRITE_LOG ("closing xapian database with %d documents", + (int)store->_db->get_doccount()); + + g_free (store->_version); + delete store->_db; + g_free (store); + + } MU_XAPIAN_CATCH_BLOCK; +} + + unsigned mu_store_count (MuStore *store) @@ -90,17 +165,18 @@ mu_store_count (MuStore *store) } -char* +const char* mu_store_version (MuStore *store) { g_return_val_if_fail (store, NULL); try { - const std::string version ( - store->_db->get_metadata (MU_XAPIAN_VERSION_KEY)); - - return version.empty() ? NULL : g_strdup (version.c_str()); - + std::string v; + v = store->_db->get_metadata (MU_XAPIAN_VERSION_KEY); + + g_free (store->_version); + return store->_version = v.empty() ? NULL : g_strdup (v.c_str()); + } MU_XAPIAN_CATCH_BLOCK; return NULL; @@ -118,7 +194,7 @@ mu_store_set_version (MuStore *store, const char* version) } MU_XAPIAN_CATCH_BLOCK; - return FALSE; + return FALSE; } @@ -153,23 +229,6 @@ rollback_trx_if (MuStore *store, gboolean cond) } -void -mu_store_destroy (MuStore *store) -{ - if (!store) - return; - - try { - mu_store_flush (store); - - MU_WRITE_LOG ("closing xapian database with %d documents", - (int)store->_db->get_doccount()); - - delete store->_db; - g_free (store); - - } MU_XAPIAN_CATCH_BLOCK; -} void mu_store_flush (MuStore *store) @@ -178,7 +237,7 @@ mu_store_flush (MuStore *store) try { commit_trx_if (store, store->_in_transaction); - store->_db->flush (); + store->_db->flush (); /* => commit, post X 1.1.x */ } MU_XAPIAN_CATCH_BLOCK; } @@ -186,30 +245,40 @@ mu_store_flush (MuStore *store) static void add_terms_values_number (Xapian::Document& doc, MuMsg *msg, - const MuMsgField* field) + MuMsgFieldId mfid) { - const std::string pfx (mu_msg_field_xapian_prefix(field), 1); - gint64 num = mu_msg_get_field_numeric (msg, field); + const std::string pfx (1, mu_msg_field_xapian_prefix(mfid)); + gint64 num = mu_msg_get_field_numeric (msg, mfid); const std::string numstr (Xapian::sortable_serialise((double)num)); - doc.add_value ((Xapian::valueno)mu_msg_field_id(field), numstr); - doc.add_term (pfx + numstr); + doc.add_value ((Xapian::valueno)mfid, numstr); + + if (mfid == MU_MSG_FIELD_ID_FLAGS) { + const char* flags, *cur; + cur = flags = mu_msg_flags_to_str_s ((MuMsgFlags)num); + while (cur && *cur) { + char kar = tolower (*cur); + doc.add_term (pfx + kar); + ++cur; + } + } else + doc.add_term (pfx + numstr); } static void add_terms_values_string (Xapian::Document& doc, MuMsg *msg, - const MuMsgField* field) + MuMsgFieldId mfid) { const char* str; - str = mu_msg_get_field_string (msg, field); + str = mu_msg_get_field_string (msg, mfid); if (!str) return; const std::string value (str); - const std::string prefix (mu_msg_field_xapian_prefix(field)); + const std::string prefix (1, mu_msg_field_xapian_prefix(mfid)); - if (mu_msg_field_xapian_index (field)) { + if (mu_msg_field_xapian_index (mfid)) { Xapian::TermGenerator termgen; gchar *norm (mu_msg_str_normalize(str, TRUE)); termgen.set_document (doc); @@ -217,28 +286,24 @@ add_terms_values_string (Xapian::Document& doc, MuMsg *msg, g_free(norm); } - if (mu_msg_field_xapian_term(field)) { - /* terms can be up to MU_STORE_MAX_TERM_LENGTH (240) - * long; this is a Xapian limit */ - // doc.add_term (std::string (prefix + value, 0, - // MU_STORE_MAX_TERM_LENGTH)); - - /* add a normalized version as well (accents removed, - * lowercase), if it's actually different */ + if (mu_msg_field_xapian_term(mfid)) { + /* add a normalized version (accents removed, + * lowercase) */ gchar *norm = mu_msg_str_normalize(str, TRUE); doc.add_term (std::string (prefix + std::string(norm), 0, MU_STORE_MAX_TERM_LENGTH)); g_free (norm); } - - if (mu_msg_field_xapian_value(field)) - doc.add_value ((Xapian::valueno)mu_msg_field_id (field), + + /* the value is what we'll display; the unchanged original */ + if (mu_msg_field_xapian_value(mfid)) + doc.add_value ((Xapian::valueno)mfid, value); } static void add_terms_values_body (Xapian::Document& doc, MuMsg *msg, - const MuMsgField* field) + MuMsgFieldId mfid) { const char *str; char *norm; @@ -257,7 +322,8 @@ add_terms_values_body (Xapian::Document& doc, MuMsg *msg, termgen.set_document(doc); norm = mu_msg_str_normalize (str, TRUE); - termgen.index_text(norm, 1, mu_msg_field_xapian_prefix(field)); + termgen.index_text_without_positions + (norm, 1, std::string(1,mu_msg_field_xapian_prefix(mfid))); g_free (norm); } @@ -268,33 +334,34 @@ struct _MsgDoc { typedef struct _MsgDoc MsgDoc; static void -add_terms_values (const MuMsgField* field, MsgDoc* msgdoc) +add_terms_values (MuMsgFieldId mfid, MsgDoc* msgdoc) { MuMsgFieldType type; /* note: contact-stuff (To/Cc/From) will handled in * add_contact_info, not here */ - if (!mu_msg_field_xapian_index(field) && - !mu_msg_field_xapian_term(field) && - !mu_msg_field_xapian_value(field)) + if (!mu_msg_field_xapian_index(mfid) && + !mu_msg_field_xapian_term(mfid) && + !mu_msg_field_xapian_value(mfid)) return; - type = mu_msg_field_type (field); + type = mu_msg_field_type (mfid); if (type == MU_MSG_FIELD_TYPE_STRING) { - if (mu_msg_field_id (field) == MU_MSG_FIELD_ID_BODY_TEXT) + if (mfid == MU_MSG_FIELD_ID_BODY_TEXT) add_terms_values_body (*msgdoc->_doc, msgdoc->_msg, - field); + mfid); else add_terms_values_string (*msgdoc->_doc, msgdoc->_msg, - field); + mfid); return; } if (type == MU_MSG_FIELD_TYPE_BYTESIZE || type == MU_MSG_FIELD_TYPE_TIME_T || type == MU_MSG_FIELD_TYPE_INT) { - add_terms_values_number (*msgdoc->_doc, msgdoc->_msg, field); + add_terms_values_number (*msgdoc->_doc, msgdoc->_msg, + mfid); return; } @@ -305,39 +372,38 @@ add_terms_values (const MuMsgField* field, MsgDoc* msgdoc) static void each_contact_info (MuMsgContact *contact, MsgDoc *data) { - std::string pfx; - - static const MuMsgField *to_field = - mu_msg_field_from_id (MU_MSG_FIELD_ID_TO); - static const MuMsgField *from_field = - mu_msg_field_from_id (MU_MSG_FIELD_ID_FROM); - static const MuMsgField *cc_field = - mu_msg_field_from_id (MU_MSG_FIELD_ID_CC); + const std::string *pfxp; - static const std::string to_pfx (mu_msg_field_xapian_prefix(to_field)); - static const std::string from_pfx (mu_msg_field_xapian_prefix(from_field)); - static const std::string cc_pfx (mu_msg_field_xapian_prefix(cc_field)); - + static const std::string to_pfx (1, + mu_msg_field_xapian_prefix(MU_MSG_FIELD_ID_TO)); + static const std::string from_pfx (1, + mu_msg_field_xapian_prefix(MU_MSG_FIELD_ID_FROM)); + static const std::string cc_pfx (1, + mu_msg_field_xapian_prefix(MU_MSG_FIELD_ID_CC)); + + /* use ptr to string to prevent copy... */ switch (contact->type) { - case MU_MSG_CONTACT_TYPE_TO: pfx = to_pfx; break; - case MU_MSG_CONTACT_TYPE_FROM: pfx = from_pfx; break; - case MU_MSG_CONTACT_TYPE_CC: pfx = cc_pfx; break; - default: return; /* other types (like bcc) are ignored */ + case MU_MSG_CONTACT_TYPE_TO: pfxp = &to_pfx; break; + case MU_MSG_CONTACT_TYPE_FROM: pfxp = &from_pfx; break; + case MU_MSG_CONTACT_TYPE_CC: pfxp = &cc_pfx; break; + default: return; + /* other types (like bcc) are ignored */ } if (contact->name && strlen(contact->name) > 0) { Xapian::TermGenerator termgen; termgen.set_document (*data->_doc); char *norm = mu_msg_str_normalize (contact->name, TRUE); - termgen.index_text_without_positions (norm, 1, pfx); + termgen.index_text_without_positions (norm, 1, *pfxp); g_free (norm); } /* don't normalize e-mail address, but do lowercase it */ if (contact->address && strlen (contact->address)) { char *lower = g_utf8_strdown (contact->address, -1); - data->_doc->add_term (std::string (pfx + lower, 0, - MU_STORE_MAX_TERM_LENGTH)); + data->_doc->add_term + (std::string (*pfxp + lower, 0, + MU_STORE_MAX_TERM_LENGTH)); g_free (lower); } } @@ -347,10 +413,8 @@ each_contact_info (MuMsgContact *contact, MsgDoc *data) static std::string get_message_uid (const char* path) { - static const MuMsgField* pathfield = - mu_msg_field_from_id(MU_MSG_FIELD_ID_PATH); static const std::string pathprefix - (mu_msg_field_xapian_prefix(pathfield)); + (1, mu_msg_field_xapian_prefix(MU_MSG_FIELD_ID_PATH)); return pathprefix + path; } @@ -377,8 +441,8 @@ mu_store_store (MuStore *store, MuMsg *msg) /* we must add a unique term, so we can replace * matching documents */ newdoc.add_term (uid); - mu_msg_field_foreach ((MuMsgFieldForEachFunc)add_terms_values, - &msgdoc); + mu_msg_field_foreach + ((MuMsgFieldForEachFunc)add_terms_values, &msgdoc); /* also store the contact-info as separate terms */ mu_msg_contact_foreach (msg, (MuMsgContactForeachFunc)each_contact_info, diff --git a/src/mu-store.h b/src/mu-store.h index c866a38e..bfea5534 100644 --- a/src/mu-store.h +++ b/src/mu-store.h @@ -45,7 +45,7 @@ MuStore* mu_store_new (const char* path); * * @param store a valid store, or NULL */ -void mu_store_destroy (MuStore *store); +void mu_store_destroy (MuStore *store); /** @@ -59,13 +59,15 @@ void mu_store_destroy (MuStore *store); unsigned mu_store_count (MuStore *store); /** - * get a version string for the database + * get a version string for the database; it's a const string, which + * is valid as long MuStore exists and mu_store_version is not called + * again. * * @param store a valid MuStore * - * @return the version string (free with g_free), or NULL in case of error + * @return the version string or NULL in case of error */ -char* mu_store_version (MuStore *store); +const char* mu_store_version (MuStore *store); /** * set the version string for the database diff --git a/toys/mug/mug-msg-list-view.c b/toys/mug/mug-msg-list-view.c index 0eb14575..db0b575d 100644 --- a/toys/mug/mug-msg-list-view.c +++ b/toys/mug/mug-msg-list-view.c @@ -311,7 +311,8 @@ run_query (const char *xpath, const char *query) return NULL; } - iter = mu_query_run (xapian, query, NULL, TRUE, 0); + iter = mu_query_run (xapian, query, MU_MSG_FIELD_ID_NONE, + TRUE, 0); mu_query_destroy (xapian); if (!iter) { g_warning ("error: running query failed\n");