Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@
<jarPluginVersion>3.5.1</jarPluginVersion>
<javadocPluginVersion>3.12.0</javadocPluginVersion>
<jxrPluginVersion>3.6.0</jxrPluginVersion>
<modernizer-maven-plugin>2.7.0</modernizer-maven-plugin>
<modernizer-maven-plugin>3.5.0</modernizer-maven-plugin>
<pmdPluginVersion>3.28.0</pmdPluginVersion>
<poiOoxmlVersion>5.2.5</poiOoxmlVersion>
<projectInfoReportsPluginVersion>3.9.0</projectInfoReportsPluginVersion>
Expand Down
1 change: 1 addition & 0 deletions src/changes/changes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@
<action dev="jeffjensen" type="add" issue="501" system="github" due-to="jeffjensen">
Add DatabaseConfig.FEATURE_SKIP_CYCLE_CHECK, an opt-in escape hatch letting DatabaseSequenceFilter proceed on a schema with a foreign-key dependency cycle instead of unconditionally rejecting it with CyclicTablesDependencyException (issues 501 and 517: dbUnit could not order, and therefore could not CLEAN_INSERT/DELETE_ALL, tables bound together by circular FK references). This is the configurable cycle-breaking escape hatch issue 411 originally proposed rather than a full topological resolution of the cycle itself: DatabaseSequenceFilter.sortTableNames now collapses each cycle into a single strongly-connected-component unit for ordering purposes and logs a warning per cycle instead of throwing, so a table outside the cycle is still correctly ordered relative to it (e.g. a table with its own FK to a cyclic table still sorts after the whole cycle, not merely after whichever cyclic member happened to be placed) and every requested table is still returned exactly once; only the relative order of the tables making up the cycle itself is unresolved and falls back to their original input order, leaving the caller responsible for making the cycle insertable another way (e.g. nullable FK columns populated in a later operation, or database-side deferred constraint checking). Off by default, preserving the existing fail-fast behavior for callers who never touch it.
</action>
<action dev="jeffjensen" type="update" issue="732" due-to="jeffjensen">Update maven dependency org.gaul:modernizer-maven-plugin from 2.7.0 to 3.5.0.</action>
</release>
<release version="3.4.0" date="Jul 28, 2026" description="Test-suite hardening (un-skip and strengthen dozens of disabled/no-op tests); add CachingConnectionProvider and reduce DefaultPrepAndExpectedTestCase's per-test connection churn; pin identifier case-folding to Locale.ENGLISH for Turkish-locale correctness; and a broad set of correctness fixes across export formats (XML, YAML, CSV, XLS, Ant), TimestampDataType timezone handling, InsertOperation/TransactionOperation, and resource-leak cleanups">
<action dev="jeffjensen" type="fix" issue="797" system="github" due-to="jeffjensen">
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/dbunit/ant/Export.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@
package org.dbunit.ant;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.sql.SQLException;
Expand Down Expand Up @@ -256,7 +256,7 @@ public void execute(IDatabaseConnection connection) throws DatabaseUnitException
}
else
{
OutputStream out = new FileOutputStream(_dest);
OutputStream out = Files.newOutputStream(_dest.toPath());
try
{
if (_format.equalsIgnoreCase(FORMAT_FLAT))
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/dbunit/ant/Operation.java
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public void addConfiguredFileset(FileSet fileSet)
{
DirectoryScanner scanner = fileSet.getDirectoryScanner(getProject());
for (String file : scanner.getIncludedFiles()) {
_sources.add(new File(scanner.getBasedir(), file));
_sources.add(scanner.getBasedir().toPath().resolve(file).toFile());
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/dbunit/database/DatabaseTableMetaData.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.dbunit.dataset.AbstractTableMetaData;
Expand Down Expand Up @@ -238,7 +238,7 @@ private String[] getPrimaryKeyNames() throws SQLException
resultSet.close();
}

Collections.sort(list);
list.sort(Comparator.naturalOrder());
String[] keys = new String[list.size()];
for (int i = 0; i < keys.length; i++)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,6 @@
import org.dbunit.dataset.datatype.TypeCastException;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

/**
* Decorator that adapts a plain {@link IBatchStatement} to the {@link IPreparedBatchStatement}
Expand All @@ -57,19 +54,7 @@ public class BatchStatementDecorator implements IPreparedBatchStatement

BatchStatementDecorator(String sql, IBatchStatement statement)
{
List list = new ArrayList();
StringTokenizer tokenizer = new StringTokenizer(sql, "?");
while (tokenizer.hasMoreTokens())
{
list.add(tokenizer.nextToken());
}

if (sql.endsWith("?"))
{
list.add("");
}

_sqlTemplate = (String[])list.toArray(new String[0]);
_sqlTemplate = sql.split("\\?", -1);
_statement = statement;

// reset sql buffer
Expand Down
18 changes: 1 addition & 17 deletions src/main/java/org/dbunit/dataset/DataSetUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@

import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import org.dbunit.Assertion;
import org.dbunit.dataset.datatype.DataType;
Expand Down Expand Up @@ -187,22 +186,7 @@ public static String getSqlValueString(Object value, DataType dataType)
}

// escaping single quotes
final StringBuilder buffer = new StringBuilder(stringValue.length() * 2);
StringTokenizer tokenizer = new StringTokenizer(stringValue, "'", true);

buffer.append("'");
while (tokenizer.hasMoreTokens())
{
String token = tokenizer.nextToken();
buffer.append(token);
if (token.equals("'"))
{
buffer.append("'");
}
}
buffer.append("'");
return buffer.toString();

return "'" + stringValue.replace("'", "''") + "'";
}

return stringValue;
Expand Down
27 changes: 20 additions & 7 deletions src/main/java/org/dbunit/dataset/csv/CsvDataSetWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,13 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
Expand Down Expand Up @@ -106,26 +107,34 @@ public void write(IDataSet dataSet) throws DataSetException {
provider.produce();
}

/**
* {@inheritDoc}
*/
@Override
public void startDataSet() throws DataSetException {
logger.debug("startDataSet() - start");

try {
tableList = new LinkedList();
new File(getTheDirectory()).mkdirs();
Paths.get(getTheDirectory()).toFile().mkdirs();
} catch (Exception e) {
throw new DataSetException("Error while creating the destination directory '" + getTheDirectory() + "'", e);
}
}

/**
* {@inheritDoc}
*/
@Override
public void endDataSet() throws DataSetException {
logger.debug("endDataSet() - start");

// write out table ordering file
File orderingFile = new File(getTheDirectory(), CsvDataSet.TABLE_ORDERING_FILE);
File orderingFile = Paths.get(getTheDirectory(), CsvDataSet.TABLE_ORDERING_FILE).toFile();

PrintWriter pw = null;
try {
pw = new PrintWriter(new FileWriter(orderingFile));
pw = new PrintWriter(Files.newBufferedWriter(orderingFile.toPath(), StandardCharsets.UTF_8));
Comment thread
coderabbitai[bot] marked this conversation as resolved.
for (Iterator fileNames = tableList.iterator(); fileNames.hasNext();) {
String file = (String) fileNames.next();
pw.println(file);
Expand All @@ -141,13 +150,17 @@ public void endDataSet() throws DataSetException {
}
}

/**
* {@inheritDoc}
*/
@Override
public void startTable(ITableMetaData metaData) throws DataSetException {
logger.debug("startTable(metaData={}) - start", metaData);

try {
_activeMetaData = metaData;
String tableName = _activeMetaData.getTableName();
setWriter(new BufferedWriter(new FileWriter(getTheDirectory() + File.separator + tableName + ".csv")));
setWriter(Files.newBufferedWriter(Paths.get(getTheDirectory(), tableName + ".csv"), StandardCharsets.UTF_8));
writeColumnNames();
getWriter().write(System.getProperty("line.separator"));
} catch (IOException e) {
Expand Down
9 changes: 6 additions & 3 deletions src/main/java/org/dbunit/dataset/csv/CsvParserImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.io.LineNumberReader;
import java.io.Reader;
import java.net.URL;
Expand Down Expand Up @@ -100,7 +101,8 @@ public List parse(String csv) throws PipelineException, IllegalInputCharacterExc
public List parse(File file) throws IOException, CsvParserException {
logger.debug("parse(file={}) - start", file);

BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
BufferedReader reader = new BufferedReader(
new InputStreamReader(Files.newInputStream(file.toPath()), StandardCharsets.UTF_8));
try {
return parse(reader, file.getAbsolutePath().toString());
}
Expand All @@ -112,7 +114,8 @@ public List parse(File file) throws IOException, CsvParserException {
public List parse(URL url) throws IOException, CsvParserException {
logger.debug("parse(url={}) - start", url);

BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
BufferedReader reader = new BufferedReader(
new InputStreamReader(url.openStream(), StandardCharsets.UTF_8));
try {
return parse(reader, url.toString());
}
Expand Down
55 changes: 50 additions & 5 deletions src/main/java/org/dbunit/dataset/csv/CsvProducer.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.InvalidPathException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
Expand Down Expand Up @@ -87,22 +92,31 @@ public void setConsumer(IDataSetConsumer consumer) throws DataSetException {
_consumer = consumer;
}

/**
* {@inheritDoc}
*/
@Override
public void produce() throws DataSetException {
logger.debug("produce() - start");

File dir = new File(_theDirectory);
File dir;
try {
dir = Paths.get(_theDirectory).toFile();
} catch (final InvalidPathException e) {
throw new DataSetException("'" + _theDirectory + "' should be a directory", e);
}

if (!dir.isDirectory()) {
throw new DataSetException("'" + _theDirectory + "' should be a directory");
}

_consumer.startDataSet();
try {
List tableSpecs = CsvProducer.getTables(dir.toURL(), CsvDataSet.TABLE_ORDERING_FILE);
List tableSpecs = CsvProducer.getTables(dir.toURI().toURL(), CsvDataSet.TABLE_ORDERING_FILE);
for (Iterator tableIter = tableSpecs.iterator(); tableIter.hasNext();) {
String table = (String) tableIter.next();
try {
produceFromFile(new File(dir, table + ".csv"));
produceFromFile(dir.toPath().resolve(table + ".csv").toFile());
} catch (CsvParserException e) {
throw new DataSetException("error producing dataset for table '" + table + "'", e);
} catch (DataSetException e) {
Expand Down Expand Up @@ -169,10 +183,10 @@ public static List getTables(URL base, String tableList) throws IOException {
logger.debug("getTables(base={}, tableList={}) - start", base, tableList);

List orderedNames = new ArrayList();
InputStream tableListStream = new URL(base, tableList).openStream();
InputStream tableListStream = resolveRelative(base, tableList).openStream();
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(tableListStream));
reader = new BufferedReader(new InputStreamReader(tableListStream, StandardCharsets.UTF_8));
String line = null;
while((line = reader.readLine()) != null) {
String table = line.trim();
Expand All @@ -190,4 +204,35 @@ public static List getTables(URL base, String tableList) throws IOException {
return orderedNames;
}

/**
* Resolves a relative spec against a base URL without the deprecated
* {@code URL(URL, String)} constructor.
*
* <p>{@link URI#resolve(String)} handles this correctly for a hierarchical
* base (e.g. a plain {@code file:}/{@code http:} URL, whether it names a
* directory or a sibling file), but for an opaque base such as a
* {@code jar:...!/} URL it silently ignores the base and returns the spec
* as-is. For an opaque base, the spec is instead appended directly to the
* scheme-specific part, matching how the {@code jar:} protocol handler
* itself combines a root jar URL with an entry path.
*
* @param base the base URL.
* @param spec the relative spec to resolve against it.
* @return the resolved URL.
* @throws IOException if the base or the resolved URL is malformed.
*/
static URL resolveRelative(final URL base, final String spec) throws IOException {
try {
final URI baseUri = base.toURI();
final URI resolved = baseUri.isOpaque()
? new URI(baseUri.getScheme(),
baseUri.getSchemeSpecificPart() + spec,
baseUri.getFragment())
: baseUri.resolve(spec);
return resolved.toURL();
} catch (final URISyntaxException e) {
throw new IOException(e);
}
}

}
7 changes: 4 additions & 3 deletions src/main/java/org/dbunit/dataset/csv/CsvURLProducer.java
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,10 @@ public void setConsumer(IDataSetConsumer consumer) throws DataSetException {
_consumer = consumer;
}

/*
* @see IDataSetProducer#produce()
/**
* {@inheritDoc}
*/
@Override
public void produce() throws DataSetException {
logger.debug("produce() - start");

Expand All @@ -104,7 +105,7 @@ public void produce() throws DataSetException {
for (Iterator tableIter = tableSpecs.iterator(); tableIter.hasNext();) {
String table = (String) tableIter.next();
try {
produceFromURL(new URL(base, table + ".csv"));
produceFromURL(CsvProducer.resolveRelative(base, table + ".csv"));
} catch (CsvParserException e) {
throw new DataSetException("error producing dataset for table '" + table + "'", e);
}
Expand Down
Loading
Loading