diff --git a/src/test/java/it/inaf/ia2/transfer/persistence/DataSourceConfig.java b/src/test/java/it/inaf/ia2/transfer/persistence/DataSourceConfig.java index 896bd82101f2f72a8dd693a9e12192eb07752b9c..364e65de94a840d73b996834fcca0b67df893503 100644 --- a/src/test/java/it/inaf/ia2/transfer/persistence/DataSourceConfig.java +++ b/src/test/java/it/inaf/ia2/transfer/persistence/DataSourceConfig.java @@ -12,9 +12,12 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; -import java.nio.file.Path; import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.sql.DataSource; @@ -24,9 +27,7 @@ import org.springframework.boot.test.context.TestConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Scope; -import org.springframework.core.io.ByteArrayResource; import org.springframework.core.io.ClassPathResource; -import org.springframework.jdbc.datasource.init.ScriptUtils; /** * Generates a DataSource that can be used for testing DAO classes. It loads an @@ -82,15 +83,59 @@ public class DataSourceConfig { assertTrue(scriptDir.exists(), "DAO tests require " + scriptDir.getAbsolutePath() + " to exists.\n" + "Please clone the repository from https://www.ict.inaf.it/gitlab/vospace/vospace-file-catalog.git"); - File[] scripts = scriptDir.listFiles(f -> f.getName().endsWith(".sql")); - Arrays.sort(scripts); // sort alphabetically + // load all sql files in vospace-file-catalog repo + File[] repoScripts = scriptDir.listFiles(f -> f.getName().endsWith(".sql")); + Arrays.sort(repoScripts); // sort alphabetically + + // add test-data.sql + List<File> scripts = new ArrayList<>(Arrays.asList(repoScripts)); + scripts.add(new ClassPathResource("test-data.sql").getFile()); for (File script : scripts) { - ByteArrayResource scriptResource = replaceDollarQuoting(script.toPath()); - ScriptUtils.executeSqlScript(conn, scriptResource); + String scriptContent = Files.readString(script.toPath()); + for (String sql : splitScript(scriptContent)) { + executeSql(conn, replaceDollarQuoting(sql)); + } } + } + } - ScriptUtils.executeSqlScript(conn, new ClassPathResource("test-data.sql")); + /** + * Spring ScriptUtils is not able to correctly split the SQL statements if a + * function definition contains semicolon characters, so this method is used + * instead of it. + */ + private List<String> splitScript(String script) { + + List<String> parts = new ArrayList<>(); + + StringBuilder sb = new StringBuilder(); + + boolean insideFunc = false; + for (int i = 0; i < script.length(); i++) { + char c = script.charAt(i); + sb.append(c); + + if (insideFunc) { + if (i > 6 && "$func$".equals(script.substring(i - 6, i))) { + insideFunc = false; + } + } else { + if (i > 6 && "$func$".equals(script.substring(i - 6, i))) { + insideFunc = true; + } else if (c == ';') { + parts.add(sb.toString()); + sb = new StringBuilder(); + } + } + } + + return parts; + } + + private void executeSql(Connection conn, String sqlStatement) throws SQLException { + try ( Statement stat = conn.createStatement()) { + stat.execute(sqlStatement); } } @@ -100,9 +145,7 @@ public class DataSourceConfig { * instead of inside the original files because dollar quoting provides a * better visibility. */ - private ByteArrayResource replaceDollarQuoting(Path sqlScriptPath) throws Exception { - - String scriptContent = Files.readString(sqlScriptPath); + private String replaceDollarQuoting(String scriptContent) { if (scriptContent.contains("$func$")) { @@ -114,7 +157,7 @@ public class DataSourceConfig { scriptContent = scriptContent.replace(originalFunction, newFunction); } - return new ByteArrayResource(scriptContent.getBytes()); + return scriptContent; } private String extractFunctionDefinition(String scriptContent) {