46 Configuration& configuration; |
46 Configuration& configuration; |
47 const char QUOTE = '"'; |
47 const char QUOTE = '"'; |
48 std::wstring_convert<std::codecvt_utf8<wchar_t>> convertor; // TODO: local system encoding or generate CSV always in UTF-8 like XML? |
48 std::wstring_convert<std::codecvt_utf8<wchar_t>> convertor; // TODO: local system encoding or generate CSV always in UTF-8 like XML? |
49 std::vector<AttributeMetadata> firstAttributes; |
49 std::vector<AttributeMetadata> firstAttributes; |
50 integer_t valueCount = 0; |
50 integer_t valueCount = 0; |
|
51 |
|
52 /** |
|
53 * @param a |
|
54 * @param b |
|
55 * @return true if relations have same number and types of attributes (names may differ) |
|
56 */ |
|
57 bool matches(const std::vector<AttributeMetadata>& a, const std::vector<AttributeMetadata>& b) { |
|
58 if (a.size() != b.size()) return false; |
|
59 for (int i = 0, limit = a.size(); i < limit; i++) if (a[i].getTypeId() != b[i].getTypeId()) return false; |
|
60 return true; |
|
61 } |
51 public: |
62 public: |
52 |
63 |
53 CSVHandler(std::ostream& output, Configuration& configuration) : output(output), configuration(configuration) { |
64 CSVHandler(std::ostream& output, Configuration& configuration) : output(output), configuration(configuration) { |
54 } |
65 } |
55 |
66 |
56 void startRelation(string_t name, std::vector<AttributeMetadata> attributes) override { |
67 void startRelation(string_t name, std::vector<AttributeMetadata> attributes) override { |
57 if (firstAttributes.empty()) { |
68 if (firstAttributes.empty()) { |
58 firstAttributes = attributes; |
69 firstAttributes = attributes; |
59 if (configuration.writeHeader) for (auto attr : attributes) attribute(configuration.writeTypes ? attr.getAttributeName() + L"::" + attr.getTypeName() : attr.getAttributeName()); |
70 if (configuration.writeHeader) for (auto attr : attributes) attribute(configuration.writeTypes ? attr.getAttributeName() + L"::" + attr.getTypeName() : attr.getAttributeName()); |
|
71 } else if (matches(firstAttributes, attributes)) { |
|
72 // do UNION ALL – just append the records |
60 } else { |
73 } else { |
61 // TODO: UNION ALL if data types and attribute count matches |
74 throw RelpipeCSVWriterException(L"To the CSV format we can convert only one relation or multiple relations that have same number of attributes of same types (relation and attribute names may differ – result is named after the first one)."); |
62 throw RelpipeCSVWriterException(L"Only a single relation can be converted to the CSV format."); |
|
63 } |
75 } |
64 } |
76 } |
65 |
77 |
66 void attribute(const string_t& value) override { |
78 void attribute(const string_t& value) override { |
67 valueCount++; |
79 valueCount++; |