/*
 * Copyright 2002-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.jdbc.support.incrementer;

import java.util.UUID;

import javax.sql.DataSource;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;

import static org.assertj.core.api.Assertions.assertThat;

/**
 * Integration tests for {@link H2SequenceMaxValueIncrementer}.
 *
 * @author Henning Pöttker
 * @author Sam Brannen
 * @since 5.3.15
 */
class H2SequenceMaxValueIncrementerTests {

	/**
	 * Tests that the incrementer works when using the JDBC connection URL used
	 * in the {@code H2EmbeddedDatabaseConfigurer} which is used transparently
	 * when using Spring's {@link EmbeddedDatabaseBuilder}.
	 *
	 * <p>In other words, this tests compatibility with the default H2
	 * <em>compatibility mode</em>.
	 */
	@Test
	void incrementsSequenceUsingH2EmbeddedDatabaseConfigurer() {
		EmbeddedDatabase database = new EmbeddedDatabaseBuilder()
				.setType(EmbeddedDatabaseType.H2)
				.generateUniqueName(true)
				.addScript("classpath:/org/springframework/jdbc/support/incrementer/schema.sql")
				.build();

		JdbcTemplate jdbcTemplate = new JdbcTemplate(database);
		assertThat(jdbcTemplate.queryForObject("values next value for SEQ", int.class)).isEqualTo(1);

		H2SequenceMaxValueIncrementer incrementer = new H2SequenceMaxValueIncrementer(database, "SEQ");
		assertThat(incrementer.nextIntValue()).isEqualTo(2);
		assertThat(incrementer.nextStringValue()).isEqualTo("3");

		database.shutdown();
	}

	/**
	 * Tests that the incrementer works when using all supported H2 <em>compatibility modes</em>.
	 */
	@ParameterizedTest
	@ValueSource(strings = { "STRICT", "LEGACY", "DB2", "Derby", "HSQLDB", "MariaDB", "MSSQLServer", "MySQL", "Oracle", "PostgreSQL" })
	void incrementsSequenceWithExplicitH2CompatibilityMode(String compatibilityMode) {
		String connectionUrl = String.format("jdbc:h2:mem:%s;MODE=%s", UUID.randomUUID().toString(), compatibilityMode);
		DataSource dataSource = new SimpleDriverDataSource(new org.h2.Driver(), connectionUrl, "sa", "");
		JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
		PlatformTransactionManager transactionManager = new DataSourceTransactionManager(dataSource);
		TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);

		transactionTemplate.executeWithoutResult(status -> {
			jdbcTemplate.execute("CREATE SEQUENCE SEQ");
			assertThat(jdbcTemplate.queryForObject("values next value for SEQ", int.class)).isEqualTo(1);

			H2SequenceMaxValueIncrementer incrementer = new H2SequenceMaxValueIncrementer(dataSource, "SEQ");
			assertThat(incrementer.nextIntValue()).isEqualTo(2);
			assertThat(incrementer.nextStringValue()).isEqualTo("3");
		});

		jdbcTemplate.execute("SHUTDOWN");
	}

}

@@ -717,32 +717,68 @@
 ql.DataSource;%0A%0A
+import org.h2.engine.Mode.ModeEnum;%0A
 import org.junit
@@ -888,21 +888,20 @@
 rovider.
-Value
+Enum
 Source;%0A
@@ -956,81 +956,8 @@
 te;%0A
-import org.springframework.jdbc.datasource.DataSourceTransactionManager;%0A
 impo
@@ -1243,143 +1243,8 @@
 ype;
-%0Aimport org.springframework.transaction.PlatformTransactionManager;%0Aimport org.springframework.transaction.support.TransactionTemplate;
 %0A%0Aim
@@ -2114,371 +2114,33 @@
 %0A%0A%09%09
-JdbcTemplate jdbcTemplate = new JdbcTemplate(database);%0A%09%09assertThat(jdbcTemplate.queryForObject(%22values next value for SEQ%22, int.class)).isEqualTo(1);%0A%0A%09%09H2SequenceMaxValueIncrementer incrementer = new H2SequenceMaxValueIncrementer(database, %22SEQ%22);%0A%09%09assertThat(incrementer.nextIntValue()).isEqualTo(2);%0A%09%09assertThat(incrementer.nextStringValue()).isEqualTo(%223%22
+assertIncrements(database
 );%0A%0A
@@ -2297,137 +2297,33 @@
 t%0A%09@
-Value
+Enum
 Source(
-strings = %7B %22STRICT%22, %22LEGACY%22, %22DB2%22, %22Derby%22, %22HSQLDB%22, %22MariaDB%22, %22MSSQLServer%22, %22MySQL%22, %22Oracle%22, %22PostgreSQL%22 %7D
+ModeEnum.class
 )%0A%09v
@@ -2380,29 +2380,18 @@
 ode(
-String compatibilityM
+ModeEnum m
 ode)
@@ -2448,16 +2448,57 @@
 :mem:%25s;
+DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false;
 MODE=%25s%22
@@ -2533,22 +2533,9 @@
 (), 
-compatibilityM
+m
 ode)
@@ -2702,296 +2702,183 @@
 ;%0A%09%09
-PlatformTransactionManager transactionManager = new DataSourceTransactionManager(dataSource
+jdbcTemplate.execute(%22CREATE SEQUENCE SEQ%22
 );%0A
+%0A
 %09%09
-TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);%0A%0A%09%09transactionTemplate.executeWithoutResult(status -%3E %7B%0A%09%09%09jdbcTemplate.execute(%22CREATE SEQUENCE SEQ%22);%0A%09
+assertIncrements(dataSource);%0A%0A%09%09jdbcTemplate.execute(%22SHUTDOWN%22);%0A%09%7D%0A%0A%09private void assertIncrements(DataSource dataSource) %7B%0A
 %09%09as
@@ -2886,17 +2886,21 @@
 ertThat(
-j
+new J
 dbcTempl
@@ -2902,16 +2902,28 @@
 Template
+(dataSource)
 .queryFo
@@ -2986,17 +2986,16 @@
 To(1);%0A%0A
-%09
 %09%09H2Sequ
@@ -3084,25 +3084,24 @@
 , %22SEQ%22);%0A%09%09
-%09
 assertThat(i
@@ -3141,17 +3141,16 @@
 lTo(2);%0A
-%09
 %09%09assert
@@ -3205,51 +3205,8 @@
 %22);%0A
-%09%09%7D);%0A%0A%09%09jdbcTemplate.execute(%22SHUTDOWN%22);%0A
 %09%7D%0A%0A

Simplify H2SequenceMaxValueIncrementerTests