morningman opened a new pull request, #69285:
URL: https://github.com/apache/doris/pull/69285

   ### What problem does this PR solve?
   
   Issue Number: None
   
   Related PR: #66032, #68786
   
   Problem Summary:
   
   **In short.** This ports to master the rule branch-4.1 got in #66032 
(`IcebergMetadataOps.resolvePrimitiveTypeForModify`): when `ALTER TABLE ... 
MODIFY COLUMN` restates the type an Iceberg column is read as, the Iceberg type 
stays as it is. On master, every MODIFY COLUMN of an Iceberg BINARY or FIXED 
column, or of such a STRUCT field, ARRAY element or MAP value, fails with 
`Unsupported type for Iceberg: VARBINARY`, so their nullability, comment and 
position cannot be changed at all. After this PR they can.
   
   **Background.** Since #68786, Doris always reads an Iceberg BINARY column as 
`VARBINARY` and a FIXED(n) column as `VARBINARY(n)`. MODIFY COLUMN carries the 
whole column definition, so a statement that only means to change the 
nullability, comment or position of such a column restates that type, for 
example `MODIFY COLUMN payload VARBINARY NULL FIRST`. The nested form (`MODIFY 
COLUMN s.a ...`, `arr.element`, `m.value`) works the same way. The Iceberg 
connector turns the requested type into an Iceberg type before it looks at the 
table (`IcebergSchemaBuilder.buildColumnType`), and then diffs it against the 
current schema. `VARBINARY` has no Iceberg type there: CREATE TABLE and ADD 
COLUMN reject it on purpose, as branch-4.x does, because a Doris `VARBINARY(n)` 
holds up to n bytes and an Iceberg FIXED(n) exactly n.
   
   **The problem, and what it cost.** The type build fails before the connector 
ever looks at the current column, so restating the type fails too:
   
   | Statement (current Iceberg type) | master | this PR |
   |---|---|---|
   | `MODIFY COLUMN payload VARBINARY NULL FIRST` (BINARY) | `Unsupported type 
for Iceberg: VARBINARY` | succeeds, stays BINARY |
   | `MODIFY COLUMN digest VARBINARY(16) NULL COMMENT 'digest'` (required 
FIXED(16)) | same error | succeeds, stays FIXED(16) |
   | `MODIFY COLUMN s.a VARBINARY COMMENT 'bytes'` (STRUCT field BINARY) | same 
error | succeeds, stays BINARY |
   | `MODIFY COLUMN arr.element VARBINARY(4) NULL` (required FIXED(4) element) 
| same error | succeeds, stays FIXED(4) |
   | `MODIFY COLUMN m.value VARBINARY NULL` (required BINARY value) | same 
error | succeeds, stays BINARY |
   | `MODIFY COLUMN payload VARBINARY(16)` (BINARY: not how it is read) | 
`Unsupported type for Iceberg: VARBINARY` | unchanged |
   
   So a column that users read and write as VARBINARY could not be moved, 
commented, or made nullable from Doris; only a comment-only `MODIFY COLUMN ... 
COMMENT '...'` worked, because it carries no type. On branch-4.1 and 
branch-4.2, `IcebergMetadataOps.resolvePrimitiveTypeForModify` keeps the 
current Iceberg type in the first five cases and rejects the last one (`Type 
varbinary(16) is not supported for Iceberg column payload`).
   
   **How this PR fixes it.** When the requested type does not build and it is a 
`VARBINARY`, `IcebergConnectorMetadata` looks up the current type of the target 
field (the same best-effort lookup it already did to rewrite the nested error 
message) and keeps it if that type is read as exactly the requested 
`VARBINARY`, length included (`IcebergTypeMapping.isReadAs`). The schema update 
then sees an unchanged type and applies only the nullability, comment and 
position the statement asks for. This is the same check the Paimon connector 
already makes in `requestedColumnType`. A `VARBINARY` that restates nothing 
(another length, a column or field of another type) still fails with 
`Unsupported type for Iceberg: VARBINARY`, as ADD COLUMN does; any other scalar 
that does not build still fails without loading the table, and a complex type 
still gets the nested error message as before. A STRUCT, ARRAY or MAP type that 
contains `VARBINARY` is rejected by Doris's DDL type check (`STRUCT unsupporte
 d sub-type: varbinary(...)`) before it reaches the connector, on branch-4.x as 
well, so it is unchanged.
   
   **Results.**
   
   - **Regression test**: new 
`external_table_p0/iceberg/test_iceberg_modify_binary_column`. The table is 
created through the REST catalog, since neither Doris nor Spark SQL can declare 
a FIXED column. The suite runs the five statements above, checks with `DESC` 
(comments shown) that the types are unchanged while the position and comments 
changed, checks that the required column, ARRAY element and MAP value reject 
NULL before and accept it after, and compares the rows with what Spark reads. 
It fails at its first MODIFY with the connector before this PR and passes with 
it. Seven related suites pass as well: 
`test_iceberg_schema_change_complex_types`, 
`test_iceberg_nested_schema_evolution_ddl`, 
`test_iceberg_nested_schema_evolution_spark_doris_interop`, 
`iceberg_schema_change_ddl`, `test_iceberg_varbinary`, 
`test_iceberg_uuid_binary_compatibility` and 
`test_iceberg_struct_schema_evolution`.
   - **FE UT**: new `IcebergConnectorMetadataBinaryModifyTest` drives 
`IcebergConnectorMetadata` into an in-memory Iceberg catalog. Its four 
restating cases fail before this PR with `Unsupported type for Iceberg: 
VARBINARY`; the fifth checks that a VARBINARY that restates nothing still fails 
and leaves the schema unchanged. Turning off the length comparison, the 
primitive check, the null check, or reading the current type at the top-level 
column instead of the nested path each turns a case red. All 1615 tests of 
fe-connector-iceberg pass.
   
   Original author: @Gabriel39
   
   ### Release note
   
   Iceberg: `ALTER TABLE ... MODIFY COLUMN` accepts a BINARY or FIXED column, 
or such a STRUCT field, ARRAY element or MAP value, restated with the 
`VARBINARY` type `DESC` shows, so its nullability, comment or position can be 
changed. It used to fail with `Unsupported type for Iceberg: VARBINARY`.
   
   ### Check List (For Author)
   
   - Test <!-- At least one of them must be included. -->
       - [x] Regression test
           - New `test_iceberg_modify_binary_column` (fails before this PR, 
passes after); seven related Iceberg suites pass.
       - [x] Unit Test
           - New `IcebergConnectorMetadataBinaryModifyTest`; all 
fe-connector-iceberg tests pass.
       - [ ] Manual test (add detailed scripts or steps below)
       - [ ] No need to test or manual test. Explain why:
           - [ ] This is a refactor/code format and no logic has been changed.
           - [ ] Previous test can cover this change.
           - [ ] No code files have been changed.
           - [ ] Other reason <!-- Add your reason?  -->
   
   - Behavior changed:
       - [ ] No.
       - [x] Yes. <!-- Explain the behavior change -->
           - The MODIFY COLUMN statements above succeed instead of failing.
   
   - Does this need documentation?
       - [x] No.
       - [ ] Yes. <!-- Add document PR link here. eg: 
https://github.com/apache/doris-website/pull/1214 -->
   
   ### Check List (For Reviewer who merge this PR)
   
   - [ ] Confirm the release note
   - [ ] Confirm test cases
   


-- 
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