icydb_core/db/session/sql/surface/
route.rs1use crate::db::{
8 GroupedRow, QueryError,
9 sql::lowering::{
10 LoweredSqlCommand, LoweredSqlLaneKind, PreparedSqlStatement as CorePreparedSqlStatement,
11 lower_sql_command_from_prepared_statement, lowered_sql_command_lane, prepare_sql_statement,
12 },
13 sql::parser::{SqlExplainTarget, SqlStatement},
14};
15
16#[derive(Clone, Debug, Eq, PartialEq)]
22pub enum SqlStatementRoute {
23 Query { entity: String },
24 Insert { entity: String },
25 Update { entity: String },
26 Explain { entity: String },
27 Describe { entity: String },
28 ShowIndexes { entity: String },
29 ShowColumns { entity: String },
30 ShowEntities,
31}
32
33#[derive(Debug)]
35pub enum SqlDispatchResult {
36 Projection {
37 columns: Vec<String>,
38 rows: Vec<Vec<crate::value::Value>>,
39 row_count: u32,
40 },
41 ProjectionText {
42 columns: Vec<String>,
43 rows: Vec<Vec<String>>,
44 row_count: u32,
45 },
46 Grouped {
47 columns: Vec<String>,
48 rows: Vec<GroupedRow>,
49 row_count: u32,
50 next_cursor: Option<String>,
51 },
52 Explain(String),
53 Describe(crate::db::EntitySchemaDescription),
54 ShowIndexes(Vec<String>),
55 ShowColumns(Vec<crate::db::EntityFieldDescription>),
56 ShowEntities(Vec<String>),
57}
58
59#[derive(Clone, Debug)]
68pub struct SqlParsedStatement {
69 pub(in crate::db::session::sql) statement: SqlStatement,
70 route: SqlStatementRoute,
71}
72
73impl SqlParsedStatement {
74 pub(in crate::db::session::sql) const fn new(
76 statement: SqlStatement,
77 route: SqlStatementRoute,
78 ) -> Self {
79 Self { statement, route }
80 }
81
82 #[must_use]
84 pub const fn route(&self) -> &SqlStatementRoute {
85 &self.route
86 }
87
88 pub(in crate::db::session::sql) fn prepare(
90 &self,
91 expected_entity: &'static str,
92 ) -> Result<CorePreparedSqlStatement, QueryError> {
93 prepare_sql_statement(self.statement.clone(), expected_entity)
94 .map_err(QueryError::from_sql_lowering_error)
95 }
96
97 #[inline(never)]
99 pub fn lower_query_lane_for_entity(
100 &self,
101 expected_entity: &'static str,
102 primary_key_field: &str,
103 ) -> Result<LoweredSqlCommand, QueryError> {
104 let lowered = lower_sql_command_from_prepared_statement(
105 self.prepare(expected_entity)?,
106 primary_key_field,
107 )
108 .map_err(QueryError::from_sql_lowering_error)?;
109 let lane = lowered_sql_command_lane(&lowered);
110
111 match lane {
112 LoweredSqlLaneKind::Query | LoweredSqlLaneKind::Explain => Ok(lowered),
113 LoweredSqlLaneKind::Describe
114 | LoweredSqlLaneKind::ShowIndexes
115 | LoweredSqlLaneKind::ShowColumns
116 | LoweredSqlLaneKind::ShowEntities => {
117 Err(QueryError::unsupported_query_lane_dispatch())
118 }
119 }
120 }
121}
122
123impl SqlStatementRoute {
124 #[must_use]
129 pub const fn entity(&self) -> &str {
130 match self {
131 Self::Query { entity }
132 | Self::Insert { entity }
133 | Self::Update { entity }
134 | Self::Explain { entity }
135 | Self::Describe { entity }
136 | Self::ShowIndexes { entity }
137 | Self::ShowColumns { entity } => entity.as_str(),
138 Self::ShowEntities => "",
139 }
140 }
141
142 #[must_use]
144 pub const fn is_explain(&self) -> bool {
145 matches!(self, Self::Explain { .. })
146 }
147
148 #[must_use]
150 pub const fn is_describe(&self) -> bool {
151 matches!(self, Self::Describe { .. })
152 }
153
154 #[must_use]
156 pub const fn is_show_indexes(&self) -> bool {
157 matches!(self, Self::ShowIndexes { .. })
158 }
159
160 #[must_use]
162 pub const fn is_show_columns(&self) -> bool {
163 matches!(self, Self::ShowColumns { .. })
164 }
165
166 #[must_use]
168 pub const fn is_show_entities(&self) -> bool {
169 matches!(self, Self::ShowEntities)
170 }
171}
172
173pub(in crate::db::session::sql) fn sql_statement_route_from_statement(
175 statement: &SqlStatement,
176) -> SqlStatementRoute {
177 match statement {
178 SqlStatement::Select(select) => SqlStatementRoute::Query {
179 entity: select.entity.clone(),
180 },
181 SqlStatement::Delete(delete) => SqlStatementRoute::Query {
182 entity: delete.entity.clone(),
183 },
184 SqlStatement::Insert(insert) => SqlStatementRoute::Insert {
185 entity: insert.entity.clone(),
186 },
187 SqlStatement::Update(update) => SqlStatementRoute::Update {
188 entity: update.entity.clone(),
189 },
190 SqlStatement::Explain(explain) => match &explain.statement {
191 SqlExplainTarget::Select(select) => SqlStatementRoute::Explain {
192 entity: select.entity.clone(),
193 },
194 SqlExplainTarget::Delete(delete) => SqlStatementRoute::Explain {
195 entity: delete.entity.clone(),
196 },
197 },
198 SqlStatement::Describe(describe) => SqlStatementRoute::Describe {
199 entity: describe.entity.clone(),
200 },
201 SqlStatement::ShowIndexes(show_indexes) => SqlStatementRoute::ShowIndexes {
202 entity: show_indexes.entity.clone(),
203 },
204 SqlStatement::ShowColumns(show_columns) => SqlStatementRoute::ShowColumns {
205 entity: show_columns.entity.clone(),
206 },
207 SqlStatement::ShowEntities(_) => SqlStatementRoute::ShowEntities,
208 }
209}