Uploaded image for project: 'MariaDB Connector/J'
  1. MariaDB Connector/J
  2. CONJ-1344

DatabaseMetaData methods do not normalize identifiers when lower_case_table_names=1 on MySQL 8.0

    XMLWordPrintable

Details

    • Bug
    • Status: Closed (View Workflow)
    • Major
    • Resolution: Fixed
    • None
    • 3.5.11, 4.0.0
    • metadata
    • None

    Description

      1. CONJ Issue: DatabaseMetaData methods do not normalize identifiers when lower_case_table_names=1 on MySQL 8.0

      —

        1. Title

      DatabaseMetaData.getColumns() / getPrimaryKeys() fail to return correct results on MySQL 8.0 with lower_case_table_names=1

        1. Environment
      • MariaDB Connector/J 2.7.2
      • MySQL 8.0.46 (official, not MariaDB)
      • lower_case_table_names=1
      • OS: Amazon Linux 2 (EMR)
      • JDK 8
      • DataNucleus RDBMS 4.1.19 (Hive Metastore)
        1. Description

      When MariaDB Connector/J connects to a MySQL 8.0 server configured with `lower_case_table_names=1`, the `DatabaseMetaData` methods (`getColumns()`, `getPrimaryKeys()`, `getTables()`, etc.) do not normalize table/schema name parameters to lowercase before querying `information_schema`.

      On MySQL 8.0 with `lower_case_table_names=1`, all table names are stored as lowercase in the data dictionary and `information_schema`. While the query itself may still match (due to case-insensitive collation on information_schema columns), the *returned metadata column values* (e.g., `TABLE_NAME`, `COLUMN_NAME`) are all lowercase. This causes problems for ORM tools (like DataNucleus/JDO) that perform case-sensitive string comparison between the returned metadata identifiers and their internally-defined mapping names.

        1. Steps to Reproduce

      1. Set up MySQL 8.0 with `lower_case_table_names=1`
      2. Create a table: `CREATE TABLE PARTITION_KEYS (TBL_ID bigint PRIMARY KEY, ...);`
      3. Connect with MariaDB Connector/J 2.7.2
      4. Call `DatabaseMetaData.getColumns(catalog, null, "PARTITION_KEYS", "%")`
      5. Iterate the ResultSet and check `rs.getString("COLUMN_NAME")`

      *Expected*: Column names match the case used in CREATE TABLE or at minimum, the case passed as parameter (e.g., `TBL_ID`)

      *Actual*: Column names are returned as lowercase (`tbl_id`) because MySQL 8.0 with `lower_case_table_names=1` stores identifiers in lowercase in its data dictionary, and the driver does not normalize/map them back.

        1. Impact

      This breaks any framework that relies on case-sensitive matching of metadata column names against ORM mappings:

      • Apache Hive Metastore (DataNucleus) fails with: `Table "partition_keys" has been specified with a primary-key to include column "TBL_ID" but this column is not found in the table.`
      • Potentially affects any JPA/JDO tool using MariaDB Connector/J against MySQL 8.0 with `lower_case_table_names=1`
        1. Root Cause Analysis

      In `MariaDbDatabaseMetaData.java`, the `patternCond()` helper method (line ~625 in 2.7.x) passes table name parameters directly to the SQL query without any case normalization:

      ```java
      private boolean patternCond(
      boolean firstCondition, StringBuilder sb, String columnName, String tableName) {
      if (tableName == null || "%".equals(tableName))

      { return firstCondition; }

      sb.append(firstCondition ? " WHERE " : " AND ")
      .append(columnName)
      .append((tableName.indexOf('%') == -1 && tableName.indexOf('_') == -1) ? "=" : " LIKE ")
      .append("'")
      .append(Utils.escapeString(tableName, true))
      .append("'");
      return false;
      }
      ```

      The connector already reads `@@lower_case_table_names` in `MariaDbConnection.getLowercaseTableNames()` (line ~1617), but this value is ONLY used for `storesLowerCaseIdentifiers()` / `supportsMixedCaseIdentifiers()` capability reporting – it is never applied in the actual metadata query methods.

        1. Suggested Fix

      When `lower_case_table_names >= 1` on the server, normalize the catalog/schema/table name parameters to lowercase (using `Locale.ROOT`) before building the `information_schema` query. This is what MySQL Connector/J does via its `normalizeIdentifierCase()` method:

      ```java
      // MySQL Connector/J approach (for reference)
      String normalizeIdentifierCase(String identifier)

      { if (identifier == null) return null; return storesLowerCaseIdentifiers() ? identifier.toLowerCase(Locale.ROOT) : identifier; }

      ```

      A similar normalization should be applied in MariaDB Connector/J's `patternCond()` and `catalogCond()` methods, or at the entry point of each metadata method.

        1. Affected Methods
      • `getColumns()`
      • `getPrimaryKeys()`
      • `getTables()`
      • `getImportedKeys()`
      • `getExportedKeys()`
      • `getCrossReference()`
      • `getIndexInfo()`
      • `getBestRowIdentifier()`
        1. Workaround

      Replace MariaDB Connector/J with MySQL Connector/J 8.0.33+ when connecting to MySQL 8.0 with `lower_case_table_names=1`.

      Attachments

        Activity

          People

            diego dupin Diego Dupin
            plantegg plantegg ren
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Git Integration

                Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.