Skip to main content

icydb_core/db/session/sql/
mod.rs

1//! Module: db::session::sql
2//! Responsibility: module-local ownership and contracts for db::session::sql.
3//! Does not own: cross-module orchestration outside this module.
4//! Boundary: exposes this module API while keeping implementation details internal.
5
6mod aggregate;
7mod computed_projection;
8mod dispatch;
9mod explain;
10mod projection;
11mod surface;
12
13use crate::{
14    db::{
15        DbSession, EntityResponse, PagedGroupedExecutionWithTrace, PersistedRow, Query, QueryError,
16        sql::parser::parse_sql,
17    },
18    traits::{CanisterKind, EntityKind, EntityValue},
19};
20
21use crate::db::session::sql::surface::sql_statement_route_from_statement;
22
23pub use crate::db::session::sql::surface::{
24    SqlDispatchResult, SqlParsedStatement, SqlStatementRoute,
25};
26
27impl<C: CanisterKind> DbSession<C> {
28    /// Parse one reduced SQL statement and return one reusable parsed envelope.
29    ///
30    /// This method is the SQL parse authority for dynamic route selection.
31    pub fn parse_sql_statement(&self, sql: &str) -> Result<SqlParsedStatement, QueryError> {
32        let statement = parse_sql(sql).map_err(QueryError::from_sql_parse_error)?;
33        let route = sql_statement_route_from_statement(&statement);
34
35        Ok(SqlParsedStatement::new(statement, route))
36    }
37
38    /// Parse one reduced SQL statement into canonical routing metadata.
39    ///
40    /// This method is the SQL dispatch authority for entity/surface routing
41    /// outside typed-entity lowering paths.
42    pub fn sql_statement_route(&self, sql: &str) -> Result<SqlStatementRoute, QueryError> {
43        let parsed = self.parse_sql_statement(sql)?;
44
45        Ok(parsed.route().clone())
46    }
47
48    /// Build one typed query intent from one reduced SQL statement.
49    ///
50    /// This parser/lowering entrypoint is intentionally constrained to the
51    /// executable subset wired in the current release.
52    pub fn query_from_sql<E>(&self, sql: &str) -> Result<Query<E>, QueryError>
53    where
54        E: EntityKind<Canister = C>,
55    {
56        let parsed = self.parse_sql_statement(sql)?;
57        let (_, query) = Self::bind_sql_query_lane_from_parsed::<E>(&parsed)?;
58
59        Ok(query)
60    }
61
62    /// Execute one reduced SQL `SELECT`/`DELETE` statement for entity `E`.
63    pub fn execute_sql<E>(&self, sql: &str) -> Result<EntityResponse<E>, QueryError>
64    where
65        E: PersistedRow<Canister = C> + EntityValue,
66    {
67        let query = self.query_from_sql::<E>(sql)?;
68        Self::ensure_sql_query_grouping(&query, false)?;
69
70        self.execute_query(&query)
71    }
72
73    /// Execute one reduced SQL grouped `SELECT` statement and return grouped rows.
74    pub fn execute_sql_grouped<E>(
75        &self,
76        sql: &str,
77        cursor_token: Option<&str>,
78    ) -> Result<PagedGroupedExecutionWithTrace, QueryError>
79    where
80        E: PersistedRow<Canister = C> + EntityValue,
81    {
82        let query = self.query_from_sql::<E>(sql)?;
83        Self::ensure_sql_query_grouping(&query, true)?;
84
85        self.execute_grouped(&query, cursor_token)
86    }
87}