Details
-
Bug
-
Status: Closed (View Workflow)
-
Major
-
Resolution: Fixed
-
None
-
None
Description
- CONJ Issue: DatabaseMetaData methods do not normalize identifiers when lower_case_table_names=1 on MySQL 8.0
—
-
- Title
DatabaseMetaData.getColumns() / getPrimaryKeys() fail to return correct results on MySQL 8.0 with lower_case_table_names=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)
-
- 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.
-
- 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.
-
- 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`
-
- 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))
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.
-
- 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)
```
A similar normalization should be applied in MariaDB Connector/J's `patternCond()` and `catalogCond()` methods, or at the entry point of each metadata method.
-
- Affected Methods
- `getColumns()`
- `getPrimaryKeys()`
- `getTables()`
- `getImportedKeys()`
- `getExportedKeys()`
- `getCrossReference()`
- `getIndexInfo()`
- `getBestRowIdentifier()`
-
- Workaround
Replace MariaDB Connector/J with MySQL Connector/J 8.0.33+ when connecting to MySQL 8.0 with `lower_case_table_names=1`.