Skip to content

Commit e337ef7

Browse files
committed
Add apache#17285 reproducer case
1 parent 129c9f7 commit e337ef7

File tree

1 file changed

+97
-0
lines changed

1 file changed

+97
-0
lines changed
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
use arrow::array::{Int64Array, RecordBatch, StructArray};
2+
use arrow::datatypes::{DataType, Field, Fields, Schema};
3+
use datafusion::execution::context::SessionContext;
4+
use datafusion::logical_expr::{cast, col};
5+
use std::sync::Arc;
6+
7+
#[tokio::main]
8+
async fn main() -> Result<(), Box<dyn std::error::Error>> {
9+
let ctx = SessionContext::new();
10+
11+
// Source: struct with fields [b=3, a=4]
12+
let source_fields = Fields::from(vec![
13+
Field::new("b", DataType::Int64, false),
14+
Field::new("a", DataType::Int64, false),
15+
]);
16+
17+
let source_struct = StructArray::new(
18+
source_fields.clone(),
19+
vec![
20+
Arc::new(Int64Array::from(vec![3i64])), // b = 3
21+
Arc::new(Int64Array::from(vec![4i64])), // a = 4
22+
],
23+
None,
24+
);
25+
26+
let batch = RecordBatch::try_new(
27+
Arc::new(Schema::new(vec![Field::new(
28+
"s",
29+
DataType::Struct(source_fields),
30+
false,
31+
)])),
32+
vec![Arc::new(source_struct)],
33+
)?;
34+
35+
let table = datafusion::datasource::memory::MemTable::try_new(
36+
batch.schema(),
37+
vec![vec![batch]],
38+
)?;
39+
40+
ctx.register_table("t", Arc::new(table))?;
41+
42+
// Validate source data: should be b=3, a=4
43+
let source_data = ctx.table("t").await?.collect().await?;
44+
use arrow::array::AsArray;
45+
let src_struct = source_data[0].column(0).as_struct();
46+
let src_a = src_struct
47+
.column_by_name("a")
48+
.unwrap()
49+
.as_primitive::<arrow::array::types::Int64Type>()
50+
.value(0);
51+
let src_b = src_struct
52+
.column_by_name("b")
53+
.unwrap()
54+
.as_primitive::<arrow::array::types::Int64Type>()
55+
.value(0);
56+
assert_eq!(src_a, 4, "Source field 'a' should be 4");
57+
assert_eq!(src_b, 3, "Source field 'b' should be 3");
58+
println!("✓ Source validation passed: b={}, a={}", src_b, src_a);
59+
60+
// Target: reorder fields to [a, b]
61+
let target_type = DataType::Struct(Fields::from(vec![
62+
Field::new("a", DataType::Int64, false),
63+
Field::new("b", DataType::Int64, false),
64+
]));
65+
66+
// Execute cast
67+
let result = ctx
68+
.table("t")
69+
.await?
70+
.select(vec![cast(col("s"), target_type)])?
71+
.collect()
72+
.await?;
73+
74+
// Validate result
75+
let res_struct = result[0].column(0).as_struct();
76+
let res_a = res_struct
77+
.column_by_name("a")
78+
.unwrap()
79+
.as_primitive::<arrow::array::types::Int64Type>()
80+
.value(0);
81+
let res_b = res_struct
82+
.column_by_name("b")
83+
.unwrap()
84+
.as_primitive::<arrow::array::types::Int64Type>()
85+
.value(0);
86+
87+
if res_a == 4 && res_b == 3 {
88+
println!("✓ Cast result passed: a={}, b={}", res_a, res_b);
89+
} else {
90+
println!(
91+
"✗ Bug: Cast maps by position, not name. Expected a=4,b=3 but got a={}, b={}",
92+
res_a, res_b
93+
);
94+
}
95+
96+
Ok(())
97+
}

0 commit comments

Comments
 (0)