28 #include <relpipe/reader/typedefs.h> |
28 #include <relpipe/reader/typedefs.h> |
29 #include <relpipe/reader/TypeId.h> |
29 #include <relpipe/reader/TypeId.h> |
30 #include <relpipe/reader/handlers/RelationalReaderStringHandler.h> |
30 #include <relpipe/reader/handlers/RelationalReaderStringHandler.h> |
31 #include <relpipe/reader/handlers/AttributeMetadata.h> |
31 #include <relpipe/reader/handlers/AttributeMetadata.h> |
32 |
32 |
|
33 #include "RelpipeCSVWriterException.h" |
|
34 |
33 namespace relpipe { |
35 namespace relpipe { |
34 namespace out { |
36 namespace out { |
35 namespace csv { |
37 namespace csv { |
36 |
38 |
37 using namespace relpipe; |
39 using namespace relpipe; |
39 using namespace relpipe::reader::handlers; |
41 using namespace relpipe::reader::handlers; |
40 |
42 |
41 class CSVHandler : public RelationalReaderStringHadler { |
43 class CSVHandler : public RelationalReaderStringHadler { |
42 private: |
44 private: |
43 std::ostream& output; |
45 std::ostream& output; |
44 std::wstring_convert<std::codecvt_utf8<wchar_t>> convertor; // TODO: support also other encodings. |
46 const char QUOTE = '"'; |
|
47 std::wstring_convert<std::codecvt_utf8<wchar_t>> convertor; // TODO: local system encoding or generate CSV always in UTF-8 like XML? |
|
48 std::vector<AttributeMetadata> firstAttributes; |
|
49 integer_t valueCount = 0; |
45 public: |
50 public: |
46 |
51 |
47 CSVHandler(std::ostream& output) : output(output) { |
52 CSVHandler(std::ostream& output) : output(output) { |
48 } |
53 } |
49 |
54 |
50 void startRelation(string_t name, std::vector<AttributeMetadata> attributes) override { |
55 void startRelation(string_t name, std::vector<AttributeMetadata> attributes) override { |
51 |
56 if (firstAttributes.empty()) { |
|
57 firstAttributes = attributes; |
|
58 for (auto attr : attributes) attribute(attr.getAttributeName()); |
|
59 } else { |
|
60 // TODO: UNION ALL if data types and attribute count matches |
|
61 throw RelpipeCSVWriterException(L"Only a single relation can be converted to the CSV format."); |
|
62 } |
52 } |
63 } |
53 |
64 |
54 void attribute(const string_t& value) override { |
65 void attribute(const string_t& value) override { |
55 output << convertor.to_bytes(value).c_str(); |
66 valueCount++; |
56 output.put(0); |
67 |
|
68 if (value.size() > 0) { |
|
69 output << QUOTE; |
|
70 for (auto ch : convertor.to_bytes(value)) { |
|
71 if (ch == QUOTE) output << QUOTE << QUOTE; |
|
72 else output << ch; |
|
73 } |
|
74 output << QUOTE; |
|
75 } |
|
76 |
|
77 if (valueCount % firstAttributes.size()) { |
|
78 output << ","; |
|
79 } else { |
|
80 output << std::endl; |
|
81 valueCount = 0; |
|
82 } |
57 } |
83 } |
58 |
84 |
59 void endOfPipe() { |
85 void endOfPipe() { |
60 output.flush(); |
86 output.flush(); |
61 } |
87 } |