rethink Tuple type

main
Ziyang Hu 2 years ago
parent f5f0683548
commit b16c5db431

@ -22,7 +22,6 @@ use crate::algo::AlgoImpl;
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::program::{MagicAlgoApply, MagicSymbol}; use crate::data::program::{MagicAlgoApply, MagicSymbol};
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::tuple::Tuple;
use crate::data::value::DataValue; use crate::data::value::DataValue;
use crate::parse::SourceSpan; use crate::parse::SourceSpan;
use crate::runtime::db::Poison; use crate::runtime::db::Poison;
@ -87,7 +86,7 @@ impl AlgoImpl for BetweennessCentrality {
for (i, s) in centrality.into_iter().enumerate() { for (i, s) in centrality.into_iter().enumerate() {
let node = indices[i].clone(); let node = indices[i].clone();
out.put(Tuple(vec![node, s.into()]), 0); out.put(vec![node, s.into()], 0);
} }
Ok(()) Ok(())
@ -138,10 +137,7 @@ impl AlgoImpl for ClosenessCentrality {
}) })
.collect::<Result<_>>()?; .collect::<Result<_>>()?;
for (idx, centrality) in res.into_iter().enumerate() { for (idx, centrality) in res.into_iter().enumerate() {
out.put( out.put(vec![indices[idx].clone(), DataValue::from(centrality)], 0);
Tuple(vec![indices[idx].clone(), DataValue::from(centrality)]),
0,
);
poison.check()?; poison.check()?;
} }
Ok(()) Ok(())

