Skip to content

Commit 70cb927

Browse files
committed
test: expand window function coverage
1 parent 4798c61 commit 70cb927

3 files changed

Lines changed: 258 additions & 4 deletions

File tree

src/execution/dql/window.rs

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

tests/macros-test/src/main.rs

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2111,20 +2111,47 @@ mod test {
21112111
e.row_number(ordered.clone())?,
21122112
e.rank(ordered.clone())?,
21132113
e.dense_rank(ordered)?,
2114-
e.sum_over(score, partition.clone())?,
2115-
e.count_all_over(partition)?,
2114+
e.sum_over(score.clone(), partition.clone())?,
2115+
e.count_all_over(partition.clone())?,
2116+
e.count_over(score.clone(), partition.clone())?,
2117+
e.avg_over(score, partition)?,
21162118
])
21172119
})?
21182120
.finish()
21192121
})?
2120-
.project_tuple::<(i32, i64, i64, i64, i32, i32)>()
2122+
.project_tuple::<(i32, i64, i64, i64, i32, i32, i32, f64)>()
21212123
.collect::<Result<Vec<_>, _>>()?;
21222124
windowed_scores.sort_by_key(|row| row.0);
21232125
assert_eq!(
21242126
windowed_scores,
2125-
vec![(1, 1, 1, 1, 30, 2), (2, 2, 2, 2, 30, 2), (3, 1, 1, 1, 5, 1)]
2127+
vec![
2128+
(1, 1, 1, 1, 30, 2, 2, 15.0),
2129+
(2, 2, 2, 2, 30, 2, 2, 15.0),
2130+
(3, 1, 1, 1, 5, 1, 1, 5.0),
2131+
]
21262132
);
21272133

2134+
let mut windowed_min_max = database
2135+
.bind(|ctx| {
2136+
ctx.from::<EventLog>()?
2137+
.project_tuple(|e| {
2138+
let id = e.column(EventLog::id())?;
2139+
let category = e.column(EventLog::category())?;
2140+
let score = e.column(EventLog::score())?;
2141+
let partition = WindowSpec::new().partition_by(category);
2142+
Ok(vec![
2143+
id,
2144+
e.min_over(score.clone(), partition.clone())?,
2145+
e.max_over(score, partition)?,
2146+
])
2147+
})?
2148+
.finish()
2149+
})?
2150+
.project_tuple::<(i32, i32, i32)>()
2151+
.collect::<Result<Vec<_>, _>>()?;
2152+
windowed_min_max.sort_by_key(|row| row.0);
2153+
assert_eq!(windowed_min_max, vec![(1, 10, 20), (2, 10, 20), (3, 5, 5)]);
2154+
21282155
let mut grouped_categories = database
21292156
.bind(|ctx| {
21302157
ctx.from::<EventLog>()?

tests/slt/window.slt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,11 @@ order by id
8585
4 2 1
8686
5 2 1
8787

88+
query I
89+
select row_number() over () from window_test where id = 1
90+
----
91+
1
92+
8893
statement ok
8994
create view window_view as
9095
select id, k, row_number() over (partition by k order by v, id) as rn
@@ -112,3 +117,25 @@ window named_window as (order by id)
112117

113118
statement error
114119
select id from window_test qualify id = 1
120+
121+
statement error
122+
select count(distinct v) over () from window_test
123+
124+
statement error
125+
select sum(v) filter (where v > 0) over () from window_test
126+
127+
statement error
128+
select row_number(id) over () from window_test
129+
130+
statement error
131+
select lower('x') over () from window_test
132+
133+
statement error
134+
select sum(row_number() over ()) over () from window_test
135+
136+
statement error
137+
select id from window_test where row_number() over () = 1
138+
139+
statement error
140+
select row_number() over (named_window order by id) from window_test
141+
window named_window as (partition by k)

0 commit comments

Comments
 (0)