[CONJ-161] invalid callable syntax when function name is quoted with backticks Created: 2015-06-03  Updated: 2016-05-23  Resolved: 2016-05-23

Status: Closed
Project: MariaDB Connector/J
Component/s: Other
Affects Version/s: 1.1.8
Fix Version/s: 1.4.0

Type: Bug Priority: Major
Reporter: Lukas Eder Assignee: Georg Richter
Resolution: Fixed Votes: 0
Labels: None


 Description   

Create the following function:

CREATE FUNCTION f_one ()
  RETURNS INT
BEGIN
  RETURN 1;
END

It's perfectly valid to use backticks to quote the function name in SQL:

select `f_one`()

But via a JDBC CallableStatement, this doesn't work. I'm getting

Caused by: java.sql.SQLSyntaxErrorException: invalid callable syntax
    at org.mariadb.jdbc.MySQLCallableStatement.<init>(MySQLCallableStatement.java:377)
    at org.mariadb.jdbc.MySQLConnection.prepareCall(MySQLConnection.java:181)

This is due to a wrong regular expression:

    static Pattern CALLABLE_STATEMENT_PATTERN =
            Pattern.compile("^\\s*\\{?\\s*(\\?\\s*=)?\\s*call\\s*([\\w.]+)(\\(.*\\))?\\s*}?", Pattern.CASE_INSENSITIVE);

Note, the regex has other issues as well, as the trailing "?", which should probably be a "$"...



 Comments   
Comment by Vladislav Vaintroub [ 2015-06-05 ]

The complain is about backticks, right? Or you are expecting "select" to work as in your example. i.e Connection.prepareCall("select `f_one`()") ?

The documentation http://docs.oracle.com/javase/7/docs/api/java/sql/CallableStatement.html does not allow "selects", there are just 2 forms, with escape syntax, both use "call".

Quotes could be allowed, the docs are not specific on what constitutes a <procedure-name>

Comment by Lukas Eder [ 2015-06-05 ]

This is what I tried, which didn't work:

connection.prepareCall("{ ? = call `f_one` () }");

The JDBC spec reads:

> JDBC drivers may optionally provide support for invoking user-defined or vendor defined functions using the escape syntax for stored procedures.

From §13.4.4: http://download.oracle.com/otn-pub/jcp/jdbc-4_2-mrel2-spec/jdbc4.2-fr-spec.pdf

A workaround is to ignore potential case-sensitivity, but I like to stay on the safe side, usually

Comment by Vladislav Vaintroub [ 2015-06-05 ]

Understood. That part in spec is not about DBMS specific rules for quotes, in my understanding. It is about using functions in place of stored procedures.
"Escape syntax for stored procedures" - sounds to me like JDBC/ODBC escapes, those with curly brackets, in the given context it would mean one of 2 variations of "

{call ...}

"

Comment by Lukas Eder [ 2015-06-05 ]

Well, in any case, the current driver is specs-compliant. On the other hand, I'm not aware of any database that doesn't allow the ordinary name quoting characters also in the JDBC/ODBC escape syntax, as this is the only way to enforce case-sensitivity (in some databases) or functions / procedures with special characters in their names (in all databases). Let me give you another, more obvious example:

CREATE FUNCTION `oop how to call this` ()
RETURNS INTEGER
BEGIN
  RETURN 1;
END

Without supporting backticks, how would you call this function?

Comment by Diego Dupin [ 2016-05-23 ]

This has been correction in 1.4 :
working example

        try (Statement st = sharedConnection.createStatement()) {
            st.execute("DROP FUNCTION IF EXISTS `oop how to call this`");
            st.execute("CREATE FUNCTION `oop how to call this` (param int)\n" +
                    "RETURNS INTEGER\n" +
                    "BEGIN\n" +
                    "  RETURN 1;\n" +
                    "END");
            CallableStatement callableStatement = sharedConnection.prepareCall("{ ? = call `oop how to call this` (?) }");
            callableStatement.registerOutParameter(1, Types.INTEGER);
            callableStatement.setInt(2, 1);
            callableStatement.execute();
            System.out.println(callableStatement.getInt(1));
        }

Generated at Thu Feb 08 03:13:37 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.