Skip to content

support using mariadb connector with mysql extensions#11402

Merged
clintropolis merged 8 commits intoapache:masterfrom
clintropolis:mysql-driver-classname
Jul 8, 2021
Merged

support using mariadb connector with mysql extensions#11402
clintropolis merged 8 commits intoapache:masterfrom
clintropolis:mysql-driver-classname

Conversation

@clintropolis
Copy link
Copy Markdown
Member

@clintropolis clintropolis commented Jul 1, 2021

Description

This PR adds support for using MariaDB java connector (and by extension database) using the Druid MySQL metadata extension, as well as JDBC connection string uri validation for lookups and SQL ingestion.

For the metadata connector, a new config, druid.metadata.mysql.driver.driverClassName has been added, which can be set to org.mariadb.jdbc.Driver for example to allow use of the MariaDB Connector/J.

I got a bit carried away, and now JDBC connection string uri validation for all supported databases has been moved into druid-core and is performed with reflection, so the logic is no longer duplicated across the lookup JDBC handling and SQL firehose logic and is instead centralized in ConnectionUriUtils.

The Docker integration tests have been modified to accept an additional environment variable, MYSQL_DRIVER_CLASSNAME, and setting it to org.mariadb.jdbc.Driver will kick the test container into a mode where they load the mariadb connector jar instead of mysql jar and use that instead. I duplicated the 'query' integration test to run against mariadb, which at least gives coverage of the metadata connector, but I have tested jdbc lookups and sql ingestion manually as well to ensure that the property validation stuff is functional.

It looked like there are a handful of documentation changes that should be made, which I will address in a follow-up PR if that is acceptable to reviewers.


This PR has:

  • been self-reviewed.
  • added documentation for new or modified features or behaviors.
  • added Javadocs for most classes and all non-trivial methods. Linked related entities via Javadoc links.
  • added or updated version, license, or notice information in licenses.yaml
  • added comments explaining the "why" and the intent of the code wherever would not be obvious for an unfamiliar reader.
  • added unit tests or modified existing tests to cover new code paths, ensuring the threshold for code coverage is met.
  • added integration tests.
  • been tested in a test Druid cluster.

}
}

public static Set<String> tryParseJdbcUriParameters(String connectionUri, boolean allowUnknown)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you add javadocs explaining the fallback to mariaDB?

try {
return tryParseMySqlConnectionUri(connectionUri);
}
catch (ClassNotFoundException notFoundMysql) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are these branches covered by unit tests?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are not currently, trying to think of a good way to test it, i guess i need some different classloaders to model different configurations or something. Any ideas?

Copy link
Copy Markdown
Contributor

@abhishekagarwal87 abhishekagarwal87 Jul 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one way would be to take Class.forName() to a different static method in a different class and use that method here instead. In tests, you could mock the other class and method.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found Mockito.mockStatic which lets me model these branches a bit by just letting me mock the tryParse{x]ConnectionUri methods, so the coverage is a bit better now i think

Copy link
Copy Markdown
Contributor

@maytasm maytasm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Few minor comments

)
{
this.connectorConfig = connectorConfig;
this.driverClassName = driverClassName;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we check if the connectURL and driverClassName match? i.e. we can gracefully fail if we get connectURL=jdbc:mariadb://localhost:3306/test?... and driverClassName=com.mysql.jdbc.Driver

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this I think should be happening in ConnectionUriUtils where if only the mysql driver is loaded then it will fail to parse the mariadb jdbc uri. I did change this though so that if driverClassName is null, and if the uri starts with the mariadb prefix, then it will default to the mariadb driver.

Or you are you imagining a case where both drivers are loaded so that one is used for validation but a separate is used for the actual driver? I guess that could happen, and would certainly be strange, but isn't really a vulnerability I think at least because you would still need access to the Druid configuration to make a more permissive configuration for validation than the actual driver.

Comment thread integration-tests/docker/Dockerfile Outdated
RUN if [ "$MYSQL_DRIVER_CLASSNAME" = "com.mysql.jdbc.Driver" ] ; \
then wget -q "https://repo1.maven.org/maven2/mysql/mysql-connector-java/$MYSQL_VERSION/mysql-connector-java-$MYSQL_VERSION.jar" \
-O /usr/local/druid/lib/mysql-connector-java.jar; \
else wget -q "https://repo1.maven.org/maven2/org/mariadb/jdbc/mariadb-java-client/$MARIA_VERSION/mariadb-java-client-$MARIA_VERSION.jar" \
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be else if and check that the MYSQL_DRIVER_CLASSNAME is set to Maria? But we easier to read/test when we add more driver classes

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed to if/else

@clintropolis clintropolis merged commit 63fcd77 into apache:master Jul 8, 2021
@clintropolis clintropolis deleted the mysql-driver-classname branch July 8, 2021 19:25
jihoonson pushed a commit to jihoonson/druid that referenced this pull request Jul 12, 2021
* support using mariadb connector with mysql extensions

* cleanup and more tests

* fix test

* javadocs, more tests, etc

* style and more test

* more test more better

* missing pom

* more pom
@clintropolis clintropolis added this to the 0.22.0 milestone Aug 12, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants