welds 0.4.22

An async ORM for (postgres, mssql, mysql, sqlite)
use welds_connections::Syntax;

use crate::writers::ColumnWriter;

#[derive(Clone)]
pub struct OrderBy {
    pub(crate) field: String,
    pub(crate) direction: String,
    pub(crate) manual: bool,
}

impl OrderBy {
    pub(crate) fn new(field: impl Into<String>, dir: impl Into<String>) -> Self {
        Self {
            field: field.into(),
            direction: dir.into(),
            manual: false,
        }
    }

    pub(crate) fn new_manual(field: impl Into<String>, dir: impl Into<String>) -> Self {
        Self {
            field: field.into(),
            direction: dir.into(),
            manual: true,
        }
    }

    pub(crate) fn write(&self, syntax: Syntax, table_alias: &str) -> String {
        let col_writer = ColumnWriter::new(syntax);
        if self.manual {
            self.field.replace("$", table_alias)
        } else {
            format!(
                "{}.{} {}",
                table_alias,
                col_writer.excape(&self.field),
                self.direction
            )
        }
    }
}

pub(crate) fn to_sql(syntax: Syntax, parts: &[OrderBy], table_alias: &str) -> String {
    if parts.is_empty() {
        return "".to_owned();
    }
    let bys: Vec<String> = parts
        .iter()
        .map(|order_by| order_by.write(syntax, table_alias))
        .collect();
    let bys = bys.join(", ");
    format!("ORDER BY {}", bys)
}

#[test]
fn single_order_by_field() {
    let parts = vec![OrderBy {
        field: "f1".to_owned(),
        direction: "desc".to_owned(),
        manual: false,
    }];
    let clause = to_sql(Syntax::Sqlite, &parts, "t1");
    assert_eq!(clause.as_str(), r#"ORDER BY t1."f1" desc"#)
}

#[test]
fn order_by_field_two_fields() {
    let parts = vec![
        OrderBy {
            field: "f1".to_owned(),
            direction: "desc".to_owned(),
            manual: false,
        },
        OrderBy {
            field: "f2".to_owned(),
            direction: "asc".to_owned(),
            manual: false,
        },
    ];
    let clause = to_sql(Syntax::Sqlite, &parts, "t33");
    assert_eq!(clause.as_str(), r#"ORDER BY t33."f1" desc, t33."f2" asc"#)
}