mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2026-10-29 07:06:20 +00:00
feat: implement DESCRIBE TABLE (#558)
Also need to support describe table in other catalog/schema
This commit is contained in:
@@ -21,8 +21,10 @@ use sqlparser::tokenizer::{Token, Tokenizer};
|
||||
use crate::error::{
|
||||
self, InvalidDatabaseNameSnafu, InvalidTableNameSnafu, Result, SyntaxSnafu, TokenizerSnafu,
|
||||
};
|
||||
use crate::statements::describe::DescribeTable;
|
||||
use crate::statements::show::{ShowCreateTable, ShowDatabases, ShowKind, ShowTables};
|
||||
use crate::statements::statement::Statement;
|
||||
use crate::statements::table_idents_to_full_name;
|
||||
|
||||
/// GrepTime SQL parser context, a simple wrapper for Datafusion SQL parser.
|
||||
pub struct ParserContext<'a> {
|
||||
@@ -85,6 +87,11 @@ impl<'a> ParserContext<'a> {
|
||||
self.parse_show()
|
||||
}
|
||||
|
||||
Keyword::DESCRIBE | Keyword::DESC => {
|
||||
self.parser.next_token();
|
||||
self.parse_describe()
|
||||
}
|
||||
|
||||
Keyword::INSERT => self.parse_insert(),
|
||||
|
||||
Keyword::SELECT | Keyword::WITH | Keyword::VALUES => self.parse_query(),
|
||||
@@ -217,6 +224,39 @@ impl<'a> ParserContext<'a> {
|
||||
Ok(Statement::ShowTables(ShowTables { kind, database }))
|
||||
}
|
||||
|
||||
/// Parses DESCRIBE statements
|
||||
fn parse_describe(&mut self) -> Result<Statement> {
|
||||
if self.matches_keyword(Keyword::TABLE) {
|
||||
self.parser.next_token();
|
||||
self.parse_describe_table()
|
||||
} else {
|
||||
self.unsupported(self.peek_token_as_string())
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_describe_table(&mut self) -> Result<Statement> {
|
||||
let table_idents =
|
||||
self.parser
|
||||
.parse_object_name()
|
||||
.with_context(|_| error::UnexpectedSnafu {
|
||||
sql: self.sql,
|
||||
expected: "a table name",
|
||||
actual: self.peek_token_as_string(),
|
||||
})?;
|
||||
ensure!(
|
||||
!table_idents.0.is_empty(),
|
||||
InvalidTableNameSnafu {
|
||||
name: table_idents.to_string(),
|
||||
}
|
||||
);
|
||||
let (catalog_name, schema_name, table_name) = table_idents_to_full_name(&table_idents)?;
|
||||
Ok(Statement::DescribeTable(DescribeTable {
|
||||
catalog_name,
|
||||
schema_name,
|
||||
table_name,
|
||||
}))
|
||||
}
|
||||
|
||||
fn parse_explain(&mut self) -> Result<Statement> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
pub mod alter;
|
||||
pub mod create;
|
||||
pub mod describe;
|
||||
pub mod insert;
|
||||
pub mod query;
|
||||
pub mod show;
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
// Copyright 2022 Greptime Team
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// SQL structure for `DESCRIBE TABLE`.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct DescribeTable {
|
||||
pub catalog_name: String,
|
||||
pub schema_name: String,
|
||||
pub table_name: String,
|
||||
}
|
||||
|
||||
impl DescribeTable {
|
||||
/// Creates a statement for `DESCRIBE TABLE`
|
||||
pub fn new(catalog_name: String, schema_name: String, table_name: String) -> Self {
|
||||
DescribeTable {
|
||||
catalog_name,
|
||||
schema_name,
|
||||
table_name,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::assert_matches::assert_matches;
|
||||
|
||||
use sqlparser::dialect::GenericDialect;
|
||||
|
||||
use crate::parser::ParserContext;
|
||||
use crate::statements::statement::Statement;
|
||||
|
||||
#[test]
|
||||
pub fn test_describe_table() {
|
||||
let sql = "DESCRIBE TABLE test";
|
||||
let stmts: Vec<Statement> =
|
||||
ParserContext::create_with_dialect(sql, &GenericDialect {}).unwrap();
|
||||
assert_eq!(1, stmts.len());
|
||||
assert_matches!(&stmts[0], Statement::DescribeTable { .. });
|
||||
match &stmts[0] {
|
||||
Statement::DescribeTable(show) => {
|
||||
assert_eq!(show.table_name.as_str(), "test");
|
||||
}
|
||||
_ => {
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_describe_schema_table() {
|
||||
let sql = "DESCRIBE TABLE test_schema.test";
|
||||
let stmts: Vec<Statement> =
|
||||
ParserContext::create_with_dialect(sql, &GenericDialect {}).unwrap();
|
||||
assert_eq!(1, stmts.len());
|
||||
assert_matches!(&stmts[0], Statement::DescribeTable { .. });
|
||||
match &stmts[0] {
|
||||
Statement::DescribeTable(show) => {
|
||||
assert_eq!(show.schema_name.as_str(), "test_schema");
|
||||
assert_eq!(show.table_name.as_str(), "test");
|
||||
}
|
||||
_ => {
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_describe_catalog_schema_table() {
|
||||
let sql = "DESCRIBE TABLE test_catalog.test_schema.test";
|
||||
let stmts: Vec<Statement> =
|
||||
ParserContext::create_with_dialect(sql, &GenericDialect {}).unwrap();
|
||||
assert_eq!(1, stmts.len());
|
||||
assert_matches!(&stmts[0], Statement::DescribeTable { .. });
|
||||
match &stmts[0] {
|
||||
Statement::DescribeTable(show) => {
|
||||
assert_eq!(show.catalog_name.as_str(), "test_catalog");
|
||||
assert_eq!(show.schema_name.as_str(), "test_schema");
|
||||
assert_eq!(show.table_name.as_str(), "test");
|
||||
}
|
||||
_ => {
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_describe_missing_table_name() {
|
||||
let sql = "DESCRIBE TABLE";
|
||||
ParserContext::create_with_dialect(sql, &GenericDialect {}).unwrap_err();
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@ use sqlparser::parser::ParserError;
|
||||
|
||||
use crate::statements::alter::AlterTable;
|
||||
use crate::statements::create::{CreateDatabase, CreateTable};
|
||||
use crate::statements::describe::DescribeTable;
|
||||
use crate::statements::insert::Insert;
|
||||
use crate::statements::query::Query;
|
||||
use crate::statements::show::{ShowCreateTable, ShowDatabases, ShowTables};
|
||||
@@ -40,6 +41,8 @@ pub enum Statement {
|
||||
ShowTables(ShowTables),
|
||||
// SHOW CREATE TABLE
|
||||
ShowCreateTable(ShowCreateTable),
|
||||
// DESCRIBE TABLE
|
||||
DescribeTable(DescribeTable),
|
||||
}
|
||||
|
||||
/// Converts Statement to sqlparser statement
|
||||
@@ -57,6 +60,9 @@ impl TryFrom<Statement> for SpStatement {
|
||||
Statement::ShowCreateTable(_) => Err(ParserError::ParserError(
|
||||
"sqlparser does not support SHOW CREATE TABLE query.".to_string(),
|
||||
)),
|
||||
Statement::DescribeTable(_) => Err(ParserError::ParserError(
|
||||
"sqlparser does not support DESCRIBE TABLE query.".to_string(),
|
||||
)),
|
||||
Statement::Query(s) => Ok(SpStatement::Query(Box::new(s.inner))),
|
||||
Statement::Insert(i) => Ok(i.inner),
|
||||
Statement::CreateDatabase(_) | Statement::CreateTable(_) | Statement::Alter(_) => {
|
||||
|
||||
Reference in New Issue
Block a user