^ MySQL

Calling MySQL Stored Procedures from JDBC http://www.mysqltutorial.org/calling-mysql-stored-procedures-from-jdbc/
PHP MySQL: Call MySQL Stored Procedures http://www.mysqltutorial.org/php-calling-mysql-stored-procedures/
Python MySQL – Call Stored Procedures in Python http://www.mysqltutorial.org/calling-mysql-stored-procedures-python/
MySQL - Returning Single Value from Stored Procedure https://wiki.ispirer.com/sqlways/mysql/techniques/return-value-from-procedure
Google: mysql function return table You cannot return table from MySQL function. The function can return string, integer, char etc. To return table from MySQL, use stored procedure, not function.
https://www.tutorialspoint.com/how-to-return-table-from-mysql-function
^ Prerequisites for testing

DDL of data tables used in MySQL examples below:

CREATE TABLE `_projects` (
  `p_id` int NOT NULL AUTO_INCREMENT,
  `p_name` varchar(45) NOT NULL,
  PRIMARY KEY (`p_id`)
);

CREATE TABLE `_tests` (
  `t_id` int NOT NULL AUTO_INCREMENT,
  `t_date` datetime NOT NULL,
  `t_name` varchar(45) NOT NULL,
  `t_rating` float NOT NULL,
  `p_id` int NOT NULL,
  PRIMARY KEY (`t_id`),
  KEY `fk_project_tests_idx` (`p_id`),
  CONSTRAINT `fk_project_tests` FOREIGN KEY (`p_id`) REFERENCES `_projects` (`p_id`)
);

It is impossible to obtain JDBC meta-data of Result-Set returned by something like 'call get_some_table(?, ?)'. As workaround, code generator obtains field info from XML declaration of DTO class:

<dto-class name="Test" ref="tests" />

or

<dto-class name="Test" ref="" >
  <field column="t_id" type="int" />
  <field column="t_date" type="java.util.Date" />
  <field column="t_name" type="String" />
  <field column="t_rating" type="java.math.BigDecimal" />
</dto-class>

Also, you may need to specify explicitly the types of method parameters and return values:

<query method="get_test_rating(int t_id)" return-type="java.math.BigDecimal" ref="select get_test_rating(?)" />
^ MySQL > UDF returning a scalar value
CREATE FUNCTION `get_test_rating`(pt_id int) RETURNS float
  DETERMINISTIC
BEGIN
  DECLARE res numeric(10, 2);
  select t_rating into res from _tests where t_id = pt_id;
  RETURN res;
END
<query method="get_test_rating(int t_id)" return-type="java.math.BigDecimal" ref="select get_test_rating(?)" />
PHP
print_r($dao->get_test_rating(314));
Java
out.println(dao.get_test_rating(314));
Python
print(dao.get_test_rating(314))
Go
r := tDao.udfGetTestRating(3)
fmt.Println(r)
^ MySQL > SP returning single Result-Set
CREATE PROCEDURE `get_tests_by_rating`(in p_rating float)
BEGIN
  select * from _tests where t_rating >= p_rating;
END
<query-dto-list method="get_tests_by_rating(double t_rating)" dto="Test" ref="call get_tests_by_rating(?)" />
PHP
foreach ($dao->get_tests_by_rating(2) as $t) {
    // ...
}
Java
for (Test t : dao.get_tests_by_rating(2)) {
    // ...
}
Python
for test in dao.get_tests_by_rating(2):
    # ...
Go
tests := tDao.spGetTestsByRating(2)
for _, t := range tests {
    // ...
}
^ MySQL > SP returning multiple Result-Sets
CREATE PROCEDURE `sp_get_all`(rating float)
BEGIN
  select distinct p.* from _projects p inner join _tests t on t.p_id = p.p_id
  where t.t_rating > rating;
  select * from _tests where t_rating > rating
  order by t_rating;
