use crate::ast::assignment_clause::HamelinAssignmentClause;
use crate::ast::pipeline::HamelinPipeline;
use crate::ast::sort_expression::HamelinSortExpression;
use crate::env::Environment;
use crate::translation::projection_builder::ProjectionBuilder;
use crate::translation::PendingQueryResult;
use hamelin_lib::antlr::hamelinparser::{
AggCommandContext, AggCommandContextAttrs, GroupClauseContextAttrs,
};
use hamelin_lib::err::{TranslationError, TranslationErrors};
use hamelin_lib::func::def::{FunctionTranslationContext, SpecialPosition};
use hamelin_lib::sql::expression::literal::ColumnReference;
use hamelin_lib::sql::query::projection::Projection;
pub fn translate(
ctx: &AggCommandContext<'static>,
pipeline: &HamelinPipeline,
pending_query_result: &mut PendingQueryResult,
) {
let mut fctx = FunctionTranslationContext::default().with_special_allowed(SpecialPosition::Agg);
let sort_expression = ctx.sortExpression_all();
if !sort_expression.is_empty() {
let sort_ctx = pipeline.context.expression_translation_context(
&pending_query_result.translation.env,
FunctionTranslationContext::default(),
);
if let Some(res) = pending_query_result
.errors
.consume_errors(HamelinSortExpression::new(sort_expression, sort_ctx).translate())
{
fctx.add_order_by(res.0);
}
}
let mut agg_projections = ProjectionBuilder::default();
for clause in ctx.assignmentClause_all() {
let expr_ctx = pipeline
.context
.expression_translation_context(&pending_query_result.translation.env, fctx.clone());
let result = HamelinAssignmentClause::new(clause.clone(), expr_ctx).to_sql();
if let Some(res) = pending_query_result.errors.consume_errors(result) {
agg_projections.bind(res.0, res.1.sql, res.1.typ);
}
}
let mut group_projections = ProjectionBuilder::default();
for clause in ctx.groupClause_all() {
let expr_ctx = pipeline
.context
.expression_translation_context(&pending_query_result.translation.env, fctx.clone());
let result = TranslationErrors::expect(clause.as_ref(), clause.assignmentClause())
.and_then(|clause| HamelinAssignmentClause::new(clause.clone(), expr_ctx).to_sql());
if let Some((identifier, translation)) = pending_query_result.errors.consume_errors(result)
{
group_projections.bind(identifier, translation.sql, translation.typ);
}
}
let all_projection_result = group_projections
.clone()
.build_projections()
.map_err(|e| TranslationError::wrap_box(ctx, e.into()).single())
.and_then(|projections| {
agg_projections
.clone()
.build_projections()
.map_err(|e| TranslationError::wrap_box(ctx, e.into()).single())
.map(|agg_projections| (projections, agg_projections))
})
.map(|(projections, agg_projections)| {
projections
.into_iter()
.chain(agg_projections.into_iter())
.collect::<Vec<_>>()
});
let group_expressions_result = group_projections
.clone()
.build_projections()
.map_err(|e| TranslationError::wrap_box(ctx, e.into()).single())
.map(|projections| {
projections
.into_iter()
.map(|p| match p {
Projection::Binding(b) => b.expression,
Projection::ColumnProjection(cp) => ColumnReference::new(cp.identifier).into(),
})
.collect::<Vec<_>>()
});
pending_query_result.translation.env = Environment::new(
agg_projections
.build_hamelin_type()
.prepend_overwrite(&group_projections.build_hamelin_type()),
);
match TranslationErrors::from_2(all_projection_result, group_expressions_result) {
Ok((all_projection, group_expressions)) => {
pending_query_result.translation.query = pending_query_result
.translation
.query
.clone()
.push_down()
.add_group_expression(group_expressions)
.select(all_projection);
}
Err(e) => {
pending_query_result.errors.extend(e);
}
}
}