Polish contribution

This commit introduces additional unit tests for CallMetaDataContext's
function return parameter matching in reconcileParameters(), verifying
that the declared return parameter is correctly resolved regardless of
whether it is declared before or after an additional OUT parameter.

See gh-37206
This commit is contained in:
Sam Brannen
2026-09-03 11:34:44 +02:00
parent ec6b925191
commit ee7a0d48c5
2 changed files with 58 additions and 6 deletions
@@ -18,6 +18,8 @@ package org.springframework.jdbc.core.simple;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.List;
@@ -41,9 +43,10 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
/**
* Mock object based tests for CallMetaDataContext.
* Mock object based tests for {@link CallMetaDataContext}.
*
* @author Thomas Risberg
* @author Sam Brannen
*/
class CallMetaDataContextTests {
@@ -103,4 +106,54 @@ class CallMetaDataContextTests {
assertThat(callParameters).as("Wrong number of call parameters").hasSize(3);
}
@Test // gh-37206
void reconcileParametersMatchesFunctionReturnParameterDeclaredBeforeOutParameter() throws Exception {
initializeGetTotalFunctionMetaData();
List<SqlParameter> parameters = List.of(
new SqlOutParameter("RESULT", Types.INTEGER),
new SqlOutParameter("out_status", Types.INTEGER));
context.setFunction(true);
context.setProcedureName("GET_TOTAL");
context.initializeMetaData(dataSource);
context.processParameters(parameters);
assertThat(context.getCallParameters()).extracting(SqlParameter::getName)
.containsExactly("RESULT", "AMOUNT", "out_status");
}
@Test // gh-37206
void reconcileParametersMatchesFunctionReturnParameterDeclaredAfterOutParameter() throws Exception {
initializeGetTotalFunctionMetaData();
List<SqlParameter> parameters = List.of(
new SqlOutParameter("out_status", Types.INTEGER),
new SqlOutParameter("RESULT", Types.INTEGER));
context.setFunction(true);
context.setProcedureName("GET_TOTAL");
context.initializeMetaData(dataSource);
context.processParameters(parameters);
assertThat(context.getCallParameters()).extracting(SqlParameter::getName)
.containsExactly("RESULT", "AMOUNT", "out_status");
}
private void initializeGetTotalFunctionMetaData() throws SQLException {
ResultSet proceduresResultSet = mock();
ResultSet procedureColumnsResultSet = mock();
given(databaseMetaData.getDatabaseProductName()).willReturn("Oracle");
given(databaseMetaData.getUserName()).willReturn("ME");
given(databaseMetaData.storesUpperCaseIdentifiers()).willReturn(true);
given(databaseMetaData.getProcedures("", "ME", "GET_TOTAL")).willReturn(proceduresResultSet);
given(databaseMetaData.getProcedureColumns("", "ME", "GET_TOTAL", null)).willReturn(procedureColumnsResultSet);
given(proceduresResultSet.next()).willReturn(true, false);
given(proceduresResultSet.getString("PROCEDURE_NAME")).willReturn("GET_TOTAL");
given(procedureColumnsResultSet.next()).willReturn(true, true, true, false);
given(procedureColumnsResultSet.getInt("DATA_TYPE")).willReturn(Types.INTEGER);
given(procedureColumnsResultSet.getString("COLUMN_NAME")).willReturn(null, "amount", "out_status");
given(procedureColumnsResultSet.getInt("COLUMN_TYPE")).willReturn(5, 1, 4);
}
}
@@ -266,8 +266,7 @@ class SimpleJdbcCallTests {
verify(procedureColumnsResultSet).close();
}
@Test
@Test // gh-37206
void functionWithAdditionalOutParameterDeclaredBeforeReturn() throws Exception {
initializeGetTotalFunctionWithMetaData();
SimpleJdbcCall function = new SimpleJdbcCall(dataSource).withFunctionName("get_total");
@@ -282,7 +281,7 @@ class SimpleJdbcCallTests {
assertThat(total).isEqualTo(42);
}
@Test
@Test // gh-37206
void functionWithAdditionalOutParameterDeclaredAfterReturn() throws Exception {
initializeGetTotalFunctionWithMetaData();
SimpleJdbcCall function = new SimpleJdbcCall(dataSource).withFunctionName("get_total");
@@ -296,7 +295,7 @@ class SimpleJdbcCallTests {
assertThat(total).isEqualTo(42);
}
@Test
@Test // gh-37206
void sqlServerProcedureWithReturnValueDeclaredAfterOutParameter() throws Exception {
initializeSqlServerProcedureWithReturnValue();
SimpleJdbcCall procedure = new SimpleJdbcCall(dataSource).withProcedureName("my_proc").withReturnValue();
@@ -309,7 +308,7 @@ class SimpleJdbcCallTests {
verifyStatement(procedure, "{? = call my_proc(?, ?)}");
}
@Test
@Test // gh-37206
void sqlServerProcedureWithReturnValueDeclaredFirst() throws Exception {
initializeSqlServerProcedureWithReturnValue();
SimpleJdbcCall procedure = new SimpleJdbcCall(dataSource).withProcedureName("my_proc").withReturnValue();