(
args: Vec<Datum<'a>>,
order_by_rows: &Vec<Row>,
window_frame: &WindowFrame,
)
| 1077 | } |
| 1078 | |
| 1079 | fn last_value_inner<'a>( |
| 1080 | args: Vec<Datum<'a>>, |
| 1081 | order_by_rows: &Vec<Row>, |
| 1082 | window_frame: &WindowFrame, |
| 1083 | ) -> Vec<Datum<'a>> { |
| 1084 | let length = args.len(); |
| 1085 | let mut results: Vec<Datum> = Vec::with_capacity(length); |
| 1086 | for (idx, (current_datum, order_by_row)) in args.iter().zip_eq(order_by_rows).enumerate() { |
| 1087 | let last_value = match &window_frame.end_bound { |
| 1088 | WindowFrameBound::CurrentRow => match &window_frame.units { |
| 1089 | // Always return the current value when in ROWS mode |
| 1090 | WindowFrameUnits::Rows => *current_datum, |
| 1091 | WindowFrameUnits::Range => { |
| 1092 | // When in RANGE mode, return the last value of the peer group |
| 1093 | // The peer group is the group of rows with the same ORDER BY value |
| 1094 | // Note: Range is only supported for the default window frame (RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), |
| 1095 | // which is why it does not appear in the other branches |
| 1096 | let target_idx = order_by_rows[idx..] |
| 1097 | .iter() |
| 1098 | .enumerate() |
| 1099 | .take_while(|(_, row)| *row == order_by_row) |
| 1100 | .last() |
| 1101 | .unwrap() |
| 1102 | .0 |
| 1103 | + idx; |
| 1104 | args[target_idx] |
| 1105 | } |
| 1106 | // GROUPS is not supported, and forbidden during planning |
| 1107 | WindowFrameUnits::Groups => unreachable!(), |
| 1108 | }, |
| 1109 | WindowFrameBound::UnboundedFollowing => { |
| 1110 | if let WindowFrameBound::OffsetFollowing(start_offset) = &window_frame.start_bound { |
| 1111 | let start_offset = usize::cast_from(*start_offset); |
| 1112 | |
| 1113 | // If the frame starts after the last row of the window, return null |
| 1114 | if idx + start_offset > length - 1 { |
| 1115 | Datum::Null |
| 1116 | } else { |
| 1117 | args[length - 1] |
| 1118 | } |
| 1119 | } else { |
| 1120 | args[length - 1] |
| 1121 | } |
| 1122 | } |
| 1123 | WindowFrameBound::OffsetFollowing(offset) => { |
| 1124 | let end_offset = usize::cast_from(*offset); |
| 1125 | let end_idx = idx.saturating_add(end_offset); |
| 1126 | if let WindowFrameBound::OffsetFollowing(start_offset) = &window_frame.start_bound { |
| 1127 | let start_offset = usize::cast_from(*start_offset); |
| 1128 | let start_idx = idx.saturating_add(start_offset); |
| 1129 | |
| 1130 | // If the frame is empty or starts after the last row of the window, return null |
| 1131 | if end_offset < start_offset || start_idx >= length { |
| 1132 | Datum::Null |
| 1133 | } else { |
| 1134 | // Return the last valid element in the window |
| 1135 | args.get(end_idx).unwrap_or(&args[length - 1]).clone() |
| 1136 | } |
no test coverage detected