|
|
|
@ -1,12 +1,13 @@
|
|
|
|
|
use std::collections::btree_map::Entry;
|
|
|
|
|
use std::collections::{BTreeMap, BTreeSet};
|
|
|
|
|
use std::collections::btree_map::Entry;
|
|
|
|
|
|
|
|
|
|
use anyhow::Result;
|
|
|
|
|
use itertools::Itertools;
|
|
|
|
|
use serde_json::Map;
|
|
|
|
|
|
|
|
|
|
use crate::{EntityId, Validity};
|
|
|
|
|
use crate::data::attr::Attribute;
|
|
|
|
|
use crate::data::expr::{get_op, Expr};
|
|
|
|
|
use crate::data::expr::{Expr, get_op};
|
|
|
|
|
use crate::data::json::JsonValue;
|
|
|
|
|
use crate::data::keyword::{Keyword, PROG_ENTRY};
|
|
|
|
|
use crate::data::value::DataValue;
|
|
|
|
@ -16,7 +17,6 @@ use crate::query::compile::{
|
|
|
|
|
RuleApplyAtom, RuleSet, Term,
|
|
|
|
|
};
|
|
|
|
|
use crate::runtime::transact::SessionTx;
|
|
|
|
|
use crate::{EntityId, Validity};
|
|
|
|
|
|
|
|
|
|
impl SessionTx {
|
|
|
|
|
pub fn parse_rule_sets(
|
|
|
|
@ -130,7 +130,7 @@ impl SessionTx {
|
|
|
|
|
op.min_arity,
|
|
|
|
|
args.len(),
|
|
|
|
|
)
|
|
|
|
|
.into());
|
|
|
|
|
.into());
|
|
|
|
|
}
|
|
|
|
|
} else if args.len() != op.min_arity {
|
|
|
|
|
return Err(QueryCompilationError::PredicateArityMismatch(
|
|
|
|
@ -138,7 +138,7 @@ impl SessionTx {
|
|
|
|
|
op.min_arity,
|
|
|
|
|
args.len(),
|
|
|
|
|
)
|
|
|
|
|
.into());
|
|
|
|
|
.into());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(Expr::Apply(op, args))
|
|
|
|
@ -163,7 +163,7 @@ impl SessionTx {
|
|
|
|
|
JsonValue::Object(map.clone()),
|
|
|
|
|
"must contain either 'const' or 'pred' key".to_string(),
|
|
|
|
|
)
|
|
|
|
|
.into())
|
|
|
|
|
.into())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
v => Ok(Expr::Const(v.into())),
|
|
|
|
@ -212,7 +212,7 @@ impl SessionTx {
|
|
|
|
|
value_rep.clone(),
|
|
|
|
|
"reserved string values must be quoted".to_string(),
|
|
|
|
|
)
|
|
|
|
|
.into());
|
|
|
|
|
.into());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if let Some(o) = value_rep.as_object() {
|
|
|
|
@ -294,15 +294,15 @@ impl SessionTx {
|
|
|
|
|
|
|
|
|
|
if rule_head.len()
|
|
|
|
|
!= rule_head
|
|
|
|
|
.iter()
|
|
|
|
|
.map(|h| &h.name)
|
|
|
|
|
.collect::<BTreeSet<_>>()
|
|
|
|
|
.len()
|
|
|
|
|
.iter()
|
|
|
|
|
.map(|h| &h.name)
|
|
|
|
|
.collect::<BTreeSet<_>>()
|
|
|
|
|
.len()
|
|
|
|
|
{
|
|
|
|
|
return Err(QueryCompilationError::DuplicateVariables(
|
|
|
|
|
rule_head.into_iter().map(|h| h.name).collect_vec(),
|
|
|
|
|
)
|
|
|
|
|
.into());
|
|
|
|
|
.into());
|
|
|
|
|
}
|
|
|
|
|
Atom::Conjunction(rule_body)
|
|
|
|
|
.disjunctive_normal_form()
|
|
|
|
@ -414,7 +414,7 @@ impl SessionTx {
|
|
|
|
|
JsonValue::Object(map.clone()),
|
|
|
|
|
"too many keys".to_string(),
|
|
|
|
|
)
|
|
|
|
|
.into());
|
|
|
|
|
.into());
|
|
|
|
|
}
|
|
|
|
|
self.parse_logical_atom(map, vld)
|
|
|
|
|
} else {
|
|
|
|
@ -422,14 +422,14 @@ impl SessionTx {
|
|
|
|
|
JsonValue::Object(map.clone()),
|
|
|
|
|
"unknown format".to_string(),
|
|
|
|
|
)
|
|
|
|
|
.into())
|
|
|
|
|
.into())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
v => Err(QueryCompilationError::UnexpectedForm(
|
|
|
|
|
v.clone(),
|
|
|
|
|
"unknown format".to_string(),
|
|
|
|
|
)
|
|
|
|
|
.into()),
|
|
|
|
|
.into()),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fn parse_logical_atom(&mut self, map: &Map<String, JsonValue>, vld: Validity) -> Result<Atom> {
|
|
|
|
@ -483,7 +483,7 @@ impl SessionTx {
|
|
|
|
|
JsonValue::Object(m.clone()),
|
|
|
|
|
"expect object with exactly one field".to_string(),
|
|
|
|
|
)
|
|
|
|
|
.into());
|
|
|
|
|
.into());
|
|
|
|
|
}
|
|
|
|
|
let (k, v) = m.iter().next().unwrap();
|
|
|
|
|
let kw = Keyword::from(k as &str);
|
|
|
|
@ -493,7 +493,7 @@ impl SessionTx {
|
|
|
|
|
JsonValue::Object(m.clone()),
|
|
|
|
|
"attribute is not a unique index".to_string(),
|
|
|
|
|
)
|
|
|
|
|
.into());
|
|
|
|
|
.into());
|
|
|
|
|
}
|
|
|
|
|
let value = attr.val_type.coerce_value(v.into())?;
|
|
|
|
|
let eid = self
|
|
|
|
@ -511,7 +511,7 @@ impl SessionTx {
|
|
|
|
|
JsonValue::Object(m.clone()),
|
|
|
|
|
"expect object with exactly one field".to_string(),
|
|
|
|
|
)
|
|
|
|
|
.into());
|
|
|
|
|
.into());
|
|
|
|
|
}
|
|
|
|
|
let (k, v) = m.iter().next().unwrap();
|
|
|
|
|
if k != "const" {
|
|
|
|
@ -519,7 +519,7 @@ impl SessionTx {
|
|
|
|
|
JsonValue::Object(m.clone()),
|
|
|
|
|
"expect object with exactly one field named 'const'".to_string(),
|
|
|
|
|
)
|
|
|
|
|
.into());
|
|
|
|
|
.into());
|
|
|
|
|
}
|
|
|
|
|
let value = attr.val_type.coerce_value(v.into())?;
|
|
|
|
|
Ok(value)
|
|
|
|
@ -539,7 +539,7 @@ impl SessionTx {
|
|
|
|
|
value_rep.clone(),
|
|
|
|
|
"reserved string values must be quoted".to_string(),
|
|
|
|
|
)
|
|
|
|
|
.into());
|
|
|
|
|
.into());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if let Some(o) = value_rep.as_object() {
|
|
|
|
@ -566,7 +566,7 @@ impl SessionTx {
|
|
|
|
|
entity_rep.clone(),
|
|
|
|
|
"reserved string values must be quoted".to_string(),
|
|
|
|
|
)
|
|
|
|
|
.into());
|
|
|
|
|
.into());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if let Some(u) = entity_rep.as_u64() {
|
|
|
|
@ -589,7 +589,7 @@ impl SessionTx {
|
|
|
|
|
v.clone(),
|
|
|
|
|
"expect attribute keyword".to_string(),
|
|
|
|
|
)
|
|
|
|
|
.into()),
|
|
|
|
|
.into()),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|