1use selene_core::DbString;
4
5use crate::ast::{
6 call::{InlineProcedureCall, ProcedureCall},
7 ddl::DdlStatement,
8 expr::{CharacterStringLiteralKind, ValueExpr},
9 mutation::MutationPipeline,
10 pattern::MatchClause,
11 span::SourceSpan,
12 types::GqlType,
13 util::NonEmpty,
14};
15
16#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
18#[non_exhaustive]
19pub enum Statement {
20 Query(QueryPipeline),
22 Composite {
24 first: QueryPipeline,
26 rest: NonEmpty<(SetOp, QueryPipeline)>,
29 span: SourceSpan,
31 },
32 Chained {
34 blocks: Vec<QueryPipeline>,
36 span: SourceSpan,
38 },
39 Mutate(MutationPipeline),
41 Ddl(DdlStatement),
43 Call(ProcedureCall),
45 Explain {
50 inner: Box<Statement>,
52 span: SourceSpan,
54 },
55 StartTransaction {
57 span: SourceSpan,
59 },
60 Commit {
62 span: SourceSpan,
64 },
65 Rollback {
67 span: SourceSpan,
69 },
70 SessionSetValue {
77 param: DbString,
79 declared_type: Option<GqlType>,
81 value: Box<ValueExpr>,
83 if_not_exists: bool,
85 span: SourceSpan,
87 },
88 SessionSetTimeZone {
90 zone: String,
92 zone_source_kind: CharacterStringLiteralKind,
94 span: SourceSpan,
96 },
97 SessionSetGraph {
99 target: SessionSetGraphTarget,
101 span: SourceSpan,
103 },
104 SessionReset {
106 target: SessionResetTarget,
108 span: SourceSpan,
110 },
111 SessionClose {
116 span: SourceSpan,
118 },
119}
120
121#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
123pub enum SessionSetGraphTarget {
124 CurrentGraph,
126 CurrentPropertyGraph,
128}
129
130#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
132#[non_exhaustive]
133pub enum SessionResetTarget {
134 AllCharacteristics,
137 Parameters,
140 TimeZone,
143 Parameter(DbString),
146}
147
148impl Statement {
149 #[must_use]
151 pub const fn span(&self) -> SourceSpan {
152 match self {
153 Self::Query(pipeline) => pipeline.span,
154 Self::Composite { span, .. } | Self::Chained { span, .. } => *span,
155 Self::Mutate(pipeline) => pipeline.span,
156 Self::Ddl(statement) => statement.span(),
157 Self::Call(call) => call.span,
158 Self::Explain { span, .. } => *span,
159 Self::StartTransaction { span } | Self::Commit { span } | Self::Rollback { span } => {
160 *span
161 }
162 Self::SessionSetValue { span, .. }
163 | Self::SessionSetTimeZone { span, .. }
164 | Self::SessionSetGraph { span, .. }
165 | Self::SessionReset { span, .. }
166 | Self::SessionClose { span } => *span,
167 }
168 }
169}
170
171#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, serde::Deserialize, serde::Serialize)]
173pub enum SetOp {
174 Union,
176 UnionAll,
178 Intersect,
180 IntersectAll,
182 Except,
184 ExceptAll,
186 Otherwise,
188}
189
190#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
192pub struct QueryPipeline {
193 pub statements: Vec<PipelineStatement>,
195 pub span: SourceSpan,
197}
198
199#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
201#[non_exhaustive]
202pub enum PipelineStatement {
203 Match(MatchClause),
205 Filter(ValueExpr),
207 Let(Vec<LetBinding>),
209 For(ForStatement),
211 Sorting(Vec<OrderTerm>),
213 Limit(LimitValue),
215 Offset(LimitValue),
217 Return(ReturnClause),
219 With(WithClause),
221 Call(ProcedureCall),
223 CallSubquery(InlineProcedureCall),
225}
226
227impl PipelineStatement {
228 #[must_use]
230 pub fn span(&self) -> SourceSpan {
231 match self {
232 Self::Match(value) => value.span,
233 Self::Filter(value) => value.span(),
234 Self::Let(values) => span_from_iter(values.iter().map(|value| value.span)),
235 Self::For(value) => value.span,
236 Self::Sorting(values) => span_from_iter(values.iter().map(|value| value.span)),
237 Self::Limit(value) | Self::Offset(value) => value.span(),
238 Self::Return(value) => value.span,
239 Self::With(value) => value.span,
240 Self::Call(value) => value.span,
241 Self::CallSubquery(value) => value.span,
242 }
243 }
244}
245
246#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
248pub struct LetBinding {
249 pub alias: DbString,
251 pub declared_type: Option<GqlType>,
253 pub value: ValueExpr,
255 pub span: SourceSpan,
257}
258
259#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
261pub struct ForStatement {
262 pub source: ValueExpr,
264 pub alias: DbString,
266 pub position: Option<RowExpansionPosition>,
268 pub span: SourceSpan,
270}
271
272#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
274pub struct RowExpansionPosition {
275 pub kind: RowExpansionPositionKind,
277 pub alias: DbString,
279}
280
281#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
283pub enum RowExpansionPositionKind {
284 Ordinality,
286 Offset,
288}
289
290#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
292pub struct OrderTerm {
293 pub expr: ValueExpr,
295 pub direction: OrderDirection,
297 pub nulls: Option<NullsPolicy>,
299 pub span: SourceSpan,
301}
302
303#[derive(
305 Clone, Copy, Debug, Default, Eq, Hash, PartialEq, serde::Deserialize, serde::Serialize,
306)]
307pub enum OrderDirection {
308 #[default]
310 Asc,
311 Desc,
313}
314
315#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, serde::Deserialize, serde::Serialize)]
317pub enum NullsPolicy {
318 NullsFirst,
320 NullsLast,
322}
323
324#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
326#[non_exhaustive]
327pub enum LimitValue {
328 Count(u64, SourceSpan),
330 Parameter {
332 name: DbString,
334 declared_type: Option<GqlType>,
336 span: SourceSpan,
338 },
339}
340
341impl LimitValue {
342 #[must_use]
344 pub const fn span(&self) -> SourceSpan {
345 match self {
346 Self::Count(_, span) | Self::Parameter { span, .. } => *span,
347 }
348 }
349}
350
351#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
353pub struct ReturnClause {
354 pub distinct: bool,
356 pub star: bool,
358 pub items: Vec<ReturnItem>,
360 pub group_by: Option<Vec<ValueExpr>>,
362 pub having: Option<ValueExpr>,
364 pub span: SourceSpan,
366}
367
368#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
370pub struct ReturnItem {
371 pub expr: ValueExpr,
373 pub alias: Option<DbString>,
375 pub span: SourceSpan,
377}
378
379#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
381pub struct WithClause {
382 pub distinct: bool,
384 pub items: Vec<ReturnItem>,
386 pub group_by: Option<Vec<ValueExpr>>,
388 pub having: Option<ValueExpr>,
390 pub where_clause: Option<ValueExpr>,
392 pub span: SourceSpan,
394}
395
396#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
398pub struct TypedBinding {
399 pub name: DbString,
401 pub ty: GqlType,
403 pub span: SourceSpan,
405}
406
407fn span_from_iter(mut spans: impl Iterator<Item = SourceSpan>) -> SourceSpan {
408 let Some(first) = spans.next() else {
409 return SourceSpan::default();
410 };
411 spans.fold(first, SourceSpan::merge)
412}