Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#3269] fix(jdbc-mysql): Solve DatabaseMetaData#getSchema return null cause list tables error on some jdbc 8.x driver #3294

Merged
merged 4 commits into from
May 9, 2024

Conversation

kalencaya
Copy link
Contributor

@kalencaya kalencaya commented May 7, 2024

What changes were proposed in this pull request?

replace DatabaseMetaData#getSchema by DatabaseMetaData#getCatalog and provide a more general way to get tables through jdbc driver

Why are the changes needed?

jdbc driver DatabaseMetaData#getSchema method return null causes list tables failure on some jdbc mysql 8.x driver (mysql-connector-java-8.0.11).

Fix: #3269

Does this PR introduce any user-facing change?

not

How was this patch tested?

(Please test your changes, and provide instructions on how to test it:

  1. If you add a feature or fix a bug, add a test to cover your changes.
  2. If you fix a flaky test, repeat it for many times to prove it works.)

@yuqi1129
Copy link
Contributor

yuqi1129 commented May 7, 2024

@kalencaya
Could you please update your PR description? By the way, is it possible to add some UT/IT regarding the changes and verify if it works?

@kalencaya
Copy link
Contributor Author

@kalencaya Could you please update your PR description? By the way, is it possible to add some UT/IT regarding the changes and verify if it works?

yes

@yuqi1129 yuqi1129 added branch-0.5 need backport Issues that need to backport to another branch labels May 7, 2024
@zhoukangcn
Copy link
Contributor

Is this worked for jdbc-doris?

@kalencaya
Copy link
Contributor Author

Is this worked for jdbc-doris?

yes, works on jdbc-doris

@kalencaya
Copy link
Contributor Author

kalencaya commented May 7, 2024

@kalencaya Could you please update your PR description? By the way, is it possible to add some UT/IT regarding the changes and verify if it works?

I have no idea about UT/IT verify my works.now jdbc-common、jdbc-mysql、jdbc-postgresql、jdbc-doris all have releated IT testing affected code. but issue is caused by a mysql 8.x driver which 8.0.11, and jdbc-mysql IT using 8.0.23 as a test dependency, checking additional mysql driver version is difficult, except just replace 8.0.23 by 8.0.11.

need some suggest @yuqi1129

local development environment build and compileDistribution work well, jdbc-mysql and jdbc-doris using mysql-connector-java-8.0.11.jar

image

@yuqi1129
Copy link
Contributor

yuqi1129 commented May 7, 2024

@kalencaya Could you please update your PR description? By the way, is it possible to add some UT/IT regarding the changes and verify if it works?

I have no idea about UT/IT verify my works.now jdbc-common、jdbc-mysql、jdbc-postgresql、jdbc-doris all have releated IT testing affected code. but issue is caused by a mysql 8.x driver which 8.0.11, and jdbc-mysql IT using 8.0.23 as a test dependency, checking additional mysql driver version is difficult, except just replace 8.0.23 by 8.0.11.

need some suggest @yuqi1129

local development environment build and compileDistribution work well, jdbc-mysql and jdbc-doris using mysql-connector-java-8.0.11.jar

image

You can refer to CatalogMysqlIT and change the version of JDBC-driver to verify if it works in the deploy mode.
image

@kalencaya
Copy link
Contributor Author

@yuqi1129 I have updated releated IT, could you help review this?

@@ -1351,6 +1355,11 @@ void testMySQLSchemaNameCaseSensitive() {
.stream()
.anyMatch(n -> n.equals(tableName)));
}

for (String schema : schemas) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you explain why we need these modifications in the test after your changes?

Copy link
Contributor Author

@kalencaya kalencaya May 8, 2024

Choose a reason for hiding this comment

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

After I had added a IT which CatalogMysqlDriverIT extends CatalogMysqlIT, There is a strange appearance on CatalogMysqlIT#testNameSpec, testSchemaComment, testMySQLSchemaNameCaseSensitive test. All of them run failed caused by database exists exception, because they create a new database for themself test purpose.

Strange thing is that why added CatalogMysqlDriverIT test class affect CatalogMysqlIT, I think they all will run on seperated mysql container for CatalogMysqlIT#startup() method:

  @BeforeAll
  public void startup() throws IOException, SQLException {

    if (!ITUtils.EMBEDDED_TEST_MODE.equals(testMode)) {
      String gravitinoHome = System.getenv("GRAVITINO_HOME");
      Path tmpPath = Paths.get(gravitinoHome, "/catalogs/jdbc-mysql/libs");
      JdbcDriverDownloader.downloadJdbcDriver(mysqlDriverDownloadUrl, tmpPath.toString());
    }

    TEST_DB_NAME = TestDatabaseName.MYSQL_CATALOG_MYSQL_IT;

    if (mysqlImageName.equals("mysql:5.7")) {
      containerSuite.startMySQLVersion5Container(TestDatabaseName.MYSQL_CATALOG_MYSQL_IT);
      MYSQL_CONTAINER = containerSuite.getMySQLVersion5Container();
    } else {
      containerSuite.startMySQLContainer(TEST_DB_NAME);
      MYSQL_CONTAINER = containerSuite.getMySQLContainer();
    }

    ...
  }

