| // 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()); |
| } |
| } |
| } |