From 1e12ce0c6ce4d3098e50ca4e6137c81715c4cd66 Mon Sep 17 00:00:00 2001 From: Ziyang Hu Date: Thu, 14 Jul 2022 17:07:33 +0800 Subject: [PATCH] rename for clearer intention --- src/data/compare.rs | 14 ++++----- src/data/encode.rs | 65 +++++++++++++++++++++++------------------ src/data/tx_triple.rs | 13 +++++++-- src/runtime/transact.rs | 10 +++---- src/transact/attr.rs | 22 +++++++------- src/transact/triple.rs | 12 ++++---- 6 files changed, 76 insertions(+), 60 deletions(-) diff --git a/src/data/compare.rs b/src/data/compare.rs index b9a8991d..d9f69637 100644 --- a/src/data/compare.rs +++ b/src/data/compare.rs @@ -1,5 +1,5 @@ use crate::data::encode::{ - decode_ae_key, decode_attr_key_by_id, decode_ea_key, decode_unique_attr_val, decode_vae_key, + decode_ae_key, decode_attr_key_by_id, decode_ea_key, decode_sentinel_attr_val, decode_vae_key, decode_value_from_key, StorageTag, }; use std::cmp::Ordering; @@ -43,10 +43,10 @@ pub(crate) fn compare_key(a: &[u8], b: &[u8]) -> Ordering { TripleValueAttrEntity => compare_key_triple_vae(a, b), AttrById => compare_key_attr_by_id(a, b), Tx => compare_key_tx(a, b), - UniqueEntityAttr => compare_key_unique_entity_attr(a, b), - UniqueAttrValue => compare_key_unique_attr_val(a, b), - UniqueAttrById => compare_key_unique_attr_by_id(a, b), - UniqueAttrByKeyword => compare_key_unique_attr_by_kw(a, b), + 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), } } @@ -129,8 +129,8 @@ fn compare_key_unique_entity_attr(a: &[u8], b: &[u8]) -> Ordering { #[inline] fn compare_key_unique_attr_val(a: &[u8], b: &[u8]) -> Ordering { - let (a_a, a_v) = decode_unique_attr_val(a).unwrap(); - let (b_a, b_v) = decode_unique_attr_val(b).unwrap(); + let (a_a, a_v) = decode_sentinel_attr_val(a).unwrap(); + let (b_a, b_v) = decode_sentinel_attr_val(b).unwrap(); return_if_resolved!(a_a.cmp(&b_a)); a_v.cmp(&b_v) } diff --git a/src/data/encode.rs b/src/data/encode.rs index ecaa325d..4dee391e 100644 --- a/src/data/encode.rs +++ b/src/data/encode.rs @@ -20,10 +20,10 @@ pub(crate) enum StorageTag { TripleValueAttrEntity = 4, AttrById = 5, Tx = 6, - UniqueEntityAttr = 7, - UniqueAttrValue = 8, - UniqueAttrById = 9, - UniqueAttrByKeyword = 10, + SentinelEntityAttr = 7, + SentinelAttrValue = 8, + SentinelAttrById = 9, + SentinelAttrByKeyword = 10, } #[derive(Debug, thiserror::Error)] @@ -65,7 +65,9 @@ impl EncodedVec { format!("{:?}{}", tx, op) } } - StorageTag::AttrById | StorageTag::UniqueAttrById | StorageTag::UniqueAttrByKeyword => { + StorageTag::AttrById + | StorageTag::SentinelAttrById + | StorageTag::SentinelAttrByKeyword => { let op = StoreOp::try_from(data[0]).unwrap(); if data.len() <= 1 { op.to_string() @@ -78,7 +80,7 @@ impl EncodedVec { } } StorageTag::Tx => format!("{:?}", TxLog::decode(data).unwrap()), - StorageTag::UniqueEntityAttr | StorageTag::UniqueAttrValue => { + StorageTag::SentinelEntityAttr | StorageTag::SentinelAttrValue => { format!("{:?}", TxId::from_bytes(data)) } } @@ -125,18 +127,23 @@ impl Debug for EncodedVec { StorageTag::Tx => { write!(f, " {:?}", TxId::from_bytes(self)) } - StorageTag::UniqueEntityAttr => { - write!(f, " {:?}", EntityId::from_bytes(self)) + StorageTag::SentinelEntityAttr => { + write!( + f, + " <{:?}: {:?}>", + EntityId::from_bytes(self), + AttrId::from_bytes(&self[VEC_SIZE_8..]) + ) } - StorageTag::UniqueAttrValue => { - let (a, v) = decode_unique_attr_val(self).unwrap(); + StorageTag::SentinelAttrValue => { + let (a, v) = decode_sentinel_attr_val(self).unwrap(); write!(f, " <{:?}: {:?}>", a, v) } - StorageTag::UniqueAttrById => { + StorageTag::SentinelAttrById => { write!(f, " {:?}", AttrId::from_bytes(self)) } - StorageTag::UniqueAttrByKeyword => { - let kw = decode_unique_attr_by_kw(self).unwrap(); + StorageTag::SentinelAttrByKeyword => { + let kw = decode_sentinel_attr_by_kw(self).unwrap(); write!(f, " {:?}", kw) } } @@ -192,10 +199,10 @@ impl TryFrom for StorageTag { 4 => TripleValueAttrEntity, 5 => AttrById, 6 => Tx, - 7 => UniqueEntityAttr, - 8 => UniqueAttrValue, - 9 => UniqueAttrById, - 10 => UniqueAttrByKeyword, + 7 => SentinelEntityAttr, + 8 => SentinelAttrValue, + 9 => SentinelAttrById, + 10 => SentinelAttrByKeyword, n => return Err(StorageTagError::UnexpectedValue(n)), }) } @@ -390,54 +397,54 @@ pub(crate) fn encode_tx(tx: TxId) -> EncodedVec { } #[inline] -pub(crate) fn encode_unique_entity_attr(eid: EntityId, aid: AttrId) -> EncodedVec { +pub(crate) fn encode_sentinel_entity_attr(eid: EntityId, aid: AttrId) -> EncodedVec { let mut ret = SmallVec::<[u8; VEC_SIZE_16]>::new(); ret.extend(eid.bytes()); - ret[0] = StorageTag::UniqueEntityAttr as u8; + ret[0] = StorageTag::SentinelEntityAttr as u8; ret.extend(aid.bytes()); ret.into() } #[inline] -pub(crate) fn decode_unique_entity_attr(src: &[u8]) -> Result<(EntityId, AttrId)> { +pub(crate) fn decode_sentinel_entity_attr(src: &[u8]) -> Result<(EntityId, AttrId)> { let eid = EntityId::from_bytes(&src[..VEC_SIZE_8]); let aid = AttrId::from_bytes(&src[VEC_SIZE_8..VEC_SIZE_16]); Ok((eid, aid)) } #[inline] -pub(crate) fn encode_unique_attr_val(aid: AttrId, val: &Value) -> EncodedVec { +pub(crate) fn encode_sentinel_attr_val(aid: AttrId, val: &Value) -> EncodedVec { let mut ret = SmallVec::<[u8; LARGE_VEC_SIZE]>::new(); ret.extend(aid.bytes()); - ret[0] = StorageTag::UniqueAttrValue as u8; + ret[0] = StorageTag::SentinelAttrValue as u8; val.serialize(&mut Serializer::new(&mut ret)).unwrap(); ret.into() } #[inline] -pub(crate) fn decode_unique_attr_val(src: &[u8]) -> Result<(AttrId, Value)> { +pub(crate) fn decode_sentinel_attr_val(src: &[u8]) -> Result<(AttrId, Value)> { let a_id = AttrId::from_bytes(&src[..VEC_SIZE_8]); let val = rmp_serde::from_slice(&src[VEC_SIZE_8..])?; Ok((a_id, val)) } #[inline] -pub(crate) fn encode_unique_attr_by_id(aid: AttrId) -> EncodedVec { +pub(crate) fn encode_sentinel_attr_by_id(aid: AttrId) -> EncodedVec { let mut ret = SmallVec::<[u8; VEC_SIZE_8]>::new(); ret.extend(aid.bytes()); - ret[0] = StorageTag::UniqueAttrById as u8; + ret[0] = StorageTag::SentinelAttrById as u8; debug_assert_eq!(ret.len(), VEC_SIZE_8); ret.into() } -pub(crate) fn decode_unique_attr_by_id(src: &[u8]) -> Result { +pub(crate) fn decode_sentinel_attr_by_id(src: &[u8]) -> Result { Ok(AttrId::from_bytes(src)) } #[inline] -pub(crate) fn encode_unique_attr_by_kw(kw: &Keyword) -> EncodedVec { +pub(crate) fn encode_sentinel_attr_by_kw(kw: &Keyword) -> EncodedVec { let mut ret = SmallVec::<[u8; LARGE_VEC_SIZE]>::new(); - ret.push(StorageTag::UniqueAttrByKeyword as u8); + ret.push(StorageTag::SentinelAttrByKeyword as u8); ret.extend_from_slice(kw.ns.as_bytes()); ret.push(b'/'); ret.extend_from_slice(kw.ident.as_bytes()); @@ -445,6 +452,6 @@ pub(crate) fn encode_unique_attr_by_kw(kw: &Keyword) -> EncodedVec Result { +pub(crate) fn decode_sentinel_attr_by_kw(src: &[u8]) -> Result { Ok(Keyword::try_from(&src[1..])?) } diff --git a/src/data/tx_triple.rs b/src/data/tx_triple.rs index 2fb342cf..84ebfb53 100644 --- a/src/data/tx_triple.rs +++ b/src/data/tx_triple.rs @@ -364,7 +364,7 @@ impl SessionTx { return Ok(()); } - let id = if attr.indexing == AttributeIndex::Identity { + let id = if attr.indexing.is_unique_index() { let value = if let serde_json::Value::Object(inner) = val { self.parse_tx_component(&attr, inner, action, since, temp_id_ctx, collected)? } else { @@ -399,7 +399,7 @@ impl SessionTx { .into()); } id - } else if let Some(_) = eid.as_str() { + } else if eid.is_string() { return Err(TxError::EntityId( existing_id.0, "specifying temp_id string together with unique constraint".into(), @@ -444,6 +444,7 @@ impl SessionTx { let mut pairs = Vec::with_capacity(item.len()); let mut eid = None; let mut has_unique_attr = false; + let mut has_identity_attr = false; for (k, v) in item { if k != PERM_ID_FIELD && k != TEMP_ID_FIELD { let kw = (k as &str).try_into()?; @@ -451,6 +452,7 @@ impl SessionTx { .attr_by_kw(&kw)? .ok_or_else(|| TxError::AttrNotFound(kw.clone()))?; has_unique_attr = has_unique_attr || attr.indexing.is_unique_index(); + has_identity_attr = has_identity_attr || attr.indexing == AttributeIndex::Identity; if attr.indexing == AttributeIndex::Identity { let value = if let serde_json::Value::Object(inner) = v { self.parse_tx_component( @@ -534,6 +536,13 @@ impl SessionTx { return Err(TxError::InvalidAction(action, "temp id not allowed".to_string()).into()); } if !is_sub_component { + if action == TxAction::Put && eid.is_perm() && !has_identity_attr { + return Err(TxError::InvalidAction( + action, + "upsert requires identity attribute present".to_string(), + ) + .into()); + } for (attr, v) in pairs { self.parse_tx_request_inner(eid, &attr, v, action, since, temp_id_ctx, collected)?; } diff --git a/src/runtime/transact.rs b/src/runtime/transact.rs index cb27d910..5dbb4ca3 100644 --- a/src/runtime/transact.rs +++ b/src/runtime/transact.rs @@ -1,6 +1,6 @@ use crate::data::attr::Attribute; use crate::data::encode::{ - encode_tx, encode_unique_attr_by_id, encode_unique_entity_attr, EncodedVec, + encode_tx, encode_sentinel_attr_by_id, encode_sentinel_entity_attr, EncodedVec, }; use crate::data::id::{AttrId, EntityId, TxId, Validity}; use crate::data::keyword::Keyword; @@ -69,8 +69,8 @@ impl SessionTx { } pub(crate) fn load_last_entity_id(&mut self) -> Result { - let e_lower = encode_unique_entity_attr(EntityId::MIN_PERM, AttrId::MIN_PERM); - let e_upper = encode_unique_entity_attr(EntityId::MAX_PERM, AttrId::MIN_PERM); + let e_lower = encode_sentinel_entity_attr(EntityId::MIN_PERM, AttrId::MIN_PERM); + let e_upper = encode_sentinel_entity_attr(EntityId::MAX_PERM, AttrId::MIN_PERM); let it = self.bounded_scan_last(&e_lower, &e_upper); Ok(match it.key()? { @@ -80,8 +80,8 @@ impl SessionTx { } pub(crate) fn load_last_attr_id(&mut self) -> Result { - let e_lower = encode_unique_attr_by_id(AttrId::MIN_PERM); - let e_upper = encode_unique_attr_by_id(AttrId::MAX_PERM); + let e_lower = encode_sentinel_attr_by_id(AttrId::MIN_PERM); + let e_upper = encode_sentinel_attr_by_id(AttrId::MAX_PERM); let it = self.bounded_scan_last(&e_lower, &e_upper); Ok(match it.key()? { None => AttrId::MAX_TEMP, diff --git a/src/transact/attr.rs b/src/transact/attr.rs index 73997122..7e52ac8d 100644 --- a/src/transact/attr.rs +++ b/src/transact/attr.rs @@ -1,6 +1,6 @@ use crate::data::attr::Attribute; use crate::data::encode::{ - encode_attr_by_id, encode_unique_attr_by_id, encode_unique_attr_by_kw, VEC_SIZE_8, + encode_attr_by_id, encode_sentinel_attr_by_id, encode_sentinel_attr_by_kw, VEC_SIZE_8, }; use crate::data::id::AttrId; use crate::data::keyword::Keyword; @@ -40,7 +40,7 @@ impl SessionTx { return Ok(res.clone()); } - let anchor = encode_unique_attr_by_id(aid); + let anchor = encode_sentinel_attr_by_id(aid); Ok(match self.tx.get(&anchor, false)? { None => { self.attr_by_id_cache.insert(aid, None); @@ -69,7 +69,7 @@ impl SessionTx { return Ok(res.clone()); } - let anchor = encode_unique_attr_by_kw(kw); + let anchor = encode_sentinel_attr_by_kw(kw); Ok(match self.tx.get(&anchor, false)? { None => { self.attr_by_kw_cache.insert(kw.clone(), None); @@ -145,9 +145,9 @@ impl SessionTx { { return Err(TransactError::ChangingImmutableProperty(attr.id).into()); } - let kw_signal = encode_unique_attr_by_kw(&existing.keyword); + let kw_sentinel = encode_sentinel_attr_by_kw(&existing.keyword); let attr_data = existing.encode_with_op_and_tx(StoreOp::Retract, tx_id); - self.tx.put(&kw_signal, &attr_data)?; + self.tx.put(&kw_sentinel, &attr_data)?; } self.put_attr(&attr, StoreOp::Assert) } @@ -157,10 +157,10 @@ impl SessionTx { let attr_data = attr.encode_with_op_and_tx(op, tx_id); let id_encoded = encode_attr_by_id(attr.id, tx_id); self.tx.put(&id_encoded, &attr_data)?; - let id_signal = encode_unique_attr_by_id(attr.id); - self.tx.put(&id_signal, &attr_data)?; - let kw_signal = encode_unique_attr_by_kw(&attr.keyword); - self.tx.put(&kw_signal, &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); + self.tx.put(&kw_sentinel, &attr_data)?; Ok(attr.id) } @@ -194,14 +194,14 @@ struct AttrIter { impl AttrIter { fn new(builder: IterBuilder) -> Self { - let upper_bound = encode_unique_attr_by_id(AttrId::MAX_PERM); + let upper_bound = encode_sentinel_attr_by_id(AttrId::MAX_PERM); let it = builder.upper_bound(&upper_bound).start(); Self { it, started: false } } fn next_inner(&mut self) -> Result> { if !self.started { - let lower_bound = encode_unique_attr_by_id(AttrId::MIN_PERM); + let lower_bound = encode_sentinel_attr_by_id(AttrId::MIN_PERM); self.it.seek(&lower_bound); self.started = true; } else { diff --git a/src/transact/triple.rs b/src/transact/triple.rs index 9b64f4fc..68ab3642 100644 --- a/src/transact/triple.rs +++ b/src/transact/triple.rs @@ -3,8 +3,8 @@ use crate::data::compare::compare_key; use crate::data::encode::{ decode_ae_key, decode_ea_key, decode_vae_key, decode_value, decode_value_from_key, decode_value_from_val, encode_aev_key, encode_ave_key, encode_ave_key_for_unique_v, - encode_eav_key, encode_unique_attr_val, encode_unique_entity_attr, encode_vae_key, EncodedVec, - LARGE_VEC_SIZE, + encode_eav_key, encode_sentinel_attr_val, encode_sentinel_entity_attr, encode_vae_key, + EncodedVec, LARGE_VEC_SIZE, }; use crate::data::id::{AttrId, EntityId, Validity}; use crate::data::keyword::Keyword; @@ -105,9 +105,9 @@ impl SessionTx { vld: Validity, ) -> Result<()> { let aid = attr.id; - let signal = encode_unique_entity_attr(eid, aid); + let sentinel = encode_sentinel_entity_attr(eid, aid); let gen_err = || TransactError::RequiredTripleNotFound(eid, aid); - self.tx.get(&signal, true)?.ok_or_else(gen_err)?; + self.tx.get(&sentinel, true)?.ok_or_else(gen_err)?; let v_in_key = if attr.cardinality.is_one() { &Value::Bottom } else { @@ -227,13 +227,13 @@ impl SessionTx { self.tx.put(&ave_encoded, &e_in_val_encoded)?; self.tx.put( - &encode_unique_attr_val(attr.id, v), + &encode_sentinel_attr_val(attr.id, v), &tx_id.bytes_with_op(op), )?; } self.tx.put( - &encode_unique_entity_attr(eid, attr.id), + &encode_sentinel_entity_attr(eid, attr.id), &tx_id.bytes_with_op(op), )?;