diff --git a/.github/workflows/build-any-branch-with-all-dbs.yml b/.github/workflows/build-any-branch-with-all-dbs.yml index 14e3c4e8f..f7c0e9338 100644 --- a/.github/workflows/build-any-branch-with-all-dbs.yml +++ b/.github/workflows/build-any-branch-with-all-dbs.yml @@ -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: ''}, diff --git a/database-profiles.txt b/database-profiles.txt index d0f9f1e16..0df005bdf 100644 --- a/database-profiles.txt +++ b/database-profiles.txt @@ -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 diff --git a/pom.xml b/pom.xml index 349754990..47f76d669 100644 --- a/pom.xml +++ b/pom.xml @@ -64,6 +64,7 @@ 10.14.2.0 1.4.200 2.7.4 + 3.5.3 8.0.31 11.2.0.4 @@ -119,6 +120,7 @@ icr.io/db2_community/db2:11.5.9.0 + mariadb:11.4 mcr.microsoft.com/mssql/server:2022-latest mysql:9.2.0 gvenzl/oracle-xe:18.4.0-faststart @@ -126,6 +128,7 @@ postgres:16.3 Setup has completed. + (?s)Giving user dbunit access to schema dbunit.*mariadbd: ready for connections. SQL Server is now ready for client connections. (?s)Giving user dbunit access to schema dbunit.*mysqld: ready for connections. DATABASE IS READY TO USE! @@ -133,6 +136,7 @@ 50000 + 3306 1433 3306 1521 @@ -344,6 +348,12 @@ ${hsqldbDriverVersion} test + + org.mariadb.jdbc + mariadb-java-client + ${mariadbDriverVersion} + test + mysql mysql-connector-java @@ -1938,6 +1948,63 @@ + + mariadb-11-4 + + true + true + + + + + org.codehaus.mojo + properties-maven-plugin + + + file:///${basedir}/src/test/resources/mariadb-dbunit.properties + + + + + io.fabric8 + docker-maven-plugin + + + + ${docker.image.name.mariadb-11-4} + + + ${database.port.mariadb}:3306 + + + ${dbunit.profile.password} + ${dbunit.profile.user} + ${dbunit.profile.user} + ${dbunit.profile.password} + America/Chicago + + + ${docker.image.ready.message.mariadb} + + + + + + + + + + + + org.mariadb.jdbc + mariadb-java-client + + + com.oracle.database.jdbc + ojdbc8 + + + mysql-9-20 diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 1bcf68f20..957b77367 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -13,7 +13,7 @@ - + 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. @@ -227,6 +227,9 @@ 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. + + 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. + diff --git a/src/main/java/org/dbunit/ext/mariadb/MariaDbDataTypeFactory.java b/src/main/java/org/dbunit/ext/mariadb/MariaDbDataTypeFactory.java new file mode 100644 index 000000000..8bc280e70 --- /dev/null +++ b/src/main/java/org/dbunit/ext/mariadb/MariaDbDataTypeFactory.java @@ -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. + *

+ * 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. + *

