1use {
2 super::{
3 alter::{
4 CreateTableOptions, alter_table, create_index, create_table, delete_function,
5 drop_table, insert_function,
6 },
7 delete::delete,
8 fetch::fetch,
9 insert::insert,
10 query, select,
11 update::Update,
12 validate::{ColumnValidation, validate_unique},
13 },
14 crate::{
15 ast::{BinaryOperator, DataType, Dictionary, Literal, Variable},
16 data::{Key, Row, SCHEMALESS_DOC_COLUMN, Schema, Value},
17 plan::{
18 DictionarySourcePlan, ExprPlan, FilterInputPlan, FilterPlan, ProjectInputPlan,
19 ProjectPlan, ProjectionPlan, QueryPlan, SelectItemPlan, SourcePlan, StatementPlan,
20 TableAliasPlan,
21 },
22 result::{Error, Result},
23 store::{GStore, GStoreMut},
24 },
25 serde::{Deserialize, Serialize},
26 std::{
27 collections::{BTreeMap, HashMap},
28 env::var,
29 fmt::Debug,
30 rc::Rc,
31 },
32 thiserror::Error as ThisError,
33};
34
35#[derive(ThisError, Serialize, Debug, PartialEq, Eq)]
36pub enum ExecuteError {
37 #[error("table not found: {0}")]
38 TableNotFound(String),
39
40 #[error("expected Map value in _doc column")]
41 ExpectedMapValueInDocColumn,
42}
43
44#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
45pub enum Payload {
46 ShowColumns(Vec<(String, DataType)>),
47 Create,
48 Insert(usize),
49 Select {
50 labels: Vec<String>,
51 rows: Vec<Vec<Value>>,
52 },
53 SelectMap(Vec<BTreeMap<String, Value>>),
54 Delete(usize),
55 Update(usize),
56 DropTable(usize),
57 DropFunction,
58 AlterTable,
59 CreateIndex,
60 DropIndex,
61 StartTransaction,
62 Commit,
63 Rollback,
64 ShowVariable(PayloadVariable),
65}
66
67impl Payload {
68 pub fn select(&self) -> Option<impl Iterator<Item = HashMap<&str, &Value>>> {
76 #[derive(iter_enum::Iterator)]
77 enum Iter<I1, I2> {
78 Schema(I1),
79 Schemaless(I2),
80 }
81
82 Some(match self {
83 Payload::Select { labels, rows } => Iter::Schema(rows.iter().map(move |row| {
84 labels
85 .iter()
86 .zip(row.iter())
87 .map(|(label, value)| (label.as_str(), value))
88 .collect::<HashMap<_, _>>()
89 })),
90 Payload::SelectMap(rows) => Iter::Schemaless(rows.iter().map(|row| {
91 row.iter()
92 .map(|(k, v)| (k.as_str(), v))
93 .collect::<HashMap<_, _>>()
94 })),
95 _ => return None,
96 })
97 }
98}
99
100#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
101pub enum PayloadVariable {
102 Tables(Vec<String>),
103 Functions(Vec<String>),
104 Version(String),
105}
106
107pub fn execute<T: GStore + GStoreMut>(
108 storage: &mut T,
109 statement: &StatementPlan,
110) -> Result<Payload> {
111 if matches!(
112 statement,
113 StatementPlan::StartTransaction | StatementPlan::Rollback | StatementPlan::Commit
114 ) {
115 return execute_inner(storage, statement);
116 }
117
118 let autocommit = storage.begin(true)?;
119 let result = execute_inner(storage, statement);
120
121 if !autocommit {
122 return result;
123 }
124
125 match result {
126 Ok(payload) => storage.commit().map(|()| payload),
127 Err(error) => {
128 storage.rollback()?;
129
130 Err(error)
131 }
132 }
133}
134
135fn execute_inner<T: GStore + GStoreMut>(
136 storage: &mut T,
137 statement: &StatementPlan,
138) -> Result<Payload> {
139 match statement {
140 StatementPlan::CreateTable {
143 name,
144 columns,
145 if_not_exists,
146 source,
147 engine,
148 foreign_keys,
149 comment,
150 } => {
151 let options = CreateTableOptions {
152 target_table_name: name,
153 column_defs: columns.as_ref().map(Vec::as_slice),
154 if_not_exists: *if_not_exists,
155 source,
156 engine,
157 foreign_keys,
158 comment,
159 };
160
161 create_table(storage, options).map(|()| Payload::Create)
162 }
163 StatementPlan::DropTable {
164 names,
165 if_exists,
166 cascade,
167 ..
168 } => drop_table(storage, names, *if_exists, *cascade).map(Payload::DropTable),
169 StatementPlan::AlterTable { name, operation } => {
170 alter_table(storage, name, operation).map(|()| Payload::AlterTable)
171 }
172 StatementPlan::CreateIndex {
173 name,
174 table_name,
175 column,
176 } => create_index(storage, table_name, name, column).map(|()| Payload::CreateIndex),
177 StatementPlan::DropIndex { name, table_name } => storage
178 .drop_index(table_name, name)
179 .map(|()| Payload::DropIndex),
180 StatementPlan::StartTransaction => storage.begin(false).map(|_| Payload::StartTransaction),
182 StatementPlan::Commit => storage.commit().map(|()| Payload::Commit),
183 StatementPlan::Rollback => storage.rollback().map(|()| Payload::Rollback),
184 StatementPlan::Insert {
186 table_name,
187 columns,
188 source,
189 } => insert(storage, table_name, columns, source).map(Payload::Insert),
190 StatementPlan::Update {
191 table_name,
192 selection,
193 assignments,
194 } => {
195 let Schema {
196 column_defs,
197 foreign_keys,
198 ..
199 } = storage
200 .fetch_schema(table_name)?
201 .ok_or_else(|| ExecuteError::TableNotFound(table_name.to_owned()))?;
202
203 let all_columns = column_defs.as_deref().map_or_else(
204 || Rc::from(vec![SCHEMALESS_DOC_COLUMN.to_owned()]),
205 |columns| columns.iter().map(|col_def| col_def.name.clone()).collect(),
206 );
207 let columns_to_update: Vec<String> = assignments
208 .iter()
209 .map(|assignment| assignment.id.clone())
210 .collect();
211
212 let update = Update::new(storage, table_name, assignments, column_defs.as_deref())?;
213
214 let foreign_keys = Rc::new(foreign_keys);
215
216 let rows = fetch(storage, table_name, all_columns, selection.as_ref())?
217 .map(|item| {
218 let (key, row) = item?;
219 let row = update.apply(row, foreign_keys.as_ref())?;
220
221 Ok((key, row))
222 })
223 .collect::<Result<Vec<(Key, Row)>>>()?;
224
225 if let Some(column_defs) = column_defs {
226 let column_validation =
227 ColumnValidation::SpecifiedColumns(&column_defs, columns_to_update);
228 let rows = rows.iter().map(|(_, row)| row.values.as_slice());
229
230 validate_unique(storage, table_name, &column_validation, rows)?;
231 }
232
233 let num_rows = rows.len();
234 let rows = rows
235 .into_iter()
236 .map(|(key, row)| (key, row.into_values()))
237 .collect();
238
239 storage
240 .insert_data(table_name, rows)
241 .map(|()| Payload::Update(num_rows))
242 }
243 StatementPlan::Delete {
244 table_name,
245 selection,
246 } => delete(storage, table_name, selection.as_ref()),
247
248 StatementPlan::Query(query) => select::execute(storage, query),
250 StatementPlan::ShowColumns { table_name } => {
251 let Schema { column_defs, .. } = storage
252 .fetch_schema(table_name)?
253 .ok_or_else(|| ExecuteError::TableNotFound(table_name.to_owned()))?;
254
255 let output: Vec<(String, DataType)> = column_defs
256 .unwrap_or_default()
257 .into_iter()
258 .map(|key| (key.name, key.data_type))
259 .collect();
260
261 Ok(Payload::ShowColumns(output))
262 }
263 StatementPlan::ShowIndexes(table_name) => {
264 let query = QueryPlan::Project(ProjectPlan {
265 projection: ProjectionPlan::SelectItems(vec![SelectItemPlan::Wildcard]),
266 input: ProjectInputPlan::Filter(FilterPlan {
267 input: FilterInputPlan::Source(SourcePlan::Dictionary(DictionarySourcePlan {
268 dictionary: Dictionary::GlueIndexes,
269 alias: TableAliasPlan {
270 name: "GLUE_INDEXES".to_owned(),
271 columns: Vec::new(),
272 },
273 })),
274 expr: ExprPlan::BinaryOp {
275 left: Box::new(ExprPlan::Identifier("TABLE_NAME".to_owned())),
276 op: BinaryOperator::Eq,
277 right: Box::new(ExprPlan::Literal(Literal::QuotedString(
278 table_name.to_owned(),
279 ))),
280 },
281 }),
282 });
283
284 let (labels, rows) = query::execute_with_labels(storage, &query, None)?;
285 let rows = rows
286 .map(|row| Ok::<_, Error>(row?.into_values()))
287 .collect::<Result<Vec<_>>>()?;
288
289 if rows.is_empty() {
290 return Err(ExecuteError::TableNotFound(table_name.to_owned()).into());
291 }
292
293 Ok(Payload::Select { labels, rows })
294 }
295 StatementPlan::ShowVariable(variable) => match variable {
296 Variable::Tables => {
297 let query = QueryPlan::Project(ProjectPlan {
298 projection: ProjectionPlan::SelectItems(vec![SelectItemPlan::Expr {
299 expr: ExprPlan::Identifier("TABLE_NAME".to_owned()),
300 label: "TABLE_NAME".to_owned(),
301 }]),
302 input: ProjectInputPlan::Source(SourcePlan::Dictionary(DictionarySourcePlan {
303 dictionary: Dictionary::GlueTables,
304 alias: TableAliasPlan {
305 name: "GLUE_TABLES".to_owned(),
306 columns: Vec::new(),
307 },
308 })),
309 });
310
311 let table_names = query::execute(storage, &query, None)?
312 .map(|row| Ok::<_, Error>(row?.into_values()))
313 .collect::<Result<Vec<Vec<Value>>>>()?
314 .iter()
315 .flat_map(|values| values.iter().map(Into::into))
316 .collect::<Vec<_>>();
317
318 Ok(Payload::ShowVariable(PayloadVariable::Tables(table_names)))
319 }
320 Variable::Functions => {
321 let mut function_desc: Vec<_> = storage
322 .fetch_all_functions()?
323 .iter()
324 .map(|f| f.to_str())
325 .collect();
326 function_desc.sort();
327 Ok(Payload::ShowVariable(PayloadVariable::Functions(
328 function_desc,
329 )))
330 }
331 Variable::Version => {
332 let version = var("CARGO_PKG_VERSION")
333 .unwrap_or_else(|_| env!("CARGO_PKG_VERSION").to_owned());
334 let payload = Payload::ShowVariable(PayloadVariable::Version(version));
335
336 Ok(payload)
337 }
338 },
339 StatementPlan::CreateFunction {
340 or_replace,
341 name,
342 args,
343 return_,
344 } => insert_function(storage, name, args, *or_replace, return_).map(|()| Payload::Create),
345 StatementPlan::DropFunction { if_exists, names } => {
346 delete_function(storage, names, *if_exists).map(|()| Payload::DropFunction)
347 }
348 }
349}