END
<exec-dml method="sp_get_all(float rating, [on_project:Project, on_test:Test])" ref="call sp_get_all(?)" />
PHP
$dao->sp_get_all(3, function($project) {
    print_r($project->getP_name());
}, function($test) {
    print_r($test->getT_name());
});
Java
dao.sp_get_all(3, project -> {
    out.println(project.getP_name());
}, test -> {
    out.println(test.getT_rating());
});
Python
dao.sp_get_all(3,
lambda p: print('Project: {}\t\t{}'.format(p.p_id, p.p_name)),
lambda t: print('Task: {}\t\t{}\t\t{:10.2f}\t\t{}'.format(t.t_id, t.t_date, t.t_rating, t.t_name)),)
Go
tDao.spGetAll(3,
    func(p *Projects) { projects = append(projects, p) },
    func(t *Test) { tests = append(tests, t) }
^ MySQL > SP to change some data
CREATE PROCEDURE `set_test_rating`(in p_t_id int, in p_rating float)
BEGIN
  update _tests set t_rating = p_rating where t_id = p_t_id;
END
<exec-dml method="set_test_rating(int t_id, double t_rating)" ref="call set_test_rating(?, ?)" />
PHP
$dao->set_test_rating(314, 5);
Java
dao.set_test_rating(314, 5);
Python
dao.set_test_rating(314, 5)
Go
tDao.spSetTestRating(314, 5)
^ MySQL > OUT and INOUT parameters
CREATE PROCEDURE `sp_get_film_title`(p_film_id int, out p_title varchar(200))
BEGIN
    select title into p_title from film where film_id = p_film_id;
END
CREATE PROCEDURE `sp_test_in_out_params`(inout res int)
BEGIN
    set res = res * 10;
END
<exec-dml method="sp_get_film_title(film_id, title)" ref="call sp_get_film_title(?, ?)" />
<exec-dml method="sp_test_in_out_params(res)" ref="call sp_test_in_out_params(?)" />
PHP
$res1 = new OutParam();
$dao->sp_get_film_title(1, $res1);
print_r($res1->value);

$res2 = new InOutParam(10);
$dao->sp_test_in_out_params($res2);
print_r($res2->value);
Java
OutParam title = new OutParam(Types.NCHAR, String.class);
dao.sp_get_film_title(1, title);
out.println(title.getValue());
Python
"""
COMMENT FROM SOURCES OF MySQL Connector => cursor.py:
For OUT and INOUT parameters the user should provide the
type of the parameter as well. The argument should be a
tuple with first item as the value of the parameter to pass
and second argument the type of the argument.
"""
title = OutParam()
title.value = (None, 'CHAR')  # ...but just None is also OK in here
dao.sp_get_film_title(1, title)
print(title.value)
Go
<exec-dml method="SpGetFilmTitleInit(int32 film_id)" ref="set @film_id=?"/>
<exec-dml method="SpGetFilmTitle()" ref="call sp_get_film_title(@film_id, @title)"/>
<query method="SpGetFilmTitleQuery()" ref="select @title" return-type="string"/>

<exec-dml method="SpTestInOutParamsInit(int32 res)" ref="set @res=?"/>
<exec-dml method="SpTestInOutParams()" ref="call sp_test_in_out_params(@res)"/>
<query method="SpTestInOutParamsQuery()" ref="select @res" return-type="int64"/>
tDao.SpGetFilmTitleInit(5)
tDao.SpGetFilmTitle()
res := tDao.SpGetFilmTitleQuery()
fmt.Println(res)/>

tDao.SpTestInOutParamsInit(123)
tDao.SpTestInOutParams()
title := tDao.SpTestInOutParamsQuery()
fmt.Println(title)

^ Oracle 12c+

Oracle: return a »table« from a function https://renenyffenegger.ch/notes/development/databases/Oracle/PL-SQL/collection-types/return-table-from-function/index
Oracle 12c: Creating users without container database https://jaykhimani.blogspot.com/2015/12/oracle-12c-creating-users-without.html
Using Python With Oracle Database 11g https://www.oracle.com/ocom/groups/public/@otn/documents/webcontent/1521398.htm
Oracle Database for Python Developers, Part 1: cx_Oracle Quick Start https://developer.oracle.com/databases/database-for-python-developers-1.html
Using Ref Cursors To Return Recordsets https://oracle-base.com/articles/misc/using-ref-cursors-to-return-recordsets
Implicit Statement Results in Oracle Database 12c Release 1 (12.1) https://oracle-base.com/articles/12c/implicit-statement-results-12cr1
Using PHP and ORACLE 12c Implicit Result Sets https://blogs.oracle.com/opal/using-php-and-oracle-database-12c-implicit-result-sets
Showing Equipment Records by Using a REF CURSOR https://docs.oracle.com/cd/E17781_01/appdev.112/e18555/ch_six_ref_cur.htm#TDPPH160
Python Oracle (cx-oracle) https://www.oracletutorial.com/python-oracle/
Using Bind Variables (cx-oracle) https://cx-oracle.readthedocs.io/en/latest/user_guide/bind.html
PL/SQL Execution (cx-oracle) https://cx-oracle.readthedocs.io/en/latest/user_guide/plsql_execution.html
Procedures of Oracle in php with PDO https://stackoverflow.com/questions/8121244/procedures-of-oracle-in-php-with-pdo
Calling the REF CURSOR in PHP (OCI) https://docs.oracle.com/cd/E17781_01/appdev.112/e18555/ch_six_ref_cur.htm#TDPPH162
PHP + OCI: Binding a REF CURSOR in an Oracle stored procedure call https://www.php.net/manual/en/function.oci-new-cursor.php
How to return rows from a declare/begin/end block in Oracle? https://stackoverflow.com/questions/3371408/how-to-return-rows-from-a-declare-begin-end-block-in-oracle
PHP + PDO + Oracle

https://blogs.oracle.com/opal/converting-ref-cursor-to-pipe-for-performance-in-php-oci8-and-pdooci ==>

https://www.oracle.com/database/technologies/underground-php-oracle-manual.html ==>

https://www.oracle.com/technetwork/database/database-technologies/php/201212-ug-php-oracle-1884760.pdf

Oracle does not contribute to PDO_OCI. The PHP community has let the PDO project languish and Oracle recommends using OCI8 instead whenever possible because of its better feature set, performance, reliability and stability. Use of PDO_OCI for general purpose applications is not recommended. However PDO is used by some frameworks and higher level packages, such as content management systems so you may need to use it.

^ Prerequisites for testing
CREATE TABLE "PROJECTS"
(
  "P_ID" NUMBER GENERATED ALWAYS AS IDENTITY,
  "P_NAME" VARCHAR2(200) NOT NULL,
   CONSTRAINT "PROJECTS_PK" PRIMARY KEY ("P_ID")
);

CREATE TABLE "TESTS"
(
  "T_ID" NUMBER GENERATED ALWAYS AS IDENTITY,
  "T_DATE" DATE NOT NULL,
  "T_NAME" VARCHAR2(200) NOT NULL,
  "T_RATING" NUMBER(10,2) NOT NULL,
  "P_ID" INT NOT NULL,
  CONSTRAINT "TEST_PK" PRIMARY KEY ("T_ID")
);

CREATE OR REPLACE NONEDITIONABLE TYPE TYPE_OF_TEST AS OBJECT
(
  T_ID INT,
  T_DATE DATE,
  T_NAME VARCHAR2(200),
  T_RATING NUMERIC(10,2)
);

CREATE OR REPLACE NONEDITIONABLE TYPE TYPE_OF_TEST_TABLE AS TABLE OF TYPE_OF_TEST;
^ Oracle > UDF returning a scalar value
CREATE OR REPLACE NONEDITIONABLE FUNCTION GET_TEST_RATING(P_T_ID IN INT) RETURN NUMBER
AS
  RES NUMERIC(10,2);
BEGIN
  SELECT T_RATING INTO RES FROM TESTS WHERE T_ID = P_T_ID;
  RETURN RES;
END GET_TEST_RATING;
Python + cx_Oracle
<query method="get_test_rating(t_id)" ref="select GET_TEST_RATING(?) from dual" />
print(dao.get_test_rating(642))
Go
<query method="get_test_rating(t_id)" ref="select GET_TEST_RATING(?) from dual" />
r := cxDao.get_test_rating(47)
fmt.Println(r)
^ Oracle > UDF returning TABLE

1) How to get single DTO from UDF returning TABLE

CREATE OR REPLACE NONEDITIONABLE FUNCTION GET_TEST(P_T_ID IN INT) RETURN TYPE_OF_TEST_TABLE
AS
  RES TYPE_OF_TEST_TABLE;
BEGIN
  RES := TYPE_OF_TEST_TABLE();
  SELECT TYPE_OF_TEST(T_ID, T_DATE, T_NAME, T_RATING)
    BULK COLLECT INTO RES FROM TESTS WHERE T_ID = P_T_ID;
  RETURN RES;
END GET_TEST;
<query-dto method="get_test(t_id)" dto="Test" ref="select * from GET_TEST(?)" />
Python + cx_Oracle
t = Test()
dao.get_test(642, t)
print(t.t_rating)
Go
t := dao.getTest(642)
print(t.TTRating)

2) How to get result of UDF as a list of DTO:

