tank_core/
column.rs

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