diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/core/simple/CallMetaDataContextTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/core/simple/CallMetaDataContextTests.java index fcca55103b3..db5e6c4a731 100644 --- a/spring-jdbc/src/test/java/org/springframework/jdbc/core/simple/CallMetaDataContextTests.java +++ b/spring-jdbc/src/test/java/org/springframework/jdbc/core/simple/CallMetaDataContextTests.java @@ -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 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 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); + } + } diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/core/simple/SimpleJdbcCallTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/core/simple/SimpleJdbcCallTests.java index 045cc28a68b..00910128223 100644 --- a/spring-jdbc/src/test/java/org/springframework/jdbc/core/simple/SimpleJdbcCallTests.java +++ b/spring-jdbc/src/test/java/org/springframework/jdbc/core/simple/SimpleJdbcCallTests.java @@ -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();