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

   ### Apache Iceberg version
   
   1.11.0 (latest release)
   
   ### Query engine
   
   Spark
   
   ### Please describe the bug 🐞
   
   Spark
   ```sql
   CREATE OR REPLACE TABLE iceberg_catalog.test_add_files.fake_data_test (
        id bigint,
        name string,
        category string,
        value double,
        count bigint,
        active boolean,
        description string
   )
   USING iceberg
   TBLPROPERTIES (
        'format-version'='2'
   )
   
   CALL iceberg_catalog.system.add_files(
        table => 'test_add_files.fake_data_test',
        source_table => 'parquet.`{FILES_DIR}`'
   )
   ```
   
   This produces the Avro key-value metadata:
   ```
   
┌───────────────────┬────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
   │        key        │                                                        
             value                                                              
        │
   │      varchar      │                                                        
            varchar                                                             
        │
   
├───────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
   │ schema            │ 
{"type":"struct","schema-id":0,"fields":[{"id":1,"name":"id","required":false,"type":"long"},{"id":2,"name":"name","required":false,"type":"st
 │
   │                   │ 
ring"},{"id":3,"name":"category","required":false,"type":"string"},{"id":4,"name":"value","required":false,"type":"double"},{"id":5,"name":"co
 │
   │                   │ 
unt","required":false,"type":"long"},{"id":6,"name":"active","required":false,"type":"boolean"},{"id":7,"name":"description","required":false,
 │
   │                   │ "type":"string"}]}                                     
                                                                                
        │
   
├───────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
   │ avro.schema       │ 
{"type":"record","name":"manifest_entry","fields":[{"name":"status","type":"int","field-id":0},{"name":"snapshot_id","type":["null","long"],"d
 │
   │                   │ 
efault":null,"field-id":1},{"name":"data_file","type":{"type":"record","name":"r2","fields":[{"name":"file_path","type":"string","doc":"Locati
 │
   │                   │ on URI with FS 
scheme","field-id":100},{"name":"file_format","type":"string","doc":"File 
format name: avro, orc, or parquet","field-id":101},{ │
   │                   │ 
"name":"partition","type":{"type":"record","name":"r102","fields":[]},"field-id":102},{"name":"record_count","type":"long","doc":"Number
 of re │
   │                   │ cords in the 
file","field-id":103},{"name":"file_size_in_bytes","type":"long","doc":"Total 
file size in bytes","field-id":104},{"name":"block_ │
   │                   │ 
size_in_bytes","type":"long","field-id":105},{"name":"column_sizes","type":["null",{"type":"array","items":{"type":"record","name":"k117_v118…
 │
   
├───────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
   │ avro.codec        │ deflate                                                
                                                                                
        │
   
├───────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
   │ format-version    │ 1                                                      
                                                                                
        │
   
├───────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
   │ partition-spec-id │ 0                                                      
                                                                                
        │
   
├───────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
   │ iceberg.schema    │ 
{"type":"struct","schema-id":0,"fields":[{"id":0,"name":"status","required":true,"type":"int"},{"id":1,"name":"snapshot_id","required":false,"
 │
   │                   │ 
type":"long"},{"id":2,"name":"data_file","required":true,"type":{"type":"struct","fields":[{"id":100,"name":"file_path","required":true,"type"
 │
   │                   │ :"string","doc":"Location URI with FS 
scheme"},{"id":101,"name":"file_format","required":true,"type":"string","doc":"File
 format name: avro, o │
   │                   │ rc, or 
parquet"},{"id":102,"name":"partition","required":true,"type":{"type":"struct","fields":[]}},{"id":103,"name":"record_count","required"
 │
   │                   │ :true,"type":"long","doc":"Number of records in the 
file"},{"id":104,"name":"file_size_in_bytes","required":true,"type":"long","doc":"Total
 fi │
   │                   │ le size in 
bytes"},{"id":105,"name":"block_size_in_bytes","required":true,"type":"long"},{"id":108,"name":"column_sizes","required":false,"ty…
 │
   
├───────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
   │ partition-spec    │ []                                                     
                                                                                
        │
   
└───────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
   ```
   That `format_version` reports `1`, but the actual manifest file's schema 
suggests v2 (as does the version of the table)
   Most notably, the `manifest_entry.data_file.snapshot_id` attribute is 
missing, which is fine for v2, but not for v1, where it's marked as `required`.
   If a reader trusts the `format_version` obtained from the manifest file's 
