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 Count {
37 row_count: u32,
38 },
39 Projection {
40 columns: Vec<String>,
41 rows: Vec<Vec<crate::value::Value>>,
42 row_count: u32,
43 },
44 ProjectionText {
45 columns: Vec<String>,
46 rows: Vec<Vec<String>>,
47 row_count: u32,
48 },
49 Grouped {
50 columns: Vec<String>,
51 rows: Vec<GroupedRow>,
52 row_count: u32,
53 next_cursor: Option<String>,
54 },
55 Explain(String),
56 Describe(crate::db::EntitySchemaDescription),
57 ShowIndexes(Vec<String>),
58 ShowColumns(Vec<crate::db::EntityFieldDescription>),
59 ShowEntities(Vec<String>),
60}
61
62#[derive(Clone, Debug)]
71pub struct SqlParsedStatement {
72 pub(in crate::db::session::sql) statement: SqlStatement,
73 route: SqlStatementRoute,
74}
75
76impl SqlParsedStatement {
77 pub(in crate::db::session::sql) const fn new(
79 statement: SqlStatement,
80 route: SqlStatementRoute,
81 ) -> Self {
82 Self { statement, route }
83 }
84
85 #[must_use]
87 pub const fn route(&self) -> &SqlStatementRoute {
88 &self.route
89 }
90
91 #[must_use]
93 pub const fn is_mutation(&self) -> bool {
94 matches!(
95 &self.statement,
96 SqlStatement::Insert(_) | SqlStatement::Update(_) | SqlStatement::Delete(_)
97 )
98 }
99
100 pub(in crate::db::session::sql) fn prepare(
102 &self,
103 expected_entity: &'static str,
104 ) -> Result<CorePreparedSqlStatement, QueryError> {
105 prepare_sql_statement(self.statement.clone(), expected_entity)
106 .map_err(QueryError::from_sql_lowering_error)
107 }
108
109 #[inline(never)]
111 pub fn lower_query_lane_for_entity(
112 &self,
113 expected_entity: &'static str,
114 primary_key_field: &str,
115 ) -> Result<LoweredSqlCommand, QueryError> {
116 let lowered = lower_sql_command_from_prepared_statement(
117 self.prepare(expected_entity)?,
118 primary_key_field,
119 )
120 .map_err(QueryError::from_sql_lowering_error)?;
121 let lane = lowered_sql_command_lane(&lowered);
122
123 match lane {
124 LoweredSqlLaneKind::Query | LoweredSqlLaneKind::Explain => Ok(lowered),
125 LoweredSqlLaneKind::Describe
126 | LoweredSqlLaneKind::ShowIndexes
127 | LoweredSqlLaneKind::ShowColumns
128 | LoweredSqlLaneKind::ShowEntities => {
129 Err(QueryError::unsupported_query_lane_dispatch())
130 }
131 }
132 }
133}
134
135impl SqlStatementRoute {
136 #[must_use]
141 pub const fn entity(&self) -> &str {
142 match self {
143 Self::Query { entity }
144 | Self::Insert { entity }
145 | Self::Update { entity }
146 | Self::Explain { entity }
147 | Self::Describe { entity }
148 | Self::ShowIndexes { entity }
149 | Self::ShowColumns { entity } => entity.as_str(),
150 Self::ShowEntities => "",
151 }
152 }
153
154 #[must_use]
156 pub const fn is_explain(&self) -> bool {
157 matches!(self, Self::Explain { .. })
158 }
159
160 #[must_use]
162 pub const fn is_describe(&self) -> bool {
163 matches!(self, Self::Describe { .. })
164 }
165
166 #[must_use]
168 pub const fn is_show_indexes(&self) -> bool {
169 matches!(self, Self::ShowIndexes { .. })
170 }
171
172 #[must_use]
174 pub const fn is_show_columns(&self) -> bool {
175 matches!(self, Self::ShowColumns { .. })
176 }
177
178 #[must_use]
180 pub const fn is_show_entities(&self) -> bool {
181 matches!(self, Self::ShowEntities)
182 }
183}
184
185pub(in crate::db::session::sql) fn sql_statement_route_from_statement(
187 statement: &SqlStatement,
188) -> SqlStatementRoute {
189 match statement {
190 SqlStatement::Select(select) => SqlStatementRoute::Query {
191 entity: select.entity.clone(),
192 },
193 SqlStatement::Delete(delete) => SqlStatementRoute::Query {
194 entity: delete.entity.clone(),
195 },
196 SqlStatement::Insert(insert) => SqlStatementRoute::Insert {
197 entity: insert.entity.clone(),
198 },
199 SqlStatement::Update(update) => SqlStatementRoute::Update {
200 entity: update.entity.clone(),
201 },
202 SqlStatement::Explain(explain) => match &explain.statement {
203 SqlExplainTarget::Select(select) => SqlStatementRoute::Explain {
204 entity: select.entity.clone(),
205 },
206 SqlExplainTarget::Delete(delete) => SqlStatementRoute::Explain {
207 entity: delete.entity.clone(),
208 },
209 },
210 SqlStatement::Describe(describe) => SqlStatementRoute::Describe {
211 entity: describe.entity.clone(),
212 },
213 SqlStatement::ShowIndexes(show_indexes) => SqlStatementRoute::ShowIndexes {
214 entity: show_indexes.entity.clone(),
215 },
216 SqlStatement::ShowColumns(show_columns) => SqlStatementRoute::ShowColumns {
217 entity: show_columns.entity.clone(),
218 },
219 SqlStatement::ShowEntities(_) => SqlStatementRoute::ShowEntities,
220 }
221}