CREATE OR REPLACE NONEDITIONABLE FUNCTION GET_TESTS_BY_RATING(P_T_RATING IN NUMERIC)
  RETURN TYPE_OF_TEST_TABLE
AS
  RES TYPE_OF_TEST_TABLE;
BEGIN
  RES := TYPE_OF_TEST_TABLE();
  SELECT TYPE_OF_TEST(T_ID, T_DATE, T_NAME, T_RATING)
    BULK COLLECT INTO RES FROM TESTS WHERE T_RATING >= P_T_RATING;
  RETURN RES;
END GET_TESTS_BY_RATING;
<query-dto-list method="get_tests_by_rating(rating)" dto="Test" ref="select * from get_tests_by_rating(?)" />
Python + cx_Oracle
for p in dao.get_tests_by_rating(2):
    # ...
Go
tests := cxDao.getTestsByRating(2)
for _, r := range tests {
    // ...
}
^ Oracle > UDF returning SYS_REFCURSOR
CREATE OR REPLACE FUNCTION GET_RC(P_RATING IN NUMBER) RETURN SYS_REFCURSOR
AS
  my_cursor SYS_REFCURSOR;
BEGIN
  OPEN my_cursor FOR
    SELECT *
    FROM   tests
    WHERE  t_rating >= p_rating
    ORDER BY t_rating;
  RETURN my_cursor;
END GET_RC;
<exec-dml method="get_rc(on_test:Test, p_rating)" ref="BEGIN ?:= GET_RC(?); END;" />
PHP + OCI8
$on_test = function($test) {
    // process DTO
};

$dao->get_rc($on_test, 2);
Java
RecordHandler<Test> on_test = new RecordHandler<Test>() {
    @Override
    public void handle(Test t) throws Exception {
        // process DTO
    }
};

dao.get_rc(on_test, 2);
Python + cx_Oracle
def on_test(test):
    # process DTO

dao.get_rc(on_test, 2)
Go
onTest := func(t *Test) {
    // ...
}
dao.getRc(onTest, 2)
^ Oracle > SYS_REFCURSOR-s as OUT parameters
CREATE OR REPLACE PROCEDURE SP_GET_RS_TEST (P_RATING IN NUMBER, P_RECORDSET OUT SYS_REFCURSOR)
AS
BEGIN
  OPEN P_RECORDSET FOR
    SELECT *
    FROM   TESTS
    WHERE  T_RATING >= P_RATING
    ORDER BY T_RATING;
END SP_GET_RS_TEST;
CREATE OR REPLACE NONEDITIONABLE PROCEDURE SP_2_RC(p_rating IN NUMBER, P_TASKS OUT SYS_REFCURSOR, P_PROJECTS OUT SYS_REFCURSOR)
AS
  rc1 SYS_REFCURSOR;
  rc2 SYS_REFCURSOR;
BEGIN
  OPEN rc1 FOR
    SELECT *
    FROM   Tests
    WHERE t_rating >= p_rating
    ORDER BY t_rating;
  P_TASKS := rc1;
  OPEN rc2 FOR
    SELECT * FROM  projects;
  P_PROJECTS := rc2;
END SP_2_RC;
<exec-dml method="sp_get_rs_test(p_rating, on_test:Test)" ref="begin SP_GET_RS_TEST(?, ?); end;" />
<exec-dml method="sp_2_rc(p_rating, on_test:Test, on_project:Project)" ref="BEGIN SP_2_RC(?, ?, ?); END;"/>
PHP + OCI8
$on_test = function($test) {
    // process DTO
};

$dao->sp_get_rs_test(2, $on_test);

$on_project = function($project) {
    // process DTO $project
};

$dao->sp_2_rc(2, $on_test, $on_project);
Java
RecordHandler<Test> on_test = new RecordHandler<Test>() {
    @Override
    public void handle(Test t) throws Exception {
        // process DTO
    }
};

dao.sp_get_rs_test(2, on_test);

RecordHandler<Project> on_project = new RecordHandler<Project>() {
    @Override
    public void handle(Project project) throws Exception {
        // process DTO project
    }
};

dao.sp_2_rc(2, on_test, on_project);
Python + cx_Oracle
def on_test(test):
    # process DTO

$dao.sp_get_rs_test(2, on_test)

def on_project(project):
    # process DTO project

dao.sp_2_rc(2, on_test, on_project)
Go
onTest := func(t *Test) {
    // ...
}
onProject := func(t *Project) {
    // ...
}
dao.get2Rc(2, onTest, onProject)
^ Oracle > Implicit SYS_REFCURSOR-s

Starting from Oracle 12c1, you can use SYS_REFCURSOR-s implicitly:

CREATE OR REPLACE NONEDITIONABLE PROCEDURE SP_IMPLICIT_RC (P_RATING IN NUMBER)
AS
  rc SYS_REFCURSOR;
BEGIN
  OPEN rc FOR
    SELECT *
    FROM   TESTS
    WHERE  T_RATING >= P_RATING
    ORDER BY T_RATING;
  DBMS_SQL.RETURN_RESULT(rc);
END SP_IMPLICIT_RC;
CREATE OR REPLACE NONEDITIONABLE PROCEDURE SP_IMPLICIT_2_RC (P_P_ID IN NUMBER)
AS
  rc1 SYS_REFCURSOR;
  rc2 SYS_REFCURSOR;
BEGIN
  OPEN rc1 FOR
    SELECT *
    FROM   TESTS
    WHERE  P_ID = P_P_ID
    ORDER BY T_RATING;
  DBMS_SQL.RETURN_RESULT(rc1);
  OPEN rc2 FOR
    SELECT *
    FROM  PROJECTS
    WHERE  P_ID = P_P_ID;
  DBMS_SQL.RETURN_RESULT(rc2);
END SP_IMPLICIT_2_RC;

To fetch implicit SYS_REFCURSOR-s, use the syntax like this:

<exec-dml method="sp_implicit_rc(p_id, [on_test:Test])" ref="begin SP_IMPLICIT_RC(?); end;" />
<exec-dml method="sp_implicit_2_rc(p_id, [on_test:Test, on_project:Project])" ref="begin SP_IMPLICIT_2_RC(?); end;" />
PHP + OCI8
$on_test = function($test) {
    // process DTO
};

$dao->sp_implicit_rc(2, $on_test);

$on_project = function($project) {
    // process DTO
};

$dao->sp_implicit_2_rc(2, $on_test, $on_project);
Java

To use implicit SYS_REFCURSOR in Java, ensure that ojdbc7.jar conforms Oracle 12c1+.

