From 0f8d3f241427b1c5be7daad930ee1142ff138033 Mon Sep 17 00:00:00 2001 From: Ziyang Hu Date: Mon, 11 Apr 2022 13:10:36 +0800 Subject: [PATCH] the remaining definitions --- src/definition.rs | 94 ++++++++++++++++++++++++++++++++++++++++++++++- src/error.rs | 3 ++ 2 files changed, 96 insertions(+), 1 deletion(-) diff --git a/src/definition.rs b/src/definition.rs index 424467b6..e937604d 100644 --- a/src/definition.rs +++ b/src/definition.rs @@ -4,7 +4,7 @@ use crate::env::Env; use crate::error::Result; use crate::error::CozoError::*; use crate::parser::{Rule}; -use crate::typing::{Col, Edge, Node, Structured, StructuredEnv, StructuredEnvItem, TableId, Typing}; +use crate::typing::{Col, Columns, Edge, Index, Node, Structured, StructuredEnv, StructuredEnvItem, TableId, Typing}; use crate::typing::Persistence::{Global, Local}; use crate::typing::StorageStatus::Planned; use crate::value::Value; @@ -109,6 +109,92 @@ impl StructuredEnvItem { } } + fn build_col_list(&mut self, pair: Pair) -> Result> { + let mut ret = vec![]; + for p in pair.into_inner() { + ret.push(build_name_in_def(p, true)?); + } + Ok(ret) + } + fn build_columns_def(&mut self, pair: Pair, table_id: TableId) -> Result<()> { + let mut inner = pair.into_inner(); + let name = build_name_in_def(inner.next().unwrap(), true)?; + let node_name = build_name_in_def(inner.next().unwrap(), true)?; + let node = self.resolve(&node_name).ok_or(UndefinedType)?; + let node_id = if let Structured::Node(n, _) = node { + n.id + } else if let Structured::Edge(n, _) = node { + n.id + } else { + return Err(WrongType); + }; + let (keys, cols) = self.build_col_defs(inner.next().unwrap())?; + if !keys.is_empty() { + return Err(UnexpectedIndexColumns) + } + if table_id.0 == Global && node_id.0 == Local { + return Err(IncompatibleEdge); + } + + if self.define_new(name, Structured::Columns(Columns { + id: table_id, + attached: node_id, + cols + }, Planned)) { + Ok(()) + } else { + Err(NameConflict) + } + } + + fn build_index_def(&mut self, pair: Pair, table_id: TableId) -> Result<()> { + let mut inner = pair.into_inner(); + let mut name = build_name_in_def(inner.next().unwrap(), true)?; + let node_name; + let nxt = inner.next().unwrap(); + + let col_list = match nxt.as_rule() { + Rule::col_list => { + node_name = name; + name = "_".to_string() + &node_name; + let cols = self.build_col_list(nxt)?; + name.push('_'); + for col in &cols { + name.push('_'); + name += col; + } + cols + } + _ => { + node_name = build_name_in_def(nxt, true)?; + self.build_col_list(inner.next().unwrap())? + } + }; + + let node = self.resolve(&node_name).ok_or(UndefinedType)?; + let node_id = if let Structured::Node(n, _) = node { + n.id + } else { + return Err(WrongType); + }; + if table_id.0 == Global && node_id.0 == Local { + return Err(IncompatibleEdge); + } + + // TODO: make sure cols make sense + + if self.define_new(name, Structured::Index(Index { + id: table_id, + attached: node_id, + cols: col_list, + }, Planned)) { + Ok(()) + } else { + Err(NameConflict) + } + } + + fn build_type(&self, pair: Pair) -> Result { let mut pairs = pair.into_inner(); let mut inner = pairs.next().unwrap(); @@ -201,6 +287,12 @@ impl StructuredEnv { Rule::edge_def => { env_to_build.build_edge_def(inner, next_id)?; } + Rule::columns_def => { + env_to_build.build_columns_def(inner, next_id)?; + } + Rule::index_def => { + env_to_build.build_index_def(inner, next_id)?; + } _ => todo!() } } diff --git a/src/error.rs b/src/error.rs index 589db792..e518eaad 100644 --- a/src/error.rs +++ b/src/error.rs @@ -28,6 +28,9 @@ pub enum CozoError { #[error("Cannot have global edge between local nodes")] IncompatibleEdge, + #[error("Unexpected index columns found")] + UnexpectedIndexColumns, + #[error(transparent)] ParseInt(#[from] std::num::ParseIntError),