use std::collections::BTreeMap;
use serde::{Deserialize, Serialize};
use crate::ids::{Namespace, TypeName};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum SpgTypeKind {
BasicType,
StandardType,
EntityType,
IndexType,
ConceptType,
EventType,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum IndexKind {
Text,
Vector,
TextAndVector,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum ValueType {
Text,
Long,
Float,
Date,
Bool,
SmallInt,
Int32,
Decimal,
Time,
Timestamp,
Uuid,
Bytes,
Json,
Array(Box<ValueType>),
Ref(TypeName),
}
impl ValueType {
pub fn from_object_type_name(name: &str) -> Self {
if let Some(inner) = name
.strip_prefix("Array<")
.and_then(|r| r.strip_suffix('>'))
{
return Self::Array(Box::new(Self::from_object_type_name(inner)));
}
match name {
"Text" => Self::Text,
"Integer" | "Long" | "BigInt" => Self::Long,
"Float" | "Double" => Self::Float,
"Date" => Self::Date,
"Boolean" | "Bool" => Self::Bool,
"SmallInt" | "Int16" => Self::SmallInt,
"Int32" | "Int" => Self::Int32,
"Decimal" | "Numeric" => Self::Decimal,
"Time" => Self::Time,
"Timestamp" | "DateTime" | "TimestampTz" => Self::Timestamp,
"Uuid" | "UUID" | "Guid" => Self::Uuid,
"Bytes" | "Binary" | "Blob" => Self::Bytes,
"Json" | "JSONB" | "Object" => Self::Json,
other => Self::Ref(TypeName(other.to_string())),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PropertyDef {
pub name: String,
pub name_zh: Option<String>,
pub value_type: ValueType,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub index: Option<IndexKind>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct RelationDef {
pub name: String,
pub name_zh: Option<String>,
pub target: TypeName,
#[serde(default)]
pub properties: Vec<PropertyDef>,
}
impl RelationDef {
pub fn properties_lookup(&self) -> std::collections::BTreeMap<&str, &PropertyDef> {
self.properties
.iter()
.map(|p| (p.name.as_str(), p))
.collect()
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SchemaType {
pub kind: SpgTypeKind,
pub name: TypeName,
pub name_zh: Option<String>,
pub properties: Vec<PropertyDef>,
pub relations: Vec<RelationDef>,
}
impl SchemaType {
pub fn new(kind: SpgTypeKind, name: TypeName) -> Self {
Self {
kind,
name,
name_zh: None,
properties: Vec::new(),
relations: Vec::new(),
}
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct Schema {
pub types: BTreeMap<TypeName, SchemaType>,
}
impl Schema {
pub fn get(&self, name: &TypeName) -> Option<&SchemaType> {
self.types.get(name)
}
pub fn upsert_all(&mut self, types: impl IntoIterator<Item = SchemaType>) {
for t in types {
self.types.insert(t.name.clone(), t);
}
}
pub fn relation_names(&self) -> Vec<&str> {
self.types
.values()
.flat_map(|t| t.relations.iter().map(|r| r.name.as_str()))
.collect()
}
}
pub fn qualify(ns: &Namespace, label: &str) -> TypeName {
TypeName::qualified(ns, label)
}