reefdb 0.1.0

ReefDB is a minimalistic, in-memory and on-disk database management system written in Rust, implementing basic SQL query capabilities and full-text search.
Documentation
use nom::{
    bytes::complete::tag,
    character::complete::{alphanumeric1, multispace0, multispace1},
    combinator::opt,
    multi::separated_list0,
    sequence::terminated,
    IResult,
};

use crate::sql::{clauses::wheres::where_type::WhereType, data_value::DataValue};

use super::Statement;

#[derive(Debug, PartialEq)]
pub enum UpdateStatement {
    UpdateTable(String, Vec<(String, DataValue)>, Option<WhereType>),
}

impl UpdateStatement {
    pub fn parse(input: &str) -> IResult<&str, Statement> {
        let (input, _) = tag("UPDATE")(input)?;
        let (input, _) = multispace1(input)?;
        let (input, table_name) = alphanumeric1(input)?;
        let (input, _) = multispace1(input)?;
        let (input, _) = tag("SET")(input)?;
        let (input, _) = multispace1(input)?;
        let (input, updates) =
            separated_list0(terminated(tag(","), multispace0), parse_column_value_pair)(input)?;
        let (input, _) = opt(multispace1)(input)?;
        let (input, where_clause) = opt(WhereType::parse)(input)?;

        Ok((
            input,
            Statement::Update(UpdateStatement::UpdateTable(
                table_name.to_string(),
                updates,
                where_clause,
            )),
        ))
    }
}

fn parse_column_value_pair(input: &str) -> IResult<&str, (String, DataValue)> {
    let (input, col_name) = alphanumeric1(input)?;
    let (input, _) = multispace1(input)?;
    let (input, _) = tag("=")(input)?;
    let (input, _) = multispace1(input)?;
    let (input, value) = DataValue::parse(input)?;

    Ok((input, (col_name.to_string(), value)))
}

#[cfg(test)]
mod tests {
    use crate::sql::clauses::wheres::where_clause::WhereClause;

    #[test]
    fn parse_test() {
        use super::UpdateStatement;
        use crate::sql::data_value::DataValue;

        assert_eq!(
            UpdateStatement::parse("UPDATE users SET id = 1, name = 'John' WHERE id = 1"),
            Ok((
                "",
                super::Statement::Update(UpdateStatement::UpdateTable(
                    "users".to_string(),
                    vec![
                        ("id".to_string(), DataValue::Integer(1)),
                        ("name".to_string(), DataValue::Text("John".to_string())),
                    ],
                    Some(super::WhereType::Regular(WhereClause {
                        col_name: "id".to_string(),
                        value: DataValue::Integer(1),
                    }))
                ))
            ))
        );
    }
}