use crate::ast::*;
use crate::transpiler::dialect::Dialect;
use crate::transpiler::dml::select::build_select;
pub fn build_cte(cmd: &Qail, dialect: Dialect) -> String {
let generator = dialect.generator();
if cmd.ctes.is_empty() {
return build_select(cmd, dialect);
}
let mut sql = String::from("WITH ");
let has_recursive = cmd.ctes.iter().any(|c| c.recursive);
if has_recursive {
sql.push_str("RECURSIVE ");
}
let cte_parts: Vec<String> = cmd
.ctes
.iter()
.map(|cte| build_single_cte(cte, dialect))
.collect();
sql.push_str(&cte_parts.join(", "));
let Some(final_table) = cmd.ctes.last().map(|cte| &cte.name) else {
return build_select(cmd, dialect);
};
sql.push_str(" SELECT * FROM ");
sql.push_str(&generator.quote_identifier(final_table));
sql
}
pub fn build_single_cte(cte: &CTEDef, dialect: Dialect) -> String {
let generator = dialect.generator();
let mut sql = String::new();
sql.push_str(&generator.quote_identifier(&cte.name));
if !cte.columns.is_empty() {
sql.push('(');
let cols: Vec<String> = cte
.columns
.iter()
.map(|c| generator.quote_identifier(c))
.collect();
sql.push_str(&cols.join(", "));
sql.push(')');
}
sql.push_str(" AS (");
sql.push_str(&build_select(&cte.base_query, dialect));
if cte.recursive
&& let Some(ref recursive_query) = cte.recursive_query
{
sql.push_str(" UNION ALL ");
sql.push_str(&build_select(recursive_query, dialect));
}
sql.push(')');
sql
}