use sea_query::{BinOper, EscapeBuilder, QueryBuilder, QuotedBuilder, SelectDistinct, SqlWriter, SubQueryStatement, TableRefBuilder, Value};
use sea_query::extension::postgres::PgBinOper;
use sea_query::Write;
pub struct ClickHouseQueryBuilder;
impl QuotedBuilder for ClickHouseQueryBuilder {
fn quote(&self) -> char {
'"'
}
}
impl EscapeBuilder for ClickHouseQueryBuilder {}
impl TableRefBuilder for ClickHouseQueryBuilder {}
impl QueryBuilder for ClickHouseQueryBuilder {
fn placeholder(&self) -> (&str, bool) {
("$", true)
}
fn prepare_select_distinct(&self, select_distinct: &SelectDistinct, sql: &mut dyn SqlWriter) {
match select_distinct {
SelectDistinct::All => write!(sql, "ALL").unwrap(),
SelectDistinct::Distinct => write!(sql, "DISTINCT").unwrap(),
SelectDistinct::DistinctOn(cols) => {
write!(sql, "DISTINCT ON (").unwrap();
cols.iter().fold(true, |first, column_ref| {
if !first {
write!(sql, ", ").unwrap();
}
self.prepare_column_ref(column_ref, sql);
false
});
write!(sql, ")").unwrap();
}
_ => {}
};
}
fn prepare_bin_oper(&self, bin_oper: &BinOper, sql: &mut dyn SqlWriter) {
match bin_oper {
BinOper::PgOperator(oper) => write!(
sql,
"{}",
match oper {
PgBinOper::ILike => "ILIKE",
PgBinOper::NotILike => "NOT ILIKE",
PgBinOper::Matches => "@@",
PgBinOper::Contains => "@>",
PgBinOper::Contained => "<@",
PgBinOper::Concatenate => "||",
PgBinOper::Similarity => "%",
PgBinOper::WordSimilarity => "<%",
PgBinOper::StrictWordSimilarity => "<<%",
PgBinOper::SimilarityDistance => "<->",
PgBinOper::WordSimilarityDistance => "<<->",
PgBinOper::StrictWordSimilarityDistance => "<<<->",
}
)
.unwrap(),
_ => self.prepare_bin_oper_common(bin_oper, sql),
}
}
fn prepare_query_statement(&self, _: &SubQueryStatement, _: &mut dyn SqlWriter) {}
fn prepare_value(&self, value: &Value, sql: &mut dyn SqlWriter) {
sql.push_param(value.clone(), self as _);
}
fn write_string_quoted(&self, string: &str, buffer: &mut String) {
let escaped = self.escape_string(string);
let string = if escaped.find('\\').is_some() {
"E'".to_owned() + &escaped + "'"
} else {
"'".to_owned() + &escaped + "'"
};
write!(buffer, "{}", string).unwrap()
}
fn if_null_function(&self) -> &str {
"COALESCE"
}
}