|
1 #pragma once |
|
2 |
|
3 #include <cstdlib> |
|
4 #include <iostream> |
|
5 #include <string> |
|
6 #include <vector> |
|
7 #include <algorithm> |
|
8 #include <string> |
|
9 |
|
10 #include <typedefs.h> |
|
11 #include <locale> |
|
12 |
|
13 #include "Command.h" |
|
14 #include "CLI.h" |
|
15 #include "RelpipeCLIException.h" |
|
16 |
|
17 namespace relpipe { |
|
18 namespace in { |
|
19 namespace cli { |
|
20 |
|
21 /** |
|
22 * TODO: consider code merge with ArgumentsCommand |
|
23 */ |
|
24 class StdInCommand : public Command { |
|
25 private: |
|
26 wstring_convert<codecvt_utf8<wchar_t>> convertor; // TODO: support also other encodings. |
|
27 |
|
28 /** |
|
29 * Reads next value from arguments and (if no arguments left) from input |
|
30 * @param input |
|
31 * @param arguments |
|
32 * @param i current index in the arguments vector |
|
33 * @param required if true, exception is thrown when no data found |
|
34 * @return |
|
35 */ |
|
36 relpipe::writer::string_t readNext(std::istream& input, const std::vector<relpipe::writer::string_t>& arguments, size_t& i, relpipe::writer::boolean_t required) { |
|
37 using namespace relpipe::writer; |
|
38 using namespace relpipe::cli; |
|
39 |
|
40 if (i < arguments.size()) { |
|
41 return arguments[i++]; |
|
42 } else { |
|
43 std::stringstream value; |
|
44 |
|
45 while (true) { |
|
46 char ch; |
|
47 input.get(ch); |
|
48 if (ch == 0 || input.eof() || input.fail()) break; |
|
49 else value << ch; |
|
50 } |
|
51 |
|
52 return convertor.from_bytes(value.str()); |
|
53 } |
|
54 } |
|
55 |
|
56 |
|
57 public: |
|
58 |
|
59 void process(std::istream& input, std::ostream& output, const relpipe::writer::string_t& command, const std::vector<relpipe::writer::string_t>& arguments) override { |
|
60 using namespace relpipe::writer; |
|
61 |
|
62 size_t i = 0; |
|
63 string_t relationName = readNext(input, arguments, i, true); |
|
64 integer_t attributeCount = std::stoul(readNext(input, arguments, i, true)); // TODO: use integer data type's method? |
|
65 boolean_t writeHeader = true; // TODO: add option for header omitting |
|
66 |
|
67 std::shared_ptr<RelationalWriter> writer(Factory::create(output)); |
|
68 |
|
69 std::vector<std::pair<string_t, TypeId >> attributes(attributeCount); |
|
70 |
|
71 for (size_t j = 0; j < attributeCount; j++) { |
|
72 string_t attributeName = readNext(input, arguments, i, true); |
|
73 TypeId attributeType = writer->toTypeId(readNext(input, arguments, i, true)); |
|
74 attributes[j] = {attributeName, attributeType}; |
|
75 } |
|
76 |
|
77 writer->startRelation(relationName, attributes, writeHeader); |
|
78 |
|
79 while (true) { |
|
80 string_t value = readNext(input, arguments, i, false); |
|
81 if (value.empty() && (input.eof() || input.fail())) break; |
|
82 else writer->writeAttribute(value); |
|
83 } |
|
84 } |
|
85 }; |
|
86 |
|
87 } |
|
88 } |
|
89 } |