diff -r a4907b207f0c -r a1775ba6d056 src/SqlHandler.h --- a/src/SqlHandler.h Sat Apr 23 18:49:25 2022 +0200 +++ b/src/SqlHandler.h Sun Aug 28 18:03:13 2022 +0200 @@ -160,6 +160,11 @@ else return L"text"; } + bool isInsertable(const relpipe::writer::string_t& tableName) { + for (Connection::TablePrivilege tp : connection->getTablePrivileges()) if (tp.name == tableName && tp.privilege == L"INSERT") return true; + return false; + } + void writeIdentifier(std::wstringstream& output, relpipe::writer::string_t identifier) { output << L'"'; for (auto & ch : identifier) { @@ -169,6 +174,23 @@ output << L'"'; } + void createTable(const string_t& name, const std::vector& attributes) { + std::wstringstream sql; + sql << L"CREATE TABLE "; + writeIdentifier(sql, name); + sql << L" (\n"; + for (int i = 0; i < attributes.size(); i++) { + sql << L"\t"; + writeIdentifier(sql, attributes[i].getAttributeName()); + sql << L" " << toSQLType(attributes[i].getTypeId()); + if (i < attributes.size() - 1) sql << L",\n"; + } + sql << L"\n)"; + + std::unique_ptr createTable(connection->prepareStatement(sql.str())); + createTable->executeUpdate(); + } + Connection* getConnection() { if (configuration.dataSourceName.size()) return driverManager->getConnectionByDSN(configuration.dataSourceName); else if (configuration.dataSourceString.size()) return driverManager->getConnectionByString(configuration.dataSourceString); @@ -191,27 +213,25 @@ currentReaderMetadata = attributes; // CREATE TABLE: - std::wstringstream sql; - // TODO: if already exist just append new columns - sql << L"CREATE TABLE "; - writeIdentifier(sql, name); - sql << L" (\n"; - for (int i = 0; i < attributes.size(); i++) { - sql << L"\t"; - writeIdentifier(sql, attributes[i].getAttributeName()); - sql << L" " << toSQLType(attributes[i].getTypeId()); - if (i < attributes.size() - 1) sql << L",\n"; + if (configuration.onDuplicateRelation == OnDuplicateRelation::Fail) { + createTable(name, attributes); // duplicate will cause exception + } else if (configuration.onDuplicateRelation == OnDuplicateRelation::Insert) { + if (isInsertable(name)); // nothing needs to be created; we will just append new records to the existing table + else createTable(name, attributes); + } else { + throw SqlException(L"Unsupported OnDuplicateRelation mode: " + std::to_wstring((int) configuration.onDuplicateRelation)); } - sql << L"\n)"; - - std::unique_ptr createTable(connection->prepareStatement(sql.str())); - createTable->executeUpdate(); // prepare INSERT: - sql = wstringstream(); + std::wstringstream sql; sql << L"INSERT INTO "; writeIdentifier(sql, name); - sql << L" VALUES ("; + sql << L" ("; + for (int i = 0; i < attributes.size(); i++) { + writeIdentifier(sql, attributes[i].getAttributeName()); + if (i < attributes.size() - 1) sql << L","; + } + sql << L") VALUES ("; for (int i = 0; i < attributes.size(); i++) { sql << L"?"; if (i < attributes.size() - 1) sql << L",";