From 5ebbe1a3149a6930f3c52d22706187cc478fbed1 Mon Sep 17 00:00:00 2001 From: Ning Sun Date: Tue, 10 Dec 2024 15:36:12 +0800 Subject: [PATCH] feat: add show create table for pg in parser --- src/operator/src/statement.rs | 13 +++++++-- src/operator/src/statement/show.rs | 31 ++++++++++++++++++++ src/sql/src/parsers/show_parser.rs | 20 ++++++++++--- src/sql/src/statements/show.rs | 46 +++++++++++++++++++++++++++++- 4 files changed, 103 insertions(+), 7 deletions(-) diff --git a/src/operator/src/statement.rs b/src/operator/src/statement.rs index b3251ca6bf2c..ad842a40fe28 100644 --- a/src/operator/src/statement.rs +++ b/src/operator/src/statement.rs @@ -59,6 +59,7 @@ use set::set_query_timeout; use snafu::{ensure, OptionExt, ResultExt}; use sql::statements::copy::{CopyDatabase, CopyDatabaseArgument, CopyTable, CopyTableArgument}; use sql::statements::set_variables::SetVariables; +use sql::statements::show::ShowCreateTableVariant; use sql::statements::statement::Statement; use sql::statements::OptionMap; use sql::util::format_raw_object_name; @@ -317,8 +318,16 @@ impl StatementExecutor { .context(TableNotFoundSnafu { table_name: &table })?; let table_name = TableName::new(catalog, schema, table); - self.show_create_table(table_name, table_ref, query_ctx) - .await + match show.variant { + ShowCreateTableVariant::Original => { + self.show_create_table(table_name, table_ref, query_ctx) + .await + } + ShowCreateTableVariant::PostgresForeignTable => { + self.show_create_table_for_pg(table_name, table_ref, query_ctx) + .await + } + } } Statement::ShowCreateFlow(show) => self.show_create_flow(show, query_ctx).await, Statement::ShowCreateView(show) => self.show_create_view(show, query_ctx).await, diff --git a/src/operator/src/statement/show.rs b/src/operator/src/statement/show.rs index 210ec4e7f28f..d8c99022490f 100644 --- a/src/operator/src/statement/show.rs +++ b/src/operator/src/statement/show.rs @@ -144,6 +144,37 @@ impl StatementExecutor { .context(ExecuteStatementSnafu) } + #[tracing::instrument(skip_all)] + pub async fn show_create_table_for_pg( + &self, + table_name: TableName, + table: TableRef, + query_ctx: QueryContextRef, + ) -> Result { + let table_info = table.table_info(); + if table_info.table_type != TableType::Base { + return error::ShowCreateTableBaseOnlySnafu { + table_name: table_name.to_string(), + table_type: table_info.table_type, + } + .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) + .context(ExecuteStatementSnafu) + } + #[tracing::instrument(skip_all)] pub async fn show_create_view( &self, diff --git a/src/sql/src/parsers/show_parser.rs b/src/sql/src/parsers/show_parser.rs index d1530c1fcbbf..fa31e813f3d6 100644 --- a/src/sql/src/parsers/show_parser.rs +++ b/src/sql/src/parsers/show_parser.rs @@ -21,9 +21,9 @@ use crate::error::{ }; use crate::parser::ParserContext; use crate::statements::show::{ - ShowColumns, ShowCreateDatabase, ShowCreateFlow, ShowCreateTable, ShowCreateView, - ShowDatabases, ShowFlows, ShowIndex, ShowKind, ShowStatus, ShowTableStatus, ShowTables, - ShowVariables, ShowViews, + ShowColumns, ShowCreateDatabase, ShowCreateFlow, ShowCreateTable, ShowCreateTableVariant, + ShowCreateView, ShowDatabases, ShowFlows, ShowIndex, ShowKind, ShowStatus, ShowTableStatus, + ShowTables, ShowVariables, ShowViews, }; use crate::statements::statement::Statement; @@ -146,7 +146,19 @@ impl ParserContext<'_> { name: table_name.to_string(), } ); - Ok(Statement::ShowCreateTable(ShowCreateTable { table_name })) + let mut variant = ShowCreateTableVariant::Original; + if self.consume_token("FOR") { + if self.consume_token("POSTGRES_FOREIGN_TABLE") { + variant = ShowCreateTableVariant::PostgresForeignTable; + } else { + self.unsupported(self.peek_token_as_string())?; + } + } + + Ok(Statement::ShowCreateTable(ShowCreateTable { + table_name, + variant, + })) } fn parse_show_create_flow(&mut self) -> Result { diff --git a/src/sql/src/statements/show.rs b/src/sql/src/statements/show.rs index f6a8dab72897..9fb939fb42b8 100644 --- a/src/sql/src/statements/show.rs +++ b/src/sql/src/statements/show.rs @@ -178,12 +178,26 @@ impl Display for ShowCreateDatabase { #[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)] pub struct ShowCreateTable { pub table_name: ObjectName, + pub variant: ShowCreateTableVariant, +} + +/// Variant of a show create table +#[derive(Default, Debug, Clone, PartialEq, Eq, Visit, VisitMut)] +pub enum ShowCreateTableVariant { + #[default] + Original, + PostgresForeignTable, } impl Display for ShowCreateTable { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let table_name = &self.table_name; - write!(f, r#"SHOW CREATE TABLE {table_name}"#) + write!(f, r#"SHOW CREATE TABLE {table_name}"#)?; + if let ShowCreateTableVariant::PostgresForeignTable = self.variant { + write!(f, " FOR POSTGRES_FOREIGN_TABLE")?; + } + + Ok(()) } } @@ -343,12 +357,31 @@ mod tests { Statement::ShowCreateTable(show) => { let table_name = show.table_name.to_string(); assert_eq!(table_name, "test"); + assert_eq!(show.variant, ShowCreateTableVariant::Original); + } + _ => { + unreachable!(); + } + } + + let sql = "SHOW CREATE TABLE test FOR POSTGRES_FOREIGN_TABLE"; + let stmts: Vec = + ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default()) + .unwrap(); + assert_eq!(1, stmts.len()); + assert_matches!(&stmts[0], Statement::ShowCreateTable { .. }); + match &stmts[0] { + Statement::ShowCreateTable(show) => { + let table_name = show.table_name.to_string(); + assert_eq!(table_name, "test"); + assert_eq!(show.variant, ShowCreateTableVariant::PostgresForeignTable); } _ => { unreachable!(); } } } + #[test] pub fn test_show_create_missing_table_name() { let sql = "SHOW CREATE TABLE"; @@ -360,6 +393,17 @@ mod tests { .is_err()); } + #[test] + pub fn test_show_create_unknown_for() { + let sql = "SHOW CREATE TABLE t FOR UNKNOWN"; + assert!(ParserContext::create_with_dialect( + sql, + &GreptimeDbDialect {}, + ParseOptions::default() + ) + .is_err()); + } + #[test] pub fn test_show_create_flow() { let sql = "SHOW CREATE FLOW test";