| 166 | } |
| 167 | |
| 168 | fn accumulator(&self, acc_args: AccumulatorArgs) -> Result<Box<dyn Accumulator>> { |
| 169 | let field = &acc_args.expr_fields[0]; |
| 170 | let data_type = field.data_type(); |
| 171 | let ignore_nulls = acc_args.ignore_nulls && field.is_nullable(); |
| 172 | |
| 173 | if acc_args.is_distinct { |
| 174 | // Limitation similar to Postgres. The aggregation function can only mix |
| 175 | // DISTINCT and ORDER BY if all the expressions in the ORDER BY appear |
| 176 | // also in the arguments of the function. This implies that if the |
| 177 | // aggregation function only accepts one argument, only one argument |
| 178 | // can be used in the ORDER BY, For example: |
| 179 | // |
| 180 | // ARRAY_AGG(DISTINCT col) |
| 181 | // |
| 182 | // can only be mixed with an ORDER BY if the order expression is "col". |
| 183 | // |
| 184 | // ARRAY_AGG(DISTINCT col ORDER BY col) <- Valid |
| 185 | // ARRAY_AGG(DISTINCT concat(col, '') ORDER BY concat(col, '')) <- Valid |
| 186 | // ARRAY_AGG(DISTINCT col ORDER BY other_col) <- Invalid |
| 187 | // ARRAY_AGG(DISTINCT col ORDER BY concat(col, '')) <- Invalid |
| 188 | let sort_option = match acc_args.order_bys { |
| 189 | [single] if single.expr.eq(&acc_args.exprs[0]) => Some(single.options), |
| 190 | [] => None, |
| 191 | _ => { |
| 192 | return exec_err!( |
| 193 | "In an aggregate with DISTINCT, ORDER BY expressions must appear in argument list" |
| 194 | ); |
| 195 | } |
| 196 | }; |
| 197 | return Ok(Box::new(DistinctArrayAggAccumulator::try_new( |
| 198 | data_type, |
| 199 | sort_option, |
| 200 | ignore_nulls, |
| 201 | )?)); |
| 202 | } |
| 203 | |
| 204 | let Some(ordering) = LexOrdering::new(acc_args.order_bys.to_vec()) else { |
| 205 | return Ok(Box::new(ArrayAggAccumulator::try_new( |
| 206 | data_type, |
| 207 | ignore_nulls, |
| 208 | )?)); |
| 209 | }; |
| 210 | |
| 211 | let ordering_dtypes = ordering |
| 212 | .iter() |
| 213 | .map(|e| e.expr.data_type(acc_args.schema)) |
| 214 | .collect::<Result<Vec<_>>>()?; |
| 215 | |
| 216 | OrderSensitiveArrayAggAccumulator::try_new( |
| 217 | data_type, |
| 218 | &ordering_dtypes, |
| 219 | ordering, |
| 220 | self.is_input_pre_ordered, |
| 221 | acc_args.is_reversed, |
| 222 | ignore_nulls, |
| 223 | ) |
| 224 | .map(|acc| Box::new(acc) as _) |
| 225 | } |