diff --git a/pom.xml b/pom.xml
index 583b2fa47..08d8f575e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -106,6 +106,7 @@
6.3.1
1.9.9.1
8.0.31
+ 3.0.8
42.5.0
11.5.7.0
19.16.0.0
diff --git a/spring-batch-core/pom.xml b/spring-batch-core/pom.xml
index e3dca3eaa..f4211c890 100644
--- a/spring-batch-core/pom.xml
+++ b/spring-batch-core/pom.xml
@@ -118,6 +118,18 @@
${testcontainers.version}
test
+
+ org.mariadb.jdbc
+ mariadb-java-client
+ ${mariadb-java-client.version}
+ test
+
+
+ org.testcontainers
+ mariadb
+ ${testcontainers.version}
+ test
+
org.postgresql
postgresql
diff --git a/spring-batch-core/src/main/resources/batch-mariadb.properties b/spring-batch-core/src/main/resources/batch-mariadb.properties
new file mode 100644
index 000000000..94be3e911
--- /dev/null
+++ b/spring-batch-core/src/main/resources/batch-mariadb.properties
@@ -0,0 +1,17 @@
+# Placeholders batch.*
+# for MariaDB:
+batch.jdbc.driver=org.mariadb.jdbc.Driver
+batch.jdbc.url=jdbc:mariadb://localhost/test
+batch.jdbc.user=test
+batch.jdbc.password=test
+batch.database.incrementer.class=org.springframework.batch.item.database.support.MariaDBSequenceMaxValueIncrementer
+batch.schema.script=classpath:/org/springframework/batch/core/schema-mariadb.sql
+batch.drop.script=classpath:/org/springframework/batch/core/schema-drop-mariadb.sql
+batch.jdbc.testWhileIdle=true
+batch.jdbc.validationQuery=
+
+
+# Non-platform dependent settings that you might like to change
+batch.data.source.init=true
+batch.table.prefix=BATCH_
+
diff --git a/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-drop-mariadb.sql b/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-drop-mariadb.sql
new file mode 100644
index 000000000..f78e4b607
--- /dev/null
+++ b/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-drop-mariadb.sql
@@ -0,0 +1,10 @@
+DROP TABLE IF EXISTS BATCH_STEP_EXECUTION_CONTEXT;
+DROP TABLE IF EXISTS BATCH_JOB_EXECUTION_CONTEXT;
+DROP TABLE IF EXISTS BATCH_STEP_EXECUTION;
+DROP TABLE IF EXISTS BATCH_JOB_EXECUTION_PARAMS;
+DROP TABLE IF EXISTS BATCH_JOB_EXECUTION;
+DROP TABLE IF EXISTS BATCH_JOB_INSTANCE;
+
+DROP SEQUENCE IF EXISTS BATCH_STEP_EXECUTION_SEQ;
+DROP SEQUENCE IF EXISTS BATCH_JOB_EXECUTION_SEQ;
+DROP SEQUENCE IF EXISTS BATCH_JOB_SEQ;
diff --git a/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-mariadb.sql b/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-mariadb.sql
new file mode 100644
index 000000000..31f585fbc
--- /dev/null
+++ b/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-mariadb.sql
@@ -0,0 +1,78 @@
+CREATE TABLE BATCH_JOB_INSTANCE (
+ JOB_INSTANCE_ID BIGINT NOT NULL PRIMARY KEY ,
+ VERSION BIGINT ,
+ JOB_NAME VARCHAR(100) NOT NULL,
+ JOB_KEY VARCHAR(32) NOT NULL,
+ constraint JOB_INST_UN unique (JOB_NAME, JOB_KEY)
+) ENGINE=InnoDB;
+
+CREATE TABLE BATCH_JOB_EXECUTION (
+ JOB_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY ,
+ VERSION BIGINT ,
+ JOB_INSTANCE_ID BIGINT NOT NULL,
+ CREATE_TIME DATETIME(6) NOT NULL,
+ START_TIME DATETIME(6) DEFAULT NULL ,
+ END_TIME DATETIME(6) DEFAULT NULL ,
+ STATUS VARCHAR(10) ,
+ EXIT_CODE VARCHAR(2500) ,
+ EXIT_MESSAGE VARCHAR(2500) ,
+ LAST_UPDATED DATETIME(6),
+ constraint JOB_INST_EXEC_FK foreign key (JOB_INSTANCE_ID)
+ references BATCH_JOB_INSTANCE(JOB_INSTANCE_ID)
+) ENGINE=InnoDB;
+
+CREATE TABLE BATCH_JOB_EXECUTION_PARAMS (
+ JOB_EXECUTION_ID BIGINT NOT NULL ,
+ PARAMETER_NAME VARCHAR(100) NOT NULL ,
+ PARAMETER_TYPE VARCHAR(100) NOT NULL ,
+ PARAMETER_VALUE VARCHAR(2500) ,
+ IDENTIFYING CHAR(1) NOT NULL ,
+ constraint JOB_EXEC_PARAMS_FK foreign key (JOB_EXECUTION_ID)
+ references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
+) ENGINE=InnoDB;
+
+CREATE TABLE BATCH_STEP_EXECUTION (
+ STEP_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY ,
+ VERSION BIGINT NOT NULL,
+ STEP_NAME VARCHAR(100) NOT NULL,
+ JOB_EXECUTION_ID BIGINT NOT NULL,
+ CREATE_TIME DATETIME(6) NOT NULL,
+ START_TIME DATETIME(6) DEFAULT NULL ,
+ END_TIME DATETIME(6) DEFAULT NULL ,
+ STATUS VARCHAR(10) ,
+ COMMIT_COUNT BIGINT ,
+ READ_COUNT BIGINT ,
+ FILTER_COUNT BIGINT ,
+ WRITE_COUNT BIGINT ,
+ READ_SKIP_COUNT BIGINT ,
+ WRITE_SKIP_COUNT BIGINT ,
+ PROCESS_SKIP_COUNT BIGINT ,
+ ROLLBACK_COUNT BIGINT ,
+ EXIT_CODE VARCHAR(2500) ,
+ EXIT_MESSAGE VARCHAR(2500) ,
+ LAST_UPDATED DATETIME(6),
+ constraint JOB_EXEC_STEP_FK foreign key (JOB_EXECUTION_ID)
+ references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
+) ENGINE=InnoDB;
+
+CREATE TABLE BATCH_STEP_EXECUTION_CONTEXT (
+ STEP_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY,
+ SHORT_CONTEXT VARCHAR(2500) NOT NULL,
+ SERIALIZED_CONTEXT TEXT ,
+ constraint STEP_EXEC_CTX_FK foreign key (STEP_EXECUTION_ID)
+ references BATCH_STEP_EXECUTION(STEP_EXECUTION_ID)
+) ENGINE=InnoDB;
+
+CREATE TABLE BATCH_JOB_EXECUTION_CONTEXT (
+ JOB_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY,
+ SHORT_CONTEXT VARCHAR(2500) NOT NULL,
+ SERIALIZED_CONTEXT TEXT ,
+ constraint JOB_EXEC_CTX_FK foreign key (JOB_EXECUTION_ID)
+ references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
+) ENGINE=InnoDB;
+
+CREATE SEQUENCE BATCH_STEP_EXECUTION_SEQ START WITH 1 MINVALUE 1 MAXVALUE 9223372036854775806 INCREMENT BY 1 NOCACHE NOCYCLE ENGINE=InnoDB;
+CREATE SEQUENCE BATCH_JOB_EXECUTION_SEQ START WITH 1 MINVALUE 1 MAXVALUE 9223372036854775806 INCREMENT BY 1 NOCACHE NOCYCLE ENGINE=InnoDB;
+CREATE SEQUENCE BATCH_JOB_SEQ START WITH 1 MINVALUE 1 MAXVALUE 9223372036854775806 INCREMENT BY 1 NOCACHE NOCYCLE ENGINE=InnoDB;
+
+
diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/MariaDBJobRepositoryIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/MariaDBJobRepositoryIntegrationTests.java
new file mode 100644
index 000000000..8ca824b42
--- /dev/null
+++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/MariaDBJobRepositoryIntegrationTests.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2022 the original author or authors.
+ *
+ * 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
+ *
+ * https://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 org.springframework.batch.core.test.repository;
+
+import javax.sql.DataSource;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mariadb.jdbc.MariaDbDataSource;
+import org.testcontainers.containers.MariaDBContainer;
+import org.testcontainers.junit.jupiter.Container;
+import org.testcontainers.junit.jupiter.Testcontainers;
+import org.testcontainers.utility.DockerImageName;
+
+import org.springframework.batch.core.ExitStatus;
+import org.springframework.batch.core.Job;
+import org.springframework.batch.core.JobExecution;
+import org.springframework.batch.core.JobParameters;
+import org.springframework.batch.core.JobParametersBuilder;
+import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
+import org.springframework.batch.core.job.builder.JobBuilder;
+import org.springframework.batch.core.launch.JobLauncher;
+import org.springframework.batch.core.repository.JobRepository;
+import org.springframework.batch.core.step.builder.StepBuilder;
+import org.springframework.batch.repeat.RepeatStatus;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
+import org.springframework.jdbc.support.JdbcTransactionManager;
+import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
+import org.springframework.transaction.PlatformTransactionManager;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+/**
+ * @author Mahmoud Ben Hassine
+ */
+@Testcontainers
+@SpringJUnitConfig
+class MariaDBJobRepositoryIntegrationTests {
+
+ // TODO find the best way to externalize and manage image versions
+ private static final DockerImageName MARIADB_IMAGE = DockerImageName.parse("mariadb:10.9.3");
+
+ @Container
+ public static MariaDBContainer> mariaDBContainer = new MariaDBContainer<>(MARIADB_IMAGE);
+
+ @Autowired
+ private DataSource dataSource;
+
+ @Autowired
+ private JobLauncher jobLauncher;
+
+ @Autowired
+ private Job job;
+
+ @BeforeEach
+ void setUp() {
+ ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator();
+ databasePopulator.addScript(new ClassPathResource("/org/springframework/batch/core/schema-mariadb.sql"));
+ databasePopulator.execute(this.dataSource);
+ }
+
+ @Test
+ void testJobExecution() throws Exception {
+ // given
+ JobParameters jobParameters = new JobParametersBuilder().toJobParameters();
+
+ // when
+ JobExecution jobExecution = this.jobLauncher.run(this.job, jobParameters);
+
+ // then
+ assertNotNull(jobExecution);
+ assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus());
+ }
+
+ @Configuration
+ @EnableBatchProcessing
+ static class TestConfiguration {
+
+ @Bean
+ public DataSource dataSource() throws Exception {
+ MariaDbDataSource datasource = new MariaDbDataSource();
+ datasource.setUrl(mariaDBContainer.getJdbcUrl());
+ datasource.setUser(mariaDBContainer.getUsername());
+ datasource.setPassword(mariaDBContainer.getPassword());
+ return datasource;
+ }
+
+ @Bean
+ public JdbcTransactionManager transactionManager(DataSource dataSource) {
+ return new JdbcTransactionManager(dataSource);
+ }
+
+ @Bean
+ public Job job(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
+ return new JobBuilder("job", jobRepository)
+ .start(new StepBuilder("step", jobRepository)
+ .tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED, transactionManager).build())
+ .build();
+ }
+
+ }
+
+}
diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/JdbcPagingItemReaderBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/JdbcPagingItemReaderBuilder.java
index eff310378..2c20b25ff 100644
--- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/JdbcPagingItemReaderBuilder.java
+++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/JdbcPagingItemReaderBuilder.java
@@ -27,6 +27,7 @@ import org.springframework.batch.item.database.support.DerbyPagingQueryProvider;
import org.springframework.batch.item.database.support.H2PagingQueryProvider;
import org.springframework.batch.item.database.support.HanaPagingQueryProvider;
import org.springframework.batch.item.database.support.HsqlPagingQueryProvider;
+import org.springframework.batch.item.database.support.MariaDBPagingQueryProvider;
import org.springframework.batch.item.database.support.MySqlPagingQueryProvider;
import org.springframework.batch.item.database.support.OraclePagingQueryProvider;
import org.springframework.batch.item.database.support.PostgresPagingQueryProvider;
@@ -49,6 +50,7 @@ import org.springframework.util.Assert;
* @author Michael Minella
* @author Glenn Renfro
* @author Drummond Dawson
+ * @author Mahmoud Ben Hassine
* @since 4.0
* @see JdbcPagingItemReader
*/
@@ -360,6 +362,9 @@ public class JdbcPagingItemReaderBuilder {
case MYSQL:
provider = new MySqlPagingQueryProvider();
break;
+ case MARIADB:
+ provider = new MariaDBPagingQueryProvider();
+ break;
case ORACLE:
provider = new OraclePagingQueryProvider();
break;
diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/DefaultDataFieldMaxValueIncrementerFactory.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/DefaultDataFieldMaxValueIncrementerFactory.java
index c4df120af..a2cb80cd2 100644
--- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/DefaultDataFieldMaxValueIncrementerFactory.java
+++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/DefaultDataFieldMaxValueIncrementerFactory.java
@@ -40,6 +40,7 @@ import static org.springframework.batch.support.DatabaseType.DERBY;
import static org.springframework.batch.support.DatabaseType.H2;
import static org.springframework.batch.support.DatabaseType.HANA;
import static org.springframework.batch.support.DatabaseType.HSQL;
+import static org.springframework.batch.support.DatabaseType.MARIADB;
import static org.springframework.batch.support.DatabaseType.MYSQL;
import static org.springframework.batch.support.DatabaseType.ORACLE;
import static org.springframework.batch.support.DatabaseType.POSTGRES;
@@ -109,6 +110,9 @@ public class DefaultDataFieldMaxValueIncrementerFactory implements DataFieldMaxV
mySQLMaxValueIncrementer.setUseNewConnection(true);
return mySQLMaxValueIncrementer;
}
+ else if (databaseType == MARIADB) {
+ return new MariaDBSequenceMaxValueIncrementer(dataSource, incrementerName);
+ }
else if (databaseType == ORACLE) {
return new OracleSequenceMaxValueIncrementer(dataSource, incrementerName);
}
diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/MariaDBPagingQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/MariaDBPagingQueryProvider.java
new file mode 100644
index 000000000..25f47b150
--- /dev/null
+++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/MariaDBPagingQueryProvider.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2022 the original author or authors.
+ *
+ * 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
+ *
+ * https://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 org.springframework.batch.item.database.support;
+
+import org.springframework.batch.item.database.PagingQueryProvider;
+import org.springframework.util.StringUtils;
+
+/**
+ * MariaDB implementation of a {@link PagingQueryProvider} using database specific
+ * features.
+ *
+ * @author Mahmoud Ben Hassine
+ * @since 5.0
+ */
+public class MariaDBPagingQueryProvider extends AbstractSqlPagingQueryProvider {
+
+ @Override
+ public String generateFirstPageQuery(int pageSize) {
+ return SqlPagingQueryUtils.generateLimitSqlQuery(this, false, buildLimitClause(pageSize));
+ }
+
+ @Override
+ public String generateRemainingPagesQuery(int pageSize) {
+ if (StringUtils.hasText(getGroupClause())) {
+ return SqlPagingQueryUtils.generateLimitGroupedSqlQuery(this, buildLimitClause(pageSize));
+ }
+ else {
+ return SqlPagingQueryUtils.generateLimitSqlQuery(this, true, buildLimitClause(pageSize));
+ }
+ }
+
+ private String buildLimitClause(int pageSize) {
+ return new StringBuilder().append("LIMIT ").append(pageSize).toString();
+ }
+
+}
diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/MariaDBSequenceMaxValueIncrementer.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/MariaDBSequenceMaxValueIncrementer.java
new file mode 100644
index 000000000..249c18e79
--- /dev/null
+++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/MariaDBSequenceMaxValueIncrementer.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2022 the original author or authors.
+ *
+ * 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 org.springframework.batch.item.database.support;
+
+import javax.sql.DataSource;
+
+import org.springframework.jdbc.support.incrementer.AbstractSequenceMaxValueIncrementer;
+import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer;
+
+/**
+ * {@link DataFieldMaxValueIncrementer} for MariaDB.
+ *
+ * @author Mahmoud Ben Hassine
+ * @since 5.0
+ */
+// TODO replace this with the one from Spring Framework when available
+public class MariaDBSequenceMaxValueIncrementer extends AbstractSequenceMaxValueIncrementer {
+
+ public MariaDBSequenceMaxValueIncrementer() {
+ }
+
+ public MariaDBSequenceMaxValueIncrementer(DataSource dataSource, String incrementerName) {
+ super(dataSource, incrementerName);
+ }
+
+ @Override
+ protected String getSequenceQuery() {
+ return "select next value for " + this.getIncrementerName();
+ }
+
+}
diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlPagingQueryProviderFactoryBean.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlPagingQueryProviderFactoryBean.java
index 3aae98615..c31b57905 100644
--- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlPagingQueryProviderFactoryBean.java
+++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlPagingQueryProviderFactoryBean.java
@@ -23,6 +23,7 @@ import static org.springframework.batch.support.DatabaseType.DERBY;
import static org.springframework.batch.support.DatabaseType.H2;
import static org.springframework.batch.support.DatabaseType.HANA;
import static org.springframework.batch.support.DatabaseType.HSQL;
+import static org.springframework.batch.support.DatabaseType.MARIADB;
import static org.springframework.batch.support.DatabaseType.MYSQL;
import static org.springframework.batch.support.DatabaseType.ORACLE;
import static org.springframework.batch.support.DatabaseType.POSTGRES;
@@ -51,6 +52,7 @@ import org.springframework.util.StringUtils;
*
* @author Dave Syer
* @author Michael Minella
+ * @author Mahmoud Ben Hassine
*/
public class SqlPagingQueryProviderFactoryBean implements FactoryBean {
@@ -80,6 +82,7 @@ public class SqlPagingQueryProviderFactoryBean implements FactoryBean nameMap;
@@ -66,8 +67,6 @@ public enum DatabaseType {
* @throws IllegalArgumentException if none is found.
*/
public static DatabaseType fromProductName(String productName) {
- if (productName.equals("MariaDB"))
- productName = "MySQL";
if (!nameMap.containsKey(productName)) {
throw new IllegalArgumentException("DatabaseType not found for product name: [" + productName + "]");
}
diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/DefaultDataFieldMaxValueIncrementerFactoryTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/DefaultDataFieldMaxValueIncrementerFactoryTests.java
index cdda73ef4..aed4171eb 100644
--- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/DefaultDataFieldMaxValueIncrementerFactoryTests.java
+++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/DefaultDataFieldMaxValueIncrementerFactoryTests.java
@@ -63,6 +63,7 @@ class DefaultDataFieldMaxValueIncrementerFactoryTests {
assertTrue(factory.isSupportedIncrementerType("sybase"));
assertTrue(factory.isSupportedIncrementerType("sqlite"));
assertTrue(factory.isSupportedIncrementerType("hana"));
+ assertTrue(factory.isSupportedIncrementerType("mariadb"));
}
@Test
@@ -95,6 +96,11 @@ class DefaultDataFieldMaxValueIncrementerFactoryTests {
assertTrue(factory.getIncrementer("mysql", "NAME") instanceof MySQLMaxValueIncrementer);
}
+ @Test
+ void testMariaDB() {
+ assertTrue(factory.getIncrementer("mariadb", "NAME") instanceof MariaDBSequenceMaxValueIncrementer);
+ }
+
@Test
void testOracle() {
factory.setIncrementerColumnName("ID");
diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/MariaDBPagingQueryProviderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/MariaDBPagingQueryProviderTests.java
new file mode 100644
index 000000000..7921e6da7
--- /dev/null
+++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/MariaDBPagingQueryProviderTests.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2022 the original author or authors.
+ *
+ * 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
+ *
+ * https://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 org.springframework.batch.item.database.support;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.jupiter.api.Test;
+
+import org.springframework.batch.item.database.Order;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * @author Mahmoud Ben Hassine
+ */
+class MariaDBPagingQueryProviderTests extends AbstractSqlPagingQueryProviderTests {
+
+ MariaDBPagingQueryProviderTests() {
+ pagingQueryProvider = new MariaDBPagingQueryProvider();
+ }
+
+ @Test
+ @Override
+ void testGenerateFirstPageQuery() {
+ String sql = "SELECT id, name, age FROM foo WHERE bar = 1 ORDER BY id ASC LIMIT 100";
+ String s = pagingQueryProvider.generateFirstPageQuery(pageSize);
+ assertEquals(sql, s);
+ }
+
+ @Test
+ @Override
+ void testGenerateRemainingPagesQuery() {
+ String sql = "SELECT id, name, age FROM foo WHERE (bar = 1) AND ((id > ?)) ORDER BY id ASC LIMIT 100";
+ String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize);
+ assertEquals(sql, s);
+ }
+
+ @Override
+ @Test
+ void testGenerateFirstPageQueryWithGroupBy() {
+ pagingQueryProvider.setGroupClause("dep");
+ String sql = "SELECT id, name, age FROM foo WHERE bar = 1 GROUP BY dep ORDER BY id ASC LIMIT 100";
+ String s = pagingQueryProvider.generateFirstPageQuery(pageSize);
+ assertEquals(sql, s);
+ }
+
+ @Override
+ @Test
+ void testGenerateRemainingPagesQueryWithGroupBy() {
+ pagingQueryProvider.setGroupClause("dep");
+ String sql = "SELECT * FROM (SELECT id, name, age FROM foo WHERE bar = 1 GROUP BY dep) AS MAIN_QRY WHERE ((id > ?)) ORDER BY id ASC LIMIT 100";
+ String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize);
+ assertEquals(sql, s);
+ }
+
+ @Test
+ void testFirstPageSqlWithAliases() {
+ Map sorts = new HashMap<>();
+ sorts.put("owner.id", Order.ASCENDING);
+
+ this.pagingQueryProvider = new MySqlPagingQueryProvider();
+ this.pagingQueryProvider.setSelectClause("SELECT owner.id as ownerid, first_name, last_name, dog_name ");
+ this.pagingQueryProvider.setFromClause("FROM dog_owner owner INNER JOIN dog ON owner.id = dog.id ");
+ this.pagingQueryProvider.setSortKeys(sorts);
+
+ String firstPage = this.pagingQueryProvider.generateFirstPageQuery(5);
+ String remainingPagesQuery = this.pagingQueryProvider.generateRemainingPagesQuery(5);
+
+ assertEquals(
+ "SELECT owner.id as ownerid, first_name, last_name, dog_name FROM dog_owner owner INNER JOIN dog ON owner.id = dog.id ORDER BY owner.id ASC LIMIT 5",
+ firstPage);
+ assertEquals(
+ "SELECT owner.id as ownerid, first_name, last_name, dog_name FROM dog_owner owner INNER JOIN dog ON owner.id = dog.id WHERE ((owner.id > ?)) ORDER BY owner.id ASC LIMIT 5",
+ remainingPagesQuery);
+ }
+
+ @Override
+ String getFirstPageSqlWithMultipleSortKeys() {
+ return "SELECT id, name, age FROM foo WHERE bar = 1 ORDER BY name ASC, id DESC LIMIT 100";
+ }
+
+ @Override
+ String getRemainingSqlWithMultipleSortKeys() {
+ return "SELECT id, name, age FROM foo WHERE (bar = 1) AND ((name > ?) OR (name = ? AND id < ?)) ORDER BY name ASC, id DESC LIMIT 100";
+ }
+
+}
diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/MariaDBSequenceMaxValueIncrementerTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/MariaDBSequenceMaxValueIncrementerTests.java
new file mode 100644
index 000000000..b27d74272
--- /dev/null
+++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/MariaDBSequenceMaxValueIncrementerTests.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2022 the original author or authors.
+ *
+ * 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
+ *
+ * https://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 org.springframework.batch.item.database.support;
+
+import javax.sql.DataSource;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * @author Mahmoud Ben Hassine
+ */
+@ExtendWith(MockitoExtension.class)
+class MariaDBSequenceMaxValueIncrementerTests {
+
+ @Mock
+ private DataSource dataSource;
+
+ @Test
+ void testGetSequenceQuery() {
+ // given
+ var incrementer = new MariaDBSequenceMaxValueIncrementer(this.dataSource, "BATCH_JOB_SEQ");
+
+ // when
+ String sequenceQuery = incrementer.getSequenceQuery();
+
+ // then
+ assertEquals("select next value for BATCH_JOB_SEQ", sequenceQuery);
+ }
+
+}
\ No newline at end of file