src/SqlHandler.h
branchv_0
changeset 3 0b932e05aa9f
parent 1 eb7134dfdcc5
child 4 925b15fb5c63
equal deleted inserted replaced
2:362f2689cb87 3:0b932e05aa9f
    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 	}
    73 	void attribute(const string_t& value) override {
   159 	void attribute(const string_t& value) override {
    74 
   160 
    75 	}
   161 	}
    76 
   162 
    77 	void endOfPipe() {
   163 	void endOfPipe() {
    78 
   164 		for (const Statement& statement : configuration.statements) processStatement(statement);
    79 	}
   165 	}
    80 
   166 
    81 };
   167 };
    82 
   168 
    83 }
   169 }