rename keyword to symbol/name

main
Ziyang Hu 2 years ago
parent 73f05e1c02
commit 3d1aabb9b5

@ -6,10 +6,11 @@
* [x] stratum
* [x] magic sets
* [x] unification
* [ ] duplicate symbols in rule heads
* [ ] aggregation
* [ ] range scan
* [ ] public API
* [ ] sorting
* [ ] limit, offset
comparators can have problems when sorting mixed integers and floats
comparators can have problems when sorting mixed integers and floats

@ -28,7 +28,7 @@ class Typing(str, Enum):
int = 'int'
float = 'float'
string = 'string'
keyword = 'keyword'
name = 'name'
uuid = 'uuid'
timestamp = 'timestamp'
bytes = 'bytes'
@ -47,9 +47,9 @@ class Indexing(str, Enum):
identity = 'identity'
def Attribute(keyword, typing, id, cardinality, index, history):
def Attribute(name, typing, id, cardinality, index, history):
ret = {
'keyword': keyword,
'name': name,
'type': typing,
'cardinality': cardinality,
'index': index,
@ -60,15 +60,15 @@ def Attribute(keyword, typing, id, cardinality, index, history):
return ret
def PutAttr(keyword, typing, id=None, cardinality=Cardinality.one, index=Indexing.none, history=False):
def PutAttr(name, typing, id=None, cardinality=Cardinality.one, index=Indexing.none, history=False):
return {
'put': Attribute(keyword, typing, id, cardinality, index, history)
'put': Attribute(name, typing, id, cardinality, index, history)
}
def RetractAttr(keyword, typing, id, cardinality, index, history):
def RetractAttr(name, typing, id, cardinality, index, history):
return {
'retract': Attribute(keyword, typing, id, cardinality, index, history)
'retract': Attribute(name, typing, id, cardinality, index, history)
}
@ -102,9 +102,9 @@ class DefAttributesHelper:
self.name = name
def __call__(self, typing, id=None, cardinality=Cardinality.one, index=Indexing.none, history=False):
keyword = f'{self.parent.prefix}.{self.name}'
name = f'{self.parent.prefix}.{self.name}'
self.parent.attrs.append({
'put': Attribute(keyword, typing, id, cardinality, index, history)
'put': Attribute(name, typing, id, cardinality, index, history)
})
return self.parent

@ -10,7 +10,7 @@ use smallvec::SmallVec;
use crate::data::encode::EncodedVec;
use crate::data::id::{AttrId, TxId};
use crate::data::json::JsonValue;
use crate::data::keyword::Keyword;
use crate::data::symb::Symbol;
use crate::data::triple::StoreOp;
use crate::data::value::DataValue;
use crate::parse::triple::TempIdCtx;
@ -223,7 +223,7 @@ pub(crate) struct Attribute {
#[serde(rename = "i")]
pub(crate) id: AttrId,
#[serde(rename = "n")]
pub(crate) keyword: Keyword,
pub(crate) name: Symbol,
#[serde(rename = "c")]
pub(crate) cardinality: AttributeCardinality,
#[serde(rename = "t")]
@ -254,7 +254,7 @@ impl Attribute {
pub(crate) fn to_json(&self) -> JsonValue {
json!({
"id": self.id.0,
"keyword": self.keyword.to_string(),
"name": self.name.to_string(),
"cardinality": self.cardinality.to_string(),
"type": self.val_type.to_string(),
"index": self.indexing.to_string(),

@ -47,7 +47,7 @@ pub(crate) fn compare_key(a: &[u8], b: &[u8]) -> Ordering {
SentinelEntityAttr => compare_key_unique_entity_attr(a, b),
SentinelAttrValue => compare_key_unique_attr_val(a, b),
SentinelAttrById => compare_key_unique_attr_by_id(a, b),
SentinelAttrByKeyword => compare_key_unique_attr_by_kw(a, b),
SentinelAttrByName => compare_key_unique_attr_by_name(a, b),
}
}
@ -164,6 +164,6 @@ fn compare_key_unique_attr_by_id(a: &[u8], b: &[u8]) -> Ordering {
}
#[inline]
fn compare_key_unique_attr_by_kw(a: &[u8], b: &[u8]) -> Ordering {
fn compare_key_unique_attr_by_name(a: &[u8], b: &[u8]) -> Ordering {
a.cmp(b)
}

@ -8,7 +8,7 @@ use smallvec::SmallVec;
use crate::data::attr::Attribute;
use crate::data::id::{AttrId, EntityId, TxId, Validity};
use crate::data::keyword::Keyword;
use crate::data::symb::Symbol;
use crate::data::triple::StoreOp;
use crate::data::value::DataValue;
use crate::runtime::transact::TxLog;
@ -25,7 +25,7 @@ pub(crate) enum StorageTag {
SentinelEntityAttr = 7,
SentinelAttrValue = 8,
SentinelAttrById = 9,
SentinelAttrByKeyword = 10,
SentinelAttrByName = 10,
}
#[derive(Clone)]
@ -58,7 +58,7 @@ impl EncodedVec<LARGE_VEC_SIZE> {
}
StorageTag::AttrById
| StorageTag::SentinelAttrById
| StorageTag::SentinelAttrByKeyword => {
| StorageTag::SentinelAttrByName => {
let op = StoreOp::try_from(data[0]).unwrap();
if data.len() <= 1 {
op.to_string()
@ -129,9 +129,9 @@ impl<const N: usize> Debug for EncodedVec<N> {
StorageTag::SentinelAttrById => {
write!(f, " {:?}", AttrId::from_bytes(self))
}
StorageTag::SentinelAttrByKeyword => {
let kw = decode_sentinel_attr_by_kw(self).unwrap();
write!(f, " {:?}", kw)
StorageTag::SentinelAttrByName => {
let name = decode_sentinel_attr_by_name(self).unwrap();
write!(f, " {:?}", name)
}
}
}
@ -197,7 +197,7 @@ impl TryFrom<u8> for StorageTag {
7 => SentinelEntityAttr,
8 => SentinelAttrValue,
9 => SentinelAttrById,
10 => SentinelAttrByKeyword,
10 => SentinelAttrByName,
n => bail!("unexpected storage tag {}", n),
})
}
@ -431,14 +431,14 @@ pub(crate) fn encode_sentinel_attr_by_id(aid: AttrId) -> EncodedVec<VEC_SIZE_8>
}
#[inline]
pub(crate) fn encode_sentinel_attr_by_kw(kw: &Keyword) -> EncodedVec<LARGE_VEC_SIZE> {
pub(crate) fn encode_sentinel_attr_by_name(name: &Symbol) -> EncodedVec<LARGE_VEC_SIZE> {
let mut ret = SmallVec::<[u8; LARGE_VEC_SIZE]>::new();
ret.push(StorageTag::SentinelAttrByKeyword as u8);
ret.extend_from_slice(kw.0.as_bytes());
ret.push(StorageTag::SentinelAttrByName as u8);
ret.extend_from_slice(name.0.as_bytes());
ret.into()
}
#[inline]
pub(crate) fn decode_sentinel_attr_by_kw(src: &[u8]) -> Result<Keyword> {
Ok(Keyword::try_from(&src[1..])?)
pub(crate) fn decode_sentinel_attr_by_name(src: &[u8]) -> Result<Symbol> {
Ok(Symbol::try_from(&src[1..])?)
}

@ -7,13 +7,13 @@ use anyhow::{bail, Result};
use itertools::Itertools;
use ordered_float::{Float, OrderedFloat};
use crate::data::keyword::Keyword;
use crate::data::symb::Symbol;
use crate::data::tuple::Tuple;
use crate::data::value::DataValue;
#[derive(Debug, Clone)]
pub(crate) enum Expr {
Binding(Keyword, Option<usize>),
Binding(Symbol, Option<usize>),
Const(DataValue),
Apply(&'static Op, Box<[Expr]>),
}
@ -25,7 +25,7 @@ impl Expr {
pub(crate) fn negate(self) -> Self {
Expr::Apply(&OP_NOT, Box::new([self]))
}
pub(crate) fn fill_binding_indices(&mut self, binding_map: &BTreeMap<Keyword, usize>) {
pub(crate) fn fill_binding_indices(&mut self, binding_map: &BTreeMap<Symbol, usize>) {
match self {
Expr::Binding(k, idx) => {
let found_idx = *binding_map.get(k).unwrap();
@ -64,12 +64,12 @@ impl Expr {
}
Ok(())
}
pub(crate) fn bindings(&self) -> BTreeSet<Keyword> {
pub(crate) fn bindings(&self) -> BTreeSet<Symbol> {
let mut ret = BTreeSet::new();
self.collect_bindings(&mut ret);
ret
}
pub(crate) fn collect_bindings(&self, coll: &mut BTreeSet<Keyword>) {
pub(crate) fn collect_bindings(&self, coll: &mut BTreeSet<Symbol>) {
match self {
Expr::Binding(b, _) => {
coll.insert(b.clone());

@ -4,7 +4,7 @@ pub(crate) use serde_json::Value as JsonValue;
use crate::data::attr::{Attribute, AttributeCardinality, AttributeIndex, AttributeTyping};
use crate::data::id::{AttrId, EntityId, TxId};
use crate::data::keyword::Keyword;
use crate::data::symb::Symbol;
use crate::data::value::DataValue;
impl From<JsonValue> for DataValue {
@ -77,13 +77,13 @@ impl From<DataValue> for JsonValue {
}
}
impl TryFrom<&'_ JsonValue> for Keyword {
impl TryFrom<&'_ JsonValue> for Symbol {
type Error = anyhow::Error;
fn try_from(value: &'_ JsonValue) -> Result<Self, Self::Error> {
let s = value
.as_str()
.ok_or_else(|| anyhow!("failed to convert {} to a keyword", value))?;
Ok(Keyword::from(s))
.ok_or_else(|| anyhow!("failed to convert {} to a symbol", value))?;
Ok(Symbol::from(s))
}
}
@ -98,17 +98,17 @@ impl TryFrom<&'_ JsonValue> for Attribute {
None => AttrId(0),
Some(v) => AttrId::try_from(v)?,
};
let keyword = map.get("keyword").ok_or_else(|| {
let name = map.get("name").ok_or_else(|| {
anyhow!(
"expect field 'keyword' in attribute definition, got {}",
"expect field 'name' in attribute definition, got {}",
value
)
})?;
let keyword = Keyword::try_from(keyword)?;
let symb = Symbol::try_from(name)?;
ensure!(
!keyword.is_reserved(),
"cannot use reserved keyword {}",
keyword
!symb.is_reserved(),
"cannot use reserved symbol {}",
symb
);
let cardinality = map
.get("cardinality")
@ -142,7 +142,7 @@ impl TryFrom<&'_ JsonValue> for Attribute {
Ok(Attribute {
id,
keyword,
name: symb,
cardinality,
val_type,
indexing,
@ -155,7 +155,7 @@ impl From<Attribute> for JsonValue {
fn from(attr: Attribute) -> Self {
json!({
"id": attr.id.0,
"keyword": attr.keyword.to_string(),
"name": attr.name.to_string(),
"cardinality": attr.cardinality.to_string(),
"type": attr.val_type.to_string(),
"index": attr.indexing.to_string(),

@ -3,7 +3,7 @@ pub(crate) mod compare;
pub(crate) mod encode;
pub(crate) mod id;
pub(crate) mod json;
pub(crate) mod keyword;
pub(crate) mod symb;
pub(crate) mod triple;
pub(crate) mod value;
pub(crate) mod tuple;

@ -8,24 +8,24 @@ use crate::data::aggr::Aggregation;
use crate::data::attr::Attribute;
use crate::data::expr::Expr;
use crate::data::id::{EntityId, Validity};
use crate::data::keyword::Keyword;
use crate::data::symb::Symbol;
use crate::data::value::DataValue;
#[derive(Default)]
pub(crate) struct TempKwGen {
pub(crate) struct TempSymbGen {
last_id: u32,
}
impl TempKwGen {
pub(crate) fn next(&mut self) -> Keyword {
impl TempSymbGen {
pub(crate) fn next(&mut self) -> Symbol {
self.last_id += 1;
Keyword::from(&format!("*{}", self.last_id) as &str)
Symbol::from(&format!("*{}", self.last_id) as &str)
}
}
#[derive(Debug, Clone)]
pub(crate) struct InputProgram {
pub(crate) prog: BTreeMap<Keyword, Vec<InputRule>>,
pub(crate) prog: BTreeMap<Symbol, Vec<InputRule>>,
}
impl InputProgram {
@ -57,7 +57,7 @@ pub(crate) struct StratifiedNormalFormProgram(pub(crate) Vec<NormalFormProgram>)
#[derive(Debug, Clone, Default)]
pub(crate) struct NormalFormProgram {
pub(crate) prog: BTreeMap<Keyword, Vec<NormalFormRule>>,
pub(crate) prog: BTreeMap<Symbol, Vec<NormalFormRule>>,
}
#[derive(Debug, Clone)]
@ -65,35 +65,35 @@ pub(crate) struct StratifiedMagicProgram(pub(crate) Vec<MagicProgram>);
#[derive(Debug, Clone)]
pub(crate) struct MagicProgram {
pub(crate) prog: BTreeMap<MagicKeyword, Vec<MagicRule>>,
pub(crate) prog: BTreeMap<MagicSymbol, Vec<MagicRule>>,
}
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq)]
pub(crate) enum MagicKeyword {
pub(crate) enum MagicSymbol {
Muggle {
inner: Keyword,
inner: Symbol,
},
Magic {
inner: Keyword,
inner: Symbol,
adornment: SmallVec<[bool; 8]>,
},
Input {
inner: Keyword,
inner: Symbol,
adornment: SmallVec<[bool; 8]>,
},
Sup {
inner: Keyword,
inner: Symbol,
adornment: SmallVec<[bool; 8]>,
rule_idx: u16,
sup_idx: u16,
},
}
impl Debug for MagicKeyword {
impl Debug for MagicSymbol {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
MagicKeyword::Muggle { inner } => write!(f, "{}", inner.0),
MagicKeyword::Magic { inner, adornment } => {
MagicSymbol::Muggle { inner } => write!(f, "{}", inner.0),
MagicSymbol::Magic { inner, adornment } => {
write!(f, "{}|M", inner.0)?;
for b in adornment {
if *b {
@ -104,7 +104,7 @@ impl Debug for MagicKeyword {
}
Ok(())
}
MagicKeyword::Input { inner, adornment } => {
MagicSymbol::Input { inner, adornment } => {
write!(f, "{}|I", inner.0)?;
for b in adornment {
if *b {
@ -115,7 +115,7 @@ impl Debug for MagicKeyword {
}
Ok(())
}
MagicKeyword::Sup {
MagicSymbol::Sup {
inner,
adornment,
rule_idx,
@ -135,21 +135,21 @@ impl Debug for MagicKeyword {
}
}
impl MagicKeyword {
pub(crate) fn as_keyword(&self) -> &Keyword {
impl MagicSymbol {
pub(crate) fn as_plain_symbol(&self) -> &Symbol {
match self {
MagicKeyword::Muggle { inner, .. }
| MagicKeyword::Magic { inner, .. }
| MagicKeyword::Input { inner, .. }
| MagicKeyword::Sup { inner, .. } => inner,
MagicSymbol::Muggle { inner, .. }
| MagicSymbol::Magic { inner, .. }
| MagicSymbol::Input { inner, .. }
| MagicSymbol::Sup { inner, .. } => inner,
}
}
pub(crate) fn magic_adornment(&self) -> &[bool] {
match self {
MagicKeyword::Muggle { .. } => &[],
MagicKeyword::Magic { adornment, .. }
| MagicKeyword::Input { adornment, .. }
| MagicKeyword::Sup { adornment, .. } => adornment,
MagicSymbol::Muggle { .. } => &[],
MagicSymbol::Magic { adornment, .. }
| MagicSymbol::Input { adornment, .. }
| MagicSymbol::Sup { adornment, .. } => adornment,
}
}
pub(crate) fn has_bound_adornment(&self) -> bool {
@ -159,7 +159,7 @@ impl MagicKeyword {
#[derive(Debug, Clone)]
pub(crate) struct InputRule {
pub(crate) head: Vec<Keyword>,
pub(crate) head: Vec<Symbol>,
pub(crate) aggr: Vec<Option<Aggregation>>,
pub(crate) body: Vec<InputAtom>,
pub(crate) vld: Validity,
@ -167,7 +167,7 @@ pub(crate) struct InputRule {
#[derive(Debug, Clone)]
pub(crate) struct NormalFormRule {
pub(crate) head: Vec<Keyword>,
pub(crate) head: Vec<Symbol>,
pub(crate) aggr: Vec<Option<Aggregation>>,
pub(crate) body: Vec<NormalFormAtom>,
pub(crate) vld: Validity,
@ -175,14 +175,14 @@ pub(crate) struct NormalFormRule {
#[derive(Debug, Clone)]
pub(crate) struct MagicRule {
pub(crate) head: Vec<Keyword>,
pub(crate) head: Vec<Symbol>,
pub(crate) aggr: Vec<Option<Aggregation>>,
pub(crate) body: Vec<MagicAtom>,
pub(crate) vld: Validity,
}
impl MagicRule {
pub(crate) fn contained_rules(&self) -> BTreeSet<MagicKeyword> {
pub(crate) fn contained_rules(&self) -> BTreeSet<MagicSymbol> {
let mut coll = BTreeSet::new();
for atom in self.body.iter() {
match atom {
@ -237,44 +237,44 @@ pub(crate) struct InputAttrTripleAtom {
#[derive(Debug, Clone)]
pub(crate) struct NormalFormAttrTripleAtom {
pub(crate) attr: Attribute,
pub(crate) entity: Keyword,
pub(crate) value: Keyword,
pub(crate) entity: Symbol,
pub(crate) value: Symbol,
}
#[derive(Debug, Clone)]
pub(crate) struct MagicAttrTripleAtom {
pub(crate) attr: Attribute,
pub(crate) entity: Keyword,
pub(crate) value: Keyword,
pub(crate) entity: Symbol,
pub(crate) value: Symbol,
}
#[derive(Clone, Debug)]
pub(crate) struct InputRuleApplyAtom {
pub(crate) name: Keyword,
pub(crate) name: Symbol,
pub(crate) args: Vec<InputTerm<DataValue>>,
}
#[derive(Clone, Debug)]
pub(crate) struct NormalFormRuleApplyAtom {
pub(crate) name: Keyword,
pub(crate) args: Vec<Keyword>,
pub(crate) name: Symbol,
pub(crate) args: Vec<Symbol>,
}
#[derive(Clone, Debug)]
pub(crate) struct MagicRuleApplyAtom {
pub(crate) name: MagicKeyword,
pub(crate) args: Vec<Keyword>,
pub(crate) name: MagicSymbol,
pub(crate) args: Vec<Symbol>,
}
#[derive(Clone, Debug)]
pub(crate) enum InputTerm<T> {
Var(Keyword),
Var(Symbol),
Const(T),
}
#[derive(Clone, Debug)]
pub(crate) struct Unification {
pub(crate) binding: Keyword,
pub(crate) binding: Symbol,
pub(crate) expr: Expr,
}
@ -282,7 +282,7 @@ impl Unification {
pub(crate) fn is_const(&self) -> bool {
matches!(self.expr, Expr::Const(_))
}
pub(crate) fn bindings_in_expr(&self) -> BTreeSet<Keyword> {
pub(crate) fn bindings_in_expr(&self) -> BTreeSet<Symbol> {
self.expr.bindings()
}
}

@ -6,34 +6,34 @@ use serde_derive::{Deserialize, Serialize};
use smartstring::{LazyCompact, SmartString};
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Deserialize, Serialize, Hash)]
pub(crate) struct Keyword(pub(crate) SmartString<LazyCompact>);
pub(crate) struct Symbol(pub(crate) SmartString<LazyCompact>);
impl Display for Keyword {
impl Display for Symbol {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl Debug for Keyword {
impl Debug for Symbol {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl From<&str> for Keyword {
impl From<&str> for Symbol {
fn from(value: &str) -> Self {
Self(value.into())
}
}
impl TryFrom<&[u8]> for Keyword {
impl TryFrom<&[u8]> for Symbol {
type Error = anyhow::Error;
fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
Ok(std::str::from_utf8(value)?.into())
}
}
impl Keyword {
impl Symbol {
pub(crate) fn is_reserved(&self) -> bool {
self.0.is_empty()
|| self
@ -46,7 +46,7 @@ impl Keyword {
pub(crate) fn validate_not_reserved(&self) -> Result<()> {
ensure!(
!self.is_reserved(),
"reserved keyword not allowed here: {}",
"reserved symbol not allowed here: {}",
self.0
);
Ok(())
@ -57,17 +57,17 @@ impl Keyword {
}
lazy_static! {
pub(crate) static ref PROG_ENTRY: Keyword = Keyword::from("?");
pub(crate) static ref PROG_ENTRY: Symbol = Symbol::from("?");
}
#[cfg(test)]
mod tests {
use crate::data::keyword::Keyword;
use crate::data::symb::Symbol;
#[test]
fn reserved_kw() {
assert!(Keyword("_a".into()).is_reserved());
assert!(Keyword(":a".into()).is_reserved());
assert!(Keyword("".into()).is_reserved());
fn reserved_symb() {
assert!(Symbol("_a".into()).is_reserved());
assert!(Symbol(":a".into()).is_reserved());
assert!(Symbol("".into()).is_reserved());
}
}

@ -107,13 +107,13 @@ mod tests {
use std::collections::{BTreeMap, HashMap};
use std::mem::size_of;
use crate::data::keyword::Keyword;
use crate::data::symb::Symbol;
use crate::data::value::DataValue;
#[test]
fn show_size() {
dbg!(size_of::<DataValue>());
dbg!(size_of::<Keyword>());
dbg!(size_of::<Symbol>());
dbg!(size_of::<String>());
dbg!(size_of::<HashMap<String, String>>());
dbg!(size_of::<BTreeMap<String, String>>());

@ -6,7 +6,7 @@ use serde_json::Map;
use crate::data::attr::AttributeCardinality;
use crate::data::json::JsonValue;
use crate::data::keyword::Keyword;
use crate::data::symb::Symbol;
use crate::data::value::DataValue;
use crate::query::pull::{AttrPullSpec, PullSpec, PullSpecs};
use crate::runtime::transact::SessionTx;
@ -34,22 +34,22 @@ impl SessionTx {
JsonValue::String(s) if s == "*" => Ok(PullSpec::PullAll),
JsonValue::String(s) if s == "_id" => Ok(PullSpec::PullId("_id".into())),
JsonValue::String(s) => {
let input_kw = Keyword::from(s.as_ref());
let reverse = input_kw.0.starts_with('<');
let kw = if reverse {
Keyword::from(input_kw.0.strip_prefix('<').unwrap())
let input_symb = Symbol::from(s.as_ref());
let reverse = input_symb.0.starts_with('<');
let symb = if reverse {
Symbol::from(input_symb.0.strip_prefix('<').unwrap())
} else {
input_kw.clone()
input_symb.clone()
};
let attr = self
.attr_by_kw(&kw)?
.ok_or_else(|| anyhow!("attribute {} not found", kw))?;
.attr_by_name(&symb)?
.ok_or_else(|| anyhow!("attribute {} not found", symb))?;
let cardinality = attr.cardinality;
Ok(PullSpec::Attr(AttrPullSpec {
attr,
default_val: DataValue::Null,
reverse,
name: input_kw,
name: input_symb,
cardinality,
take: None,
nested: vec![],
@ -71,7 +71,7 @@ impl SessionTx {
let mut as_override = None;
let mut take = None;
let mut cardinality_override = None;
let mut input_kw = None;
let mut input_symb = None;
let mut sub_target = vec![];
let mut recursive = false;
let mut recursion_limit = None;
@ -82,7 +82,7 @@ impl SessionTx {
match k as &str {
"as" => {
as_override =
Some(Keyword::from(v.as_str().ok_or_else(|| {
Some(Symbol::from(v.as_str().ok_or_else(|| {
anyhow!("expect 'as' field to be string, got {}", v)
})?))
}
@ -105,7 +105,7 @@ impl SessionTx {
if v == "_id" {
pull_id = true
} else {
input_kw = Some(Keyword::from(v));
input_symb = Some(Symbol::from(v));
}
}
"recurse" => {
@ -149,21 +149,21 @@ impl SessionTx {
));
}
if input_kw.is_none() {
if input_symb.is_none() {
bail!("no target key in pull definition");
}
let input_kw = input_kw.unwrap();
let input_symb = input_symb.unwrap();
let reverse = input_kw.0.starts_with('<');
let kw = if reverse {
Keyword::from(input_kw.0.strip_prefix('<').unwrap())
let reverse = input_symb.0.starts_with('<');
let symb = if reverse {
Symbol::from(input_symb.0.strip_prefix('<').unwrap())
} else {
input_kw.clone()
input_symb.clone()
};
let attr = self
.attr_by_kw(&kw)?
.ok_or_else(|| anyhow!("attribute not found: {}", kw))?;
.attr_by_name(&symb)?
.ok_or_else(|| anyhow!("attribute not found: {}", symb))?;
let cardinality = cardinality_override.unwrap_or(attr.cardinality);
let nested = self.parse_pull(&JsonValue::Array(sub_target), depth + 1)?;
@ -181,7 +181,7 @@ impl SessionTx {
attr,
default_val,
reverse,
name: as_override.unwrap_or(input_kw),
name: as_override.unwrap_or(input_symb),
cardinality,
take,
nested,

@ -9,11 +9,11 @@ use crate::data::attr::Attribute;
use crate::data::expr::{get_op, Expr};
use crate::data::id::{EntityId, Validity};
use crate::data::json::JsonValue;
use crate::data::keyword::{Keyword, PROG_ENTRY};
use crate::data::program::{
InputAtom, InputAttrTripleAtom, InputProgram, InputRule, InputRuleApplyAtom, InputTerm,
Unification,
};
use crate::data::symb::{Symbol, PROG_ENTRY};
use crate::data::value::DataValue;
use crate::query::pull::PullSpecs;
use crate::runtime::transact::SessionTx;
@ -59,7 +59,7 @@ impl SessionTx {
fn parse_query_out_spec(
&mut self,
payload: &JsonValue,
entry_bindings: &[Keyword],
entry_bindings: &[Symbol],
) -> Result<OutSpec> {
match payload {
JsonValue::Object(out_spec_map) => {
@ -79,7 +79,7 @@ impl SessionTx {
pub(crate) fn parse_pull_specs_for_query_spec(
&mut self,
out_spec: &Vec<JsonValue>,
entry_bindings: &[Keyword],
entry_bindings: &[Symbol],
) -> Result<Vec<(usize, Option<PullSpecs>)>> {
let entry_bindings: BTreeMap<_, _> = entry_bindings
.iter()
@ -91,22 +91,22 @@ impl SessionTx {
.map(|spec| -> Result<(usize, Option<PullSpecs>)> {
match spec {
JsonValue::String(s) => {
let kw = Keyword::from(s as &str);
let symb = Symbol::from(s as &str);
let idx = *entry_bindings
.get(&kw)
.ok_or_else(|| anyhow!("binding {} not found", kw))?;
.get(&symb)
.ok_or_else(|| anyhow!("binding {} not found", symb))?;
Ok((idx, None))
}
JsonValue::Object(m) => {
let kw = m
let symb = m
.get("pull")
.ok_or_else(|| anyhow!("expect field 'pull' in {:?}", m))?
.as_str()
.ok_or_else(|| anyhow!("expect 'pull' to be a binding in {:?}", m))?;
let kw = Keyword::from(kw);
let symb = Symbol::from(symb);
let idx = *entry_bindings
.get(&kw)
.ok_or_else(|| anyhow!("binding {} not found", kw))?;
.get(&symb)
.ok_or_else(|| anyhow!("binding {} not found", symb))?;
let spec = m
.get("spec")
.ok_or_else(|| anyhow!("expect field 'spec' in {:?}", m))?;
@ -129,7 +129,7 @@ impl SessionTx {
.ok_or_else(|| anyhow!("expect array for rules, got {}", payload))?
.iter()
.map(|o| self.parse_input_rule_definition(o, default_vld));
let mut collected: BTreeMap<Keyword, Vec<InputRule>> = BTreeMap::new();
let mut collected: BTreeMap<Symbol, Vec<InputRule>> = BTreeMap::new();
for res in rules {
let (name, rule) = res?;
match collected.entry(name) {
@ -141,9 +141,9 @@ impl SessionTx {
}
}
}
let ret: BTreeMap<Keyword, Vec<InputRule>> = collected
let ret: BTreeMap<Symbol, Vec<InputRule>> = collected
.into_iter()
.map(|(name, rules)| -> Result<(Keyword, Vec<InputRule>)> {
.map(|(name, rules)| -> Result<(Symbol, Vec<InputRule>)> {
let mut arities = rules.iter().map(|r| r.head.len());
let arity = arities.next().unwrap();
for other in arities {
@ -155,7 +155,7 @@ impl SessionTx {
})
.try_collect()?;
match ret.get(&PROG_ENTRY as &Keyword) {
match ret.get(&PROG_ENTRY as &Symbol) {
None => bail!("no entry defined for datalog program"),
Some(ruleset) => {
if !ruleset.iter().map(|r| &r.head).all_equal() {
@ -183,8 +183,8 @@ impl SessionTx {
.get("unify")
.ok_or_else(|| anyhow!("expect expression to have field 'unify'"))?
.as_str()
.ok_or_else(|| anyhow!("expect field 'unify' to be a keyword"))?;
let binding = Keyword::from(binding);
.ok_or_else(|| anyhow!("expect field 'unify' to be a symbol"))?;
let binding = Symbol::from(binding);
ensure!(
binding.is_query_var(),
"binding for unification {} is reserved",
@ -237,9 +237,9 @@ impl SessionTx {
fn parse_expr_arg(payload: &JsonValue) -> Result<Expr> {
match payload {
JsonValue::String(s) => {
let kw = Keyword::from(s as &str);
if kw.is_reserved() {
Ok(Expr::Binding(kw, None))
let symb = Symbol::from(s as &str);
if symb.is_reserved() {
Ok(Expr::Binding(symb, None))
} else {
Ok(Expr::Const(DataValue::String(s.into())))
}
@ -275,7 +275,7 @@ impl SessionTx {
.iter()
.map(|value_rep| -> Result<InputTerm<DataValue>> {
if let Some(s) = value_rep.as_str() {
let var = Keyword::from(s);
let var = Symbol::from(s);
if s.starts_with(['?', '_']) {
return Ok(InputTerm::Var(var));
} else {
@ -306,11 +306,11 @@ impl SessionTx {
&mut self,
payload: &JsonValue,
default_vld: Validity,
) -> Result<(Keyword, InputRule)> {
) -> Result<(Symbol, InputRule)> {
let rule_name = payload
.get("rule")
.ok_or_else(|| anyhow!("expect key 'rule' in rule definition"))?;
let rule_name = Keyword::try_from(rule_name)?;
let rule_name = Symbol::try_from(rule_name)?;
if !rule_name.is_prog_entry() {
rule_name.validate_not_reserved()?;
}
@ -334,7 +334,7 @@ impl SessionTx {
let mut rule_aggr = vec![];
for head_item in rule_head_vec {
if let Some(s) = head_item.as_str() {
rule_head.push(Keyword::from(s));
rule_head.push(Symbol::from(s));
rule_aggr.push(None);
} else {
todo!()
@ -446,14 +446,14 @@ impl SessionTx {
m
);
let (k, v) = m.iter().next().unwrap();
let kw = Keyword::from(k as &str);
let symb = Symbol::from(k as &str);
let attr = self
.attr_by_kw(&kw)?
.ok_or_else(|| anyhow!("attribute {} not found", kw))?;
.attr_by_name(&symb)?
.ok_or_else(|| anyhow!("attribute {} not found", symb))?;
ensure!(
attr.indexing.is_unique_index(),
"pull inside query must use unique index, of which {} is not",
attr.keyword
attr.name
);
let value = attr.val_type.coerce_value(v.into())?;
let eid = self
@ -483,7 +483,7 @@ impl SessionTx {
vld: Validity,
) -> Result<InputTerm<DataValue>> {
if let Some(s) = value_rep.as_str() {
let var = Keyword::from(s);
let var = Symbol::from(s);
if s.starts_with(['?', '_']) {
return Ok(InputTerm::Var(var));
} else {
@ -508,7 +508,7 @@ impl SessionTx {
vld: Validity,
) -> Result<InputTerm<EntityId>> {
if let Some(s) = entity_rep.as_str() {
let var = Keyword::from(s);
let var = Symbol::from(s);
if s.starts_with(['?', '_']) {
return Ok(InputTerm::Var(var));
} else {
@ -527,13 +527,13 @@ impl SessionTx {
fn parse_triple_atom_attr(&mut self, attr_rep: &JsonValue) -> Result<Attribute> {
match attr_rep {
JsonValue::String(s) => {
let kw = Keyword::from(s as &str);
let kw = Symbol::from(s as &str);
let attr = self
.attr_by_kw(&kw)?
.attr_by_name(&kw)?
.ok_or_else(|| anyhow!("attribute {} not found", kw))?;
Ok(attr)
}
v => bail!("expect attribute keyword for triple atom, got {}", v),
v => bail!("expect attribute name for triple atom, got {}", v),
}
}
}

@ -8,7 +8,7 @@ use serde_json::Map;
use crate::data::attr::{Attribute, AttributeIndex, AttributeTyping};
use crate::data::id::{AttrId, EntityId, Validity};
use crate::data::json::JsonValue;
use crate::data::keyword::Keyword;
use crate::data::symb::Symbol;
use crate::data::value::DataValue;
use crate::runtime::transact::SessionTx;
@ -282,9 +282,9 @@ impl SessionTx {
"double only allowed for 'retract', got {}",
action
);
let kw: Keyword = attr.try_into()?;
let kw: Symbol = attr.try_into()?;
let attr = self
.attr_by_kw(&kw)?
.attr_by_name(&kw)?
.ok_or_else(|| anyhow!("attribute not found {}", kw))?;
let eid = eid
@ -319,9 +319,9 @@ impl SessionTx {
temp_id_ctx: &mut TempIdCtx,
collected: &mut Vec<Quintuple>,
) -> Result<()> {
let kw: Keyword = attr_kw.try_into()?;
let kw: Symbol = attr_kw.try_into()?;
let attr = self
.attr_by_kw(&kw)?
.attr_by_name(&kw)?
.ok_or_else(|| anyhow!("attribute not found: {}", kw))?;
if attr.cardinality.is_many() && attr.val_type != AttributeTyping::List && val.is_array() {
for cur_val in val.as_array().unwrap() {
@ -407,7 +407,7 @@ impl SessionTx {
if k != PERM_ID_FIELD && k != TEMP_ID_FIELD {
let kw = (k as &str).into();
let attr = self
.attr_by_kw(&kw)?
.attr_by_name(&kw)?
.ok_or_else(|| anyhow!("attribute {} not found", kw))?;
has_unique_attr = has_unique_attr || attr.indexing.is_unique_index();
has_identity_attr = has_identity_attr || attr.indexing == AttributeIndex::Identity;
@ -502,7 +502,7 @@ impl SessionTx {
ensure!(
attr.indexing.is_unique_index(),
"cannot use non-unique attribute {} to specify entity",
attr.keyword
attr.name
);
}
}

@ -4,20 +4,20 @@ use anyhow::{anyhow, ensure, Result};
use itertools::Itertools;
use crate::data::expr::Expr;
use crate::data::keyword::Keyword;
use crate::data::program::{MagicAtom, MagicKeyword, MagicRule, StratifiedMagicProgram};
use crate::data::symb::Symbol;
use crate::data::program::{MagicAtom, MagicSymbol, MagicRule, StratifiedMagicProgram};
use crate::query::relation::Relation;
use crate::runtime::temp_store::TempStore;
use crate::runtime::transact::SessionTx;
pub(crate) type CompiledProgram =
BTreeMap<MagicKeyword, Vec<(Vec<Keyword>, BTreeSet<MagicKeyword>, Relation)>>;
BTreeMap<MagicSymbol, Vec<(Vec<Symbol>, BTreeSet<MagicSymbol>, Relation)>>;
impl SessionTx {
pub(crate) fn stratified_magic_compile(
&mut self,
prog: &StratifiedMagicProgram,
) -> Result<(Vec<CompiledProgram>, BTreeMap<MagicKeyword, TempStore>)> {
) -> Result<(Vec<CompiledProgram>, BTreeMap<MagicSymbol, TempStore>)> {
let stores = prog
.0
.iter()
@ -40,8 +40,8 @@ impl SessionTx {
.iter()
.map(
|(k, body)| -> Result<(
MagicKeyword,
Vec<(Vec<Keyword>, BTreeSet<MagicKeyword>, Relation)>,
MagicSymbol,
Vec<(Vec<Symbol>, BTreeSet<MagicSymbol>, Relation)>,
)> {
let mut collected = Vec::with_capacity(body.len());
for (rule_idx, rule) in body.iter().enumerate() {
@ -67,16 +67,16 @@ impl SessionTx {
pub(crate) fn compile_magic_rule_body(
&mut self,
rule: &MagicRule,
rule_name: &MagicKeyword,
rule_name: &MagicSymbol,
rule_idx: usize,
stores: &BTreeMap<MagicKeyword, TempStore>,
ret_vars: &[Keyword],
stores: &BTreeMap<MagicSymbol, TempStore>,
ret_vars: &[Symbol],
) -> Result<Relation> {
let mut ret = Relation::unit();
let mut seen_variables = BTreeSet::new();
let mut serial_id = 0;
let mut gen_kw = || {
let ret = Keyword::from(&format!("**{}", serial_id) as &str);
let ret = Symbol::from(&format!("**{}", serial_id) as &str);
serial_id += 1;
ret
};

@ -4,8 +4,8 @@ use std::mem;
use anyhow::{anyhow, Result};
use log::{debug, log_enabled, trace, Level};
use crate::data::keyword::PROG_ENTRY;
use crate::data::program::MagicKeyword;
use crate::data::symb::PROG_ENTRY;
use crate::data::program::MagicSymbol;
use crate::query::compile::CompiledProgram;
use crate::runtime::temp_store::TempStore;
use crate::runtime::transact::SessionTx;
@ -14,10 +14,10 @@ impl SessionTx {
pub(crate) fn stratified_magic_evaluate(
&mut self,
strata: &[CompiledProgram],
stores: &BTreeMap<MagicKeyword, TempStore>,
stores: &BTreeMap<MagicSymbol, TempStore>,
) -> Result<TempStore> {
let ret_area = stores
.get(&MagicKeyword::Muggle {
.get(&MagicSymbol::Muggle {
inner: PROG_ENTRY.clone(),
})
.ok_or_else(|| anyhow!("program entry not found in rules"))?
@ -32,7 +32,7 @@ impl SessionTx {
fn semi_naive_magic_evaluate(
&mut self,
prog: &CompiledProgram,
stores: &BTreeMap<MagicKeyword, TempStore>,
stores: &BTreeMap<MagicSymbol, TempStore>,
) -> Result<()> {
if log_enabled!(Level::Debug) {
for (k, vs) in prog.iter() {

@ -6,7 +6,7 @@ use itertools::Itertools;
use crate::data::expr::Expr;
use crate::data::program::{
InputAtom, InputAttrTripleAtom, InputRuleApplyAtom, InputTerm, NormalFormAtom,
NormalFormAttrTripleAtom, NormalFormRuleApplyAtom, TempKwGen, Unification,
NormalFormAttrTripleAtom, NormalFormRuleApplyAtom, TempSymbGen, Unification,
};
#[derive(Debug)]
@ -79,11 +79,11 @@ impl InputAtom {
pub(crate) fn disjunctive_normal_form(self) -> Result<Disjunction> {
let neg_form = self.negation_normal_form()?;
let mut gen = TempKwGen::default();
let mut gen = TempSymbGen::default();
neg_form.do_disjunctive_normal_form(&mut gen)
}
fn do_disjunctive_normal_form(self, gen: &mut TempKwGen) -> Result<Disjunction> {
fn do_disjunctive_normal_form(self, gen: &mut TempSymbGen) -> Result<Disjunction> {
// invariants: the input is already in negation normal form
// the return value is a disjunction of conjunctions, with no nesting
Ok(match self {
@ -121,7 +121,7 @@ impl InputAtom {
}
impl InputRuleApplyAtom {
fn normalize(self, is_negated: bool, gen: &mut TempKwGen) -> Disjunction {
fn normalize(self, is_negated: bool, gen: &mut TempSymbGen) -> Disjunction {
let mut ret = Vec::with_capacity(self.args.len() + 1);
let mut args = Vec::with_capacity(self.args.len());
let mut seen_variables = BTreeSet::new();
@ -168,7 +168,7 @@ impl InputRuleApplyAtom {
}
impl InputAttrTripleAtom {
fn normalize(self, is_negated: bool, gen: &mut TempKwGen) -> Disjunction {
fn normalize(self, is_negated: bool, gen: &mut TempSymbGen) -> Disjunction {
let wrap = |atom| {
if is_negated {
NormalFormAtom::NegatedAttrTriple(atom)

@ -4,9 +4,9 @@ use std::mem;
use itertools::Itertools;
use smallvec::SmallVec;
use crate::data::keyword::{Keyword, PROG_ENTRY};
use crate::data::symb::{Symbol, PROG_ENTRY};
use crate::data::program::{
MagicAtom, MagicAttrTripleAtom, MagicKeyword, MagicProgram, MagicRule, MagicRuleApplyAtom,
MagicAtom, MagicAttrTripleAtom, MagicSymbol, MagicProgram, MagicRule, MagicRuleApplyAtom,
NormalFormAtom, NormalFormProgram, NormalFormRule, StratifiedMagicProgram,
StratifiedNormalFormProgram,
};
@ -31,7 +31,7 @@ impl MagicProgram {
};
for (rule_head, rules) in self.prog {
// at this point, rule_head must be Muggle or Magic, the remaining options are impossible
let rule_name = rule_head.as_keyword();
let rule_name = rule_head.as_plain_symbol();
let adornment = rule_head.magic_adornment();
// can only be true if rule is magic and args are not all free
@ -40,7 +40,7 @@ impl MagicProgram {
for (rule_idx, rule) in rules.into_iter().enumerate() {
let mut sup_idx = 0;
let mut make_sup_kw = || {
let ret = MagicKeyword::Sup {
let ret = MagicSymbol::Sup {
inner: rule_name.clone(),
adornment: adornment.into(),
rule_idx: rule_idx as u16,
@ -50,7 +50,7 @@ impl MagicProgram {
ret
};
let mut collected_atoms = vec![];
let mut seen_bindings: BTreeSet<Keyword> = Default::default();
let mut seen_bindings: BTreeSet<Symbol> = Default::default();
// SIP from input rule if rule has any bound args
if rule_has_bound_args {
@ -66,7 +66,7 @@ impl MagicProgram {
.collect_vec();
let sup_aggr = vec![None; sup_args.len()];
let sup_body = vec![MagicAtom::Rule(MagicRuleApplyAtom {
name: MagicKeyword::Input {
name: MagicSymbol::Input {
inner: rule_name.clone(),
adornment: adornment.into(),
},
@ -132,8 +132,8 @@ impl MagicProgram {
collected_atoms.push(sup_rule_app.clone());
// finally add to the input rule application
let inp_kw = MagicKeyword::Input {
inner: r_app.name.as_keyword().clone(),
let inp_kw = MagicSymbol::Input {
inner: r_app.name.as_plain_symbol().clone(),
adornment: r_app.name.magic_adornment().into(),
};
let inp_entry = ret_prog.prog.entry(inp_kw.clone()).or_default();
@ -179,9 +179,9 @@ impl MagicProgram {
}
impl NormalFormProgram {
fn get_downstream_rules(&self) -> BTreeSet<Keyword> {
fn get_downstream_rules(&self) -> BTreeSet<Symbol> {
let own_rules: BTreeSet<_> = self.prog.keys().collect();
let mut downstream_rules: BTreeSet<Keyword> = Default::default();
let mut downstream_rules: BTreeSet<Symbol> = Default::default();
for rules in self.prog.values() {
for rule in rules {
for atom in rule.body.iter() {
@ -198,7 +198,7 @@ impl NormalFormProgram {
}
downstream_rules
}
fn adorn(&self, upstream_rules: &BTreeSet<Keyword>) -> MagicProgram {
fn adorn(&self, upstream_rules: &BTreeSet<Symbol>) -> MagicProgram {
let rules_to_rewrite: BTreeSet<_> = self
.prog
.keys()
@ -226,7 +226,7 @@ impl NormalFormProgram {
adorned_rules.push(adorned_rule);
}
adorned_prog.prog.insert(
MagicKeyword::Muggle {
MagicSymbol::Muggle {
inner: rule_name.clone(),
},
adorned_rules,
@ -237,7 +237,7 @@ impl NormalFormProgram {
if adorned_prog.prog.contains_key(&head) {
continue;
}
let original_rules = self.prog.get(head.as_keyword()).unwrap();
let original_rules = self.prog.get(head.as_plain_symbol()).unwrap();
let adornment = head.magic_adornment();
let mut adorned_rules = Vec::with_capacity(original_rules.len());
for rule in original_rules {
@ -260,9 +260,9 @@ impl NormalFormProgram {
impl NormalFormAtom {
fn adorn(
&self,
pending: &mut Vec<MagicKeyword>,
seen_bindings: &mut BTreeSet<Keyword>,
rules_to_rewrite: &BTreeSet<Keyword>,
pending: &mut Vec<MagicSymbol>,
seen_bindings: &mut BTreeSet<Symbol>,
rules_to_rewrite: &BTreeSet<Symbol>,
) -> MagicAtom {
match self {
NormalFormAtom::AttrTriple(a) => {
@ -291,7 +291,7 @@ impl NormalFormAtom {
for arg in rule.args.iter() {
adornment.push(!seen_bindings.insert(arg.clone()));
}
let name = MagicKeyword::Magic {
let name = MagicSymbol::Magic {
inner: rule.name.clone(),
adornment,
};
@ -304,7 +304,7 @@ impl NormalFormAtom {
})
} else {
MagicAtom::Rule(MagicRuleApplyAtom {
name: MagicKeyword::Muggle {
name: MagicSymbol::Muggle {
inner: rule.name.clone(),
},
args: rule.args.clone(),
@ -319,7 +319,7 @@ impl NormalFormAtom {
})
}
NormalFormAtom::NegatedRule(nr) => MagicAtom::NegatedRule(MagicRuleApplyAtom {
name: MagicKeyword::Muggle {
name: MagicSymbol::Muggle {
inner: nr.name.clone(),
},
args: nr.args.clone(),
@ -335,9 +335,9 @@ impl NormalFormAtom {
impl NormalFormRule {
fn adorn(
&self,
pending: &mut Vec<MagicKeyword>,
rules_to_rewrite: &BTreeSet<Keyword>,
mut seen_bindings: BTreeSet<Keyword>,
pending: &mut Vec<MagicSymbol>,
rules_to_rewrite: &BTreeSet<Symbol>,
mut seen_bindings: BTreeSet<Symbol>,
) -> MagicRule {
let mut ret_body = Vec::with_capacity(self.body.len());

@ -11,7 +11,7 @@ use crate::data::encode::{
};
use crate::data::id::{AttrId, EntityId, Validity};
use crate::data::json::JsonValue;
use crate::data::keyword::Keyword;
use crate::data::symb::Symbol;
use crate::data::triple::StoreOp;
use crate::data::value::DataValue;
use crate::parse::query::OutSpec;
@ -24,7 +24,7 @@ pub(crate) type PullSpecs = Vec<PullSpec>;
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
pub(crate) enum PullSpec {
PullAll,
PullId(Keyword),
PullId(Symbol),
Attr(AttrPullSpec),
}
@ -45,7 +45,7 @@ pub(crate) struct AttrPullSpec {
pub(crate) reverse: bool,
pub(crate) attr: Attribute,
pub(crate) default_val: DataValue,
pub(crate) name: Keyword,
pub(crate) name: Symbol,
pub(crate) cardinality: AttributeCardinality,
pub(crate) take: Option<usize>,
pub(crate) nested: PullSpecs,
@ -532,7 +532,7 @@ impl SessionTx {
let val_id = value.get_entity_id()?;
if pull_all_seen.contains(&val_id) {
let arr = collector
.entry(attr.keyword.to_string())
.entry(attr.name.to_string())
.or_insert_with(|| json!([]));
let arr = arr.as_array_mut().unwrap();
arr.push(value.into());
@ -541,14 +541,14 @@ impl SessionTx {
self.pull_all(val_id, vld, &mut subcollector, pull_all_seen)?;
let arr = collector
.entry(attr.keyword.to_string())
.entry(attr.name.to_string())
.or_insert_with(|| json!([]));
let arr = arr.as_array_mut().unwrap();
arr.push(subcollector.into());
}
} else {
let arr = collector
.entry(attr.keyword.to_string())
.entry(attr.name.to_string())
.or_insert_with(|| json!([]));
let arr = arr.as_array_mut().unwrap();
arr.push(value.into());
@ -556,14 +556,14 @@ impl SessionTx {
} else if attr.val_type == AttributeTyping::Component {
let val_id = value.get_entity_id()?;
if pull_all_seen.contains(&val_id) {
collector.insert(attr.keyword.to_string(), value.into());
collector.insert(attr.name.to_string(), value.into());
} else {
let mut subcollector = Map::default();
self.pull_all(val_id, vld, &mut subcollector, pull_all_seen)?;
collector.insert(attr.keyword.to_string(), subcollector.into());
collector.insert(attr.name.to_string(), subcollector.into());
}
} else {
collector.insert(attr.keyword.to_string(), value.into());
collector.insert(attr.name.to_string(), value.into());
}
current.encoded_entity_amend_validity_to_inf_past();
it.seek(&current);

@ -8,7 +8,7 @@ use itertools::Itertools;
use crate::data::attr::Attribute;
use crate::data::expr::Expr;
use crate::data::id::Validity;
use crate::data::keyword::Keyword;
use crate::data::symb::Symbol;
use crate::data::tuple::{Tuple, TupleIter};
use crate::data::value::DataValue;
use crate::runtime::temp_store::{TempStore, TempStoreId};
@ -27,9 +27,9 @@ pub(crate) enum Relation {
pub(crate) struct UnificationRelation {
parent: Box<Relation>,
binding: Keyword,
binding: Symbol,
expr: Expr,
pub(crate) to_eliminate: BTreeSet<Keyword>,
pub(crate) to_eliminate: BTreeSet<Symbol>,
}
impl UnificationRelation {
@ -43,7 +43,7 @@ impl UnificationRelation {
.collect();
self.expr.fill_binding_indices(&parent_bindings);
}
pub(crate) fn do_eliminate_temp_vars(&mut self, used: &BTreeSet<Keyword>) -> Result<()> {
pub(crate) fn do_eliminate_temp_vars(&mut self, used: &BTreeSet<Symbol>) -> Result<()> {
for binding in self.parent.bindings_before_eliminate() {
if !used.contains(&binding) {
self.to_eliminate.insert(binding.clone());
@ -94,11 +94,11 @@ impl UnificationRelation {
pub(crate) struct FilteredRelation {
parent: Box<Relation>,
pred: Expr,
pub(crate) to_eliminate: BTreeSet<Keyword>,
pub(crate) to_eliminate: BTreeSet<Symbol>,
}
impl FilteredRelation {
pub(crate) fn do_eliminate_temp_vars(&mut self, used: &BTreeSet<Keyword>) -> Result<()> {
pub(crate) fn do_eliminate_temp_vars(&mut self, used: &BTreeSet<Symbol>) -> Result<()> {
for binding in self.parent.bindings_before_eliminate() {
if !used.contains(&binding) {
self.to_eliminate.insert(binding.clone());
@ -160,7 +160,7 @@ impl FilteredRelation {
}
}
struct BindingFormatter(Vec<Keyword>);
struct BindingFormatter(Vec<Symbol>);
impl Debug for BindingFormatter {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
@ -191,7 +191,7 @@ impl Debug for Relation {
Relation::Triple(r) => f
.debug_tuple("Triple")
.field(&bindings)
.field(&r.attr.keyword)
.field(&r.attr.name)
.finish(),
Relation::Derived(r) => f
.debug_tuple("Derived")
@ -278,14 +278,14 @@ impl Relation {
pub(crate) fn cartesian_join(self, right: Relation) -> Self {
self.join(right, vec![], vec![])
}
pub(crate) fn derived(bindings: Vec<Keyword>, storage: TempStore) -> Self {
pub(crate) fn derived(bindings: Vec<Symbol>, storage: TempStore) -> Self {
Self::Derived(StoredDerivedRelation { bindings, storage })
}
pub(crate) fn triple(
attr: Attribute,
vld: Validity,
e_binding: Keyword,
v_binding: Keyword,
e_binding: Symbol,
v_binding: Symbol,
) -> Self {
Self::Triple(TripleRelation {
attr,
@ -293,7 +293,7 @@ impl Relation {
bindings: [e_binding, v_binding],
})
}
pub(crate) fn reorder(self, new_order: Vec<Keyword>) -> Self {
pub(crate) fn reorder(self, new_order: Vec<Symbol>) -> Self {
Self::Reorder(ReorderRelation {
relation: Box::new(self),
new_order,
@ -306,7 +306,7 @@ impl Relation {
to_eliminate: Default::default(),
})
}
pub(crate) fn unify(self, binding: Keyword, expr: Expr) -> Self {
pub(crate) fn unify(self, binding: Symbol, expr: Expr) -> Self {
Relation::Unification(UnificationRelation {
parent: Box::new(self),
binding,
@ -317,8 +317,8 @@ impl Relation {
pub(crate) fn join(
self,
right: Relation,
left_keys: Vec<Keyword>,
right_keys: Vec<Keyword>,
left_keys: Vec<Symbol>,
right_keys: Vec<Symbol>,
) -> Self {
Relation::Join(Box::new(InnerJoin {
left: self,
@ -333,8 +333,8 @@ impl Relation {
pub(crate) fn neg_join(
self,
right: Relation,
left_keys: Vec<Keyword>,
right_keys: Vec<Keyword>,
left_keys: Vec<Symbol>,
right_keys: Vec<Symbol>,
) -> Self {
Relation::NegJoin(Box::new(NegJoin {
left: self,
@ -351,11 +351,11 @@ impl Relation {
#[derive(Debug)]
pub(crate) struct ReorderRelation {
pub(crate) relation: Box<Relation>,
pub(crate) new_order: Vec<Keyword>,
pub(crate) new_order: Vec<Symbol>,
}
impl ReorderRelation {
fn bindings(&self) -> Vec<Keyword> {
fn bindings(&self) -> Vec<Symbol> {
self.new_order.clone()
}
fn iter<'a>(
@ -396,9 +396,9 @@ impl ReorderRelation {
#[derive(Debug)]
pub(crate) struct InlineFixedRelation {
pub(crate) bindings: Vec<Keyword>,
pub(crate) bindings: Vec<Symbol>,
pub(crate) data: Vec<Vec<DataValue>>,
pub(crate) to_eliminate: BTreeSet<Keyword>,
pub(crate) to_eliminate: BTreeSet<Symbol>,
}
impl InlineFixedRelation {
@ -409,7 +409,7 @@ impl InlineFixedRelation {
to_eliminate: Default::default(),
}
}
pub(crate) fn do_eliminate_temp_vars(&mut self, used: &BTreeSet<Keyword>) -> Result<()> {
pub(crate) fn do_eliminate_temp_vars(&mut self, used: &BTreeSet<Symbol>) -> Result<()> {
for binding in &self.bindings {
if !used.contains(binding) {
self.to_eliminate.insert(binding.clone());
@ -496,7 +496,7 @@ impl InlineFixedRelation {
pub(crate) struct TripleRelation {
pub(crate) attr: Attribute,
pub(crate) vld: Validity,
pub(crate) bindings: [Keyword; 2],
pub(crate) bindings: [Symbol; 2],
}
pub(crate) fn flatten_err<T, E1: Into<anyhow::Error>, E2: Into<anyhow::Error>>(
@ -1035,7 +1035,7 @@ impl TripleRelation {
}
}
fn get_eliminate_indices(bindings: &[Keyword], eliminate: &BTreeSet<Keyword>) -> BTreeSet<usize> {
fn get_eliminate_indices(bindings: &[Symbol], eliminate: &BTreeSet<Symbol>) -> BTreeSet<usize> {
bindings
.iter()
.enumerate()
@ -1051,7 +1051,7 @@ fn get_eliminate_indices(bindings: &[Keyword], eliminate: &BTreeSet<Keyword>) ->
#[derive(Debug)]
pub(crate) struct StoredDerivedRelation {
pub(crate) bindings: Vec<Keyword>,
pub(crate) bindings: Vec<Symbol>,
pub(crate) storage: TempStore,
}
@ -1209,8 +1209,8 @@ impl StoredDerivedRelation {
pub(crate) struct Joiner {
// invariant: these are of the same lengths
pub(crate) left_keys: Vec<Keyword>,
pub(crate) right_keys: Vec<Keyword>,
pub(crate) left_keys: Vec<Symbol>,
pub(crate) right_keys: Vec<Symbol>,
}
impl Debug for Joiner {
@ -1224,8 +1224,8 @@ impl Debug for Joiner {
impl Joiner {
pub(crate) fn join_indices(
&self,
left_bindings: &[Keyword],
right_bindings: &[Keyword],
left_bindings: &[Symbol],
right_bindings: &[Symbol],
) -> Result<(Vec<usize>, Vec<usize>)> {
let left_binding_map = left_bindings
.iter()
@ -1262,7 +1262,7 @@ impl Joiner {
}
impl Relation {
pub(crate) fn eliminate_temp_vars(&mut self, used: &BTreeSet<Keyword>) -> Result<()> {
pub(crate) fn eliminate_temp_vars(&mut self, used: &BTreeSet<Symbol>) -> Result<()> {
match self {
Relation::Fixed(r) => r.do_eliminate_temp_vars(used),
Relation::Triple(_r) => Ok(()),
@ -1275,7 +1275,7 @@ impl Relation {
}
}
fn eliminate_set(&self) -> Option<&BTreeSet<Keyword>> {
fn eliminate_set(&self) -> Option<&BTreeSet<Symbol>> {
match self {
Relation::Fixed(r) => Some(&r.to_eliminate),
Relation::Triple(_) => None,
@ -1288,7 +1288,7 @@ impl Relation {
}
}
pub(crate) fn bindings_after_eliminate(&self) -> Vec<Keyword> {
pub(crate) fn bindings_after_eliminate(&self) -> Vec<Symbol> {
let ret = self.bindings_before_eliminate();
if let Some(to_eliminate) = self.eliminate_set() {
ret.into_iter()
@ -1299,7 +1299,7 @@ impl Relation {
}
}
fn bindings_before_eliminate(&self) -> Vec<Keyword> {
fn bindings_before_eliminate(&self) -> Vec<Symbol> {
match self {
Relation::Fixed(f) => f.bindings.clone(),
Relation::Triple(t) => t.bindings.to_vec(),
@ -1342,11 +1342,11 @@ pub(crate) struct NegJoin {
pub(crate) left: Relation,
pub(crate) right: Relation,
pub(crate) joiner: Joiner,
pub(crate) to_eliminate: BTreeSet<Keyword>,
pub(crate) to_eliminate: BTreeSet<Symbol>,
}
impl NegJoin {
pub(crate) fn do_eliminate_temp_vars(&mut self, used: &BTreeSet<Keyword>) -> Result<()> {
pub(crate) fn do_eliminate_temp_vars(&mut self, used: &BTreeSet<Symbol>) -> Result<()> {
for binding in self.left.bindings_after_eliminate() {
if !used.contains(&binding) {
self.to_eliminate.insert(binding.clone());
@ -1409,11 +1409,11 @@ pub(crate) struct InnerJoin {
pub(crate) left: Relation,
pub(crate) right: Relation,
pub(crate) joiner: Joiner,
pub(crate) to_eliminate: BTreeSet<Keyword>,
pub(crate) to_eliminate: BTreeSet<Symbol>,
}
impl InnerJoin {
pub(crate) fn do_eliminate_temp_vars(&mut self, used: &BTreeSet<Keyword>) -> Result<()> {
pub(crate) fn do_eliminate_temp_vars(&mut self, used: &BTreeSet<Symbol>) -> Result<()> {
for binding in self.bindings() {
if !used.contains(&binding) {
self.to_eliminate.insert(binding.clone());
@ -1428,7 +1428,7 @@ impl InnerJoin {
Ok(())
}
pub(crate) fn bindings(&self) -> Vec<Keyword> {
pub(crate) fn bindings(&self) -> Vec<Symbol> {
let mut ret = self.left.bindings_after_eliminate();
ret.extend(self.right.bindings_after_eliminate());
debug_assert_eq!(ret.len(), ret.iter().collect::<BTreeSet<_>>().len());

@ -4,14 +4,14 @@ use std::collections::{BTreeMap, BTreeSet};
use anyhow::{ensure, Result};
use itertools::Itertools;
use crate::data::keyword::{Keyword, PROG_ENTRY};
use crate::data::symb::{Symbol, PROG_ENTRY};
use crate::data::program::{NormalFormAtom, NormalFormProgram, StratifiedNormalFormProgram};
use crate::query::graph::{
generalized_kahn, reachable_components, strongly_connected_components, Graph, StratifiedGraph,
};
impl NormalFormAtom {
fn contained_rules(&self) -> BTreeMap<&Keyword, bool> {
fn contained_rules(&self) -> BTreeMap<&Symbol, bool> {
match self {
NormalFormAtom::AttrTriple(_)
| NormalFormAtom::Predicate(_)
@ -25,12 +25,12 @@ impl NormalFormAtom {
fn convert_normal_form_program_to_graph(
nf_prog: &NormalFormProgram,
) -> StratifiedGraph<&'_ Keyword> {
) -> StratifiedGraph<&'_ Symbol> {
nf_prog
.prog
.iter()
.map(|(k, ruleset)| {
let mut ret: BTreeMap<&Keyword, bool> = BTreeMap::default();
let mut ret: BTreeMap<&Symbol, bool> = BTreeMap::default();
for rule in ruleset {
for atom in &rule.body {
let contained = atom.contained_rules();
@ -52,13 +52,13 @@ fn convert_normal_form_program_to_graph(
.collect()
}
fn reduce_to_graph<'a>(g: &StratifiedGraph<&'a Keyword>) -> Graph<&'a Keyword> {
fn reduce_to_graph<'a>(g: &StratifiedGraph<&'a Symbol>) -> Graph<&'a Symbol> {
g.iter()
.map(|(k, s)| (*k, s.iter().map(|(sk, _)| *sk).collect_vec()))
.collect()
}
fn verify_no_cycle(g: &StratifiedGraph<&'_ Keyword>, sccs: &[BTreeSet<&Keyword>]) -> Result<()> {
fn verify_no_cycle(g: &StratifiedGraph<&'_ Symbol>, sccs: &[BTreeSet<&Symbol>]) -> Result<()> {
for (k, vs) in g {
for scc in sccs {
if scc.contains(k) {
@ -76,9 +76,9 @@ fn verify_no_cycle(g: &StratifiedGraph<&'_ Keyword>, sccs: &[BTreeSet<&Keyword>]
}
fn make_scc_reduced_graph<'a>(
sccs: &[BTreeSet<&'a Keyword>],
graph: &StratifiedGraph<&Keyword>,
) -> (BTreeMap<Keyword, usize>, StratifiedGraph<usize>) {
sccs: &[BTreeSet<&'a Symbol>],
graph: &StratifiedGraph<&Symbol>,
) -> (BTreeMap<Symbol, usize>, StratifiedGraph<usize>) {
let indices = sccs
.iter()
.enumerate()
@ -111,7 +111,7 @@ impl NormalFormProgram {
pub(crate) fn stratify(self) -> Result<StratifiedNormalFormProgram> {
// prerequisite: the program is already in disjunctive normal form
// 0. build a graph of the program
let prog_entry: &Keyword = &PROG_ENTRY;
let prog_entry: &Symbol = &PROG_ENTRY;
let stratified_graph = convert_normal_form_program_to_graph(&self);
let graph = reduce_to_graph(&stratified_graph);
ensure!(
@ -134,7 +134,7 @@ impl NormalFormProgram {
.filter(|(k, _)| reachable.contains(k))
.collect();
// 3. find SCC of the clauses
let sccs: Vec<BTreeSet<&Keyword>> = strongly_connected_components(&graph)
let sccs: Vec<BTreeSet<&Symbol>> = strongly_connected_components(&graph)
.into_iter()
.map(|scc| scc.into_iter().cloned().collect())
.collect_vec();

@ -265,12 +265,12 @@ impl Db {
map_for_entry.insert("_id".to_string(), e_found.0.into());
if attr.cardinality.is_many() {
let arr = map_for_entry
.entry(attr.keyword.to_string())
.entry(attr.name.to_string())
.or_insert_with(|| json!([]));
let arr = arr.as_array_mut().unwrap();
arr.push(value.into());
} else {
map_for_entry.insert(attr.keyword.to_string(), value.into());
map_for_entry.insert(attr.name.to_string(), value.into());
}
current.encoded_entity_amend_validity_to_inf_past();
it.seek(&current);

@ -4,7 +4,7 @@ use log::error;
use cozorocks::{DbIter, RawRocksDb, RocksDbStatus};
use crate::data::program::MagicKeyword;
use crate::data::program::MagicSymbol;
use crate::data::tuple::{EncodedTuple, Tuple};
use crate::data::value::DataValue;
@ -23,7 +23,7 @@ pub(crate) struct TempStore {
pub(crate) id: TempStoreId,
pub(crate) key_size: usize,
pub(crate) val_size: usize,
pub(crate) rule_name: MagicKeyword,
pub(crate) rule_name: MagicSymbol,
}
impl Debug for TempStore {

@ -15,8 +15,8 @@ use crate::data::encode::{
encode_sentinel_attr_by_id, encode_sentinel_entity_attr, encode_tx, EncodedVec,
};
use crate::data::id::{AttrId, EntityId, TxId, Validity};
use crate::data::keyword::Keyword;
use crate::data::program::MagicKeyword;
use crate::data::symb::Symbol;
use crate::data::program::MagicSymbol;
use crate::data::value::DataValue;
use crate::runtime::temp_store::{TempStore, TempStoreId};
@ -29,7 +29,7 @@ pub struct SessionTx {
pub(crate) last_ent_id: Arc<AtomicU64>,
pub(crate) last_tx_id: Arc<AtomicU64>,
pub(crate) attr_by_id_cache: BTreeMap<AttrId, Option<Attribute>>,
pub(crate) attr_by_kw_cache: BTreeMap<Keyword, Option<Attribute>>,
pub(crate) attr_by_kw_cache: BTreeMap<Symbol, Option<Attribute>>,
pub(crate) temp_entity_to_perm: BTreeMap<EntityId, EntityId>,
pub(crate) eid_by_attr_val_cache:
BTreeMap<DataValue, BTreeMap<(AttrId, Validity), Option<EntityId>>>,
@ -71,7 +71,7 @@ impl SessionTx {
&self,
key_size: usize,
val_size: usize,
rule_name: MagicKeyword,
rule_name: MagicSymbol,
) -> TempStore {
let old_count = self.temp_store_id.fetch_add(1, Ordering::AcqRel);
let old_count = old_count & 0x00ff_ffffu32;
@ -92,8 +92,8 @@ impl SessionTx {
id: TempStoreId(old_count),
key_size: 0,
val_size: 0,
rule_name: MagicKeyword::Muggle {
inner: Keyword::from(""),
rule_name: MagicSymbol::Muggle {
inner: Symbol::from(""),
},
}
}

@ -212,7 +212,7 @@ impl SessionTx {
ensure!(
found_eid == eid,
"unique constraint violated for attr {} with value {:?}",
attr.keyword,
attr.name,
v
);
}
@ -222,7 +222,7 @@ impl SessionTx {
ensure!(
found_eid == eid,
"unique constraint violated for attr {} with value {:?}",
attr.keyword,
attr.name,
v
);
}
@ -231,7 +231,7 @@ impl SessionTx {
ensure!(
found_eid == eid,
"unique constraint violated for attr {} with value {:?}",
attr.keyword,
attr.name,
v
);
}

@ -6,10 +6,10 @@ use cozorocks::{DbIter, IterBuilder};
use crate::data::attr::Attribute;
use crate::data::encode::{
encode_attr_by_id, encode_sentinel_attr_by_id, encode_sentinel_attr_by_kw, VEC_SIZE_8,
encode_attr_by_id, encode_sentinel_attr_by_id, encode_sentinel_attr_by_name, VEC_SIZE_8,
};
use crate::data::id::AttrId;
use crate::data::keyword::Keyword;
use crate::data::symb::Symbol;
use crate::data::triple::StoreOp;
use crate::parse::schema::AttrTxItem;
use crate::runtime::transact::SessionTx;
@ -20,12 +20,12 @@ impl SessionTx {
let mut ret = Vec::with_capacity(payloads.len());
for item in payloads {
let id = item.attr.id;
let kw = item.attr.keyword.clone();
let kw = item.attr.name.clone();
if item.op.is_retract() {
if item.attr.id.is_perm() {
ret.push((item.op, self.retract_attr(item.attr.id)?));
} else {
ret.push((item.op, self.retract_attr_by_kw(&item.attr.keyword)?));
ret.push((item.op, self.retract_attr_by_kw(&item.attr.name)?));
}
} else if item.attr.id.is_perm() {
ret.push((item.op, self.amend_attr(item.attr)?));
@ -55,27 +55,27 @@ impl SessionTx {
let attr = Attribute::decode(&data[VEC_SIZE_8..])?;
if op.is_retract() {
self.attr_by_id_cache.insert(attr.id, None);
self.attr_by_kw_cache.insert(attr.keyword, None);
self.attr_by_kw_cache.insert(attr.name, None);
None
} else {
self.attr_by_id_cache.insert(attr.id, Some(attr.clone()));
self.attr_by_kw_cache
.insert(attr.keyword.clone(), Some(attr.clone()));
.insert(attr.name.clone(), Some(attr.clone()));
Some(attr)
}
}
})
}
pub(crate) fn attr_by_kw(&mut self, kw: &Keyword) -> Result<Option<Attribute>> {
if let Some(res) = self.attr_by_kw_cache.get(kw) {
pub(crate) fn attr_by_name(&mut self, name: &Symbol) -> Result<Option<Attribute>> {
if let Some(res) = self.attr_by_kw_cache.get(name) {
return Ok(res.clone());
}
let anchor = encode_sentinel_attr_by_kw(kw);
let anchor = encode_sentinel_attr_by_name(name);
Ok(match self.tx.get(&anchor, false)? {
None => {
self.attr_by_kw_cache.insert(kw.clone(), None);
self.attr_by_kw_cache.insert(name.clone(), None);
None
}
Some(v_slice) => {
@ -85,12 +85,12 @@ impl SessionTx {
let attr = Attribute::decode(&data[VEC_SIZE_8..])?;
if op.is_retract() {
self.attr_by_id_cache.insert(attr.id, None);
self.attr_by_kw_cache.insert(kw.clone(), None);
self.attr_by_kw_cache.insert(name.clone(), None);
None
} else {
self.attr_by_id_cache.insert(attr.id, Some(attr.clone()));
self.attr_by_kw_cache
.insert(attr.keyword.clone(), Some(attr.clone()));
.insert(attr.name.clone(), Some(attr.clone()));
Some(attr)
}
}
@ -110,9 +110,9 @@ impl SessionTx {
);
ensure!(
self.attr_by_kw(&attr.keyword)?.is_none(),
self.attr_by_name(&attr.name)?.is_none(),
"new attribute conflicts with existing one for alias {}",
attr.keyword
attr.name
);
attr.id = AttrId(self.last_attr_id.fetch_add(1, Ordering::AcqRel) + 1);
@ -127,11 +127,11 @@ impl SessionTx {
.attr_by_id(attr.id)?
.ok_or_else(|| anyhow!("expected attribute id {:?} not found", attr.id))?;
let tx_id = self.get_write_tx_id()?;
if existing.keyword != attr.keyword {
if existing.name != attr.name {
ensure!(
self.attr_by_kw(&attr.keyword)?.is_none(),
self.attr_by_name(&attr.name)?.is_none(),
"attribute alias {} conflict with existing one",
attr.keyword
attr.name
);
ensure!(
existing.val_type == attr.val_type
@ -141,7 +141,7 @@ impl SessionTx {
"changing immutable property for {:?}",
attr
);
let kw_sentinel = encode_sentinel_attr_by_kw(&existing.keyword);
let kw_sentinel = encode_sentinel_attr_by_name(&existing.name);
let attr_data = existing.encode_with_op_and_tx(StoreOp::Retract, tx_id);
self.tx.put(&kw_sentinel, &attr_data)?;
}
@ -155,7 +155,7 @@ impl SessionTx {
self.tx.put(&id_encoded, &attr_data)?;
let id_sentinel = encode_sentinel_attr_by_id(attr.id);
self.tx.put(&id_sentinel, &attr_data)?;
let kw_sentinel = encode_sentinel_attr_by_kw(&attr.keyword);
let kw_sentinel = encode_sentinel_attr_by_name(&attr.name);
self.tx.put(&kw_sentinel, &attr_data)?;
Ok(attr.id)
}
@ -171,9 +171,9 @@ impl SessionTx {
}
}
pub(crate) fn retract_attr_by_kw(&mut self, kw: &Keyword) -> Result<AttrId> {
pub(crate) fn retract_attr_by_kw(&mut self, kw: &Symbol) -> Result<AttrId> {
let attr = self
.attr_by_kw(kw)?
.attr_by_name(kw)?
.ok_or_else(|| anyhow!("attribute not found: {}", kw))?;
self.retract_attr(attr.id)
}

@ -37,13 +37,13 @@ fn creation() {
assert!(db.current_schema().unwrap().as_array().unwrap().is_empty());
let res = db.transact_attributes(&json!({
"attrs": [
{"put": {"keyword": "person.idd", "cardinality": "one", "type": "string", "index": "identity", "history": false}},
{"put": {"keyword": "person.first_name", "cardinality": "one", "type": "string", "index": true}},
{"put": {"keyword": "person.last_name", "cardinality": "one", "type": "string", "index": true}},
{"put": {"keyword": "person.age", "cardinality": "one", "type": "int"}},
{"put": {"keyword": "person.friend", "cardinality": "many", "type": "ref"}},
{"put": {"keyword": "person.weight", "cardinality": "one", "type": "float"}},
{"put": {"keyword": "person.covid", "cardinality": "one", "type": "bool"}},
{"put": {"name": "person.idd", "cardinality": "one", "type": "string", "index": "identity", "history": false}},
{"put": {"name": "person.first_name", "cardinality": "one", "type": "string", "index": true}},
{"put": {"name": "person.last_name", "cardinality": "one", "type": "string", "index": true}},
{"put": {"name": "person.age", "cardinality": "one", "type": "int"}},
{"put": {"name": "person.friend", "cardinality": "many", "type": "ref"}},
{"put": {"name": "person.weight", "cardinality": "one", "type": "float"}},
{"put": {"name": "person.covid", "cardinality": "one", "type": "bool"}},
]
}))
.unwrap();
@ -52,8 +52,8 @@ fn creation() {
let last_id = res["results"][6][0].as_u64().unwrap();
db.transact_attributes(&json!({
"attrs": [
{"put": {"id": first_id, "keyword": "person.id", "cardinality": "one", "type": "string", "index": "identity", "history": false}},
{"retract": {"id": last_id, "keyword": "person.covid", "cardinality": "one", "type": "bool"}}
{"put": {"id": first_id, "name": "person.id", "cardinality": "one", "type": "string", "index": "identity", "history": false}},
{"retract": {"id": last_id, "name": "person.covid", "cardinality": "one", "type": "bool"}}
]
})).unwrap();
assert_eq!(db.current_schema().unwrap().as_array().unwrap().len(), 6);

Loading…
Cancel
Save