rjango 0.1.1

A full-stack Rust backend framework inspired by Django
Documentation
use sea_orm::sea_query::{Func, SimpleExpr};

use super::custom_function;

/// SQL CONCAT(a, b, ...).
pub fn concat(exprs: Vec<SimpleExpr>) -> SimpleExpr {
    assert!(!exprs.is_empty(), "CONCAT requires at least one argument");
    custom_function("CONCAT", exprs)
}

/// SQL LOWER(expr).
pub fn lower(expr: SimpleExpr) -> SimpleExpr {
    Func::lower(expr).into()
}

/// SQL UPPER(expr).
pub fn upper(expr: SimpleExpr) -> SimpleExpr {
    Func::upper(expr).into()
}

/// SQL LENGTH(expr).
pub fn length(expr: SimpleExpr) -> SimpleExpr {
    custom_function("LENGTH", vec![expr])
}

/// SQL TRIM(expr).
pub fn trim(expr: SimpleExpr) -> SimpleExpr {
    custom_function("TRIM", vec![expr])
}

/// SQL REPLACE(expr, from, to).
pub fn replace(expr: SimpleExpr, from: SimpleExpr, to: SimpleExpr) -> SimpleExpr {
    custom_function("REPLACE", vec![expr, from, to])
}

/// SQL SUBSTR(expr, start, length).
pub fn substr(expr: SimpleExpr, start: SimpleExpr, length: SimpleExpr) -> SimpleExpr {
    custom_function("SUBSTR", vec![expr, start, length])
}

/// SQL LEFT(expr, count).
pub fn left(expr: SimpleExpr, count: SimpleExpr) -> SimpleExpr {
    custom_function("LEFT", vec![expr, count])
}

/// SQL RIGHT(expr, count).
pub fn right(expr: SimpleExpr, count: SimpleExpr) -> SimpleExpr {
    custom_function("RIGHT", vec![expr, count])
}

/// SQL REVERSE(expr).
pub fn reverse(expr: SimpleExpr) -> SimpleExpr {
    custom_function("REVERSE", vec![expr])
}

/// SQL REPEAT(expr, count).
pub fn repeat(expr: SimpleExpr, count: SimpleExpr) -> SimpleExpr {
    custom_function("REPEAT", vec![expr, count])
}

/// SQL LPAD(expr, length, fill).
pub fn lpad(expr: SimpleExpr, length: SimpleExpr, fill: SimpleExpr) -> SimpleExpr {
    custom_function("LPAD", vec![expr, length, fill])
}

/// SQL RPAD(expr, length, fill).
pub fn rpad(expr: SimpleExpr, length: SimpleExpr, fill: SimpleExpr) -> SimpleExpr {
    custom_function("RPAD", vec![expr, length, fill])
}

#[cfg(test)]
mod tests {
    use super::{
        concat, left, length, lower, lpad, repeat, replace, reverse, right, rpad, substr, trim,
        upper,
    };
    use sea_orm::sea_query::{Alias, Expr, PostgresQueryBuilder, Query, SimpleExpr};

    fn column(name: &str) -> SimpleExpr {
        Expr::col(Alias::new(name)).into()
    }

    fn render_select_expr(expr: SimpleExpr, alias: &str) -> String {
        Query::select()
            .expr_as(expr, Alias::new(alias))
            .from(Alias::new("widgets"))
            .to_owned()
            .to_string(PostgresQueryBuilder)
    }

    #[test]
    fn test_concat() {
        let sql = render_select_expr(
            concat(vec![
                column("first_name"),
                Expr::value(" "),
                column("last_name"),
            ]),
            "full_name",
        );
        assert!(sql.contains("CONCAT"), "expected CONCAT SQL, got: {sql}");
    }

    #[test]
    fn test_lower() {
        let sql = render_select_expr(lower(column("name")), "name_lower");
        assert!(sql.contains("LOWER"), "expected LOWER SQL, got: {sql}");
    }

    #[test]
    fn test_upper() {
        let sql = render_select_expr(upper(column("name")), "name_upper");
        assert!(sql.contains("UPPER"), "expected UPPER SQL, got: {sql}");
    }

    #[test]
    fn test_length() {
        let sql = render_select_expr(length(column("name")), "name_length");
        assert!(sql.contains("LENGTH"), "expected LENGTH SQL, got: {sql}");
    }

    #[test]
    fn test_trim() {
        let sql = render_select_expr(trim(column("name")), "trimmed_name");
        assert!(sql.contains("TRIM"), "expected TRIM SQL, got: {sql}");
    }

    #[test]
    fn test_replace() {
        let sql = render_select_expr(
            replace(column("name"), Expr::value("foo"), Expr::value("bar")),
            "renamed",
        );
        assert!(sql.contains("REPLACE"), "expected REPLACE SQL, got: {sql}");
    }

    #[test]
    fn test_substr() {
        let sql = render_select_expr(
            substr(column("name"), Expr::value(2), Expr::value(3)),
            "slice",
        );
        assert!(sql.contains("SUBSTR"), "expected SUBSTR SQL, got: {sql}");
    }

    #[test]
    fn test_left() {
        let sql = render_select_expr(left(column("name"), Expr::value(3)), "prefix");
        assert!(sql.contains("LEFT"), "expected LEFT SQL, got: {sql}");
    }

    #[test]
    fn test_right() {
        let sql = render_select_expr(right(column("name"), Expr::value(3)), "suffix");
        assert!(sql.contains("RIGHT"), "expected RIGHT SQL, got: {sql}");
    }

    #[test]
    fn test_reverse() {
        let sql = render_select_expr(reverse(column("name")), "reversed");
        assert!(sql.contains("REVERSE"), "expected REVERSE SQL, got: {sql}");
    }

    #[test]
    fn test_repeat() {
        let sql = render_select_expr(repeat(column("name"), Expr::value(2)), "repeated");
        assert!(sql.contains("REPEAT"), "expected REPEAT SQL, got: {sql}");
    }

    #[test]
    fn test_lpad() {
        let sql = render_select_expr(
            lpad(column("name"), Expr::value(8), Expr::value("0")),
            "left_padded",
        );
        assert!(sql.contains("LPAD"), "expected LPAD SQL, got: {sql}");
    }

    #[test]
    fn test_rpad() {
        let sql = render_select_expr(
            rpad(column("name"), Expr::value(8), Expr::value("0")),
            "right_padded",
        );
        assert!(sql.contains("RPAD"), "expected RPAD SQL, got: {sql}");
    }
}