1use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5use crate::types::*;
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
9#[serde(tag = "op")]
10pub enum LogicalOp {
11 NodeScan {
13 label: Label,
14 as_: String,
15 #[serde(skip_serializing_if = "Option::is_none")]
16 props: Option<Properties>,
17 },
18
19 IndexScan {
21 label: Label,
22 as_: String,
23 index: String,
24 value: Value,
25 },
26
27 Filter {
29 pred: Predicate,
30 input: Box<LogicalOp>,
31 },
32
33 Expand {
35 edge: EdgePattern,
36 to_as: String,
37 from: Box<LogicalOp>,
38 },
39
40 Join {
42 left: Box<LogicalOp>,
43 right: Box<LogicalOp>,
44 on: Vec<String>, },
46
47 Project {
49 cols: Vec<String>,
50 input: Box<LogicalOp>,
51 },
52
53 Group {
55 keys: Vec<String>,
56 aggregations: Vec<Aggregation>,
57 input: Box<LogicalOp>,
58 },
59
60 Sort {
62 keys: Vec<SortKey>,
63 input: Box<LogicalOp>,
64 },
65
66 Limit {
68 count: usize,
69 input: Box<LogicalOp>,
70 },
71
72 Distinct {
74 input: Box<LogicalOp>,
75 },
76}
77
78#[derive(Debug, Clone, Serialize, Deserialize)]
80pub struct EdgePattern {
81 pub label: Label,
82 pub dir: Direction,
83 #[serde(skip_serializing_if = "Option::is_none")]
84 pub props: Option<Properties>,
85}
86
87#[derive(Debug, Clone, Serialize, Deserialize)]
89pub enum Direction {
90 #[serde(rename = "out")]
91 Out,
92 #[serde(rename = "in")]
93 In,
94 #[serde(rename = "both")]
95 Both,
96}
97
98#[derive(Debug, Clone, Serialize, Deserialize)]
100#[serde(untagged)]
101pub enum Predicate {
102 Eq { eq: [Expr; 2] },
103 Ne { ne: [Expr; 2] },
104 Lt { lt: [Expr; 2] },
105 Le { le: [Expr; 2] },
106 Gt { gt: [Expr; 2] },
107 Ge { ge: [Expr; 2] },
108 And { and: Vec<Predicate> },
109 Or { or: Vec<Predicate> },
110 Not { not: Box<Predicate> },
111}
112
113#[derive(Debug, Clone, Serialize, Deserialize)]
115#[serde(untagged)]
116pub enum Expr {
117 Var(String),
118 Const(Value),
119 Fn { fn_: String, args: Vec<Expr> },
120}
121
122impl std::fmt::Display for Expr {
123 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
124 match self {
125 Expr::Var(v) => write!(f, "{}", v),
126 Expr::Const(val) => write!(f, "{:?}", val),
127 Expr::Fn { fn_, args } => {
128 write!(f, "{}({})", fn_, args.len())
129 }
130 }
131 }
132}
133
134#[derive(Debug, Clone, Serialize, Deserialize)]
136pub struct Aggregation {
137 pub fn_: String,
138 pub args: Vec<String>,
139 pub as_: String,
140}
141
142#[derive(Debug, Clone, Serialize, Deserialize)]
144pub struct SortKey {
145 pub expr: Expr,
146 pub asc: bool,
147}
148
149#[derive(Debug, Clone, Serialize, Deserialize)]
151pub struct PlanIR {
152 pub plan: LogicalOp,
153 #[serde(skip_serializing_if = "Option::is_none")]
154 pub limit: Option<usize>,
155}
156
157#[derive(Debug, Clone)]
159pub struct Row {
160 pub values: HashMap<String, Value>,
161}
162
163pub type RowStream = Vec<Row>;