insert multiple records at once – first version v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Sat, 10 Dec 2022 20:41:40 +0100
branchv_0
changeset 2 8a30971d285f
parent 1 4c0366e1b4df
child 3 202ce847990c
insert multiple records at once – first version
src/Configuration.h
src/SQLHandler.h
--- a/src/Configuration.h	Wed Dec 07 01:38:50 2022 +0100
+++ b/src/Configuration.h	Sat Dec 10 20:41:40 2022 +0100
@@ -28,8 +28,15 @@
 
 class Configuration {
 public:
+
+	enum class InsertMode {
+		SINGLE,
+		MULTI,
+	};
+
 	relpipe::reader::boolean_t writeHeader = true;
 	relpipe::reader::boolean_t writeTypes = false;
+	InsertMode insertMode = InsertMode::MULTI; // TODO: per-relation mode
 
 	virtual ~Configuration() {
 	}
--- a/src/SQLHandler.h	Wed Dec 07 01:38:50 2022 +0100
+++ b/src/SQLHandler.h	Sat Dec 10 20:41:40 2022 +0100
@@ -84,6 +84,15 @@
 		// output << "-- Record count: " << recordCount << std::endl;
 	}
 
+	void endRelation() {
+
+		if (configuration.insertMode == Configuration::InsertMode::MULTI) {
+			output << std::endl << ";" << std::endl;
+		}
+
+		writeRecordCount();
+	}
+
 public:
 
 	SQLHandler(std::ostream& output, Configuration& configuration) : output(output), configuration(configuration) {
@@ -104,7 +113,7 @@
 		// TODO: share code/behavior with relpipe-tr-sql (but it uses parametrized statements)
 
 		if (currentTable.size()) {
-			writeRecordCount();
+			endRelation();
 			output << std::endl;
 		}
 
@@ -145,9 +154,41 @@
 			// TODO: custom line-ends + indentation
 			// TODO: optionally write also the column names
 			recordCount++;
-			output << "INSERT INTO ";
-			writeIdentifier(output, convertor.to_bytes(currentTable));
-			output << " VALUES (";
+
+			if (configuration.insertMode == Configuration::InsertMode::SINGLE) {
+				output << "INSERT INTO ";
+				writeIdentifier(output, convertor.to_bytes(currentTable));
+
+				output << " (";
+				for (size_t i = 0, limit = currentAttributes.size(); i < limit; i++) {
+					writeIdentifier(output, convertor.to_bytes(currentAttributes[i].getAttributeName()));
+					if (i < (limit - 1)) output << ", ";
+				}
+				output << ")";
+
+				output << " VALUES (";
+			} else if (configuration.insertMode == Configuration::InsertMode::MULTI) {
+				if (recordCount == 1) {
+					// --------
+					output << "INSERT INTO ";
+					writeIdentifier(output, convertor.to_bytes(currentTable));
+
+					output << "\n\t(";
+					for (size_t i = 0, limit = currentAttributes.size(); i < limit; i++) {
+						writeIdentifier(output, convertor.to_bytes(currentAttributes[i].getAttributeName()));
+						if (i < (limit - 1)) output << ", ";
+					}
+					output << ")";
+					// --------
+
+					output << std::endl << "VALUES" << std::endl;
+				} else {
+					output << "," << std::endl;
+				}
+				output << "\t(";
+			} else {
+				throw RelpipeSQLWriterException(L"Unsupported InsertMode: " + std::to_wstring((int) configuration.insertMode));
+			}
 		}
 
 		valueCount++;
@@ -163,14 +204,20 @@
 		if (valueCount % currentAttributes.size()) {
 			output << ", ";
 		} else {
-			output << ");" << std::endl;
+			if (configuration.insertMode == Configuration::InsertMode::SINGLE) {
+				output << ");" << std::endl;
+			} else if (configuration.insertMode == Configuration::InsertMode::MULTI) {
+				output << ")";
+			} else {
+				throw RelpipeSQLWriterException(L"Unsupported InsertMode: " + std::to_wstring((int) configuration.insertMode));
+			}
 			valueCount = 0;
 		}
 	}
 
 	void endOfPipe() {
 		if (currentTable.size()) {
-			writeRecordCount();
+			endRelation();
 		}
 		output.flush();
 	}