--- a/src/SqlHandler.h Mon Jul 29 19:49:12 2019 +0200
+++ b/src/SqlHandler.h Tue Jul 30 14:01:21 2019 +0200
@@ -44,26 +44,112 @@
using namespace relpipe::reader;
using namespace relpipe::reader::handlers;
+class PreparedStatement {
+private:
+ sqlite3_stmt* stmt;
+
+public:
+
+ PreparedStatement(sqlite3_stmt* stmt) : stmt(stmt) {
+ }
+
+ virtual ~PreparedStatement() {
+ sqlite3_finalize(stmt);
+ }
+
+ void setString(int parameterIndex, std::string value) {
+ int result = sqlite3_bind_text(stmt, parameterIndex, value.c_str(), -1, SQLITE_TRANSIENT);
+ if (result != SQLITE_OK) throw SqlException(L"Unable to set SQLite parameter.");
+ }
+
+ void setNull(int parameterIndex) {
+ int result = sqlite3_bind_null(stmt, parameterIndex);
+ if (result != SQLITE_OK) throw SqlException(L"Unable to set SQLite parameter.");
+ }
+
+ bool next() {
+ int result = sqlite3_step(stmt);
+ if (result == SQLITE_ROW) return true;
+ else if (result == SQLITE_DONE) return false;
+ else throw SqlException(L"Error while iterating over SQLite result.");
+ }
+
+ int getColumnCount() {
+ return sqlite3_column_count(stmt);
+ }
+
+ std::string getColumName(int columnIndex) {
+ const char* name = sqlite3_column_name(stmt, columnIndex);
+ if (name) return name;
+ else throw SqlException(L"Unable to get SQLite column name.");
+ }
+
+ // TODO: sqlite3_column_type
+
+ std::string getString(int columnIndex) {
+ return (char *) sqlite3_column_text(stmt, columnIndex);
+ }
+
+};
+
+class Connection {
+private:
+ sqlite3* db;
+public:
+
+ Connection(const char* filename) {
+ int result = sqlite3_open(filename, &db);
+ if (result != SQLITE_OK) throw SqlException(L"Unable to open SQLite database.");
+ }
+
+ virtual ~Connection() {
+ sqlite3_close(db);
+ }
+
+ PreparedStatement prepareStatement(const char* sql) {
+ const char* remaining;
+ sqlite3_stmt *stmt;
+ int result = sqlite3_prepare(db, sql, -1, &stmt, &remaining);
+ if (result == SQLITE_OK) return PreparedStatement(stmt);
+ else throw SqlException(L"Unable to prepare SQLite statement.");
+ }
+
+};
+
class SqlHandler : public RelationalReaderStringHandler {
private:
Configuration configuration;
writer::RelationalWriter* relationalWriter;
std::wstring_convert<codecvt_utf8<wchar_t>> convertor; // TODO: support also other encodings
- sqlite3* db;
- sqlite3_stmt* currentStatement;
+ std::unique_ptr<Connection> connection;
+
+ void processStatement(const Statement& statement) {
+ PreparedStatement prepared = connection->prepareStatement(convertor.to_bytes(statement.sql).c_str());
+ int columnCount = prepared.getColumnCount();
+ int parameterCount = statement.parameters.size();
+
+ for (int i = 0; i < parameterCount; i++) {
+ prepared.setString(i + 1, convertor.to_bytes(statement.parameters[i].value));
+ }
+
+ for (int i = 0; i < columnCount; i++) {
+ printf("column %d ~ %s\n", i, prepared.getColumName(i).c_str());
+ }
+
+ while (prepared.next()) {
+ for (int i = 0; i < columnCount; i++) {
+ printf("column %d ~ %s = %s\n", i, prepared.getColumName(i).c_str(), prepared.getString(i).c_str());
+ }
+ }
+ }
public:
SqlHandler(writer::RelationalWriter* relationalWriter, Configuration& configuration) : relationalWriter(relationalWriter), configuration(configuration) {
- int error = sqlite3_open(":memory:", &db);
- if (error) {
- sqlite3_close(db);
- throw SqlException(L"Unable to open sqlite database.");
- }
+ connection.reset(new Connection(":memory:"));
}
virtual ~SqlHandler() {
- sqlite3_close(db);
}
void startRelation(string_t name, vector<AttributeMetadata> attributes) override {
@@ -75,7 +161,7 @@
}
void endOfPipe() {
-
+ for (const Statement& statement : configuration.statements) processStatement(statement);
}
};