mirror of https://github.com/djcb/mu.git
* <many>: update for mu-msg-field change
This commit is contained in:
parent
7f617e32f0
commit
b69cf8f589
|
@ -70,20 +70,23 @@ print_xapian_query (MuQuery *xapian, const gchar *query)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* returns NULL if there is an error */
|
/* returns NULL if there is an error */
|
||||||
const MuMsgField*
|
static MuMsgFieldId
|
||||||
sort_field_from_string (const char* fieldstr)
|
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)
|
/* not found? try a shortcut */
|
||||||
field = mu_msg_field_from_shortcut(fieldstr[0]);
|
if (mfid == MU_MSG_FIELD_ID_NONE &&
|
||||||
|
strlen(fieldstr) == 1)
|
||||||
if (!field)
|
mfid = mu_msg_field_id_from_shortcut(fieldstr[0],
|
||||||
g_printerr ("not a valid sort field: '%s'\n",
|
FALSE);
|
||||||
fieldstr);
|
|
||||||
return field;
|
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)
|
run_query (MuQuery *xapian, const gchar *query, MuConfigOptions *opts)
|
||||||
{
|
{
|
||||||
MuMsgIter *iter;
|
MuMsgIter *iter;
|
||||||
const MuMsgField *sortfield;
|
MuMsgFieldId sortid;
|
||||||
size_t matches;
|
size_t matches;
|
||||||
|
|
||||||
sortfield = NULL;
|
sortid = MU_MSG_FIELD_ID_NONE;
|
||||||
if (opts->sortfield) {
|
if (opts->sortfield) {
|
||||||
sortfield = sort_field_from_string (opts->sortfield);
|
sortid = sort_field_from_string (opts->sortfield);
|
||||||
if (!sortfield) /* error occured? */
|
if (sortid == MU_MSG_FIELD_ID_NONE) /* error occured? */
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
iter = mu_query_run (xapian, query, sortfield, !opts->descending, 0);
|
iter = mu_query_run (xapian, query, sortid, !opts->descending, 0);
|
||||||
if (!iter) {
|
if (!iter) {
|
||||||
g_printerr ("error: running query failed\n");
|
g_printerr ("error: running query failed\n");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts->linksdir)
|
if (opts->linksdir)
|
||||||
matches = make_links (iter, opts->linksdir, opts->clearlinks);
|
matches = make_links (iter, opts->linksdir,
|
||||||
|
opts->clearlinks);
|
||||||
else
|
else
|
||||||
matches = print_rows (iter, opts->fields, opts->summary_len);
|
matches = print_rows (iter, opts->fields,
|
||||||
|
opts->summary_len);
|
||||||
|
|
||||||
if (matches == 0)
|
if (matches == 0)
|
||||||
g_printerr ("No matches found\n");
|
g_printerr ("No matches found\n");
|
||||||
|
|
|
@ -181,54 +181,50 @@ mu_msg_iter_is_done (MuMsgIter *iter)
|
||||||
|
|
||||||
|
|
||||||
const gchar*
|
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_iter_is_done(iter), NULL);
|
||||||
|
g_return_val_if_fail (mu_msg_field_id_is_valid(mfid), NULL);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
MuMsgFieldId id;
|
if (!iter->_str[mfid]) { /* cache the value */
|
||||||
|
|
||||||
id = mu_msg_field_id (field);
|
|
||||||
if (!iter->_str[id]) { /* cache the value */
|
|
||||||
Xapian::Document doc (iter->_cursor.get_document());
|
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);
|
} MU_XAPIAN_CATCH_BLOCK_RETURN(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gint64
|
gint64
|
||||||
mu_msg_iter_get_field_numeric (MuMsgIter *iter,
|
mu_msg_iter_get_field_numeric (MuMsgIter *iter, MuMsgFieldId mfid)
|
||||||
const MuMsgField *field)
|
|
||||||
{
|
{
|
||||||
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_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 {
|
try {
|
||||||
return static_cast<gint64>(
|
return static_cast<gint64>(
|
||||||
Xapian::sortable_unserialise(
|
Xapian::sortable_unserialise(
|
||||||
mu_msg_iter_get_field(iter, field)));
|
mu_msg_iter_get_field(iter, mfid)));
|
||||||
|
|
||||||
} MU_XAPIAN_CATCH_BLOCK_RETURN(static_cast<gint64>(-1));
|
} MU_XAPIAN_CATCH_BLOCK_RETURN(static_cast<gint64>(-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static const gchar*
|
// static const gchar*
|
||||||
get_field (MuMsgIter *iter, MuMsgFieldId id)
|
// get_field (MuMsgIter *iter, MuMsgFieldId mfid)
|
||||||
{
|
// {
|
||||||
return mu_msg_iter_get_field(iter, mu_msg_field_from_id (id));
|
// return mu_msg_iter_get_field(iter, mfid);
|
||||||
}
|
// }
|
||||||
|
|
||||||
static long
|
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;
|
return str ? atol (str) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,14 +246,14 @@ const char*
|
||||||
mu_msg_iter_get_path (MuMsgIter *iter)
|
mu_msg_iter_get_path (MuMsgIter *iter)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (!mu_msg_iter_is_done(iter), NULL);
|
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*
|
const char*
|
||||||
mu_msg_iter_get_maildir (MuMsgIter *iter)
|
mu_msg_iter_get_maildir (MuMsgIter *iter)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (!mu_msg_iter_is_done(iter), NULL);
|
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)
|
mu_msg_iter_get_from (MuMsgIter *iter)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (!mu_msg_iter_is_done(iter), NULL);
|
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*
|
const char*
|
||||||
mu_msg_iter_get_to (MuMsgIter *iter)
|
mu_msg_iter_get_to (MuMsgIter *iter)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (!mu_msg_iter_is_done(iter), NULL);
|
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)
|
mu_msg_iter_get_cc (MuMsgIter *iter)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (!mu_msg_iter_is_done(iter), NULL);
|
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)
|
mu_msg_iter_get_subject (MuMsgIter *iter)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (!mu_msg_iter_is_done(iter), NULL);
|
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)
|
mu_msg_iter_get_size (MuMsgIter *iter)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (!mu_msg_iter_is_done(iter), 0);
|
g_return_val_if_fail (!mu_msg_iter_is_done(iter), 0);
|
||||||
return static_cast<size_t>(get_field_number (iter, MU_MSG_FIELD_ID_SIZE));
|
return static_cast<size_t>(get_field_number
|
||||||
|
(iter, MU_MSG_FIELD_ID_SIZE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
time_t
|
time_t
|
||||||
mu_msg_iter_get_date (MuMsgIter *iter)
|
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);
|
g_return_val_if_fail (!mu_msg_iter_is_done(iter), 0);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return static_cast<time_t>(
|
return static_cast<time_t>(
|
||||||
Xapian::sortable_unserialise(
|
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);
|
} MU_XAPIAN_CATCH_BLOCK_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
MuMsgFlags
|
MuMsgFlags
|
||||||
mu_msg_iter_get_flags (MuMsgIter *iter)
|
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);
|
g_return_val_if_fail (!mu_msg_iter_is_done(iter), MU_MSG_FLAG_NONE);
|
||||||
|
|
||||||
return static_cast<MuMsgFlags>(mu_msg_iter_get_field_numeric
|
return static_cast<MuMsgFlags>(mu_msg_iter_get_field_numeric
|
||||||
(iter, flags_field));
|
(iter, MU_MSG_FIELD_ID_FLAGS));
|
||||||
}
|
}
|
||||||
|
|
||||||
MuMsgPrio
|
MuMsgPrio
|
||||||
mu_msg_iter_get_prio (MuMsgIter *iter)
|
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);
|
g_return_val_if_fail (!mu_msg_iter_is_done(iter), MU_MSG_PRIO_NONE);
|
||||||
|
|
||||||
return static_cast<MuMsgPrio>(mu_msg_iter_get_field_numeric
|
return static_cast<MuMsgPrio>(mu_msg_iter_get_field_numeric
|
||||||
(iter, prio_field));
|
(iter, MU_MSG_FIELD_ID_PRIO));
|
||||||
}
|
}
|
||||||
|
|
|
@ -198,7 +198,7 @@ MuMsgPrio mu_msg_iter_get_prio (MuMsgIter *iter);
|
||||||
* @return the field value, or NULL
|
* @return the field value, or NULL
|
||||||
*/
|
*/
|
||||||
const gchar* mu_msg_iter_get_field (MuMsgIter *iter,
|
const gchar* mu_msg_iter_get_field (MuMsgIter *iter,
|
||||||
const MuMsgField *field);
|
MuMsgFieldId mfid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get some numeric message field
|
* 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
|
* @return the field value, or -1 in case of error
|
||||||
*/
|
*/
|
||||||
gint64 mu_msg_iter_get_field_numeric (MuMsgIter *iter,
|
gint64 mu_msg_iter_get_field_numeric (MuMsgIter *iter,
|
||||||
const MuMsgField *field);
|
MuMsgFieldId mfid);
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /*__MU_MSG_ITER_H__*/
|
#endif /*__MU_MSG_ITER_H__*/
|
||||||
|
|
18
src/mu-msg.c
18
src/mu-msg.c
|
@ -751,15 +751,11 @@ mu_msg_get_summary (MuMsg *msg, size_t max_lines)
|
||||||
|
|
||||||
|
|
||||||
const char*
|
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);
|
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_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_BODY_HTML: return mu_msg_get_body_html (msg);
|
||||||
case MU_MSG_FIELD_ID_CC: return mu_msg_get_cc (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
|
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);
|
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:
|
case MU_MSG_FIELD_ID_DATE:
|
||||||
return mu_msg_get_date(msg);
|
return mu_msg_get_date(msg);
|
||||||
case MU_MSG_FIELD_ID_FLAGS:
|
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:
|
case MU_MSG_FIELD_ID_SIZE:
|
||||||
return mu_msg_get_size(msg);
|
return mu_msg_get_size(msg);
|
||||||
default:
|
default:
|
||||||
g_warning ("%s: %u", __FUNCTION__, (guint)id);
|
g_warning ("%s: %u", __FUNCTION__, mfid);
|
||||||
g_return_val_if_reached (0);
|
g_return_val_if_reached (0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -238,8 +238,8 @@ size_t mu_msg_get_size (MuMsg *msg);
|
||||||
*
|
*
|
||||||
* @return a string that should not be freed
|
* @return a string that should not be freed
|
||||||
*/
|
*/
|
||||||
const char* mu_msg_get_field_string (MuMsg *msg,
|
const char* mu_msg_get_field_string (MuMsg *msg, MuMsgFieldId mfid);
|
||||||
const MuMsgField* field);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get some field value as string
|
* 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
|
* @return a string that should not be freed
|
||||||
*/
|
*/
|
||||||
gint64 mu_msg_get_field_numeric (MuMsg *msg,
|
gint64 mu_msg_get_field_numeric (MuMsg *msg, MuMsgFieldId mfid);
|
||||||
const MuMsgField* field);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get the message priority for this message (MU_MSG_PRIO_LOW,
|
* get the message priority for this message (MU_MSG_PRIO_LOW,
|
||||||
|
|
|
@ -57,15 +57,12 @@ gboolean
|
||||||
mu_output_link_row (MuMsgIter *iter, const char* linksdir)
|
mu_output_link_row (MuMsgIter *iter, const char* linksdir)
|
||||||
{
|
{
|
||||||
const char *path;
|
const char *path;
|
||||||
const MuMsgField *pathfield;
|
|
||||||
|
|
||||||
g_return_val_if_fail (iter, FALSE);
|
g_return_val_if_fail (iter, FALSE);
|
||||||
g_return_val_if_fail (linksdir, FALSE);
|
g_return_val_if_fail (linksdir, FALSE);
|
||||||
g_return_val_if_fail (!mu_msg_iter_is_done (iter), 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, MU_MSG_FIELD_ID_PATH);
|
||||||
|
|
||||||
path = mu_msg_iter_get_field (iter, pathfield);
|
|
||||||
if (!path)
|
if (!path)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
|
|
@ -40,34 +40,31 @@
|
||||||
|
|
||||||
|
|
||||||
static const gchar*
|
static const gchar*
|
||||||
display_field (MuMsgIter *iter, const MuMsgField* field)
|
display_field (MuMsgIter *iter, MuMsgFieldId mfid)
|
||||||
{
|
{
|
||||||
gint64 val;
|
gint64 val;
|
||||||
|
|
||||||
switch (mu_msg_field_type(field)) {
|
switch (mu_msg_field_type(mfid)) {
|
||||||
case MU_MSG_FIELD_TYPE_STRING:
|
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:
|
case MU_MSG_FIELD_TYPE_INT:
|
||||||
|
|
||||||
if (mu_msg_field_id(field) == MU_MSG_FIELD_ID_PRIO) {
|
if (mfid == MU_MSG_FIELD_ID_PRIO) {
|
||||||
val = mu_msg_iter_get_field_numeric (iter, field);
|
val = mu_msg_iter_get_field_numeric (iter, mfid);
|
||||||
return mu_msg_str_prio ((MuMsgPrio)val);
|
return mu_msg_str_prio ((MuMsgPrio)val);
|
||||||
}
|
} else if (mfid == MU_MSG_FIELD_ID_FLAGS) {
|
||||||
|
val = mu_msg_iter_get_field_numeric (iter, mfid);
|
||||||
if (mu_msg_field_id(field) == MU_MSG_FIELD_ID_FLAGS) {
|
return mu_msg_str_flags_s ((MuMsgFlags)val);
|
||||||
val = mu_msg_iter_get_field_numeric (iter, field);
|
} else /* as string */
|
||||||
return mu_msg_str_flags_s ((MuMsgPrio)val);
|
return mu_msg_iter_get_field (iter, mfid);
|
||||||
}
|
|
||||||
|
|
||||||
return mu_msg_iter_get_field (iter, field); /* as string */
|
|
||||||
|
|
||||||
case MU_MSG_FIELD_TYPE_TIME_T:
|
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);
|
return mu_msg_str_date_s ("%c", (time_t)val);
|
||||||
|
|
||||||
case MU_MSG_FIELD_TYPE_BYTESIZE:
|
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);
|
return mu_msg_str_size_s ((unsigned)val);
|
||||||
default:
|
default:
|
||||||
g_return_val_if_reached (NULL);
|
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;
|
myfields = fields;
|
||||||
while (*myfields) {
|
while (*myfields) {
|
||||||
const MuMsgField* field;
|
MuMsgFieldId mfid;
|
||||||
field = mu_msg_field_from_shortcut (*myfields);
|
mfid = mu_msg_field_id_from_shortcut (*myfields, FALSE);
|
||||||
if (!field || ( !mu_msg_field_xapian_value (field) &&
|
if (mfid == MU_MSG_FIELD_ID_NONE ||
|
||||||
!mu_msg_field_xapian_contact (field)))
|
( !mu_msg_field_xapian_value (mfid) &&
|
||||||
|
!mu_msg_field_xapian_contact (mfid)))
|
||||||
len += printf ("%c", *myfields);
|
len += printf ("%c", *myfields);
|
||||||
else
|
else
|
||||||
len += printf ("%s",
|
len += printf ("%s",
|
||||||
display_field(iter, field));
|
display_field(iter, mfid));
|
||||||
++myfields;
|
++myfields;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,8 +32,7 @@
|
||||||
#include "mu-util-db.h"
|
#include "mu-util-db.h"
|
||||||
#include "mu-msg-str.h"
|
#include "mu-msg-str.h"
|
||||||
|
|
||||||
static void add_prefix (const MuMsgField* field,
|
static void add_prefix (MuMsgFieldId field, Xapian::QueryParser* qparser);
|
||||||
Xapian::QueryParser* qparser);
|
|
||||||
|
|
||||||
struct _MuQuery {
|
struct _MuQuery {
|
||||||
Xapian::Database* _db;
|
Xapian::Database* _db;
|
||||||
|
@ -51,14 +50,23 @@ init_mu_query (MuQuery *mqx, const char* dbpath)
|
||||||
mqx->_db = new Xapian::Database(dbpath);
|
mqx->_db = new Xapian::Database(dbpath);
|
||||||
mqx->_qparser = new Xapian::QueryParser;
|
mqx->_qparser = new Xapian::QueryParser;
|
||||||
|
|
||||||
mqx->_qparser->set_database(*mqx->_db);
|
mqx->_qparser->set_database (*mqx->_db);
|
||||||
mqx->_qparser->set_default_op(Xapian::Query::OP_AND);
|
mqx->_qparser->set_default_op (Xapian::Query::OP_AND);
|
||||||
mqx->_qparser->set_stemming_strategy
|
//mqx->_qparser->set_stemming_strategy (Xapian::QueryParser::STEM_NONE);
|
||||||
(Xapian::QueryParser::STEM_ALL);
|
|
||||||
|
|
||||||
memset (mqx->_sorters, 0, sizeof(mqx->_sorters));
|
memset (mqx->_sorters, 0, sizeof(mqx->_sorters));
|
||||||
mu_msg_field_foreach ((MuMsgFieldForEachFunc)add_prefix,
|
mu_msg_field_foreach ((MuMsgFieldForEachFunc)add_prefix,
|
||||||
(gpointer)mqx->_qparser);
|
(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;
|
return TRUE;
|
||||||
|
|
||||||
} MU_XAPIAN_CATCH_BLOCK;
|
} MU_XAPIAN_CATCH_BLOCK;
|
||||||
|
@ -95,8 +103,9 @@ get_query (MuQuery * mqx, const char* searchexpr, int *err = 0) {
|
||||||
(searchexpr,
|
(searchexpr,
|
||||||
Xapian::QueryParser::FLAG_BOOLEAN |
|
Xapian::QueryParser::FLAG_BOOLEAN |
|
||||||
Xapian::QueryParser::FLAG_PHRASE |
|
Xapian::QueryParser::FLAG_PHRASE |
|
||||||
|
Xapian::QueryParser::FLAG_AUTO_SYNONYMS |
|
||||||
Xapian::QueryParser::FLAG_BOOLEAN_ANY_CASE);
|
Xapian::QueryParser::FLAG_BOOLEAN_ANY_CASE);
|
||||||
|
|
||||||
} MU_XAPIAN_CATCH_BLOCK;
|
} MU_XAPIAN_CATCH_BLOCK;
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -106,22 +115,43 @@ get_query (MuQuery * mqx, const char* searchexpr, int *err = 0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_prefix (const MuMsgField* field, Xapian::QueryParser* qparser)
|
add_prefix (MuMsgFieldId mfid, Xapian::QueryParser* qparser)
|
||||||
{
|
{
|
||||||
if (!mu_msg_field_xapian_index(field) &&
|
static char pfx[] = "\0\0";
|
||||||
!mu_msg_field_xapian_term(field) &&
|
static char shortcut[] = "\0\0";
|
||||||
!mu_msg_field_xapian_contact(field))
|
|
||||||
|
if (!mu_msg_field_xapian_index(mfid) &&
|
||||||
|
!mu_msg_field_xapian_term(mfid) &&
|
||||||
|
!mu_msg_field_xapian_contact(mfid))
|
||||||
return;
|
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
|
try {
|
||||||
(std::string(mu_msg_field_name(field)), prefix);
|
|
||||||
qparser->add_boolean_prefix
|
|
||||||
(std::string(mu_msg_field_shortcut(field)), prefix);
|
|
||||||
|
|
||||||
/* make the empty string match this field too*/
|
if (mfid == MU_MSG_FIELD_ID_MSGID ||
|
||||||
qparser->add_prefix ("", prefix);
|
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*
|
MuQuery*
|
||||||
|
@ -162,10 +192,11 @@ mu_query_new (const char* xpath)
|
||||||
void
|
void
|
||||||
mu_query_destroy (MuQuery *self)
|
mu_query_destroy (MuQuery *self)
|
||||||
{
|
{
|
||||||
if (self) {
|
if (!self)
|
||||||
uninit_mu_query (self);
|
return;
|
||||||
g_free (self);
|
|
||||||
}
|
uninit_mu_query (self);
|
||||||
|
g_free (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct _CheckPrefix {
|
struct _CheckPrefix {
|
||||||
|
@ -176,21 +207,21 @@ struct _CheckPrefix {
|
||||||
typedef struct _CheckPrefix CheckPrefix;
|
typedef struct _CheckPrefix CheckPrefix;
|
||||||
|
|
||||||
static void
|
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;
|
return;
|
||||||
|
|
||||||
field_shortcut = mu_msg_field_shortcut (field);
|
field_shortcut = mu_msg_field_shortcut (mfid);
|
||||||
if (field_shortcut &&
|
if (field_shortcut == cpfx->pfx[0]) {
|
||||||
strncmp (cpfx->pfx, field_shortcut, cpfx->len) == 0) {
|
|
||||||
cpfx->match = TRUE;
|
cpfx->match = TRUE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
field_name = mu_msg_field_name (field);
|
field_name = mu_msg_field_name (mfid);
|
||||||
if (field_name &&
|
if (field_name &&
|
||||||
strncmp (cpfx->pfx, field_name, cpfx->len) == 0) {
|
strncmp (cpfx->pfx, field_name, cpfx->len) == 0) {
|
||||||
cpfx->match = TRUE;
|
cpfx->match = TRUE;
|
||||||
|
@ -265,11 +296,13 @@ mu_query_preprocess (const char *query)
|
||||||
|
|
||||||
MuMsgIter*
|
MuMsgIter*
|
||||||
mu_query_run (MuQuery *self, const char* searchexpr,
|
mu_query_run (MuQuery *self, const char* searchexpr,
|
||||||
const MuMsgField* sortfield, gboolean ascending,
|
MuMsgFieldId sortfieldid, gboolean ascending,
|
||||||
size_t batchsize)
|
size_t batchsize)
|
||||||
{
|
{
|
||||||
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);
|
||||||
|
g_return_val_if_fail (mu_msg_field_id_is_valid (sortfieldid) ||
|
||||||
|
sortfieldid == MU_MSG_FIELD_ID_NONE, NULL);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
char *preprocessed;
|
char *preprocessed;
|
||||||
|
@ -290,9 +323,9 @@ mu_query_run (MuQuery *self, const char* searchexpr,
|
||||||
if (batchsize == 0)
|
if (batchsize == 0)
|
||||||
batchsize = self->_db->get_doccount();
|
batchsize = self->_db->get_doccount();
|
||||||
|
|
||||||
if (sortfield)
|
if (sortfieldid != MU_MSG_FIELD_ID_NONE)
|
||||||
enq.set_sort_by_value (
|
enq.set_sort_by_value (
|
||||||
(Xapian::valueno)mu_msg_field_id(sortfield),
|
(Xapian::valueno)sortfieldid,
|
||||||
ascending);
|
ascending);
|
||||||
|
|
||||||
enq.set_query(q);
|
enq.set_query(q);
|
||||||
|
@ -312,7 +345,7 @@ mu_query_as_string (MuQuery *self, const char *searchexpr)
|
||||||
try {
|
try {
|
||||||
char *preprocessed;
|
char *preprocessed;
|
||||||
int err (0);
|
int err (0);
|
||||||
|
|
||||||
preprocessed = mu_query_preprocess (searchexpr);
|
preprocessed = mu_query_preprocess (searchexpr);
|
||||||
|
|
||||||
Xapian::Query q(get_query(self, preprocessed, &err));
|
Xapian::Query q(get_query(self, preprocessed, &err));
|
||||||
|
|
|
@ -63,7 +63,8 @@ char* mu_query_version (MuQuery *store) G_GNUC_WARN_UNUSED_RESULT;
|
||||||
*
|
*
|
||||||
* @param self a valid MuQuery instance
|
* @param self a valid MuQuery instance
|
||||||
* @param expr the search expression
|
* @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,
|
* @param ascending if TRUE sort in ascending (A-Z) order, otherwise,
|
||||||
* sort in descending (Z-A) order
|
* sort in descending (Z-A) order
|
||||||
* @param batchsize the size of batches to receive; this is mainly for
|
* @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,
|
MuMsgIter* mu_query_run (MuQuery *self,
|
||||||
const char* expr,
|
const char* expr,
|
||||||
const MuMsgField* sortfield,
|
MuMsgFieldId sortfieldid,
|
||||||
gboolean ascending,
|
gboolean ascending,
|
||||||
size_t batchsize) G_GNUC_WARN_UNUSED_RESULT;
|
size_t batchsize) G_GNUC_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
|
228
src/mu-store.cc
228
src/mu-store.cc
|
@ -40,12 +40,60 @@
|
||||||
struct _MuStore {
|
struct _MuStore {
|
||||||
Xapian::WritableDatabase *_db;
|
Xapian::WritableDatabase *_db;
|
||||||
|
|
||||||
|
char *_version;
|
||||||
|
|
||||||
/* transaction handling */
|
/* transaction handling */
|
||||||
bool _in_transaction;
|
bool _in_transaction;
|
||||||
int _processed;
|
int _processed;
|
||||||
size_t _trx_size;
|
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*
|
MuStore*
|
||||||
mu_store_new (const char* xpath)
|
mu_store_new (const char* xpath)
|
||||||
{
|
{
|
||||||
|
@ -55,15 +103,22 @@ mu_store_new (const char* xpath)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
store = g_new0(MuStore,1);
|
store = g_new0(MuStore,1);
|
||||||
store->_db = new Xapian::WritableDatabase
|
store->_db = new Xapian::WritableDatabase (xpath,
|
||||||
(xpath, Xapian::DB_CREATE_OR_OPEN);
|
Xapian::DB_CREATE_OR_OPEN);
|
||||||
|
if (!check_version (store)) {
|
||||||
|
mu_store_destroy (store);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* keep count of processed docs */
|
/* keep count of processed docs */
|
||||||
store->_trx_size = MU_STORE_TRX_SIZE;
|
store->_trx_size = MU_STORE_TRX_SIZE;
|
||||||
store->_in_transaction = false;
|
store->_in_transaction = false;
|
||||||
store->_processed = 0;
|
store->_processed = 0;
|
||||||
|
|
||||||
|
add_synonyms (store);
|
||||||
|
|
||||||
MU_WRITE_LOG ("%s: opened %s", __FUNCTION__, xpath);
|
MU_WRITE_LOG ("%s: opened %s", __FUNCTION__, xpath);
|
||||||
|
|
||||||
return store;
|
return store;
|
||||||
|
|
||||||
} MU_XAPIAN_CATCH_BLOCK;
|
} 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
|
unsigned
|
||||||
mu_store_count (MuStore *store)
|
mu_store_count (MuStore *store)
|
||||||
|
@ -90,17 +165,18 @@ mu_store_count (MuStore *store)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char*
|
const char*
|
||||||
mu_store_version (MuStore *store)
|
mu_store_version (MuStore *store)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (store, NULL);
|
g_return_val_if_fail (store, NULL);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const std::string version (
|
std::string v;
|
||||||
store->_db->get_metadata (MU_XAPIAN_VERSION_KEY));
|
v = store->_db->get_metadata (MU_XAPIAN_VERSION_KEY);
|
||||||
|
|
||||||
return version.empty() ? NULL : g_strdup (version.c_str());
|
g_free (store->_version);
|
||||||
|
return store->_version = v.empty() ? NULL : g_strdup (v.c_str());
|
||||||
|
|
||||||
} MU_XAPIAN_CATCH_BLOCK;
|
} MU_XAPIAN_CATCH_BLOCK;
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -118,7 +194,7 @@ mu_store_set_version (MuStore *store, const char* version)
|
||||||
|
|
||||||
} MU_XAPIAN_CATCH_BLOCK;
|
} 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
|
void
|
||||||
mu_store_flush (MuStore *store)
|
mu_store_flush (MuStore *store)
|
||||||
|
@ -178,7 +237,7 @@ mu_store_flush (MuStore *store)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
commit_trx_if (store, store->_in_transaction);
|
commit_trx_if (store, store->_in_transaction);
|
||||||
store->_db->flush ();
|
store->_db->flush (); /* => commit, post X 1.1.x */
|
||||||
|
|
||||||
} MU_XAPIAN_CATCH_BLOCK;
|
} MU_XAPIAN_CATCH_BLOCK;
|
||||||
}
|
}
|
||||||
|
@ -186,30 +245,40 @@ mu_store_flush (MuStore *store)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_terms_values_number (Xapian::Document& doc, MuMsg *msg,
|
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);
|
const std::string pfx (1, mu_msg_field_xapian_prefix(mfid));
|
||||||
gint64 num = mu_msg_get_field_numeric (msg, field);
|
gint64 num = mu_msg_get_field_numeric (msg, mfid);
|
||||||
const std::string numstr (Xapian::sortable_serialise((double)num));
|
const std::string numstr (Xapian::sortable_serialise((double)num));
|
||||||
|
|
||||||
doc.add_value ((Xapian::valueno)mu_msg_field_id(field), numstr);
|
doc.add_value ((Xapian::valueno)mfid, numstr);
|
||||||
doc.add_term (pfx + 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
|
static void
|
||||||
add_terms_values_string (Xapian::Document& doc, MuMsg *msg,
|
add_terms_values_string (Xapian::Document& doc, MuMsg *msg,
|
||||||
const MuMsgField* field)
|
MuMsgFieldId mfid)
|
||||||
{
|
{
|
||||||
const char* str;
|
const char* str;
|
||||||
|
|
||||||
str = mu_msg_get_field_string (msg, field);
|
str = mu_msg_get_field_string (msg, mfid);
|
||||||
if (!str)
|
if (!str)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const std::string value (str);
|
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;
|
Xapian::TermGenerator termgen;
|
||||||
gchar *norm (mu_msg_str_normalize(str, TRUE));
|
gchar *norm (mu_msg_str_normalize(str, TRUE));
|
||||||
termgen.set_document (doc);
|
termgen.set_document (doc);
|
||||||
|
@ -217,28 +286,24 @@ add_terms_values_string (Xapian::Document& doc, MuMsg *msg,
|
||||||
g_free(norm);
|
g_free(norm);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mu_msg_field_xapian_term(field)) {
|
if (mu_msg_field_xapian_term(mfid)) {
|
||||||
/* terms can be up to MU_STORE_MAX_TERM_LENGTH (240)
|
/* add a normalized version (accents removed,
|
||||||
* long; this is a Xapian limit */
|
* lowercase) */
|
||||||
// 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 */
|
|
||||||
gchar *norm = mu_msg_str_normalize(str, TRUE);
|
gchar *norm = mu_msg_str_normalize(str, TRUE);
|
||||||
doc.add_term (std::string (prefix + std::string(norm), 0,
|
doc.add_term (std::string (prefix + std::string(norm), 0,
|
||||||
MU_STORE_MAX_TERM_LENGTH));
|
MU_STORE_MAX_TERM_LENGTH));
|
||||||
g_free (norm);
|
g_free (norm);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mu_msg_field_xapian_value(field))
|
/* the value is what we'll display; the unchanged original */
|
||||||
doc.add_value ((Xapian::valueno)mu_msg_field_id (field),
|
if (mu_msg_field_xapian_value(mfid))
|
||||||
|
doc.add_value ((Xapian::valueno)mfid,
|
||||||
value);
|
value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_terms_values_body (Xapian::Document& doc, MuMsg *msg,
|
add_terms_values_body (Xapian::Document& doc, MuMsg *msg,
|
||||||
const MuMsgField* field)
|
MuMsgFieldId mfid)
|
||||||
{
|
{
|
||||||
const char *str;
|
const char *str;
|
||||||
char *norm;
|
char *norm;
|
||||||
|
@ -257,7 +322,8 @@ add_terms_values_body (Xapian::Document& doc, MuMsg *msg,
|
||||||
termgen.set_document(doc);
|
termgen.set_document(doc);
|
||||||
|
|
||||||
norm = mu_msg_str_normalize (str, TRUE);
|
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);
|
g_free (norm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,33 +334,34 @@ struct _MsgDoc {
|
||||||
typedef struct _MsgDoc MsgDoc;
|
typedef struct _MsgDoc MsgDoc;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_terms_values (const MuMsgField* field, MsgDoc* msgdoc)
|
add_terms_values (MuMsgFieldId mfid, MsgDoc* msgdoc)
|
||||||
{
|
{
|
||||||
MuMsgFieldType type;
|
MuMsgFieldType type;
|
||||||
|
|
||||||
/* note: contact-stuff (To/Cc/From) will handled in
|
/* note: contact-stuff (To/Cc/From) will handled in
|
||||||
* add_contact_info, not here */
|
* add_contact_info, not here */
|
||||||
if (!mu_msg_field_xapian_index(field) &&
|
if (!mu_msg_field_xapian_index(mfid) &&
|
||||||
!mu_msg_field_xapian_term(field) &&
|
!mu_msg_field_xapian_term(mfid) &&
|
||||||
!mu_msg_field_xapian_value(field))
|
!mu_msg_field_xapian_value(mfid))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
type = mu_msg_field_type (field);
|
type = mu_msg_field_type (mfid);
|
||||||
|
|
||||||
if (type == MU_MSG_FIELD_TYPE_STRING) {
|
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,
|
add_terms_values_body (*msgdoc->_doc, msgdoc->_msg,
|
||||||
field);
|
mfid);
|
||||||
else
|
else
|
||||||
add_terms_values_string (*msgdoc->_doc, msgdoc->_msg,
|
add_terms_values_string (*msgdoc->_doc, msgdoc->_msg,
|
||||||
field);
|
mfid);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == MU_MSG_FIELD_TYPE_BYTESIZE ||
|
if (type == MU_MSG_FIELD_TYPE_BYTESIZE ||
|
||||||
type == MU_MSG_FIELD_TYPE_TIME_T ||
|
type == MU_MSG_FIELD_TYPE_TIME_T ||
|
||||||
type == MU_MSG_FIELD_TYPE_INT) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,39 +372,38 @@ add_terms_values (const MuMsgField* field, MsgDoc* msgdoc)
|
||||||
static void
|
static void
|
||||||
each_contact_info (MuMsgContact *contact, MsgDoc *data)
|
each_contact_info (MuMsgContact *contact, MsgDoc *data)
|
||||||
{
|
{
|
||||||
std::string pfx;
|
const std::string *pfxp;
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
static const std::string to_pfx (mu_msg_field_xapian_prefix(to_field));
|
static const std::string to_pfx (1,
|
||||||
static const std::string from_pfx (mu_msg_field_xapian_prefix(from_field));
|
mu_msg_field_xapian_prefix(MU_MSG_FIELD_ID_TO));
|
||||||
static const std::string cc_pfx (mu_msg_field_xapian_prefix(cc_field));
|
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) {
|
switch (contact->type) {
|
||||||
case MU_MSG_CONTACT_TYPE_TO: pfx = to_pfx; break;
|
case MU_MSG_CONTACT_TYPE_TO: pfxp = &to_pfx; break;
|
||||||
case MU_MSG_CONTACT_TYPE_FROM: pfx = from_pfx; break;
|
case MU_MSG_CONTACT_TYPE_FROM: pfxp = &from_pfx; break;
|
||||||
case MU_MSG_CONTACT_TYPE_CC: pfx = cc_pfx; break;
|
case MU_MSG_CONTACT_TYPE_CC: pfxp = &cc_pfx; break;
|
||||||
default: return; /* other types (like bcc) are ignored */
|
default: return;
|
||||||
|
/* other types (like bcc) are ignored */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (contact->name && strlen(contact->name) > 0) {
|
if (contact->name && strlen(contact->name) > 0) {
|
||||||
Xapian::TermGenerator termgen;
|
Xapian::TermGenerator termgen;
|
||||||
termgen.set_document (*data->_doc);
|
termgen.set_document (*data->_doc);
|
||||||
char *norm = mu_msg_str_normalize (contact->name, TRUE);
|
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);
|
g_free (norm);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* don't normalize e-mail address, but do lowercase it */
|
/* don't normalize e-mail address, but do lowercase it */
|
||||||
if (contact->address && strlen (contact->address)) {
|
if (contact->address && strlen (contact->address)) {
|
||||||
char *lower = g_utf8_strdown (contact->address, -1);
|
char *lower = g_utf8_strdown (contact->address, -1);
|
||||||
data->_doc->add_term (std::string (pfx + lower, 0,
|
data->_doc->add_term
|
||||||
MU_STORE_MAX_TERM_LENGTH));
|
(std::string (*pfxp + lower, 0,
|
||||||
|
MU_STORE_MAX_TERM_LENGTH));
|
||||||
g_free (lower);
|
g_free (lower);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -347,10 +413,8 @@ each_contact_info (MuMsgContact *contact, MsgDoc *data)
|
||||||
static std::string
|
static std::string
|
||||||
get_message_uid (const char* path)
|
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
|
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;
|
return pathprefix + path;
|
||||||
}
|
}
|
||||||
|
@ -377,8 +441,8 @@ mu_store_store (MuStore *store, MuMsg *msg)
|
||||||
/* we must add a unique term, so we can replace
|
/* we must add a unique term, so we can replace
|
||||||
* matching documents */
|
* matching documents */
|
||||||
newdoc.add_term (uid);
|
newdoc.add_term (uid);
|
||||||
mu_msg_field_foreach ((MuMsgFieldForEachFunc)add_terms_values,
|
mu_msg_field_foreach
|
||||||
&msgdoc);
|
((MuMsgFieldForEachFunc)add_terms_values, &msgdoc);
|
||||||
/* also store the contact-info as separate terms */
|
/* also store the contact-info as separate terms */
|
||||||
mu_msg_contact_foreach (msg,
|
mu_msg_contact_foreach (msg,
|
||||||
(MuMsgContactForeachFunc)each_contact_info,
|
(MuMsgContactForeachFunc)each_contact_info,
|
||||||
|
|
|
@ -45,7 +45,7 @@ MuStore* mu_store_new (const char* path);
|
||||||
*
|
*
|
||||||
* @param store a valid store, or NULL
|
* @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);
|
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
|
* @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
|
* set the version string for the database
|
||||||
|
|
|
@ -311,7 +311,8 @@ run_query (const char *xpath, const char *query)
|
||||||
return NULL;
|
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);
|
mu_query_destroy (xapian);
|
||||||
if (!iter) {
|
if (!iter) {
|
||||||
g_warning ("error: running query failed\n");
|
g_warning ("error: running query failed\n");
|
||||||
|
|
Loading…
Reference in New Issue