Zoltán Borók-Nagy created IMPALA-15462:
------------------------------------------

             Summary: Iceberg: one column of a type Impala cannot read 
(GEOMETRY, GEOGRAPHY, TIME, FIXED, TIMESTAMP_NS, UNKNOWN) makes the whole table 
unloadable
                 Key: IMPALA-15462
                 URL: https://issues.apache.org/jira/browse/IMPALA-15462
             Project: IMPALA
          Issue Type: Improvement
          Components: Catalog, Frontend
            Reporter: Zoltán Borók-Nagy


h3. Problem
Impala converts the whole Iceberg schema when it loads a table. If any column 
has an Iceberg type that {{IcebergSchemaConverter.toImpalaType()}} does not 
map, the load fails. Nested struct fields count too. After that, every 
statement on the table fails, even one that never reads the column: {{SELECT 
count(*)}}, a SELECT of other columns, DESCRIBE, SHOW CREATE TABLE, SHOW 
TABLE/COLUMN STATS, SHOW FILES, DESCRIBE HISTORY, metadata tables, COMPUTE 
STATS and CREATE EXTERNAL TABLE. Only SHOW TABLES works. For HMS tables, 
INVALIDATE METADATA and DROP TABLE also succeed. REFRESH reports success only 
once, on a table that was loaded before the change (see below). After a failed 
load, REFRESH returns the cached load error without reloading, even after 
another engine has removed the column. Only INVALIDATE METADATA clears it. 
ALTER TABLE ... DROP COLUMN fails too, so the column cannot be removed from 
Impala. The error names the type but not the column.

On master the unmapped types are GEOMETRY, GEOGRAPHY, TIMESTAMP_NANO 
(timestamp_ns and timestamptz_ns, both run), UNKNOWN (all v3), and TIME and 
FIXED (valid since v1). I verified all six.

Why this matters:
* A schema change made by another engine breaks existing Impala queries. After 
DuckDB added one GEOMETRY column, every Impala query on the table failed (for 
HMS tables, after the next REFRESH).
* IMPALA-15162 will make GEOMETRY load, but not the other five types. Its patch 
(Gerrit 24536 PS19, code reading only) also throws in {{toImpalaType()}} for a 
geometry column whose CRS is not OGC:CRS84, so such tables will still fail to 
load.

h3. Steps to reproduce
DuckDB 1.5.5 (iceberg + spatial extensions), attached to an Iceberg REST 
catalog:
{code:sql}
CREATE TABLE ath.zz.geom (id BIGINT, name VARCHAR, g GEOMETRY) WITH 
('format-version'='3');
INSERT INTO ath.zz.geom VALUES (1, 'a', ST_Point(1, 2)), (2, 'b', ST_Point(3, 
4)), (3, 'c', NULL);
{code}
Impala, with the REST catalog configured through {{--catalog_config_dir}}:
{code:sql}
SELECT count(*) FROM zz.geom;
SELECT id FROM zz.geom;
DESCRIBE zz.geom;
{code}
HMS variant: publish the HadoopTables layout ({{metadata/v1.metadata.json}} + 
{{version-hint.text}}), then run {{CREATE EXTERNAL TABLE ... STORED AS ICEBERG 
LOCATION '...' TBLPROPERTIES('iceberg.catalog'='hadoop.tables')}}.
Schema-change variant: register and query a v3 table {{(id, name)}} (on a v2 
table, adding a GEOMETRY column fails at commit; there, {{ADD COLUMN t TIME}} 
breaks the table the same way). In DuckDB, run {{ALTER TABLE ... ADD COLUMN g 
GEOMETRY}}. Republish the layout for the new metadata file, run REFRESH in 
Impala, then query again.
Other types: empty tables created through the REST API with {{time}} or 
{{fixed\[16\]}} (v2), or with {{timestamp_ns}}, {{timestamptz_ns}}, 
{{geography}}, {{unknown}} or {{struct<x: long, g: geometry>}} (v3).

