xhmz opened a new issue, #17300:
URL: https://github.com/apache/iceberg/issues/17300

   ### Describe the bug
   
   When multiple schemas/databases on the same MySQL instance each have an 
`iceberg_tables` table with different schema versions (V0 vs V1), `JdbcCatalog` 
incorrectly detects the `iceberg_type` column from a **different schema**, 
causing `schemaVersion` to be wrongly set to V1 while the actual table in the 
current connection's schema is V0.
   
   This results in `SQLSyntaxErrorException: Unknown column 'iceberg_type' in 
'where clause'` when creating or loading tables.
   
   ### Root Cause
   
   In `JdbcCatalog.java`, both `updateSchemaIfRequired()` and 
`atomicCreateTable()` call `DatabaseMetaData.getColumns()` / `getTables()` with 
`null` as the catalog parameter:
   
   ```java
   // updateSchemaIfRequired() — line 234
   dbMeta.getColumns(
       null,                              // ← scans ALL schemas on the server
       null,
       JdbcUtil.CATALOG_TABLE_VIEW_NAME,  // "iceberg_tables" — '_' is a LIKE 
wildcard
       JdbcUtil.RECORD_TYPE);             // "iceberg_type"
   
   // atomicCreateTable() — line 171
   dbMeta.getTables(
       null,   // ← scans ALL schemas on the server
       null,
       name,
       null);
   ```
   
   Per JDBC spec, `null` for the catalog parameter means "no limitation" — the 
driver scans **all** schemas/databases on the server. When another schema on 
the same MySQL instance has an `iceberg_tables` table **with** the 
`iceberg_type` column (V1 schema), `getColumns()` returns that column even 
though the current connection's schema has a V0 table (without `iceberg_type`). 
This causes `schemaVersion` to be incorrectly set to `V1`, and subsequent V1 
SQL queries fail with `Unknown column 'iceberg_type'`.
   
   Additionally, `iceberg_tables` contains underscores (`_`), which are 
single-character wildcards in SQL `LIKE` matching, potentially causing further 
false matches.
   
   ### To Reproduce
   
   **Environment:** A single MySQL instance with two schemas:
   - `metaservice_db` — has `iceberg_tables` **with** `iceberg_type` column (V1 
schema)
   - `iceberg_catalog_db` — has `iceberg_tables` **without** `iceberg_type` 
column (V0 schema)
   
   **Flink SQL:**
   ```sql
   create catalog custom_iceberg_jdbc with (
     'type' = 'iceberg',
     'catalog-impl' = 'org.apache.iceberg.jdbc.JdbcCatalog',
     'catalog-name' = 'custom_iceberg_jdbc',
     'uri' = 'jdbc:mysql://host:port/iceberg_catalog_db',
     'jdbc.user' = 'root',
     'jdbc.password' = '***',
     'jdbc.schema-version' = 'V0',
     'warehouse' = 'hdfs://...'
   );
   
   create table if not exists custom_iceberg_jdbc.my_db.my_table (id int, name 
string);
   ```
   
   Even though `jdbc.schema-version=V0` is set, the error still occurs:
   ```
   Caused by: java.sql.SQLSyntaxErrorException: Unknown column 'iceberg_type' 
in 'where clause'
       at 
org.apache.iceberg.jdbc.JdbcUtil.lambda$tableOrView$2(JdbcUtil.java:614)
       at org.apache.iceberg.jdbc.JdbcUtil.tableOrView(JdbcUtil.java:602)
       at org.apache.iceberg.jdbc.JdbcUtil.loadTable(JdbcUtil.java:641)
       at 
org.apache.iceberg.jdbc.JdbcTableOperations.doRefresh(JdbcTableOperations.java:74)
   ```
   
   ### Verification on MySQL
   
   ```sql
   -- Simulating getColumns(null, null, 'iceberg_tables', 'iceberg_type') — 
scans ALL schemas
   SELECT TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME
   FROM information_schema.COLUMNS
   WHERE TABLE_NAME LIKE 'iceberg\_tables' AND COLUMN_NAME LIKE 'iceberg_type';
   -- Result: metaservice_db | iceberg_tables | iceberg_type  ← false positive 
from another schema!
   
   -- Simulating getColumns('iceberg_catalog_db', null, 'iceberg_tables', 
'iceberg_type') — limited to current schema
   SELECT TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME
   FROM information_schema.COLUMNS
   WHERE TABLE_SCHEMA = 'iceberg_catalog_db' AND TABLE_NAME LIKE 
'iceberg\_tables' AND COLUMN_NAME LIKE 'iceberg_type';
   -- Result: (empty)  ← correct, no iceberg_type column in this schema
   
   -- Current schema's iceberg_tables table structure:
   DESCRIBE iceberg_catalog_db.iceberg_tables;
   -- Only 5 columns: catalog_name, table_namespace, table_name, 
metadata_location, previous_metadata_location
   -- No iceberg_type column (V0 schema)
   ```
   
   ### Expected behavior
   
   `JdbcCatalog` should only check for the `iceberg_type` column within the 
schema/database specified in the JDBC connection URL, not across all schemas on 
the server. The `jdbc.schema-version=V0` setting should be respected, and 
`schemaVersion` should remain V0 when the current schema's `iceberg_tables` 
table lacks the `iceberg_type` column.
   
   ### Proposed Fix
   
   Use `conn.getCatalog()` to limit the `getColumns` / `getTables` search scope 
to the current schema, and escape underscores in the table name pattern to 
prevent LIKE wildcard matching:
   
   ```java
   // updateSchemaIfRequired()
   String catalog = conn.getCatalog();
   String escapedTableName = JdbcUtil.CATALOG_TABLE_VIEW_NAME.replace("_", 
"\\_");
   ResultSet typeColumn = dbMeta.getColumns(catalog, null, escapedTableName, 
JdbcUtil.RECORD_TYPE);
   
   // atomicCreateTable()
   String catalog = conn.getCatalog();
   String escapedName = name.replace("_", "\\_");
   ResultSet result = dbMeta.getTables(catalog, null, escapedName, null);
   ```
   
   ### Why existing tests didn't catch this
   
   All existing `JdbcCatalog` tests use **SQLite** (in-memory or file-based). 
SQLite does not have the concept of multiple schemas/databases on the same 
server in the same way MySQL does, so `getColumns(null, null, ...)` in SQLite 
only sees the current database. The bug only manifests with multi-schema 
databases like MySQL or PostgreSQL when multiple schemas coexist on the same 
instance.
   
   ### Impact
   
   This bug affects any deployment where multiple schemas on the same database 
instance have `iceberg_tables` tables with different schema versions. This is 
common in:
   - Shared database instances (e.g., a metaservice schema and user catalog 
schemas coexisting on the same MySQL instance)
   - Multi-tenant environments where different tenants use different schemas on 
the same database server
   
   The same class of bug has been reported in other Iceberg language 
implementations:
   - iceberg-go: #1188
   - iceberg-rust: #2068
   
   ### Environment
   
   - Iceberg version: 1.10.x (also confirmed present on `main` branch as of 
July 2026)
   - Database: MySQL 8.0
   - Compute engine: Flink 1.20
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to