@@ -38,7 +38,7 @@ use datafusion_functions_aggregate::expr_fn::{
38
38
array_agg, avg, count, count_distinct, max, median, min, sum,
39
39
} ;
40
40
use datafusion_functions_nested:: make_array:: make_array_udf;
41
- use datafusion_functions_window:: expr_fn:: { first_value, row_number} ;
41
+ use datafusion_functions_window:: expr_fn:: { first_value, lead , row_number} ;
42
42
use insta:: assert_snapshot;
43
43
use object_store:: local:: LocalFileSystem ;
44
44
use std:: collections:: HashMap ;
@@ -85,6 +85,9 @@ use datafusion_physical_expr::Partitioning;
85
85
use datafusion_physical_expr_common:: physical_expr:: PhysicalExpr ;
86
86
use datafusion_physical_plan:: { displayable, ExecutionPlanProperties } ;
87
87
88
+ use datafusion:: error:: Result as DataFusionResult ;
89
+ use datafusion_functions_window:: expr_fn:: lag;
90
+
88
91
// Get string representation of the plan
89
92
async fn physical_plan_to_string ( df : & DataFrame ) -> String {
90
93
let physical_plan = df
@@ -152,6 +155,47 @@ async fn test_array_agg_ord_schema() -> Result<()> {
152
155
Ok ( ( ) )
153
156
}
154
157
158
+ #[ tokio:: test]
159
+ async fn with_column_lag ( ) -> DataFusionResult < ( ) > {
160
+ let schema = Schema :: new ( vec ! [ Field :: new( "a" , DataType :: Int32 , true ) ] ) ;
161
+
162
+ let batch = RecordBatch :: try_new (
163
+ Arc :: new ( schema. clone ( ) ) ,
164
+ vec ! [ Arc :: new( Int32Array :: from( vec![ 1 , 2 , 3 , 4 , 5 ] ) ) ] ,
165
+ ) ?;
166
+
167
+ let ctx = SessionContext :: new ( ) ;
168
+
169
+ let provider = MemTable :: try_new ( Arc :: new ( schema) , vec ! [ vec![ batch] ] ) ?;
170
+ ctx. register_table ( "t" , Arc :: new ( provider) ) ?;
171
+
172
+ // Define test cases: (expr builder, alias name)
173
+ let test_cases: Vec < ( Box < dyn Fn ( ) -> Expr > , & str ) > = vec ! [
174
+ ( Box :: new( || lag( col( "a" ) , Some ( 1 ) , None ) ) , "lag_val" ) ,
175
+ ( Box :: new( || lead( col( "a" ) , Some ( 1 ) , None ) ) , "lead_val" ) ,
176
+ ( Box :: new( || row_number( ) ) , "row_num" ) ,
177
+ ] ;
178
+
179
+ for ( make_expr, alias) in test_cases {
180
+ let df = ctx. table ( "t" ) . await ?;
181
+ let expr = make_expr ( ) ;
182
+ let df_with = df. with_column ( alias, expr) ?;
183
+ let df_schema = df_with. schema ( ) . clone ( ) ;
184
+
185
+ // Assert schema contains the alias column
186
+ assert ! (
187
+ df_schema. has_column_with_unqualified_name( alias) ,
188
+ "Schema does not contain expected column {}" ,
189
+ alias
190
+ ) ;
191
+
192
+ // Schema should have exactly 2 columns: original + alias
193
+ assert_eq ! ( 2 , df_schema. columns( ) . len( ) ) ;
194
+ }
195
+
196
+ Ok ( ( ) )
197
+ }
198
+
155
199
#[ tokio:: test]
156
200
async fn test_coalesce_schema ( ) -> Result < ( ) > {
157
201
let ctx = SessionContext :: new ( ) ;
0 commit comments