use crate::utils::{
direct_function_translation, hamelin_string_index_to_sql_with_negatives,
string_negative_index_to_positive, to_sql_concat,
};
use crate::TranslationRegistry;
use hamelin_lib::func::defs::{
CidrContains, Contains, EndsWith, IsIpv4, IsIpv6, Lower, Replace2, Replace3, StartsWith,
StringConcat, StringLen, Substr2, Substr3, Upper,
};
use hamelin_lib::sql::expression::apply::{BinaryOperatorApply, FunctionCallApply};
use hamelin_lib::sql::expression::literal::StringLiteral;
use hamelin_lib::sql::expression::operator::Operator;
use hamelin_lib::sql::expression::{Cast, TryCast};
use hamelin_lib::sql::types::{SQLBaseType, SQLType};
pub fn register(registry: &mut TranslationRegistry) {
registry.register::<StringConcat>(to_sql_concat);
registry.register::<Replace2>(direct_function_translation);
registry.register::<Replace3>(direct_function_translation);
registry.register::<Substr2>(|_, mut bindings| {
let string = bindings.take()?;
let start = bindings.take()?;
let sql_start = hamelin_string_index_to_sql_with_negatives(start.sql, string.sql.clone());
Ok(FunctionCallApply::with_two("substr", string.sql, sql_start).into())
});
registry.register::<Substr3>(|_, mut bindings| {
let string = bindings.take()?;
let start = bindings.take()?;
let end = bindings.take()?;
let positive_end = string_negative_index_to_positive(end.sql.clone(), string.sql.clone());
let positive_start =
string_negative_index_to_positive(start.sql.clone(), string.sql.clone());
let length = BinaryOperatorApply::new(Operator::Minus, positive_end, positive_start).into();
let sql_start = hamelin_string_index_to_sql_with_negatives(start.sql, string.sql.clone());
Ok(FunctionCallApply::with_three("substr", string.sql, sql_start, length).into())
});
registry.register::<StartsWith>(direct_function_translation);
registry.register::<EndsWith>(|_, mut bindings| {
let string = bindings.take()?;
let suffix = bindings.take()?;
Ok(BinaryOperatorApply::new(
Operator::Like,
string.sql,
BinaryOperatorApply::new(Operator::Concat, StringLiteral::new("%").into(), suffix.sql)
.into(),
)
.into())
});
registry.register::<Contains>(|_, mut bindings| {
let string = bindings.take()?;
let substring = bindings.take()?;
Ok(BinaryOperatorApply::new(
Operator::Like,
string.sql,
BinaryOperatorApply::new(
Operator::Concat,
StringLiteral::new("%").into(),
BinaryOperatorApply::new(
Operator::Concat,
substring.sql,
StringLiteral::new("%").into(),
)
.into(),
)
.into(),
)
.into())
});
registry.register::<CidrContains>(|_, mut bindings| {
let cidr = bindings.take()?;
let ip = bindings.take()?;
Ok(FunctionCallApply::with_one(
"try",
FunctionCallApply::with_two(
"contains",
cidr.sql,
TryCast::new(ip.sql, SQLType::SQLBaseType(SQLBaseType::IpAddress)).into(),
)
.into(),
)
.into())
});
registry.register::<IsIpv4>(|_, mut bindings| {
let ip = bindings.take()?;
Ok(BinaryOperatorApply::new(
Operator::Like,
Cast::new(
TryCast::new(ip.sql, SQLType::SQLBaseType(SQLBaseType::IpAddress)).into(),
SQLType::SQLBaseType(SQLBaseType::VarChar),
)
.into(),
StringLiteral::new("%.%").into(),
)
.into())
});
registry.register::<IsIpv6>(|_, mut bindings| {
let ip = bindings.take()?;
Ok(BinaryOperatorApply::new(
Operator::Like,
Cast::new(
TryCast::new(ip.sql, SQLType::SQLBaseType(SQLBaseType::IpAddress)).into(),
SQLType::SQLBaseType(SQLBaseType::VarChar),
)
.into(),
StringLiteral::new("%:%").into(),
)
.into())
});
registry.register::<Lower>(direct_function_translation);
registry.register::<Upper>(direct_function_translation);
registry.register::<StringLen>(|_, mut bindings| {
let x = bindings.take()?;
Ok(FunctionCallApply::with_one("length", x.sql).into())
});
}