spacetimedb_query_planner/logical/
expr.rs1use std::sync::Arc;
2
3use spacetimedb_lib::AlgebraicValue;
4use spacetimedb_schema::schema::TableSchema;
5use spacetimedb_sql_parser::ast::BinOp;
6
7use crate::static_assert_size;
8
9use super::ty::{InvalidTypeId, Symbol, TyCtx, TyId, TypeWithCtx};
10
11#[derive(Debug)]
13pub enum RelExpr {
14 RelVar(Arc<TableSchema>, TyId),
16 Select(Box<Select>),
18 Proj(Box<Project>),
20 Join(Box<[RelExpr]>, TyId),
22 Union(Box<RelExpr>, Box<RelExpr>),
24 Minus(Box<RelExpr>, Box<RelExpr>),
26 Dedup(Box<RelExpr>),
28}
29
30static_assert_size!(RelExpr, 24);
31
32impl RelExpr {
33 pub fn project(input: RelExpr, expr: Let) -> Self {
35 Self::Proj(Box::new(Project { input, expr }))
36 }
37
38 pub fn select(input: RelExpr, expr: Let) -> Self {
40 Self::Select(Box::new(Select { input, expr }))
41 }
42
43 pub fn ty_id(&self) -> TyId {
45 match self {
46 Self::RelVar(_, id) | Self::Join(_, id) => *id,
47 Self::Select(op) => op.input.ty_id(),
48 Self::Proj(op) => op.expr.exprs[0].ty_id(),
49 Self::Union(input, _) | Self::Minus(input, _) | Self::Dedup(input) => input.ty_id(),
50 }
51 }
52
53 pub fn ty<'a>(&self, ctx: &'a TyCtx) -> Result<TypeWithCtx<'a>, InvalidTypeId> {
55 ctx.try_resolve(self.ty_id())
56 }
57}
58
59#[derive(Debug)]
61pub struct Select {
62 pub input: RelExpr,
64 pub expr: Let,
66}
67
68#[derive(Debug)]
70pub struct Project {
71 pub input: RelExpr,
73 pub expr: Let,
75}
76
77#[derive(Debug)]
82pub struct Let {
83 pub vars: Vec<(Symbol, Expr)>,
85 pub exprs: Vec<Expr>,
87}
88
89#[derive(Debug)]
91pub enum Expr {
92 Bin(BinOp, Box<Expr>, Box<Expr>),
94 Var(Symbol, TyId),
96 Row(Box<[(Symbol, Expr)]>, TyId),
98 Lit(AlgebraicValue, TyId),
100 Field(Box<Expr>, usize, TyId),
102 Input(TyId),
104}
105
106static_assert_size!(Expr, 32);
107
108impl Expr {
109 pub const fn bool(v: bool) -> Self {
111 Self::Lit(AlgebraicValue::Bool(v), TyId::BOOL)
112 }
113
114 pub fn str(v: String) -> Self {
116 let s = v.into_boxed_str();
117 Self::Lit(AlgebraicValue::String(s), TyId::STR)
118 }
119
120 pub fn ty_id(&self) -> TyId {
122 match self {
123 Self::Bin(..) => TyId::BOOL,
124 Self::Lit(_, id) | Self::Var(_, id) | Self::Input(id) | Self::Field(_, _, id) | Self::Row(_, id) => *id,
125 }
126 }
127
128 pub fn ty<'a>(&self, ctx: &'a TyCtx) -> Result<TypeWithCtx<'a>, InvalidTypeId> {
130 ctx.try_resolve(self.ty_id())
131 }
132}