1
0
Fork 0
mirror of https://github.com/KingDuckZ/dindexer.git synced 2024-11-25 00:53:43 +00:00

Implement tag deletion.

This commit is contained in:
King_DuckZ 2016-05-19 20:17:05 +02:00
parent adcdf56254
commit 7cfc25aeeb
5 changed files with 146 additions and 17 deletions

View file

@ -9,6 +9,7 @@ add_executable(${PROJECT_NAME}
target_include_directories(${PROJECT_NAME}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/..
PRIVATE ${CMAKE_SOURCE_DIR}/lib/glob2regex/include
PRIVATE ${CMAKE_SOURCE_DIR}/lib/better-enums
)
target_link_libraries(${PROJECT_NAME}

View file

@ -27,7 +27,8 @@ namespace din {
bool parse_commandline (int parArgc, char* parArgv[], po::variables_map& parVarMap) {
po::options_description set_options(ACTION_NAME " options");
set_options.add_options()
//("switch,s", "Help message")
("delete,d", "Delete tags instead of adding")
("alltags,a", "Only allowed when --delete is also specified - ignores any given tag list and delete all tags associated to the matching elements instead")
//("option,o", po::value<std::string>()->default_value("default_value"), "Help message")
("ids", po::value<std::string>(), "Comma-separated list of IDs of files to be tagged")
("set,s", po::value<uint32_t>(), "Limit matching to files belonging to the specified set ID")

View file

@ -21,6 +21,7 @@
#include "tag_postgres.hpp"
#include "dindexer-common/split_tags.hpp"
#include "glob2regex/glob2regex.hpp"
#include "enum.h"
#include <iostream>
#include <ciso646>
#include <algorithm>
@ -29,10 +30,9 @@
#include <iterator>
namespace {
enum TaggingModes {
TaggingMode_Glob,
TaggingMode_ID
};
BETTER_ENUM(TaggingMode, char,
Glob, ID
);
std::vector<std::string> globs_to_regex_list (const std::vector<std::string>& parGlobs) {
std::vector<std::string> retval;
@ -46,10 +46,7 @@ namespace {
return retval;
}
int tag_files (const dinlib::SettingsDB& parDB, TaggingModes parMode, const boost::program_options::variables_map& parVM, const std::vector<boost::string_ref>& parTags) {
using boost::lexical_cast;
using boost::string_ref;
din::OwnerSetInfo make_owner_set_info (const boost::program_options::variables_map& parVM) {
din::OwnerSetInfo set_info;
if (parVM.count("set")) {
set_info.is_valid = true;
@ -59,9 +56,17 @@ namespace {
set_info.is_valid = false;
set_info.group_id = 0;
}
return set_info;
}
int tag_files (const dinlib::SettingsDB& parDB, TaggingMode parMode, const boost::program_options::variables_map& parVM, const std::vector<boost::string_ref>& parTags) {
using boost::lexical_cast;
using boost::string_ref;
const din::OwnerSetInfo set_info = make_owner_set_info(parVM);
switch (parMode) {
case TaggingMode_ID:
case TaggingMode::ID:
{
auto ids_string = dinlib::split_tags(parVM["ids"].as<std::string>());
std::vector<uint64_t> ids;
@ -71,7 +76,7 @@ namespace {
return 0;
}
case TaggingMode_Glob:
case TaggingMode::Glob:
{
const auto regexes(globs_to_regex_list(parVM["globs"].as<std::vector<std::string>>()));
din::tag_files(parDB, regexes, parTags, set_info);
@ -83,6 +88,42 @@ namespace {
return 1;
}
}
int delete_tags (const dinlib::SettingsDB& parDB, TaggingMode parMode, const boost::program_options::variables_map& parVM, const std::vector<boost::string_ref>& parTags) {
using boost::lexical_cast;
using boost::string_ref;
assert(parVM.count("delete"));
switch (parMode) {
case TaggingMode::ID:
{
auto ids_string = dinlib::split_tags(parVM["ids"].as<std::string>());
std::vector<uint64_t> ids;
ids.reserve(ids_string.size());
std::transform(ids_string.begin(), ids_string.end(), std::back_inserter(ids), &lexical_cast<uint64_t, string_ref>);
if (parVM.count("alltags"))
din::delete_all_tags(parDB, ids, make_owner_set_info(parVM));
else
din::delete_tags(parDB, ids, parTags, make_owner_set_info(parVM));
return 0;
}
case TaggingMode::Glob:
{
const auto regexes(globs_to_regex_list(parVM["globs"].as<std::vector<std::string>>()));
if (parVM.count("alltags"))
din::delete_all_tags(parDB, regexes, make_owner_set_info(parVM));
else
din::delete_tags(parDB, regexes, parTags, make_owner_set_info(parVM));
return 0;
}
default:
assert(false);
return 1;
}
}
} //unnamed namespace
int main (int parArgc, char* parArgv[]) {
@ -122,11 +163,10 @@ int main (int parArgc, char* parArgv[]) {
const auto master_tags_string = vm["tags"].as<std::string>();
const std::vector<boost::string_ref> tags = dinlib::split_tags(master_tags_string);
const auto mode = (glob_mode ? TaggingMode::Glob : TaggingMode::ID);
return tag_files(
settings.db,
(glob_mode ? TaggingMode_Glob : TaggingMode_ID),
vm,
tags
);
if (not vm.count("delete"))
return tag_files(settings.db, mode, vm, tags);
else
return delete_tags(settings.db, mode, vm, tags);
}

View file

@ -70,4 +70,86 @@ namespace din {
}
}
}
void delete_tags (const dinlib::SettingsDB& parDB, const std::vector<uint64_t>& parFiles, const std::vector<boost::string_ref>& parTags, OwnerSetInfo parSet) {
pq::Connection conn(std::string(parDB.username), std::string(parDB.password), std::string(parDB.dbname), std::string(parDB.address), parDB.port);
conn.connect();
if (parTags.size() == 1) {
if (parSet.is_valid) {
const std::string query = "UPDATE \"files\" SET \"tags\" = ARRAY_REMOVE(tags, $1) WHERE \"id\" = ANY($2) AND \"group_id\" = $3;";
conn.query(query, parTags.front(), parFiles, parSet.group_id);
}
else {
const std::string query = "UPDATE \"files\" SET \"tags\" = ARRAY_REMOVE(tags, $1) WHERE \"id\" = ANY($2);";
conn.query(query, parTags.front(), parFiles);
}
}
else {
if (parSet.is_valid) {
const std::string query = "UPDATE \"files\" SET \"tags\" = ARRAY(SELECT UNNEST(\"tags\") EXCEPT SELECT UNNEST($1)) WHERE \"id\" = ANY($2) AND \"group_id\" = $3;";
conn.query(query, parTags, parFiles, parSet.group_id);
}
else {
const std::string query = "UPDATE \"files\" SET \"tags\" = ARRAY(SELECT UNNEST(\"tags\") EXCEPT SELECT UNNEST($1)) WHERE \"id\" = ANY($2);";
conn.query(query, parTags, parFiles);
}
}
}
void delete_tags (const dinlib::SettingsDB& parDB, const std::vector<std::string>& parRegexes, const std::vector<boost::string_ref>& parTags, OwnerSetInfo parSet) {
pq::Connection conn(std::string(parDB.username), std::string(parDB.password), std::string(parDB.dbname), std::string(parDB.address), parDB.port);
conn.connect();
if (parTags.size() == 1) {
if (parSet.is_valid) {
const std::string query = "UPDATE \"files\" SET \"tags\" = ARRAY_REMOVE(tags, $1) WHERE \"group_id\" = $3 AND \"path\" ~ ANY($3);";
conn.query(query, parTags.front(), parSet.group_id, parRegexes);
}
else {
const std::string query = "UPDATE \"files\" SET \"tags\" = ARRAY_REMOVE(tags, $1) WHERE \"path\" ~ ANY($2);";
conn.query(query, parTags.front(), parRegexes);
}
}
else {
if (parSet.is_valid) {
const std::string query = "UPDATE \"files\" SET \"tags\" = ARRAY(SELECT UNNEST(\"tags\") EXCEPT SELECT UNNEST($1)) WHERE \"group_id\" = $2 AND \"path\" ~ ANY($3);";
conn.query(query, parTags, parSet.group_id, parRegexes);
}
else {
const std::string query = "UPDATE \"files\" SET \"tags\" = ARRAY(SELECT UNNEST(\"tags\") EXCEPT SELECT UNNEST($1)) WHERE \"path\" = ANY($2);";
conn.query(query, parTags, parRegexes);
}
}
}
void delete_all_tags (const dinlib::SettingsDB& parDB, const std::vector<uint64_t>& parFiles, OwnerSetInfo parSet) {
pq::Connection conn(std::string(parDB.username), std::string(parDB.password), std::string(parDB.dbname), std::string(parDB.address), parDB.port);
conn.connect();
if (parSet.is_valid) {
const std::string query =
"UPDATE \"files\" SET \"tags\" = '{}' WHERE \"id\"=ANY($1) AND \"group_id\"=$2;";
conn.query(query, parFiles, parSet.group_id);
}
else {
const std::string query =
"UPDATE \"files\" SET \"tags\" = '{}' WHERE \"id\"=ANY($1);";
conn.query(query, parFiles);
}
}
void delete_all_tags (const dinlib::SettingsDB& parDB, const std::vector<std::string>& parRegexes, OwnerSetInfo parSet) {
pq::Connection conn(std::string(parDB.username), std::string(parDB.password), std::string(parDB.dbname), std::string(parDB.address), parDB.port);
conn.connect();
if (parSet.is_valid) {
const std::string query = "UPDATE \"files\" SET \"tags\" = '{}' WHERE \"group_id\"=$1 AND \"path\" ~ ANY($2);";
conn.query(query, parSet.group_id, parRegexes);
}
else {
const std::string query = "UPDATE \"files\" SET \"tags\" = '{}' WHERE \"path\" ~ ANY($2);";
conn.query(query, parRegexes);
}
}
} //namespace din

View file

@ -34,6 +34,11 @@ namespace din {
void tag_files ( const dinlib::SettingsDB& parDB, const std::vector<uint64_t>& parFiles, const std::vector<boost::string_ref>& parTags, OwnerSetInfo parSet );
void tag_files ( const dinlib::SettingsDB& parDB, const std::vector<std::string>& parRegexes, const std::vector<boost::string_ref>& parTags, OwnerSetInfo parSet );
void delete_tags ( const dinlib::SettingsDB& parDB, const std::vector<uint64_t>& parFiles, const std::vector<boost::string_ref>& parTags, OwnerSetInfo parSet );
void delete_tags ( const dinlib::SettingsDB& parDB, const std::vector<std::string>& parRegexes, const std::vector<boost::string_ref>& parTags, OwnerSetInfo parSet );
void delete_all_tags ( const dinlib::SettingsDB& parDB, const std::vector<uint64_t>& parFiles, OwnerSetInfo parSet );
void delete_all_tags ( const dinlib::SettingsDB& parDB, const std::vector<std::string>& parRegexes, OwnerSetInfo parSet );
} //namespace din
#endif