42 using namespace std; |
42 using namespace std; |
43 using namespace relpipe; |
43 using namespace relpipe; |
44 using namespace relpipe::reader; |
44 using namespace relpipe::reader; |
45 using namespace relpipe::reader::handlers; |
45 using namespace relpipe::reader::handlers; |
46 |
46 |
|
47 class PreparedStatement { |
|
48 private: |
|
49 sqlite3_stmt* stmt; |
|
50 |
|
51 public: |
|
52 |
|
53 PreparedStatement(sqlite3_stmt* stmt) : stmt(stmt) { |
|
54 } |
|
55 |
|
56 virtual ~PreparedStatement() { |
|
57 sqlite3_finalize(stmt); |
|
58 } |
|
59 |
|
60 void setString(int parameterIndex, std::string value) { |
|
61 int result = sqlite3_bind_text(stmt, parameterIndex, value.c_str(), -1, SQLITE_TRANSIENT); |
|
62 if (result != SQLITE_OK) throw SqlException(L"Unable to set SQLite parameter."); |
|
63 } |
|
64 |
|
65 void setNull(int parameterIndex) { |
|
66 int result = sqlite3_bind_null(stmt, parameterIndex); |
|
67 if (result != SQLITE_OK) throw SqlException(L"Unable to set SQLite parameter."); |
|
68 } |
|
69 |
|
70 bool next() { |
|
71 int result = sqlite3_step(stmt); |
|
72 if (result == SQLITE_ROW) return true; |
|
73 else if (result == SQLITE_DONE) return false; |
|
74 else throw SqlException(L"Error while iterating over SQLite result."); |
|
75 } |
|
76 |
|
77 int getColumnCount() { |
|
78 return sqlite3_column_count(stmt); |
|
79 } |
|
80 |
|
81 std::string getColumName(int columnIndex) { |
|
82 const char* name = sqlite3_column_name(stmt, columnIndex); |
|
83 if (name) return name; |
|
84 else throw SqlException(L"Unable to get SQLite column name."); |
|
85 } |
|
86 |
|
87 // TODO: sqlite3_column_type |
|
88 |
|
89 std::string getString(int columnIndex) { |
|
90 return (char *) sqlite3_column_text(stmt, columnIndex); |
|
91 } |
|
92 |
|
93 }; |
|
94 |
|
95 class Connection { |
|
96 private: |
|
97 sqlite3* db; |
|
98 public: |
|
99 |
|
100 Connection(const char* filename) { |
|
101 int result = sqlite3_open(filename, &db); |
|
102 if (result != SQLITE_OK) throw SqlException(L"Unable to open SQLite database."); |
|
103 } |
|
104 |
|
105 virtual ~Connection() { |
|
106 sqlite3_close(db); |
|
107 } |
|
108 |
|
109 PreparedStatement prepareStatement(const char* sql) { |
|
110 const char* remaining; |
|
111 sqlite3_stmt *stmt; |
|
112 int result = sqlite3_prepare(db, sql, -1, &stmt, &remaining); |
|
113 if (result == SQLITE_OK) return PreparedStatement(stmt); |
|
114 else throw SqlException(L"Unable to prepare SQLite statement."); |
|
115 } |
|
116 |
|
117 }; |
|
118 |
47 class SqlHandler : public RelationalReaderStringHandler { |
119 class SqlHandler : public RelationalReaderStringHandler { |
48 private: |
120 private: |
49 Configuration configuration; |
121 Configuration configuration; |
50 writer::RelationalWriter* relationalWriter; |
122 writer::RelationalWriter* relationalWriter; |
51 std::wstring_convert<codecvt_utf8<wchar_t>> convertor; // TODO: support also other encodings |
123 std::wstring_convert<codecvt_utf8<wchar_t>> convertor; // TODO: support also other encodings |
52 sqlite3* db; |
124 std::unique_ptr<Connection> connection; |
53 sqlite3_stmt* currentStatement; |
125 |
|
126 void processStatement(const Statement& statement) { |
|
127 PreparedStatement prepared = connection->prepareStatement(convertor.to_bytes(statement.sql).c_str()); |
|
128 int columnCount = prepared.getColumnCount(); |
|
129 int parameterCount = statement.parameters.size(); |
|
130 |
|
131 for (int i = 0; i < parameterCount; i++) { |
|
132 prepared.setString(i + 1, convertor.to_bytes(statement.parameters[i].value)); |
|
133 } |
|
134 |
|
135 for (int i = 0; i < columnCount; i++) { |
|
136 printf("column %d ~ %s\n", i, prepared.getColumName(i).c_str()); |
|
137 } |
|
138 |
|
139 while (prepared.next()) { |
|
140 for (int i = 0; i < columnCount; i++) { |
|
141 printf("column %d ~ %s = %s\n", i, prepared.getColumName(i).c_str(), prepared.getString(i).c_str()); |
|
142 } |
|
143 } |
|
144 } |
54 |
145 |
55 public: |
146 public: |
56 |
147 |
57 SqlHandler(writer::RelationalWriter* relationalWriter, Configuration& configuration) : relationalWriter(relationalWriter), configuration(configuration) { |
148 SqlHandler(writer::RelationalWriter* relationalWriter, Configuration& configuration) : relationalWriter(relationalWriter), configuration(configuration) { |
58 int error = sqlite3_open(":memory:", &db); |
149 connection.reset(new Connection(":memory:")); |
59 if (error) { |
|
60 sqlite3_close(db); |
|
61 throw SqlException(L"Unable to open sqlite database."); |
|
62 } |
|
63 } |
150 } |
64 |
151 |
65 virtual ~SqlHandler() { |
152 virtual ~SqlHandler() { |
66 sqlite3_close(db); |
|
67 } |
153 } |
68 |
154 |
69 void startRelation(string_t name, vector<AttributeMetadata> attributes) override { |
155 void startRelation(string_t name, vector<AttributeMetadata> attributes) override { |
70 |
156 |
71 } |
157 } |