tank_core/
column.rs

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