HHH-18302 Add test for issue

This commit is contained in:
Andrea Boriero 2024-07-05 14:32:39 +02:00 committed by Steve Ebersole
parent 8766a8e012
commit a3c779a019
2 changed files with 169 additions and 7 deletions

View File

@ -28,10 +28,15 @@ import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
import org.hibernate.testing.orm.junit.Jira;
import org.hibernate.testing.orm.junit.Jpa;
import org.hibernate.testing.orm.junit.RequiresDialect;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.NamedStoredProcedureQueries;
@ -39,8 +44,11 @@ import jakarta.persistence.NamedStoredProcedureQuery;
import jakarta.persistence.ParameterMode;
import jakarta.persistence.StoredProcedureParameter;
import jakarta.persistence.StoredProcedureQuery;
import jakarta.persistence.Table;
import org.hamcrest.MatcherAssert;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.core.Is.is;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
@ -55,10 +63,16 @@ import static org.junit.jupiter.api.Assertions.fail;
Phone.class,
Vote.class,
DB2StoredProcedureTest.IdHolder.class,
DB2StoredProcedureTest.Address.class,
} )
@RequiresDialect( value = DB2Dialect.class )
@Jira( "https://hibernate.atlassian.net/browse/HHH-18332" )
public class DB2StoredProcedureTest {
private static final String CITY = "London";
private static final String STREET = "Lollard Street";
private static final String ZIP = "SE116U";
@Test
public void testStoredProcedureOutParameter(EntityManagerFactoryScope scope) {
scope.inTransaction( entityManager -> {
@ -242,6 +256,88 @@ public class DB2StoredProcedureTest {
} );
}
@Test
@Jira( "https://hibernate.atlassian.net/browse/HHH-18302" )
public void testStoredProcedureInAndOutAndRefCursorParameters(EntityManagerFactoryScope scope) {
scope.inTransaction(
entityManager -> {
StoredProcedureQuery query = entityManager.createStoredProcedureQuery( "sp_get_address_by_street_city" );
query.registerStoredProcedureParameter( "street_in", String.class, ParameterMode.IN );
query.registerStoredProcedureParameter( "city_in", String.class, ParameterMode.IN );
query.registerStoredProcedureParameter( "rec_out", ResultSet.class, ParameterMode.REF_CURSOR );
query.setParameter( "street_in", STREET )
.setParameter( "city_in", CITY );
query.execute();
ResultSet rs = (ResultSet) query.getOutputParameterValue( "rec_out" );
try {
Assertions.assertTrue( rs.next() );
MatcherAssert.assertThat( rs.getString( "street" ), is( STREET ) );
MatcherAssert.assertThat( rs.getString( "city" ), is( CITY ) );
MatcherAssert.assertThat( rs.getString( "zip" ), is( ZIP ) );
}
catch (SQLException e) {
throw new RuntimeException( e );
}
}
);
}
@Test
@Jira( "https://hibernate.atlassian.net/browse/HHH-18302" )
public void testStoredProcedureInAndOutAndRefCursorParametersDifferentRegistrationOrder(EntityManagerFactoryScope scope) {
scope.inTransaction(
entityManager -> {
StoredProcedureQuery query = entityManager.createStoredProcedureQuery( "sp_get_address_by_street_city" );
query.registerStoredProcedureParameter( "city_in", String.class, ParameterMode.IN );
query.registerStoredProcedureParameter( "street_in", String.class, ParameterMode.IN );
query.registerStoredProcedureParameter( "rec_out", ResultSet.class, ParameterMode.REF_CURSOR );
query.setParameter( "street_in", STREET )
.setParameter( "city_in", CITY );
query.execute();
ResultSet rs = (ResultSet) query.getOutputParameterValue( "rec_out" );
try {
Assertions.assertTrue( rs.next() );
MatcherAssert.assertThat( rs.getString( "street" ), is( STREET ) );
MatcherAssert.assertThat( rs.getString( "city" ), is( CITY ) );
MatcherAssert.assertThat( rs.getString( "zip" ), is( ZIP ) );
}
catch (SQLException e) {
throw new RuntimeException( e );
}
}
);
}
@Test
@Jira( "https://hibernate.atlassian.net/browse/HHH-18302" )
public void testStoredProcedureInAndOutAndRefCursorParametersDifferentRegistrationOrder2(EntityManagerFactoryScope scope) {
scope.inTransaction(
entityManager -> {
StoredProcedureQuery query = entityManager.createStoredProcedureQuery( "sp_get_address_by_street_city" );
query.registerStoredProcedureParameter( "rec_out", ResultSet.class, ParameterMode.REF_CURSOR );
query.registerStoredProcedureParameter( "city_in", String.class, ParameterMode.IN );
query.registerStoredProcedureParameter( "street_in", String.class, ParameterMode.IN );
query.setParameter( "street_in", STREET )
.setParameter( "city_in", CITY );
query.execute();
ResultSet rs = (ResultSet) query.getOutputParameterValue( "rec_out" );
try {
Assertions.assertTrue( rs.next() );
MatcherAssert.assertThat( rs.getString( "street" ), is( STREET ) );
MatcherAssert.assertThat( rs.getString( "city" ), is( CITY ) );
MatcherAssert.assertThat( rs.getString( "zip" ), is( ZIP ) );
}
catch (SQLException e) {
throw new RuntimeException( e );
}
}
);
}
@BeforeAll
public void prepareSchema(EntityManagerFactoryScope scope) {
scope.inTransaction( (entityManager) -> entityManager.unwrap( Session.class ).doWork( (connection) -> {
@ -355,9 +451,27 @@ public class DB2StoredProcedureTest {
" OPEN votes; " +
"END"
);
statement.executeUpdate(
"CREATE OR REPLACE PROCEDURE sp_get_address_by_street_city ( " +
" IN street_in VARCHAR(255), " +
" IN city_in VARCHAR(255), " +
" OUT rec_out CURSOR ) " +
"BEGIN " +
" SET rec_out = CURSOR FOR " +
" SELECT * " +
" FROM ADDRESS_TABLE A " +
" WHERE " +
" A.STREET = street_in" +
" AND A.CITY = city_in;" +
" OPEN rec_out; " +
"END;"
);
}
} ) );
}
@BeforeEach
public void setUp(EntityManagerFactoryScope scope){
scope.inTransaction( (entityManager) -> {
final Person person1 = new Person( 1L, "John Doe" );
person1.setNickName( "JD" );
@ -377,6 +491,8 @@ public class DB2StoredProcedureTest {
phone2.setValid( false );
person1.addPhone( phone2 );
Address address = new Address( 1l, STREET, CITY, ZIP );
entityManager.persist( address );
} );
}
@ -394,15 +510,21 @@ public class DB2StoredProcedureTest {
statement.executeUpdate( "DROP PROCEDURE outAndRefCursor" );
statement.executeUpdate( "DROP PROCEDURE sp_phone_validity" );
statement.executeUpdate( "DROP PROCEDURE sp_votes" );
statement.executeUpdate( "DROP PROCEDURE sp_get_address_by_street_city" );
}
catch (final SQLException ignore) {
}
} );
} );
}
scope.inTransaction( em, (em2) -> {
final List<Person> people = em.createQuery( "from Person", Person.class ).getResultList();
people.forEach( em::remove );
} );
@AfterEach
public void cleanData(EntityManagerFactoryScope scope) {
scope.inTransaction( (em) -> {
final List<Person> people = em.createQuery( "from Person", Person.class ).getResultList();
people.forEach( em::remove );
em.createQuery( "delete Address" ).executeUpdate();
} );
}
@ -429,4 +551,44 @@ public class DB2StoredProcedureTest {
Long id;
String name;
}
@Entity(name = "Address")
@Table(name = "ADDRESS_TABLE")
public static class Address {
@Id
@Column(name = "ID")
private long id;
@Column(name = "STREET")
private String street;
@Column(name = "CITY")
private String city;
@Column(name = "ZIP")
private String zip;
public Address() {
}
public Address(long id, String street, String city, String zip) {
this.id = id;
this.street = street;
this.city = city;
this.zip = zip;
}
public long getId() {
return id;
}
public String getStreet() {
return street;
}
public String getCity() {
return city;
}
public String getZip() {
return zip;
}
}
}

View File

@ -186,7 +186,7 @@
<sql-query name="simpleScalar" callable="true">
<return-scalar column="name" type="string"/>
<return-scalar column="`value`" type="long"/>
{ call simpleScalar(:number) }
{ call simpleScalar(:p_number) }
</sql-query>
<sql-query name="paramhandling" callable="true">
@ -261,10 +261,10 @@
<database-object>
<create>
CREATE PROCEDURE simpleScalar (IN j SMALLINT) RESULT SETS 1
CREATE PROCEDURE simpleScalar (IN p_number SMALLINT) RESULT SETS 1
P1: BEGIN
DECLARE C1 CURSOR WITH RETURN FOR
SELECT j as value, 'getAll' as name from sysibm.sysdummy1;
SELECT p_number as value, 'getAll' as name from sysibm.sysdummy1;
OPEN C1;
END P1
</create>