kotoba_core/ir/
catalog.rs

1//! Catalog-IR(スキーマ/索引/不変量)
2
3use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5use crate::types::*;
6
7/// プロパティ定義
8#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
9pub struct PropertyDef {
10    pub name: PropertyKey,
11    pub type_: ValueType,
12    pub nullable: bool,
13    #[serde(skip_serializing_if = "Option::is_none")]
14    pub default: Option<Value>,
15}
16
17/// 値型
18#[derive(Debug, Clone, Serialize, Deserialize)]
19pub enum ValueType {
20    #[serde(rename = "null")]
21    Null,
22    #[serde(rename = "bool")]
23    Bool,
24    #[serde(rename = "int")]
25    Int,
26    #[serde(rename = "float")]
27    Float,
28    #[serde(rename = "string")]
29    String,
30    #[serde(rename = "list")]
31    List(Box<ValueType>),
32    #[serde(rename = "map")]
33    Map,
34}
35
36impl PartialEq for ValueType {
37    fn eq(&self, other: &Self) -> bool {
38        match (self, other) {
39            (ValueType::Null, ValueType::Null) => true,
40            (ValueType::Bool, ValueType::Bool) => true,
41            (ValueType::Int, ValueType::Int) => true,
42            (ValueType::Float, ValueType::Float) => true,
43            (ValueType::String, ValueType::String) => true,
44            (ValueType::List(a), ValueType::List(b)) => a == b,
45            (ValueType::Map, ValueType::Map) => true,
46            _ => false,
47        }
48    }
49}
50
51/// ラベル定義
52#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
53pub struct LabelDef {
54    pub name: Label,
55    pub properties: Vec<PropertyDef>,
56    #[serde(skip_serializing_if = "Option::is_none")]
57    pub super_labels: Option<Vec<Label>>,
58}
59
60/// インデックス定義
61#[derive(Debug, Clone, Serialize, Deserialize)]
62pub struct IndexDef {
63    pub name: String,
64    pub label: Label,
65    pub properties: Vec<PropertyKey>,
66    pub unique: bool,
67}
68
69/// 不変条件
70#[derive(Debug, Clone, Serialize, Deserialize)]
71pub struct Invariant {
72    pub name: String,
73    pub expr: String,  // 制約式(GQL風)
74    pub message: String,
75}
76
77/// カタログ
78#[derive(Debug, Clone, Serialize, Deserialize)]
79pub struct Catalog {
80    pub labels: HashMap<Label, LabelDef>,
81    pub indexes: Vec<IndexDef>,
82    pub invariants: Vec<Invariant>,
83}
84
85impl Catalog {
86    /// 空のカタログを作成
87    pub fn empty() -> Self {
88        Self {
89            labels: HashMap::new(),
90            indexes: Vec::new(),
91            invariants: Vec::new(),
92        }
93    }
94
95    /// ラベル定義を追加
96    pub fn add_label(&mut self, def: LabelDef) {
97        self.labels.insert(def.name.clone(), def);
98    }
99
100    /// インデックス定義を追加
101    pub fn add_index(&mut self, def: IndexDef) {
102        self.indexes.push(def);
103    }
104
105    /// 不変条件を追加
106    pub fn add_invariant(&mut self, inv: Invariant) {
107        self.invariants.push(inv);
108    }
109
110    /// ラベル定義を取得
111    pub fn get_label(&self, name: &Label) -> Option<&LabelDef> {
112        self.labels.get(name)
113    }
114
115    /// ラベルのプロパティを取得
116    pub fn get_property_def(&self, label: &Label, prop: &PropertyKey) -> Option<&PropertyDef> {
117        self.labels.get(label)?
118            .properties.iter()
119            .find(|p| p.name == *prop)
120    }
121
122    /// ラベルにプロパティが存在するかチェック
123    pub fn has_property(&self, label: &Label, prop: &PropertyKey) -> bool {
124        self.get_property_def(label, prop).is_some()
125    }
126}