DATAJPA-652 - Added support for REF_CURSOR output parameters for stored procedures.

We now support detecting output parameters for stored-procedures with ParameterMode.REF_CURSOR. Previously we only considered parameters with OUT or INOUT mode as output parameters.

Added additional test cases for various procedure definition options.
Introduced new Dummy test type to avoid polluting the User test type anymore with  additional procedure definitions. Added test for eclipse link and Openjpa but I had to deactivate them since they currently need to be run with HSQLDB V1 which doesn’t support stored procedures.

Original pull request: #130.
This commit is contained in:
Thomas Darimont
2015-01-16 10:01:31 +01:00
committed by Oliver Gierke
parent 81e69ab65a
commit a5f20d23ce
11 changed files with 577 additions and 27 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014 the original author or authors.
* Copyright 2014-2015 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.
@@ -57,7 +57,7 @@ enum StoredProcedureAttributeSource {
procedure);
if (namedStoredProc != null) {
return newProcedureAttributesFrom(method, namedStoredProc);
return newProcedureAttributesFrom(method, namedStoredProc, procedure);
}
String procedureName = deriveProcedureNameFrom(method, procedure);
@@ -90,31 +90,55 @@ enum StoredProcedureAttributeSource {
/**
* @param method
* @param namedStoredProc
* @param procedure
* @return
*/
private StoredProcedureAttributes newProcedureAttributesFrom(Method method, NamedStoredProcedureQuery namedStoredProc) {
private StoredProcedureAttributes newProcedureAttributesFrom(Method method,
NamedStoredProcedureQuery namedStoredProc, Procedure procedure) {
String outputParameterName = null;
Class<?> outputParameterType = null;
int outputParameterCount = 0;
if (!procedure.outputParameterName().isEmpty()) {
// we give the output parameter definition from the @Procedure annotation precedence
outputParameterName = procedure.outputParameterName();
} else {
// try to discover the output parameter
List<StoredProcedureParameter> outputParameters = extractOutputParametersFrom(namedStoredProc);
if (outputParameters.size() != 1 && !void.class.equals(method.getReturnType())) {
throw new IllegalStateException(String.format(
"Could not create ProcedureAttributes from %s. We currently support exactly one output parameter!", method));
}
if (!outputParameters.isEmpty()) {
StoredProcedureParameter outputParameter = outputParameters.get(0);
outputParameterName = outputParameter.name();
outputParameterType = outputParameter.type();
}
}
if (outputParameterType == null || Object.class.equals(outputParameterType)
|| void.class.equals(outputParameterType)) {
outputParameterType = method.getReturnType();
}
return new StoredProcedureAttributes(namedStoredProc.name(), outputParameterName, outputParameterType, true);
}
private List<StoredProcedureParameter> extractOutputParametersFrom(NamedStoredProcedureQuery namedStoredProc) {
List<StoredProcedureParameter> outputParameters = new ArrayList<StoredProcedureParameter>();
for (StoredProcedureParameter param : namedStoredProc.parameters()) {
switch (param.mode()) {
case OUT:
case INOUT:
if (outputParameterCount > 0) {
throw new IllegalStateException(
String.format(
"Could not create ProcedureAttributes from %s. We currently support only one output parameter!",
method));
}
outputParameterName = param.name();
outputParameterType = param.type();
outputParameterCount++;
case REF_CURSOR:
outputParameters.add(param);
break;
case IN:
default:
@@ -122,11 +146,7 @@ enum StoredProcedureAttributeSource {
}
}
if (outputParameterType == null) {
outputParameterType = method.getReturnType();
}
return new StoredProcedureAttributes(namedStoredProc.name(), outputParameterName, outputParameterType, true);
return outputParameters;
}
/**

View File

@@ -0,0 +1,116 @@
/*
* Copyright 2015 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.data.jpa.domain.sample;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.NamedStoredProcedureQueries;
import javax.persistence.NamedStoredProcedureQuery;
import javax.persistence.ParameterMode;
import javax.persistence.StoredProcedureParameter;
import org.springframework.util.ObjectUtils;
/**
* Sample domain class representing used for Stored Procedure tests.
*
* @author Thomas Darimont
*/
@Entity
@NamedStoredProcedureQueries({ //
@NamedStoredProcedureQuery(name = "Dummy.procedureWith1InputAnd1OutputParameter",
procedureName = "procedure_in1_out1", parameters = {
@StoredProcedureParameter(mode = ParameterMode.IN, type = Integer.class),
@StoredProcedureParameter(mode = ParameterMode.OUT, type = Integer.class) }) //
,
@NamedStoredProcedureQuery(name = "Dummy.procedureWith1InputAndNoOutputParameter",
procedureName = "procedure_in1_out0", parameters = { @StoredProcedureParameter(mode = ParameterMode.IN,
type = Integer.class) }) //
,
@NamedStoredProcedureQuery(name = "Dummy.procedureWithNoInputAnd1OutputParameter",
procedureName = "procedure_in0_out1", parameters = { @StoredProcedureParameter(mode = ParameterMode.OUT,
type = Integer.class) }) //
,
@NamedStoredProcedureQuery(name = "Dummy.procedureWith1InputAnd1OutputParameterWithResultSet",
procedureName = "procedure_in1_out0_return_rs_no_update", parameters = {
@StoredProcedureParameter(mode = ParameterMode.IN, type = Integer.class),
@StoredProcedureParameter(mode = ParameterMode.REF_CURSOR, type = void.class) }) //
,
@NamedStoredProcedureQuery(name = "Dummy.procedureWith1InputAnd1OutputParameterWithResultSetWithUpdate",
procedureName = "procedure_in1_out0_return_rs_with_update", parameters = {
@StoredProcedureParameter(mode = ParameterMode.IN, type = Integer.class),
@StoredProcedureParameter(mode = ParameterMode.REF_CURSOR, type = void.class) }) //
,
@NamedStoredProcedureQuery(name = "Dummy.procedureWith1InputAndNoOutputParameterWithUpdate",
procedureName = "procedure_in1_out0_no_return_with_update", parameters = { @StoredProcedureParameter(
mode = ParameterMode.IN, type = String.class) }) //
})
public class Dummy {
@Id @GeneratedValue private Integer id;
private String name;
public Dummy() {}
public Dummy(String name) {
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Dummy [id=" + id + ", name=" + name + "]";
}
@Override
public int hashCode() {
return ObjectUtils.nullSafeHashCode(name);
}
@Override
public boolean equals(Object that) {
if (that == this) {
return true;
}
if (that == null) {
return false;
}
if (!(that instanceof Dummy)) {
return false;
}
return ObjectUtils.nullSafeEquals(this.name, ((Dummy) that).name);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2008-2014 the original author or authors.
* Copyright 2008-2015 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.
@@ -84,7 +84,7 @@ public class User {
@Lob private byte[] binaryData;
@ElementCollection private Set<String> attributes;
@Temporal(TemporalType.DATE) private Date dateOfBirth;
/**
@@ -367,7 +367,7 @@ public class User {
public void setAttributes(Set<String> attributes) {
this.attributes = attributes;
}
public Date getDateOfBirth() {
return dateOfBirth;
}

View File

@@ -0,0 +1,28 @@
/*
* Copyright 2008-2015 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.data.jpa.repository;
import org.springframework.context.annotation.ImportResource;
import org.springframework.test.context.ContextConfiguration;
/**
* Testcase to run {@link StoredProcedureIntegrationTests} integration tests on top of EclipseLink.
*
* @author Thomas Darimont
*/
@ContextConfiguration(classes = { StoredProcedureIntegrationTests.Config.class })
@ImportResource("classpath:eclipselink.xml")
public class EclipseLinkStoredProcedureIntegrationTests extends StoredProcedureIntegrationTests {}

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2015 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.data.jpa.repository;
import org.junit.Ignore;
import org.springframework.context.annotation.ImportResource;
import org.springframework.test.context.ContextConfiguration;
/**
* Test case to run {@link StoredProcedureIntegrationTests} integration tests on top of OpenJpa. This is currently not
* supported since, the OpenJPA tests need to be executed with hsqldb1 which doesn't supported stored procedures.
*
* @author Thomas Darimont
*/
@Ignore
@ContextConfiguration(classes = { StoredProcedureIntegrationTests.Config.class })
@ImportResource("classpath:openjpa.xml")
public class OpenJpaStoredProcedureIntegrationTests extends StoredProcedureIntegrationTests {}

View File

@@ -0,0 +1,214 @@
/*
* Copyright 2015 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.data.jpa.repository;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import static org.junit.Assume.*;
import static org.springframework.data.jpa.support.EntityManagerTestUtils.*;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.ImportResource;
import org.springframework.data.jpa.domain.sample.Dummy;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.jpa.repository.sample.DummyRepository;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
/**
* @see scripts/schema-stored-procedures.sql for procedure definitions.
* @author Thomas Darimont
*/
@Transactional
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class StoredProcedureIntegrationTests {
@PersistenceContext EntityManager em;
@Autowired DummyRepository repository;
Dummy dummyA;
Dummy dummyB;
Dummy dummyC;
@Configuration
@EnableJpaRepositories(basePackageClasses = DummyRepository.class, includeFilters = { @Filter(
pattern = ".*DummyRepository", type = FilterType.REGEX) })
@ImportResource("classpath:infrastructure.xml")
static class Config {}
@Before
public void setup() {
assumeTrue(currentEntityManagerIsAJpa21EntityManager(em));
dummyA = em.merge(new Dummy("A"));
dummyB = em.merge(new Dummy("B"));
dummyC = em.merge(new Dummy("C"));
}
/**
* @see DATAJPA-652
*/
@Test
public void shouldExecuteAdHocProcedureWithNoInputAnd1OutputParameter() {
assertThat(repository.adHocProcedureWithNoInputAnd1OutputParameter(), is(equalTo(42)));
}
/**
* @see DATAJPA-652
*/
@Test
public void shouldExecuteAdHocProcedureWith1InputAnd1OutputParameter() {
assertThat(repository.adHocProcedureWith1InputAnd1OutputParameter(23), is(equalTo(24)));
}
/**
* @see DATAJPA-652
*/
@Test
public void shouldExecuteAdHocProcedureWith1InputAndNoOutputParameter() {
repository.adHocProcedureWith1InputAndNoOutputParameter(42);
assertTrue(true);
}
/**
* @see DATAJPA-652
*/
@Test
public void shouldExecuteAdHocProcedureWith1InputAnd1OutputParameterWithResultSet() {
// hibernate currently (v4.3) doesn't support returning ResultSets in output parameters
assumeFalse(currentEntityManagerIsHibernateEntityManager(em));
List<Dummy> dummies = repository.adHocProcedureWith1InputAnd1OutputParameterWithResultSet("FOO");
System.out.println("### Found dummies: " + dummies);
assertThat(dummies, is(notNullValue()));
assertThat(dummies.size(), is(equalTo(3)));
}
/**
* @see DATAJPA-652
*/
@Test
public void shouldExecuteAdHocProcedureWith1InputAnd1OutputParameterWithResultSetWithUpdate() {
// hibernate currently (v4.3) doesn't support returning ResultSets in output parameters
assumeFalse(currentEntityManagerIsHibernateEntityManager(em));
List<Dummy> dummies = repository.adHocProcedureWith1InputAnd1OutputParameterWithResultSetWithUpdate("FOO");
System.out.println("### Found dummies: " + dummies);
assertThat(dummies, is(notNullValue()));
assertThat(dummies.size(), is(equalTo(3)));
}
/**
* @see DATAJPA-652
*/
@Test
public void shouldExecuteAdHocProcedureWith1InputAnd1OutputParameterWithUpdate() {
repository.adHocProcedureWith1InputAndNoOutputParameterWithUpdate("FOO");
assertTrue(true);
}
/**
* @see DATAJPA-652
*/
@Test
public void shouldExecuteProcedureWithNoInputAnd1OutputParameter() {
assertThat(repository.procedureWithNoInputAnd1OutputParameter(), is(equalTo(42)));
}
/**
* @see DATAJPA-652
*/
@Test
public void shouldExecuteProcedureWith1InputAnd1OutputParameter() {
assertThat(repository.procedureWith1InputAnd1OutputParameter(23), is(equalTo(24)));
}
/**
* @see DATAJPA-652
*/
@Test
public void shouldExecuteProcedureWith1InputAndNoOutputParameter() {
repository.procedureWith1InputAndNoOutputParameter(42);
assertTrue(true);
}
/**
* @see DATAJPA-652
*/
@Test
public void shouldExecuteProcedureWith1InputAnd1OutputParameterWithResultSet() {
// hibernate currently (v4.3) doesn't support returning ResultSets in output parameters
assumeFalse(currentEntityManagerIsHibernateEntityManager(em));
List<Dummy> dummies = repository.procedureWith1InputAnd1OutputParameterWithResultSet("FOO");
assertThat(dummies, is(notNullValue()));
assertThat(dummies.size(), is(equalTo(3)));
}
/**
* @see DATAJPA-652
*/
@Test
public void shouldExecuteProcedureWith1InputAnd1OutputParameterWithResultSetWithUpdate() {
// hibernate currently (v4.3) doesn't support returning ResultSets in output parameters
assumeFalse(currentEntityManagerIsHibernateEntityManager(em));
List<Dummy> dummies = repository.procedureWith1InputAnd1OutputParameterWithResultSetWithUpdate("FOO");
assertThat(dummies, is(notNullValue()));
assertThat(dummies.size(), is(equalTo(3)));
}
/**
* @see DATAJPA-652
*/
@Test
public void shouldExecuteProcedureWith1InputAnd1OutputParameterWithUpdate() {
repository.procedureWith1InputAndNoOutputParameterWithUpdate("FOO");
assertTrue(true);
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright 2015 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.data.jpa.repository.sample;
import java.util.List;
import org.springframework.data.jpa.domain.sample.Dummy;
import org.springframework.data.jpa.repository.query.Procedure;
import org.springframework.data.repository.CrudRepository;
import org.springframework.transaction.annotation.Transactional;
@Transactional
public interface DummyRepository extends CrudRepository<Dummy, Long> {
@Procedure("procedure_in1_out1")
Integer adHocProcedureWith1InputAnd1OutputParameter(Integer in);
@Procedure("procedure_in1_out0")
void adHocProcedureWith1InputAndNoOutputParameter(Integer in);
@Procedure("procedure_in0_out1")
Integer adHocProcedureWithNoInputAnd1OutputParameter();
@Procedure("procedure_in1_out0_return_rs_no_update")
List<Dummy> adHocProcedureWith1InputAnd1OutputParameterWithResultSet(String in);
@Procedure("procedure_in1_out0_return_rs_with_update")
List<Dummy> adHocProcedureWith1InputAnd1OutputParameterWithResultSetWithUpdate(String in);
@Procedure("procedure_in1_out0_no_return_with_update")
void adHocProcedureWith1InputAndNoOutputParameterWithUpdate(String in);
@Procedure
Integer procedureWith1InputAnd1OutputParameter(Integer in);
@Procedure
void procedureWith1InputAndNoOutputParameter(Integer in);
@Procedure
Integer procedureWithNoInputAnd1OutputParameter();
@Procedure
List<Dummy> procedureWith1InputAnd1OutputParameterWithResultSet(String in);
@Procedure
List<Dummy> procedureWith1InputAnd1OutputParameterWithResultSetWithUpdate(String in);
@Procedure
void procedureWith1InputAndNoOutputParameterWithUpdate(String in);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014 the original author or authors.
* Copyright 2014-2015 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.
@@ -32,4 +32,8 @@ public abstract class EntityManagerTestUtils {
return ReflectionUtils.findMethod(((org.springframework.orm.jpa.EntityManagerProxy) em).getTargetEntityManager()
.getClass(), "getEntityGraph", String.class) != null;
}
public static boolean currentEntityManagerIsHibernateEntityManager(EntityManager em) {
return em.getDelegate().getClass().getName().toLowerCase().contains("hibernate");
}
}

View File

@@ -38,6 +38,7 @@
<class>org.springframework.data.jpa.domain.sample.SpecialUser</class>
<class>org.springframework.data.jpa.domain.sample.User</class>
<class>org.springframework.data.jpa.domain.sample.VersionedUser</class>
<class>org.springframework.data.jpa.domain.sample.Dummy</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
</persistence-unit>
<persistence-unit name="querydsl">
@@ -46,6 +47,7 @@
<class>org.springframework.data.jpa.domain.sample.MailSender</class>
<class>org.springframework.data.jpa.domain.sample.MailUser</class>
<class>org.springframework.data.jpa.domain.sample.User</class>
<class>org.springframework.data.jpa.domain.sample.Dummy</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
</persistence-unit>
<persistence-unit name="cdi">
@@ -55,6 +57,7 @@
<class>org.springframework.data.jpa.domain.sample.MailUser</class>
<class>org.springframework.data.jpa.domain.sample.User</class>
<class>org.springframework.data.jpa.repository.cdi.Person</class>
<class>org.springframework.data.jpa.domain.sample.Dummy</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="hibernate.connection.username" value="sa" />
@@ -101,6 +104,7 @@
<class>org.springframework.data.jpa.domain.sample.MailUser</class>
<class>org.springframework.data.jpa.domain.sample.User</class>
<class>org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformationIntegrationTests$Sample</class>
<class>org.springframework.data.jpa.domain.sample.Dummy</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
</persistence-unit>
<persistence-unit name="metadata_oj">
@@ -111,6 +115,7 @@
<class>org.springframework.data.jpa.domain.sample.MailUser</class>
<class>org.springframework.data.jpa.domain.sample.User</class>
<class>org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformationIntegrationTests$Sample</class>
<class>org.springframework.data.jpa.domain.sample.Dummy</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="openjpa.jdbc.DBDictionary" value="hsql" />

View File

@@ -15,6 +15,7 @@
<class>org.springframework.data.jpa.domain.sample.Role</class>
<class>org.springframework.data.jpa.domain.sample.SpecialUser</class>
<class>org.springframework.data.jpa.domain.sample.User</class>
<class>org.springframework.data.jpa.domain.sample.Dummy</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
</persistence-unit>
<persistence-unit name="second">
@@ -22,7 +23,7 @@
<class>org.springframework.data.jpa.domain.sample.AuditableUser</class>
<class>org.springframework.data.jpa.domain.sample.AuditableRole</class>
<class>org.springframework.data.jpa.domain.sample.Category</class>
<class>org.springframework.data.jpa.domain.sample.CustomAbstractPersistable</class>
<class>org.springframework.data.jpa.domain.sample.CustomAbstractPersistable</class>
<class>org.springframework.data.jpa.domain.sample.MailMessage</class>
<class>org.springframework.data.jpa.domain.sample.MailSender</class>
<class>org.springframework.data.jpa.domain.sample.MailUser</class>
@@ -30,6 +31,7 @@
<class>org.springframework.data.jpa.domain.sample.Role</class>
<class>org.springframework.data.jpa.domain.sample.SpecialUser</class>
<class>org.springframework.data.jpa.domain.sample.User</class>
<class>org.springframework.data.jpa.domain.sample.Dummy</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
</persistence-unit>
</persistence>

View File

@@ -5,4 +5,71 @@ CREATE procedure plus1inout (IN arg int, OUT res int)
BEGIN ATOMIC
set res = arg + 1;
END
/;
/;
DROP procedure IF EXISTS procedure_in1_out1
/;
DROP procedure IF EXISTS procedure_in1_out0
/;
DROP procedure IF EXISTS procedure_in0_out1
/;
DROP procedure IF EXISTS procedure_in1_out0_return_rs_no_update
/;
DROP procedure IF EXISTS procedure_in1_out0_return_rs_with_update
/;
DROP procedure IF EXISTS procedure_in1_out0_no_return_with_update
/;
DROP table dummy if exists
/;
create table dummy (id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, name VARCHAR(32))
/;
insert into public.dummy(name) values ('A')
/;
insert into public.dummy(name) values ('B')
/;
insert into public.dummy(name) values ('C')
/;
/;
CREATE procedure procedure_in1_out1 (IN arg int, OUT res int)
BEGIN ATOMIC
set res = arg + 1;
END
/;
CREATE procedure procedure_in1_out0 (IN arg int)
BEGIN ATOMIC
DECLARE res int;
set res = arg + 1;
END
/;
CREATE procedure procedure_in0_out1 (OUT res int)
BEGIN ATOMIC
set res = 42;
END
/;
CREATE procedure procedure_in1_out0_return_rs_no_update (IN arg varchar(32))
READS SQL DATA DYNAMIC RESULT SETS 1
BEGIN ATOMIC
DECLARE result CURSOR WITH RETURN FOR SELECT * FROM public.dummy FOR READ ONLY;
open result;
END
/;
CREATE procedure procedure_in1_out0_return_rs_with_update (IN arg varchar(32))
MODIFIES SQL DATA DYNAMIC RESULT SETS 1
BEGIN ATOMIC
DECLARE result CURSOR WITH RETURN FOR SELECT * FROM public.dummy FOR READ ONLY;
update public.dummy set name = name;
OPEN result;
END
/;
CREATE procedure procedure_in1_out0_no_return_with_update (IN arg varchar(32))
MODIFIES SQL DATA
BEGIN ATOMIC
update public.dummy set name = name;
END
/;