src/relpipe-in-csv.cpp
branchv_0
changeset 1 5eb4d149c6e2
parent 0 eca0b23802e8
child 2 e83895da3e8f
equal deleted inserted replaced
0:eca0b23802e8 1:5eb4d149c6e2
    14  *
    14  *
    15  * You should have received a copy of the GNU General Public License
    15  * You should have received a copy of the GNU General Public License
    16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
    16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
    17  */
    17  */
    18 #include <cstdlib>
    18 #include <cstdlib>
    19 #include <fstream>
    19 #include <vector>
    20 #include <memory>
    20 #include <memory>
    21 #include <regex>
    21 #include <regex>
    22 #include <algorithm>
    22 #include <algorithm>
    23 #include <unistd.h>
    23 #include <unistd.h>
    24 
    24 
    25 #include <relpipe/writer/RelationalWriter.h>
    25 #include <relpipe/writer/RelationalWriter.h>
    26 #include <relpipe/writer/RelpipeWriterException.h>
    26 #include <relpipe/writer/RelpipeWriterException.h>
       
    27 #include <relpipe/writer/AttributeMetadata.h>
    27 #include <relpipe/writer/Factory.h>
    28 #include <relpipe/writer/Factory.h>
    28 #include <relpipe/writer/TypeId.h>
    29 #include <relpipe/writer/TypeId.h>
    29 
    30 
    30 #include <relpipe/cli/CLI.h>
    31 #include <relpipe/cli/CLI.h>
    31 
    32 
    32 using namespace std;
    33 using namespace std;
    33 using namespace relpipe::cli;
    34 using namespace relpipe::cli;
    34 using namespace relpipe::writer;
    35 using namespace relpipe::writer;
    35 
    36 
    36 /**
    37 bool readValue(istream& input, stringstream& currentValue, bool& lastInRecord) {
    37  * see https://hg.frantovo.cz/sql-api/file/tip/prototyp/prototyp.sql#l49
    38 	lastInRecord = false;
    38  */
    39 	char ch;
    39 void processDataStream(ostream &output, istream* input) {
    40 	input.get(ch);
       
    41 	if (ch == '"') {
       
    42 		while (input.get(ch)) {
       
    43 			if (ch == '"') {
       
    44 				input.get(ch);
       
    45 				if (ch == '"') {
       
    46 					currentValue << ch;
       
    47 				} else {
       
    48 					if (ch == '\r') input.get(ch);
       
    49 					if (ch == '\n') lastInRecord = true;
       
    50 					else if (ch != ',') throw RelpipeWriterException(L"Unexpected character (should be ā€ž\\nā€œ or ā€ž,ā€œ)");
       
    51 					return true;
       
    52 				}
       
    53 			} else {
       
    54 				currentValue << ch;
       
    55 			}
       
    56 		}
       
    57 	} else if (ch == ',') {
       
    58 		return true;
       
    59 	} else if (ch == '\n') {
       
    60 		lastInRecord = true;
       
    61 		return true;
       
    62 	} else if (ch == '\r') {
       
    63 		currentValue << ch;
       
    64 		if (ch == '\n') {
       
    65 			lastInRecord = true;
       
    66 			return true;
       
    67 		} else {
       
    68 			throw RelpipeWriterException(L"Crazy carriage stuck during journey");
       
    69 		}
       
    70 	} else {
       
    71 		for (currentValue << ch; input.get(ch);) {
       
    72 			switch (ch) {
       
    73 				case ',': return true;
       
    74 				case '\r': break;
       
    75 				case '\n':
       
    76 					lastInRecord = true;
       
    77 					return true;
       
    78 				default: currentValue << ch;
       
    79 			}
       
    80 		}
       
    81 	}
       
    82 	return false;
       
    83 }
    40 
    84 
    41 	for (char ch; input->get(ch);) {
    85 void processDataStream(ostream &output, istream& input) {
    42 		output << "ch: " << ch << endl;
    86 	wstring_convert < codecvt_utf8<wchar_t>> convertor; // UTF-8 is required for CSV
       
    87 	std::shared_ptr<RelationalWriter> writer(Factory::create(output));
       
    88 	vector<AttributeMetadata> metadata;
       
    89 	bool headerDone = false;
       
    90 	bool lastInRecord = false;
       
    91 	stringstream currentValue;
       
    92 
       
    93 
       
    94 	while (readValue(input, currentValue, lastInRecord) && input.good()) {
       
    95 		if (headerDone) {
       
    96 			writer->writeAttribute(convertor.from_bytes(currentValue.str()));
       
    97 		} else {
       
    98 			AttributeMetadata am;
       
    99 			am.attributeName = convertor.from_bytes(currentValue.str());
       
   100 			am.typeId = TypeId::STRING; // TODO: support also other types passed as CLI parameters
       
   101 			metadata.push_back(am);
       
   102 			if (lastInRecord) {
       
   103 				headerDone = true;
       
   104 				writer->startRelation(L"csv", metadata, true); // TODO: support also custom relation name passed as CLI parameter
       
   105 			}
       
   106 		}
       
   107 
       
   108 		currentValue.str("");
       
   109 		currentValue.clear();
    43 	}
   110 	}
    44 }
   111 }
    45 
   112 
    46 int main(int argc, char** argv) {
   113 int main(int argc, char** argv) {
    47 	setlocale(LC_ALL, "");
   114 	setlocale(LC_ALL, "");
    49 	CLI cli(argc, argv);
   116 	CLI cli(argc, argv);
    50 
   117 
    51 	int resultCode = CLI::EXIT_CODE_UNEXPECTED_ERROR;
   118 	int resultCode = CLI::EXIT_CODE_UNEXPECTED_ERROR;
    52 
   119 
    53 	try {
   120 	try {
    54 		processDataStream(cout, &cin);
   121 		processDataStream(cout, cin);
    55 		resultCode = CLI::EXIT_CODE_SUCCESS;
   122 		resultCode = CLI::EXIT_CODE_SUCCESS;
    56 	} catch (RelpipeWriterException e) {
   123 	} catch (RelpipeWriterException e) {
    57 		fwprintf(stderr, L"Caught Writer exception: %ls\n", e.getMessge().c_str());
   124 		fwprintf(stderr, L"Caught Writer exception: %ls\n", e.getMessge().c_str());
    58 		fwprintf(stderr, L"Debug: Input stream: eof=%ls, lastRead=%d\n", (cin.eof() ? L"true" : L"false"), cin.gcount());
   125 		fwprintf(stderr, L"Debug: Input stream: eof=%ls, lastRead=%d\n", (cin.eof() ? L"true" : L"false"), cin.gcount());
    59 		resultCode = CLI::EXIT_CODE_DATA_ERROR;
   126 		resultCode = CLI::EXIT_CODE_DATA_ERROR;