h3. Expected
The table loads. Statements that do not reference the column work: count(*), 
other columns, predicates on other columns. DESCRIBE lists the column and marks 
its type as unsupported. A statement that references the column, including 
{{SELECT *}}, fails during analysis with a message that names the column and 
its Iceberg type. Writes to the table are rejected.

Impala already does this for HBase ({{FeHBaseTable.java:181-186}}: "We can load 
the metadata but won't be able to select from it."). HMS tables with a type 
Impala parses but does not support, such as DATETIME, also load 
({{FeCatalogUtils.java:78-83}}, {{ScalarType.isSupported()}} :317-319; 
documented in {{AnalyzerTest.java:276-279}}). Verified on master 3d4d47dc30 
with an HMS table {{(id BIGINT, d DATETIME)}}: count(*), SELECT id and DESCRIBE 
work. SELECT d fails in the analyzer ({{SlotRef.java:172-181}}) with 
{{Unsupported type 'DATETIME' in 'd'.}} (5d4b095998fac9e2:d226f1f800000000). 
INSERT fails ({{InsertStmt.java:502-508}}) with {{... because the column 'd' 
has an unsupported type 'DATETIME'.}} (b6480a608e8312f4:54d1e2b800000000). 
COMPUTE STATS skips the column ({{ComputeStatsStmt.java:967-971}}).

h3. Actual (master 3d4d47dc30, RELEASE, docker; REST catalog in hybrid mode)
REST catalog, {{SELECT count(*) FROM zz_jira_geometry.geom}} (query 
df4539d7adb14864:270377a100000000), abridged:
{noformat}
AnalysisException: Failed to load metadata for table: 'zz_jira_geometry.geom'
CAUSED BY: TableLoadingException: Could not load table zz_jira_geometry.geom 
from catalog
CAUSED BY: TException: Every MetaProvider failed with the following exceptions: 
Iceberg REST (http://rest:8181): ...
Caused by: java.lang.IllegalStateException: Error loading Iceberg table 
zz_jira_geometry.geom
Caused by: org.apache.impala.common.ImpalaRuntimeException: Iceberg type 
'GEOMETRY' is not supported in Impala
        at 
org.apache.impala.util.IcebergSchemaConverter.toImpalaType(IcebergSchemaConverter.java:130)
        at 
...IcebergSchemaConverter.convertToHiveSchema(IcebergSchemaConverter.java:142)
        at 
...IcebergMetaProvider.createStorageDescriptor(IcebergMetaProvider.java:227)
Catalogd (URI TODO): ... InconsistentMetadataFetchException: Fetching TABLE 
failed: DB_NOT_FOUND ...
{noformat}
* Same error: {{SELECT id}} a5499332860a7a52:6230cfd600000000, DESCRIBE 
d74978d157aefac9:26251e0400000000, SHOW CREATE TABLE 
e6466d4188b5f1c5:fd825dd400000000, {{geom.snapshots}} 
164976bebaaca411:9e0a672f00000000; on a second copy SHOW TABLE STATS 
5349cee4ce80dbb2, SHOW COLUMN STATS 3a400b6729412d5a, SHOW FILES 
ae446eac6ea07b53, DESCRIBE HISTORY ce44b9534dc0f87f.
* {{geo.trip_v3}}: count(*) e640bebbf68ed2d8:2a94a4fb00000000, the {{p1-xy}} 
query aa41c487e3416d7f:c9426ac200000000; {{geo.trip_v3_hilbert}} 
0f40363e5763f70c:899514f200000000; {{geo.building_v3}} 
af4cbfe9648386b4:6e28afb700000000. The {{p1-xy}} query on {{geo.trip_bridge}} 
(same rows, WKB as {{binary}}) returns cnt=14, sum_key=459188959 
(cd4392972c099afa:c241684800000000). Trino 483 and StarRocks 4.1.4 return the 
same answer on {{geo.trip_v3}}.
* Other types: TIME 6149bceac19da5da:89a4aef500000000, FIXED 
b946ceb98bef8118:8c7796df00000000, TIMESTAMP_NANO 
ac4678f901cd284d:4ffba16300000000 (timestamp_ns) and 
6945d06cc6a0529f:1bd34f9500000000 (timestamptz_ns), GEOGRAPHY 
4e486e1d79f40c99:1c7ef78200000000, UNKNOWN 7345ff425846346d:b749633000000000. 
The struct case (7c4eee4eaf32248e:823aada600000000) says only {{Iceberg type 
'GEOMETRY'}}, with no column or field name.
* HMS, CREATE EXTERNAL TABLE (49482d742e20196c:e9ff080900000000): 
{{ImpalaRuntimeException: Error making 'createTable' RPC to Hive Metastore: 
CAUSED BY: TableLoadingException: Iceberg type 'GEOMETRY' is not supported in 
Impala}}. This is misleading because no HMS RPC failed. The error comes from 
{{IcebergCatalogOpExecutor.populateExternalTableCols()}} 
({{IcebergCatalogOpExecutor.java:130-132}}) and is wrapped at 
{{CatalogOpExecutor.java:4407-4408}}.
* HMS, schema change: after the ADD COLUMN, count(*) still returned 3 from the 
cached metadata (d84da571554ad277:bbd56b7800000000); through the REST catalog 
the same table already failed (aa4cbd9eeee43854:896e11c200000000). REFRESH then 
reported success (c0466540b7caa985:bc25661400000000), because it invalidates 
the table on an IcebergTableLoadingException 
({{CatalogOpExecutor.java:7547-7553}}). The next count(*) failed 
(974adf54cb4e39d8:fc02f34400000000; catalogd: {{IcebergTableLoadingException 
... CAUSED BY: TableLoadingException: Iceberg type 'GEOMETRY' is not supported 
in Impala}}). In a rerun, a second REFRESH failed with the same load error 
(6e4756d5c2cdecbe:220fa5af00000000). After DuckDB inserted a row and dropped 
the column (layout republished), REFRESH still returned the cached error in 1 
ms without reloading ({{CatalogOpExecutor.java:8418-8425}}; 
794839ac448986ad:8569e91c00000000). INVALIDATE METADATA fixed it 
(2b4bb8afe84c3111:e5458c9c00000000; count(*) 60423e89b7fb4a96:a120357800000000 
returned 4). On a second copy, ALTER TABLE ... DROP COLUMN g (6f4ebcf4ca1051fa) 
and COMPUTE STATS (5841545f1791c4ad) failed with the load error; INVALIDATE 
METADATA (524746c0a8aedee8) and DROP TABLE (c74d1db0872eca91) succeeded.

h3. Analysis (master 3d4d47dc30)
* {{IcebergSchemaConverter.toImpalaType()}} throws in its {{default:}} branch 
({{IcebergSchemaConverter.java:129-131}}). {{convertToHiveSchema()}} (:142) and 
{{convertToImpalaSchema()}} (:159) call it for every column at load time: in 
catalogd from {{IcebergTable.loadSchema()}} ({{IcebergTable.java:783-790}}, via 
{{load()}} :533 -> {{loadTableMetadata()}} :558 -> {{loadSchemaFromIceberg()}} 
:770), and for REST tables from {{IcebergMetaProvider.loadTable()}} (:199, 
wrapped at :212-213) and {{LocalIcebergTable.java:109}}. Time travel 
({{IcebergTimeTravelTable.java:124}}), metadata tables 
({{IcebergMetadataTable.java:71}}), partition fields 
({{FeIcebergTable.java:1237}}), equality-delete fields 
({{IcebergEqualityDeleteTable.java:50}}), fields with default values 
({{IcebergScanPlanner.java:1165}}), CTAS ({{IcebergCtasTarget.java:122}}) and 
CREATE EXTERNAL TABLE ({{IcebergCatalogOpExecutor.java:130}}) call it too.
* Impala 4.5.2 has the same {{default:}} throw 
({{IcebergSchemaConverter.java:116-117}}), and there UUID is unmapped too. 
Verified on the apache/impala:4.5.2 docker images (HMS, hadoop.tables). CREATE 
EXTERNAL TABLE of a v2 table with a TIME, FIXED or UUID column fails with 
{{Error making 'createTable' RPC to Hive Metastore: CAUSED BY: 
TableLoadingException: Iceberg type 'TIME' is not supported in Impala}} 
(d64def7424a0718e:041fa42d00000000; FIXED 4f4c0d96def483cf:062d42a700000000, 
UUID 64425d6bcd397a29:faa16a8000000000). A registered v2 table that got a TIME 
column from DuckDB fails to load after REFRESH, with a 6-line error 
(534319ac164af4e4:160748ca00000000), and its DROP COLUMN fails too 
(754d967e597bd146:480bac8200000000). 4.5.2 cannot read v3 tables at all: its 
Iceberg 1.3.1 rejects them with {{IllegalArgumentException: Cannot read 
unsupported version 3}} (bc4a4a38b37f8093:d17eaa7e00000000).
* Suggested fix: when converting an existing Iceberg schema (table load, and 
CREATE EXTERNAL TABLE, which copies it at 
{{IcebergCatalogOpExecutor.java:130}}), but not user-given types in CREATE 
TABLE or ALTER TABLE, map an unmapped Iceberg type to a placeholder instead of 
throwing: {{Type.INVALID}}, as for HBase, or an unsupported ScalarType that 
keeps the Iceberg type string for DESCRIBE and SHOW CREATE TABLE. Give it an 
HMS type string such as {{binary}} (PS19 of IMPALA-15162 stores GEOMETRY as 
binary in HMS). Keep the column in both {{convertToHiveSchema()}} and 
{{convertToImpalaSchema()}}: {{LocalIcebergTable.validateColumns()}} 
({{LocalIcebergTable.java:183-189}}) needs the same column count and names 
(code reading). The reverse conversion (used by CREATE, ALTER and CTAS) must 
reject the placeholder. Make the SlotRef error name the Iceberg type. Reject 
DML that writes data files. Until then, the load error should name the column 
(and struct path) and not claim an HMS RPC failure.
* Fix scope: use the placeholder also for time-travel schemas and metadata 
tables. Time travel to a snapshot written with the column fails even after the 
column is dropped (see Workaround). In Iceberg 1.11 the {{readable_metrics}} of 
{{files}} and {{entries}} has lower_bound/upper_bound fields of the column's 
own type, so {{IcebergMetadataTable.java:71}} would still throw (code reading). 
Partition fields of every spec, old ones included, are converted at load 
({{FeIcebergTable.java:1222}}, :1237), so an identity partition on a TIME, 
FIXED or timestamp_ns column needs the placeholder too. Equality-delete fields 
with such sources can stay unsupported at scan time. For HiveCatalog tables, 
Iceberg 1.11's {{HiveSchemaUtil}} throws on every commit for TIMESTAMP_NANO, 
GEOMETRY, GEOGRAPHY and UNKNOWN (code reading; PS19 patches GEOMETRY and 
GEOGRAPHY), so writes and ALTER TABLE on such tables can still fail.
* Tests: Impala test data has no Iceberg table with these types (git grep; the 
IMPALA-14738 commit deferred the V3-type tables). They can be made with REST 
createTable, as in the repro.

h3. Workaround
None in Impala. ALTER TABLE ... DROP COLUMN fails with the same load error 
(6f4ebcf4ca1051fa:ae17ca1100000000). Dropping the column with another engine 
makes the table load again. After DuckDB {{ALTER TABLE ... DROP COLUMN g}}, the 
REST table loaded at once (97452099defe564c:78798b7c00000000). The HMS table 
needed INVALIDATE METADATA; REFRESH kept returning the cached load error 
(794839ac448986ad:8569e91c00000000). Time travel to a snapshot written with the 
column still fails with {{AnalysisException: Could not create iceberg schema. 
CAUSED BY: ImpalaRuntimeException: Iceberg type 'GEOMETRY' is not supported in 
Impala}} (e34ed00cf978fb01:71d3d1db00000000). Otherwise, keep a copy of the 
table without the unsupported column. The benchmark keeps a v2 "bridge" copy 
with WKB in {{binary}} plus x/y DOUBLE columns. Impala reads that copy, and all 
36 bridge runs executed (34 ok, 2 timed out on {{sb8}}).





--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to