* 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

@ -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 ();
}