Skip to main content

reifydb_rql/expression/
mod.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2025 ReifyDB
3
4pub mod fragment;
5pub mod join;
6pub mod json;
7pub mod name;
8
9use crate::{
10	ast,
11	ast::{
12		ast::{Ast, AstFrom, AstInfix, AstLiteral, InfixOperator},
13		parse_str,
14	},
15	bump::{Bump, BumpBox},
16	convert_data_type,
17};
18
19pub fn parse_expression(rql: &str) -> Result<Vec<Expression>> {
20	let bump = Bump::new();
21	let statements = parse_str(&bump, rql)?;
22	if statements.is_empty() {
23		return Ok(vec![]);
24	}
25
26	let mut result = Vec::new();
27	for statement in statements {
28		for ast in statement.nodes {
29			result.push(ExpressionCompiler::compile(ast)?);
30		}
31	}
32
33	Ok(result)
34}
35
36use std::{
37	fmt,
38	fmt::{Display, Formatter},
39	str::FromStr,
40	sync::Arc,
41};
42
43use ast::ast::AstMatchArm;
44use reifydb_core::interface::identifier::{ColumnIdentifier, ColumnShape};
45use reifydb_type::{
46	err,
47	error::Diagnostic,
48	fragment::Fragment,
49	value::{row_number::ROW_NUMBER_COLUMN_NAME, r#type::Type},
50};
51use serde::{Deserialize, Serialize};
52
53use crate::{Result, ast::ast::AstBlock, diagnostic::AstError};
54
55#[derive(Debug, Clone, Serialize, Deserialize)]
56pub struct AliasExpression {
57	pub alias: IdentExpression,
58	pub expression: Box<Expression>,
59	pub fragment: Fragment,
60}
61
62impl Display for AliasExpression {
63	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
64		Display::fmt(&self.alias, f)
65	}
66}
67
68#[derive(Debug, Clone, Serialize, Deserialize)]
69pub enum Expression {
70	AccessSource(AccessShapeExpression),
71
72	Alias(AliasExpression),
73
74	Cast(CastExpression),
75
76	Constant(ConstantExpression),
77
78	Column(ColumnExpression),
79
80	Add(AddExpression),
81
82	Div(DivExpression),
83
84	Call(CallExpression),
85
86	Rem(RemExpression),
87
88	Mul(MulExpression),
89
90	Sub(SubExpression),
91
92	Tuple(TupleExpression),
93
94	List(ListExpression),
95
96	Prefix(PrefixExpression),
97
98	GreaterThan(GreaterThanExpression),
99
100	GreaterThanEqual(GreaterThanEqExpression),
101
102	LessThan(LessThanExpression),
103
104	LessThanEqual(LessThanEqExpression),
105
106	Equal(EqExpression),
107
108	NotEqual(NotEqExpression),
109
110	Between(BetweenExpression),
111
112	And(AndExpression),
113
114	Or(OrExpression),
115
116	Xor(XorExpression),
117
118	In(InExpression),
119
120	Contains(ContainsExpression),
121
122	Type(TypeExpression),
123
124	Parameter(ParameterExpression),
125	Variable(VariableExpression),
126
127	If(IfExpression),
128	Map(MapExpression),
129	Extend(ExtendExpression),
130	SumTypeConstructor(SumTypeConstructorExpression),
131	IsVariant(IsVariantExpression),
132	FieldAccess(FieldAccessExpression),
133}
134
135#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
136pub struct AccessShapeExpression {
137	pub column: ColumnIdentifier,
138}
139
140impl AccessShapeExpression {
141	pub fn full_fragment_owned(&self) -> Fragment {
142		// For backward compatibility, merge shape and column fragments
143		match &self.column.shape {
144			ColumnShape::Qualified {
145				name,
146				..
147			} => Fragment::merge_all([name.clone(), self.column.name.clone()]),
148			ColumnShape::Alias(alias) => Fragment::merge_all([alias.clone(), self.column.name.clone()]),
149		}
150	}
151}
152
153#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
154pub enum ConstantExpression {
155	None {
156		fragment: Fragment,
157	},
158	Bool {
159		fragment: Fragment,
160	},
161	// any number
162	Number {
163		fragment: Fragment,
164	},
165	// any textual representation can be String, Text, ...
166	Text {
167		fragment: Fragment,
168	},
169	// any temporal representation can be Date, Time, DateTime, ...
170	Temporal {
171		fragment: Fragment,
172	},
173}
174
175impl Display for ConstantExpression {
176	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
177		match self {
178			ConstantExpression::None {
179				..
180			} => write!(f, "none"),
181			ConstantExpression::Bool {
182				fragment,
183			} => write!(f, "{}", fragment.text()),
184			ConstantExpression::Number {
185				fragment,
186			} => write!(f, "{}", fragment.text()),
187			ConstantExpression::Text {
188				fragment,
189			} => write!(f, "\"{}\"", fragment.text()),
190			ConstantExpression::Temporal {
191				fragment,
192			} => write!(f, "{}", fragment.text()),
193		}
194	}
195}
196
197impl ConstantExpression {
198	pub fn infer_type(&self) -> Type {
199		match self {
200			ConstantExpression::None {
201				..
202			} => Type::Any,
203			ConstantExpression::Bool {
204				..
205			} => Type::Boolean,
206			ConstantExpression::Number {
207				..
208			} => Type::Int4,
209			ConstantExpression::Text {
210				..
211			} => Type::Utf8,
212			ConstantExpression::Temporal {
213				..
214			} => Type::DateTime,
215		}
216	}
217}
218
219impl Expression {
220	pub fn infer_type(&self) -> Option<Type> {
221		match self {
222			Expression::Constant(c) => Some(c.infer_type()),
223			_ => None,
224		}
225	}
226}
227
228#[derive(Debug, Clone, Serialize, Deserialize)]
229pub struct CastExpression {
230	pub fragment: Fragment,
231	pub expression: Box<Expression>,
232	pub to: TypeExpression,
233}
234
235impl CastExpression {
236	pub fn full_fragment_owned(&self) -> Fragment {
237		Fragment::merge_all([
238			self.fragment.clone(),
239			self.expression.full_fragment_owned(),
240			self.to.full_fragment_owned(),
241		])
242	}
243
244	pub fn lazy_fragment(&self) -> impl Fn() -> Fragment {
245		move || self.full_fragment_owned()
246	}
247}
248
249#[derive(Debug, Clone, Serialize, Deserialize)]
250pub struct TypeExpression {
251	pub fragment: Fragment,
252	pub ty: Type,
253}
254
255impl TypeExpression {
256	pub fn full_fragment_owned(&self) -> Fragment {
257		self.fragment.clone()
258	}
259
260	pub fn lazy_fragment(&self) -> impl Fn() -> Fragment {
261		move || self.full_fragment_owned()
262	}
263}
264
265#[derive(Debug, Clone, Serialize, Deserialize)]
266pub struct AddExpression {
267	pub left: Box<Expression>,
268	pub right: Box<Expression>,
269	pub fragment: Fragment,
270}
271
272#[derive(Debug, Clone, Serialize, Deserialize)]
273pub struct DivExpression {
274	pub left: Box<Expression>,
275	pub right: Box<Expression>,
276	pub fragment: Fragment,
277}
278
279#[derive(Debug, Clone, Serialize, Deserialize)]
280pub struct SubExpression {
281	pub left: Box<Expression>,
282	pub right: Box<Expression>,
283	pub fragment: Fragment,
284}
285
286#[derive(Debug, Clone, Serialize, Deserialize)]
287pub struct RemExpression {
288	pub left: Box<Expression>,
289	pub right: Box<Expression>,
290	pub fragment: Fragment,
291}
292
293#[derive(Debug, Clone, Serialize, Deserialize)]
294pub struct MulExpression {
295	pub left: Box<Expression>,
296	pub right: Box<Expression>,
297	pub fragment: Fragment,
298}
299
300#[derive(Debug, Clone, Serialize, Deserialize)]
301pub struct GreaterThanExpression {
302	pub left: Box<Expression>,
303	pub right: Box<Expression>,
304	pub fragment: Fragment,
305}
306
307impl GreaterThanExpression {
308	pub fn full_fragment_owned(&self) -> Fragment {
309		Fragment::merge_all([
310			self.left.full_fragment_owned(),
311			self.fragment.clone(),
312			self.right.full_fragment_owned(),
313		])
314	}
315}
316
317#[derive(Debug, Clone, Serialize, Deserialize)]
318pub struct GreaterThanEqExpression {
319	pub left: Box<Expression>,
320	pub right: Box<Expression>,
321	pub fragment: Fragment,
322}
323
324impl GreaterThanEqExpression {
325	pub fn full_fragment_owned(&self) -> Fragment {
326		Fragment::merge_all([
327			self.left.full_fragment_owned(),
328			self.fragment.clone(),
329			self.right.full_fragment_owned(),
330		])
331	}
332}
333
334#[derive(Debug, Clone, Serialize, Deserialize)]
335pub struct LessThanExpression {
336	pub left: Box<Expression>,
337	pub right: Box<Expression>,
338	pub fragment: Fragment,
339}
340
341impl LessThanExpression {
342	pub fn full_fragment_owned(&self) -> Fragment {
343		Fragment::merge_all([
344			self.left.full_fragment_owned(),
345			self.fragment.clone(),
346			self.right.full_fragment_owned(),
347		])
348	}
349}
350
351#[derive(Debug, Clone, Serialize, Deserialize)]
352pub struct LessThanEqExpression {
353	pub left: Box<Expression>,
354	pub right: Box<Expression>,
355	pub fragment: Fragment,
356}
357
358impl LessThanEqExpression {
359	pub fn full_fragment_owned(&self) -> Fragment {
360		Fragment::merge_all([
361			self.left.full_fragment_owned(),
362			self.fragment.clone(),
363			self.right.full_fragment_owned(),
364		])
365	}
366}
367
368#[derive(Debug, Clone, Serialize, Deserialize)]
369pub struct EqExpression {
370	pub left: Box<Expression>,
371	pub right: Box<Expression>,
372	pub fragment: Fragment,
373}
374
375impl EqExpression {
376	pub fn full_fragment_owned(&self) -> Fragment {
377		Fragment::merge_all([
378			self.left.full_fragment_owned(),
379			self.fragment.clone(),
380			self.right.full_fragment_owned(),
381		])
382	}
383}
384
385#[derive(Debug, Clone, Serialize, Deserialize)]
386pub struct NotEqExpression {
387	pub left: Box<Expression>,
388	pub right: Box<Expression>,
389	pub fragment: Fragment,
390}
391
392impl NotEqExpression {
393	pub fn full_fragment_owned(&self) -> Fragment {
394		Fragment::merge_all([
395			self.left.full_fragment_owned(),
396			self.fragment.clone(),
397			self.right.full_fragment_owned(),
398		])
399	}
400}
401
402#[derive(Debug, Clone, Serialize, Deserialize)]
403pub struct BetweenExpression {
404	pub value: Box<Expression>,
405	pub lower: Box<Expression>,
406	pub upper: Box<Expression>,
407	pub fragment: Fragment,
408}
409
410impl BetweenExpression {
411	pub fn full_fragment_owned(&self) -> Fragment {
412		Fragment::merge_all([
413			self.value.full_fragment_owned(),
414			self.fragment.clone(),
415			self.lower.full_fragment_owned(),
416			self.upper.full_fragment_owned(),
417		])
418	}
419}
420
421#[derive(Debug, Clone, Serialize, Deserialize)]
422pub struct AndExpression {
423	pub left: Box<Expression>,
424	pub right: Box<Expression>,
425	pub fragment: Fragment,
426}
427
428impl AndExpression {
429	pub fn full_fragment_owned(&self) -> Fragment {
430		Fragment::merge_all([
431			self.left.full_fragment_owned(),
432			self.fragment.clone(),
433			self.right.full_fragment_owned(),
434		])
435	}
436}
437
438#[derive(Debug, Clone, Serialize, Deserialize)]
439pub struct OrExpression {
440	pub left: Box<Expression>,
441	pub right: Box<Expression>,
442	pub fragment: Fragment,
443}
444
445impl OrExpression {
446	pub fn full_fragment_owned(&self) -> Fragment {
447		Fragment::merge_all([
448			self.left.full_fragment_owned(),
449			self.fragment.clone(),
450			self.right.full_fragment_owned(),
451		])
452	}
453}
454
455#[derive(Debug, Clone, Serialize, Deserialize)]
456pub struct XorExpression {
457	pub left: Box<Expression>,
458	pub right: Box<Expression>,
459	pub fragment: Fragment,
460}
461
462impl XorExpression {
463	pub fn full_fragment_owned(&self) -> Fragment {
464		Fragment::merge_all([
465			self.left.full_fragment_owned(),
466			self.fragment.clone(),
467			self.right.full_fragment_owned(),
468		])
469	}
470}
471
472#[derive(Debug, Clone, Serialize, Deserialize)]
473pub struct InExpression {
474	pub value: Box<Expression>,
475	pub list: Box<Expression>,
476	pub negated: bool,
477	pub fragment: Fragment,
478}
479
480impl InExpression {
481	pub fn full_fragment_owned(&self) -> Fragment {
482		Fragment::merge_all([
483			self.value.full_fragment_owned(),
484			self.fragment.clone(),
485			self.list.full_fragment_owned(),
486		])
487	}
488}
489
490#[derive(Debug, Clone, Serialize, Deserialize)]
491pub struct ContainsExpression {
492	pub value: Box<Expression>,
493	pub list: Box<Expression>,
494	pub fragment: Fragment,
495}
496
497impl ContainsExpression {
498	pub fn full_fragment_owned(&self) -> Fragment {
499		Fragment::merge_all([
500			self.value.full_fragment_owned(),
501			self.fragment.clone(),
502			self.list.full_fragment_owned(),
503		])
504	}
505}
506
507#[derive(Debug, Clone, Serialize, Deserialize)]
508pub struct ColumnExpression(pub ColumnIdentifier);
509
510impl ColumnExpression {
511	pub fn full_fragment_owned(&self) -> Fragment {
512		// Return just the column name for unqualified column references
513		self.0.name.clone()
514	}
515
516	pub fn column(&self) -> &ColumnIdentifier {
517		&self.0
518	}
519}
520
521impl Display for Expression {
522	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
523		match self {
524			Expression::AccessSource(AccessShapeExpression {
525				column,
526			}) => match &column.shape {
527				ColumnShape::Qualified {
528					name,
529					..
530				} => {
531					write!(f, "{}.{}", name.text(), column.name.text())
532				}
533				ColumnShape::Alias(alias) => {
534					write!(f, "{}.{}", alias.text(), column.name.text())
535				}
536			},
537			Expression::Alias(AliasExpression {
538				alias,
539				expression,
540				..
541			}) => {
542				write!(f, "{} as {}", expression, alias)
543			}
544			Expression::Cast(CastExpression {
545				expression: expr,
546				..
547			}) => write!(f, "{}", expr),
548			Expression::Constant(fragment) => {
549				write!(f, "Constant({})", fragment)
550			}
551			Expression::Column(ColumnExpression(column)) => {
552				write!(f, "{}", column.name.text())
553			}
554			Expression::Add(AddExpression {
555				left,
556				right,
557				..
558			}) => {
559				write!(f, "({} + {})", left, right)
560			}
561			Expression::Div(DivExpression {
562				left,
563				right,
564				..
565			}) => {
566				write!(f, "({} / {})", left, right)
567			}
568			Expression::Call(call) => write!(f, "{}", call),
569			Expression::Rem(RemExpression {
570				left,
571				right,
572				..
573			}) => {
574				write!(f, "({} % {})", left, right)
575			}
576			Expression::Mul(MulExpression {
577				left,
578				right,
579				..
580			}) => {
581				write!(f, "({} * {})", left, right)
582			}
583			Expression::Sub(SubExpression {
584				left,
585				right,
586				..
587			}) => {
588				write!(f, "({} - {})", left, right)
589			}
590			Expression::Tuple(tuple) => write!(f, "({})", tuple),
591			Expression::List(list) => write!(f, "{}", list),
592			Expression::Prefix(prefix) => write!(f, "{}", prefix),
593			Expression::GreaterThan(GreaterThanExpression {
594				left,
595				right,
596				..
597			}) => {
598				write!(f, "({} > {})", left, right)
599			}
600			Expression::GreaterThanEqual(GreaterThanEqExpression {
601				left,
602				right,
603				..
604			}) => {
605				write!(f, "({} >= {})", left, right)
606			}
607			Expression::LessThan(LessThanExpression {
608				left,
609				right,
610				..
611			}) => {
612				write!(f, "({} < {})", left, right)
613			}
614			Expression::LessThanEqual(LessThanEqExpression {
615				left,
616				right,
617				..
618			}) => {
619				write!(f, "({} <= {})", left, right)
620			}
621			Expression::Equal(EqExpression {
622				left,
623				right,
624				..
625			}) => {
626				write!(f, "({} == {})", left, right)
627			}
628			Expression::NotEqual(NotEqExpression {
629				left,
630				right,
631				..
632			}) => {
633				write!(f, "({} != {})", left, right)
634			}
635			Expression::Between(BetweenExpression {
636				value,
637				lower,
638				upper,
639				..
640			}) => {
641				write!(f, "({} BETWEEN {} AND {})", value, lower, upper)
642			}
643			Expression::And(AndExpression {
644				left,
645				right,
646				..
647			}) => {
648				write!(f, "({} and {})", left, right)
649			}
650			Expression::Or(OrExpression {
651				left,
652				right,
653				..
654			}) => {
655				write!(f, "({} or {})", left, right)
656			}
657			Expression::Xor(XorExpression {
658				left,
659				right,
660				..
661			}) => {
662				write!(f, "({} xor {})", left, right)
663			}
664			Expression::In(InExpression {
665				value,
666				list,
667				negated,
668				..
669			}) => {
670				if *negated {
671					write!(f, "({} NOT IN {})", value, list)
672				} else {
673					write!(f, "({} IN {})", value, list)
674				}
675			}
676			Expression::Contains(ContainsExpression {
677				value,
678				list,
679				..
680			}) => {
681				write!(f, "({} CONTAINS {})", value, list)
682			}
683			Expression::Type(TypeExpression {
684				fragment,
685				..
686			}) => write!(f, "{}", fragment.text()),
687			Expression::Parameter(param) => match param {
688				ParameterExpression::Positional {
689					fragment,
690					..
691				} => write!(f, "{}", fragment.text()),
692				ParameterExpression::Named {
693					fragment,
694				} => write!(f, "{}", fragment.text()),
695			},
696			Expression::Variable(var) => write!(f, "{}", var.fragment.text()),
697			Expression::If(if_expr) => write!(f, "{}", if_expr),
698			Expression::Map(map_expr) => write!(
699				f,
700				"MAP{{ {} }}",
701				map_expr.expressions
702					.iter()
703					.map(|expr| format!("{}", expr))
704					.collect::<Vec<_>>()
705					.join(", ")
706			),
707			Expression::Extend(extend_expr) => write!(
708				f,
709				"EXTEND{{ {} }}",
710				extend_expr
711					.expressions
712					.iter()
713					.map(|expr| format!("{}", expr))
714					.collect::<Vec<_>>()
715					.join(", ")
716			),
717			Expression::SumTypeConstructor(ctor) => write!(
718				f,
719				"{}::{}{{ {} }}",
720				ctor.sumtype_name.text(),
721				ctor.variant_name.text(),
722				ctor.columns
723					.iter()
724					.map(|(name, expr)| format!("{}: {}", name.text(), expr))
725					.collect::<Vec<_>>()
726					.join(", ")
727			),
728			Expression::IsVariant(e) => write!(f, "({} IS {})", e.expression, e.variant_name.text()),
729			Expression::FieldAccess(field_access) => write!(f, "{}", field_access),
730		}
731	}
732}
733
734#[derive(Debug, Clone, Serialize, Deserialize)]
735pub struct CallExpression {
736	pub func: IdentExpression,
737	pub args: Vec<Expression>,
738	pub fragment: Fragment,
739}
740
741impl CallExpression {
742	pub fn full_fragment_owned(&self) -> Fragment {
743		Fragment::Statement {
744			column: self.func.0.column(),
745			line: self.func.0.line(),
746			text: Arc::from(format!(
747				"{}({})",
748				self.func.0.text(),
749				self.args
750					.iter()
751					.map(|arg| arg.full_fragment_owned().text().to_string())
752					.collect::<Vec<_>>()
753					.join(",")
754			)),
755		}
756	}
757}
758
759impl Display for CallExpression {
760	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
761		let args = self.args.iter().map(|arg| format!("{}", arg)).collect::<Vec<_>>().join(", ");
762		write!(f, "{}({})", self.func, args)
763	}
764}
765
766#[derive(Debug, Clone, Serialize, Deserialize)]
767pub struct IdentExpression(pub Fragment);
768
769#[derive(Debug, Clone, Serialize, Deserialize)]
770pub enum ParameterExpression {
771	Positional {
772		fragment: Fragment,
773	},
774	Named {
775		fragment: Fragment,
776	},
777}
778
779impl ParameterExpression {
780	pub fn position(&self) -> Option<u32> {
781		match self {
782			ParameterExpression::Positional {
783				fragment,
784			} => fragment.text()[1..].parse().ok(),
785			ParameterExpression::Named {
786				..
787			} => None,
788		}
789	}
790
791	pub fn name(&self) -> Option<&str> {
792		match self {
793			ParameterExpression::Named {
794				fragment,
795			} => Some(&fragment.text()[1..]),
796			ParameterExpression::Positional {
797				..
798			} => None,
799		}
800	}
801}
802
803#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
804pub struct VariableExpression {
805	pub fragment: Fragment,
806}
807
808impl VariableExpression {
809	pub fn name(&self) -> &str {
810		// Extract variable name from token value (skip the '$')
811		let text = self.fragment.text();
812		text.strip_prefix('$').unwrap_or(text)
813	}
814}
815
816#[derive(Debug, Clone, Serialize, Deserialize)]
817pub struct IfExpression {
818	pub condition: Box<Expression>,
819	pub then_expr: Box<Expression>,
820	pub else_ifs: Vec<ElseIfExpression>,
821	pub else_expr: Option<Box<Expression>>,
822	pub fragment: Fragment,
823}
824
825#[derive(Debug, Clone, Serialize, Deserialize)]
826pub struct ElseIfExpression {
827	pub condition: Box<Expression>,
828	pub then_expr: Box<Expression>,
829	pub fragment: Fragment,
830}
831
832impl IfExpression {
833	pub fn full_fragment_owned(&self) -> Fragment {
834		self.fragment.clone()
835	}
836
837	pub fn lazy_fragment(&self) -> impl Fn() -> Fragment {
838		move || self.full_fragment_owned()
839	}
840}
841
842impl Display for IfExpression {
843	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
844		write!(f, "if {} {{ {} }}", self.condition, self.then_expr)?;
845
846		for else_if in &self.else_ifs {
847			write!(f, " else if {} {{ {} }}", else_if.condition, else_if.then_expr)?;
848		}
849
850		if let Some(else_expr) = &self.else_expr {
851			write!(f, " else {{ {} }}", else_expr)?;
852		}
853
854		Ok(())
855	}
856}
857
858impl IdentExpression {
859	pub fn name(&self) -> &str {
860		self.0.text()
861	}
862}
863
864impl Display for IdentExpression {
865	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
866		write!(f, "{}", self.0.text())
867	}
868}
869
870#[derive(Debug, Clone, Serialize, Deserialize)]
871pub enum PrefixOperator {
872	Minus(Fragment),
873	Plus(Fragment),
874	Not(Fragment),
875}
876
877impl PrefixOperator {
878	pub fn full_fragment_owned(&self) -> Fragment {
879		match self {
880			PrefixOperator::Minus(fragment) => fragment.clone(),
881			PrefixOperator::Plus(fragment) => fragment.clone(),
882			PrefixOperator::Not(fragment) => fragment.clone(),
883		}
884	}
885}
886
887impl Display for PrefixOperator {
888	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
889		match self {
890			PrefixOperator::Minus(_) => write!(f, "-"),
891			PrefixOperator::Plus(_) => write!(f, "+"),
892			PrefixOperator::Not(_) => write!(f, "not"),
893		}
894	}
895}
896
897#[derive(Debug, Clone, Serialize, Deserialize)]
898pub struct PrefixExpression {
899	pub operator: PrefixOperator,
900	pub expression: Box<Expression>,
901	pub fragment: Fragment,
902}
903
904impl PrefixExpression {
905	pub fn full_fragment_owned(&self) -> Fragment {
906		Fragment::merge_all([self.operator.full_fragment_owned(), self.expression.full_fragment_owned()])
907	}
908}
909
910impl Display for PrefixExpression {
911	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
912		write!(f, "({}{})", self.operator, self.expression)
913	}
914}
915
916#[derive(Debug, Clone, Serialize, Deserialize)]
917pub struct TupleExpression {
918	pub expressions: Vec<Expression>,
919	pub fragment: Fragment,
920}
921
922impl Display for TupleExpression {
923	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
924		let items = self.expressions.iter().map(|e| format!("{}", e)).collect::<Vec<_>>().join(", ");
925		write!(f, "({})", items)
926	}
927}
928
929#[derive(Debug, Clone, Serialize, Deserialize)]
930pub struct ListExpression {
931	pub expressions: Vec<Expression>,
932	pub fragment: Fragment,
933}
934
935impl Display for ListExpression {
936	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
937		let items = self.expressions.iter().map(|e| format!("{}", e)).collect::<Vec<_>>().join(", ");
938		write!(f, "[{}]", items)
939	}
940}
941
942pub struct ExpressionCompiler {}
943
944impl ExpressionCompiler {
945	pub fn compile(ast: Ast<'_>) -> Result<Expression> {
946		match ast {
947			Ast::Literal(literal) => match literal {
948				AstLiteral::Boolean(_) => Ok(Expression::Constant(ConstantExpression::Bool {
949					fragment: literal.fragment().to_owned(),
950				})),
951				AstLiteral::Number(_) => Ok(Expression::Constant(ConstantExpression::Number {
952					fragment: literal.fragment().to_owned(),
953				})),
954				AstLiteral::Temporal(_) => Ok(Expression::Constant(ConstantExpression::Temporal {
955					fragment: literal.fragment().to_owned(),
956				})),
957				AstLiteral::Text(_) => Ok(Expression::Constant(ConstantExpression::Text {
958					fragment: literal.fragment().to_owned(),
959				})),
960				AstLiteral::None(_) => Ok(Expression::Constant(ConstantExpression::None {
961					fragment: literal.fragment().to_owned(),
962				})),
963			},
964			Ast::Identifier(identifier) => {
965				// Create an unqualified column identifier
966
967				let column = ColumnIdentifier {
968					shape: ColumnShape::Qualified {
969						namespace: Fragment::Internal {
970							text: Arc::from("_context"),
971						},
972						name: Fragment::Internal {
973							text: Arc::from("_context"),
974						},
975					},
976					name: identifier.token.fragment.to_owned(),
977				};
978				Ok(Expression::Column(ColumnExpression(column)))
979			}
980			Ast::CallFunction(call) => {
981				// Build the full function name from namespace + function
982				let full_name = if call.function.namespaces.is_empty() {
983					call.function.name.text().to_string()
984				} else {
985					let namespace_path = call
986						.function
987						.namespaces
988						.iter()
989						.map(|ns| ns.text())
990						.collect::<Vec<_>>()
991						.join("::");
992					format!("{}::{}", namespace_path, call.function.name.text())
993				};
994
995				// Compile arguments
996				let mut arg_expressions = Vec::new();
997				for arg_ast in call.arguments.nodes {
998					let compiled = Self::compile(arg_ast)?;
999					let compiled = match &compiled {
1000						Expression::Column(col_expr) => {
1001							if let Ok(ty) = Type::from_str(col_expr.0.name.text()) {
1002								Expression::Type(TypeExpression {
1003									fragment: col_expr.0.name.clone(),
1004									ty,
1005								})
1006							} else {
1007								compiled
1008							}
1009						}
1010						_ => compiled,
1011					};
1012					arg_expressions.push(compiled);
1013				}
1014
1015				Ok(Expression::Call(CallExpression {
1016					func: IdentExpression(Fragment::testing(&full_name)),
1017					args: arg_expressions,
1018					fragment: call.token.fragment.to_owned(),
1019				}))
1020			}
1021			Ast::Infix(ast) => Self::infix(ast),
1022			Ast::Between(between) => {
1023				let value = Self::compile(BumpBox::into_inner(between.value))?;
1024				let lower = Self::compile(BumpBox::into_inner(between.lower))?;
1025				let upper = Self::compile(BumpBox::into_inner(between.upper))?;
1026
1027				Ok(Expression::Between(BetweenExpression {
1028					value: Box::new(value),
1029					lower: Box::new(lower),
1030					upper: Box::new(upper),
1031					fragment: between.token.fragment.to_owned(),
1032				}))
1033			}
1034			Ast::Tuple(tuple) => {
1035				let mut expressions = Vec::with_capacity(tuple.len());
1036
1037				for ast in tuple.nodes {
1038					expressions.push(Self::compile(ast)?);
1039				}
1040
1041				Ok(Expression::Tuple(TupleExpression {
1042					expressions,
1043					fragment: tuple.token.fragment.to_owned(),
1044				}))
1045			}
1046			Ast::Prefix(prefix) => {
1047				let (fragment, operator) = match prefix.operator {
1048					ast::ast::AstPrefixOperator::Plus(token) => (
1049						token.fragment.to_owned(),
1050						PrefixOperator::Plus(token.fragment.to_owned()),
1051					),
1052					ast::ast::AstPrefixOperator::Negate(token) => (
1053						token.fragment.to_owned(),
1054						PrefixOperator::Minus(token.fragment.to_owned()),
1055					),
1056					ast::ast::AstPrefixOperator::Not(token) => (
1057						token.fragment.to_owned(),
1058						PrefixOperator::Not(token.fragment.to_owned()),
1059					),
1060				};
1061
1062				Ok(Expression::Prefix(PrefixExpression {
1063					operator,
1064					expression: Box::new(Self::compile(BumpBox::into_inner(prefix.node))?),
1065					fragment,
1066				}))
1067			}
1068			Ast::Cast(node) => {
1069				let mut tuple = node.tuple;
1070				let node = tuple.nodes.pop().unwrap();
1071				let bump_fragment = node.as_identifier().token.fragment;
1072				let ty = convert_data_type(&bump_fragment)?;
1073				let fragment = bump_fragment.to_owned();
1074
1075				let expr = tuple.nodes.pop().unwrap();
1076
1077				Ok(Expression::Cast(CastExpression {
1078					fragment: tuple.token.fragment.to_owned(),
1079					expression: Box::new(Self::compile(expr)?),
1080					to: TypeExpression {
1081						fragment,
1082						ty,
1083					},
1084				}))
1085			}
1086			Ast::Variable(var) => Ok(Expression::Variable(VariableExpression {
1087				fragment: var.token.fragment.to_owned(),
1088			})),
1089			Ast::Rownum(_rownum) => {
1090				let column = ColumnIdentifier {
1091					shape: ColumnShape::Qualified {
1092						namespace: Fragment::Internal {
1093							text: Arc::from("_context"),
1094						},
1095						name: Fragment::Internal {
1096							text: Arc::from("_context"),
1097						},
1098					},
1099					name: Fragment::Internal {
1100						text: Arc::from(ROW_NUMBER_COLUMN_NAME),
1101					},
1102				};
1103				Ok(Expression::Column(ColumnExpression(column)))
1104			}
1105			Ast::SystemColumn(node) => {
1106				let name = node
1107					.token
1108					.fragment
1109					.text()
1110					.strip_prefix('#')
1111					.unwrap_or(node.token.fragment.text());
1112				let column = ColumnIdentifier {
1113					shape: ColumnShape::Qualified {
1114						namespace: Fragment::Internal {
1115							text: Arc::from("_context"),
1116						},
1117						name: Fragment::Internal {
1118							text: Arc::from("_context"),
1119						},
1120					},
1121					name: Fragment::Internal {
1122						text: Arc::from(name),
1123					},
1124				};
1125				Ok(Expression::Column(ColumnExpression(column)))
1126			}
1127			Ast::If(if_ast) => {
1128				// Compile condition
1129				let condition = Box::new(Self::compile(BumpBox::into_inner(if_ast.condition))?);
1130
1131				// Compile then expression (take first expression from first statement in block)
1132				let then_expr = Box::new(Self::compile_block_as_expr(if_ast.then_block)?);
1133
1134				// Compile else_if chains
1135				let mut else_ifs = Vec::new();
1136				for else_if in if_ast.else_ifs {
1137					let else_if_condition =
1138						Box::new(Self::compile(BumpBox::into_inner(else_if.condition))?);
1139					let else_if_then = Box::new(Self::compile_block_as_expr(else_if.then_block)?);
1140					else_ifs.push(ElseIfExpression {
1141						condition: else_if_condition,
1142						then_expr: else_if_then,
1143						fragment: else_if.token.fragment.to_owned(),
1144					});
1145				}
1146
1147				// Compile optional else expression
1148				let else_expr = if let Some(else_block) = if_ast.else_block {
1149					Some(Box::new(Self::compile_block_as_expr(else_block)?))
1150				} else {
1151					None
1152				};
1153
1154				Ok(Expression::If(IfExpression {
1155					condition,
1156					then_expr,
1157					else_ifs,
1158					else_expr,
1159					fragment: if_ast.token.fragment.to_owned(),
1160				}))
1161			}
1162			Ast::Map(map) => {
1163				// Compile expressions in the map
1164				let mut expressions = Vec::with_capacity(map.nodes.len());
1165				for node in map.nodes {
1166					expressions.push(Self::compile(node)?);
1167				}
1168
1169				Ok(Expression::Map(MapExpression {
1170					expressions,
1171					fragment: map.token.fragment.to_owned(),
1172				}))
1173			}
1174			Ast::Extend(extend) => {
1175				// Compile expressions in the extend
1176				let mut expressions = Vec::with_capacity(extend.nodes.len());
1177				for node in extend.nodes {
1178					expressions.push(Self::compile(node)?);
1179				}
1180
1181				Ok(Expression::Extend(ExtendExpression {
1182					expressions,
1183					fragment: extend.token.fragment.to_owned(),
1184				}))
1185			}
1186			Ast::List(list) => {
1187				// Compile list expressions (used for IN [...] syntax)
1188				let mut expressions = Vec::with_capacity(list.nodes.len());
1189				for ast in list.nodes {
1190					expressions.push(Self::compile(ast)?);
1191				}
1192				Ok(Expression::List(ListExpression {
1193					expressions,
1194					fragment: list.token.fragment.to_owned(),
1195				}))
1196			}
1197			Ast::SumTypeConstructor(ctor) => {
1198				let mut columns = Vec::with_capacity(ctor.columns.keyed_values.len());
1199				for kv in ctor.columns.keyed_values {
1200					let name = kv.key.token.fragment.to_owned();
1201					let expr = Self::compile(BumpBox::into_inner(kv.value))?;
1202					columns.push((name, expr));
1203				}
1204				Ok(Expression::SumTypeConstructor(SumTypeConstructorExpression {
1205					namespace: ctor.namespace.to_owned(),
1206					sumtype_name: ctor.sumtype_name.to_owned(),
1207					variant_name: ctor.variant_name.to_owned(),
1208					columns,
1209					fragment: ctor.token.fragment.to_owned(),
1210				}))
1211			}
1212			Ast::IsVariant(is) => {
1213				let expression = Self::compile(BumpBox::into_inner(is.expression))?;
1214				Ok(Expression::IsVariant(IsVariantExpression {
1215					expression: Box::new(expression),
1216					namespace: is.namespace.map(|n| n.to_owned()),
1217					sumtype_name: is.sumtype_name.to_owned(),
1218					variant_name: is.variant_name.to_owned(),
1219					tag: None,
1220					fragment: is.token.fragment.to_owned(),
1221				}))
1222			}
1223			Ast::Match(match_ast) => Self::compile_match(match_ast),
1224			Ast::Identity(ident) => Ok(Expression::Variable(VariableExpression {
1225				fragment: ident.token.fragment.to_owned(),
1226			})),
1227			Ast::From(AstFrom::Variable {
1228				variable,
1229				..
1230			}) => Ok(Expression::Variable(VariableExpression {
1231				fragment: variable.token.fragment.to_owned(),
1232			})),
1233			ast => unimplemented!("{:?}", ast),
1234		}
1235	}
1236
1237	/// Compile an AstBlock as a single expression.
1238	/// Takes the first expression from the first statement in the block.
1239	/// Used for IF/ELSE blocks in expression context.
1240	fn compile_block_as_expr(block: AstBlock<'_>) -> Result<Expression> {
1241		let fragment = block.token.fragment.to_owned();
1242		if let Some(first_stmt) = block.statements.into_iter().next()
1243			&& let Some(first_node) = first_stmt.nodes.into_iter().next()
1244		{
1245			return Self::compile(first_node);
1246		}
1247		// Empty block → none
1248		Ok(Expression::Constant(ConstantExpression::None {
1249			fragment,
1250		}))
1251	}
1252
1253	/// Compile a MATCH expression by lowering it to an IfExpression.
1254	fn compile_match(match_ast: ast::ast::AstMatch<'_>) -> Result<Expression> {
1255		let fragment = match_ast.token.fragment.to_owned();
1256
1257		// Compile subject expression (if present)
1258		let subject = match match_ast.subject {
1259			Some(s) => Some(Self::compile(BumpBox::into_inner(s))?),
1260			None => None,
1261		};
1262
1263		// Extract the subject column name for field rewriting (if subject is a simple column)
1264		let subject_col_name = subject.as_ref().and_then(|s| match s {
1265			Expression::Column(ColumnExpression(col)) => Some(col.name.text().to_string()),
1266			_ => None,
1267		});
1268
1269		// Build list of (condition, result) pairs + optional else
1270		let mut branches: Vec<(Expression, Expression)> = Vec::new();
1271		let mut else_result: Option<Expression> = None;
1272
1273		for arm in match_ast.arms {
1274			match arm {
1275				AstMatchArm::Else {
1276					result,
1277				} => {
1278					else_result = Some(Self::compile(BumpBox::into_inner(result))?);
1279				}
1280				AstMatchArm::Value {
1281					pattern,
1282					guard,
1283					result,
1284				} => {
1285					let subject_expr = subject.clone().expect("Value arm requires a MATCH subject");
1286					let pattern_expr = Self::compile(BumpBox::into_inner(pattern))?;
1287
1288					// condition = subject == pattern
1289					let mut condition = Expression::Equal(EqExpression {
1290						left: Box::new(subject_expr),
1291						right: Box::new(pattern_expr),
1292						fragment: fragment.clone(),
1293					});
1294
1295					// If guard, condition = condition AND guard
1296					if let Some(guard) = guard {
1297						let guard_expr = Self::compile(BumpBox::into_inner(guard))?;
1298						condition = Expression::And(AndExpression {
1299							left: Box::new(condition),
1300							right: Box::new(guard_expr),
1301							fragment: fragment.clone(),
1302						});
1303					}
1304
1305					let result_expr = Self::compile(BumpBox::into_inner(result))?;
1306					branches.push((condition, result_expr));
1307				}
1308				AstMatchArm::IsVariant {
1309					namespace,
1310					sumtype_name,
1311					variant_name,
1312					destructure,
1313					guard,
1314					result,
1315				} => {
1316					let subject_expr = subject.clone().expect("IS arm requires a MATCH subject");
1317
1318					// Build field bindings for rewriting
1319					let bindings: Vec<(String, String)> = match (&destructure, &subject_col_name) {
1320						(Some(destr), Some(col_name)) => {
1321							let variant_lower = variant_name.text().to_lowercase();
1322							destr.fields
1323								.iter()
1324								.map(|f| {
1325									let field_name = f.text().to_string();
1326									let physical = format!(
1327										"{}_{}_{}",
1328										col_name,
1329										variant_lower,
1330										field_name.to_lowercase()
1331									);
1332									(field_name, physical)
1333								})
1334								.collect()
1335						}
1336						_ => vec![],
1337					};
1338
1339					// condition = subject IS [ns.]Type::Variant
1340					let mut condition = Expression::IsVariant(IsVariantExpression {
1341						expression: Box::new(subject_expr),
1342						namespace: namespace.map(|n| n.to_owned()),
1343						sumtype_name: sumtype_name.to_owned(),
1344						variant_name: variant_name.to_owned(),
1345						tag: None,
1346						fragment: fragment.clone(),
1347					});
1348
1349					// If guard, rewrite field refs in guard, then AND
1350					if let Some(guard) = guard {
1351						let mut guard_expr = Self::compile(BumpBox::into_inner(guard))?;
1352						Self::rewrite_field_refs(&mut guard_expr, &bindings);
1353						condition = Expression::And(AndExpression {
1354							left: Box::new(condition),
1355							right: Box::new(guard_expr),
1356							fragment: fragment.clone(),
1357						});
1358					}
1359
1360					let mut result_expr = Self::compile(BumpBox::into_inner(result))?;
1361					Self::rewrite_field_refs(&mut result_expr, &bindings);
1362					branches.push((condition, result_expr));
1363				}
1364				AstMatchArm::Variant {
1365					variant_name,
1366					destructure,
1367					guard,
1368					result,
1369				} => {
1370					let subject_expr =
1371						subject.clone().expect("Variant arm requires a MATCH subject");
1372
1373					// Build field bindings for rewriting
1374					let bindings: Vec<(String, String)> = match (&destructure, &subject_col_name) {
1375						(Some(destr), Some(col_name)) => {
1376							let variant_lower = variant_name.text().to_lowercase();
1377							destr.fields
1378								.iter()
1379								.map(|f| {
1380									let field_name = f.text().to_string();
1381									let physical = format!(
1382										"{}_{}_{}",
1383										col_name,
1384										variant_lower,
1385										field_name.to_lowercase()
1386									);
1387									(field_name, physical)
1388								})
1389								.collect()
1390						}
1391						_ => vec![],
1392					};
1393
1394					// condition = subject IS Variant (placeholder sumtype_name = variant_name)
1395					let mut condition = Expression::IsVariant(IsVariantExpression {
1396						expression: Box::new(subject_expr),
1397						namespace: None,
1398						sumtype_name: variant_name.to_owned(),
1399						variant_name: variant_name.to_owned(),
1400						tag: None,
1401						fragment: fragment.clone(),
1402					});
1403
1404					// If guard, rewrite field refs in guard, then AND
1405					if let Some(guard) = guard {
1406						let mut guard_expr = Self::compile(BumpBox::into_inner(guard))?;
1407						Self::rewrite_field_refs(&mut guard_expr, &bindings);
1408						condition = Expression::And(AndExpression {
1409							left: Box::new(condition),
1410							right: Box::new(guard_expr),
1411							fragment: fragment.clone(),
1412						});
1413					}
1414
1415					let mut result_expr = Self::compile(BumpBox::into_inner(result))?;
1416					Self::rewrite_field_refs(&mut result_expr, &bindings);
1417					branches.push((condition, result_expr));
1418				}
1419				AstMatchArm::Condition {
1420					condition,
1421					guard,
1422					result,
1423				} => {
1424					let mut cond = Self::compile(BumpBox::into_inner(condition))?;
1425
1426					if let Some(guard) = guard {
1427						let guard_expr = Self::compile(BumpBox::into_inner(guard))?;
1428						cond = Expression::And(AndExpression {
1429							left: Box::new(cond),
1430							right: Box::new(guard_expr),
1431							fragment: fragment.clone(),
1432						});
1433					}
1434
1435					let result_expr = Self::compile(BumpBox::into_inner(result))?;
1436					branches.push((cond, result_expr));
1437				}
1438			}
1439		}
1440
1441		// Assemble into IfExpression
1442		if branches.is_empty() {
1443			// Degenerate: only ELSE or empty match
1444			return Ok(else_result.unwrap_or(Expression::Constant(ConstantExpression::None {
1445				fragment,
1446			})));
1447		}
1448
1449		let (first_cond, first_then) = branches.remove(0);
1450
1451		let else_ifs: Vec<ElseIfExpression> = branches
1452			.into_iter()
1453			.map(|(cond, then_expr)| ElseIfExpression {
1454				condition: Box::new(cond),
1455				then_expr: Box::new(then_expr),
1456				fragment: fragment.clone(),
1457			})
1458			.collect();
1459
1460		Ok(Expression::If(IfExpression {
1461			condition: Box::new(first_cond),
1462			then_expr: Box::new(first_then),
1463			else_ifs,
1464			else_expr: else_result.map(Box::new),
1465			fragment,
1466		}))
1467	}
1468
1469	/// Rewrite field references in a compiled expression tree.
1470	/// Replaces Column expressions whose name matches a bound field name
1471	/// with the corresponding physical column name.
1472	pub(crate) fn rewrite_field_refs(expr: &mut Expression, bindings: &[(String, String)]) {
1473		if bindings.is_empty() {
1474			return;
1475		}
1476		match expr {
1477			Expression::Column(ColumnExpression(col)) => {
1478				let name = col.name.text().to_string();
1479				for (field_name, physical_name) in bindings {
1480					if name == *field_name {
1481						col.name = Fragment::internal(physical_name);
1482						break;
1483					}
1484				}
1485			}
1486			Expression::Add(e) => {
1487				Self::rewrite_field_refs(&mut e.left, bindings);
1488				Self::rewrite_field_refs(&mut e.right, bindings);
1489			}
1490			Expression::Sub(e) => {
1491				Self::rewrite_field_refs(&mut e.left, bindings);
1492				Self::rewrite_field_refs(&mut e.right, bindings);
1493			}
1494			Expression::Mul(e) => {
1495				Self::rewrite_field_refs(&mut e.left, bindings);
1496				Self::rewrite_field_refs(&mut e.right, bindings);
1497			}
1498			Expression::Div(e) => {
1499				Self::rewrite_field_refs(&mut e.left, bindings);
1500				Self::rewrite_field_refs(&mut e.right, bindings);
1501			}
1502			Expression::Rem(e) => {
1503				Self::rewrite_field_refs(&mut e.left, bindings);
1504				Self::rewrite_field_refs(&mut e.right, bindings);
1505			}
1506			Expression::Equal(e) => {
1507				Self::rewrite_field_refs(&mut e.left, bindings);
1508				Self::rewrite_field_refs(&mut e.right, bindings);
1509			}
1510			Expression::NotEqual(e) => {
1511				Self::rewrite_field_refs(&mut e.left, bindings);
1512				Self::rewrite_field_refs(&mut e.right, bindings);
1513			}
1514			Expression::GreaterThan(e) => {
1515				Self::rewrite_field_refs(&mut e.left, bindings);
1516				Self::rewrite_field_refs(&mut e.right, bindings);
1517			}
1518			Expression::GreaterThanEqual(e) => {
1519				Self::rewrite_field_refs(&mut e.left, bindings);
1520				Self::rewrite_field_refs(&mut e.right, bindings);
1521			}
1522			Expression::LessThan(e) => {
1523				Self::rewrite_field_refs(&mut e.left, bindings);
1524				Self::rewrite_field_refs(&mut e.right, bindings);
1525			}
1526			Expression::LessThanEqual(e) => {
1527				Self::rewrite_field_refs(&mut e.left, bindings);
1528				Self::rewrite_field_refs(&mut e.right, bindings);
1529			}
1530			Expression::And(e) => {
1531				Self::rewrite_field_refs(&mut e.left, bindings);
1532				Self::rewrite_field_refs(&mut e.right, bindings);
1533			}
1534			Expression::Or(e) => {
1535				Self::rewrite_field_refs(&mut e.left, bindings);
1536				Self::rewrite_field_refs(&mut e.right, bindings);
1537			}
1538			Expression::Xor(e) => {
1539				Self::rewrite_field_refs(&mut e.left, bindings);
1540				Self::rewrite_field_refs(&mut e.right, bindings);
1541			}
1542			Expression::Prefix(e) => {
1543				Self::rewrite_field_refs(&mut e.expression, bindings);
1544			}
1545			Expression::Cast(e) => {
1546				Self::rewrite_field_refs(&mut e.expression, bindings);
1547			}
1548			Expression::Call(e) => {
1549				for arg in &mut e.args {
1550					Self::rewrite_field_refs(arg, bindings);
1551				}
1552			}
1553			Expression::If(e) => {
1554				Self::rewrite_field_refs(&mut e.condition, bindings);
1555				Self::rewrite_field_refs(&mut e.then_expr, bindings);
1556				for else_if in &mut e.else_ifs {
1557					Self::rewrite_field_refs(&mut else_if.condition, bindings);
1558					Self::rewrite_field_refs(&mut else_if.then_expr, bindings);
1559				}
1560				if let Some(else_expr) = &mut e.else_expr {
1561					Self::rewrite_field_refs(else_expr, bindings);
1562				}
1563			}
1564			Expression::Alias(e) => {
1565				Self::rewrite_field_refs(&mut e.expression, bindings);
1566			}
1567			Expression::Tuple(e) => {
1568				for expr in &mut e.expressions {
1569					Self::rewrite_field_refs(expr, bindings);
1570				}
1571			}
1572			Expression::List(e) => {
1573				for expr in &mut e.expressions {
1574					Self::rewrite_field_refs(expr, bindings);
1575				}
1576			}
1577			Expression::Between(e) => {
1578				Self::rewrite_field_refs(&mut e.value, bindings);
1579				Self::rewrite_field_refs(&mut e.lower, bindings);
1580				Self::rewrite_field_refs(&mut e.upper, bindings);
1581			}
1582			Expression::In(e) => {
1583				Self::rewrite_field_refs(&mut e.value, bindings);
1584				Self::rewrite_field_refs(&mut e.list, bindings);
1585			}
1586			Expression::Contains(e) => {
1587				Self::rewrite_field_refs(&mut e.value, bindings);
1588				Self::rewrite_field_refs(&mut e.list, bindings);
1589			}
1590			// Leaf nodes that don't contain column references
1591			Expression::Constant(_)
1592			| Expression::AccessSource(_)
1593			| Expression::Type(_)
1594			| Expression::Parameter(_)
1595			| Expression::Variable(_)
1596			| Expression::Map(_)
1597			| Expression::Extend(_)
1598			| Expression::SumTypeConstructor(_)
1599			| Expression::IsVariant(_)
1600			| Expression::FieldAccess(_) => {}
1601		}
1602	}
1603
1604	fn infix(ast: AstInfix<'_>) -> Result<Expression> {
1605		match ast.operator {
1606			InfixOperator::Add(token) => {
1607				let left = Self::compile(BumpBox::into_inner(ast.left))?;
1608				let right = Self::compile(BumpBox::into_inner(ast.right))?;
1609				Ok(Expression::Add(AddExpression {
1610					left: Box::new(left),
1611					right: Box::new(right),
1612					fragment: token.fragment.to_owned(),
1613				}))
1614			}
1615			InfixOperator::Divide(token) => {
1616				let left = Self::compile(BumpBox::into_inner(ast.left))?;
1617				let right = Self::compile(BumpBox::into_inner(ast.right))?;
1618				Ok(Expression::Div(DivExpression {
1619					left: Box::new(left),
1620					right: Box::new(right),
1621					fragment: token.fragment.to_owned(),
1622				}))
1623			}
1624			InfixOperator::Subtract(token) => {
1625				let left = Self::compile(BumpBox::into_inner(ast.left))?;
1626				let right = Self::compile(BumpBox::into_inner(ast.right))?;
1627				Ok(Expression::Sub(SubExpression {
1628					left: Box::new(left),
1629					right: Box::new(right),
1630					fragment: token.fragment.to_owned(),
1631				}))
1632			}
1633			InfixOperator::Rem(token) => {
1634				let left = Self::compile(BumpBox::into_inner(ast.left))?;
1635				let right = Self::compile(BumpBox::into_inner(ast.right))?;
1636				Ok(Expression::Rem(RemExpression {
1637					left: Box::new(left),
1638					right: Box::new(right),
1639					fragment: token.fragment.to_owned(),
1640				}))
1641			}
1642			InfixOperator::Multiply(token) => {
1643				let left = Self::compile(BumpBox::into_inner(ast.left))?;
1644				let right = Self::compile(BumpBox::into_inner(ast.right))?;
1645				Ok(Expression::Mul(MulExpression {
1646					left: Box::new(left),
1647					right: Box::new(right),
1648					fragment: token.fragment.to_owned(),
1649				}))
1650			}
1651			InfixOperator::Call(token) => {
1652				let left = Self::compile(BumpBox::into_inner(ast.left))?;
1653				let right = Self::compile(BumpBox::into_inner(ast.right))?;
1654
1655				let func_name = match left {
1656					Expression::Column(ColumnExpression(column)) => column.name,
1657					Expression::Variable(var) => var.fragment,
1658					_ => panic!("unexpected left-hand side in call expression"),
1659				};
1660				let Expression::Tuple(tuple) = right else {
1661					panic!()
1662				};
1663
1664				Ok(Expression::Call(CallExpression {
1665					func: IdentExpression(func_name),
1666					args: tuple.expressions,
1667					fragment: token.fragment.to_owned(),
1668				}))
1669			}
1670			InfixOperator::GreaterThan(token) => {
1671				let left = Self::compile(BumpBox::into_inner(ast.left))?;
1672				let right = Self::compile(BumpBox::into_inner(ast.right))?;
1673
1674				Ok(Expression::GreaterThan(GreaterThanExpression {
1675					left: Box::new(left),
1676					right: Box::new(right),
1677					fragment: token.fragment.to_owned(),
1678				}))
1679			}
1680			InfixOperator::GreaterThanEqual(token) => {
1681				let left = Self::compile(BumpBox::into_inner(ast.left))?;
1682				let right = Self::compile(BumpBox::into_inner(ast.right))?;
1683
1684				Ok(Expression::GreaterThanEqual(GreaterThanEqExpression {
1685					left: Box::new(left),
1686					right: Box::new(right),
1687					fragment: token.fragment.to_owned(),
1688				}))
1689			}
1690			InfixOperator::LessThan(token) => {
1691				let left = Self::compile(BumpBox::into_inner(ast.left))?;
1692				let right = Self::compile(BumpBox::into_inner(ast.right))?;
1693
1694				Ok(Expression::LessThan(LessThanExpression {
1695					left: Box::new(left),
1696					right: Box::new(right),
1697					fragment: token.fragment.to_owned(),
1698				}))
1699			}
1700			InfixOperator::LessThanEqual(token) => {
1701				let left = Self::compile(BumpBox::into_inner(ast.left))?;
1702				let right = Self::compile(BumpBox::into_inner(ast.right))?;
1703
1704				Ok(Expression::LessThanEqual(LessThanEqExpression {
1705					left: Box::new(left),
1706					right: Box::new(right),
1707					fragment: token.fragment.to_owned(),
1708				}))
1709			}
1710			InfixOperator::Equal(token) => {
1711				let left = Self::compile(BumpBox::into_inner(ast.left))?;
1712				let right = Self::compile(BumpBox::into_inner(ast.right))?;
1713
1714				Ok(Expression::Equal(EqExpression {
1715					left: Box::new(left),
1716					right: Box::new(right),
1717					fragment: token.fragment.to_owned(),
1718				}))
1719			}
1720			InfixOperator::NotEqual(token) => {
1721				let left = Self::compile(BumpBox::into_inner(ast.left))?;
1722				let right = Self::compile(BumpBox::into_inner(ast.right))?;
1723
1724				Ok(Expression::NotEqual(NotEqExpression {
1725					left: Box::new(left),
1726					right: Box::new(right),
1727					fragment: token.fragment.to_owned(),
1728				}))
1729			}
1730			InfixOperator::As(token) => {
1731				let left = Self::compile(BumpBox::into_inner(ast.left))?;
1732				let alias_fragment = match BumpBox::into_inner(ast.right) {
1733					Ast::Identifier(ident) => ident.token.fragment.to_owned(),
1734					Ast::Literal(AstLiteral::Text(text)) => {
1735						let raw = text.0.fragment.text();
1736						let unquoted = raw.trim_matches('"');
1737						Fragment::internal(unquoted)
1738					}
1739					_ => unimplemented!(),
1740				};
1741
1742				Ok(Expression::Alias(AliasExpression {
1743					alias: IdentExpression(alias_fragment),
1744					expression: Box::new(left),
1745					fragment: token.fragment.to_owned(),
1746				}))
1747			}
1748
1749			InfixOperator::And(token) => {
1750				let left = Self::compile(BumpBox::into_inner(ast.left))?;
1751				let right = Self::compile(BumpBox::into_inner(ast.right))?;
1752
1753				Ok(Expression::And(AndExpression {
1754					left: Box::new(left),
1755					right: Box::new(right),
1756					fragment: token.fragment.to_owned(),
1757				}))
1758			}
1759
1760			InfixOperator::Or(token) => {
1761				let left = Self::compile(BumpBox::into_inner(ast.left))?;
1762				let right = Self::compile(BumpBox::into_inner(ast.right))?;
1763
1764				Ok(Expression::Or(OrExpression {
1765					left: Box::new(left),
1766					right: Box::new(right),
1767					fragment: token.fragment.to_owned(),
1768				}))
1769			}
1770
1771			InfixOperator::Xor(token) => {
1772				let left = Self::compile(BumpBox::into_inner(ast.left))?;
1773				let right = Self::compile(BumpBox::into_inner(ast.right))?;
1774
1775				Ok(Expression::Xor(XorExpression {
1776					left: Box::new(left),
1777					right: Box::new(right),
1778					fragment: token.fragment.to_owned(),
1779				}))
1780			}
1781
1782			InfixOperator::In(token) => {
1783				let value = Self::compile(BumpBox::into_inner(ast.left))?;
1784				let list = Self::compile(BumpBox::into_inner(ast.right))?;
1785
1786				Ok(Expression::In(InExpression {
1787					value: Box::new(value),
1788					list: Box::new(list),
1789					negated: false,
1790					fragment: token.fragment.to_owned(),
1791				}))
1792			}
1793
1794			InfixOperator::NotIn(token) => {
1795				let value = Self::compile(BumpBox::into_inner(ast.left))?;
1796				let list = Self::compile(BumpBox::into_inner(ast.right))?;
1797
1798				Ok(Expression::In(InExpression {
1799					value: Box::new(value),
1800					list: Box::new(list),
1801					negated: true,
1802					fragment: token.fragment.to_owned(),
1803				}))
1804			}
1805
1806			InfixOperator::Contains(token) => {
1807				let value = Self::compile(BumpBox::into_inner(ast.left))?;
1808				let list = Self::compile(BumpBox::into_inner(ast.right))?;
1809
1810				Ok(Expression::Contains(ContainsExpression {
1811					value: Box::new(value),
1812					list: Box::new(list),
1813					fragment: token.fragment.to_owned(),
1814				}))
1815			}
1816
1817			InfixOperator::Assign(token) => {
1818				// Assignment operator (=) is not valid in expression context
1819				// Use == for equality comparison
1820				Err(AstError::UnsupportedToken {
1821					fragment: token.fragment.to_owned(),
1822				}
1823				.into())
1824			}
1825
1826			InfixOperator::TypeAscription(token) => {
1827				match BumpBox::into_inner(ast.left) {
1828					Ast::Identifier(alias) => {
1829						let right = Self::compile(BumpBox::into_inner(ast.right))?;
1830
1831						Ok(Expression::Alias(AliasExpression {
1832							alias: IdentExpression(alias.token.fragment.to_owned()),
1833							expression: Box::new(right),
1834							fragment: token.fragment.to_owned(),
1835						}))
1836					}
1837					Ast::Literal(AstLiteral::Text(text)) => {
1838						// Handle string literals as alias names (common in MAP syntax)
1839						let right = Self::compile(BumpBox::into_inner(ast.right))?;
1840
1841						Ok(Expression::Alias(AliasExpression {
1842							alias: IdentExpression(text.0.fragment.to_owned()),
1843							expression: Box::new(right),
1844							fragment: token.fragment.to_owned(),
1845						}))
1846					}
1847					_ => {
1848						err!(Diagnostic {
1849							code: "EXPR_001".to_string(),
1850							rql: None,
1851							message: "Invalid alias expression".to_string(),
1852							column: None,
1853							fragment: Fragment::None,
1854							label: Some("Only identifiers and string literals can be used as alias names".to_string()),
1855							help: Some("Use an identifier or string literal for the alias name".to_string()),
1856							notes: vec![],
1857							cause: None,
1858							operator_chain: None,
1859						})
1860					}
1861				}
1862			}
1863			InfixOperator::AccessNamespace(_token) => {
1864				// Handle namespace access: `ns::func(args)` → CallExpression with namespaced name
1865				// Extract namespace name from left side (always an identifier)
1866				let left = Self::compile(BumpBox::into_inner(ast.left))?;
1867				let namespace = match &left {
1868					Expression::Column(ColumnExpression(col)) => col.name.text().to_string(),
1869					other => unimplemented!("unsupported namespace expression: {other:?}"),
1870				};
1871
1872				// The right side may contain keywords (e.g. `undefined`) that should be
1873				// treated as identifiers in a namespace context. Extract the name from the
1874				// raw AST token before compiling, so keywords are treated as identifier_or_keyword.
1875				let right_ast = BumpBox::into_inner(ast.right);
1876				Self::compile_namespace_right(&namespace, right_ast)
1877			}
1878
1879			InfixOperator::AccessTable(token) => {
1880				let left = Self::compile(BumpBox::into_inner(ast.left))?;
1881				let right_ast = BumpBox::into_inner(ast.right);
1882				let field_name = right_ast.token().fragment.to_owned();
1883				let fragment = token.fragment.to_owned();
1884				Ok(Expression::FieldAccess(FieldAccessExpression {
1885					object: Box::new(left),
1886					field: field_name,
1887					fragment,
1888				}))
1889			}
1890		}
1891	}
1892
1893	/// Compile the right-hand side of a namespace access (`ns::...`).
1894	///
1895	/// Keywords like `undefined` or `true` are treated as identifiers in this
1896	/// context so that `is::none(x)` resolves to a function call rather
1897	/// than parsing `undefined` as the literal keyword.
1898	fn compile_namespace_right(namespace: &str, right_ast: Ast<'_>) -> Result<Expression> {
1899		// Helper: extract a token's text from any AST node that should be treated
1900		// as an identifier_or_keyword in namespace position.
1901		fn identifier_or_keyword_name(ast: &Ast<'_>) -> Option<String> {
1902			Some(ast.token().fragment.text().to_string())
1903		}
1904
1905		match right_ast {
1906			// ns::func(args)  where func is parsed as Infix(left, Call, right)
1907			Ast::Infix(infix) if matches!(infix.operator, InfixOperator::Call(_)) => {
1908				let func_name = identifier_or_keyword_name(&infix.left)
1909					.expect("namespace function name must be extractable");
1910				let full_name = format!("{}::{}", namespace, func_name);
1911
1912				let right = Self::compile(BumpBox::into_inner(infix.right))?;
1913				let Expression::Tuple(tuple) = right else {
1914					panic!("expected tuple arguments for namespaced call");
1915				};
1916
1917				Ok(Expression::Call(CallExpression {
1918					func: IdentExpression(Fragment::testing(&full_name)),
1919					args: tuple.expressions,
1920					fragment: infix.token.fragment.to_owned(),
1921				}))
1922			}
1923			// ns::func(args) where func is parsed as CallFunction
1924			// (happens when the namespace token is a keyword like `is`,
1925			// so the parser treats the right side as a standalone call)
1926			Ast::CallFunction(call) => {
1927				let func_name = call.function.name.text().to_string();
1928				let full_name = if call.function.namespaces.is_empty() {
1929					format!("{}::{}", namespace, func_name)
1930				} else {
1931					let sub_ns = call
1932						.function
1933						.namespaces
1934						.iter()
1935						.map(|ns| ns.text())
1936						.collect::<Vec<_>>()
1937						.join("::");
1938					format!("{}::{}::{}", namespace, sub_ns, func_name)
1939				};
1940
1941				let mut arg_expressions = Vec::new();
1942				for arg_ast in call.arguments.nodes {
1943					let compiled = Self::compile(arg_ast)?;
1944					let compiled = match &compiled {
1945						Expression::Column(col_expr) => {
1946							if let Ok(ty) = Type::from_str(col_expr.0.name.text()) {
1947								Expression::Type(TypeExpression {
1948									fragment: col_expr.0.name.clone(),
1949									ty,
1950								})
1951							} else {
1952								compiled
1953							}
1954						}
1955						_ => compiled,
1956					};
1957					arg_expressions.push(compiled);
1958				}
1959
1960				Ok(Expression::Call(CallExpression {
1961					func: IdentExpression(Fragment::testing(&full_name)),
1962					args: arg_expressions,
1963					fragment: call.token.fragment.to_owned(),
1964				}))
1965			}
1966			// ns::name  (bare namespaced reference, no call)
1967			other => {
1968				if let Some(name) = identifier_or_keyword_name(&other) {
1969					let full_name = format!("{}::{}", namespace, name);
1970					Ok(Expression::Column(ColumnExpression(ColumnIdentifier {
1971						shape: ColumnShape::Qualified {
1972							namespace: Fragment::Internal {
1973								text: Arc::from("_context"),
1974							},
1975							name: Fragment::Internal {
1976								text: Arc::from("_context"),
1977							},
1978						},
1979						name: Fragment::testing(&full_name),
1980					})))
1981				} else {
1982					let compiled = Self::compile(other)?;
1983					match compiled {
1984						Expression::Column(ColumnExpression(col)) => {
1985							let full_name = format!("{}::{}", namespace, col.name.text());
1986							Ok(Expression::Column(ColumnExpression(ColumnIdentifier {
1987								shape: col.shape,
1988								name: Fragment::testing(&full_name),
1989							})))
1990						}
1991						other => unimplemented!(
1992							"unsupported namespace right-hand side: {other:?}"
1993						),
1994					}
1995				}
1996			}
1997		}
1998	}
1999}
2000
2001#[derive(Debug, Clone, Serialize, Deserialize)]
2002pub struct MapExpression {
2003	pub expressions: Vec<Expression>,
2004	pub fragment: Fragment,
2005}
2006
2007#[derive(Debug, Clone, Serialize, Deserialize)]
2008pub struct ExtendExpression {
2009	pub expressions: Vec<Expression>,
2010	pub fragment: Fragment,
2011}
2012
2013#[derive(Debug, Clone, Serialize, Deserialize)]
2014pub struct SumTypeConstructorExpression {
2015	pub namespace: Fragment,
2016	pub sumtype_name: Fragment,
2017	pub variant_name: Fragment,
2018	pub columns: Vec<(Fragment, Expression)>,
2019	pub fragment: Fragment,
2020}
2021
2022#[derive(Debug, Clone, Serialize, Deserialize)]
2023pub struct IsVariantExpression {
2024	pub expression: Box<Expression>,
2025	pub namespace: Option<Fragment>,
2026	pub sumtype_name: Fragment,
2027	pub variant_name: Fragment,
2028	pub tag: Option<u8>,
2029	pub fragment: Fragment,
2030}
2031
2032#[derive(Debug, Clone, Serialize, Deserialize)]
2033pub struct FieldAccessExpression {
2034	pub object: Box<Expression>,
2035	pub field: Fragment,
2036	pub fragment: Fragment,
2037}
2038
2039impl FieldAccessExpression {
2040	pub fn full_fragment_owned(&self) -> Fragment {
2041		Fragment::merge_all([self.object.full_fragment_owned(), self.fragment.clone(), self.field.clone()])
2042	}
2043}
2044
2045impl Display for FieldAccessExpression {
2046	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2047		write!(f, "{}.{}", self.object, self.field.text())
2048	}
2049}
2050
2051/// Recursively extract all variable names referenced in an expression tree.
2052pub fn extract_variable_names(expr: &Expression) -> Vec<String> {
2053	let mut names = Vec::new();
2054	collect_variable_names(expr, &mut names);
2055	names
2056}
2057
2058fn collect_variable_names(expr: &Expression, names: &mut Vec<String>) {
2059	match expr {
2060		Expression::Variable(v) => {
2061			let name = v.name().to_string();
2062			if !names.contains(&name) {
2063				names.push(name);
2064			}
2065		}
2066		Expression::Add(e) => {
2067			collect_variable_names(&e.left, names);
2068			collect_variable_names(&e.right, names);
2069		}
2070		Expression::Sub(e) => {
2071			collect_variable_names(&e.left, names);
2072			collect_variable_names(&e.right, names);
2073		}
2074		Expression::Mul(e) => {
2075			collect_variable_names(&e.left, names);
2076			collect_variable_names(&e.right, names);
2077		}
2078		Expression::Div(e) => {
2079			collect_variable_names(&e.left, names);
2080			collect_variable_names(&e.right, names);
2081		}
2082		Expression::Rem(e) => {
2083			collect_variable_names(&e.left, names);
2084			collect_variable_names(&e.right, names);
2085		}
2086		Expression::GreaterThan(e) => {
2087			collect_variable_names(&e.left, names);
2088			collect_variable_names(&e.right, names);
2089		}
2090		Expression::GreaterThanEqual(e) => {
2091			collect_variable_names(&e.left, names);
2092			collect_variable_names(&e.right, names);
2093		}
2094		Expression::LessThan(e) => {
2095			collect_variable_names(&e.left, names);
2096			collect_variable_names(&e.right, names);
2097		}
2098		Expression::LessThanEqual(e) => {
2099			collect_variable_names(&e.left, names);
2100			collect_variable_names(&e.right, names);
2101		}
2102		Expression::Equal(e) => {
2103			collect_variable_names(&e.left, names);
2104			collect_variable_names(&e.right, names);
2105		}
2106		Expression::NotEqual(e) => {
2107			collect_variable_names(&e.left, names);
2108			collect_variable_names(&e.right, names);
2109		}
2110		Expression::And(e) => {
2111			collect_variable_names(&e.left, names);
2112			collect_variable_names(&e.right, names);
2113		}
2114		Expression::Or(e) => {
2115			collect_variable_names(&e.left, names);
2116			collect_variable_names(&e.right, names);
2117		}
2118		Expression::Xor(e) => {
2119			collect_variable_names(&e.left, names);
2120			collect_variable_names(&e.right, names);
2121		}
2122		Expression::Between(e) => {
2123			collect_variable_names(&e.value, names);
2124			collect_variable_names(&e.lower, names);
2125			collect_variable_names(&e.upper, names);
2126		}
2127		Expression::In(e) => {
2128			collect_variable_names(&e.value, names);
2129			collect_variable_names(&e.list, names);
2130		}
2131		Expression::Contains(e) => {
2132			collect_variable_names(&e.value, names);
2133			collect_variable_names(&e.list, names);
2134		}
2135		Expression::Prefix(e) => collect_variable_names(&e.expression, names),
2136		Expression::Cast(e) => collect_variable_names(&e.expression, names),
2137		Expression::Alias(e) => collect_variable_names(&e.expression, names),
2138		Expression::Call(e) => {
2139			for arg in &e.args {
2140				collect_variable_names(arg, names);
2141			}
2142		}
2143		Expression::Tuple(e) => {
2144			for expr in &e.expressions {
2145				collect_variable_names(expr, names);
2146			}
2147		}
2148		Expression::List(e) => {
2149			for expr in &e.expressions {
2150				collect_variable_names(expr, names);
2151			}
2152		}
2153		Expression::If(e) => {
2154			collect_variable_names(&e.condition, names);
2155			collect_variable_names(&e.then_expr, names);
2156			for else_if in &e.else_ifs {
2157				collect_variable_names(&else_if.condition, names);
2158				collect_variable_names(&else_if.then_expr, names);
2159			}
2160			if let Some(else_expr) = &e.else_expr {
2161				collect_variable_names(else_expr, names);
2162			}
2163		}
2164		Expression::Map(e) => {
2165			for expr in &e.expressions {
2166				collect_variable_names(expr, names);
2167			}
2168		}
2169		Expression::Extend(e) => {
2170			for expr in &e.expressions {
2171				collect_variable_names(expr, names);
2172			}
2173		}
2174		Expression::SumTypeConstructor(e) => {
2175			for (_, expr) in &e.columns {
2176				collect_variable_names(expr, names);
2177			}
2178		}
2179		Expression::IsVariant(e) => collect_variable_names(&e.expression, names),
2180		Expression::FieldAccess(e) => collect_variable_names(&e.object, names),
2181		// Leaf nodes with no sub-expressions
2182		Expression::Constant(_)
2183		| Expression::Column(_)
2184		| Expression::AccessSource(_)
2185		| Expression::Parameter(_)
2186		| Expression::Type(_) => {}
2187	}
2188}