sql_select_parser 0.1.4

The SQL Parser CLI is a command-line tool designed to parse and analyze SQL SELECT queries.
Documentation
use anyhow::{Context, Result};
use sql_select_parser::parse_query;
use sql_select_parser::{SelectItem, Table, Value};

#[test]
fn test_whitespace_handling() -> Result<()> {
    let query = "select name, age from users where active = true  ";

    let parsed = parse_query(query).context("Failed to parse query with various whitespace")?;

    assert_eq!(parsed.columns.len(), 2);
    match &parsed.columns[0] {
        SelectItem::Column(col) => assert_eq!(col, "name"),
        _ => panic!("Expected column 'name'"),
    }
    match &parsed.columns[1] {
        SelectItem::Column(col) => assert_eq!(col, "age"),
        _ => panic!("Expected column 'age'"),
    }

    match parsed.table {
        Table::Simple(ref table_name) => assert_eq!(table_name, "users"),
        _ => panic!("Expected simple table 'users'"),
    }

    match parsed.where_clause {
        Some(ref condition) => {
            assert_eq!(condition.left, "active");
            assert_eq!(condition.operator, "=");
            match condition.right {
                Value::Boolean(b) => assert!(b),
                _ => panic!("Expected boolean value in WHERE clause"),
            }
        }
        None => panic!("Expected where clause"),
    }

    Ok(())
}

#[test]
fn test_select_keyword() -> Result<()> {
    let query = "select name from users";

    let parsed = parse_query(query).context("Failed to parse query with select keyword")?;

    assert_eq!(parsed.columns.len(), 1);
    match &parsed.columns[0] {
        SelectItem::Column(col) => assert_eq!(col, "name"),
        _ => panic!("Expected column 'name'"),
    }

    Ok(())
}

#[test]
fn test_from_keyword() -> Result<()> {
    let query = "select name from users";

    let parsed = parse_query(query).context("Failed to parse query with from keyword")?;

    match parsed.table {
        Table::Simple(ref table_name) => assert_eq!(table_name, "users"),
        _ => panic!("Expected simple table 'users'"),
    }

    Ok(())
}

#[test]
fn test_where_keyword() -> Result<()> {
    let query = "select name from users where active = true";

    let parsed = parse_query(query).context("Failed to parse query with WHERE keyword")?;

    assert!(parsed.where_clause.is_some());

    Ok(())
}

#[test]
fn test_identifier() -> Result<()> {
    let query = "select user_name, _email from users_table";

    let parsed = parse_query(query).context("Failed to parse query with identifiers")?;

    assert_eq!(parsed.columns.len(), 2);
    match &parsed.columns[0] {
        SelectItem::Column(col) => assert_eq!(col, "user_name"),
        _ => panic!("Expected column 'user_name'"),
    }
    match &parsed.columns[1] {
        SelectItem::Column(col) => assert_eq!(col, "_email"),
        _ => panic!("Expected column '_email'"),
    }

    match parsed.table {
        Table::Simple(ref table_name) => assert_eq!(table_name, "users_table"),
        _ => panic!("Expected simple table 'users_table'"),
    }

    Ok(())
}

#[test]
fn test_number_value() -> Result<()> {
    let query = "select id from orders where quantity = 100";

    let parsed = parse_query(query).context("Failed to parse query with numeric value")?;

    match parsed.where_clause {
        Some(ref condition) => {
            assert_eq!(condition.left, "quantity");
            assert_eq!(condition.operator, "=");
            match condition.right {
                Value::Number(n) => assert_eq!(n, 100),
                _ => panic!("Expected number value in where clause"),
            }
        }
        None => panic!("Expected WHERE clause"),
    }

    Ok(())
}

#[test]
fn test_function_name() -> Result<()> {
    let query = "select count(id) from orders";

    let parsed = parse_query(query).context("Failed to parse query with function call")?;

    assert_eq!(parsed.columns.len(), 1);
    match &parsed.columns[0] {
        SelectItem::Function { name, arguments } => {
            assert_eq!(name, "count");
            assert_eq!(arguments.len(), 1);
            match &arguments[0] {
                SelectItem::Column(col) => assert_eq!(col, "id"),
                _ => panic!("Expected column 'id' as function argument"),
            }
        }
        _ => panic!("Expected function in select columns"),
    }

    Ok(())
}

#[test]
fn test_select_star() -> Result<()> {
    let query = "select * from users";

    let parsed = parse_query(query).context("Failed to parse select * query")?;

    assert_eq!(parsed.columns.len(), 1);
    match &parsed.columns[0] {
        SelectItem::Column(col) => assert_eq!(col, "*"),
        _ => panic!("Expected '*' in select columns"),
    }

    match parsed.table {
        Table::Simple(ref table_name) => assert_eq!(table_name, "users"),
        _ => panic!("Expected simple table 'users'"),
    }

    Ok(())
}

#[test]
fn test_select_list() -> Result<()> {
    let query = "select id, name, email from users";

    let parsed = parse_query(query).context("Failed to parse select list with multiple items")?;

    assert_eq!(parsed.columns.len(), 3);
    let expected_columns = vec!["id", "name", "email"];
    for (i, col) in expected_columns.iter().enumerate() {
        match &parsed.columns[i] {
            SelectItem::Column(c) => assert_eq!(c, col),
            _ => panic!("Expected column '{}'", col),
        }
    }

    Ok(())
}

#[test]
fn test_table_subquery() -> Result<()> {
    let query = "select name from (select name, age from users)b";

    let parsed = parse_query(query).context("Failed to parse subquery in from clause")?;

    assert_eq!(parsed.columns.len(), 1);
    match &parsed.columns[0] {
        SelectItem::Column(ref col) => assert_eq!(col, "name"),
        _ => panic!("Expected column 'name'"),
    }
    match parsed.table {
        Table::Subquery(ref subquery) => {
            assert_eq!(subquery.columns.len(), 2);
            match &subquery.columns[0] {
                SelectItem::Column(col) => assert_eq!(col, "name"),
                _ => panic!("Expected column 'name' in subquery"),
            }
            match &subquery.columns[1] {
                SelectItem::Column(col) => assert_eq!(col, "age"),
                _ => panic!("Expected column 'age' in subquery"),
            }

            match subquery.table {
                Table::Simple(ref table_name) => assert_eq!(table_name, "users"),
                _ => panic!("Expected simple table 'users' in subquery"),
            }

            assert!(subquery.where_clause.is_none());
        }
        _ => panic!("Expected table as subquery"),
    }

    Ok(())
}

#[test]
fn test_invalid_select_missing_columns() -> Result<()> {
    let query = "select from users";

    let parsed = parse_query(query);

    assert!(
        parsed.is_err(),
        "Expected parsing to fail due to missing columns"
    );

    if let Err(e) = parsed {
        println!("Error: {}", e);
    }

    Ok(())
}