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