Avro key-value metadata, the reader will error.
   
   And the contents of the file (not relevant, but sharing for completeness)
   ```
   
┌────────┬─────────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
   │ status │ snapshot_id │                                                     
             data_file                                                          
        │
   │ int32  │    int64    │ struct(file_path varchar, file_format varchar, 
"partition" "null", record_count bigint, file_size_in_bytes bigint, 
block_size_in_bytes bigi │
   │        │             │ nt, column_sizes map(integer, bigint), value_counts 
map(integer, bigint), null_value_counts map(integer, bigint), nan_value_counts 
map(inte │
   │        │             │ ger, bigint), lower_bounds map(integer, blob), 
upper_bounds map(integer, blob), key_metadata blob, split_offsets bigint[], 
sort_order_id in │
   │        │             │                                                     
              teger)                                                            
        │
   
├────────┼─────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
   │      1 │        NULL │ {                                                   
                                                                                
        │
   │        │             │   'file_path': 'file:/output/files/file_0.parquet', 
                                                                                
        │
   │        │             │   'file_format': PARQUET, 'partition': null, 
'record_count': 22402, 'file_size_in_bytes': 952597, 'block_size_in_bytes': 
67108864,          │
   │        │             │   'column_sizes': {}, 'value_counts': {}, 
'null_value_counts': {}, 'nan_value_counts': {}, 'lower_bounds': {}, 
'upper_bounds': {},          │
   │        │             │   'key_metadata': null, 'split_offsets': null, 
'sort_order_id': 0                                                              
             │
   │        │             │ }                                                   
                                                                                
        │
   
├────────┼─────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
   │      1 │        NULL │ {                                                   
                                                                                
        │
   │        │             │   'file_path': 'file:/output/files/file_1.parquet', 
                                                                                
        │
   │        │             │   'file_format': PARQUET, 'partition': null, 
'record_count': 33436, 'file_size_in_bytes': 1418456, 'block_size_in_bytes': 
67108864,         │
   │        │             │   'column_sizes': {}, 'value_counts': {}, 
'null_value_counts': {}, 'nan_value_counts': {}, 'lower_bounds': {}, 
'upper_bounds': {},          │
   │        │             │   'key_metadata': null, 'split_offsets': null, 
'sort_order_id': 0                                                              
             │
   │        │             │ }                                                   
                                                                                
        │
   
├────────┼─────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
   │      1 │        NULL │ {                                                   
                                                                                
        │
   │        │             │   'file_path': 'file:/output/files/file_2.parquet', 
                                                                                
        │
   │        │             │   'file_format': PARQUET, 'partition': null, 
'record_count': 44162, 'file_size_in_bytes': 1875070, 'block_size_in_bytes': 
67108864,         │
   │        │             │   'column_sizes': {}, 'value_counts': {}, 
'null_value_counts': {}, 'nan_value_counts': {}, 'lower_bounds': {}, 
'upper_bounds': {},          │
   │        │             │   'key_metadata': null, 'split_offsets': null, 
'sort_order_id': 0                                                              
             │
   │        │             │ }                                                   
                                                                                
        │
   
└────────┴─────────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
   ```
   
   Not super relevant, but the parquet files were created with DuckDB:
   ```py
   con = duckdb.connect()
   con.execute("select setseed(0.42)")
   
   # Generate synthetic data inside DuckDB
   con.execute(f"""
        CREATE OR REPLACE TABLE fake_data AS
        SELECT
                i AS id,
                'item_' || i AS name,
                CASE floor(random() * 3)
                        WHEN 0 THEN 'A'
                        WHEN 1 THEN 'B'
                        ELSE 'C'
                END AS category,
                100 + 15 * random() AS value,
                CAST(floor(random() * 99) + 1 AS INTEGER) AS count,
                random() < 0.5 AS active,
                substr(md5(random()::VARCHAR), 1, 24) AS description
        FROM range(1, {n_rows + 1}) t(i)
   """)
   
   # Get categories
   categories = [row[0] for row in con.execute(
        "SELECT DISTINCT category FROM fake_data"
   ).fetchall()]
   
   # Write one parquet file per category
   for i, category in enumerate(categories):
        file_path = parquet_dir / f"file_{i}.parquet"
        con.execute(f"""
                COPY (
                        SELECT * FROM fake_data
                        WHERE category = '{category}'
                )
                TO '{file_path}'
                (FORMAT PARQUET)
        """)
   ```
   
   ### Willingness to contribute
   
   - [ ] I can contribute a fix for this bug independently
   - [ ] I would be willing to contribute a fix for this bug with guidance from 
the Iceberg community
   - [x] I cannot contribute a fix for this bug at this time


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