Bug #111107 CallableStatement::getParameterMetaData reports incorrect parameterCount
Submitted: 22 May 2023 15:54 Modified: 15 Dec 2023 23:32
Reporter: Jason Boyer Email Updates:
Status: Closed Impact on me:
None 
Category:Connector / J Severity:S3 (Non-critical)
Version:8.0.33, 8.1.0 OS:Any
Assigned to: CPU Architecture:Any

[22 May 2023 15:54] Jason Boyer
Description:
When getting the parameterCount for a procedure via callableStatement.getParameterMetaData().getParameterCount(), the result is one less that the actual parameter count (i.e. the number of placeholders).

How to repeat:
Here is a JUnit test that demonstrates the error.
This test will fail.

    @Test
    void callStoredProcedure()  {
        try (Connection connection = ds.getConnection()) {
            try (Statement statement = connection.createStatement()) {
                statement.execute("DROP PROCEDURE IF EXISTS test.badParameterCount");
                String definition = """
                        CREATE PROCEDURE test.badParameterCount(a BIGINT, b BIGINT, c BIGINT, d BIGINT)
                        BEGIN
                            SELECT 1;
                        END
                        """;
                statement.execute(definition);
            }
            try (PreparedStatement ps = connection.prepareCall("CALL test.badParameterCount(?,?,null,null)")) {
                ParameterMetaData pmd = ps.getParameterMetaData();
                assertEquals(2, pmd.getParameterCount(), "parameter count");
            }
        } catch (SQLException e) {
            fail(e);
        }
    }

Suggested fix:
In https://github.com/mysql/mysql-connector-j/blob/release/8.0/src/main/user-impl/java/com/my... line 181, there is an if statement that skips adding the first placeholder if it maps to the zeroth parameter. I believe that this should only apply to functions, not procedures.
(See the use of isFunctionCall on line 178.)

So, the if statement should be something along the lines of:

if (localParameterMap[i] != 0 || !this.isFunctionCall) {
[22 May 2023 19:15] Jason Boyer
This only occurs when the query parameter count differs from the metadata parameter account. In the example:
 - the metadata parameter count is 4 because there are four procedure parameters, including the two NULLs.
 - the query parameter count is 2 because there are two occurrences of "?"
If the both counts are the same (i.e. all procedure parameters are specified with placeholders) the the code path leading to this bug is not followed, and it returns the correct number of results.
[18 Aug 2023 14:06] Jason Boyer
This bug is still present in version 8.1.0.
[18 Nov 2023 0:11] Filipe Silva
Hi Jason,

Thanks for you interest in MySQL Connector/J and for taking the time to file this report.

This bug was verified as reported.
[15 Dec 2023 23:32] Daniel So
Posted by developer:
 
Added the following entry to the Connector/J 8.3.0 changelog: 

"ParameterMetaData.getParameterCount() did not report the correct number for a procedure called through a PreparedStatement when not all the procedure parameters were not specified in the query statement."