1
0
Fork 0
mirror of https://github.com/KingDuckZ/dindexer.git synced 2025-07-13 15:54:11 +00:00

Re-enable navigate in the postgre plugin.

This commit is contained in:
King_DuckZ 2016-06-02 09:35:33 +02:00
parent 780cd9b0ca
commit dfe3655296
11 changed files with 238 additions and 238 deletions

View file

@ -5,7 +5,7 @@ add_library(${PROJECT_NAME} SHARED
delete.cpp
locate.cpp
scan.cpp
#dbsource.cpp
navigate.cpp
backend_postgresql.cpp
)

View file

@ -21,6 +21,7 @@
#include "delete.hpp"
#include "scan.hpp"
#include "locate.hpp"
#include "navigate.hpp"
#include "pq/connection.hpp"
#include <ciso646>
#include <utility>
@ -79,6 +80,14 @@ namespace dindb {
m_conn->disconnect();
}
void BackendPostgreSql::connect() {
m_conn->connect();
}
void BackendPostgreSql::disconnect() {
m_conn->disconnect();
}
void BackendPostgreSql::tag_files (const std::vector<FileIDType>& parFiles, const std::vector<boost::string_ref>& parTags, GroupIDType parSet) {
dindb::tag_files(*m_conn, parFiles, parTags, parSet);
}
@ -130,6 +139,22 @@ namespace dindb {
std::vector<LocatedSet> BackendPostgreSql::locate_sets_in_db (const std::string& parSearch, const std::vector<GroupIDType>& parSets, bool parCaseInsensitive) {
return dindb::locate_sets_in_db(*m_conn, parSearch, parSets, parCaseInsensitive);
}
std::vector<GroupIDType> BackendPostgreSql::find_all_sets() {
return dindb::find_all_sets(*m_conn);
}
std::vector<dinhelp::MaxSizedArray<std::string, 3>> BackendPostgreSql::find_set_details (const std::vector<GroupIDType>& parSets) {
return dindb::find_set_details<dindb::SetDetail_ID, dindb::SetDetail_Desc, dindb::SetDetail_CreeationDate>(*m_conn, parSets);
}
std::vector<dinhelp::MaxSizedArray<std::string, 1>> BackendPostgreSql::find_file_details (GroupIDType parSetID, uint16_t parLevel, boost::string_ref parDir) {
return dindb::find_file_details<dindb::FileDetail_Path>(*m_conn, parSetID, parLevel, parDir);
}
std::vector<std::string> BackendPostgreSql::find_paths_starting_by (GroupIDType parGroupID, uint16_t parLevel, boost::string_ref parPath) {
return dindb::find_paths_starting_by(*m_conn, parGroupID, parLevel, parPath);
}
} //namespace dindb
extern "C" dindb::Backend* dindexer_create_backend (const YAML::Node* parConfig) {

View file

@ -34,6 +34,9 @@ namespace dindb {
BackendPostgreSql ( std::string&& parUser, std::string&& parPass, std::string&& parDB, std::string&& parAddr, uint16_t parPort );
virtual ~BackendPostgreSql ( void ) noexcept;
virtual void connect ( void );
virtual void disconnect ( void );
virtual void tag_files ( const std::vector<FileIDType>& parFiles, const std::vector<boost::string_ref>& parTags, GroupIDType parSet ) override;
virtual void tag_files ( const std::vector<std::string>& parRegexes, const std::vector<boost::string_ref>& parTags, GroupIDType parSet ) override;
virtual void delete_tags ( const std::vector<FileIDType>& parFiles, const std::vector<boost::string_ref>& parTags, GroupIDType parSet ) override;
@ -51,6 +54,11 @@ namespace dindb {
virtual std::vector<LocatedSet> locate_sets_in_db ( const std::string& parSearch, bool parCaseInsensitive );
virtual std::vector<LocatedSet> locate_sets_in_db ( const std::string& parSearch, const std::vector<GroupIDType>& parSets, bool parCaseInsensitive );
virtual std::vector<GroupIDType> find_all_sets ( void );
virtual std::vector<dinhelp::MaxSizedArray<std::string, 3>> find_set_details ( const std::vector<GroupIDType>& parSets );
virtual std::vector<dinhelp::MaxSizedArray<std::string, 1>> find_file_details ( GroupIDType parSetID, uint16_t parLevel, boost::string_ref parDir );
virtual std::vector<std::string> find_paths_starting_by ( GroupIDType parGroupID, uint16_t parLevel, boost::string_ref parPath );
private:
std::unique_ptr<pq::Connection> m_conn;
};

View file

@ -1,183 +0,0 @@
/* Copyright 2015, 2016, Michele Santullo
* This file is part of "dindexer".
*
* "dindexer" is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* "dindexer" is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with "dindexer". If not, see <http://www.gnu.org/licenses/>.
*/
#include "db/dbsource.hpp"
#include "db/settings.hpp"
#include "pq/connection.hpp"
#include "helpers/infix_iterator.hpp"
#include <ciso646>
#include <utility>
#include <boost/lexical_cast.hpp>
#include <sstream>
#include <boost/range/algorithm/copy.hpp>
namespace dindb {
namespace {
const uint32_t g_files_query_limit = 500;
std::ostream& operator<< (std::ostream& parOut, const std::vector<std::string>& parCols) {
parOut << '"';
boost::copy(parCols, infix_ostream_iterator<std::string>(parOut, "\", \""));
parOut << '"';
return parOut;
}
} //unnamed namespace
const DBSource::SetDetailsMap DBSource::m_set_details_map {
{SetDetail_Desc, "desc"},
{SetDetail_Type, "type"},
{SetDetail_CreeationDate, "creation"},
{SetDetail_AppName, "app_name"},
{SetDetail_ID, "id"}
};
const DBSource::FileDetailsMap DBSource::m_file_details_map {
{FileDetail_ID, "id"},
{FileDetail_Path, "path"},
{FileDetail_Level, "level"},
{FileDetail_GroupID, "group_id"},
{FileDetail_IsDir, "is_directory"},
{FileDetail_IsSymLink, "is_symlink"},
{FileDetail_Size, "size"},
{FileDetail_Hash, "hash"},
{FileDetail_IsHashValid, "is_hash_valid"},
{FileDetail_ATime, "access_time"},
{FileDetail_MTime, "modify_time"},
{FileDetail_Unreadable, "unreadable"},
{FileDetail_MimeType, "mimetype"},
{FileDetail_Charset, "charset"}
};
struct DBSource::LocalData {
explicit LocalData ( const Settings& parDBSettings ) :
conn(
std::string(parDBSettings.username),
std::string(parDBSettings.password),
std::string(parDBSettings.dbname),
std::string(parDBSettings.address),
parDBSettings.port
)
{
}
pq::Connection conn;
};
DBSource::DBSource (const Settings& parDBSettings) :
m_local_data(new LocalData(parDBSettings))
{
assert(not m_local_data->conn.is_connected());
}
DBSource::~DBSource() noexcept {
}
void DBSource::disconnect() {
if (m_local_data->conn.is_connected()) {
m_local_data->conn.disconnect();
}
}
pq::Connection& DBSource::get_conn() {
if (not m_local_data->conn.is_connected()) {
m_local_data->conn.connect();
}
return m_local_data->conn;
}
std::vector<uint32_t> DBSource::sets() {
using boost::lexical_cast;
auto& conn = get_conn();
const std::string query = "SELECT \"id\" FROM \"sets\";";
auto res = conn.query(query);
std::vector<uint32_t> retval;
retval.reserve(res.size());
for (const auto& row : res) {
retval.push_back(lexical_cast<uint32_t>(row[0]));
}
return retval;
}
void DBSource::query_no_conditions (const ColumnList& parCols, boost::string_ref parTable, const std::vector<uint32_t>& parIDs, std::function<void(std::string&&)> parCallback) {
std::ostringstream oss;
oss << "SELECT " << parCols << ' ' <<
"FROM \"" << parTable << "\" " <<
"WHERE \"id\"=ANY($1) " <<
"ORDER BY \"desc\" ASC " <<
"LIMIT " << g_files_query_limit << ';';
auto& conn = get_conn();
auto result = conn.query(oss.str(), parIDs);
for (auto row : result) {
for (auto val : row) {
parCallback(std::move(val));
}
}
}
void DBSource::query_files_in_dir (const ColumnList& parCols, boost::string_ref parDir, uint16_t parLevel, uint32_t parGroupID, QueryCallback parCallback) {
std::ostringstream oss;
oss << "SELECT " << parCols << ' ' <<
"FROM \"files\" WHERE " <<
"\"level\"=$1 " <<
"AND \"group_id\"=$2 " <<
"AND str_begins_with(\"path\", COALESCE($3, '')) " <<
"ORDER BY \"is_directory\" DESC, \"path\" ASC " <<
"LIMIT " << g_files_query_limit << ';';
auto& conn = get_conn();
auto result = conn.query(
oss.str(),
parLevel,
parGroupID,
parDir
);
for (auto row : result) {
for (auto val : row) {
parCallback(std::move(val));
}
}
}
std::vector<std::string> DBSource::paths_starting_by (uint32_t parGroupID, uint16_t parLevel, boost::string_ref parPath) {
std::ostringstream oss;
oss << "SELECT \"path\" ||\n" <<
"(SELECT CASE \"is_directory\"\n" <<
"WHEN TRUE THEN '/'\n" <<
"ELSE ''\n" <<
"END) as path FROM \"files\" WHERE \"group_id\"=$1 AND " <<
"\"level\"=$2 AND str_begins_with(\"path\", COALESCE($3, '')) " <<
"ORDER BY \"is_directory\" DESC, \"path\" ASC LIMIT " <<
g_files_query_limit << ';';
auto& conn = get_conn();
auto result = conn.query(
oss.str(),
parGroupID,
parLevel,
parPath
);
std::vector<std::string> retval;
retval.reserve(retval.size());
for (auto row : result) {
assert(not row.empty());
retval.push_back(row[0]);
}
return retval;
}
} //namespace dindb

View file

@ -0,0 +1,152 @@
/* Copyright 2015, 2016, Michele Santullo
* This file is part of "dindexer".
*
* "dindexer" is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* "dindexer" is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with "dindexer". If not, see <http://www.gnu.org/licenses/>.
*/
#include "navigate.hpp"
#include "pq/connection.hpp"
#include "helpers/infix_iterator.hpp"
#include <ciso646>
#include <utility>
#include <boost/lexical_cast.hpp>
#include <sstream>
#include <boost/range/algorithm/copy.hpp>
#include <cassert>
namespace dindb {
namespace {
const uint32_t g_files_query_limit = 500;
std::ostream& operator<< (std::ostream& parOut, const std::vector<std::string>& parCols) {
parOut << '"';
boost::copy(parCols, infix_ostream_iterator<std::string>(parOut, "\", \""));
parOut << '"';
return parOut;
}
} //unnamed namespace
namespace implem {
const SetDetailsMap g_set_details_map {
{SetDetail_Desc, "desc"},
{SetDetail_Type, "type"},
{SetDetail_CreeationDate, "creation"},
{SetDetail_AppName, "app_name"},
{SetDetail_ID, "id"}
};
const FileDetailsMap g_file_details_map {
{FileDetail_ID, "id"},
{FileDetail_Path, "path"},
{FileDetail_Level, "level"},
{FileDetail_GroupID, "group_id"},
{FileDetail_IsDir, "is_directory"},
{FileDetail_IsSymLink, "is_symlink"},
{FileDetail_Size, "size"},
{FileDetail_Hash, "hash"},
{FileDetail_IsHashValid, "is_hash_valid"},
{FileDetail_ATime, "access_time"},
{FileDetail_MTime, "modify_time"},
{FileDetail_Unreadable, "unreadable"},
{FileDetail_MimeType, "mimetype"},
{FileDetail_Charset, "charset"}
};
void query_no_conditions (pq::Connection& parDB, const ColumnList& parCols, boost::string_ref parTable, const std::vector<GroupIDType>& parIDs, std::function<void(std::string&&)> parCallback) {
assert(parDB.is_connected());
std::ostringstream oss;
oss << "SELECT " << parCols << ' ' <<
"FROM \"" << parTable << "\" " <<
"WHERE \"id\"=ANY($1) " <<
"ORDER BY \"desc\" ASC " <<
"LIMIT " << g_files_query_limit << ';';
auto result = parDB.query(oss.str(), parIDs);
for (auto row : result) {
for (auto val : row) {
parCallback(std::move(val));
}
}
}
void query_files_in_dir (pq::Connection& parDB, const ColumnList& parCols, boost::string_ref parDir, uint16_t parLevel, GroupIDType parGroupID, QueryCallback parCallback) {
assert(parDB.is_connected());
std::ostringstream oss;
oss << "SELECT " << parCols << ' ' <<
"FROM \"files\" WHERE " <<
"\"level\"=$1 " <<
"AND \"group_id\"=$2 " <<
"AND str_begins_with(\"path\", COALESCE($3, '')) " <<
"ORDER BY \"is_directory\" DESC, \"path\" ASC " <<
"LIMIT " << g_files_query_limit << ';';
auto result = parDB.query(
oss.str(),
parLevel,
parGroupID,
parDir
);
for (auto row : result) {
for (auto val : row) {
parCallback(std::move(val));
}
}
}
} //namespace implem
std::vector<GroupIDType> find_all_sets (pq::Connection& parDB) {
using boost::lexical_cast;
assert(parDB.is_connected());
const std::string query = "SELECT \"id\" FROM \"sets\";";
auto res = parDB.query(query);
std::vector<GroupIDType> retval;
retval.reserve(res.size());
for (const auto& row : res) {
retval.push_back(lexical_cast<GroupIDType>(row[0]));
}
return retval;
}
std::vector<std::string> find_paths_starting_by (pq::Connection& parDB, GroupIDType parGroupID, uint16_t parLevel, boost::string_ref parPath) {
assert(parDB.is_connected());
std::ostringstream oss;
oss << "SELECT \"path\" ||\n" <<
"(SELECT CASE \"is_directory\"\n" <<
"WHEN TRUE THEN '/'\n" <<
"ELSE ''\n" <<
"END) as path FROM \"files\" WHERE \"group_id\"=$1 AND " <<
"\"level\"=$2 AND str_begins_with(\"path\", COALESCE($3, '')) " <<
"ORDER BY \"is_directory\" DESC, \"path\" ASC LIMIT " <<
g_files_query_limit << ';';
auto result = parDB.query(
oss.str(),
parGroupID,
parLevel,
parPath
);
std::vector<std::string> retval;
retval.reserve(retval.size());
for (auto row : result) {
assert(not row.empty());
retval.push_back(row[0]);
}
return retval;
}
} //namespace dindb

View file

@ -21,6 +21,7 @@
#include "dindexer-machinery/recorddata.hpp"
#include "helpers/flatinsertin2dlist.hpp"
#include "helpers/MaxSizedArray.hpp"
#include "backends/db_backend.hpp"
#include <memory>
#include <cstdint>
#include <vector>
@ -38,8 +39,6 @@ namespace pq {
namespace dindb {
using dinhelp::MaxSizedArray;
struct Settings;
enum SetDetails {
SetDetail_Desc = 0x01,
SetDetail_Type = 0x02,
@ -65,40 +64,25 @@ namespace dindb {
FileDetail_Charset = 0x2000
};
class DBSource {
public:
explicit DBSource ( const Settings& parDBSettings );
~DBSource ( void ) noexcept;
std::vector<GroupIDType> find_all_sets ( pq::Connection& parDB );
void disconnect ( void );
std::vector<uint32_t> sets ( void );
template <SetDetails... D>
auto find_set_details ( pq::Connection& parDB, const std::vector<GroupIDType>& parIDs ) -> std::vector<MaxSizedArray<std::string, sizeof...(D)>>;
template <SetDetails... D>
auto set_details ( const std::vector<uint32_t>& parIDs ) -> std::vector<MaxSizedArray<std::string, sizeof...(D)>>;
template <FileDetails... D>
auto find_file_details ( pq::Connection& parDB, GroupIDType parSetID, uint16_t parLevel, boost::string_ref parDir ) -> std::vector<MaxSizedArray<std::string, sizeof...(D)>>;
template <FileDetails... D>
auto file_details ( uint32_t parSetID, uint16_t parLevel, boost::string_ref parDir ) -> std::vector<MaxSizedArray<std::string, sizeof...(D)>>;
std::vector<std::string> paths_starting_by ( uint32_t parGroupID, uint16_t parLevel, boost::string_ref parPath );
private:
struct LocalData;
typedef std::map<SetDetails, std::string> SetDetailsMap;
typedef std::map<FileDetails, std::string> FileDetailsMap;
typedef std::vector<std::string> ColumnList;
typedef std::function<void(std::string&&)> QueryCallback;
pq::Connection& get_conn ( void );
void query_no_conditions ( const ColumnList& parCols, boost::string_ref parTable, const std::vector<uint32_t>& parIDs, QueryCallback parCallback );
void query_files_in_dir ( const ColumnList& parCols, boost::string_ref parDir, uint16_t parLevel, uint32_t parGroupID, QueryCallback parCallback );
static const SetDetailsMap m_set_details_map;
static const FileDetailsMap m_file_details_map;
std::unique_ptr<LocalData> m_local_data;
};
std::vector<std::string> find_paths_starting_by ( pq::Connection& parDB, GroupIDType parGroupID, uint16_t parLevel, boost::string_ref parPath );
namespace implem {
typedef std::vector<std::string> ColumnList;
typedef std::function<void(std::string&&)> QueryCallback;
typedef std::map<SetDetails, std::string> SetDetailsMap;
typedef std::map<FileDetails, std::string> FileDetailsMap;
extern const SetDetailsMap g_set_details_map;
extern const FileDetailsMap g_file_details_map;
template <class M, M... Details>
inline
std::vector<std::string> make_columns_vec (const std::map<M, std::string>& parDic) {
@ -115,35 +99,40 @@ namespace dindb {
}
return columns;
}
void query_no_conditions ( pq::Connection& parDB, const ColumnList& parCols, boost::string_ref parTable, const std::vector<GroupIDType>& parIDs, QueryCallback parCallback );
void query_files_in_dir ( pq::Connection& parDB, const ColumnList& parCols, boost::string_ref parDir, uint16_t parLevel, GroupIDType parGroupID, QueryCallback parCallback );
} //namespace implem
template <SetDetails... D>
auto DBSource::set_details (const std::vector<uint32_t>& parIDs) -> std::vector<MaxSizedArray<std::string, sizeof...(D)>> {
inline
auto find_set_details (pq::Connection& parDB, const std::vector<GroupIDType>& parIDs) -> std::vector<MaxSizedArray<std::string, sizeof...(D)>> {
using dinhelp::FlatInsertIn2DList;
typedef std::vector<MaxSizedArray<std::string, sizeof...(D)>> ReturnType;
typedef void(FlatInsertIn2DList<ReturnType>::*FlatPushBackFunc)(std::string&&);
const auto columns = implem::make_columns_vec<SetDetails, D...>(m_set_details_map);
const auto columns = implem::make_columns_vec<SetDetails, D...>(implem::g_set_details_map);
ReturnType list;
FlatInsertIn2DList<ReturnType> flat_list(&list, sizeof...(D));
FlatPushBackFunc pback_func = &FlatInsertIn2DList<ReturnType>::push_back;
this->query_no_conditions(columns, "sets", parIDs, std::bind(pback_func, &flat_list, std::placeholders::_1));
implem::query_no_conditions(parDB, columns, "sets", parIDs, std::bind(pback_func, &flat_list, std::placeholders::_1));
return list;
}
template <FileDetails... D>
auto DBSource::file_details (uint32_t parSetID, uint16_t parLevel, boost::string_ref parDir) -> std::vector<MaxSizedArray<std::string, sizeof...(D)>> {
inline
auto find_file_details (pq::Connection& parDB, GroupIDType parSetID, uint16_t parLevel, boost::string_ref parDir) -> std::vector<MaxSizedArray<std::string, sizeof...(D)>> {
using dinhelp::FlatInsertIn2DList;
typedef std::vector<MaxSizedArray<std::string, sizeof...(D)>> ReturnType;
typedef void(FlatInsertIn2DList<ReturnType>::*FlatPushBackFunc)(std::string&&);
const auto columns = implem::make_columns_vec<FileDetails, D...>(m_file_details_map);
const auto columns = implem::make_columns_vec<FileDetails, D...>(implem::g_file_details_map);
ReturnType list;
FlatInsertIn2DList<ReturnType> flat_list(&list, sizeof...(D));
FlatPushBackFunc pback_func = &FlatInsertIn2DList<ReturnType>::push_back;
this->query_files_in_dir(columns, parDir, parLevel, parSetID, std::bind(pback_func, &flat_list, std::placeholders::_1));
implem::query_files_in_dir(parDB, columns, parDir, parLevel, parSetID, std::bind(pback_func, &flat_list, std::placeholders::_1));
return list;
}
} //namespace dindb