tank_core/
column.rs

1use crate::{
2    DynQuery, DefaultValueType, Expression, OpPrecedence, SqlWriter, TableRef, Value,
3    writer::Context,
4};
5use proc_macro2::TokenStream;
6use quote::{ToTokens, TokenStreamExt, quote};
7use std::collections::BTreeMap;
8
9/// Helper trait for types that expose an underlying column definition and reference.
10pub trait ColumnTrait {
11    /// Logical definition (column metadata).
12    fn column_def(&self) -> &ColumnDef;
13    /// Column reference to be used in expressions.
14    fn column_ref(&self) -> &ColumnRef;
15}
16
17/// Reference to a table column.
18#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
19pub struct ColumnRef {
20    /// Column name.
21    pub name: &'static str,
22    /// Table name.
23    pub table: &'static str,
24    /// Schema name (may be empty).
25    pub schema: &'static str,
26}
27
28impl ColumnRef {
29    /// Return a `TableRef` referencing the column's table and schema.
30    pub fn table(&self) -> TableRef {
31        TableRef {
32            name: self.table.into(),
33            schema: self.schema.into(),
34            ..Default::default()
35        }
36    }
37}
38
39/// Indicates if and how a column participates in the primary key.
40#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
41pub enum PrimaryKeyType {
42    /// Single-column primary key.
43    PrimaryKey,
44    /// Member of a composite primary key.
45    PartOfPrimaryKey,
46    /// Not part of the primary key.
47    #[default]
48    None,
49}
50
51impl ToTokens for PrimaryKeyType {
52    fn to_tokens(&self, tokens: &mut TokenStream) {
53        use PrimaryKeyType::*;
54        tokens.append_all(match self {
55            PrimaryKey => quote!(::tank::PrimaryKeyType::PrimaryKey),
56            PartOfPrimaryKey => quote!(::tank::PrimaryKeyType::PartOfPrimaryKey),
57            None => quote!(::tank::PrimaryKeyType::None),
58        });
59    }
60}
61
62/// Referential action for foreign key updates or deletes.
63#[derive(Default, Debug, PartialEq, Eq)]
64pub enum Action {
65    /// No special action.
66    #[default]
67    NoAction,
68    /// Reject the operation.
69    Restrict,
70    /// Propagate delete, update...
71    Cascade,
72    /// Set referencing columns to NULL.
73    SetNull,
74    /// Apply column DEFAULT.
75    SetDefault,
76}
77
78impl ToTokens for Action {
79    fn to_tokens(&self, tokens: &mut TokenStream) {
80        tokens.append_all(match self {
81            Action::NoAction => quote! { ::tank::Action::NoAction },
82            Action::Restrict => quote! { ::tank::Action::Restrict },
83            Action::Cascade => quote! { ::tank::Action::Cascade },
84            Action::SetNull => quote! { ::tank::Action::SetNull },
85            Action::SetDefault => quote! { ::tank::Action::SetDefault },
86        });
87    }
88}
89
90/// Column specification.
91#[derive(Default, Debug)]
92pub struct ColumnDef {
93    /// Column identity.
94    pub column_ref: ColumnRef,
95    /// Explicit SQL type override (empty means infer from `value`).
96    pub column_type: BTreeMap<&'static str, &'static str>,
97    /// `Value` describing column type and parameters.
98    pub value: Value,
99    /// Nullability flag.
100    pub nullable: bool,
101    /// Default value (expression rendered by `SqlWriter`).
102    pub default: DefaultValueType,
103    /// Primary key participation.
104    pub primary_key: PrimaryKeyType,
105    /// Defines the ordering of the rows.
106    pub clustering_key: bool,
107    /// Unique constraint (single column only, composite handled in the `TableDef`).
108    pub unique: bool,
109    /// Foreign key target column.
110    pub references: Option<ColumnRef>,
111    /// Action for deletes.
112    pub on_delete: Option<Action>,
113    /// Action for updates.
114    pub on_update: Option<Action>,
115    /// Passive columns are skipped when generating `INSERT` value lists (DEFAULT used).
116    pub passive: bool,
117    /// Optional human-readable comment.
118    pub comment: &'static str,
119}
120
121impl ColumnDef {
122    /// Column name (as declared in the table definition).
123    pub fn name(&self) -> &'static str {
124        &self.column_ref.name
125    }
126    /// Table name owning this column.
127    pub fn table(&self) -> &'static str {
128        &self.column_ref.table
129    }
130    /// Schema name owning this column (may be empty).
131    pub fn schema(&self) -> &'static str {
132        &self.column_ref.schema
133    }
134}
135
136impl<'a> From<&'a ColumnDef> for &'a ColumnRef {
137    fn from(value: &'a ColumnDef) -> Self {
138        &value.column_ref
139    }
140}
141
142impl OpPrecedence for ColumnRef {
143    fn precedence(&self, _writer: &dyn SqlWriter) -> i32 {
144        1_000_000
145    }
146}
147
148impl Expression for ColumnRef {
149    fn write_query(&self, writer: &dyn SqlWriter, context: &mut Context, out: &mut DynQuery) {
150        writer.write_column_ref(context, out, self);
151    }
152}
153
154impl OpPrecedence for ColumnDef {
155    fn precedence(&self, _writer: &dyn SqlWriter) -> i32 {
156        1_000_000
157    }
158}
159
160impl Expression for ColumnDef {
161    fn write_query(&self, writer: &dyn SqlWriter, context: &mut Context, out: &mut DynQuery) {
162        writer.write_column_ref(context, out, &self.column_ref);
163    }
164}