src/CSVHandler.h
branchv_0
changeset 1 82f86dc48339
parent 0 97967db4b95b
child 3 b5a5bf32f7ff
--- 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() {