From 2c27a352a2f8c9fefe0f8bf83e11e4e9f0f7633d Mon Sep 17 00:00:00 2001 From: tastytea Date: Thu, 16 May 2019 00:05:18 +0200 Subject: [PATCH] Export as CSV to stdout. --- src/main.cpp | 38 +++++++++++++++++++++++++++-- src/sqlite.cpp | 66 +++++++++++++++++++++++++++++++++++++++++++------- src/sqlite.hpp | 22 ++++++++++++++--- 3 files changed, 111 insertions(+), 15 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 87cad63..58fc402 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -47,8 +47,42 @@ int main(const int argc, const char *argv[]) { URL url(opts.url); html_extract page = url.get(); - db.store(opts.url, url.archive(), system_clock::now(), opts.tags, - page.title, page.description, page.fulltext); + db.store({opts.url, url.archive(), system_clock::now(), opts.tags, + page.title, page.description, page.fulltext}); + } + + switch (opts.format) + { + case export_format::csv: + { + for (const Database::entry &entry : db.retrieve()) + { + string strtags; + for (const string &tag : entry.tags) + { + strtags += tag; + if (tag != *(entry.tags.rbegin())) + { + strtags += ","; + } + } + cout << entry.uri << ';' << entry.archive_uri << ';' + << timepoint_to_string(entry.datetime) << ';' + << strtags << ';' << entry.title << ';' + << entry.description << endl; + } + break; + } + case export_format::asciidoc: + { + cerr << "AsciiDoc is not yet supported.\n"; + break; + } + default: + { + // Do nothing. + break; + } } return 0; diff --git a/src/sqlite.cpp b/src/sqlite.cpp index 43240fe..991ea75 100644 --- a/src/sqlite.cpp +++ b/src/sqlite.cpp @@ -60,19 +60,16 @@ Database::operator bool() const return _connected; } -void Database::store(const string &uri, const string &archive_uri, - const time_point &datetime, const vector &tags, - const string &title, const string &description, - const string &fulltext) +void Database::store(const Database::entry &data) const { try { - const string strdatetime = timepoint_to_string(datetime); + const string strdatetime = timepoint_to_string(data.datetime, true); string strtags; - for (const string &tag : tags) + for (const string &tag : data.tags) { strtags += tag; - if (tag != *(tags.rbegin())) + if (tag != *(data.tags.rbegin())) { strtags += ","; } @@ -80,8 +77,8 @@ void Database::store(const string &uri, const string &archive_uri, sqlite::execute ins(*_con, "INSERT INTO remwharead " "VALUES(?, ?, ?, ?, ?, ?, ?);"); - ins % uri % archive_uri % strdatetime % strtags - % title % description % fulltext; + ins % data.uri % data.archive_uri % strdatetime % strtags + % data.title % data.description % data.fulltext; ins(); } catch (std::exception &e) @@ -89,3 +86,54 @@ void Database::store(const string &uri, const string &archive_uri, cerr << "Error in " << __func__ << ": " << e.what() << endl; } } + +const vector Database::retrieve(const time_point &start, + const time_point &end) const +{ + try + { + const string query = "SELECT * FROM remwharead WHERE datetime " + "BETWEEN '" + timepoint_to_string(start, true) + + "' AND '" + timepoint_to_string(end, true) + + "' ORDER BY datetime;"; + + sqlite::query q(*_con, query); + sqlite::result_type res = q.get_result(); + vector entries; + + while(res->next_row()) + { + vector tags; + const string strtags = res->get_string(3); + size_t pos = 0; + while (pos != std::string::npos) + { + const size_t newpos = strtags.find(',', pos); + tags.push_back(strtags.substr(pos, newpos - pos)); + pos = newpos; + if (pos != std::string::npos) + { + ++pos; + } + } + entries.push_back + ({ + res->get_string(0), + res->get_string(1), + string_to_timepoint(res->get_string(2), true), + tags, + res->get_string(4), + res->get_string(5), + res->get_string(6) + }); + } + + return entries; + } + catch (std::exception &e) + { + cerr << "Error in " << __func__ << ": " << e.what() << endl; + } + + return {}; +} diff --git a/src/sqlite.hpp b/src/sqlite.hpp index 1b2e96a..31beb59 100644 --- a/src/sqlite.hpp +++ b/src/sqlite.hpp @@ -23,6 +23,7 @@ #include #include #include +#include "types.hpp" namespace fs = std::experimental::filesystem; using std::string; @@ -33,14 +34,27 @@ using time_point = system_clock::time_point; class Database { public: + typedef struct entry + { + string uri; + string archive_uri; + time_point datetime; + vector tags; + string title; + string description; + string fulltext; + } entry; + Database(); operator bool() const; //! Store in database. - void store(const string &uri, const string &archive_uri, - const time_point &datetime, const vector &tags, - const string &title, const string &description, - const string &fulltext); + void store(const entry &data) const; + + //! retrieve from database. + const vector retrieve(const time_point &start = time_point(), + const time_point &end = system_clock::now()) + const; private: fs::path _dbpath;