blob: b10b3f86ce27b5df8ea4be7528e8fa46694e2732 [file] [log] [blame]
// SPDX-License-Identifier: LGPL-2.1-or-later
// Copyright (c) 2012-2014 Monty Program Ab
// Copyright (c) 2015-2021 MariaDB Corporation Ab
package org.mariadb.jdbc.integration;
import static org.junit.jupiter.api.Assertions.*;
import java.sql.*;
import org.junit.jupiter.api.Assumptions;
import org.junit.jupiter.api.Test;
import org.mariadb.jdbc.CallableParameterMetaData;
import org.mariadb.jdbc.Connection;
import org.mariadb.jdbc.Statement;
public class FunctionTest extends Common {
@Test
public void basicFunction() throws SQLException {
// disabled for mysql : see https://bugs.mysql.com/bug.php?id=108545
Assumptions.assumeTrue(isMariaDBServer());
Statement stmt = sharedConn.createStatement();
stmt.execute("DROP FUNCTION IF EXISTS basic_function");
stmt.execute(
"CREATE FUNCTION basic_function (t1 INT, t2 INT unsigned) RETURNS INT DETERMINISTIC RETURN"
+ " t1 * t2;");
try (CallableStatement callableStatement =
sharedConn.prepareCall("{? = call basic_function(?,?)}")) {
callableStatement.registerOutParameter(1, JDBCType.INTEGER);
callableStatement.setInt(2, 2);
callableStatement.setInt(3, 3);
callableStatement.execute();
assertEquals(6, callableStatement.getInt(1));
callableStatement.clearParameters();
callableStatement.setInt(2, 3);
callableStatement.setInt(3, 3);
callableStatement.execute();
assertEquals(9, callableStatement.getInt(1));
callableStatement.clearParameters();
assertThrowsContains(
SQLTransientConnectionException.class,
() -> callableStatement.execute(),
"Parameter at position 1 is not set");
}
try (CallableStatement callableStatement =
sharedConn.prepareCall("{? = call basic_function(?,?)}")) {
callableStatement.setInt(2, 2);
callableStatement.setInt(3, 3);
callableStatement.execute();
assertEquals(6, callableStatement.getInt(1));
}
}
@Test
public void functionWithoutArg() throws SQLException {
functionWithoutArg(sharedConn);
functionWithoutArg(sharedConnBinary);
}
private void functionWithoutArg(Connection con) throws SQLException {
Statement stmt = con.createStatement();
stmt.execute("DROP FUNCTION IF EXISTS no_arg_function");
stmt.execute("CREATE FUNCTION no_arg_function () RETURNS DOUBLE DETERMINISTIC RETURN RAND();");
try (CallableStatement callableStatement = con.prepareCall("{? = call no_arg_function()}")) {
callableStatement.registerOutParameter(1, JDBCType.DOUBLE);
callableStatement.execute();
callableStatement.getDouble(1);
Common.assertThrowsContains(
SQLException.class,
() -> callableStatement.registerOutParameter(2, JDBCType.DOUBLE),
" wrong parameter index 2");
}
try (CallableStatement callableStatement = con.prepareCall("{? = call no_arg_function()}")) {
callableStatement.execute();
callableStatement.getDouble(1);
}
try (CallableStatement callableStatement = con.prepareCall("{? = call no_arg_function}")) {
callableStatement.execute();
callableStatement.getDouble(1);
}
}
@Test
public void parameterMeta() throws SQLException {
Statement stmt = sharedConn.createStatement();
stmt.execute("DROP FUNCTION IF EXISTS parameter_meta");
stmt.execute("CREATE FUNCTION parameter_meta () RETURNS DOUBLE DETERMINISTIC RETURN RAND();");
try (CallableStatement callableStatement =
sharedConn.prepareCall("{? = call parameter_meta()}")) {
Common.assertThrowsContains(
SQLSyntaxErrorException.class,
() -> callableStatement.registerOutParameter(-1, JDBCType.DOUBLE),
"wrong parameter index");
callableStatement.registerOutParameter(1, JDBCType.DOUBLE);
// XPAND doesn't support I_S.parameters: https://jira.mariadb.org/browse/XPT-267
if (!isXpand()) {
CallableParameterMetaData meta =
(CallableParameterMetaData) callableStatement.getParameterMetaData();
assertEquals(org.mariadb.jdbc.ParameterMetaData.parameterModeOut, meta.getParameterMode(1));
assertNull(meta.getParameterName(1));
}
} finally {
stmt.execute("DROP FUNCTION IF EXISTS parameter_meta");
}
}
@Test
public void functionError() throws SQLException {
functionError(sharedConn);
functionError(sharedConnBinary);
}
private void functionError(Connection con) throws SQLException {
Statement stmt = con.createStatement();
stmt.execute("DROP FUNCTION IF EXISTS no_arg_function");
stmt.execute("CREATE FUNCTION no_arg_function () RETURNS DOUBLE DETERMINISTIC RETURN RAND();");
try (CallableStatement callableStatement = con.prepareCall("{? = call no_arg_function()}")) {
Common.assertThrowsContains(
SQLSyntaxErrorException.class,
() -> callableStatement.registerOutParameter(-1, JDBCType.DOUBLE),
"wrong parameter index");
callableStatement.registerOutParameter(1, JDBCType.DOUBLE);
Common.assertThrowsContains(
SQLSyntaxErrorException.class,
() -> callableStatement.registerOutParameter(-1, JDBCType.DOUBLE),
"wrong parameter index");
callableStatement.registerOutParameter(1, JDBCType.DOUBLE);
Common.assertThrowsContains(
SQLSyntaxErrorException.class,
() -> callableStatement.registerOutParameter(2, JDBCType.DOUBLE),
"wrong parameter index");
callableStatement.execute();
Common.assertThrowsContains(
SQLSyntaxErrorException.class,
() -> callableStatement.registerOutParameter(-1, JDBCType.DOUBLE),
"wrong parameter index");
callableStatement.registerOutParameter(1, JDBCType.DOUBLE);
if (!isXpand()) {
Common.assertThrowsContains(
SQLSyntaxErrorException.class,
() -> callableStatement.registerOutParameter("r", JDBCType.DOUBLE),
"parameter name r not found");
}
Common.assertThrowsContains(
SQLSyntaxErrorException.class,
() -> callableStatement.registerOutParameter(2, JDBCType.DOUBLE),
"wrong parameter index");
}
}
@Test
public void functionToString() throws SQLException {
try (CallableStatement callableStatement =
sharedConn.prepareCall("{? = call basic_function(?,?)}")) {
assertEquals(
"FunctionStatement{sql:'SELECT basic_function(?,?)', parameters:[<OUT>null]}",
callableStatement.toString());
callableStatement.setLong(2, 10L);
callableStatement.setBytes(3, new byte[] {(byte) 'a', (byte) 'b'});
assertEquals(
"FunctionStatement{sql:'SELECT basic_function(?,?)', parameters:[<OUT>null,10,_binary"
+ " 'ab']}",
callableStatement.toString());
}
}
}