qail-core 3.0.1

QAIL AST Kernel - typed query AST, schema validation, RLS context, and native access policy
//! DELETE SQL generation.

use crate::ast::*;
use crate::transpiler::conditions::{ConditionToSql, output_expr_sql, returning_clause_sql};
use crate::transpiler::dialect::Dialect;
use crate::transpiler::identifier::render_table_reference;

/// Generate DELETE FROM SQL with optional USING and WHERE clauses.
pub fn build_delete(cmd: &Qail, dialect: Dialect) -> String {
    let generator = dialect.generator();
    let mut sql = super::cte::build_write_with_prefix(cmd, dialect);
    sql.push_str(if cmd.only_table {
        "DELETE FROM ONLY "
    } else {
        "DELETE FROM "
    });
    sql.push_str(&render_table_reference(&cmd.table, generator.as_ref()));

    // USING clause (multi-table delete)
    if !cmd.using_tables.is_empty() {
        sql.push_str(" USING ");
        sql.push_str(
            &cmd.using_tables
                .iter()
                .map(|t| render_table_reference(t, generator.as_ref()))
                .collect::<Vec<_>>()
                .join(", "),
        );
    }

    // Process WHERE clauses
    let mut where_groups: Vec<String> = Vec::new();

    for cage in &cmd.cages {
        if let CageKind::Filter = cage.kind
            && !cage.conditions.is_empty()
        {
            let joiner = match cage.logical_op {
                LogicalOp::And => " AND ",
                LogicalOp::Or => " OR ",
            };
            let conditions: Vec<String> = cage
                .conditions
                .iter()
                .map(|c| c.to_sql(generator.as_ref(), Some(cmd)))
                .collect();
            let group = conditions.join(joiner);
            if cage.logical_op == LogicalOp::Or && cage.conditions.len() > 1 {
                where_groups.push(format!("({})", group));
            } else {
                where_groups.push(group);
            }
        }
    }

    if !where_groups.is_empty() {
        sql.push_str(" WHERE ");
        sql.push_str(&where_groups.join(" AND "));
    }

    sql.push_str(&returning_clause_sql(cmd, generator.as_ref(), |expr| {
        output_expr_sql(expr, generator.as_ref())
    }));

    sql
}