MCPcopy Create free account
hub / github.com/PRQL/prql / distinct

Function distinct

prqlc/prqlc/src/sql/pq/preprocess.rs:126–186  ·  view source on GitHub ↗

Creates [SqlTransform::Distinct] from [Transform::Take]

(
    pipeline: Vec<SqlTransform>,
    ctx: &mut Context,
)

Source from the content-addressed store, hash-verified

124
125/// Creates [SqlTransform::Distinct] from [Transform::Take]
126pub(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 }

Callers 1

preprocessFunction · 0.85

Calls 8

into_column_sortFunction · 0.85
is_emptyMethod · 0.80
pushMethod · 0.80
try_mapMethod · 0.80
supports_distinct_onMethod · 0.45

Tested by

no test coverage detected