dao.sp_implicit_rc(2, test -> {
    // process DTO
});

dao.sp_implicit_2_rc(2, test -> {
    // process DTO
}, project -> {
    // process DTO
});
Python + cx_Oracle
def on_test(test):
    # process DTO

dao.sp_implicit_rc(2, on_test)

def on_project(project):
    # process DTO

dao.sp_implicit_2_rc(2, on_test, on_project)
Go
onTest := func(test *Test) {
    // process DTO
}
onProject := func(project *Project) {
    // process DTO
}
dao.SpImplicitRc(2, onTest, onProject)

NOTE. Multiple implicit RC are not available yet.

^ Oracle > SP to change some data
CREATE OR REPLACE NONEDITIONABLE PROCEDURE SET_TEST_RATING (P_T_ID IN INT, P_T_RATING IN NUMBER)
AS
BEGIN
  UPDATE TESTS SET T_RATING = P_T_RATING WHERE T_ID = P_T_ID;
END SET_TEST_RATING;
Python + cx_Oracle
<exec-dml method="set_test_rating(t_id, rating)" ref="begin SET_TEST_RATING(?, ?); end;" />
dao.set_test_rating(642, 5)
^ Oracle > OUT and INOUT parameters
create or replace NONEDITIONABLE PROCEDURE SP_TEST_OUT_PARAMS(P_ID IN NUMBER, P_RATING OUT NUMBER) AS
    id number;
BEGIN
    id := P_ID; -- failed while using WHERE t_id = P_ID
    SELECT t_rating INTO P_RATING
    FROM tests
    WHERE t_id = id;
END SP_TEST_OUT_PARAMS;
create or replace PROCEDURE SP_TEST_INOUT_PARAMS(PARAM1 IN OUT NUMBER) AS
BEGIN
  PARAM1 := PARAM1 * 10;
END SP_TEST_INOUT_PARAMS;
<exec-dml method="sp_test_inout_params(res)" ref="begin SP_TEST_INOUT_PARAMS(?); end;"/>
<exec-dml method="sp_test_out_params(t_id, out_rating)" ref="begin SP_TEST_OUT_PARAMS(?, ?); end;"/>
PHP + PDO
// There isn't any PDO::PARAM for decimals / floats, you'll have to use PDO::PARAM_STR.
// https://stackoverflow.com/questions/2718628/pdoparam-for-type-decimal

$res1 = new OutParam(PDO::PARAM_STR, "10");
$dao->sp_test_inout_params($res1);
print_r($res1->value); // OUT is 100

$res2 = new OutParam(PDO::PARAM_STR, "0"); // out parameters must be initialized anyway
$dao->sp_test_out_params(642, $res2);
print_r($res2->value);
PHP + OCI8
$res1 = new OutParam(SQLT_CHR, 10); // IN is 10
$dao->sp_test_inout_params($res1);
print_r($res1->value);

$res2 = new OutParam(); // no need to init OUT param with a value
$dao->sp_test_out_params(642, $res2);
print_r($res2->value);
Java
OutParam in_out_param = new OutParam(OracleTypes.NUMBER, BigDecimal.class, 10); // IN is 10
dao.sp_test_inout_params(in_out_param);
out.println(in_out_param.getValue()); // prints 100

OutParam out_rating = new OutParam(OracleTypes.NUMBER, BigDecimal.class); // no need to init OUT param with a value
dao.sp_test_out_params(642, out_rating);
out.println(out_rating.getValue());
Python + cx_Oracle
res2 = OutParam(int, 10) # IN is 10
dao.sp_test_inout_params(res2)
print(res2.param_value)

res1 = OutParam(float) # no need to init OUT param with a value
dao.sp_test_out_params(642, res1)
print(res1.param_value)
Go
<exec-dml method="SpTestInoutParams(InOutParam inOut)" ref="begin SP_TEST_INOUT_PARAMS(?); end;"/>
<exec-dml method="SpTestOutParams(int64 tId, *float64 outRating)" ref="begin SP_TEST_OUT_PARAMS(?, ?); end;"/>
<exec-dml method="SpTestOutParams2(int64 tId, OutParam outRating)" ref="begin SP_TEST_OUT_PARAMS(?, ?); end;"/>
inOut := 123.0
cxDao.SpTestInoutParams(InOutParam{Dest: &inOut})
fmt.Println(inOut)

var outRating float64
cxDao.SpTestOutParams(47, &outRating)
// cxDao.SpTestOutParams2(47, OutParam{Dest: &outRating}) // This one works too.
fmt.Println(outRating)

^ PostgreSQL

SELECT * FROM get_film ('Al%') vs SELECT get_film ('Al%') http://www.postgresqltutorial.com/plpgsql-function-returns-a-table/

https://stackoverflow.com/questions/18084936/pl-pgsql-functions-how-to-return-a-normal-table-with-multiple-columns-using-an
How To Call PostgreSQL Stored Function Using JDBC http://www.postgresqltutorial.com/postgresql-jdbc/call-postgresql-stored-function/
Can I call a postgres “Procedure” (not “function”) from java using the postgres JDBC driver? https://stackoverflow.com/questions/53633672/can-i-call-a-postgres-procedure-not-function-from-java-using-the-postgres
PL/pgSQL Function That Returns A Table http://www.postgresqltutorial.com/plpgsql-function-returns-a-table/
PostgreSQL - How to Return a Result Set from a Stored Procedure http://www.sqlines.com/postgresql/how-to/return_result_set_from_stored_procedure
How to handle postgres stored procedure out parameter in python https://stackoverflow.com/questions/29544050/how-to-handle-postgres-stored-procedure-out-parameter-in-python
Returning Cursors (FETCH ALL FROM a) https://www.postgresql.org/docs/9.5/plpgsql-cursors.html
^ Notes

NOTE 1. Both stored procedures and user-defined functions are created with CREATE FUNCTION statement in PostgreSQL.

NOTE 2. PostgreSQL JDBC Driver is able to detect the types of SQL parameters.

^ Prerequisites for testing

DDL of data table used in PostgreSQL examples below:

CREATE TABLE IF NOT EXISTS public.projects
(
    p_id serial NOT NULL,
    p_name character varying(200),
    CONSTRAINT projects_pkey PRIMARY KEY (p_id)
);

CREATE TABLE IF NOT EXISTS public.tests
(
    t_id serial NOT NULL,
    t_date timestamp without time zone NOT NULL,
    t_name character varying(200),
    t_rating numeric(10,2) NOT NULL,
    p_id integer NOT NULL,
    CONSTRAINT tests_pkey PRIMARY KEY (t_id)
);
^ PostgreSQL > UDF returning a scalar value
<query method="get_test_rating(t_id)" return-type="java.math.BigDecimal" ref="select get_test_rating(?)" />
CREATE OR REPLACE FUNCTION public.get_test_rating(p_t_id integer)
    RETURNS numeric
    LANGUAGE 'plpgsql'
