@@ -1542,6 +1542,69 @@ TEST_F(AvroScannerTest, test_struct_type) {
15421542 }
15431543}
15441544
1545+ // Regression for issue #11522: a BOOLEAN element nested inside a native ARRAY target column.
1546+ // BooleanColumn is FixedLengthColumn<uint8_t>, but the nested (non-adaptive) add_nullable_column
1547+ // dispatched TYPE_BOOLEAN through add_nullable_numeric_column<int8_t>, so add_numeric_column's
1548+ // down_cast<FixedLengthColumn<int8_t>*> tripped the dynamic_cast assert (casts.h) under ASAN/DEBUG.
1549+ // STRUCT/MAP/ARRAY all funnel their leaf columns through this same add_nullable_column dispatch, so
1550+ // the ARRAY case exercises (and guards) the one-line fix for every container. ARRAY is used here
1551+ // because it is the path present on all release branches (the STRUCT crash path came from #74901).
1552+ TEST_F (AvroScannerTest, test_array_with_boolean) {
1553+ // record root { array<boolean> a }
1554+ std::string schema_json =
1555+ R"( {"type":"record","name":"root","fields":[{"name":"a","type":{"type":"array","items":"boolean"}}]})" ;
1556+
1557+ AvroHelper avro_helper;
1558+ init_avro_value (schema_json.data (), schema_json.size (), avro_helper);
1559+ DeferOp avro_helper_deleter ([&] {
1560+ avro_schema_decref (avro_helper.schema );
1561+ avro_value_iface_decref (avro_helper.iface );
1562+ avro_value_decref (&avro_helper.avro_val );
1563+ });
1564+
1565+ avro_value_t a_value;
1566+ ASSERT_EQ (0 , avro_value_get_by_name (&avro_helper.avro_val , " a" , &a_value, NULL ));
1567+ avro_value_t e0 ;
1568+ avro_value_append (&a_value, &e0 , NULL );
1569+ avro_value_set_boolean (&e0 , true );
1570+ avro_value_t e1 ;
1571+ avro_value_append (&a_value, &e1 , NULL );
1572+ avro_value_set_boolean (&e1 , false );
1573+ avro_value_t e2 ;
1574+ avro_value_append (&a_value, &e2 , NULL );
1575+ avro_value_set_boolean (&e2 , true );
1576+
1577+ std::string data_path = " ./be/test/exec/test_data/avro_scanner/tmp/avro_array_boolean_data.avro" ;
1578+ ASSERT_TRUE (write_avro_data (avro_helper, data_path).ok ());
1579+
1580+ std::vector<TypeDescriptor> types;
1581+ TypeDescriptor t (TYPE_ARRAY );
1582+ t.children .emplace_back (TYPE_BOOLEAN );
1583+ types.emplace_back (t);
1584+
1585+ std::vector<TBrokerRangeDesc> ranges;
1586+ TBrokerRangeDesc range;
1587+ range.format_type = TFileFormatType::FORMAT_AVRO ;
1588+ range.__isset .jsonpaths = false ;
1589+ range.__set_path (data_path);
1590+ ranges.emplace_back (range);
1591+
1592+ auto scanner = create_avro_scanner (types, ranges, {" a" }, avro_helper.schema_text );
1593+ Status st = scanner->open ();
1594+ ASSERT_TRUE (st.ok ()) << st;
1595+ auto st2 = scanner->get_next ();
1596+ ASSERT_TRUE (st2.ok ()) << st2.status ();
1597+
1598+ ChunkPtr chunk = st2.value ();
1599+ EXPECT_EQ (1 , chunk->num_columns ());
1600+ EXPECT_EQ (1 , chunk->num_rows ());
1601+ auto array = chunk->get (0 )[0 ].get_array ();
1602+ ASSERT_EQ (3 , array.size ());
1603+ EXPECT_EQ (1 , array[0 ].get_int8 ());
1604+ EXPECT_EQ (0 , array[1 ].get_int8 ());
1605+ EXPECT_EQ (1 , array[2 ].get_int8 ());
1606+ }
1607+
15451608TEST_F (AvroScannerTest, test_array_of_nullable_string) {
15461609 // record root { array< union{ null, string } > a }
15471610 // Regression guard for the codex review (PR #74901): an ARRAY<VARCHAR> whose elements are avro
0 commit comments