Part 3: Move query
into edn
.
It's unfortunate to squash two crates together like this, but it's the best option.
This commit is contained in:
parent
a4a8892309
commit
a8073056f2
4 changed files with 81 additions and 73 deletions
|
@ -25,6 +25,7 @@ extern crate serde_derive;
|
||||||
pub mod entities;
|
pub mod entities;
|
||||||
// Intentionally not pub.
|
// Intentionally not pub.
|
||||||
mod namespaceable_name;
|
mod namespaceable_name;
|
||||||
|
pub mod query;
|
||||||
pub mod symbols;
|
pub mod symbols;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
pub mod pretty_print;
|
pub mod pretty_print;
|
||||||
|
|
126
edn/src/query.rs
126
edn/src/query.rs
|
@ -30,18 +30,18 @@
|
||||||
///! deeply into this it's worth recognizing that this loss of 'sovereignty' is
|
///! deeply into this it's worth recognizing that this loss of 'sovereignty' is
|
||||||
///! a tradeoff against well-typed function signatures and other such boundaries.
|
///! a tradeoff against well-typed function signatures and other such boundaries.
|
||||||
|
|
||||||
extern crate edn;
|
|
||||||
extern crate mentat_core;
|
|
||||||
|
|
||||||
use std::collections::{
|
use std::collections::{
|
||||||
BTreeSet,
|
BTreeSet,
|
||||||
HashSet,
|
HashSet,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use std;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::rc::Rc;
|
use std::rc::{
|
||||||
|
Rc,
|
||||||
|
};
|
||||||
|
|
||||||
use edn::{
|
use ::{
|
||||||
BigInt,
|
BigInt,
|
||||||
DateTime,
|
DateTime,
|
||||||
OrderedFloat,
|
OrderedFloat,
|
||||||
|
@ -49,15 +49,14 @@ use edn::{
|
||||||
Utc,
|
Utc,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use edn::{
|
use ::value_rc::{
|
||||||
Keyword,
|
FromRc,
|
||||||
PlainSymbol,
|
ValueRc,
|
||||||
};
|
};
|
||||||
|
|
||||||
use mentat_core::{
|
pub use ::{
|
||||||
FromRc,
|
Keyword,
|
||||||
TypedValue,
|
PlainSymbol,
|
||||||
ValueRc,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type SrcVarName = String; // Do not include the required syntactic '$'.
|
pub type SrcVarName = String; // Do not include the required syntactic '$'.
|
||||||
|
@ -87,15 +86,15 @@ impl Variable {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait FromValue<T> {
|
pub trait FromValue<T> {
|
||||||
fn from_value(v: &edn::ValueAndSpan) -> Option<T>;
|
fn from_value(v: &::ValueAndSpan) -> Option<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If the provided EDN value is a PlainSymbol beginning with '?', return
|
/// If the provided EDN value is a PlainSymbol beginning with '?', return
|
||||||
/// it wrapped in a Variable. If not, return None.
|
/// it wrapped in a Variable. If not, return None.
|
||||||
/// TODO: intern strings. #398.
|
/// TODO: intern strings. #398.
|
||||||
impl FromValue<Variable> for Variable {
|
impl FromValue<Variable> for Variable {
|
||||||
fn from_value(v: &edn::ValueAndSpan) -> Option<Variable> {
|
fn from_value(v: &::ValueAndSpan) -> Option<Variable> {
|
||||||
if let edn::SpannedValue::PlainSymbol(ref s) = v.inner {
|
if let ::SpannedValue::PlainSymbol(ref s) = v.inner {
|
||||||
Variable::from_symbol(s)
|
Variable::from_symbol(s)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -138,8 +137,8 @@ impl std::fmt::Display for Variable {
|
||||||
pub struct QueryFunction(pub PlainSymbol);
|
pub struct QueryFunction(pub PlainSymbol);
|
||||||
|
|
||||||
impl FromValue<QueryFunction> for QueryFunction {
|
impl FromValue<QueryFunction> for QueryFunction {
|
||||||
fn from_value(v: &edn::ValueAndSpan) -> Option<QueryFunction> {
|
fn from_value(v: &::ValueAndSpan) -> Option<QueryFunction> {
|
||||||
if let edn::SpannedValue::PlainSymbol(ref s) = v.inner {
|
if let ::SpannedValue::PlainSymbol(ref s) = v.inner {
|
||||||
QueryFunction::from_symbol(s)
|
QueryFunction::from_symbol(s)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -177,8 +176,8 @@ pub enum SrcVar {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromValue<SrcVar> for SrcVar {
|
impl FromValue<SrcVar> for SrcVar {
|
||||||
fn from_value(v: &edn::ValueAndSpan) -> Option<SrcVar> {
|
fn from_value(v: &::ValueAndSpan) -> Option<SrcVar> {
|
||||||
if let edn::SpannedValue::PlainSymbol(ref s) = v.inner {
|
if let ::SpannedValue::PlainSymbol(ref s) = v.inner {
|
||||||
SrcVar::from_symbol(s)
|
SrcVar::from_symbol(s)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -211,19 +210,6 @@ pub enum NonIntegerConstant {
|
||||||
Uuid(Uuid),
|
Uuid(Uuid),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NonIntegerConstant {
|
|
||||||
pub fn into_typed_value(self) -> TypedValue {
|
|
||||||
match self {
|
|
||||||
NonIntegerConstant::BigInteger(_) => unimplemented!(), // TODO: #280.
|
|
||||||
NonIntegerConstant::Boolean(v) => TypedValue::Boolean(v),
|
|
||||||
NonIntegerConstant::Float(v) => TypedValue::Double(v),
|
|
||||||
NonIntegerConstant::Text(v) => v.into(),
|
|
||||||
NonIntegerConstant::Instant(v) => TypedValue::Instant(v),
|
|
||||||
NonIntegerConstant::Uuid(v) => TypedValue::Uuid(v),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> From<&'a str> for NonIntegerConstant {
|
impl<'a> From<&'a str> for NonIntegerConstant {
|
||||||
fn from(val: &'a str) -> NonIntegerConstant {
|
fn from(val: &'a str) -> NonIntegerConstant {
|
||||||
NonIntegerConstant::Text(ValueRc::new(val.to_string()))
|
NonIntegerConstant::Text(ValueRc::new(val.to_string()))
|
||||||
|
@ -249,8 +235,8 @@ pub enum FnArg {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromValue<FnArg> for FnArg {
|
impl FromValue<FnArg> for FnArg {
|
||||||
fn from_value(v: &edn::ValueAndSpan) -> Option<FnArg> {
|
fn from_value(v: &::ValueAndSpan) -> Option<FnArg> {
|
||||||
use edn::SpannedValue::*;
|
use ::SpannedValue::*;
|
||||||
match v.inner {
|
match v.inner {
|
||||||
Integer(x) =>
|
Integer(x) =>
|
||||||
Some(FnArg::EntidOrInteger(x)),
|
Some(FnArg::EntidOrInteger(x)),
|
||||||
|
@ -362,14 +348,14 @@ impl PatternNonValuePlace {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromValue<PatternNonValuePlace> for PatternNonValuePlace {
|
impl FromValue<PatternNonValuePlace> for PatternNonValuePlace {
|
||||||
fn from_value(v: &edn::ValueAndSpan) -> Option<PatternNonValuePlace> {
|
fn from_value(v: &::ValueAndSpan) -> Option<PatternNonValuePlace> {
|
||||||
match v.inner {
|
match v.inner {
|
||||||
edn::SpannedValue::Integer(x) => if x >= 0 {
|
::SpannedValue::Integer(x) => if x >= 0 {
|
||||||
Some(PatternNonValuePlace::Entid(x))
|
Some(PatternNonValuePlace::Entid(x))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
edn::SpannedValue::PlainSymbol(ref x) => if x.0.as_str() == "_" {
|
::SpannedValue::PlainSymbol(ref x) => if x.0.as_str() == "_" {
|
||||||
Some(PatternNonValuePlace::Placeholder)
|
Some(PatternNonValuePlace::Placeholder)
|
||||||
} else {
|
} else {
|
||||||
if let Some(v) = Variable::from_symbol(x) {
|
if let Some(v) = Variable::from_symbol(x) {
|
||||||
|
@ -378,7 +364,7 @@ impl FromValue<PatternNonValuePlace> for PatternNonValuePlace {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
edn::SpannedValue::Keyword(ref x) =>
|
::SpannedValue::Keyword(ref x) =>
|
||||||
Some(x.clone().into()),
|
Some(x.clone().into()),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
@ -416,38 +402,38 @@ impl From<Keyword> for PatternValuePlace {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromValue<PatternValuePlace> for PatternValuePlace {
|
impl FromValue<PatternValuePlace> for PatternValuePlace {
|
||||||
fn from_value(v: &edn::ValueAndSpan) -> Option<PatternValuePlace> {
|
fn from_value(v: &::ValueAndSpan) -> Option<PatternValuePlace> {
|
||||||
match v.inner {
|
match v.inner {
|
||||||
edn::SpannedValue::Integer(x) =>
|
::SpannedValue::Integer(x) =>
|
||||||
Some(PatternValuePlace::EntidOrInteger(x)),
|
Some(PatternValuePlace::EntidOrInteger(x)),
|
||||||
edn::SpannedValue::PlainSymbol(ref x) if x.0.as_str() == "_" =>
|
::SpannedValue::PlainSymbol(ref x) if x.0.as_str() == "_" =>
|
||||||
Some(PatternValuePlace::Placeholder),
|
Some(PatternValuePlace::Placeholder),
|
||||||
edn::SpannedValue::PlainSymbol(ref x) =>
|
::SpannedValue::PlainSymbol(ref x) =>
|
||||||
Variable::from_symbol(x).map(PatternValuePlace::Variable),
|
Variable::from_symbol(x).map(PatternValuePlace::Variable),
|
||||||
edn::SpannedValue::Keyword(ref x) if x.is_namespaced() =>
|
::SpannedValue::Keyword(ref x) if x.is_namespaced() =>
|
||||||
Some(x.clone().into()),
|
Some(x.clone().into()),
|
||||||
edn::SpannedValue::Boolean(x) =>
|
::SpannedValue::Boolean(x) =>
|
||||||
Some(PatternValuePlace::Constant(NonIntegerConstant::Boolean(x))),
|
Some(PatternValuePlace::Constant(NonIntegerConstant::Boolean(x))),
|
||||||
edn::SpannedValue::Float(x) =>
|
::SpannedValue::Float(x) =>
|
||||||
Some(PatternValuePlace::Constant(NonIntegerConstant::Float(x))),
|
Some(PatternValuePlace::Constant(NonIntegerConstant::Float(x))),
|
||||||
edn::SpannedValue::BigInteger(ref x) =>
|
::SpannedValue::BigInteger(ref x) =>
|
||||||
Some(PatternValuePlace::Constant(NonIntegerConstant::BigInteger(x.clone()))),
|
Some(PatternValuePlace::Constant(NonIntegerConstant::BigInteger(x.clone()))),
|
||||||
edn::SpannedValue::Instant(x) =>
|
::SpannedValue::Instant(x) =>
|
||||||
Some(PatternValuePlace::Constant(NonIntegerConstant::Instant(x))),
|
Some(PatternValuePlace::Constant(NonIntegerConstant::Instant(x))),
|
||||||
edn::SpannedValue::Text(ref x) =>
|
::SpannedValue::Text(ref x) =>
|
||||||
// TODO: intern strings. #398.
|
// TODO: intern strings. #398.
|
||||||
Some(PatternValuePlace::Constant(x.clone().into())),
|
Some(PatternValuePlace::Constant(x.clone().into())),
|
||||||
edn::SpannedValue::Uuid(ref u) =>
|
::SpannedValue::Uuid(ref u) =>
|
||||||
Some(PatternValuePlace::Constant(NonIntegerConstant::Uuid(u.clone()))),
|
Some(PatternValuePlace::Constant(NonIntegerConstant::Uuid(u.clone()))),
|
||||||
|
|
||||||
// These don't appear in queries.
|
// These don't appear in queries.
|
||||||
edn::SpannedValue::Nil => None,
|
::SpannedValue::Nil => None,
|
||||||
edn::SpannedValue::NamespacedSymbol(_) => None,
|
::SpannedValue::NamespacedSymbol(_) => None,
|
||||||
edn::SpannedValue::Keyword(_) => None, // … yet.
|
::SpannedValue::Keyword(_) => None, // … yet.
|
||||||
edn::SpannedValue::Map(_) => None,
|
::SpannedValue::Map(_) => None,
|
||||||
edn::SpannedValue::List(_) => None,
|
::SpannedValue::List(_) => None,
|
||||||
edn::SpannedValue::Set(_) => None,
|
::SpannedValue::Set(_) => None,
|
||||||
edn::SpannedValue::Vector(_) => None,
|
::SpannedValue::Vector(_) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -647,8 +633,7 @@ pub enum Limit {
|
||||||
/// Examples:
|
/// Examples:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # extern crate mentat_query;
|
/// # use edn::query::{Element, FindSpec, Variable};
|
||||||
/// # use mentat_query::{Element, FindSpec, Variable};
|
|
||||||
///
|
///
|
||||||
/// # fn main() {
|
/// # fn main() {
|
||||||
///
|
///
|
||||||
|
@ -687,7 +672,7 @@ pub enum FindSpec {
|
||||||
/// Returns true if the provided `FindSpec` returns at most one result.
|
/// Returns true if the provided `FindSpec` returns at most one result.
|
||||||
impl FindSpec {
|
impl FindSpec {
|
||||||
pub fn is_unit_limited(&self) -> bool {
|
pub fn is_unit_limited(&self) -> bool {
|
||||||
use FindSpec::*;
|
use self::FindSpec::*;
|
||||||
match self {
|
match self {
|
||||||
&FindScalar(..) => true,
|
&FindScalar(..) => true,
|
||||||
&FindTuple(..) => true,
|
&FindTuple(..) => true,
|
||||||
|
@ -697,7 +682,7 @@ impl FindSpec {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expected_column_count(&self) -> usize {
|
pub fn expected_column_count(&self) -> usize {
|
||||||
use FindSpec::*;
|
use self::FindSpec::*;
|
||||||
match self {
|
match self {
|
||||||
&FindScalar(..) => 1,
|
&FindScalar(..) => 1,
|
||||||
&FindColl(..) => 1,
|
&FindColl(..) => 1,
|
||||||
|
@ -729,7 +714,7 @@ impl FindSpec {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn columns<'s>(&'s self) -> Box<Iterator<Item=&Element> + 's> {
|
pub fn columns<'s>(&'s self) -> Box<Iterator<Item=&Element> + 's> {
|
||||||
use FindSpec::*;
|
use self::FindSpec::*;
|
||||||
match self {
|
match self {
|
||||||
&FindScalar(ref e) => Box::new(std::iter::once(e)),
|
&FindScalar(ref e) => Box::new(std::iter::once(e)),
|
||||||
&FindColl(ref e) => Box::new(std::iter::once(e)),
|
&FindColl(ref e) => Box::new(std::iter::once(e)),
|
||||||
|
@ -792,16 +777,16 @@ impl Binding {
|
||||||
/// placeholder or unique.
|
/// placeholder or unique.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// extern crate mentat_query;
|
/// use edn::query::{Binding,Variable,VariableOrPlaceholder};
|
||||||
/// use std::rc::Rc;
|
/// use std::rc::Rc;
|
||||||
///
|
///
|
||||||
/// let v = mentat_query::Variable::from_valid_name("?foo");
|
/// let v = Variable::from_valid_name("?foo");
|
||||||
/// let vv = mentat_query::VariableOrPlaceholder::Variable(v);
|
/// let vv = VariableOrPlaceholder::Variable(v);
|
||||||
/// let p = mentat_query::VariableOrPlaceholder::Placeholder;
|
/// let p = VariableOrPlaceholder::Placeholder;
|
||||||
///
|
///
|
||||||
/// let e = mentat_query::Binding::BindTuple(vec![p.clone()]);
|
/// let e = Binding::BindTuple(vec![p.clone()]);
|
||||||
/// let b = mentat_query::Binding::BindTuple(vec![p.clone(), vv.clone()]);
|
/// let b = Binding::BindTuple(vec![p.clone(), vv.clone()]);
|
||||||
/// let d = mentat_query::Binding::BindTuple(vec![vv.clone(), p, vv]);
|
/// let d = Binding::BindTuple(vec![vv.clone(), p, vv]);
|
||||||
/// assert!(b.is_valid()); // One var, one placeholder: OK.
|
/// assert!(b.is_valid()); // One var, one placeholder: OK.
|
||||||
/// assert!(!e.is_valid()); // Empty: not OK.
|
/// assert!(!e.is_valid()); // Empty: not OK.
|
||||||
/// assert!(!d.is_valid()); // Duplicate var: not OK.
|
/// assert!(!d.is_valid()); // Duplicate var: not OK.
|
||||||
|
@ -1052,7 +1037,7 @@ pub trait ContainsVariables {
|
||||||
|
|
||||||
impl ContainsVariables for WhereClause {
|
impl ContainsVariables for WhereClause {
|
||||||
fn accumulate_mentioned_variables(&self, acc: &mut BTreeSet<Variable>) {
|
fn accumulate_mentioned_variables(&self, acc: &mut BTreeSet<Variable>) {
|
||||||
use WhereClause::*;
|
use self::WhereClause::*;
|
||||||
match self {
|
match self {
|
||||||
&OrJoin(ref o) => o.accumulate_mentioned_variables(acc),
|
&OrJoin(ref o) => o.accumulate_mentioned_variables(acc),
|
||||||
&Pred(ref p) => p.accumulate_mentioned_variables(acc),
|
&Pred(ref p) => p.accumulate_mentioned_variables(acc),
|
||||||
|
@ -1067,7 +1052,7 @@ impl ContainsVariables for WhereClause {
|
||||||
|
|
||||||
impl ContainsVariables for OrWhereClause {
|
impl ContainsVariables for OrWhereClause {
|
||||||
fn accumulate_mentioned_variables(&self, acc: &mut BTreeSet<Variable>) {
|
fn accumulate_mentioned_variables(&self, acc: &mut BTreeSet<Variable>) {
|
||||||
use OrWhereClause::*;
|
use self::OrWhereClause::*;
|
||||||
match self {
|
match self {
|
||||||
&And(ref clauses) => for clause in clauses { clause.accumulate_mentioned_variables(acc) },
|
&And(ref clauses) => for clause in clauses { clause.accumulate_mentioned_variables(acc) },
|
||||||
&Clause(ref clause) => clause.accumulate_mentioned_variables(acc),
|
&Clause(ref clause) => clause.accumulate_mentioned_variables(acc),
|
||||||
|
@ -1124,7 +1109,6 @@ impl ContainsVariables for Predicate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl ContainsVariables for TypeAnnotation {
|
impl ContainsVariables for TypeAnnotation {
|
||||||
fn accumulate_mentioned_variables(&self, acc: &mut BTreeSet<Variable>) {
|
fn accumulate_mentioned_variables(&self, acc: &mut BTreeSet<Variable>) {
|
||||||
acc_ref(acc, &self.variable);
|
acc_ref(acc, &self.variable);
|
||||||
|
|
|
@ -18,6 +18,7 @@ use mentat_core::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use mentat_query::{
|
use mentat_query::{
|
||||||
|
NonIntegerConstant,
|
||||||
Pattern,
|
Pattern,
|
||||||
PatternValuePlace,
|
PatternValuePlace,
|
||||||
PatternNonValuePlace,
|
PatternNonValuePlace,
|
||||||
|
@ -42,6 +43,17 @@ use types::{
|
||||||
|
|
||||||
use Known;
|
use Known;
|
||||||
|
|
||||||
|
pub fn into_typed_value(nic: NonIntegerConstant) -> TypedValue {
|
||||||
|
match nic {
|
||||||
|
NonIntegerConstant::BigInteger(_) => unimplemented!(), // TODO: #280.
|
||||||
|
NonIntegerConstant::Boolean(v) => TypedValue::Boolean(v),
|
||||||
|
NonIntegerConstant::Float(v) => TypedValue::Double(v),
|
||||||
|
NonIntegerConstant::Text(v) => v.into(),
|
||||||
|
NonIntegerConstant::Instant(v) => TypedValue::Instant(v),
|
||||||
|
NonIntegerConstant::Uuid(v) => TypedValue::Uuid(v),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Application of patterns.
|
/// Application of patterns.
|
||||||
impl ConjoiningClauses {
|
impl ConjoiningClauses {
|
||||||
|
|
||||||
|
@ -518,7 +530,7 @@ impl ConjoiningClauses {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
PatternValuePlace::Constant(nic) => {
|
PatternValuePlace::Constant(nic) => {
|
||||||
Place(EvolvedValuePlace::Value(nic.into_typed_value()))
|
Place(EvolvedValuePlace::Value(into_typed_value(nic)))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -655,7 +667,6 @@ mod testing {
|
||||||
|
|
||||||
use mentat_query::{
|
use mentat_query::{
|
||||||
Keyword,
|
Keyword,
|
||||||
NonIntegerConstant,
|
|
||||||
Variable,
|
Variable,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
12
query/src/lib.rs
Normal file
12
query/src/lib.rs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
// Copyright 2016 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.
|
||||||
|
|
||||||
|
extern crate edn;
|
||||||
|
pub use edn::query::*;
|
Loading…
Reference in a new issue