Skip to content

Commit

Permalink
feat(query): Support show dictionaries DQL. (#16602)
Browse files Browse the repository at this point in the history
* feat: show dictionaries stmt,planner.

* feat: add storages dictionaries

* feat: dictionaries_table.

* update: disctionaries_table and binder.

* fix

* fix

* fix and test.

* fmt

* update.

* update binder and test.

* update privilege_access and testdata.
  • Loading branch information
Winnie-Hong0927 authored Oct 15, 2024
1 parent d249097 commit 86cd608
Show file tree
Hide file tree
Showing 12 changed files with 367 additions and 14 deletions.
20 changes: 20 additions & 0 deletions src/query/ast/src/ast/statements/dictionary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use std::fmt::Formatter;
use derive_visitor::Drive;
use derive_visitor::DriveMut;

use super::ShowLimit;
use crate::ast::write_comma_separated_list;
use crate::ast::write_dot_separated_list;
use crate::ast::write_space_separated_string_map;
Expand Down Expand Up @@ -123,3 +124,22 @@ impl Display for ShowCreateDictionaryStmt {
)
}
}

#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
pub struct ShowDictionariesStmt {
pub database: Option<Identifier>,
pub limit: Option<ShowLimit>,
}

impl Display for ShowDictionariesStmt {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
write!(f, "SHOW DICTIONARIES")?;
if let Some(database) = &self.database {
write!(f, " FROM {database}")?;
}
if let Some(limit) = &self.limit {
write!(f, " {limit}")?;
}
Ok(())
}
}
11 changes: 2 additions & 9 deletions src/query/ast/src/ast/statements/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,7 @@ pub enum Statement {
CreateDictionary(CreateDictionaryStmt),
DropDictionary(DropDictionaryStmt),
ShowCreateDictionary(ShowCreateDictionaryStmt),
ShowDictionaries {
show_options: Option<ShowOptions>,
},
ShowDictionaries(ShowDictionariesStmt),

// Columns
ShowColumns(ShowColumnsStmt),
Expand Down Expand Up @@ -613,12 +611,7 @@ impl Display for Statement {
Statement::CreateDictionary(stmt) => write!(f, "{stmt}")?,
Statement::DropDictionary(stmt) => write!(f, "{stmt}")?,
Statement::ShowCreateDictionary(stmt) => write!(f, "{stmt}")?,
Statement::ShowDictionaries { show_options } => {
write!(f, "SHOW DICTIONARIES")?;
if let Some(show_options) = show_options {
write!(f, " {show_options}")?;
}
}
Statement::ShowDictionaries(stmt) => write!(f, "{stmt}")?,
Statement::CreateView(stmt) => write!(f, "{stmt}")?,
Statement::AlterView(stmt) => write!(f, "{stmt}")?,
Statement::DropView(stmt) => write!(f, "{stmt}")?,
Expand Down
10 changes: 8 additions & 2 deletions src/query/ast/src/parser/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -957,9 +957,15 @@ pub fn statement_body(i: Input) -> IResult<Statement> {
);
let show_dictionaries = map(
rule! {
SHOW ~ DICTIONARIES ~ #show_options?
SHOW ~ DICTIONARIES ~ ((FROM|IN) ~ #ident)? ~ #show_limit?
},
|(_, _, db, limit)| {
let database = match db {
Some((_, d)) => Some(d),
_ => None,
};
Statement::ShowDictionaries(ShowDictionariesStmt { database, limit })
},
|(_, _, show_options)| Statement::ShowDictionaries { show_options },
);
let show_create_dictionary = map(
rule! {
Expand Down
2 changes: 2 additions & 0 deletions src/query/service/src/databases/system/system_database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ use databend_common_storages_system::ConfigsTable;
use databend_common_storages_system::ContributorsTable;
use databend_common_storages_system::CreditsTable;
use databend_common_storages_system::DatabasesTable;
use databend_common_storages_system::DictionariesTable;
use databend_common_storages_system::EnginesTable;
use databend_common_storages_system::FullStreamsTable;
use databend_common_storages_system::FunctionsTable;
Expand Down Expand Up @@ -144,6 +145,7 @@ impl SystemDatabase {
ViewsTableWithoutHistory::create(sys_db_meta.next_table_id()),
TemporaryTablesTable::create(sys_db_meta.next_table_id()),
ProceduresTable::create(sys_db_meta.next_table_id()),
DictionariesTable::create(sys_db_meta.next_table_id()),
];

let disable_tables = Self::disable_system_tables();
Expand Down
6 changes: 4 additions & 2 deletions src/query/service/src/interpreters/access/privilege_access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,11 @@ enum ObjectId {
// some statements like `SELECT 1`, `SHOW USERS`, `SHOW ROLES`, `SHOW TABLES` will be
// rewritten to the queries on the system tables, we need to skip the privilege check on
// these tables.
const SYSTEM_TABLES_ALLOW_LIST: [&str; 19] = [
const SYSTEM_TABLES_ALLOW_LIST: [&str; 20] = [
"catalogs",
"columns",
"databases",
"dictionaries",
"tables",
"views",
"tables_with_history",
Expand Down Expand Up @@ -709,7 +710,8 @@ impl AccessChecker for PrivilegeAccess {
Some(RewriteKind::ShowDatabases)
| Some(RewriteKind::ShowEngines)
| Some(RewriteKind::ShowFunctions)
| Some(RewriteKind::ShowUserFunctions) => {
| Some(RewriteKind::ShowUserFunctions)
| Some(RewriteKind::ShowDictionaries(_)) => {
return Ok(());
}
| Some(RewriteKind::ShowTableFunctions) => {
Expand Down
10 changes: 10 additions & 0 deletions src/query/service/tests/it/storages/testdata/columns_table.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ DB.Table: 'system'.'columns', Table: columns-table_id:1, ver:0, Engine: SystemCo
| 'arguments' | 'system' | 'procedures' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'arguments' | 'system' | 'user_functions' | 'Variant' | 'VARIANT' | '' | '' | 'NO' | '' |
| 'attempt_number' | 'system' | 'task_history' | 'Int32' | 'INT' | '' | '' | 'NO' | '' |
| 'attribute_names' | 'system' | 'dictionaries' | 'Array(String)' | 'ARRAY(STRING)' | '' | '' | 'NO' | '' |
| 'attribute_types' | 'system' | 'dictionaries' | 'Array(String)' | 'ARRAY(STRING)' | '' | '' | 'NO' | '' |
| 'auth_type' | 'system' | 'users' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'auto_increment' | 'information_schema' | 'tables' | 'NULL' | 'NULL' | '' | '' | 'NO' | '' |
| 'byte_size' | 'system' | 'clustering_history' | 'UInt64' | 'BIGINT UNSIGNED' | '' | '' | 'NO' | '' |
Expand Down Expand Up @@ -59,6 +61,7 @@ DB.Table: 'system'.'columns', Table: columns-table_id:1, ver:0, Engine: SystemCo
| 'command' | 'system' | 'processes' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'comment' | 'information_schema' | 'statistics' | 'NULL' | 'NULL' | '' | '' | 'NO' | '' |
| 'comment' | 'system' | 'columns' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'comment' | 'system' | 'dictionaries' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'comment' | 'system' | 'notifications' | 'Nullable(String)' | 'VARCHAR' | '' | '' | 'YES' | '' |
| 'comment' | 'system' | 'password_policies' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'comment' | 'system' | 'procedures' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
Expand All @@ -82,6 +85,7 @@ DB.Table: 'system'.'columns', Table: columns-table_id:1, ver:0, Engine: SystemCo
| 'create_time' | 'information_schema' | 'tables' | 'Timestamp' | 'TIMESTAMP' | '' | '' | 'NO' | '' |
| 'created_on' | 'system' | 'background_jobs' | 'Timestamp' | 'TIMESTAMP' | '' | '' | 'NO' | '' |
| 'created_on' | 'system' | 'background_tasks' | 'Timestamp' | 'TIMESTAMP' | '' | '' | 'NO' | '' |
| 'created_on' | 'system' | 'dictionaries' | 'Timestamp' | 'TIMESTAMP' | '' | '' | 'NO' | '' |
| 'created_on' | 'system' | 'indexes' | 'Timestamp' | 'TIMESTAMP' | '' | '' | 'NO' | '' |
| 'created_on' | 'system' | 'locks' | 'Timestamp' | 'TIMESTAMP' | '' | '' | 'NO' | '' |
| 'created_on' | 'system' | 'notification_history' | 'Timestamp' | 'TIMESTAMP' | '' | '' | 'NO' | '' |
Expand Down Expand Up @@ -116,6 +120,7 @@ DB.Table: 'system'.'columns', Table: columns-table_id:1, ver:0, Engine: SystemCo
| 'data_write_bytes' | 'system' | 'processes' | 'UInt64' | 'BIGINT UNSIGNED' | '' | '' | 'NO' | '' |
| 'database' | 'system' | 'clustering_history' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'database' | 'system' | 'columns' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'database' | 'system' | 'dictionaries' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'database' | 'system' | 'processes' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'database' | 'system' | 'streams' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'database' | 'system' | 'streams_terse' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
Expand Down Expand Up @@ -231,6 +236,8 @@ DB.Table: 'system'.'columns', Table: columns-table_id:1, ver:0, Engine: SystemCo
| 'job_type' | 'system' | 'background_jobs' | 'Nullable(String)' | 'VARCHAR' | '' | '' | 'YES' | '' |
| 'join_spilled_bytes' | 'system' | 'query_log' | 'UInt64' | 'BIGINT UNSIGNED' | '' | '' | 'NO' | '' |
| 'join_spilled_rows' | 'system' | 'query_log' | 'UInt64' | 'BIGINT UNSIGNED' | '' | '' | 'NO' | '' |
| 'key_names' | 'system' | 'dictionaries' | 'Array(String)' | 'ARRAY(STRING)' | '' | '' | 'NO' | '' |
| 'key_types' | 'system' | 'dictionaries' | 'Array(String)' | 'ARRAY(STRING)' | '' | '' | 'NO' | '' |
| 'keywords' | 'information_schema' | 'keywords' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'kind' | 'system' | 'metrics' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'labels' | 'system' | 'metrics' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
Expand Down Expand Up @@ -266,6 +273,7 @@ DB.Table: 'system'.'columns', Table: columns-table_id:1, ver:0, Engine: SystemCo
| 'name' | 'system' | 'contributors' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'name' | 'system' | 'credits' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'name' | 'system' | 'databases' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'name' | 'system' | 'dictionaries' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'name' | 'system' | 'functions' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'name' | 'system' | 'indexes' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'name' | 'system' | 'malloc_stats_totals' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
Expand Down Expand Up @@ -386,6 +394,7 @@ DB.Table: 'system'.'columns', Table: columns-table_id:1, ver:0, Engine: SystemCo
| 'session_settings' | 'system' | 'query_log' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'size' | 'system' | 'caches' | 'UInt64' | 'BIGINT UNSIGNED' | '' | '' | 'NO' | '' |
| 'snapshot_location' | 'system' | 'streams' | 'Nullable(String)' | 'VARCHAR' | '' | '' | 'YES' | '' |
| 'source' | 'system' | 'dictionaries' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'sql' | 'system' | 'query_cache' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'sql_path' | 'information_schema' | 'schemata' | 'NULL' | 'NULL' | '' | '' | 'NO' | '' |
| 'sql_user' | 'system' | 'query_log' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
Expand Down Expand Up @@ -465,6 +474,7 @@ DB.Table: 'system'.'columns', Table: columns-table_id:1, ver:0, Engine: SystemCo
| 'update_on' | 'system' | 'roles' | 'Timestamp' | 'TIMESTAMP' | '' | '' | 'NO' | '' |
| 'update_on' | 'system' | 'users' | 'Nullable(Timestamp)' | 'TIMESTAMP' | '' | '' | 'YES' | '' |
| 'updated_on' | 'system' | 'background_tasks' | 'Timestamp' | 'TIMESTAMP' | '' | '' | 'NO' | '' |
| 'updated_on' | 'system' | 'dictionaries' | 'Timestamp' | 'TIMESTAMP' | '' | '' | 'NO' | '' |
| 'updated_on' | 'system' | 'indexes' | 'Nullable(Timestamp)' | 'TIMESTAMP' | '' | '' | 'YES' | '' |
| 'updated_on' | 'system' | 'password_policies' | 'Nullable(Timestamp)' | 'TIMESTAMP' | '' | '' | 'YES' | '' |
| 'updated_on' | 'system' | 'streams' | 'Timestamp' | 'TIMESTAMP' | '' | '' | 'NO' | '' |
Expand Down
2 changes: 1 addition & 1 deletion src/query/sql/src/planner/binder/binder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ impl<'a> Binder {
Statement::CreateDictionary(stmt) => self.bind_create_dictionary(stmt).await?,
Statement::DropDictionary(stmt) => self.bind_drop_dictionary(stmt).await?,
Statement::ShowCreateDictionary(stmt) => self.bind_show_create_dictionary(stmt).await?,
Statement::ShowDictionaries { show_options: _ } => todo!(),
Statement::ShowDictionaries(stmt) => self.bind_show_dictionaries(bind_context, stmt).await?,
// Views
Statement::CreateView(stmt) => self.bind_create_view(stmt).await?,
Statement::AlterView(stmt) => self.bind_alter_view(stmt).await?,
Expand Down
52 changes: 52 additions & 0 deletions src/query/sql/src/planner/binder/ddl/dictionary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ use std::sync::LazyLock;
use databend_common_ast::ast::CreateDictionaryStmt;
use databend_common_ast::ast::DropDictionaryStmt;
use databend_common_ast::ast::ShowCreateDictionaryStmt;
use databend_common_ast::ast::ShowDictionariesStmt;
use databend_common_ast::ast::ShowLimit;
use databend_common_exception::ErrorCode;
use databend_common_exception::Result;
use databend_common_expression::types::DataType;
Expand All @@ -28,12 +30,16 @@ use databend_common_expression::TableDataType;
use databend_common_expression::TableSchema;
use databend_common_meta_app::schema::DictionaryMeta;
use itertools::Itertools;
use log::debug;

use crate::plans::CreateDictionaryPlan;
use crate::plans::DropDictionaryPlan;
use crate::plans::Plan;
use crate::plans::RewriteKind;
use crate::plans::ShowCreateDictionaryPlan;
use crate::BindContext;
use crate::Binder;
use crate::SelectBuilder;

pub const DICT_OPT_KEY_SQL_HOST: &str = "host";
pub const DICT_OPT_KEY_SQL_PORT: &str = "port";
Expand Down Expand Up @@ -383,4 +389,50 @@ impl Binder {
},
)))
}

#[async_backtrace::framed]
pub(in crate::planner::binder) async fn bind_show_dictionaries(
&mut self,
bind_context: &mut BindContext,
stmt: &ShowDictionariesStmt,
) -> Result<Plan> {
let ShowDictionariesStmt { database, limit } = stmt;

let mut select_builder = SelectBuilder::from("system.dictionaries");

select_builder
.with_column("database AS Database")
.with_column("name AS Dictionary")
.with_column("key_names AS Key_Names")
.with_column("key_types AS key_Types")
.with_column("attribute_names AS Attribute_Names")
.with_column("attribute_types AS Attribute_Types")
.with_column("source AS Source")
.with_column("comment AS Comment");

select_builder
.with_order_by("database")
.with_order_by("name");

let database = self.check_database_exist(&None, database).await?;
select_builder.with_filter(format!("database = '{}'", database.clone()));

match limit {
None => (),
Some(ShowLimit::Like { pattern }) => {
select_builder.with_filter(format!("name LIKE '{pattern}'"));
}
Some(ShowLimit::Where { selection }) => {
select_builder.with_filter(format!("({selection})"));
}
};
let query = select_builder.build();
debug!("show dictionaries rewrite to: {:?}", query);
self.bind_rewrite_to_query(
bind_context,
query.as_str(),
RewriteKind::ShowDictionaries(database.clone()),
)
.await
}
}
1 change: 1 addition & 0 deletions src/query/sql/src/planner/plans/plan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,7 @@ pub enum RewriteKind {
ShowColumns(String, String, String),
ShowTablesStatus,
ShowVirtualColumns,
ShowDictionaries(String),

ShowStreams(String),

Expand Down
Loading

0 comments on commit 86cd608

Please sign in to comment.