use crate::ast::*;
use crate::transpiler::dialect::Dialect;
use crate::transpiler::dml::select::{build_select, build_set_operand};
pub fn build_cte(cmd: &Qail, dialect: Dialect) -> String {
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 mut final_query = cmd.clone();
final_query.ctes.clear();
if final_query.table.is_empty()
&& let Some(final_table) = cmd.ctes.last().map(|cte| &cte.name)
{
final_query.table = final_table.clone();
}
sql.push(' ');
sql.push_str(&build_select(&final_query, dialect));
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_set_operand(&cte.base_query, dialect));
if cte.recursive
&& let Some(ref recursive_query) = cte.recursive_query
{
sql.push_str(" UNION ALL ");
sql.push_str(&build_set_operand(recursive_query, dialect));
}
sql.push(')');
sql
}