mirror of
https://github.com/KingDuckZ/dindexer.git
synced 2024-11-25 00:53:43 +00:00
Implement ls into subdirectories
This commit is contained in:
parent
362a5d3128
commit
f40600d6e2
6 changed files with 167 additions and 33 deletions
|
@ -29,6 +29,8 @@
|
||||||
namespace din {
|
namespace din {
|
||||||
const size_t MAXSZARR_MAX_STACK_ALLOC_SIZE = MAX_STACK_ALLOC_SIZE;
|
const size_t MAXSZARR_MAX_STACK_ALLOC_SIZE = MAX_STACK_ALLOC_SIZE;
|
||||||
|
|
||||||
|
//TODO: add a template parameter to force stack allocation regardless of
|
||||||
|
//sizeof(T) * S
|
||||||
template <typename T, size_t S, typename A=std::allocator<T> >
|
template <typename T, size_t S, typename A=std::allocator<T> >
|
||||||
class MaxSizedArray :
|
class MaxSizedArray :
|
||||||
private std::conditional<
|
private std::conditional<
|
||||||
|
|
|
@ -26,6 +26,41 @@
|
||||||
#include <boost/range/algorithm/copy.hpp>
|
#include <boost/range/algorithm/copy.hpp>
|
||||||
|
|
||||||
namespace din {
|
namespace din {
|
||||||
|
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 {
|
struct DBSource::LocalData {
|
||||||
explicit LocalData ( const dinlib::SettingsDB& parDBSettings ) :
|
explicit LocalData ( const dinlib::SettingsDB& parDBSettings ) :
|
||||||
conn(
|
conn(
|
||||||
|
@ -78,12 +113,13 @@ namespace din {
|
||||||
return std::move(retval);
|
return std::move(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DBSource::query_push_results (const std::vector<std::string>& parCols, boost::string_ref parTable, const std::vector<uint32_t>& parIDs, std::function<void(std::string&&)> parCallback) {
|
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;
|
std::ostringstream oss;
|
||||||
oss << "SELECT \"";
|
oss << "SELECT " << parCols << ' ' <<
|
||||||
boost::copy(parCols, infix_ostream_iterator<std::string>(oss, "\", \""));
|
"FROM \"" << parTable << "\" " <<
|
||||||
oss << '"';
|
"WHERE \"id\"=ANY($1) " <<
|
||||||
oss << " FROM \"" << parTable << "\" WHERE \"id\" = ANY($1) ORDER BY \"desc\" ASC LIMIT 500;";
|
"ORDER BY \"desc\" ASC " <<
|
||||||
|
"LIMIT " << g_files_query_limit << ';';
|
||||||
|
|
||||||
auto& conn = get_conn();
|
auto& conn = get_conn();
|
||||||
auto result = conn.query(oss.str(), parIDs);
|
auto result = conn.query(oss.str(), parIDs);
|
||||||
|
@ -93,4 +129,28 @@ namespace din {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 \"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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} //namespace din
|
} //namespace din
|
||||||
|
|
|
@ -48,6 +48,23 @@ namespace din {
|
||||||
SetDetail_ID = 0x10
|
SetDetail_ID = 0x10
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum FileDetails {
|
||||||
|
FileDetail_ID = 0x0001,
|
||||||
|
FileDetail_Path = 0x0002,
|
||||||
|
FileDetail_Level = 0x0004,
|
||||||
|
FileDetail_GroupID = 0x0008,
|
||||||
|
FileDetail_IsDir = 0x0010,
|
||||||
|
FileDetail_IsSymLink = 0x0020,
|
||||||
|
FileDetail_Size = 0x0040,
|
||||||
|
FileDetail_Hash = 0x0080,
|
||||||
|
FileDetail_IsHashValid = 0x0100,
|
||||||
|
FileDetail_ATime = 0x0200,
|
||||||
|
FileDetail_MTime = 0x0400,
|
||||||
|
FileDetail_Unreadable = 0x800,
|
||||||
|
FileDetail_MimeType = 0x1000,
|
||||||
|
FileDetail_Charset = 0x2000
|
||||||
|
};
|
||||||
|
|
||||||
class DBSource {
|
class DBSource {
|
||||||
public:
|
public:
|
||||||
explicit DBSource ( const dinlib::SettingsDB& parDBSettings );
|
explicit DBSource ( const dinlib::SettingsDB& parDBSettings );
|
||||||
|
@ -58,47 +75,72 @@ namespace din {
|
||||||
|
|
||||||
template <SetDetails... D>
|
template <SetDetails... D>
|
||||||
auto set_details ( const std::vector<uint32_t>& parIDs ) -> std::vector<MaxSizedArray<std::string, sizeof...(D)>>;
|
auto set_details ( const std::vector<uint32_t>& parIDs ) -> std::vector<MaxSizedArray<std::string, sizeof...(D)>>;
|
||||||
//TODO: replace return value with vector of maxsizedarray
|
|
||||||
//auto set_details ( const std::vector<uint32_t>& parIDs ) -> std::array<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)>>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct LocalData;
|
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 );
|
pq::Connection& get_conn ( void );
|
||||||
void query_push_results ( const std::vector<std::string>& parCols, boost::string_ref parTable, const std::vector<uint32_t>& parIDs, std::function<void(std::string&&)> parCallback );
|
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::unique_ptr<LocalData> m_local_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace implem {
|
||||||
|
template <class M, M... Details>
|
||||||
|
inline
|
||||||
|
std::vector<std::string> make_columns_vec (const std::map<M, std::string>& parDic) {
|
||||||
|
std::vector<std::string> columns;
|
||||||
|
columns.reserve(sizeof...(Details));
|
||||||
|
|
||||||
|
const std::array<M, sizeof...(Details)> details { Details... };
|
||||||
|
//std::generate(details.begin(), details.end(), columns.begin(), std::bind(at_func, &details_dic, std::placeholders::_1));
|
||||||
|
for (auto detail : details) {
|
||||||
|
columns.push_back(parDic.at(detail));
|
||||||
|
}
|
||||||
|
return std::move(columns);
|
||||||
|
}
|
||||||
|
} //namespace implem
|
||||||
|
|
||||||
template <SetDetails... D>
|
template <SetDetails... D>
|
||||||
auto DBSource::set_details (const std::vector<uint32_t>& parIDs) -> std::vector<MaxSizedArray<std::string, sizeof...(D)>> {
|
auto DBSource::set_details (const std::vector<uint32_t>& parIDs) -> std::vector<MaxSizedArray<std::string, sizeof...(D)>> {
|
||||||
//auto DBSource::set_details (const std::vector<uint32_t>& parIDs) -> std::array<std::string, sizeof...(D)> {
|
|
||||||
typedef std::vector<MaxSizedArray<std::string, sizeof...(D)>> ReturnType;
|
typedef std::vector<MaxSizedArray<std::string, sizeof...(D)>> ReturnType;
|
||||||
typedef std::map<SetDetails, std::string> DetailsMap;
|
typedef const std::string&(SetDetailsMap::*AtFunc)(const SetDetails&) const;
|
||||||
typedef const std::string&(DetailsMap::*AtFunc)(const SetDetails&) const;
|
|
||||||
typedef void(din::FlatInsertIn2DList<ReturnType>::*FlatPushBackFunc)(std::string&&);
|
typedef void(din::FlatInsertIn2DList<ReturnType>::*FlatPushBackFunc)(std::string&&);
|
||||||
|
|
||||||
const std::array<SetDetails, sizeof...(D)> details { D... };
|
const auto columns = implem::make_columns_vec<SetDetails, D...>(m_set_details_map);
|
||||||
const DetailsMap details_dic {
|
AtFunc at_func = &SetDetailsMap::at;
|
||||||
{SetDetail_Desc, "desc"},
|
|
||||||
{SetDetail_Type, "type"},
|
|
||||||
{SetDetail_CreeationDate, "creation"},
|
|
||||||
{SetDetail_AppName, "app_name"},
|
|
||||||
{SetDetail_ID, "id"}
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<std::string> columns;
|
|
||||||
columns.reserve(sizeof...(D));
|
|
||||||
AtFunc at_func = &DetailsMap::at;
|
|
||||||
//std::generate(details.begin(), details.end(), columns.begin(), std::bind(at_func, &details_dic, std::placeholders::_1));
|
|
||||||
for (auto detail : details) {
|
|
||||||
columns.push_back(details_dic.at(detail));
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnType list;
|
ReturnType list;
|
||||||
FlatInsertIn2DList<ReturnType> flat_list(&list, sizeof...(D));
|
FlatInsertIn2DList<ReturnType> flat_list(&list, sizeof...(D));
|
||||||
FlatPushBackFunc pback_func = &FlatInsertIn2DList<ReturnType>::push_back;
|
FlatPushBackFunc pback_func = &FlatInsertIn2DList<ReturnType>::push_back;
|
||||||
this->query_push_results(columns, "sets", parIDs, std::bind(pback_func, &flat_list, std::placeholders::_1));
|
this->query_no_conditions(columns, "sets", parIDs, std::bind(pback_func, &flat_list, std::placeholders::_1));
|
||||||
|
return std::move(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)>> {
|
||||||
|
typedef std::vector<MaxSizedArray<std::string, sizeof...(D)>> ReturnType;
|
||||||
|
typedef const std::string&(SetDetailsMap::*AtFunc)(const SetDetails&) const;
|
||||||
|
typedef void(din::FlatInsertIn2DList<ReturnType>::*FlatPushBackFunc)(std::string&&);
|
||||||
|
|
||||||
|
const auto columns = implem::make_columns_vec<FileDetails, D...>(m_file_details_map);
|
||||||
|
AtFunc at_func = &SetDetailsMap::at;
|
||||||
|
|
||||||
|
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));
|
||||||
return std::move(list);
|
return std::move(list);
|
||||||
}
|
}
|
||||||
} //namespace din
|
} //namespace din
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <boost/phoenix/bind/bind_function.hpp>
|
#include <boost/phoenix/bind/bind_function.hpp>
|
||||||
#include <boost/phoenix/operator.hpp>
|
#include <boost/phoenix/operator.hpp>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
namespace qi = boost::spirit::qi;
|
namespace qi = boost::spirit::qi;
|
||||||
|
|
||||||
|
@ -103,4 +104,13 @@ namespace din {
|
||||||
boost::copy(m_stack, infix_ostream_iterator<std::string>(oss, "/"));
|
boost::copy(m_stack, infix_ostream_iterator<std::string>(oss, "/"));
|
||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t GenericPath::level() const {
|
||||||
|
return static_cast<uint16_t>(m_stack.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& GenericPath::operator[] (std::size_t parIndex) const {
|
||||||
|
assert(parIndex < level());
|
||||||
|
return m_stack[parIndex];
|
||||||
|
}
|
||||||
} //namespace din
|
} //namespace din
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
namespace din {
|
namespace din {
|
||||||
class GenericPath {
|
class GenericPath {
|
||||||
|
@ -28,6 +29,8 @@ namespace din {
|
||||||
|
|
||||||
void push_piece ( const std::string& parPiece );
|
void push_piece ( const std::string& parPiece );
|
||||||
std::string to_string ( void ) const;
|
std::string to_string ( void ) const;
|
||||||
|
uint16_t level ( void ) const;
|
||||||
|
const std::string& operator[] ( std::size_t parIndex ) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using StackType = std::vector<std::string>;
|
using StackType = std::vector<std::string>;
|
||||||
|
|
|
@ -28,10 +28,12 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <boost/range/algorithm/copy.hpp>
|
#include <boost/range/algorithm/copy.hpp>
|
||||||
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
void do_navigation ( din::DBSource& parDB );
|
void do_navigation ( din::DBSource& parDB );
|
||||||
|
|
||||||
|
template <typename V> void print_db_result ( const V& parResult );
|
||||||
bool on_exit ( void );
|
bool on_exit ( void );
|
||||||
void on_pwd ( const din::GenericPath& parDirMan );
|
void on_pwd ( const din::GenericPath& parDirMan );
|
||||||
void on_ls ( const din::GenericPath& parDirMan, din::DBSource& parDB );
|
void on_ls ( const din::GenericPath& parDirMan, din::DBSource& parDB );
|
||||||
|
@ -67,6 +69,14 @@ int main (int parArgc, char* parArgv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
template <typename V>
|
||||||
|
void print_db_result (const V& parResult) {
|
||||||
|
for (const auto& row : parResult) {
|
||||||
|
boost::copy(row, infix_ostream_iterator<std::string>(std::cout, "\t"));
|
||||||
|
std::cout << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool on_exit() {
|
bool on_exit() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -78,11 +88,18 @@ namespace {
|
||||||
void on_ls (const din::GenericPath& parDirMan, din::DBSource& parDB) {
|
void on_ls (const din::GenericPath& parDirMan, din::DBSource& parDB) {
|
||||||
using namespace din;
|
using namespace din;
|
||||||
|
|
||||||
auto sets_ids = parDB.sets();
|
const auto curr_path = parDirMan.to_string();
|
||||||
auto sets_info = parDB.set_details<SetDetail_ID, SetDetail_Desc, SetDetail_CreeationDate>(sets_ids);
|
if ("/" == curr_path) {
|
||||||
for (const auto& row : sets_info) {
|
auto sets_ids = parDB.sets();
|
||||||
boost::copy(row, infix_ostream_iterator<std::string>(std::cout, "\t"));
|
auto sets_info = parDB.set_details<SetDetail_ID, SetDetail_Desc, SetDetail_CreeationDate>(sets_ids);
|
||||||
std::cout << "\n";
|
print_db_result(sets_info);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const auto start_from = curr_path.find('/', 1);
|
||||||
|
auto path_prefix = boost::string_ref(curr_path).substr(start_from == curr_path.npos ? curr_path.size() : start_from + 1);
|
||||||
|
const auto set_id = boost::lexical_cast<uint32_t>(parDirMan[0]);
|
||||||
|
auto files_info = parDB.file_details<FileDetail_Path>(set_id, parDirMan.level(), path_prefix);
|
||||||
|
print_db_result(files_info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue