diff --git a/src/locate/commandline.cpp b/src/locate/commandline.cpp index 2f51977..8b2b00c 100644 --- a/src/locate/commandline.cpp +++ b/src/locate/commandline.cpp @@ -29,6 +29,7 @@ namespace din { ("case-insensitive,i", "Disable case sensitivity during search") ("set,s", "Look for matching sets instead of files") ("byhash,a", "Paths on the command line are local paths and searching should be done by content hash") + ("tags,t", po::value(), "Match files only if they belong to the listed tags") //("option,o", po::value()->default_value("default_value"), "Help message") //("option2", po::value(), "Help message") ; diff --git a/src/locate/main.cpp b/src/locate/main.cpp index 615d8b1..7689e0f 100644 --- a/src/locate/main.cpp +++ b/src/locate/main.cpp @@ -18,6 +18,7 @@ #include "commandline.hpp" #include "postgre_locate.hpp" #include "dindexer-common/settings.hpp" +#include "dindexer-common/split_tags.hpp" #include "dindexerConfig.h" #include "hash.hpp" #include "glob2regex/glob2regex.hpp" @@ -42,6 +43,15 @@ namespace din { } } //namespace din +namespace { + std::vector extract_tags (const boost::program_options::variables_map& parVM) { + if (not parVM.count("tags")) + return std::vector(); + else + return dinlib::split_tags(parVM["tags"].as()); + } +} //unnamed namespace + int main (int parArgc, char* parArgv[]) { using boost::program_options::variables_map; @@ -76,14 +86,15 @@ int main (int parArgc, char* parArgv[]) { } else { std::vector results; + const std::vector tags = extract_tags(vm); if (vm.count("byhash")) { const auto hash = din::hash(vm["substring"].as()); - results = din::locate_in_db(settings.db, hash); + results = din::locate_in_db(settings.db, hash, tags); } else { const auto search_regex = g2r::convert(vm["substring"].as()); - results = din::locate_in_db(settings.db, search_regex, not not vm.count("case-insensitive")); + results = din::locate_in_db(settings.db, search_regex, not not vm.count("case-insensitive"), tags); } std::copy(results.begin(), results.end(), std::ostream_iterator(std::cout, "\n")); } diff --git a/src/locate/postgre_locate.cpp b/src/locate/postgre_locate.cpp index ed1201f..37f1d02 100644 --- a/src/locate/postgre_locate.cpp +++ b/src/locate/postgre_locate.cpp @@ -68,29 +68,46 @@ namespace din { return retval; } + + template + std::vector locate_in_db (pq::Connection& parConn, const char* parBaseQuery, std::size_t parBaseQueryLength, const char* parTagsParamToken, const TagList& parTags, const P&... parParams) { + using boost::lexical_cast; + + assert(parTagsParamToken or parTags.empty()); + auto query = std::string(parBaseQuery, parBaseQueryLength); + if (not parTags.empty()) { + query += " AND \"tags\" @> "; + query += parTagsParamToken; + } + query += " LIMIT "; + query += lexical_cast(g_max_results); + query += ";"; + + if (parTags.empty()) { + auto result = parConn.query(query, parParams...); + return file_result_to_vec(std::move(result)); + } + else { + auto result = parConn.query(query, parParams..., parTags); + return file_result_to_vec(std::move(result)); + } + } } //unnamed namespace - std::vector locate_in_db (const dinlib::SettingsDB& parDB, const std::string& parSearch, bool parCaseInsensitive) { + std::vector locate_in_db (const dinlib::SettingsDB& parDB, const std::string& parSearch, bool parCaseInsensitive, const TagList& parTags) { auto conn = make_pq_conn(parDB); const auto clean_string_with_quotes = conn.escaped_literal(parSearch); const std::string search_regex = (parCaseInsensitive ? "(?i)" : "") + parSearch; - const std::string query = - std::string("SELECT \"path\",\"id\",\"group_id\" FROM \"files\" WHERE \"path\" ~ $1 LIMIT ") + - boost::lexical_cast(g_max_results) + - ";"; - - auto result = conn.query(query, search_regex); - return file_result_to_vec(std::move(result)); + const char base_query[] = "SELECT \"path\",\"id\",\"group_id\" FROM \"files\" WHERE \"path\" ~ $1"; + return locate_in_db(conn, base_query, sizeof(base_query) - 1, "$2", parTags, search_regex); } - std::vector locate_in_db (const dinlib::SettingsDB& parDB, const mchlib::TigerHash& parSearch) { - const std::string query = std::string("SELECT \"path\",\"id\",\"group_id\" FROM \"files\" WHERE \"hash\"=$1 LIMIT ") + boost::lexical_cast(g_max_results) + ';'; - + std::vector locate_in_db (const dinlib::SettingsDB& parDB, const mchlib::TigerHash& parSearch, const TagList& parTags) { auto conn = make_pq_conn(parDB); - auto result = conn.query(query, mchlib::tiger_to_string(parSearch, true)); - return file_result_to_vec(std::move(result)); + const char base_query[] = "SELECT \"path\",\"id\",\"group_id\" FROM \"files\" WHERE \"hash\"=$1"; + return locate_in_db(conn, base_query, sizeof(base_query) - 1, "$2", parTags, mchlib::tiger_to_string(parSearch, true)); } std::vector locate_sets_in_db (const dinlib::SettingsDB& parDB, const std::string& parSearch, bool parCaseInsensitive) { diff --git a/src/locate/postgre_locate.hpp b/src/locate/postgre_locate.hpp index 917d687..061db5f 100644 --- a/src/locate/postgre_locate.hpp +++ b/src/locate/postgre_locate.hpp @@ -22,6 +22,7 @@ #include #include #include +#include namespace mchlib { struct TigerHash; @@ -41,8 +42,10 @@ namespace din { uint32_t dir_count; }; - std::vector locate_in_db ( const dinlib::SettingsDB& parDB, const std::string& parSearch, bool parCaseInsensitive ); - std::vector locate_in_db ( const dinlib::SettingsDB& parDB, const mchlib::TigerHash& parSearch ); + using TagList = std::vector; + + std::vector locate_in_db ( const dinlib::SettingsDB& parDB, const std::string& parSearch, bool parCaseInsensitive, const TagList& parTags ); + std::vector locate_in_db ( const dinlib::SettingsDB& parDB, const mchlib::TigerHash& parSearch, const TagList& parTags ); std::vector locate_sets_in_db ( const dinlib::SettingsDB& parDB, const std::string& parSearch, bool parCaseInsensitive ); std::vector locate_sets_in_db ( const dinlib::SettingsDB& parDB, const std::string& parSearch, const std::vector& parSets, bool parCaseInsensitive ); } //namespace din