diff --git a/pom.xml b/pom.xml
index 3b923a2f36..3f2edffd3e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -13,7 +13,7 @@
io.vertigo
vertigo-parent
- 4.3.3-SNAPSHOT
+ 4.3.2
vertigo-libs
diff --git a/vertigo-database/pom.xml b/vertigo-database/pom.xml
index 844a93fe7e..793b5e173a 100644
--- a/vertigo-database/pom.xml
+++ b/vertigo-database/pom.xml
@@ -23,11 +23,16 @@
ojdbc11
23.8.0.25.04
-
- org.postgresql
- postgresql
- 42.7.7
-
+
+ org.postgresql
+ postgresql
+ 42.7.7
+
+
+ org.mariadb.jdbc
+ mariadb-java-client
+ 3.3.3
+
org.liquibase
liquibase-core
@@ -36,7 +41,7 @@
io.vertigo
vertigo-commons
- ${project.version}
+ ${vertigo.version}
pom
import
@@ -47,10 +52,10 @@
io.vertigo
vertigo-commons
- ${project.version}
+ ${vertigo.version}
- io.vertigo
+ io.vertigo
vertigo-influxdb-connector
${vertigo.version}
true
@@ -81,6 +86,12 @@
test
+
+ org.mariadb.jdbc
+ mariadb-java-client
+ test
+
+
com.mchange
diff --git a/vertigo-database/src/main/java/io/vertigo/database/impl/sql/vendor/mariadb/MariaDbDataBase.java b/vertigo-database/src/main/java/io/vertigo/database/impl/sql/vendor/mariadb/MariaDbDataBase.java
new file mode 100644
index 0000000000..7aeceb4d96
--- /dev/null
+++ b/vertigo-database/src/main/java/io/vertigo/database/impl/sql/vendor/mariadb/MariaDbDataBase.java
@@ -0,0 +1,53 @@
+/*
+ * vertigo - application development platform
+ *
+ * Copyright (C) 2013-2025, Vertigo.io, team@vertigo.io
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.vertigo.database.impl.sql.vendor.mariadb;
+
+import io.vertigo.database.impl.sql.vendor.core.SqlVendorMapping;
+import io.vertigo.database.sql.vendor.SqlDataBase;
+import io.vertigo.database.sql.vendor.SqlDialect;
+import io.vertigo.database.sql.vendor.SqlExceptionHandler;
+import io.vertigo.database.sql.vendor.SqlMapping;
+
+/**
+ * Gestion de la base de données MariaDB.
+ * Utilise InnoDB comme moteur de stockage pour garantir les transactions ACID.
+ *
+ * @author ppinette
+ */
+public final class MariaDbDataBase implements SqlDataBase {
+ private final SqlExceptionHandler sqlExceptionHandler = new MariaDbExceptionHandler();
+ private final SqlMapping sqlVendorMapping = SqlVendorMapping.createWithBooleanAsBit();
+ private final SqlDialect sqlDialect = new MariaDbDialect();
+
+ /** {@inheritDoc} */
+ @Override
+ public SqlExceptionHandler getSqlExceptionHandler() {
+ return sqlExceptionHandler;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public SqlMapping getSqlMapping() {
+ return sqlVendorMapping;
+ }
+
+ @Override
+ public SqlDialect getSqlDialect() {
+ return sqlDialect;
+ }
+}
diff --git a/vertigo-database/src/main/java/io/vertigo/database/impl/sql/vendor/mariadb/MariaDbDialect.java b/vertigo-database/src/main/java/io/vertigo/database/impl/sql/vendor/mariadb/MariaDbDialect.java
new file mode 100644
index 0000000000..464ace5a9b
--- /dev/null
+++ b/vertigo-database/src/main/java/io/vertigo/database/impl/sql/vendor/mariadb/MariaDbDialect.java
@@ -0,0 +1,86 @@
+/*
+ * vertigo - application development platform
+ *
+ * Copyright (C) 2013-2025, Vertigo.io, team@vertigo.io
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.vertigo.database.impl.sql.vendor.mariadb;
+
+import io.vertigo.core.lang.Assertion;
+import io.vertigo.core.util.StringUtil;
+import io.vertigo.database.sql.vendor.SqlDialect;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Dialecte SQL spécifique à MariaDB.
+ * Utilise InnoDB comme moteur de stockage et AUTO_INCREMENT pour les clés primaires.
+ *
+ * @author ppinette
+ */
+final class MariaDbDialect implements SqlDialect {
+
+ /** {@inheritDoc} */
+ @Override
+ public String createInsertQuery(
+ final String idFieldName,
+ final List dataFieldsName,
+ final String sequencePrefix,
+ final String tableName,
+ final String parameterName) {
+ Assertion.check()
+ .isNotBlank(idFieldName)
+ .isNotNull(dataFieldsName)
+ .isNotBlank(tableName);
+
+ return new StringBuilder()
+ .append("insert into ").append(tableName).append(" (")
+ .append(dataFieldsName
+ .stream()
+ .map(StringUtil::camelToConstCase)
+ .collect(Collectors.joining(", ")))
+ .append(") values (")
+ .append(dataFieldsName
+ .stream()
+ .map(fieldName -> " #" + parameterName + '.' + fieldName + '#')
+ .collect(Collectors.joining(", ")))
+ .append(") ")
+ .toString();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void appendListState(final StringBuilder query, final Integer maxRows, final int skipRows, final String sortFieldName, final boolean sortDesc) {
+ if (sortFieldName != null) {
+ query.append(" order by ").append(StringUtil.camelToConstCase(sortFieldName));
+ query.append(sortDesc ? " desc" : "");
+ }
+
+ if (maxRows != null) {
+ query.append(" limit ").append(maxRows);
+ if (skipRows > 0) {
+ query.append(" offset ").append(skipRows).append(" rows");
+ }
+ } else if (skipRows > 0) {
+ query.append(" offset ").append(skipRows).append(" rows");
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public GenerationMode getGenerationMode() {
+ return GenerationMode.GENERATED_KEYS;
+ }
+}
diff --git a/vertigo-database/src/main/java/io/vertigo/database/impl/sql/vendor/mariadb/MariaDbExceptionHandler.java b/vertigo-database/src/main/java/io/vertigo/database/impl/sql/vendor/mariadb/MariaDbExceptionHandler.java
new file mode 100644
index 0000000000..6d691f237b
--- /dev/null
+++ b/vertigo-database/src/main/java/io/vertigo/database/impl/sql/vendor/mariadb/MariaDbExceptionHandler.java
@@ -0,0 +1,89 @@
+/*
+ * vertigo - application development platform
+ *
+ * Copyright (C) 2013-2025, Vertigo.io, team@vertigo.io
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.vertigo.database.impl.sql.vendor.mariadb;
+
+import java.sql.SQLException;
+
+import io.vertigo.database.impl.sql.vendor.core.AbstractSqlExceptionHandler;
+
+/**
+ * Handler des exceptions SQL spécifique à MariaDB.
+ * Gère les codes d'erreur MySQL/MariaDB et les deadlocks InnoDB.
+ *
+ * @author ppinette
+ */
+final class MariaDbExceptionHandler extends AbstractSqlExceptionHandler {
+
+ /**
+ * Constructor.
+ */
+ MariaDbExceptionHandler() {
+ super();
+ }
+
+ @Override
+ public RuntimeException handleSQLException(final SQLException sqle, final String statementInfos) {
+ final int errCode = sqle.getErrorCode();
+ switch (errCode) {
+ case 1062:
+ // Violation de contrainte d'unicité (Duplicate entry)
+ return handleUniqueConstraintSQLException(sqle);
+ case 1452:
+ // Violation de contrainte d'intégrité référentielle (Cannot add or update a child row)
+ return handleForeignConstraintSQLException(sqle);
+ case 1264:
+ case 1265:
+ // Valeur trop grande pour la colonne (Out of range value)
+ return handleTooLargeValueSqlException(sqle);
+ default:
+ if (isUserSQLException(errCode)) {
+ return handleUserSQLException(sqle);
+ }
+ }
+ return handleOtherSQLException(sqle, statementInfos);
+ }
+
+ private static boolean isUserSQLException(final int errCode) {
+ // Codes d'erreur utilisateur dans MySQL/MariaDB
+ return errCode >= 1000 && errCode < 2000;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected String extractConstraintName(final String msg) {
+ // Extraction du nom de contrainte depuis le message d'erreur MariaDB
+ String constraintName = extractConstraintName(msg, "for key", '\'', '\'');
+ if (constraintName == null) {
+ constraintName = extractConstraintName(msg, "constraint", '\'', '\'');
+ }
+ return constraintName;
+ }
+
+ private static String extractConstraintName(
+ final String msg,
+ final String constraintName,
+ final char constraintNameStart,
+ final char constraintNameEnd) {
+ final int i1 = msg.indexOf(constraintNameStart, msg.indexOf(constraintName));
+ final int i2 = msg.indexOf(constraintNameEnd, i1 + 1);
+ if (i1 > -1 && i2 > -1 && i2 > i1) {
+ return msg.substring(i1 + 1, i2).toUpperCase().trim();
+ }
+ return null;
+ }
+}
diff --git a/vertigo-database/src/test/java/io/vertigo/database/sql/vendor/mariadb/MariaDbDataBaseManagerTest.java b/vertigo-database/src/test/java/io/vertigo/database/sql/vendor/mariadb/MariaDbDataBaseManagerTest.java
new file mode 100644
index 0000000000..d9bb152fc6
--- /dev/null
+++ b/vertigo-database/src/test/java/io/vertigo/database/sql/vendor/mariadb/MariaDbDataBaseManagerTest.java
@@ -0,0 +1,106 @@
+/*
+ * vertigo - application development platform
+ *
+ * Copyright (C) 2013-2025, Vertigo.io, team@vertigo.io
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.vertigo.database.sql.vendor.mariadb;
+
+import io.vertigo.commons.CommonsFeatures;
+import io.vertigo.core.node.AutoCloseableNode;
+import io.vertigo.core.node.config.BootConfig;
+import io.vertigo.core.node.config.NodeConfig;
+import io.vertigo.core.param.Param;
+import io.vertigo.database.DatabaseFeatures;
+import io.vertigo.database.impl.sql.vendor.h2.H2DataBase;
+import io.vertigo.database.impl.sql.vendor.mariadb.MariaDbDataBase;
+import io.vertigo.database.sql.AbstractSqlManagerTest;
+import io.vertigo.database.sql.vendor.SqlDialect;
+import io.vertigo.database.sql.vendor.SqlDialect.GenerationMode;
+
+/**
+ * Tests d'intégration pour MariaDB avec InnoDB.
+ * Ces tests peuvent être lents car ils nécessitent une instance MariaDB.
+ * Utilisez @Disabled pour les désactiver en développement.
+ *
+ * @author ppinette
+ */
+public final class MariaDbDataBaseManagerTest extends AbstractSqlManagerTest {
+
+ private AutoCloseableNode node;
+
+ @Override
+ public SqlDialect getDialect() {
+ return new MariaDbDataBase().getSqlDialect();
+ }
+
+ @Override
+ protected NodeConfig buildNodeConfig() {
+ return NodeConfig.builder()
+ .withBoot(BootConfig.builder()
+ .withLocales("fr_FR")
+ .build())
+ .addModule(new CommonsFeatures()
+ .build())
+ .addModule(new DatabaseFeatures()
+ .withSqlDataBase()
+ .withC3p0(
+ Param.of("dataBaseClass", MariaDbDataBase.class.getName()),
+ Param.of("jdbcDriver", "org.mariadb.jdbc.Driver"),
+ Param.of("jdbcUrl", "jdbc:mariadb://localhost:3306/test?user=root&password=root"),
+ Param.of("minPoolSize", "1"),
+ Param.of("maxPoolSize", "5"),
+ Param.of("acquireIncrement", "1"))
+ .withC3p0(
+ Param.of("name", "secondary"),
+ Param.of("dataBaseClass", H2DataBase.class.getName()),
+ Param.of("jdbcDriver", "org.h2.Driver"),
+ Param.of("jdbcUrl", "jdbc:h2:mem:secondaryDatabase"))
+ .build())
+ .build();
+ }
+
+ @Override
+ protected String createTableMovie() {
+ return "CREATE TABLE IF NOT EXISTS movie ( "
+ + "mov_id INT AUTO_INCREMENT PRIMARY KEY, "
+ + "title VARCHAR(255), "
+ + "mail VARCHAR(255), "
+ + "fps DECIMAL(6,3), "
+ + "income DECIMAL(6,3), "
+ + "color TINYINT(1), "
+ + "release_date DATETIME NULL, "
+ + "release_local_date DATE NULL, "
+ + "release_instant DATETIME NULL, "
+ + "icon LONGBLOB"
+ + ") ENGINE=InnoDB";
+ }
+
+ @Override
+ protected String createSequenceMovie() {
+ return "CREATE SEQUENCE IF NOT EXISTS seq_movie START WITH 1 INCREMENT BY 20";
+ }
+
+ @Override
+ protected GenerationMode getExpectedGenerationMode() {
+ return GenerationMode.GENERATED_KEYS;
+ }
+
+ @Override
+ protected boolean commitRequiredOnSchemaModification() {
+ return true; // InnoDB nécessite un commit après DDL
+ }
+
+
+}
diff --git a/vertigo-database/src/test/java/io/vertigo/database/sql/vendor/mariadb/MariaDbDialectTest.java b/vertigo-database/src/test/java/io/vertigo/database/sql/vendor/mariadb/MariaDbDialectTest.java
new file mode 100644
index 0000000000..038af6d70b
--- /dev/null
+++ b/vertigo-database/src/test/java/io/vertigo/database/sql/vendor/mariadb/MariaDbDialectTest.java
@@ -0,0 +1,78 @@
+/*
+ * vertigo - application development platform
+ *
+ * Copyright (C) 2013-2025, Vertigo.io, team@vertigo.io
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.vertigo.database.sql.vendor.mariadb;
+
+import java.util.Optional;
+
+import io.vertigo.database.impl.sql.vendor.mariadb.MariaDbDataBase;
+import io.vertigo.database.sql.AbstractSqlDialectTest;
+import io.vertigo.database.sql.vendor.SqlDialect;
+
+/**
+ * Tests unitaires pour le dialecte MariaDB.
+ * Ces tests sont rapides car ils testent uniquement la logique du dialecte.
+ *
+ * @author ppinette
+ */
+public final class MariaDbDialectTest extends AbstractSqlDialectTest {
+
+ @Override
+ public SqlDialect getDialect() {
+ return new MariaDbDataBase().getSqlDialect();
+ }
+
+ @Override
+ public String getExpectedInsertQuery() {
+ return "insert into MOVIE (TITLE) values ( #dto.title#) ";
+ }
+
+ @Override
+ public String getExpectedSelectForUpdateWildCardQuery() {
+ return " select * from MOVIE where ID = #id# for update ";
+ }
+
+ @Override
+ public String getExpectedSelectForUpdateFieldsQuery() {
+ return " select ID, TITLE from MOVIE where ID = #id# for update ";
+ }
+
+ @Override
+ public Optional getExpectedCreatePrimaryKeyQuery() {
+ return Optional.empty();
+ }
+
+ @Override
+ public String getExpectedAppendMaxRowsQuery() {
+ return "select * from MOVIE limit 100";
+ }
+
+ @Override
+ public String getExpectedAppendSkipRowsQuery() {
+ return "select * from MOVIE offset 10 rows";
+ }
+
+ @Override
+ public String getExpectedAppendSortQuery() {
+ return "select * from MOVIE order by TITLE";
+ }
+
+ @Override
+ public String getExpectedAppendSortDescQuery() {
+ return "select * from MOVIE order by TITLE desc";
+ }
+}