spacetimedb_sql_parser/ast/
sub.rs

1use spacetimedb_lib::Identity;
2
3use crate::parser::{errors::SqlUnsupported, SqlParseResult};
4
5use super::{Project, SqlExpr, SqlFrom};
6
7/// A SELECT statement in the SQL subscription language
8#[derive(Debug)]
9pub struct SqlSelect {
10    pub project: Project,
11    pub from: SqlFrom,
12    pub filter: Option<SqlExpr>,
13}
14
15impl SqlSelect {
16    pub fn qualify_vars(self) -> Self {
17        match &self.from {
18            SqlFrom::Expr(_, alias) => Self {
19                project: self.project.qualify_vars(alias.clone()),
20                filter: self.filter.map(|expr| expr.qualify_vars(alias.clone())),
21                from: self.from,
22            },
23            SqlFrom::Join(..) => self,
24        }
25    }
26
27    pub fn find_unqualified_vars(self) -> SqlParseResult<Self> {
28        if self.from.has_unqualified_vars() {
29            return Err(SqlUnsupported::UnqualifiedNames.into());
30        }
31        if self.project.has_unqualified_vars() {
32            return Err(SqlUnsupported::UnqualifiedNames.into());
33        }
34        if let Some(expr) = &self.filter {
35            if expr.has_unqualified_vars() {
36                return Err(SqlUnsupported::UnqualifiedNames.into());
37            }
38        }
39        Ok(self)
40    }
41
42    /// Is this AST parameterized?
43    /// We need to know in order to hash subscription queries correctly.
44    pub fn has_parameter(&self) -> bool {
45        self.filter.as_ref().is_some_and(|expr| expr.has_parameter())
46    }
47
48    /// Replace the `:sender` parameter with the [Identity] it represents
49    pub fn resolve_sender(self, sender_identity: Identity) -> Self {
50        Self {
51            filter: self.filter.map(|expr| expr.resolve_sender(sender_identity)),
52            ..self
53        }
54    }
55}