Skip to main content

nounsql_core/
ir.rs

1use indexmap::IndexMap;
2
3use crate::dict::Compound;
4use crate::span::Span;
5
6/// 定義がどこから来たか。診断で定義元を指すのに使う。
7#[derive(Debug, Clone)]
8pub enum Origin {
9    /// テーブル定義に直接書かれた。
10    Own,
11    Mixin {
12        name: String,
13        def_span: Span,
14    },
15    Blueprint {
16        name: String,
17        def_span: Span,
18        apply_span: Span,
19    },
20    /// `belongs_to` / `associate` が生成した。
21    Generated {
22        by: String,
23    },
24}
25
26#[derive(Debug, Clone, PartialEq, Eq)]
27pub enum Val {
28    Literal(String),
29    Eval(String),
30}
31
32#[derive(Debug, Clone)]
33pub struct Column {
34    pub name: String,
35    pub ty: String,
36    pub null: bool,
37    pub default: Option<Val>,
38    pub on_update: Option<Val>,
39    pub comment: Option<String>,
40    pub origin: Origin,
41    pub span: Span,
42}
43
44#[derive(Debug, Clone)]
45pub struct Index {
46    pub name: String,
47    pub columns: Vec<String>,
48    pub unique: bool,
49    pub span: Span,
50}
51
52#[derive(Debug, Clone)]
53pub struct ForeignKey {
54    /// FKを持つ側の関連名。DDL には出ない。
55    pub alias: String,
56    pub columns: Vec<String>,
57    pub ref_table: String,
58    pub ref_columns: Vec<String>,
59    pub on_delete: String,
60    pub on_update: String,
61    pub span: Span,
62}
63
64/// 参照される側から見た関連。DDL には出ない。
65#[derive(Debug, Clone)]
66pub struct Reverse {
67    pub alias: String,
68    /// FKを持つテーブル。
69    pub from_table: String,
70    /// 対応するFK列。
71    pub via: Vec<String>,
72    /// one_to_one か。
73    pub unique: bool,
74    pub span: Span,
75}
76
77#[derive(Debug, Clone)]
78pub struct Table {
79    /// 最終テーブル名。
80    pub name: String,
81    /// 由来した名詞。`associate` が生成したテーブルでは None。
82    pub noun: Option<Compound>,
83    pub comment: Option<String>,
84    pub columns: IndexMap<String, Column>,
85    pub pk: Vec<String>,
86    pub indexes: Vec<Index>,
87    pub foreign_keys: Vec<ForeignKey>,
88    pub reverses: Vec<Reverse>,
89    pub origin: Origin,
90    pub span: Span,
91}
92
93#[derive(Debug, Clone, Default)]
94pub struct Schema {
95    pub tables: Vec<Table>,
96}
97
98impl Schema {
99    pub fn table(&self, name: &str) -> Option<&Table> {
100        self.tables.iter().find(|t| t.name == name)
101    }
102
103    /// 単一の名詞から作られたテーブルを引く。
104    pub fn table_by_noun(&self, name: &str) -> Option<&Table> {
105        self.tables
106            .iter()
107            .find(|t| t.noun.as_ref().and_then(Compound::as_single_noun) == Some(name))
108    }
109}