AS $BODY$DECLARE
  res NUMERIC;
BEGIN
  select t_rating into res from tests where t_id = p_t_id;
  RETURN res;
END;$BODY$;
Python
t = Test()
dao.get_test(642, t)
print(t.t_rating)
Go
t := dao.getTest(642)
print(t.TTRating)
^ PostgreSQL > UDF returning TABLE
CREATE OR REPLACE FUNCTION public.get_tests_by_rating(p_t_rating numeric)
    RETURNS TABLE (r_id integer, r_date date, r_name character varying, r_rating numeric)
    LANGUAGE 'plpgsql'
AS $BODY$
DECLARE
    var_r record;
BEGIN
   FOR var_r IN(SELECT t_id, t_date, t_name, t_rating FROM tests WHERE t_rating >= p_t_rating)
   LOOP
        r_id := var_r.t_id;
        r_date := var_r.t_date;
        r_name := var_r.t_name;
        r_rating := var_r.t_rating;
        RETURN NEXT;
   END LOOP;
END; $BODY$;
<dto-class name="Test3" ref="select * from get_tests_by_rating(?)" />
<query-dto-list method="get_tests_by_rating(t_rating)" dto="Test3" ref="select * from get_tests_by_rating(?)" />
PHP
foreach ($dao->get_tests_by_rating(2) as $t) {
    // ...
}
Java
for (Test3 t : dao.get_tests_by_rating(new BigDecimal(2))) {
    // ...
}
Python
for p in dao.get_tests_by_rating(2):
    # ...
Go
tests := spDao.get_tests_by_rating_table(2)
for _, r := range tests {
    // ...
}
^ PostgreSQL > UDF returning SETOF TABLE
CREATE OR REPLACE FUNCTION public.get_tests_setof_table(p_rating numeric) RETURNS SETOF tests
  LANGUAGE 'plpgsql'
AS $BODY$
DECLARE
  r record;
BEGIN
  for r in SELECT t_id, t_date, concat('1. ', t_name), t_rating, p_id FROM tests WHERE t_rating >= p_rating order by t_rating loop
    return next r;
  end loop;
  for r in SELECT t_id, t_date, concat('2. ', t_name), t_rating, p_id FROM tests WHERE t_rating < p_rating order by t_rating loop
    return next r;
  end loop;
  return;
END; $BODY$;
<query-dto-list method="get_tests_setof_table(t_rating)" dto="Test" ref="select * from get_tests_setof_table(?)" />
PHP
foreach ($dao->get_tests_setof_table(2) as $t) {
    // process ...
}
Java
for (Test t : dao.get_tests_setof_table(new BigDecimal(2))) {
    // process ...
}
Python
for p in dao.get_tests_setof_table(2):
    # process ...
Go
tests4 := spDao.getTestsSetOfTable(3)
for _, r := range tests4 {
    // ...
}
^ PostgreSQL > UDF returning REFCURSOR
CREATE OR REPLACE FUNCTION public.get_tests_by_rating_rc(p_rating numeric) RETURNS REFCURSOR
  LANGUAGE 'plpgsql'
AS $BODY$
DECLARE
  ref REFCURSOR;
BEGIN
  OPEN ref FOR SELECT t_id, p_id, t_date, t_name, t_rating
  FROM tests WHERE t_rating >= p_rating;
  RETURN ref;
END;$BODY$;

NOTE 1. To call such UDF, you need transactions.

NOTE 2. You cannot create something like this

CREATE FUNCTION public.get_rc_and_out_param(IN p_rating numeric, OUT p_avg_rating NUMERIC) RETURNS REFCURSOR
    ...

or this

CREATE FUNCTION public.get_rc_and_out_param(IN p_rating numeric, INOUT p_avg_rating NUMERIC) RETURNS REFCURSOR
    ...

because of ERROR: function result type must be numeric because of OUT parameters.

PHP
<query method="get_tests_by_rating_rc(rating)" ref="select * from get_tests_by_rating_rc(?)" />
<query-dto-list method="get_tests()" external-sql="true" dto="Test" ref="" />
$ds->beginTransaction(); // ensure transaction
// ...
$cursor = $dao->get_tests_by_rating_rc(3);
foreach ($dao->get_tests($ds->pg_fetch(cursor))) as $tt) {
    // ...
}
Java
<query-dto-list method="get_tests_by_rating_rc(t_rating)" dto="Test" ref="select * from get_tests_by_rating_rc(?)" />
// ensure transaction
for (Test t : dao.get_tests_by_rating_rc(new BigDecimal(1))) {
    // ...
}
Python
<query method="get_tests_by_rating_rc(rating)" ref="select * from get_tests_by_rating_rc(?)" />
<query-dto-list method="get_tests()" external-sql="true" dto="Test" ref="" />
# ensure transaction
cursor = dao.get_tests_by_rating_rc(4)
for p in dao.get_tests(ds.pg_fetch(cursor)):
    # ...
Go
<query method="getTestsByRatingRc(rating)" ref="select * from get_tests_by_rating_rc(?)" />
<query-dto-list method="getTests()" external-sql="true" dto="Test" ref="" />
ds.begin() // ensure transaction
defer ds.commit()
// ...
cursor := spDao.getTestsByRatingRc(2)
tests := spDao.getTests(ds.pgFetch(cursor))
for _, t := range tests {
    // ...
}
^ PostgreSQL > UDF returning SETOF REFCURSOR

NOTE. To call such UDF, you need transactions.

CREATE OR REPLACE FUNCTION public.get_tests_multiple(p_rating integer)
    RETURNS SETOF REFCURSOR 
    LANGUAGE 'plpgsql'
AS $BODY$DECLARE
    ref1 REFCURSOR; 
    ref2 REFCURSOR;                             
BEGIN
    OPEN ref1 FOR SELECT *, 1 as sign FROM tests WHERE t_rating >= p_rating
    ORDER by t_rating;
    RETURN NEXT ref1;                                                                            
    OPEN ref2 FOR SELECT *, 2 as sign FROM tests WHERE t_rating < p_rating
    ORDER by t_rating;
    RETURN NEXT ref2;                                                                              
END;$BODY$;
PHP
<dto-class name="Test5" ref="tests" >
    <field java-type="Integer" column="sign" />
