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
3 changes: 3 additions & 0 deletions .github/workflows/build-any-branch-with-all-dbs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ jobs:
{name: 'Derby', profile: 'derby-10-14', url: ''},
{name: 'H2', profile: 'h2-1-4', url: ''},
{name: 'HSQLDB', profile: 'hsqldb-2-7', url: ''},
# nullCatalogMeansCurrent=true must also stay on mariadb-dbunit.properties'
# dbunit.profile.url - see mariadb.adoc's IMetadataHandler section for why.
{name: 'MariaDB', profile: 'mariadb-11-4', url: 'jdbc:mariadb://localhost:3306/dbunit?nullCatalogMeansCurrent=true'},
{name: 'MSSQL', profile: 'mssql-2022', url: 'jdbc:sqlserver://localhost:1433;DatabaseName=dbunit;user=sa;password=theSaPassword1234;Trusted_Connection=True;SelectMethod=cursor'},
{name: 'MySQL', profile: 'mysql-9-20', url: 'jdbc:mysql://localhost:3306/dbunit'},
{name: 'Oracle 18', profile: 'oracle-18', url: ''},
Expand Down
1 change: 1 addition & 0 deletions database-profiles.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ db2-11-5
derby-10-14
h2-1-4
hsqldb-2-7
mariadb-11-4
mssql-2022
mysql-9-20
oracle-18
Expand Down
67 changes: 67 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
<derbyDriverVersion>10.14.2.0</derbyDriverVersion>
<h2DriverVersion>1.4.200</h2DriverVersion>
<hsqldbDriverVersion>2.7.4</hsqldbDriverVersion>
<mariadbDriverVersion>3.5.3</mariadbDriverVersion>
<mysqlDriverVersion>8.0.31</mysqlDriverVersion>
<!-- Oracle JDBC Driver compatible with JDK6, JDK7, and JDK8 -->
<oracleJ6DriverVersion>11.2.0.4</oracleJ6DriverVersion>
Expand Down Expand Up @@ -119,20 +120,23 @@

<!-- docker images -->
<docker.image.name.db2-11>icr.io/db2_community/db2:11.5.9.0</docker.image.name.db2-11>
<docker.image.name.mariadb-11-4>mariadb:11.4</docker.image.name.mariadb-11-4>
<docker.image.name.mssql-2022>mcr.microsoft.com/mssql/server:2022-latest</docker.image.name.mssql-2022>
<docker.image.name.mysql.9-20>mysql:9.2.0</docker.image.name.mysql.9-20>
<docker.image.name.oracle-18>gvenzl/oracle-xe:18.4.0-faststart</docker.image.name.oracle-18>
<docker.image.name.oracle-23>gvenzl/oracle-free:23.6-faststart</docker.image.name.oracle-23>
<docker.image.name.postgresql-16>postgres:16.3</docker.image.name.postgresql-16>

<docker.image.ready.message.db2>Setup has completed.</docker.image.ready.message.db2>
<docker.image.ready.message.mariadb>(?s)Giving user dbunit access to schema dbunit.*mariadbd: ready for connections.</docker.image.ready.message.mariadb>
<docker.image.ready.message.mssql>SQL Server is now ready for client connections.</docker.image.ready.message.mssql>
<docker.image.ready.message.mysql>(?s)Giving user dbunit access to schema dbunit.*mysqld: ready for connections.</docker.image.ready.message.mysql>
<docker.image.ready.message.oracle>DATABASE IS READY TO USE!</docker.image.ready.message.oracle>
<docker.image.ready.message.postgresql>(?s)database system is shut down.*database system is ready to accept connections</docker.image.ready.message.postgresql>