@ -61,12 +61,12 @@ impl AlgoImpl for ShortestPathAStar {
poison.clone(), poison.clone(),
)?; )?;
out.put( out.put(
Tuple(vec![ vec![
start.0[0].clone(), start[0].clone(),
goal.0[0].clone(), goal[0].clone(),
DataValue::from(cost), DataValue::from(cost),
DataValue::List(path), DataValue::List(path),
]), ],
0, 0,
); );
} }
@ -95,12 +95,12 @@ fn astar<'a>(
stores: &'a BTreeMap<MagicSymbol, InMemRelation>, stores: &'a BTreeMap<MagicSymbol, InMemRelation>,
poison: Poison, poison: Poison,
) -> Result<(f64, Vec<DataValue>)> { ) -> Result<(f64, Vec<DataValue>)> {
let start_node = &starting.0[0]; let start_node = &starting[0];
let goal_node = &goal.0[0]; let goal_node = &goal[0];
let eval_heuristic = |node: &Tuple| -> Result<f64> { let eval_heuristic = |node: &Tuple| -> Result<f64> {
let mut v = node.0.clone(); let mut v = node.clone();
v.extend_from_slice(&goal.0); v.extend_from_slice(&goal);
let t = Tuple(v); let t = v;
let cost_val = heuristic.eval(&t)?; let cost_val = heuristic.eval(&t)?;
let cost = cost_val.get_float().ok_or_else(|| { let cost = cost_val.get_float().ok_or_else(|| {
BadExprValueError( BadExprValueError(
@ -141,8 +141,8 @@ fn astar<'a>(
for edge in edges.prefix_iter(&node, tx, stores)? { for edge in edges.prefix_iter(&node, tx, stores)? {
let edge = edge?; let edge = edge?;
let edge_dst = &edge.0[1]; let edge_dst = &edge[1];
let edge_cost = edge.0[2].get_float().ok_or_else(|| { let edge_cost = edge[2].get_float().ok_or_else(|| {
BadExprValueError( BadExprValueError(
edge_dst.clone(), edge_dst.clone(),
edges.span(), edges.span(),

@ -15,7 +15,6 @@ use crate::algo::{AlgoImpl, NodeNotFoundError};
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::program::{MagicAlgoApply, MagicSymbol}; use crate::data::program::{MagicAlgoApply, MagicSymbol};
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::tuple::Tuple;
use crate::data::value::DataValue; use crate::data::value::DataValue;
use crate::parse::SourceSpan; use crate::parse::SourceSpan;
use crate::runtime::db::Poison; use crate::runtime::db::Poison;
@ -49,7 +48,7 @@ impl AlgoImpl for Bfs {
'outer: for node_tuple in starting_nodes.iter(tx, stores)? { 'outer: for node_tuple in starting_nodes.iter(tx, stores)? {
let node_tuple = node_tuple?; let node_tuple = node_tuple?;
let starting_node = &node_tuple.0[0]; let starting_node = &node_tuple[0];
if visited.contains(starting_node) { if visited.contains(starting_node) {
continue; continue;
} }
@ -61,7 +60,7 @@ impl AlgoImpl for Bfs {
while let Some(candidate) = queue.pop_back() { while let Some(candidate) = queue.pop_back() {
for edge in edges.prefix_iter(&candidate, tx, stores)? { for edge in edges.prefix_iter(&candidate, tx, stores)? {
let edge = edge?; let edge = edge?;
let to_node = &edge.0[1]; let to_node = &edge[1];
if visited.contains(to_node) { if visited.contains(to_node) {
continue; continue;
} }
@ -70,7 +69,7 @@ impl AlgoImpl for Bfs {
backtrace.insert(to_node.clone(), candidate.clone()); backtrace.insert(to_node.clone(), candidate.clone());
let cand_tuple = if skip_query_nodes { let cand_tuple = if skip_query_nodes {
Tuple(vec![to_node.clone()]) vec![to_node.clone()]
} else { } else {
nodes nodes
.prefix_iter(to_node, tx, stores)? .prefix_iter(to_node, tx, stores)?
@ -103,7 +102,7 @@ impl AlgoImpl for Bfs {
} }
route.push(starting.clone()); route.push(starting.clone());
route.reverse(); route.reverse();
let tuple = Tuple(vec![starting, ending, DataValue::List(route)]); let tuple = vec![starting, ending, DataValue::List(route)];
out.put(tuple, 0); out.put(tuple, 0);
} }
Ok(()) Ok(())

@ -16,7 +16,6 @@ use crate::algo::AlgoImpl;
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::program::{MagicAlgoApply, MagicSymbol, WrongAlgoOptionError}; use crate::data::program::{MagicAlgoApply, MagicSymbol, WrongAlgoOptionError};
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::tuple::Tuple;
use crate::data::value::DataValue; use crate::data::value::DataValue;
use crate::parse::SourceSpan; use crate::parse::SourceSpan;
use crate::runtime::db::Poison; use crate::runtime::db::Poison;
@ -37,7 +36,7 @@ impl AlgoImpl for Constant {
let data = algo.expr_option("data", None).unwrap(); let data = algo.expr_option("data", None).unwrap();
let data = data.get_const().unwrap().get_list().unwrap(); let data = data.get_const().unwrap().get_list().unwrap();
for row in data { for row in data {
let tuple = Tuple(row.get_list().unwrap().into()); let tuple = row.get_list().unwrap().into();
out.put(tuple, 0) out.put(tuple, 0)
} }
Ok(()) Ok(())

@ -22,7 +22,6 @@ use crate::data::program::{
}; };
use crate::data::relation::{ColType, NullableColType}; use crate::data::relation::{ColType, NullableColType};
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::tuple::Tuple;
use crate::data::value::DataValue; use crate::data::value::DataValue;
use crate::parse::{parse_type, SourceSpan}; use crate::parse::{parse_type, SourceSpan};
use crate::runtime::db::Poison; use crate::runtime::db::Poison;
@ -91,16 +90,16 @@ impl AlgoImpl for CsvReader {
types.len() types.len()
}; };
let mut process_row = |row: StringRecord| -> Result<()> { let mut process_row = |row: StringRecord| -> Result<()> {
let mut out_tuple = Tuple(Vec::with_capacity(out_tuple_size)); let mut out_tuple = Vec::with_capacity(out_tuple_size);
if prepend_index { if prepend_index {
counter += 1; counter += 1;
out_tuple.0.push(DataValue::from(counter)); out_tuple.push(DataValue::from(counter));
} }
for (i, typ) in types.iter().enumerate() { for (i, typ) in types.iter().enumerate() {
match row.get(i) { match row.get(i) {
None => { None => {
if typ.nullable { if typ.nullable {
out_tuple.0.push(DataValue::Null) out_tuple.push(DataValue::Null)
} else { } else {
bail!( bail!(
"encountered null value when processing CSV when non-null required" "encountered null value when processing CSV when non-null required"
@ -110,8 +109,8 @@ impl AlgoImpl for CsvReader {
Some(s) => { Some(s) => {
let dv = DataValue::Str(SmartString::from(s)); let dv = DataValue::Str(SmartString::from(s));
match &typ.coltype { match &typ.coltype {
ColType::Any | ColType::String => out_tuple.0.push(dv), ColType::Any | ColType::String => out_tuple.push(dv),
ColType::Uuid => out_tuple.0.push(match op_to_uuid(&[dv]) { ColType::Uuid => out_tuple.push(match op_to_uuid(&[dv]) {
Ok(uuid) => uuid, Ok(uuid) => uuid,
Err(err) => { Err(err) => {
if typ.nullable { if typ.nullable {
@ -121,7 +120,7 @@ impl AlgoImpl for CsvReader {
} }
} }
}), }),
ColType::Float => out_tuple.0.push(match op_to_float(&[dv]) { ColType::Float => out_tuple.push(match op_to_float(&[dv]) {
Ok(data) => data, Ok(data) => data,
Err(err) => { Err(err) => {
if typ.nullable { if typ.nullable {
@ -136,12 +135,12 @@ impl AlgoImpl for CsvReader {
match f.get_int() { match f.get_int() {
None => { None => {
if typ.nullable { if typ.nullable {
out_tuple.0.push(DataValue::Null) out_tuple.push(DataValue::Null)
} else { } else {
bail!("cannot convert {} to type {}", s, typ) bail!("cannot convert {} to type {}", s, typ)
} }
} }
Some(i) => out_tuple.0.push(DataValue::from(i)), Some(i) => out_tuple.push(DataValue::from(i)),
}; };
} }
_ => bail!("cannot convert {} to type {}", s, typ), _ => bail!("cannot convert {} to type {}", s, typ),

@ -15,7 +15,6 @@ use crate::algo::AlgoImpl;
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::program::{MagicAlgoApply, MagicSymbol}; use crate::data::program::{MagicAlgoApply, MagicSymbol};
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::tuple::Tuple;
use crate::data::value::DataValue; use crate::data::value::DataValue;
use crate::parse::SourceSpan; use crate::parse::SourceSpan;
use crate::runtime::db::Poison; use crate::runtime::db::Poison;
@ -39,12 +38,12 @@ impl AlgoImpl for DegreeCentrality {
let mut counter: BTreeMap<DataValue, (usize, usize, usize)> = BTreeMap::new(); let mut counter: BTreeMap<DataValue, (usize, usize, usize)> = BTreeMap::new();
for tuple in it { for tuple in it {
let tuple = tuple?; let tuple = tuple?;
let from = tuple.0[0].clone(); let from = tuple[0].clone();
let (from_total, from_out, _) = counter.entry(from).or_default(); let (from_total, from_out, _) = counter.entry(from).or_default();
*from_total += 1; *from_total += 1;
*from_out += 1; *from_out += 1;
let to = tuple.0[1].clone(); let to = tuple[1].clone();
let (to_total, _, to_in) = counter.entry(to).or_default(); let (to_total, _, to_in) = counter.entry(to).or_default();
*to_total += 1; *to_total += 1;
*to_in += 1; *to_in += 1;
@ -53,7 +52,7 @@ impl AlgoImpl for DegreeCentrality {
if let Ok(nodes) = algo.relation(1) { if let Ok(nodes) = algo.relation(1) {
for tuple in nodes.iter(tx, stores)? { for tuple in nodes.iter(tx, stores)? {
let tuple = tuple?; let tuple = tuple?;
let id = &tuple.0[0]; let id = &tuple[0];
if !counter.contains_key(id) { if !counter.contains_key(id) {
counter.insert(id.clone(), (0, 0, 0)); counter.insert(id.clone(), (0, 0, 0));
} }
@ -61,12 +60,12 @@ impl AlgoImpl for DegreeCentrality {
} }
} }
for (k, (total_d, out_d, in_d)) in counter.into_iter() { for (k, (total_d, out_d, in_d)) in counter.into_iter() {
let tuple = Tuple(vec![ let tuple = vec![
k, k,
DataValue::from(total_d as i64), DataValue::from(total_d as i64),
DataValue::from(out_d as i64), DataValue::from(out_d as i64),
DataValue::from(in_d as i64), DataValue::from(in_d as i64),
]); ];
out.put(tuple, 0); out.put(tuple, 0);
poison.check()?; poison.check()?;
} }

@ -15,7 +15,6 @@ use crate::algo::{AlgoImpl, NodeNotFoundError};
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::program::{MagicAlgoApply, MagicSymbol}; use crate::data::program::{MagicAlgoApply, MagicSymbol};
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::tuple::Tuple;
use crate::data::value::DataValue; use crate::data::value::DataValue;
use crate::parse::SourceSpan; use crate::parse::SourceSpan;
use crate::runtime::db::Poison; use crate::runtime::db::Poison;
@ -49,7 +48,7 @@ impl AlgoImpl for Dfs {
'outer: for node_tuple in starting_nodes.iter(tx, stores)? { 'outer: for node_tuple in starting_nodes.iter(tx, stores)? {
let node_tuple = node_tuple?; let node_tuple = node_tuple?;
let starting_node = &node_tuple.0[0]; let starting_node = &node_tuple[0];
if visited.contains(starting_node) { if visited.contains(starting_node) {
continue; continue;
} }
@ -63,7 +62,7 @@ impl AlgoImpl for Dfs {
} }
let cand_tuple = if skip_query_nodes { let cand_tuple = if skip_query_nodes {
Tuple(vec![candidate.clone()]) vec![candidate.clone()]
} else { } else {
nodes nodes
.prefix_iter(&candidate, tx, stores)? .prefix_iter(&candidate, tx, stores)?
@ -85,7 +84,7 @@ impl AlgoImpl for Dfs {
for edge in edges.prefix_iter(&candidate, tx, stores)? { for edge in edges.prefix_iter(&candidate, tx, stores)? {
let edge = edge?; let edge = edge?;
let to_node = &edge.0[1]; let to_node = &edge[1];
if visited.contains(to_node) { if visited.contains(to_node) {
continue; continue;
} }
@ -105,7 +104,7 @@ impl AlgoImpl for Dfs {
} }
route.push(starting.clone()); route.push(starting.clone());
route.reverse(); route.reverse();
let tuple = Tuple(vec![starting, ending, DataValue::List(route)]); let tuple = vec![starting, ending, DataValue::List(route)];
out.put(tuple, 0); out.put(tuple, 0);
poison.check()?; poison.check()?;
} }

@ -25,7 +25,6 @@ use crate::data::expr::Expr;
use crate::data::json::JsonValue; use crate::data::json::JsonValue;
use crate::data::program::{MagicAlgoApply, MagicSymbol}; use crate::data::program::{MagicAlgoApply, MagicSymbol};
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::tuple::Tuple;
use crate::data::value::DataValue; use crate::data::value::DataValue;
use crate::parse::SourceSpan; use crate::parse::SourceSpan;
use crate::runtime::db::Poison; use crate::runtime::db::Poison;
@ -86,7 +85,7 @@ impl AlgoImpl for JsonReader {
}; };
ret.push(val); ret.push(val);
} }
out.put(Tuple(ret), 0); out.put(ret, 0);
Ok(()) Ok(())
}; };
match url.strip_prefix("file://") { match url.strip_prefix("file://") {

@ -19,7 +19,6 @@ use crate::algo::AlgoImpl;
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::program::{MagicAlgoApply, MagicSymbol}; use crate::data::program::{MagicAlgoApply, MagicSymbol};
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::tuple::Tuple;
use crate::data::value::DataValue; use crate::data::value::DataValue;
use crate::parse::SourceSpan; use crate::parse::SourceSpan;
use crate::runtime::db::Poison; use crate::runtime::db::Poison;
@ -46,11 +45,11 @@ impl AlgoImpl for MinimumSpanningForestKruskal {
let msp = kruskal(&graph, poison)?; let msp = kruskal(&graph, poison)?;
for (src, dst, cost) in msp { for (src, dst, cost) in msp {
out.put( out.put(
Tuple(vec![ vec![
indices[src].clone(), indices[src].clone(),
indices[dst].clone(), indices[dst].clone(),
DataValue::from(cost), DataValue::from(cost),
]), ],
0, 0,
); );
} }

@ -17,7 +17,6 @@ use crate::algo::AlgoImpl;
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::program::{MagicAlgoApply, MagicSymbol}; use crate::data::program::{MagicAlgoApply, MagicSymbol};
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::tuple::Tuple;
use crate::data::value::DataValue; use crate::data::value::DataValue;
use crate::parse::SourceSpan; use crate::parse::SourceSpan;
use crate::runtime::db::Poison; use crate::runtime::db::Poison;
@ -43,7 +42,7 @@ impl AlgoImpl for LabelPropagation {
let labels = label_propagation(&graph, max_iter, poison)?; let labels = label_propagation(&graph, max_iter, poison)?;
for (idx, label) in labels.into_iter().enumerate() { for (idx, label) in labels.into_iter().enumerate() {
let node = indices[idx].clone(); let node = indices[idx].clone();
out.put(Tuple(vec![DataValue::from(label as i64), node]), 0); out.put(vec![DataValue::from(label as i64), node], 0);
} }
Ok(()) Ok(())
} }

@ -17,7 +17,6 @@ use crate::algo::AlgoImpl;
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::program::{MagicAlgoApply, MagicSymbol}; use crate::data::program::{MagicAlgoApply, MagicSymbol};
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::tuple::Tuple;
use crate::data::value::DataValue; use crate::data::value::DataValue;
use crate::parse::SourceSpan; use crate::parse::SourceSpan;
use crate::runtime::db::Poison; use crate::runtime::db::Poison;
@ -66,7 +65,7 @@ impl AlgoImpl for CommunityDetectionLouvain {
if let Some(l) = keep_depth { if let Some(l) = keep_depth {
labels.truncate(l); labels.truncate(l);
} }
out.put(Tuple(vec![DataValue::List(labels), node]), 0); out.put(vec![DataValue::List(labels), node], 0);
} }
Ok(()) Ok(())

@ -51,7 +51,7 @@ use crate::algo::yen::KShortestPathYen;
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::program::{MagicAlgoApply, MagicAlgoRuleArg, MagicSymbol}; use crate::data::program::{MagicAlgoApply, MagicAlgoRuleArg, MagicSymbol};
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::tuple::{Tuple, TupleIter}; use crate::data::tuple::TupleIter;
use crate::data::value::DataValue; use crate::data::value::DataValue;
use crate::parse::SourceSpan; use crate::parse::SourceSpan;
use crate::runtime::db::Poison; use crate::runtime::db::Poison;
@ -263,7 +263,7 @@ impl MagicAlgoRuleArg {
let mut has_neg_edge = false; let mut has_neg_edge = false;
for tuple in self.iter(tx, stores)? { for tuple in self.iter(tx, stores)? {
let mut tuple = tuple?.0.into_iter(); let mut tuple = tuple?.into_iter();
let from = tuple.next().ok_or_else(|| NotAnEdgeError(self.span()))?; let from = tuple.next().ok_or_else(|| NotAnEdgeError(self.span()))?;
let to = tuple.next().ok_or_else(|| NotAnEdgeError(self.span()))?; let to = tuple.next().ok_or_else(|| NotAnEdgeError(self.span()))?;
let weight = match tuple.next() { let weight = match tuple.next() {
@ -342,7 +342,7 @@ impl MagicAlgoRuleArg {
let mut inv_indices: BTreeMap<DataValue, usize> = Default::default(); let mut inv_indices: BTreeMap<DataValue, usize> = Default::default();
for tuple in self.iter(tx, stores)? { for tuple in self.iter(tx, stores)? {
let mut tuple = tuple?.0.into_iter(); let mut tuple = tuple?.into_iter();
let from = tuple.next().ok_or_else(|| NotAnEdgeError(self.span()))?; let from = tuple.next().ok_or_else(|| NotAnEdgeError(self.span()))?;
let to = tuple.next().ok_or_else(|| NotAnEdgeError(self.span()))?; let to = tuple.next().ok_or_else(|| NotAnEdgeError(self.span()))?;
let from_idx = if let Some(idx) = inv_indices.get(&from) { let from_idx = if let Some(idx) = inv_indices.get(&from) {
@ -382,12 +382,12 @@ impl MagicAlgoRuleArg {
let store = stores.get(name).ok_or_else(|| { let store = stores.get(name).ok_or_else(|| {
RuleNotFoundError(name.symbol().to_string(), name.symbol().span) RuleNotFoundError(name.symbol().to_string(), name.symbol().span)
})?; })?;
let t = Tuple(vec![prefix.clone()]); let t = vec![prefix.clone()];
Box::new(store.scan_prefix(&t)) Box::new(store.scan_prefix(&t))
} }
MagicAlgoRuleArg::Stored { name, .. } => { MagicAlgoRuleArg::Stored { name, .. } => {
let relation = tx.get_relation(name, false)?; let relation = tx.get_relation(name, false)?;
let t = Tuple(vec![prefix.clone()]); let t = vec![prefix.clone()];
Box::new(relation.scan_prefix(tx, &t)) Box::new(relation.scan_prefix(tx, &t))
} }
}) })

@ -21,7 +21,6 @@ use crate::algo::AlgoImpl;
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::program::{MagicAlgoApply, MagicSymbol}; use crate::data::program::{MagicAlgoApply, MagicSymbol};
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::tuple::Tuple;
use crate::data::value::DataValue; use crate::data::value::DataValue;
use crate::parse::SourceSpan; use crate::parse::SourceSpan;
use crate::runtime::db::Poison; use crate::runtime::db::Poison;
@ -66,7 +65,7 @@ impl AlgoImpl for PageRank {
for (idx, score) in ranks.iter().enumerate() { for (idx, score) in ranks.iter().enumerate() {
out.put( out.put(
Tuple(vec![indices[idx].clone(), DataValue::from(*score as f64)]), vec![indices[idx].clone(), DataValue::from(*score as f64)],
0, 0,
); );
} }

@ -20,7 +20,6 @@ use crate::algo::AlgoImpl;
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::program::{MagicAlgoApply, MagicSymbol}; use crate::data::program::{MagicAlgoApply, MagicSymbol};
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::tuple::Tuple;
use crate::data::value::DataValue; use crate::data::value::DataValue;
use crate::parse::SourceSpan; use crate::parse::SourceSpan;
use crate::runtime::db::Poison; use crate::runtime::db::Poison;
@ -55,7 +54,7 @@ impl AlgoImpl for MinimumSpanningTreePrim {
EmptyStarting(rel.span()) EmptyStarting(rel.span())
})??; })??;
let dv = &tuple.0[0]; let dv = &tuple[0];
*inv_indices.get(dv).ok_or_else(|| { *inv_indices.get(dv).ok_or_else(|| {
#[derive(Debug, Error, Diagnostic)] #[derive(Debug, Error, Diagnostic)]
#[error("The requested starting node {0:?} is not found")] #[error("The requested starting node {0:?} is not found")]
@ -69,11 +68,11 @@ impl AlgoImpl for MinimumSpanningTreePrim {
let msp = prim(&graph, starting, poison)?; let msp = prim(&graph, starting, poison)?;
for (src, dst, cost) in msp { for (src, dst, cost) in msp {
out.put( out.put(
Tuple(vec![ vec![
indices[src].clone(), indices[src].clone(),
indices[dst].clone(), indices[dst].clone(),
DataValue::from(cost), DataValue::from(cost),
]), ],
0, 0,
); );
} }

@ -18,7 +18,6 @@ use crate::algo::{AlgoImpl, BadExprValueError, NodeNotFoundError};
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::program::{MagicAlgoApply, MagicSymbol}; use crate::data::program::{MagicAlgoApply, MagicSymbol};
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::tuple::Tuple;
use crate::data::value::DataValue; use crate::data::value::DataValue;
use crate::parse::SourceSpan; use crate::parse::SourceSpan;
use crate::runtime::db::Poison; use crate::runtime::db::Poison;
@ -55,7 +54,7 @@ impl AlgoImpl for RandomWalk {
let mut rng = thread_rng(); let mut rng = thread_rng();
for start_node in starting.iter(tx, stores)? { for start_node in starting.iter(tx, stores)? {
let start_node = start_node?; let start_node = start_node?;
let start_node_key = &start_node.0[0]; let start_node_key = &start_node[0];
let starting_tuple = nodes let starting_tuple = nodes
.prefix_iter(start_node_key, tx, stores)? .prefix_iter(start_node_key, tx, stores)?
.next() .next()
@ -68,7 +67,7 @@ impl AlgoImpl for RandomWalk {
let mut current_tuple = starting_tuple.clone(); let mut current_tuple = starting_tuple.clone();
let mut path = vec![start_node_key.clone()]; let mut path = vec![start_node_key.clone()];
for _ in 0..steps { for _ in 0..steps {
let cur_node_key = &current_tuple.0[0]; let cur_node_key = &current_tuple[0];
let candidate_steps: Vec<_> = let candidate_steps: Vec<_> =
edges.prefix_iter(cur_node_key, tx, stores)?.try_collect()?; edges.prefix_iter(cur_node_key, tx, stores)?.try_collect()?;
if candidate_steps.is_empty() { if candidate_steps.is_empty() {
@ -79,7 +78,7 @@ impl AlgoImpl for RandomWalk {
.iter() .iter()
.map(|t| -> Result<f64> { .map(|t| -> Result<f64> {
let mut cand = current_tuple.clone(); let mut cand = current_tuple.clone();
cand.0.extend_from_slice(&t.0); cand.extend_from_slice(&t);
Ok(match weight_expr.eval(&cand)? { Ok(match weight_expr.eval(&cand)? {
DataValue::Num(n) => { DataValue::Num(n) => {
let f = n.get_float(); let f = n.get_float();
@ -108,7 +107,7 @@ impl AlgoImpl for RandomWalk {
} else { } else {
candidate_steps.choose(&mut rng).unwrap() candidate_steps.choose(&mut rng).unwrap()
}; };
let next_node = &next_step.0[1]; let next_node = &next_step[1];
path.push(next_node.clone()); path.push(next_node.clone());
current_tuple = nodes current_tuple = nodes
.prefix_iter(next_node, tx, stores)? .prefix_iter(next_node, tx, stores)?
@ -120,11 +119,11 @@ impl AlgoImpl for RandomWalk {
poison.check()?; poison.check()?;
} }
out.put( out.put(
Tuple(vec![ vec![
DataValue::from(counter), DataValue::from(counter),
start_node_key.clone(), start_node_key.clone(),
DataValue::List(path), DataValue::List(path),
]), ],
0, 0,
); );
} }

@ -17,7 +17,6 @@ use crate::data::expr::Expr;
use crate::data::functions::OP_LIST; use crate::data::functions::OP_LIST;
use crate::data::program::{MagicAlgoApply, MagicSymbol, WrongAlgoOptionError}; use crate::data::program::{MagicAlgoApply, MagicSymbol, WrongAlgoOptionError};
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::tuple::Tuple;
use crate::data::value::DataValue; use crate::data::value::DataValue;
use crate::parse::SourceSpan; use crate::parse::SourceSpan;
use crate::runtime::db::Poison; use crate::runtime::db::Poison;
@ -117,7 +116,7 @@ impl AlgoImpl for ReorderSort {
} }
let mut out_t = vec![DataValue::from(if break_ties { count } else { rank } as i64)]; let mut out_t = vec![DataValue::from(if break_ties { count } else { rank } as i64)];
out_t.extend_from_slice(&val[0..val.len() - 1]); out_t.extend_from_slice(&val[0..val.len() - 1]);
out.put(Tuple(out_t), 0); out.put(out_t, 0);
poison.check()?; poison.check()?;
} }
Ok(()) Ok(())

@ -23,7 +23,6 @@ use crate::algo::AlgoImpl;
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::program::{MagicAlgoApply, MagicSymbol}; use crate::data::program::{MagicAlgoApply, MagicSymbol};
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::tuple::Tuple;
use crate::data::value::DataValue; use crate::data::value::DataValue;
use crate::parse::SourceSpan; use crate::parse::SourceSpan;
use crate::runtime::db::Poison; use crate::runtime::db::Poison;
@ -53,7 +52,7 @@ impl AlgoImpl for ShortestPathDijkstra {
let mut starting_nodes = BTreeSet::new(); let mut starting_nodes = BTreeSet::new();
for tuple in starting.iter(tx, stores)? { for tuple in starting.iter(tx, stores)? {
let tuple = tuple?; let tuple = tuple?;
let node = &tuple.0[0]; let node = &tuple[0];
if let Some(idx) = inv_indices.get(node) { if let Some(idx) = inv_indices.get(node) {
starting_nodes.insert(*idx); starting_nodes.insert(*idx);
} }
@ -64,7 +63,7 @@ impl AlgoImpl for ShortestPathDijkstra {
let mut tn = BTreeSet::new(); let mut tn = BTreeSet::new();
for tuple in t.iter(tx, stores)? { for tuple in t.iter(tx, stores)? {
let tuple = tuple?; let tuple = tuple?;
let node = &tuple.0[0]; let node = &tuple[0];
if let Some(idx) = inv_indices.get(node) { if let Some(idx) = inv_indices.get(node) {
tn.insert(*idx); tn.insert(*idx);
} }
@ -98,7 +97,7 @@ impl AlgoImpl for ShortestPathDijkstra {
DataValue::from(cost), DataValue::from(cost),
DataValue::List(path.into_iter().map(|u| indices[u].clone()).collect_vec()), DataValue::List(path.into_iter().map(|u| indices[u].clone()).collect_vec()),
]; ];
out.put(Tuple(t), 0) out.put(t, 0)
} }
} }
} else { } else {
@ -145,7 +144,7 @@ impl AlgoImpl for ShortestPathDijkstra {
DataValue::from(cost), DataValue::from(cost),
DataValue::List(path.into_iter().map(|u| indices[u].clone()).collect_vec()), DataValue::List(path.into_iter().map(|u| indices[u].clone()).collect_vec()),
]; ];
out.put(Tuple(t), 0) out.put(t, 0)
} }
} }
} }

@ -55,7 +55,7 @@ impl AlgoImpl for StronglyConnectedComponent {
for (grp_id, cc) in tarjan.iter().enumerate() { for (grp_id, cc) in tarjan.iter().enumerate() {
for idx in cc { for idx in cc {
let val = indices.get(*idx).unwrap(); let val = indices.get(*idx).unwrap();
let tuple = Tuple(vec![val.clone(), DataValue::from(grp_id as i64)]); let tuple = vec![val.clone(), DataValue::from(grp_id as i64)];
out.put(tuple, 0); out.put(tuple, 0);
} }
} }
@ -65,10 +65,10 @@ impl AlgoImpl for StronglyConnectedComponent {
if let Ok(nodes) = algo.relation(1) { if let Ok(nodes) = algo.relation(1) {
for tuple in nodes.iter(tx, stores)? { for tuple in nodes.iter(tx, stores)? {
let tuple = tuple?; let tuple = tuple?;
let node = tuple.0.into_iter().next().unwrap(); let node = tuple.into_iter().next().unwrap();
if !inv_indices.contains_key(&node) { if !inv_indices.contains_key(&node) {
inv_indices.insert(node.clone(), usize::MAX); inv_indices.insert(node.clone(), usize::MAX);
let tuple = Tuple(vec![node, DataValue::from(counter)]); let tuple = vec![node, DataValue::from(counter)];
out.put(tuple, 0); out.put(tuple, 0);
counter += 1; counter += 1;
} }

@ -15,7 +15,6 @@ use crate::algo::AlgoImpl;
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::program::{MagicAlgoApply, MagicSymbol}; use crate::data::program::{MagicAlgoApply, MagicSymbol};
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::tuple::Tuple;
use crate::data::value::DataValue; use crate::data::value::DataValue;
use crate::parse::SourceSpan; use crate::parse::SourceSpan;
use crate::runtime::db::Poison; use crate::runtime::db::Poison;
@ -41,7 +40,7 @@ impl AlgoImpl for TopSort {
for (idx, val_id) in sorted.iter().enumerate() { for (idx, val_id) in sorted.iter().enumerate() {
let val = indices.get(*val_id).unwrap(); let val = indices.get(*val_id).unwrap();
let tuple = Tuple(vec![DataValue::from(idx as i64), val.clone()]); let tuple = vec![DataValue::from(idx as i64), val.clone()];
out.put(tuple, 0); out.put(tuple, 0);
} }

@ -17,7 +17,6 @@ use crate::algo::AlgoImpl;
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::program::{MagicAlgoApply, MagicSymbol}; use crate::data::program::{MagicAlgoApply, MagicSymbol};
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::tuple::Tuple;
use crate::data::value::DataValue; use crate::data::value::DataValue;
use crate::parse::SourceSpan; use crate::parse::SourceSpan;
use crate::runtime::db::Poison; use crate::runtime::db::Poison;
@ -42,12 +41,12 @@ impl AlgoImpl for ClusteringCoefficients {
let coefficients = clustering_coefficients(&graph, poison)?; let coefficients = clustering_coefficients(&graph, poison)?;
for (idx, (cc, n_triangles, degree)) in coefficients.into_iter().enumerate() { for (idx, (cc, n_triangles, degree)) in coefficients.into_iter().enumerate() {
out.put( out.put(
Tuple(vec![ vec![
indices[idx].clone(), indices[idx].clone(),
DataValue::from(cc), DataValue::from(cc),
DataValue::from(n_triangles as i64), DataValue::from(n_triangles as i64),
DataValue::from(degree as i64), DataValue::from(degree as i64),
]), ],
0, 0,
); );
} }

@ -19,7 +19,6 @@ use crate::algo::AlgoImpl;
use crate::data::expr::Expr; use crate::data::expr::Expr;
use crate::data::program::{MagicAlgoApply, MagicSymbol}; use crate::data::program::{MagicAlgoApply, MagicSymbol};
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::tuple::Tuple;
use crate::data::value::DataValue; use crate::data::value::DataValue;
use crate::parse::SourceSpan; use crate::parse::SourceSpan;
use crate::runtime::db::Poison; use crate::runtime::db::Poison;
@ -49,7 +48,7 @@ impl AlgoImpl for KShortestPathYen {
let mut starting_nodes = BTreeSet::new(); let mut starting_nodes = BTreeSet::new();
for tuple in starting.iter(tx, stores)? { for tuple in starting.iter(tx, stores)? {
let tuple = tuple?; let tuple = tuple?;
let node = &tuple.0[0]; let node = &tuple[0];
if let Some(idx) = inv_indices.get(node) { if let Some(idx) = inv_indices.get(node) {
starting_nodes.insert(*idx); starting_nodes.insert(*idx);
} }
@ -57,7 +56,7 @@ impl AlgoImpl for KShortestPathYen {
let mut termination_nodes = BTreeSet::new(); let mut termination_nodes = BTreeSet::new();
for tuple in termination.iter(tx, stores)? { for tuple in termination.iter(tx, stores)? {
let tuple = tuple?; let tuple = tuple?;
let node = &tuple.0[0]; let node = &tuple[0];
if let Some(idx) = inv_indices.get(node) { if let Some(idx) = inv_indices.get(node) {
termination_nodes.insert(*idx); termination_nodes.insert(*idx);
} }
@ -76,7 +75,7 @@ impl AlgoImpl for KShortestPathYen {
path.into_iter().map(|u| indices[u].clone()).collect_vec(), path.into_iter().map(|u| indices[u].clone()).collect_vec(),
), ),
]; ];
out.put(Tuple(t), 0) out.put(t, 0)
} }
} }
} }
@ -107,7 +106,7 @@ impl AlgoImpl for KShortestPathYen {
DataValue::from(cost), DataValue::from(cost),
DataValue::List(path.into_iter().map(|u| indices[u].clone()).collect_vec()), DataValue::List(path.into_iter().map(|u| indices[u].clone()).collect_vec()),
]; ];
out.put(Tuple(t), 0) out.put(t, 0)
} }
} }
} }

@ -253,7 +253,7 @@ impl Expr {
all_evaluated = all_evaluated && matches!(arg, Expr::Const { .. }); all_evaluated = all_evaluated && matches!(arg, Expr::Const { .. });
} }
if all_evaluated { if all_evaluated {
let result = self.eval(&Tuple(vec![]))?; let result = self.eval(&vec![])?;
mem::swap(self, &mut Expr::Const { val: result, span }); mem::swap(self, &mut Expr::Const { val: result, span });
} }
// nested not's can accumulate during conversion to normal form // nested not's can accumulate during conversion to normal form
@ -328,10 +328,9 @@ impl Expr {
struct TupleTooShortError(String, usize, usize, #[label] SourceSpan); struct TupleTooShortError(String, usize, usize, #[label] SourceSpan);
Ok(bindings Ok(bindings
.0
.get(*i) .get(*i)
.ok_or_else(|| { .ok_or_else(|| {
TupleTooShortError(var.name.to_string(), *i, bindings.0.len(), var.span) TupleTooShortError(var.name.to_string(), *i, bindings.len(), var.span)
})? })?
.clone()) .clone())
} }

@ -6,37 +6,33 @@
* You can obtain one at https://mozilla.org/MPL/2.0/. * You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
use std::fmt::{Debug, Formatter};
use miette::Result; use miette::Result;
use crate::data::memcmp::MemCmpEncoder; use crate::data::memcmp::MemCmpEncoder;
use crate::data::value::DataValue; use crate::data::value::DataValue;
use crate::runtime::relation::RelationId; use crate::runtime::relation::RelationId;
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Default)] pub type Tuple = Vec<DataValue>;
pub struct Tuple(pub(crate) Vec<DataValue>);
impl Debug for Tuple {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_list().entries(&self.0).finish()
}
}
pub(crate) type TupleIter<'a> = Box<dyn Iterator<Item = Result<Tuple>> + 'a>; pub(crate) type TupleIter<'a> = Box<dyn Iterator<Item = Result<Tuple>> + 'a>;
impl Tuple { pub(crate) trait TupleT {
pub(crate) fn encode_as_key(&self, prefix: RelationId) -> Vec<u8> { fn encode_as_key(&self, prefix: RelationId) -> Vec<u8>;
let len = self.0.len(); fn decode_from_key(key: &[u8]) -> Self;
}
impl TupleT for Tuple {
fn encode_as_key(&self, prefix: RelationId) -> Vec<u8> {
let len = self.len();
let mut ret = Vec::with_capacity(4 + 4 * len + 10 * len); let mut ret = Vec::with_capacity(4 + 4 * len + 10 * len);
let prefix_bytes = prefix.0.to_be_bytes(); let prefix_bytes = prefix.0.to_be_bytes();
ret.extend(prefix_bytes); ret.extend(prefix_bytes);
for val in self.0.iter() { for val in self.iter() {
ret.encode_datavalue(val); ret.encode_datavalue(val);
} }
ret ret
} }
pub(crate) fn decode_from_key(key: &[u8]) -> Self { fn decode_from_key(key: &[u8]) -> Self {
let mut remaining = &key[ENCODED_KEY_MIN_LEN..]; let mut remaining = &key[ENCODED_KEY_MIN_LEN..];
let mut ret = vec![]; let mut ret = vec![];
while !remaining.is_empty() { while !remaining.is_empty() {
@ -44,7 +40,7 @@ impl Tuple {
ret.push(val); ret.push(val);
remaining = next; remaining = next;
} }
Tuple(ret) ret
} }
} }
pub(crate) const ENCODED_KEY_MIN_LEN: usize = 8; pub(crate) const ENCODED_KEY_MIN_LEN: usize = 8;

@ -87,7 +87,7 @@ impl PartialOrd for RegexWrapper {
#[derive( #[derive(
Clone, PartialEq, Eq, PartialOrd, Ord, serde_derive::Deserialize, serde_derive::Serialize, Hash, Clone, PartialEq, Eq, PartialOrd, Ord, serde_derive::Deserialize, serde_derive::Serialize, Hash,
)] )]
pub(crate) enum DataValue { pub enum DataValue {
Null, Null,
Bool(bool), Bool(bool),
Num(Num), Num(Num),

@ -232,7 +232,7 @@ impl<'a> SessionTx<'a> {
.filter_map(|(i, a)| if a.is_none() { Some(i) } else { None }) .filter_map(|(i, a)| if a.is_none() { Some(i) } else { None })
.collect_vec(); .collect_vec();
let extract_keys = |t: &Tuple| -> Vec<DataValue> { let extract_keys = |t: &Tuple| -> Vec<DataValue> {
keys_indices.iter().map(|i| t.0[*i].clone()).collect_vec() keys_indices.iter().map(|i| t[*i].clone()).collect_vec()
}; };
let val_indices_and_aggrs = rule let val_indices_and_aggrs = rule
@ -261,7 +261,7 @@ impl<'a> SessionTx<'a> {
.normal_op .normal_op
.as_mut() .as_mut()
.unwrap() .unwrap()
.set(&item.0[*tuple_idx])?; .set(&item[*tuple_idx])?;
} }
} }
Entry::Vacant(ent) => { Entry::Vacant(ent) => {
@ -269,7 +269,7 @@ impl<'a> SessionTx<'a> {
for (i, (aggr, params)) in &val_indices_and_aggrs { for (i, (aggr, params)) in &val_indices_and_aggrs {
let mut cur_aggr = aggr.clone(); let mut cur_aggr = aggr.clone();
cur_aggr.normal_init(params)?; cur_aggr.normal_init(params)?;
cur_aggr.normal_op.as_mut().unwrap().set(&item.0[*i])?; cur_aggr.normal_op.as_mut().unwrap().set(&item[*i])?;
aggr_ops.push(cur_aggr) aggr_ops.push(cur_aggr)
} }
ent.insert(aggr_ops); ent.insert(aggr_ops);
@ -305,7 +305,7 @@ impl<'a> SessionTx<'a> {
} }
}) })
.try_collect()?; .try_collect()?;
let tuple = Tuple(tuple_data); let tuple = tuple_data;
if should_check_limit { if should_check_limit {
if !store.exists(&tuple, 0) { if !store.exists(&tuple, 0) {
store.put_with_skip(tuple, limiter.should_skip_next()); store.put_with_skip(tuple, limiter.should_skip_next());

@ -71,19 +71,17 @@ struct EntityIdExpected(DataValue, #[label] SourceSpan);
fn eliminate_from_tuple(mut ret: Tuple, eliminate_indices: &BTreeSet<usize>) -> Tuple { fn eliminate_from_tuple(mut ret: Tuple, eliminate_indices: &BTreeSet<usize>) -> Tuple {
if !eliminate_indices.is_empty() { if !eliminate_indices.is_empty() {
ret = Tuple( ret = ret
ret.0 .into_iter()
.into_iter() .enumerate()
.enumerate() .filter_map(|(i, v)| {
.filter_map(|(i, v)| { if eliminate_indices.contains(&i) {
if eliminate_indices.contains(&i) { None
None } else {
} else { Some(v)
Some(v) }
} })
}) .collect_vec();
.collect_vec(),
);
} }
ret ret
} }
@ -137,9 +135,9 @@ impl UnificationRA {
})?; })?;
let mut coll = vec![]; let mut coll = vec![];
for result in result_list { for result in result_list {
let mut ret = tuple.0.clone(); let mut ret = tuple.clone();
ret.push(result.clone()); ret.push(result.clone());
let ret = Tuple(ret); let ret = ret;
let ret = eliminate_from_tuple(ret, &eliminate_indices); let ret = eliminate_from_tuple(ret, &eliminate_indices);
coll.push(ret); coll.push(ret);
} }
@ -154,9 +152,9 @@ impl UnificationRA {
.iter(tx, epoch, use_delta)? .iter(tx, epoch, use_delta)?
.map_ok(move |tuple| -> Result<Tuple> { .map_ok(move |tuple| -> Result<Tuple> {
let result = self.expr.eval(&tuple)?; let result = self.expr.eval(&tuple)?;
let mut ret = tuple.0; let mut ret = tuple;
ret.push(result); ret.push(result);
let ret = Tuple(ret); let ret = ret;
let ret = eliminate_from_tuple(ret, &eliminate_indices); let ret = eliminate_from_tuple(ret, &eliminate_indices);
Ok(ret) Ok(ret)
}) })
@ -575,12 +573,12 @@ impl ReorderRA {
.collect_vec(); .collect_vec();
Ok(Box::new(self.relation.iter(tx, epoch, use_delta)?.map_ok( Ok(Box::new(self.relation.iter(tx, epoch, use_delta)?.map_ok(
move |tuple| { move |tuple| {
let old = tuple.0; let old = tuple;
let new = reorder_indices let new = reorder_indices
.iter() .iter()
.map(|i| old[*i].clone()) .map(|i| old[*i].clone())
.collect_vec(); .collect_vec();
Tuple(new) new
}, },
))) )))
} }
@ -638,11 +636,11 @@ impl InlineFixedRA {
.map(|v| data[v].clone()) .map(|v| data[v].clone())
.collect_vec(); .collect_vec();
Box::new(left_iter.filter_map_ok(move |tuple| { Box::new(left_iter.filter_map_ok(move |tuple| {
let left_join_values = left_join_indices.iter().map(|v| &tuple.0[*v]).collect_vec(); let left_join_values = left_join_indices.iter().map(|v| &tuple[*v]).collect_vec();
if left_join_values.into_iter().eq(right_join_values.iter()) { if left_join_values.into_iter().eq(right_join_values.iter()) {
let mut ret = tuple.0; let mut ret = tuple;
ret.extend_from_slice(&data); ret.extend_from_slice(&data);
let ret = Tuple(ret); let ret = ret;
let ret = eliminate_from_tuple(ret, &eliminate_indices); let ret = eliminate_from_tuple(ret, &eliminate_indices);
Some(ret) Some(ret)
} else { } else {
@ -666,13 +664,13 @@ impl InlineFixedRA {
left_iter left_iter
.filter_map_ok(move |tuple| { .filter_map_ok(move |tuple| {
let left_join_values = let left_join_values =
left_join_indices.iter().map(|v| &tuple.0[*v]).collect_vec(); left_join_indices.iter().map(|v| &tuple[*v]).collect_vec();
right_mapping.get(&left_join_values).map(|v| { right_mapping.get(&left_join_values).map(|v| {
v.iter() v.iter()
.map(|right_values| { .map(|right_values| {
let mut left_data = tuple.0.clone(); let mut left_data = tuple.clone();
left_data.extend_from_slice(right_values); left_data.extend_from_slice(right_values);
Tuple(left_data) left_data
}) })
.collect_vec() .collect_vec()
}) })
@ -775,12 +773,10 @@ impl StoredRA {
let mut skip_range_check = false; let mut skip_range_check = false;
let it = left_iter let it = left_iter
.map_ok(move |tuple| { .map_ok(move |tuple| {
let prefix = Tuple( let prefix = left_to_prefix_indices
left_to_prefix_indices .iter()
.iter() .map(|i| tuple[*i].clone())
.map(|i| tuple.0[*i].clone()) .collect_vec();
.collect_vec(),
);
let filters = self.filters.clone(); let filters = self.filters.clone();
if !skip_range_check && !self.filters.is_empty() { if !skip_range_check && !self.filters.is_empty() {
@ -802,9 +798,9 @@ impl StoredRA {
return Ok(None); return Ok(None);
} }
} }
let mut ret = tuple.0.clone(); let mut ret = tuple.clone();
ret.extend(found.0); ret.extend(found);
Ok(Some(Tuple(ret))) Ok(Some(ret))
}) })
.filter_map(swap_option_result), .filter_map(swap_option_result),
); );
@ -821,9 +817,9 @@ impl StoredRA {
return Ok(None); return Ok(None);
} }
} }
let mut ret = tuple.0.clone(); let mut ret = tuple.clone();
ret.extend(found.0); ret.extend(found);
Ok(Some(Tuple(ret))) Ok(Some(ret))
}) })
.filter_map(swap_option_result), .filter_map(swap_option_result),
) )
@ -859,19 +855,17 @@ impl StoredRA {
Ok(Box::new( Ok(Box::new(
left_iter left_iter
.map_ok(move |tuple| -> Result<Option<Tuple>> { .map_ok(move |tuple| -> Result<Option<Tuple>> {
let prefix = Tuple( let prefix = left_to_prefix_indices
left_to_prefix_indices .iter()
.iter() .map(|i| tuple[*i].clone())
.map(|i| tuple.0[*i].clone()) .collect_vec();
.collect_vec(),
);
'outer: for found in self.storage.scan_prefix(tx, &prefix) { 'outer: for found in self.storage.scan_prefix(tx, &prefix) {
let found = found?; let found = found?;
for (left_idx, right_idx) in for (left_idx, right_idx) in
left_join_indices.iter().zip(right_join_indices.iter()) left_join_indices.iter().zip(right_join_indices.iter())
{ {
if tuple.0[*left_idx] != found.0[*right_idx] { if tuple[*left_idx] != found[*right_idx] {
continue 'outer; continue 'outer;
} }
} }
@ -879,20 +873,17 @@ impl StoredRA {
} }
Ok(Some(if !eliminate_indices.is_empty() { Ok(Some(if !eliminate_indices.is_empty() {
Tuple( tuple
tuple .into_iter()
.0 .enumerate()
.into_iter() .filter_map(|(i, v)| {
.enumerate() if eliminate_indices.contains(&i) {
.filter_map(|(i, v)| { None
if eliminate_indices.contains(&i) { } else {
None Some(v)
} else { }
Some(v) })
} .collect_vec()
})
.collect_vec(),
)
} else { } else {
tuple tuple
})) }))
@ -907,7 +898,7 @@ impl StoredRA {
let tuple = tuple?; let tuple = tuple?;
let to_join: Box<[DataValue]> = right_join_indices let to_join: Box<[DataValue]> = right_join_indices
.iter() .iter()
.map(|i| tuple.0[*i].clone()) .map(|i| tuple[*i].clone())
.collect(); .collect();
right_join_vals.insert(to_join); right_join_vals.insert(to_join);
} }
@ -916,27 +907,24 @@ impl StoredRA {
.map_ok(move |tuple| -> Result<Option<Tuple>> { .map_ok(move |tuple| -> Result<Option<Tuple>> {
let left_join_vals: Box<[DataValue]> = left_join_indices let left_join_vals: Box<[DataValue]> = left_join_indices
.iter() .iter()
.map(|i| tuple.0[*i].clone()) .map(|i| tuple[*i].clone())
.collect(); .collect();
if right_join_vals.contains(&left_join_vals) { if right_join_vals.contains(&left_join_vals) {
return Ok(None); return Ok(None);
} }
Ok(Some(if !eliminate_indices.is_empty() { Ok(Some(if !eliminate_indices.is_empty() {
Tuple( tuple
tuple .into_iter()
.0 .enumerate()
.into_iter() .filter_map(|(i, v)| {
.enumerate() if eliminate_indices.contains(&i) {
.filter_map(|(i, v)| { None
if eliminate_indices.contains(&i) { } else {
None Some(v)
} else { }
Some(v) })
} .collect_vec()
})
.collect_vec(),
)
} else { } else {
tuple tuple
})) }))
@ -1033,19 +1021,17 @@ impl InMemRelationRA {
Ok(Box::new( Ok(Box::new(
left_iter left_iter
.map_ok(move |tuple| -> Result<Option<Tuple>> { .map_ok(move |tuple| -> Result<Option<Tuple>> {
let prefix = Tuple( let prefix = left_to_prefix_indices
left_to_prefix_indices .iter()
.iter() .map(|i| tuple[*i].clone())
.map(|i| tuple.0[*i].clone()) .collect_vec();
.collect_vec(),
);
'outer: for found in self.storage.scan_prefix(&prefix) { 'outer: for found in self.storage.scan_prefix(&prefix) {
let found = found?; let found = found?;
for (left_idx, right_idx) in for (left_idx, right_idx) in
left_join_indices.iter().zip(right_join_indices.iter()) left_join_indices.iter().zip(right_join_indices.iter())
{ {
if tuple.0[*left_idx] != found.0[*right_idx] { if tuple[*left_idx] != found[*right_idx] {
continue 'outer; continue 'outer;
} }
} }
@ -1053,20 +1039,17 @@ impl InMemRelationRA {
} }
Ok(Some(if !eliminate_indices.is_empty() { Ok(Some(if !eliminate_indices.is_empty() {
Tuple( tuple
tuple .into_iter()
.0 .enumerate()
.into_iter() .filter_map(|(i, v)| {
.enumerate() if eliminate_indices.contains(&i) {
.filter_map(|(i, v)| { None
if eliminate_indices.contains(&i) { } else {
None Some(v)
} else { }
Some(v) })
} .collect_vec()
})
.collect_vec(),
)
} else { } else {
tuple tuple
})) }))
@ -1080,7 +1063,7 @@ impl InMemRelationRA {
let tuple = tuple?; let tuple = tuple?;
let to_join: Box<[DataValue]> = right_join_indices let to_join: Box<[DataValue]> = right_join_indices
.iter() .iter()
.map(|i| tuple.0[*i].clone()) .map(|i| tuple[*i].clone())
.collect(); .collect();
right_join_vals.insert(to_join); right_join_vals.insert(to_join);
} }
@ -1090,26 +1073,23 @@ impl InMemRelationRA {
.map_ok(move |tuple| -> Result<Option<Tuple>> { .map_ok(move |tuple| -> Result<Option<Tuple>> {
let left_join_vals: Box<[DataValue]> = left_join_indices let left_join_vals: Box<[DataValue]> = left_join_indices
.iter() .iter()
.map(|i| tuple.0[*i].clone()) .map(|i| tuple[*i].clone())
.collect(); .collect();
if right_join_vals.contains(&left_join_vals) { if right_join_vals.contains(&left_join_vals) {
return Ok(None); return Ok(None);
} }
Ok(Some(if !eliminate_indices.is_empty() { Ok(Some(if !eliminate_indices.is_empty() {
Tuple( tuple
tuple .into_iter()
.0 .enumerate()
.into_iter() .filter_map(|(i, v)| {
.enumerate() if eliminate_indices.contains(&i) {
.filter_map(|(i, v)| { None
if eliminate_indices.contains(&i) { } else {
None Some(v)
} else { }
Some(v) })
} .collect_vec()
})
.collect_vec(),
)
} else { } else {
tuple tuple
})) }))
@ -1149,12 +1129,10 @@ impl InMemRelationRA {
let mut skip_range_check = false; let mut skip_range_check = false;
let it = left_iter let it = left_iter
.map_ok(move |tuple| { .map_ok(move |tuple| {
let prefix = Tuple( let prefix = left_to_prefix_indices
left_to_prefix_indices .iter()
.iter() .map(|i| tuple[*i].clone())
.map(|i| tuple.0[*i].clone()) .collect_vec();
.collect_vec(),
);
let filters = self.filters.clone(); let filters = self.filters.clone();
@ -1179,9 +1157,9 @@ impl InMemRelationRA {
return Ok(None); return Ok(None);
} }
} }
let mut ret = tuple.0.clone(); let mut ret = tuple.clone();
ret.extend(found.0); ret.extend(found);
Ok(Some(Tuple(ret))) Ok(Some(ret))
}) })
.filter_map(swap_option_result), .filter_map(swap_option_result),
); );
@ -1198,9 +1176,9 @@ impl InMemRelationRA {
return Ok(None); return Ok(None);
} }
} }
let mut ret = tuple.0.clone(); let mut ret = tuple.clone();
ret.extend(found.0); ret.extend(found);
Ok(Some(Tuple(ret))) Ok(Some(ret))
}) })
.filter_map(swap_option_result), .filter_map(swap_option_result),
) )
@ -1325,7 +1303,7 @@ impl RelAlgebra {
use_delta: &BTreeSet<StoredRelationId>, use_delta: &BTreeSet<StoredRelationId>,
) -> Result<TupleIter<'a>> { ) -> Result<TupleIter<'a>> {
match self { match self {
RelAlgebra::Fixed(f) => Ok(Box::new(f.data.iter().map(|t| Ok(Tuple(t.clone()))))), RelAlgebra::Fixed(f) => Ok(Box::new(f.data.iter().map(|t| Ok(t.clone())))),
RelAlgebra::InMem(r) => r.iter(epoch, use_delta), RelAlgebra::InMem(r) => r.iter(epoch, use_delta),
RelAlgebra::Stored(v) => v.iter(tx), RelAlgebra::Stored(v) => v.iter(tx),
RelAlgebra::Join(j) => j.iter(tx, epoch, use_delta), RelAlgebra::Join(j) => j.iter(tx, epoch, use_delta),
@ -1640,9 +1618,9 @@ impl InnerJoin {
Ok(tuple) => { Ok(tuple) => {
let stored_tuple = right_store_indices let stored_tuple = right_store_indices
.iter() .iter()
.map(|i| tuple.0[*i].clone()) .map(|i| tuple[*i].clone())
.collect_vec(); .collect_vec();
cache.insert(Tuple(stored_tuple)); cache.insert(stored_tuple);
} }
Err(e) => return Err(e), Err(e) => return Err(e),
} }
@ -1687,7 +1665,7 @@ impl<'a> CachedMaterializedIterator<'a> {
None None
} else { } else {
let ret = &self.materialized[self.right_idx]; let ret = &self.materialized[self.right_idx];
if ret.0.starts_with(&self.prefix.0) { if ret.starts_with(&self.prefix) {
self.right_idx += 1; self.right_idx += 1;
Some(ret) Some(ret)
} else { } else {
@ -1703,7 +1681,7 @@ impl<'a> CachedMaterializedIterator<'a> {
let data = data.clone(); let data = data.clone();
let mut ret = self.left_cache.clone(); let mut ret = self.left_cache.clone();
for i in &self.right_invert_indices { for i in &self.right_invert_indices {
ret.0.push(data.0[*i].clone()); ret.push(data[*i].clone());
} }
let tuple = eliminate_from_tuple(ret, &self.eliminate_indices); let tuple = eliminate_from_tuple(ret, &self.eliminate_indices);
return Ok(Some(tuple)); return Ok(Some(tuple));
@ -1736,12 +1714,10 @@ fn build_mat_range_iter(
left_join_indices: &[usize], left_join_indices: &[usize],
left_tuple: &Tuple, left_tuple: &Tuple,
) -> (Tuple, usize) { ) -> (Tuple, usize) {
let prefix = Tuple( let prefix = left_join_indices
left_join_indices .iter()
.iter() .map(|i| left_tuple[*i].clone())
.map(|i| left_tuple.0[*i].clone()) .collect_vec();
.collect_vec(),
);
let idx = match mat.binary_search(&prefix) { let idx = match mat.binary_search(&prefix) {
Ok(i) => i, Ok(i) => i,
Err(i) => i, Err(i) => i,

@ -34,7 +34,7 @@ impl<'a> SessionTx<'a> {
let mut all_data: Vec<_> = original.scan_all().try_collect()?; let mut all_data: Vec<_> = original.scan_all().try_collect()?;
all_data.sort_by(|a, b| { all_data.sort_by(|a, b| {
for (idx, dir) in &idx_sorters { for (idx, dir) in &idx_sorters {
match a.0[*idx].cmp(&b.0[*idx]) { match a[*idx].cmp(&b[*idx]) {
Ordering::Equal => {} Ordering::Equal => {}
o => { o => {
return match dir { return match dir {

@ -111,12 +111,10 @@ impl<'a> SessionTx<'a> {
for tuple in res_iter { for tuple in res_iter {
let tuple = tuple?; let tuple = tuple?;
let extracted = Tuple( let extracted = key_extractors
key_extractors .iter()
.iter() .map(|ex| ex.extract_data(&tuple))
.map(|ex| ex.extract_data(&tuple)) .try_collect()?;
.try_collect()?,
);
let key = relation_store.encode_key_for_store(&extracted, *span)?; let key = relation_store.encode_key_for_store(&extracted, *span)?;
if has_triggers { if has_triggers {
if let Some(existing) = self.tx.get(&key, false)? { if let Some(existing) = self.tx.get(&key, false)? {
@ -125,13 +123,13 @@ impl<'a> SessionTx<'a> {
let mut remaining = &existing[ENCODED_KEY_MIN_LEN..]; let mut remaining = &existing[ENCODED_KEY_MIN_LEN..];
while !remaining.is_empty() { while !remaining.is_empty() {
let (val, nxt) = DataValue::decode_from_key(remaining); let (val, nxt) = DataValue::decode_from_key(remaining);
tup.0.push(val); tup.push(val);
remaining = nxt; remaining = nxt;
} }
} }
old_tuples.push(DataValue::List(tup.0)); old_tuples.push(DataValue::List(tup));
} }
new_tuples.push(DataValue::List(extracted.0.clone())); new_tuples.push(DataValue::List(extracted.clone()));
} }
self.tx.del(&key)?; self.tx.del(&key)?;
} }
@ -197,12 +195,10 @@ impl<'a> SessionTx<'a> {
for tuple in res_iter { for tuple in res_iter {
let tuple = tuple?; let tuple = tuple?;
let extracted = Tuple( let extracted = key_extractors
key_extractors .iter()
.iter() .map(|ex| ex.extract_data(&tuple))
.map(|ex| ex.extract_data(&tuple)) .try_collect()?;
.try_collect()?,
);
let key = relation_store.encode_key_for_store(&extracted, *span)?; let key = relation_store.encode_key_for_store(&extracted, *span)?;
let val = relation_store.encode_val_for_store(&extracted, *span)?; let val = relation_store.encode_val_for_store(&extracted, *span)?;
@ -212,7 +208,7 @@ impl<'a> SessionTx<'a> {
None => { None => {
bail!(TransactAssertionFailure { bail!(TransactAssertionFailure {
relation: relation_store.name.to_string(), relation: relation_store.name.to_string(),
key: extracted.0, key: extracted,
notice: "key does not exist in database".to_string() notice: "key does not exist in database".to_string()
}) })
} }
@ -220,7 +216,7 @@ impl<'a> SessionTx<'a> {
if &v as &[u8] != &val as &[u8] { if &v as &[u8] != &val as &[u8] {
bail!(TransactAssertionFailure { bail!(TransactAssertionFailure {
relation: relation_store.name.to_string(), relation: relation_store.name.to_string(),
key: extracted.0, key: extracted,
notice: "key exists in database, but value does not match" notice: "key exists in database, but value does not match"
.to_string() .to_string()
}) })
@ -247,17 +243,15 @@ impl<'a> SessionTx<'a> {
for tuple in res_iter { for tuple in res_iter {
let tuple = tuple?; let tuple = tuple?;
let extracted = Tuple( let extracted = key_extractors
key_extractors .iter()
.iter() .map(|ex| ex.extract_data(&tuple))
.map(|ex| ex.extract_data(&tuple)) .try_collect()?;
.try_collect()?,
);
let key = relation_store.encode_key_for_store(&extracted, *span)?; let key = relation_store.encode_key_for_store(&extracted, *span)?;
if self.tx.exists(&key, true)? { if self.tx.exists(&key, true)? {
bail!(TransactAssertionFailure { bail!(TransactAssertionFailure {
relation: relation_store.name.to_string(), relation: relation_store.name.to_string(),
key: extracted.0, key: extracted,
notice: "key exists in database".to_string() notice: "key exists in database".to_string()
}) })
} }
@ -294,12 +288,10 @@ impl<'a> SessionTx<'a> {
for tuple in res_iter { for tuple in res_iter {
let tuple = tuple?; let tuple = tuple?;
let extracted = Tuple( let extracted = key_extractors
key_extractors .iter()
.iter() .map(|ex| ex.extract_data(&tuple))
.map(|ex| ex.extract_data(&tuple)) .try_collect()?;
.try_collect()?,
);
let key = relation_store.encode_key_for_store(&extracted, *span)?; let key = relation_store.encode_key_for_store(&extracted, *span)?;
let val = relation_store.encode_val_for_store(&extracted, *span)?; let val = relation_store.encode_val_for_store(&extracted, *span)?;
@ -310,13 +302,13 @@ impl<'a> SessionTx<'a> {
let mut remaining = &existing[ENCODED_KEY_MIN_LEN..]; let mut remaining = &existing[ENCODED_KEY_MIN_LEN..];
while !remaining.is_empty() { while !remaining.is_empty() {
let (val, nxt) = DataValue::decode_from_key(remaining); let (val, nxt) = DataValue::decode_from_key(remaining);
tup.0.push(val); tup.push(val);
remaining = nxt; remaining = nxt;
} }
old_tuples.push(DataValue::List(tup.0)); old_tuples.push(DataValue::List(tup));
} }
new_tuples.push(DataValue::List(extracted.0)); new_tuples.push(DataValue::List(extracted));
} }
self.tx.put(&key, &val)?; self.tx.put(&key, &val)?;
@ -378,10 +370,10 @@ impl DataExtractor {
Ok(match self { Ok(match self {
DataExtractor::DefaultExtractor(expr, typ) => typ DataExtractor::DefaultExtractor(expr, typ) => typ
.coerce(expr.clone().eval_to_const()?) .coerce(expr.clone().eval_to_const()?)
.wrap_err_with(|| format!("when processing tuple {:?}", tuple.0))?, .wrap_err_with(|| format!("when processing tuple {:?}", tuple))?,
DataExtractor::IndexExtractor(i, typ) => typ DataExtractor::IndexExtractor(i, typ) => typ
.coerce(tuple.0[*i].clone()) .coerce(tuple[*i].clone())
.wrap_err_with(|| format!("when processing tuple {:?}", tuple.0))?, .wrap_err_with(|| format!("when processing tuple {:?}", tuple))?,
}) })
} }
} }

@ -24,7 +24,7 @@ use thiserror::Error;
use crate::data::json::JsonValue; use crate::data::json::JsonValue;
use crate::data::program::{InputProgram, QueryAssertion, RelationOp}; use crate::data::program::{InputProgram, QueryAssertion, RelationOp};
use crate::data::relation::ColumnDef; use crate::data::relation::ColumnDef;
use crate::data::tuple::Tuple; use crate::data::tuple::{Tuple, TupleT};
use crate::data::value::{DataValue, LARGEST_UTF_CHAR}; use crate::data::value::{DataValue, LARGEST_UTF_CHAR};
use crate::decode_tuple_from_kv; use crate::decode_tuple_from_kv;
use crate::parse::sys::SysOp; use crate::parse::sys::SysOp;
@ -180,7 +180,7 @@ impl<'s, S: Storage<'s>> Db<S> {
for data in tx.tx.range_scan(&start, &end) { for data in tx.tx.range_scan(&start, &end) {
let (k, v) = data?; let (k, v) = data?;
let tuple = decode_tuple_from_kv(&k, &v); let tuple = decode_tuple_from_kv(&k, &v);
let row = tuple.0.into_iter().map(JsonValue::from).collect_vec(); let row = tuple.into_iter().map(JsonValue::from).collect_vec();
rows.push(row); rows.push(row);
} }
let headers = cols.iter().map(|col| col.to_string()).collect_vec(); let headers = cols.iter().map(|col| col.to_string()).collect_vec();
@ -277,7 +277,7 @@ impl<'s, S: Storage<'s>> Db<S> {
col.typing.coerce(DataValue::from(v)) col.typing.coerce(DataValue::from(v))
}) })
.try_collect()?; .try_collect()?;
let k_store = handle.encode_key_for_store(&Tuple(keys), Default::default())?; let k_store = handle.encode_key_for_store(&keys, Default::default())?;
if is_delete { if is_delete {
tx.tx.del(&k_store)?; tx.tx.del(&k_store)?;
} else { } else {
@ -291,7 +291,7 @@ impl<'s, S: Storage<'s>> Db<S> {
}) })
.try_collect()?; .try_collect()?;
let v_store = let v_store =
handle.encode_val_only_for_store(&Tuple(vals), Default::default())?; handle.encode_val_only_for_store(&vals, Default::default())?;
tx.tx.put(&k_store, &v_store)?; tx.tx.put(&k_store, &v_store)?;
} }
} }
@ -390,7 +390,7 @@ impl<'s, S: Storage<'s>> Db<S> {
fn compact_relation(&'s self) -> Result<()> { fn compact_relation(&'s self) -> Result<()> {
let l = Tuple::default().encode_as_key(RelationId(0)); let l = Tuple::default().encode_as_key(RelationId(0));
let u = Tuple(vec![DataValue::Bot]).encode_as_key(RelationId(u64::MAX)); let u = vec![DataValue::Bot].encode_as_key(RelationId(u64::MAX));
self.db.range_compact(&l, &u)?; self.db.range_compact(&l, &u)?;
Ok(()) Ok(())
} }
@ -891,7 +891,7 @@ impl<'s, S: Storage<'s>> Db<S> {
} else { } else {
let rows: Vec<Vec<JsonValue>> = sorted_iter let rows: Vec<Vec<JsonValue>> = sorted_iter
.map_ok(|tuple| -> Vec<JsonValue> { .map_ok(|tuple| -> Vec<JsonValue> {
tuple.0.into_iter().map(JsonValue::from).collect() tuple.into_iter().map(JsonValue::from).collect()
}) })
.try_collect()?; .try_collect()?;
let headers: Vec<String> = match input_program.get_entry_out_head() { let headers: Vec<String> = match input_program.get_entry_out_head() {
@ -937,7 +937,7 @@ impl<'s, S: Storage<'s>> Db<S> {
} else { } else {
let rows: Vec<Vec<JsonValue>> = scan let rows: Vec<Vec<JsonValue>> = scan
.map_ok(|tuple| -> Vec<JsonValue> { .map_ok(|tuple| -> Vec<JsonValue> {
tuple.0.into_iter().map(JsonValue::from).collect() tuple.into_iter().map(JsonValue::from).collect()
}) })
.try_collect()?; .try_collect()?;
@ -1005,10 +1005,10 @@ impl<'s, S: Storage<'s>> Db<S> {
} }
fn list_relations(&'s self) -> Result<NamedRows> { fn list_relations(&'s self) -> Result<NamedRows> {
let lower = let lower =
Tuple(vec![DataValue::Str(SmartString::from(""))]).encode_as_key(RelationId::SYSTEM); vec![DataValue::Str(SmartString::from(""))].encode_as_key(RelationId::SYSTEM);
let upper = Tuple(vec![DataValue::Str(SmartString::from(String::from( let upper = vec![DataValue::Str(SmartString::from(String::from(
LARGEST_UTF_CHAR, LARGEST_UTF_CHAR,
)))]) )))]
.encode_as_key(RelationId::SYSTEM); .encode_as_key(RelationId::SYSTEM);
let tx = self.db.transact(false)?; let tx = self.db.transact(false)?;
let mut rows: Vec<Vec<JsonValue>> = vec![]; let mut rows: Vec<Vec<JsonValue>> = vec![];
@ -1073,10 +1073,10 @@ impl Poison {
} }
#[cfg(not(feature = "nothread"))] #[cfg(not(feature = "nothread"))]
pub(crate) fn set_timeout(&self, secs: f64) -> Result<()> { pub(crate) fn set_timeout(&self, secs: f64) -> Result<()> {
let pill = self.0.clone(); let pill = self.clone();
thread::spawn(move || { thread::spawn(move || {
thread::sleep(Duration::from_micros((secs * 1000000.) as u64)); thread::sleep(Duration::from_micros((secs * 1000000.) as u64));
pill.store(true, Ordering::Relaxed); pill.0.store(true, Ordering::Relaxed);
}); });
Ok(()) Ok(())
} }

@ -10,7 +10,6 @@ use std::borrow::Borrow;
use std::cell::RefCell; use std::cell::RefCell;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::fmt::{Debug, Formatter}; use std::fmt::{Debug, Formatter};
use std::ops::Bound::Included;
use std::rc::Rc; use std::rc::Rc;
use std::sync::atomic::{AtomicU32, Ordering}; use std::sync::atomic::{AtomicU32, Ordering};
use std::sync::Arc; use std::sync::Arc;
@ -88,20 +87,18 @@ impl InMemRelation {
let zero_target: &RefCell<BTreeMap<_, _>> = zero_map.borrow(); let zero_target: &RefCell<BTreeMap<_, _>> = zero_map.borrow();
let mut zero_target = zero_target.borrow_mut(); let mut zero_target = zero_target.borrow_mut();
let key = Tuple( let key = aggrs
aggrs .iter()
.iter() .enumerate()
.enumerate() .map(|(i, ma)| {
.map(|(i, ma)| { if ma.is_none() {
if ma.is_none() { tuple[i].clone()
tuple.0[i].clone() } else {
} else { // placeholder for meet aggregation
// placeholder for meet aggregation DataValue::Guard
DataValue::Guard }
} })
}) .collect_vec();
.collect_vec(),
);
let prev_aggr = zero_target.get_mut(&key); let prev_aggr = zero_target.get_mut(&key);
if let Some(prev_aggr) = prev_aggr { if let Some(prev_aggr) = prev_aggr {
@ -109,7 +106,7 @@ impl InMemRelation {
for (i, aggr) in aggrs.iter_mut().enumerate() { for (i, aggr) in aggrs.iter_mut().enumerate() {
if let Some((aggr_op, _aggr_args)) = aggr { if let Some((aggr_op, _aggr_args)) = aggr {
let op = aggr_op.meet_op.as_mut().unwrap(); let op = aggr_op.meet_op.as_mut().unwrap();
changed |= op.update(&mut prev_aggr.0[i], &tuple.0[i])?; changed |= op.update(&mut prev_aggr[i], &tuple[i])?;
} }
} }
if changed && epoch != 0 { if changed && epoch != 0 {
@ -121,20 +118,18 @@ impl InMemRelation {
} }
Ok(changed) Ok(changed)
} else { } else {
let tuple_to_store = Tuple( let tuple_to_store: Tuple = aggrs
aggrs .iter()
.iter() .enumerate()
.enumerate() .map(|(i, aggr)| -> Result<DataValue> {
.map(|(i, aggr)| -> Result<DataValue> { if aggr.is_some() {
if aggr.is_some() { Ok(tuple[i].clone())
Ok(tuple.0[i].clone()) } else {
} else { // placeholder for key part
// placeholder for key part Ok(DataValue::Guard)
Ok(DataValue::Guard) }
} })
}) .try_collect()?;
.try_collect()?,
);
zero_target.insert(key.clone(), tuple_to_store.clone()); zero_target.insert(key.clone(), tuple_to_store.clone());
if epoch != 0 { if epoch != 0 {
let epoch_maps = mem_db.borrow(); let epoch_maps = mem_db.borrow();
@ -163,7 +158,7 @@ impl InMemRelation {
if should_skip { if should_skip {
// put guard, so that when iterating results, those with guards are ignored // put guard, so that when iterating results, those with guards are ignored
epoch_map.insert(tuple, Tuple(vec![DataValue::Guard])); epoch_map.insert(tuple, vec![DataValue::Guard]);
} else { } else {
epoch_map.insert(tuple, Tuple::default()); epoch_map.insert(tuple, Tuple::default());
} }
@ -191,22 +186,22 @@ impl InMemRelation {
let collected = epoch_map let collected = epoch_map
.iter() .iter()
.map(|(k, v)| { .map(|(k, v)| {
if v.0.is_empty() { if v.is_empty() {
k.clone() k.clone()
} else { } else {
let combined = let combined = k
k.0.iter() .iter()
.zip(v.0.iter()) .zip(v.iter())
.map(|(kel, vel)| { .map(|(kel, vel)| {
// merge meet aggregation kv // merge meet aggregation kv
if matches!(kel, DataValue::Guard) { if matches!(kel, DataValue::Guard) {
vel.clone() vel.clone()
} else { } else {
kel.clone() kel.clone()
} }
}) })
.collect_vec(); .collect_vec();
Tuple(combined) combined
} }
}) })
.collect_vec(); .collect_vec();
@ -225,25 +220,25 @@ impl InMemRelation {
let collected = epoch_map let collected = epoch_map
.iter() .iter()
.filter_map(|(k, v)| { .filter_map(|(k, v)| {
if v.0.is_empty() { if v.is_empty() {
Some(k.clone()) Some(k.clone())
} else if v.0.last() == Some(&DataValue::Guard) { } else if v.last() == Some(&DataValue::Guard) {
// ignore since we are using :offset // ignore since we are using :offset
None None
} else { } else {
let combined = let combined = k
k.0.iter() .iter()
.zip(v.0.iter()) .zip(v.iter())
.map(|(kel, vel)| { .map(|(kel, vel)| {
// merge kv parts of meet aggr // merge kv parts of meet aggr
if matches!(kel, DataValue::Guard) { if matches!(kel, DataValue::Guard) {
vel.clone() vel.clone()
} else { } else {
kel.clone() kel.clone()
} }
}) })
.collect_vec(); .collect_vec();
Some(Tuple(combined)) Some(combined)
} }
}) })
.collect_vec(); .collect_vec();
@ -257,9 +252,9 @@ impl InMemRelation {
prefix: &Tuple, prefix: &Tuple,
epoch: u32, epoch: u32,
) -> impl Iterator<Item = Result<Tuple>> { ) -> impl Iterator<Item = Result<Tuple>> {
let mut upper = prefix.0.clone(); let mut upper = prefix.clone();
upper.push(DataValue::Bot); upper.push(DataValue::Bot);
let upper = Tuple(upper); let upper = upper;
let mem_db: &RefCell<_> = self.mem_db.borrow(); let mem_db: &RefCell<_> = self.mem_db.borrow();
let epoch_maps = mem_db.borrow(); let epoch_maps = mem_db.borrow();
let epoch_map = epoch_maps.get(epoch as usize).unwrap(); let epoch_map = epoch_maps.get(epoch as usize).unwrap();
@ -267,24 +262,24 @@ impl InMemRelation {
let epoch_map = epoch_map.borrow(); let epoch_map = epoch_map.borrow();
let collected = epoch_map let collected = epoch_map
.range((Included(prefix), Included(&upper))) .range(prefix.clone()..=upper)
.map(|(k, v)| { .map(|(k, v)| {
if v.0.is_empty() { if v.is_empty() {
k.clone() k.clone()
} else { } else {
let combined = let combined = k
k.0.iter() .iter()
.zip(v.0.iter()) .zip(v.iter())
.map(|(kel, vel)| { .map(|(kel, vel)| {
// merge kv parts of meet aggr // merge kv parts of meet aggr
if matches!(kel, DataValue::Guard) { if matches!(kel, DataValue::Guard) {
vel.clone() vel.clone()
} else { } else {
kel.clone() kel.clone()
} }
}) })
.collect_vec(); .collect_vec();
Tuple(combined) combined
} }
}) })
.collect_vec(); .collect_vec();
@ -298,9 +293,9 @@ impl InMemRelation {
epoch: u32, epoch: u32,
) -> impl Iterator<Item = Result<Tuple>> { ) -> impl Iterator<Item = Result<Tuple>> {
let mut prefix_bound = prefix.clone(); let mut prefix_bound = prefix.clone();
prefix_bound.0.extend_from_slice(lower); prefix_bound.extend_from_slice(lower);
let mut upper_bound = prefix.clone(); let mut upper_bound = prefix.clone();
upper_bound.0.extend_from_slice(upper); upper_bound.extend_from_slice(upper);
let mem_db: &RefCell<_> = self.mem_db.borrow(); let mem_db: &RefCell<_> = self.mem_db.borrow();
let epoch_maps = mem_db.borrow(); let epoch_maps = mem_db.borrow();
@ -309,7 +304,7 @@ impl InMemRelation {
let epoch_map = epoch_map.borrow(); let epoch_map = epoch_map.borrow();
let res = epoch_map let res = epoch_map
.range((Included(&prefix_bound), Included(&upper_bound))) .range(prefix_bound..=upper_bound)
.map(|(k, _v)| k.clone()) .map(|(k, _v)| k.clone())
.collect_vec(); .collect_vec();
res.into_iter().map(Ok) res.into_iter().map(Ok)

@ -19,7 +19,7 @@ use thiserror::Error;
use crate::data::memcmp::MemCmpEncoder; use crate::data::memcmp::MemCmpEncoder;
use crate::data::relation::StoredRelationMetadata; use crate::data::relation::StoredRelationMetadata;
use crate::data::symb::Symbol; use crate::data::symb::Symbol;
use crate::data::tuple::{Tuple, ENCODED_KEY_MIN_LEN}; use crate::data::tuple::{Tuple, TupleT, ENCODED_KEY_MIN_LEN};
use crate::data::value::DataValue; use crate::data::value::DataValue;
use crate::parse::SourceSpan; use crate::parse::SourceSpan;
use crate::runtime::transact::SessionTx; use crate::runtime::transact::SessionTx;
@ -130,16 +130,16 @@ impl RelationHandle {
pub(crate) fn encode_key_for_store(&self, tuple: &Tuple, span: SourceSpan) -> Result<Vec<u8>> { pub(crate) fn encode_key_for_store(&self, tuple: &Tuple, span: SourceSpan) -> Result<Vec<u8>> {
let len = self.metadata.keys.len(); let len = self.metadata.keys.len();
ensure!( ensure!(
tuple.0.len() >= len, tuple.len() >= len,
StoredRelArityMismatch { StoredRelArityMismatch {
name: self.name.to_string(), name: self.name.to_string(),
expect_arity: self.arity(), expect_arity: self.arity(),
actual_arity: tuple.0.len(), actual_arity: tuple.len(),
span span
} }
); );
let mut ret = self.encode_key_prefix(len); let mut ret = self.encode_key_prefix(len);
for val in &tuple.0[0..len] { for val in &tuple[0..len] {
ret.encode_datavalue(val); ret.encode_datavalue(val);
} }
Ok(ret) Ok(ret)
@ -148,7 +148,7 @@ impl RelationHandle {
let start = self.metadata.keys.len(); let start = self.metadata.keys.len();
let len = self.metadata.non_keys.len(); let len = self.metadata.non_keys.len();
let mut ret = self.encode_key_prefix(len); let mut ret = self.encode_key_prefix(len);
tuple.0[start..] tuple[start..]
.serialize(&mut Serializer::new(&mut ret)) .serialize(&mut Serializer::new(&mut ret))
.unwrap(); .unwrap();
Ok(ret) Ok(ret)
@ -158,8 +158,8 @@ impl RelationHandle {
tuple: &Tuple, tuple: &Tuple,
_span: SourceSpan, _span: SourceSpan,
) -> Result<Vec<u8>> { ) -> Result<Vec<u8>> {
let mut ret = self.encode_key_prefix(tuple.0.len()); let mut ret = self.encode_key_prefix(tuple.len());
tuple.0.serialize(&mut Serializer::new(&mut ret)).unwrap(); tuple.serialize(&mut Serializer::new(&mut ret)).unwrap();
Ok(ret) Ok(ret)
} }
pub(crate) fn ensure_compatible(&self, inp: &InputRelationHandle) -> Result<()> { pub(crate) fn ensure_compatible(&self, inp: &InputRelationHandle) -> Result<()> {
@ -230,12 +230,12 @@ impl RelationHandle {
tx: &'a SessionTx<'_>, tx: &'a SessionTx<'_>,
prefix: &Tuple, prefix: &Tuple,
) -> impl Iterator<Item = Result<Tuple>> + 'a { ) -> impl Iterator<Item = Result<Tuple>> + 'a {
let mut lower = prefix.0.clone(); let mut lower = prefix.clone();
lower.truncate(self.metadata.keys.len()); lower.truncate(self.metadata.keys.len());
let mut upper = lower.clone(); let mut upper = lower.clone();
upper.push(DataValue::Bot); upper.push(DataValue::Bot);
let prefix_encoded = Tuple(lower).encode_as_key(self.id); let prefix_encoded = lower.encode_as_key(self.id);
let upper_encoded = Tuple(upper).encode_as_key(self.id); let upper_encoded = upper.encode_as_key(self.id);
// RelationIterator::new(tx, &prefix_encoded, &upper_encoded) // RelationIterator::new(tx, &prefix_encoded, &upper_encoded)
tx.tx.range_scan_tuple(&prefix_encoded, &upper_encoded) tx.tx.range_scan_tuple(&prefix_encoded, &upper_encoded)
} }
@ -247,10 +247,10 @@ impl RelationHandle {
upper: &[DataValue], upper: &[DataValue],
) -> impl Iterator<Item = Result<Tuple>> + 'a { ) -> impl Iterator<Item = Result<Tuple>> + 'a {
let mut lower_t = prefix.clone(); let mut lower_t = prefix.clone();
lower_t.0.extend_from_slice(lower); lower_t.extend_from_slice(lower);
let mut upper_t = prefix.clone(); let mut upper_t = prefix.clone();
upper_t.0.extend_from_slice(upper); upper_t.extend_from_slice(upper);
upper_t.0.push(DataValue::Bot); upper_t.push(DataValue::Bot);
let lower_encoded = lower_t.encode_as_key(self.id); let lower_encoded = lower_t.encode_as_key(self.id);
let upper_encoded = upper_t.encode_as_key(self.id); let upper_encoded = upper_t.encode_as_key(self.id);
tx.tx.range_scan_tuple(&lower_encoded, &upper_encoded) tx.tx.range_scan_tuple(&lower_encoded, &upper_encoded)
@ -264,7 +264,7 @@ pub fn decode_tuple_from_kv(key: &[u8], val: &[u8]) -> Tuple {
let mut tup = Tuple::decode_from_key(key); let mut tup = Tuple::decode_from_key(key);
if !val.is_empty() { if !val.is_empty() {
let vals: Vec<DataValue> = rmp_serde::from_slice(&val[ENCODED_KEY_MIN_LEN..]).unwrap(); let vals: Vec<DataValue> = rmp_serde::from_slice(&val[ENCODED_KEY_MIN_LEN..]).unwrap();
tup.0.extend(vals); tup.extend(vals);
} }
tup tup
} }
@ -277,7 +277,7 @@ struct RelNameConflictError(String);
impl<'a> SessionTx<'a> { impl<'a> SessionTx<'a> {
pub(crate) fn relation_exists(&self, name: &str) -> Result<bool> { pub(crate) fn relation_exists(&self, name: &str) -> Result<bool> {
let key = DataValue::Str(SmartString::from(name)); let key = DataValue::Str(SmartString::from(name));
let encoded = Tuple(vec![key]).encode_as_key(RelationId::SYSTEM); let encoded = vec![key].encode_as_key(RelationId::SYSTEM);
self.tx.exists(&encoded, false) self.tx.exists(&encoded, false)
} }
pub(crate) fn set_relation_triggers( pub(crate) fn set_relation_triggers(
@ -300,7 +300,7 @@ impl<'a> SessionTx<'a> {
original.replace_triggers = replaces; original.replace_triggers = replaces;
let name_key = let name_key =
Tuple(vec![DataValue::Str(original.name.clone())]).encode_as_key(RelationId::SYSTEM); vec![DataValue::Str(original.name.clone())].encode_as_key(RelationId::SYSTEM);
let mut meta_val = vec![]; let mut meta_val = vec![];
original original
@ -315,7 +315,7 @@ impl<'a> SessionTx<'a> {
input_meta: InputRelationHandle, input_meta: InputRelationHandle,
) -> Result<RelationHandle> { ) -> Result<RelationHandle> {
let key = DataValue::Str(input_meta.name.name.clone()); let key = DataValue::Str(input_meta.name.name.clone());
let encoded = Tuple(vec![key]).encode_as_key(RelationId::SYSTEM); let encoded = vec![key].encode_as_key(RelationId::SYSTEM);
if self.tx.exists(&encoded, true)? { if self.tx.exists(&encoded, true)? {
bail!(RelNameConflictError(input_meta.name.to_string())) bail!(RelNameConflictError(input_meta.name.to_string()))
@ -334,15 +334,14 @@ impl<'a> SessionTx<'a> {
}; };
self.tx.put(&encoded, &meta.id.raw_encode())?; self.tx.put(&encoded, &meta.id.raw_encode())?;
let name_key = let name_key = vec![DataValue::Str(meta.name.clone())].encode_as_key(RelationId::SYSTEM);
Tuple(vec![DataValue::Str(meta.name.clone())]).encode_as_key(RelationId::SYSTEM);
let mut meta_val = vec![]; let mut meta_val = vec![];
meta.serialize(&mut Serializer::new(&mut meta_val).with_struct_map()) meta.serialize(&mut Serializer::new(&mut meta_val).with_struct_map())
.unwrap(); .unwrap();
self.tx.put(&name_key, &meta_val)?; self.tx.put(&name_key, &meta_val)?;
let tuple = Tuple(vec![DataValue::Null]); let tuple = vec![DataValue::Null];
let t_encoded = tuple.encode_as_key(RelationId::SYSTEM); let t_encoded = tuple.encode_as_key(RelationId::SYSTEM);
self.tx.put(&t_encoded, &meta.id.raw_encode())?; self.tx.put(&t_encoded, &meta.id.raw_encode())?;
Ok(meta) Ok(meta)
@ -354,7 +353,7 @@ impl<'a> SessionTx<'a> {
struct StoredRelationNotFoundError(String); struct StoredRelationNotFoundError(String);
let key = DataValue::Str(SmartString::from(name as &str)); let key = DataValue::Str(SmartString::from(name as &str));
let encoded = Tuple(vec![key]).encode_as_key(RelationId::SYSTEM); let encoded = vec![key].encode_as_key(RelationId::SYSTEM);
let found = self let found = self
.tx .tx
@ -373,7 +372,7 @@ impl<'a> SessionTx<'a> {
)) ))
} }
let key = DataValue::Str(SmartString::from(name as &str)); let key = DataValue::Str(SmartString::from(name as &str));
let encoded = Tuple(vec![key]).encode_as_key(RelationId::SYSTEM); let encoded = vec![key].encode_as_key(RelationId::SYSTEM);
self.tx.del(&encoded)?; self.tx.del(&encoded)?;
let lower_bound = Tuple::default().encode_as_key(store.id); let lower_bound = Tuple::default().encode_as_key(store.id);
let upper_bound = Tuple::default().encode_as_key(store.id.next()); let upper_bound = Tuple::default().encode_as_key(store.id.next());
@ -383,8 +382,7 @@ impl<'a> SessionTx<'a> {
let mut meta = self.get_relation(&rel, true)?; let mut meta = self.get_relation(&rel, true)?;
meta.access_level = level; meta.access_level = level;
let name_key = let name_key = vec![DataValue::Str(meta.name.clone())].encode_as_key(RelationId::SYSTEM);
Tuple(vec![DataValue::Str(meta.name.clone())]).encode_as_key(RelationId::SYSTEM);
let mut meta_val = vec![]; let mut meta_val = vec![];
meta.serialize(&mut Serializer::new(&mut meta_val).with_struct_map()) meta.serialize(&mut Serializer::new(&mut meta_val).with_struct_map())
@ -395,14 +393,14 @@ impl<'a> SessionTx<'a> {
} }
pub(crate) fn rename_relation(&mut self, old: Symbol, new: Symbol) -> Result<()> { pub(crate) fn rename_relation(&mut self, old: Symbol, new: Symbol) -> Result<()> {
let new_key = DataValue::Str(new.name.clone()); let new_key = DataValue::Str(new.name.clone());
let new_encoded = Tuple(vec![new_key]).encode_as_key(RelationId::SYSTEM); let new_encoded = vec![new_key].encode_as_key(RelationId::SYSTEM);
if self.tx.exists(&new_encoded, true)? { if self.tx.exists(&new_encoded, true)? {
bail!(RelNameConflictError(new.name.to_string())) bail!(RelNameConflictError(new.name.to_string()))
}; };
let old_key = DataValue::Str(old.name.clone()); let old_key = DataValue::Str(old.name.clone());
let old_encoded = Tuple(vec![old_key]).encode_as_key(RelationId::SYSTEM); let old_encoded = vec![old_key].encode_as_key(RelationId::SYSTEM);
let mut rel = self.get_relation(&old, true)?; let mut rel = self.get_relation(&old, true)?;
if rel.access_level < AccessLevel::Normal { if rel.access_level < AccessLevel::Normal {
@ -434,6 +432,7 @@ pub(crate) struct InsufficientAccessLevel(
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use serde_json::json; use serde_json::json;
use crate::new_cozo_mem; use crate::new_cozo_mem;
#[test] #[test]
@ -443,7 +442,8 @@ mod tests {
.unwrap(); .unwrap();
db.run_script(":create friends.rev {to: Int, fr: Int}", Default::default()) db.run_script(":create friends.rev {to: Int, fr: Int}", Default::default())
.unwrap(); .unwrap();
db.run_script(r#" db.run_script(
r#"
::set_triggers friends ::set_triggers friends
on put { on put {
@ -456,7 +456,10 @@ mod tests {
:rm friends.rev{ to, fr } :rm friends.rev{ to, fr }
} }
"#, Default::default()).unwrap(); "#,
Default::default(),
)
.unwrap();
db.run_script( db.run_script(
r"?[fr, to] <- [[1,2]] :put friends {fr, to}", r"?[fr, to] <- [[1,2]] :put friends {fr, to}",
Default::default(), Default::default(),

@ -12,7 +12,7 @@ use std::sync::Arc;
use miette::Result; use miette::Result;
use crate::data::program::MagicSymbol; use crate::data::program::MagicSymbol;
use crate::data::tuple::Tuple; use crate::data::tuple::TupleT;
use crate::data::value::DataValue; use crate::data::value::DataValue;
use crate::runtime::in_mem::{InMemRelation, StoredRelationId}; use crate::runtime::in_mem::{InMemRelation, StoredRelationId};
use crate::runtime::relation::RelationId; use crate::runtime::relation::RelationId;
@ -34,7 +34,7 @@ impl<'a> SessionTx<'a> {
} }
pub(crate) fn load_last_relation_store_id(&self) -> Result<RelationId> { pub(crate) fn load_last_relation_store_id(&self) -> Result<RelationId> {
let tuple = Tuple(vec![DataValue::Null]); let tuple = vec![DataValue::Null];
let t_encoded = tuple.encode_as_key(RelationId::SYSTEM); let t_encoded = tuple.encode_as_key(RelationId::SYSTEM);
let found = self.tx.get(&t_encoded, false)?; let found = self.tx.get(&t_encoded, false)?;
Ok(match found { Ok(match found {

Loading…
Cancel
Save