use std::sync::Arc;
use hamelin_lib::err::TranslationError;
use hamelin_lib::tree::ast::command::{AggCommand, Command, CommandKind};
use hamelin_lib::tree::{
builder,
typed_ast::{
command::TypedCommandKind, context::StatementTranslationContext, pipeline::TypedPipeline,
},
};
fn distinct_command_to_agg_command(cmd: &Command) -> Command {
match &cmd.kind {
CommandKind::Distinct(d) => Command {
span: cmd.span,
kind: AggCommand {
clauses: vec![],
group_by: d.clauses.clone(),
sort: vec![],
}
.into(),
},
_ => cmd.clone(),
}
}
pub fn lower_distinct(
pipeline: Arc<TypedPipeline>,
ctx: &mut StatementTranslationContext,
) -> Result<Arc<TypedPipeline>, Arc<TranslationError>> {
if !pipeline
.valid_ref()?
.commands
.iter()
.any(|cmd| matches!(cmd.kind, TypedCommandKind::Distinct(_)))
{
return Ok(pipeline);
}
let valid = pipeline.valid_ref()?;
let mut pipe_builder = builder::pipeline();
for cmd in &valid.commands {
let ast = match &cmd.kind {
TypedCommandKind::Distinct(_) => {
Arc::new(distinct_command_to_agg_command(cmd.ast.as_ref()))
}
_ => cmd.ast.clone(),
};
pipe_builder = pipe_builder.command(ast);
}
let new_ast = pipe_builder.build().at(pipeline.ast.span);
Ok(Arc::new(TypedPipeline::from_ast_with_context(
Arc::new(new_ast),
ctx,
)))
}