Creates [SqlTransform::Distinct] from [Transform::Take]
(
pipeline: Vec<SqlTransform>,
ctx: &mut Context,
)
| 124 | |
| 125 | /// Creates [SqlTransform::Distinct] from [Transform::Take] |
| 126 | pub(in crate::sql) fn distinct( |
| 127 | pipeline: Vec<SqlTransform>, |
| 128 | ctx: &mut Context, |
| 129 | ) -> Result<Vec<SqlTransform>> { |
| 130 | use SqlTransform::Super; |
| 131 | use Transform::*; |
| 132 | |
| 133 | let mut res = Vec::new(); |
| 134 | for transform in pipeline.clone() { |
| 135 | match transform { |
| 136 | Super(Take(rq::Take { ref partition, .. })) if partition.is_empty() => { |
| 137 | res.push(transform); |
| 138 | } |
| 139 | |
| 140 | Super(Take(rq::Take { |
| 141 | range, |
| 142 | partition, |
| 143 | sort, |
| 144 | })) => { |
| 145 | let range_int = range |
| 146 | .clone() |
| 147 | .try_map(as_int) |
| 148 | .map_err(|_| Error::new_simple("Invalid take arguments"))?; |
| 149 | |
| 150 | let take_only_first = |
| 151 | range_int.start.unwrap_or(1) == 1 && matches!(range_int.end, Some(1)); |
| 152 | |
| 153 | // Check whether the columns within the partition are the same |
| 154 | // as the columns in the table; otherwise we can't use DISTINCT. |
| 155 | let columns_in_frame = ctx.anchor.determine_select_columns(&pipeline.clone()); |
| 156 | let matching_columns = vecs_contain_same_elements(&columns_in_frame, &partition); |
| 157 | |
| 158 | if take_only_first && sort.is_empty() && matching_columns { |
| 159 | // DISTINCT |
| 160 | |
| 161 | res.push(SqlTransform::Distinct); |
| 162 | } else if ctx.dialect.supports_distinct_on() && range_int.end == Some(1) { |
| 163 | // DISTINCT ON (only if we want to select only one row per group) |
| 164 | |
| 165 | let sort = if sort.is_empty() { |
| 166 | vec![] |
| 167 | } else { |
| 168 | [into_column_sort(&partition), sort].concat() |
| 169 | }; |
| 170 | |
| 171 | res.push(SqlTransform::Sort(sort)); |
| 172 | res.push(SqlTransform::DistinctOn(partition)); |
| 173 | } else { |
| 174 | // convert `take range` into: |
| 175 | // derive _rn = s"ROW NUMBER" |
| 176 | // filter (_rn | in range) |
| 177 | res.extend(create_filter_by_row_number(range, sort, partition, ctx)); |
| 178 | } |
| 179 | } |
| 180 | _ => { |
| 181 | res.push(transform); |
| 182 | } |
| 183 | } |
no test coverage detected