@@ -156,3 +156,203 @@ impl<'a, T: Transaction + 'a> ExecutorNode<'a, T> for Window {
156156 }
157157 }
158158}
159+
160+ // GRCOV_EXCL_START
161+ #[ cfg( all( test, not( target_arch = "wasm32" ) ) ) ]
162+ mod tests {
163+ use super :: * ;
164+ use crate :: catalog:: { ColumnCatalog , ColumnDesc , ColumnRef } ;
165+ use crate :: execution:: { empty_context, execute_input, try_collect} ;
166+ use crate :: expression:: agg:: AggKind ;
167+ use crate :: expression:: window:: {
168+ WindowFunction as WindowExpressionFunction , WindowFunctionKind ,
169+ } ;
170+ use crate :: planner:: operator:: values:: ValuesOperator ;
171+ use crate :: planner:: operator:: Operator ;
172+ use crate :: planner:: Childrens ;
173+ use crate :: storage:: memory:: MemoryStorage ;
174+ use crate :: storage:: Storage ;
175+ use crate :: types:: LogicalType ;
176+
177+ fn column ( position : usize ) -> ScalarExpression {
178+ ScalarExpression :: column_expr ( ColumnRef :: new ( position + 1 ) , position)
179+ }
180+
181+ fn rows ( values : & [ i32 ] ) -> Vec < Tuple > {
182+ values
183+ . iter ( )
184+ . map ( |value| Tuple :: new ( None , vec ! [ DataValue :: Int32 ( * value) ] ) )
185+ . collect ( )
186+ }
187+
188+ fn functions ( ) -> Vec < Box < dyn WindowFunction > > {
189+ vec ! [
190+ function:: new(
191+ WindowFunctionKind :: RowNumber ,
192+ Vec :: new( ) ,
193+ LogicalType :: Bigint ,
194+ ) ,
195+ function:: new( WindowFunctionKind :: Rank , Vec :: new( ) , LogicalType :: Bigint ) ,
196+ function:: new(
197+ WindowFunctionKind :: DenseRank ,
198+ Vec :: new( ) ,
199+ LogicalType :: Bigint ,
200+ ) ,
201+ function:: new(
202+ WindowFunctionKind :: Aggregate ( AggKind :: Sum ) ,
203+ vec![ column( 0 ) ] ,
204+ LogicalType :: Integer ,
205+ ) ,
206+ ]
207+ }
208+
209+ #[ test]
210+ fn evaluate_peer_groups ( ) -> Result < ( ) , DatabaseError > {
211+ let mut rows = rows ( & [ 10 , 10 , 20 ] ) ;
212+ evaluate_partition ( & mut rows, & [ column ( 0 ) . asc ( ) ] , & mut functions ( ) ) ?;
213+
214+ assert_eq ! (
215+ rows. into_iter( ) . map( |row| row. values) . collect:: <Vec <_>>( ) ,
216+ vec![
217+ vec![
218+ 10 . into( ) ,
219+ 1_i64 . into( ) ,
220+ 1_i64 . into( ) ,
221+ 1_i64 . into( ) ,
222+ 20 . into( )
223+ ] ,
224+ vec![
225+ 10 . into( ) ,
226+ 2_i64 . into( ) ,
227+ 1_i64 . into( ) ,
228+ 1_i64 . into( ) ,
229+ 20 . into( )
230+ ] ,
231+ vec![
232+ 20 . into( ) ,
233+ 3_i64 . into( ) ,
234+ 3_i64 . into( ) ,
235+ 2_i64 . into( ) ,
236+ 40 . into( )
237+ ] ,
238+ ]
239+ ) ;
240+ Ok ( ( ) )
241+ }
242+
243+ #[ test]
244+ fn evaluate_without_order_by ( ) -> Result < ( ) , DatabaseError > {
245+ let mut rows = rows ( & [ 3 , 7 ] ) ;
246+ evaluate_partition ( & mut rows, & [ ] , & mut functions ( ) ) ?;
247+
248+ assert_eq ! (
249+ rows. into_iter( ) . map( |row| row. values) . collect:: <Vec <_>>( ) ,
250+ vec![
251+ vec![
252+ 3 . into( ) ,
253+ 1_i64 . into( ) ,
254+ 1_i64 . into( ) ,
255+ 1_i64 . into( ) ,
256+ 10 . into( )
257+ ] ,
258+ vec![
259+ 7 . into( ) ,
260+ 2_i64 . into( ) ,
261+ 1_i64 . into( ) ,
262+ 1_i64 . into( ) ,
263+ 10 . into( )
264+ ] ,
265+ ]
266+ ) ;
267+ Ok ( ( ) )
268+ }
269+
270+ #[ test]
271+ fn evaluate_empty_partition ( ) -> Result < ( ) , DatabaseError > {
272+ let mut rows = Vec :: new ( ) ;
273+ evaluate_partition ( & mut rows, & [ ] , & mut functions ( ) ) ?;
274+ assert ! ( rows. is_empty( ) ) ;
275+ Ok ( ( ) )
276+ }
277+
278+ #[ test]
279+ fn execute_partitions ( ) -> Result < ( ) , DatabaseError > {
280+ let table_arena = crate :: planner:: TableArenaCell :: default ( ) ;
281+ let mut plan_arena = crate :: planner:: PlanArena :: new ( & table_arena) ;
282+ let input_desc = ColumnDesc :: new ( LogicalType :: Integer , None , false , None ) ?;
283+ let input_columns = [ "partition" , "value" ]
284+ . map ( |name| {
285+ plan_arena. alloc_column ( ColumnCatalog :: new (
286+ name. to_string ( ) ,
287+ true ,
288+ input_desc. clone ( ) ,
289+ ) )
290+ } )
291+ . to_vec ( ) ;
292+ let output_desc = ColumnDesc :: new ( LogicalType :: Bigint , None , false , None ) ?;
293+ let output_columns = [ "row_number" , "rank" ]
294+ . map ( |name| {
295+ plan_arena. alloc_column ( ColumnCatalog :: new (
296+ name. to_string ( ) ,
297+ true ,
298+ output_desc. clone ( ) ,
299+ ) )
300+ } )
301+ . to_vec ( ) ;
302+ let input = LogicalPlan :: new (
303+ Operator :: Values ( ValuesOperator {
304+ rows : vec ! [
305+ vec![ 1 . into( ) , 10 . into( ) ] ,
306+ vec![ 1 . into( ) , 10 . into( ) ] ,
307+ vec![ 1 . into( ) , 20 . into( ) ] ,
308+ vec![ 2 . into( ) , 5 . into( ) ] ,
309+ vec![ 2 . into( ) , 7 . into( ) ] ,
310+ ] ,
311+ schema_ref : input_columns. clone ( ) ,
312+ } ) ,
313+ Childrens :: None ,
314+ ) ;
315+ let operator = WindowOperator {
316+ partition_by : vec ! [ ScalarExpression :: column_expr( input_columns[ 0 ] , 0 ) ] ,
317+ order_by : vec ! [ ScalarExpression :: column_expr( input_columns[ 1 ] , 1 ) . asc( ) ] ,
318+ functions : vec ! [
319+ WindowExpressionFunction {
320+ kind: WindowFunctionKind :: RowNumber ,
321+ args: Vec :: new( ) ,
322+ ty: LogicalType :: Bigint ,
323+ } ,
324+ WindowExpressionFunction {
325+ kind: WindowFunctionKind :: Rank ,
326+ args: Vec :: new( ) ,
327+ ty: LogicalType :: Bigint ,
328+ } ,
329+ ] ,
330+ output_columns,
331+ } ;
332+ let table_cache = crate :: storage:: TableCache :: default ( ) ;
333+ let view_cache = crate :: storage:: ViewCache :: default ( ) ;
334+ let meta_cache = crate :: storage:: StatisticsMetaCache :: default ( ) ;
335+ let storage = MemoryStorage :: new ( ) ;
336+ let transaction = storage. transaction ( ) ?;
337+
338+ let tuples = try_collect ( execute_input :: < _ , Window > (
339+ ( operator, input) ,
340+ empty_context ( & table_cache, & view_cache, & meta_cache) ,
341+ plan_arena,
342+ & transaction,
343+ ) ) ?;
344+
345+ assert_eq ! (
346+ tuples. into_iter( ) . map( |row| row. values) . collect:: <Vec <_>>( ) ,
347+ vec![
348+ vec![ 1 . into( ) , 10 . into( ) , 1_i64 . into( ) , 1_i64 . into( ) ] ,
349+ vec![ 1 . into( ) , 10 . into( ) , 2_i64 . into( ) , 1_i64 . into( ) ] ,
350+ vec![ 1 . into( ) , 20 . into( ) , 3_i64 . into( ) , 3_i64 . into( ) ] ,
351+ vec![ 2 . into( ) , 5 . into( ) , 1_i64 . into( ) , 1_i64 . into( ) ] ,
352+ vec![ 2 . into( ) , 7 . into( ) , 2_i64 . into( ) , 2_i64 . into( ) ] ,
353+ ]
354+ ) ;
355+ Ok ( ( ) )
356+ }
357+ }
358+ // GRCOV_EXCL_STOP
0 commit comments