Add query sub-crate, implementing more of the beginnings of the query language.
This commit is contained in:
parent
476f04e27b
commit
daddfd3e0f
6 changed files with 161 additions and 0 deletions
|
@ -9,6 +9,9 @@ rusqlite = "0.8.0"
|
||||||
[dependencies.edn]
|
[dependencies.edn]
|
||||||
path = "edn"
|
path = "edn"
|
||||||
|
|
||||||
|
[dependencies.mentat_query]
|
||||||
|
path = "query"
|
||||||
|
|
||||||
[dependencies.mentat_query_parser]
|
[dependencies.mentat_query_parser]
|
||||||
path = "query-parser"
|
path = "query-parser"
|
||||||
|
|
||||||
|
|
7
query/Cargo.toml
Normal file
7
query/Cargo.toml
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
[package]
|
||||||
|
name = "mentat_query"
|
||||||
|
version = "0.0.1"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
[dependencies.edn]
|
||||||
|
path = "../edn"
|
4
query/README.md
Normal file
4
query/README.md
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
This sub-crate implements the core types used by the query parser,
|
||||||
|
translator, and executor — variables, find specifications, etc.
|
||||||
|
|
||||||
|
The `edn` sub-crate implements some even lower-level types, such as `Keyword`.
|
135
query/src/find.rs
Normal file
135
query/src/find.rs
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
///! This module defines some core types that support find expressions: sources,
|
||||||
|
///! variables, expressions, etc.
|
||||||
|
///! These are produced as 'fuel' by the query parser, consumed by the query
|
||||||
|
///! translator and executor.
|
||||||
|
///!
|
||||||
|
///! Many of these types are defined as simple structs that are little more than
|
||||||
|
///! a richer type alias: a variable, for example, is really just a fancy kind
|
||||||
|
///! of string.
|
||||||
|
///!
|
||||||
|
///! At some point in the future, we might consider reducing copying and memory
|
||||||
|
///! usage by recasting all of these string-holding structs and enums in terms
|
||||||
|
///! of string references, with those references being slices of some parsed
|
||||||
|
///! input query string, and valid for the lifetime of that string.
|
||||||
|
///!
|
||||||
|
///! For now, for the sake of simplicity, all of these strings are heap-allocated.
|
||||||
|
///!
|
||||||
|
///! Furthermore, we might cut out some of the chaff here: each time a 'tagged'
|
||||||
|
///! type is used within an enum, we have an opportunity to simplify and use the
|
||||||
|
///! inner type directly in conjunction with matching on the enum. Before diving
|
||||||
|
///! deeply into this it's worth recognizing that this loss of 'sovereignty' is
|
||||||
|
///! a tradeoff against well-typed function signatures and other such boundaries.
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: support other kinds of sources.
|
||||||
|
#[derive(Clone,Debug,Eq,PartialEq)]
|
||||||
|
pub enum SrcVar {
|
||||||
|
DefaultSrc,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Constant {} // This is essentially Box. TODO: flesh out.
|
||||||
|
|
||||||
|
#[derive(Clone,Debug,Eq,PartialEq)]
|
||||||
|
pub struct Variable {
|
||||||
|
pub name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum FnArg {
|
||||||
|
Constant { constant: Constant },
|
||||||
|
Variable { variable: Variable },
|
||||||
|
Src { src: SrcVar },
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum PullPattern {
|
||||||
|
Constant { constant: Constant },
|
||||||
|
Variable { variable: Variable },
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Pull {
|
||||||
|
pub src: SrcVar,
|
||||||
|
pub var: Variable,
|
||||||
|
pub pattern: PullPattern, // Constant, variable, or plain variable.
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Aggregate {
|
||||||
|
pub fn_name: String,
|
||||||
|
pub args: Vec<FnArg>,
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: look up the idiomatic way to express these kinds of type
|
||||||
|
// combinations in Rust. It must be common in ASTs. Trait objects
|
||||||
|
// presumably aren't the answer…
|
||||||
|
pub enum Element {
|
||||||
|
Variable { variable: Variable },
|
||||||
|
Pull { expression: Pull },
|
||||||
|
Aggregate { expression: Aggregate },
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A definition of the first part of a find query: the
|
||||||
|
/// `[:find ?foo ?bar…]` bit.
|
||||||
|
///
|
||||||
|
/// There are four different kinds of find specs, allowing you to query for
|
||||||
|
/// a single value, a collection of values from different entities, a single
|
||||||
|
/// tuple (relation), or a collection of tuples.
|
||||||
|
///
|
||||||
|
/// Examples:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use mentat_query::find::{FindSpec, Element, Variable};
|
||||||
|
///
|
||||||
|
/// // TODO: this feels clunky.
|
||||||
|
/// let foo = Variable { name: "foo".to_string() };
|
||||||
|
/// let bar = Variable { name: "bar".to_string() };
|
||||||
|
/// let elements = vec![
|
||||||
|
/// Element::Variable { variable: foo },
|
||||||
|
/// Element::Variable { variable: bar },
|
||||||
|
/// ];
|
||||||
|
/// let rel = FindSpec::FindRel { elements: elements };
|
||||||
|
///
|
||||||
|
/// if let FindSpec::FindRel { elements } = rel {
|
||||||
|
/// assert_eq!(2, elements.len());
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
pub enum FindSpec {
|
||||||
|
/// Returns an array of arrays.
|
||||||
|
FindRel { elements: Vec<Element> },
|
||||||
|
|
||||||
|
/// Returns an array of scalars, usually homogeneous.
|
||||||
|
/// This is equivalent to mapping over the results of a `FindRel`,
|
||||||
|
/// returning the first value of each.
|
||||||
|
FindColl { element: Element },
|
||||||
|
|
||||||
|
/// Returns a single tuple: a heterogeneous array of scalars. Equivalent to
|
||||||
|
/// taking the first result from a `FindRel`.
|
||||||
|
FindTuple { elements: Vec<Element> },
|
||||||
|
|
||||||
|
/// Returns a single scalar value. Equivalent to taking the first result
|
||||||
|
/// from a `FindColl`.
|
||||||
|
FindScalar { element: Element },
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true if the provided `FindSpec` returns at most one result.
|
||||||
|
pub fn is_unit_limited(spec: &FindSpec) -> bool {
|
||||||
|
match spec {
|
||||||
|
&FindSpec::FindScalar { .. } => true,
|
||||||
|
&FindSpec::FindTuple { .. } => true,
|
||||||
|
&FindSpec::FindRel { .. } => false,
|
||||||
|
&FindSpec::FindColl { .. } => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true if the provided `FindSpec` cares about distinct results.
|
||||||
|
pub fn requires_distinct(spec: &FindSpec) -> bool {
|
||||||
|
return !is_unit_limited(spec);
|
||||||
|
}
|
11
query/src/lib.rs
Normal file
11
query/src/lib.rs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
pub mod find;
|
|
@ -9,6 +9,7 @@
|
||||||
// specific language governing permissions and limitations under the License.
|
// specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
extern crate edn;
|
extern crate edn;
|
||||||
|
extern crate mentat_query;
|
||||||
extern crate mentat_query_parser;
|
extern crate mentat_query_parser;
|
||||||
extern crate rusqlite;
|
extern crate rusqlite;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue