Post: Indent.
This commit is contained in:
parent
d88823e7c4
commit
eb220528bf
1 changed files with 102 additions and 102 deletions
204
db/src/tx.rs
204
db/src/tx.rs
|
@ -297,7 +297,7 @@ impl<'conn, 'a> Tx<'conn, 'a> {
|
||||||
// Here is where we do schema-aware typechecking: we either assert that
|
// Here is where we do schema-aware typechecking: we either assert that
|
||||||
// the given value is in the attribute's value set, or (in limited
|
// the given value is in the attribute's value set, or (in limited
|
||||||
// cases) coerce the value into the attribute's value set.
|
// cases) coerce the value into the attribute's value set.
|
||||||
if let TypedValue::Ref(entid) = self.schema.to_typed_value(&v.clone().without_spans(), &reversed_attribute)? {
|
if let TypedValue::Ref(entid) = self.schema.to_typed_value(&v.clone().without_spans(), reversed_attribute.value_type)? {
|
||||||
Ok(Either::Left(entid))
|
Ok(Either::Left(entid))
|
||||||
} else {
|
} else {
|
||||||
// reversed_attribute is :db.type/ref, so this shouldn't happen.
|
// reversed_attribute is :db.type/ref, so this shouldn't happen.
|
||||||
|
@ -356,115 +356,115 @@ impl<'conn, 'a> Tx<'conn, 'a> {
|
||||||
} else {
|
} else {
|
||||||
let (a, attribute) = in_process.entity_a_into_term_a(a)?;
|
let (a, attribute) = in_process.entity_a_into_term_a(a)?;
|
||||||
|
|
||||||
let v = match v {
|
let v = match v {
|
||||||
entmod::AtomOrLookupRefOrVectorOrMapNotation::Atom(v) => {
|
entmod::AtomOrLookupRefOrVectorOrMapNotation::Atom(v) => {
|
||||||
if attribute.value_type == ValueType::Ref && v.inner.is_text() {
|
if attribute.value_type == ValueType::Ref && v.inner.is_text() {
|
||||||
Either::Right(LookupRefOrTempId::TempId(in_process.intern_temp_id(v.inner.as_text().cloned().map(TempId::External).unwrap())))
|
Either::Right(LookupRefOrTempId::TempId(in_process.intern_temp_id(v.inner.as_text().cloned().map(TempId::External).unwrap())))
|
||||||
} else {
|
|
||||||
// Here is where we do schema-aware typechecking: we either assert that
|
|
||||||
// the given value is in the attribute's value set, or (in limited
|
|
||||||
// cases) coerce the value into the attribute's value set.
|
|
||||||
let typed_value: TypedValue = self.schema.to_typed_value(&v.without_spans(), attribute.value_type)?;
|
|
||||||
Either::Left(typed_value)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
entmod::AtomOrLookupRefOrVectorOrMapNotation::LookupRef(ref lookup_ref) => {
|
|
||||||
if attribute.value_type != ValueType::Ref {
|
|
||||||
bail!(ErrorKind::NotYetImplemented(format!("Cannot resolve value lookup ref for attribute {} that is not :db/valueType :db.type/ref", a)))
|
|
||||||
}
|
|
||||||
|
|
||||||
Either::Right(LookupRefOrTempId::LookupRef(in_process.intern_lookup_ref(lookup_ref)?))
|
|
||||||
},
|
|
||||||
|
|
||||||
entmod::AtomOrLookupRefOrVectorOrMapNotation::Vector(vs) => {
|
|
||||||
if !attribute.multival {
|
|
||||||
bail!(ErrorKind::NotYetImplemented(format!("Cannot explode vector value for attribute {} that is not :db.cardinality :db.cardinality/many", a)));
|
|
||||||
}
|
|
||||||
|
|
||||||
for vv in vs {
|
|
||||||
deque.push_front(Entity::AddOrRetract {
|
|
||||||
op: op.clone(),
|
|
||||||
e: e.clone(),
|
|
||||||
a: entmod::Entid::Entid(a),
|
|
||||||
v: vv,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
},
|
|
||||||
|
|
||||||
entmod::AtomOrLookupRefOrVectorOrMapNotation::MapNotation(mut map_notation) => {
|
|
||||||
// TODO: consider handling this at the tx-parser level. That would be
|
|
||||||
// more strict and expressive, but it would lead to splitting
|
|
||||||
// AddOrRetract, which proliferates types and code, or only handling
|
|
||||||
// nested maps rather than map values, like Datomic does.
|
|
||||||
if op != OpType::Add {
|
|
||||||
bail!(ErrorKind::NotYetImplemented(format!("Cannot explode nested map value in :db/retract for attribute {}", a)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if attribute.value_type != ValueType::Ref {
|
|
||||||
bail!(ErrorKind::NotYetImplemented(format!("Cannot explode nested map value for attribute {} that is not :db/valueType :db.type/ref", a)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// :db/id is optional; if it's not given, we generate a special internal tempid
|
|
||||||
// to use for upserting. This tempid will not be reported in the TxReport.
|
|
||||||
let db_id: Option<entmod::EntidOrLookupRefOrTempId> = mentat_tx_parser::remove_db_id(&mut map_notation)?;
|
|
||||||
let mut dangling = db_id.is_none();
|
|
||||||
let db_id: entmod::EntidOrLookupRefOrTempId = db_id.unwrap_or_else(|| in_process.allocate_mentat_id());
|
|
||||||
|
|
||||||
// We're nested, so we want to ensure we're not creating "dangling"
|
|
||||||
// entities that can't be reached. If we're :db/isComponent, then this
|
|
||||||
// is not dangling. Otherwise, the resulting map needs to have a
|
|
||||||
// :db/unique :db.unique/identity [a v] pair, so that it's reachable.
|
|
||||||
// Per http://docs.datomic.com/transactions.html: "Either the reference
|
|
||||||
// to the nested map must be a component attribute, or the nested map
|
|
||||||
// must include a unique attribute. This constraint prevents the
|
|
||||||
// accidental creation of easily-orphaned entities that have no identity
|
|
||||||
// or relation to other entities."
|
|
||||||
if attribute.component {
|
|
||||||
dangling = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (inner_a, inner_v) in map_notation {
|
|
||||||
if inner_a.is_backward() {
|
|
||||||
// We definitely have a reference. The reference might be
|
|
||||||
// dangling (a bare entid, for example), but we don't yet
|
|
||||||
// support nested maps and reverse notation simultaneously
|
|
||||||
// (i.e., we don't accept {:reverse/_attribute {:nested map}})
|
|
||||||
// so we don't need to check that the nested map reference isn't
|
|
||||||
// danglign.
|
|
||||||
dangling = false;
|
|
||||||
|
|
||||||
let reversed_e = in_process.entity_v_into_term_e(inner_v, &inner_a)?;
|
|
||||||
let (reversed_a, _reversed_attribute) = in_process.entity_a_into_term_a(inner_a.to_reversed().unwrap())?;
|
|
||||||
let reversed_v = in_process.entity_e_into_term_v(db_id.clone())?;
|
|
||||||
terms.push(Term::AddOrRetract(OpType::Add, reversed_e, reversed_a, reversed_v));
|
|
||||||
} else {
|
} else {
|
||||||
let (inner_a, inner_attribute) = in_process.entity_a_into_term_a(inner_a)?;
|
// Here is where we do schema-aware typechecking: we either assert that
|
||||||
if inner_attribute.unique == Some(attribute::Unique::Identity) {
|
// the given value is in the attribute's value set, or (in limited
|
||||||
dangling = false;
|
// cases) coerce the value into the attribute's value set.
|
||||||
}
|
let typed_value: TypedValue = self.schema.to_typed_value(&v.without_spans(), attribute.value_type)?;
|
||||||
|
Either::Left(typed_value)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
entmod::AtomOrLookupRefOrVectorOrMapNotation::LookupRef(ref lookup_ref) => {
|
||||||
|
if attribute.value_type != ValueType::Ref {
|
||||||
|
bail!(ErrorKind::NotYetImplemented(format!("Cannot resolve value lookup ref for attribute {} that is not :db/valueType :db.type/ref", a)))
|
||||||
|
}
|
||||||
|
|
||||||
|
Either::Right(LookupRefOrTempId::LookupRef(in_process.intern_lookup_ref(lookup_ref)?))
|
||||||
|
},
|
||||||
|
|
||||||
|
entmod::AtomOrLookupRefOrVectorOrMapNotation::Vector(vs) => {
|
||||||
|
if !attribute.multival {
|
||||||
|
bail!(ErrorKind::NotYetImplemented(format!("Cannot explode vector value for attribute {} that is not :db.cardinality :db.cardinality/many", a)));
|
||||||
|
}
|
||||||
|
|
||||||
|
for vv in vs {
|
||||||
deque.push_front(Entity::AddOrRetract {
|
deque.push_front(Entity::AddOrRetract {
|
||||||
op: OpType::Add,
|
op: op.clone(),
|
||||||
e: db_id.clone(),
|
e: e.clone(),
|
||||||
a: entmod::Entid::Entid(inner_a),
|
a: entmod::Entid::Entid(a),
|
||||||
v: inner_v,
|
v: vv,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
continue
|
||||||
|
},
|
||||||
|
|
||||||
if dangling {
|
entmod::AtomOrLookupRefOrVectorOrMapNotation::MapNotation(mut map_notation) => {
|
||||||
bail!(ErrorKind::NotYetImplemented(format!("Cannot explode nested map value that would lead to dangling entity for attribute {}", a)));
|
// TODO: consider handling this at the tx-parser level. That would be
|
||||||
}
|
// more strict and expressive, but it would lead to splitting
|
||||||
|
// AddOrRetract, which proliferates types and code, or only handling
|
||||||
|
// nested maps rather than map values, like Datomic does.
|
||||||
|
if op != OpType::Add {
|
||||||
|
bail!(ErrorKind::NotYetImplemented(format!("Cannot explode nested map value in :db/retract for attribute {}", a)));
|
||||||
|
}
|
||||||
|
|
||||||
in_process.entity_e_into_term_v(db_id)?
|
if attribute.value_type != ValueType::Ref {
|
||||||
},
|
bail!(ErrorKind::NotYetImplemented(format!("Cannot explode nested map value for attribute {} that is not :db/valueType :db.type/ref", a)))
|
||||||
};
|
}
|
||||||
|
|
||||||
let e = in_process.entity_e_into_term_e(e)?;
|
// :db/id is optional; if it's not given, we generate a special internal tempid
|
||||||
terms.push(Term::AddOrRetract(op, e, a, v));
|
// to use for upserting. This tempid will not be reported in the TxReport.
|
||||||
}
|
let db_id: Option<entmod::EntidOrLookupRefOrTempId> = mentat_tx_parser::remove_db_id(&mut map_notation)?;
|
||||||
|
let mut dangling = db_id.is_none();
|
||||||
|
let db_id: entmod::EntidOrLookupRefOrTempId = db_id.unwrap_or_else(|| in_process.allocate_mentat_id());
|
||||||
|
|
||||||
|
// We're nested, so we want to ensure we're not creating "dangling"
|
||||||
|
// entities that can't be reached. If we're :db/isComponent, then this
|
||||||
|
// is not dangling. Otherwise, the resulting map needs to have a
|
||||||
|
// :db/unique :db.unique/identity [a v] pair, so that it's reachable.
|
||||||
|
// Per http://docs.datomic.com/transactions.html: "Either the reference
|
||||||
|
// to the nested map must be a component attribute, or the nested map
|
||||||
|
// must include a unique attribute. This constraint prevents the
|
||||||
|
// accidental creation of easily-orphaned entities that have no identity
|
||||||
|
// or relation to other entities."
|
||||||
|
if attribute.component {
|
||||||
|
dangling = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (inner_a, inner_v) in map_notation {
|
||||||
|
if inner_a.is_backward() {
|
||||||
|
// We definitely have a reference. The reference might be
|
||||||
|
// dangling (a bare entid, for example), but we don't yet
|
||||||
|
// support nested maps and reverse notation simultaneously
|
||||||
|
// (i.e., we don't accept {:reverse/_attribute {:nested map}})
|
||||||
|
// so we don't need to check that the nested map reference isn't
|
||||||
|
// danglign.
|
||||||
|
dangling = false;
|
||||||
|
|
||||||
|
let reversed_e = in_process.entity_v_into_term_e(inner_v, &inner_a)?;
|
||||||
|
let (reversed_a, _reversed_attribute) = in_process.entity_a_into_term_a(inner_a.to_reversed().unwrap())?;
|
||||||
|
let reversed_v = in_process.entity_e_into_term_v(db_id.clone())?;
|
||||||
|
terms.push(Term::AddOrRetract(OpType::Add, reversed_e, reversed_a, reversed_v));
|
||||||
|
} else {
|
||||||
|
let (inner_a, inner_attribute) = in_process.entity_a_into_term_a(inner_a)?;
|
||||||
|
if inner_attribute.unique == Some(attribute::Unique::Identity) {
|
||||||
|
dangling = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
deque.push_front(Entity::AddOrRetract {
|
||||||
|
op: OpType::Add,
|
||||||
|
e: db_id.clone(),
|
||||||
|
a: entmod::Entid::Entid(inner_a),
|
||||||
|
v: inner_v,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if dangling {
|
||||||
|
bail!(ErrorKind::NotYetImplemented(format!("Cannot explode nested map value that would lead to dangling entity for attribute {}", a)));
|
||||||
|
}
|
||||||
|
|
||||||
|
in_process.entity_e_into_term_v(db_id)?
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let e = in_process.entity_e_into_term_e(e)?;
|
||||||
|
terms.push(Term::AddOrRetract(op, e, a, v));
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue