tank-core 0.31.0

Core of Tank: the Rust data layer. This is intended to be used by drivers to implement a backend.
Documentation
use crate::{
    DynQuery, Expression, ExpressionVisitor, GenericSqlWriter, OpPrecedence,
    writer::{Context, SqlWriter},
};
use proc_macro2::TokenStream;
use quote::{ToTokens, TokenStreamExt, quote};
use std::mem;

#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum BinaryOpType {
    Indexing,
    Cast,
    Multiplication,
    Division,
    Remainder,
    Addition,
    Subtraction,
    ShiftLeft,
    ShiftRight,
    BitwiseAnd,
    BitwiseOr,
    In,
    NotIn,
    Is,
    IsNot,
    Like,
    NotLike,
    Regexp,
    NotRegexp,
    Glob,
    NotGlob,
    Equal,
    NotEqual,
    Less,
    Greater,
    LessEqual,
    GreaterEqual,
    And,
    Or,
    Alias,
}

impl OpPrecedence for BinaryOpType {
    fn precedence(&self, writer: &dyn SqlWriter) -> i32 {
        writer.expression_binary_op_precedence(self)
    }
}

#[derive(Debug)]
pub struct BinaryOp<L: Expression, R: Expression> {
    pub op: BinaryOpType,
    pub lhs: L,
    pub rhs: R,
}

impl<L: Expression, R: Expression> OpPrecedence for BinaryOp<L, R> {
    fn precedence(&self, writer: &dyn SqlWriter) -> i32 {
        writer.expression_binary_op_precedence(&self.op)
    }
}

impl<L: Expression, R: Expression> Expression for BinaryOp<L, R> {
    fn write_query(&self, writer: &dyn SqlWriter, context: &mut Context, out: &mut DynQuery) {
        writer.write_binary_op(
            context,
            out,
            &BinaryOp {
                op: self.op,
                lhs: &self.lhs,
                rhs: &self.rhs,
            },
        )
    }
    fn accept_visitor(
        &self,
        matcher: &mut dyn ExpressionVisitor,
        writer: &dyn SqlWriter,
        context: &mut Context,
        out: &mut DynQuery,
    ) -> bool {
        matcher.visit_binary_op(
            writer,
            context,
            out,
            &BinaryOp {
                op: self.op,
                lhs: &self.lhs,
                rhs: &self.rhs,
            },
        )
    }
    fn as_identifier(&self, context: &mut Context) -> String {
        if self.op == BinaryOpType::Alias {
            self.rhs.as_identifier(context)
        } else {
            let mut out = DynQuery::new(String::new());
            let writer = GenericSqlWriter::new();
            self.write_query(&writer, context, &mut out);
            mem::take(out.buffer())
        }
    }
}

impl ToTokens for BinaryOpType {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        let v = format!("{self:?}");
        tokens.append_all(quote!(::tank::BinaryOpType::#v));
    }
}