</dto-class/>
<query-list method="get_tests_multiple(p_rating)" ref="select * from get_tests_multiple(?)" />
<query-dto-list dto="Test5" ref="" external-sql="true" method="get_tests()" />
// ensure transaction
$cursors = $dao->get_tests_multiple(3);
foreach ($dao->get_tests($ds->pg_fetch($cursors[0]) as $tt) {
    // ...
}
foreach ($dao->get_tests(ds.pg_fetch($cursors[1]) as $tt) {
    // ...
}
Java

Problem 1. This line

<query-list method="get_tests_multiple(p_rating)" ref="select * from get_tests_multiple(?)" />

produces this

public List<java.sql.ResultSet> get_tests_multiple(Integer p_rating) throws Exception {
    String sql = "select * from get_tests_multiple(?)";
    return ds.queryList(java.sql.ResultSet.class, sql, p_rating);
}

and you need to deal with JDBC directly.

Problem 2. With this,

<dto-class name="Test5" ref="tests" >
    <field java-type="Integer" column="sign" />
</dto-class/>
<query-dto-list method="get_tests_multiple(p_rating)" dto="Test5" ref="select * from get_tests_multiple(?)" />

you obtain all Result-Sets in single list:

for (Test5 t : dao.get_tests_multiple(3)) {
    // ...
}

Workaround. If you need separate lists (with even different types of DTO), look towards named REFCURSOR-s: http://www.sqlines.com/postgresql/how-to/return_result_set_from_stored_procedure

CREATE FUNCTION public.get_set_of_named_ref_cursors(IN p_rating numeric, IN p_ref_1 refcursor, IN p_ref_2 refcursor)
    RETURNS SETOF REFCURSOR
    LANGUAGE 'plpgsql'
AS $BODY$    BEGIN
    OPEN p_ref_1 FOR SELECT *, 1 as sign1 FROM tests WHERE t_rating <= p_rating
    ORDER BY t_rating;
    RETURN NEXT p_ref_1;
    OPEN p_ref_2 FOR SELECT *, 2 as sign2 FROM tests WHERE t_rating > p_rating
    ORDER BY t_rating;
    RETURN NEXT p_ref_2;
END$BODY$;
<dto-class name="Test1" ref="tests" >
    <field java-type="Integer" column="sign1" />
</dto-class/>
<dto-class name="Test2" ref="tests" >
    <field java-type="Integer" column="sign2" />
</dto-class/>
<query method="get_set_of_named_ref_cursors(p_rating)" ref="select get_set_of_named_ref_cursors(?, 'p_ref_1', 'p_ref_2');" return-type="Void" />
<query-dto-list dto="Test1" ref="fetch all from ref_1" method="fetch_ref_1()" />
<query-dto-list dto="Test2" ref="fetch all from ref_2" method="fetch_ref_2()" />

NOTE. ^^ Ensure return-type="Void" to prevent processing of ResultSet.

// ensure transaction
dao.get_set_of_named_ref_cursors(new BigDecimal(3));
for (Test1 t : dao.fetch_ref_1()) {
    // ...
}
for (Test2 t : dao.fetch_ref_2()) {
    // ...
}
Python
<query-list method="get_tests_multiple(p_rating)" ref="select * from get_tests_multiple(?)" />
<query-dto-list dto="Test5" ref="" external-sql="true" method="get_tests()" />
# ensure transaction
cursors = dao.get_tests_multiple(3)
for t5 in dao.get_tests(ds.pg_fetch(cursors[0])):
    # ...
for t5 in dao.get_tests(ds.pg_fetch(cursors[1])):
    # ...
Go
<query-list method="getTestsMultiple(p_rating)" ref="select * from get_tests_multiple(?)" />
<query-dto-list dto="Test5" ref="" external-sql="true" method="getTests()" />
ds.begin() // begin transaction to use ref-cursors
defer ds.commit()
// ...
cursors := spDao.getTestsMultiple(2)
tests1 := spDao.getTests(ds.pgFetch(cursors[0]))
for _, t := range tests1 {
    // ...
}
tests2 := spDao.getTests(ds.pgFetch(cursors[1]))
for _, t := range tests2 {
    // ...
}
^ PostgreSQL > REFCURSOR-s as INOUT parameters
CREATE OR REPLACE PROCEDURE public.sp_out_ref_cursor(p_rating NUMERIC, INOUT p_ref REFCURSOR)
LANGUAGE 'plpgsql'
AS $BODY$ BEGIN
    OPEN p_ref FOR SELECT * FROM tests WHERE t_rating >= p_rating
    ORDER BY t_rating;
END$BODY$;
<exec-dml method="sp_out_ref_cursor(p_rating)" ref="CALL sp_out_ref_cursor(?, 'ref1')" />
<query-dto-list dto="Test" ref="fetch all from ref1" method="fetch_out_ref_cursor()" />

NOTE 1. ^^ Ensure no {} in SQL.

NOTE 2. To call such UDF, you need transactions.

PHP
$dao->sp_out_ref_cursor(3);
foreach ($dao->fetch_out_ref_cursor() as $tt) {
    // ...
}
Java
dao.sp_out_ref_cursor(new BigDecimal(3));
for (Test t : dao.fetch_out_ref_cursor()) {
    // ...
}
Python
dao.sp_out_ref_cursor(3)
for t in dao.fetch_out_ref_cursor():
    # ...
Go
dao.spOutRefCursor(3)
for _, r := range spDao.fetchOutRefCursor() {
    // ...
}
^ PostgreSQL > SP to change some data
<exec-dml method="set_test_rating(t_id, t_rating)" ref="call set_test_rating(?, ?)" />
CREATE OR REPLACE PROCEDURE public.set_test_rating(
  p_t_id integer,
  p_t_rating numeric)
  LANGUAGE 'plpgsql'
AS $BODY$BEGIN
  update tests set t_rating = p_t_rating where t_id = p_t_id; 
END;$BODY$;
^ PostgreSQL > OUT and INOUT parameters
CREATE OR REPLACE PROCEDURE public.sp_test_in_out_param(INOUT res int)
LANGUAGE 'plpgsql'
AS $BODY$begin
    res := res * 10;
end;$BODY$;
<exec-dml method="sp_test_in_out_param(Object res)" ref="call sp_test_in_out_param(?)" />

^^ 1) No {} in SQL. 2) Redefine the type of res to Object for Java.

CREATE OR REPLACE PROCEDURE public.sp_test_out_string_param(INOUT res CHARACTER VARYING)
LANGUAGE 'plpgsql'
AS $BODY$begin
    res := 'Hello from sp_test_out_string_param!';
