multisql/executor/query/
mod.rs1mod get_columns;
2mod get_data;
3mod get_rows;
4mod select;
5mod set_expr;
6
7pub use select::{join::*, ManualError, Plan, PlanError, SelectError};
8use {
9 crate::{
10 recipe::{MetaRecipe, RecipeUtilities},
11 result::Result,
12 types::LabelsAndRows,
13 Cast, Glue, Value,
14 },
15 async_recursion::async_recursion,
16 serde::Serialize,
17 sqlparser::ast::{Cte, Query, TableAlias, With},
18 thiserror::Error as ThisError,
19};
20
21const ENSURE_SIZE: bool = true;
22
23#[derive(ThisError, Serialize, Debug, PartialEq)]
24pub enum QueryError {
25 #[error("query not supported")]
26 QueryNotSupported,
27 #[error("values does not support columns, aggregates or subqueries")]
28 MissingComponentsForValues,
29 #[error("limit does not support columns, aggregates or subqueries")]
30 MissingComponentsForLimit,
31 #[error("offset does not support columns, aggregates or subqueries")]
32 MissingComponentsForOffset,
33 #[error("expected values but found none")]
34 NoValues,
35 #[error(
36 "UNION/EXCEPT/INTERSECT columns misaligned, sides should have an equal number of columns"
37 )]
38 OperationColumnsMisaligned,
39}
40
41impl Glue {
42 #[async_recursion(?Send)]
43 pub async fn ast_query(&mut self, query: Query) -> Result<LabelsAndRows> {
44 let Query {
45 body,
46 order_by,
47 limit,
48 offset,
49 with,
50 fetch: _,
52 lock: _,
53 } = query;
54
55 let limit: Option<usize> = limit
56 .map(|expression| {
57 MetaRecipe::new(expression)?
58 .simplify_by_tempdb(&self.tempdb)?
59 .confirm_or_err(QueryError::MissingComponentsForLimit.into())?
60 .cast()
61 })
62 .transpose()?;
63 let offset: Option<usize> = offset
64 .map(|offset| {
65 MetaRecipe::new(offset.value)?
66 .simplify_by_tempdb(&self.tempdb)?
67 .confirm_or_err(QueryError::MissingComponentsForOffset.into())?
68 .cast()
69 })
70 .transpose()?;
71
72 if let Some(with) = with {
73 let With {
74 recursive: _, cte_tables,
76 } = with;
77 for cte in cte_tables.into_iter() {
78 let Cte {
79 alias,
80 query,
81 from: _, } = cte;
83 let TableAlias {
84 name,
85 columns: _, } = alias;
87 let name = name.value;
88 let data = self.ast_query(query).await?;
89 self.tempdb.set_table(name, data);
90 }
91 }
92
93 let (mut labels, mut rows) = self.from_body(body, order_by).await?;
94
95 if let Some(offset) = offset {
96 rows.drain(0..offset);
97 }
98 if let Some(limit) = limit {
99 rows.truncate(limit);
100 }
101 if ENSURE_SIZE {
102 let row_width = rows
103 .iter()
104 .map(|values_row| values_row.len())
105 .max()
106 .unwrap_or(0);
107 if row_width > 0 {
108 rows = rows
109 .into_iter()
110 .map(|mut row| {
111 row.resize(row_width, Value::Null);
112 row
113 })
114 .collect();
115 labels.resize(row_width, String::new())
116 };
117 }
118 Ok((labels, rows))
119 }
120}