* add date-range searches using date:/d:

This commit is contained in:
Dirk-Jan C. Binnema 2010-11-21 18:12:01 +02:00
parent c1203dd047
commit e0cada86d6
5 changed files with 88 additions and 31 deletions

View File

@ -104,6 +104,7 @@ search fields and their abbreviations:
msgid,i Message-ID
prio,p Message priority ('low', 'normal' or 'high')
flag,g Message Flags
date,d Date-Range
.fi
For clarity, this man-page uses the longer versions.
@ -159,6 +160,16 @@ can do with a single '/':
(and of course you can use the \fBm:\fR shortcut instead of \fBmaildir:\fR)
The date:/d: search parameter is 'special' in the fact that it takes a range
of dates. For now, these dates are in ISO 8601 format (YYYYMMDD). To get all
messages between (inclusive) the 5th of May 2009 and the 2nd of June 2010, you
could use:
.nf
mu find date:20090505..20100602
.fi
.SH OPTIONS
Note, some of the important options are described in the \fBmu(1)\fR man-page

View File

@ -81,7 +81,7 @@ static const MuMsgField FIELD_DATA[] = {
MU_MSG_FIELD_ID_DATE,
MU_MSG_FIELD_TYPE_TIME_T,
"date", 'd', 'D',
FLAG_GMIME | FLAG_XAPIAN_VALUE
FLAG_GMIME | FLAG_XAPIAN_TERM | FLAG_XAPIAN_VALUE
},
{

View File

@ -41,12 +41,15 @@ enum _MuMsgFieldId {
MU_MSG_FIELD_ID_TO,
MU_MSG_FIELD_ID_MSGID,
MU_MSG_FIELD_ID_TIMESTAMP,
MU_MSG_FIELD_ID_NUM
};
typedef enum _MuMsgFieldId MuMsgFieldId;
static const guint MU_MSG_FIELD_ID_NONE = (guint)-1;
typedef guint MuMsgFieldId;
/* some specials... */
static const MuMsgFieldId MU_MSG_FIELD_ID_NONE = (MuMsgFieldId)-1;
static const MuMsgFieldId MU_MSG_FIELD_ID_DATESTR =
(MuMsgFieldId) (MU_MSG_FIELD_ID_NUM + 1);
#define mu_msg_field_id_is_valid(MFID) \
((MFID) < MU_MSG_FIELD_ID_NUM)

View File

@ -1,4 +1,4 @@
/*
make/*
** Copyright (C) 2008-2010 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
**
** This program is free software; you can redistribute it and/or modify
@ -32,12 +32,36 @@
#include "mu-util-db.h"
#include "mu-msg-str.h"
struct ISODateRangeProcessor : public Xapian::ValueRangeProcessor {
ISODateRangeProcessor() {}
Xapian::valueno operator()(std::string &begin, std::string &end) {
static const std::string colon (":");
static const std::string name (
mu_msg_field_name (MU_MSG_FIELD_ID_DATE) + colon);
static const std::string shortcut (
std::string(1, mu_msg_field_shortcut
(MU_MSG_FIELD_ID_DATE)) + colon);
if (begin.find (name) == 0)
begin.erase (0, name.length());
else if (begin.find (shortcut) == 0)
begin.erase (0, shortcut.length());
else
return Xapian::BAD_VALUENO;
return (Xapian::valueno)MU_MSG_FIELD_ID_DATESTR;
}
};
static void add_prefix (MuMsgFieldId field, Xapian::QueryParser* qparser);
struct _MuQuery {
Xapian::Database* _db;
Xapian::QueryParser* _qparser;
Xapian::Sorter* _sorters[MU_MSG_FIELD_TYPE_NUM];
Xapian::Database* _db;
Xapian::QueryParser* _qparser;
Xapian::Sorter* _sorters[MU_MSG_FIELD_TYPE_NUM];
Xapian::ValueRangeProcessor* _range_processor;
};
gboolean
@ -52,8 +76,11 @@ init_mu_query (MuQuery *mqx, const char* dbpath)
mqx->_qparser->set_database (*mqx->_db);
mqx->_qparser->set_default_op (Xapian::Query::OP_AND);
//mqx->_qparser->set_stemming_strategy (Xapian::QueryParser::STEM_NONE);
mqx->_range_processor = new ISODateRangeProcessor ();
mqx->_qparser->add_valuerangeprocessor
(mqx->_range_processor);
memset (mqx->_sorters, 0, sizeof(mqx->_sorters));
mu_msg_field_foreach ((MuMsgFieldForEachFunc)add_prefix,
(gpointer)mqx->_qparser);
@ -88,7 +115,8 @@ uninit_mu_query (MuQuery *mqx)
try {
delete mqx->_db;
delete mqx->_qparser;
delete mqx->_range_processor;
for (int i = 0; i != MU_MSG_FIELD_TYPE_NUM; ++i)
delete mqx->_sorters[i];

View File

@ -266,6 +266,24 @@ mu_store_flush (MuStore *store)
}
static void
add_terms_values_date (Xapian::Document& doc, MuMsg *msg,
MuMsgFieldId mfid)
{
char datebuf[9];
static const std::string pfx (1, mu_msg_field_xapian_prefix(mfid));
gint64 num = mu_msg_get_field_numeric (msg, mfid);
if (G_UNLIKELY(strftime(datebuf, sizeof(datebuf), "%Y%m%d",
gmtime((const time_t*)&num)) == 0))
g_return_if_reached();
const std::string numstr (Xapian::sortable_serialise((double)num));
doc.add_value ((Xapian::valueno)mfid, numstr);
doc.add_value ((Xapian::valueno)MU_MSG_FIELD_ID_DATESTR, datebuf);
}
static void
add_terms_values_number (Xapian::Document& doc, MuMsg *msg,
MuMsgFieldId mfid)
@ -288,6 +306,7 @@ add_terms_values_number (Xapian::Document& doc, MuMsg *msg,
} else if (mfid == MU_MSG_FIELD_ID_PRIO) {
doc.add_term (pfx + std::string(1,
mu_msg_prio_char((MuMsgPrio)num)));
} else
doc.add_term (pfx + numstr);
}
@ -364,36 +383,32 @@ typedef struct _MsgDoc MsgDoc;
static void
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(mfid) &&
!mu_msg_field_xapian_term(mfid) &&
!mu_msg_field_xapian_value(mfid))
return;
type = mu_msg_field_type (mfid);
if (type == MU_MSG_FIELD_TYPE_STRING) {
if (mfid == MU_MSG_FIELD_ID_BODY_TEXT)
add_terms_values_body (*msgdoc->_doc, msgdoc->_msg,
mfid);
switch (mfid) {
case MU_MSG_FIELD_ID_DATE:
add_terms_values_date (*msgdoc->_doc, msgdoc->_msg, mfid);
break;
case MU_MSG_FIELD_ID_BODY_TEXT:
add_terms_values_body (*msgdoc->_doc, msgdoc->_msg, mfid);
break;
default:
if (mu_msg_field_is_numeric (mfid))
add_terms_values_number (*msgdoc->_doc, msgdoc->_msg,
mfid);
else if (mu_msg_field_type (mfid) ==
MU_MSG_FIELD_TYPE_STRING)
add_terms_values_string (*msgdoc->_doc,
msgdoc->_msg,
mfid);
else
add_terms_values_string (*msgdoc->_doc, msgdoc->_msg,
mfid);
return;
g_return_if_reached ();
}
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,
mfid);
return;
}
g_return_if_reached ();
}