operator/statement/
show.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use common_error::ext::BoxedError;
16use common_meta::key::schema_name::SchemaNameKey;
17use common_query::Output;
18use common_telemetry::tracing;
19use partition::manager::PartitionInfo;
20use session::context::QueryContextRef;
21use session::table_name::table_idents_to_full_name;
22use snafu::{OptionExt, ResultExt};
23use sql::ast::ObjectNamePartExt;
24use sql::statements::OptionMap;
25use sql::statements::create::Partitions;
26use sql::statements::show::{
27    ShowColumns, ShowCreateFlow, ShowCreateView, ShowDatabases, ShowFlows, ShowIndex, ShowKind,
28    ShowProcessList, ShowRegion, ShowTableStatus, ShowTables, ShowVariables, ShowViews,
29};
30use table::TableRef;
31use table::metadata::{TableInfo, TableType};
32use table::table_name::TableName;
33
34use crate::error::{
35    self, CatalogSnafu, ExecLogicalPlanSnafu, ExecuteStatementSnafu, ExternalSnafu,
36    FindViewInfoSnafu, InvalidSqlSnafu, Result, TableMetadataManagerSnafu, ViewInfoNotFoundSnafu,
37    ViewNotFoundSnafu,
38};
39use crate::statement::StatementExecutor;
40
41impl StatementExecutor {
42    #[tracing::instrument(skip_all)]
43    pub(super) async fn show_databases(
44        &self,
45        stmt: ShowDatabases,
46        query_ctx: QueryContextRef,
47    ) -> Result<Output> {
48        query::sql::show_databases(stmt, &self.query_engine, &self.catalog_manager, query_ctx)
49            .await
50            .context(ExecuteStatementSnafu)
51    }
52
53    #[tracing::instrument(skip_all)]
54    pub(super) async fn show_tables(
55        &self,
56        stmt: ShowTables,
57        query_ctx: QueryContextRef,
58    ) -> Result<Output> {
59        query::sql::show_tables(stmt, &self.query_engine, &self.catalog_manager, query_ctx)
60            .await
61            .context(ExecuteStatementSnafu)
62    }
63
64    #[tracing::instrument(skip_all)]
65    pub(super) async fn show_table_status(
66        &self,
67        stmt: ShowTableStatus,
68        query_ctx: QueryContextRef,
69    ) -> Result<Output> {
70        query::sql::show_table_status(stmt, &self.query_engine, &self.catalog_manager, query_ctx)
71            .await
72            .context(ExecuteStatementSnafu)
73    }
74
75    #[tracing::instrument(skip_all)]
76    pub(super) async fn show_columns(
77        &self,
78        stmt: ShowColumns,
79        query_ctx: QueryContextRef,
80    ) -> Result<Output> {
81        query::sql::show_columns(stmt, &self.query_engine, &self.catalog_manager, query_ctx)
82            .await
83            .context(ExecuteStatementSnafu)
84    }
85
86    #[tracing::instrument(skip_all)]
87    pub(super) async fn show_index(
88        &self,
89        stmt: ShowIndex,
90        query_ctx: QueryContextRef,
91    ) -> Result<Output> {
92        query::sql::show_index(stmt, &self.query_engine, &self.catalog_manager, query_ctx)
93            .await
94            .context(ExecuteStatementSnafu)
95    }
96
97    pub(super) async fn show_region(
98        &self,
99        stmt: ShowRegion,
100        query_ctx: QueryContextRef,
101    ) -> Result<Output> {
102        query::sql::show_region(stmt, &self.query_engine, &self.catalog_manager, query_ctx)
103            .await
104            .context(ExecuteStatementSnafu)
105    }
106
107    #[tracing::instrument(skip_all)]
108    pub async fn show_create_database(
109        &self,
110        database_name: &str,
111        opts: OptionMap,
112    ) -> Result<Output> {
113        query::sql::show_create_database(database_name, opts).context(ExecuteStatementSnafu)
114    }
115
116    #[tracing::instrument(skip_all)]
117    pub async fn show_create_table(
118        &self,
119        table_name: TableName,
120        table: TableRef,
121        query_ctx: QueryContextRef,
122    ) -> Result<Output> {
123        let table_info = table.table_info();
124        if table_info.table_type != TableType::Base {
125            return error::ShowCreateTableBaseOnlySnafu {
126                table_name: table_name.to_string(),
127                table_type: table_info.table_type,
128            }
129            .fail();
130        }
131
132        let schema_options = self
133            .table_metadata_manager
134            .schema_manager()
135            .get(SchemaNameKey {
136                catalog: &table_name.catalog_name,
137                schema: &table_name.schema_name,
138            })
139            .await
140            .context(TableMetadataManagerSnafu)?
141            .map(|v| v.into_inner());
142
143        let partitions = self
144            .partition_manager
145            .find_table_partitions(table_info.table_id())
146            .await
147            .context(error::FindTablePartitionRuleSnafu {
148                table_name: &table_name.table_name,
149            })?;
150
151        let partitions = create_partitions_stmt(&table_info, partitions)?;
152
153        query::sql::show_create_table(table, schema_options, partitions, query_ctx)
154            .context(ExecuteStatementSnafu)
155    }
156
157    #[tracing::instrument(skip_all)]
158    pub async fn show_create_table_for_pg(
159        &self,
160        table_name: TableName,
161        table: TableRef,
162        query_ctx: QueryContextRef,
163    ) -> Result<Output> {
164        let table_info = table.table_info();
165        if table_info.table_type != TableType::Base {
166            return error::ShowCreateTableBaseOnlySnafu {
167                table_name: table_name.to_string(),
168                table_type: table_info.table_type,
169            }
170            .fail();
171        }
172
173        query::sql::show_create_foreign_table_for_pg(table, query_ctx)
174            .context(ExecuteStatementSnafu)
175    }
176
177    #[tracing::instrument(skip_all)]
178    pub async fn show_create_view(
179        &self,
180        show: ShowCreateView,
181        query_ctx: QueryContextRef,
182    ) -> Result<Output> {
183        let (catalog, schema, view) = table_idents_to_full_name(&show.view_name, &query_ctx)
184            .map_err(BoxedError::new)
185            .context(ExternalSnafu)?;
186
187        let table_ref = self
188            .catalog_manager
189            .table(&catalog, &schema, &view, Some(&query_ctx))
190            .await
191            .context(CatalogSnafu)?
192            .context(ViewNotFoundSnafu { view_name: &view })?;
193
194        let view_id = table_ref.table_info().ident.table_id;
195
196        let view_info = self
197            .view_info_manager
198            .get(view_id)
199            .await
200            .context(FindViewInfoSnafu { view_name: &view })?
201            .context(ViewInfoNotFoundSnafu { view_name: &view })?;
202
203        query::sql::show_create_view(show.view_name, &view_info.definition, query_ctx)
204            .context(error::ExecuteStatementSnafu)
205    }
206
207    #[tracing::instrument(skip_all)]
208    pub(super) async fn show_views(
209        &self,
210        stmt: ShowViews,
211        query_ctx: QueryContextRef,
212    ) -> Result<Output> {
213        query::sql::show_views(stmt, &self.query_engine, &self.catalog_manager, query_ctx)
214            .await
215            .context(ExecuteStatementSnafu)
216    }
217
218    #[tracing::instrument(skip_all)]
219    pub(super) async fn show_flows(
220        &self,
221        stmt: ShowFlows,
222        query_ctx: QueryContextRef,
223    ) -> Result<Output> {
224        query::sql::show_flows(stmt, &self.query_engine, &self.catalog_manager, query_ctx)
225            .await
226            .context(ExecuteStatementSnafu)
227    }
228
229    #[cfg(feature = "enterprise")]
230    #[tracing::instrument(skip_all)]
231    pub(super) async fn show_triggers(
232        &self,
233        stmt: sql::statements::show::trigger::ShowTriggers,
234        query_ctx: QueryContextRef,
235    ) -> Result<Output> {
236        query::sql::show_triggers(stmt, &self.query_engine, &self.catalog_manager, query_ctx)
237            .await
238            .context(ExecuteStatementSnafu)
239    }
240
241    #[tracing::instrument(skip_all)]
242    pub async fn show_create_flow(
243        &self,
244        show: ShowCreateFlow,
245        query_ctx: QueryContextRef,
246    ) -> Result<Output> {
247        let obj_name = &show.flow_name;
248        let (catalog_name, flow_name) = match &obj_name.0[..] {
249            [flow] => (query_ctx.current_catalog().to_string(), flow.to_string_unquoted()),
250            [catalog, flow] => (catalog.to_string_unquoted(), flow.to_string_unquoted()),
251            _ => {
252                return InvalidSqlSnafu {
253                    err_msg: format!(
254                        "expect flow name to be <catalog>.<flow_name> or <flow_name>, actual: {obj_name}",
255                    ),
256                }
257                .fail()
258            }
259        };
260
261        let flow_name_val = self
262            .flow_metadata_manager
263            .flow_name_manager()
264            .get(&catalog_name, &flow_name)
265            .await
266            .context(error::TableMetadataManagerSnafu)?
267            .context(error::FlowNotFoundSnafu {
268                flow_name: &flow_name,
269            })?;
270
271        let flow_val = self
272            .flow_metadata_manager
273            .flow_info_manager()
274            .get(flow_name_val.flow_id())
275            .await
276            .context(error::TableMetadataManagerSnafu)?
277            .context(error::FlowNotFoundSnafu {
278                flow_name: &flow_name,
279            })?;
280
281        query::sql::show_create_flow(obj_name.clone(), flow_val, query_ctx)
282            .context(error::ExecuteStatementSnafu)
283    }
284
285    #[cfg(feature = "enterprise")]
286    #[tracing::instrument(skip_all)]
287    pub async fn show_create_trigger(
288        &self,
289        show: sql::statements::show::trigger::ShowCreateTrigger,
290        query_ctx: QueryContextRef,
291    ) -> Result<Output> {
292        let Some(trigger_querier) = self.trigger_querier.as_ref() else {
293            return error::MissingTriggerQuerierSnafu.fail();
294        };
295
296        let obj_name = &show.trigger_name;
297        let (catalog_name, trigger_name) = match &obj_name.0[..] {
298            [trigger] => (query_ctx.current_catalog().to_string(), trigger.to_string_unquoted()),
299            [catalog, trigger] => (catalog.to_string_unquoted(), trigger.to_string_unquoted()),
300            _ => {
301                return InvalidSqlSnafu {
302                    err_msg: format!(
303                        "expect trigger name to be <catalog>.<trigger_name> or <trigger_name>, actual: {obj_name}",
304                    ),
305                }
306                .fail()
307            }
308        };
309        trigger_querier
310            .show_create_trigger(&catalog_name, &trigger_name, &query_ctx)
311            .await
312            .context(error::TriggerQuerierSnafu)
313    }
314
315    #[tracing::instrument(skip_all)]
316    pub fn show_variable(&self, stmt: ShowVariables, query_ctx: QueryContextRef) -> Result<Output> {
317        query::sql::show_variable(stmt, query_ctx).context(error::ExecuteStatementSnafu)
318    }
319
320    #[tracing::instrument(skip_all)]
321    pub async fn show_collation(
322        &self,
323        kind: ShowKind,
324        query_ctx: QueryContextRef,
325    ) -> Result<Output> {
326        query::sql::show_collations(kind, &self.query_engine, &self.catalog_manager, query_ctx)
327            .await
328            .context(error::ExecuteStatementSnafu)
329    }
330
331    #[tracing::instrument(skip_all)]
332    pub async fn show_charset(&self, kind: ShowKind, query_ctx: QueryContextRef) -> Result<Output> {
333        query::sql::show_charsets(kind, &self.query_engine, &self.catalog_manager, query_ctx)
334            .await
335            .context(error::ExecuteStatementSnafu)
336    }
337
338    #[tracing::instrument(skip_all)]
339    pub async fn show_status(&self, query_ctx: QueryContextRef) -> Result<Output> {
340        query::sql::show_status(query_ctx)
341            .await
342            .context(error::ExecuteStatementSnafu)
343    }
344    pub async fn show_search_path(&self, query_ctx: QueryContextRef) -> Result<Output> {
345        query::sql::show_search_path(query_ctx)
346            .await
347            .context(error::ExecuteStatementSnafu)
348    }
349
350    pub async fn show_processlist(
351        &self,
352        stmt: ShowProcessList,
353        query_ctx: QueryContextRef,
354    ) -> Result<Output> {
355        query::sql::show_processlist(stmt, &self.query_engine, &self.catalog_manager, query_ctx)
356            .await
357            .context(ExecLogicalPlanSnafu)
358    }
359}
360
361pub(crate) fn create_partitions_stmt(
362    table_info: &TableInfo,
363    partitions: Vec<PartitionInfo>,
364) -> Result<Option<Partitions>> {
365    if partitions.is_empty() {
366        return Ok(None);
367    }
368
369    let column_list = table_info
370        .meta
371        .partition_column_names()
372        .map(|name| name[..].into())
373        .collect();
374
375    let exprs = partitions
376        .iter()
377        .filter_map(|partition| {
378            partition
379                .partition_expr
380                .as_ref()
381                .map(|expr| expr.to_parser_expr())
382        })
383        .collect();
384
385    Ok(Some(Partitions { column_list, exprs }))
386}