<!-- docker image configs -->
<database.port.db2>50000</database.port.db2>
<database.port.mariadb>3306</database.port.mariadb>
<database.port.mssql>1433</database.port.mssql>
<database.port.mysql>3306</database.port.mysql>
<database.port.oracle>1521</database.port.oracle>
Expand Down Expand Up @@ -344,6 +348,12 @@
<version>${hsqldbDriverVersion}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<version>${mariadbDriverVersion}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
Comment thread
sourcery-ai[bot] marked this conversation as resolved.
Expand Down Expand Up @@ -1938,6 +1948,63 @@
</dependency>
</dependencies>
</profile>
<profile>
<id>mariadb-11-4</id>
<properties>
<surefirePluginSkip>true</surefirePluginSkip>
<modernizerPluginSkip>true</modernizerPluginSkip>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<configuration>
<urls>
<url>file:///${basedir}/src/test/resources/mariadb-dbunit.properties</url>
</urls>
</configuration>
</plugin>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<configuration>
<images>
<image>
<name>${docker.image.name.mariadb-11-4}</name>
<run>
<ports>
<port>${database.port.mariadb}:3306</port>
</ports>
<env>
<MARIADB_ROOT_PASSWORD>${dbunit.profile.password}</MARIADB_ROOT_PASSWORD>
<MARIADB_DATABASE>${dbunit.profile.user}</MARIADB_DATABASE>
<MARIADB_USER>${dbunit.profile.user}</MARIADB_USER>
<MARIADB_PASSWORD>${dbunit.profile.password}</MARIADB_PASSWORD>
<TZ>America/Chicago</TZ>
</env>
<wait>
<log>${docker.image.ready.message.mariadb}</log>
<time>${docker.plugin.start.wait.time.ms}</time>
</wait>
</run>
</image>
</images>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
</dependency>
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
</dependency>
</dependencies>
</profile>
<profile>
<id>mysql-9-20</id>
<properties>
Expand Down
5 changes: 4 additions & 1 deletion src/changes/changes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
</properties>

