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

   ### What problem does this PR solve?
   
   Issue Number: None
   
   Related PR: #69723, #69821
   
   Problem Summary:
   
   #### In short
   
   Since #69723 removed the V1 file scanner, FileScannerV2 also reads the plans 
of an FE that predates the Iceberg scan semantics versions (Doris 4.1.3 and 
earlier), which a BE upgraded first executes during a rolling upgrade. For such 
a plan, the V2 Iceberg reader ignored an equality delete keyed on a nested 
field of a data file without field ids, or made it delete every row of the 
file, whenever the query did not read the field's parent struct. Neither case 
raised an error. This PR resolves such a key by its full path in the delete 
file. It also adds the V2 tests for old-FE plans whose equality keys are 
missing from the data file, which #69821 covered on the V1 reader before V1 was 
removed.
   
   #### Background
   
   An FE of 4.1.3 or earlier plans an Iceberg scan without 
`iceberg_scan_semantics_version` and without initial defaults. Its schema 
metadata (`current_schema_id = -1`, a single schema `-1`) lists only the 
projected columns, or every column when Top-N lazy materialization needs them, 
and marks every field optional. An equality-delete key is a hidden dependency 
of the scan, so the old FE usually does not list it.
   
   The V2 reader resolves an equality key through that schema metadata. For a 
key that an old FE does not list, it falls back to the name the delete file 
gives the key (`IcebergTableReader::_find_equality_delete_data_field`). In a 
data file with field ids the key is found by its field id at any depth. In a 
data file without them, as in an Iceberg table created by `migrate` or 
`add_files`, it is looked up by name.
   
   #### The problem, and what it cost
   
   The fallback kept only the key's leaf name and looked it up among the data 
file's top-level columns. A nested key was therefore never found and was read 
as a missing key: NULL in every row of the file.
   
   Take an ID-less data file `id, payload STRUCT<k INT>` holding `(1, {5})`, 
`(2, {7})` and `(3, NULL)`, an equality delete on `payload.k`, and an old-FE 
scan that reads only `id`:
   
   | Tombstones on `payload.k` | Iceberg result | Before this PR | This PR |
   |---|---|---|---|
   | `7` | 1, 3 | 1, 2, 3 (row 2 comes back) | 1, 3 |
   | `7`, `NULL` | 1 | none (every row is deleted) | 1 |
   
   Parquet and ORC behave the same. A data file with field ids, or a scan whose 
schema lists `payload`, was already read correctly. Before #69723 the V1 reader 
failed this plan (`Missing Iceberg schema metadata for equality-delete field 
id`), and a 4.1.3 BE refuses equality deletes on data files without field ids, 
so during an upgrade this was an error before it became wrong rows. It takes an 
old FE in front of an upgraded BE, data files without field ids, an equality 
delete keyed on a nested struct field, and a query that does not read that 
struct. branch-4.2 reads 4.1.3 plans with the same V2 code.
   
   #### How this PR fixes it
   
   `EqualityDeleteFilter` now keeps, for each key, the delete file's names from 
the key's top-level column down to the key (`field_name_paths`, for example 
`{"payload", "k"}`) instead of the leaf name alone. The old-FE fallback builds 
a table path from these names, so the walk by name finds `payload` and then 
`k`, with the same matcher as before. A present parent without the leaf is 
still a missing key and reads as NULL. The retry with the delete file's leaf 
name, and the fallback field that builds a missing key's NULL, use the last 
name of the path, as before.
   
   One limit remains: a key renamed after a data file without field ids was 
written is not found under the delete file's name, because the old FE sends no 
name mapping for a column it does not list. Such a key reads as NULL, as a 
top-level key already does.
   
   #### Results
   
   New cases in `be/test/format_v2/table/iceberg_reader_test.cpp`, all on scan 
parameters built the way a 4.1.3 FE builds them 
(`make_old_fe_iceberg_scan_params`):
   
   | Test | Cases | Before this PR | This PR |
   |---|---|---|---|
   | `IcebergOldFePlanFindsUnlistedNestedEqualityKeyByDeleteFileNames`: the 
example above, with and without field ids, with and without `payload` in the 
schema | 16 | 4 fail: no field ids and `payload` not listed, Parquet and ORC, 
both tombstone sets | all pass |
   | `IcebergOldFePlanMatchesMissingEqualityKeyAsNull`: an INT or STRING key 
the file lacks, alone or with `id`, against NULL and `0` / `''` tombstones | 24 
| all pass | all pass |
   | `IcebergOldFePlanMatchesMissingNestedEqualityKeyAsNull`: `payload.k` the 
file lacks, under NULL and present parents | 8 | all pass | all pass |
   
   The last two pin what V2 already did for a key the file lacks: it is NULL in 
every row and matches only a NULL tombstone, never the `0` or empty string 
stored under a NULL slot.
   
   ### Release note
   
   Fix equality deletes on a nested field of Iceberg data files without field 
ids being ignored, or deleting every row of the file, when a BE runs a query 
planned by an FE of 4.1.3 or earlier during a rolling upgrade.
   
   ### Check List (For Author)
   
   - Test: Unit Test
       - BE UT: the three tests above. Without the two source changes only the 
4 cases listed fail; with them all pass. `IcebergV2ReaderTest`, 
`IcebergTableReaderTest`, `EqualityDeletePredicateTest`, 
`IcebergPositionDeleteSysTableV2*`, `TableReaderTest`, `ColumnMapper*`, 
`LocalColumnIndexTest` and `CloneTableExprTreeTest` pass locally (411 tests, 
macOS, ASAN). `build-support/check-build-hygiene.sh` passes, and clang-tidy 
reports nothing on the changed lines.
       - No regression test: it needs an FE of 4.1.3 or earlier in front of 
this BE, which the regression framework cannot set up.
   - Behavior changed: Yes. For such a plan, a nested equality key that a data 
file without field ids stores is read from the file, so its tombstones delete 
the rows Iceberg deletes.
   - Does this need documentation: No
   


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