tank_core/
column.rs

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