I tried some ways and didn't find the indeed reason, so I add some clear clean schema behavior on tests to avoid tests run failed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I checked containerSuite.startMySQLContainer(TEST_DB_NAME);. I have a misunderstood that it didn't start a new container always, so new added CatalogMysqlDriverIT and extends CatalogMysqlIT IT using the same mysql container.

CatalogMysqlIT#testNameSpec, testSchemaComment, testMySQLSchemaNameCaseSensitive test create schema and don't clean them cause database exists exception

Copy link
Contributor

Choose a reason for hiding this comment

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

Dropping the database after the tests won't guarantee success if they are run in parallel. You might be able to confirm that the newly added tests CatalogMysqlDriverIT and CatalogMysqlIT always run in serialization.

Copy link
Contributor Author

@kalencaya kalencaya May 9, 2024

Choose a reason for hiding this comment

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

Dropping the database after the tests won't guarantee success if they are run in parallel. You might be able to confirm that the newly added tests CatalogMysqlDriverIT and CatalogMysqlIT always run in serialization.

not IT run parallel but ITs use the same mysql container.

@Tag("gravitino-docker-it")
@TestInstance(Lifecycle.PER_CLASS)
public class CatalogMysqlIT extends AbstractIT {
  private static final ContainerSuite containerSuite = ContainerSuite.getInstance();
  ...
  private MySQLContainer MYSQL_CONTAINER;
  ...

  @BeforeAll
  public void startup() throws IOException, SQLException {
  ...
    if (mysqlImageName.equals("mysql:5.7")) {
      containerSuite.startMySQLVersion5Container(TestDatabaseName.MYSQL_CATALOG_MYSQL_IT);
      MYSQL_CONTAINER = containerSuite.getMySQLVersion5Container();
    } else {
      containerSuite.startMySQLContainer(TEST_DB_NAME);
      MYSQL_CONTAINER = containerSuite.getMySQLContainer();
    }
  ...
  }
  ...

CatalogMysqlIT and new added CatalogMysqlDriverIT use the same mysql container, CatalogMysqlVersion5IT start a new mysql 5.7 container that's why CatalogMysqlVersion5IT extends CatalogMysqlIT similarly and not affected by database exists exception

      containerSuite.startMySQLContainer(TEST_DB_NAME);
      MYSQL_CONTAINER = containerSuite.getMySQLContainer();

CatalogMysqlIT#stop or CatalogMysqlIT#resetSchema method can't clear every test created schemas, only clear the global schema

public class CatalogMysqlIT extends AbstractIT {

  public String metalakeName = GravitinoITUtils.genRandomName("mysql_it_metalake");
  public String catalogName = GravitinoITUtils.genRandomName("mysql_it_catalog");
  public String schemaName = GravitinoITUtils.genRandomName("mysql_it_schema");
  public String tableName = GravitinoITUtils.genRandomName("mysql_it_table");

  @AfterAll
  public void stop() {
    clearTableAndSchema();
    client.dropMetalake(NameIdentifier.of(metalakeName));
    mysqlService.close();
  }

  @AfterEach
  public void resetSchema() {
    clearTableAndSchema();
    createSchema();
  }

