Skip to main content

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