DB Backup Bugfix

This commit is contained in:
Stefan Hardegger
2025-07-31 07:54:43 +02:00
parent e89331e059
commit 415eab07de

View File

@@ -12,6 +12,7 @@ import javax.sql.DataSource;
import java.io.*; import java.io.*;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.sql.*; import java.sql.*;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@@ -120,12 +121,14 @@ public class DatabaseManagementService {
connection.setAutoCommit(false); connection.setAutoCommit(false);
try { try {
// Split by semicolon and execute each statement // Parse SQL statements properly (handle semicolons inside string literals)
String[] statements = sqlContent.toString().split(";"); List<String> statements = parseStatements(sqlContent.toString());
for (String statement : statements) { for (String statement : statements) {
String trimmedStatement = statement.trim(); String trimmedStatement = statement.trim();
if (!trimmedStatement.isEmpty()) { if (!trimmedStatement.isEmpty()) {
System.err.println("DEBUG: Executing statement: " +
(trimmedStatement.length() > 200 ? trimmedStatement.substring(0, 200) + "..." : trimmedStatement));
try (PreparedStatement stmt = connection.prepareStatement(trimmedStatement)) { try (PreparedStatement stmt = connection.prepareStatement(trimmedStatement)) {
stmt.execute(); stmt.execute();
} }
@@ -183,6 +186,55 @@ public class DatabaseManagementService {
return totalDeleted; return totalDeleted;
} }
/**
* Parses SQL content into individual statements, properly handling semicolons inside string literals
*/
private List<String> parseStatements(String sql) {
List<String> statements = new ArrayList<>();
StringBuilder currentStatement = new StringBuilder();
boolean inString = false;
for (int i = 0; i < sql.length(); i++) {
char c = sql.charAt(i);
if (c == '\'' && !inString) {
// Start of string literal
inString = true;
currentStatement.append(c);
} else if (c == '\'' && inString) {
// Potential end of string literal
currentStatement.append(c);
// Check if this is an escaped quote (doubled single quote)
if (i + 1 < sql.length() && sql.charAt(i + 1) == '\'') {
// This is an escaped quote, skip the next quote
i++;
currentStatement.append('\'');
} else {
// End of string literal
inString = false;
}
} else if (c == ';' && !inString) {
// Statement terminator outside of string literal
String statement = currentStatement.toString().trim();
if (!statement.isEmpty()) {
statements.add(statement);
}
currentStatement = new StringBuilder();
} else {
currentStatement.append(c);
}
}
// Add final statement if any
String finalStatement = currentStatement.toString().trim();
if (!finalStatement.isEmpty()) {
statements.add(finalStatement);
}
return statements;
}
/** /**
* Formats a database value for SQL insertion, handling proper escaping * Formats a database value for SQL insertion, handling proper escaping
*/ */
@@ -214,16 +266,9 @@ public class DatabaseManagementService {
stringValue = value.toString(); stringValue = value.toString();
} }
// Debug output for large fields
if (stringValue.length() > 1000) {
System.err.println("DEBUG: Processing large field (length: " + stringValue.length() +
") with quotes: " + stringValue.contains("'") +
" type: " + value.getClass().getSimpleName());
}
// Escape single quotes by replacing ' with '' and wrap in quotes // Escape single quotes by replacing ' with '' and wrap in quotes
// This is the critical line - make absolutely sure single quotes are escaped
String escapedValue = stringValue.replace("'", "''"); String escapedValue = stringValue.replace("'", "''");
return "'" + escapedValue + "'"; return "'" + escapedValue + "'";
} }
} }