mirror of
https://github.com/KingDuckZ/dindexer.git
synced 2025-02-17 11:45:50 +00:00
Implement listing sets from the db (ls)
This commit is contained in:
parent
9071b25dec
commit
8cbd9560ec
6 changed files with 354 additions and 5 deletions
|
@ -5,6 +5,7 @@ add_executable(${PROJECT_NAME}
|
||||||
commandline.cpp
|
commandline.cpp
|
||||||
commandprocessor.cpp
|
commandprocessor.cpp
|
||||||
genericpath.cpp
|
genericpath.cpp
|
||||||
|
dbsource.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(${PROJECT_NAME}
|
target_include_directories(${PROJECT_NAME}
|
||||||
|
|
96
src/navigate/dbsource.cpp
Normal file
96
src/navigate/dbsource.cpp
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
/* Copyright 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 "dbsource.hpp"
|
||||||
|
#include "dindexer-common/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 din {
|
||||||
|
struct DBSource::LocalData {
|
||||||
|
explicit LocalData ( const dinlib::SettingsDB& 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 dinlib::SettingsDB& 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 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) {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "SELECT \"";
|
||||||
|
boost::copy(parCols, infix_ostream_iterator<std::string>(oss, "\", \""));
|
||||||
|
oss << '"';
|
||||||
|
oss << " FROM \"" << parTable << "\" WHERE \"id\" = ANY($1) ORDER BY \"desc\" ASC LIMIT 500;";
|
||||||
|
|
||||||
|
auto& conn = get_conn();
|
||||||
|
auto result = conn.query(oss.str(), parIDs);
|
||||||
|
for (auto row : result) {
|
||||||
|
for (auto val : row) {
|
||||||
|
parCallback(std::move(val));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} //namespace din
|
105
src/navigate/dbsource.hpp
Normal file
105
src/navigate/dbsource.hpp
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
/* Copyright 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef id63F35BA8B3C94A129291D963ABE66018
|
||||||
|
#define id63F35BA8B3C94A129291D963ABE66018
|
||||||
|
|
||||||
|
#include "dindexer-machinery/recorddata.hpp"
|
||||||
|
#include "flatinsertin2dlist.hpp"
|
||||||
|
#include <memory>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
#include <array>
|
||||||
|
#include <map>
|
||||||
|
#include <boost/range/algorithm/copy.hpp>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <functional>
|
||||||
|
#include <boost/utility/string_ref.hpp>
|
||||||
|
|
||||||
|
namespace dinlib {
|
||||||
|
struct SettingsDB;
|
||||||
|
} //namespace dinlib
|
||||||
|
|
||||||
|
namespace pq {
|
||||||
|
class Connection;
|
||||||
|
} //namespace pq
|
||||||
|
|
||||||
|
namespace din {
|
||||||
|
enum SetDetails {
|
||||||
|
SetDetail_Desc = 0x01,
|
||||||
|
SetDetail_Type = 0x02,
|
||||||
|
SetDetail_CreeationDate = 0x04,
|
||||||
|
SetDetail_AppName = 0x08,
|
||||||
|
SetDetail_ID = 0x10
|
||||||
|
};
|
||||||
|
|
||||||
|
class DBSource {
|
||||||
|
public:
|
||||||
|
explicit DBSource ( const dinlib::SettingsDB& parDBSettings );
|
||||||
|
~DBSource ( void ) noexcept;
|
||||||
|
|
||||||
|
void disconnect ( void );
|
||||||
|
std::vector<uint32_t> sets ( void );
|
||||||
|
|
||||||
|
template <SetDetails... D>
|
||||||
|
std::vector<std::vector<std::string>> set_details ( const std::vector<uint32_t>& parIDs );
|
||||||
|
//TODO: replace return value with vector of maxsizedarray
|
||||||
|
//auto set_details ( const std::vector<uint32_t>& parIDs ) -> std::array<std::string, sizeof...(D)>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct LocalData;
|
||||||
|
|
||||||
|
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 );
|
||||||
|
|
||||||
|
std::unique_ptr<LocalData> m_local_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <SetDetails... D>
|
||||||
|
std::vector<std::vector<std::string>> DBSource::set_details (const std::vector<uint32_t>& parIDs) {
|
||||||
|
//auto DBSource::set_details (const std::vector<uint32_t>& parIDs) -> std::array<std::string, sizeof...(D)> {
|
||||||
|
typedef std::vector<std::vector<std::string>> ReturnType;
|
||||||
|
typedef std::map<SetDetails, std::string> DetailsMap;
|
||||||
|
typedef const std::string&(DetailsMap::*AtFunc)(const SetDetails&) const;
|
||||||
|
typedef void(din::FlatInsertIn2DList<ReturnType>::*FlatPushBackFunc)(const std::string&);
|
||||||
|
|
||||||
|
const std::array<SetDetails, sizeof...(D)> details { D... };
|
||||||
|
const DetailsMap details_dic {
|
||||||
|
{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;
|
||||||
|
FlatInsertIn2DList<ReturnType> flat_list(&list, sizeof...(D));
|
||||||
|
FlatPushBackFunc pback_func = &FlatInsertIn2DList<ReturnType>::push_back;
|
||||||
|
this->query_push_results(columns, "sets", parIDs, std::bind(pback_func, &flat_list, std::placeholders::_1));
|
||||||
|
return std::move(list);
|
||||||
|
}
|
||||||
|
} //namespace din
|
||||||
|
|
||||||
|
#endif
|
51
src/navigate/flatinsertin2dlist.hpp
Normal file
51
src/navigate/flatinsertin2dlist.hpp
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
/* Copyright 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef idAA901DA47E234E37B325B3192EF50423
|
||||||
|
#define idAA901DA47E234E37B325B3192EF50423
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cassert>
|
||||||
|
#include <ciso646>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace din {
|
||||||
|
template <typename OuterList, typename InnerList=typename OuterList::value_type, typename InnerVal=typename InnerList::value_type>
|
||||||
|
class FlatInsertIn2DList {
|
||||||
|
public:
|
||||||
|
typedef OuterList list_type;
|
||||||
|
typedef InnerVal value_type;
|
||||||
|
typedef InnerList inner_list_type;
|
||||||
|
|
||||||
|
FlatInsertIn2DList ( list_type* parList, std::size_t parInnerCount, std::size_t parOuterCount=0 );
|
||||||
|
void push_back ( value_type&& parValue );
|
||||||
|
void push_back ( const value_type& parValue );
|
||||||
|
std::size_t size ( void ) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void expand_array ( void );
|
||||||
|
|
||||||
|
list_type* const m_list;
|
||||||
|
const std::size_t m_inner_count;
|
||||||
|
const std::size_t m_outer_count;
|
||||||
|
};
|
||||||
|
} //namespace din
|
||||||
|
|
||||||
|
#include "flatinsertin2dlist.inl"
|
||||||
|
|
||||||
|
#endif
|
73
src/navigate/flatinsertin2dlist.inl
Normal file
73
src/navigate/flatinsertin2dlist.inl
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
/* Copyright 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace din {
|
||||||
|
template <typename OuterList, typename InnerList, typename InnerVal>
|
||||||
|
FlatInsertIn2DList<OuterList, InnerList, InnerVal>::FlatInsertIn2DList (list_type* parList, std::size_t parInnerCount, std::size_t parOuterCount) :
|
||||||
|
m_list(parList),
|
||||||
|
m_inner_count(parInnerCount),
|
||||||
|
m_outer_count(parOuterCount)
|
||||||
|
{
|
||||||
|
assert(m_list);
|
||||||
|
if (m_outer_count) {
|
||||||
|
m_list->reserve(m_outer_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename OuterList, typename InnerList, typename InnerVal>
|
||||||
|
void FlatInsertIn2DList<OuterList, InnerList, InnerVal>::push_back (value_type&& parValue) {
|
||||||
|
expand_array();
|
||||||
|
const auto curr_outer_index = m_list->size() - 1;
|
||||||
|
(*m_list)[curr_outer_index].push_back(std::move(parValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename OuterList, typename InnerList, typename InnerVal>
|
||||||
|
void FlatInsertIn2DList<OuterList, InnerList, InnerVal>::push_back (const value_type& parValue) {
|
||||||
|
expand_array();
|
||||||
|
const auto curr_outer_index = m_list->size() - 1;
|
||||||
|
(*m_list)[curr_outer_index].push_back(parValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename OuterList, typename InnerList, typename InnerVal>
|
||||||
|
void FlatInsertIn2DList<OuterList, InnerList, InnerVal>::expand_array() {
|
||||||
|
auto& list = *m_list;
|
||||||
|
const auto inner_size = (list.empty() ? m_inner_count : list[list.size() - 1].size());
|
||||||
|
if (inner_size == m_inner_count) {
|
||||||
|
if (not m_outer_count or m_outer_count < list.size()) {
|
||||||
|
list.push_back(inner_list_type());
|
||||||
|
list[list.size() - 1].reserve(m_inner_count);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("Outer list is full");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(not m_outer_count or list.size() <= m_outer_count);
|
||||||
|
assert(list.size() > 0);
|
||||||
|
assert(list[list.size() - 1].size() <= m_inner_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename OuterList, typename InnerList, typename InnerVal>
|
||||||
|
std::size_t FlatInsertIn2DList<OuterList, InnerList, InnerVal>::size() const {
|
||||||
|
if (m_list->empty()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return (m_list->size() - 1) * m_inner_count + m_list[m_list->size() - 1].size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} //namespace din
|
|
@ -17,19 +17,24 @@
|
||||||
|
|
||||||
#include "commandline.hpp"
|
#include "commandline.hpp"
|
||||||
#include "commandprocessor.hpp"
|
#include "commandprocessor.hpp"
|
||||||
|
#include "dindexer-common/settings.hpp"
|
||||||
#include "genericpath.hpp"
|
#include "genericpath.hpp"
|
||||||
|
#include "dbsource.hpp"
|
||||||
|
#include "dindexerConfig.h"
|
||||||
|
#include "helpers/infix_iterator.hpp"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <ciso646>
|
#include <ciso646>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <boost/range/algorithm/copy.hpp>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
void do_navigation ( void );
|
void do_navigation ( din::DBSource& parDB );
|
||||||
|
|
||||||
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 );
|
void on_ls ( const din::GenericPath& parDirMan, din::DBSource& parDB );
|
||||||
} //unnamed namespace
|
} //unnamed namespace
|
||||||
|
|
||||||
int main (int parArgc, char* parArgv[]) {
|
int main (int parArgc, char* parArgv[]) {
|
||||||
|
@ -46,7 +51,18 @@ int main (int parArgc, char* parArgv[]) {
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
do_navigation();
|
dinlib::Settings settings;
|
||||||
|
{
|
||||||
|
const bool loaded = dinlib::load_settings(CONFIG_FILE_PATH, settings);
|
||||||
|
if (not loaded) {
|
||||||
|
std::cerr << "Can't load settings from " << CONFIG_FILE_PATH << ", quitting\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
din::DBSource db_source(settings.db);
|
||||||
|
|
||||||
|
do_navigation(db_source);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,8 +75,15 @@ namespace {
|
||||||
std::cout << parDirMan.to_string() << '\n';
|
std::cout << parDirMan.to_string() << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_ls (const din::GenericPath& parDirMan) {
|
void on_ls (const din::GenericPath& parDirMan, din::DBSource& parDB) {
|
||||||
|
using namespace din;
|
||||||
|
|
||||||
|
auto sets_ids = parDB.sets();
|
||||||
|
auto sets_info = parDB.set_details<SetDetail_ID, SetDetail_Desc, SetDetail_CreeationDate>(sets_ids);
|
||||||
|
for (const auto& row : sets_info) {
|
||||||
|
boost::copy(row, infix_ostream_iterator<std::string>(std::cout, "\t"));
|
||||||
|
std::cout << "\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_navigation (din::DBSource& parDB) {
|
void do_navigation (din::DBSource& parDB) {
|
||||||
|
@ -74,7 +97,7 @@ namespace {
|
||||||
proc.add_command("cd", std::function<void(const std::string&)>(std::bind(&din::GenericPath::push_piece, &dir_man, std::placeholders::_1)), 1);
|
proc.add_command("cd", std::function<void(const std::string&)>(std::bind(&din::GenericPath::push_piece, &dir_man, std::placeholders::_1)), 1);
|
||||||
proc.add_command("disconnect", std::function<void()>(std::bind(&din::DBSource::disconnect, &parDB)), 0);
|
proc.add_command("disconnect", std::function<void()>(std::bind(&din::DBSource::disconnect, &parDB)), 0);
|
||||||
proc.add_command("pwd", std::function<void()>(std::bind(&on_pwd, std::ref(dir_man))), 0);
|
proc.add_command("pwd", std::function<void()>(std::bind(&on_pwd, std::ref(dir_man))), 0);
|
||||||
proc.add_command("ls", std::function<void()>(std::bind(&on_ls, std::ref(dir_man))), 0);
|
proc.add_command("ls", std::function<void()>(std::bind(&on_ls, std::ref(dir_man), std::ref(parDB))), 0);
|
||||||
do {
|
do {
|
||||||
do {
|
do {
|
||||||
std::getline(inp, curr_line);
|
std::getline(inp, curr_line);
|
||||||
|
|
Loading…
Add table
Reference in a new issue