<body>
<release version="3.4.1-SNAPSHOT" date="TBD" description="A documentation-site overhaul (new tutorials, 9 database vendor guides, a class-by-class Core Components reference, consolidated Filters/Datasets/Operations pages, and a new Developing DbUnit contributor section covering coding standards, commit/changelog requirements, and the GitHub workflow); an opt-in all-column sort for tables without a primary key; an opt-in sort-on-filtered-columns-only mode for DefaultPrepAndExpectedTestCase fixing false failures on tables with a generated/identity first column; MultiSchemaMySqlMetadataHandler for multi-schema MySQL connections; constructor-injected per-connection DatabaseConfig support for DataSourceDatabaseTester; and multiple bug fixes including escape-pattern handling, primary-key filter fallback, empty-dataset DTD export, DatabaseDataSet initialization order, and a from-scratch clean-build pass across Javadoc doclint, Checkstyle, and compiler warnings">
<release version="3.4.1-SNAPSHOT" date="TBD" description="A documentation-site overhaul (new tutorials, 9 database vendor guides, a class-by-class Core Components reference, consolidated Filters/Datasets/Operations pages, and a new Developing DbUnit contributor section covering coding standards, commit/changelog requirements, and the GitHub workflow); an opt-in all-column sort for tables without a primary key; an opt-in sort-on-filtered-columns-only mode for DefaultPrepAndExpectedTestCase fixing false failures on tables with a generated/identity first column; MultiSchemaMySqlMetadataHandler for multi-schema MySQL connections; constructor-injected per-connection DatabaseConfig support for DataSourceDatabaseTester; new MariaDB support (MariaDbDataTypeFactory plus a Docker-backed IT profile); and multiple bug fixes including escape-pattern handling, primary-key filter fallback, empty-dataset DTD export, DatabaseDataSet initialization order, and a from-scratch clean-build pass across Javadoc doclint, Checkstyle, and compiler warnings">
<action dev="jeffjensen" type="add" issue="840" system="github" due-to="jeffjensen">
Add repo-root README.adoc, rendered natively by GitHub via Asciidoctor, so the repository landing page shows a pitch, build/reproducible-build badges, a pointer to the "dbUnit in 5 Minutes" tutorial, and links to the documentation site, Maven coordinates, GitHub Discussions, and CONTRIBUTING.md instead of nothing.
</action>
Expand Down Expand Up @@ -227,6 +227,9 @@
<action dev="jeffjensen" type="add" issue="707" system="github" due-to="pmoukhataev">
Add a DataSourceDatabaseTester(DataSource, String schema, CachingConnectionProvider, DatabaseConfig) constructor and a new DatabaseConfig#copyPropertiesInto(DatabaseConfig) method, so per-connection properties and features (e.g. PROPERTY_DATATYPE_FACTORY for a specific database) can be applied to every connection a DataSourceDatabaseTester creates directly through the constructor, instead of requiring an IOperationListener#connectionRetrieved() override to reach into each connection's DatabaseConfig after the fact. Also fix DatabaseConfig's own constructor, which left FEATURE_SKIP_ORACLE_RECYCLEBIN_TABLES's underlying property value unset despite ALL_PROPERTIES declaring it non-nullable - harmless until copyPropertiesInto()'s full iteration over ALL_PROPERTIES became the first caller to round-trip every declared property through setProperty(), which enforces that constraint strictly.
</action>
<action dev="jeffjensen" type="add" issue="706" system="github" due-to="estebanjgarcia">
Add MariaDB support in a new org.dbunit.ext.mariadb package, separate from org.dbunit.ext.mysql since MariaDB is its own distinct, independently-branded product (mirroring how org.dbunit.ext.netezza stays independent of org.dbunit.ext.postgresql despite Netezza's Postgres lineage): MariaDbDataTypeFactory (extends MySqlDataTypeFactory to reuse its real, verified-shared type handling) declares "mariadb" as a valid database product, silencing the "might cause problems with the current database" warning, and recognizes MariaDB's native UUID (10.7+) and INET4/INET6 (10.10+) column types, which MariaDB Connector/J reports as SQL type OTHER with no MySQL equivalent; MariaDB's JSON type is a LONGTEXT alias and already worked via the inherited longtext handling. Add a mariadb-11-4 Maven profile and Docker-backed IT suite mirroring the existing mysql-9-20 profile, and a dedicated databases/mariadb.adoc site page (with its own navigation entry) instead of folding coverage into the MySQL page. Along the way, found and documented that MariaDB Connector/J, unlike MySQL Connector/J, has no nullCatalogMeansCurrent-equivalent default: an unfiltered DatabaseMetaData#getTables() call leaks information_schema/performance_schema tables into dbUnit's table map, surfacing as a SQLSyntaxErrorException the moment an operation like DELETE_ALL touches one of them, unless MySqlMetadataHandler is registered or nullCatalogMeansCurrent=true is added to the JDBC URL.
</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
87 changes: 87 additions & 0 deletions src/main/java/org/dbunit/ext/mariadb/MariaDbDataTypeFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
*
* The DbUnit Database Testing Framework
* Copyright (C)2002-2004, DbUnit.org
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package org.dbunit.ext.mariadb;

import java.sql.Types;
import java.util.Arrays;
import java.util.Collection;

import org.dbunit.dataset.datatype.DataType;
import org.dbunit.dataset.datatype.DataTypeException;
import org.dbunit.ext.mysql.MySqlDataTypeFactory;

/**
* Specialized factory that recognizes MariaDB data types.
* <p>
* MariaDB is wire-compatible with MySQL, so this extends
* {@link MySqlDataTypeFactory} and adds recognition for the MariaDB-native
* types that have no MySQL equivalent: {@code UUID} (10.7+) and
* {@code INET4}/{@code INET6} (10.10+). MariaDB's JDBC driver reports all
* three as SQL type {@link Types#OTHER}, which {@link MySqlDataTypeFactory}
* (and its {@code DefaultDataTypeFactory} parent) does not otherwise
* recognize.
* <p>
* MariaDB's {@code JSON} type is a {@code LONGTEXT} alias enforced by a
* {@code CHECK} constraint, not a distinct SQL type — it already reports as
* plain {@code LONGTEXT} and needs no special handling here.
*
* @author Jeff Jensen
* @since 3.4.1
*/
public class MariaDbDataTypeFactory extends MySqlDataTypeFactory
{
/** SQL type name MariaDB reports for a native {@code UUID} column. */
public static final String SQL_TYPE_NAME_UUID = "UUID";
/** SQL type name MariaDB reports for a native {@code INET4} column. */
public static final String SQL_TYPE_NAME_INET4 = "INET4";
/** SQL type name MariaDB reports for a native {@code INET6} column. */
public static final String SQL_TYPE_NAME_INET6 = "INET6";

/**
* Database product names supported.
*/
private static final Collection DATABASE_PRODUCTS = Arrays.asList(new String[] {"mariadb"});

/**
* @see org.dbunit.dataset.datatype.IDbProductRelatable#getValidDbProducts()
*/
@Override
public Collection getValidDbProducts()
{
return DATABASE_PRODUCTS;
}

@Override
public DataType createDataType(int sqlType, String sqlTypeName) throws DataTypeException
{
if (sqlType == Types.OTHER)
{
if (SQL_TYPE_NAME_UUID.equalsIgnoreCase(sqlTypeName)
|| SQL_TYPE_NAME_INET4.equalsIgnoreCase(sqlTypeName)
|| SQL_TYPE_NAME_INET6.equalsIgnoreCase(sqlTypeName))
{
return DataType.VARCHAR;
}
Comment thread
sourcery-ai[bot] marked this conversation as resolved.
}

return super.createDataType(sqlType, sqlTypeName);
}
}
1 change: 1 addition & 0 deletions src/site/asciidoc/databases.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ registration mechanism.
|link:databases/db2.html[DB2] |A metadata handler fixing a catalog/schema column-matching bug.
|link:databases/h2.html[H2] |`BOOLEAN`/`UUID` type recognition.
|link:databases/hsqldb.html[HSQLDB] |`BOOLEAN` type recognition.
|link:databases/mariadb.html[MariaDB] |A factory (extending MySQL's) for `UUID`/`INET4`/`INET6` types.
|link:databases/mckoi.html[Mckoi] |SQL type name recognition for this niche/legacy database.
|link:databases/mssql.html[MSSQL] |`uniqueidentifier`/`datetimeoffset` types, `InsertIdentityOperation` for explicit IDENTITY inserts.
|link:databases/mysql.html[MySQL] |A metadata handler fixing qualified-table-name matching.
Expand Down
77 changes: 77 additions & 0 deletions src/site/asciidoc/databases/mariadb.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
= MariaDB

== Overview

`org.dbunit.ext.mariadb` provides MariaDB-specific type recognition for
dbUnit. MariaDB is wire- and SQL-compatible with MySQL, so its factory
builds on link:mysql.html[MySQL]'s rather than duplicating it, but this
page is self-contained — no need to read the MySQL page too.

== IDataTypeFactory

link:/dbunit/apidocs/org/dbunit/ext/mariadb/MariaDbDataTypeFactory.html[MariaDbDataTypeFactory]
extends `MySqlDataTypeFactory`, so it inherits MySQL's mappings —
Comment thread
coderabbitai[bot] marked this conversation as resolved.
`longtext` as `CLOB`, `bit` as `BOOLEAN`/`TINYINT` depending on context,
`point` as `BINARY`, and the `UNSIGNED` integer family — and adds
recognition of MariaDB-native types with no MySQL equivalent:

[cols="1,3", options="header"]
|===
|Type |Handling

|`UUID` (10.7+) |Reported as SQL type `OTHER`; mapped to `VARCHAR`.
|`INET4` (10.10+) |Reported as SQL type `OTHER` via table metadata (a live query instead reports it as plain `CHAR`, indistinguishable from a real char column); mapped to `VARCHAR`.
|`INET6` (10.10+) |Same as `INET4`.
|`JSON` |A `LONGTEXT` alias enforced by a `CHECK` constraint, not a distinct SQL type — already works via the inherited `longtext` handling, no extra mapping needed.
|===

Register it via `DatabaseConfig.PROPERTY_DATATYPE_FACTORY` — see
link:../properties.html#typefactory[Properties] and
link:../connections.html[Connections & Configuration].

== IMetadataHandler

There is no MariaDB-specific `IMetadataHandler` — register MySQL's
link:/dbunit/apidocs/org/dbunit/ext/mysql/MySqlMetadataHandler.html[MySqlMetadataHandler]
instead, and treat it as a requirement rather than an option: MariaDB
Connector/J needs it even more than MySQL does. MySQL Connector/J's
`nullCatalogMeansCurrent` default already restricts an unfiltered
`DatabaseMetaData#getTables()` call to the connection's current database;
MariaDB Connector/J has no such default, so a connection using dbUnit's
plain default handler sees every catalog's tables, including
`information_schema`/`performance_schema` system tables. dbUnit then fails
with a `SQLSyntaxErrorException` the moment it tries to operate on one of
those leaked tables (e.g. during `DELETE_ALL`). `MySqlMetadataHandler`
fixes this because it passes the schema as the JDBC catalog argument,
which MariaDB Connector/J does honor even though it ignores the schema
pattern argument. Equivalently — or in addition, for defense in depth —
add `nullCatalogMeansCurrent=true` to the MariaDB JDBC URL to match MySQL
Connector/J's own default.

== Connection Preconfiguration Class

None — MariaDB has no dedicated `IDatabaseConnection` subclass. Register
`MariaDbDataTypeFactory` and `MySqlMetadataHandler` directly on a plain
`DatabaseConnection`'s `DatabaseConfig`:

[source,java]
----
IDatabaseConnection connection = new DatabaseConnection(jdbcConnection, schema);
DatabaseConfig config = connection.getConfig();
config.setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new MariaDbDataTypeFactory());
config.setProperty(DatabaseConfig.PROPERTY_METADATA_HANDLER, new MySqlMetadataHandler());
----

== Vendor-Specific Types

The `longtext`/`bit`/`point`/`UNSIGNED` handling inherited from MySQL,
plus MariaDB's own `UUID`/`INET4`/`INET6` handling — see
`IDataTypeFactory` above.

== Known Quirks

Forgetting to register `MySqlMetadataHandler` (or the
`nullCatalogMeansCurrent=true` URL parameter) is the most common surprise
on MariaDB: it surfaces as a `SQLSyntaxErrorException` naming an
`information_schema`/`performance_schema` table rather than anything
that looks like a configuration problem — see `IMetadataHandler` above.
5 changes: 3 additions & 2 deletions src/site/asciidoc/databases/mysql.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

== Overview

`org.dbunit.ext.mysql` provides MySQL/MariaDB-specific type recognition and
metadata handling for dbUnit.
`org.dbunit.ext.mysql` provides MySQL-specific type recognition and
metadata handling for dbUnit. See link:mariadb.html[MariaDB] for MariaDB,
which has its own dedicated factory and reuses MySQL's metadata handling.

== IDataTypeFactory

Expand Down
1 change: 1 addition & 0 deletions src/site/site.xml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
<item name="DB2" href="/databases/db2.html"/>
<item name="H2" href="/databases/h2.html"/>
<item name="HSQLDB" href="/databases/hsqldb.html"/>
<item name="MariaDB" href="/databases/mariadb.html"/>
<item name="Mckoi" href="/databases/mckoi.html"/>
<item name="MSSQL" href="/databases/mssql.html"/>
<item name="MySQL" href="/databases/mysql.html"/>
Expand Down
Loading
Loading