--- 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() {