--- a/src/relpipe-in-csv.cpp Wed Jan 09 17:23:02 2019 +0100
+++ b/src/relpipe-in-csv.cpp Wed Jan 09 23:04:51 2019 +0100
@@ -16,7 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cstdlib>
-#include <fstream>
+#include <vector>
#include <memory>
#include <regex>
#include <algorithm>
@@ -24,6 +24,7 @@
#include <relpipe/writer/RelationalWriter.h>
#include <relpipe/writer/RelpipeWriterException.h>
+#include <relpipe/writer/AttributeMetadata.h>
#include <relpipe/writer/Factory.h>
#include <relpipe/writer/TypeId.h>
@@ -33,13 +34,79 @@
using namespace relpipe::cli;
using namespace relpipe::writer;
-/**
- * see https://hg.frantovo.cz/sql-api/file/tip/prototyp/prototyp.sql#l49
- */
-void processDataStream(ostream &output, istream* input) {
+bool readValue(istream& input, stringstream& currentValue, bool& lastInRecord) {
+ lastInRecord = false;
+ char ch;
+ input.get(ch);
+ if (ch == '"') {
+ while (input.get(ch)) {
+ if (ch == '"') {
+ input.get(ch);
+ if (ch == '"') {
+ currentValue << ch;
+ } else {
+ if (ch == '\r') input.get(ch);
+ if (ch == '\n') lastInRecord = true;
+ else if (ch != ',') throw RelpipeWriterException(L"Unexpected character (should be ā\\nā or ā,ā)");
+ return true;
+ }
+ } else {
+ currentValue << ch;
+ }
+ }
+ } else if (ch == ',') {
+ return true;
+ } else if (ch == '\n') {
+ lastInRecord = true;
+ return true;
+ } else if (ch == '\r') {
+ currentValue << ch;
+ if (ch == '\n') {
+ lastInRecord = true;
+ return true;
+ } else {
+ throw RelpipeWriterException(L"Crazy carriage stuck during journey");
+ }
+ } else {
+ for (currentValue << ch; input.get(ch);) {
+ switch (ch) {
+ case ',': return true;
+ case '\r': break;
+ case '\n':
+ lastInRecord = true;
+ return true;
+ default: currentValue << ch;
+ }
+ }
+ }
+ return false;
+}
- for (char ch; input->get(ch);) {
- output << "ch: " << ch << endl;
+void processDataStream(ostream &output, istream& input) {
+ wstring_convert < codecvt_utf8<wchar_t>> convertor; // UTF-8 is required for CSV
+ std::shared_ptr<RelationalWriter> writer(Factory::create(output));
+ vector<AttributeMetadata> metadata;
+ bool headerDone = false;
+ bool lastInRecord = false;
+ stringstream currentValue;
+
+
+ while (readValue(input, currentValue, lastInRecord) && input.good()) {
+ if (headerDone) {
+ writer->writeAttribute(convertor.from_bytes(currentValue.str()));
+ } else {
+ AttributeMetadata am;
+ am.attributeName = convertor.from_bytes(currentValue.str());
+ am.typeId = TypeId::STRING; // TODO: support also other types passed as CLI parameters
+ metadata.push_back(am);
+ if (lastInRecord) {
+ headerDone = true;
+ writer->startRelation(L"csv", metadata, true); // TODO: support also custom relation name passed as CLI parameter
+ }
+ }
+
+ currentValue.str("");
+ currentValue.clear();
}
}
@@ -51,7 +118,7 @@
int resultCode = CLI::EXIT_CODE_UNEXPECTED_ERROR;
try {
- processDataStream(cout, &cin);
+ processDataStream(cout, cin);
resultCode = CLI::EXIT_CODE_SUCCESS;
} catch (RelpipeWriterException e) {
fwprintf(stderr, L"Caught Writer exception: %ls\n", e.getMessge().c_str());