Combine NamespacedKeyword and Keyword. (#689) r=nalexander
* Make properties on NamespacedKeyword/NamespacedSymbol private * Use only a single String for NamespacedKeyword/NamespacedSymbol * Review comments. * Remove unsafe code in namespaced_name. Benchmarking shows approximately zero change. * Allow the types of ns and name to differ when constructing a NamespacedName. * Make symbol namespaces optional. * Normalize names of keyword/symbol constructors. This will make the subsequent refactor much less painful. * Use expect not unwrap. * Merge Keyword and NamespacedKeyword.
This commit is contained in:
parent
c8f74fa41b
commit
3dc68bcd38
59 changed files with 1001 additions and 602 deletions
|
@ -165,7 +165,7 @@ This is the lowest-level Mentat crate. It collects together the following things
|
||||||
|
|
||||||
- Fundamental domain-specific data structures like `ValueType` and `TypedValue`.
|
- Fundamental domain-specific data structures like `ValueType` and `TypedValue`.
|
||||||
- Fundamental SQL-related linkages like `SQLValueType`. These encode the mapping between Mentat's types and values and their representation in our SQLite format.
|
- Fundamental SQL-related linkages like `SQLValueType`. These encode the mapping between Mentat's types and values and their representation in our SQLite format.
|
||||||
- Conversion to and from EDN types (_e.g._, `edn::NamespacedKeyword` to `TypedValue::Keyword`).
|
- Conversion to and from EDN types (_e.g._, `edn::Keyword` to `TypedValue::Keyword`).
|
||||||
- Common utilities (some in the `util` module, and others that should be moved there or broken out) like `Either`, `InternSet`, and `RcCounter`.
|
- Common utilities (some in the `util` module, and others that should be moved there or broken out) like `Either`, `InternSet`, and `RcCounter`.
|
||||||
- Reusable lazy namespaced keywords (_e.g._, `DB_TYPE_DOUBLE`) that are used by `mentat_db` and EDN serialization of core structs.
|
- Reusable lazy namespaced keywords (_e.g._, `DB_TYPE_DOUBLE`) that are used by `mentat_db` and EDN serialization of core structs.
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ pub use chrono::{
|
||||||
|
|
||||||
pub use edn::{
|
pub use edn::{
|
||||||
FromMicros,
|
FromMicros,
|
||||||
NamespacedKeyword,
|
Keyword,
|
||||||
ToMicros,
|
ToMicros,
|
||||||
Utc,
|
Utc,
|
||||||
};
|
};
|
||||||
|
@ -180,10 +180,10 @@ impl Attribute {
|
||||||
flags
|
flags
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_edn_value(&self, ident: Option<NamespacedKeyword>) -> edn::Value {
|
pub fn to_edn_value(&self, ident: Option<Keyword>) -> edn::Value {
|
||||||
let mut attribute_map: BTreeMap<edn::Value, edn::Value> = BTreeMap::default();
|
let mut attribute_map: BTreeMap<edn::Value, edn::Value> = BTreeMap::default();
|
||||||
if let Some(ident) = ident {
|
if let Some(ident) = ident {
|
||||||
attribute_map.insert(values::DB_IDENT.clone(), edn::Value::NamespacedKeyword(ident));
|
attribute_map.insert(values::DB_IDENT.clone(), edn::Value::Keyword(ident));
|
||||||
}
|
}
|
||||||
|
|
||||||
attribute_map.insert(values::DB_VALUE_TYPE.clone(), self.value_type.into_edn_value());
|
attribute_map.insert(values::DB_VALUE_TYPE.clone(), self.value_type.into_edn_value());
|
||||||
|
@ -231,11 +231,11 @@ impl Default for Attribute {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Map `NamespacedKeyword` idents (`:db/ident`) to positive integer entids (`1`).
|
/// Map `Keyword` idents (`:db/ident`) to positive integer entids (`1`).
|
||||||
pub type IdentMap = BTreeMap<NamespacedKeyword, Entid>;
|
pub type IdentMap = BTreeMap<Keyword, Entid>;
|
||||||
|
|
||||||
/// Map positive integer entids (`1`) to `NamespacedKeyword` idents (`:db/ident`).
|
/// Map positive integer entids (`1`) to `Keyword` idents (`:db/ident`).
|
||||||
pub type EntidMap = BTreeMap<Entid, NamespacedKeyword>;
|
pub type EntidMap = BTreeMap<Entid, Keyword>;
|
||||||
|
|
||||||
/// Map attribute entids to `Attribute` instances.
|
/// Map attribute entids to `Attribute` instances.
|
||||||
pub type AttributeMap = BTreeMap<Entid, Attribute>;
|
pub type AttributeMap = BTreeMap<Entid, Attribute>;
|
||||||
|
@ -273,18 +273,18 @@ pub struct Schema {
|
||||||
pub trait HasSchema {
|
pub trait HasSchema {
|
||||||
fn entid_for_type(&self, t: ValueType) -> Option<KnownEntid>;
|
fn entid_for_type(&self, t: ValueType) -> Option<KnownEntid>;
|
||||||
|
|
||||||
fn get_ident<T>(&self, x: T) -> Option<&NamespacedKeyword> where T: Into<Entid>;
|
fn get_ident<T>(&self, x: T) -> Option<&Keyword> where T: Into<Entid>;
|
||||||
fn get_entid(&self, x: &NamespacedKeyword) -> Option<KnownEntid>;
|
fn get_entid(&self, x: &Keyword) -> Option<KnownEntid>;
|
||||||
fn attribute_for_entid<T>(&self, x: T) -> Option<&Attribute> where T: Into<Entid>;
|
fn attribute_for_entid<T>(&self, x: T) -> Option<&Attribute> where T: Into<Entid>;
|
||||||
|
|
||||||
// Returns the attribute and the entid named by the provided ident.
|
// Returns the attribute and the entid named by the provided ident.
|
||||||
fn attribute_for_ident(&self, ident: &NamespacedKeyword) -> Option<(&Attribute, KnownEntid)>;
|
fn attribute_for_ident(&self, ident: &Keyword) -> Option<(&Attribute, KnownEntid)>;
|
||||||
|
|
||||||
/// Return true if the provided entid identifies an attribute in this schema.
|
/// Return true if the provided entid identifies an attribute in this schema.
|
||||||
fn is_attribute<T>(&self, x: T) -> bool where T: Into<Entid>;
|
fn is_attribute<T>(&self, x: T) -> bool where T: Into<Entid>;
|
||||||
|
|
||||||
/// Return true if the provided ident identifies an attribute in this schema.
|
/// Return true if the provided ident identifies an attribute in this schema.
|
||||||
fn identifies_attribute(&self, x: &NamespacedKeyword) -> bool;
|
fn identifies_attribute(&self, x: &Keyword) -> bool;
|
||||||
|
|
||||||
fn component_attributes(&self) -> &[Entid];
|
fn component_attributes(&self) -> &[Entid];
|
||||||
}
|
}
|
||||||
|
@ -304,7 +304,7 @@ impl Schema {
|
||||||
.collect())
|
.collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_raw_entid(&self, x: &NamespacedKeyword) -> Option<Entid> {
|
fn get_raw_entid(&self, x: &Keyword) -> Option<Entid> {
|
||||||
self.ident_map.get(x).map(|x| *x)
|
self.ident_map.get(x).map(|x| *x)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,11 +325,11 @@ impl HasSchema for Schema {
|
||||||
self.get_entid(&t.into_keyword())
|
self.get_entid(&t.into_keyword())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_ident<T>(&self, x: T) -> Option<&NamespacedKeyword> where T: Into<Entid> {
|
fn get_ident<T>(&self, x: T) -> Option<&Keyword> where T: Into<Entid> {
|
||||||
self.entid_map.get(&x.into())
|
self.entid_map.get(&x.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_entid(&self, x: &NamespacedKeyword) -> Option<KnownEntid> {
|
fn get_entid(&self, x: &Keyword) -> Option<KnownEntid> {
|
||||||
self.get_raw_entid(x).map(KnownEntid)
|
self.get_raw_entid(x).map(KnownEntid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,7 +337,7 @@ impl HasSchema for Schema {
|
||||||
self.attribute_map.get(&x.into())
|
self.attribute_map.get(&x.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn attribute_for_ident(&self, ident: &NamespacedKeyword) -> Option<(&Attribute, KnownEntid)> {
|
fn attribute_for_ident(&self, ident: &Keyword) -> Option<(&Attribute, KnownEntid)> {
|
||||||
self.get_raw_entid(&ident)
|
self.get_raw_entid(&ident)
|
||||||
.and_then(|entid| {
|
.and_then(|entid| {
|
||||||
self.attribute_for_entid(entid).map(|a| (a, KnownEntid(entid)))
|
self.attribute_for_entid(entid).map(|a| (a, KnownEntid(entid)))
|
||||||
|
@ -350,7 +350,7 @@ impl HasSchema for Schema {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return true if the provided ident identifies an attribute in this schema.
|
/// Return true if the provided ident identifies an attribute in this schema.
|
||||||
fn identifies_attribute(&self, x: &NamespacedKeyword) -> bool {
|
fn identifies_attribute(&self, x: &Keyword) -> bool {
|
||||||
self.get_raw_entid(x).map(|e| self.is_attribute(e)).unwrap_or(false)
|
self.get_raw_entid(x).map(|e| self.is_attribute(e)).unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -408,7 +408,7 @@ mod test {
|
||||||
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
fn associate_ident(schema: &mut Schema, i: NamespacedKeyword, e: Entid) {
|
fn associate_ident(schema: &mut Schema, i: Keyword, e: Entid) {
|
||||||
schema.entid_map.insert(e, i.clone());
|
schema.entid_map.insert(e, i.clone());
|
||||||
schema.ident_map.insert(i, e);
|
schema.ident_map.insert(i, e);
|
||||||
}
|
}
|
||||||
|
@ -491,7 +491,7 @@ mod test {
|
||||||
component: false,
|
component: false,
|
||||||
no_history: true,
|
no_history: true,
|
||||||
};
|
};
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "bar"), 97);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "bar"), 97);
|
||||||
add_attribute(&mut schema, 97, attr1);
|
add_attribute(&mut schema, 97, attr1);
|
||||||
|
|
||||||
let attr2 = Attribute {
|
let attr2 = Attribute {
|
||||||
|
@ -503,7 +503,7 @@ mod test {
|
||||||
component: false,
|
component: false,
|
||||||
no_history: false,
|
no_history: false,
|
||||||
};
|
};
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "bas"), 98);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "bas"), 98);
|
||||||
add_attribute(&mut schema, 98, attr2);
|
add_attribute(&mut schema, 98, attr2);
|
||||||
|
|
||||||
let attr3 = Attribute {
|
let attr3 = Attribute {
|
||||||
|
@ -516,7 +516,7 @@ mod test {
|
||||||
no_history: false,
|
no_history: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "bat"), 99);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "bat"), 99);
|
||||||
add_attribute(&mut schema, 99, attr3);
|
add_attribute(&mut schema, 99, attr3);
|
||||||
|
|
||||||
let value = schema.to_edn_value();
|
let value = schema.to_edn_value();
|
||||||
|
|
|
@ -40,7 +40,7 @@ use ::indexmap::{
|
||||||
use ::edn::{
|
use ::edn::{
|
||||||
self,
|
self,
|
||||||
FromMicros,
|
FromMicros,
|
||||||
NamespacedKeyword,
|
Keyword,
|
||||||
Utc,
|
Utc,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -205,8 +205,8 @@ impl ::enum_set::CLike for ValueType {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ValueType {
|
impl ValueType {
|
||||||
pub fn into_keyword(self) -> NamespacedKeyword {
|
pub fn into_keyword(self) -> Keyword {
|
||||||
NamespacedKeyword::new("db.type", match self {
|
Keyword::namespaced("db.type", match self {
|
||||||
ValueType::Ref => "ref",
|
ValueType::Ref => "ref",
|
||||||
ValueType::Boolean => "boolean",
|
ValueType::Boolean => "boolean",
|
||||||
ValueType::Instant => "instant",
|
ValueType::Instant => "instant",
|
||||||
|
@ -280,7 +280,7 @@ pub enum TypedValue {
|
||||||
Instant(DateTime<Utc>), // Use `into()` to ensure truncation.
|
Instant(DateTime<Utc>), // Use `into()` to ensure truncation.
|
||||||
// TODO: &str throughout?
|
// TODO: &str throughout?
|
||||||
String(ValueRc<String>),
|
String(ValueRc<String>),
|
||||||
Keyword(ValueRc<NamespacedKeyword>),
|
Keyword(ValueRc<Keyword>),
|
||||||
Uuid(Uuid), // It's only 128 bits, so this should be acceptable to clone.
|
Uuid(Uuid), // It's only 128 bits, so this should be acceptable to clone.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,23 +335,23 @@ impl Binding {
|
||||||
/// We entirely support the former, and partially support the latter -- you can alias
|
/// We entirely support the former, and partially support the latter -- you can alias
|
||||||
/// using a different keyword only.
|
/// using a different keyword only.
|
||||||
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
||||||
pub struct StructuredMap(pub IndexMap<ValueRc<NamespacedKeyword>, Binding>);
|
pub struct StructuredMap(pub IndexMap<ValueRc<Keyword>, Binding>);
|
||||||
|
|
||||||
impl StructuredMap {
|
impl StructuredMap {
|
||||||
pub fn insert<N, B>(&mut self, name: N, value: B) where N: Into<ValueRc<NamespacedKeyword>>, B: Into<Binding> {
|
pub fn insert<N, B>(&mut self, name: N, value: B) where N: Into<ValueRc<Keyword>>, B: Into<Binding> {
|
||||||
self.0.insert(name.into(), value.into());
|
self.0.insert(name.into(), value.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<IndexMap<ValueRc<NamespacedKeyword>, Binding>> for StructuredMap {
|
impl From<IndexMap<ValueRc<Keyword>, Binding>> for StructuredMap {
|
||||||
fn from(src: IndexMap<ValueRc<NamespacedKeyword>, Binding>) -> Self {
|
fn from(src: IndexMap<ValueRc<Keyword>, Binding>) -> Self {
|
||||||
StructuredMap(src)
|
StructuredMap(src)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mostly for testing.
|
// Mostly for testing.
|
||||||
impl<T> From<Vec<(NamespacedKeyword, T)>> for StructuredMap where T: Into<Binding> {
|
impl<T> From<Vec<(Keyword, T)>> for StructuredMap where T: Into<Binding> {
|
||||||
fn from(value: Vec<(NamespacedKeyword, T)>) -> Self {
|
fn from(value: Vec<(Keyword, T)>) -> Self {
|
||||||
let mut sm = StructuredMap::default();
|
let mut sm = StructuredMap::default();
|
||||||
for (k, v) in value.into_iter() {
|
for (k, v) in value.into_iter() {
|
||||||
sm.insert(k, v);
|
sm.insert(k, v);
|
||||||
|
@ -414,7 +414,7 @@ impl TypedValue {
|
||||||
/// values and wrapping them in a new `ValueRc`. This is expensive, so this might
|
/// values and wrapping them in a new `ValueRc`. This is expensive, so this might
|
||||||
/// be best limited to tests.
|
/// be best limited to tests.
|
||||||
pub fn typed_ns_keyword(ns: &str, name: &str) -> TypedValue {
|
pub fn typed_ns_keyword(ns: &str, name: &str) -> TypedValue {
|
||||||
NamespacedKeyword::new(ns, name).into()
|
Keyword::namespaced(ns, name).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a new `TypedValue::String` instance by cloning the provided
|
/// Construct a new `TypedValue::String` instance by cloning the provided
|
||||||
|
@ -509,20 +509,20 @@ impl From<String> for TypedValue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Arc<NamespacedKeyword>> for TypedValue {
|
impl From<Arc<Keyword>> for TypedValue {
|
||||||
fn from(value: Arc<NamespacedKeyword>) -> TypedValue {
|
fn from(value: Arc<Keyword>) -> TypedValue {
|
||||||
TypedValue::Keyword(ValueRc::from_arc(value))
|
TypedValue::Keyword(ValueRc::from_arc(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Rc<NamespacedKeyword>> for TypedValue {
|
impl From<Rc<Keyword>> for TypedValue {
|
||||||
fn from(value: Rc<NamespacedKeyword>) -> TypedValue {
|
fn from(value: Rc<Keyword>) -> TypedValue {
|
||||||
TypedValue::Keyword(ValueRc::from_rc(value))
|
TypedValue::Keyword(ValueRc::from_rc(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<NamespacedKeyword> for TypedValue {
|
impl From<Keyword> for TypedValue {
|
||||||
fn from(value: NamespacedKeyword) -> TypedValue {
|
fn from(value: Keyword) -> TypedValue {
|
||||||
TypedValue::Keyword(ValueRc::new(value))
|
TypedValue::Keyword(ValueRc::new(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -560,7 +560,7 @@ impl TypedValue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_kw(self) -> Option<ValueRc<NamespacedKeyword>> {
|
pub fn into_kw(self) -> Option<ValueRc<Keyword>> {
|
||||||
match self {
|
match self {
|
||||||
TypedValue::Keyword(v) => Some(v),
|
TypedValue::Keyword(v) => Some(v),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -687,7 +687,7 @@ impl Binding {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_kw(self) -> Option<ValueRc<NamespacedKeyword>> {
|
pub fn into_kw(self) -> Option<ValueRc<Keyword>> {
|
||||||
match self {
|
match self {
|
||||||
Binding::Scalar(TypedValue::Keyword(v)) => Some(v),
|
Binding::Scalar(TypedValue::Keyword(v)) => Some(v),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
use edn::types::Value;
|
use edn::types::Value;
|
||||||
use edn::symbols;
|
use edn::symbols;
|
||||||
|
|
||||||
/// Declare a lazy static `ident` of type `Value::NamespacedKeyword` with the given `namespace` and
|
/// Declare a lazy static `ident` of type `Value::Keyword` with the given `namespace` and
|
||||||
/// `name`.
|
/// `name`.
|
||||||
///
|
///
|
||||||
/// It may look surprising that we declare a new `lazy_static!` block rather than including
|
/// It may look surprising that we declare a new `lazy_static!` block rather than including
|
||||||
|
@ -31,7 +31,7 @@ macro_rules! lazy_static_namespaced_keyword_value (
|
||||||
($tag:ident, $namespace:expr, $name:expr) => (
|
($tag:ident, $namespace:expr, $name:expr) => (
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref $tag: Value = {
|
pub static ref $tag: Value = {
|
||||||
Value::NamespacedKeyword(symbols::NamespacedKeyword::new($namespace, $name))
|
Value::Keyword(symbols::Keyword::namespaced($namespace, $name))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -38,7 +38,7 @@ pub const USER0: i64 = 0x10000;
|
||||||
pub const CORE_SCHEMA_VERSION: u32 = 1;
|
pub const CORE_SCHEMA_VERSION: u32 = 1;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref V1_IDENTS: [(symbols::NamespacedKeyword, i64); 40] = {
|
static ref V1_IDENTS: [(symbols::Keyword, i64); 40] = {
|
||||||
[(ns_keyword!("db", "ident"), entids::DB_IDENT),
|
[(ns_keyword!("db", "ident"), entids::DB_IDENT),
|
||||||
(ns_keyword!("db.part", "db"), entids::DB_PART_DB),
|
(ns_keyword!("db.part", "db"), entids::DB_PART_DB),
|
||||||
(ns_keyword!("db", "txInstant"), entids::DB_TX_INSTANT),
|
(ns_keyword!("db", "txInstant"), entids::DB_TX_INSTANT),
|
||||||
|
@ -82,14 +82,14 @@ lazy_static! {
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
static ref V1_PARTS: [(symbols::NamespacedKeyword, i64, i64); 3] = {
|
static ref V1_PARTS: [(symbols::Keyword, i64, i64); 3] = {
|
||||||
[(ns_keyword!("db.part", "db"), 0, (1 + V1_IDENTS.len()) as i64),
|
[(ns_keyword!("db.part", "db"), 0, (1 + V1_IDENTS.len()) as i64),
|
||||||
(ns_keyword!("db.part", "user"), USER0, USER0),
|
(ns_keyword!("db.part", "user"), USER0, USER0),
|
||||||
(ns_keyword!("db.part", "tx"), TX0, TX0),
|
(ns_keyword!("db.part", "tx"), TX0, TX0),
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
static ref V1_CORE_SCHEMA: [(symbols::NamespacedKeyword); 16] = {
|
static ref V1_CORE_SCHEMA: [(symbols::Keyword); 16] = {
|
||||||
[(ns_keyword!("db", "ident")),
|
[(ns_keyword!("db", "ident")),
|
||||||
(ns_keyword!("db.install", "partition")),
|
(ns_keyword!("db.install", "partition")),
|
||||||
(ns_keyword!("db.install", "valueType")),
|
(ns_keyword!("db.install", "valueType")),
|
||||||
|
@ -162,25 +162,25 @@ lazy_static! {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert (ident, entid) pairs into [:db/add IDENT :db/ident IDENT] `Value` instances.
|
/// Convert (ident, entid) pairs into [:db/add IDENT :db/ident IDENT] `Value` instances.
|
||||||
fn idents_to_assertions(idents: &[(symbols::NamespacedKeyword, i64)]) -> Vec<Value> {
|
fn idents_to_assertions(idents: &[(symbols::Keyword, i64)]) -> Vec<Value> {
|
||||||
idents
|
idents
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|&(ref ident, _)| {
|
.map(|&(ref ident, _)| {
|
||||||
let value = Value::NamespacedKeyword(ident.clone());
|
let value = Value::Keyword(ident.clone());
|
||||||
Value::Vector(vec![values::DB_ADD.clone(), value.clone(), values::DB_IDENT.clone(), value.clone()])
|
Value::Vector(vec![values::DB_ADD.clone(), value.clone(), values::DB_IDENT.clone(), value.clone()])
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert an ident list into [:db/add :db.schema/core :db.schema/attribute IDENT] `Value` instances.
|
/// Convert an ident list into [:db/add :db.schema/core :db.schema/attribute IDENT] `Value` instances.
|
||||||
fn schema_attrs_to_assertions(version: u32, idents: &[symbols::NamespacedKeyword]) -> Vec<Value> {
|
fn schema_attrs_to_assertions(version: u32, idents: &[symbols::Keyword]) -> Vec<Value> {
|
||||||
let schema_core = Value::NamespacedKeyword(ns_keyword!("db.schema", "core"));
|
let schema_core = Value::Keyword(ns_keyword!("db.schema", "core"));
|
||||||
let schema_attr = Value::NamespacedKeyword(ns_keyword!("db.schema", "attribute"));
|
let schema_attr = Value::Keyword(ns_keyword!("db.schema", "attribute"));
|
||||||
let schema_version = Value::NamespacedKeyword(ns_keyword!("db.schema", "version"));
|
let schema_version = Value::Keyword(ns_keyword!("db.schema", "version"));
|
||||||
idents
|
idents
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|ident| {
|
.map(|ident| {
|
||||||
let value = Value::NamespacedKeyword(ident.clone());
|
let value = Value::Keyword(ident.clone());
|
||||||
Value::Vector(vec![values::DB_ADD.clone(),
|
Value::Vector(vec![values::DB_ADD.clone(),
|
||||||
schema_core.clone(),
|
schema_core.clone(),
|
||||||
schema_attr.clone(),
|
schema_attr.clone(),
|
||||||
|
@ -194,27 +194,27 @@ fn schema_attrs_to_assertions(version: u32, idents: &[symbols::NamespacedKeyword
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert {:ident {:key :value ...} ...} to
|
/// Convert {:ident {:key :value ...} ...} to
|
||||||
/// vec![(symbols::NamespacedKeyword(:ident), symbols::NamespacedKeyword(:key), TypedValue(:value)), ...].
|
/// vec![(symbols::Keyword(:ident), symbols::Keyword(:key), TypedValue(:value)), ...].
|
||||||
///
|
///
|
||||||
/// Such triples are closer to what the transactor will produce when processing attribute
|
/// Such triples are closer to what the transactor will produce when processing attribute
|
||||||
/// assertions.
|
/// assertions.
|
||||||
fn symbolic_schema_to_triples(ident_map: &IdentMap, symbolic_schema: &Value) -> Result<Vec<(symbols::NamespacedKeyword, symbols::NamespacedKeyword, TypedValue)>> {
|
fn symbolic_schema_to_triples(ident_map: &IdentMap, symbolic_schema: &Value) -> Result<Vec<(symbols::Keyword, symbols::Keyword, TypedValue)>> {
|
||||||
// Failure here is a coding error, not a runtime error.
|
// Failure here is a coding error, not a runtime error.
|
||||||
let mut triples: Vec<(symbols::NamespacedKeyword, symbols::NamespacedKeyword, TypedValue)> = vec![];
|
let mut triples: Vec<(symbols::Keyword, symbols::Keyword, TypedValue)> = vec![];
|
||||||
// TODO: Consider `flat_map` and `map` rather than loop.
|
// TODO: Consider `flat_map` and `map` rather than loop.
|
||||||
match *symbolic_schema {
|
match *symbolic_schema {
|
||||||
Value::Map(ref m) => {
|
Value::Map(ref m) => {
|
||||||
for (ident, mp) in m {
|
for (ident, mp) in m {
|
||||||
let ident = match ident {
|
let ident = match ident {
|
||||||
&Value::NamespacedKeyword(ref ident) => ident,
|
&Value::Keyword(ref ident) => ident,
|
||||||
_ => bail!(ErrorKind::BadBootstrapDefinition(format!("Expected namespaced keyword for ident but got '{:?}'", ident)))
|
v => bail!(ErrorKind::BadBootstrapDefinition(format!("Expected namespaced keyword for ident but got '{:?}'", ident))),
|
||||||
};
|
};
|
||||||
match *mp {
|
match *mp {
|
||||||
Value::Map(ref mpp) => {
|
Value::Map(ref mpp) => {
|
||||||
for (attr, value) in mpp {
|
for (attr, value) in mpp {
|
||||||
let attr = match attr {
|
let attr = match attr {
|
||||||
&Value::NamespacedKeyword(ref attr) => attr,
|
&Value::Keyword(ref attr) => attr,
|
||||||
_ => bail!(ErrorKind::BadBootstrapDefinition(format!("Expected namespaced keyword for attr but got '{:?}'", attr)))
|
_ => bail!(ErrorKind::BadBootstrapDefinition(format!("Expected namespaced keyword for attr but got '{:?}'", attr))),
|
||||||
};
|
};
|
||||||
|
|
||||||
// We have symbolic idents but the transactor handles entids. Ad-hoc
|
// We have symbolic idents but the transactor handles entids. Ad-hoc
|
||||||
|
@ -286,19 +286,19 @@ pub(crate) fn bootstrap_ident_map() -> IdentMap {
|
||||||
|
|
||||||
pub(crate) fn bootstrap_schema() -> Schema {
|
pub(crate) fn bootstrap_schema() -> Schema {
|
||||||
let ident_map = bootstrap_ident_map();
|
let ident_map = bootstrap_ident_map();
|
||||||
let bootstrap_triples = symbolic_schema_to_triples(&ident_map, &V1_SYMBOLIC_SCHEMA).unwrap();
|
let bootstrap_triples = symbolic_schema_to_triples(&ident_map, &V1_SYMBOLIC_SCHEMA).expect("symbolic schema");
|
||||||
Schema::from_ident_map_and_triples(ident_map, bootstrap_triples).unwrap()
|
Schema::from_ident_map_and_triples(ident_map, bootstrap_triples).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn bootstrap_entities() -> Vec<Entity> {
|
pub(crate) fn bootstrap_entities() -> Vec<Entity> {
|
||||||
let bootstrap_assertions: Value = Value::Vector([
|
let bootstrap_assertions: Value = Value::Vector([
|
||||||
symbolic_schema_to_assertions(&V1_SYMBOLIC_SCHEMA).unwrap(),
|
symbolic_schema_to_assertions(&V1_SYMBOLIC_SCHEMA).expect("symbolic schema"),
|
||||||
idents_to_assertions(&V1_IDENTS[..]),
|
idents_to_assertions(&V1_IDENTS[..]),
|
||||||
schema_attrs_to_assertions(CORE_SCHEMA_VERSION, V1_CORE_SCHEMA.as_ref()),
|
schema_attrs_to_assertions(CORE_SCHEMA_VERSION, V1_CORE_SCHEMA.as_ref()),
|
||||||
].concat());
|
].concat());
|
||||||
|
|
||||||
// Failure here is a coding error (since the inputs are fixed), not a runtime error.
|
// Failure here is a coding error (since the inputs are fixed), not a runtime error.
|
||||||
// TODO: represent these bootstrap data errors rather than just panicing.
|
// TODO: represent these bootstrap data errors rather than just panicing.
|
||||||
let bootstrap_entities: Vec<Entity> = edn::parse::entities(&bootstrap_assertions.to_string()).unwrap();
|
let bootstrap_entities: Vec<Entity> = edn::parse::entities(&bootstrap_assertions.to_string()).expect("bootstrap assertions");
|
||||||
return bootstrap_entities;
|
return bootstrap_entities;
|
||||||
}
|
}
|
||||||
|
|
|
@ -422,7 +422,7 @@ impl TypedSQLValue for TypedValue {
|
||||||
&Value::Uuid(x) => Some(TypedValue::Uuid(x)),
|
&Value::Uuid(x) => Some(TypedValue::Uuid(x)),
|
||||||
&Value::Float(ref x) => Some(TypedValue::Double(x.clone())),
|
&Value::Float(ref x) => Some(TypedValue::Double(x.clone())),
|
||||||
&Value::Text(ref x) => Some(x.clone().into()),
|
&Value::Text(ref x) => Some(x.clone().into()),
|
||||||
&Value::NamespacedKeyword(ref x) => Some(x.clone().into()),
|
&Value::Keyword(ref x) => Some(x.clone().into()),
|
||||||
_ => None
|
_ => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -452,7 +452,7 @@ impl TypedSQLValue for TypedValue {
|
||||||
&TypedValue::Double(x) => (Value::Float(x), ValueType::Double),
|
&TypedValue::Double(x) => (Value::Float(x), ValueType::Double),
|
||||||
&TypedValue::String(ref x) => (Value::Text(x.as_ref().clone()), ValueType::String),
|
&TypedValue::String(ref x) => (Value::Text(x.as_ref().clone()), ValueType::String),
|
||||||
&TypedValue::Uuid(ref u) => (Value::Uuid(u.clone()), ValueType::Uuid),
|
&TypedValue::Uuid(ref u) => (Value::Uuid(u.clone()), ValueType::Uuid),
|
||||||
&TypedValue::Keyword(ref x) => (Value::NamespacedKeyword(x.as_ref().clone()), ValueType::Keyword),
|
&TypedValue::Keyword(ref x) => (Value::Keyword(x.as_ref().clone()), ValueType::Keyword),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1155,7 +1155,7 @@ mod tests {
|
||||||
use edn;
|
use edn;
|
||||||
use mentat_core::{
|
use mentat_core::{
|
||||||
HasSchema,
|
HasSchema,
|
||||||
NamespacedKeyword,
|
Keyword,
|
||||||
Schema,
|
Schema,
|
||||||
attribute,
|
attribute,
|
||||||
};
|
};
|
||||||
|
@ -1840,7 +1840,7 @@ mod tests {
|
||||||
|
|
||||||
// Once we've done so, the schema shows it's not unique…
|
// Once we've done so, the schema shows it's not unique…
|
||||||
{
|
{
|
||||||
let attr = conn.schema.attribute_for_ident(&NamespacedKeyword::new("test", "ident")).unwrap().0;
|
let attr = conn.schema.attribute_for_ident(&Keyword::namespaced("test", "ident")).unwrap().0;
|
||||||
assert_eq!(None, attr.unique);
|
assert_eq!(None, attr.unique);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,7 @@ impl Datom {
|
||||||
let f = |entid: &Entid| -> edn::Value {
|
let f = |entid: &Entid| -> edn::Value {
|
||||||
match *entid {
|
match *entid {
|
||||||
Entid::Entid(ref y) => edn::Value::Integer(y.clone()),
|
Entid::Entid(ref y) => edn::Value::Integer(y.clone()),
|
||||||
Entid::Ident(ref y) => edn::Value::NamespacedKeyword(y.clone()),
|
Entid::Ident(ref y) => edn::Value::Keyword(y.clone()),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,14 @@ impl TransactableValue for ValueAndSpan {
|
||||||
use self::SpannedValue::*;
|
use self::SpannedValue::*;
|
||||||
match self.inner {
|
match self.inner {
|
||||||
Integer(v) => Ok(EntidOrLookupRefOrTempId::Entid(entities::Entid::Entid(v))),
|
Integer(v) => Ok(EntidOrLookupRefOrTempId::Entid(entities::Entid::Entid(v))),
|
||||||
NamespacedKeyword(v) => Ok(EntidOrLookupRefOrTempId::Entid(entities::Entid::Ident(v))),
|
Keyword(v) => {
|
||||||
|
if v.is_namespaced() {
|
||||||
|
Ok(EntidOrLookupRefOrTempId::Entid(entities::Entid::Ident(v)))
|
||||||
|
} else {
|
||||||
|
// We only allow namespaced idents.
|
||||||
|
bail!(ErrorKind::InputError(errors::InputError::BadEntityPlace))
|
||||||
|
}
|
||||||
|
},
|
||||||
Text(v) => Ok(EntidOrLookupRefOrTempId::TempId(TempId::External(v))),
|
Text(v) => Ok(EntidOrLookupRefOrTempId::TempId(TempId::External(v))),
|
||||||
List(ls) => {
|
List(ls) => {
|
||||||
let mut it = ls.iter();
|
let mut it = ls.iter();
|
||||||
|
@ -102,7 +109,6 @@ impl TransactableValue for ValueAndSpan {
|
||||||
Uuid(_) |
|
Uuid(_) |
|
||||||
PlainSymbol(_) |
|
PlainSymbol(_) |
|
||||||
NamespacedSymbol(_) |
|
NamespacedSymbol(_) |
|
||||||
Keyword(_) |
|
|
||||||
Vector(_) |
|
Vector(_) |
|
||||||
Set(_) |
|
Set(_) |
|
||||||
Map(_) => bail!(ErrorKind::InputError(errors::InputError::BadEntityPlace)),
|
Map(_) => bail!(ErrorKind::InputError(errors::InputError::BadEntityPlace)),
|
||||||
|
|
|
@ -98,16 +98,16 @@ pub use types::{
|
||||||
TxReport,
|
TxReport,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn to_namespaced_keyword(s: &str) -> Result<symbols::NamespacedKeyword> {
|
pub fn to_namespaced_keyword(s: &str) -> Result<symbols::Keyword> {
|
||||||
let splits = [':', '/'];
|
let splits = [':', '/'];
|
||||||
let mut i = s.split(&splits[..]);
|
let mut i = s.split(&splits[..]);
|
||||||
let nsk = match (i.next(), i.next(), i.next(), i.next()) {
|
let nsk = match (i.next(), i.next(), i.next(), i.next()) {
|
||||||
(Some(""), Some(namespace), Some(name), None) => Some(symbols::NamespacedKeyword::new(namespace, name)),
|
(Some(""), Some(namespace), Some(name), None) => Some(symbols::Keyword::namespaced(namespace, name)),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO Use custom ErrorKind https://github.com/brson/error-chain/issues/117
|
// TODO Use custom ErrorKind https://github.com/brson/error-chain/issues/117
|
||||||
nsk.ok_or(ErrorKind::NotYetImplemented(format!("InvalidNamespacedKeyword: {}", s)).into())
|
nsk.ok_or(ErrorKind::NotYetImplemented(format!("InvalidKeyword: {}", s)).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Prepare an SQL `VALUES` block, like (?, ?, ?), (?, ?, ?).
|
/// Prepare an SQL `VALUES` block, like (?, ?, ?), (?, ?, ?).
|
||||||
|
|
|
@ -72,7 +72,7 @@ pub enum AttributeAlteration {
|
||||||
/// An alteration to an ident.
|
/// An alteration to an ident.
|
||||||
#[derive(Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)]
|
#[derive(Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)]
|
||||||
pub enum IdentAlteration {
|
pub enum IdentAlteration {
|
||||||
Ident(symbols::NamespacedKeyword),
|
Ident(symbols::Keyword),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Summarizes changes to metadata such as a a `Schema` and (in the future) a `PartitionMap`.
|
/// Summarizes changes to metadata such as a a `Schema` and (in the future) a `PartitionMap`.
|
||||||
|
@ -285,7 +285,7 @@ pub fn update_schema_from_entid_quadruples<U>(schema: &mut Schema, assertions: U
|
||||||
// retracted at most once), which means all attribute alterations are simple changes from an old
|
// retracted at most once), which means all attribute alterations are simple changes from an old
|
||||||
// value to a new value.
|
// value to a new value.
|
||||||
let mut attribute_set: AddRetractAlterSet<(Entid, Entid), TypedValue> = AddRetractAlterSet::default();
|
let mut attribute_set: AddRetractAlterSet<(Entid, Entid), TypedValue> = AddRetractAlterSet::default();
|
||||||
let mut ident_set: AddRetractAlterSet<Entid, symbols::NamespacedKeyword> = AddRetractAlterSet::default();
|
let mut ident_set: AddRetractAlterSet<Entid, symbols::Keyword> = AddRetractAlterSet::default();
|
||||||
|
|
||||||
for (e, a, typed_value, added) in assertions.into_iter() {
|
for (e, a, typed_value, added) in assertions.into_iter() {
|
||||||
// Here we handle :db/ident assertions.
|
// Here we handle :db/ident assertions.
|
||||||
|
|
|
@ -237,20 +237,20 @@ impl AttributeBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait SchemaBuilding {
|
pub trait SchemaBuilding {
|
||||||
fn require_ident(&self, entid: Entid) -> Result<&symbols::NamespacedKeyword>;
|
fn require_ident(&self, entid: Entid) -> Result<&symbols::Keyword>;
|
||||||
fn require_entid(&self, ident: &symbols::NamespacedKeyword) -> Result<KnownEntid>;
|
fn require_entid(&self, ident: &symbols::Keyword) -> Result<KnownEntid>;
|
||||||
fn require_attribute_for_entid(&self, entid: Entid) -> Result<&Attribute>;
|
fn require_attribute_for_entid(&self, entid: Entid) -> Result<&Attribute>;
|
||||||
fn from_ident_map_and_attribute_map(ident_map: IdentMap, attribute_map: AttributeMap) -> Result<Schema>;
|
fn from_ident_map_and_attribute_map(ident_map: IdentMap, attribute_map: AttributeMap) -> Result<Schema>;
|
||||||
fn from_ident_map_and_triples<U>(ident_map: IdentMap, assertions: U) -> Result<Schema>
|
fn from_ident_map_and_triples<U>(ident_map: IdentMap, assertions: U) -> Result<Schema>
|
||||||
where U: IntoIterator<Item=(symbols::NamespacedKeyword, symbols::NamespacedKeyword, TypedValue)>;
|
where U: IntoIterator<Item=(symbols::Keyword, symbols::Keyword, TypedValue)>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SchemaBuilding for Schema {
|
impl SchemaBuilding for Schema {
|
||||||
fn require_ident(&self, entid: Entid) -> Result<&symbols::NamespacedKeyword> {
|
fn require_ident(&self, entid: Entid) -> Result<&symbols::Keyword> {
|
||||||
self.get_ident(entid).ok_or(ErrorKind::UnrecognizedEntid(entid).into())
|
self.get_ident(entid).ok_or(ErrorKind::UnrecognizedEntid(entid).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn require_entid(&self, ident: &symbols::NamespacedKeyword) -> Result<KnownEntid> {
|
fn require_entid(&self, ident: &symbols::Keyword) -> Result<KnownEntid> {
|
||||||
self.get_entid(&ident).ok_or(ErrorKind::UnrecognizedIdent(ident.to_string()).into())
|
self.get_entid(&ident).ok_or(ErrorKind::UnrecognizedIdent(ident.to_string()).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,9 +266,9 @@ impl SchemaBuilding for Schema {
|
||||||
Ok(Schema::new(ident_map, entid_map, attribute_map))
|
Ok(Schema::new(ident_map, entid_map, attribute_map))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Turn vec![(NamespacedKeyword(:ident), NamespacedKeyword(:key), TypedValue(:value)), ...] into a Mentat `Schema`.
|
/// Turn vec![(Keyword(:ident), Keyword(:key), TypedValue(:value)), ...] into a Mentat `Schema`.
|
||||||
fn from_ident_map_and_triples<U>(ident_map: IdentMap, assertions: U) -> Result<Schema>
|
fn from_ident_map_and_triples<U>(ident_map: IdentMap, assertions: U) -> Result<Schema>
|
||||||
where U: IntoIterator<Item=(symbols::NamespacedKeyword, symbols::NamespacedKeyword, TypedValue)>{
|
where U: IntoIterator<Item=(symbols::Keyword, symbols::Keyword, TypedValue)>{
|
||||||
|
|
||||||
let entid_assertions: Result<Vec<(Entid, Entid, TypedValue)>> = assertions.into_iter().map(|(symbolic_ident, symbolic_attr, value)| {
|
let entid_assertions: Result<Vec<(Entid, Entid, TypedValue)>> = assertions.into_iter().map(|(symbolic_ident, symbolic_attr, value)| {
|
||||||
let ident: i64 = *ident_map.get(&symbolic_ident).ok_or(ErrorKind::UnrecognizedIdent(symbolic_ident.to_string()))?;
|
let ident: i64 = *ident_map.get(&symbolic_ident).ok_or(ErrorKind::UnrecognizedIdent(symbolic_ident.to_string()))?;
|
||||||
|
@ -342,11 +342,11 @@ impl SchemaTypeChecking for Schema {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use self::edn::NamespacedKeyword;
|
use self::edn::Keyword;
|
||||||
use errors::Error;
|
use errors::Error;
|
||||||
|
|
||||||
fn add_attribute(schema: &mut Schema,
|
fn add_attribute(schema: &mut Schema,
|
||||||
ident: NamespacedKeyword,
|
ident: Keyword,
|
||||||
entid: Entid,
|
entid: Entid,
|
||||||
attribute: Attribute) {
|
attribute: Attribute) {
|
||||||
|
|
||||||
|
@ -364,7 +364,7 @@ mod test {
|
||||||
fn validate_attribute_map_success() {
|
fn validate_attribute_map_success() {
|
||||||
let mut schema = Schema::default();
|
let mut schema = Schema::default();
|
||||||
// attribute that is not an index has no uniqueness
|
// attribute that is not an index has no uniqueness
|
||||||
add_attribute(&mut schema, NamespacedKeyword::new("foo", "bar"), 97, Attribute {
|
add_attribute(&mut schema, Keyword::namespaced("foo", "bar"), 97, Attribute {
|
||||||
index: false,
|
index: false,
|
||||||
value_type: ValueType::Boolean,
|
value_type: ValueType::Boolean,
|
||||||
fulltext: false,
|
fulltext: false,
|
||||||
|
@ -374,7 +374,7 @@ mod test {
|
||||||
no_history: false,
|
no_history: false,
|
||||||
});
|
});
|
||||||
// attribute is unique by value and an index
|
// attribute is unique by value and an index
|
||||||
add_attribute(&mut schema, NamespacedKeyword::new("foo", "baz"), 98, Attribute {
|
add_attribute(&mut schema, Keyword::namespaced("foo", "baz"), 98, Attribute {
|
||||||
index: true,
|
index: true,
|
||||||
value_type: ValueType::Long,
|
value_type: ValueType::Long,
|
||||||
fulltext: false,
|
fulltext: false,
|
||||||
|
@ -384,7 +384,7 @@ mod test {
|
||||||
no_history: false,
|
no_history: false,
|
||||||
});
|
});
|
||||||
// attribue is unique by identity and an index
|
// attribue is unique by identity and an index
|
||||||
add_attribute(&mut schema, NamespacedKeyword::new("foo", "bat"), 99, Attribute {
|
add_attribute(&mut schema, Keyword::namespaced("foo", "bat"), 99, Attribute {
|
||||||
index: true,
|
index: true,
|
||||||
value_type: ValueType::Ref,
|
value_type: ValueType::Ref,
|
||||||
fulltext: false,
|
fulltext: false,
|
||||||
|
@ -394,7 +394,7 @@ mod test {
|
||||||
no_history: false,
|
no_history: false,
|
||||||
});
|
});
|
||||||
// attribute is a components and a `Ref`
|
// attribute is a components and a `Ref`
|
||||||
add_attribute(&mut schema, NamespacedKeyword::new("foo", "bak"), 100, Attribute {
|
add_attribute(&mut schema, Keyword::namespaced("foo", "bak"), 100, Attribute {
|
||||||
index: false,
|
index: false,
|
||||||
value_type: ValueType::Ref,
|
value_type: ValueType::Ref,
|
||||||
fulltext: false,
|
fulltext: false,
|
||||||
|
@ -404,7 +404,7 @@ mod test {
|
||||||
no_history: false,
|
no_history: false,
|
||||||
});
|
});
|
||||||
// fulltext attribute is a string and an index
|
// fulltext attribute is a string and an index
|
||||||
add_attribute(&mut schema, NamespacedKeyword::new("foo", "bap"), 101, Attribute {
|
add_attribute(&mut schema, Keyword::namespaced("foo", "bap"), 101, Attribute {
|
||||||
index: true,
|
index: true,
|
||||||
value_type: ValueType::String,
|
value_type: ValueType::String,
|
||||||
fulltext: true,
|
fulltext: true,
|
||||||
|
@ -421,7 +421,7 @@ mod test {
|
||||||
fn invalid_schema_unique_value_not_index() {
|
fn invalid_schema_unique_value_not_index() {
|
||||||
let mut schema = Schema::default();
|
let mut schema = Schema::default();
|
||||||
// attribute unique by value but not index
|
// attribute unique by value but not index
|
||||||
let ident = NamespacedKeyword::new("foo", "bar");
|
let ident = Keyword::namespaced("foo", "bar");
|
||||||
add_attribute(&mut schema, ident , 99, Attribute {
|
add_attribute(&mut schema, ident , 99, Attribute {
|
||||||
index: false,
|
index: false,
|
||||||
value_type: ValueType::Boolean,
|
value_type: ValueType::Boolean,
|
||||||
|
@ -445,7 +445,7 @@ mod test {
|
||||||
fn invalid_schema_unique_identity_not_index() {
|
fn invalid_schema_unique_identity_not_index() {
|
||||||
let mut schema = Schema::default();
|
let mut schema = Schema::default();
|
||||||
// attribute is unique by identity but not index
|
// attribute is unique by identity but not index
|
||||||
add_attribute(&mut schema, NamespacedKeyword::new("foo", "bar"), 99, Attribute {
|
add_attribute(&mut schema, Keyword::namespaced("foo", "bar"), 99, Attribute {
|
||||||
index: false,
|
index: false,
|
||||||
value_type: ValueType::Long,
|
value_type: ValueType::Long,
|
||||||
fulltext: false,
|
fulltext: false,
|
||||||
|
@ -468,7 +468,7 @@ mod test {
|
||||||
fn invalid_schema_component_not_ref() {
|
fn invalid_schema_component_not_ref() {
|
||||||
let mut schema = Schema::default();
|
let mut schema = Schema::default();
|
||||||
// attribute that is a component is not a `Ref`
|
// attribute that is a component is not a `Ref`
|
||||||
add_attribute(&mut schema, NamespacedKeyword::new("foo", "bar"), 99, Attribute {
|
add_attribute(&mut schema, Keyword::namespaced("foo", "bar"), 99, Attribute {
|
||||||
index: false,
|
index: false,
|
||||||
value_type: ValueType::Boolean,
|
value_type: ValueType::Boolean,
|
||||||
fulltext: false,
|
fulltext: false,
|
||||||
|
@ -491,7 +491,7 @@ mod test {
|
||||||
fn invalid_schema_fulltext_not_index() {
|
fn invalid_schema_fulltext_not_index() {
|
||||||
let mut schema = Schema::default();
|
let mut schema = Schema::default();
|
||||||
// attribute that is fulltext is not an index
|
// attribute that is fulltext is not an index
|
||||||
add_attribute(&mut schema, NamespacedKeyword::new("foo", "bar"), 99, Attribute {
|
add_attribute(&mut schema, Keyword::namespaced("foo", "bar"), 99, Attribute {
|
||||||
index: false,
|
index: false,
|
||||||
value_type: ValueType::String,
|
value_type: ValueType::String,
|
||||||
fulltext: true,
|
fulltext: true,
|
||||||
|
@ -513,7 +513,7 @@ mod test {
|
||||||
fn invalid_schema_fulltext_index_not_string() {
|
fn invalid_schema_fulltext_index_not_string() {
|
||||||
let mut schema = Schema::default();
|
let mut schema = Schema::default();
|
||||||
// attribute that is fulltext and not a `String`
|
// attribute that is fulltext and not a `String`
|
||||||
add_attribute(&mut schema, NamespacedKeyword::new("foo", "bar"), 99, Attribute {
|
add_attribute(&mut schema, Keyword::namespaced("foo", "bar"), 99, Attribute {
|
||||||
index: true,
|
index: true,
|
||||||
value_type: ValueType::Long,
|
value_type: ValueType::Long,
|
||||||
fulltext: true,
|
fulltext: true,
|
||||||
|
|
|
@ -64,7 +64,7 @@ use db::{
|
||||||
PartitionMapping,
|
PartitionMapping,
|
||||||
};
|
};
|
||||||
use edn::{
|
use edn::{
|
||||||
NamespacedKeyword,
|
Keyword,
|
||||||
};
|
};
|
||||||
use entids;
|
use entids;
|
||||||
use errors;
|
use errors;
|
||||||
|
@ -165,7 +165,7 @@ pub struct Tx<'conn, 'a, W> where W: TransactWatcher {
|
||||||
/// something suitable for the entity position rather than something suitable for a value position.
|
/// something suitable for the entity position rather than something suitable for a value position.
|
||||||
pub fn remove_db_id(map: &mut entmod::MapNotation) -> Result<Option<entmod::EntidOrLookupRefOrTempId>> {
|
pub fn remove_db_id(map: &mut entmod::MapNotation) -> Result<Option<entmod::EntidOrLookupRefOrTempId>> {
|
||||||
// TODO: extract lazy defined constant.
|
// TODO: extract lazy defined constant.
|
||||||
let db_id_key = entmod::Entid::Ident(NamespacedKeyword::new("db", "id"));
|
let db_id_key = entmod::Entid::Ident(Keyword::namespaced("db", "id"));
|
||||||
|
|
||||||
let db_id: Option<entmod::EntidOrLookupRefOrTempId> = if let Some(id) = map.remove(&db_id_key) {
|
let db_id: Option<entmod::EntidOrLookupRefOrTempId> = if let Some(id) = map.remove(&db_id_key) {
|
||||||
match id {
|
match id {
|
||||||
|
@ -281,7 +281,7 @@ impl<'conn, 'a, W> Tx<'conn, 'a, W> where W: TransactWatcher {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ensure_ident_exists(&self, e: &NamespacedKeyword) -> Result<KnownEntid> {
|
fn ensure_ident_exists(&self, e: &Keyword) -> Result<KnownEntid> {
|
||||||
self.schema.require_entid(e)
|
self.schema.require_entid(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,5 +54,5 @@ fn test_to_edn_value_pair() {
|
||||||
assert_eq!(TypedValue::Double(OrderedFloat(0.5)).to_edn_value_pair(), (edn::Value::Float(OrderedFloat(0.5)), ValueType::Double));
|
assert_eq!(TypedValue::Double(OrderedFloat(0.5)).to_edn_value_pair(), (edn::Value::Float(OrderedFloat(0.5)), ValueType::Double));
|
||||||
|
|
||||||
assert_eq!(TypedValue::typed_string(":db/keyword").to_edn_value_pair(), (edn::Value::Text(":db/keyword".into()), ValueType::String));
|
assert_eq!(TypedValue::typed_string(":db/keyword").to_edn_value_pair(), (edn::Value::Text(":db/keyword".into()), ValueType::String));
|
||||||
assert_eq!(TypedValue::typed_ns_keyword("db", "keyword").to_edn_value_pair(), (edn::Value::NamespacedKeyword(symbols::NamespacedKeyword::new("db", "keyword")), ValueType::Keyword));
|
assert_eq!(TypedValue::typed_ns_keyword("db", "keyword").to_edn_value_pair(), (edn::Value::Keyword(symbols::Keyword::namespaced("db", "keyword")), ValueType::Keyword));
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,10 @@ uuid = { version = "0.5", features = ["v4", "serde"] }
|
||||||
serde = { version = "1.0", optional = true }
|
serde = { version = "1.0", optional = true }
|
||||||
serde_derive = { version = "1.0", optional = true }
|
serde_derive = { version = "1.0", optional = true }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
serde_test = "1.0"
|
||||||
|
serde_json = "1.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
serde_support = ["serde", "serde_derive"]
|
serde_support = ["serde", "serde_derive"]
|
||||||
|
|
||||||
|
|
|
@ -203,13 +203,13 @@ pub op -> OpType
|
||||||
= ":db/add" { OpType::Add }
|
= ":db/add" { OpType::Add }
|
||||||
/ ":db/retract" { OpType::Retract }
|
/ ":db/retract" { OpType::Retract }
|
||||||
|
|
||||||
raw_keyword -> NamespacedKeyword
|
raw_keyword -> Keyword
|
||||||
= keyword_prefix ns:$(symbol_namespace) namespace_separator n:$(symbol_name) { NamespacedKeyword::new(ns, n) }
|
= keyword_prefix ns:$(symbol_namespace) namespace_separator n:$(symbol_name) { Keyword::namespaced(ns, n) }
|
||||||
|
|
||||||
raw_forward_keyword -> NamespacedKeyword
|
raw_forward_keyword -> Keyword
|
||||||
= v:raw_keyword {? if v.is_forward() { Ok(v) } else { Err("expected :forward/keyword") } }
|
= v:raw_keyword {? if v.is_forward() { Ok(v) } else { Err("expected :forward/keyword") } }
|
||||||
|
|
||||||
raw_backward_keyword -> NamespacedKeyword
|
raw_backward_keyword -> Keyword
|
||||||
= v:raw_keyword {? if v.is_backward() { Ok(v) } else { Err("expected :backward/_keyword") } }
|
= v:raw_keyword {? if v.is_backward() { Ok(v) } else { Err("expected :backward/_keyword") } }
|
||||||
|
|
||||||
entid -> Entid
|
entid -> Entid
|
||||||
|
@ -227,7 +227,7 @@ lookup_ref -> LookupRef
|
||||||
= "(" __ "lookup-ref" __ a:(entid) __ v:(value) __ ")" { LookupRef { a, v: v.without_spans() } }
|
= "(" __ "lookup-ref" __ a:(entid) __ v:(value) __ ")" { LookupRef { a, v: v.without_spans() } }
|
||||||
|
|
||||||
tx_function -> TxFunction
|
tx_function -> TxFunction
|
||||||
= "(" __ n:$(symbol_name) __ ")" { TxFunction { op: PlainSymbol::new(n) } }
|
= "(" __ n:$(symbol_name) __ ")" { TxFunction { op: PlainSymbol::plain(n) } }
|
||||||
|
|
||||||
entity_place -> EntidOrLookupRefOrTempId
|
entity_place -> EntidOrLookupRefOrTempId
|
||||||
= v:raw_text { EntidOrLookupRefOrTempId::TempId(TempId::External(v)) }
|
= v:raw_text { EntidOrLookupRefOrTempId::TempId(TempId::External(v)) }
|
||||||
|
|
|
@ -14,7 +14,7 @@ use std::collections::BTreeMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use symbols::{
|
use symbols::{
|
||||||
NamespacedKeyword,
|
Keyword,
|
||||||
PlainSymbol,
|
PlainSymbol,
|
||||||
};
|
};
|
||||||
use types::{
|
use types::{
|
||||||
|
@ -51,7 +51,7 @@ impl fmt::Display for TempId {
|
||||||
#[derive(Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)]
|
#[derive(Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)]
|
||||||
pub enum Entid {
|
pub enum Entid {
|
||||||
Entid(i64),
|
Entid(i64),
|
||||||
Ident(NamespacedKeyword),
|
Ident(Keyword),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Entid {
|
impl Entid {
|
||||||
|
|
|
@ -23,6 +23,8 @@ extern crate serde;
|
||||||
extern crate serde_derive;
|
extern crate serde_derive;
|
||||||
|
|
||||||
pub mod entities;
|
pub mod entities;
|
||||||
|
// Intentionally not pub.
|
||||||
|
mod namespaceable_name;
|
||||||
pub mod symbols;
|
pub mod symbols;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
pub mod pretty_print;
|
pub mod pretty_print;
|
||||||
|
@ -53,7 +55,6 @@ pub use types::{
|
||||||
|
|
||||||
pub use symbols::{
|
pub use symbols::{
|
||||||
Keyword,
|
Keyword,
|
||||||
NamespacedKeyword,
|
|
||||||
NamespacedSymbol,
|
NamespacedSymbol,
|
||||||
PlainSymbol,
|
PlainSymbol,
|
||||||
};
|
};
|
||||||
|
|
285
edn/src/namespaceable_name.rs
Normal file
285
edn/src/namespaceable_name.rs
Normal file
|
@ -0,0 +1,285 @@
|
||||||
|
// Copyright 2018 Mozilla
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||||
|
// this file except in compliance with the License. You may obtain a copy of the
|
||||||
|
// License at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
|
use std::cmp::{
|
||||||
|
Ord,
|
||||||
|
Ordering,
|
||||||
|
PartialOrd,
|
||||||
|
};
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
#[cfg(feature = "serde_support")]
|
||||||
|
use serde::{
|
||||||
|
de::{self, Deserialize, Deserializer},
|
||||||
|
ser::{Serialize, Serializer}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Data storage for both NamespaceableKeyword and NamespaceableSymbol.
|
||||||
|
#[derive(Clone, Eq, Hash, PartialEq)]
|
||||||
|
pub struct NamespaceableName {
|
||||||
|
// The bytes that make up the namespace followed directly by those
|
||||||
|
// that make up the name.
|
||||||
|
components: String,
|
||||||
|
|
||||||
|
// The index (in bytes) into `components` where the namespace ends and
|
||||||
|
// name begins.
|
||||||
|
//
|
||||||
|
// If this is zero, it means that this is _not_ a namespaced value!
|
||||||
|
//
|
||||||
|
// Important: The following invariants around `boundary` must be maintained
|
||||||
|
// for memory safety.
|
||||||
|
//
|
||||||
|
// 1. `boundary` must always be less than or equal to `components.len()`.
|
||||||
|
// 2. `boundary` must be byte index that points to a character boundary,
|
||||||
|
// and not point into the middle of a utf8 codepoint. That is,
|
||||||
|
// `components.is_char_boundary(boundary)` must always be true.
|
||||||
|
//
|
||||||
|
// These invariants are enforced by `NamespaceableName::namespaced()`, and since
|
||||||
|
// we never mutate `NamespaceableName`s, that's the only place we need to
|
||||||
|
// worry about them.
|
||||||
|
boundary: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NamespaceableName {
|
||||||
|
#[inline]
|
||||||
|
pub fn plain<T>(name: T) -> Self where T: Into<String> {
|
||||||
|
let n = name.into();
|
||||||
|
assert!(!n.is_empty(), "Symbols and keywords cannot be unnamed.");
|
||||||
|
|
||||||
|
NamespaceableName {
|
||||||
|
components: n,
|
||||||
|
boundary: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn namespaced<N, T>(namespace: N, name: T) -> Self where N: AsRef<str>, T: AsRef<str> {
|
||||||
|
let n = name.as_ref();
|
||||||
|
let ns = namespace.as_ref();
|
||||||
|
|
||||||
|
// Note: These invariants are not required for safety. That is, if we
|
||||||
|
// decide to allow these we can safely remove them.
|
||||||
|
assert!(!n.is_empty(), "Symbols and keywords cannot be unnamed.");
|
||||||
|
assert!(!ns.is_empty(), "Symbols and keywords cannot have an empty non-null namespace.");
|
||||||
|
|
||||||
|
let mut dest = String::with_capacity(n.len() + ns.len());
|
||||||
|
|
||||||
|
dest.push_str(ns);
|
||||||
|
dest.push_str(n);
|
||||||
|
|
||||||
|
let boundary = ns.len();
|
||||||
|
|
||||||
|
NamespaceableName {
|
||||||
|
components: dest,
|
||||||
|
boundary: boundary,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dwim<N, T>(namespace: Option<N>, name: T) -> Self where N: AsRef<str>, T: AsRef<str> {
|
||||||
|
if let Some(ns) = namespace {
|
||||||
|
Self::namespaced(ns, name)
|
||||||
|
} else {
|
||||||
|
Self::plain(name.as_ref())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_namespaced(&self) -> bool {
|
||||||
|
self.boundary > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn is_backward(&self) -> bool {
|
||||||
|
self.name().starts_with('_')
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn is_forward(&self) -> bool {
|
||||||
|
!self.is_backward()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_reversed(&self) -> NamespaceableName {
|
||||||
|
let name = self.name();
|
||||||
|
|
||||||
|
if name.starts_with('_') {
|
||||||
|
Self::dwim(self.namespace(), &name[1..])
|
||||||
|
} else {
|
||||||
|
Self::dwim(self.namespace(), &format!("_{}", name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn namespace(&self) -> Option<&str> {
|
||||||
|
if self.boundary > 0 {
|
||||||
|
Some(&self.components[0..self.boundary])
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn name(&self) -> &str {
|
||||||
|
if self.boundary == 0 {
|
||||||
|
&self.components
|
||||||
|
} else {
|
||||||
|
&self.components[self.boundary..]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn components<'a>(&'a self) -> (&'a str, &'a str) {
|
||||||
|
self.components.split_at(self.boundary)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We order by namespace then by name.
|
||||||
|
// Non-namespaced values always sort before.
|
||||||
|
impl PartialOrd for NamespaceableName {
|
||||||
|
fn partial_cmp(&self, other: &NamespaceableName) -> Option<Ordering> {
|
||||||
|
match (self.boundary, other.boundary) {
|
||||||
|
(0, 0) => self.components.partial_cmp(&other.components),
|
||||||
|
(0, _) => Some(Ordering::Less),
|
||||||
|
(_, 0) => Some(Ordering::Greater),
|
||||||
|
(_, _) => {
|
||||||
|
// Just use a lexicographic ordering.
|
||||||
|
self.components().partial_cmp(&other.components())
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ord for NamespaceableName {
|
||||||
|
fn cmp(&self, other: &NamespaceableName) -> Ordering {
|
||||||
|
self.components().cmp(&other.components())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We could derive this, but it's really hard to make sense of as-is.
|
||||||
|
impl fmt::Debug for NamespaceableName {
|
||||||
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
fmt.debug_struct("NamespaceableName")
|
||||||
|
.field("namespace", &self.namespace())
|
||||||
|
.field("name", &self.name())
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is convoluted, but the basic idea is that since we don't want to rely on our input being
|
||||||
|
// correct, we'll need to implement a custom serializer no matter what (e.g. we can't just
|
||||||
|
// `derive(Deserialize)` since `unsafe` code depends on `self.boundary` being a valid index).
|
||||||
|
//
|
||||||
|
// We'd also like for users consuming our serialized data as e.g. JSON not to have to learn how we
|
||||||
|
// store NamespaceableName internally, since it's very much an implementation detail.
|
||||||
|
//
|
||||||
|
// We achieve both of these by implemeting a type that can serialize in way that's both user-
|
||||||
|
// friendly and automatic (e.g. `derive`d), and just pass all work off to it in our custom
|
||||||
|
// implementation of Serialize and Deserialize.
|
||||||
|
#[cfg(feature = "serde_support")]
|
||||||
|
#[cfg_attr(feature = "serde_support", serde(rename = "NamespaceableName"))]
|
||||||
|
#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
|
||||||
|
struct SerializedNamespaceableName<'a> {
|
||||||
|
namespace: Option<&'a str>,
|
||||||
|
name: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "serde_support")]
|
||||||
|
impl<'de> Deserialize<'de> for NamespaceableName {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
|
||||||
|
let separated = SerializedNamespaceableName::deserialize(deserializer)?;
|
||||||
|
if separated.name.len() == 0 {
|
||||||
|
return Err(de::Error::custom("Empty name in keyword or symbol"));
|
||||||
|
}
|
||||||
|
if let Some(ns) = separated.namespace {
|
||||||
|
if ns.len() == 0 {
|
||||||
|
Err(de::Error::custom("Empty but present namespace in keyword or symbol"))
|
||||||
|
} else {
|
||||||
|
Ok(NamespaceableName::namespaced(ns, separated.name))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok(NamespaceableName::plain(separated.name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "serde_support")]
|
||||||
|
impl Serialize for NamespaceableName {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
|
||||||
|
let ser = SerializedNamespaceableName {
|
||||||
|
namespace: self.namespace(),
|
||||||
|
name: self.name(),
|
||||||
|
};
|
||||||
|
ser.serialize(serializer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
use std::panic;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_new_invariants_maintained() {
|
||||||
|
assert!(panic::catch_unwind(|| NamespaceableName::namespaced("", "foo")).is_err(),
|
||||||
|
"Empty namespace should panic");
|
||||||
|
assert!(panic::catch_unwind(|| NamespaceableName::namespaced("foo", "")).is_err(),
|
||||||
|
"Empty name should panic");
|
||||||
|
assert!(panic::catch_unwind(|| NamespaceableName::namespaced("", "")).is_err(),
|
||||||
|
"Should panic if both fields are empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_basic() {
|
||||||
|
let s = NamespaceableName::namespaced("aaaaa", "b");
|
||||||
|
assert_eq!(s.namespace(), Some("aaaaa"));
|
||||||
|
assert_eq!(s.name(), "b");
|
||||||
|
assert_eq!(s.components(), ("aaaaa", "b"));
|
||||||
|
|
||||||
|
let s = NamespaceableName::namespaced("b", "aaaaa");
|
||||||
|
assert_eq!(s.namespace(), Some("b"));
|
||||||
|
assert_eq!(s.name(), "aaaaa");
|
||||||
|
assert_eq!(s.components(), ("b", "aaaaa"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_order() {
|
||||||
|
let n0 = NamespaceableName::namespaced("a", "aa");
|
||||||
|
let n1 = NamespaceableName::namespaced("aa", "a");
|
||||||
|
|
||||||
|
let n2 = NamespaceableName::namespaced("a", "ab");
|
||||||
|
let n3 = NamespaceableName::namespaced("aa", "b");
|
||||||
|
|
||||||
|
let n4 = NamespaceableName::namespaced("b", "ab");
|
||||||
|
let n5 = NamespaceableName::namespaced("ba", "b");
|
||||||
|
|
||||||
|
let n6 = NamespaceableName::namespaced("z", "zz");
|
||||||
|
|
||||||
|
let mut arr = [
|
||||||
|
n5.clone(),
|
||||||
|
n6.clone(),
|
||||||
|
n0.clone(),
|
||||||
|
n3.clone(),
|
||||||
|
n2.clone(),
|
||||||
|
n1.clone(),
|
||||||
|
n4.clone()
|
||||||
|
];
|
||||||
|
|
||||||
|
arr.sort();
|
||||||
|
|
||||||
|
assert_eq!(arr, [
|
||||||
|
n0.clone(),
|
||||||
|
n2.clone(),
|
||||||
|
n1.clone(),
|
||||||
|
n3.clone(),
|
||||||
|
n4.clone(),
|
||||||
|
n5.clone(),
|
||||||
|
n6.clone(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -68,10 +68,9 @@ impl Value {
|
||||||
.append(pp.text("}"))
|
.append(pp.text("}"))
|
||||||
.group()
|
.group()
|
||||||
}
|
}
|
||||||
Value::NamespacedSymbol(ref v) => pp.text(v.namespace.as_ref()).append("/").append(v.name.as_ref()),
|
Value::NamespacedSymbol(ref v) => pp.text(v.namespace()).append("/").append(v.name()),
|
||||||
Value::PlainSymbol(ref v) => pp.text(v.0.as_ref()),
|
Value::PlainSymbol(ref v) => pp.text(v.to_string()),
|
||||||
Value::NamespacedKeyword(ref v) => pp.text(":").append(v.namespace.as_ref()).append("/").append(v.name.as_ref()),
|
Value::Keyword(ref v) => pp.text(v.to_string()),
|
||||||
Value::Keyword(ref v) => pp.text(":").append(v.0.as_ref()),
|
|
||||||
Value::Text(ref v) => pp.text("\"").append(v.as_ref()).append("\""),
|
Value::Text(ref v) => pp.text("\"").append(v.as_ref()).append("\""),
|
||||||
Value::Uuid(ref u) => pp.text("#uuid \"").append(u.hyphenated().to_string()).append("\""),
|
Value::Uuid(ref u) => pp.text("#uuid \"").append(u.hyphenated().to_string()).append("\""),
|
||||||
Value::Instant(ref v) => pp.text("#inst \"").append(v.to_rfc3339_opts(SecondsFormat::AutoSi, true)).append("\""),
|
Value::Instant(ref v) => pp.text("#inst \"").append(v.to_rfc3339_opts(SecondsFormat::AutoSi, true)).append("\""),
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 Mozilla
|
// Copyright 2018 Mozilla
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||||
// this file except in compliance with the License. You may obtain a copy of the
|
// this file except in compliance with the License. You may obtain a copy of the
|
||||||
|
@ -9,11 +9,12 @@
|
||||||
// specific language governing permissions and limitations under the License.
|
// specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
|
use namespaceable_name::NamespaceableName;
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! ns_keyword {
|
macro_rules! ns_keyword {
|
||||||
($ns: expr, $name: expr) => {{
|
($ns: expr, $name: expr) => {{
|
||||||
$crate::NamespacedKeyword::new($ns, $name)
|
$crate::Keyword::namespaced($ns, $name)
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,12 +23,7 @@ macro_rules! ns_keyword {
|
||||||
pub struct PlainSymbol(pub String);
|
pub struct PlainSymbol(pub String);
|
||||||
|
|
||||||
#[derive(Clone,Debug,Eq,Hash,Ord,PartialOrd,PartialEq)]
|
#[derive(Clone,Debug,Eq,Hash,Ord,PartialOrd,PartialEq)]
|
||||||
pub struct NamespacedSymbol {
|
pub struct NamespacedSymbol(NamespaceableName);
|
||||||
// We derive PartialOrd, which implements a lexicographic based
|
|
||||||
// on the order of members, so put namespace first.
|
|
||||||
pub namespace: String,
|
|
||||||
pub name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A keyword is a symbol, optionally with a namespace, that prints with a leading colon.
|
/// A keyword is a symbol, optionally with a namespace, that prints with a leading colon.
|
||||||
/// This concept is imported from Clojure, as it features in EDN and the query
|
/// This concept is imported from Clojure, as it features in EDN and the query
|
||||||
|
@ -50,12 +46,12 @@ pub struct NamespacedSymbol {
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use edn::symbols::Keyword;
|
/// # use edn::symbols::Keyword;
|
||||||
/// # use edn::symbols::NamespacedKeyword;
|
/// let bar = Keyword::plain("bar"); // :bar
|
||||||
/// let bar = Keyword::new("bar"); // :bar
|
/// let foo_bar = Keyword::namespaced("foo", "bar"); // :foo/bar
|
||||||
/// let foo_bar = NamespacedKeyword::new("foo", "bar"); // :foo/bar
|
/// assert_eq!("bar", bar.name());
|
||||||
/// assert_eq!("bar", bar.0);
|
/// assert_eq!(None, bar.namespace());
|
||||||
/// assert_eq!("bar", foo_bar.name);
|
/// assert_eq!("bar", foo_bar.name());
|
||||||
/// assert_eq!("foo", foo_bar.namespace);
|
/// assert_eq!(Some("foo"), foo_bar.namespace());
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// If you're not sure whether your input is well-formed, you should use a
|
/// If you're not sure whether your input is well-formed, you should use a
|
||||||
|
@ -66,20 +62,12 @@ pub struct NamespacedSymbol {
|
||||||
///
|
///
|
||||||
/// Future: fast equality (interning?) for keywords.
|
/// Future: fast equality (interning?) for keywords.
|
||||||
///
|
///
|
||||||
#[derive(Clone,Debug,Eq,Hash,Ord,PartialOrd,PartialEq)]
|
|
||||||
pub struct Keyword(pub String);
|
|
||||||
|
|
||||||
#[derive(Clone,Debug,Eq,Hash,Ord,PartialOrd,PartialEq)]
|
#[derive(Clone,Debug,Eq,Hash,Ord,PartialOrd,PartialEq)]
|
||||||
#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
|
||||||
pub struct NamespacedKeyword {
|
pub struct Keyword(NamespaceableName);
|
||||||
// We derive PartialOrd, which implements a lexicographic order based
|
|
||||||
// on the order of members, so put namespace first.
|
|
||||||
pub namespace: String,
|
|
||||||
pub name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PlainSymbol {
|
impl PlainSymbol {
|
||||||
pub fn new<T>(name: T) -> Self where T: Into<String> {
|
pub fn plain<T>(name: T) -> Self where T: Into<String> {
|
||||||
let n = name.into();
|
let n = name.into();
|
||||||
assert!(!n.is_empty(), "Symbols cannot be unnamed.");
|
assert!(!n.is_empty(), "Symbols cannot be unnamed.");
|
||||||
|
|
||||||
|
@ -90,11 +78,11 @@ impl PlainSymbol {
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use edn::symbols::PlainSymbol;
|
/// # use edn::symbols::PlainSymbol;
|
||||||
/// assert_eq!("foo", PlainSymbol::new("?foo").plain_name());
|
/// assert_eq!("foo", PlainSymbol::plain("?foo").name());
|
||||||
/// assert_eq!("foo", PlainSymbol::new("$foo").plain_name());
|
/// assert_eq!("foo", PlainSymbol::plain("$foo").name());
|
||||||
/// assert_eq!("!foo", PlainSymbol::new("!foo").plain_name());
|
/// assert_eq!("!foo", PlainSymbol::plain("!foo").name());
|
||||||
/// ```
|
/// ```
|
||||||
pub fn plain_name(&self) -> &str {
|
pub fn name(&self) -> &str {
|
||||||
if self.is_src_symbol() || self.is_var_symbol() {
|
if self.is_src_symbol() || self.is_var_symbol() {
|
||||||
&self.0[1..]
|
&self.0[1..]
|
||||||
} else {
|
} else {
|
||||||
|
@ -114,52 +102,68 @@ impl PlainSymbol {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NamespacedSymbol {
|
impl NamespacedSymbol {
|
||||||
pub fn new<T>(namespace: T, name: T) -> Self where T: Into<String> {
|
pub fn namespaced<N, T>(namespace: N, name: T) -> Self where N: AsRef<str>, T: AsRef<str> {
|
||||||
let n = name.into();
|
let r = namespace.as_ref();
|
||||||
let ns = namespace.into();
|
assert!(!r.is_empty(), "Namespaced symbols cannot have an empty non-null namespace.");
|
||||||
|
NamespacedSymbol(NamespaceableName::namespaced(r, name))
|
||||||
|
}
|
||||||
|
|
||||||
assert!(!n.is_empty(), "Symbols cannot be unnamed.");
|
#[inline]
|
||||||
assert!(!ns.is_empty(), "Symbols cannot have an empty non-null namespace.");
|
pub fn name(&self) -> &str {
|
||||||
|
self.0.name()
|
||||||
|
}
|
||||||
|
|
||||||
NamespacedSymbol { name: n, namespace: ns }
|
#[inline]
|
||||||
|
pub fn namespace(&self) -> &str {
|
||||||
|
self.0.namespace().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn components<'a>(&'a self) -> (&'a str, &'a str) {
|
||||||
|
self.0.components()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Keyword {
|
impl Keyword {
|
||||||
pub fn new<T>(name: T) -> Self where T: Into<String> {
|
pub fn plain<T>(name: T) -> Self where T: Into<String> {
|
||||||
let n = name.into();
|
Keyword(NamespaceableName::plain(name))
|
||||||
assert!(!n.is_empty(), "Keywords cannot be unnamed.");
|
|
||||||
|
|
||||||
Keyword(n)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NamespacedKeyword {
|
impl Keyword {
|
||||||
/// Creates a new `NamespacedKeyword`.
|
/// Creates a new `Keyword`.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use edn::symbols::NamespacedKeyword;
|
/// # use edn::symbols::Keyword;
|
||||||
/// let keyword = NamespacedKeyword::new("foo", "bar");
|
/// let keyword = Keyword::namespaced("foo", "bar");
|
||||||
/// assert_eq!(keyword.to_string(), ":foo/bar");
|
/// assert_eq!(keyword.to_string(), ":foo/bar");
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// See also the `kw!` macro in the main `mentat` crate.
|
/// See also the `kw!` macro in the main `mentat` crate.
|
||||||
pub fn new<T>(namespace: T, name: T) -> Self where T: Into<String> {
|
pub fn namespaced<N, T>(namespace: N, name: T) -> Self where N: AsRef<str>, T: AsRef<str> {
|
||||||
let n = name.into();
|
let r = namespace.as_ref();
|
||||||
let ns = namespace.into();
|
assert!(!r.is_empty(), "Namespaced keywords cannot have an empty non-null namespace.");
|
||||||
assert!(!n.is_empty(), "Keywords cannot be unnamed.");
|
Keyword(NamespaceableName::namespaced(r, name))
|
||||||
assert!(!ns.is_empty(), "Keywords cannot have an empty non-null namespace.");
|
|
||||||
|
|
||||||
// TODO: debug asserts to ensure that neither field matches [ :/].
|
|
||||||
NamespacedKeyword {
|
|
||||||
name: n,
|
|
||||||
namespace: ns,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether this `NamespacedKeyword` should be interpreted in reverse order. For example,
|
#[inline]
|
||||||
|
pub fn name(&self) -> &str {
|
||||||
|
self.0.name()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn namespace(&self) -> Option<&str> {
|
||||||
|
self.0.namespace()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn components<'a>(&'a self) -> (&'a str, &'a str) {
|
||||||
|
self.0.components()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Whether this `Keyword` should be interpreted in reverse order. For example,
|
||||||
/// the two following snippets are identical:
|
/// the two following snippets are identical:
|
||||||
///
|
///
|
||||||
/// ```edn
|
/// ```edn
|
||||||
|
@ -173,38 +177,46 @@ impl NamespacedKeyword {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use edn::symbols::NamespacedKeyword;
|
/// # use edn::symbols::Keyword;
|
||||||
/// assert!(!NamespacedKeyword::new("foo", "bar").is_backward());
|
/// assert!(!Keyword::namespaced("foo", "bar").is_backward());
|
||||||
/// assert!(NamespacedKeyword::new("foo", "_bar").is_backward());
|
/// assert!(Keyword::namespaced("foo", "_bar").is_backward());
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_backward(&self) -> bool {
|
pub fn is_backward(&self) -> bool {
|
||||||
self.name.starts_with('_')
|
self.0.is_backward()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether this `NamespacedKeyword` should be interpreted in forward order.
|
/// Whether this `Keyword` should be interpreted in forward order.
|
||||||
/// See `symbols::NamespacedKeyword::is_backward`.
|
/// See `symbols::Keyword::is_backward`.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use edn::symbols::NamespacedKeyword;
|
/// # use edn::symbols::Keyword;
|
||||||
/// assert!(NamespacedKeyword::new("foo", "bar").is_forward());
|
/// assert!(Keyword::namespaced("foo", "bar").is_forward());
|
||||||
/// assert!(!NamespacedKeyword::new("foo", "_bar").is_forward());
|
/// assert!(!Keyword::namespaced("foo", "_bar").is_forward());
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_forward(&self) -> bool {
|
pub fn is_forward(&self) -> bool {
|
||||||
!self.is_backward()
|
self.0.is_forward()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a `NamespacedKeyword` with the same namespace and a
|
#[inline]
|
||||||
/// 'backward' name. See `symbols::NamespacedKeyword::is_backward`.
|
pub fn is_namespaced(&self) -> bool {
|
||||||
|
self.0.is_namespaced()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a `Keyword` with the same namespace and a
|
||||||
|
/// 'backward' name. See `symbols::Keyword::is_backward`.
|
||||||
|
///
|
||||||
|
/// Returns a forward name if passed a reversed keyword; i.e., this
|
||||||
|
/// function is its own inverse.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use edn::symbols::NamespacedKeyword;
|
/// # use edn::symbols::Keyword;
|
||||||
/// let nsk = NamespacedKeyword::new("foo", "bar");
|
/// let nsk = Keyword::namespaced("foo", "bar");
|
||||||
/// assert!(!nsk.is_backward());
|
/// assert!(!nsk.is_backward());
|
||||||
/// assert_eq!(":foo/bar", nsk.to_string());
|
/// assert_eq!(":foo/bar", nsk.to_string());
|
||||||
///
|
///
|
||||||
|
@ -212,38 +224,26 @@ impl NamespacedKeyword {
|
||||||
/// assert!(reversed.is_backward());
|
/// assert!(reversed.is_backward());
|
||||||
/// assert_eq!(":foo/_bar", reversed.to_string());
|
/// assert_eq!(":foo/_bar", reversed.to_string());
|
||||||
/// ```
|
/// ```
|
||||||
pub fn to_reversed(&self) -> NamespacedKeyword {
|
pub fn to_reversed(&self) -> Keyword {
|
||||||
let name = if self.is_backward() {
|
Keyword(self.0.to_reversed())
|
||||||
self.name[1..].to_string()
|
|
||||||
} else {
|
|
||||||
format!("{}{}", "_", self.name)
|
|
||||||
};
|
|
||||||
|
|
||||||
NamespacedKeyword {
|
|
||||||
name: name,
|
|
||||||
namespace: self.namespace.clone(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If this `NamespacedKeyword` is 'backward' (see `symbols::NamespacedKeyword::is_backward`),
|
/// If this `Keyword` is 'backward' (see `symbols::Keyword::is_backward`),
|
||||||
/// return `Some('forward name')`; otherwise, return `None`.
|
/// return `Some('forward name')`; otherwise, return `None`.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use edn::symbols::NamespacedKeyword;
|
/// # use edn::symbols::Keyword;
|
||||||
/// let nsk = NamespacedKeyword::new("foo", "bar");
|
/// let nsk = Keyword::namespaced("foo", "bar");
|
||||||
/// assert_eq!(None, nsk.unreversed());
|
/// assert_eq!(None, nsk.unreversed());
|
||||||
///
|
///
|
||||||
/// let reversed = nsk.to_reversed();
|
/// let reversed = nsk.to_reversed();
|
||||||
/// assert_eq!(Some(nsk), reversed.unreversed());
|
/// assert_eq!(Some(nsk), reversed.unreversed());
|
||||||
/// ```
|
/// ```
|
||||||
pub fn unreversed(&self) -> Option<NamespacedKeyword> {
|
pub fn unreversed(&self) -> Option<Keyword> {
|
||||||
if self.is_backward() {
|
if self.is_backward() {
|
||||||
Some(NamespacedKeyword {
|
Some(self.to_reversed())
|
||||||
name: self.name[1..].to_string(),
|
|
||||||
namespace: self.namespace.clone(),
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -261,7 +261,7 @@ impl Display for PlainSymbol {
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use edn::symbols::PlainSymbol;
|
/// # use edn::symbols::PlainSymbol;
|
||||||
/// assert_eq!("baz", PlainSymbol::new("baz").to_string());
|
/// assert_eq!("baz", PlainSymbol::plain("baz").to_string());
|
||||||
/// ```
|
/// ```
|
||||||
fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result {
|
||||||
write!(f, "{}", self.0)
|
write!(f, "{}", self.0)
|
||||||
|
@ -275,10 +275,10 @@ impl Display for NamespacedSymbol {
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use edn::symbols::NamespacedSymbol;
|
/// # use edn::symbols::NamespacedSymbol;
|
||||||
/// assert_eq!("bar/baz", NamespacedSymbol::new("bar", "baz").to_string());
|
/// assert_eq!("bar/baz", NamespacedSymbol::namespaced("bar", "baz").to_string());
|
||||||
/// ```
|
/// ```
|
||||||
fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result {
|
||||||
write!(f, "{}/{}", self.namespace, self.name)
|
write!(f, "{}/{}", self.namespace(), self.name())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,33 +289,25 @@ impl Display for Keyword {
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use edn::symbols::Keyword;
|
/// # use edn::symbols::Keyword;
|
||||||
/// assert_eq!(":baz", Keyword::new("baz").to_string());
|
/// assert_eq!(":baz", Keyword::plain("baz").to_string());
|
||||||
|
/// assert_eq!(":bar/baz", Keyword::namespaced("bar", "baz").to_string());
|
||||||
|
/// assert_eq!(":bar/_baz", Keyword::namespaced("bar", "baz").to_reversed().to_string());
|
||||||
|
/// assert_eq!(":bar/baz", Keyword::namespaced("bar", "baz").to_reversed().to_reversed().to_string());
|
||||||
/// ```
|
/// ```
|
||||||
fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result {
|
||||||
write!(f, ":{}", self.0)
|
if self.0.is_namespaced() {
|
||||||
|
let (ns, name) = self.0.components();
|
||||||
|
write!(f, ":{}/{}", ns, name)
|
||||||
|
} else {
|
||||||
|
write!(f, ":{}", self.0.name())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for NamespacedKeyword {
|
|
||||||
/// Print the keyword in EDN format.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// # use edn::symbols::NamespacedKeyword;
|
|
||||||
/// assert_eq!(":bar/baz", NamespacedKeyword::new("bar", "baz").to_string());
|
|
||||||
/// assert_eq!(":bar/_baz", NamespacedKeyword::new("bar", "baz").to_reversed().to_string());
|
|
||||||
/// assert_eq!(":bar/baz", NamespacedKeyword::new("bar", "baz").to_reversed().to_reversed().to_string());
|
|
||||||
/// ```
|
|
||||||
fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result {
|
|
||||||
write!(f, ":{}/{}", self.namespace, self.name)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ns_keyword_macro() {
|
fn test_ns_keyword_macro() {
|
||||||
assert_eq!(ns_keyword!("test", "name").to_string(),
|
assert_eq!(ns_keyword!("test", "name").to_string(),
|
||||||
NamespacedKeyword::new("test", "name").to_string());
|
Keyword::namespaced("test", "name").to_string());
|
||||||
assert_eq!(ns_keyword!("ns", "_name").to_string(),
|
assert_eq!(ns_keyword!("ns", "_name").to_string(),
|
||||||
NamespacedKeyword::new("ns", "_name").to_string());
|
Keyword::namespaced("ns", "_name").to_string());
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,6 @@ pub enum Value {
|
||||||
PlainSymbol(symbols::PlainSymbol),
|
PlainSymbol(symbols::PlainSymbol),
|
||||||
NamespacedSymbol(symbols::NamespacedSymbol),
|
NamespacedSymbol(symbols::NamespacedSymbol),
|
||||||
Keyword(symbols::Keyword),
|
Keyword(symbols::Keyword),
|
||||||
NamespacedKeyword(symbols::NamespacedKeyword),
|
|
||||||
Vector(Vec<Value>),
|
Vector(Vec<Value>),
|
||||||
// We're using a LinkedList here instead of a Vec or VecDeque because the
|
// We're using a LinkedList here instead of a Vec or VecDeque because the
|
||||||
// LinkedList is faster for appending (which we do a lot of).
|
// LinkedList is faster for appending (which we do a lot of).
|
||||||
|
@ -70,7 +69,6 @@ pub enum SpannedValue {
|
||||||
PlainSymbol(symbols::PlainSymbol),
|
PlainSymbol(symbols::PlainSymbol),
|
||||||
NamespacedSymbol(symbols::NamespacedSymbol),
|
NamespacedSymbol(symbols::NamespacedSymbol),
|
||||||
Keyword(symbols::Keyword),
|
Keyword(symbols::Keyword),
|
||||||
NamespacedKeyword(symbols::NamespacedKeyword),
|
|
||||||
Vector(Vec<ValueAndSpan>),
|
Vector(Vec<ValueAndSpan>),
|
||||||
List(LinkedList<ValueAndSpan>),
|
List(LinkedList<ValueAndSpan>),
|
||||||
Set(BTreeSet<ValueAndSpan>),
|
Set(BTreeSet<ValueAndSpan>),
|
||||||
|
@ -159,7 +157,6 @@ impl From<SpannedValue> for Value {
|
||||||
SpannedValue::PlainSymbol(v) => Value::PlainSymbol(v),
|
SpannedValue::PlainSymbol(v) => Value::PlainSymbol(v),
|
||||||
SpannedValue::NamespacedSymbol(v) => Value::NamespacedSymbol(v),
|
SpannedValue::NamespacedSymbol(v) => Value::NamespacedSymbol(v),
|
||||||
SpannedValue::Keyword(v) => Value::Keyword(v),
|
SpannedValue::Keyword(v) => Value::Keyword(v),
|
||||||
SpannedValue::NamespacedKeyword(v) => Value::NamespacedKeyword(v),
|
|
||||||
SpannedValue::Vector(v) => Value::Vector(v.into_iter().map(|x| x.without_spans()).collect()),
|
SpannedValue::Vector(v) => Value::Vector(v.into_iter().map(|x| x.without_spans()).collect()),
|
||||||
SpannedValue::List(v) => Value::List(v.into_iter().map(|x| x.without_spans()).collect()),
|
SpannedValue::List(v) => Value::List(v.into_iter().map(|x| x.without_spans()).collect()),
|
||||||
SpannedValue::Set(v) => Value::Set(v.into_iter().map(|x| x.without_spans()).collect()),
|
SpannedValue::Set(v) => Value::Set(v.into_iter().map(|x| x.without_spans()).collect()),
|
||||||
|
@ -249,10 +246,10 @@ macro_rules! def_into {
|
||||||
/// # use edn::types::Value;
|
/// # use edn::types::Value;
|
||||||
/// # use edn::symbols;
|
/// # use edn::symbols;
|
||||||
/// let value = to_symbol!("foo", "bar", Value);
|
/// let value = to_symbol!("foo", "bar", Value);
|
||||||
/// assert_eq!(value, Value::NamespacedSymbol(symbols::NamespacedSymbol::new("foo", "bar")));
|
/// assert_eq!(value, Value::NamespacedSymbol(symbols::NamespacedSymbol::namespaced("foo", "bar")));
|
||||||
///
|
///
|
||||||
/// let value = to_symbol!(None, "baz", Value);
|
/// let value = to_symbol!(None, "baz", Value);
|
||||||
/// assert_eq!(value, Value::PlainSymbol(symbols::PlainSymbol::new("baz")));
|
/// assert_eq!(value, Value::PlainSymbol(symbols::PlainSymbol::plain("baz")));
|
||||||
///
|
///
|
||||||
/// let value = to_symbol!("foo", "bar", SpannedValue);
|
/// let value = to_symbol!("foo", "bar", SpannedValue);
|
||||||
/// assert_eq!(value.into(), to_symbol!("foo", "bar", Value));
|
/// assert_eq!(value.into(), to_symbol!("foo", "bar", Value));
|
||||||
|
@ -263,8 +260,8 @@ macro_rules! def_into {
|
||||||
macro_rules! to_symbol {
|
macro_rules! to_symbol {
|
||||||
( $namespace:expr, $name:expr, $t:tt ) => {
|
( $namespace:expr, $name:expr, $t:tt ) => {
|
||||||
$namespace.into().map_or_else(
|
$namespace.into().map_or_else(
|
||||||
|| $t::PlainSymbol(symbols::PlainSymbol::new($name)),
|
|| $t::PlainSymbol(symbols::PlainSymbol::plain($name)),
|
||||||
|ns| $t::NamespacedSymbol(symbols::NamespacedSymbol::new(ns, $name)))
|
|ns| $t::NamespacedSymbol(symbols::NamespacedSymbol::namespaced(ns, $name)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,10 +275,10 @@ macro_rules! to_symbol {
|
||||||
/// # use edn::types::Value;
|
/// # use edn::types::Value;
|
||||||
/// # use edn::symbols;
|
/// # use edn::symbols;
|
||||||
/// let value = to_keyword!("foo", "bar", Value);
|
/// let value = to_keyword!("foo", "bar", Value);
|
||||||
/// assert_eq!(value, Value::NamespacedKeyword(symbols::NamespacedKeyword::new("foo", "bar")));
|
/// assert_eq!(value, Value::Keyword(symbols::Keyword::namespaced("foo", "bar")));
|
||||||
///
|
///
|
||||||
/// let value = to_keyword!(None, "baz", Value);
|
/// let value = to_keyword!(None, "baz", Value);
|
||||||
/// assert_eq!(value, Value::Keyword(symbols::Keyword::new("baz")));
|
/// assert_eq!(value, Value::Keyword(symbols::Keyword::plain("baz")));
|
||||||
///
|
///
|
||||||
/// let value = to_keyword!("foo", "bar", SpannedValue);
|
/// let value = to_keyword!("foo", "bar", SpannedValue);
|
||||||
/// assert_eq!(value.into(), to_keyword!("foo", "bar", Value));
|
/// assert_eq!(value.into(), to_keyword!("foo", "bar", Value));
|
||||||
|
@ -292,8 +289,8 @@ macro_rules! to_symbol {
|
||||||
macro_rules! to_keyword {
|
macro_rules! to_keyword {
|
||||||
( $namespace:expr, $name:expr, $t:tt ) => {
|
( $namespace:expr, $name:expr, $t:tt ) => {
|
||||||
$namespace.into().map_or_else(
|
$namespace.into().map_or_else(
|
||||||
|| $t::Keyword(symbols::Keyword::new($name)),
|
|| $t::Keyword(symbols::Keyword::plain($name)),
|
||||||
|ns| $t::NamespacedKeyword(symbols::NamespacedKeyword::new(ns, $name)))
|
|ns| $t::Keyword(symbols::Keyword::namespaced(ns, $name)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,13 +308,25 @@ macro_rules! def_common_value_methods {
|
||||||
def_is!(is_uuid, $t::Uuid(_));
|
def_is!(is_uuid, $t::Uuid(_));
|
||||||
def_is!(is_symbol, $t::PlainSymbol(_));
|
def_is!(is_symbol, $t::PlainSymbol(_));
|
||||||
def_is!(is_namespaced_symbol, $t::NamespacedSymbol(_));
|
def_is!(is_namespaced_symbol, $t::NamespacedSymbol(_));
|
||||||
def_is!(is_keyword, $t::Keyword(_));
|
|
||||||
def_is!(is_namespaced_keyword, $t::NamespacedKeyword(_));
|
|
||||||
def_is!(is_vector, $t::Vector(_));
|
def_is!(is_vector, $t::Vector(_));
|
||||||
def_is!(is_list, $t::List(_));
|
def_is!(is_list, $t::List(_));
|
||||||
def_is!(is_set, $t::Set(_));
|
def_is!(is_set, $t::Set(_));
|
||||||
def_is!(is_map, $t::Map(_));
|
def_is!(is_map, $t::Map(_));
|
||||||
|
|
||||||
|
pub fn is_keyword(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
&$t::Keyword(ref k) => !k.is_namespaced(),
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_namespaced_keyword(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
&$t::Keyword(ref k) => k.is_namespaced(),
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// `as_nil` does not use the macro as it does not have an underlying
|
/// `as_nil` does not use the macro as it does not have an underlying
|
||||||
/// value, and returns `Option<()>`.
|
/// value, and returns `Option<()>`.
|
||||||
pub fn as_nil(&self) -> Option<()> {
|
pub fn as_nil(&self) -> Option<()> {
|
||||||
|
@ -335,8 +344,21 @@ macro_rules! def_common_value_methods {
|
||||||
def_as_ref!(as_uuid, $t::Uuid, Uuid);
|
def_as_ref!(as_uuid, $t::Uuid, Uuid);
|
||||||
def_as_ref!(as_symbol, $t::PlainSymbol, symbols::PlainSymbol);
|
def_as_ref!(as_symbol, $t::PlainSymbol, symbols::PlainSymbol);
|
||||||
def_as_ref!(as_namespaced_symbol, $t::NamespacedSymbol, symbols::NamespacedSymbol);
|
def_as_ref!(as_namespaced_symbol, $t::NamespacedSymbol, symbols::NamespacedSymbol);
|
||||||
def_as_ref!(as_keyword, $t::Keyword, symbols::Keyword);
|
|
||||||
def_as_ref!(as_namespaced_keyword, $t::NamespacedKeyword, symbols::NamespacedKeyword);
|
pub fn as_keyword(&self) -> Option<&symbols::Keyword> {
|
||||||
|
match self {
|
||||||
|
&$t::Keyword(ref k) if !k.is_namespaced() => Some(k),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_namespaced_keyword(&self) -> Option<&symbols::Keyword> {
|
||||||
|
match self {
|
||||||
|
&$t::Keyword(ref k) if k.is_namespaced() => Some(k),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def_as_ref!(as_vector, $t::Vector, Vec<$tchild>);
|
def_as_ref!(as_vector, $t::Vector, Vec<$tchild>);
|
||||||
def_as_ref!(as_list, $t::List, LinkedList<$tchild>);
|
def_as_ref!(as_list, $t::List, LinkedList<$tchild>);
|
||||||
def_as_ref!(as_set, $t::Set, BTreeSet<$tchild>);
|
def_as_ref!(as_set, $t::Set, BTreeSet<$tchild>);
|
||||||
|
@ -352,8 +374,34 @@ macro_rules! def_common_value_methods {
|
||||||
def_into!(into_uuid, $t::Uuid, Uuid,);
|
def_into!(into_uuid, $t::Uuid, Uuid,);
|
||||||
def_into!(into_symbol, $t::PlainSymbol, symbols::PlainSymbol,);
|
def_into!(into_symbol, $t::PlainSymbol, symbols::PlainSymbol,);
|
||||||
def_into!(into_namespaced_symbol, $t::NamespacedSymbol, symbols::NamespacedSymbol,);
|
def_into!(into_namespaced_symbol, $t::NamespacedSymbol, symbols::NamespacedSymbol,);
|
||||||
def_into!(into_keyword, $t::Keyword, symbols::Keyword,);
|
|
||||||
def_into!(into_namespaced_keyword, $t::NamespacedKeyword, symbols::NamespacedKeyword,);
|
pub fn into_keyword(self) -> Option<symbols::Keyword> {
|
||||||
|
match self {
|
||||||
|
$t::Keyword(k) => {
|
||||||
|
if !k.is_namespaced() {
|
||||||
|
Some(k)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_namespaced_keyword(self) -> Option<symbols::Keyword> {
|
||||||
|
match self {
|
||||||
|
$t::Keyword(k) => {
|
||||||
|
if k.is_namespaced() {
|
||||||
|
Some(k)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def_into!(into_vector, $t::Vector, Vec<$tchild>,);
|
def_into!(into_vector, $t::Vector, Vec<$tchild>,);
|
||||||
def_into!(into_list, $t::List, LinkedList<$tchild>,);
|
def_into!(into_list, $t::List, LinkedList<$tchild>,);
|
||||||
def_into!(into_set, $t::Set, BTreeSet<$tchild>,);
|
def_into!(into_set, $t::Set, BTreeSet<$tchild>,);
|
||||||
|
@ -383,8 +431,8 @@ macro_rules! def_common_value_methods {
|
||||||
$t::Uuid(_) => 7,
|
$t::Uuid(_) => 7,
|
||||||
$t::PlainSymbol(_) => 8,
|
$t::PlainSymbol(_) => 8,
|
||||||
$t::NamespacedSymbol(_) => 9,
|
$t::NamespacedSymbol(_) => 9,
|
||||||
$t::Keyword(_) => 10,
|
$t::Keyword(ref k) if !k.is_namespaced() => 10,
|
||||||
$t::NamespacedKeyword(_) => 11,
|
$t::Keyword(_) => 11,
|
||||||
$t::Vector(_) => 12,
|
$t::Vector(_) => 12,
|
||||||
$t::List(_) => 13,
|
$t::List(_) => 13,
|
||||||
$t::Set(_) => 14,
|
$t::Set(_) => 14,
|
||||||
|
@ -405,7 +453,6 @@ macro_rules! def_common_value_methods {
|
||||||
$t::PlainSymbol(_) => false,
|
$t::PlainSymbol(_) => false,
|
||||||
$t::NamespacedSymbol(_) => false,
|
$t::NamespacedSymbol(_) => false,
|
||||||
$t::Keyword(_) => false,
|
$t::Keyword(_) => false,
|
||||||
$t::NamespacedKeyword(_) => false,
|
|
||||||
$t::Vector(_) => true,
|
$t::Vector(_) => true,
|
||||||
$t::List(_) => true,
|
$t::List(_) => true,
|
||||||
$t::Set(_) => true,
|
$t::Set(_) => true,
|
||||||
|
@ -443,7 +490,6 @@ macro_rules! def_common_value_ord {
|
||||||
(&$t::PlainSymbol(ref a), &$t::PlainSymbol(ref b)) => b.cmp(a),
|
(&$t::PlainSymbol(ref a), &$t::PlainSymbol(ref b)) => b.cmp(a),
|
||||||
(&$t::NamespacedSymbol(ref a), &$t::NamespacedSymbol(ref b)) => b.cmp(a),
|
(&$t::NamespacedSymbol(ref a), &$t::NamespacedSymbol(ref b)) => b.cmp(a),
|
||||||
(&$t::Keyword(ref a), &$t::Keyword(ref b)) => b.cmp(a),
|
(&$t::Keyword(ref a), &$t::Keyword(ref b)) => b.cmp(a),
|
||||||
(&$t::NamespacedKeyword(ref a), &$t::NamespacedKeyword(ref b)) => b.cmp(a),
|
|
||||||
(&$t::Vector(ref a), &$t::Vector(ref b)) => b.cmp(a),
|
(&$t::Vector(ref a), &$t::Vector(ref b)) => b.cmp(a),
|
||||||
(&$t::List(ref a), &$t::List(ref b)) => b.cmp(a),
|
(&$t::List(ref a), &$t::List(ref b)) => b.cmp(a),
|
||||||
(&$t::Set(ref a), &$t::Set(ref b)) => b.cmp(a),
|
(&$t::Set(ref a), &$t::Set(ref b)) => b.cmp(a),
|
||||||
|
@ -482,7 +528,6 @@ macro_rules! def_common_value_display {
|
||||||
$t::PlainSymbol(ref v) => v.fmt($f),
|
$t::PlainSymbol(ref v) => v.fmt($f),
|
||||||
$t::NamespacedSymbol(ref v) => v.fmt($f),
|
$t::NamespacedSymbol(ref v) => v.fmt($f),
|
||||||
$t::Keyword(ref v) => v.fmt($f),
|
$t::Keyword(ref v) => v.fmt($f),
|
||||||
$t::NamespacedKeyword(ref v) => v.fmt($f),
|
|
||||||
$t::Vector(ref v) => {
|
$t::Vector(ref v) => {
|
||||||
write!($f, "[")?;
|
write!($f, "[")?;
|
||||||
for x in v {
|
for x in v {
|
||||||
|
|
56
edn/tests/serde_support.rs
Normal file
56
edn/tests/serde_support.rs
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
// Copyright 2018 Mozilla
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||||
|
// this file except in compliance with the License. You may obtain a copy of the
|
||||||
|
// License at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
|
|
||||||
|
#![cfg(feature = "serde_support")]
|
||||||
|
|
||||||
|
extern crate serde_test;
|
||||||
|
extern crate serde_json;
|
||||||
|
|
||||||
|
extern crate edn;
|
||||||
|
use edn::symbols::Keyword;
|
||||||
|
use serde_test::{assert_tokens, Token};
|
||||||
|
|
||||||
|
#[cfg(feature = "serde_support")]
|
||||||
|
#[test]
|
||||||
|
fn test_serialize_keyword() {
|
||||||
|
let kw = Keyword::namespaced("foo", "bar");
|
||||||
|
assert_tokens(&kw, &[
|
||||||
|
Token::NewtypeStruct { name: "Keyword" },
|
||||||
|
Token::Struct { name: "NamespaceableName", len: 2 },
|
||||||
|
Token::Str("namespace"),
|
||||||
|
Token::Some,
|
||||||
|
Token::BorrowedStr("foo"),
|
||||||
|
Token::Str("name"),
|
||||||
|
Token::BorrowedStr("bar"),
|
||||||
|
Token::StructEnd,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[cfg(feature = "serde_support")]
|
||||||
|
#[test]
|
||||||
|
fn test_deserialize_keyword() {
|
||||||
|
let json = r#"{"name": "foo", "namespace": "bar"}"#;
|
||||||
|
let kw = serde_json::from_str::<Keyword>(json).unwrap();
|
||||||
|
assert_eq!(kw.name(), "foo");
|
||||||
|
assert_eq!(kw.namespace(), Some("bar"));
|
||||||
|
|
||||||
|
let bad_ns_json = r#"{"name": "foo", "namespace": ""}"#;
|
||||||
|
let not_kw = serde_json::from_str::<Keyword>(bad_ns_json);
|
||||||
|
assert!(not_kw.is_err());
|
||||||
|
|
||||||
|
let bad_ns_json = r#"{"name": "", "namespace": "bar"}"#;
|
||||||
|
let not_kw = serde_json::from_str::<Keyword>(bad_ns_json);
|
||||||
|
assert!(not_kw.is_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -38,22 +38,22 @@ use edn::utils;
|
||||||
|
|
||||||
// Helper for making wrapped keywords with a namespace.
|
// Helper for making wrapped keywords with a namespace.
|
||||||
fn k_ns(ns: &str, name: &str) -> Value {
|
fn k_ns(ns: &str, name: &str) -> Value {
|
||||||
Value::NamespacedKeyword(symbols::NamespacedKeyword::new(ns, name))
|
Value::Keyword(symbols::Keyword::namespaced(ns, name))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper for making wrapped keywords without a namespace.
|
// Helper for making wrapped keywords without a namespace.
|
||||||
fn k_plain(name: &str) -> Value {
|
fn k_plain(name: &str) -> Value {
|
||||||
Value::Keyword(symbols::Keyword::new(name))
|
Value::Keyword(symbols::Keyword::plain(name))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper for making wrapped symbols with a namespace
|
// Helper for making wrapped symbols with a namespace
|
||||||
fn s_ns(ns: &str, name: &str) -> Value {
|
fn s_ns(ns: &str, name: &str) -> Value {
|
||||||
Value::NamespacedSymbol(symbols::NamespacedSymbol::new(ns, name))
|
Value::NamespacedSymbol(symbols::NamespacedSymbol::namespaced(ns, name))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper for making wrapped symbols without a namespace
|
// Helper for making wrapped symbols without a namespace
|
||||||
fn s_plain(name: &str) -> Value {
|
fn s_plain(name: &str) -> Value {
|
||||||
Value::PlainSymbol(symbols::PlainSymbol::new(name))
|
Value::PlainSymbol(symbols::PlainSymbol::plain(name))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helpers for parsing strings and converting them into edn::Value.
|
// Helpers for parsing strings and converting them into edn::Value.
|
||||||
|
@ -831,7 +831,7 @@ fn test_map() {
|
||||||
|
|
||||||
let test = "{:a 1, $b {:b/a nil, :b/b #{nil 5}}, c [1 2], d (3 4)}";
|
let test = "{:a 1, $b {:b/a nil, :b/b #{nil 5}}, c [1 2], d (3 4)}";
|
||||||
let value = Map(BTreeMap::from_iter(vec![
|
let value = Map(BTreeMap::from_iter(vec![
|
||||||
(Keyword(symbols::Keyword::new("a")), Integer(1)),
|
(Keyword(symbols::Keyword::plain("a")), Integer(1)),
|
||||||
(s_plain("$b"), Map(BTreeMap::from_iter(vec![
|
(s_plain("$b"), Map(BTreeMap::from_iter(vec![
|
||||||
(k_ns("b", "a"), Nil),
|
(k_ns("b", "a"), Nil),
|
||||||
(k_ns("b", "b"), Set(BTreeSet::from_iter(vec![
|
(k_ns("b", "b"), Set(BTreeSet::from_iter(vec![
|
||||||
|
@ -1457,7 +1457,7 @@ fn test_is_and_as_type_helper_functions() {
|
||||||
assert_eq!(values.len(), is_result.len());
|
assert_eq!(values.len(), is_result.len());
|
||||||
|
|
||||||
for (j, result) in is_result.iter().enumerate() {
|
for (j, result) in is_result.iter().enumerate() {
|
||||||
assert_eq!(j == i, *result);
|
assert_eq!(j == i, *result, "Expected {} = {} to equal {}", j, i, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
|
@ -1474,10 +1474,10 @@ fn test_is_and_as_type_helper_functions() {
|
||||||
def_test_as_type!(value, as_big_integer, i == 3, &max_i64 * &max_i64);
|
def_test_as_type!(value, as_big_integer, i == 3, &max_i64 * &max_i64);
|
||||||
def_test_as_type!(value, as_ordered_float, i == 4, OrderedFloat(22.22f64));
|
def_test_as_type!(value, as_ordered_float, i == 4, OrderedFloat(22.22f64));
|
||||||
def_test_as_type!(value, as_text, i == 5, "hello world".to_string());
|
def_test_as_type!(value, as_text, i == 5, "hello world".to_string());
|
||||||
def_test_as_type!(value, as_symbol, i == 6, symbols::PlainSymbol::new("$symbol"));
|
def_test_as_type!(value, as_symbol, i == 6, symbols::PlainSymbol::plain("$symbol"));
|
||||||
def_test_as_type!(value, as_namespaced_symbol, i == 7, symbols::NamespacedSymbol::new("$ns", "$symbol"));
|
def_test_as_type!(value, as_namespaced_symbol, i == 7, symbols::NamespacedSymbol::namespaced("$ns", "$symbol"));
|
||||||
def_test_as_type!(value, as_keyword, i == 8, symbols::Keyword::new("hello"));
|
def_test_as_type!(value, as_keyword, i == 8, symbols::Keyword::plain("hello"));
|
||||||
def_test_as_type!(value, as_namespaced_keyword, i == 9, symbols::NamespacedKeyword::new("hello", "world"));
|
def_test_as_type!(value, as_namespaced_keyword, i == 9, symbols::Keyword::namespaced("hello", "world"));
|
||||||
def_test_as_type!(value, as_vector, i == 10, vec![Value::Integer(1)]);
|
def_test_as_type!(value, as_vector, i == 10, vec![Value::Integer(1)]);
|
||||||
def_test_as_type!(value, as_list, i == 11, LinkedList::from_iter(vec![]));
|
def_test_as_type!(value, as_list, i == 11, LinkedList::from_iter(vec![]));
|
||||||
def_test_as_type!(value, as_set, i == 12, BTreeSet::from_iter(vec![]));
|
def_test_as_type!(value, as_set, i == 12, BTreeSet::from_iter(vec![]));
|
||||||
|
@ -1492,10 +1492,10 @@ fn test_is_and_as_type_helper_functions() {
|
||||||
def_test_into_type!(value, into_big_integer, i == 3, &max_i64 * &max_i64);
|
def_test_into_type!(value, into_big_integer, i == 3, &max_i64 * &max_i64);
|
||||||
def_test_into_type!(value, into_ordered_float, i == 4, OrderedFloat(22.22f64));
|
def_test_into_type!(value, into_ordered_float, i == 4, OrderedFloat(22.22f64));
|
||||||
def_test_into_type!(value, into_text, i == 5, "hello world".to_string());
|
def_test_into_type!(value, into_text, i == 5, "hello world".to_string());
|
||||||
def_test_into_type!(value, into_symbol, i == 6, symbols::PlainSymbol::new("$symbol"));
|
def_test_into_type!(value, into_symbol, i == 6, symbols::PlainSymbol::plain("$symbol"));
|
||||||
def_test_into_type!(value, into_namespaced_symbol, i == 7, symbols::NamespacedSymbol::new("$ns", "$symbol"));
|
def_test_into_type!(value, into_namespaced_symbol, i == 7, symbols::NamespacedSymbol::namespaced("$ns", "$symbol"));
|
||||||
def_test_into_type!(value, into_keyword, i == 8, symbols::Keyword::new("hello"));
|
def_test_into_type!(value, into_keyword, i == 8, symbols::Keyword::plain("hello"));
|
||||||
def_test_into_type!(value, into_namespaced_keyword, i == 9, symbols::NamespacedKeyword::new("hello", "world"));
|
def_test_into_type!(value, into_namespaced_keyword, i == 9, symbols::Keyword::namespaced("hello", "world"));
|
||||||
def_test_into_type!(value, into_vector, i == 10, vec![Value::Integer(1)]);
|
def_test_into_type!(value, into_vector, i == 10, vec![Value::Integer(1)]);
|
||||||
def_test_into_type!(value, into_list, i == 11, LinkedList::from_iter(vec![]));
|
def_test_into_type!(value, into_list, i == 11, LinkedList::from_iter(vec![]));
|
||||||
def_test_into_type!(value, into_set, i == 12, BTreeSet::from_iter(vec![]));
|
def_test_into_type!(value, into_set, i == 12, BTreeSet::from_iter(vec![]));
|
||||||
|
|
|
@ -32,7 +32,7 @@ pub use mentat::{
|
||||||
FindSpec,
|
FindSpec,
|
||||||
HasSchema,
|
HasSchema,
|
||||||
KnownEntid,
|
KnownEntid,
|
||||||
NamespacedKeyword,
|
Keyword,
|
||||||
Queryable,
|
Queryable,
|
||||||
QueryBuilder,
|
QueryBuilder,
|
||||||
QueryInputs,
|
QueryInputs,
|
||||||
|
|
|
@ -16,7 +16,7 @@ pub mod strings {
|
||||||
use std::os::raw::c_char;
|
use std::os::raw::c_char;
|
||||||
|
|
||||||
use mentat::{
|
use mentat::{
|
||||||
NamespacedKeyword,
|
Keyword,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn c_char_to_string(cchar: *const c_char) -> String {
|
pub fn c_char_to_string(cchar: *const c_char) -> String {
|
||||||
|
@ -30,10 +30,10 @@ pub mod strings {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: validate. The input might not be a keyword!
|
// TODO: validate. The input might not be a keyword!
|
||||||
pub fn kw_from_string(mut keyword_string: String) -> NamespacedKeyword {
|
pub fn kw_from_string(mut keyword_string: String) -> Keyword {
|
||||||
let attr_name = keyword_string.split_off(1);
|
let attr_name = keyword_string.split_off(1);
|
||||||
let parts: Vec<&str> = attr_name.split("/").collect();
|
let parts: Vec<&str> = attr_name.split("/").collect();
|
||||||
NamespacedKeyword::new(parts[0], parts[1])
|
Keyword::namespaced(parts[0], parts[1])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,7 @@ macro_rules! matches_plain_symbol {
|
||||||
($name: expr, $input: ident) => {
|
($name: expr, $input: ident) => {
|
||||||
satisfy_map(|x: edn::Value| {
|
satisfy_map(|x: edn::Value| {
|
||||||
if let edn::Value::PlainSymbol(ref s) = x {
|
if let edn::Value::PlainSymbol(ref s) = x {
|
||||||
if s.0.as_str() == $name {
|
if s.name() == $name {
|
||||||
return Some(());
|
return Some(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -442,34 +442,37 @@ pub fn integer<'a>() -> Expected<FnParser<Stream<'a>, fn(Stream<'a>) -> ParseRes
|
||||||
parser(integer_ as fn(Stream<'a>) -> ParseResult<i64, Stream<'a>>).expected("integer")
|
parser(integer_ as fn(Stream<'a>) -> ParseResult<i64, Stream<'a>>).expected("integer")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn namespaced_keyword_<'a>(input: Stream<'a>) -> ParseResult<&'a edn::NamespacedKeyword, Stream<'a>> {
|
pub fn namespaced_keyword_<'a>(input: Stream<'a>) -> ParseResult<&'a edn::Keyword, Stream<'a>> {
|
||||||
satisfy_map(|v: &'a edn::ValueAndSpan| v.inner.as_namespaced_keyword())
|
satisfy_map(|v: &'a edn::ValueAndSpan|
|
||||||
|
v.inner.as_namespaced_keyword()
|
||||||
|
.and_then(|k| if k.is_namespaced() { Some(k) } else { None })
|
||||||
|
)
|
||||||
.parse_lazy(input)
|
.parse_lazy(input)
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn namespaced_keyword<'a>() -> Expected<FnParser<Stream<'a>, fn(Stream<'a>) -> ParseResult<&'a edn::NamespacedKeyword, Stream<'a>>>> {
|
pub fn namespaced_keyword<'a>() -> Expected<FnParser<Stream<'a>, fn(Stream<'a>) -> ParseResult<&'a edn::Keyword, Stream<'a>>>> {
|
||||||
parser(namespaced_keyword_ as fn(Stream<'a>) -> ParseResult<&'a edn::NamespacedKeyword, Stream<'a>>).expected("namespaced_keyword")
|
parser(namespaced_keyword_ as fn(Stream<'a>) -> ParseResult<&'a edn::Keyword, Stream<'a>>).expected("namespaced_keyword")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn forward_keyword_<'a>(input: Stream<'a>) -> ParseResult<&'a edn::NamespacedKeyword, Stream<'a>> {
|
pub fn forward_keyword_<'a>(input: Stream<'a>) -> ParseResult<&'a edn::Keyword, Stream<'a>> {
|
||||||
satisfy_map(|v: &'a edn::ValueAndSpan| v.inner.as_namespaced_keyword().and_then(|k| if k.is_forward() { Some(k) } else { None }))
|
satisfy_map(|v: &'a edn::ValueAndSpan| v.inner.as_namespaced_keyword().and_then(|k| if k.is_forward() && k.is_namespaced() { Some(k) } else { None }))
|
||||||
.parse_lazy(input)
|
.parse_lazy(input)
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn forward_keyword<'a>() -> Expected<FnParser<Stream<'a>, fn(Stream<'a>) -> ParseResult<&'a edn::NamespacedKeyword, Stream<'a>>>> {
|
pub fn forward_keyword<'a>() -> Expected<FnParser<Stream<'a>, fn(Stream<'a>) -> ParseResult<&'a edn::Keyword, Stream<'a>>>> {
|
||||||
parser(forward_keyword_ as fn(Stream<'a>) -> ParseResult<&'a edn::NamespacedKeyword, Stream<'a>>).expected("forward_keyword")
|
parser(forward_keyword_ as fn(Stream<'a>) -> ParseResult<&'a edn::Keyword, Stream<'a>>).expected("forward_keyword")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn backward_keyword_<'a>(input: Stream<'a>) -> ParseResult<&'a edn::NamespacedKeyword, Stream<'a>> {
|
pub fn backward_keyword_<'a>(input: Stream<'a>) -> ParseResult<&'a edn::Keyword, Stream<'a>> {
|
||||||
satisfy_map(|v: &'a edn::ValueAndSpan| v.inner.as_namespaced_keyword().and_then(|k| if k.is_backward() { Some(k) } else { None }))
|
satisfy_map(|v: &'a edn::ValueAndSpan| v.inner.as_namespaced_keyword().and_then(|k| if k.is_backward() && k.is_namespaced() { Some(k) } else { None }))
|
||||||
.parse_lazy(input)
|
.parse_lazy(input)
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn backward_keyword<'a>() -> Expected<FnParser<Stream<'a>, fn(Stream<'a>) -> ParseResult<&'a edn::NamespacedKeyword, Stream<'a>>>> {
|
pub fn backward_keyword<'a>() -> Expected<FnParser<Stream<'a>, fn(Stream<'a>) -> ParseResult<&'a edn::Keyword, Stream<'a>>>> {
|
||||||
parser(backward_keyword_ as fn(Stream<'a>) -> ParseResult<&'a edn::NamespacedKeyword, Stream<'a>>).expected("backward_keyword")
|
parser(backward_keyword_ as fn(Stream<'a>) -> ParseResult<&'a edn::Keyword, Stream<'a>>).expected("backward_keyword")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate a `satisfy` expression that matches a `PlainSymbol` value with the given name.
|
/// Generate a `satisfy` expression that matches a `PlainSymbol` value with the given name.
|
||||||
|
@ -482,7 +485,7 @@ macro_rules! def_matches_plain_symbol {
|
||||||
def_parser!($parser, $name, &'a edn::ValueAndSpan, {
|
def_parser!($parser, $name, &'a edn::ValueAndSpan, {
|
||||||
satisfy(|v: &'a edn::ValueAndSpan| {
|
satisfy(|v: &'a edn::ValueAndSpan| {
|
||||||
match v.inner {
|
match v.inner {
|
||||||
edn::SpannedValue::PlainSymbol(ref s) => s.0.as_str() == $input,
|
edn::SpannedValue::PlainSymbol(ref s) => s.name() == $input,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -499,7 +502,7 @@ macro_rules! def_matches_keyword {
|
||||||
def_parser!($parser, $name, &'a edn::ValueAndSpan, {
|
def_parser!($parser, $name, &'a edn::ValueAndSpan, {
|
||||||
satisfy(|v: &'a edn::ValueAndSpan| {
|
satisfy(|v: &'a edn::ValueAndSpan| {
|
||||||
match v.inner {
|
match v.inner {
|
||||||
edn::SpannedValue::Keyword(ref s) => s.0.as_str() == $input,
|
edn::SpannedValue::Keyword(ref s) if !s.is_namespaced() => s.name() == $input,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -507,7 +510,7 @@ macro_rules! def_matches_keyword {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate a `satisfy` expression that matches a `NamespacedKeyword` value with the given
|
/// Generate a `satisfy` expression that matches a `Keyword` value with the given
|
||||||
/// namespace and name.
|
/// namespace and name.
|
||||||
///
|
///
|
||||||
/// We do this rather than using `combine::token` to save allocations.
|
/// We do this rather than using `combine::token` to save allocations.
|
||||||
|
@ -517,7 +520,10 @@ macro_rules! def_matches_namespaced_keyword {
|
||||||
def_parser!($parser, $name, &'a edn::ValueAndSpan, {
|
def_parser!($parser, $name, &'a edn::ValueAndSpan, {
|
||||||
satisfy(|v: &'a edn::ValueAndSpan| {
|
satisfy(|v: &'a edn::ValueAndSpan| {
|
||||||
match v.inner {
|
match v.inner {
|
||||||
edn::SpannedValue::NamespacedKeyword(ref s) => s.namespace.as_str() == $input_namespace && s.name.as_str() == $input_name,
|
edn::SpannedValue::Keyword(ref s) if s.is_namespaced() => {
|
||||||
|
let (ns, n) = s.components();
|
||||||
|
ns == $input_namespace && n == $input_name
|
||||||
|
},
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -565,7 +571,7 @@ macro_rules! keyword_map_parser {
|
||||||
Ok(value) => {
|
Ok(value) => {
|
||||||
$(
|
$(
|
||||||
if let Some(ref keyword) = value.inner.as_keyword() {
|
if let Some(ref keyword) = value.inner.as_keyword() {
|
||||||
if keyword.0.as_str() == *$keyword {
|
if &keyword.name() == $keyword {
|
||||||
if $tmp.is_some() {
|
if $tmp.is_some() {
|
||||||
// Repeated match -- bail out! Providing good error
|
// Repeated match -- bail out! Providing good error
|
||||||
// messages is hard; this will do for now.
|
// messages is hard; this will do for now.
|
||||||
|
@ -711,7 +717,7 @@ mod tests {
|
||||||
fn test_keyword_map_failures() {
|
fn test_keyword_map_failures() {
|
||||||
assert_parse_failure_contains!(|| vector().of_exactly(keyword_map_of!(("x", Test::entid()), ("y", Test::entid()))),
|
assert_parse_failure_contains!(|| vector().of_exactly(keyword_map_of!(("x", Test::entid()), ("y", Test::entid()))),
|
||||||
"[:x 1 :x 2]",
|
"[:x 1 :x 2]",
|
||||||
r#"errors: [Unexpected(Token(ValueAndSpan { inner: Keyword(Keyword("x"))"#);
|
r#"errors: [Unexpected(Token(ValueAndSpan { inner: Keyword(Keyword(NamespaceableName { namespace: None, name: "x" }))"#);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -269,7 +269,7 @@ mod testing {
|
||||||
use mentat_query::{
|
use mentat_query::{
|
||||||
Binding,
|
Binding,
|
||||||
FnArg,
|
FnArg,
|
||||||
NamespacedKeyword,
|
Keyword,
|
||||||
PlainSymbol,
|
PlainSymbol,
|
||||||
Variable,
|
Variable,
|
||||||
};
|
};
|
||||||
|
@ -284,14 +284,14 @@ mod testing {
|
||||||
let mut cc = ConjoiningClauses::default();
|
let mut cc = ConjoiningClauses::default();
|
||||||
let mut schema = Schema::default();
|
let mut schema = Schema::default();
|
||||||
|
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "bar"), 101);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "bar"), 101);
|
||||||
add_attribute(&mut schema, 101, Attribute {
|
add_attribute(&mut schema, 101, Attribute {
|
||||||
value_type: ValueType::String,
|
value_type: ValueType::String,
|
||||||
fulltext: false,
|
fulltext: false,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "fts"), 100);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "fts"), 100);
|
||||||
add_attribute(&mut schema, 100, Attribute {
|
add_attribute(&mut schema, 100, Attribute {
|
||||||
value_type: ValueType::String,
|
value_type: ValueType::String,
|
||||||
index: true,
|
index: true,
|
||||||
|
@ -301,12 +301,12 @@ mod testing {
|
||||||
|
|
||||||
let known = Known::for_schema(&schema);
|
let known = Known::for_schema(&schema);
|
||||||
|
|
||||||
let op = PlainSymbol::new("fulltext");
|
let op = PlainSymbol::plain("fulltext");
|
||||||
cc.apply_fulltext(known, WhereFn {
|
cc.apply_fulltext(known, WhereFn {
|
||||||
operator: op,
|
operator: op,
|
||||||
args: vec![
|
args: vec![
|
||||||
FnArg::SrcVar(SrcVar::DefaultSrc),
|
FnArg::SrcVar(SrcVar::DefaultSrc),
|
||||||
FnArg::IdentOrKeyword(NamespacedKeyword::new("foo", "fts")),
|
FnArg::IdentOrKeyword(Keyword::namespaced("foo", "fts")),
|
||||||
FnArg::Constant("needle".into()),
|
FnArg::Constant("needle".into()),
|
||||||
],
|
],
|
||||||
binding: Binding::BindRel(vec![VariableOrPlaceholder::Variable(Variable::from_valid_name("?entity")),
|
binding: Binding::BindRel(vec![VariableOrPlaceholder::Variable(Variable::from_valid_name("?entity")),
|
||||||
|
@ -359,12 +359,12 @@ mod testing {
|
||||||
vec![ValueType::Double].into_iter().collect());
|
vec![ValueType::Double].into_iter().collect());
|
||||||
|
|
||||||
let mut cc = ConjoiningClauses::default();
|
let mut cc = ConjoiningClauses::default();
|
||||||
let op = PlainSymbol::new("fulltext");
|
let op = PlainSymbol::plain("fulltext");
|
||||||
cc.apply_fulltext(known, WhereFn {
|
cc.apply_fulltext(known, WhereFn {
|
||||||
operator: op,
|
operator: op,
|
||||||
args: vec![
|
args: vec![
|
||||||
FnArg::SrcVar(SrcVar::DefaultSrc),
|
FnArg::SrcVar(SrcVar::DefaultSrc),
|
||||||
FnArg::IdentOrKeyword(NamespacedKeyword::new("foo", "bar")),
|
FnArg::IdentOrKeyword(Keyword::namespaced("foo", "bar")),
|
||||||
FnArg::Constant("needle".into()),
|
FnArg::Constant("needle".into()),
|
||||||
],
|
],
|
||||||
binding: Binding::BindRel(vec![VariableOrPlaceholder::Variable(Variable::from_valid_name("?entity")),
|
binding: Binding::BindRel(vec![VariableOrPlaceholder::Variable(Variable::from_valid_name("?entity")),
|
||||||
|
|
|
@ -329,7 +329,7 @@ mod testing {
|
||||||
use mentat_query::{
|
use mentat_query::{
|
||||||
Binding,
|
Binding,
|
||||||
FnArg,
|
FnArg,
|
||||||
NamespacedKeyword,
|
Keyword,
|
||||||
PlainSymbol,
|
PlainSymbol,
|
||||||
Variable,
|
Variable,
|
||||||
};
|
};
|
||||||
|
@ -346,7 +346,7 @@ mod testing {
|
||||||
let mut cc = ConjoiningClauses::default();
|
let mut cc = ConjoiningClauses::default();
|
||||||
let mut schema = Schema::default();
|
let mut schema = Schema::default();
|
||||||
|
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "fts"), 100);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "fts"), 100);
|
||||||
add_attribute(&mut schema, 100, Attribute {
|
add_attribute(&mut schema, 100, Attribute {
|
||||||
value_type: ValueType::String,
|
value_type: ValueType::String,
|
||||||
index: true,
|
index: true,
|
||||||
|
@ -358,7 +358,7 @@ mod testing {
|
||||||
|
|
||||||
// It's awkward enough to write these expansions that we give the details for the simplest
|
// It's awkward enough to write these expansions that we give the details for the simplest
|
||||||
// case only. See the tests of the translator for more extensive (albeit looser) coverage.
|
// case only. See the tests of the translator for more extensive (albeit looser) coverage.
|
||||||
let op = PlainSymbol::new("ground");
|
let op = PlainSymbol::plain("ground");
|
||||||
cc.apply_ground(known, WhereFn {
|
cc.apply_ground(known, WhereFn {
|
||||||
operator: op,
|
operator: op,
|
||||||
args: vec![
|
args: vec![
|
||||||
|
|
|
@ -42,7 +42,7 @@ use mentat_core::counter::RcCounter;
|
||||||
use mentat_query::{
|
use mentat_query::{
|
||||||
Element,
|
Element,
|
||||||
FindSpec,
|
FindSpec,
|
||||||
NamespacedKeyword,
|
Keyword,
|
||||||
Pull,
|
Pull,
|
||||||
Variable,
|
Variable,
|
||||||
WhereClause,
|
WhereClause,
|
||||||
|
@ -760,7 +760,7 @@ impl ConjoiningClauses {
|
||||||
self.empty_because = Some(why);
|
self.empty_because = Some(why);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn entid_for_ident<'s, 'a>(&self, schema: &'s Schema, ident: &'a NamespacedKeyword) -> Option<KnownEntid> {
|
fn entid_for_ident<'s, 'a>(&self, schema: &'s Schema, ident: &'a Keyword) -> Option<KnownEntid> {
|
||||||
schema.get_entid(&ident)
|
schema.get_entid(&ident)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1155,7 +1155,7 @@ impl PushComputed for Vec<ComputedTable> {
|
||||||
|
|
||||||
// These are helpers that tests use to build Schema instances.
|
// These are helpers that tests use to build Schema instances.
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
fn associate_ident(schema: &mut Schema, i: NamespacedKeyword, e: Entid) {
|
fn associate_ident(schema: &mut Schema, i: Keyword, e: Entid) {
|
||||||
schema.entid_map.insert(e, i.clone());
|
schema.entid_map.insert(e, i.clone());
|
||||||
schema.ident_map.insert(i.clone(), e);
|
schema.ident_map.insert(i.clone(), e);
|
||||||
}
|
}
|
||||||
|
@ -1167,7 +1167,7 @@ fn add_attribute(schema: &mut Schema, e: Entid, a: Attribute) {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub(crate) fn ident(ns: &str, name: &str) -> PatternNonValuePlace {
|
pub(crate) fn ident(ns: &str, name: &str) -> PatternNonValuePlace {
|
||||||
NamespacedKeyword::new(ns, name).into()
|
Keyword::namespaced(ns, name).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -101,7 +101,7 @@ mod testing {
|
||||||
};
|
};
|
||||||
|
|
||||||
use mentat_query::{
|
use mentat_query::{
|
||||||
NamespacedKeyword,
|
Keyword,
|
||||||
PlainSymbol,
|
PlainSymbol,
|
||||||
Variable
|
Variable
|
||||||
};
|
};
|
||||||
|
@ -151,11 +151,11 @@ mod testing {
|
||||||
|
|
||||||
fn prepopulated_schema() -> Schema {
|
fn prepopulated_schema() -> Schema {
|
||||||
let mut schema = Schema::default();
|
let mut schema = Schema::default();
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "name"), 65);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "name"), 65);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "knows"), 66);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "knows"), 66);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "parent"), 67);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "parent"), 67);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "age"), 68);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "age"), 68);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "height"), 69);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "height"), 69);
|
||||||
add_attribute(&mut schema,
|
add_attribute(&mut schema,
|
||||||
65,
|
65,
|
||||||
Attribute {
|
Attribute {
|
||||||
|
|
|
@ -763,7 +763,7 @@ mod testing {
|
||||||
};
|
};
|
||||||
|
|
||||||
use mentat_query::{
|
use mentat_query::{
|
||||||
NamespacedKeyword,
|
Keyword,
|
||||||
Variable,
|
Variable,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -810,11 +810,11 @@ mod testing {
|
||||||
|
|
||||||
fn prepopulated_schema() -> Schema {
|
fn prepopulated_schema() -> Schema {
|
||||||
let mut schema = Schema::default();
|
let mut schema = Schema::default();
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "name"), 65);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "name"), 65);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "knows"), 66);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "knows"), 66);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "parent"), 67);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "parent"), 67);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "age"), 68);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "age"), 68);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "height"), 69);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "height"), 69);
|
||||||
add_attribute(&mut schema, 65, Attribute {
|
add_attribute(&mut schema, 65, Attribute {
|
||||||
value_type: ValueType::String,
|
value_type: ValueType::String,
|
||||||
multival: false,
|
multival: false,
|
||||||
|
@ -855,7 +855,7 @@ mod testing {
|
||||||
[?x :foo/nope3 "Daphne"])]"#;
|
[?x :foo/nope3 "Daphne"])]"#;
|
||||||
let cc = alg(known, query);
|
let cc = alg(known, query);
|
||||||
assert!(cc.is_known_empty());
|
assert!(cc.is_known_empty());
|
||||||
assert_eq!(cc.empty_because, Some(EmptyBecause::UnresolvedIdent(NamespacedKeyword::new("foo", "nope3"))));
|
assert_eq!(cc.empty_because, Some(EmptyBecause::UnresolvedIdent(Keyword::namespaced("foo", "nope3"))));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Test that if only one of the attributes in an `or` resolves, it's equivalent to a simple query.
|
/// Test that if only one of the attributes in an `or` resolves, it's equivalent to a simple query.
|
||||||
|
|
|
@ -654,7 +654,7 @@ mod testing {
|
||||||
};
|
};
|
||||||
|
|
||||||
use mentat_query::{
|
use mentat_query::{
|
||||||
NamespacedKeyword,
|
Keyword,
|
||||||
NonIntegerConstant,
|
NonIntegerConstant,
|
||||||
Variable,
|
Variable,
|
||||||
};
|
};
|
||||||
|
@ -709,7 +709,7 @@ mod testing {
|
||||||
let mut cc = ConjoiningClauses::default();
|
let mut cc = ConjoiningClauses::default();
|
||||||
let mut schema = Schema::default();
|
let mut schema = Schema::default();
|
||||||
|
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "bar"), 99);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "bar"), 99);
|
||||||
|
|
||||||
let known = Known::for_schema(&schema);
|
let known = Known::for_schema(&schema);
|
||||||
cc.apply_parsed_pattern(known, Pattern {
|
cc.apply_parsed_pattern(known, Pattern {
|
||||||
|
@ -728,7 +728,7 @@ mod testing {
|
||||||
let mut cc = ConjoiningClauses::default();
|
let mut cc = ConjoiningClauses::default();
|
||||||
let mut schema = Schema::default();
|
let mut schema = Schema::default();
|
||||||
|
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "bar"), 99);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "bar"), 99);
|
||||||
add_attribute(&mut schema, 99, Attribute {
|
add_attribute(&mut schema, 99, Attribute {
|
||||||
value_type: ValueType::Boolean,
|
value_type: ValueType::Boolean,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -814,7 +814,7 @@ mod testing {
|
||||||
fn test_apply_unattributed_but_bound_pattern_with_returned() {
|
fn test_apply_unattributed_but_bound_pattern_with_returned() {
|
||||||
let mut cc = ConjoiningClauses::default();
|
let mut cc = ConjoiningClauses::default();
|
||||||
let mut schema = Schema::default();
|
let mut schema = Schema::default();
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "bar"), 99);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "bar"), 99);
|
||||||
add_attribute(&mut schema, 99, Attribute {
|
add_attribute(&mut schema, 99, Attribute {
|
||||||
value_type: ValueType::Boolean,
|
value_type: ValueType::Boolean,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -962,8 +962,8 @@ mod testing {
|
||||||
let mut cc = ConjoiningClauses::default();
|
let mut cc = ConjoiningClauses::default();
|
||||||
let mut schema = Schema::default();
|
let mut schema = Schema::default();
|
||||||
|
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "bar"), 99);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "bar"), 99);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "roz"), 98);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "roz"), 98);
|
||||||
add_attribute(&mut schema, 99, Attribute {
|
add_attribute(&mut schema, 99, Attribute {
|
||||||
value_type: ValueType::Boolean,
|
value_type: ValueType::Boolean,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -1035,7 +1035,7 @@ mod testing {
|
||||||
fn test_value_bindings() {
|
fn test_value_bindings() {
|
||||||
let mut schema = Schema::default();
|
let mut schema = Schema::default();
|
||||||
|
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "bar"), 99);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "bar"), 99);
|
||||||
add_attribute(&mut schema, 99, Attribute {
|
add_attribute(&mut schema, 99, Attribute {
|
||||||
value_type: ValueType::Boolean,
|
value_type: ValueType::Boolean,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -1083,7 +1083,7 @@ mod testing {
|
||||||
fn test_value_bindings_type_disagreement() {
|
fn test_value_bindings_type_disagreement() {
|
||||||
let mut schema = Schema::default();
|
let mut schema = Schema::default();
|
||||||
|
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "bar"), 99);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "bar"), 99);
|
||||||
add_attribute(&mut schema, 99, Attribute {
|
add_attribute(&mut schema, 99, Attribute {
|
||||||
value_type: ValueType::Boolean,
|
value_type: ValueType::Boolean,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -1117,7 +1117,7 @@ mod testing {
|
||||||
fn test_fulltext_type_disagreement() {
|
fn test_fulltext_type_disagreement() {
|
||||||
let mut schema = Schema::default();
|
let mut schema = Schema::default();
|
||||||
|
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "bar"), 99);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "bar"), 99);
|
||||||
add_attribute(&mut schema, 99, Attribute {
|
add_attribute(&mut schema, 99, Attribute {
|
||||||
value_type: ValueType::String,
|
value_type: ValueType::String,
|
||||||
index: true,
|
index: true,
|
||||||
|
@ -1155,8 +1155,8 @@ mod testing {
|
||||||
let mut cc = ConjoiningClauses::default();
|
let mut cc = ConjoiningClauses::default();
|
||||||
let mut schema = Schema::default();
|
let mut schema = Schema::default();
|
||||||
|
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "bar"), 99);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "bar"), 99);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "roz"), 98);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "roz"), 98);
|
||||||
add_attribute(&mut schema, 99, Attribute {
|
add_attribute(&mut schema, 99, Attribute {
|
||||||
value_type: ValueType::Boolean,
|
value_type: ValueType::Boolean,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -1244,7 +1244,7 @@ mod testing {
|
||||||
fn ensure_extracted_types_is_cleared() {
|
fn ensure_extracted_types_is_cleared() {
|
||||||
let query = r#"[:find ?e ?v :where [_ _ ?v] [?e :foo/bar ?v]]"#;
|
let query = r#"[:find ?e ?v :where [_ _ ?v] [?e :foo/bar ?v]]"#;
|
||||||
let mut schema = Schema::default();
|
let mut schema = Schema::default();
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "bar"), 99);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "bar"), 99);
|
||||||
add_attribute(&mut schema, 99, Attribute {
|
add_attribute(&mut schema, 99, Attribute {
|
||||||
value_type: ValueType::Boolean,
|
value_type: ValueType::Boolean,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
|
|
@ -192,7 +192,7 @@ mod testing {
|
||||||
|
|
||||||
use mentat_query::{
|
use mentat_query::{
|
||||||
FnArg,
|
FnArg,
|
||||||
NamespacedKeyword,
|
Keyword,
|
||||||
Pattern,
|
Pattern,
|
||||||
PatternNonValuePlace,
|
PatternNonValuePlace,
|
||||||
PatternValuePlace,
|
PatternValuePlace,
|
||||||
|
@ -220,7 +220,7 @@ mod testing {
|
||||||
let mut cc = ConjoiningClauses::default();
|
let mut cc = ConjoiningClauses::default();
|
||||||
let mut schema = Schema::default();
|
let mut schema = Schema::default();
|
||||||
|
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "bar"), 99);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "bar"), 99);
|
||||||
add_attribute(&mut schema, 99, Attribute {
|
add_attribute(&mut schema, 99, Attribute {
|
||||||
value_type: ValueType::Long,
|
value_type: ValueType::Long,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -238,8 +238,8 @@ mod testing {
|
||||||
});
|
});
|
||||||
assert!(!cc.is_known_empty());
|
assert!(!cc.is_known_empty());
|
||||||
|
|
||||||
let op = PlainSymbol::new("<");
|
let op = PlainSymbol::plain("<");
|
||||||
let comp = Inequality::from_datalog_operator(op.plain_name()).unwrap();
|
let comp = Inequality::from_datalog_operator(op.name()).unwrap();
|
||||||
assert!(cc.apply_inequality(known, comp, Predicate {
|
assert!(cc.apply_inequality(known, comp, Predicate {
|
||||||
operator: op,
|
operator: op,
|
||||||
args: vec![
|
args: vec![
|
||||||
|
@ -275,8 +275,8 @@ mod testing {
|
||||||
let mut cc = ConjoiningClauses::default();
|
let mut cc = ConjoiningClauses::default();
|
||||||
let mut schema = Schema::default();
|
let mut schema = Schema::default();
|
||||||
|
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "bar"), 99);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "bar"), 99);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "roz"), 98);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "roz"), 98);
|
||||||
add_attribute(&mut schema, 99, Attribute {
|
add_attribute(&mut schema, 99, Attribute {
|
||||||
value_type: ValueType::Long,
|
value_type: ValueType::Long,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -299,8 +299,8 @@ mod testing {
|
||||||
});
|
});
|
||||||
assert!(!cc.is_known_empty());
|
assert!(!cc.is_known_empty());
|
||||||
|
|
||||||
let op = PlainSymbol::new(">=");
|
let op = PlainSymbol::plain(">=");
|
||||||
let comp = Inequality::from_datalog_operator(op.plain_name()).unwrap();
|
let comp = Inequality::from_datalog_operator(op.name()).unwrap();
|
||||||
assert!(cc.apply_inequality(known, comp, Predicate {
|
assert!(cc.apply_inequality(known, comp, Predicate {
|
||||||
operator: op,
|
operator: op,
|
||||||
args: vec![
|
args: vec![
|
||||||
|
|
|
@ -268,7 +268,7 @@ mod testing {
|
||||||
|
|
||||||
let known = Known::for_schema(&schema);
|
let known = Known::for_schema(&schema);
|
||||||
|
|
||||||
let op = PlainSymbol::new("tx-ids");
|
let op = PlainSymbol::plain("tx-ids");
|
||||||
cc.apply_tx_ids(known, WhereFn {
|
cc.apply_tx_ids(known, WhereFn {
|
||||||
operator: op,
|
operator: op,
|
||||||
args: vec![
|
args: vec![
|
||||||
|
@ -323,7 +323,7 @@ mod testing {
|
||||||
|
|
||||||
let known = Known::for_schema(&schema);
|
let known = Known::for_schema(&schema);
|
||||||
|
|
||||||
let op = PlainSymbol::new("tx-data");
|
let op = PlainSymbol::plain("tx-data");
|
||||||
cc.apply_tx_data(known, WhereFn {
|
cc.apply_tx_data(known, WhereFn {
|
||||||
operator: op,
|
operator: op,
|
||||||
args: vec![
|
args: vec![
|
||||||
|
|
|
@ -25,7 +25,7 @@ use mentat_core::{
|
||||||
|
|
||||||
use mentat_query::{
|
use mentat_query::{
|
||||||
Direction,
|
Direction,
|
||||||
NamespacedKeyword,
|
Keyword,
|
||||||
Order,
|
Order,
|
||||||
SrcVar,
|
SrcVar,
|
||||||
Variable,
|
Variable,
|
||||||
|
@ -617,8 +617,8 @@ pub enum EmptyBecause {
|
||||||
NonEntityArgument,
|
NonEntityArgument,
|
||||||
NonStringFulltextValue,
|
NonStringFulltextValue,
|
||||||
NonFulltextAttribute(Entid),
|
NonFulltextAttribute(Entid),
|
||||||
UnresolvedIdent(NamespacedKeyword),
|
UnresolvedIdent(Keyword),
|
||||||
InvalidAttributeIdent(NamespacedKeyword),
|
InvalidAttributeIdent(Keyword),
|
||||||
InvalidAttributeEntid(Entid),
|
InvalidAttributeEntid(Entid),
|
||||||
InvalidBinding(Column, TypedValue),
|
InvalidBinding(Column, TypedValue),
|
||||||
ValueTypeMismatch(ValueType, TypedValue),
|
ValueTypeMismatch(ValueType, TypedValue),
|
||||||
|
@ -708,7 +708,7 @@ pub enum EvolvedValuePlace {
|
||||||
Entid(Entid),
|
Entid(Entid),
|
||||||
Value(TypedValue),
|
Value(TypedValue),
|
||||||
EntidOrInteger(i64),
|
EntidOrInteger(i64),
|
||||||
IdentOrKeyword(ValueRc<NamespacedKeyword>),
|
IdentOrKeyword(ValueRc<Keyword>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum PlaceOrEmpty<T> {
|
pub enum PlaceOrEmpty<T> {
|
||||||
|
|
|
@ -100,7 +100,7 @@ mod tests {
|
||||||
|
|
||||||
use self::mentat_query::{
|
use self::mentat_query::{
|
||||||
FindQuery,
|
FindQuery,
|
||||||
NamespacedKeyword,
|
Keyword,
|
||||||
OrWhereClause,
|
OrWhereClause,
|
||||||
Pattern,
|
Pattern,
|
||||||
PatternNonValuePlace,
|
PatternNonValuePlace,
|
||||||
|
@ -120,7 +120,7 @@ mod tests {
|
||||||
};
|
};
|
||||||
|
|
||||||
fn value_ident(ns: &str, name: &str) -> PatternValuePlace {
|
fn value_ident(ns: &str, name: &str) -> PatternValuePlace {
|
||||||
NamespacedKeyword::new(ns, name).into()
|
Keyword::namespaced(ns, name).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tests that the top-level form is a valid `or`, returning the clauses.
|
/// Tests that the top-level form is a valid `or`, returning the clauses.
|
||||||
|
|
|
@ -22,7 +22,7 @@ use mentat_core::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use mentat_query::{
|
use mentat_query::{
|
||||||
NamespacedKeyword,
|
Keyword,
|
||||||
};
|
};
|
||||||
|
|
||||||
use utils::{
|
use utils::{
|
||||||
|
@ -35,11 +35,11 @@ use mentat_query_algebrizer::Known;
|
||||||
|
|
||||||
fn prepopulated_schema() -> Schema {
|
fn prepopulated_schema() -> Schema {
|
||||||
let mut schema = Schema::default();
|
let mut schema = Schema::default();
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "name"), 65);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "name"), 65);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "description"), 66);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "description"), 66);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "parent"), 67);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "parent"), 67);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "age"), 68);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "age"), 68);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "height"), 69);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "height"), 69);
|
||||||
add_attribute(&mut schema, 65, Attribute {
|
add_attribute(&mut schema, 65, Attribute {
|
||||||
value_type: ValueType::String,
|
value_type: ValueType::String,
|
||||||
multival: false,
|
multival: false,
|
||||||
|
|
|
@ -25,7 +25,7 @@ use mentat_core::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use mentat_query::{
|
use mentat_query::{
|
||||||
NamespacedKeyword,
|
Keyword,
|
||||||
PlainSymbol,
|
PlainSymbol,
|
||||||
Variable,
|
Variable,
|
||||||
};
|
};
|
||||||
|
@ -49,11 +49,11 @@ use utils::{
|
||||||
|
|
||||||
fn prepopulated_schema() -> Schema {
|
fn prepopulated_schema() -> Schema {
|
||||||
let mut schema = Schema::default();
|
let mut schema = Schema::default();
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "name"), 65);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "name"), 65);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "knows"), 66);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "knows"), 66);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "parent"), 67);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "parent"), 67);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "age"), 68);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "age"), 68);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "height"), 69);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "height"), 69);
|
||||||
add_attribute(&mut schema, 65, Attribute {
|
add_attribute(&mut schema, 65, Attribute {
|
||||||
value_type: ValueType::String,
|
value_type: ValueType::String,
|
||||||
multival: false,
|
multival: false,
|
||||||
|
@ -276,7 +276,7 @@ fn test_ground_tuple_duplicate_vars() {
|
||||||
let e = bails(known, &q);
|
let e = bails(known, &q);
|
||||||
match e {
|
match e {
|
||||||
Error(ErrorKind::InvalidBinding(v, e), _) => {
|
Error(ErrorKind::InvalidBinding(v, e), _) => {
|
||||||
assert_eq!(v, PlainSymbol::new("ground"));
|
assert_eq!(v, PlainSymbol::plain("ground"));
|
||||||
assert_eq!(e, BindingError::RepeatedBoundVariable);
|
assert_eq!(e, BindingError::RepeatedBoundVariable);
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -293,7 +293,7 @@ fn test_ground_rel_duplicate_vars() {
|
||||||
let e = bails(known, &q);
|
let e = bails(known, &q);
|
||||||
match e {
|
match e {
|
||||||
Error(ErrorKind::InvalidBinding(v, e), _) => {
|
Error(ErrorKind::InvalidBinding(v, e), _) => {
|
||||||
assert_eq!(v, PlainSymbol::new("ground"));
|
assert_eq!(v, PlainSymbol::plain("ground"));
|
||||||
assert_eq!(e, BindingError::RepeatedBoundVariable);
|
assert_eq!(e, BindingError::RepeatedBoundVariable);
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
|
|
|
@ -26,7 +26,7 @@ use mentat_core::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use mentat_query::{
|
use mentat_query::{
|
||||||
NamespacedKeyword,
|
Keyword,
|
||||||
PlainSymbol,
|
PlainSymbol,
|
||||||
Variable,
|
Variable,
|
||||||
};
|
};
|
||||||
|
@ -48,9 +48,9 @@ use utils::{
|
||||||
|
|
||||||
fn prepopulated_schema() -> Schema {
|
fn prepopulated_schema() -> Schema {
|
||||||
let mut schema = Schema::default();
|
let mut schema = Schema::default();
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "date"), 65);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "date"), 65);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "double"), 66);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "double"), 66);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "long"), 67);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "long"), 67);
|
||||||
add_attribute(&mut schema, 65, Attribute {
|
add_attribute(&mut schema, 65, Attribute {
|
||||||
value_type: ValueType::Instant,
|
value_type: ValueType::Instant,
|
||||||
multival: false,
|
multival: false,
|
||||||
|
@ -81,7 +81,7 @@ fn test_instant_predicates_require_instants() {
|
||||||
[(> ?t "2017-06-16T00:56:41.257Z")]]"#;
|
[(> ?t "2017-06-16T00:56:41.257Z")]]"#;
|
||||||
match bails(known, query).0 {
|
match bails(known, query).0 {
|
||||||
ErrorKind::InvalidArgumentType(op, why, idx) => {
|
ErrorKind::InvalidArgumentType(op, why, idx) => {
|
||||||
assert_eq!(op, PlainSymbol::new(">"));
|
assert_eq!(op, PlainSymbol::plain(">"));
|
||||||
assert_eq!(why, ValueTypeSet::of_numeric_and_instant_types());
|
assert_eq!(why, ValueTypeSet::of_numeric_and_instant_types());
|
||||||
assert_eq!(idx, 1);
|
assert_eq!(idx, 1);
|
||||||
},
|
},
|
||||||
|
@ -94,7 +94,7 @@ fn test_instant_predicates_require_instants() {
|
||||||
[(> "2017-06-16T00:56:41.257Z", ?t)]]"#;
|
[(> "2017-06-16T00:56:41.257Z", ?t)]]"#;
|
||||||
match bails(known, query).0 {
|
match bails(known, query).0 {
|
||||||
ErrorKind::InvalidArgumentType(op, why, idx) => {
|
ErrorKind::InvalidArgumentType(op, why, idx) => {
|
||||||
assert_eq!(op, PlainSymbol::new(">"));
|
assert_eq!(op, PlainSymbol::plain(">"));
|
||||||
assert_eq!(why, ValueTypeSet::of_numeric_and_instant_types());
|
assert_eq!(why, ValueTypeSet::of_numeric_and_instant_types());
|
||||||
assert_eq!(idx, 0); // We get this right.
|
assert_eq!(idx, 0); // We get this right.
|
||||||
},
|
},
|
||||||
|
|
|
@ -25,7 +25,7 @@ use mentat_query_parser::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use mentat_query::{
|
use mentat_query::{
|
||||||
NamespacedKeyword,
|
Keyword,
|
||||||
};
|
};
|
||||||
|
|
||||||
use mentat_query_algebrizer::{
|
use mentat_query_algebrizer::{
|
||||||
|
@ -40,7 +40,7 @@ use mentat_query_algebrizer::{
|
||||||
// Common utility functions used in multiple test files.
|
// Common utility functions used in multiple test files.
|
||||||
|
|
||||||
// These are helpers that tests use to build Schema instances.
|
// These are helpers that tests use to build Schema instances.
|
||||||
pub fn associate_ident(schema: &mut Schema, i: NamespacedKeyword, e: Entid) {
|
pub fn associate_ident(schema: &mut Schema, i: Keyword, e: Entid) {
|
||||||
schema.entid_map.insert(e, i.clone());
|
schema.entid_map.insert(e, i.clone());
|
||||||
schema.ident_map.insert(i.clone(), e);
|
schema.ident_map.insert(i.clone(), e);
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ impl SchemaBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn define_attr(mut self, kw: NamespacedKeyword, attr: Attribute) -> Self {
|
pub fn define_attr(mut self, kw: Keyword, attr: Attribute) -> Self {
|
||||||
associate_ident(&mut self.schema, kw, self.counter);
|
associate_ident(&mut self.schema, kw, self.counter);
|
||||||
add_attribute(&mut self.schema, self.counter, attr);
|
add_attribute(&mut self.schema, self.counter, attr);
|
||||||
self.counter += 1;
|
self.counter += 1;
|
||||||
|
@ -74,9 +74,9 @@ impl SchemaBuilder {
|
||||||
keyword_name: T,
|
keyword_name: T,
|
||||||
value_type: ValueType,
|
value_type: ValueType,
|
||||||
multival: bool) -> Self
|
multival: bool) -> Self
|
||||||
where T: Into<String>
|
where T: AsRef<str>
|
||||||
{
|
{
|
||||||
self.define_attr(NamespacedKeyword::new(keyword_ns, keyword_name), Attribute {
|
self.define_attr(Keyword::namespaced(keyword_ns, keyword_name), Attribute {
|
||||||
value_type,
|
value_type,
|
||||||
multival,
|
multival,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
|
|
@ -734,22 +734,22 @@ mod test {
|
||||||
Variable(Rc::new(x))
|
Variable(Rc::new(x))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ident_kw(kw: edn::NamespacedKeyword) -> PatternNonValuePlace {
|
fn ident_kw(kw: edn::Keyword) -> PatternNonValuePlace {
|
||||||
PatternNonValuePlace::Ident(kw.into())
|
PatternNonValuePlace::Ident(kw.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ident(ns: &str, name: &str) -> PatternNonValuePlace {
|
fn ident(ns: &str, name: &str) -> PatternNonValuePlace {
|
||||||
ident_kw(edn::NamespacedKeyword::new(ns, name))
|
ident_kw(edn::Keyword::namespaced(ns, name))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_pattern_mixed() {
|
fn test_pattern_mixed() {
|
||||||
let e = edn::PlainSymbol::new("_");
|
let e = edn::PlainSymbol::plain("_");
|
||||||
let a = edn::NamespacedKeyword::new("foo", "bar");
|
let a = edn::Keyword::namespaced("foo", "bar");
|
||||||
let v = OrderedFloat(99.9);
|
let v = OrderedFloat(99.9);
|
||||||
let tx = edn::PlainSymbol::new("?tx");
|
let tx = edn::PlainSymbol::plain("?tx");
|
||||||
let input = edn::Value::Vector(vec!(edn::Value::PlainSymbol(e.clone()),
|
let input = edn::Value::Vector(vec!(edn::Value::PlainSymbol(e.clone()),
|
||||||
edn::Value::NamespacedKeyword(a.clone()),
|
edn::Value::Keyword(a.clone()),
|
||||||
edn::Value::Float(v.clone()),
|
edn::Value::Float(v.clone()),
|
||||||
edn::Value::PlainSymbol(tx.clone())));
|
edn::Value::PlainSymbol(tx.clone())));
|
||||||
assert_parses_to!(Where::pattern, input, WhereClause::Pattern(Pattern {
|
assert_parses_to!(Where::pattern, input, WhereClause::Pattern(Pattern {
|
||||||
|
@ -763,11 +763,11 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_pattern_vars() {
|
fn test_pattern_vars() {
|
||||||
let s = edn::PlainSymbol::new("$x");
|
let s = edn::PlainSymbol::plain("$x");
|
||||||
let e = edn::PlainSymbol::new("?e");
|
let e = edn::PlainSymbol::plain("?e");
|
||||||
let a = edn::PlainSymbol::new("?a");
|
let a = edn::PlainSymbol::plain("?a");
|
||||||
let v = edn::PlainSymbol::new("?v");
|
let v = edn::PlainSymbol::plain("?v");
|
||||||
let tx = edn::PlainSymbol::new("?tx");
|
let tx = edn::PlainSymbol::plain("?tx");
|
||||||
let input = edn::Value::Vector(vec!(edn::Value::PlainSymbol(s.clone()),
|
let input = edn::Value::Vector(vec!(edn::Value::PlainSymbol(s.clone()),
|
||||||
edn::Value::PlainSymbol(e.clone()),
|
edn::Value::PlainSymbol(e.clone()),
|
||||||
edn::Value::PlainSymbol(a.clone()),
|
edn::Value::PlainSymbol(a.clone()),
|
||||||
|
@ -784,12 +784,12 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_pattern_reversed_invalid() {
|
fn test_pattern_reversed_invalid() {
|
||||||
let e = edn::PlainSymbol::new("_");
|
let e = edn::PlainSymbol::plain("_");
|
||||||
let a = edn::NamespacedKeyword::new("foo", "_bar");
|
let a = edn::Keyword::namespaced("foo", "_bar");
|
||||||
let v = OrderedFloat(99.9);
|
let v = OrderedFloat(99.9);
|
||||||
let tx = edn::PlainSymbol::new("?tx");
|
let tx = edn::PlainSymbol::plain("?tx");
|
||||||
let input = edn::Value::Vector(vec!(edn::Value::PlainSymbol(e.clone()),
|
let input = edn::Value::Vector(vec!(edn::Value::PlainSymbol(e.clone()),
|
||||||
edn::Value::NamespacedKeyword(a.clone()),
|
edn::Value::Keyword(a.clone()),
|
||||||
edn::Value::Float(v.clone()),
|
edn::Value::Float(v.clone()),
|
||||||
edn::Value::PlainSymbol(tx.clone())));
|
edn::Value::PlainSymbol(tx.clone())));
|
||||||
|
|
||||||
|
@ -801,12 +801,12 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_pattern_reversed() {
|
fn test_pattern_reversed() {
|
||||||
let e = edn::PlainSymbol::new("_");
|
let e = edn::PlainSymbol::plain("_");
|
||||||
let a = edn::NamespacedKeyword::new("foo", "_bar");
|
let a = edn::Keyword::namespaced("foo", "_bar");
|
||||||
let v = edn::PlainSymbol::new("?v");
|
let v = edn::PlainSymbol::plain("?v");
|
||||||
let tx = edn::PlainSymbol::new("?tx");
|
let tx = edn::PlainSymbol::plain("?tx");
|
||||||
let input = edn::Value::Vector(vec!(edn::Value::PlainSymbol(e.clone()),
|
let input = edn::Value::Vector(vec!(edn::Value::PlainSymbol(e.clone()),
|
||||||
edn::Value::NamespacedKeyword(a.clone()),
|
edn::Value::Keyword(a.clone()),
|
||||||
edn::Value::PlainSymbol(v.clone()),
|
edn::Value::PlainSymbol(v.clone()),
|
||||||
edn::Value::PlainSymbol(tx.clone())));
|
edn::Value::PlainSymbol(tx.clone())));
|
||||||
|
|
||||||
|
@ -823,7 +823,7 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rule_vars() {
|
fn test_rule_vars() {
|
||||||
let e = edn::PlainSymbol::new("?e");
|
let e = edn::PlainSymbol::plain("?e");
|
||||||
let input = edn::Value::Vector(vec![edn::Value::PlainSymbol(e.clone())]);
|
let input = edn::Value::Vector(vec![edn::Value::PlainSymbol(e.clone())]);
|
||||||
assert_parses_to!(Where::rule_vars, input,
|
assert_parses_to!(Where::rule_vars, input,
|
||||||
btreeset!{variable(e.clone())});
|
btreeset!{variable(e.clone())});
|
||||||
|
@ -831,14 +831,14 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_repeated_vars() {
|
fn test_repeated_vars() {
|
||||||
let e = edn::PlainSymbol::new("?e");
|
let e = edn::PlainSymbol::plain("?e");
|
||||||
let f = edn::PlainSymbol::new("?f");
|
let f = edn::PlainSymbol::plain("?f");
|
||||||
let input = edn::Value::Vector(vec![edn::Value::PlainSymbol(e.clone()),
|
let input = edn::Value::Vector(vec![edn::Value::PlainSymbol(e.clone()),
|
||||||
edn::Value::PlainSymbol(f.clone()),]);
|
edn::Value::PlainSymbol(f.clone()),]);
|
||||||
assert_parses_to!(|| vector().of_exactly(Find::vars()), input,
|
assert_parses_to!(|| vector().of_exactly(Find::vars()), input,
|
||||||
btreeset!{variable(e.clone()), variable(f.clone())});
|
btreeset!{variable(e.clone()), variable(f.clone())});
|
||||||
|
|
||||||
let g = edn::PlainSymbol::new("?g");
|
let g = edn::PlainSymbol::plain("?g");
|
||||||
let input = edn::Value::Vector(vec![edn::Value::PlainSymbol(g.clone()),
|
let input = edn::Value::Vector(vec![edn::Value::PlainSymbol(g.clone()),
|
||||||
edn::Value::PlainSymbol(g.clone()),]);
|
edn::Value::PlainSymbol(g.clone()),]);
|
||||||
|
|
||||||
|
@ -859,10 +859,10 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_or() {
|
fn test_or() {
|
||||||
let oj = edn::PlainSymbol::new("or");
|
let oj = edn::PlainSymbol::plain("or");
|
||||||
let e = edn::PlainSymbol::new("?e");
|
let e = edn::PlainSymbol::plain("?e");
|
||||||
let a = edn::PlainSymbol::new("?a");
|
let a = edn::PlainSymbol::plain("?a");
|
||||||
let v = edn::PlainSymbol::new("?v");
|
let v = edn::PlainSymbol::plain("?v");
|
||||||
let input = edn::Value::List(
|
let input = edn::Value::List(
|
||||||
vec![edn::Value::PlainSymbol(oj),
|
vec![edn::Value::PlainSymbol(oj),
|
||||||
edn::Value::Vector(vec![edn::Value::PlainSymbol(e.clone()),
|
edn::Value::Vector(vec![edn::Value::PlainSymbol(e.clone()),
|
||||||
|
@ -883,10 +883,10 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_or_join() {
|
fn test_or_join() {
|
||||||
let oj = edn::PlainSymbol::new("or-join");
|
let oj = edn::PlainSymbol::plain("or-join");
|
||||||
let e = edn::PlainSymbol::new("?e");
|
let e = edn::PlainSymbol::plain("?e");
|
||||||
let a = edn::PlainSymbol::new("?a");
|
let a = edn::PlainSymbol::plain("?a");
|
||||||
let v = edn::PlainSymbol::new("?v");
|
let v = edn::PlainSymbol::plain("?v");
|
||||||
let input = edn::Value::List(
|
let input = edn::Value::List(
|
||||||
vec![edn::Value::PlainSymbol(oj),
|
vec![edn::Value::PlainSymbol(oj),
|
||||||
edn::Value::Vector(vec![edn::Value::PlainSymbol(e.clone())]),
|
edn::Value::Vector(vec![edn::Value::PlainSymbol(e.clone())]),
|
||||||
|
@ -908,9 +908,9 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_not() {
|
fn test_not() {
|
||||||
let e = edn::PlainSymbol::new("?e");
|
let e = edn::PlainSymbol::plain("?e");
|
||||||
let a = edn::PlainSymbol::new("?a");
|
let a = edn::PlainSymbol::plain("?a");
|
||||||
let v = edn::PlainSymbol::new("?v");
|
let v = edn::PlainSymbol::plain("?v");
|
||||||
|
|
||||||
assert_edn_parses_to!(Where::not_clause,
|
assert_edn_parses_to!(Where::not_clause,
|
||||||
"(not [?e ?a ?v])",
|
"(not [?e ?a ?v])",
|
||||||
|
@ -930,9 +930,9 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_not_join() {
|
fn test_not_join() {
|
||||||
let e = edn::PlainSymbol::new("?e");
|
let e = edn::PlainSymbol::plain("?e");
|
||||||
let a = edn::PlainSymbol::new("?a");
|
let a = edn::PlainSymbol::plain("?a");
|
||||||
let v = edn::PlainSymbol::new("?v");
|
let v = edn::PlainSymbol::plain("?v");
|
||||||
|
|
||||||
assert_edn_parses_to!(Where::not_join_clause,
|
assert_edn_parses_to!(Where::not_join_clause,
|
||||||
"(not-join [?e] [?e ?a ?v])",
|
"(not-join [?e] [?e ?a ?v])",
|
||||||
|
@ -951,15 +951,15 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_find_sp_variable() {
|
fn test_find_sp_variable() {
|
||||||
let sym = edn::PlainSymbol::new("?x");
|
let sym = edn::PlainSymbol::plain("?x");
|
||||||
let input = edn::Value::Vector(vec![edn::Value::PlainSymbol(sym.clone())]);
|
let input = edn::Value::Vector(vec![edn::Value::PlainSymbol(sym.clone())]);
|
||||||
assert_parses_to!(|| vector().of_exactly(Query::variable()), input, variable(sym));
|
assert_parses_to!(|| vector().of_exactly(Query::variable()), input, variable(sym));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_find_scalar() {
|
fn test_find_scalar() {
|
||||||
let sym = edn::PlainSymbol::new("?x");
|
let sym = edn::PlainSymbol::plain("?x");
|
||||||
let period = edn::PlainSymbol::new(".");
|
let period = edn::PlainSymbol::plain(".");
|
||||||
let input = edn::Value::Vector(vec![edn::Value::PlainSymbol(sym.clone()), edn::Value::PlainSymbol(period.clone())]);
|
let input = edn::Value::Vector(vec![edn::Value::PlainSymbol(sym.clone()), edn::Value::PlainSymbol(period.clone())]);
|
||||||
assert_parses_to!(|| vector().of_exactly(Find::find_scalar()),
|
assert_parses_to!(|| vector().of_exactly(Find::find_scalar()),
|
||||||
input,
|
input,
|
||||||
|
@ -968,8 +968,8 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_find_coll() {
|
fn test_find_coll() {
|
||||||
let sym = edn::PlainSymbol::new("?x");
|
let sym = edn::PlainSymbol::plain("?x");
|
||||||
let period = edn::PlainSymbol::new("...");
|
let period = edn::PlainSymbol::plain("...");
|
||||||
let input = edn::Value::Vector(vec![edn::Value::PlainSymbol(sym.clone()),
|
let input = edn::Value::Vector(vec![edn::Value::PlainSymbol(sym.clone()),
|
||||||
edn::Value::PlainSymbol(period.clone())]);
|
edn::Value::PlainSymbol(period.clone())]);
|
||||||
assert_parses_to!(Find::find_coll,
|
assert_parses_to!(Find::find_coll,
|
||||||
|
@ -979,8 +979,8 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_find_rel() {
|
fn test_find_rel() {
|
||||||
let vx = edn::PlainSymbol::new("?x");
|
let vx = edn::PlainSymbol::plain("?x");
|
||||||
let vy = edn::PlainSymbol::new("?y");
|
let vy = edn::PlainSymbol::plain("?y");
|
||||||
let input = edn::Value::Vector(vec![edn::Value::PlainSymbol(vx.clone()), edn::Value::PlainSymbol(vy.clone())]);
|
let input = edn::Value::Vector(vec![edn::Value::PlainSymbol(vx.clone()), edn::Value::PlainSymbol(vy.clone())]);
|
||||||
assert_parses_to!(|| vector().of_exactly(Find::find_rel()),
|
assert_parses_to!(|| vector().of_exactly(Find::find_rel()),
|
||||||
input,
|
input,
|
||||||
|
@ -990,8 +990,8 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_find_tuple() {
|
fn test_find_tuple() {
|
||||||
let vx = edn::PlainSymbol::new("?x");
|
let vx = edn::PlainSymbol::plain("?x");
|
||||||
let vy = edn::PlainSymbol::new("?y");
|
let vy = edn::PlainSymbol::plain("?y");
|
||||||
let input = edn::Value::Vector(vec![edn::Value::PlainSymbol(vx.clone()),
|
let input = edn::Value::Vector(vec![edn::Value::PlainSymbol(vx.clone()),
|
||||||
edn::Value::PlainSymbol(vy.clone())]);
|
edn::Value::PlainSymbol(vy.clone())]);
|
||||||
assert_parses_to!(Find::find_tuple,
|
assert_parses_to!(Find::find_tuple,
|
||||||
|
@ -1033,8 +1033,8 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fn_arg_collections() {
|
fn test_fn_arg_collections() {
|
||||||
let vx = edn::PlainSymbol::new("?x");
|
let vx = edn::PlainSymbol::plain("?x");
|
||||||
let vy = edn::PlainSymbol::new("?y");
|
let vy = edn::PlainSymbol::plain("?y");
|
||||||
let input = edn::Value::Vector(vec![edn::Value::Vector(vec![edn::Value::PlainSymbol(vx.clone()),
|
let input = edn::Value::Vector(vec![edn::Value::Vector(vec![edn::Value::PlainSymbol(vx.clone()),
|
||||||
edn::Value::PlainSymbol(vy.clone())])]);
|
edn::Value::PlainSymbol(vy.clone())])]);
|
||||||
|
|
||||||
|
@ -1047,7 +1047,7 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_bind_scalar() {
|
fn test_bind_scalar() {
|
||||||
let vx = edn::PlainSymbol::new("?x");
|
let vx = edn::PlainSymbol::plain("?x");
|
||||||
assert_edn_parses_to!(|| list().of_exactly(Bind::binding()),
|
assert_edn_parses_to!(|| list().of_exactly(Bind::binding()),
|
||||||
"(?x)",
|
"(?x)",
|
||||||
Binding::BindScalar(variable(vx)));
|
Binding::BindScalar(variable(vx)));
|
||||||
|
@ -1055,7 +1055,7 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_bind_coll() {
|
fn test_bind_coll() {
|
||||||
let vx = edn::PlainSymbol::new("?x");
|
let vx = edn::PlainSymbol::plain("?x");
|
||||||
assert_edn_parses_to!(|| list().of_exactly(Bind::binding()),
|
assert_edn_parses_to!(|| list().of_exactly(Bind::binding()),
|
||||||
"([?x ...])",
|
"([?x ...])",
|
||||||
Binding::BindColl(variable(vx)));
|
Binding::BindColl(variable(vx)));
|
||||||
|
@ -1063,9 +1063,9 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_bind_rel() {
|
fn test_bind_rel() {
|
||||||
let vx = edn::PlainSymbol::new("?x");
|
let vx = edn::PlainSymbol::plain("?x");
|
||||||
let vy = edn::PlainSymbol::new("?y");
|
let vy = edn::PlainSymbol::plain("?y");
|
||||||
let vw = edn::PlainSymbol::new("?w");
|
let vw = edn::PlainSymbol::plain("?w");
|
||||||
assert_edn_parses_to!(|| list().of_exactly(Bind::binding()),
|
assert_edn_parses_to!(|| list().of_exactly(Bind::binding()),
|
||||||
"([[?x ?y _ ?w]])",
|
"([[?x ?y _ ?w]])",
|
||||||
Binding::BindRel(vec![VariableOrPlaceholder::Variable(variable(vx)),
|
Binding::BindRel(vec![VariableOrPlaceholder::Variable(variable(vx)),
|
||||||
|
@ -1077,9 +1077,9 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_bind_tuple() {
|
fn test_bind_tuple() {
|
||||||
let vx = edn::PlainSymbol::new("?x");
|
let vx = edn::PlainSymbol::plain("?x");
|
||||||
let vy = edn::PlainSymbol::new("?y");
|
let vy = edn::PlainSymbol::plain("?y");
|
||||||
let vw = edn::PlainSymbol::new("?w");
|
let vw = edn::PlainSymbol::plain("?w");
|
||||||
assert_edn_parses_to!(|| list().of_exactly(Bind::binding()),
|
assert_edn_parses_to!(|| list().of_exactly(Bind::binding()),
|
||||||
"([?x ?y _ ?w])",
|
"([?x ?y _ ?w])",
|
||||||
Binding::BindTuple(vec![VariableOrPlaceholder::Variable(variable(vx)),
|
Binding::BindTuple(vec![VariableOrPlaceholder::Variable(variable(vx)),
|
||||||
|
@ -1138,7 +1138,7 @@ mod test {
|
||||||
assert_edn_parses_to!(Where::where_fn,
|
assert_edn_parses_to!(Where::where_fn,
|
||||||
"[(f ?x 1) ?y]",
|
"[(f ?x 1) ?y]",
|
||||||
WhereClause::WhereFn(WhereFn {
|
WhereClause::WhereFn(WhereFn {
|
||||||
operator: edn::PlainSymbol::new("f"),
|
operator: edn::PlainSymbol::plain("f"),
|
||||||
args: vec![FnArg::Variable(Variable::from_valid_name("?x")),
|
args: vec![FnArg::Variable(Variable::from_valid_name("?x")),
|
||||||
FnArg::EntidOrInteger(1)],
|
FnArg::EntidOrInteger(1)],
|
||||||
binding: Binding::BindScalar(Variable::from_valid_name("?y")),
|
binding: Binding::BindScalar(Variable::from_valid_name("?y")),
|
||||||
|
@ -1147,7 +1147,7 @@ mod test {
|
||||||
assert_edn_parses_to!(Where::where_fn,
|
assert_edn_parses_to!(Where::where_fn,
|
||||||
"[(f ?x) [?y ...]]",
|
"[(f ?x) [?y ...]]",
|
||||||
WhereClause::WhereFn(WhereFn {
|
WhereClause::WhereFn(WhereFn {
|
||||||
operator: edn::PlainSymbol::new("f"),
|
operator: edn::PlainSymbol::plain("f"),
|
||||||
args: vec![FnArg::Variable(Variable::from_valid_name("?x"))],
|
args: vec![FnArg::Variable(Variable::from_valid_name("?x"))],
|
||||||
binding: Binding::BindColl(Variable::from_valid_name("?y")),
|
binding: Binding::BindColl(Variable::from_valid_name("?y")),
|
||||||
}));
|
}));
|
||||||
|
@ -1155,7 +1155,7 @@ mod test {
|
||||||
assert_edn_parses_to!(Where::where_fn,
|
assert_edn_parses_to!(Where::where_fn,
|
||||||
"[(f) [?y _]]",
|
"[(f) [?y _]]",
|
||||||
WhereClause::WhereFn(WhereFn {
|
WhereClause::WhereFn(WhereFn {
|
||||||
operator: edn::PlainSymbol::new("f"),
|
operator: edn::PlainSymbol::plain("f"),
|
||||||
args: vec![],
|
args: vec![],
|
||||||
binding: Binding::BindTuple(vec![VariableOrPlaceholder::Variable(Variable::from_valid_name("?y")),
|
binding: Binding::BindTuple(vec![VariableOrPlaceholder::Variable(Variable::from_valid_name("?y")),
|
||||||
VariableOrPlaceholder::Placeholder]),
|
VariableOrPlaceholder::Placeholder]),
|
||||||
|
@ -1164,7 +1164,7 @@ mod test {
|
||||||
assert_edn_parses_to!(Where::where_fn,
|
assert_edn_parses_to!(Where::where_fn,
|
||||||
"[(f) [[_ ?y]]]",
|
"[(f) [[_ ?y]]]",
|
||||||
WhereClause::WhereFn(WhereFn {
|
WhereClause::WhereFn(WhereFn {
|
||||||
operator: edn::PlainSymbol::new("f"),
|
operator: edn::PlainSymbol::plain("f"),
|
||||||
args: vec![],
|
args: vec![],
|
||||||
binding: Binding::BindRel(vec![VariableOrPlaceholder::Placeholder,
|
binding: Binding::BindRel(vec![VariableOrPlaceholder::Placeholder,
|
||||||
VariableOrPlaceholder::Variable(Variable::from_valid_name("?y"))]),
|
VariableOrPlaceholder::Variable(Variable::from_valid_name("?y"))]),
|
||||||
|
@ -1203,8 +1203,8 @@ mod test {
|
||||||
patterns: vec![PullAttributeSpec::Wildcard],
|
patterns: vec![PullAttributeSpec::Wildcard],
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let foo_bar = ::std::rc::Rc::new(edn::NamespacedKeyword::new("foo", "bar"));
|
let foo_bar = ::std::rc::Rc::new(edn::Keyword::namespaced("foo", "bar"));
|
||||||
let foo_baz = ::std::rc::Rc::new(edn::NamespacedKeyword::new("foo", "baz"));
|
let foo_baz = ::std::rc::Rc::new(edn::Keyword::namespaced("foo", "baz"));
|
||||||
assert_edn_parses_to!(Query::pull_concrete_attribute,
|
assert_edn_parses_to!(Query::pull_concrete_attribute,
|
||||||
":foo/bar",
|
":foo/bar",
|
||||||
PullAttributeSpec::Attribute(
|
PullAttributeSpec::Attribute(
|
||||||
|
@ -1241,7 +1241,7 @@ mod test {
|
||||||
patterns: vec![
|
patterns: vec![
|
||||||
PullAttributeSpec::Attribute(
|
PullAttributeSpec::Attribute(
|
||||||
PullConcreteAttribute::Ident(
|
PullConcreteAttribute::Ident(
|
||||||
::std::rc::Rc::new(edn::NamespacedKeyword::new("foo", "bar"))
|
::std::rc::Rc::new(edn::Keyword::namespaced("foo", "bar"))
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
] })]),
|
] })]),
|
||||||
|
|
|
@ -17,7 +17,7 @@ extern crate mentat_query;
|
||||||
extern crate mentat_query_parser;
|
extern crate mentat_query_parser;
|
||||||
|
|
||||||
use edn::{
|
use edn::{
|
||||||
NamespacedKeyword,
|
Keyword,
|
||||||
PlainSymbol,
|
PlainSymbol,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ fn can_parse_predicates() {
|
||||||
value: PatternValuePlace::Variable(Variable::from_valid_name("?y")),
|
value: PatternValuePlace::Variable(Variable::from_valid_name("?y")),
|
||||||
tx: PatternNonValuePlace::Placeholder,
|
tx: PatternNonValuePlace::Placeholder,
|
||||||
}),
|
}),
|
||||||
WhereClause::Pred(Predicate { operator: PlainSymbol::new("<"), args: vec![
|
WhereClause::Pred(Predicate { operator: PlainSymbol::plain("<"), args: vec![
|
||||||
FnArg::Variable(Variable::from_valid_name("?y")), FnArg::EntidOrInteger(10),
|
FnArg::Variable(Variable::from_valid_name("?y")), FnArg::EntidOrInteger(10),
|
||||||
]}),
|
]}),
|
||||||
]);
|
]);
|
||||||
|
@ -162,7 +162,7 @@ fn can_parse_simple_or_join() {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
fn ident(ns: &str, name: &str) -> PatternNonValuePlace {
|
fn ident(ns: &str, name: &str) -> PatternNonValuePlace {
|
||||||
NamespacedKeyword::new(ns, name).into()
|
Keyword::namespaced(ns, name).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -207,7 +207,7 @@ fn can_parse_simple_or_and_join() {
|
||||||
],
|
],
|
||||||
)),
|
)),
|
||||||
|
|
||||||
WhereClause::Pred(Predicate { operator: PlainSymbol::new("<"), args: vec![
|
WhereClause::Pred(Predicate { operator: PlainSymbol::plain("<"), args: vec![
|
||||||
FnArg::Variable(Variable::from_valid_name("?y")), FnArg::EntidOrInteger(1),
|
FnArg::Variable(Variable::from_valid_name("?y")), FnArg::EntidOrInteger(1),
|
||||||
]}),
|
]}),
|
||||||
],
|
],
|
||||||
|
@ -281,7 +281,7 @@ fn can_parse_uuid() {
|
||||||
WhereClause::Pattern(
|
WhereClause::Pattern(
|
||||||
Pattern::new(None,
|
Pattern::new(None,
|
||||||
PatternNonValuePlace::Variable(Variable::from_valid_name("?x")),
|
PatternNonValuePlace::Variable(Variable::from_valid_name("?x")),
|
||||||
NamespacedKeyword::new("foo", "baz").into(),
|
Keyword::namespaced("foo", "baz").into(),
|
||||||
PatternValuePlace::Constant(NonIntegerConstant::Uuid(expected)),
|
PatternValuePlace::Constant(NonIntegerConstant::Uuid(expected)),
|
||||||
PatternNonValuePlace::Placeholder)
|
PatternNonValuePlace::Placeholder)
|
||||||
.expect("valid pattern")));
|
.expect("valid pattern")));
|
||||||
|
|
|
@ -59,7 +59,7 @@ impl SimpleAggregationOp {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn for_function(function: &QueryFunction) -> Option<SimpleAggregationOp> {
|
fn for_function(function: &QueryFunction) -> Option<SimpleAggregationOp> {
|
||||||
match function.0.plain_name() {
|
match function.0.name() {
|
||||||
"avg" => Some(SimpleAggregationOp::Avg),
|
"avg" => Some(SimpleAggregationOp::Avg),
|
||||||
"count" => Some(SimpleAggregationOp::Count),
|
"count" => Some(SimpleAggregationOp::Count),
|
||||||
"max" => Some(SimpleAggregationOp::Max),
|
"max" => Some(SimpleAggregationOp::Max),
|
||||||
|
|
|
@ -26,7 +26,7 @@ use mentat_query_parser::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use mentat_query::{
|
use mentat_query::{
|
||||||
NamespacedKeyword,
|
Keyword,
|
||||||
};
|
};
|
||||||
|
|
||||||
use mentat_query_algebrizer::{
|
use mentat_query_algebrizer::{
|
||||||
|
@ -39,7 +39,7 @@ use mentat_query_projector::{
|
||||||
};
|
};
|
||||||
|
|
||||||
// These are helpers that tests use to build Schema instances.
|
// These are helpers that tests use to build Schema instances.
|
||||||
fn associate_ident(schema: &mut Schema, i: NamespacedKeyword, e: Entid) {
|
fn associate_ident(schema: &mut Schema, i: Keyword, e: Entid) {
|
||||||
schema.entid_map.insert(e, i.clone());
|
schema.entid_map.insert(e, i.clone());
|
||||||
schema.ident_map.insert(i.clone(), e);
|
schema.ident_map.insert(i.clone(), e);
|
||||||
}
|
}
|
||||||
|
@ -50,9 +50,9 @@ fn add_attribute(schema: &mut Schema, e: Entid, a: Attribute) {
|
||||||
|
|
||||||
fn prepopulated_schema() -> Schema {
|
fn prepopulated_schema() -> Schema {
|
||||||
let mut schema = Schema::default();
|
let mut schema = Schema::default();
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "name"), 65);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "name"), 65);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "age"), 68);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "age"), 68);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "height"), 69);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "height"), 69);
|
||||||
add_attribute(&mut schema, 65, Attribute {
|
add_attribute(&mut schema, 65, Attribute {
|
||||||
value_type: ValueType::String,
|
value_type: ValueType::String,
|
||||||
multival: false,
|
multival: false,
|
||||||
|
|
|
@ -82,7 +82,7 @@ use mentat_core::{
|
||||||
Cloned,
|
Cloned,
|
||||||
Entid,
|
Entid,
|
||||||
HasSchema,
|
HasSchema,
|
||||||
NamespacedKeyword,
|
Keyword,
|
||||||
Schema,
|
Schema,
|
||||||
StructuredMap,
|
StructuredMap,
|
||||||
ValueRc,
|
ValueRc,
|
||||||
|
@ -140,7 +140,7 @@ pub fn pull_attributes_for_entities<E, A>(schema: &Schema,
|
||||||
pub struct Puller {
|
pub struct Puller {
|
||||||
// The domain of this map is the set of attributes to fetch.
|
// The domain of this map is the set of attributes to fetch.
|
||||||
// The range is the set of aliases to use in the output.
|
// The range is the set of aliases to use in the output.
|
||||||
attributes: BTreeMap<Entid, ValueRc<NamespacedKeyword>>,
|
attributes: BTreeMap<Entid, ValueRc<Keyword>>,
|
||||||
attribute_spec: cache::AttributeSpec,
|
attribute_spec: cache::AttributeSpec,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,7 +163,7 @@ impl Puller {
|
||||||
.ok_or_else(|| ErrorKind::UnnamedAttribute(*i))
|
.ok_or_else(|| ErrorKind::UnnamedAttribute(*i))
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut names: BTreeMap<Entid, ValueRc<NamespacedKeyword>> = Default::default();
|
let mut names: BTreeMap<Entid, ValueRc<Keyword>> = Default::default();
|
||||||
let mut attrs: BTreeSet<Entid> = Default::default();
|
let mut attrs: BTreeSet<Entid> = Default::default();
|
||||||
for attr in attributes.iter() {
|
for attr in attributes.iter() {
|
||||||
match attr {
|
match attr {
|
||||||
|
|
|
@ -22,7 +22,7 @@ use std::rc::Rc;
|
||||||
|
|
||||||
use mentat_query::{
|
use mentat_query::{
|
||||||
FindSpec,
|
FindSpec,
|
||||||
NamespacedKeyword,
|
Keyword,
|
||||||
Variable,
|
Variable,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ macro_rules! var {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn associate_ident(schema: &mut Schema, i: NamespacedKeyword, e: Entid) {
|
fn associate_ident(schema: &mut Schema, i: Keyword, e: Entid) {
|
||||||
schema.entid_map.insert(e, i.clone());
|
schema.entid_map.insert(e, i.clone());
|
||||||
schema.ident_map.insert(i.clone(), e);
|
schema.ident_map.insert(i.clone(), e);
|
||||||
}
|
}
|
||||||
|
@ -123,12 +123,12 @@ fn translate_to_constant(schema: &Schema, query: &'static str) -> ConstantProjec
|
||||||
|
|
||||||
fn prepopulated_typed_schema(foo_type: ValueType) -> Schema {
|
fn prepopulated_typed_schema(foo_type: ValueType) -> Schema {
|
||||||
let mut schema = Schema::default();
|
let mut schema = Schema::default();
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "bar"), 99);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "bar"), 99);
|
||||||
add_attribute(&mut schema, 99, Attribute {
|
add_attribute(&mut schema, 99, Attribute {
|
||||||
value_type: foo_type,
|
value_type: foo_type,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("foo", "fts"), 100);
|
associate_ident(&mut schema, Keyword::namespaced("foo", "fts"), 100);
|
||||||
add_attribute(&mut schema, 100, Attribute {
|
add_attribute(&mut schema, 100, Attribute {
|
||||||
value_type: ValueType::String,
|
value_type: ValueType::String,
|
||||||
index: true,
|
index: true,
|
||||||
|
@ -486,9 +486,9 @@ fn test_compare_double_to_long() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_simple_or_join() {
|
fn test_simple_or_join() {
|
||||||
let mut schema = Schema::default();
|
let mut schema = Schema::default();
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("page", "url"), 97);
|
associate_ident(&mut schema, Keyword::namespaced("page", "url"), 97);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("page", "title"), 98);
|
associate_ident(&mut schema, Keyword::namespaced("page", "title"), 98);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("page", "description"), 99);
|
associate_ident(&mut schema, Keyword::namespaced("page", "description"), 99);
|
||||||
for x in 97..100 {
|
for x in 97..100 {
|
||||||
add_attribute(&mut schema, x, Attribute {
|
add_attribute(&mut schema, x, Attribute {
|
||||||
value_type: ValueType::String,
|
value_type: ValueType::String,
|
||||||
|
@ -511,16 +511,16 @@ fn test_simple_or_join() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_complex_or_join() {
|
fn test_complex_or_join() {
|
||||||
let mut schema = Schema::default();
|
let mut schema = Schema::default();
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("page", "save"), 95);
|
associate_ident(&mut schema, Keyword::namespaced("page", "save"), 95);
|
||||||
add_attribute(&mut schema, 95, Attribute {
|
add_attribute(&mut schema, 95, Attribute {
|
||||||
value_type: ValueType::Ref,
|
value_type: ValueType::Ref,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("save", "title"), 96);
|
associate_ident(&mut schema, Keyword::namespaced("save", "title"), 96);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("page", "url"), 97);
|
associate_ident(&mut schema, Keyword::namespaced("page", "url"), 97);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("page", "title"), 98);
|
associate_ident(&mut schema, Keyword::namespaced("page", "title"), 98);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("page", "description"), 99);
|
associate_ident(&mut schema, Keyword::namespaced("page", "description"), 99);
|
||||||
for x in 96..100 {
|
for x in 96..100 {
|
||||||
add_attribute(&mut schema, x, Attribute {
|
add_attribute(&mut schema, x, Attribute {
|
||||||
value_type: ValueType::String,
|
value_type: ValueType::String,
|
||||||
|
@ -572,7 +572,7 @@ fn test_complex_or_join() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_complex_or_join_type_projection() {
|
fn test_complex_or_join_type_projection() {
|
||||||
let mut schema = Schema::default();
|
let mut schema = Schema::default();
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("page", "title"), 98);
|
associate_ident(&mut schema, Keyword::namespaced("page", "title"), 98);
|
||||||
add_attribute(&mut schema, 98, Attribute {
|
add_attribute(&mut schema, 98, Attribute {
|
||||||
value_type: ValueType::String,
|
value_type: ValueType::String,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -603,9 +603,9 @@ fn test_complex_or_join_type_projection() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_not() {
|
fn test_not() {
|
||||||
let mut schema = Schema::default();
|
let mut schema = Schema::default();
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("page", "url"), 97);
|
associate_ident(&mut schema, Keyword::namespaced("page", "url"), 97);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("page", "title"), 98);
|
associate_ident(&mut schema, Keyword::namespaced("page", "title"), 98);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("page", "bookmarked"), 99);
|
associate_ident(&mut schema, Keyword::namespaced("page", "bookmarked"), 99);
|
||||||
for x in 97..99 {
|
for x in 97..99 {
|
||||||
add_attribute(&mut schema, x, Attribute {
|
add_attribute(&mut schema, x, Attribute {
|
||||||
value_type: ValueType::String,
|
value_type: ValueType::String,
|
||||||
|
@ -629,9 +629,9 @@ fn test_not() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_not_join() {
|
fn test_not_join() {
|
||||||
let mut schema = Schema::default();
|
let mut schema = Schema::default();
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("page", "url"), 97);
|
associate_ident(&mut schema, Keyword::namespaced("page", "url"), 97);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("bookmarks", "page"), 98);
|
associate_ident(&mut schema, Keyword::namespaced("bookmarks", "page"), 98);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("bookmarks", "date_created"), 99);
|
associate_ident(&mut schema, Keyword::namespaced("bookmarks", "date_created"), 99);
|
||||||
add_attribute(&mut schema, 97, Attribute {
|
add_attribute(&mut schema, 97, Attribute {
|
||||||
value_type: ValueType::String,
|
value_type: ValueType::String,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -698,7 +698,7 @@ fn test_order_by() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_complex_nested_or_join_type_projection() {
|
fn test_complex_nested_or_join_type_projection() {
|
||||||
let mut schema = Schema::default();
|
let mut schema = Schema::default();
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("page", "title"), 98);
|
associate_ident(&mut schema, Keyword::namespaced("page", "title"), 98);
|
||||||
add_attribute(&mut schema, 98, Attribute {
|
add_attribute(&mut schema, 98, Attribute {
|
||||||
value_type: ValueType::String,
|
value_type: ValueType::String,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -884,10 +884,10 @@ fn test_unbound_attribute_with_ground() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_not_with_ground() {
|
fn test_not_with_ground() {
|
||||||
let mut schema = prepopulated_schema();
|
let mut schema = prepopulated_schema();
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("db", "valueType"), 7);
|
associate_ident(&mut schema, Keyword::namespaced("db", "valueType"), 7);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("db.type", "ref"), 23);
|
associate_ident(&mut schema, Keyword::namespaced("db.type", "ref"), 23);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("db.type", "bool"), 28);
|
associate_ident(&mut schema, Keyword::namespaced("db.type", "bool"), 28);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("db.type", "instant"), 29);
|
associate_ident(&mut schema, Keyword::namespaced("db.type", "instant"), 29);
|
||||||
add_attribute(&mut schema, 7, Attribute {
|
add_attribute(&mut schema, 7, Attribute {
|
||||||
value_type: ValueType::Ref,
|
value_type: ValueType::Ref,
|
||||||
multival: false,
|
multival: false,
|
||||||
|
@ -1139,7 +1139,7 @@ fn test_tx_before_and_after() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_tx_ids() {
|
fn test_tx_ids() {
|
||||||
let mut schema = prepopulated_typed_schema(ValueType::Double);
|
let mut schema = prepopulated_typed_schema(ValueType::Double);
|
||||||
associate_ident(&mut schema, NamespacedKeyword::new("db", "txInstant"), 101);
|
associate_ident(&mut schema, Keyword::namespaced("db", "txInstant"), 101);
|
||||||
add_attribute(&mut schema, 101, Attribute {
|
add_attribute(&mut schema, 101, Attribute {
|
||||||
value_type: ValueType::Instant,
|
value_type: ValueType::Instant,
|
||||||
multival: false,
|
multival: false,
|
||||||
|
|
|
@ -50,7 +50,7 @@ use edn::{
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use edn::{
|
pub use edn::{
|
||||||
NamespacedKeyword,
|
Keyword,
|
||||||
PlainSymbol,
|
PlainSymbol,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ impl Variable {
|
||||||
|
|
||||||
/// Return a new `Variable`, assuming that the provided string is a valid name.
|
/// Return a new `Variable`, assuming that the provided string is a valid name.
|
||||||
pub fn from_valid_name(name: &str) -> Variable {
|
pub fn from_valid_name(name: &str) -> Variable {
|
||||||
let s = PlainSymbol::new(name);
|
let s = PlainSymbol::plain(name);
|
||||||
assert!(s.is_var_symbol());
|
assert!(s.is_var_symbol());
|
||||||
Variable(Rc::new(s))
|
Variable(Rc::new(s))
|
||||||
}
|
}
|
||||||
|
@ -193,7 +193,7 @@ impl SrcVar {
|
||||||
if sym.0 == "$" {
|
if sym.0 == "$" {
|
||||||
Some(SrcVar::DefaultSrc)
|
Some(SrcVar::DefaultSrc)
|
||||||
} else {
|
} else {
|
||||||
Some(SrcVar::NamedSrc(sym.plain_name().to_string()))
|
Some(SrcVar::NamedSrc(sym.name().to_string()))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -242,7 +242,7 @@ pub enum FnArg {
|
||||||
Variable(Variable),
|
Variable(Variable),
|
||||||
SrcVar(SrcVar),
|
SrcVar(SrcVar),
|
||||||
EntidOrInteger(i64),
|
EntidOrInteger(i64),
|
||||||
IdentOrKeyword(NamespacedKeyword),
|
IdentOrKeyword(Keyword),
|
||||||
Constant(NonIntegerConstant),
|
Constant(NonIntegerConstant),
|
||||||
// The collection values representable in EDN. There's no advantage to destructuring up front,
|
// The collection values representable in EDN. There's no advantage to destructuring up front,
|
||||||
// since consumers will need to handle arbitrarily nested EDN themselves anyway.
|
// since consumers will need to handle arbitrarily nested EDN themselves anyway.
|
||||||
|
@ -260,7 +260,7 @@ impl FromValue<FnArg> for FnArg {
|
||||||
PlainSymbol(ref x) if x.is_var_symbol() =>
|
PlainSymbol(ref x) if x.is_var_symbol() =>
|
||||||
Variable::from_symbol(x).map(FnArg::Variable),
|
Variable::from_symbol(x).map(FnArg::Variable),
|
||||||
PlainSymbol(_) => None,
|
PlainSymbol(_) => None,
|
||||||
NamespacedKeyword(ref x) =>
|
Keyword(ref x) =>
|
||||||
Some(FnArg::IdentOrKeyword(x.clone())),
|
Some(FnArg::IdentOrKeyword(x.clone())),
|
||||||
Instant(x) =>
|
Instant(x) =>
|
||||||
Some(FnArg::Constant(NonIntegerConstant::Instant(x))),
|
Some(FnArg::Constant(NonIntegerConstant::Instant(x))),
|
||||||
|
@ -277,7 +277,6 @@ impl FromValue<FnArg> for FnArg {
|
||||||
Some(FnArg::Constant(x.clone().into())),
|
Some(FnArg::Constant(x.clone().into())),
|
||||||
Nil |
|
Nil |
|
||||||
NamespacedSymbol(_) |
|
NamespacedSymbol(_) |
|
||||||
Keyword(_) |
|
|
||||||
Vector(_) |
|
Vector(_) |
|
||||||
List(_) |
|
List(_) |
|
||||||
Set(_) |
|
Set(_) |
|
||||||
|
@ -326,17 +325,17 @@ pub enum PatternNonValuePlace {
|
||||||
Placeholder,
|
Placeholder,
|
||||||
Variable(Variable),
|
Variable(Variable),
|
||||||
Entid(i64), // Will always be +ve. See #190.
|
Entid(i64), // Will always be +ve. See #190.
|
||||||
Ident(ValueRc<NamespacedKeyword>),
|
Ident(ValueRc<Keyword>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Rc<NamespacedKeyword>> for PatternNonValuePlace {
|
impl From<Rc<Keyword>> for PatternNonValuePlace {
|
||||||
fn from(value: Rc<NamespacedKeyword>) -> Self {
|
fn from(value: Rc<Keyword>) -> Self {
|
||||||
PatternNonValuePlace::Ident(ValueRc::from_rc(value))
|
PatternNonValuePlace::Ident(ValueRc::from_rc(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<NamespacedKeyword> for PatternNonValuePlace {
|
impl From<Keyword> for PatternNonValuePlace {
|
||||||
fn from(value: NamespacedKeyword) -> Self {
|
fn from(value: Keyword) -> Self {
|
||||||
PatternNonValuePlace::Ident(ValueRc::new(value))
|
PatternNonValuePlace::Ident(ValueRc::new(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -380,7 +379,7 @@ impl FromValue<PatternNonValuePlace> for PatternNonValuePlace {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
edn::SpannedValue::NamespacedKeyword(ref x) =>
|
edn::SpannedValue::Keyword(ref x) =>
|
||||||
Some(x.clone().into()),
|
Some(x.clone().into()),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
@ -389,7 +388,7 @@ impl FromValue<PatternNonValuePlace> for PatternNonValuePlace {
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub enum IdentOrEntid {
|
pub enum IdentOrEntid {
|
||||||
Ident(NamespacedKeyword),
|
Ident(Keyword),
|
||||||
Entid(i64),
|
Entid(i64),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -401,18 +400,18 @@ pub enum PatternValuePlace {
|
||||||
Placeholder,
|
Placeholder,
|
||||||
Variable(Variable),
|
Variable(Variable),
|
||||||
EntidOrInteger(i64),
|
EntidOrInteger(i64),
|
||||||
IdentOrKeyword(ValueRc<NamespacedKeyword>),
|
IdentOrKeyword(ValueRc<Keyword>),
|
||||||
Constant(NonIntegerConstant),
|
Constant(NonIntegerConstant),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Rc<NamespacedKeyword>> for PatternValuePlace {
|
impl From<Rc<Keyword>> for PatternValuePlace {
|
||||||
fn from(value: Rc<NamespacedKeyword>) -> Self {
|
fn from(value: Rc<Keyword>) -> Self {
|
||||||
PatternValuePlace::IdentOrKeyword(ValueRc::from_rc(value))
|
PatternValuePlace::IdentOrKeyword(ValueRc::from_rc(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<NamespacedKeyword> for PatternValuePlace {
|
impl From<Keyword> for PatternValuePlace {
|
||||||
fn from(value: NamespacedKeyword) -> Self {
|
fn from(value: Keyword) -> Self {
|
||||||
PatternValuePlace::IdentOrKeyword(ValueRc::new(value))
|
PatternValuePlace::IdentOrKeyword(ValueRc::new(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -426,7 +425,7 @@ impl FromValue<PatternValuePlace> for PatternValuePlace {
|
||||||
Some(PatternValuePlace::Placeholder),
|
Some(PatternValuePlace::Placeholder),
|
||||||
edn::SpannedValue::PlainSymbol(ref x) =>
|
edn::SpannedValue::PlainSymbol(ref x) =>
|
||||||
Variable::from_symbol(x).map(PatternValuePlace::Variable),
|
Variable::from_symbol(x).map(PatternValuePlace::Variable),
|
||||||
edn::SpannedValue::NamespacedKeyword(ref x) =>
|
edn::SpannedValue::Keyword(ref x) if x.is_namespaced() =>
|
||||||
Some(x.clone().into()),
|
Some(x.clone().into()),
|
||||||
edn::SpannedValue::Boolean(x) =>
|
edn::SpannedValue::Boolean(x) =>
|
||||||
Some(PatternValuePlace::Constant(NonIntegerConstant::Boolean(x))),
|
Some(PatternValuePlace::Constant(NonIntegerConstant::Boolean(x))),
|
||||||
|
@ -445,7 +444,7 @@ impl FromValue<PatternValuePlace> for PatternValuePlace {
|
||||||
// These don't appear in queries.
|
// These don't appear in queries.
|
||||||
edn::SpannedValue::Nil => None,
|
edn::SpannedValue::Nil => None,
|
||||||
edn::SpannedValue::NamespacedSymbol(_) => None,
|
edn::SpannedValue::NamespacedSymbol(_) => None,
|
||||||
edn::SpannedValue::Keyword(_) => None,
|
edn::SpannedValue::Keyword(_) => None, // … yet.
|
||||||
edn::SpannedValue::Map(_) => None,
|
edn::SpannedValue::Map(_) => None,
|
||||||
edn::SpannedValue::List(_) => None,
|
edn::SpannedValue::List(_) => None,
|
||||||
edn::SpannedValue::Set(_) => None,
|
edn::SpannedValue::Set(_) => None,
|
||||||
|
@ -489,13 +488,13 @@ impl PatternValuePlace {
|
||||||
// Not yet used.
|
// Not yet used.
|
||||||
// pub enum PullDefaultValue {
|
// pub enum PullDefaultValue {
|
||||||
// EntidOrInteger(i64),
|
// EntidOrInteger(i64),
|
||||||
// IdentOrKeyword(Rc<NamespacedKeyword>),
|
// IdentOrKeyword(Rc<Keyword>),
|
||||||
// Constant(NonIntegerConstant),
|
// Constant(NonIntegerConstant),
|
||||||
// }
|
// }
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub enum PullConcreteAttribute {
|
pub enum PullConcreteAttribute {
|
||||||
Ident(Rc<NamespacedKeyword>),
|
Ident(Rc<Keyword>),
|
||||||
Entid(i64),
|
Entid(i64),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
54
src/conn.rs
54
src/conn.rs
|
@ -47,7 +47,7 @@ use mentat_core::{
|
||||||
Entid,
|
Entid,
|
||||||
HasSchema,
|
HasSchema,
|
||||||
KnownEntid,
|
KnownEntid,
|
||||||
NamespacedKeyword,
|
Keyword,
|
||||||
Schema,
|
Schema,
|
||||||
StructuredMap,
|
StructuredMap,
|
||||||
TypedValue,
|
TypedValue,
|
||||||
|
@ -215,9 +215,9 @@ pub trait Queryable {
|
||||||
where T: Into<Option<QueryInputs>>;
|
where T: Into<Option<QueryInputs>>;
|
||||||
fn q_prepare<T>(&self, query: &str, inputs: T) -> PreparedResult
|
fn q_prepare<T>(&self, query: &str, inputs: T) -> PreparedResult
|
||||||
where T: Into<Option<QueryInputs>>;
|
where T: Into<Option<QueryInputs>>;
|
||||||
fn lookup_values_for_attribute<E>(&self, entity: E, attribute: &edn::NamespacedKeyword) -> Result<Vec<TypedValue>>
|
fn lookup_values_for_attribute<E>(&self, entity: E, attribute: &edn::Keyword) -> Result<Vec<TypedValue>>
|
||||||
where E: Into<Entid>;
|
where E: Into<Entid>;
|
||||||
fn lookup_value_for_attribute<E>(&self, entity: E, attribute: &edn::NamespacedKeyword) -> Result<Option<TypedValue>>
|
fn lookup_value_for_attribute<E>(&self, entity: E, attribute: &edn::Keyword) -> Result<Option<TypedValue>>
|
||||||
where E: Into<Entid>;
|
where E: Into<Entid>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,12 +269,12 @@ impl<'a, 'c> Queryable for InProgressRead<'a, 'c> {
|
||||||
self.0.q_explain(query, inputs)
|
self.0.q_explain(query, inputs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lookup_values_for_attribute<E>(&self, entity: E, attribute: &edn::NamespacedKeyword) -> Result<Vec<TypedValue>>
|
fn lookup_values_for_attribute<E>(&self, entity: E, attribute: &edn::Keyword) -> Result<Vec<TypedValue>>
|
||||||
where E: Into<Entid> {
|
where E: Into<Entid> {
|
||||||
self.0.lookup_values_for_attribute(entity, attribute)
|
self.0.lookup_values_for_attribute(entity, attribute)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lookup_value_for_attribute<E>(&self, entity: E, attribute: &edn::NamespacedKeyword) -> Result<Option<TypedValue>>
|
fn lookup_value_for_attribute<E>(&self, entity: E, attribute: &edn::Keyword) -> Result<Option<TypedValue>>
|
||||||
where E: Into<Entid> {
|
where E: Into<Entid> {
|
||||||
self.0.lookup_value_for_attribute(entity, attribute)
|
self.0.lookup_value_for_attribute(entity, attribute)
|
||||||
}
|
}
|
||||||
|
@ -331,13 +331,13 @@ impl<'a, 'c> Queryable for InProgress<'a, 'c> {
|
||||||
inputs)
|
inputs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lookup_values_for_attribute<E>(&self, entity: E, attribute: &edn::NamespacedKeyword) -> Result<Vec<TypedValue>>
|
fn lookup_values_for_attribute<E>(&self, entity: E, attribute: &edn::Keyword) -> Result<Vec<TypedValue>>
|
||||||
where E: Into<Entid> {
|
where E: Into<Entid> {
|
||||||
let known = Known::new(&self.schema, Some(&self.cache));
|
let known = Known::new(&self.schema, Some(&self.cache));
|
||||||
lookup_values_for_attribute(&*(self.transaction), known, entity, attribute)
|
lookup_values_for_attribute(&*(self.transaction), known, entity, attribute)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lookup_value_for_attribute<E>(&self, entity: E, attribute: &edn::NamespacedKeyword) -> Result<Option<TypedValue>>
|
fn lookup_value_for_attribute<E>(&self, entity: E, attribute: &edn::Keyword) -> Result<Option<TypedValue>>
|
||||||
where E: Into<Entid> {
|
where E: Into<Entid> {
|
||||||
let known = Known::new(&self.schema, Some(&self.cache));
|
let known = Known::new(&self.schema, Some(&self.cache));
|
||||||
lookup_value_for_attribute(&*(self.transaction), known, entity, attribute)
|
lookup_value_for_attribute(&*(self.transaction), known, entity, attribute)
|
||||||
|
@ -364,11 +364,11 @@ impl<'a, 'c> HasSchema for InProgressRead<'a, 'c> {
|
||||||
self.0.entid_for_type(t)
|
self.0.entid_for_type(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_ident<T>(&self, x: T) -> Option<&NamespacedKeyword> where T: Into<Entid> {
|
fn get_ident<T>(&self, x: T) -> Option<&Keyword> where T: Into<Entid> {
|
||||||
self.0.get_ident(x)
|
self.0.get_ident(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_entid(&self, x: &NamespacedKeyword) -> Option<KnownEntid> {
|
fn get_entid(&self, x: &Keyword) -> Option<KnownEntid> {
|
||||||
self.0.get_entid(x)
|
self.0.get_entid(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,7 +376,7 @@ impl<'a, 'c> HasSchema for InProgressRead<'a, 'c> {
|
||||||
self.0.attribute_for_entid(x)
|
self.0.attribute_for_entid(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn attribute_for_ident(&self, ident: &NamespacedKeyword) -> Option<(&Attribute, KnownEntid)> {
|
fn attribute_for_ident(&self, ident: &Keyword) -> Option<(&Attribute, KnownEntid)> {
|
||||||
self.0.attribute_for_ident(ident)
|
self.0.attribute_for_ident(ident)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,7 +386,7 @@ impl<'a, 'c> HasSchema for InProgressRead<'a, 'c> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return true if the provided ident identifies an attribute in this schema.
|
/// Return true if the provided ident identifies an attribute in this schema.
|
||||||
fn identifies_attribute(&self, x: &NamespacedKeyword) -> bool {
|
fn identifies_attribute(&self, x: &Keyword) -> bool {
|
||||||
self.0.identifies_attribute(x)
|
self.0.identifies_attribute(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -400,11 +400,11 @@ impl<'a, 'c> HasSchema for InProgress<'a, 'c> {
|
||||||
self.schema.entid_for_type(t)
|
self.schema.entid_for_type(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_ident<T>(&self, x: T) -> Option<&NamespacedKeyword> where T: Into<Entid> {
|
fn get_ident<T>(&self, x: T) -> Option<&Keyword> where T: Into<Entid> {
|
||||||
self.schema.get_ident(x)
|
self.schema.get_ident(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_entid(&self, x: &NamespacedKeyword) -> Option<KnownEntid> {
|
fn get_entid(&self, x: &Keyword) -> Option<KnownEntid> {
|
||||||
self.schema.get_entid(x)
|
self.schema.get_entid(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -412,7 +412,7 @@ impl<'a, 'c> HasSchema for InProgress<'a, 'c> {
|
||||||
self.schema.attribute_for_entid(x)
|
self.schema.attribute_for_entid(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn attribute_for_ident(&self, ident: &NamespacedKeyword) -> Option<(&Attribute, KnownEntid)> {
|
fn attribute_for_ident(&self, ident: &Keyword) -> Option<(&Attribute, KnownEntid)> {
|
||||||
self.schema.attribute_for_ident(ident)
|
self.schema.attribute_for_ident(ident)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -422,7 +422,7 @@ impl<'a, 'c> HasSchema for InProgress<'a, 'c> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return true if the provided ident identifies an attribute in this schema.
|
/// Return true if the provided ident identifies an attribute in this schema.
|
||||||
fn identifies_attribute(&self, x: &NamespacedKeyword) -> bool {
|
fn identifies_attribute(&self, x: &Keyword) -> bool {
|
||||||
self.schema.identifies_attribute(x)
|
self.schema.identifies_attribute(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -549,7 +549,7 @@ impl<'a, 'c> InProgress<'a, 'c> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cache(&mut self,
|
pub fn cache(&mut self,
|
||||||
attribute: &NamespacedKeyword,
|
attribute: &Keyword,
|
||||||
cache_direction: CacheDirection,
|
cache_direction: CacheDirection,
|
||||||
cache_action: CacheAction) -> Result<()> {
|
cache_action: CacheAction) -> Result<()> {
|
||||||
let attribute_entid: Entid = self.schema
|
let attribute_entid: Entid = self.schema
|
||||||
|
@ -631,7 +631,7 @@ impl Store {
|
||||||
self.conn.begin_transaction(&mut self.sqlite)
|
self.conn.begin_transaction(&mut self.sqlite)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cache(&mut self, attr: &NamespacedKeyword, direction: CacheDirection) -> Result<()> {
|
pub fn cache(&mut self, attr: &Keyword, direction: CacheDirection) -> Result<()> {
|
||||||
let schema = &self.conn.current_schema();
|
let schema = &self.conn.current_schema();
|
||||||
self.conn.cache(&mut self.sqlite,
|
self.conn.cache(&mut self.sqlite,
|
||||||
schema,
|
schema,
|
||||||
|
@ -648,7 +648,7 @@ impl Store {
|
||||||
self.conn.unregister_observer(key);
|
self.conn.unregister_observer(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn assert_datom<T>(&mut self, entid: T, attribute: NamespacedKeyword, value: TypedValue) -> Result<()> where T: Into<KnownEntid> {
|
pub fn assert_datom<T>(&mut self, entid: T, attribute: Keyword, value: TypedValue) -> Result<()> where T: Into<KnownEntid> {
|
||||||
self.conn.assert_datom(&mut self.sqlite, entid, attribute, value)
|
self.conn.assert_datom(&mut self.sqlite, entid, attribute, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -669,12 +669,12 @@ impl Queryable for Store {
|
||||||
self.conn.q_explain(&self.sqlite, query, inputs)
|
self.conn.q_explain(&self.sqlite, query, inputs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lookup_values_for_attribute<E>(&self, entity: E, attribute: &edn::NamespacedKeyword) -> Result<Vec<TypedValue>>
|
fn lookup_values_for_attribute<E>(&self, entity: E, attribute: &edn::Keyword) -> Result<Vec<TypedValue>>
|
||||||
where E: Into<Entid> {
|
where E: Into<Entid> {
|
||||||
self.conn.lookup_values_for_attribute(&self.sqlite, entity.into(), attribute)
|
self.conn.lookup_values_for_attribute(&self.sqlite, entity.into(), attribute)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lookup_value_for_attribute<E>(&self, entity: E, attribute: &edn::NamespacedKeyword) -> Result<Option<TypedValue>>
|
fn lookup_value_for_attribute<E>(&self, entity: E, attribute: &edn::Keyword) -> Result<Option<TypedValue>>
|
||||||
where E: Into<Entid> {
|
where E: Into<Entid> {
|
||||||
self.conn.lookup_value_for_attribute(&self.sqlite, entity.into(), attribute)
|
self.conn.lookup_value_for_attribute(&self.sqlite, entity.into(), attribute)
|
||||||
}
|
}
|
||||||
|
@ -845,7 +845,7 @@ impl Conn {
|
||||||
pub fn lookup_values_for_attribute(&self,
|
pub fn lookup_values_for_attribute(&self,
|
||||||
sqlite: &rusqlite::Connection,
|
sqlite: &rusqlite::Connection,
|
||||||
entity: Entid,
|
entity: Entid,
|
||||||
attribute: &edn::NamespacedKeyword) -> Result<Vec<TypedValue>> {
|
attribute: &edn::Keyword) -> Result<Vec<TypedValue>> {
|
||||||
let metadata = self.metadata.lock().unwrap();
|
let metadata = self.metadata.lock().unwrap();
|
||||||
let known = Known::new(&*metadata.schema, Some(&metadata.attribute_cache));
|
let known = Known::new(&*metadata.schema, Some(&metadata.attribute_cache));
|
||||||
lookup_values_for_attribute(sqlite, known, entity, attribute)
|
lookup_values_for_attribute(sqlite, known, entity, attribute)
|
||||||
|
@ -854,7 +854,7 @@ impl Conn {
|
||||||
pub fn lookup_value_for_attribute(&self,
|
pub fn lookup_value_for_attribute(&self,
|
||||||
sqlite: &rusqlite::Connection,
|
sqlite: &rusqlite::Connection,
|
||||||
entity: Entid,
|
entity: Entid,
|
||||||
attribute: &edn::NamespacedKeyword) -> Result<Option<TypedValue>> {
|
attribute: &edn::Keyword) -> Result<Option<TypedValue>> {
|
||||||
let metadata = self.metadata.lock().unwrap();
|
let metadata = self.metadata.lock().unwrap();
|
||||||
let known = Known::new(&*metadata.schema, Some(&metadata.attribute_cache));
|
let known = Known::new(&*metadata.schema, Some(&metadata.attribute_cache));
|
||||||
lookup_value_for_attribute(sqlite, known, entity, attribute)
|
lookup_value_for_attribute(sqlite, known, entity, attribute)
|
||||||
|
@ -937,7 +937,7 @@ impl Conn {
|
||||||
pub fn cache(&mut self,
|
pub fn cache(&mut self,
|
||||||
sqlite: &mut rusqlite::Connection,
|
sqlite: &mut rusqlite::Connection,
|
||||||
schema: &Schema,
|
schema: &Schema,
|
||||||
attribute: &NamespacedKeyword,
|
attribute: &Keyword,
|
||||||
cache_direction: CacheDirection,
|
cache_direction: CacheDirection,
|
||||||
cache_action: CacheAction) -> Result<()> {
|
cache_action: CacheAction) -> Result<()> {
|
||||||
let mut metadata = self.metadata.lock().unwrap();
|
let mut metadata = self.metadata.lock().unwrap();
|
||||||
|
@ -977,7 +977,7 @@ impl Conn {
|
||||||
// TODO: expose the entity builder over FFI and remove the need for this function entirely
|
// TODO: expose the entity builder over FFI and remove the need for this function entirely
|
||||||
// It's really only here in order to keep the FFI layer as thin as possible.
|
// It's really only here in order to keep the FFI layer as thin as possible.
|
||||||
// Once the entity builder is exposed, we can perform all of these functions over FFI from the client.
|
// Once the entity builder is exposed, we can perform all of these functions over FFI from the client.
|
||||||
pub fn assert_datom<T>(&mut self, sqlite: &mut rusqlite::Connection, entid: T, attribute: NamespacedKeyword, value: TypedValue) -> Result<()> where T: Into<KnownEntid> {
|
pub fn assert_datom<T>(&mut self, sqlite: &mut rusqlite::Connection, entid: T, attribute: Keyword, value: TypedValue) -> Result<()> where T: Into<KnownEntid> {
|
||||||
let in_progress = self.begin_transaction(sqlite)?;
|
let in_progress = self.begin_transaction(sqlite)?;
|
||||||
let mut builder = in_progress.builder().describe(entid.into());
|
let mut builder = in_progress.builder().describe(entid.into());
|
||||||
builder.add_kw(&attribute, value)?;
|
builder.add_kw(&attribute, value)?;
|
||||||
|
@ -1122,6 +1122,8 @@ mod tests {
|
||||||
assert!(one == tempid_offset || one == tempid_offset + 1);
|
assert!(one == tempid_offset || one == tempid_offset + 1);
|
||||||
assert!(two == tempid_offset || two == tempid_offset + 1);
|
assert!(two == tempid_offset || two == tempid_offset + 1);
|
||||||
|
|
||||||
|
println!("RES: {:?}", in_progress.q_once("[:find ?v :where [?x :db/ident ?v]]", None).unwrap());
|
||||||
|
|
||||||
let during = in_progress.q_once("[:find ?x . :where [?x :db/ident :a/keyword1]]", None)
|
let during = in_progress.q_once("[:find ?x . :where [?x :db/ident :a/keyword1]]", None)
|
||||||
.expect("query succeeded");
|
.expect("query succeeded");
|
||||||
assert_eq!(during.results, QueryResults::Scalar(Some(TypedValue::Ref(one).into())));
|
assert_eq!(during.results, QueryResults::Scalar(Some(TypedValue::Ref(one).into())));
|
||||||
|
@ -1208,9 +1210,9 @@ mod tests {
|
||||||
assert_eq!(during.results, QueryResults::Scalar(Some(TypedValue::Ref(one).into())));
|
assert_eq!(during.results, QueryResults::Scalar(Some(TypedValue::Ref(one).into())));
|
||||||
|
|
||||||
// And we can do direct lookup, too.
|
// And we can do direct lookup, too.
|
||||||
let kw = in_progress.lookup_value_for_attribute(one, &edn::NamespacedKeyword::new("db", "ident"))
|
let kw = in_progress.lookup_value_for_attribute(one, &edn::Keyword::namespaced("db", "ident"))
|
||||||
.expect("lookup succeeded");
|
.expect("lookup succeeded");
|
||||||
assert_eq!(kw, Some(TypedValue::Keyword(edn::NamespacedKeyword::new("a", "keyword1").into())));
|
assert_eq!(kw, Some(TypedValue::Keyword(edn::Keyword::namespaced("a", "keyword1").into())));
|
||||||
|
|
||||||
in_progress.rollback()
|
in_progress.rollback()
|
||||||
.expect("rollback succeeded");
|
.expect("rollback succeeded");
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
// Entity::AddOrRetract {
|
// Entity::AddOrRetract {
|
||||||
// op: OpType::Add,
|
// op: OpType::Add,
|
||||||
// e: EntidOrLookupRefOrTempId::LookupRef(LookupRef {
|
// e: EntidOrLookupRefOrTempId::LookupRef(LookupRef {
|
||||||
// a: Entid::Ident(NamespacedKeyword::new("test", "a1")),
|
// a: Entid::Ident(Keyword::namespaced("test", "a1")),
|
||||||
// v: Value::Text("v1".into()),
|
// v: Value::Text("v1".into()),
|
||||||
// }),
|
// }),
|
||||||
// a: Entid::Ident(kw!(:test/a)),
|
// a: Entid::Ident(kw!(:test/a)),
|
||||||
|
@ -56,7 +56,7 @@
|
||||||
use mentat_core::{
|
use mentat_core::{
|
||||||
HasSchema,
|
HasSchema,
|
||||||
KnownEntid,
|
KnownEntid,
|
||||||
NamespacedKeyword,
|
Keyword,
|
||||||
TypedValue,
|
TypedValue,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -256,21 +256,21 @@ impl<'a, 'c> BuildTerms for InProgressBuilder<'a, 'c> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'c> InProgressBuilder<'a, 'c> {
|
impl<'a, 'c> InProgressBuilder<'a, 'c> {
|
||||||
pub fn add_kw<E, V>(&mut self, e: E, a: &NamespacedKeyword, v: V) -> Result<()>
|
pub fn add_kw<E, V>(&mut self, e: E, a: &Keyword, v: V) -> Result<()>
|
||||||
where E: IntoThing<KnownEntidOr<TempIdHandle>>,
|
where E: IntoThing<KnownEntidOr<TempIdHandle>>,
|
||||||
V: IntoThing<TypedValueOr<TempIdHandle>> {
|
V: IntoThing<TypedValueOr<TempIdHandle>> {
|
||||||
let (attribute, value) = self.extract_kw_value(a, v.into_thing())?;
|
let (attribute, value) = self.extract_kw_value(a, v.into_thing())?;
|
||||||
self.add(e, attribute, value)
|
self.add(e, attribute, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn retract_kw<E, V>(&mut self, e: E, a: &NamespacedKeyword, v: V) -> Result<()>
|
pub fn retract_kw<E, V>(&mut self, e: E, a: &Keyword, v: V) -> Result<()>
|
||||||
where E: IntoThing<KnownEntidOr<TempIdHandle>>,
|
where E: IntoThing<KnownEntidOr<TempIdHandle>>,
|
||||||
V: IntoThing<TypedValueOr<TempIdHandle>> {
|
V: IntoThing<TypedValueOr<TempIdHandle>> {
|
||||||
let (attribute, value) = self.extract_kw_value(a, v.into_thing())?;
|
let (attribute, value) = self.extract_kw_value(a, v.into_thing())?;
|
||||||
self.retract(e, attribute, value)
|
self.retract(e, attribute, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract_kw_value(&mut self, a: &NamespacedKeyword, v: TypedValueOr<TempIdHandle>) -> Result<(KnownEntid, TypedValueOr<TempIdHandle>)> {
|
fn extract_kw_value(&mut self, a: &Keyword, v: TypedValueOr<TempIdHandle>) -> Result<(KnownEntid, TypedValueOr<TempIdHandle>)> {
|
||||||
let attribute: KnownEntid;
|
let attribute: KnownEntid;
|
||||||
if let Some((attr, aa)) = self.in_progress.attribute_for_ident(a) {
|
if let Some((attr, aa)) = self.in_progress.attribute_for_ident(a) {
|
||||||
if let Either::Left(ref tv) = v {
|
if let Either::Left(ref tv) = v {
|
||||||
|
@ -289,12 +289,12 @@ impl<'a, 'c> InProgressBuilder<'a, 'c> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'c> EntityBuilder<InProgressBuilder<'a, 'c>> {
|
impl<'a, 'c> EntityBuilder<InProgressBuilder<'a, 'c>> {
|
||||||
pub fn add_kw<V>(&mut self, a: &NamespacedKeyword, v: V) -> Result<()>
|
pub fn add_kw<V>(&mut self, a: &Keyword, v: V) -> Result<()>
|
||||||
where V: IntoThing<TypedValueOr<TempIdHandle>> {
|
where V: IntoThing<TypedValueOr<TempIdHandle>> {
|
||||||
self.builder.add_kw(self.entity.clone(), a, v)
|
self.builder.add_kw(self.entity.clone(), a, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn retract_kw<V>(&mut self, a: &NamespacedKeyword, v: V) -> Result<()>
|
pub fn retract_kw<V>(&mut self, a: &Keyword, v: V) -> Result<()>
|
||||||
where V: IntoThing<TypedValueOr<TempIdHandle>> {
|
where V: IntoThing<TypedValueOr<TempIdHandle>> {
|
||||||
self.builder.retract_kw(self.entity.clone(), a, v)
|
self.builder.retract_kw(self.entity.clone(), a, v)
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,7 +95,7 @@ error_chain! {
|
||||||
display("core schema: wanted {}, got {:?}", mentat_db::CORE_SCHEMA_VERSION, version)
|
display("core schema: wanted {}, got {:?}", mentat_db::CORE_SCHEMA_VERSION, version)
|
||||||
}
|
}
|
||||||
|
|
||||||
MissingCoreVocabulary(kw: mentat_query::NamespacedKeyword) {
|
MissingCoreVocabulary(kw: mentat_query::Keyword) {
|
||||||
description("missing core vocabulary")
|
description("missing core vocabulary")
|
||||||
display("missing core attribute {}", kw)
|
display("missing core attribute {}", kw)
|
||||||
}
|
}
|
||||||
|
|
34
src/lib.rs
34
src/lib.rs
|
@ -39,7 +39,7 @@ pub use mentat_core::{
|
||||||
DateTime,
|
DateTime,
|
||||||
HasSchema,
|
HasSchema,
|
||||||
KnownEntid,
|
KnownEntid,
|
||||||
NamespacedKeyword,
|
Keyword,
|
||||||
Schema,
|
Schema,
|
||||||
Binding,
|
Binding,
|
||||||
TypedValue,
|
TypedValue,
|
||||||
|
@ -70,25 +70,29 @@ macro_rules! var {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Produce the appropriate `NamespacedKeyword` for the provided namespace and name.
|
/// Produce the appropriate `Keyword` for the provided namespace and name.
|
||||||
/// This lives here because we can't re-export macros:
|
/// This lives here because we can't re-export macros:
|
||||||
/// https://github.com/rust-lang/rust/issues/29638.
|
/// https://github.com/rust-lang/rust/issues/29638.
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! kw {
|
macro_rules! kw {
|
||||||
|
( : $n:ident ) => {
|
||||||
|
$crate::Keyword::plain(
|
||||||
|
stringify!($n)
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
( : $ns:ident / $n:ident ) => {
|
( : $ns:ident / $n:ident ) => {
|
||||||
// We don't need to go through `new` -- `ident` is strict enough.
|
$crate::Keyword::namespaced(
|
||||||
$crate::NamespacedKeyword {
|
stringify!($ns),
|
||||||
namespace: stringify!($ns).into(),
|
stringify!($n)
|
||||||
name: stringify!($n).into(),
|
)
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
( : $ns:ident$(. $nss:ident)+ / $n:ident ) => {
|
( : $ns:ident$(. $nss:ident)+ / $n:ident ) => {
|
||||||
// We don't need to go through `new` -- `ident` is strict enough.
|
$crate::Keyword::namespaced(
|
||||||
$crate::NamespacedKeyword {
|
concat!(stringify!($ns) $(, ".", stringify!($nss))+),
|
||||||
namespace: concat!(stringify!($ns) $(, ".", stringify!($nss))+).into(),
|
stringify!($n)
|
||||||
name: stringify!($n).into(),
|
)
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,13 +141,13 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn can_import_edn() {
|
fn can_import_edn() {
|
||||||
assert_eq!("foo", Keyword::new("foo").0);
|
assert_eq!(":foo", &Keyword::plain("foo").to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_kw() {
|
fn test_kw() {
|
||||||
assert_eq!(kw!(:foo/bar), NamespacedKeyword::new("foo", "bar"));
|
assert_eq!(kw!(:foo/bar), Keyword::namespaced("foo", "bar"));
|
||||||
assert_eq!(kw!(:org.mozilla.foo/bar_baz), NamespacedKeyword::new("org.mozilla.foo", "bar_baz"));
|
assert_eq!(kw!(:org.mozilla.foo/bar_baz), Keyword::namespaced("org.mozilla.foo", "bar_baz"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
10
src/query.rs
10
src/query.rs
|
@ -33,7 +33,7 @@ pub use mentat_query_algebrizer::{
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use mentat_query::{
|
pub use mentat_query::{
|
||||||
NamespacedKeyword,
|
Keyword,
|
||||||
PlainSymbol,
|
PlainSymbol,
|
||||||
Variable,
|
Variable,
|
||||||
};
|
};
|
||||||
|
@ -212,9 +212,9 @@ fn fetch_values<'sqlite>
|
||||||
run_algebrized_query(known, sqlite, algebrized)
|
run_algebrized_query(known, sqlite, algebrized)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lookup_attribute(schema: &Schema, attribute: &NamespacedKeyword) -> Result<KnownEntid> {
|
fn lookup_attribute(schema: &Schema, attribute: &Keyword) -> Result<KnownEntid> {
|
||||||
schema.get_entid(attribute)
|
schema.get_entid(attribute)
|
||||||
.ok_or_else(|| ErrorKind::UnknownAttribute(attribute.name.clone()).into())
|
.ok_or_else(|| ErrorKind::UnknownAttribute(attribute.name().into()).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a single value for the provided entity and attribute.
|
/// Return a single value for the provided entity and attribute.
|
||||||
|
@ -271,7 +271,7 @@ pub fn lookup_value_for_attribute<'sqlite, 'attribute, E>
|
||||||
(sqlite: &'sqlite rusqlite::Connection,
|
(sqlite: &'sqlite rusqlite::Connection,
|
||||||
known: Known,
|
known: Known,
|
||||||
entity: E,
|
entity: E,
|
||||||
attribute: &'attribute NamespacedKeyword) -> Result<Option<TypedValue>>
|
attribute: &'attribute Keyword) -> Result<Option<TypedValue>>
|
||||||
where E: Into<Entid> {
|
where E: Into<Entid> {
|
||||||
let attribute = lookup_attribute(known.schema, attribute)?;
|
let attribute = lookup_attribute(known.schema, attribute)?;
|
||||||
lookup_value(sqlite, known, entity.into(), attribute)
|
lookup_value(sqlite, known, entity.into(), attribute)
|
||||||
|
@ -281,7 +281,7 @@ pub fn lookup_values_for_attribute<'sqlite, 'attribute, E>
|
||||||
(sqlite: &'sqlite rusqlite::Connection,
|
(sqlite: &'sqlite rusqlite::Connection,
|
||||||
known: Known,
|
known: Known,
|
||||||
entity: E,
|
entity: E,
|
||||||
attribute: &'attribute NamespacedKeyword) -> Result<Vec<TypedValue>>
|
attribute: &'attribute Keyword) -> Result<Vec<TypedValue>>
|
||||||
where E: Into<Entid> {
|
where E: Into<Entid> {
|
||||||
let attribute = lookup_attribute(known.schema, attribute)?;
|
let attribute = lookup_attribute(known.schema, attribute)?;
|
||||||
lookup_values(sqlite, known, entity.into(), attribute)
|
lookup_values(sqlite, known, entity.into(), attribute)
|
||||||
|
|
|
@ -15,7 +15,7 @@ use std::collections::{
|
||||||
|
|
||||||
use mentat_core::{
|
use mentat_core::{
|
||||||
Entid,
|
Entid,
|
||||||
NamespacedKeyword,
|
Keyword,
|
||||||
Binding,
|
Binding,
|
||||||
TypedValue,
|
TypedValue,
|
||||||
ValueType,
|
ValueType,
|
||||||
|
@ -53,7 +53,7 @@ impl<'a> QueryBuilder<'a> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bind_ref_from_kw(&mut self, var: &str, value: NamespacedKeyword) -> Result<&mut Self> {
|
pub fn bind_ref_from_kw(&mut self, var: &str, value: Keyword) -> Result<&mut Self> {
|
||||||
let entid = self.store.conn().current_schema().get_entid(&value).ok_or(ErrorKind::UnknownAttribute(value.to_string()))?;
|
let entid = self.store.conn().current_schema().get_entid(&value).ok_or(ErrorKind::UnknownAttribute(value.to_string()))?;
|
||||||
self.values.insert(Variable::from_valid_name(var), TypedValue::Ref(entid.into()));
|
self.values.insert(Variable::from_valid_name(var), TypedValue::Ref(entid.into()));
|
||||||
Ok(self)
|
Ok(self)
|
||||||
|
|
|
@ -109,7 +109,7 @@ use ::{
|
||||||
Entid,
|
Entid,
|
||||||
HasSchema,
|
HasSchema,
|
||||||
IntoResult,
|
IntoResult,
|
||||||
NamespacedKeyword,
|
Keyword,
|
||||||
Binding,
|
Binding,
|
||||||
TypedValue,
|
TypedValue,
|
||||||
ValueType,
|
ValueType,
|
||||||
|
@ -157,9 +157,9 @@ pub type Datom = (Entid, Entid, TypedValue);
|
||||||
/// checks or employ more fine-grained logic.
|
/// checks or employ more fine-grained logic.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Definition {
|
pub struct Definition {
|
||||||
pub name: NamespacedKeyword,
|
pub name: Keyword,
|
||||||
pub version: Version,
|
pub version: Version,
|
||||||
pub attributes: Vec<(NamespacedKeyword, Attribute)>,
|
pub attributes: Vec<(Keyword, Attribute)>,
|
||||||
pub pre: fn(&mut InProgress, &Vocabulary) -> Result<()>,
|
pub pre: fn(&mut InProgress, &Vocabulary) -> Result<()>,
|
||||||
pub post: fn(&mut InProgress, &Vocabulary) -> Result<()>,
|
pub post: fn(&mut InProgress, &Vocabulary) -> Result<()>,
|
||||||
}
|
}
|
||||||
|
@ -252,8 +252,8 @@ impl Definition {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new<N, A>(name: N, version: Version, attributes: A) -> Definition
|
pub fn new<N, A>(name: N, version: Version, attributes: A) -> Definition
|
||||||
where N: Into<NamespacedKeyword>,
|
where N: Into<Keyword>,
|
||||||
A: Into<Vec<(NamespacedKeyword, Attribute)>> {
|
A: Into<Vec<(Keyword, Attribute)>> {
|
||||||
Definition {
|
Definition {
|
||||||
name: name.into(),
|
name: name.into(),
|
||||||
version: version,
|
version: version,
|
||||||
|
@ -279,7 +279,7 @@ impl Definition {
|
||||||
/// A definition of a vocabulary as retrieved from a particular store.
|
/// A definition of a vocabulary as retrieved from a particular store.
|
||||||
///
|
///
|
||||||
/// A `Vocabulary` is just like `Definition`, but concrete: its name and attributes are identified
|
/// A `Vocabulary` is just like `Definition`, but concrete: its name and attributes are identified
|
||||||
/// by `Entid`, not `NamespacedKeyword`.
|
/// by `Entid`, not `Keyword`.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct Vocabulary {
|
pub struct Vocabulary {
|
||||||
pub entity: Entid,
|
pub entity: Entid,
|
||||||
|
@ -295,68 +295,68 @@ impl Vocabulary {
|
||||||
|
|
||||||
/// A collection of named `Vocabulary` instances, as retrieved from the store.
|
/// A collection of named `Vocabulary` instances, as retrieved from the store.
|
||||||
#[derive(Debug, Default, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
pub struct Vocabularies(pub BTreeMap<NamespacedKeyword, Vocabulary>); // N.B., this has a copy of the attributes in Schema!
|
pub struct Vocabularies(pub BTreeMap<Keyword, Vocabulary>); // N.B., this has a copy of the attributes in Schema!
|
||||||
|
|
||||||
impl Vocabularies {
|
impl Vocabularies {
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.0.len()
|
self.0.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&self, name: &NamespacedKeyword) -> Option<&Vocabulary> {
|
pub fn get(&self, name: &Keyword) -> Option<&Vocabulary> {
|
||||||
self.0.get(name)
|
self.0.get(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter(&self) -> ::std::collections::btree_map::Iter<NamespacedKeyword, Vocabulary> {
|
pub fn iter(&self) -> ::std::collections::btree_map::Iter<Keyword, Vocabulary> {
|
||||||
self.0.iter()
|
self.0.iter()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref DB_SCHEMA_CORE: NamespacedKeyword = {
|
static ref DB_SCHEMA_CORE: Keyword = {
|
||||||
kw!(:db.schema/core)
|
kw!(:db.schema/core)
|
||||||
};
|
};
|
||||||
static ref DB_SCHEMA_ATTRIBUTE: NamespacedKeyword = {
|
static ref DB_SCHEMA_ATTRIBUTE: Keyword = {
|
||||||
kw!(:db.schema/attribute)
|
kw!(:db.schema/attribute)
|
||||||
};
|
};
|
||||||
static ref DB_SCHEMA_VERSION: NamespacedKeyword = {
|
static ref DB_SCHEMA_VERSION: Keyword = {
|
||||||
kw!(:db.schema/version)
|
kw!(:db.schema/version)
|
||||||
};
|
};
|
||||||
static ref DB_IDENT: NamespacedKeyword = {
|
static ref DB_IDENT: Keyword = {
|
||||||
kw!(:db/ident)
|
kw!(:db/ident)
|
||||||
};
|
};
|
||||||
static ref DB_UNIQUE: NamespacedKeyword = {
|
static ref DB_UNIQUE: Keyword = {
|
||||||
kw!(:db/unique)
|
kw!(:db/unique)
|
||||||
};
|
};
|
||||||
static ref DB_UNIQUE_VALUE: NamespacedKeyword = {
|
static ref DB_UNIQUE_VALUE: Keyword = {
|
||||||
kw!(:db.unique/value)
|
kw!(:db.unique/value)
|
||||||
};
|
};
|
||||||
static ref DB_UNIQUE_IDENTITY: NamespacedKeyword = {
|
static ref DB_UNIQUE_IDENTITY: Keyword = {
|
||||||
kw!(:db.unique/identity)
|
kw!(:db.unique/identity)
|
||||||
};
|
};
|
||||||
static ref DB_IS_COMPONENT: NamespacedKeyword = {
|
static ref DB_IS_COMPONENT: Keyword = {
|
||||||
NamespacedKeyword::new("db", "isComponent")
|
Keyword::namespaced("db", "isComponent")
|
||||||
};
|
};
|
||||||
static ref DB_VALUE_TYPE: NamespacedKeyword = {
|
static ref DB_VALUE_TYPE: Keyword = {
|
||||||
NamespacedKeyword::new("db", "valueType")
|
Keyword::namespaced("db", "valueType")
|
||||||
};
|
};
|
||||||
static ref DB_INDEX: NamespacedKeyword = {
|
static ref DB_INDEX: Keyword = {
|
||||||
kw!(:db/index)
|
kw!(:db/index)
|
||||||
};
|
};
|
||||||
static ref DB_FULLTEXT: NamespacedKeyword = {
|
static ref DB_FULLTEXT: Keyword = {
|
||||||
kw!(:db/fulltext)
|
kw!(:db/fulltext)
|
||||||
};
|
};
|
||||||
static ref DB_CARDINALITY: NamespacedKeyword = {
|
static ref DB_CARDINALITY: Keyword = {
|
||||||
kw!(:db/cardinality)
|
kw!(:db/cardinality)
|
||||||
};
|
};
|
||||||
static ref DB_CARDINALITY_ONE: NamespacedKeyword = {
|
static ref DB_CARDINALITY_ONE: Keyword = {
|
||||||
kw!(:db.cardinality/one)
|
kw!(:db.cardinality/one)
|
||||||
};
|
};
|
||||||
static ref DB_CARDINALITY_MANY: NamespacedKeyword = {
|
static ref DB_CARDINALITY_MANY: Keyword = {
|
||||||
kw!(:db.cardinality/many)
|
kw!(:db.cardinality/many)
|
||||||
};
|
};
|
||||||
|
|
||||||
static ref DB_NO_HISTORY: NamespacedKeyword = {
|
static ref DB_NO_HISTORY: Keyword = {
|
||||||
NamespacedKeyword::new("db", "noHistory")
|
Keyword::namespaced("db", "noHistory")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,11 +365,11 @@ trait HasCoreSchema {
|
||||||
fn core_type(&self, t: ValueType) -> Result<KnownEntid>;
|
fn core_type(&self, t: ValueType) -> Result<KnownEntid>;
|
||||||
|
|
||||||
/// Return the entity ID for an ident. On failure, return `MissingCoreVocabulary`.
|
/// Return the entity ID for an ident. On failure, return `MissingCoreVocabulary`.
|
||||||
fn core_entid(&self, ident: &NamespacedKeyword) -> Result<KnownEntid>;
|
fn core_entid(&self, ident: &Keyword) -> Result<KnownEntid>;
|
||||||
|
|
||||||
/// Return the entity ID for an attribute's keyword. On failure, return
|
/// Return the entity ID for an attribute's keyword. On failure, return
|
||||||
/// `MissingCoreVocabulary`.
|
/// `MissingCoreVocabulary`.
|
||||||
fn core_attribute(&self, ident: &NamespacedKeyword) -> Result<KnownEntid>;
|
fn core_attribute(&self, ident: &Keyword) -> Result<KnownEntid>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> HasCoreSchema for T where T: HasSchema {
|
impl<T> HasCoreSchema for T where T: HasSchema {
|
||||||
|
@ -378,12 +378,12 @@ impl<T> HasCoreSchema for T where T: HasSchema {
|
||||||
.ok_or_else(|| ErrorKind::MissingCoreVocabulary(DB_SCHEMA_VERSION.clone()).into())
|
.ok_or_else(|| ErrorKind::MissingCoreVocabulary(DB_SCHEMA_VERSION.clone()).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn core_entid(&self, ident: &NamespacedKeyword) -> Result<KnownEntid> {
|
fn core_entid(&self, ident: &Keyword) -> Result<KnownEntid> {
|
||||||
self.get_entid(ident)
|
self.get_entid(ident)
|
||||||
.ok_or_else(|| ErrorKind::MissingCoreVocabulary(DB_SCHEMA_VERSION.clone()).into())
|
.ok_or_else(|| ErrorKind::MissingCoreVocabulary(DB_SCHEMA_VERSION.clone()).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn core_attribute(&self, ident: &NamespacedKeyword) -> Result<KnownEntid> {
|
fn core_attribute(&self, ident: &Keyword) -> Result<KnownEntid> {
|
||||||
self.attribute_for_ident(ident)
|
self.attribute_for_ident(ident)
|
||||||
.ok_or_else(|| ErrorKind::MissingCoreVocabulary(DB_SCHEMA_VERSION.clone()).into())
|
.ok_or_else(|| ErrorKind::MissingCoreVocabulary(DB_SCHEMA_VERSION.clone()).into())
|
||||||
.map(|(_, e)| e)
|
.map(|(_, e)| e)
|
||||||
|
@ -391,9 +391,9 @@ impl<T> HasCoreSchema for T where T: HasSchema {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Definition {
|
impl Definition {
|
||||||
fn description_for_attributes<'s, T, R>(&'s self, attributes: &[R], via: &T, diff: Option<BTreeMap<NamespacedKeyword, Attribute>>) -> Result<Terms>
|
fn description_for_attributes<'s, T, R>(&'s self, attributes: &[R], via: &T, diff: Option<BTreeMap<Keyword, Attribute>>) -> Result<Terms>
|
||||||
where T: HasCoreSchema,
|
where T: HasCoreSchema,
|
||||||
R: ::std::borrow::Borrow<(NamespacedKeyword, Attribute)> {
|
R: ::std::borrow::Borrow<(Keyword, Attribute)> {
|
||||||
|
|
||||||
// The attributes we'll need to describe this vocabulary.
|
// The attributes we'll need to describe this vocabulary.
|
||||||
let a_version = via.core_attribute(&DB_SCHEMA_VERSION)?;
|
let a_version = via.core_attribute(&DB_SCHEMA_VERSION)?;
|
||||||
|
@ -520,7 +520,7 @@ pub enum VocabularyCheck<'definition> {
|
||||||
PresentButTooNew { newer_version: Vocabulary },
|
PresentButTooNew { newer_version: Vocabulary },
|
||||||
|
|
||||||
/// The provided definition is present in the store, but some of its attributes are not.
|
/// The provided definition is present in the store, but some of its attributes are not.
|
||||||
PresentButMissingAttributes { attributes: Vec<&'definition (NamespacedKeyword, Attribute)> },
|
PresentButMissingAttributes { attributes: Vec<&'definition (Keyword, Attribute)> },
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This enum captures the outcome of attempting to ensure that a vocabulary definition is present
|
/// This enum captures the outcome of attempting to ensure that a vocabulary definition is present
|
||||||
|
@ -545,7 +545,7 @@ pub enum VocabularyOutcome {
|
||||||
/// This trait captures the ability to retrieve and describe stored vocabularies.
|
/// This trait captures the ability to retrieve and describe stored vocabularies.
|
||||||
pub trait HasVocabularies {
|
pub trait HasVocabularies {
|
||||||
fn read_vocabularies(&self) -> Result<Vocabularies>;
|
fn read_vocabularies(&self) -> Result<Vocabularies>;
|
||||||
fn read_vocabulary_named(&self, name: &NamespacedKeyword) -> Result<Option<Vocabulary>>;
|
fn read_vocabulary_named(&self, name: &Keyword) -> Result<Option<Vocabulary>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This trait captures the ability of a store to check and install/upgrade vocabularies.
|
/// This trait captures the ability of a store to check and install/upgrade vocabularies.
|
||||||
|
@ -557,7 +557,7 @@ pub trait VersionedStore: HasVocabularies + HasSchema {
|
||||||
// Check the version.
|
// Check the version.
|
||||||
if vocabulary.version == definition.version {
|
if vocabulary.version == definition.version {
|
||||||
// Same version. Check that all of our attributes are present.
|
// Same version. Check that all of our attributes are present.
|
||||||
let mut missing: Vec<&'definition (NamespacedKeyword, Attribute)> = vec![];
|
let mut missing: Vec<&'definition (Keyword, Attribute)> = vec![];
|
||||||
for pair in definition.attributes.iter() {
|
for pair in definition.attributes.iter() {
|
||||||
if let Some(entid) = self.get_entid(&pair.0) {
|
if let Some(entid) = self.get_entid(&pair.0) {
|
||||||
if let Some(existing) = vocabulary.find(entid) {
|
if let Some(existing) = vocabulary.find(entid) {
|
||||||
|
@ -609,7 +609,7 @@ pub trait VersionedStore: HasVocabularies + HasSchema {
|
||||||
///
|
///
|
||||||
/// Use this function instead of calling `ensure_vocabulary` if you need to have pre/post
|
/// Use this function instead of calling `ensure_vocabulary` if you need to have pre/post
|
||||||
/// functions invoked when vocabulary changes are necessary.
|
/// functions invoked when vocabulary changes are necessary.
|
||||||
fn ensure_vocabularies(&mut self, vocabularies: &mut VocabularySource) -> Result<BTreeMap<NamespacedKeyword, VocabularyOutcome>>;
|
fn ensure_vocabularies(&mut self, vocabularies: &mut VocabularySource) -> Result<BTreeMap<Keyword, VocabularyOutcome>>;
|
||||||
|
|
||||||
/// Make sure that our expectations of the core vocabulary — basic types and attributes — are met.
|
/// Make sure that our expectations of the core vocabulary — basic types and attributes — are met.
|
||||||
fn verify_core_schema(&self) -> Result<()> {
|
fn verify_core_schema(&self) -> Result<()> {
|
||||||
|
@ -632,13 +632,13 @@ pub trait VersionedStore: HasVocabularies + HasSchema {
|
||||||
/// vocabularies — you can retrieve the requested definition and the resulting `VocabularyCheck`
|
/// vocabularies — you can retrieve the requested definition and the resulting `VocabularyCheck`
|
||||||
/// by name.
|
/// by name.
|
||||||
pub trait VocabularyStatus {
|
pub trait VocabularyStatus {
|
||||||
fn get(&self, name: &NamespacedKeyword) -> Option<(&Definition, &VocabularyCheck)>;
|
fn get(&self, name: &Keyword) -> Option<(&Definition, &VocabularyCheck)>;
|
||||||
fn version(&self, name: &NamespacedKeyword) -> Option<Version>;
|
fn version(&self, name: &Keyword) -> Option<Version>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct CheckedVocabularies<'a> {
|
struct CheckedVocabularies<'a> {
|
||||||
items: BTreeMap<NamespacedKeyword, (&'a Definition, VocabularyCheck<'a>)>,
|
items: BTreeMap<Keyword, (&'a Definition, VocabularyCheck<'a>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> CheckedVocabularies<'a> {
|
impl<'a> CheckedVocabularies<'a> {
|
||||||
|
@ -652,18 +652,18 @@ impl<'a> CheckedVocabularies<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> VocabularyStatus for CheckedVocabularies<'a> {
|
impl<'a> VocabularyStatus for CheckedVocabularies<'a> {
|
||||||
fn get(&self, name: &NamespacedKeyword) -> Option<(&Definition, &VocabularyCheck)> {
|
fn get(&self, name: &Keyword) -> Option<(&Definition, &VocabularyCheck)> {
|
||||||
self.items.get(name).map(|&(ref d, ref c)| (*d, c))
|
self.items.get(name).map(|&(ref d, ref c)| (*d, c))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn version(&self, name: &NamespacedKeyword) -> Option<Version> {
|
fn version(&self, name: &Keyword) -> Option<Version> {
|
||||||
self.items.get(name).map(|&(d, _)| d.version)
|
self.items.get(name).map(|&(d, _)| d.version)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait VocabularyMechanics {
|
trait VocabularyMechanics {
|
||||||
fn install_vocabulary(&mut self, definition: &Definition) -> Result<VocabularyOutcome>;
|
fn install_vocabulary(&mut self, definition: &Definition) -> Result<VocabularyOutcome>;
|
||||||
fn install_attributes_for<'definition>(&mut self, definition: &'definition Definition, attributes: Vec<&'definition (NamespacedKeyword, Attribute)>) -> Result<VocabularyOutcome>;
|
fn install_attributes_for<'definition>(&mut self, definition: &'definition Definition, attributes: Vec<&'definition (Keyword, Attribute)>) -> Result<VocabularyOutcome>;
|
||||||
fn upgrade_vocabulary(&mut self, definition: &Definition, from_version: Vocabulary) -> Result<VocabularyOutcome>;
|
fn upgrade_vocabulary(&mut self, definition: &Definition, from_version: Vocabulary) -> Result<VocabularyOutcome>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -686,7 +686,7 @@ impl<'a, 'c> VersionedStore for InProgress<'a, 'c> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ensure_vocabularies(&mut self, vocabularies: &mut VocabularySource) -> Result<BTreeMap<NamespacedKeyword, VocabularyOutcome>> {
|
fn ensure_vocabularies(&mut self, vocabularies: &mut VocabularySource) -> Result<BTreeMap<Keyword, VocabularyOutcome>> {
|
||||||
let definitions = vocabularies.definitions();
|
let definitions = vocabularies.definitions();
|
||||||
|
|
||||||
let mut update = Vec::new();
|
let mut update = Vec::new();
|
||||||
|
@ -817,7 +817,7 @@ impl<'a, 'c> VocabularyMechanics for InProgress<'a, 'c> {
|
||||||
Ok(VocabularyOutcome::Installed)
|
Ok(VocabularyOutcome::Installed)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn install_attributes_for<'definition>(&mut self, definition: &'definition Definition, attributes: Vec<&'definition (NamespacedKeyword, Attribute)>) -> Result<VocabularyOutcome> {
|
fn install_attributes_for<'definition>(&mut self, definition: &'definition Definition, attributes: Vec<&'definition (Keyword, Attribute)>) -> Result<VocabularyOutcome> {
|
||||||
let (terms, tempids) = definition.description_for_attributes(&attributes, self, None)?;
|
let (terms, tempids) = definition.description_for_attributes(&attributes, self, None)?;
|
||||||
self.transact_terms(terms, tempids)?;
|
self.transact_terms(terms, tempids)?;
|
||||||
Ok(VocabularyOutcome::InstalledMissingAttributes)
|
Ok(VocabularyOutcome::InstalledMissingAttributes)
|
||||||
|
@ -843,7 +843,7 @@ impl<'a, 'c> VocabularyMechanics for InProgress<'a, 'c> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> HasVocabularies for T where T: HasSchema + Queryable {
|
impl<T> HasVocabularies for T where T: HasSchema + Queryable {
|
||||||
fn read_vocabulary_named(&self, name: &NamespacedKeyword) -> Result<Option<Vocabulary>> {
|
fn read_vocabulary_named(&self, name: &Keyword) -> Result<Option<Vocabulary>> {
|
||||||
if let Some(entid) = self.get_entid(name) {
|
if let Some(entid) = self.get_entid(name) {
|
||||||
match self.lookup_value_for_attribute(entid, &DB_SCHEMA_VERSION)? {
|
match self.lookup_value_for_attribute(entid, &DB_SCHEMA_VERSION)? {
|
||||||
None => Ok(None),
|
None => Ok(None),
|
||||||
|
|
|
@ -34,7 +34,7 @@ use mentat::{
|
||||||
Entid,
|
Entid,
|
||||||
HasSchema,
|
HasSchema,
|
||||||
IntoResult,
|
IntoResult,
|
||||||
NamespacedKeyword,
|
Keyword,
|
||||||
Pullable,
|
Pullable,
|
||||||
Queryable,
|
Queryable,
|
||||||
QueryInputs,
|
QueryInputs,
|
||||||
|
@ -127,14 +127,14 @@ fn test_simple_pull() {
|
||||||
.into_rel_result()
|
.into_rel_result()
|
||||||
.expect("results");
|
.expect("results");
|
||||||
|
|
||||||
let beacon_district: Vec<(NamespacedKeyword, TypedValue)> = vec![
|
let beacon_district: Vec<(Keyword, TypedValue)> = vec![
|
||||||
(kw!(:district/name), "Greater Duwamish".into()),
|
(kw!(:district/name), "Greater Duwamish".into()),
|
||||||
(kw!(:district/region), schema.get_entid(&NamespacedKeyword::new("region", "se")).unwrap().into())
|
(kw!(:district/region), schema.get_entid(&Keyword::namespaced("region", "se")).unwrap().into())
|
||||||
];
|
];
|
||||||
let beacon_district: StructuredMap = beacon_district.into();
|
let beacon_district: StructuredMap = beacon_district.into();
|
||||||
let capitol_district: Vec<(NamespacedKeyword, TypedValue)> = vec![
|
let capitol_district: Vec<(Keyword, TypedValue)> = vec![
|
||||||
(kw!(:district/name), "East".into()),
|
(kw!(:district/name), "East".into()),
|
||||||
(kw!(:district/region), schema.get_entid(&NamespacedKeyword::new("region", "e")).unwrap().into())
|
(kw!(:district/region), schema.get_entid(&Keyword::namespaced("region", "e")).unwrap().into())
|
||||||
];
|
];
|
||||||
let capitol_district: StructuredMap = capitol_district.into();
|
let capitol_district: StructuredMap = capitol_district.into();
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ use mentat_query_projector::{
|
||||||
|
|
||||||
use mentat::{
|
use mentat::{
|
||||||
IntoResult,
|
IntoResult,
|
||||||
NamespacedKeyword,
|
Keyword,
|
||||||
PlainSymbol,
|
PlainSymbol,
|
||||||
QueryInputs,
|
QueryInputs,
|
||||||
Queryable,
|
Queryable,
|
||||||
|
@ -135,7 +135,7 @@ fn test_scalar() {
|
||||||
|
|
||||||
if let QueryResults::Scalar(Some(Binding::Scalar(TypedValue::Keyword(ref rc)))) = results {
|
if let QueryResults::Scalar(Some(Binding::Scalar(TypedValue::Keyword(ref rc)))) = results {
|
||||||
// Should be '24'.
|
// Should be '24'.
|
||||||
assert_eq!(&NamespacedKeyword::new("db.type", "keyword"), rc.as_ref());
|
assert_eq!(&Keyword::namespaced("db.type", "keyword"), rc.as_ref());
|
||||||
assert_eq!(KnownEntid(24),
|
assert_eq!(KnownEntid(24),
|
||||||
db.schema.get_entid(rc).unwrap());
|
db.schema.get_entid(rc).unwrap());
|
||||||
} else {
|
} else {
|
||||||
|
@ -165,7 +165,7 @@ fn test_tuple() {
|
||||||
assert_eq!(1, results.len());
|
assert_eq!(1, results.len());
|
||||||
|
|
||||||
if let QueryResults::Tuple(Some(ref tuple)) = results {
|
if let QueryResults::Tuple(Some(ref tuple)) = results {
|
||||||
let cardinality_one = NamespacedKeyword::new("db.cardinality", "one");
|
let cardinality_one = Keyword::namespaced("db.cardinality", "one");
|
||||||
assert_eq!(tuple.len(), 2);
|
assert_eq!(tuple.len(), 2);
|
||||||
assert_eq!(tuple[0], TypedValue::Boolean(true).into());
|
assert_eq!(tuple[0], TypedValue::Boolean(true).into());
|
||||||
assert_eq!(tuple[1], db.schema.get_entid(&cardinality_one).expect("c1").into());
|
assert_eq!(tuple[1], db.schema.get_entid(&cardinality_one).expect("c1").into());
|
||||||
|
@ -216,7 +216,7 @@ fn test_inputs() {
|
||||||
.results;
|
.results;
|
||||||
|
|
||||||
if let QueryResults::Scalar(Some(Binding::Scalar(TypedValue::Keyword(value)))) = results {
|
if let QueryResults::Scalar(Some(Binding::Scalar(TypedValue::Keyword(value)))) = results {
|
||||||
assert_eq!(value.as_ref(), &NamespacedKeyword::new("db.install", "valueType"));
|
assert_eq!(value.as_ref(), &Keyword::namespaced("db.install", "valueType"));
|
||||||
} else {
|
} else {
|
||||||
panic!("Expected scalar.");
|
panic!("Expected scalar.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ use mentat::{
|
||||||
Conn,
|
Conn,
|
||||||
InProgress,
|
InProgress,
|
||||||
KnownEntid,
|
KnownEntid,
|
||||||
NamespacedKeyword,
|
Keyword,
|
||||||
QueryInputs,
|
QueryInputs,
|
||||||
Queryable,
|
Queryable,
|
||||||
RelResult,
|
RelResult,
|
||||||
|
@ -65,11 +65,11 @@ use mentat::errors::{
|
||||||
};
|
};
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref FOO_NAME: NamespacedKeyword = {
|
static ref FOO_NAME: Keyword = {
|
||||||
kw!(:foo/name)
|
kw!(:foo/name)
|
||||||
};
|
};
|
||||||
|
|
||||||
static ref FOO_MOMENT: NamespacedKeyword = {
|
static ref FOO_MOMENT: Keyword = {
|
||||||
kw!(:foo/moment)
|
kw!(:foo/moment)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ use mentat_core::{
|
||||||
|
|
||||||
use mentat::{
|
use mentat::{
|
||||||
CacheDirection,
|
CacheDirection,
|
||||||
NamespacedKeyword,
|
Keyword,
|
||||||
Queryable,
|
Queryable,
|
||||||
QueryExplanation,
|
QueryExplanation,
|
||||||
QueryOutput,
|
QueryOutput,
|
||||||
|
@ -109,12 +109,12 @@ fn eprint_out(s: &str) {
|
||||||
eprint!("{green}{s}{reset}", green = color::Fg(::GREEN), s = s, reset = color::Fg(color::Reset));
|
eprint!("{green}{s}{reset}", green = color::Fg(::GREEN), s = s, reset = color::Fg(color::Reset));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_namespaced_keyword(input: &str) -> Option<NamespacedKeyword> {
|
fn parse_namespaced_keyword(input: &str) -> Option<Keyword> {
|
||||||
let splits = [':', '/'];
|
let splits = [':', '/'];
|
||||||
let mut i = input.split(&splits[..]);
|
let mut i = input.split(&splits[..]);
|
||||||
match (i.next(), i.next(), i.next(), i.next()) {
|
match (i.next(), i.next(), i.next(), i.next()) {
|
||||||
(Some(""), Some(namespace), Some(name), None) => {
|
(Some(""), Some(namespace), Some(name), None) => {
|
||||||
Some(NamespacedKeyword::new(namespace, name))
|
Some(Keyword::namespaced(namespace, name))
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue