sqlutil 0.1.4

A utility library for building SQL queries
Documentation

use crate::quote_identifier;

pub fn build_select_sql(
    table: &str,
    column: Option<&str>,
    where_clause: Option<&str>,
    order_clause: Option<&str>,
    offset: Option<i64>,
    limit: Option<i64>,
) -> String {
    // Default to dummy table and all columns if not provided
    let column = column.unwrap_or("*");

    // Start building the query
    let mut query = format!("SELECT {} FROM {}", column, quote_identifier(table));

    // Add WHERE clause if provided
    if let Some(cond) = where_clause {
        if !cond.trim().is_empty() {
            query.push_str(&format!(" WHERE {}", cond));
        }
    }

    // Add ORDER BY clause if provided
    if let Some(order) = order_clause {
        if !order.trim().is_empty() {
            query.push_str(&format!(" ORDER BY {}", order));
        }
    }

    // Add OFFSET and LIMIT if provided
    if let Some(off) = offset {
        query.push_str(&format!(" OFFSET {}", off));
    }

    // Add LIMIT if provided
    if let Some(lim) = limit {
        query.push_str(&format!(" LIMIT {}", lim));
    }

    query
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_select_basic() {
        let sql = build_select_sql("users", None, None, None, None, None);
        assert_eq!(sql, "SELECT * FROM \"users\"");
    }

    #[test]
    fn test_select_columns() {
        let sql = build_select_sql("users", Some("id, name"), None, None, None, None);
        assert_eq!(sql, "SELECT id, name FROM \"users\"");
    }

    #[test]
    fn test_select_where() {
        let sql = build_select_sql("users", None, Some("age > 18"), None, None, None);
        assert_eq!(sql, "SELECT * FROM \"users\" WHERE age > 18");
    }

    #[test]
    fn test_select_order() {
        let sql = build_select_sql("users", None, None, Some("created_at DESC"), None, None);
        assert_eq!(sql, "SELECT * FROM \"users\" ORDER BY created_at DESC");
    }

    #[test]
    fn test_select_limit_offset() {
        let sql = build_select_sql("users", None, None, None, Some(10), Some(5));
        assert_eq!(sql, "SELECT * FROM \"users\" OFFSET 10 LIMIT 5");
    }

    #[test]
    fn test_select_full() {
        let sql = build_select_sql(
            "users",
            Some("id, email"),
            Some("active = 1"),
            Some("id ASC"),
            Some(0),
            Some(20),
        );
        assert_eq!(
            sql,
            "SELECT id, email FROM \"users\" WHERE active = 1 ORDER BY id ASC OFFSET 0 LIMIT 20"
        );
    }

    #[test]
    fn test_select_empty_where_string_is_skipped() {
        let sql = build_select_sql("users", None, Some(""), None, None, None);
        assert_eq!(sql, "SELECT * FROM \"users\"");
    }

    #[test]
    fn test_select_whitespace_where_string_is_skipped() {
        let sql = build_select_sql("users", None, Some("   "), None, None, None);
        assert_eq!(sql, "SELECT * FROM \"users\"");
    }

    #[test]
    fn test_select_empty_order_string_is_skipped() {
        let sql = build_select_sql("users", None, None, Some(""), None, None);
        assert_eq!(sql, "SELECT * FROM \"users\"");
    }

    #[test]
    fn test_select_whitespace_order_string_is_skipped() {
        let sql = build_select_sql("users", None, None, Some("   "), None, None);
        assert_eq!(sql, "SELECT * FROM \"users\"");
    }

    #[test]
    fn test_select_negative_offset() {
        let sql = build_select_sql("users", None, None, None, Some(-1), None);
        assert_eq!(sql, "SELECT * FROM \"users\" OFFSET -1");
    }

    #[test]
    fn test_select_table_with_double_quote_is_escaped() {
        let sql = build_select_sql("user\"data", None, None, None, None, None);
        assert_eq!(sql, "SELECT * FROM \"user\"\"data\"");
    }
}