--- a/src/CSVHandler.h Tue Jan 08 18:40:15 2019 +0100
+++ b/src/CSVHandler.h Tue Jan 08 22:49:21 2019 +0100
@@ -30,6 +30,8 @@
#include <relpipe/reader/handlers/RelationalReaderStringHandler.h>
#include <relpipe/reader/handlers/AttributeMetadata.h>
+#include "RelpipeCSVWriterException.h"
+
namespace relpipe {
namespace out {
namespace csv {
@@ -41,19 +43,43 @@
class CSVHandler : public RelationalReaderStringHadler {
private:
std::ostream& output;
- std::wstring_convert<std::codecvt_utf8<wchar_t>> convertor; // TODO: support also other encodings.
+ const char QUOTE = '"';
+ std::wstring_convert<std::codecvt_utf8<wchar_t>> convertor; // TODO: local system encoding or generate CSV always in UTF-8 like XML?
+ std::vector<AttributeMetadata> firstAttributes;
+ integer_t valueCount = 0;
public:
CSVHandler(std::ostream& output) : output(output) {
}
void startRelation(string_t name, std::vector<AttributeMetadata> attributes) override {
-
+ if (firstAttributes.empty()) {
+ firstAttributes = attributes;
+ for (auto attr : attributes) attribute(attr.getAttributeName());
+ } else {
+ // TODO: UNION ALL if data types and attribute count matches
+ throw RelpipeCSVWriterException(L"Only a single relation can be converted to the CSV format.");
+ }
}
void attribute(const string_t& value) override {
- output << convertor.to_bytes(value).c_str();
- output.put(0);
+ valueCount++;
+
+ if (value.size() > 0) {
+ output << QUOTE;
+ for (auto ch : convertor.to_bytes(value)) {
+ if (ch == QUOTE) output << QUOTE << QUOTE;
+ else output << ch;
+ }
+ output << QUOTE;
+ }
+
+ if (valueCount % firstAttributes.size()) {
+ output << ",";
+ } else {
+ output << std::endl;
+ valueCount = 0;
+ }
}
void endOfPipe() {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/RelpipeCSVWriterException.h Tue Jan 08 22:49:21 2019 +0100
@@ -0,0 +1,44 @@
+/**
+ * Relational pipes
+ * Copyright © 2018 František Kučera (Frantovo.cz, GlobalCode.info)
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include <string>
+
+using namespace std;
+
+namespace relpipe {
+namespace out {
+namespace csv {
+
+class RelpipeCSVWriterException {
+private:
+ wstring message;
+public:
+
+ RelpipeCSVWriterException(wstring message) : message(message) {
+ }
+
+ wstring getMessge() {
+ return message;
+ }
+
+};
+
+}
+}
+}
\ No newline at end of file
--- a/src/relpipe-out-csv.cpp Tue Jan 08 18:40:15 2019 +0100
+++ b/src/relpipe-out-csv.cpp Tue Jan 08 22:49:21 2019 +0100
@@ -27,6 +27,7 @@
#include <relpipe/reader/RelpipeReaderException.h>
#include "CSVHandler.h"
+#include "RelpipeCSVWriterException.h"
using namespace relpipe::cli;
using namespace relpipe::reader;
@@ -53,6 +54,9 @@
fwprintf(stderr, L"Caught Reader exception: %ls\n", e.getMessge().c_str());
fwprintf(stderr, L"Debug: Input stream: eof=%ls, lastRead=%d\n", (cin.eof() ? L"true" : L"false"), cin.gcount());
resultCode = CLI::EXIT_CODE_DATA_ERROR;
+ } catch (RelpipeCSVWriterException e) {
+ fwprintf(stderr, L"Error while generating CSV: %ls\n", e.getMessge().c_str());
+ resultCode = CLI::EXIT_CODE_DATA_ERROR;
}
return resultCode;