1mod show_create_table;
16
17use std::collections::HashMap;
18use std::ops::ControlFlow;
19use std::sync::Arc;
20
21use catalog::CatalogManagerRef;
22use catalog::information_schema::{
23 CHARACTER_SETS, COLLATIONS, COLUMNS, FLOW_STATISTICS, FLOWS, REGION_PEERS, SCHEMATA,
24 STATISTICS, TABLES, VIEWS, columns, flow_statistics, flows, process_list, region_peers,
25 schemata, statistics, tables,
26};
27use common_catalog::consts::{
28 INFORMATION_SCHEMA_NAME, SEMANTIC_TYPE_FIELD, SEMANTIC_TYPE_PRIMARY_KEY,
29 SEMANTIC_TYPE_TIME_INDEX,
30};
31use common_catalog::format_full_table_name;
32use common_datasource::file_format::{FileFormat, Format, infer_schemas};
33use common_datasource::lister::{Lister, Source};
34use common_datasource::object_store::{LocalFileAccess, build_backend_with_path};
35use common_meta::SchemaOptions;
36use common_meta::ddl::create_flow::FlowType;
37use common_meta::key::flow::flow_info::FlowInfoValue;
38use common_query::Output;
39use common_query::prelude::greptime_timestamp;
40use common_recordbatch::RecordBatches;
41use common_recordbatch::adapter::RecordBatchStreamAdapter;
42use common_time::Timestamp;
43use common_time::timezone::get_timezone;
44use datafusion::dataframe::DataFrame;
45use datafusion::prelude::SessionContext;
46use datafusion_expr::{Expr, SortExpr, col, lit};
47use datatypes::prelude::*;
48use datatypes::schema::{ColumnDefaultConstraint, ColumnSchema, Schema};
49use datatypes::vectors::StringVector;
50use itertools::Itertools;
51use object_store::ObjectStore;
52use once_cell::sync::Lazy;
53use regex::Regex;
54use session::context::{Channel, QueryContextRef};
55pub use show_create_table::create_table_stmt;
56use snafu::{OptionExt, ResultExt, ensure};
57use sql::ast::{Ident, visit_expressions_mut};
58use sql::parser::ParserContext;
59use sql::statements::OptionMap;
60use sql::statements::create::{CreateDatabase, CreateFlow, CreateView, Partitions, SqlOrTql};
61use sql::statements::show::{
62 ShowColumns, ShowDatabases, ShowFlowStatus, ShowFlows, ShowIndex, ShowKind, ShowProcessList,
63 ShowRegion, ShowTableStatus, ShowTables, ShowVariables, ShowViews,
64};
65use sql::statements::statement::Statement;
66use sqlparser::ast::ObjectName;
67use store_api::metric_engine_consts::{is_metric_engine, is_metric_engine_internal_column};
68use table::TableRef;
69use table::metadata::TableInfoRef;
70use table::requests::{FILE_TABLE_LOCATION_KEY, FILE_TABLE_PATTERN_KEY};
71
72use crate::QueryEngineRef;
73use crate::error::{self, Result, UnsupportedVariableSnafu};
74use crate::planner::DfLogicalPlanner;
75
76const SCHEMAS_COLUMN: &str = "Database";
77const OPTIONS_COLUMN: &str = "Options";
78const VIEWS_COLUMN: &str = "Views";
79const FLOWS_COLUMN: &str = "Flows";
80const FIELD_COLUMN: &str = "Field";
81const TABLE_TYPE_COLUMN: &str = "Table_type";
82
83const COLUMN_NAME_COLUMN: &str = "Column";
84const COLUMN_GREPTIME_TYPE_COLUMN: &str = "Greptime_type";
85const COLUMN_TYPE_COLUMN: &str = "Type";
86const COLUMN_KEY_COLUMN: &str = "Key";
87const COLUMN_EXTRA_COLUMN: &str = "Extra";
88const COLUMN_PRIVILEGES_COLUMN: &str = "Privileges";
89const COLUMN_COLLATION_COLUMN: &str = "Collation";
90const COLUMN_NULLABLE_COLUMN: &str = "Null";
91const COLUMN_DEFAULT_COLUMN: &str = "Default";
92const COLUMN_COMMENT_COLUMN: &str = "Comment";
93const COLUMN_SEMANTIC_TYPE_COLUMN: &str = "Semantic Type";
94
95const YES_STR: &str = "YES";
96const NO_STR: &str = "NO";
97const PRI_KEY: &str = "PRI";
98
99const INDEX_TABLE_COLUMN: &str = "Table";
101const INDEX_NONT_UNIQUE_COLUMN: &str = "Non_unique";
102const INDEX_CARDINALITY_COLUMN: &str = "Cardinality";
103const INDEX_SUB_PART_COLUMN: &str = "Sub_part";
104const INDEX_PACKED_COLUMN: &str = "Packed";
105const INDEX_INDEX_TYPE_COLUMN: &str = "Index_type";
106const INDEX_COMMENT_COLUMN: &str = "Index_comment";
107const INDEX_VISIBLE_COLUMN: &str = "Visible";
108const INDEX_EXPRESSION_COLUMN: &str = "Expression";
109const INDEX_KEY_NAME_COLUMN: &str = "Key_name";
110const INDEX_SEQ_IN_INDEX_COLUMN: &str = "Seq_in_index";
111const INDEX_COLUMN_NAME_COLUMN: &str = "Column_name";
112
113pub static DESCRIBE_TABLE_OUTPUT_SCHEMA: Lazy<Arc<Schema>> = Lazy::new(|| {
114 Arc::new(Schema::new(vec![
115 ColumnSchema::new(
116 COLUMN_NAME_COLUMN,
117 ConcreteDataType::string_datatype(),
118 false,
119 ),
120 ColumnSchema::new(
121 COLUMN_TYPE_COLUMN,
122 ConcreteDataType::string_datatype(),
123 false,
124 ),
125 ColumnSchema::new(COLUMN_KEY_COLUMN, ConcreteDataType::string_datatype(), true),
126 ColumnSchema::new(
127 COLUMN_NULLABLE_COLUMN,
128 ConcreteDataType::string_datatype(),
129 false,
130 ),
131 ColumnSchema::new(
132 COLUMN_DEFAULT_COLUMN,
133 ConcreteDataType::string_datatype(),
134 false,
135 ),
136 ColumnSchema::new(
137 COLUMN_SEMANTIC_TYPE_COLUMN,
138 ConcreteDataType::string_datatype(),
139 false,
140 ),
141 ]))
142});
143
144static SHOW_CREATE_DATABASE_OUTPUT_SCHEMA: Lazy<Arc<Schema>> = Lazy::new(|| {
145 Arc::new(Schema::new(vec![
146 ColumnSchema::new("Database", ConcreteDataType::string_datatype(), false),
147 ColumnSchema::new(
148 "Create Database",
149 ConcreteDataType::string_datatype(),
150 false,
151 ),
152 ]))
153});
154
155static SHOW_CREATE_TABLE_OUTPUT_SCHEMA: Lazy<Arc<Schema>> = Lazy::new(|| {
156 Arc::new(Schema::new(vec![
157 ColumnSchema::new("Table", ConcreteDataType::string_datatype(), false),
158 ColumnSchema::new("Create Table", ConcreteDataType::string_datatype(), false),
159 ]))
160});
161
162static SHOW_CREATE_FLOW_OUTPUT_SCHEMA: Lazy<Arc<Schema>> = Lazy::new(|| {
163 Arc::new(Schema::new(vec![
164 ColumnSchema::new("Flow", ConcreteDataType::string_datatype(), false),
165 ColumnSchema::new("Create Flow", ConcreteDataType::string_datatype(), false),
166 ]))
167});
168
169static SHOW_CREATE_VIEW_OUTPUT_SCHEMA: Lazy<Arc<Schema>> = Lazy::new(|| {
170 Arc::new(Schema::new(vec![
171 ColumnSchema::new("View", ConcreteDataType::string_datatype(), false),
172 ColumnSchema::new("Create View", ConcreteDataType::string_datatype(), false),
173 ]))
174});
175
176pub async fn show_databases(
177 stmt: ShowDatabases,
178 query_engine: &QueryEngineRef,
179 catalog_manager: &CatalogManagerRef,
180 query_ctx: QueryContextRef,
181) -> Result<Output> {
182 let dataframe =
183 show_databases_dataframe(&stmt, query_engine, catalog_manager, query_ctx).await?;
184 dataframe_to_output(dataframe).await
185}
186
187pub async fn show_databases_dataframe(
189 stmt: &ShowDatabases,
190 query_engine: &QueryEngineRef,
191 catalog_manager: &CatalogManagerRef,
192 query_ctx: QueryContextRef,
193) -> Result<DataFrame> {
194 let projects = if stmt.full {
195 vec![
196 (schemata::SCHEMA_NAME, SCHEMAS_COLUMN),
197 (schemata::SCHEMA_OPTS, OPTIONS_COLUMN),
198 ]
199 } else {
200 vec![(schemata::SCHEMA_NAME, SCHEMAS_COLUMN)]
201 };
202
203 let filters = vec![col(schemata::CATALOG_NAME).eq(lit(query_ctx.current_catalog()))];
204 let like_field = Some(schemata::SCHEMA_NAME);
205 let sort = vec![col(schemata::SCHEMA_NAME).sort(true, true)];
206
207 query_from_information_schema_dataframe(
208 query_engine,
209 catalog_manager,
210 query_ctx,
211 SCHEMATA,
212 vec![],
213 projects,
214 filters,
215 like_field,
216 sort,
217 &stmt.kind,
218 )
219 .await
220}
221
222fn replace_column_in_expr(expr: &mut sqlparser::ast::Expr, from_column: &str, to_column: &str) {
225 let _ = visit_expressions_mut(expr, |e| {
226 match e {
227 sqlparser::ast::Expr::Identifier(ident)
228 if ident.value.eq_ignore_ascii_case(from_column) =>
229 {
230 ident.value = to_column.to_string();
231 }
232 sqlparser::ast::Expr::CompoundIdentifier(idents) => {
233 if let Some(last) = idents.last_mut()
234 && last.value.eq_ignore_ascii_case(from_column)
235 {
236 last.value = to_column.to_string();
237 }
238 }
239 _ => {}
240 }
241 ControlFlow::<()>::Continue(())
242 });
243}
244
245#[allow(clippy::too_many_arguments)]
253async fn query_from_information_schema_table(
254 query_engine: &QueryEngineRef,
255 catalog_manager: &CatalogManagerRef,
256 query_ctx: QueryContextRef,
257 table_name: &str,
258 select: Vec<Expr>,
259 projects: Vec<(&str, &str)>,
260 filters: Vec<Expr>,
261 like_field: Option<&str>,
262 sort: Vec<SortExpr>,
263 kind: ShowKind,
264) -> Result<Output> {
265 let dataframe = query_from_information_schema_dataframe(
266 query_engine,
267 catalog_manager,
268 query_ctx,
269 table_name,
270 select,
271 projects,
272 filters,
273 like_field,
274 sort,
275 &kind,
276 )
277 .await?;
278 dataframe_to_output(dataframe).await
279}
280
281async fn dataframe_to_output(dataframe: DataFrame) -> Result<Output> {
282 let stream = dataframe.execute_stream().await?;
283 Ok(Output::new_with_stream(Box::pin(
284 RecordBatchStreamAdapter::try_new(stream).context(error::CreateRecordBatchSnafu)?,
285 )))
286}
287
288#[allow(clippy::too_many_arguments)]
292async fn query_from_information_schema_dataframe(
293 query_engine: &QueryEngineRef,
294 catalog_manager: &CatalogManagerRef,
295 query_ctx: QueryContextRef,
296 table_name: &str,
297 select: Vec<Expr>,
298 projects: Vec<(&str, &str)>,
299 filters: Vec<Expr>,
300 like_field: Option<&str>,
301 sort: Vec<SortExpr>,
302 kind: &ShowKind,
303) -> Result<DataFrame> {
304 let table = catalog_manager
305 .table(
306 query_ctx.current_catalog(),
307 INFORMATION_SCHEMA_NAME,
308 table_name,
309 Some(&query_ctx),
310 )
311 .await
312 .context(error::CatalogSnafu)?
313 .with_context(|| error::TableNotFoundSnafu {
314 table: format_full_table_name(
315 query_ctx.current_catalog(),
316 INFORMATION_SCHEMA_NAME,
317 table_name,
318 ),
319 })?;
320
321 let dataframe = query_engine.read_table(table)?;
322
323 let dataframe = filters.into_iter().try_fold(dataframe, |df, expr| {
325 df.filter(expr).context(error::PlanSqlSnafu)
326 })?;
327
328 let dataframe = if let (ShowKind::Like(ident), Some(field)) = (&kind, like_field) {
330 dataframe
331 .filter(col(field).like(lit(ident.value.clone())))
332 .context(error::PlanSqlSnafu)?
333 } else {
334 dataframe
335 };
336
337 let dataframe = if sort.is_empty() {
339 dataframe
340 } else {
341 dataframe.sort(sort).context(error::PlanSqlSnafu)?
342 };
343
344 let dataframe = if select.is_empty() {
346 if projects.is_empty() {
347 dataframe
348 } else {
349 let projection = projects
350 .iter()
351 .map(|x| col(x.0).alias(x.1))
352 .collect::<Vec<_>>();
353 dataframe.select(projection).context(error::PlanSqlSnafu)?
354 }
355 } else {
356 dataframe.select(select).context(error::PlanSqlSnafu)?
357 };
358
359 let dataframe = projects
361 .into_iter()
362 .try_fold(dataframe, |df, (column, renamed_column)| {
363 df.with_column_renamed(column, renamed_column)
364 .context(error::PlanSqlSnafu)
365 })?;
366
367 let dataframe = match kind {
368 ShowKind::All | ShowKind::Like(_) => {
369 dataframe
371 }
372 ShowKind::Where(filter) => {
373 let view = dataframe.into_view();
376 let dataframe = SessionContext::new_with_state(
377 query_engine
378 .engine_context(query_ctx.clone())
379 .state()
380 .clone(),
381 )
382 .read_table(view)?;
383
384 let planner = query_engine.planner();
385 let planner = planner
386 .as_any()
387 .downcast_ref::<DfLogicalPlanner>()
388 .expect("Must be the datafusion planner");
389
390 let filter = planner
391 .sql_to_expr(filter.clone(), dataframe.schema(), false, query_ctx)
392 .await?;
393
394 dataframe.filter(filter).context(error::PlanSqlSnafu)?
396 }
397 };
398
399 Ok(dataframe)
400}
401
402pub async fn show_columns(
404 stmt: ShowColumns,
405 query_engine: &QueryEngineRef,
406 catalog_manager: &CatalogManagerRef,
407 query_ctx: QueryContextRef,
408) -> Result<Output> {
409 let dataframe = show_columns_dataframe(&stmt, query_engine, catalog_manager, query_ctx).await?;
410 dataframe_to_output(dataframe).await
411}
412
413pub async fn show_columns_dataframe(
415 stmt: &ShowColumns,
416 query_engine: &QueryEngineRef,
417 catalog_manager: &CatalogManagerRef,
418 query_ctx: QueryContextRef,
419) -> Result<DataFrame> {
420 let schema_name = if let Some(database) = &stmt.database {
421 database.clone()
422 } else {
423 query_ctx.current_schema()
424 };
425
426 let projects = if stmt.full {
427 vec![
428 (columns::COLUMN_NAME, FIELD_COLUMN),
429 (columns::DATA_TYPE, COLUMN_TYPE_COLUMN),
430 (columns::COLLATION_NAME, COLUMN_COLLATION_COLUMN),
431 (columns::IS_NULLABLE, COLUMN_NULLABLE_COLUMN),
432 (columns::COLUMN_KEY, COLUMN_KEY_COLUMN),
433 (columns::COLUMN_DEFAULT, COLUMN_DEFAULT_COLUMN),
434 (columns::COLUMN_COMMENT, COLUMN_COMMENT_COLUMN),
435 (columns::PRIVILEGES, COLUMN_PRIVILEGES_COLUMN),
436 (columns::EXTRA, COLUMN_EXTRA_COLUMN),
437 (columns::GREPTIME_DATA_TYPE, COLUMN_GREPTIME_TYPE_COLUMN),
438 ]
439 } else {
440 vec![
441 (columns::COLUMN_NAME, FIELD_COLUMN),
442 (columns::DATA_TYPE, COLUMN_TYPE_COLUMN),
443 (columns::IS_NULLABLE, COLUMN_NULLABLE_COLUMN),
444 (columns::COLUMN_KEY, COLUMN_KEY_COLUMN),
445 (columns::COLUMN_DEFAULT, COLUMN_DEFAULT_COLUMN),
446 (columns::EXTRA, COLUMN_EXTRA_COLUMN),
447 (columns::GREPTIME_DATA_TYPE, COLUMN_GREPTIME_TYPE_COLUMN),
448 ]
449 };
450
451 let filters = vec![
452 col(columns::TABLE_NAME).eq(lit(&stmt.table)),
453 col(columns::TABLE_SCHEMA).eq(lit(schema_name.clone())),
454 col(columns::TABLE_CATALOG).eq(lit(query_ctx.current_catalog())),
455 ];
456 let like_field = Some(columns::COLUMN_NAME);
457 let sort = vec![col(columns::COLUMN_NAME).sort(true, true)];
458
459 query_from_information_schema_dataframe(
460 query_engine,
461 catalog_manager,
462 query_ctx,
463 COLUMNS,
464 vec![],
465 projects,
466 filters,
467 like_field,
468 sort,
469 &stmt.kind,
470 )
471 .await
472}
473
474pub async fn show_index(
476 stmt: ShowIndex,
477 query_engine: &QueryEngineRef,
478 catalog_manager: &CatalogManagerRef,
479 query_ctx: QueryContextRef,
480) -> Result<Output> {
481 let dataframe = show_index_dataframe(&stmt, query_engine, catalog_manager, query_ctx).await?;
482 dataframe_to_output(dataframe).await
483}
484
485pub async fn show_index_dataframe(
487 stmt: &ShowIndex,
488 query_engine: &QueryEngineRef,
489 catalog_manager: &CatalogManagerRef,
490 query_ctx: QueryContextRef,
491) -> Result<DataFrame> {
492 let schema_name = if let Some(database) = &stmt.database {
493 database.clone()
494 } else {
495 query_ctx.current_schema()
496 };
497
498 let select = vec![
499 col(statistics::TABLE_NAME).alias(INDEX_TABLE_COLUMN),
500 col(statistics::NON_UNIQUE).alias(INDEX_NONT_UNIQUE_COLUMN),
501 col(statistics::INDEX_NAME).alias(INDEX_KEY_NAME_COLUMN),
502 col(statistics::SEQ_IN_INDEX).alias(INDEX_SEQ_IN_INDEX_COLUMN),
503 col(statistics::COLUMN_NAME).alias(INDEX_COLUMN_NAME_COLUMN),
504 col(statistics::COLLATION).alias(COLUMN_COLLATION_COLUMN),
505 col(statistics::CARDINALITY).alias(INDEX_CARDINALITY_COLUMN),
506 col(statistics::SUB_PART).alias(INDEX_SUB_PART_COLUMN),
507 col(statistics::PACKED).alias(INDEX_PACKED_COLUMN),
508 col(statistics::NULLABLE).alias(COLUMN_NULLABLE_COLUMN),
509 col(statistics::INDEX_TYPE).alias(INDEX_INDEX_TYPE_COLUMN),
510 col(statistics::COMMENT).alias(COLUMN_COMMENT_COLUMN),
511 col(statistics::INDEX_COMMENT).alias(INDEX_COMMENT_COLUMN),
512 col(statistics::IS_VISIBLE).alias(INDEX_VISIBLE_COLUMN),
513 col(statistics::EXPRESSION).alias(INDEX_EXPRESSION_COLUMN),
514 ];
515
516 let projects = vec![
517 (statistics::TABLE_NAME, INDEX_TABLE_COLUMN),
518 (INDEX_NONT_UNIQUE_COLUMN, INDEX_NONT_UNIQUE_COLUMN),
519 (statistics::INDEX_NAME, INDEX_KEY_NAME_COLUMN),
520 (statistics::SEQ_IN_INDEX, INDEX_SEQ_IN_INDEX_COLUMN),
521 (statistics::COLUMN_NAME, INDEX_COLUMN_NAME_COLUMN),
522 (COLUMN_COLLATION_COLUMN, COLUMN_COLLATION_COLUMN),
523 (INDEX_CARDINALITY_COLUMN, INDEX_CARDINALITY_COLUMN),
524 (INDEX_SUB_PART_COLUMN, INDEX_SUB_PART_COLUMN),
525 (INDEX_PACKED_COLUMN, INDEX_PACKED_COLUMN),
526 (COLUMN_NULLABLE_COLUMN, COLUMN_NULLABLE_COLUMN),
527 (statistics::INDEX_TYPE, INDEX_INDEX_TYPE_COLUMN),
528 (COLUMN_COMMENT_COLUMN, COLUMN_COMMENT_COLUMN),
529 (INDEX_COMMENT_COLUMN, INDEX_COMMENT_COLUMN),
530 (INDEX_VISIBLE_COLUMN, INDEX_VISIBLE_COLUMN),
531 (INDEX_EXPRESSION_COLUMN, INDEX_EXPRESSION_COLUMN),
532 ];
533
534 let filters = vec![
535 col(statistics::TABLE_NAME).eq(lit(&stmt.table)),
536 col(statistics::TABLE_SCHEMA).eq(lit(schema_name.clone())),
537 ];
538 let like_field = None;
539 let sort = vec![
540 col(statistics::INDEX_NAME).sort(true, true),
541 col(statistics::SEQ_IN_INDEX).sort(true, true),
542 ];
543
544 query_from_information_schema_dataframe(
545 query_engine,
546 catalog_manager,
547 query_ctx,
548 STATISTICS,
549 select,
550 projects,
551 filters,
552 like_field,
553 sort,
554 &stmt.kind,
555 )
556 .await
557}
558
559pub async fn show_region(
561 stmt: ShowRegion,
562 query_engine: &QueryEngineRef,
563 catalog_manager: &CatalogManagerRef,
564 query_ctx: QueryContextRef,
565) -> Result<Output> {
566 let dataframe = show_region_dataframe(&stmt, query_engine, catalog_manager, query_ctx).await?;
567 dataframe_to_output(dataframe).await
568}
569
570pub async fn show_region_dataframe(
572 stmt: &ShowRegion,
573 query_engine: &QueryEngineRef,
574 catalog_manager: &CatalogManagerRef,
575 query_ctx: QueryContextRef,
576) -> Result<DataFrame> {
577 let schema_name = if let Some(database) = &stmt.database {
578 database.clone()
579 } else {
580 query_ctx.current_schema()
581 };
582
583 let filters = vec![
584 col(region_peers::TABLE_NAME).eq(lit(&stmt.table)),
585 col(region_peers::TABLE_SCHEMA).eq(lit(schema_name.clone())),
586 col(region_peers::TABLE_CATALOG).eq(lit(query_ctx.current_catalog())),
587 ];
588 let projects = vec![
589 (region_peers::TABLE_NAME, "Table"),
590 (region_peers::REGION_ID, "Region"),
591 (region_peers::PEER_ID, "Peer"),
592 (region_peers::IS_LEADER, "Leader"),
593 ];
594
595 let like_field = None;
596 let sort = vec![
597 col(columns::REGION_ID).sort(true, true),
598 col(columns::PEER_ID).sort(true, true),
599 ];
600
601 query_from_information_schema_dataframe(
602 query_engine,
603 catalog_manager,
604 query_ctx,
605 REGION_PEERS,
606 vec![],
607 projects,
608 filters,
609 like_field,
610 sort,
611 &stmt.kind,
612 )
613 .await
614}
615
616pub async fn show_tables(
618 stmt: ShowTables,
619 query_engine: &QueryEngineRef,
620 catalog_manager: &CatalogManagerRef,
621 query_ctx: QueryContextRef,
622) -> Result<Output> {
623 let dataframe = show_tables_dataframe(&stmt, query_engine, catalog_manager, query_ctx).await?;
624 dataframe_to_output(dataframe).await
625}
626
627pub async fn show_tables_dataframe(
629 stmt: &ShowTables,
630 query_engine: &QueryEngineRef,
631 catalog_manager: &CatalogManagerRef,
632 query_ctx: QueryContextRef,
633) -> Result<DataFrame> {
634 let schema_name = if let Some(database) = &stmt.database {
635 database.clone()
636 } else {
637 query_ctx.current_schema()
638 };
639
640 let tables_column = format!("Tables_in_{}", schema_name);
642 let projects = if stmt.full {
643 vec![
644 (tables::TABLE_NAME, tables_column.as_str()),
645 (tables::TABLE_TYPE, TABLE_TYPE_COLUMN),
646 ]
647 } else {
648 vec![(tables::TABLE_NAME, tables_column.as_str())]
649 };
650 let filters = vec![
651 col(tables::TABLE_SCHEMA).eq(lit(schema_name.clone())),
652 col(tables::TABLE_CATALOG).eq(lit(query_ctx.current_catalog())),
653 ];
654 let like_field = Some(tables::TABLE_NAME);
655 let sort = vec![col(tables::TABLE_NAME).sort(true, true)];
656
657 let rewritten_kind = match &stmt.kind {
660 ShowKind::Where(filter) => {
661 let mut filter = filter.clone();
662 replace_column_in_expr(&mut filter, "Tables", &tables_column);
663 ShowKind::Where(filter)
664 }
665 kind => kind.clone(),
666 };
667
668 query_from_information_schema_dataframe(
669 query_engine,
670 catalog_manager,
671 query_ctx,
672 TABLES,
673 vec![],
674 projects,
675 filters,
676 like_field,
677 sort,
678 &rewritten_kind,
679 )
680 .await
681}
682
683pub async fn show_table_status(
685 stmt: ShowTableStatus,
686 query_engine: &QueryEngineRef,
687 catalog_manager: &CatalogManagerRef,
688 query_ctx: QueryContextRef,
689) -> Result<Output> {
690 let dataframe =
691 show_table_status_dataframe(&stmt, query_engine, catalog_manager, query_ctx).await?;
692 dataframe_to_output(dataframe).await
693}
694
695pub async fn show_table_status_dataframe(
697 stmt: &ShowTableStatus,
698 query_engine: &QueryEngineRef,
699 catalog_manager: &CatalogManagerRef,
700 query_ctx: QueryContextRef,
701) -> Result<DataFrame> {
702 let schema_name = if let Some(database) = &stmt.database {
703 database.clone()
704 } else {
705 query_ctx.current_schema()
706 };
707
708 let projects = vec![
710 (tables::TABLE_NAME, "Name"),
711 (tables::ENGINE, "Engine"),
712 (tables::VERSION, "Version"),
713 (tables::ROW_FORMAT, "Row_format"),
714 (tables::TABLE_ROWS, "Rows"),
715 (tables::AVG_ROW_LENGTH, "Avg_row_length"),
716 (tables::DATA_LENGTH, "Data_length"),
717 (tables::MAX_DATA_LENGTH, "Max_data_length"),
718 (tables::INDEX_LENGTH, "Index_length"),
719 (tables::DATA_FREE, "Data_free"),
720 (tables::AUTO_INCREMENT, "Auto_increment"),
721 (tables::CREATE_TIME, "Create_time"),
722 (tables::UPDATE_TIME, "Update_time"),
723 (tables::CHECK_TIME, "Check_time"),
724 (tables::TABLE_COLLATION, "Collation"),
725 (tables::CHECKSUM, "Checksum"),
726 (tables::CREATE_OPTIONS, "Create_options"),
727 (tables::TABLE_COMMENT, "Comment"),
728 ];
729
730 let filters = vec![
731 col(tables::TABLE_SCHEMA).eq(lit(schema_name.clone())),
732 col(tables::TABLE_CATALOG).eq(lit(query_ctx.current_catalog())),
733 ];
734 let like_field = Some(tables::TABLE_NAME);
735 let sort = vec![col(tables::TABLE_NAME).sort(true, true)];
736
737 query_from_information_schema_dataframe(
738 query_engine,
739 catalog_manager,
740 query_ctx,
741 TABLES,
742 vec![],
743 projects,
744 filters,
745 like_field,
746 sort,
747 &stmt.kind,
748 )
749 .await
750}
751
752pub async fn show_collations(
754 kind: ShowKind,
755 query_engine: &QueryEngineRef,
756 catalog_manager: &CatalogManagerRef,
757 query_ctx: QueryContextRef,
758) -> Result<Output> {
759 let dataframe =
760 show_collations_dataframe(&kind, query_engine, catalog_manager, query_ctx).await?;
761 dataframe_to_output(dataframe).await
762}
763
764pub async fn show_collations_dataframe(
766 kind: &ShowKind,
767 query_engine: &QueryEngineRef,
768 catalog_manager: &CatalogManagerRef,
769 query_ctx: QueryContextRef,
770) -> Result<DataFrame> {
771 let projects = vec![
773 ("collation_name", "Collation"),
774 ("character_set_name", "Charset"),
775 ("id", "Id"),
776 ("is_default", "Default"),
777 ("is_compiled", "Compiled"),
778 ("sortlen", "Sortlen"),
779 ];
780
781 let filters = vec![];
782 let like_field = Some("collation_name");
783 let sort = vec![];
784
785 query_from_information_schema_dataframe(
786 query_engine,
787 catalog_manager,
788 query_ctx,
789 COLLATIONS,
790 vec![],
791 projects,
792 filters,
793 like_field,
794 sort,
795 kind,
796 )
797 .await
798}
799
800pub async fn show_charsets(
802 kind: ShowKind,
803 query_engine: &QueryEngineRef,
804 catalog_manager: &CatalogManagerRef,
805 query_ctx: QueryContextRef,
806) -> Result<Output> {
807 let dataframe =
808 show_charsets_dataframe(&kind, query_engine, catalog_manager, query_ctx).await?;
809 dataframe_to_output(dataframe).await
810}
811
812pub async fn show_charsets_dataframe(
814 kind: &ShowKind,
815 query_engine: &QueryEngineRef,
816 catalog_manager: &CatalogManagerRef,
817 query_ctx: QueryContextRef,
818) -> Result<DataFrame> {
819 let projects = vec![
821 ("character_set_name", "Charset"),
822 ("description", "Description"),
823 ("default_collate_name", "Default collation"),
824 ("maxlen", "Maxlen"),
825 ];
826
827 let filters = vec![];
828 let like_field = Some("character_set_name");
829 let sort = vec![];
830
831 query_from_information_schema_dataframe(
832 query_engine,
833 catalog_manager,
834 query_ctx,
835 CHARACTER_SETS,
836 vec![],
837 projects,
838 filters,
839 like_field,
840 sort,
841 kind,
842 )
843 .await
844}
845
846pub fn show_variable(stmt: ShowVariables, query_ctx: QueryContextRef) -> Result<Output> {
847 let variable = stmt.variable.to_string().to_uppercase();
848 let value = match variable.as_str() {
849 "SYSTEM_TIME_ZONE" | "SYSTEM_TIMEZONE" => get_timezone(None).to_string(),
850 "TIME_ZONE" | "TIMEZONE" => query_ctx.timezone().to_string(),
851 "READ_PREFERENCE" => query_ctx.read_preference().to_string(),
852 "DATESTYLE" => {
853 let (style, order) = *query_ctx.configuration_parameter().pg_datetime_style();
854 format!("{}, {}", style, order)
855 }
856 "INTERVALSTYLE" => {
857 let style = *query_ctx
858 .configuration_parameter()
859 .pg_intervalstyle_format();
860 style.to_string()
861 }
862 "MAX_EXECUTION_TIME"
863 if query_ctx.channel() == Channel::Mysql => {
864 query_ctx.query_timeout_as_millis().to_string()
865 }
866 "STATEMENT_TIMEOUT"
867 if query_ctx.channel() == Channel::Postgres => {
869 let mut timeout = query_ctx.query_timeout_as_millis().to_string();
870 timeout.push_str("ms");
871 timeout
872 }
873 _ => return UnsupportedVariableSnafu { name: variable }.fail(),
874 };
875 let schema = Arc::new(Schema::new(vec![ColumnSchema::new(
876 variable,
877 ConcreteDataType::string_datatype(),
878 false,
879 )]));
880 let records = RecordBatches::try_from_columns(
881 schema,
882 vec![Arc::new(StringVector::from(vec![value])) as _],
883 )
884 .context(error::CreateRecordBatchSnafu)?;
885 Ok(Output::new_with_record_batches(records))
886}
887
888pub async fn show_status(_query_ctx: QueryContextRef) -> Result<Output> {
889 let schema = Arc::new(Schema::new(vec![
890 ColumnSchema::new("Variable_name", ConcreteDataType::string_datatype(), false),
891 ColumnSchema::new("Value", ConcreteDataType::string_datatype(), true),
892 ]));
893 let records = RecordBatches::try_from_columns(
894 schema,
895 vec![
896 Arc::new(StringVector::from(Vec::<&str>::new())) as _,
897 Arc::new(StringVector::from(Vec::<&str>::new())) as _,
898 ],
899 )
900 .context(error::CreateRecordBatchSnafu)?;
901 Ok(Output::new_with_record_batches(records))
902}
903
904pub async fn show_search_path(_query_ctx: QueryContextRef) -> Result<Output> {
905 let schema = Arc::new(Schema::new(vec![ColumnSchema::new(
906 "search_path",
907 ConcreteDataType::string_datatype(),
908 false,
909 )]));
910 let records = RecordBatches::try_from_columns(
911 schema,
912 vec![Arc::new(StringVector::from(vec![_query_ctx.current_schema()])) as _],
913 )
914 .context(error::CreateRecordBatchSnafu)?;
915 Ok(Output::new_with_record_batches(records))
916}
917
918pub fn show_create_database(database_name: &str, options: OptionMap) -> Result<Output> {
919 let stmt = CreateDatabase {
920 name: ObjectName::from(vec![Ident::new(database_name)]),
921 if_not_exists: true,
922 options,
923 };
924 let sql = format!("{stmt}");
925 let columns = vec![
926 Arc::new(StringVector::from(vec![database_name.to_string()])) as _,
927 Arc::new(StringVector::from(vec![sql])) as _,
928 ];
929 let records =
930 RecordBatches::try_from_columns(SHOW_CREATE_DATABASE_OUTPUT_SCHEMA.clone(), columns)
931 .context(error::CreateRecordBatchSnafu)?;
932 Ok(Output::new_with_record_batches(records))
933}
934
935pub fn show_create_table(
936 table_info: TableInfoRef,
937 schema_options: Option<SchemaOptions>,
938 partitions: Option<Partitions>,
939 query_ctx: QueryContextRef,
940) -> Result<Output> {
941 let table_name = table_info.name.clone();
942
943 let quote_style = query_ctx.quote_style();
944
945 let mut stmt = create_table_stmt(&table_info, schema_options, quote_style)?;
946 stmt.partitions = partitions.map(|mut p| {
947 p.set_quote(quote_style);
948 p
949 });
950 let sql = format!("{}", stmt);
951 let columns = vec![
952 Arc::new(StringVector::from(vec![table_name])) as _,
953 Arc::new(StringVector::from(vec![sql])) as _,
954 ];
955 let records = RecordBatches::try_from_columns(SHOW_CREATE_TABLE_OUTPUT_SCHEMA.clone(), columns)
956 .context(error::CreateRecordBatchSnafu)?;
957
958 Ok(Output::new_with_record_batches(records))
959}
960
961pub fn show_create_foreign_table_for_pg(
962 table: TableRef,
963 _query_ctx: QueryContextRef,
964) -> Result<Output> {
965 let table_info = table.table_info();
966
967 let table_meta = &table_info.meta;
968 let table_name = &table_info.name;
969 let schema = &table_info.meta.schema;
970 let is_metric_engine = is_metric_engine(&table_meta.engine);
971
972 let columns = schema
973 .column_schemas()
974 .iter()
975 .filter_map(|c| {
976 if is_metric_engine && is_metric_engine_internal_column(&c.name) {
977 None
978 } else {
979 Some(format!(
980 "\"{}\" {}",
981 c.name,
982 c.data_type.postgres_datatype_name()
983 ))
984 }
985 })
986 .join(",\n ");
987
988 let sql = format!(
989 r#"CREATE FOREIGN TABLE ft_{} (
990 {}
991)
992SERVER greptimedb
993OPTIONS (table_name '{}')"#,
994 table_name, columns, table_name
995 );
996
997 let columns = vec![
998 Arc::new(StringVector::from(vec![table_name.clone()])) as _,
999 Arc::new(StringVector::from(vec![sql])) as _,
1000 ];
1001 let records = RecordBatches::try_from_columns(SHOW_CREATE_TABLE_OUTPUT_SCHEMA.clone(), columns)
1002 .context(error::CreateRecordBatchSnafu)?;
1003
1004 Ok(Output::new_with_record_batches(records))
1005}
1006
1007pub fn show_create_view(
1008 view_name: ObjectName,
1009 definition: &str,
1010 query_ctx: QueryContextRef,
1011) -> Result<Output> {
1012 let mut parser_ctx =
1013 ParserContext::new(query_ctx.sql_dialect(), definition).context(error::SqlSnafu)?;
1014
1015 let Statement::CreateView(create_view) =
1016 parser_ctx.parse_statement().context(error::SqlSnafu)?
1017 else {
1018 unreachable!();
1020 };
1021
1022 let stmt = CreateView {
1023 name: view_name.clone(),
1024 columns: create_view.columns,
1025 query: create_view.query,
1026 or_replace: create_view.or_replace,
1027 if_not_exists: create_view.if_not_exists,
1028 };
1029
1030 let sql = format!("{}", stmt);
1031 let columns = vec![
1032 Arc::new(StringVector::from(vec![view_name.to_string()])) as _,
1033 Arc::new(StringVector::from(vec![sql])) as _,
1034 ];
1035 let records = RecordBatches::try_from_columns(SHOW_CREATE_VIEW_OUTPUT_SCHEMA.clone(), columns)
1036 .context(error::CreateRecordBatchSnafu)?;
1037
1038 Ok(Output::new_with_record_batches(records))
1039}
1040
1041pub async fn show_views(
1043 stmt: ShowViews,
1044 query_engine: &QueryEngineRef,
1045 catalog_manager: &CatalogManagerRef,
1046 query_ctx: QueryContextRef,
1047) -> Result<Output> {
1048 let dataframe = show_views_dataframe(&stmt, query_engine, catalog_manager, query_ctx).await?;
1049 dataframe_to_output(dataframe).await
1050}
1051
1052pub async fn show_views_dataframe(
1054 stmt: &ShowViews,
1055 query_engine: &QueryEngineRef,
1056 catalog_manager: &CatalogManagerRef,
1057 query_ctx: QueryContextRef,
1058) -> Result<DataFrame> {
1059 let schema_name = if let Some(database) = &stmt.database {
1060 database.clone()
1061 } else {
1062 query_ctx.current_schema()
1063 };
1064
1065 let projects = vec![(tables::TABLE_NAME, VIEWS_COLUMN)];
1066 let filters = vec![
1067 col(tables::TABLE_SCHEMA).eq(lit(schema_name.clone())),
1068 col(tables::TABLE_CATALOG).eq(lit(query_ctx.current_catalog())),
1069 ];
1070 let like_field = Some(tables::TABLE_NAME);
1071 let sort = vec![col(tables::TABLE_NAME).sort(true, true)];
1072
1073 query_from_information_schema_dataframe(
1074 query_engine,
1075 catalog_manager,
1076 query_ctx,
1077 VIEWS,
1078 vec![],
1079 projects,
1080 filters,
1081 like_field,
1082 sort,
1083 &stmt.kind,
1084 )
1085 .await
1086}
1087
1088pub async fn show_flows(
1090 stmt: ShowFlows,
1091 query_engine: &QueryEngineRef,
1092 catalog_manager: &CatalogManagerRef,
1093 query_ctx: QueryContextRef,
1094) -> Result<Output> {
1095 let dataframe = show_flows_dataframe(&stmt, query_engine, catalog_manager, query_ctx).await?;
1096 dataframe_to_output(dataframe).await
1097}
1098
1099pub async fn show_flows_dataframe(
1101 stmt: &ShowFlows,
1102 query_engine: &QueryEngineRef,
1103 catalog_manager: &CatalogManagerRef,
1104 query_ctx: QueryContextRef,
1105) -> Result<DataFrame> {
1106 let projects = vec![(flows::FLOW_NAME, FLOWS_COLUMN)];
1107 let filters = vec![col(flows::TABLE_CATALOG).eq(lit(query_ctx.current_catalog()))];
1108 let like_field = Some(flows::FLOW_NAME);
1109 let sort = vec![col(flows::FLOW_NAME).sort(true, true)];
1110
1111 query_from_information_schema_dataframe(
1112 query_engine,
1113 catalog_manager,
1114 query_ctx,
1115 FLOWS,
1116 vec![],
1117 projects,
1118 filters,
1119 like_field,
1120 sort,
1121 &stmt.kind,
1122 )
1123 .await
1124}
1125
1126pub async fn show_flow_status(
1128 stmt: ShowFlowStatus,
1129 query_engine: &QueryEngineRef,
1130 catalog_manager: &CatalogManagerRef,
1131 query_ctx: QueryContextRef,
1132) -> Result<Output> {
1133 let projects = vec![
1134 (flow_statistics::FLOW_ID, flow_statistics::FLOW_ID),
1135 (flow_statistics::FLOW_NAME, flow_statistics::FLOW_NAME),
1136 (flow_statistics::START_TIME, flow_statistics::START_TIME),
1137 (
1138 flow_statistics::LAST_EXECUTION_TIME,
1139 flow_statistics::LAST_EXECUTION_TIME,
1140 ),
1141 (
1142 flow_statistics::UPTIME_SECONDS,
1143 flow_statistics::UPTIME_SECONDS,
1144 ),
1145 (flow_statistics::STATE_SIZE, flow_statistics::STATE_SIZE),
1146 ];
1147 let like_field = Some(flow_statistics::FLOW_NAME);
1148 let sort = vec![col(flow_statistics::FLOW_NAME).sort(true, true)];
1149
1150 query_from_information_schema_table(
1151 query_engine,
1152 catalog_manager,
1153 query_ctx,
1154 FLOW_STATISTICS,
1155 vec![],
1156 projects,
1157 vec![],
1158 like_field,
1159 sort,
1160 stmt.kind,
1161 )
1162 .await
1163}
1164
1165#[cfg(feature = "enterprise")]
1166pub async fn show_triggers(
1167 stmt: sql::statements::show::trigger::ShowTriggers,
1168 query_engine: &QueryEngineRef,
1169 catalog_manager: &CatalogManagerRef,
1170 query_ctx: QueryContextRef,
1171) -> Result<Output> {
1172 const TRIGGER_NAME: &str = "trigger_name";
1173 const TRIGGERS_COLUMN: &str = "Triggers";
1174
1175 let projects = vec![(TRIGGER_NAME, TRIGGERS_COLUMN)];
1176 let like_field = Some(TRIGGER_NAME);
1177 let sort = vec![col(TRIGGER_NAME).sort(true, true)];
1178
1179 query_from_information_schema_table(
1180 query_engine,
1181 catalog_manager,
1182 query_ctx,
1183 catalog::information_schema::TRIGGERS,
1184 vec![],
1185 projects,
1186 vec![],
1187 like_field,
1188 sort,
1189 stmt.kind,
1190 )
1191 .await
1192}
1193
1194pub fn show_create_flow(
1195 flow_name: ObjectName,
1196 flow_val: FlowInfoValue,
1197 query_ctx: QueryContextRef,
1198) -> Result<Output> {
1199 let mut parser_ctx =
1200 ParserContext::new(query_ctx.sql_dialect(), flow_val.raw_sql()).context(error::SqlSnafu)?;
1201
1202 let query = parser_ctx.parse_statement().context(error::SqlSnafu)?;
1203
1204 let raw_query = match &query {
1206 Statement::Tql(_) => flow_val.raw_sql().clone(),
1207 _ => query.to_string(),
1208 };
1209
1210 let query = Box::new(SqlOrTql::try_from_statement(query, &raw_query).context(error::SqlSnafu)?);
1211
1212 let comment = if flow_val.comment().is_empty() {
1213 None
1214 } else {
1215 Some(flow_val.comment().clone())
1216 };
1217
1218 let stmt = CreateFlow {
1219 flow_name,
1220 sink_table_name: ObjectName::from(vec![
1221 Ident::new(&flow_val.sink_table_name().schema_name),
1222 Ident::new(&flow_val.sink_table_name().table_name),
1223 ]),
1224 or_replace: false,
1227 if_not_exists: true,
1228 expire_after: flow_val.expire_after(),
1229 eval_interval: flow_val.eval_interval(),
1230 comment,
1231 flow_options: OptionMap::from_filtered_string_map(
1232 flow_val.options(),
1233 &[FlowType::FLOW_TYPE_KEY],
1234 ),
1235 query,
1236 };
1237
1238 let sql = format!("{}", stmt);
1239 let columns = vec![
1240 Arc::new(StringVector::from(vec![flow_val.flow_name().clone()])) as _,
1241 Arc::new(StringVector::from(vec![sql])) as _,
1242 ];
1243 let records = RecordBatches::try_from_columns(SHOW_CREATE_FLOW_OUTPUT_SCHEMA.clone(), columns)
1244 .context(error::CreateRecordBatchSnafu)?;
1245
1246 Ok(Output::new_with_record_batches(records))
1247}
1248
1249pub fn describe_table(table: TableRef) -> Result<Output> {
1250 let table_info = table.table_info();
1251 let columns_schemas = table_info.meta.schema.column_schemas();
1252 let columns = vec![
1253 describe_column_names(columns_schemas),
1254 describe_column_types(columns_schemas),
1255 describe_column_keys(columns_schemas, &table_info.meta.primary_key_indices),
1256 describe_column_nullables(columns_schemas),
1257 describe_column_defaults(columns_schemas),
1258 describe_column_semantic_types(columns_schemas, &table_info.meta.primary_key_indices),
1259 ];
1260 let records = RecordBatches::try_from_columns(DESCRIBE_TABLE_OUTPUT_SCHEMA.clone(), columns)
1261 .context(error::CreateRecordBatchSnafu)?;
1262 Ok(Output::new_with_record_batches(records))
1263}
1264
1265fn describe_column_names(columns_schemas: &[ColumnSchema]) -> VectorRef {
1266 Arc::new(StringVector::from_iterator(
1267 columns_schemas.iter().map(|cs| cs.name.as_str()),
1268 ))
1269}
1270
1271fn describe_column_types(columns_schemas: &[ColumnSchema]) -> VectorRef {
1272 Arc::new(StringVector::from(
1273 columns_schemas
1274 .iter()
1275 .map(|cs| describe_column_type_name(&cs.data_type))
1276 .collect::<Vec<_>>(),
1277 ))
1278}
1279
1280fn describe_column_type_name(data_type: &ConcreteDataType) -> String {
1281 match data_type {
1282 ConcreteDataType::Json(json_type) if json_type.is_json2() => "Json2".to_string(),
1283 data_type => data_type.name(),
1284 }
1285}
1286
1287fn describe_column_keys(
1288 columns_schemas: &[ColumnSchema],
1289 primary_key_indices: &[usize],
1290) -> VectorRef {
1291 Arc::new(StringVector::from_iterator(
1292 columns_schemas.iter().enumerate().map(|(i, cs)| {
1293 if cs.is_time_index() || primary_key_indices.contains(&i) {
1294 PRI_KEY
1295 } else {
1296 ""
1297 }
1298 }),
1299 ))
1300}
1301
1302fn describe_column_nullables(columns_schemas: &[ColumnSchema]) -> VectorRef {
1303 Arc::new(StringVector::from_iterator(columns_schemas.iter().map(
1304 |cs| {
1305 if cs.is_nullable() { YES_STR } else { NO_STR }
1306 },
1307 )))
1308}
1309
1310fn describe_column_defaults(columns_schemas: &[ColumnSchema]) -> VectorRef {
1311 Arc::new(StringVector::from(
1312 columns_schemas
1313 .iter()
1314 .map(|cs| {
1315 cs.default_constraint()
1316 .map_or(String::from(""), |dc| dc.to_string())
1317 })
1318 .collect::<Vec<String>>(),
1319 ))
1320}
1321
1322fn describe_column_semantic_types(
1323 columns_schemas: &[ColumnSchema],
1324 primary_key_indices: &[usize],
1325) -> VectorRef {
1326 Arc::new(StringVector::from_iterator(
1327 columns_schemas.iter().enumerate().map(|(i, cs)| {
1328 if primary_key_indices.contains(&i) {
1329 SEMANTIC_TYPE_PRIMARY_KEY
1330 } else if cs.is_time_index() {
1331 SEMANTIC_TYPE_TIME_INDEX
1332 } else {
1333 SEMANTIC_TYPE_FIELD
1334 }
1335 }),
1336 ))
1337}
1338
1339pub async fn prepare_file_table_files(
1341 options: &HashMap<String, String>,
1342 local_file_access: &LocalFileAccess,
1343) -> Result<(ObjectStore, Vec<String>)> {
1344 let url = options
1345 .get(FILE_TABLE_LOCATION_KEY)
1346 .context(error::MissingRequiredFieldSnafu {
1347 name: FILE_TABLE_LOCATION_KEY,
1348 })?;
1349
1350 let regex = options
1351 .get(FILE_TABLE_PATTERN_KEY)
1352 .map(|x| Regex::new(x))
1353 .transpose()
1354 .context(error::BuildRegexSnafu)?;
1355 let backend = build_backend_with_path(url, options, local_file_access)
1356 .await
1357 .context(error::BuildBackendSnafu)?;
1358 let source = if let Some(filename) = backend.object_path {
1359 Source::Filename(filename)
1360 } else {
1361 Source::Dir
1362 };
1363 let lister = Lister::new(backend.object_store.clone(), source, url.clone(), regex);
1364 let files = lister
1369 .list()
1370 .await
1371 .context(error::ListObjectsSnafu)?
1372 .into_iter()
1373 .filter_map(|entry| {
1374 if entry.path().ends_with('/') {
1375 None
1376 } else {
1377 Some(entry.path().to_string())
1378 }
1379 })
1380 .collect::<Vec<_>>();
1381 Ok((backend.object_store, files))
1382}
1383
1384pub async fn infer_file_table_schema(
1385 object_store: &ObjectStore,
1386 files: &[String],
1387 options: &HashMap<String, String>,
1388) -> Result<Schema> {
1389 let format = parse_file_table_format(options)?;
1390 let merged = infer_schemas(object_store, files, format.as_ref())
1391 .await
1392 .context(error::InferSchemaSnafu)?;
1393 Schema::try_from(merged).context(error::ConvertSchemaSnafu)
1394}
1395
1396pub fn file_column_schemas_to_table(
1406 file_column_schemas: &[ColumnSchema],
1407) -> (Vec<ColumnSchema>, String) {
1408 let mut column_schemas = file_column_schemas.to_owned();
1409 if let Some(time_index_column) = column_schemas.iter().find(|c| c.is_time_index()) {
1410 let time_index = time_index_column.name.clone();
1411 return (column_schemas, time_index);
1412 }
1413
1414 let timestamp_type = ConcreteDataType::timestamp_millisecond_datatype();
1415 let default_zero = Value::Timestamp(Timestamp::new_millisecond(0));
1416 let timestamp_column_schema = ColumnSchema::new(greptime_timestamp(), timestamp_type, false)
1417 .with_time_index(true)
1418 .with_default_constraint(Some(ColumnDefaultConstraint::Value(default_zero)))
1419 .unwrap();
1420
1421 if let Some(column_schema) = column_schemas
1422 .iter_mut()
1423 .find(|column_schema| column_schema.name == greptime_timestamp())
1424 {
1425 *column_schema = timestamp_column_schema;
1427 } else {
1428 column_schemas.push(timestamp_column_schema);
1429 }
1430
1431 (column_schemas, greptime_timestamp().to_string())
1432}
1433
1434pub fn check_file_to_table_schema_compatibility(
1443 file_column_schemas: &[ColumnSchema],
1444 table_column_schemas: &[ColumnSchema],
1445) -> Result<()> {
1446 let file_schemas_map = file_column_schemas
1447 .iter()
1448 .map(|s| (s.name.clone(), s))
1449 .collect::<HashMap<_, _>>();
1450
1451 for table_column in table_column_schemas {
1452 if let Some(file_column) = file_schemas_map.get(&table_column.name) {
1453 ensure!(
1455 file_column
1456 .data_type
1457 .can_arrow_type_cast_to(&table_column.data_type),
1458 error::ColumnSchemaIncompatibleSnafu {
1459 column: table_column.name.clone(),
1460 file_type: file_column.data_type.clone(),
1461 table_type: table_column.data_type.clone(),
1462 }
1463 );
1464 } else {
1465 ensure!(
1466 table_column.is_nullable() || table_column.default_constraint().is_some(),
1467 error::ColumnSchemaNoDefaultSnafu {
1468 column: table_column.name.clone(),
1469 }
1470 );
1471 }
1472 }
1473
1474 Ok(())
1475}
1476
1477fn parse_file_table_format(options: &HashMap<String, String>) -> Result<Box<dyn FileFormat>> {
1478 Ok(
1479 match Format::try_from(options).context(error::ParseFileFormatSnafu)? {
1480 Format::Csv(format) => Box::new(format),
1481 Format::Json(format) => Box::new(format),
1482 Format::Parquet(format) => Box::new(format),
1483 Format::Orc(format) => Box::new(format),
1484 },
1485 )
1486}
1487
1488pub async fn show_processlist(
1489 stmt: ShowProcessList,
1490 query_engine: &QueryEngineRef,
1491 catalog_manager: &CatalogManagerRef,
1492 query_ctx: QueryContextRef,
1493) -> Result<Output> {
1494 let dataframe =
1495 show_processlist_dataframe(&stmt, query_engine, catalog_manager, query_ctx).await?;
1496 dataframe_to_output(dataframe).await
1497}
1498
1499pub async fn show_processlist_dataframe(
1501 stmt: &ShowProcessList,
1502 query_engine: &QueryEngineRef,
1503 catalog_manager: &CatalogManagerRef,
1504 query_ctx: QueryContextRef,
1505) -> Result<DataFrame> {
1506 let projects = if stmt.full {
1507 vec![
1508 (process_list::ID, "Id"),
1509 (process_list::CATALOG, "Catalog"),
1510 (process_list::SCHEMAS, "Schema"),
1511 (process_list::CLIENT, "Client"),
1512 (process_list::FRONTEND, "Frontend"),
1513 (process_list::START_TIMESTAMP, "Start Time"),
1514 (process_list::ELAPSED_TIME, "Elapsed Time"),
1515 (process_list::QUERY, "Query"),
1516 ]
1517 } else {
1518 vec![
1519 (process_list::ID, "Id"),
1520 (process_list::CATALOG, "Catalog"),
1521 (process_list::QUERY, "Query"),
1522 (process_list::ELAPSED_TIME, "Elapsed Time"),
1523 ]
1524 };
1525
1526 let filters = if query_ctx.current_user().is_admin() {
1527 vec![]
1528 } else {
1529 vec![col(process_list::CATALOG).eq(lit(query_ctx.current_catalog()))]
1530 };
1531 let like_field = None;
1532 let sort = vec![col("id").sort(true, true)];
1533 query_from_information_schema_dataframe(
1534 query_engine,
1535 catalog_manager,
1536 query_ctx.clone(),
1537 "process_list",
1538 vec![],
1539 projects,
1540 filters,
1541 like_field,
1542 sort,
1543 &ShowKind::All,
1544 )
1545 .await
1546}
1547
1548#[cfg(test)]
1549mod test {
1550 use std::sync::Arc;
1551
1552 use common_query::{Output, OutputData};
1553 use common_recordbatch::{RecordBatch, RecordBatches};
1554 use common_time::Timezone;
1555 use common_time::timestamp::TimeUnit;
1556 use datatypes::prelude::ConcreteDataType;
1557 use datatypes::schema::{ColumnDefaultConstraint, ColumnSchema, Schema, SchemaRef};
1558 use datatypes::types::json_type::JsonNativeType;
1559 use datatypes::vectors::{StringVector, TimestampMillisecondVector, UInt32Vector, VectorRef};
1560 use session::context::QueryContextBuilder;
1561 use snafu::ResultExt;
1562 use sql::ast::{Ident, ObjectName};
1563 use sql::statements::show::ShowVariables;
1564 use table::TableRef;
1565 use table::test_util::MemTable;
1566
1567 use super::{describe_column_type_name, show_variable};
1568 use crate::error;
1569 use crate::error::Result;
1570 use crate::sql::{
1571 DESCRIBE_TABLE_OUTPUT_SCHEMA, NO_STR, SEMANTIC_TYPE_FIELD, SEMANTIC_TYPE_TIME_INDEX,
1572 YES_STR, describe_table,
1573 };
1574
1575 #[test]
1576 fn test_describe_table_multiple_columns() -> Result<()> {
1577 let table_name = "test_table";
1578 let schema = vec![
1579 ColumnSchema::new("t1", ConcreteDataType::uint32_datatype(), true),
1580 ColumnSchema::new(
1581 "t2",
1582 ConcreteDataType::timestamp_datatype(TimeUnit::Millisecond),
1583 false,
1584 )
1585 .with_default_constraint(Some(ColumnDefaultConstraint::Function(String::from(
1586 "current_timestamp()",
1587 ))))
1588 .unwrap()
1589 .with_time_index(true),
1590 ];
1591 let data = vec![
1592 Arc::new(UInt32Vector::from_slice([0])) as _,
1593 Arc::new(TimestampMillisecondVector::from_slice([0])) as _,
1594 ];
1595 let expected_columns = vec![
1596 Arc::new(StringVector::from(vec!["t1", "t2"])) as _,
1597 Arc::new(StringVector::from(vec!["UInt32", "TimestampMillisecond"])) as _,
1598 Arc::new(StringVector::from(vec!["", "PRI"])) as _,
1599 Arc::new(StringVector::from(vec![YES_STR, NO_STR])) as _,
1600 Arc::new(StringVector::from(vec!["", "current_timestamp()"])) as _,
1601 Arc::new(StringVector::from(vec![
1602 SEMANTIC_TYPE_FIELD,
1603 SEMANTIC_TYPE_TIME_INDEX,
1604 ])) as _,
1605 ];
1606
1607 describe_table_test_by_schema(table_name, schema, data, expected_columns)
1608 }
1609
1610 #[test]
1611 fn test_describe_column_type_name_json2() {
1612 assert_eq!(
1613 describe_column_type_name(&ConcreteDataType::json2(JsonNativeType::Null)),
1614 "Json2"
1615 );
1616 assert_eq!(
1617 describe_column_type_name(&ConcreteDataType::uint32_datatype()),
1618 "UInt32"
1619 );
1620 }
1621
1622 fn describe_table_test_by_schema(
1623 table_name: &str,
1624 schema: Vec<ColumnSchema>,
1625 data: Vec<VectorRef>,
1626 expected_columns: Vec<VectorRef>,
1627 ) -> Result<()> {
1628 let table_schema = SchemaRef::new(Schema::new(schema));
1629 let table = prepare_describe_table(table_name, table_schema, data);
1630
1631 let expected =
1632 RecordBatches::try_from_columns(DESCRIBE_TABLE_OUTPUT_SCHEMA.clone(), expected_columns)
1633 .context(error::CreateRecordBatchSnafu)?;
1634
1635 if let OutputData::RecordBatches(res) = describe_table(table)?.data {
1636 assert_eq!(res.take(), expected.take());
1637 } else {
1638 panic!("describe table must return record batch");
1639 }
1640
1641 Ok(())
1642 }
1643
1644 fn prepare_describe_table(
1645 table_name: &str,
1646 table_schema: SchemaRef,
1647 data: Vec<VectorRef>,
1648 ) -> TableRef {
1649 let record_batch = RecordBatch::new(table_schema, data).unwrap();
1650 MemTable::table(table_name, record_batch)
1651 }
1652
1653 #[test]
1654 fn test_show_variable() {
1655 assert_eq!(
1656 exec_show_variable("SYSTEM_TIME_ZONE", "Asia/Shanghai").unwrap(),
1657 "UTC"
1658 );
1659 assert_eq!(
1660 exec_show_variable("SYSTEM_TIMEZONE", "Asia/Shanghai").unwrap(),
1661 "UTC"
1662 );
1663 assert_eq!(
1664 exec_show_variable("TIME_ZONE", "Asia/Shanghai").unwrap(),
1665 "Asia/Shanghai"
1666 );
1667 assert_eq!(
1668 exec_show_variable("TIMEZONE", "Asia/Shanghai").unwrap(),
1669 "Asia/Shanghai"
1670 );
1671 assert!(exec_show_variable("TIME ZONE", "Asia/Shanghai").is_err());
1672 assert!(exec_show_variable("SYSTEM TIME ZONE", "Asia/Shanghai").is_err());
1673 }
1674
1675 fn exec_show_variable(variable: &str, tz: &str) -> Result<String> {
1676 let stmt = ShowVariables {
1677 variable: ObjectName::from(vec![Ident::new(variable)]),
1678 };
1679 let ctx = Arc::new(
1680 QueryContextBuilder::default()
1681 .timezone(Timezone::from_tz_string(tz).unwrap())
1682 .build(),
1683 );
1684 match show_variable(stmt, ctx) {
1685 Ok(Output {
1686 data: OutputData::RecordBatches(record),
1687 ..
1688 }) => {
1689 let record = record.take().first().cloned().unwrap();
1690 Ok(record.iter_column_as_string(0).next().unwrap().unwrap())
1691 }
1692 Ok(_) => unreachable!(),
1693 Err(e) => Err(e),
1694 }
1695 }
1696}