diff --git a/partiql-common/Cargo.toml b/partiql-common/Cargo.toml index 203a3b71..2e487b1b 100644 --- a/partiql-common/Cargo.toml +++ b/partiql-common/Cargo.toml @@ -25,11 +25,13 @@ pretty = "0.12" serde = { version = "1.*", features = ["derive"], optional = true } smallvec = { version = "1.*" } thiserror = "1.0" +dashmap = "6.0" [features] default = [] serde = [ "dep:serde", "indexmap/serde", - "smallvec/serde" + "smallvec/serde", + "dashmap/serde" ] diff --git a/partiql-common/src/node.rs b/partiql-common/src/node.rs index 8f3b5425..bd736f44 100644 --- a/partiql-common/src/node.rs +++ b/partiql-common/src/node.rs @@ -1,11 +1,52 @@ -use indexmap::IndexMap; -use std::hash::Hash; +use dashmap::DashMap; use std::sync::{Arc, RwLock}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; -pub type NodeMap = IndexMap; +#[derive(Debug, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct NodeMap { + map: DashMap, + #[cfg_attr(feature = "serde", serde(skip))] + order: Arc>>, +} + +impl Default for NodeMap { + fn default() -> Self { + Self::new() + } +} + +impl NodeMap { + pub fn new() -> Self { + NodeMap { + map: DashMap::new(), + order: Arc::new(RwLock::new(Vec::new())), + } + } + + pub fn with_capacity(capacity: usize) -> Self { + NodeMap { + map: DashMap::with_capacity(capacity), + order: Arc::new(RwLock::new(Vec::with_capacity(capacity))), + } + } + + pub fn insert(&self, node_id: NodeId, value: T) -> Option { + let mut order = self.order.write().expect("NodeMap order write lock"); + if self.map.contains_key(&node_id) { + self.map.insert(node_id, value) + } else { + order.push(node_id); + self.map.insert(node_id, value) + } + } + + pub fn get(&self, node_id: &NodeId) -> Option> { + self.map.get(node_id) + } +} #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] diff --git a/partiql-eval/Cargo.toml b/partiql-eval/Cargo.toml index 4384d6c4..1ed152c4 100644 --- a/partiql-eval/Cargo.toml +++ b/partiql-eval/Cargo.toml @@ -41,6 +41,9 @@ delegate = "0.12" [dev-dependencies] criterion = "0.4" +[features] +default = [] + [[bench]] name = "bench_eval" harness = false diff --git a/partiql-eval/src/eval/mod.rs b/partiql-eval/src/eval/mod.rs index 5cfe7dce..d693427d 100644 --- a/partiql-eval/src/eval/mod.rs +++ b/partiql-eval/src/eval/mod.rs @@ -146,7 +146,6 @@ pub type EvalResult = Result; /// Represents result of evaluation as an evaluated entity. #[non_exhaustive] #[derive(Debug)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct Evaluated { pub result: Value, } diff --git a/partiql-parser/Cargo.toml b/partiql-parser/Cargo.toml index fa666915..74dbce68 100644 --- a/partiql-parser/Cargo.toml +++ b/partiql-parser/Cargo.toml @@ -36,6 +36,7 @@ bigdecimal = "~0.2.0" rust_decimal = { version = "1.25.0", default-features = false, features = ["std"] } bitflags = "2" +dashmap = "6.0.1" lalrpop-util = "0.20" logos = "0.12" diff --git a/partiql-parser/src/parse/partiql.lalrpop b/partiql-parser/src/parse/partiql.lalrpop index 8aa04b52..ef10a99b 100644 --- a/partiql-parser/src/parse/partiql.lalrpop +++ b/partiql-parser/src/parse/partiql.lalrpop @@ -287,8 +287,8 @@ FromClause: ast::AstNode = { ast::FromSource::Join(node) => node.id, }; - let start = state.locations.get(&start_id).unwrap_or(&total).start.0.clone(); - let end = state.locations.get(&end_id).unwrap_or(&total).end.0.clone(); + let start = state.locations.get(&start_id).map_or(total.start.0.clone(), |v| v.start.0.clone()); + let end = state.locations.get(&end_id).map_or(total.end.0.clone(), |v| v.end.0.clone()); let range = start..end; let join = state.node(ast::Join { kind: ast::JoinKind::Cross,