+ * 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; + } + } + + return super.createDataType(sqlType, sqlTypeName); + } +} diff --git a/src/site/asciidoc/databases.adoc b/src/site/asciidoc/databases.adoc index 5fe26e415..f095c3b6e 100644 --- a/src/site/asciidoc/databases.adoc +++ b/src/site/asciidoc/databases.adoc @@ -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. diff --git a/src/site/asciidoc/databases/mariadb.adoc b/src/site/asciidoc/databases/mariadb.adoc new file mode 100644 index 000000000..c983a6f40 --- /dev/null +++ b/src/site/asciidoc/databases/mariadb.adoc @@ -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 — +`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. diff --git a/src/site/asciidoc/databases/mysql.adoc b/src/site/asciidoc/databases/mysql.adoc index c5c65b739..656cd9747 100644 --- a/src/site/asciidoc/databases/mysql.adoc +++ b/src/site/asciidoc/databases/mysql.adoc @@ -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 diff --git a/src/site/site.xml b/src/site/site.xml index 8f471c6fa..9a7b7ee56 100644 --- a/src/site/site.xml +++ b/src/site/site.xml @@ -97,6 +97,7 @@ + diff --git a/src/test/java/org/dbunit/DatabaseEnvironment.java b/src/test/java/org/dbunit/DatabaseEnvironment.java index 9df6eac07..8cd14024b 100644 --- a/src/test/java/org/dbunit/DatabaseEnvironment.java +++ b/src/test/java/org/dbunit/DatabaseEnvironment.java @@ -148,6 +148,9 @@ public static DatabaseEnvironment getInstance() throws Exception } else if (profileName.equals("mysql")) { INSTANCE = new MySqlEnvironment(profile); + } else if (profileName.equals("mariadb")) + { + INSTANCE = new MariaDbEnvironment(profile); } else if (profileName.equals("derby")) { INSTANCE = new DerbyEnvironment(profile); diff --git a/src/test/java/org/dbunit/MariaDbEnvironment.java b/src/test/java/org/dbunit/MariaDbEnvironment.java new file mode 100644 index 000000000..523f6632b --- /dev/null +++ b/src/test/java/org/dbunit/MariaDbEnvironment.java @@ -0,0 +1,70 @@ +/* + * + * The DbUnit Database Testing Framework + * Copyright (C)2002-2009, 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; + +import org.dbunit.database.DatabaseConfig; +import org.dbunit.ext.mariadb.MariaDbDataTypeFactory; +import org.dbunit.ext.mysql.MySqlMetadataHandler; + +/** + * @author Jeff Jensen (adapted from John Hurst: MySqlEnvironment) + * @since 3.4.1 + */ +public class MariaDbEnvironment extends DatabaseEnvironment +{ + public MariaDbEnvironment(DatabaseProfile profile) throws Exception + { + super(profile); + } + + /** + * {@inheritDoc} + *

+ * Also registers {@link MySqlMetadataHandler}: unlike MySQL Connector/J + * (whose {@code nullCatalogMeansCurrent} default restricts an unfiltered + * {@code DatabaseMetaData#getTables()} call to the current database), + * MariaDB Connector/J returns every catalog's tables - including + * {@code information_schema}/{@code performance_schema} - unless the + * schema is passed as the JDBC catalog argument, which is exactly what + * {@link MySqlMetadataHandler} does. + */ + @Override + protected void setupDatabaseConfig(DatabaseConfig config) + { + config.setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, + new MariaDbDataTypeFactory()); + config.setProperty(DatabaseConfig.PROPERTY_METADATA_HANDLER, + new MySqlMetadataHandler()); + } + + /** + * Preserve case for MariaDB + * + * @see DatabaseEnvironment#convertString(String) + */ + @Override + public String convertString(String str) + { + return str; + } + +} diff --git a/src/test/java/org/dbunit/ext/mariadb/MariaDbDataTypeFactoryIT.java b/src/test/java/org/dbunit/ext/mariadb/MariaDbDataTypeFactoryIT.java new file mode 100644 index 000000000..5806a7883 --- /dev/null +++ b/src/test/java/org/dbunit/ext/mariadb/MariaDbDataTypeFactoryIT.java @@ -0,0 +1,142 @@ +/* + * + * 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 static org.assertj.core.api.Assertions.assertThat; + +import java.io.StringReader; +import java.sql.Statement; +import java.util.Objects; + +import org.dbunit.DatabaseEnvironment; +import org.dbunit.database.DatabaseConfig; +import org.dbunit.database.IDatabaseConnection; +import org.dbunit.dataset.Column; +import org.dbunit.dataset.IDataSet; +import org.dbunit.dataset.ITable; +import org.dbunit.dataset.ITableMetaData; +import org.dbunit.dataset.datatype.DataType; +import org.dbunit.dataset.xml.FlatXmlDataSetBuilder; +import org.dbunit.ext.mysql.MySqlMetadataHandler; +import org.dbunit.operation.DatabaseOperation; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledIfSystemProperty; +import org.xml.sax.InputSource; + +/** + * Proves {@link MariaDbDataTypeFactory} handles MariaDB's native + * {@code UUID}/{@code INET4}/{@code INET6} column types end-to-end through a + * live connection, not just in isolated {@code createDataType()} unit tests. + * + * @author Jeff Jensen + * @since 3.4.1 + */ +@EnabledIfSystemProperty(named = "dbunit.profile", matches = "mariadb") +class MariaDbDataTypeFactoryIT +{ + private IDatabaseConnection _connection; + private final String testTable = "MARIADB_TYPE_DIVERGENCE_TABLE"; + // @formatter:off + private static final String xmlData = "" + + "" + + "" + + ""; + // @formatter:on + + @BeforeEach + protected void setUp() throws Exception + { + _connection = DatabaseEnvironment.getInstance().getConnection(); + final Statement stat = _connection.getConnection().createStatement(); + stat.execute("DROP TABLE IF EXISTS " + testTable + ";"); + stat.execute("CREATE TABLE " + testTable + + "(ID INT NOT NULL PRIMARY KEY, " + + "UUID_COL UUID, INET4_COL INET4, INET6_COL INET6);"); + stat.close(); + _connection.close(); + _connection = DatabaseEnvironment.getInstance().getConnection(); + + final DatabaseConfig config = _connection.getConfig(); + config.setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, + new MariaDbDataTypeFactory()); + config.setProperty(DatabaseConfig.PROPERTY_METADATA_HANDLER, + new MySqlMetadataHandler()); + } + + @AfterEach + protected void tearDown() throws Exception + { + if (!Objects.isNull(_connection)) + { + final Statement stat = + _connection.getConnection().createStatement(); + stat.execute("DROP TABLE IF EXISTS " + testTable + ";"); + _connection.close(); + + _connection = null; + } + } + + @Test + void testMariaDbNativeTypes_withUuidInet4Inet6Columns_roundTripThroughDatabase() + throws Exception + { + assertThat(_connection).as("didn't get a connection.").isNotNull(); + + final IDataSet dataSet = new FlatXmlDataSetBuilder() + .build(new InputSource(new StringReader(xmlData))); + + IDataSet ids = _connection.createDataSet(); + final ITableMetaData tableMetaData = ids.getTableMetaData(testTable); + for (final Column column : tableMetaData.getColumns()) + { + if ("UUID_COL".equalsIgnoreCase(column.getColumnName()) + || "INET4_COL".equalsIgnoreCase(column.getColumnName()) + || "INET6_COL".equalsIgnoreCase(column.getColumnName())) + { + // MariaDB reports these as SQL type OTHER with a native type + // name; MariaDbDataTypeFactory maps that to VARCHAR. + assertThat(column.getSqlTypeName()) + .as("sql type name of " + column.getColumnName() + ".") + .isNotNull(); + assertThat(column.getDataType()) + .as("data type of " + column.getColumnName() + ".") + .isSameAs(DataType.VARCHAR); + } + } + + DatabaseOperation.CLEAN_INSERT.execute(_connection, dataSet); + + ids = _connection.createDataSet(); + final ITable actualTable = ids.getTable(testTable); + assertThat(actualTable.getValue(0, "UUID_COL")).as("uuid column value.") + .isEqualTo("08004327-3f6c-4335-9738-0b2bf885cc43"); + assertThat(actualTable.getValue(0, "INET4_COL")).as("inet4 column value.") + .isEqualTo("192.168.1.1"); + assertThat(actualTable.getValue(0, "INET6_COL")).as("inet6 column value.") + .isEqualTo("::1"); + } +} diff --git a/src/test/java/org/dbunit/ext/mariadb/MariaDbDataTypeFactoryTest.java b/src/test/java/org/dbunit/ext/mariadb/MariaDbDataTypeFactoryTest.java new file mode 100644 index 000000000..2e6a87434 --- /dev/null +++ b/src/test/java/org/dbunit/ext/mariadb/MariaDbDataTypeFactoryTest.java @@ -0,0 +1,107 @@ +/* + * + * 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 static org.assertj.core.api.Assertions.assertThat; + +import java.sql.Types; + +import org.dbunit.dataset.datatype.DataType; +import org.dbunit.dataset.datatype.IDataTypeFactory; +import org.dbunit.ext.mysql.MySqlDataTypeFactoryTest; +import org.junit.jupiter.api.Test; + +/** + * @author Jeff Jensen + * @since 3.4.1 + */ +class MariaDbDataTypeFactoryTest extends MySqlDataTypeFactoryTest +{ + + @Override + public IDataTypeFactory createFactory() throws Exception + { + return new MariaDbDataTypeFactory(); + } + + @Test + void testGetValidDbProducts_returnsMariadb() + { + final MariaDbDataTypeFactory factory = new MariaDbDataTypeFactory(); + + assertThat(factory.getValidDbProducts()).as("valid db products.").containsExactly("mariadb"); + } + + @Test + void testCreateUuidDataType_withUuidTypeName_returnsVarcharDataType() throws Exception + { + final DataType actual = + createFactory().createDataType(Types.OTHER, MariaDbDataTypeFactory.SQL_TYPE_NAME_UUID); + final DataType expected = DataType.VARCHAR; + assertThat(actual).as("type").isSameAs(expected); + } + + @Test + void testCreateUuidLowerCaseDataType_withLowercaseUuidTypeName_returnsVarcharDataType() throws Exception + { + // MariaDB Connector/J's ResultSetMetaData reports this type name in + // lowercase, unlike DatabaseMetaData#getColumns() which reports it + // uppercase - both must work. + final DataType actual = createFactory().createDataType(Types.OTHER, "uuid"); + final DataType expected = DataType.VARCHAR; + assertThat(actual).as("type").isSameAs(expected); + } + + @Test + void testCreateInet4DataType_withInet4TypeName_returnsVarcharDataType() throws Exception + { + final DataType actual = + createFactory().createDataType(Types.OTHER, MariaDbDataTypeFactory.SQL_TYPE_NAME_INET4); + final DataType expected = DataType.VARCHAR; + assertThat(actual).as("type").isSameAs(expected); + } + + @Test + void testCreateInet4LowerCaseDataType_withLowercaseInet4TypeName_returnsVarcharDataType() throws Exception + { + final DataType actual = createFactory().createDataType(Types.OTHER, "inet4"); + final DataType expected = DataType.VARCHAR; + assertThat(actual).as("type").isSameAs(expected); + } + + @Test + void testCreateInet6DataType_withInet6TypeName_returnsVarcharDataType() throws Exception + { + final DataType actual = + createFactory().createDataType(Types.OTHER, MariaDbDataTypeFactory.SQL_TYPE_NAME_INET6); + final DataType expected = DataType.VARCHAR; + assertThat(actual).as("type").isSameAs(expected); + } + + @Test + void testCreateInet6LowerCaseDataType_withLowercaseInet6TypeName_returnsVarcharDataType() throws Exception + { + final DataType actual = createFactory().createDataType(Types.OTHER, "inet6"); + final DataType expected = DataType.VARCHAR; + assertThat(actual).as("type").isSameAs(expected); + } + +} diff --git a/src/test/java/org/dbunit/ext/mysql/MySqlDataTypeFactoryTest.java b/src/test/java/org/dbunit/ext/mysql/MySqlDataTypeFactoryTest.java index 9516b0b86..15a3376db 100644 --- a/src/test/java/org/dbunit/ext/mysql/MySqlDataTypeFactoryTest.java +++ b/src/test/java/org/dbunit/ext/mysql/MySqlDataTypeFactoryTest.java @@ -34,7 +34,7 @@ * @since Sep 3, 2003 * @version $Revision$ */ -class MySqlDataTypeFactoryTest extends AbstractDataTypeFactoryTest +public class MySqlDataTypeFactoryTest extends AbstractDataTypeFactoryTest { @Override diff --git a/src/test/resources/mariadb-dbunit.properties b/src/test/resources/mariadb-dbunit.properties new file mode 100644 index 000000000..64dc369e1 --- /dev/null +++ b/src/test/resources/mariadb-dbunit.properties @@ -0,0 +1,12 @@ +dbunit.profile=mariadb +dbunit.profile.driverClass=org.mariadb.jdbc.Driver +# nullCatalogMeansCurrent=true must also stay on the matrix "url" override in +# .github/workflows/build-any-branch-with-all-dbs.yml, which replaces this +# value in CI - see mariadb.adoc's IMetadataHandler section for why. +dbunit.profile.url=jdbc:mariadb://localhost:3306/dbunit?nullCatalogMeansCurrent=true +dbunit.profile.schema= +dbunit.profile.user=dbunit +dbunit.profile.password=dbunit +dbunit.profile.ddl=mariadb.sql +dbunit.profile.unsupportedFeatures=BLOB,CLOB,SCROLLABLE_RESULTSET,INSERT_IDENTITY,SDO_GEOMETRY,XML_TYPE,TIMESTAMP_WITH_TIMEZONE +dbunit.profile.multiLineSupport=false diff --git a/src/test/resources/sql/mariadb.sql b/src/test/resources/sql/mariadb.sql new file mode 100644 index 000000000..bdf36e67e --- /dev/null +++ b/src/test/resources/sql/mariadb.sql @@ -0,0 +1,74 @@ +---------------------------------------------------------------------------- +- TEST_TABLE +---------------------------------------------------------------------------- + +DROP TABLE IF EXISTS TEST_TABLE; +CREATE TABLE TEST_TABLE + (COLUMN0 VARCHAR(32), + COLUMN1 VARCHAR(32), + COLUMN2 VARCHAR(32), + COLUMN3 VARCHAR(32)) ENGINE = InnoDB; + +---------------------------------------------------------------------------- +- SECOND_TABLE +--------------------------------------------------------------------------- + +DROP TABLE IF EXISTS SECOND_TABLE; +CREATE TABLE SECOND_TABLE + (COLUMN0 VARCHAR(32), + COLUMN1 VARCHAR(32), + COLUMN2 VARCHAR(32), + COLUMN3 VARCHAR(32)) ENGINE = InnoDB; + +---------------------------------------------------------------------------- +- EMPTY_TABLE +---------------------------------------------------------------------------- + +DROP TABLE IF EXISTS EMPTY_TABLE; +CREATE TABLE EMPTY_TABLE + (COLUMN0 VARCHAR(32), + COLUMN1 VARCHAR(32), + COLUMN2 VARCHAR(32), + COLUMN3 VARCHAR(32)) ENGINE = InnoDB; + +---------------------------------------------------------------------------- +- PK_TABLE +---------------------------------------------------------------------------- + +DROP TABLE IF EXISTS PK_TABLE; +CREATE TABLE PK_TABLE + (PK0 NUMERIC(38, 0) NOT NULL, + PK1 NUMERIC(38, 0) NOT NULL, + PK2 NUMERIC(38, 0) NOT NULL, + NORMAL0 VARCHAR(32), + NORMAL1 VARCHAR(32), PRIMARY KEY (PK0, PK1, PK2)) ENGINE = InnoDB; + +---------------------------------------------------------------------------- +- ONLY_PK_TABLE +---------------------------------------------------------------------------- + +DROP TABLE IF EXISTS ONLY_PK_TABLE; +CREATE TABLE ONLY_PK_TABLE + (PK0 NUMERIC(38, 0) NOT NULL PRIMARY KEY) ENGINE = InnoDB; + +---------------------------------------------------------------------------- +- EMPTY_MULTITYPE_TABLE +---------------------------------------------------------------------------- + +DROP TABLE IF EXISTS EMPTY_MULTITYPE_TABLE; +CREATE TABLE EMPTY_MULTITYPE_TABLE + (VARCHAR_COL VARCHAR(32), + NUMERIC_COL NUMERIC(38, 0), + TIMESTAMP_COL TIMESTAMP NULL, + VARBINARY_COL VARBINARY(254)) ENGINE = InnoDB; + +---------------------------------------------------------------------------- +- IDENTITY_TABLE +---------------------------------------------------------------------------- + +DROP TABLE IF EXISTS IDENTITY_TABLE; +CREATE TABLE IDENTITY_TABLE + (IDENTITY_TABLE_ID INT NOT NULL AUTO_INCREMENT, + COLUMN0 VARCHAR(32), + COLUMN1 VARCHAR(32), + PRIMARY KEY (IDENTITY_TABLE_ID)) ENGINE = InnoDB;