From b955f42655311dfdf43d4f536011b0c19653c0c6 Mon Sep 17 00:00:00 2001 From: dockes Date: Fri, 7 Apr 2006 13:10:22 +0000 Subject: [PATCH] check for and forbid pure negative query --- src/qtgui/advsearch.ui.h | 13 +++++++++ src/rcldb/rcldb.cpp | 63 ++++++++++++++++++++++++---------------- 2 files changed, 51 insertions(+), 25 deletions(-) diff --git a/src/qtgui/advsearch.ui.h b/src/qtgui/advsearch.ui.h index 7561ccc8..4081373e 100644 --- a/src/qtgui/advsearch.ui.h +++ b/src/qtgui/advsearch.ui.h @@ -27,6 +27,7 @@ *****************************************************************************/ #include +#include #include #include @@ -127,11 +128,23 @@ void advsearch::restrictFtCB_toggled(bool on) void advsearch::searchPB_clicked() { Rcl::AdvSearchData mydata; + mydata.allwords = string((const char*)(andWordsLE->text().utf8())); mydata.phrase = string((const char*)(phraseLE->text().utf8())); mydata.orwords = string((const char*)(orWordsLE->text().utf8())); mydata.nowords = string((const char*)(noWordsLE->text().utf8())); mydata.filename = string((const char*)(fileNameLE->text().utf8())); + + if (mydata.allwords.empty() && mydata.phrase.empty() && + mydata.orwords.empty() && mydata.filename.empty()) { + if (mydata.nowords.empty()) + return; + QMessageBox::warning(0, "Recoll", + tr("Cannot execute pure negative query. " + "Please enter common terms in the 'any words' field")); + return; + } + if (restrictFtCB->isOn() && noFiltypsLB->count() > 0) { for (unsigned int i = 0; i < yesFiltypsLB->count(); i++) { QCString ctext = yesFiltypsLB->item(i)->text().utf8(); diff --git a/src/rcldb/rcldb.cpp b/src/rcldb/rcldb.cpp index a213939f..6664d566 100644 --- a/src/rcldb/rcldb.cpp +++ b/src/rcldb/rcldb.cpp @@ -1,5 +1,5 @@ #ifndef lint -static char rcsid[] = "@(#$Id: rcldb.cpp,v 1.62 2006-04-05 13:39:07 dockes Exp $ (C) 2004 J.F.Dockes"; +static char rcsid[] = "@(#$Id: rcldb.cpp,v 1.63 2006-04-07 13:10:22 dockes Exp $ (C) 2004 J.F.Dockes"; #endif /* * This program is free software; you can redistribute it and/or modify @@ -545,13 +545,6 @@ bool Db::add(const string &fn, const Doc &idoc, // Mime type newdocument.add_term("T" + doc.mimetype); - // Path name term. This is used for existence/uptodate checks - string hash; - pathHash(fn, hash, PATHHASHLEN); - LOGDEB2(("Db::add: pathhash [%s]\n", hash.c_str())); - string pathterm = "P" + hash; - newdocument.add_term(pathterm); - // Simple file name. This is used for file name searches only. We index // it with a term prefix. utf8fn used to be the full path, but it's now // the simple file name. @@ -560,10 +553,23 @@ bool Db::add(const string &fn, const Doc &idoc, newdocument.add_term(noacc); } - // Internal path: with path, makes unique identifier for documents + // Pathname/ipath terms. This is used for file existence/uptodate + // checks, and unique id for the replace_document() call + + // Truncate the filepath part to a reasonable length and + // replace the truncated part with a hopefully unique hash + string hash; + pathHash(fn, hash, PATHHASHLEN); + LOGDEB2(("Db::add: pathhash [%s]\n", hash.c_str())); + string pathterm = "P" + hash; + newdocument.add_term(pathterm); + + // Unique term: with path, makes unique identifier for documents // inside multidocument files. string uniterm; - if (!doc.ipath.empty()) { + if (doc.ipath.empty()) { + uniterm = pathterm; + } else { uniterm = "Q" + hash + "|" + doc.ipath; newdocument.add_term(uniterm); } @@ -617,8 +623,7 @@ bool Db::add(const string &fn, const Doc &idoc, // Add db entry or update existing entry: try { Xapian::docid did = - m_ndb->wdb.replace_document(uniterm.empty() ? pathterm : uniterm, - newdocument); + m_ndb->wdb.replace_document(uniterm, newdocument); if (did < m_ndb->updated.size()) { m_ndb->updated[did] = true; LOGDEB(("Db::add: docid %d updated [%s , %s]\n", did, fnc, @@ -1216,19 +1221,6 @@ bool Db::setQuery(AdvSearchData &sdata, QueryOpts opts, } } - // We do no stem expansion on 'No' words. Should we ? - if (!sdata.nowords.empty()) { - stringToXapianQueries(sdata.nowords, stemlang, m_ndb, pqueries); - if (!pqueries.empty()) { - Xapian::Query nq; - nq = Xapian::Query(Xapian::Query::OP_OR, pqueries.begin(), - pqueries.end()); - xq = xq.empty() ? nq : - Xapian::Query(Xapian::Query::OP_AND_NOT, xq, nq); - pqueries.clear(); - } - } - if (!sdata.phrase.empty()) { Xapian::Query nq; string s = string("\"") + sdata.phrase + string("\""); @@ -1253,6 +1245,27 @@ bool Db::setQuery(AdvSearchData &sdata, QueryOpts opts, xq = xq.empty() ? tq : Xapian::Query(Xapian::Query::OP_FILTER, xq, tq); } + // "And not" part. Must come last, as we have to check it's not + // the only term in the query. We do no stem expansion on 'No' + // words. Should we ? + if (!sdata.nowords.empty()) { + stringToXapianQueries(sdata.nowords, stemlang, m_ndb, pqueries); + if (!pqueries.empty()) { + Xapian::Query nq; + nq = Xapian::Query(Xapian::Query::OP_OR, pqueries.begin(), + pqueries.end()); + if (xq.empty()) { + // Xapian cant do this currently. Have to have a positive + // part! + sdata.description = "Error: pure negative query\n"; + LOGERR(("Rcl::Db::setQuery: error: pure negative query\n")); + return false; + } + xq = Xapian::Query(Xapian::Query::OP_AND_NOT, xq, nq); + pqueries.clear(); + } + } + m_ndb->query = xq; delete m_ndb->enquire; m_ndb->enquire = new Xapian::Enquire(m_ndb->db);