use crate::{
DefaultValueType, DynQuery, Expression, ExpressionVisitor, OpPrecedence, SqlWriter, TableRef,
Value, writer::Context,
};
use proc_macro2::TokenStream;
use quote::{ToTokens, TokenStreamExt, quote};
use std::{borrow::Cow, collections::BTreeMap, hash::Hash};
pub trait ColumnTrait {
fn column_def(&self) -> &ColumnDef;
fn column_ref(&self) -> &ColumnRef;
}
#[derive(Default, Debug, Clone, PartialEq, Eq, Hash)]
pub struct ColumnRef {
pub name: Cow<'static, str>,
pub table: Cow<'static, str>,
pub schema: Cow<'static, str>,
}
impl ColumnRef {
pub fn new(name: Cow<'static, str>) -> Self {
Self {
name,
..Default::default()
}
}
pub fn table(&self) -> TableRef {
TableRef {
name: self.table.clone(),
schema: self.schema.clone(),
..Default::default()
}
}
}
#[derive(Default, Clone, Copy, PartialEq, Eq, Debug)]
pub enum PrimaryKeyType {
PrimaryKey,
PartOfPrimaryKey,
#[default]
None,
}
impl ToTokens for PrimaryKeyType {
fn to_tokens(&self, tokens: &mut TokenStream) {
use PrimaryKeyType::*;
tokens.append_all(match self {
PrimaryKey => quote!(::tank::PrimaryKeyType::PrimaryKey),
PartOfPrimaryKey => quote!(::tank::PrimaryKeyType::PartOfPrimaryKey),
None => quote!(::tank::PrimaryKeyType::None),
});
}
}
#[derive(Default, Debug, PartialEq, Eq)]
pub enum Action {
#[default]
NoAction,
Restrict,
Cascade,
SetNull,
SetDefault,
}
impl ToTokens for Action {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.append_all(match self {
Action::NoAction => quote! { ::tank::Action::NoAction },
Action::Restrict => quote! { ::tank::Action::Restrict },
Action::Cascade => quote! { ::tank::Action::Cascade },
Action::SetNull => quote! { ::tank::Action::SetNull },
Action::SetDefault => quote! { ::tank::Action::SetDefault },
});
}
}
#[derive(Default, Debug)]
pub struct ColumnDef {
pub column_ref: ColumnRef,
pub column_type: BTreeMap<&'static str, &'static str>,
pub value: Value,
pub nullable: bool,
pub default: DefaultValueType,
pub primary_key: PrimaryKeyType,
pub clustering_key: bool,
pub unique: bool,
pub references: Option<ColumnRef>,
pub on_delete: Option<Action>,
pub on_update: Option<Action>,
pub comment: &'static str,
}
impl ColumnDef {
pub fn name(&self) -> &str {
&self.column_ref.name
}
pub fn table(&self) -> &str {
&self.column_ref.table
}
pub fn schema(&self) -> &str {
&self.column_ref.schema
}
}
impl<'a> From<&'a ColumnDef> for &'a ColumnRef {
fn from(value: &'a ColumnDef) -> Self {
&value.column_ref
}
}
impl OpPrecedence for ColumnRef {
fn precedence(&self, _writer: &dyn SqlWriter) -> i32 {
1_000_000
}
}
impl Expression for ColumnRef {
fn write_query(&self, writer: &dyn SqlWriter, context: &mut Context, out: &mut DynQuery) {
writer.write_column_ref(context, out, self);
}
fn accept_visitor(
&self,
matcher: &mut dyn ExpressionVisitor,
writer: &dyn SqlWriter,
context: &mut Context,
out: &mut DynQuery,
) -> bool {
matcher.visit_column(writer, context, out, self)
}
}
impl OpPrecedence for ColumnDef {
fn precedence(&self, _writer: &dyn SqlWriter) -> i32 {
1_000_000
}
}
impl Expression for ColumnDef {
fn write_query(&self, writer: &dyn SqlWriter, context: &mut Context, out: &mut DynQuery) {
writer.write_column_ref(context, out, &self.column_ref);
}
fn accept_visitor(
&self,
matcher: &mut dyn ExpressionVisitor,
writer: &dyn SqlWriter,
context: &mut Context,
out: &mut DynQuery,
) -> bool {
matcher.visit_column(writer, context, out, &self.column_ref)
}
}
impl PartialEq for ColumnDef {
fn eq(&self, other: &Self) -> bool {
self.column_ref == other.column_ref
}
}
impl Eq for ColumnDef {}
impl Hash for ColumnDef {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.column_ref.hash(state)
}
}