Skip to main content

edn/
query.rs

1// Copyright 2016 Mozilla
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4// this file except in compliance with the License. You may obtain a copy of the
5// License at http://www.apache.org/licenses/LICENSE-2.0
6// Unless required by applicable law or agreed to in writing, software distributed
7// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8// CONDITIONS OF ANY KIND, either express or implied. See the License for the
9// specific language governing permissions and limitations under the License.
10
11//! This module defines some core types that support find expressions: sources,
12//! variables, expressions, etc.
13//! These are produced as 'fuel' by the query parser, consumed by the query
14//! translator and executor.
15//!
16//! Many of these types are defined as simple structs that are little more than
17//! a richer type alias: a variable, for example, is really just a fancy kind
18//! of string.
19//!
20//! At some point in the future, we might consider reducing copying and memory
21//! usage by recasting all of these string-holding structs and enums in terms
22//! of string references, with those references being slices of some parsed
23//! input query string, and valid for the lifetime of that string.
24//!
25//! For now, for the sake of simplicity, all of these strings are heap-allocated.
26//!
27//! Furthermore, we might cut out some of the chaff here: each time a 'tagged'
28//! type is used within an enum, we have an opportunity to simplify and use the
29//! inner type directly in conjunction with matching on the enum. Before diving
30//! deeply into this it's worth recognizing that this loss of 'sovereignty' is
31//! a tradeoff against well-typed function signatures and other such boundaries.
32use std::collections::{BTreeSet, HashSet};
33
34use std;
35use std::fmt;
36use std::rc::Rc;
37use std::sync::Arc;
38
39use crate::{BigInt, DateTime, OrderedFloat, Utc, Uuid};
40
41use crate::value_rc::{FromRc, ValueRc};
42
43pub use crate::{Keyword, PlainSymbol};
44
45pub type SrcVarName = String; // Do not include the required syntactic '$'.
46
47#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
48pub struct Variable(pub Arc<PlainSymbol>);
49
50impl Variable {
51    pub fn as_str(&self) -> &str {
52        self.0.as_ref().0.as_str()
53    }
54
55    pub fn name(&self) -> PlainSymbol {
56        self.0.as_ref().clone()
57    }
58
59    /// Return a new `Variable`, assuming that the provided string is a valid name.
60    pub fn from_valid_name(name: &str) -> Variable {
61        let s = PlainSymbol::plain(name);
62        assert!(s.is_var_symbol());
63        Variable(Arc::new(s))
64    }
65}
66
67pub trait ToVariable {
68    fn to_var(&self) -> Variable;
69}
70
71impl ToVariable for str {
72    fn to_var(&self) -> Variable {
73        Variable::from_valid_name(self)
74    }
75}
76
77pub trait FromValue<T> {
78    fn from_value(v: &crate::ValueAndSpan) -> Option<T>;
79}
80
81/// If the provided EDN value is a PlainSymbol beginning with '?', return
82/// it wrapped in a Variable. If not, return None.
83/// TODO: intern strings. #398.
84impl FromValue<Variable> for Variable {
85    fn from_value(v: &crate::ValueAndSpan) -> Option<Variable> {
86        if let crate::SpannedValue::PlainSymbol(ref s) = v.inner {
87            Variable::from_symbol(s)
88        } else {
89            None
90        }
91    }
92}
93
94impl Variable {
95    pub fn from_arc(sym: Arc<PlainSymbol>) -> Option<Variable> {
96        if sym.is_var_symbol() {
97            Some(Variable(sym.clone()))
98        } else {
99            None
100        }
101    }
102
103    /// TODO: intern strings. #398.
104    pub fn from_symbol(sym: &PlainSymbol) -> Option<Variable> {
105        if sym.is_var_symbol() {
106            Some(Variable(Arc::new(sym.clone())))
107        } else {
108            None
109        }
110    }
111}
112
113impl fmt::Debug for Variable {
114    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
115        write!(f, "var({})", self.0)
116    }
117}
118
119impl std::fmt::Display for Variable {
120    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
121        write!(f, "{}", self.0)
122    }
123}
124
125#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
126pub struct QueryFunction(pub PlainSymbol);
127
128impl FromValue<QueryFunction> for QueryFunction {
129    fn from_value(v: &crate::ValueAndSpan) -> Option<QueryFunction> {
130        if let crate::SpannedValue::PlainSymbol(ref s) = v.inner {
131            QueryFunction::from_symbol(s)
132        } else {
133            None
134        }
135    }
136}
137
138impl QueryFunction {
139    pub fn from_symbol(sym: &PlainSymbol) -> Option<QueryFunction> {
140        // TODO: validate the acceptable set of function names.
141        Some(QueryFunction(sym.clone()))
142    }
143}
144
145impl std::fmt::Display for QueryFunction {
146    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
147        write!(f, "{}", self.0)
148    }
149}
150
151#[derive(Clone, Debug, Eq, PartialEq)]
152pub enum Direction {
153    Ascending,
154    Descending,
155}
156
157/// An abstract declaration of ordering: direction and variable.
158#[derive(Clone, Debug, Eq, PartialEq)]
159pub struct Order(pub Direction, pub Variable); // Future: Element instead of Variable?
160
161#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
162pub enum SrcVar {
163    DefaultSrc,
164    NamedSrc(SrcVarName),
165}
166
167impl FromValue<SrcVar> for SrcVar {
168    fn from_value(v: &crate::ValueAndSpan) -> Option<SrcVar> {
169        if let crate::SpannedValue::PlainSymbol(ref s) = v.inner {
170            SrcVar::from_symbol(s)
171        } else {
172            None
173        }
174    }
175}
176
177impl SrcVar {
178    pub fn from_symbol(sym: &PlainSymbol) -> Option<SrcVar> {
179        if sym.is_src_symbol() {
180            if sym.0 == "$" {
181                Some(SrcVar::DefaultSrc)
182            } else {
183                Some(SrcVar::NamedSrc(sym.name().to_string()))
184            }
185        } else {
186            None
187        }
188    }
189}
190
191/// These are the scalar values representable in EDN.
192#[derive(Clone, Debug, Eq, PartialEq)]
193pub enum NonIntegerConstant {
194    Boolean(bool),
195    BigInteger(BigInt),
196    Float(OrderedFloat<f64>),
197    Text(ValueRc<String>),
198    Instant(DateTime<Utc>),
199    Uuid(Uuid),
200}
201
202impl<'a> From<&'a str> for NonIntegerConstant {
203    fn from(val: &'a str) -> NonIntegerConstant {
204        NonIntegerConstant::Text(ValueRc::new(val.to_string()))
205    }
206}
207
208impl From<String> for NonIntegerConstant {
209    fn from(val: String) -> NonIntegerConstant {
210        NonIntegerConstant::Text(ValueRc::new(val))
211    }
212}
213
214#[derive(Clone, Debug, Eq, PartialEq)]
215pub enum FnArg {
216    Variable(Variable),
217    SrcVar(SrcVar),
218    EntidOrInteger(i64),
219    IdentOrKeyword(Keyword),
220    Constant(NonIntegerConstant),
221    /// A nested s-expression function call, e.g. `(= ?x 10)` or `(+ (* ?x 2) 1)`.
222    SExpr(PlainSymbol, Vec<FnArg>),
223}
224
225impl FromValue<FnArg> for FnArg {
226    fn from_value(v: &crate::ValueAndSpan) -> Option<FnArg> {
227        use crate::SpannedValue::*;
228        match v.inner {
229            Integer(x) => Some(FnArg::EntidOrInteger(x)),
230            PlainSymbol(ref x) if x.is_src_symbol() => SrcVar::from_symbol(x).map(FnArg::SrcVar),
231            PlainSymbol(ref x) if x.is_var_symbol() => {
232                Variable::from_symbol(x).map(FnArg::Variable)
233            }
234            PlainSymbol(_) => None,
235            Keyword(ref x) => Some(FnArg::IdentOrKeyword(x.clone())),
236            Instant(x) => Some(FnArg::Constant(NonIntegerConstant::Instant(x))),
237            Uuid(x) => Some(FnArg::Constant(NonIntegerConstant::Uuid(x))),
238            Boolean(x) => Some(FnArg::Constant(NonIntegerConstant::Boolean(x))),
239            Float(x) => Some(FnArg::Constant(NonIntegerConstant::Float(x))),
240            BigInteger(ref x) => Some(FnArg::Constant(NonIntegerConstant::BigInteger(x.clone()))),
241            Text(ref x) =>
242            // TODO: intern strings. #398.
243            {
244                Some(FnArg::Constant(x.clone().into()))
245            }
246            Nil | NamespacedSymbol(_) | Vector(_) | List(_) | Set(_) | Map(_) => None,
247        }
248    }
249}
250
251// For display in column headings in the repl.
252impl std::fmt::Display for FnArg {
253    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
254        match self {
255            FnArg::Variable(var) => write!(f, "{}", var),
256            FnArg::SrcVar(var) => {
257                if var == &SrcVar::DefaultSrc {
258                    write!(f, "$")
259                } else {
260                    write!(
261                        f,
262                        "${}",
263                        match var {
264                            SrcVar::NamedSrc(ref n) => n,
265                            _ => "",
266                        }
267                    )
268                }
269            }
270            &FnArg::EntidOrInteger(entid) => write!(f, "{}", entid),
271            FnArg::IdentOrKeyword(kw) => write!(f, "{}", kw),
272            FnArg::Constant(constant) => write!(f, "{}", constant),
273            FnArg::SExpr(ref func, ref args) => {
274                write!(f, "({}", func)?;
275                for arg in args {
276                    write!(f, " {}", arg)?;
277                }
278                write!(f, ")")
279            }
280        }
281    }
282}
283
284impl FnArg {
285    pub fn as_variable(&self) -> Option<&Variable> {
286        match self {
287            FnArg::Variable(v) => Some(v),
288            _ => None,
289        }
290    }
291}
292
293/// e, a, tx can't be values -- no strings, no floats -- and so
294/// they can only be variables, entity IDs, ident keywords, or
295/// placeholders.
296/// This encoding allows us to represent integers that aren't
297/// entity IDs. That'll get filtered out in the context of the
298/// database.
299#[derive(Clone, Debug, Eq, PartialEq)]
300pub enum PatternNonValuePlace {
301    Placeholder,
302    Variable(Variable),
303    Entid(i64), // Will always be +ve. See #190.
304    Ident(ValueRc<Keyword>),
305}
306
307impl From<Rc<Keyword>> for PatternNonValuePlace {
308    fn from(value: Rc<Keyword>) -> Self {
309        PatternNonValuePlace::Ident(ValueRc::from_rc(value))
310    }
311}
312
313impl From<Keyword> for PatternNonValuePlace {
314    fn from(value: Keyword) -> Self {
315        PatternNonValuePlace::Ident(ValueRc::new(value))
316    }
317}
318
319impl PatternNonValuePlace {
320    // I think we'll want move variants, so let's leave these here for now.
321    #[allow(dead_code)]
322    fn into_pattern_value_place(self) -> PatternValuePlace {
323        match self {
324            PatternNonValuePlace::Placeholder => PatternValuePlace::Placeholder,
325            PatternNonValuePlace::Variable(x) => PatternValuePlace::Variable(x),
326            PatternNonValuePlace::Entid(x) => PatternValuePlace::EntidOrInteger(x),
327            PatternNonValuePlace::Ident(x) => PatternValuePlace::IdentOrKeyword(x),
328        }
329    }
330
331    fn to_pattern_value_place(&self) -> PatternValuePlace {
332        match *self {
333            PatternNonValuePlace::Placeholder => PatternValuePlace::Placeholder,
334            PatternNonValuePlace::Variable(ref x) => PatternValuePlace::Variable(x.clone()),
335            PatternNonValuePlace::Entid(x) => PatternValuePlace::EntidOrInteger(x),
336            PatternNonValuePlace::Ident(ref x) => PatternValuePlace::IdentOrKeyword(x.clone()),
337        }
338    }
339}
340
341impl FromValue<PatternNonValuePlace> for PatternNonValuePlace {
342    fn from_value(v: &crate::ValueAndSpan) -> Option<PatternNonValuePlace> {
343        match v.inner {
344            crate::SpannedValue::Integer(x) => {
345                if x >= 0 {
346                    Some(PatternNonValuePlace::Entid(x))
347                } else {
348                    None
349                }
350            }
351            crate::SpannedValue::PlainSymbol(ref x) => {
352                if x.0.as_str() == "_" {
353                    Some(PatternNonValuePlace::Placeholder)
354                } else {
355                    Variable::from_symbol(x).map(PatternNonValuePlace::Variable)
356                }
357            }
358            crate::SpannedValue::Keyword(ref x) => Some(x.clone().into()),
359            _ => None,
360        }
361    }
362}
363
364#[derive(Clone, Debug, Eq, PartialEq)]
365pub enum IdentOrEntid {
366    Ident(Keyword),
367    Entid(i64),
368}
369
370/// The `v` part of a pattern can be much broader: it can represent
371/// integers that aren't entity IDs (particularly negative integers),
372/// strings, and all the rest. We group those under `Constant`.
373#[derive(Clone, Debug, Eq, PartialEq)]
374pub enum PatternValuePlace {
375    Placeholder,
376    Variable(Variable),
377    EntidOrInteger(i64),
378    IdentOrKeyword(ValueRc<Keyword>),
379    Constant(NonIntegerConstant),
380}
381
382impl From<Rc<Keyword>> for PatternValuePlace {
383    fn from(value: Rc<Keyword>) -> Self {
384        PatternValuePlace::IdentOrKeyword(ValueRc::from_rc(value))
385    }
386}
387
388impl From<Keyword> for PatternValuePlace {
389    fn from(value: Keyword) -> Self {
390        PatternValuePlace::IdentOrKeyword(ValueRc::new(value))
391    }
392}
393
394impl FromValue<PatternValuePlace> for PatternValuePlace {
395    fn from_value(v: &crate::ValueAndSpan) -> Option<PatternValuePlace> {
396        match v.inner {
397            crate::SpannedValue::Integer(x) => Some(PatternValuePlace::EntidOrInteger(x)),
398            crate::SpannedValue::PlainSymbol(ref x) if x.0.as_str() == "_" => {
399                Some(PatternValuePlace::Placeholder)
400            }
401            crate::SpannedValue::PlainSymbol(ref x) => {
402                Variable::from_symbol(x).map(PatternValuePlace::Variable)
403            }
404            crate::SpannedValue::Keyword(ref x) if x.is_namespaced() => Some(x.clone().into()),
405            crate::SpannedValue::Boolean(x) => {
406                Some(PatternValuePlace::Constant(NonIntegerConstant::Boolean(x)))
407            }
408            crate::SpannedValue::Float(x) => {
409                Some(PatternValuePlace::Constant(NonIntegerConstant::Float(x)))
410            }
411            crate::SpannedValue::BigInteger(ref x) => Some(PatternValuePlace::Constant(
412                NonIntegerConstant::BigInteger(x.clone()),
413            )),
414            crate::SpannedValue::Instant(x) => {
415                Some(PatternValuePlace::Constant(NonIntegerConstant::Instant(x)))
416            }
417            crate::SpannedValue::Text(ref x) =>
418            // TODO: intern strings. #398.
419            {
420                Some(PatternValuePlace::Constant(x.clone().into()))
421            }
422            crate::SpannedValue::Uuid(ref u) => {
423                Some(PatternValuePlace::Constant(NonIntegerConstant::Uuid(*u)))
424            }
425
426            // TODO(#105): review which of these types should be supported
427            // in the value position of query patterns.
428            crate::SpannedValue::Nil => None,
429            crate::SpannedValue::NamespacedSymbol(_) => None,
430            crate::SpannedValue::Keyword(ref x) => Some(x.clone().into()),
431            crate::SpannedValue::Map(_) => None,
432            crate::SpannedValue::List(_) => None,
433            crate::SpannedValue::Set(_) => None,
434            crate::SpannedValue::Vector(_) => None,
435        }
436    }
437}
438
439impl PatternValuePlace {
440    // I think we'll want move variants, so let's leave these here for now.
441    #[allow(dead_code)]
442    fn into_pattern_non_value_place(self) -> Option<PatternNonValuePlace> {
443        match self {
444            PatternValuePlace::Placeholder => Some(PatternNonValuePlace::Placeholder),
445            PatternValuePlace::Variable(x) => Some(PatternNonValuePlace::Variable(x)),
446            PatternValuePlace::EntidOrInteger(x) => {
447                if x >= 0 {
448                    Some(PatternNonValuePlace::Entid(x))
449                } else {
450                    None
451                }
452            }
453            PatternValuePlace::IdentOrKeyword(x) => Some(PatternNonValuePlace::Ident(x)),
454            PatternValuePlace::Constant(_) => None,
455        }
456    }
457
458    fn to_pattern_non_value_place(&self) -> Option<PatternNonValuePlace> {
459        match *self {
460            PatternValuePlace::Placeholder => Some(PatternNonValuePlace::Placeholder),
461            PatternValuePlace::Variable(ref x) => Some(PatternNonValuePlace::Variable(x.clone())),
462            PatternValuePlace::EntidOrInteger(x) => {
463                if x >= 0 {
464                    Some(PatternNonValuePlace::Entid(x))
465                } else {
466                    None
467                }
468            }
469            PatternValuePlace::IdentOrKeyword(ref x) => {
470                Some(PatternNonValuePlace::Ident(x.clone()))
471            }
472            PatternValuePlace::Constant(_) => None,
473        }
474    }
475}
476
477// Not yet used.
478// pub enum PullDefaultValue {
479//     EntidOrInteger(i64),
480//     IdentOrKeyword(Rc<Keyword>),
481//     Constant(NonIntegerConstant),
482// }
483
484#[derive(Clone, Debug, Eq, PartialEq)]
485pub enum PullConcreteAttribute {
486    Ident(Arc<Keyword>),
487    Entid(i64),
488}
489
490#[derive(Clone, Debug, Eq, PartialEq)]
491pub struct NamedPullAttribute {
492    pub attribute: PullConcreteAttribute,
493    pub alias: Option<Arc<Keyword>>,
494}
495
496impl From<PullConcreteAttribute> for NamedPullAttribute {
497    fn from(a: PullConcreteAttribute) -> Self {
498        NamedPullAttribute {
499            attribute: a,
500            alias: None,
501        }
502    }
503}
504
505#[derive(Clone, Debug, Eq, PartialEq)]
506pub enum PullAttributeSpec {
507    Wildcard,
508    Attribute(NamedPullAttribute),
509    // PullMapSpec(Vec<…>),
510    // LimitedAttribute(NamedPullAttribute, u64),  // Limit nil => Attribute instead.
511    // DefaultedAttribute(NamedPullAttribute, PullDefaultValue),
512}
513
514impl std::fmt::Display for PullConcreteAttribute {
515    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
516        match self {
517            PullConcreteAttribute::Ident(k) => {
518                write!(f, "{}", k)
519            }
520            &PullConcreteAttribute::Entid(i) => {
521                write!(f, "{}", i)
522            }
523        }
524    }
525}
526
527impl std::fmt::Display for NamedPullAttribute {
528    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
529        if let Some(alias) = &self.alias {
530            write!(f, "{} :as {}", self.attribute, alias)
531        } else {
532            write!(f, "{}", self.attribute)
533        }
534    }
535}
536
537impl std::fmt::Display for PullAttributeSpec {
538    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
539        match self {
540            &PullAttributeSpec::Wildcard => {
541                write!(f, "*")
542            }
543            PullAttributeSpec::Attribute(attr) => {
544                write!(f, "{}", attr)
545            }
546        }
547    }
548}
549
550#[derive(Clone, Debug, Eq, PartialEq)]
551pub struct Pull {
552    pub var: Variable,
553    pub patterns: Vec<PullAttributeSpec>,
554}
555
556#[derive(Clone, Debug, Eq, PartialEq)]
557pub struct Aggregate {
558    pub func: QueryFunction,
559    pub args: Vec<FnArg>,
560}
561
562#[derive(Clone, Debug, Eq, PartialEq)]
563pub enum Element {
564    Variable(Variable),
565    Aggregate(Aggregate),
566
567    /// In a query with a `max` or `min` aggregate, a corresponding variable
568    /// (indicated in the query with `(the ?var)`, is guaranteed to come from
569    /// the row that provided the max or min value. Queries with more than one
570    /// `max` or `min` cannot yield predictable behavior, and will err during
571    /// algebrizing.
572    Corresponding(Variable),
573    Pull(Pull),
574}
575
576impl Element {
577    /// Returns true if the element must yield only one value.
578    pub fn is_unit(&self) -> bool {
579        match *self {
580            Element::Variable(_) => false,
581            Element::Pull(_) => false,
582            Element::Aggregate(_) => true,
583            Element::Corresponding(_) => true,
584        }
585    }
586}
587
588impl From<Variable> for Element {
589    fn from(x: Variable) -> Element {
590        Element::Variable(x)
591    }
592}
593
594impl std::fmt::Display for Element {
595    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
596        match self {
597            Element::Variable(var) => {
598                write!(f, "{}", var)
599            }
600            &Element::Pull(Pull {
601                ref var,
602                ref patterns,
603            }) => {
604                write!(f, "(pull {} [ ", var)?;
605                for p in patterns.iter() {
606                    write!(f, "{} ", p)?;
607                }
608                write!(f, "])")
609            }
610            Element::Aggregate(agg) => match agg.args.len() {
611                0 => write!(f, "({})", agg.func),
612                1 => write!(f, "({} {})", agg.func, agg.args[0]),
613                _ => write!(f, "({} {:?})", agg.func, agg.args),
614            },
615            Element::Corresponding(var) => {
616                write!(f, "(the {})", var)
617            }
618        }
619    }
620}
621
622#[derive(Clone, Debug, Eq, PartialEq)]
623pub enum Limit {
624    None,
625    Fixed(u64),
626    Variable(Variable),
627}
628
629/// A definition of the first part of a find query: the
630/// `[:find ?foo ?bar…]` bit.
631///
632/// There are four different kinds of find specs, allowing you to query for
633/// a single value, a collection of values from different entities, a single
634/// tuple (relation), or a collection of tuples.
635///
636/// Examples:
637///
638/// ```ignore
639/// # use edn::query::{Element, FindSpec, Variable};
640///
641/// # fn main() {
642///
643///   let elements = vec![
644///     Element::Variable("?foo".to_var()),
645///     Element::Variable("?bar".to_var()),
646///   ];
647///   let rel = FindSpec::FindRel(elements);
648///
649///   if let FindSpec::FindRel(elements) = rel {
650///     assert_eq!(2, elements.len());
651///   }
652///
653/// # }
654/// ```
655///
656#[derive(Clone, Debug, Eq, PartialEq)]
657pub enum FindSpec {
658    /// Returns an array of arrays, represented as a single array with length a multiple of width.
659    FindRel(Vec<Element>),
660
661    /// Returns an array of scalars, usually homogeneous.
662    /// This is equivalent to mapping over the results of a `FindRel`,
663    /// returning the first value of each.
664    FindColl(Element),
665
666    /// Returns a single tuple: a heterogeneous array of scalars. Equivalent to
667    /// taking the first result from a `FindRel`.
668    FindTuple(Vec<Element>),
669
670    /// Returns a single scalar value. Equivalent to taking the first result
671    /// from a `FindColl`.
672    FindScalar(Element),
673}
674
675/// Returns true if the provided `FindSpec` returns at most one result.
676impl FindSpec {
677    pub fn is_unit_limited(&self) -> bool {
678        use self::FindSpec::*;
679        match *self {
680            FindScalar(..) => true,
681            FindTuple(..) => true,
682            FindRel(..) => false,
683            FindColl(..) => false,
684        }
685    }
686
687    pub fn expected_column_count(&self) -> usize {
688        use self::FindSpec::*;
689        match self {
690            &FindScalar(..) => 1,
691            &FindColl(..) => 1,
692            &FindTuple(ref elems) | &FindRel(ref elems) => elems.len(),
693        }
694    }
695
696    /// Returns true if the provided `FindSpec` cares about distinct results.
697    ///
698    /// I use the words "cares about" because find is generally defined in terms of producing distinct
699    /// results at the Datalog level.
700    ///
701    /// Two of the find specs (scalar and tuple) produce only a single result. Those don't need to be
702    /// run with `SELECT DISTINCT`, because we're only consuming a single result. Those queries will be
703    /// run with `LIMIT 1`.
704    ///
705    /// Additionally, some projections cannot produce duplicate results: `[:find (max ?x) …]`, for
706    /// example.
707    ///
708    /// This function gives us the hook to add that logic when we're ready.
709    ///
710    /// Beyond this, `DISTINCT` is not always needed. For example, in some kinds of accumulation or
711    /// sampling projections we might not need to do it at the SQL level because we're consuming into
712    /// a dupe-eliminating data structure like a Set, or we know that a particular query cannot produce
713    /// duplicate results.
714    pub fn requires_distinct(&self) -> bool {
715        !self.is_unit_limited()
716    }
717
718    pub fn columns<'s>(&'s self) -> Box<dyn Iterator<Item = &'s Element> + 's> {
719        use self::FindSpec::*;
720        match self {
721            FindScalar(e) => Box::new(std::iter::once(e)),
722            FindColl(e) => Box::new(std::iter::once(e)),
723            FindTuple(v) => Box::new(v.iter()),
724            FindRel(v) => Box::new(v.iter()),
725        }
726    }
727}
728
729// Datomic accepts variable or placeholder.  DataScript accepts recursive bindings.  Mentat sticks
730// to the non-recursive form Datomic accepts, which is much simpler to process.
731#[derive(Clone, Debug, Eq, Hash, PartialEq)]
732pub enum VariableOrPlaceholder {
733    Placeholder,
734    Variable(Variable),
735}
736
737impl VariableOrPlaceholder {
738    pub fn into_var(self) -> Option<Variable> {
739        match self {
740            VariableOrPlaceholder::Placeholder => None,
741            VariableOrPlaceholder::Variable(var) => Some(var),
742        }
743    }
744
745    pub fn var(&self) -> Option<&Variable> {
746        match self {
747            &VariableOrPlaceholder::Placeholder => None,
748            VariableOrPlaceholder::Variable(var) => Some(var),
749        }
750    }
751}
752
753#[derive(Clone, Debug, Eq, PartialEq)]
754pub enum Binding {
755    BindScalar(Variable),
756    BindColl(Variable),
757    BindRel(Vec<VariableOrPlaceholder>),
758    BindTuple(Vec<VariableOrPlaceholder>),
759}
760
761impl Binding {
762    /// Return each variable or `None`, in order.
763    pub fn variables(&self) -> Vec<Option<Variable>> {
764        match self {
765            &Binding::BindScalar(ref var) | &Binding::BindColl(ref var) => vec![Some(var.clone())],
766            &Binding::BindRel(ref vars) | &Binding::BindTuple(ref vars) => {
767                vars.iter().map(|x| x.var().cloned()).collect()
768            }
769        }
770    }
771
772    /// Return `true` if no variables are bound, i.e., all binding entries are placeholders.
773    pub fn is_empty(&self) -> bool {
774        match self {
775            &Binding::BindScalar(_) | &Binding::BindColl(_) => false,
776            &Binding::BindRel(ref vars) | &Binding::BindTuple(ref vars) => {
777                vars.iter().all(|x| x.var().is_none())
778            }
779        }
780    }
781
782    /// Return `true` if no variable is bound twice, i.e., each binding entry is either a
783    /// placeholder or unique.
784    ///
785    /// ```ignore
786    /// use edn::query::{Binding,Variable,VariableOrPlaceholder};
787    /// use std::rc::Rc;
788    ///
789    /// let v = "?foo".to_var();
790    /// let vv = VariableOrPlaceholder::Variable(v);
791    /// let p = VariableOrPlaceholder::Placeholder;
792    ///
793    /// let e = Binding::BindTuple(vec![p.clone()]);
794    /// let b = Binding::BindTuple(vec![p.clone(), vv.clone()]);
795    /// let d = Binding::BindTuple(vec![vv.clone(), p, vv]);
796    /// assert!(b.is_valid());          // One var, one placeholder: OK.
797    /// assert!(!e.is_valid());         // Empty: not OK.
798    /// assert!(!d.is_valid());         // Duplicate var: not OK.
799    /// ```
800    pub fn is_valid(&self) -> bool {
801        match self {
802            &Binding::BindScalar(_) | &Binding::BindColl(_) => true,
803            &Binding::BindRel(ref vars) | &Binding::BindTuple(ref vars) => {
804                let mut acc = HashSet::<Variable>::new();
805                for var in vars {
806                    if let VariableOrPlaceholder::Variable(var) = var {
807                        if !acc.insert(var.clone()) {
808                            // It's invalid if there was an equal var already present in the set --
809                            // i.e., we have a duplicate var.
810                            return false;
811                        }
812                    }
813                }
814                // We're not valid if every place is a placeholder!
815                !acc.is_empty()
816            }
817        }
818    }
819}
820
821// Note that the "implicit blank" rule applies.
822// A pattern with a reversed attribute — :foo/_bar — is reversed
823// at the point of parsing. These `Pattern` instances only represent
824// one direction.
825#[derive(Clone, Debug, Eq, PartialEq)]
826pub struct Pattern {
827    pub source: Option<SrcVar>,
828    pub entity: PatternNonValuePlace,
829    pub attribute: PatternNonValuePlace,
830    pub value: PatternValuePlace,
831    pub tx: PatternNonValuePlace,
832}
833
834impl Pattern {
835    pub fn simple(
836        e: PatternNonValuePlace,
837        a: PatternNonValuePlace,
838        v: PatternValuePlace,
839    ) -> Option<Pattern> {
840        Pattern::new(None, e, a, v, PatternNonValuePlace::Placeholder)
841    }
842
843    pub fn new(
844        src: Option<SrcVar>,
845        e: PatternNonValuePlace,
846        a: PatternNonValuePlace,
847        v: PatternValuePlace,
848        tx: PatternNonValuePlace,
849    ) -> Option<Pattern> {
850        let aa = a.clone(); // Too tired of fighting borrow scope for now.
851        if let PatternNonValuePlace::Ident(ref k) = aa {
852            if k.is_backward() {
853                // e and v have different types; we must convert them.
854                // Not every parseable value is suitable for the entity field!
855                // As such, this is a failable constructor.
856                let e_v = e.to_pattern_value_place();
857                if let Some(v_e) = v.to_pattern_non_value_place() {
858                    return Some(Pattern {
859                        source: src,
860                        entity: v_e,
861                        attribute: k.to_reversed().into(),
862                        value: e_v,
863                        tx,
864                    });
865                } else {
866                    return None;
867                }
868            }
869        }
870        Some(Pattern {
871            source: src,
872            entity: e,
873            attribute: a,
874            value: v,
875            tx,
876        })
877    }
878}
879
880#[derive(Clone, Debug, Eq, PartialEq)]
881pub struct Predicate {
882    pub expr: FnArg, // always SExpr at top level
883}
884
885#[derive(Clone, Debug, Eq, PartialEq)]
886pub struct WhereFn {
887    pub expr: FnArg, // always SExpr at top level
888    pub binding: Binding,
889}
890
891#[derive(Clone, Debug, Eq, PartialEq)]
892pub enum UnifyVars {
893    /// `Implicit` means the variables in an `or` or `not` are derived from the enclosed pattern.
894    /// DataScript regards these vars as 'free': these variables don't need to be bound by the
895    /// enclosing environment.
896    ///
897    /// Datomic's documentation implies that all implicit variables are required:
898    ///
899    /// > Datomic will attempt to push the or clause down until all necessary variables are bound,
900    /// > and will throw an exception if that is not possible.
901    ///
902    /// but that would render top-level `or` expressions (as used in Datomic's own examples!)
903    /// impossible, so we assume that this is an error in the documentation.
904    ///
905    /// All contained 'arms' in an `or` with implicit variables must bind the same vars.
906    Implicit,
907
908    /// `Explicit` means the variables in an `or-join` or `not-join` are explicitly listed,
909    /// specified with `required-vars` syntax.
910    ///
911    /// DataScript parses these as free, but allows (incorrectly) the use of more complicated
912    /// `rule-vars` syntax.
913    ///
914    /// Only the named variables will be unified with the enclosing query.
915    ///
916    /// Every 'arm' in an `or-join` must mention the entire set of explicit vars.
917    Explicit(BTreeSet<Variable>),
918}
919
920impl WhereClause {
921    pub fn is_pattern(&self) -> bool {
922        matches!(self, WhereClause::Pattern(_))
923    }
924}
925
926#[derive(Clone, Debug, Eq, PartialEq)]
927pub enum OrWhereClause {
928    Clause(WhereClause),
929    And(Vec<WhereClause>),
930}
931
932impl OrWhereClause {
933    pub fn is_pattern_or_patterns(&self) -> bool {
934        match self {
935            &OrWhereClause::Clause(WhereClause::Pattern(_)) => true,
936            OrWhereClause::And(clauses) => clauses.iter().all(|clause| clause.is_pattern()),
937            _ => false,
938        }
939    }
940}
941
942#[derive(Clone, Debug, Eq, PartialEq)]
943pub struct OrJoin {
944    pub unify_vars: UnifyVars,
945    pub clauses: Vec<OrWhereClause>,
946
947    /// Caches the result of `collect_mentioned_variables`.
948    mentioned_vars: Option<BTreeSet<Variable>>,
949}
950
951#[derive(Clone, Debug, Eq, PartialEq)]
952pub struct NotJoin {
953    pub unify_vars: UnifyVars,
954    pub clauses: Vec<WhereClause>,
955}
956
957impl NotJoin {
958    pub fn new(unify_vars: UnifyVars, clauses: Vec<WhereClause>) -> NotJoin {
959        NotJoin {
960            unify_vars,
961            clauses,
962        }
963    }
964}
965
966#[derive(Clone, Debug, Eq, PartialEq)]
967pub struct TypeAnnotation {
968    pub value_type: Keyword,
969    pub variable: Variable,
970}
971
972#[allow(dead_code)]
973#[derive(Clone, Debug, Eq, PartialEq)]
974pub enum WhereClause {
975    NotJoin(NotJoin),
976    OrJoin(OrJoin),
977    Pred(Predicate),
978    WhereFn(WhereFn),
979    RuleExpr,
980    Pattern(Pattern),
981    TypeAnnotation(TypeAnnotation),
982}
983
984#[allow(dead_code)]
985#[derive(Clone, Debug, Eq, PartialEq)]
986pub struct ParsedQuery {
987    pub find_spec: FindSpec,
988    pub default_source: SrcVar,
989    pub with: Vec<Variable>,
990    pub in_bindings: Vec<Binding>,
991    pub in_sources: BTreeSet<SrcVar>,
992    pub limit: Limit,
993    pub where_clauses: Vec<WhereClause>,
994    pub order: Option<Vec<Order>>,
995}
996
997pub(crate) enum QueryPart {
998    FindSpec(FindSpec),
999    WithVars(Vec<Variable>),
1000    InBindings(Vec<Binding>),
1001    Limit(Limit),
1002    WhereClauses(Vec<WhereClause>),
1003    Order(Vec<Order>),
1004}
1005
1006/// A `ParsedQuery` represents a parsed but potentially invalid query to the query algebrizer.
1007/// Such a query is syntactically valid but might be semantically invalid, for example because
1008/// constraints on the set of variables are not respected.
1009///
1010/// We split `ParsedQuery` from `FindQuery` because it's not easy to generalize over containers
1011/// (here, `Vec` and `BTreeSet`) in Rust.
1012impl ParsedQuery {
1013    /// Extract a flat list of variables from in_bindings (each binding contributes its variable(s)).
1014    pub fn in_vars(&self) -> Vec<Variable> {
1015        self.in_bindings
1016            .iter()
1017            .flat_map(|b| b.variables().into_iter().flatten())
1018            .collect()
1019    }
1020
1021    pub(crate) fn from_parts(
1022        parts: Vec<QueryPart>,
1023    ) -> std::result::Result<ParsedQuery, &'static str> {
1024        let mut find_spec: Option<FindSpec> = None;
1025        let mut with: Option<Vec<Variable>> = None;
1026        let mut in_bindings: Option<Vec<Binding>> = None;
1027        let mut limit: Option<Limit> = None;
1028        let mut where_clauses: Option<Vec<WhereClause>> = None;
1029        let mut order: Option<Vec<Order>> = None;
1030
1031        for part in parts.into_iter() {
1032            match part {
1033                QueryPart::FindSpec(x) => {
1034                    if find_spec.is_some() {
1035                        return Err("find query has repeated :find");
1036                    }
1037                    find_spec = Some(x)
1038                }
1039                QueryPart::WithVars(x) => {
1040                    if with.is_some() {
1041                        return Err("find query has repeated :with");
1042                    }
1043                    with = Some(x)
1044                }
1045                QueryPart::InBindings(x) => {
1046                    if in_bindings.is_some() {
1047                        return Err("find query has repeated :in");
1048                    }
1049                    in_bindings = Some(x)
1050                }
1051                QueryPart::Limit(x) => {
1052                    if limit.is_some() {
1053                        return Err("find query has repeated :limit");
1054                    }
1055                    limit = Some(x)
1056                }
1057                QueryPart::WhereClauses(x) => {
1058                    if where_clauses.is_some() {
1059                        return Err("find query has repeated :where");
1060                    }
1061                    where_clauses = Some(x)
1062                }
1063                QueryPart::Order(x) => {
1064                    if order.is_some() {
1065                        return Err("find query has repeated :order");
1066                    }
1067                    order = Some(x)
1068                }
1069            }
1070        }
1071
1072        Ok(ParsedQuery {
1073            find_spec: find_spec.ok_or("expected :find")?,
1074            default_source: SrcVar::DefaultSrc,
1075            with: with.unwrap_or(vec![]),
1076            in_bindings: in_bindings.unwrap_or(vec![]),
1077            in_sources: BTreeSet::default(),
1078            limit: limit.unwrap_or(Limit::None),
1079            where_clauses: where_clauses.ok_or("expected :where")?,
1080            order,
1081        })
1082    }
1083}
1084
1085impl OrJoin {
1086    pub fn new(unify_vars: UnifyVars, clauses: Vec<OrWhereClause>) -> OrJoin {
1087        OrJoin {
1088            unify_vars,
1089            clauses,
1090            mentioned_vars: None,
1091        }
1092    }
1093
1094    /// Return true if either the `OrJoin` is `UnifyVars::Implicit`, or if
1095    /// every variable mentioned inside the join is also mentioned in the `UnifyVars` list.
1096    pub fn is_fully_unified(&self) -> bool {
1097        match &self.unify_vars {
1098            &UnifyVars::Implicit => true,
1099            UnifyVars::Explicit(vars) => {
1100                // We know that the join list must be a subset of the vars in the pattern, or
1101                // it would have failed validation. That allows us to simply compare counts here.
1102                // TODO: in debug mode, do a full intersection, and verify that our count check
1103                // returns the same results.
1104                // Use the cached list if we have one.
1105                if let Some(ref mentioned) = self.mentioned_vars {
1106                    vars.len() == mentioned.len()
1107                } else {
1108                    vars.len() == self.collect_mentioned_variables().len()
1109                }
1110            }
1111        }
1112    }
1113}
1114
1115pub trait ContainsVariables {
1116    fn accumulate_mentioned_variables(&self, acc: &mut BTreeSet<Variable>);
1117    fn collect_mentioned_variables(&self) -> BTreeSet<Variable> {
1118        let mut out = BTreeSet::new();
1119        self.accumulate_mentioned_variables(&mut out);
1120        out
1121    }
1122}
1123
1124impl ContainsVariables for WhereClause {
1125    fn accumulate_mentioned_variables(&self, acc: &mut BTreeSet<Variable>) {
1126        use self::WhereClause::*;
1127        match self {
1128            OrJoin(o) => o.accumulate_mentioned_variables(acc),
1129            Pred(p) => p.accumulate_mentioned_variables(acc),
1130            Pattern(p) => p.accumulate_mentioned_variables(acc),
1131            NotJoin(n) => n.accumulate_mentioned_variables(acc),
1132            WhereFn(f) => f.accumulate_mentioned_variables(acc),
1133            TypeAnnotation(a) => a.accumulate_mentioned_variables(acc),
1134            &RuleExpr => (),
1135        }
1136    }
1137}
1138
1139impl ContainsVariables for OrWhereClause {
1140    fn accumulate_mentioned_variables(&self, acc: &mut BTreeSet<Variable>) {
1141        use self::OrWhereClause::*;
1142        match self {
1143            And(clauses) => {
1144                for clause in clauses {
1145                    clause.accumulate_mentioned_variables(acc)
1146                }
1147            }
1148            Clause(clause) => clause.accumulate_mentioned_variables(acc),
1149        }
1150    }
1151}
1152
1153impl ContainsVariables for OrJoin {
1154    fn accumulate_mentioned_variables(&self, acc: &mut BTreeSet<Variable>) {
1155        for clause in &self.clauses {
1156            clause.accumulate_mentioned_variables(acc);
1157        }
1158    }
1159}
1160
1161impl OrJoin {
1162    pub fn dismember(self) -> (Vec<OrWhereClause>, UnifyVars, BTreeSet<Variable>) {
1163        let vars = match self.mentioned_vars {
1164            Some(m) => m,
1165            None => self.collect_mentioned_variables(),
1166        };
1167        (self.clauses, self.unify_vars, vars)
1168    }
1169
1170    pub fn mentioned_variables(&mut self) -> &BTreeSet<Variable> {
1171        if self.mentioned_vars.is_none() {
1172            let m = self.collect_mentioned_variables();
1173            self.mentioned_vars = Some(m);
1174        }
1175
1176        if let Some(ref mentioned) = self.mentioned_vars {
1177            mentioned
1178        } else {
1179            unreachable!()
1180        }
1181    }
1182}
1183
1184impl ContainsVariables for NotJoin {
1185    fn accumulate_mentioned_variables(&self, acc: &mut BTreeSet<Variable>) {
1186        for clause in &self.clauses {
1187            clause.accumulate_mentioned_variables(acc);
1188        }
1189    }
1190}
1191
1192fn accumulate_fn_arg_variables(arg: &FnArg, acc: &mut BTreeSet<Variable>) {
1193    match arg {
1194        FnArg::Variable(v) => acc_ref(acc, v),
1195        FnArg::SExpr(_, args) => {
1196            for a in args {
1197                accumulate_fn_arg_variables(a, acc);
1198            }
1199        }
1200        _ => {}
1201    }
1202}
1203
1204impl ContainsVariables for Predicate {
1205    fn accumulate_mentioned_variables(&self, acc: &mut BTreeSet<Variable>) {
1206        accumulate_fn_arg_variables(&self.expr, acc);
1207    }
1208}
1209
1210impl ContainsVariables for TypeAnnotation {
1211    fn accumulate_mentioned_variables(&self, acc: &mut BTreeSet<Variable>) {
1212        acc_ref(acc, &self.variable);
1213    }
1214}
1215
1216impl ContainsVariables for Binding {
1217    fn accumulate_mentioned_variables(&self, acc: &mut BTreeSet<Variable>) {
1218        match self {
1219            &Binding::BindScalar(ref v) | &Binding::BindColl(ref v) => acc_ref(acc, v),
1220            &Binding::BindRel(ref vs) | &Binding::BindTuple(ref vs) => {
1221                for v in vs {
1222                    if let VariableOrPlaceholder::Variable(v) = v {
1223                        acc_ref(acc, v);
1224                    }
1225                }
1226            }
1227        }
1228    }
1229}
1230
1231impl ContainsVariables for WhereFn {
1232    fn accumulate_mentioned_variables(&self, acc: &mut BTreeSet<Variable>) {
1233        accumulate_fn_arg_variables(&self.expr, acc);
1234        self.binding.accumulate_mentioned_variables(acc);
1235    }
1236}
1237
1238fn acc_ref<T: Clone + Ord>(acc: &mut BTreeSet<T>, v: &T) {
1239    // Roll on, reference entries!
1240    if !acc.contains(v) {
1241        acc.insert(v.clone());
1242    }
1243}
1244
1245impl ContainsVariables for Pattern {
1246    fn accumulate_mentioned_variables(&self, acc: &mut BTreeSet<Variable>) {
1247        if let PatternNonValuePlace::Variable(ref v) = self.entity {
1248            acc_ref(acc, v)
1249        }
1250        if let PatternNonValuePlace::Variable(ref v) = self.attribute {
1251            acc_ref(acc, v)
1252        }
1253        if let PatternValuePlace::Variable(ref v) = self.value {
1254            acc_ref(acc, v)
1255        }
1256        if let PatternNonValuePlace::Variable(ref v) = self.tx {
1257            acc_ref(acc, v)
1258        }
1259    }
1260}
1261
1262// ---------------------------------------------------------------------------
1263// Display implementations for EDN round-tripping
1264// ---------------------------------------------------------------------------
1265
1266impl std::fmt::Display for NonIntegerConstant {
1267    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1268        use chrono::SecondsFormat;
1269        match self {
1270            NonIntegerConstant::Boolean(v) => write!(f, "{}", v),
1271            NonIntegerConstant::BigInteger(ref v) => write!(f, "{}N", v),
1272            NonIntegerConstant::Float(ref v) => {
1273                if *v == OrderedFloat(f64::INFINITY) {
1274                    write!(f, "#f +Infinity")
1275                } else if *v == OrderedFloat(f64::NEG_INFINITY) {
1276                    write!(f, "#f -Infinity")
1277                } else if v.is_nan() {
1278                    write!(f, "#f NaN")
1279                } else if v.fract() == 0.0 {
1280                    write!(f, "{:.1}", v)
1281                } else {
1282                    write!(f, "{}", v)
1283                }
1284            }
1285            NonIntegerConstant::Text(ref v) => {
1286                write!(f, "\"")?;
1287                for c in v.chars() {
1288                    match c {
1289                        '"' => write!(f, "\\\"")?,
1290                        '\\' => write!(f, "\\\\")?,
1291                        '\n' => write!(f, "\\n")?,
1292                        '\r' => write!(f, "\\r")?,
1293                        '\t' => write!(f, "\\t")?,
1294                        c => write!(f, "{}", c)?,
1295                    }
1296                }
1297                write!(f, "\"")
1298            }
1299            NonIntegerConstant::Instant(v) => write!(
1300                f,
1301                "#inst \"{}\"",
1302                v.to_rfc3339_opts(SecondsFormat::AutoSi, true)
1303            ),
1304            NonIntegerConstant::Uuid(ref u) => write!(f, "#uuid \"{}\"", u.hyphenated()),
1305        }
1306    }
1307}
1308
1309impl std::fmt::Display for PatternNonValuePlace {
1310    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1311        match self {
1312            PatternNonValuePlace::Placeholder => write!(f, "_"),
1313            PatternNonValuePlace::Variable(ref v) => write!(f, "{}", v),
1314            PatternNonValuePlace::Entid(e) => write!(f, "{}", e),
1315            PatternNonValuePlace::Ident(ref k) => write!(f, "{}", k),
1316        }
1317    }
1318}
1319
1320impl std::fmt::Display for PatternValuePlace {
1321    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1322        match self {
1323            PatternValuePlace::Placeholder => write!(f, "_"),
1324            PatternValuePlace::Variable(ref v) => write!(f, "{}", v),
1325            PatternValuePlace::EntidOrInteger(i) => write!(f, "{}", i),
1326            PatternValuePlace::IdentOrKeyword(ref k) => write!(f, "{}", k),
1327            PatternValuePlace::Constant(ref c) => write!(f, "{}", c),
1328        }
1329    }
1330}
1331
1332impl std::fmt::Display for Pattern {
1333    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1334        write!(f, "[{} {} {}", self.entity, self.attribute, self.value)?;
1335        if !matches!(self.tx, PatternNonValuePlace::Placeholder) {
1336            write!(f, " {}", self.tx)?;
1337        }
1338        write!(f, "]")
1339    }
1340}
1341
1342impl std::fmt::Display for Predicate {
1343    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1344        write!(f, "{}", self.expr)
1345    }
1346}
1347
1348impl std::fmt::Display for Binding {
1349    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1350        match self {
1351            Binding::BindScalar(ref v) => write!(f, "{}", v),
1352            Binding::BindColl(ref v) => write!(f, "[{} ...]", v),
1353            Binding::BindTuple(ref vs) => {
1354                write!(f, "[")?;
1355                for (i, v) in vs.iter().enumerate() {
1356                    if i > 0 {
1357                        write!(f, " ")?;
1358                    }
1359                    match v {
1360                        VariableOrPlaceholder::Variable(ref var) => write!(f, "{}", var)?,
1361                        VariableOrPlaceholder::Placeholder => write!(f, "_")?,
1362                    }
1363                }
1364                write!(f, "]")
1365            }
1366            Binding::BindRel(ref vs) => {
1367                write!(f, "[[")?;
1368                for (i, v) in vs.iter().enumerate() {
1369                    if i > 0 {
1370                        write!(f, " ")?;
1371                    }
1372                    match v {
1373                        VariableOrPlaceholder::Variable(ref var) => write!(f, "{}", var)?,
1374                        VariableOrPlaceholder::Placeholder => write!(f, "_")?,
1375                    }
1376                }
1377                write!(f, "]]")
1378            }
1379        }
1380    }
1381}
1382
1383impl std::fmt::Display for WhereFn {
1384    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1385        write!(f, "[{} {}]", self.expr, self.binding)
1386    }
1387}
1388
1389impl std::fmt::Display for WhereClause {
1390    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1391        match self {
1392            WhereClause::Pattern(ref p) => write!(f, "{}", p),
1393            WhereClause::Pred(ref p) => write!(f, "[{}]", p),
1394            WhereClause::WhereFn(ref wf) => write!(f, "{}", wf),
1395            WhereClause::NotJoin(ref nj) => write!(f, "{}", nj),
1396            WhereClause::OrJoin(ref oj) => write!(f, "{}", oj),
1397            WhereClause::TypeAnnotation(ref ta) => {
1398                write!(f, "[(type {} {})]", ta.variable, ta.value_type)
1399            }
1400            WhereClause::RuleExpr => write!(f, "(rule-expr)"),
1401        }
1402    }
1403}
1404
1405impl std::fmt::Display for NotJoin {
1406    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1407        match self.unify_vars {
1408            UnifyVars::Implicit => write!(f, "(not")?,
1409            UnifyVars::Explicit(ref vars) => {
1410                write!(f, "(not-join [")?;
1411                for (i, v) in vars.iter().enumerate() {
1412                    if i > 0 {
1413                        write!(f, " ")?;
1414                    }
1415                    write!(f, "{}", v)?;
1416                }
1417                write!(f, "]")?;
1418            }
1419        }
1420        for clause in &self.clauses {
1421            write!(f, " {}", clause)?;
1422        }
1423        write!(f, ")")
1424    }
1425}
1426
1427impl std::fmt::Display for OrWhereClause {
1428    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1429        match self {
1430            OrWhereClause::Clause(ref c) => write!(f, "{}", c),
1431            OrWhereClause::And(ref clauses) => {
1432                write!(f, "(and")?;
1433                for c in clauses {
1434                    write!(f, " {}", c)?;
1435                }
1436                write!(f, ")")
1437            }
1438        }
1439    }
1440}
1441
1442impl std::fmt::Display for OrJoin {
1443    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1444        match self.unify_vars {
1445            UnifyVars::Implicit => write!(f, "(or")?,
1446            UnifyVars::Explicit(ref vars) => {
1447                write!(f, "(or-join [")?;
1448                for (i, v) in vars.iter().enumerate() {
1449                    if i > 0 {
1450                        write!(f, " ")?;
1451                    }
1452                    write!(f, "{}", v)?;
1453                }
1454                write!(f, "]")?;
1455            }
1456        }
1457        for clause in &self.clauses {
1458            write!(f, " {}", clause)?;
1459        }
1460        write!(f, ")")
1461    }
1462}
1463
1464impl std::fmt::Display for FindSpec {
1465    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1466        match self {
1467            FindSpec::FindRel(ref elems) => {
1468                for (i, e) in elems.iter().enumerate() {
1469                    if i > 0 {
1470                        write!(f, " ")?;
1471                    }
1472                    write!(f, "{}", e)?;
1473                }
1474                Ok(())
1475            }
1476            FindSpec::FindColl(ref e) => write!(f, "[{} ...]", e),
1477            FindSpec::FindTuple(ref elems) => {
1478                write!(f, "[")?;
1479                for (i, e) in elems.iter().enumerate() {
1480                    if i > 0 {
1481                        write!(f, " ")?;
1482                    }
1483                    write!(f, "{}", e)?;
1484                }
1485                write!(f, "]")
1486            }
1487            FindSpec::FindScalar(ref e) => write!(f, "{} .", e),
1488        }
1489    }
1490}
1491
1492impl std::fmt::Display for Order {
1493    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1494        match self.0 {
1495            Direction::Ascending => write!(f, "[{} :asc]", self.1),
1496            Direction::Descending => write!(f, "[{} :desc]", self.1),
1497        }
1498    }
1499}
1500
1501impl std::fmt::Display for Limit {
1502    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1503        match self {
1504            Limit::None => Ok(()),
1505            Limit::Fixed(n) => write!(f, "{}", n),
1506            Limit::Variable(ref v) => write!(f, "{}", v),
1507        }
1508    }
1509}
1510
1511impl std::str::FromStr for ParsedQuery {
1512    type Err = peg::error::ParseError<peg::str::LineCol>;
1513
1514    fn from_str(s: &str) -> Result<Self, Self::Err> {
1515        crate::parse::parse_query(s)
1516    }
1517}
1518
1519impl std::fmt::Display for ParsedQuery {
1520    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1521        write!(f, "{{:find [{}]", self.find_spec)?;
1522        if !self.with.is_empty() {
1523            write!(f, " :with [")?;
1524            for (i, v) in self.with.iter().enumerate() {
1525                if i > 0 {
1526                    write!(f, " ")?;
1527                }
1528                write!(f, "{}", v)?;
1529            }
1530            write!(f, "]")?;
1531        }
1532        if !self.in_bindings.is_empty() {
1533            write!(f, " :in [")?;
1534            for (i, b) in self.in_bindings.iter().enumerate() {
1535                if i > 0 {
1536                    write!(f, " ")?;
1537                }
1538                write!(f, "{}", b)?;
1539            }
1540            write!(f, "]")?;
1541        }
1542        write!(f, " :where [")?;
1543        for (i, c) in self.where_clauses.iter().enumerate() {
1544            if i > 0 {
1545                write!(f, " ")?;
1546            }
1547            write!(f, "{}", c)?;
1548        }
1549        write!(f, "]")?;
1550        if let Some(ref orders) = self.order {
1551            write!(f, " :order [")?;
1552            for (i, o) in orders.iter().enumerate() {
1553                if i > 0 {
1554                    write!(f, " ")?;
1555                }
1556                write!(f, "{}", o)?;
1557            }
1558            write!(f, "]")?;
1559        }
1560        if let Limit::Fixed(_) | Limit::Variable(_) = self.limit {
1561            write!(f, " :limit {}", self.limit)?;
1562        }
1563        write!(f, "}}")
1564    }
1565}