| 1462 | } |
| 1463 | |
| 1464 | fn rows_between_offset_and_offset<'a>( |
| 1465 | args: Vec<Datum<'a>>, |
| 1466 | result: &mut Vec<Datum<'a>>, |
| 1467 | wrapped_aggregate: &AggregateFunc, |
| 1468 | temp_storage: &'a RowArena, |
| 1469 | offset_start: i64, |
| 1470 | offset_end: i64, |
| 1471 | ) { |
| 1472 | let len = args |
| 1473 | .len() |
| 1474 | .to_i64() |
| 1475 | .expect("window partition's len should fit into i64"); |
| 1476 | for i in 0..len { |
| 1477 | let i = i.to_i64().expect("window partition shouldn't be super big"); |
| 1478 | // Trim the start of the frame to make it not reach over the start of the window |
| 1479 | // partition. |
| 1480 | let frame_start = max(i + offset_start, 0) |
| 1481 | .to_usize() |
| 1482 | .expect("The max made sure it's not negative"); |
| 1483 | // Trim the end of the frame to make it not reach over the end of the window |
| 1484 | // partition. |
| 1485 | let frame_end = min(i + offset_end, len - 1).to_usize(); |
| 1486 | match frame_end { |
| 1487 | Some(frame_end) => { |
| 1488 | if frame_start <= frame_end { |
| 1489 | // Compute the aggregate on the frame. |
| 1490 | // TODO: |
| 1491 | // This implementation is quite slow if the frame is large: we do an |
| 1492 | // inner loop over the entire frame, and compute the aggregate from |
| 1493 | // scratch. We could do better: |
| 1494 | // - For invertible aggregations we could do a rolling aggregation. |
| 1495 | // - There are various tricks for min/max as well, making use of either |
| 1496 | // the fixed size of the window, or that we are not retracting |
| 1497 | // arbitrary elements but doing queue operations. E.g., see |
| 1498 | // http://codercareer.blogspot.com/2012/02/no-33-maximums-in-sliding-windows.html |
| 1499 | let frame_values = args[frame_start..=frame_end] |
| 1500 | .iter() |
| 1501 | .map(|d| (*d, Diff::ONE)); |
| 1502 | let result_value = wrapped_aggregate.eval(frame_values, temp_storage); |
| 1503 | result.push(result_value); |
| 1504 | } else { |
| 1505 | // frame_start > frame_end, so this is an empty frame. |
| 1506 | let result_value = wrapped_aggregate.default(); |
| 1507 | result.push(result_value); |
| 1508 | } |
| 1509 | } |
| 1510 | None => { |
| 1511 | // frame_end would be negative, so this is an empty frame. |
| 1512 | let result_value = wrapped_aggregate.default(); |
| 1513 | result.push(result_value); |
| 1514 | } |
| 1515 | } |
| 1516 | } |
| 1517 | } |
| 1518 | |
| 1519 | match ( |
| 1520 | &window_frame.units, |