src/SqlHandler.h
branchv_0
changeset 59 a1775ba6d056
parent 58 a4907b207f0c
--- 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<AttributeMetadata>& 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<PreparedStatement> 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<PreparedStatement> 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",";