kip-sql 0.0.1-alpha.8

build the SQL layer of KipDB database
Documentation
use crate::binder::{lower_case_name, split_name, BindError, Binder};
use crate::expression::ScalarExpression;
use crate::planner::operator::update::UpdateOperator;
use crate::planner::operator::Operator;
use crate::planner::LogicalPlan;
use crate::storage::Transaction;
use crate::types::value::ValueRef;
use sqlparser::ast::{Assignment, Expr, TableFactor, TableWithJoins};
use std::slice;
use std::sync::Arc;

impl<'a, T: Transaction> Binder<'a, T> {
    pub(crate) fn bind_update(
        &mut self,
        to: &TableWithJoins,
        selection: &Option<Expr>,
        assignments: &[Assignment],
    ) -> Result<LogicalPlan, BindError> {
        if let TableFactor::Table { name, .. } = &to.relation {
            let name = lower_case_name(name);
            let name = split_name(&name)?;
            let table_name = Arc::new(name.to_string());

            let mut plan = self.bind_table_ref(slice::from_ref(to))?;

            if let Some(predicate) = selection {
                plan = self.bind_where(plan, predicate)?;
            }

            let bind_table_name = Some(table_name.to_string());

            let mut columns = Vec::with_capacity(assignments.len());
            let mut row = Vec::with_capacity(assignments.len());

            for assignment in assignments {
                let value = match self.bind_expr(&assignment.value)? {
                    ScalarExpression::Constant(value) => Ok::<ValueRef, BindError>(value),
                    _ => unreachable!(),
                }?;

                for ident in &assignment.id {
                    match self.bind_column_ref_from_identifiers(
                        slice::from_ref(ident),
                        bind_table_name.as_ref(),
                    )? {
                        ScalarExpression::ColumnRef(catalog) => {
                            value.check_len(catalog.datatype())?;
                            columns.push(catalog);
                            row.push(value.clone());
                        }
                        _ => unreachable!(),
                    }
                }
            }

            let values_plan = self.bind_values(vec![row], columns);

            Ok(LogicalPlan {
                operator: Operator::Update(UpdateOperator { table_name }),
                childrens: vec![plan, values_plan],
            })
        } else {
            unreachable!("only table")
        }
    }
}