  private void clearTableAndSchema() {
    NameIdentifier[] nameIdentifiers =
        catalog.asTableCatalog().listTables(Namespace.of(metalakeName, catalogName, schemaName));
    for (NameIdentifier nameIdentifier : nameIdentifiers) {
      catalog.asTableCatalog().dropTable(nameIdentifier);
    }
    catalog.asSchemas().dropSchema(NameIdentifier.of(metalakeName, catalogName, schemaName), false);
  }

Copy link
Contributor

Choose a reason for hiding this comment

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

not IT run parallel but ITs use the same mysql container.

I know that they use a shared container, so if they run serialization, dropping the database after each test case should work. If they run parallel, I believe it won't solve the problem completely.

Thread1.          Thread2

create db1.     create db1
drop db1         drop db1  

Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should try to clear schemas created by every test or start a seperate mysql container for every IT.

to clear created schemas when tests finish, add clear behavior on every test last or the @AfterEach method. But @AfterEach method should be aware of what schemas to be cleared, clear behavior added on every test last may be better

Yes, this should be reasonable in any case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

not IT run parallel but ITs use the same mysql container.

I know that they use a shared container, so if they run serialization, dropping the database after each test case should work. If they run parallel, I believe it won't solve the problem completely.

Thread1.          Thread2

create db1.     create db1
drop db1         drop db1  

I have understood what you means, now CatalogMysqlIT and CatalogMysqlDriverIT run parallel and there is probability that database exists exception appears, but serialization will not.

I try to find out how to do this

Copy link
Contributor Author

Choose a reason for hiding this comment

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

junit5 runs serialization default, junit5 support parallel runs and should not be enabled on gravitino.

so clear schemas after tests finish will be ok.

what about your suggest ? @yuqi1129

Copy link
Contributor

Choose a reason for hiding this comment

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

junit5 runs serialization default, junit5 support parallel runs and should not be enabled on gravitino.

so clear schemas after tests finish will be ok.

what about your suggest ? @yuqi1129

Then, the current changes will resolve the problem. I'm okay with it. Let's wait for the CI to succeed.

@kalencaya kalencaya force-pushed the fix/mysql-driver-8 branch 2 times, most recently from 500ca63 to a597a2c Compare May 9, 2024 02:07
@kalencaya kalencaya force-pushed the fix/mysql-driver-8 branch from a597a2c to a855816 Compare May 9, 2024 09:37
Copy link
Contributor

@yuqi1129 yuqi1129 left a comment

Choose a reason for hiding this comment

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

LGTM

@yuqi1129 yuqi1129 changed the title [#3269]fix[jdbc-mysql] solve DatabaseMetaData#getSchema return null cause list tables error on some jdbc 8.x driver [#3269] fix(jdbc-mysql): Solve DatabaseMetaData#getSchema return null cause list tables error on some jdbc 8.x driver May 9, 2024
@yuqi1129 yuqi1129 merged commit bd28288 into apache:main May 9, 2024
22 checks passed
github-actions bot pushed a commit that referenced this pull request May 9, 2024
… cause list tables error on some jdbc 8.x driver (#3294)

<!--
1. Title: [#<issue>] <type>(<scope>): <subject>
   Examples:
     - "[#123] feat(operator): support xxx"
     - "[#233] fix: check null before access result in xxx"
     - "[MINOR] refactor: fix typo in variable name"
     - "[MINOR] docs: fix typo in README"
     - "[#255] test: fix flaky test NameOfTheTest"
   Reference: https://www.conventionalcommits.org/en/v1.0.0/
2. If the PR is unfinished, please mark this PR as draft.
-->

### What changes were proposed in this pull request?

replace `DatabaseMetaData#getSchema` by `DatabaseMetaData#getCatalog`
and provide a more general way to get tables through jdbc driver

### Why are the changes needed?

jdbc driver `DatabaseMetaData#getSchema` method return null causes list
tables failure on some jdbc mysql 8.x driver
(mysql-connector-java-8.0.11).

Fix: #3269

### Does this PR introduce _any_ user-facing change?

not

### How was this patch tested?

(Please test your changes, and provide instructions on how to test it:
1. If you add a feature or fix a bug, add a test to cover your changes.
2. If you fix a flaky test, repeat it for many times to prove it works.)

---------

Co-authored-by: wangqi <[email protected]>
@yuqi1129
Copy link
Contributor

yuqi1129 commented May 9, 2024

@kalencaya
Thanks for your contributions.

diqiu50 pushed a commit to diqiu50/gravitino that referenced this pull request Jun 13, 2024
…n null cause list tables error on some jdbc 8.x driver (apache#3294)

<!--
1. Title: [#<issue>] <type>(<scope>): <subject>
   Examples:
     - "[apache#123] feat(operator): support xxx"
     - "[apache#233] fix: check null before access result in xxx"
     - "[MINOR] refactor: fix typo in variable name"
     - "[MINOR] docs: fix typo in README"
     - "[apache#255] test: fix flaky test NameOfTheTest"
   Reference: https://www.conventionalcommits.org/en/v1.0.0/
2. If the PR is unfinished, please mark this PR as draft.
-->

### What changes were proposed in this pull request?

replace `DatabaseMetaData#getSchema` by `DatabaseMetaData#getCatalog`
and provide a more general way to get tables through jdbc driver

### Why are the changes needed?

jdbc driver `DatabaseMetaData#getSchema` method return null causes list
tables failure on some jdbc mysql 8.x driver
(mysql-connector-java-8.0.11).

Fix: apache#3269

### Does this PR introduce _any_ user-facing change?

not

### How was this patch tested?

(Please test your changes, and provide instructions on how to test it:
1. If you add a feature or fix a bug, add a test to cover your changes.
2. If you fix a flaky test, repeat it for many times to prove it works.)

---------

Co-authored-by: wangqi <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
need backport Issues that need to backport to another branch
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Bug report] jdbc-mysql catalogs failed on mysql 8.x driver
3 participants