Search code examples
javaandroiddatabasejdbcmariadb

PatternSyntaxException when connecting to Database (Kotlin)


I want to access a MariaDB database on a server inside my network.
For that I set up a JDBC-Connector in my kotlin project.
(I am working on an android app using Android Studio).

That is my code so far:

class Database {

    fun connect(){
            val jdbcDriver = "org.mariadb.jdbc.Driver"
            val jdbcURL = "jdbc:mariadb://192.168.178.66:3306/test"

            Class.forName(jdbcDriver)

            val password = "CDhkv7AD/OkRDrgv"

            val connection = DriverManager.getConnection(jdbcURL, "test", password)
    }
}

But when trying to connect, following line throws following exception:

val connection = DriverManager.getConnection(jdbcURL, "test", password)
java.lang.ExceptionInInitializerError
    at org.mariadb.jdbc.Driver.connect(Driver.java:70)
    at org.mariadb.jdbc.Driver.connect(Driver.java:95)
    at org.mariadb.jdbc.Driver.connect(Driver.java:26)
    at java.sql.DriverManager.getConnection(DriverManager.java:580)
    at java.sql.DriverManager.getConnection(DriverManager.java:218)
    at de.krabimannbardo.test.Database.connect(Database.kt:22)
    at de.krabimannbardo.test.MainActivity$onCreate$1.invokeSuspend(MainActivity.kt:28)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
    at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
    at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:42)
    at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
    at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
    at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
    at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
    at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)
    Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@6c8e0ec, Dispatchers.IO]
Caused by: java.util.regex.PatternSyntaxException: Syntax error in regexp pattern near index 185
^(\s*\{)?\s*((\?\s*=)?(\s*/\*([^*]|\*[^/])*\*/)*\s*call(\s*/\*([^*]|\*[^/])*\*/)*\s*((((`[^`]+`)|([^`}]+))\.)?((`[^`]+`)|([^`}(]+)))\s*(\(.*\))?(\s*/\*([^*]|\*[^/])*\*/)*\s*(#.*)?)\s*(}\s*)?$
^
    at com.android.icu.util.regex.PatternNative.compileImpl(Native Method)
    at com.android.icu.util.regex.PatternNative.<init>(PatternNative.java:53)
    at com.android.icu.util.regex.PatternNative.create(PatternNative.java:49)
    at java.util.regex.Pattern.compile(Pattern.java:3527)
    at java.util.regex.Pattern.<init>(Pattern.java:1413)
    at java.util.regex.Pattern.compile(Pattern.java:941)
    at org.mariadb.jdbc.Connection.<clinit>(Connection.java:32)
    ... 15 more

When I try to connect with another password or username my access gets successfully denied.
I think this validates that a connection to the Database is successfully established because I only get the above mentioned Exception when using the correct login information. (Or is this assumption wrong?)

Do you have any ideas why the PatternSyntaxException is occurring?
Thanks in advance.


Solution

  • I checked the sourcecode of the MariaDB JDBC driver at https://github.com/mariadb-corporation/mariadb-connector-j and it seems that a static variable in the class org.mariadb.jdbc.Connection is initialized with a regex Pattern.

    ^(\s*\{)?\s*((\?\s*=)?(\s*/\*([^*]|\*[^/])*\*/)*\s*call(\s*/\*([^*]|\*[^/])*\*/)*\s*((((`[^`]+`)|([^`}]+))\.)?((`[^`]+`)|([^`}(]+)))\s*(\(.*\))?(\s*/\*([^*]|\*[^/])*\*/)*\s*(#.*)?)\s*(}\s*)?$
    

    The index 185 that is mentioned in your stacktrace is an unescaped } with the meaning to match exactly that character. (It is the last } of that string, so start to search from the end.)

    For other SO posts like java.util.regex.PatternSyntaxException on Android or Regex pattern SyntaxException that are related to regular expressions on Android that contain a closing curly brace, the solutions all include to escape that with a backslash \.

    I also found a statement in the official documentation of Android that a closing curly brace has to be escaped:

    Behavior starting from API level 10 (Android 2.3)

    Starting from Android 2.3 Gingerbread, ICU4C becomes the backend of the regular expression implementation. Android could behave differently compared with other regex implementation, e.g. literal right brace ('}') has to be escaped on Android.

    The escaping of the literal right brace does not make a difference in "desktop Java", it behaves similar with or without the escaping.

    So you found an incompatibility of the MariaDB JDBC driver with Android. You can either try to report an issue with them, or you try to fix the driver by yourself (you will find the place to look for in your stacktrace) or maybe best try to do both in parallel: propose a fix in the opensource project and in the meanwhile use your own updated driver.

    BTW you are right, this error only occurs after the first successful authentication to the server when the Connection class is loaded.