end$BODY$;
<exec-dml method="sp_test_out_string_param(Object res)" ref="call sp_test_out_string_param(?)" />

^^ 1) No {} in SQL. 2) Redefine the type of res to Object for Java.

NOTE 1. You cannot create something like this

CREATE OR REPLACE PROCEDURE public.sp_out_ref_cursor(p_rating numeric, INOUT p_ref REFCURSOR, OUT p_avg NUMERIC)

because of 'ERROR: procedures cannot have OUT arguments. HINT: INOUT arguments are permitted.'.

This one is OK:

CREATE OR REPLACE PROCEDURE public.sp_out_ref_cursor2(p_rating NUMERIC, INOUT p_ref REFCURSOR, INOUT p_avg NUMERIC)
LANGUAGE 'plpgsql'
AS $BODY$ BEGIN
    OPEN p_ref FOR SELECT * FROM tests WHERE t_rating >= p_rating
    ORDER BY t_rating;
    
    SELECT AVG(t_rating) INTO p_avg FROM tests WHERE t_rating >= p_rating;
END$BODY$;
<!-- don't use "exec-dml" with out params /> -->
<!-- <exec-dml method="sp_out_ref_cursor2(p_rating, ref1, p_avg)" ref="CALL sp_out_ref_cursor(?, ?, ?)" /> -->
<query method="sp_out_ref_cursor2(p_rating, ref1, p_avg)" ref="CALL sp_out_ref_cursor(?, ?, ?)" />
<query-dto-list dto="Test" ref="" external-sql="true" method="fetch_out_ref_cursor()" />

NOTE 2. Trying to use RETURNS REFCURSOR with OUT/INOUT parameters produces 'ERROR: function result type must be numeric because of OUT parameters':

CREATE FUNCTION public.get_rc_and_out_param(IN p_rating numeric, OUT p_avg_rating NUMERIC) RETURNS REFCURSOR
    ...
CREATE FUNCTION public.get_rc_and_out_param(IN p_rating numeric, INOUT p_avg_rating NUMERIC) RETURNS REFCURSOR
    ...
PHP

(starting from DataStore.php + PDO + PostgreSQL v.1.110)

$res1 = new OutParam(PDO::PARAM_INT, 123);
$dao->sp_test_in_out_param($res1);
print_r($res1->value);

$res2 = new OutParam(PDO::PARAM_STR);
$dao->sp_test_out_string_param($res2);
print_r($res2->value);

// There isn't any PDO::PARAM for decimals / floats, you'll have to use PDO::PARAM_STR.
// https://stackoverflow.com/questions/2718628/pdoparam-for-type-decimal
$avg = new OutParam(PDO::PARAM_STR);
$dao->sp_out_ref_cursor2(3, new InOutParam(PDO::PARAM_STR, 'ref1'), $avg);
foreach ($dao->fetch_out_ref_cursor2('fetch all from ref1') as $tt) {
    // ...
}
print_r($avg->value);
Java
OutParam res = new OutParam(Types.INTEGER, Integer.class, 10);
dao.sp_test_in_out_param(res);
out.println(res.getValue());

OutParam out_param = new OutParam(Types.VARCHAR, String.class, "");
dao.sp_test_out_string_param(out_param);
System.out.println(out_param.getValue());
Python
inout = OutParam(10)
dao.sp_test_in_out_param(inout)
print(inout.value)

out = OutParam("")
dao.sp_test_out_string_param(out)
print(out.value)

avg = OutParam(0)
dao.sp_out_ref_cursor2(2, OutParam('ref1'), avg)
for task in dao.fetch_out_ref_cursor('fetch all from ref1'):
    # ...
print(avg.value)
Go
<query method="SpTestOutStringParam(*string outStr)" ref="call SpTestOutStringParam(?)"/>
var outStr string
_, err := spDao.SpTestOutStringParam(&outStr)
if err != nil {
    // ...
}
fmt.Println(outStr)
<query method="SpTestInOutParam(*int64 value)" ref="call SpTestInOutParam(?)"/>
inoutInt64 := int64(123)
_, err := spDao.SpTestInOutParam(&inoutInt64)
if err != nil {
    // ...
}
fmt.Println(inoutInt64)

Alternatively, use DTO (preferable because of auto-detection of types/names):

<dto-class name="sqlx-OutParams" ref="call sp_test_out_string_param('')"/>
<query-dto dto="sqlx-OutParams" method="SpTestOutStringParam2()"/>
res, err := spDao.SpTestOutStringParam2(txCtx)
if err != nil {
    // ...
}
fmt.Println(res.Res)

^ SQL Server

SQL Server Table-valued Functions https://www.sqlservertutorial.net/sql-server-user-defined-functions/sql-server-table-valued-functions/
Google: sql server stored procedure return table ==> SQL Server: Returning TABLE/VALUE From A Stored Procedure – Querychat https://www.got-it.ai/solutions/sqlquerychat/sql-help/data-query/sql-server-returning-table-value-from-a-stored-procedure/
PHP: Example Application (PDO_SQLSRV Driver) https://docs.microsoft.com/en-us/sql/connect/php/example-application-pdo-sqlsrv-driver?view=sql-server-ver15
Python: Calling Stored Procedures https://github.com/mkleehammer/pyodbc/wiki/Calling-Stored-Procedures
^ SQL Server > UDF returning a scalar value
<query method="ufnLeadingZeros(value)" ref="select dbo.ufnLeadingZeros(?)" />
ALTER FUNCTION [dbo].[ufnLeadingZeros](@Value int)
RETURNS varchar(8)
WITH SCHEMABINDING 
AS 
BEGIN
    DECLARE @ReturnValue varchar(8);
    SET @ReturnValue = CONVERT(varchar(8), @Value);
    SET @ReturnValue = REPLICATE('0', 8 - DATALENGTH(@ReturnValue)) + @ReturnValue;
    RETURN (@ReturnValue);
END;
^ SQL Server > UDF returning a list of strings
<query-list method="ufnDepartmentGroupNames" ref="select * from HumanResources.ufnDepartmentGroupNames()" />

NOTE. Ensure '()' in the end of SQL statement for UDF without parameters.

ALTER FUNCTION [HumanResources].[ufnDepartmentGroupNames] ()
RETURNS TABLE
AS
    RETURN SELECT DISTINCT GroupName 
    FROM HumanResources.Department
^ SQL Server > UDF that RETURNS TABLE
<dto-class name="Department2" ref="select * from HumanResources.ufnDepartmentsByGroup(?)" />

NOTE. With SQL Server, select from UDF in declarations of DTO classes is OK.

