edgedb-query-builder 0.1.2

A query builder for Edgedb written in Rust
Documentation
pub enum Keyword {
    Select {
        table: String,
        fields: Vec<String>
    },
    Insert {
        table: String,
        fields: Vec<(String, String)>,
    },
    Filter {
        fields: Vec<(String, String)>,
    }
}

/// Base struct for all queries built with the query builder
pub struct Query {
    pub keywords: Vec<Keyword>
}

impl Query {
    /// Create a new query builder
    pub fn new() -> Self {
        Query { keywords: Vec::new() }
    }
    /// Add a select statement to the query. Takes the name of the table you're selecting and the values.
    /// You can add a filter with `.filter`.
    pub fn select<T: Into<String> + std::fmt::Display>(&mut self, table: T, values: Vec<T>) -> &mut Self {
        self.keywords.push(Keyword::Select { table: table.into(), fields: values.iter().map(|e| e.to_string()).collect::<Vec<String>>() });
        return self
    }
    /// Add a filter statement to the query. Takes a vector of (String,String). The first value is the field name and the 
    /// second field is the value that should be filtered with. 
    pub fn filter(&mut self, fields: Vec<(String, String)>) -> &mut Self {
        self.keywords.push(Keyword::Filter { fields });
        return self
    }
    /// Add an insert statement to your query. Takes the name of the table being inserted into and a vector of (String,String).
    /// Similarly to `.filter()` this tuple is in the order (field, value).
    pub fn insert<T: Into<String> + std::fmt::Display>(&mut self, table: T, fields: Vec<(String, String)>) -> &mut Self {
        self.keywords.push(Keyword::Insert { table: table.into(), fields });
        return self
    }
    /// Builds the query into an actual statement. 
    /// ```rust
    /// use edgedb_query_builder::Query;
    /// 
    /// let builder = Query::new().select("Movie", vec!["id","title"]).build();
    /// // This will be turned into:
    /// // select Movie { id, title };
    /// ```
    pub fn build(&self) -> String {
        let mut query = String::new();
        for keyword in &self.keywords {
            match keyword {
                Keyword::Select { table, fields } => {
                    query.push_str(&format!("select {table} {{ {} }}", fields.join(",")))
                },
                Keyword::Insert { table, fields } => {
                    query.push_str(&format!("insert {table} {{ {} }}", fields.iter().map(|f| format!("{} := \"{}\"", f.0, f.1)).collect::<Vec<String>>().join(",")))
                }
                Keyword::Filter { fields } => {
                    let mut filter_stmt = String::from("filter");
                    let filters = fields.iter().map(|f| format!(".{} = \"{}\"", f.0, f.1)).collect::<Vec<String>>().join("and");
                    filter_stmt.push_str(&filters);
                    query.push_str(&filter_stmt);
                }
            }
        }
        query.push(';');
        return query
    }
}

#[cfg(test)]
mod query_tests {
    #[test]
    fn basic_query() {
        let mut query = crate::Query::new();
        query.select("movie".to_string(), vec!["title".to_string()]);
        
        let query_str = query.build();

        assert_eq!(query_str, String::from("select movie { title }"));
    }
}