1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
use crate::{DatabaseInner, ExecuteError, Payload, Row, Schema, Value};
use crate::{Glue, Result};
use sqlparser::ast::ObjectName;
impl Glue {
pub async fn explain(&self, object: &ObjectName) -> Result<Payload> {
let mut name_vec = object.0.clone();
let (store_name, opt_table_name) = match name_vec.len() {
2 => (
Some(name_vec.remove(0).value),
Some(name_vec.remove(0).value),
),
1 => {
let name = name_vec.remove(0).value;
if name == "ALL" {
let databases: Vec<Row> = self
.get_database_list()
.into_iter()
.map(|name| Row(vec![name.clone().into()]))
.collect();
return Ok(Payload::Select {
labels: vec![String::from("database")],
rows: databases,
});
}
if name == "ALL_TABLE" {
let mut tables = vec![];
for db_name in self.get_database_list().into_iter() {
tables.extend(
self.get_database(&Some(db_name.clone()))?
.get_tables()
.await?
.iter()
.map(|table| Row(vec![db_name.clone().into(), table.clone()])),
);
}
return Ok(Payload::Select {
labels: vec![String::from("database"), String::from("table")],
rows: tables,
});
} else if self.get_database_list().contains(&&name) {
(Some(name), None)
} else {
(None, Some(name))
}
}
_ => return Err(ExecuteError::ObjectNotRecognised.into()),
};
let database = self.get_database(&store_name)?;
if let Some(table_name) = opt_table_name {
let Schema { column_defs, .. } = database
.fetch_schema(&table_name)
.await?
.ok_or(ExecuteError::ObjectNotRecognised)?;
let columns = column_defs
.iter()
.map(|column| {
(
column.name.clone().into(),
column.data_type.to_string().into(),
)
})
.map(|(name, data_type)| Row(vec![name, data_type]))
.collect();
Ok(Payload::Select {
labels: vec![String::from("column"), String::from("data_type")],
rows: columns,
})
} else {
Ok(Payload::Select {
labels: vec![String::from("table")],
rows: database
.get_tables()
.await?
.into_iter()
.map(|table| Row(vec![table]))
.collect(),
})
}
}
}
impl DatabaseInner {
async fn get_tables(&self) -> Result<Vec<Value>> {
Ok(self
.scan_schemas()
.await?
.into_iter()
.map(|Schema { table_name, .. }| table_name.into())
.collect())
}
}