1use std::collections::{BTreeSet, HashSet};
33
34use std;
35use std::fmt;
36use std::rc::Rc;
37
38use crate::{BigInt, DateTime, OrderedFloat, Utc, Uuid};
39
40use crate::value_rc::{FromRc, ValueRc};
41
42pub use crate::{Keyword, PlainSymbol};
43
44pub type SrcVarName = String; #[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
47pub struct Variable(pub Rc<PlainSymbol>);
48
49impl Variable {
50 pub fn as_str(&self) -> &str {
51 self.0.as_ref().0.as_str()
52 }
53
54 pub fn name(&self) -> PlainSymbol {
55 self.0.as_ref().clone()
56 }
57
58 pub fn from_valid_name(name: &str) -> Variable {
60 let s = PlainSymbol::plain(name);
61 assert!(s.is_var_symbol());
62 Variable(Rc::new(s))
63 }
64}
65
66pub trait FromValue<T> {
67 fn from_value(v: &crate::ValueAndSpan) -> Option<T>;
68}
69
70impl FromValue<Variable> for Variable {
74 fn from_value(v: &crate::ValueAndSpan) -> Option<Variable> {
75 if let crate::SpannedValue::PlainSymbol(ref s) = v.inner {
76 Variable::from_symbol(s)
77 } else {
78 None
79 }
80 }
81}
82
83impl Variable {
84 pub fn from_rc(sym: Rc<PlainSymbol>) -> Option<Variable> {
85 if sym.is_var_symbol() {
86 Some(Variable(sym))
87 } else {
88 None
89 }
90 }
91
92 pub fn from_symbol(sym: &PlainSymbol) -> Option<Variable> {
94 if sym.is_var_symbol() {
95 Some(Variable(Rc::new(sym.clone())))
96 } else {
97 None
98 }
99 }
100}
101
102impl fmt::Debug for Variable {
103 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
104 write!(f, "var({})", self.0)
105 }
106}
107
108impl std::fmt::Display for Variable {
109 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
110 write!(f, "{}", self.0)
111 }
112}
113
114#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
115pub struct QueryFunction(pub PlainSymbol);
116
117impl FromValue<QueryFunction> for QueryFunction {
118 fn from_value(v: &crate::ValueAndSpan) -> Option<QueryFunction> {
119 if let crate::SpannedValue::PlainSymbol(ref s) = v.inner {
120 QueryFunction::from_symbol(s)
121 } else {
122 None
123 }
124 }
125}
126
127impl QueryFunction {
128 pub fn from_symbol(sym: &PlainSymbol) -> Option<QueryFunction> {
129 Some(QueryFunction(sym.clone()))
131 }
132}
133
134impl std::fmt::Display for QueryFunction {
135 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
136 write!(f, "{}", self.0)
137 }
138}
139
140#[derive(Clone, Debug, Eq, PartialEq)]
141pub enum Direction {
142 Ascending,
143 Descending,
144}
145
146#[derive(Clone, Debug, Eq, PartialEq)]
148pub struct Order(pub Direction, pub Variable); #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
151pub enum SrcVar {
152 DefaultSrc,
153 NamedSrc(SrcVarName),
154}
155
156impl FromValue<SrcVar> for SrcVar {
157 fn from_value(v: &crate::ValueAndSpan) -> Option<SrcVar> {
158 if let crate::SpannedValue::PlainSymbol(ref s) = v.inner {
159 SrcVar::from_symbol(s)
160 } else {
161 None
162 }
163 }
164}
165
166impl SrcVar {
167 pub fn from_symbol(sym: &PlainSymbol) -> Option<SrcVar> {
168 if sym.is_src_symbol() {
169 if sym.0 == "$" {
170 Some(SrcVar::DefaultSrc)
171 } else {
172 Some(SrcVar::NamedSrc(sym.name().to_string()))
173 }
174 } else {
175 None
176 }
177 }
178}
179
180#[derive(Clone, Debug, Eq, PartialEq)]
182pub enum NonIntegerConstant {
183 Boolean(bool),
184 BigInteger(BigInt),
185 Float(OrderedFloat<f64>),
186 Text(ValueRc<String>),
187 Instant(DateTime<Utc>),
188 Uuid(Uuid),
189}
190
191impl<'a> From<&'a str> for NonIntegerConstant {
192 fn from(val: &'a str) -> NonIntegerConstant {
193 NonIntegerConstant::Text(ValueRc::new(val.to_string()))
194 }
195}
196
197impl From<String> for NonIntegerConstant {
198 fn from(val: String) -> NonIntegerConstant {
199 NonIntegerConstant::Text(ValueRc::new(val))
200 }
201}
202
203#[derive(Clone, Debug, Eq, PartialEq)]
204pub enum FnArg {
205 Variable(Variable),
206 SrcVar(SrcVar),
207 EntidOrInteger(i64),
208 IdentOrKeyword(Keyword),
209 Constant(NonIntegerConstant),
210 Vector(Vec<FnArg>),
213}
214
215impl FromValue<FnArg> for FnArg {
216 fn from_value(v: &crate::ValueAndSpan) -> Option<FnArg> {
217 use crate::SpannedValue::*;
218 match v.inner {
219 Integer(x) => Some(FnArg::EntidOrInteger(x)),
220 PlainSymbol(ref x) if x.is_src_symbol() => SrcVar::from_symbol(x).map(FnArg::SrcVar),
221 PlainSymbol(ref x) if x.is_var_symbol() => {
222 Variable::from_symbol(x).map(FnArg::Variable)
223 }
224 PlainSymbol(_) => None,
225 Keyword(ref x) => Some(FnArg::IdentOrKeyword(x.clone())),
226 Instant(x) => Some(FnArg::Constant(NonIntegerConstant::Instant(x))),
227 Uuid(x) => Some(FnArg::Constant(NonIntegerConstant::Uuid(x))),
228 Boolean(x) => Some(FnArg::Constant(NonIntegerConstant::Boolean(x))),
229 Float(x) => Some(FnArg::Constant(NonIntegerConstant::Float(x))),
230 BigInteger(ref x) => Some(FnArg::Constant(NonIntegerConstant::BigInteger(x.clone()))),
231 Text(ref x) =>
232 {
234 Some(FnArg::Constant(x.clone().into()))
235 }
236 Nil | NamespacedSymbol(_) | Vector(_) | List(_) | Set(_) | Map(_) | Bytes(_) => None,
237 }
238 }
239}
240
241impl std::fmt::Display for FnArg {
243 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
244 match self {
245 FnArg::Variable(ref var) => write!(f, "{}", var),
246 FnArg::SrcVar(ref var) => {
247 if var == &SrcVar::DefaultSrc {
248 write!(f, "$")
249 } else {
250 write!(f, "{:?}", var)
251 }
252 }
253 FnArg::EntidOrInteger(entid) => write!(f, "{}", entid),
254 FnArg::IdentOrKeyword(ref kw) => write!(f, "{}", kw),
255 FnArg::Constant(ref constant) => write!(f, "{:?}", constant),
256 FnArg::Vector(ref vec) => write!(f, "{:?}", vec),
257 }
258 }
259}
260
261impl FnArg {
262 pub fn as_variable(&self) -> Option<&Variable> {
263 match self {
264 FnArg::Variable(ref v) => Some(v),
265 _ => None,
266 }
267 }
268}
269
270#[derive(Clone, Debug, Eq, PartialEq)]
277pub enum PatternNonValuePlace {
278 Placeholder,
279 Variable(Variable),
280 Entid(i64), Ident(ValueRc<Keyword>),
282}
283
284impl From<Rc<Keyword>> for PatternNonValuePlace {
285 fn from(value: Rc<Keyword>) -> Self {
286 PatternNonValuePlace::Ident(ValueRc::from_rc(value))
287 }
288}
289
290impl From<Keyword> for PatternNonValuePlace {
291 fn from(value: Keyword) -> Self {
292 PatternNonValuePlace::Ident(ValueRc::new(value))
293 }
294}
295
296impl PatternNonValuePlace {
297 #[allow(dead_code)]
299 fn into_pattern_value_place(self) -> PatternValuePlace {
300 match self {
301 PatternNonValuePlace::Placeholder => PatternValuePlace::Placeholder,
302 PatternNonValuePlace::Variable(x) => PatternValuePlace::Variable(x),
303 PatternNonValuePlace::Entid(x) => PatternValuePlace::EntidOrInteger(x),
304 PatternNonValuePlace::Ident(x) => PatternValuePlace::IdentOrKeyword(x),
305 }
306 }
307
308 fn to_pattern_value_place(&self) -> PatternValuePlace {
309 match *self {
310 PatternNonValuePlace::Placeholder => PatternValuePlace::Placeholder,
311 PatternNonValuePlace::Variable(ref x) => PatternValuePlace::Variable(x.clone()),
312 PatternNonValuePlace::Entid(x) => PatternValuePlace::EntidOrInteger(x),
313 PatternNonValuePlace::Ident(ref x) => PatternValuePlace::IdentOrKeyword(x.clone()),
314 }
315 }
316}
317
318impl FromValue<PatternNonValuePlace> for PatternNonValuePlace {
319 fn from_value(v: &crate::ValueAndSpan) -> Option<PatternNonValuePlace> {
320 match v.inner {
321 crate::SpannedValue::Integer(x) => {
322 if x >= 0 {
323 Some(PatternNonValuePlace::Entid(x))
324 } else {
325 None
326 }
327 }
328 crate::SpannedValue::PlainSymbol(ref x) => {
329 if x.0.as_str() == "_" {
330 Some(PatternNonValuePlace::Placeholder)
331 } else {
332 Variable::from_symbol(x).map(PatternNonValuePlace::Variable)
333 }
334 }
335 crate::SpannedValue::Keyword(ref x) => Some(x.clone().into()),
336 _ => None,
337 }
338 }
339}
340
341#[derive(Clone, Debug, Eq, PartialEq)]
342pub enum IdentOrEntid {
343 Ident(Keyword),
344 Entid(i64),
345}
346
347#[derive(Clone, Debug, Eq, PartialEq)]
351pub enum PatternValuePlace {
352 Placeholder,
353 Variable(Variable),
354 EntidOrInteger(i64),
355 IdentOrKeyword(ValueRc<Keyword>),
356 Constant(NonIntegerConstant),
357}
358
359impl From<Rc<Keyword>> for PatternValuePlace {
360 fn from(value: Rc<Keyword>) -> Self {
361 PatternValuePlace::IdentOrKeyword(ValueRc::from_rc(value))
362 }
363}
364
365impl From<Keyword> for PatternValuePlace {
366 fn from(value: Keyword) -> Self {
367 PatternValuePlace::IdentOrKeyword(ValueRc::new(value))
368 }
369}
370
371impl FromValue<PatternValuePlace> for PatternValuePlace {
372 fn from_value(v: &crate::ValueAndSpan) -> Option<PatternValuePlace> {
373 match v.inner {
374 crate::SpannedValue::Integer(x) => Some(PatternValuePlace::EntidOrInteger(x)),
375 crate::SpannedValue::PlainSymbol(ref x) if x.0.as_str() == "_" => {
376 Some(PatternValuePlace::Placeholder)
377 }
378 crate::SpannedValue::PlainSymbol(ref x) => {
379 Variable::from_symbol(x).map(PatternValuePlace::Variable)
380 }
381 crate::SpannedValue::Keyword(ref x) => Some(x.clone().into()),
382 crate::SpannedValue::Boolean(x) => {
383 Some(PatternValuePlace::Constant(NonIntegerConstant::Boolean(x)))
384 }
385 crate::SpannedValue::Float(x) => {
386 Some(PatternValuePlace::Constant(NonIntegerConstant::Float(x)))
387 }
388 crate::SpannedValue::BigInteger(ref x) => Some(PatternValuePlace::Constant(
389 NonIntegerConstant::BigInteger(x.clone()),
390 )),
391 crate::SpannedValue::Instant(x) => {
392 Some(PatternValuePlace::Constant(NonIntegerConstant::Instant(x)))
393 }
394 crate::SpannedValue::Text(ref x) =>
395 {
397 Some(PatternValuePlace::Constant(x.clone().into()))
398 }
399 crate::SpannedValue::Uuid(ref u) => {
400 Some(PatternValuePlace::Constant(NonIntegerConstant::Uuid(*u)))
401 }
402
403 crate::SpannedValue::Nil => None,
405 crate::SpannedValue::NamespacedSymbol(_) => None,
406 crate::SpannedValue::Map(_) => None,
407 crate::SpannedValue::List(_) => None,
408 crate::SpannedValue::Set(_) => None,
409 crate::SpannedValue::Vector(_) => None,
410 crate::SpannedValue::Bytes(_) => None,
411 }
412 }
413}
414
415impl PatternValuePlace {
416 #[allow(dead_code)]
418 fn into_pattern_non_value_place(self) -> Option<PatternNonValuePlace> {
419 match self {
420 PatternValuePlace::Placeholder => Some(PatternNonValuePlace::Placeholder),
421 PatternValuePlace::Variable(x) => Some(PatternNonValuePlace::Variable(x)),
422 PatternValuePlace::EntidOrInteger(x) => {
423 if x >= 0 {
424 Some(PatternNonValuePlace::Entid(x))
425 } else {
426 None
427 }
428 }
429 PatternValuePlace::IdentOrKeyword(x) => Some(PatternNonValuePlace::Ident(x)),
430 PatternValuePlace::Constant(_) => None,
431 }
432 }
433
434 fn to_pattern_non_value_place(&self) -> Option<PatternNonValuePlace> {
435 match *self {
436 PatternValuePlace::Placeholder => Some(PatternNonValuePlace::Placeholder),
437 PatternValuePlace::Variable(ref x) => Some(PatternNonValuePlace::Variable(x.clone())),
438 PatternValuePlace::EntidOrInteger(x) => {
439 if x >= 0 {
440 Some(PatternNonValuePlace::Entid(x))
441 } else {
442 None
443 }
444 }
445 PatternValuePlace::IdentOrKeyword(ref x) => {
446 Some(PatternNonValuePlace::Ident(x.clone()))
447 }
448 PatternValuePlace::Constant(_) => None,
449 }
450 }
451}
452
453#[derive(Clone, Debug, Eq, PartialEq)]
461pub enum PullConcreteAttribute {
462 Ident(Rc<Keyword>),
463 Entid(i64),
464}
465
466#[derive(Clone, Debug, Eq, PartialEq)]
467pub struct NamedPullAttribute {
468 pub attribute: PullConcreteAttribute,
469 pub alias: Option<Rc<Keyword>>,
470 pub reverse: bool,
475}
476
477impl From<PullConcreteAttribute> for NamedPullAttribute {
478 fn from(a: PullConcreteAttribute) -> Self {
479 NamedPullAttribute {
480 attribute: a,
481 alias: None,
482 reverse: false,
483 }
484 }
485}
486
487#[derive(Clone, Debug, Eq, PartialEq)]
488pub enum PullAttributeSpec {
489 Wildcard,
490 Attribute(NamedPullAttribute),
491 }
495
496impl std::fmt::Display for PullConcreteAttribute {
497 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
498 match self {
499 PullConcreteAttribute::Ident(ref k) => write!(f, "{}", k),
500 PullConcreteAttribute::Entid(i) => write!(f, "{}", i),
501 }
502 }
503}
504
505impl std::fmt::Display for NamedPullAttribute {
506 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
507 let attr = &self.attribute;
508 if let Some(ref alias) = self.alias {
509 if self.reverse {
510 write!(f, "_{} :as {}", attr, alias)
511 } else {
512 write!(f, "{} :as {}", attr, alias)
513 }
514 } else if self.reverse {
515 write!(f, "_{}", attr)
516 } else {
517 write!(f, "{}", attr)
518 }
519 }
520}
521
522impl std::fmt::Display for PullAttributeSpec {
523 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
524 match self {
525 PullAttributeSpec::Wildcard => write!(f, "*"),
526 PullAttributeSpec::Attribute(ref attr) => write!(f, "{}", attr),
527 }
528 }
529}
530
531#[derive(Clone, Debug, Eq, PartialEq)]
532pub struct Pull {
533 pub var: Variable,
534 pub patterns: Vec<PullAttributeSpec>,
535}
536
537#[derive(Clone, Debug, Eq, PartialEq)]
538pub struct Aggregate {
539 pub func: QueryFunction,
540 pub args: Vec<FnArg>,
541}
542
543#[derive(Clone, Debug, Eq, PartialEq)]
544pub enum Element {
545 Variable(Variable),
546 Aggregate(Aggregate),
547
548 Corresponding(Variable),
554 Pull(Pull),
555}
556
557impl Element {
558 pub fn is_unit(&self) -> bool {
560 match self {
561 Element::Variable(_) => false,
562 Element::Pull(_) => false,
563 Element::Aggregate(_) => true,
564 Element::Corresponding(_) => true,
565 }
566 }
567}
568
569impl From<Variable> for Element {
570 fn from(x: Variable) -> Element {
571 Element::Variable(x)
572 }
573}
574
575impl std::fmt::Display for Element {
576 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
577 match self {
578 Element::Variable(ref var) => write!(f, "{}", var),
579 Element::Pull(Pull {
580 ref var,
581 ref patterns,
582 }) => {
583 write!(f, "(pull {} [ ", var)?;
584 for p in patterns.iter() {
585 write!(f, "{} ", p)?;
586 }
587 write!(f, "])")
588 }
589 Element::Aggregate(ref agg) => match agg.args.len() {
590 0 => write!(f, "({})", agg.func),
591 1 => write!(f, "({} {})", agg.func, agg.args[0]),
592 _ => write!(f, "({} {:?})", agg.func, agg.args),
593 },
594 Element::Corresponding(ref var) => write!(f, "(the {})", var),
595 }
596 }
597}
598
599#[derive(Clone, Debug, Eq, PartialEq)]
600pub enum Limit {
601 Unlimited,
602 Fixed(u64),
603 Variable(Variable),
604}
605
606#[derive(Clone, Debug, Eq, PartialEq)]
609pub enum Offset {
610 Unlimited,
612 Fixed(u64),
613 Variable(Variable),
614}
615
616#[derive(Clone, Debug, Eq, PartialEq)]
639pub enum FindSpec {
640 FindRel(Vec<Element>),
642
643 FindColl(Element),
647
648 FindTuple(Vec<Element>),
651
652 FindScalar(Element),
655}
656
657impl FindSpec {
659 pub fn is_unit_limited(&self) -> bool {
660 use self::FindSpec::*;
661 match self {
662 FindScalar(..) => true,
663 FindTuple(..) => true,
664 FindRel(..) => false,
665 FindColl(..) => false,
666 }
667 }
668
669 pub fn expected_column_count(&self) -> usize {
670 use self::FindSpec::*;
671 match self {
672 FindScalar(..) => 1,
673 FindColl(..) => 1,
674 FindTuple(ref elems) | &FindRel(ref elems) => elems.len(),
675 }
676 }
677
678 pub fn requires_distinct(&self) -> bool {
697 !self.is_unit_limited()
698 }
699
700 pub fn columns<'s>(&'s self) -> Box<dyn Iterator<Item = &'s Element> + 's> {
701 use self::FindSpec::*;
702 match self {
703 FindScalar(ref e) => Box::new(std::iter::once(e)),
704 FindColl(ref e) => Box::new(std::iter::once(e)),
705 FindTuple(ref v) => Box::new(v.iter()),
706 FindRel(ref v) => Box::new(v.iter()),
707 }
708 }
709}
710
711#[derive(Clone, Debug, Eq, Hash, PartialEq)]
714pub enum VariableOrPlaceholder {
715 Placeholder,
716 Variable(Variable),
717}
718
719impl VariableOrPlaceholder {
720 pub fn into_var(self) -> Option<Variable> {
721 match self {
722 VariableOrPlaceholder::Placeholder => None,
723 VariableOrPlaceholder::Variable(var) => Some(var),
724 }
725 }
726
727 pub fn var(&self) -> Option<&Variable> {
728 match self {
729 VariableOrPlaceholder::Placeholder => None,
730 VariableOrPlaceholder::Variable(ref var) => Some(var),
731 }
732 }
733}
734
735#[derive(Clone, Debug, Eq, PartialEq)]
736pub enum Binding {
737 BindScalar(Variable),
738 BindColl(Variable),
739 BindRel(Vec<VariableOrPlaceholder>),
740 BindTuple(Vec<VariableOrPlaceholder>),
741}
742
743impl Binding {
744 pub fn variables(&self) -> Vec<Option<Variable>> {
746 match self {
747 &Binding::BindScalar(ref var) | &Binding::BindColl(ref var) => vec![Some(var.clone())],
748 &Binding::BindRel(ref vars) | &Binding::BindTuple(ref vars) => {
749 vars.iter().map(|x| x.var().cloned()).collect()
750 }
751 }
752 }
753
754 pub fn is_empty(&self) -> bool {
756 match self {
757 &Binding::BindScalar(_) | &Binding::BindColl(_) => false,
758 &Binding::BindRel(ref vars) | &Binding::BindTuple(ref vars) => {
759 vars.iter().all(|x| x.var().is_none())
760 }
761 }
762 }
763
764 pub fn is_valid(&self) -> bool {
783 match self {
784 Binding::BindScalar(_) | &Binding::BindColl(_) => true,
785 Binding::BindRel(ref vars) | &Binding::BindTuple(ref vars) => {
786 let mut acc = HashSet::<Variable>::new();
787 for var in vars {
788 if let VariableOrPlaceholder::Variable(ref var) = *var {
789 if !acc.insert(var.clone()) {
790 return false;
793 }
794 }
795 }
796 !acc.is_empty()
798 }
799 }
800 }
801}
802
803#[derive(Clone, Debug, Eq, PartialEq)]
808pub struct Pattern {
809 pub source: Option<SrcVar>,
810 pub entity: PatternNonValuePlace,
811 pub attribute: PatternNonValuePlace,
812 pub value: PatternValuePlace,
813 pub tx: PatternNonValuePlace,
814 pub added: PatternNonValuePlace,
817}
818
819impl Pattern {
820 pub fn simple(
821 e: PatternNonValuePlace,
822 a: PatternNonValuePlace,
823 v: PatternValuePlace,
824 ) -> Option<Pattern> {
825 Pattern::new(
826 None,
827 e,
828 a,
829 v,
830 PatternNonValuePlace::Placeholder,
831 PatternNonValuePlace::Placeholder,
832 )
833 }
834
835 pub fn new(
836 src: Option<SrcVar>,
837 e: PatternNonValuePlace,
838 a: PatternNonValuePlace,
839 v: PatternValuePlace,
840 tx: PatternNonValuePlace,
841 added: PatternNonValuePlace,
842 ) -> Option<Pattern> {
843 let aa = a.clone(); if let PatternNonValuePlace::Ident(ref k) = aa {
845 if k.is_backward() {
846 let e_v = e.to_pattern_value_place();
850 if let Some(v_e) = v.to_pattern_non_value_place() {
851 return Some(Pattern {
852 source: src,
853 entity: v_e,
854 attribute: k.to_reversed().into(),
855 value: e_v,
856 tx,
857 added,
858 });
859 } else {
860 return None;
861 }
862 }
863 }
864 Some(Pattern {
865 source: src,
866 entity: e,
867 attribute: a,
868 value: v,
869 tx,
870 added,
871 })
872 }
873}
874
875#[derive(Clone, Debug, Eq, PartialEq)]
876pub struct Predicate {
877 pub operator: PlainSymbol,
878 pub args: Vec<FnArg>,
879}
880
881#[derive(Clone, Debug, Eq, PartialEq)]
882pub struct WhereFn {
883 pub operator: PlainSymbol,
884 pub args: Vec<FnArg>,
885 pub binding: Binding,
886}
887
888#[derive(Clone, Debug, Eq, PartialEq)]
889pub enum UnifyVars {
890 Implicit,
904
905 Explicit(BTreeSet<Variable>),
915}
916
917impl WhereClause {
918 pub fn is_pattern(&self) -> bool {
919 matches!(self, WhereClause::Pattern(_))
920 }
921}
922
923#[derive(Clone, Debug, Eq, PartialEq)]
924pub enum OrWhereClause {
925 Clause(WhereClause),
926 And(Vec<WhereClause>),
927}
928
929impl OrWhereClause {
930 pub fn is_pattern_or_patterns(&self) -> bool {
931 match self {
932 OrWhereClause::Clause(WhereClause::Pattern(_)) => true,
933 OrWhereClause::And(ref clauses) => clauses.iter().all(|clause| clause.is_pattern()),
934 _ => false,
935 }
936 }
937}
938
939#[derive(Clone, Debug, Eq, PartialEq)]
940pub struct OrJoin {
941 pub unify_vars: UnifyVars,
942 pub clauses: Vec<OrWhereClause>,
943
944 mentioned_vars: Option<BTreeSet<Variable>>,
946}
947
948#[derive(Clone, Debug, Eq, PartialEq)]
949pub struct NotJoin {
950 pub unify_vars: UnifyVars,
951 pub clauses: Vec<WhereClause>,
952}
953
954impl NotJoin {
955 pub fn new(unify_vars: UnifyVars, clauses: Vec<WhereClause>) -> NotJoin {
956 NotJoin {
957 unify_vars,
958 clauses,
959 }
960 }
961}
962
963#[derive(Clone, Debug, Eq, PartialEq)]
964pub struct TypeAnnotation {
965 pub value_type: Keyword,
966 pub variable: Variable,
967}
968
969#[allow(dead_code)]
970#[derive(Clone, Debug, Eq, PartialEq)]
973pub struct RuleInvocation {
974 pub name: PlainSymbol,
975 pub args: Vec<FnArg>,
976}
977
978#[derive(Clone, Debug, Eq, PartialEq)]
982pub struct RuleClause {
983 pub head: RuleInvocation,
984 pub body: Vec<WhereClause>,
985}
986
987#[derive(Clone, Debug, Eq, PartialEq)]
990pub struct Rule {
991 pub name: PlainSymbol,
992 pub clauses: Vec<RuleClause>,
993}
994
995#[derive(Clone, Debug, Eq, PartialEq)]
996pub enum WhereClause {
997 NotJoin(NotJoin),
998 OrJoin(OrJoin),
999 Pred(Predicate),
1000 WhereFn(WhereFn),
1001 RuleExpr(RuleInvocation),
1002 Pattern(Pattern),
1003 TypeAnnotation(TypeAnnotation),
1004}
1005
1006#[allow(dead_code)]
1007#[derive(Debug, Eq, PartialEq)]
1008pub struct ParsedQuery {
1009 pub find_spec: FindSpec,
1010 pub default_source: SrcVar,
1011 pub with: Vec<Variable>,
1012 pub in_vars: Vec<Variable>,
1013 pub in_bindings: Vec<Binding>,
1014 pub in_sources: BTreeSet<SrcVar>,
1015 pub limit: Limit,
1016 pub offset: Offset,
1017 pub where_clauses: Vec<WhereClause>,
1018 pub order: Option<Vec<Order>>,
1019 pub distinct: bool,
1020 pub rules: Vec<Rule>,
1021}
1022
1023pub(crate) enum QueryPart {
1024 FindSpec(FindSpec),
1025 WithVars(Vec<Variable>),
1026 #[allow(dead_code)]
1027 InVars(Vec<Variable>),
1028 InBindings(Vec<Binding>),
1029 InSources(Vec<SrcVar>),
1034 Limit(Limit),
1035 Offset(Offset),
1036 WhereClauses(Vec<WhereClause>),
1037 Order(Vec<Order>),
1038 Distinct,
1039 Rules(Vec<Rule>),
1040}
1041impl ParsedQuery {
1048 pub(crate) fn from_parts(
1049 parts: Vec<QueryPart>,
1050 ) -> std::result::Result<ParsedQuery, &'static str> {
1051 let mut find_spec: Option<FindSpec> = None;
1052 let mut with: Option<Vec<Variable>> = None;
1053 let mut in_vars: Option<Vec<Variable>> = None;
1054 let mut in_bindings: Option<Vec<Binding>> = None;
1055 let mut in_sources: Option<Vec<SrcVar>> = None;
1056 let mut limit: Option<Limit> = None;
1057 let mut offset: Option<Offset> = None;
1058 let mut where_clauses: Option<Vec<WhereClause>> = None;
1059 let mut order: Option<Vec<Order>> = None;
1060 let mut distinct = false;
1061 let mut rules: Option<Vec<Rule>> = None;
1062
1063 for part in parts.into_iter() {
1064 match part {
1065 QueryPart::FindSpec(x) => {
1066 if find_spec.is_some() {
1067 return Err("find query has repeated :find");
1068 }
1069 find_spec = Some(x)
1070 }
1071 QueryPart::WithVars(x) => {
1072 if with.is_some() {
1073 return Err("find query has repeated :with");
1074 }
1075 with = Some(x)
1076 }
1077 QueryPart::InVars(x) => {
1078 if in_vars.is_some() {
1079 return Err("find query has repeated :in");
1080 }
1081 in_vars = Some(x)
1082 }
1083 QueryPart::InBindings(x) => {
1084 if in_bindings.is_some() {
1085 return Err("find query has repeated :in");
1086 }
1087 in_bindings = Some(x)
1088 }
1089 QueryPart::InSources(x) => {
1090 if in_sources.is_some() {
1091 return Err("find query has repeated :in");
1092 }
1093 in_sources = Some(x)
1094 }
1095 QueryPart::Limit(x) => {
1096 if limit.is_some() {
1097 return Err("find query has repeated :limit");
1098 }
1099 limit = Some(x)
1100 }
1101 QueryPart::Offset(x) => {
1102 if offset.is_some() {
1103 return Err("find query has repeated :offset");
1104 }
1105 offset = Some(x)
1106 }
1107 QueryPart::WhereClauses(x) => {
1108 if where_clauses.is_some() {
1109 return Err("find query has repeated :where");
1110 }
1111 where_clauses = Some(x)
1112 }
1113 QueryPart::Order(x) => {
1114 if order.is_some() {
1115 return Err("find query has repeated :order");
1116 }
1117 order = Some(x)
1118 }
1119 QueryPart::Distinct => {
1120 distinct = true;
1121 }
1122 QueryPart::Rules(x) => {
1123 if rules.is_some() {
1124 return Err("find query has repeated :rules");
1125 }
1126 rules = Some(x)
1127 }
1128 }
1129 }
1130
1131 let final_in_bindings = in_bindings.unwrap_or_default();
1134 let final_in_vars = if let Some(v) = in_vars {
1135 v
1136 } else {
1137 final_in_bindings
1138 .iter()
1139 .filter_map(|b| match b {
1140 Binding::BindScalar(v) => Some(v.clone()),
1141 _ => None,
1142 })
1143 .collect()
1144 };
1145
1146 Ok(ParsedQuery {
1147 find_spec: find_spec.ok_or("expected :find")?,
1148 default_source: SrcVar::DefaultSrc,
1149 with: with.unwrap_or_default(),
1150 in_vars: final_in_vars,
1151 in_bindings: final_in_bindings,
1152 in_sources: in_sources.unwrap_or_default().into_iter().collect(),
1153 limit: limit.unwrap_or(Limit::Unlimited),
1154 offset: offset.unwrap_or(Offset::Unlimited),
1155 where_clauses: where_clauses.ok_or("expected :where")?,
1156 order,
1157 distinct,
1158 rules: rules.unwrap_or_default(),
1159 })
1160 }
1161}
1162
1163impl OrJoin {
1164 pub fn new(unify_vars: UnifyVars, clauses: Vec<OrWhereClause>) -> OrJoin {
1165 OrJoin {
1166 unify_vars,
1167 clauses,
1168 mentioned_vars: None,
1169 }
1170 }
1171
1172 pub fn is_fully_unified(&self) -> bool {
1175 match &self.unify_vars {
1176 UnifyVars::Implicit => true,
1177 UnifyVars::Explicit(ref vars) => {
1178 if let Some(ref mentioned) = self.mentioned_vars {
1184 vars.len() == mentioned.len()
1185 } else {
1186 vars.len() == self.collect_mentioned_variables().len()
1187 }
1188 }
1189 }
1190 }
1191}
1192
1193pub trait ContainsVariables {
1194 fn accumulate_mentioned_variables(&self, acc: &mut BTreeSet<Variable>);
1195 fn collect_mentioned_variables(&self) -> BTreeSet<Variable> {
1196 let mut out = BTreeSet::new();
1197 self.accumulate_mentioned_variables(&mut out);
1198 out
1199 }
1200}
1201
1202impl ContainsVariables for WhereClause {
1203 fn accumulate_mentioned_variables(&self, acc: &mut BTreeSet<Variable>) {
1204 use self::WhereClause::*;
1205 match self {
1206 OrJoin(ref o) => o.accumulate_mentioned_variables(acc),
1207 Pred(ref p) => p.accumulate_mentioned_variables(acc),
1208 Pattern(ref p) => p.accumulate_mentioned_variables(acc),
1209 NotJoin(ref n) => n.accumulate_mentioned_variables(acc),
1210 WhereFn(ref f) => f.accumulate_mentioned_variables(acc),
1211 TypeAnnotation(ref a) => a.accumulate_mentioned_variables(acc),
1212 RuleExpr(ref invocation) => {
1213 for arg in &invocation.args {
1214 if let FnArg::Variable(ref var) = arg {
1215 acc.insert(var.clone());
1216 }
1217 }
1218 }
1219 }
1220 }
1221}
1222
1223impl ContainsVariables for OrWhereClause {
1224 fn accumulate_mentioned_variables(&self, acc: &mut BTreeSet<Variable>) {
1225 use self::OrWhereClause::*;
1226 match self {
1227 And(ref clauses) => {
1228 for clause in clauses {
1229 clause.accumulate_mentioned_variables(acc)
1230 }
1231 }
1232 Clause(ref clause) => clause.accumulate_mentioned_variables(acc),
1233 }
1234 }
1235}
1236
1237impl ContainsVariables for OrJoin {
1238 fn accumulate_mentioned_variables(&self, acc: &mut BTreeSet<Variable>) {
1239 for clause in &self.clauses {
1240 clause.accumulate_mentioned_variables(acc);
1241 }
1242 }
1243}
1244
1245impl OrJoin {
1246 pub fn dismember(self) -> (Vec<OrWhereClause>, UnifyVars, BTreeSet<Variable>) {
1247 let vars = match self.mentioned_vars {
1248 Some(m) => m,
1249 None => self.collect_mentioned_variables(),
1250 };
1251 (self.clauses, self.unify_vars, vars)
1252 }
1253
1254 pub fn mentioned_variables(&mut self) -> &BTreeSet<Variable> {
1255 if self.mentioned_vars.is_none() {
1256 let m = self.collect_mentioned_variables();
1257 self.mentioned_vars = Some(m);
1258 }
1259
1260 if let Some(ref mentioned) = self.mentioned_vars {
1261 mentioned
1262 } else {
1263 unreachable!()
1264 }
1265 }
1266}
1267
1268impl ContainsVariables for NotJoin {
1269 fn accumulate_mentioned_variables(&self, acc: &mut BTreeSet<Variable>) {
1270 for clause in &self.clauses {
1271 clause.accumulate_mentioned_variables(acc);
1272 }
1273 }
1274}
1275
1276impl ContainsVariables for Predicate {
1277 fn accumulate_mentioned_variables(&self, acc: &mut BTreeSet<Variable>) {
1278 for arg in &self.args {
1279 if let FnArg::Variable(ref v) = *arg {
1280 acc_ref(acc, v)
1281 }
1282 }
1283 }
1284}
1285
1286impl ContainsVariables for TypeAnnotation {
1287 fn accumulate_mentioned_variables(&self, acc: &mut BTreeSet<Variable>) {
1288 acc_ref(acc, &self.variable);
1289 }
1290}
1291
1292impl ContainsVariables for Binding {
1293 fn accumulate_mentioned_variables(&self, acc: &mut BTreeSet<Variable>) {
1294 match self {
1295 Binding::BindScalar(ref v) | &Binding::BindColl(ref v) => acc_ref(acc, v),
1296 Binding::BindRel(ref vs) | &Binding::BindTuple(ref vs) => {
1297 for v in vs {
1298 if let VariableOrPlaceholder::Variable(ref v) = *v {
1299 acc_ref(acc, v);
1300 }
1301 }
1302 }
1303 }
1304 }
1305}
1306
1307impl ContainsVariables for WhereFn {
1308 fn accumulate_mentioned_variables(&self, acc: &mut BTreeSet<Variable>) {
1309 for arg in &self.args {
1310 if let FnArg::Variable(ref v) = *arg {
1311 acc_ref(acc, v)
1312 }
1313 }
1314 self.binding.accumulate_mentioned_variables(acc);
1315 }
1316}
1317
1318fn acc_ref<T: Clone + Ord>(acc: &mut BTreeSet<T>, v: &T) {
1319 if !acc.contains(v) {
1321 acc.insert(v.clone());
1322 }
1323}
1324
1325impl ContainsVariables for Pattern {
1326 fn accumulate_mentioned_variables(&self, acc: &mut BTreeSet<Variable>) {
1327 if let PatternNonValuePlace::Variable(ref v) = self.entity {
1328 acc_ref(acc, v)
1329 }
1330 if let PatternNonValuePlace::Variable(ref v) = self.attribute {
1331 acc_ref(acc, v)
1332 }
1333 if let PatternValuePlace::Variable(ref v) = self.value {
1334 acc_ref(acc, v)
1335 }
1336 if let PatternNonValuePlace::Variable(ref v) = self.tx {
1337 acc_ref(acc, v)
1338 }
1339 if let PatternNonValuePlace::Variable(ref v) = self.added {
1340 acc_ref(acc, v)
1341 }
1342 }
1343}