sql_query_builder 2.6.2

Write SQL queries in a simple and composable way
Documentation
#[cfg(any(feature = "postgresql", feature = "sqlite", feature = "mysql"))]
use crate::{behavior::WithQuery, concat::concat_raw_before_after, fmt, utils};

#[cfg(any(feature = "postgresql", feature = "sqlite", feature = "mysql"))]
pub(crate) trait ConcatLimit<Clause: PartialEq> {
  fn concat_limit(
    &self,
    items_raw_before: &Vec<(Clause, String)>,
    items_raw_after: &Vec<(Clause, String)>,
    query: String,
    fmts: &fmt::Formatter,
    clause: Clause,
    limit: &str,
  ) -> String {
    let fmt::Formatter { lb, space, .. } = fmts;
    let sql = if limit.is_empty() == false {
      format!("LIMIT{space}{limit}{space}{lb}")
    } else {
      "".to_string()
    };

    concat_raw_before_after(items_raw_before, items_raw_after, query, fmts, clause, sql)
  }
}

#[cfg(any(feature = "postgresql", feature = "sqlite"))]
pub(crate) trait ConcatReturning<Clause: PartialEq> {
  fn concat_returning(
    &self,
    items_raw_before: &Vec<(Clause, String)>,
    items_raw_after: &Vec<(Clause, String)>,
    query: String,
    fmts: &fmt::Formatter,
    clause: Clause,
    items: &Vec<String>,
  ) -> String {
    let fmt::Formatter { lb, space, comma, .. } = fmts;
    let sql = if items.is_empty() == false {
      let output_names = utils::join(items, comma);
      format!("RETURNING{space}{output_names}{space}{lb}")
    } else {
      "".to_string()
    };

    concat_raw_before_after(items_raw_before, items_raw_after, query, fmts, clause, sql)
  }
}

#[cfg(any(feature = "postgresql", feature = "sqlite", feature = "mysql"))]
pub(crate) trait ConcatWith<Clause: PartialEq> {
  fn concat_with(
    &self,
    items_raw_before: &Vec<(Clause, String)>,
    items_raw_after: &Vec<(Clause, String)>,
    query: String,
    fmts: &fmt::Formatter,
    clause: Clause,
    items: &Vec<(String, std::sync::Arc<dyn WithQuery + Send + Sync>)>,
  ) -> String {
    let fmt::Formatter {
      comma,
      lb,
      indent,
      space,
      ..
    } = fmts;
    let sql = if items.is_empty() == false {
      let with = items.iter().fold("".to_string(), |acc, item| {
        let (name, query) = item;
        let inner_lb = format!("{lb}{indent}");
        let inner_fmts = fmt::Formatter {
          comma,
          lb: inner_lb.as_str(),
          indent,
          space,
          ..*fmts
        };
        let query_string = query.concat(&inner_fmts);

        if query_string.is_empty() == false {
          format!("{acc}{name}{space}AS{space}({lb}{indent}{query_string}{lb}){comma}{lb}")
        } else {
          acc
        }
      });
      let with = &with[..with.len() - comma.len() - lb.len()];

      format!("WITH{space}{lb}{with}{space}{lb}")
    } else {
      "".to_string()
    };

    concat_raw_before_after(items_raw_before, items_raw_after, query, fmts, clause, sql)
  }
}

#[cfg(feature = "mysql")]
pub(crate) trait ConcatColumn<Clause: PartialEq> {
  fn concat_column(
    &self,
    items_raw_before: &Vec<(Clause, String)>,
    items_raw_after: &Vec<(Clause, String)>,
    query: String,
    fmts: &fmt::Formatter,
    clause: Clause,
    items: &Vec<String>,
  ) -> String {
    let fmt::Formatter { lb, comma, space, .. } = fmts;

    let sql = if items.is_empty() == false {
      let column_names = utils::join(&items, comma);
      if column_names.is_empty() == false {
        format!("({column_names}){space}{lb}")
      } else {
        "".to_string()
      }
    } else {
      "".to_string()
    };

    concat_raw_before_after(items_raw_before, items_raw_after, query, fmts, clause, sql)
  }
}