use crate::db::{
query::builder::{TextProjectionExpr, TextProjectionTransform},
sql::parser::{SqlStatement, SqlTextFunction},
};
use crate::value::Value;
impl SqlTextFunction {
pub(in crate::db::session::sql::computed_projection) const fn projection_label(
self,
) -> &'static str {
self.projection_transform().label()
}
const fn projection_transform(self) -> TextProjectionTransform {
match self {
Self::Trim => TextProjectionTransform::Trim,
Self::Ltrim => TextProjectionTransform::Ltrim,
Self::Rtrim => TextProjectionTransform::Rtrim,
Self::Lower => TextProjectionTransform::Lower,
Self::Upper => TextProjectionTransform::Upper,
Self::Length => TextProjectionTransform::Length,
Self::Left => TextProjectionTransform::Left,
Self::Right => TextProjectionTransform::Right,
Self::StartsWith => TextProjectionTransform::StartsWith,
Self::EndsWith => TextProjectionTransform::EndsWith,
Self::Contains => TextProjectionTransform::Contains,
Self::Position => TextProjectionTransform::Position,
Self::Replace => TextProjectionTransform::Replace,
Self::Substring => TextProjectionTransform::Substring,
}
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub(in crate::db::session::sql::computed_projection) struct SqlComputedProjectionItem {
pub(in crate::db::session::sql::computed_projection) expr: TextProjectionExpr,
pub(in crate::db::session::sql::computed_projection) output_label: String,
}
impl SqlComputedProjectionItem {
#[must_use]
pub(in crate::db::session::sql::computed_projection) fn field(field: String) -> Self {
Self {
output_label: field.clone(),
expr: TextProjectionExpr::new(field, TextProjectionTransform::Field),
}
}
#[must_use]
pub(in crate::db::session::sql::computed_projection) fn passthrough(
output_label: String,
) -> Self {
Self {
expr: TextProjectionExpr::new(output_label.clone(), TextProjectionTransform::Field),
output_label,
}
}
#[must_use]
pub(in crate::db::session::sql::computed_projection) fn text_function(
function: SqlTextFunction,
field: String,
literal: Option<Value>,
literal2: Option<Value>,
literal3: Option<Value>,
) -> Self {
let expr = TextProjectionExpr::new(field, function.projection_transform())
.with_optional_literal(literal)
.with_optional_second_literal(literal2)
.with_optional_third_literal(literal3);
let output_label = expr.sql_label();
Self { expr, output_label }
}
#[must_use]
pub(in crate::db::session::sql::computed_projection) const fn expr(
&self,
) -> &TextProjectionExpr {
&self.expr
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub(in crate::db::session::sql) struct SqlComputedProjectionPlan {
pub(in crate::db::session::sql::computed_projection) base_statement: SqlStatement,
pub(in crate::db::session::sql::computed_projection) items: Vec<SqlComputedProjectionItem>,
}
impl SqlComputedProjectionPlan {
#[must_use]
pub(in crate::db::session::sql) fn cloned_base_statement(&self) -> SqlStatement {
self.base_statement.clone()
}
#[must_use]
pub(in crate::db::session::sql) fn into_base_statement(self) -> SqlStatement {
self.base_statement
}
#[must_use]
pub(in crate::db::session::sql) const fn is_grouped(&self) -> bool {
self.group_key_arity() != 0
}
#[must_use]
pub(in crate::db::session::sql) const fn group_key_arity(&self) -> usize {
let SqlStatement::Select(select) = &self.base_statement else {
return 0;
};
select.group_by.len()
}
#[must_use]
pub(in crate::db::session::sql) fn output_labels(&self) -> Vec<String> {
self.items
.iter()
.map(|item| item.output_label.clone())
.collect()
}
}