Skip to main content

rdbi_codegen/parser/
metadata.rs

1//! Metadata structures for parsed SQL schema
2
3use serde::{Deserialize, Serialize};
4
5/// Metadata for a database table
6#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct TableMetadata {
8    /// Table name
9    pub name: String,
10
11    /// Table comment (if any)
12    pub comment: Option<String>,
13
14    /// Columns in the table
15    pub columns: Vec<ColumnMetadata>,
16
17    /// Indexes (excluding primary key)
18    pub indexes: Vec<IndexMetadata>,
19
20    /// Foreign key constraints
21    pub foreign_keys: Vec<ForeignKeyMetadata>,
22
23    /// Primary key (if any)
24    pub primary_key: Option<PrimaryKey>,
25}
26
27/// Metadata for a column
28#[derive(Debug, Clone, Serialize, Deserialize)]
29pub struct ColumnMetadata {
30    /// Column name
31    pub name: String,
32
33    /// Data type as string (e.g., "BIGINT", "VARCHAR(255)")
34    pub data_type: String,
35
36    /// Whether the column is nullable
37    pub nullable: bool,
38
39    /// Default value expression (if any)
40    pub default_value: Option<String>,
41
42    /// Whether this column is auto-increment
43    pub is_auto_increment: bool,
44
45    /// Whether this column is unsigned (for numeric types)
46    pub is_unsigned: bool,
47
48    /// Enum values if this is an ENUM column
49    pub enum_values: Option<Vec<String>>,
50
51    /// Column comment (if any)
52    pub comment: Option<String>,
53}
54
55/// Metadata for an index
56#[derive(Debug, Clone, Serialize, Deserialize)]
57pub struct IndexMetadata {
58    /// Index name
59    pub name: String,
60
61    /// Columns in the index (in order)
62    pub columns: Vec<String>,
63
64    /// Whether this is a unique index
65    pub unique: bool,
66}
67
68/// Primary key definition
69#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct PrimaryKey {
71    /// Columns in the primary key (in order)
72    pub columns: Vec<String>,
73}
74
75impl PrimaryKey {
76    /// Check if this is a composite primary key
77    pub fn is_composite(&self) -> bool {
78        self.columns.len() > 1
79    }
80}
81
82/// Foreign key constraint
83#[derive(Debug, Clone, Serialize, Deserialize)]
84pub struct ForeignKeyMetadata {
85    /// Column name in this table
86    pub column_name: String,
87
88    /// Referenced table name
89    pub referenced_table: String,
90
91    /// Referenced column name
92    pub referenced_column: String,
93}
94
95impl TableMetadata {
96    /// Get a column by name
97    pub fn get_column(&self, name: &str) -> Option<&ColumnMetadata> {
98        self.columns.iter().find(|c| c.name == name)
99    }
100
101    /// Get all indexed columns (single-column indexes only)
102    pub fn get_indexed_columns(&self) -> Vec<&str> {
103        self.indexes
104            .iter()
105            .filter(|idx| idx.columns.len() == 1)
106            .map(|idx| idx.columns[0].as_str())
107            .collect()
108    }
109
110    /// Check if a column is part of the primary key
111    pub fn is_primary_key_column(&self, column_name: &str) -> bool {
112        self.primary_key
113            .as_ref()
114            .map(|pk| pk.columns.contains(&column_name.to_string()))
115            .unwrap_or(false)
116    }
117}
118
119impl ColumnMetadata {
120    /// Check if this column has an enum type
121    pub fn is_enum(&self) -> bool {
122        self.enum_values.is_some()
123    }
124}