Skip to main content

linkrs_query/binder/bound/
stmt_dql.rs

1use crate::binder::query_graph::QueryGraph;
2use crate::parser::ast::{LimitClause, SkipClause, Steps};
3
4use linkrs_core::types::EdgeDirection;
5
6use super::clause::{
7    BoundOrderByItem, BoundProjectionItem, BoundReturnClause, BoundWhereClause, BoundYieldClause,
8};
9use super::expr::{BoundAggregateCall, BoundExpression};
10use super::stmt::BoundStatement;
11
12#[derive(Debug, Clone)]
13pub struct BoundMatchStatement {
14    pub query_graph: QueryGraph,
15    pub join_hint: Option<BoundJoinHint>,
16    pub where_clause: Option<BoundWhereClause>,
17    pub return_clause: Option<BoundReturnClause>,
18    pub order_by: Option<Vec<BoundOrderByItem>>,
19    pub limit: Option<LimitClause>,
20    pub skip: Option<SkipClause>,
21    pub optional: bool,
22    pub delete_clause: Option<BoundMatchDeleteClause>,
23}
24
25/// Bound `USING JOIN` hint: pattern variables pinned to a join shape.
26/// Resolution against the planning query graph happens in the planner;
27/// the binder only checks that every named variable is in scope.
28#[derive(Debug, Clone)]
29pub enum BoundJoinHint {
30    Binary { left: String, right: String },
31    Multiway { probe: String, builds: Vec<String> },
32}
33
34impl BoundJoinHint {
35    /// Variables referenced by the hint, in order.
36    pub fn variables(&self) -> Vec<&str> {
37        match self {
38            BoundJoinHint::Binary { left, right } => vec![left.as_str(), right.as_str()],
39            BoundJoinHint::Multiway { probe, builds } => {
40                let mut vars = Vec::with_capacity(builds.len() + 1);
41                vars.push(probe.as_str());
42                vars.extend(builds.iter().map(String::as_str));
43                vars
44            }
45        }
46    }
47}
48
49#[derive(Debug, Clone)]
50pub struct BoundGoStatement {
51    pub steps: Steps,
52    pub from: Vec<BoundExpression>,
53    pub over: Option<Vec<String>>,
54    pub direction: EdgeDirection,
55    pub where_clause: Option<BoundWhereClause>,
56    pub yield_clause: Option<BoundYieldClause>,
57}
58
59#[derive(Debug, Clone)]
60pub struct BoundLookupStatement {
61    pub target: BoundLookupTarget,
62    pub where_clause: Option<BoundWhereClause>,
63    pub yield_clause: Option<BoundYieldClause>,
64}
65
66#[derive(Debug, Clone)]
67pub enum BoundLookupTarget {
68    Tag(String),
69    Edge(String),
70}
71
72#[derive(Debug, Clone)]
73pub struct BoundFetchVerticesStatement {
74    pub tag_name: Option<String>,
75    pub ids: Vec<BoundExpression>,
76    pub properties: Option<Vec<String>>,
77}
78
79#[derive(Debug, Clone)]
80pub struct BoundFetchEdgesStatement {
81    pub src: BoundExpression,
82    pub dst: BoundExpression,
83    pub edge_type: String,
84    pub rank: Option<BoundExpression>,
85    pub properties: Option<Vec<String>>,
86}
87
88#[derive(Debug, Clone)]
89pub struct BoundFindPathStatement {
90    pub from: Vec<BoundExpression>,
91    pub to: BoundExpression,
92    pub over: Option<(Vec<String>, EdgeDirection)>,
93    pub where_clause: Option<BoundWhereClause>,
94    pub shortest: bool,
95    pub max_steps: Option<usize>,
96    pub limit: Option<LimitClause>,
97    pub skip: Option<SkipClause>,
98    pub yield_clause: Option<BoundYieldClause>,
99    /// WEIGHT clause: property name used as the edge weight (validated at
100    /// bind time to only appear on FIND SHORTEST PATH).
101    pub weight_expression: Option<String>,
102    /// `WITH LOOP`: self-loop edges may be taken as terminal extensions.
103    pub with_loop: bool,
104    /// `WITH TRAIL`: path edges may not repeat; vertices may.
105    pub with_trail: bool,
106    /// `WITH WALK`: path vertices may repeat.
107    pub with_walk: bool,
108}
109
110#[derive(Debug, Clone)]
111pub struct BoundSubgraphStatement {
112    pub steps: Steps,
113    pub from: Vec<BoundExpression>,
114    pub over: Option<(Vec<String>, EdgeDirection)>,
115    pub where_clause: Option<BoundWhereClause>,
116    pub yield_clause: Option<BoundYieldClause>,
117}
118
119#[derive(Debug, Clone)]
120pub struct BoundReturnStatement {
121    pub items: Vec<BoundProjectionItem>,
122    pub distinct: bool,
123    pub order_by: Option<Vec<BoundOrderByItem>>,
124    pub skip: Option<SkipClause>,
125    pub limit: Option<LimitClause>,
126}
127
128#[derive(Debug, Clone)]
129pub struct BoundWithStatement {
130    pub items: Vec<BoundProjectionItem>,
131    pub condition: Option<BoundExpression>,
132    pub ctes: Vec<BoundCteDef>,
133}
134
135/// A bound common table expression.
136///
137/// Under `WITH RECURSIVE`, `step` is the `UNION ALL` right branch bound with
138/// the CTE name visible as a scannable working table; otherwise `step` is
139/// `None` and the CTE is a plain inline view.
140#[derive(Debug, Clone)]
141pub struct BoundCteDef {
142    pub name: String,
143    pub anchor: Box<BoundStatement>,
144    pub step: Option<Box<BoundStatement>>,
145}
146
147#[derive(Debug, Clone)]
148pub struct BoundUnwindStatement {
149    pub expression: BoundExpression,
150    pub alias: String,
151}
152
153#[derive(Debug, Clone)]
154pub struct BoundPipeStatement {
155    pub statements: Vec<BoundStatement>,
156}
157
158#[derive(Debug, Clone)]
159pub struct BoundGroupByStatement {
160    pub keys: Vec<BoundExpression>,
161    pub aggregates: Vec<BoundAggregateCall>,
162}
163
164#[derive(Debug, Clone)]
165pub struct BoundSetOperationStatement {
166    pub left: Box<BoundStatement>,
167    pub right: Box<BoundStatement>,
168    pub operation: SetOperationKind,
169}
170
171#[derive(Debug, Clone, Copy, PartialEq, Eq)]
172pub enum SetOperationKind {
173    Union,
174    UnionAll,
175    Intersect,
176    Minus,
177}
178
179#[derive(Debug, Clone)]
180pub struct BoundFilter {
181    pub condition: BoundExpression,
182}
183
184#[derive(Debug, Clone)]
185pub struct BoundYield {
186    pub items: Vec<BoundProjectionItem>,
187    pub where_clause: Option<BoundExpression>,
188    pub distinct: bool,
189    pub order_by: Option<Vec<BoundOrderByItem>>,
190    pub skip: Option<SkipClause>,
191    pub limit: Option<LimitClause>,
192}
193
194#[derive(Debug, Clone)]
195pub struct BoundCollect {
196    pub items: Vec<BoundProjectionItem>,
197}
198
199#[derive(Debug, Clone)]
200pub struct BoundAssignVariable {
201    pub name: String,
202    pub expression: BoundExpression,
203}
204
205#[derive(Debug, Clone)]
206pub struct BoundMatchDeleteClause {
207    pub target: BoundMatchDeleteTarget,
208    pub with_edge: bool,
209}
210
211#[derive(Debug, Clone)]
212pub enum BoundMatchDeleteTarget {
213    Vertices(Vec<BoundExpression>),
214    Edges(Vec<BoundExpression>),
215    EdgeRefs(Vec<(BoundExpression, BoundExpression, Option<BoundExpression>)>),
216}