From 4ebfd5c1a3ba4868c6e93368ac18ae23335e8243 Mon Sep 17 00:00:00 2001 From: Ning Sun Date: Wed, 11 Dec 2024 18:42:38 +0800 Subject: [PATCH] feat: implement show create table operation --- src/datatypes/src/data_type.rs | 45 +++++++++++++++++ src/operator/src/statement/show.rs | 13 +---- src/query/src/sql.rs | 48 +++++++++++++++++++ .../standalone/common/show/show_create.result | 30 ++++++++++++ .../standalone/common/show/show_create.sql | 4 ++ 5 files changed, 128 insertions(+), 12 deletions(-) diff --git a/src/datatypes/src/data_type.rs b/src/datatypes/src/data_type.rs index 8f81a0c86f76..b3342cc6f525 100644 --- a/src/datatypes/src/data_type.rs +++ b/src/datatypes/src/data_type.rs @@ -370,6 +370,51 @@ impl ConcreteDataType { _ => None, } } + + /// Return the datatype name in postgres type system + pub fn postgres_datatype_name(&self) -> &'static str { + match self { + &ConcreteDataType::Null(_) => "UNKNOWN", + &ConcreteDataType::Boolean(_) => "BOOL", + &ConcreteDataType::Int8(_) | &ConcreteDataType::UInt8(_) => "CHAR", + &ConcreteDataType::Int16(_) | &ConcreteDataType::UInt16(_) => "INT2", + &ConcreteDataType::Int32(_) | &ConcreteDataType::UInt32(_) => "INT4", + &ConcreteDataType::Int64(_) | &ConcreteDataType::UInt64(_) => "INT8", + &ConcreteDataType::Float32(_) => "FLOAT4", + &ConcreteDataType::Float64(_) => "FLOAT8", + &ConcreteDataType::Binary(_) | &ConcreteDataType::Vector(_) => "BYTEA", + &ConcreteDataType::String(_) => "VARCHAR", + &ConcreteDataType::Date(_) => "DATE", + &ConcreteDataType::DateTime(_) | &ConcreteDataType::Timestamp(_) => "TIMESTAMP", + &ConcreteDataType::Time(_) => "TIME", + &ConcreteDataType::Interval(_) => "INTERVAL", + &ConcreteDataType::Decimal128(_) => "NUMERIC", + &ConcreteDataType::Json(_) => "JSON", + ConcreteDataType::List(list) => match list.item_type() { + &ConcreteDataType::Null(_) => "UNKNOWN", + &ConcreteDataType::Boolean(_) => "_BOOL", + &ConcreteDataType::Int8(_) | &ConcreteDataType::UInt8(_) => "_CHAR", + &ConcreteDataType::Int16(_) | &ConcreteDataType::UInt16(_) => "_INT2", + &ConcreteDataType::Int32(_) | &ConcreteDataType::UInt32(_) => "_INT4", + &ConcreteDataType::Int64(_) | &ConcreteDataType::UInt64(_) => "_INT8", + &ConcreteDataType::Float32(_) => "_FLOAT4", + &ConcreteDataType::Float64(_) => "_FLOAT8", + &ConcreteDataType::Binary(_) => "_BYTEA", + &ConcreteDataType::String(_) => "_VARCHAR", + &ConcreteDataType::Date(_) => "_DATE", + &ConcreteDataType::DateTime(_) | &ConcreteDataType::Timestamp(_) => "_TIMESTAMP", + &ConcreteDataType::Time(_) => "_TIME", + &ConcreteDataType::Interval(_) => "_INTERVAL", + &ConcreteDataType::Decimal128(_) => "_NUMERIC", + &ConcreteDataType::Json(_) => "_JSON", + &ConcreteDataType::Duration(_) + | &ConcreteDataType::Dictionary(_) + | &ConcreteDataType::Vector(_) + | &ConcreteDataType::List(_) => "UNKNOWN", + }, + &ConcreteDataType::Duration(_) | &ConcreteDataType::Dictionary(_) => "UNKNOWN", + } + } } impl From<&ConcreteDataType> for ConcreteDataType { diff --git a/src/operator/src/statement/show.rs b/src/operator/src/statement/show.rs index d8c99022490f..fe91c71abe24 100644 --- a/src/operator/src/statement/show.rs +++ b/src/operator/src/statement/show.rs @@ -160,18 +160,7 @@ impl StatementExecutor { .fail(); } - let schema_options = self - .table_metadata_manager - .schema_manager() - .get(SchemaNameKey { - catalog: &table_name.catalog_name, - schema: &table_name.schema_name, - }) - .await - .context(TableMetadataManagerSnafu)? - .map(|v| v.into_inner()); - - query::sql::show_create_table(table, schema_options, None, query_ctx) + query::sql::show_create_foreign_table_for_pg(table, query_ctx) .context(ExecuteStatementSnafu) } diff --git a/src/query/src/sql.rs b/src/query/src/sql.rs index 062bd8e14e18..c0cdc7cc63be 100644 --- a/src/query/src/sql.rs +++ b/src/query/src/sql.rs @@ -45,6 +45,7 @@ use datafusion_expr::{case, col, lit, Expr}; use datatypes::prelude::*; use datatypes::schema::{ColumnDefaultConstraint, ColumnSchema, RawSchema, Schema}; use datatypes::vectors::StringVector; +use itertools::Itertools; use object_store::ObjectStore; use once_cell::sync::Lazy; use regex::Regex; @@ -61,6 +62,7 @@ use sql::statements::show::{ use sql::statements::statement::Statement; use sql::statements::OptionMap; use sqlparser::ast::ObjectName; +use store_api::metric_engine_consts::{is_metric_engine, is_metric_engine_internal_column}; use table::requests::{FILE_TABLE_LOCATION_KEY, FILE_TABLE_PATTERN_KEY}; use table::TableRef; @@ -746,6 +748,52 @@ pub fn show_create_table( Ok(Output::new_with_record_batches(records)) } +pub fn show_create_foreign_table_for_pg( + table: TableRef, + _query_ctx: QueryContextRef, +) -> Result { + let table_info = table.table_info(); + + let table_meta = &table_info.meta; + let table_name = &table_info.name; + let schema = &table_info.meta.schema; + let is_metric_engine = is_metric_engine(&table_meta.engine); + + let columns = schema + .column_schemas() + .iter() + .filter_map(|c| { + if is_metric_engine && is_metric_engine_internal_column(&c.name) { + None + } else { + Some(format!( + "\"{}\" {}", + c.name, + c.data_type.postgres_datatype_name() + )) + } + }) + .join(",\n "); + + let sql = format!( + r#"CREATE FOREIGN TABLE ft_{} ( + {} +) +SERVER greptimedb +OPTIONS (table_name '{}')"#, + table_name, columns, table_name + ); + + let columns = vec![ + Arc::new(StringVector::from(vec![table_name.clone()])) as _, + Arc::new(StringVector::from(vec![sql])) as _, + ]; + let records = RecordBatches::try_from_columns(SHOW_CREATE_TABLE_OUTPUT_SCHEMA.clone(), columns) + .context(error::CreateRecordBatchSnafu)?; + + Ok(Output::new_with_record_batches(records)) +} + pub fn show_create_view( view_name: ObjectName, definition: &str, diff --git a/tests/cases/standalone/common/show/show_create.result b/tests/cases/standalone/common/show/show_create.result index ec692c0f293a..85536954d435 100644 --- a/tests/cases/standalone/common/show/show_create.result +++ b/tests/cases/standalone/common/show/show_create.result @@ -46,6 +46,22 @@ SHOW CREATE TABLE system_metrics; | | ) | +----------------+-----------------------------------------------------------+ +SHOW CREATE TABLE system_metrics FOR POSTGRES_FOREIGN_TABLE; + ++----------------+------------------------------------------+ +| Table | Create Table | ++----------------+------------------------------------------+ +| system_metrics | CREATE FOREIGN TABLE ft_system_metrics ( | +| | "id" INT4, | +| | "host" VARCHAR, | +| | "cpu" FLOAT8, | +| | "disk" FLOAT4, | +| | "ts" TIMESTAMP | +| | ) | +| | SERVER greptimedb | +| | OPTIONS (table_name 'system_metrics') | ++----------------+------------------------------------------+ + DROP TABLE system_metrics; Affected Rows: 0 @@ -141,6 +157,20 @@ show create table t1; | | ) | +-------+-----------------------------------+ +SHOW CREATE TABLE t1 FOR POSTGRES_FOREIGN_TABLE; + ++-------+------------------------------+ +| Table | Create Table | ++-------+------------------------------+ +| t1 | CREATE FOREIGN TABLE ft_t1 ( | +| | "host" VARCHAR, | +| | "ts" TIMESTAMP, | +| | "val" FLOAT8 | +| | ) | +| | SERVER greptimedb | +| | OPTIONS (table_name 't1') | ++-------+------------------------------+ + drop table t1; Affected Rows: 0 diff --git a/tests/cases/standalone/common/show/show_create.sql b/tests/cases/standalone/common/show/show_create.sql index 45c8f7a3ef4c..5289df6e76f5 100644 --- a/tests/cases/standalone/common/show/show_create.sql +++ b/tests/cases/standalone/common/show/show_create.sql @@ -20,6 +20,8 @@ WITH( SHOW CREATE TABLE system_metrics; +SHOW CREATE TABLE system_metrics FOR POSTGRES_FOREIGN_TABLE; + DROP TABLE system_metrics; create table table_without_partition ( @@ -57,6 +59,8 @@ show create table phy; show create table t1; +SHOW CREATE TABLE t1 FOR POSTGRES_FOREIGN_TABLE; + drop table t1; drop table phy;