<query-dto-list method="ufnDepartmentsByGroup(groupName)" dto="Department2"
    ref="select * from HumanResources.ufnDepartmentsByGroup(?)" />

NOTE. Ensure '()' in the end of SQL statement for UDF without parameters.

ALTER FUNCTION [HumanResources].[ufnDepartmentsByGroup] (@GroupName varchar(100))
RETURNS TABLE
AS
    RETURN SELECT DepartmentID, Name 
    FROM HumanResources.Department 
    WHERE GroupName = @GroupName
^ SQL Server > SP returning Result-Set
ALTER PROCEDURE [HumanResources].[uspDepartments]
AS
  SELECT DepartmentID, Name, GroupName
  FROM HumanResources.Department ORDER BY Name

1) How to call SP and obtain a list of 'Integer':

<query-list method="get_department_ids()" ref="{call HumanResources.uspDepartments()}" />

2) How to call SP to obtain a list of DTO:

<query-dto-list method="get_departments()" dto="Department" ref="{call HumanResources.uspDepartments()}" />

Syntax for Go + SQL Server (github.com/denisenkom/go-mssqldb) differs:

<query-dto-list method="get_departments()" dto="Department" ref="exec HumanResources.uspDepartments" />
^ SQL Server > SP to change some data
<exec-dml method="uspUpdateEmployeePersonalInfo(BusinessEntityID, NationalIDNumber, BirthDate, MaritalStatus, Gender)"
    ref="{CALL HumanResources.uspUpdateEmployeePersonalInfo(?, ?, ?, ?, ?)}" />

^^ Ensure enclosing {} for 'CALL' statement.

Syntax for Go + SQL Server (github.com/denisenkom/go-mssqldb) differs:

<exec-dml method="uspUpdateEmployeePersonalInfo(BusinessEntityID, NationalIDNumber, BirthDate, MaritalStatus, Gender)"
    ref="exec HumanResources.uspUpdateEmployeePersonalInfo ?, ?, ?, ?, ?" />
ALTER PROCEDURE [HumanResources].[uspUpdateEmployeePersonalInfo]
    @BusinessEntityID [int], @NationalIDNumber [nvarchar](15), @BirthDate [datetime], @MaritalStatus [nchar](1), @Gender [nchar](1)
WITH EXECUTE AS CALLER
AS
BEGIN
    SET NOCOUNT ON;
    BEGIN TRY
        UPDATE [HumanResources].[Employee] 
        SET [NationalIDNumber] = @NationalIDNumber, [BirthDate] = @BirthDate, [MaritalStatus] = @MaritalStatus, [Gender] = @Gender 
        WHERE [BusinessEntityID] = @BusinessEntityID;
    END TRY
    BEGIN CATCH
        EXECUTE [dbo].[uspLogError];
    END CATCH;
END;
^ SQL Server > SP with Return-Value
<query method="test_sp_return_value" ref="
DECLARE @rv int;
EXEC @rv = [dbo].[test_sp_return_value];
SELECT @rv AS return_value;"/>
ALTER PROCEDURE [dbo].test_sp_return_value
AS
BEGIN
  SET NOCOUNT ON;
  RETURN 123;
END
^ SQL Server > OUT and INOUT parameters
ALTER PROCEDURE [dbo].[sp_test_inout_params]
	@Param1 int out 
AS
BEGIN
	SET NOCOUNT ON;
	SET @Param1 = @Param1 * 10;
END

NOTE. If you declare a parameter as OUTPUT, it acts as both Input and Output.

https://stackoverflow.com/questions/49129536/how-to-declare-input-output-parameters-in-sql-server-stored-procedure-function

PHP
<exec-dml method="sp_test_inout_params(res)" ref="{CALL [dbo].[sp_test_inout_params](?)}" />

NOTES. 1) Use 'exec-dml'. 2) Do use {} in ref.

$res = new OutParam(PDO::PARAM_STR, "10"); // use PDO::PARAM_STR for OUT parameters
$dao->sp_test_inout_params($res);
print_r($res->value);
Java
<exec-dml method="sp_test_inout_params(Object res)" ref="{call dbo.sp_test_inout_params(?)}" />

NOTES. 1) Use 'exec-dml'. 2) Do use {} in ref. 2) Define the type of res as DataStore.OutParam or just as Object.

OutParam res = new OutParam(Types.INTEGER, Integer.class, 10);
dao.sp_test_inout_params(res);
System.out.println(res.getValue());
Python + pyodbc

Use <query... for single out/inout param:

<query method="sp_test_inout_params(inout)" ref="
DECLARE @res int;
SET @res = ?;
EXEC [dbo].[sp_test_inout_params] @res OUT;
SELECT @res;"/>
res = dao.sp_test_inout_params(10)
print(res)

Use <query-list... for multiple out/inout params:

<query-list method="sp_test_out_params2(in_param)" ref="
DECLARE @value int;
DECLARE @name varchar(200);
SET @value = ?;
EXEC [dbo].[sp_test_out_params2] @value OUT, @name OUT;
SELECT @value;
SELECT @name;"/>
op := dao.sp_test_out_params2(123)
print(f"value={op[0]}\tname={op[1]}")
Go

Use <query... for single out/inout param:

<query method="spTestInoutParams(inout)" ref="
DECLARE @res int;
SET @res = ?;
EXEC [dbo].[sp_test_inout_params] @res OUT;
SELECT @res;"/>
res := spDao.spTestInoutParams(123)
fmt.Println(res)

For multiple out/inout params:

  1. use <query-list...
  2. if the output types are variable, define return-type="interface{}"
  3. use multiple SELECT
<query-list method="spTestInoutParams2(inParam)" return-type="interface{}" ref="
DECLARE @value int;
DECLARE @name varchar(200);
SET @value = ?;
EXEC [dbo].[sp_test_out_params2] @value OUT, @name OUT;
SELECT @value;
SELECT @name;"/>

Alternatively:

  1. use <query...
  2. if the output types are variable, define return-type="[]interface{}"
  3. use single SELECT
<query method="spTestInoutParams2(inParam)" return-type="[]interface{}" ref="
DECLARE @value int;
DECLARE @name varchar(200);
SET @value = ?;
EXEC [dbo].[sp_test_out_params2] @value OUT, @name OUT;
SELECT @value, @name;"/>
outs := spDao.spTestInoutParams2(123)
fmt.Println(outs)

(Also, it is possible to use something like <dto-class name="MyOutParams" ref=""... + <query-dto dto="MyOutParams"... + labels for fetched variables: SELECT @value as value; @name as name;).

^ Top